1/////////////////////////////////////////////////////////////////////////// 2// 3// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas 4// Digital Ltd. LLC 5// 6// All rights reserved. 7// 8// Redistribution and use in source and binary forms, with or without 9// modification, are permitted provided that the following conditions are 10// met: 11// * Redistributions of source code must retain the above copyright 12// notice, this list of conditions and the following disclaimer. 13// * Redistributions in binary form must reproduce the above 14// copyright notice, this list of conditions and the following disclaimer 15// in the documentation and/or other materials provided with the 16// distribution. 17// * Neither the name of Industrial Light & Magic nor the names of 18// its contributors may be used to endorse or promote products derived 19// from this software without specific prior written permission. 20// 21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32// 33/////////////////////////////////////////////////////////////////////////// 34 35// Primary authors: 36// Florian Kainz <kainz@ilm.com> 37// Rod Bogart <rgb@ilm.com> 38 39 40//--------------------------------------------------------------------------- 41// 42// class half -- 43// implementation of non-inline members 44// 45//--------------------------------------------------------------------------- 46 47#include <assert.h> 48#include "half.h" 49 50using namespace std; 51 52//------------------------------------------------------------- 53// Lookup tables for half-to-float and float-to-half conversion 54//------------------------------------------------------------- 55 56#if defined (OPENEXR_DLL) 57__declspec(dllexport) half::uif _toFloat[1 << 16] = 58 #include "toFloat.h" 59__declspec(dllexport) unsigned short _eLut[1 << 9] = 60 #include "eLut.h" 61#else 62const half::uif half::_toFloat[1 << 16] = 63 #include "toFloat.h" 64const unsigned short half::_eLut[1 << 9] = 65 #include "eLut.h" 66#endif 67 68//----------------------------------------------- 69// Overflow handler for float-to-half conversion; 70// generates a hardware floating-point overflow, 71// which may be trapped by the operating system. 72//----------------------------------------------- 73 74float 75half::overflow () 76{ 77 volatile float f = 1e10; 78 79 for (int i = 0; i < 10; i++) 80 f *= f; // this will overflow before 81 // the for�loop terminates 82 return f; 83} 84 85 86//----------------------------------------------------- 87// Float-to-half conversion -- general case, including 88// zeroes, denormalized numbers and exponent overflows. 89//----------------------------------------------------- 90 91short 92half::convert (int i) 93{ 94 // 95 // Our floating point number, f, is represented by the bit 96 // pattern in integer i. Disassemble that bit pattern into 97 // the sign, s, the exponent, e, and the significand, m. 98 // Shift s into the position where it will go in in the 99 // resulting half number. 100 // Adjust e, accounting for the different exponent bias 101 // of float and half (127 versus 15). 102 // 103 104 register int s = (i >> 16) & 0x00008000; 105 register int e = ((i >> 23) & 0x000000ff) - (127 - 15); 106 register int m = i & 0x007fffff; 107 108 // 109 // Now reassemble s, e and m into a half: 110 // 111 112 if (e <= 0) 113 { 114 if (e < -10) 115 { 116 // 117 // E is less than -10. The absolute value of f is 118 // less than HALF_MIN (f may be a small normalized 119 // float, a denormalized float or a zero). 120 // 121 // We convert f to a half zero with the same sign as f. 122 // 123 124 return s; 125 } 126 127 // 128 // E is between -10 and 0. F is a normalized float 129 // whose magnitude is less than HALF_NRM_MIN. 130 // 131 // We convert f to a denormalized half. 132 // 133 134 // 135 // Add an explicit leading 1 to the significand. 136 // 137 138 m = m | 0x00800000; 139 140 // 141 // Round to m to the nearest (10+e)-bit value (with e between 142 // -10 and 0); in case of a tie, round to the nearest even value. 143 // 144 // Rounding may cause the significand to overflow and make 145 // our number normalized. Because of the way a half's bits 146 // are laid out, we don't have to treat this case separately; 147 // the code below will handle it correctly. 148 // 149 150 int t = 14 - e; 151 int a = (1 << (t - 1)) - 1; 152 int b = (m >> t) & 1; 153 154 m = (m + a + b) >> t; 155 156 // 157 // Assemble the half from s, e (zero) and m. 158 // 159 160 return s | m; 161 } 162 else if (e == 0xff - (127 - 15)) 163 { 164 if (m == 0) 165 { 166 // 167 // F is an infinity; convert f to a half 168 // infinity with the same sign as f. 169 // 170 171 return s | 0x7c00; 172 } 173 else 174 { 175 // 176 // F is a NAN; we produce a half NAN that preserves 177 // the sign bit and the 10 leftmost bits of the 178 // significand of f, with one exception: If the 10 179 // leftmost bits are all zero, the NAN would turn 180 // into an infinity, so we have to set at least one 181 // bit in the significand. 182 // 183 184 m >>= 13; 185 return s | 0x7c00 | m | (m == 0); 186 } 187 } 188 else 189 { 190 // 191 // E is greater than zero. F is a normalized float. 192 // We try to convert f to a normalized half. 193 // 194 195 // 196 // Round to m to the nearest 10-bit value. In case of 197 // a tie, round to the nearest even value. 198 // 199 200 m = m + 0x00000fff + ((m >> 13) & 1); 201 202 if (m & 0x00800000) 203 { 204 m = 0; // overflow in significand, 205 e += 1; // adjust exponent 206 } 207 208 // 209 // Handle exponent overflow 210 // 211 212 if (e > 30) 213 { 214 overflow (); // Cause a hardware floating point overflow; 215 return s | 0x7c00; // if this returns, the half becomes an 216 } // infinity with the same sign as f. 217 218 // 219 // Assemble the half from s, e and m. 220 // 221 222 return s | (e << 10) | (m >> 13); 223 } 224} 225 226 227//--------------------- 228// Stream I/O operators 229//--------------------- 230 231ostream & 232operator << (ostream &os, half h) 233{ 234 os << float (h); 235 return os; 236} 237 238 239istream & 240operator >> (istream &is, half &h) 241{ 242 float f; 243 is >> f; 244 h = half (f); 245 return is; 246} 247 248 249//--------------------------------------- 250// Functions to print the bit-layout of 251// floats and halfs, mostly for debugging 252//--------------------------------------- 253 254void 255printBits (ostream &os, half h) 256{ 257 unsigned short b = h.bits(); 258 259 for (int i = 15; i >= 0; i--) 260 { 261 os << (((b >> i) & 1)? '1': '0'); 262 263 if (i == 15 || i == 10) 264 os << ' '; 265 } 266} 267 268 269void 270printBits (ostream &os, float f) 271{ 272 half::uif x; 273 x.f = f; 274 275 for (int i = 31; i >= 0; i--) 276 { 277 os << (((x.i >> i) & 1)? '1': '0'); 278 279 if (i == 31 || i == 23) 280 os << ' '; 281 } 282} 283 284 285void 286printBits (char c[19], half h) 287{ 288 unsigned short b = h.bits(); 289 290 for (int i = 15, j = 0; i >= 0; i--, j++) 291 { 292 c[j] = (((b >> i) & 1)? '1': '0'); 293 294 if (i == 15 || i == 10) 295 c[++j] = ' '; 296 } 297 298 c[18] = 0; 299} 300 301 302void 303printBits (char c[35], float f) 304{ 305 half::uif x; 306 x.f = f; 307 308 for (int i = 31, j = 0; i >= 0; i--, j++) 309 { 310 c[j] = (((x.i >> i) & 1)? '1': '0'); 311 312 if (i == 31 || i == 23) 313 c[++j] = ' '; 314 } 315 316 c[34] = 0; 317} 318