Nebula
Loading...
Searching...
No Matches
half.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
11//------------------------------------------------------------------------------
12#include <limits>
13#include "core/types.h"
14namespace Math
15{
16
17
18
19class half
20{
21
22public:
23
25 inline half();
27 inline half(const half& h);
29 inline half(const float f);
30
32 inline operator float() const;
33
35 inline bool operator==(const half rhs) const;
37 inline bool operator==(const float rhs) const;
39 inline bool operator!=(const half rhs) const;
41 inline bool operator!=(const float rhs) const;
43 inline bool operator<(const half rhs) const;
45 inline bool operator<(const float rhs) const;
47 inline bool operator<=(const half rhs) const;
49 inline bool operator<=(const float rhs) const;
51 inline bool operator>(const half rhs) const;
53 inline bool operator>(const float rhs) const;
55 inline bool operator>=(const half rhs) const;
57 inline bool operator>=(const float rhs) const;
58
59 inline half& operator+=(half other);
60 inline half& operator-=(half other);
61 inline half& operator*=(half other);
62 inline half& operator/=(half other);
63
64 inline half operator-() const;
65
66private:
67
68 union Float
69 {
70 float f;
71 struct
72 {
73 uint32_t frac : 23;
74 uint32_t exp : 8;
75 uint32_t sign : 1;
77 };
78
79 friend class std::numeric_limits<Math::half>;
80 static const uint8_t BITS_MANTISSA = 10;
81 static const uint8_t BITS_EXPONENT = 5;
82 static const uint8_t MAX_EXPONENT_VALUE = 31;
83 static const uint8_t BIAS = MAX_EXPONENT_VALUE / 2;
84 static const uint8_t MAX_EXPONENT = BIAS;
85 static const uint8_t MIN_EXPONENT = -BIAS;
86 static const uint8_t MAX_EXPONENT10 = 9;
87 static const uint8_t MIN_EXPONENT10 = -9;
88
89 union
90 {
91 uint16_t bits;
92 struct
93 {
94 uint16_t frac : 10;
95 uint16_t exp : 5;
96 uint16_t sign : 1;
97 } ieee;
98 };
99};
100
101//------------------------------------------------------------------------------
104inline half
106{
107 return half((float)one + (float)two);
108}
109
110//------------------------------------------------------------------------------
113inline half
115{
116 return half(one + (-two));
117}
118
119//------------------------------------------------------------------------------
122inline half
124{
125 return half((float)one * (float)two);
126}
127
128//------------------------------------------------------------------------------
131inline half
133{
134 return half((float)one / (float)two);
135}
136
137//------------------------------------------------------------------------------
140inline half
141operator+ (half one, float two)
142{
143 return half((float)one + two);
144}
145
146//------------------------------------------------------------------------------
149inline half
150operator- (half one, float two)
151{
152 return half(one + (-two));
153}
154
155//------------------------------------------------------------------------------
158inline half
159operator* (half one, float two)
160{
161 return half((float)one * two);
162}
163
164//------------------------------------------------------------------------------
167inline half
168operator/ (half one, float two)
169{
170 return half((float)one / two);
171}
172
173//------------------------------------------------------------------------------
176inline float
177operator+ (float one, half two)
178{
179 return one + (float)two;
180}
181
182//------------------------------------------------------------------------------
185inline float
186operator- (float one, half two)
187{
188 return one - (float)two;
189}
190
191//------------------------------------------------------------------------------
194inline float
195operator* (float one, half two)
196{
197 return one * (float)two;
198}
199
200//------------------------------------------------------------------------------
203inline float
204operator/ (float one, half two)
205{
206 return one / (float)two;
207}
208
209//------------------------------------------------------------------------------
212inline
214{
215 this->bits = 0x0;
216}
217
218//------------------------------------------------------------------------------
221inline
223{
224 this->bits = h.bits;
225}
226
227//------------------------------------------------------------------------------
230inline
231half::half(const float f)
232{
233 Float fl;
234 fl.f = f;
235
236 this->ieee.sign = fl.ieee.sign;
237
238 if (!fl.ieee.exp)
239 {
240 this->ieee.frac = 0;
241 this->ieee.exp = 0;
242 }
243 else if (fl.ieee.exp == 0xFF)
244 {
245 this->ieee.frac = (fl.ieee.frac != 0) ? 1 : 0;
246 this->ieee.exp = 31;
247 }
248 else
249 {
250 int exp = fl.ieee.exp - 127;
251 if (exp < -24)
252 {
253 this->ieee.frac = 0;
254 this->ieee.exp = 0;
255 }
256 else if (exp < -14)
257 {
258 this->ieee.exp = 0;
259 uint expVal = (uint)(-14 - exp);
260 switch (expVal)
261 {
262 case 0:
263 this->ieee.frac = 0;
264 break;
265 case 1: this->ieee.frac = 512 + (fl.ieee.frac >> 14); break;
266 case 2: this->ieee.frac = 256 + (fl.ieee.frac >> 15); break;
267 case 3: this->ieee.frac = 128 + (fl.ieee.frac >> 16); break;
268 case 4: this->ieee.frac = 64 + (fl.ieee.frac >> 17); break;
269 case 5: this->ieee.frac = 32 + (fl.ieee.frac >> 18); break;
270 case 6: this->ieee.frac = 16 + (fl.ieee.frac >> 19); break;
271 case 7: this->ieee.frac = 8 + (fl.ieee.frac >> 20); break;
272 case 8: this->ieee.frac = 4 + (fl.ieee.frac >> 21); break;
273 case 9: this->ieee.frac = 2 + (fl.ieee.frac >> 22); break;
274 case 10: this->ieee.frac = 1; break;
275 }
276 }
277 else if (exp > 15)
278 {
279 this->ieee.frac = 0;
280 this->ieee.exp = 31;
281 }
282 else
283 {
284 this->ieee.frac = (fl.ieee.frac >> 13);
285 this->ieee.exp = exp + 15;
286 }
287 }
288}
289
290//------------------------------------------------------------------------------
293inline half::operator float() const
294{
295 Float f;
296 f.ieee.sign = this->ieee.sign;
297
298 if (!this->ieee.exp)
299 {
300 if (!this->ieee.frac)
301 {
302 f.ieee.frac = 0;
303 f.ieee.exp = 0;
304 }
305 else
306 {
307 const float half_denorm = (1.0f / 16384.0f);
308 float m = ((float)this->ieee.frac) / 1024.0f;
309 float s = this->ieee.sign ? -1.0f : 1.0f;
310 f.f = s * m * half_denorm;
311 }
312 }
313 else if (this->ieee.exp == 31)
314 {
315 f.ieee.exp = 0xff;
316 f.ieee.frac = this->ieee.frac != 0 ? 1 : 0;
317 }
318 else
319 {
320 f.ieee.exp = this->ieee.exp + 112;
321 f.ieee.frac = this->ieee.frac << 13;
322 }
323 return f.f;
324}
325
326//------------------------------------------------------------------------------
329inline bool
330half::operator==(const half rhs) const
331{
332 return this->bits == rhs.bits;
333}
334
335//------------------------------------------------------------------------------
338inline bool
339half::operator==(const float rhs) const
340{
341 return (float)(*this) == rhs;
342}
343
344//------------------------------------------------------------------------------
347inline bool
348half::operator!=(const half rhs) const
349{
350 return this->bits != rhs.bits;
351}
352
353//------------------------------------------------------------------------------
356inline bool
357half::operator!=(const float rhs) const
358{
359 return (float)(*this) != rhs;
360}
361
362//------------------------------------------------------------------------------
365inline bool
366half::operator<(const half rhs) const
367{
368 return (int16_t)this->bits < (int16_t)rhs.bits;
369}
370
371//------------------------------------------------------------------------------
374inline bool
375half::operator<(const float rhs) const
376{
377 return (float)(*this) < rhs;
378}
379
380//------------------------------------------------------------------------------
383inline bool
384half::operator<=(const half rhs) const
385{
386 return !(*this > rhs);
387}
388
389//------------------------------------------------------------------------------
392inline bool
393half::operator<=(const float rhs) const
394{
395 return !(*this > rhs);
396}
397
398//------------------------------------------------------------------------------
401inline bool
402half::operator>(const half rhs) const
403{
404 return (int16_t)this->bits > (int16_t)rhs.bits;
405}
406
407//------------------------------------------------------------------------------
410inline bool
411half::operator>(const float rhs) const
412{
413 return (float)(*this) > rhs;
414}
415
416//------------------------------------------------------------------------------
419inline bool
420half::operator>=(const half rhs) const
421{
422 return !(*this < rhs);
423}
424
425//------------------------------------------------------------------------------
428inline bool
429half::operator>=(const float rhs) const
430{
431 return !(*this < rhs);
432}
433
434//------------------------------------------------------------------------------
437inline half&
439{
440 *this = (*this) + other;
441 return *this;
442}
443
444//------------------------------------------------------------------------------
447inline half&
449{
450 *this = (*this) - other;
451 return *this;
452}
453
454//------------------------------------------------------------------------------
457inline half&
459{
460 *this = (float)(*this) * (float)other;
461 return *this;
462}
463
464//------------------------------------------------------------------------------
467inline half&
469{
470 *this = (float)(*this) / (float)other;
471 return *this;
472}
473
474//------------------------------------------------------------------------------
477inline half
479{
480 half ret = *this;
481 ret.ieee.sign = ~ret.ieee.sign;
482 return ret;
483}
484
485static_assert(sizeof(half) == 2);
486
487
488} // namespace Math
489
490namespace std
491{
492template <>
493class numeric_limits<Math::half>
494{
495public:
496
497 // General -- meaningful for all specializations.
498 static const bool is_specialized = true;
500 {
501 Math::half ret;
502 ret.ieee.frac = 0;
503 ret.ieee.exp = 1;
504 ret.ieee.sign = 0;
505 return ret;
506 }
508 {
509 Math::half ret;
510 ret.ieee.frac = ~0;
512 ret.ieee.sign = 0;
513 return ret;
514 }
515 static const int radix = 2;
516 static const int digits = 10; // conservative assumption
517 static const int digits10 = 2; // conservative assumption
518 static const bool is_signed = true;
519 static const bool is_integer = true;
520 static const bool is_exact = false;
521 static const bool traps = false;
522 static const bool is_modulo = false;
523 static const bool is_bounded = true;
524
525 // Floating point specific.
526
528 {
529 return Math::half(0.00097656f);
530 } // from OpenEXR, needs to be confirmed
532 {
533 return Math::half(0.00097656f / 2);
534 }
535 static const int min_exponent10 = Math::half::MIN_EXPONENT10;
536 static const int max_exponent10 = Math::half::MAX_EXPONENT10;
537 static const int min_exponent = Math::half::MIN_EXPONENT;
538 static const int max_exponent = Math::half::MAX_EXPONENT;
539
540 static const bool has_infinity = true;
541 static const bool has_quiet_NaN = true;
542 static const bool has_signaling_NaN = true;
543 static const bool is_iec559 = false;
544 static const bool has_denorm = denorm_present;
545 static const bool tinyness_before = false;
546 static const float_round_style round_style = round_to_nearest;
547
549 {
550 Math::half ret;
551 ret.ieee.frac = 1;
552 ret.ieee.exp = 0;
553 ret.ieee.sign = 1;
554 return ret;
555 }
557 {
558 Math::half ret;
559 ret.ieee.frac = 0;
561 ret.ieee.sign = 0;
562 return ret;
563 }
565 {
566 Math::half ret;
567 ret.ieee.frac = 1;
569 ret.ieee.sign = 0;
570 return ret;
571 }
573 {
574 Math::half ret;
575 ret.ieee.frac = 1;
577 ret.ieee.sign = 0;
578 return ret;
579 }
580};
581
582
583} // namespace std
Definition half.h:20
static const uint8_t MAX_EXPONENT
Definition half.h:84
half & operator-=(half other)
Definition half.h:448
uint16_t exp
Definition half.h:95
static const uint8_t MIN_EXPONENT
Definition half.h:85
uint16_t frac
Definition half.h:94
bool operator<=(const half rhs) const
Compare less equals.
Definition half.h:384
half operator-() const
Definition half.h:478
static const uint8_t MAX_EXPONENT10
Definition half.h:86
half()
Constructor.
Definition half.h:213
bool operator<(const half rhs) const
Compare less.
Definition half.h:366
struct Math::half::@22::@25 ieee
bool operator==(const half rhs) const
Compare equals.
Definition half.h:330
half & operator*=(half other)
Definition half.h:458
uint16_t bits
Definition half.h:91
uint16_t sign
Definition half.h:96
static const uint8_t BITS_MANTISSA
Definition half.h:80
static const uint8_t BIAS
Definition half.h:83
static const uint8_t BITS_EXPONENT
Definition half.h:81
half & operator/=(half other)
Definition half.h:468
half & operator+=(half other)
Definition half.h:438
bool operator!=(const half rhs) const
Compare not equals.
Definition half.h:348
static const uint8_t MAX_EXPONENT_VALUE
Definition half.h:82
bool operator>=(const half rhs) const
Compare greater equals.
Definition half.h:420
static const uint8_t MIN_EXPONENT10
Definition half.h:87
bool operator>(const half rhs) const
Compare greater.
Definition half.h:402
static Math::half max()
Definition half.h:507
static Math::half round_error()
Definition half.h:531
static Math::half epsilon()
Definition half.h:527
static Math::half quiet_NaN()
Definition half.h:564
static Math::half denorm_min()
Definition half.h:548
static Math::half infinity()
Definition half.h:556
static Math::half min()
Definition half.h:499
static Math::half signaling_NaN()
Definition half.h:572
Half precision (16 bit) float implementation.
Definition angularpfeedbackloop.h:17
half operator/(half one, half two)
Definition half.h:132
half operator-(half one, half two)
Definition half.h:114
half operator+(half one, half two)
Definition half.h:105
half operator*(half one, half two)
Definition half.h:123
Definition half.h:491
unsigned int uint
Definition types.h:31
Definition half.h:69
uint32_t exp
Definition half.h:74
float f
Definition half.h:70
uint32_t sign
Definition half.h:75
struct Math::half::Float::@24 ieee
uint32_t frac
Definition half.h:73