|
| 1 | + |
| 2 | +/////////////////////////////////////////////////////////////////////////////////// |
| 3 | +/* |
| 4 | +Copyright (c) 2006-2008, |
| 5 | +Chris "Krishty" Maiwald, Alexander "Aramis" Gessler |
| 6 | +
|
| 7 | +All rights reserved. |
| 8 | +
|
| 9 | +Redistribution and use of this software in source and binary forms, |
| 10 | +with or without modification, are permitted provided that the following |
| 11 | +conditions are met: |
| 12 | +
|
| 13 | +* Redistributions of source code must retain the above |
| 14 | + copyright notice, this list of conditions and the |
| 15 | + following disclaimer. |
| 16 | +
|
| 17 | +* Redistributions in binary form must reproduce the above |
| 18 | + copyright notice, this list of conditions and the |
| 19 | + following disclaimer in the documentation and/or other |
| 20 | + materials provided with the distribution. |
| 21 | +
|
| 22 | +* Neither the name of the class, nor the names of its |
| 23 | + contributors may be used to endorse or promote products |
| 24 | + derived from this software without specific prior |
| 25 | + written permission of the Development Team. |
| 26 | +
|
| 27 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 28 | +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 29 | +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 30 | +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 31 | +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 32 | +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 33 | +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 34 | +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 35 | +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 36 | +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 37 | +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 38 | +*/ |
| 39 | +/////////////////////////////////////////////////////////////////////////////////// |
| 40 | + |
| 41 | +#ifndef UM_HALF_H_INCLUDED |
| 42 | +#define UM_HALF_H_INCLUDED |
| 43 | + |
| 44 | +#include <limits> |
| 45 | +#include <algorithm> |
| 46 | + |
| 47 | +#ifdef _MSC_VER |
| 48 | +#include "stdint.h" |
| 49 | +#else |
| 50 | +#include <stdint.h> |
| 51 | +#endif |
| 52 | + |
| 53 | +#undef min |
| 54 | +#undef max |
| 55 | + |
| 56 | +/////////////////////////////////////////////////////////////////////////////////// |
| 57 | +/** 1. Represents a half-precision floating point value (16 bits) that behaves |
| 58 | + * nearly conformant to the IEE 754 standard for floating-point computations. |
| 59 | + * |
| 60 | + * Not all operators have special implementations, most perform time-consuming |
| 61 | + * conversions from half to float and back again. |
| 62 | + * Differences to IEEE 754: |
| 63 | + * - no difference between qnan and snan |
| 64 | + * - no traps |
| 65 | + * - no well-defined rounding mode |
| 66 | + */ |
| 67 | +/////////////////////////////////////////////////////////////////////////////////// |
| 68 | +class HalfFloat |
| 69 | +{ |
| 70 | + friend HalfFloat operator+ (HalfFloat, HalfFloat); |
| 71 | + friend HalfFloat operator- (HalfFloat, HalfFloat); |
| 72 | + friend HalfFloat operator* (HalfFloat, HalfFloat); |
| 73 | + friend HalfFloat operator/ (HalfFloat, HalfFloat); |
| 74 | + |
| 75 | +public: |
| 76 | + |
| 77 | + enum { BITS_MANTISSA = 10 }; |
| 78 | + enum { BITS_EXPONENT = 5 }; |
| 79 | + |
| 80 | + enum { MAX_EXPONENT_VALUE = 31 }; |
| 81 | + enum { BIAS = MAX_EXPONENT_VALUE/2 }; |
| 82 | + |
| 83 | + enum { MAX_EXPONENT = BIAS }; |
| 84 | + enum { MIN_EXPONENT = -BIAS }; |
| 85 | + |
| 86 | + enum { MAX_EXPONENT10 = 9 }; |
| 87 | + enum { MIN_EXPONENT10 = -9 }; |
| 88 | + |
| 89 | +public: |
| 90 | + |
| 91 | + /** Default constructor. Unitialized by default. |
| 92 | + */ |
| 93 | + inline HalfFloat() {} |
| 94 | + |
| 95 | + /** Construction from an existing half |
| 96 | + */ |
| 97 | + inline HalfFloat(const HalfFloat& other) |
| 98 | + : bits(other.GetBits()) |
| 99 | + {} |
| 100 | + |
| 101 | + /** Construction from existing values for mantissa, sign |
| 102 | + * and exponent. No validation is performed. |
| 103 | + * @note The exponent is unsigned and biased by #BIAS |
| 104 | + */ |
| 105 | + inline HalfFloat(uint16_t _m,uint16_t _e,uint16_t _s); |
| 106 | + |
| 107 | + |
| 108 | + /** Construction from a single-precision float |
| 109 | + */ |
| 110 | + inline HalfFloat(float other); |
| 111 | + |
| 112 | + /** Construction from a double-precision float |
| 113 | + */ |
| 114 | + inline HalfFloat(const double); |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | + /** Conversion operator to convert from half to float |
| 119 | + */ |
| 120 | + inline operator float() const; |
| 121 | + |
| 122 | + /** Conversion operator to convert from half to double |
| 123 | + */ |
| 124 | + inline operator double() const; |
| 125 | + |
| 126 | + |
| 127 | + |
| 128 | + /** Assignment operator to assign another half to |
| 129 | + * *this* object. |
| 130 | + */ |
| 131 | + inline HalfFloat& operator= (HalfFloat other); |
| 132 | + inline HalfFloat& operator= (float other); |
| 133 | + inline HalfFloat& operator= (const double other); |
| 134 | + |
| 135 | + |
| 136 | + /** Comparison operators |
| 137 | + */ |
| 138 | + inline bool operator== (HalfFloat other) const; |
| 139 | + inline bool operator!= (HalfFloat other) const; |
| 140 | + |
| 141 | + |
| 142 | + /** Relational comparison operators |
| 143 | + */ |
| 144 | + inline bool operator< (HalfFloat other) const; |
| 145 | + inline bool operator> (HalfFloat other) const; |
| 146 | + inline bool operator<= (HalfFloat other) const; |
| 147 | + inline bool operator>= (HalfFloat other) const; |
| 148 | + |
| 149 | + inline bool operator< (float other) const; |
| 150 | + inline bool operator> (float other) const; |
| 151 | + inline bool operator<= (float other) const; |
| 152 | + inline bool operator>= (float other) const; |
| 153 | + |
| 154 | + |
| 155 | + /** Combined assignment operators |
| 156 | + */ |
| 157 | + inline HalfFloat& operator += (HalfFloat other); |
| 158 | + inline HalfFloat& operator -= (HalfFloat other); |
| 159 | + inline HalfFloat& operator *= (HalfFloat other); |
| 160 | + inline HalfFloat& operator /= (HalfFloat other); |
| 161 | + |
| 162 | + inline HalfFloat& operator += (float other); |
| 163 | + inline HalfFloat& operator -= (float other); |
| 164 | + inline HalfFloat& operator *= (float other); |
| 165 | + inline HalfFloat& operator /= (float other); |
| 166 | + |
| 167 | + /** Post and prefix increment operators |
| 168 | + */ |
| 169 | + inline HalfFloat& operator++(); |
| 170 | + inline HalfFloat operator++(int); |
| 171 | + |
| 172 | + /** Post and prefix decrement operators |
| 173 | + */ |
| 174 | + inline HalfFloat& operator--(); |
| 175 | + inline HalfFloat operator--(int); |
| 176 | + |
| 177 | + /** Unary minus operator |
| 178 | + */ |
| 179 | + inline HalfFloat operator-() const; |
| 180 | + |
| 181 | + |
| 182 | + /** Provides direct access to the bits of a half float |
| 183 | + */ |
| 184 | + inline uint16_t GetBits() const; |
| 185 | + inline uint16_t& GetBits(); |
| 186 | + |
| 187 | + |
| 188 | + /** Classification of floating-point types |
| 189 | + */ |
| 190 | + inline bool IsNaN() const; |
| 191 | + inline bool IsInfinity() const; |
| 192 | + inline bool IsDenorm() const; |
| 193 | + |
| 194 | + /** Returns the sign of the floating-point value - |
| 195 | + * true stands for positive. |
| 196 | + */ |
| 197 | + inline bool GetSign() const; |
| 198 | + |
| 199 | +public: |
| 200 | + |
| 201 | + union |
| 202 | + { |
| 203 | + uint16_t bits; // All bits |
| 204 | + struct |
| 205 | + { |
| 206 | + uint16_t Frac : 10; // mantissa |
| 207 | + uint16_t Exp : 5; // exponent |
| 208 | + uint16_t Sign : 1; // sign |
| 209 | + } IEEE; |
| 210 | + }; |
| 211 | + |
| 212 | + |
| 213 | + union IEEESingle |
| 214 | + { |
| 215 | + float Float; |
| 216 | + struct |
| 217 | + { |
| 218 | + uint32_t Frac : 23; |
| 219 | + uint32_t Exp : 8; |
| 220 | + uint32_t Sign : 1; |
| 221 | + } IEEE; |
| 222 | + }; |
| 223 | + |
| 224 | + union IEEEDouble |
| 225 | + { |
| 226 | + double Double; |
| 227 | + struct { |
| 228 | + uint64_t Frac : 52; |
| 229 | + uint64_t Exp : 11; |
| 230 | + uint64_t Sign : 1; |
| 231 | + } IEEE; |
| 232 | + }; |
| 233 | + |
| 234 | + // Enums can not store 64 bit values, so we have to use static constants. |
| 235 | + static const uint64_t IEEEDouble_MaxExpontent = 0x7FF; |
| 236 | + static const uint64_t IEEEDouble_ExponentBias = IEEEDouble_MaxExpontent / 2; |
| 237 | +}; |
| 238 | + |
| 239 | +/** 2. Binary operations |
| 240 | + */ |
| 241 | +inline HalfFloat operator+ (HalfFloat one, HalfFloat two); |
| 242 | +inline HalfFloat operator- (HalfFloat one, HalfFloat two); |
| 243 | +inline HalfFloat operator* (HalfFloat one, HalfFloat two); |
| 244 | +inline HalfFloat operator/ (HalfFloat one, HalfFloat two); |
| 245 | + |
| 246 | +inline float operator+ (HalfFloat one, float two); |
| 247 | +inline float operator- (HalfFloat one, float two); |
| 248 | +inline float operator* (HalfFloat one, float two); |
| 249 | +inline float operator/ (HalfFloat one, float two); |
| 250 | + |
| 251 | +inline float operator+ (float one, HalfFloat two); |
| 252 | +inline float operator- (float one, HalfFloat two); |
| 253 | +inline float operator* (float one, HalfFloat two); |
| 254 | +inline float operator/ (float one, HalfFloat two); |
| 255 | + |
| 256 | + |
| 257 | + |
| 258 | +/////////////////////////////////////////////////////////////////////////////////// |
| 259 | +/** 3. Specialization of std::numeric_limits for type half. |
| 260 | + */ |
| 261 | +/////////////////////////////////////////////////////////////////////////////////// |
| 262 | +namespace std { |
| 263 | +template <> |
| 264 | +class numeric_limits<HalfFloat> { |
| 265 | + |
| 266 | + public: |
| 267 | + |
| 268 | + // General -- meaningful for all specializations. |
| 269 | + |
| 270 | + static const bool is_specialized = true; |
| 271 | + static HalfFloat min () |
| 272 | + {return HalfFloat(0,1,0);} |
| 273 | + static HalfFloat max () |
| 274 | + {return HalfFloat(~0,HalfFloat::MAX_EXPONENT_VALUE-1,0);} |
| 275 | + static const int radix = 2; |
| 276 | + static const int digits = 10; // conservative assumption |
| 277 | + static const int digits10 = 2; // conservative assumption |
| 278 | + static const bool is_signed = true; |
| 279 | + static const bool is_integer = true; |
| 280 | + static const bool is_exact = false; |
| 281 | + static const bool traps = false; |
| 282 | + static const bool is_modulo = false; |
| 283 | + static const bool is_bounded = true; |
| 284 | + |
| 285 | + // Floating point specific. |
| 286 | + |
| 287 | + static HalfFloat epsilon () |
| 288 | + {return HalfFloat(0.00097656f);} // from OpenEXR, needs to be confirmed |
| 289 | + static HalfFloat round_error () |
| 290 | + {return HalfFloat(0.00097656f/2);} |
| 291 | + static const int min_exponent10 = HalfFloat::MIN_EXPONENT10; |
| 292 | + static const int max_exponent10 = HalfFloat::MAX_EXPONENT10; |
| 293 | + static const int min_exponent = HalfFloat::MIN_EXPONENT; |
| 294 | + static const int max_exponent = HalfFloat::MAX_EXPONENT; |
| 295 | + |
| 296 | + static const bool has_infinity = true; |
| 297 | + static const bool has_quiet_NaN = true; |
| 298 | + static const bool has_signaling_NaN = true; |
| 299 | + static const bool is_iec559 = false; |
| 300 | + static const bool has_denorm = denorm_present; |
| 301 | + static const bool tinyness_before = false; |
| 302 | + static const float_round_style round_style = round_to_nearest; |
| 303 | + |
| 304 | + static HalfFloat denorm_min () |
| 305 | + {return HalfFloat(1,0,1);} |
| 306 | + static HalfFloat infinity () |
| 307 | + {return HalfFloat(0,HalfFloat::MAX_EXPONENT_VALUE,0);} |
| 308 | + static HalfFloat quiet_NaN () |
| 309 | + {return HalfFloat(1,HalfFloat::MAX_EXPONENT_VALUE,0);} |
| 310 | + static HalfFloat signaling_NaN () |
| 311 | + {return HalfFloat(1,HalfFloat::MAX_EXPONENT_VALUE,0);} |
| 312 | + }; |
| 313 | +} // end namespace std |
| 314 | + |
| 315 | + |
| 316 | +#include "./umHalf.inl" |
| 317 | + |
| 318 | +#ifndef UM_HALF_NO_TYPEDEFS |
| 319 | + typedef HalfFloat float16; |
| 320 | + typedef HalfFloat half; |
| 321 | +#endif |
| 322 | + |
| 323 | +#endif // !! UM_HALF_H_INCLUDED |
0 commit comments