Coverage Report

Created: 2023-12-08 06:53

/src/freeimage-svn/FreeImage/trunk/Source/OpenEXR/Half/half.cpp
Line
Count
Source (jump to first uncovered line)
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
50
using namespace std;
51
52
//-------------------------------------------------------------
53
// Lookup tables for half-to-float and float-to-half conversion
54
//-------------------------------------------------------------
55
56
HALF_EXPORT const half::uif half::_toFloat[1 << 16] =
57
    #include "toFloat.h"
58
HALF_EXPORT const unsigned short half::_eLut[1 << 9] =
59
    #include "eLut.h"
60
61
//-----------------------------------------------
62
// Overflow handler for float-to-half conversion;
63
// generates a hardware floating-point overflow,
64
// which may be trapped by the operating system.
65
//-----------------------------------------------
66
67
HALF_EXPORT float
68
half::overflow ()
69
0
{
70
0
    volatile float f = 1e10;
71
72
0
    for (int i = 0; i < 10; i++) 
73
0
  f *= f;       // this will overflow before
74
          // the for­loop terminates
75
0
    return f;
76
0
}
77
78
79
//-----------------------------------------------------
80
// Float-to-half conversion -- general case, including
81
// zeroes, denormalized numbers and exponent overflows.
82
//-----------------------------------------------------
83
84
HALF_EXPORT short
85
half::convert (int i)
86
0
{
87
    //
88
    // Our floating point number, f, is represented by the bit
89
    // pattern in integer i.  Disassemble that bit pattern into
90
    // the sign, s, the exponent, e, and the significand, m.
91
    // Shift s into the position where it will go in in the
92
    // resulting half number.
93
    // Adjust e, accounting for the different exponent bias
94
    // of float and half (127 versus 15).
95
    //
96
97
0
    register int s =  (i >> 16) & 0x00008000;
98
0
    register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
99
0
    register int m =   i        & 0x007fffff;
100
101
    //
102
    // Now reassemble s, e and m into a half:
103
    //
104
105
0
    if (e <= 0)
106
0
    {
107
0
  if (e < -10)
108
0
  {
109
      //
110
      // E is less than -10.  The absolute value of f is
111
      // less than HALF_MIN (f may be a small normalized
112
      // float, a denormalized float or a zero).
113
      //
114
      // We convert f to a half zero with the same sign as f.
115
      //
116
117
0
      return s;
118
0
  }
119
120
  //
121
  // E is between -10 and 0.  F is a normalized float
122
  // whose magnitude is less than HALF_NRM_MIN.
123
  //
124
  // We convert f to a denormalized half.
125
  //
126
127
  //
128
  // Add an explicit leading 1 to the significand.
129
  // 
130
131
0
  m = m | 0x00800000;
132
133
  //
134
  // Round to m to the nearest (10+e)-bit value (with e between
135
  // -10 and 0); in case of a tie, round to the nearest even value.
136
  //
137
  // Rounding may cause the significand to overflow and make
138
  // our number normalized.  Because of the way a half's bits
139
  // are laid out, we don't have to treat this case separately;
140
  // the code below will handle it correctly.
141
  // 
142
143
0
  int t = 14 - e;
144
0
  int a = (1 << (t - 1)) - 1;
145
0
  int b = (m >> t) & 1;
146
147
0
  m = (m + a + b) >> t;
148
149
  //
150
  // Assemble the half from s, e (zero) and m.
151
  //
152
153
0
  return s | m;
154
0
    }
155
0
    else if (e == 0xff - (127 - 15))
156
0
    {
157
0
  if (m == 0)
158
0
  {
159
      //
160
      // F is an infinity; convert f to a half
161
      // infinity with the same sign as f.
162
      //
163
164
0
      return s | 0x7c00;
165
0
  }
166
0
  else
167
0
  {
168
      //
169
      // F is a NAN; we produce a half NAN that preserves
170
      // the sign bit and the 10 leftmost bits of the
171
      // significand of f, with one exception: If the 10
172
      // leftmost bits are all zero, the NAN would turn 
173
      // into an infinity, so we have to set at least one
174
      // bit in the significand.
175
      //
176
177
0
      m >>= 13;
178
0
      return s | 0x7c00 | m | (m == 0);
179
0
  }
180
0
    }
181
0
    else
182
0
    {
183
  //
184
  // E is greater than zero.  F is a normalized float.
185
  // We try to convert f to a normalized half.
186
  //
187
188
  //
189
  // Round to m to the nearest 10-bit value.  In case of
190
  // a tie, round to the nearest even value.
191
  //
192
193
0
  m = m + 0x00000fff + ((m >> 13) & 1);
194
195
0
  if (m & 0x00800000)
196
0
  {
197
0
      m =  0;   // overflow in significand,
198
0
      e += 1;   // adjust exponent
199
0
  }
200
201
  //
202
  // Handle exponent overflow
203
  //
204
205
0
  if (e > 30)
206
0
  {
207
0
      overflow ();  // Cause a hardware floating point overflow;
208
0
      return s | 0x7c00;  // if this returns, the half becomes an
209
0
  }        // infinity with the same sign as f.
210
211
  //
212
  // Assemble the half from s, e and m.
213
  //
214
215
0
  return s | (e << 10) | (m >> 13);
216
0
    }
217
0
}
218
219
220
//---------------------
221
// Stream I/O operators
222
//---------------------
223
224
HALF_EXPORT ostream &
225
operator << (ostream &os, half h)
226
0
{
227
0
    os << float (h);
228
0
    return os;
229
0
}
230
231
232
HALF_EXPORT istream &
233
operator >> (istream &is, half &h)
234
0
{
235
0
    float f;
236
0
    is >> f;
237
0
    h = half (f);
238
0
    return is;
239
0
}
240
241
242
//---------------------------------------
243
// Functions to print the bit-layout of
244
// floats and halfs, mostly for debugging
245
//---------------------------------------
246
247
HALF_EXPORT void
248
printBits (ostream &os, half h)
249
0
{
250
0
    unsigned short b = h.bits();
251
252
0
    for (int i = 15; i >= 0; i--)
253
0
    {
254
0
  os << (((b >> i) & 1)? '1': '0');
255
256
0
  if (i == 15 || i == 10)
257
0
      os << ' ';
258
0
    }
259
0
}
260
261
262
HALF_EXPORT void
263
printBits (ostream &os, float f)
264
0
{
265
0
    half::uif x;
266
0
    x.f = f;
267
268
0
    for (int i = 31; i >= 0; i--)
269
0
    {
270
0
  os << (((x.i >> i) & 1)? '1': '0');
271
272
0
  if (i == 31 || i == 23)
273
0
      os << ' ';
274
0
    }
275
0
}
276
277
278
HALF_EXPORT void
279
printBits (char c[19], half h)
280
0
{
281
0
    unsigned short b = h.bits();
282
283
0
    for (int i = 15, j = 0; i >= 0; i--, j++)
284
0
    {
285
0
  c[j] = (((b >> i) & 1)? '1': '0');
286
287
0
  if (i == 15 || i == 10)
288
0
      c[++j] = ' ';
289
0
    }
290
    
291
0
    c[18] = 0;
292
0
}
293
294
295
HALF_EXPORT void
296
printBits (char c[35], float f)
297
0
{
298
0
    half::uif x;
299
0
    x.f = f;
300
301
0
    for (int i = 31, j = 0; i >= 0; i--, j++)
302
0
    {
303
0
  c[j] = (((x.i >> i) & 1)? '1': '0');
304
305
0
  if (i == 31 || i == 23)
306
0
      c[++j] = ' ';
307
0
    }
308
309
0
    c[34] = 0;
310
0
}