VR-Vantage 3.0 API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
vrv_float16.h
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright (c) 2019 MAK Technologies, Inc.
3 ** All rights reserved.
4 ******************************************************************************/
5 
9 
10 #pragma once
11 
12 typedef unsigned short st_uint16;
13 typedef unsigned int st_uint32;
14 
15 // Half-to-float and Float-to-half code taken from "OpenGL ES 2.0
16 // Programming Guide" by Aaftab Munshi, Dan Ginsburg, and Dave Shreiner.
17 
18 
20 // Constants
21 
22 // -15 stored using a single precision bias of 127
23 const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
24 
25 // max exponent value in single precision that will be converted
26 // to Inf or Nan when stored as a half-float
27 const unsigned int HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
28 
29 // 255 is the max exponent biased value
30 const unsigned int FLOAT_MAX_BIASED_EXP = (0xFF << 23);
31 const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10);
32 
34 {
35 public:
36  vrv_float16();
37  vrv_float16(float fSinglePrecision);
38  vrv_float16(const vrv_float16& hfCopy);
39 
40  operator float(void) const;
41 
42 private:
44 };
45 
46 
48 // vrv_float16::vrv_float16
49 
51 {
52  *this = vrv_float16(0.0f);
53 }
54 
55 
57 // vrv_float16::vrv_float16
58 
59 inline vrv_float16::vrv_float16(float fSinglePrecision)
60 {
61  union
62  {
63  float f;
64  st_uint32 x;
65  };
66  // GNP not sure why this is needed but I see random craziness
67  if (fabs(fSinglePrecision) < .0001) {
68  fSinglePrecision = 0.0f;
69  }
70  f = fSinglePrecision;
71  st_uint32 sign = (st_uint16)(x >> 31);
72  st_uint32 mantissa;
73  st_uint32 exp;
74 
75  // get mantissa
76  mantissa = x & ((1 << 23) - 1);
77 
78  // get exponent bits
79  exp = x & FLOAT_MAX_BIASED_EXP;
80 
81  if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
82  {
83  // check if the original single precision float number is a NaN
84  if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
85  {
86  // we have a single precision NaN
87  mantissa = (1 << 23) - 1;
88  }
89  else
90  {
91  // 16-bit half-float representation stores number as Inf
92  mantissa = 0;
93  }
95  (st_uint16)(mantissa >> 13);
96  }
97  // check if exponent is <= -15
98  else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
99  {
100  // store a denorm half-float value or zero
101  exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
102  mantissa >>= (14 + exp);
103  m_uiValue = (((st_uint16)sign) << 15) | (st_uint16)(mantissa);
104  }
105  else
106  {
107  m_uiValue = (((st_uint16)sign) << 15) |
109  (st_uint16)(mantissa >> 13);
110  }
111 }
112 
113 
115 // st_float16::st_float16
116 
118 {
119  m_uiValue = hfCopy.m_uiValue;
120 }
121 
122 
124 // st_float16::operator st_float32
125 
126 inline vrv_float16::operator float(void) const
127 {
128  st_uint32 sign = (st_uint32)(m_uiValue >> 15);
129  st_uint32 mantissa = (st_uint32)(m_uiValue & ((1 << 10) - 1));
130  st_uint32 exp = (st_uint32)(m_uiValue & HALF_FLOAT_MAX_BIASED_EXP);
131  union
132  {
133  float f;
134  st_uint32 x;
135  };
136 
137  if (exp == HALF_FLOAT_MAX_BIASED_EXP)
138  {
139  // we have a half-float NaN or Inf
140  // half-float NaNs will be converted to a single precision NaN
141  // half-float Infs will be converted to a single precision Inf
142  exp = FLOAT_MAX_BIASED_EXP;
143 
144  if (mantissa)
145  mantissa = (1 << 23) - 1; // set all bits to indicate a NaN
146  }
147  else if (exp == 0x0)
148  {
149  // convert half-float zero/denorm to single precision value
150  if (mantissa)
151  {
152  mantissa <<= 1;
154 
155  // check for leading 1 in denorm mantissa
156  while ((mantissa & (1 << 10)) == 0)
157  {
158  // for every leading 0, decrement single precision exponent by 1
159  // and shift half-float mantissa value to the left
160  mantissa <<= 1;
161  exp -= (1 << 23);
162  }
163 
164  // clamp the mantissa to 10-bits
165  mantissa &= ((1 << 10) - 1);
166 
167  // shift left to generate single-precision mantissa of 23-bits
168  mantissa <<= 13;
169  }
170  }
171  else
172  {
173  // shift left to generate single-precision mantissa of 23-bits
174  mantissa <<= 13;
175 
176  // generate single precision biased exponent value
177  exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
178  }
179 
180  x = (sign << 31) | exp | mantissa;
181 
182  return f;
183 }


Copyright © 2005-2021 MAK Technologies. All Rights Reserved (www.mak.com)