yum-mirror/glslang
git clone https://git.yummers.dev/yum-mirror/glslang
62f5430e
main
1// Copyright (c) 2015-2016 The Khronos Group Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ 16#define LIBSPIRV_UTIL_HEX_FLOAT_H_ 17 18#include <cassert> 19#include <cctype> 20#include <cmath> 21#include <cstdint> 22#include <iomanip> 23#include <limits> 24#include <sstream> 25 26#include "bitutils.h" 27 28namespace spvutils { 29 30class Float16 { 31public : 32Float16 (uint16_t v ) :val (v ) {} 33Float16 () {} 34static bool isNan (const Float16 & val ) { 35return ((val .val & 0x7C00 )== 0x7C00 )&& ((val .val & 0x3FF )!= 0 ); 36 } 37// Returns true if the given value is any kind of infinity. 38static bool isInfinity (const Float16 & val ) { 39return ((val .val & 0x7C00 )== 0x7C00 )&& ((val .val & 0x3FF )== 0 ); 40 } 41Float16 (const Float16 & other ) {val = other .val ; } 42uint16_t get_value ()const {return val ; } 43 44// Returns the maximum normal value. 45static Float16 max () {return Float16 (0x7bff ); } 46// Returns the lowest normal value. 47static Float16 lowest () {return Float16 (0xfbff ); } 48 49private : 50uint16_t val ; 51}; 52 53class FloatE5M2 { 54public : 55FloatE5M2 (uint8_t v ) :val (v ) {} 56FloatE5M2 () {} 57static bool isNan (const FloatE5M2 & val ) { 58return ((val .val & 0x7C )== 0x7C )&& ((val .val & 0x3 )!= 0 ); 59 } 60// Returns true if the given value is any kind of infinity. 61static bool isInfinity (const FloatE5M2 & val ) { 62return ((val .val & 0x7C )== 0x7C )&& ((val .val & 0x3 )== 0 ); 63 } 64FloatE5M2 (const FloatE5M2 & other ) {val = other .val ; } 65uint8_t get_value ()const {return val ; } 66 67// Returns the maximum normal value. 68static FloatE5M2 max () {return FloatE5M2 (0x7B ); } 69// Returns the lowest normal value. 70static FloatE5M2 lowest () {return FloatE5M2 (0xFB ); } 71 72private : 73uint8_t val ; 74}; 75 76class FloatE4M3 { 77public : 78FloatE4M3 (uint8_t v ) :val (v ) {} 79FloatE4M3 () {} 80static bool isNan (const FloatE4M3 & val ) { 81return (val .val & 0x7F )== 0x7F ; 82 } 83// Returns true if the given value is any kind of infinity. 84static bool isInfinity (const FloatE4M3 & ) { 85return false; 86 } 87FloatE4M3 (const FloatE4M3 & other ) {val = other .val ; } 88uint8_t get_value ()const {return val ; } 89 90// Returns the maximum normal value. 91static FloatE4M3 max () {return FloatE4M3 (0x7E ); } 92// Returns the lowest normal value. 93static FloatE4M3 lowest () {return FloatE4M3 (0xFE ); } 94 95private : 96uint8_t val ; 97}; 98 99class FloatE2M1 { 100public : 101FloatE2M1 (uint8_t v ) :val (v ) {} 102FloatE2M1 () {} 103static bool isNan (const FloatE2M1 & val ) { 104static_cast < void > (val ); 105return false; 106 } 107// Returns true if the given value is any kind of infinity. 108static bool isInfinity (const FloatE2M1 & val ) { 109static_cast < void > (val ); 110return false; 111 } 112FloatE2M1 (const FloatE2M1 & other ) {val = other .val ; } 113uint8_t get_value ()const {return val ; } 114 115// Returns the maximum normal value. 116static FloatE2M1 max () {return FloatE2M1 (0x7 ); } 117// Returns the lowest normal value. 118static FloatE2M1 lowest () {return FloatE2M1 (0xF ); } 119 120private : 121uint8_t val ; 122}; 123 124class FloatE3M2 { 125public : 126FloatE3M2 (uint8_t v ) :val (v ) {} 127FloatE3M2 () {} 128static bool isNan (const FloatE3M2 & val ) { 129static_cast < void > (val ); 130return false; 131 } 132// Returns true if the given value is any kind of infinity. 133static bool isInfinity (const FloatE3M2 & val ) { 134static_cast < void > (val ); 135return false; 136 } 137FloatE3M2 (const FloatE3M2 & other ) {val = other .val ; } 138uint8_t get_value ()const {return val ; } 139 140// Returns the maximum normal value. 141static FloatE3M2 max () {return FloatE3M2 (0x1F ); } 142// Returns the lowest normal value. 143static FloatE3M2 lowest () {return FloatE3M2 (0x3F ); } 144 145private : 146uint8_t val ; 147}; 148 149class FloatE2M3 { 150public : 151FloatE2M3 (uint8_t v ) :val (v ) {} 152FloatE2M3 () {} 153static bool isNan (const FloatE2M3 & val ) { 154static_cast < void > (val ); 155return false; 156 } 157// Returns true if the given value is any kind of infinity. 158static bool isInfinity (const FloatE2M3 & val ) { 159static_cast < void > (val ); 160return false; 161 } 162FloatE2M3 (const FloatE2M3 & other ) {val = other .val ; } 163uint8_t get_value ()const {return val ; } 164 165// Returns the maximum normal value. 166static FloatE2M3 max () {return FloatE2M3 (0x1F ); } 167// Returns the lowest normal value. 168static FloatE2M3 lowest () {return FloatE2M3 (0x3F ); } 169 170private : 171uint8_t val ; 172}; 173 174// To specialize this type, you must override uint_type to define 175// an unsigned integer that can fit your floating point type. 176// You must also add a isNan function that returns true if 177// a value is Nan. 178template < typename T > 179struct FloatProxyTraits { 180typedef void uint_type ; 181}; 182 183template <> 184struct FloatProxyTraits < float > { 185typedef uint32_t uint_type ; 186static bool isNan (float f ) {return std ::isnan (f ); } 187// Returns true if the given value is any kind of infinity. 188static bool isInfinity (float f ) {return std ::isinf (f ); } 189// Returns the maximum normal value. 190static float max () {return std ::numeric_limits < float > ::max (); } 191// Returns the lowest normal value. 192static float lowest () {return std ::numeric_limits < float > ::lowest (); } 193}; 194 195template <> 196struct FloatProxyTraits < double > { 197typedef uint64_t uint_type ; 198static bool isNan (double f ) {return std ::isnan (f ); } 199// Returns true if the given value is any kind of infinity. 200static bool isInfinity (double f ) {return std ::isinf (f ); } 201// Returns the maximum normal value. 202static double max () {return std ::numeric_limits < double > ::max (); } 203// Returns the lowest normal value. 204static double lowest () {return std ::numeric_limits < double > ::lowest (); } 205}; 206 207template <> 208struct FloatProxyTraits < Float16 > { 209typedef uint16_t uint_type ; 210static bool isNan (Float16 f ) {return Float16 ::isNan (f ); } 211// Returns true if the given value is any kind of infinity. 212static bool isInfinity (Float16 f ) {return Float16 ::isInfinity (f ); } 213// Returns the maximum normal value. 214static Float16 max () {return Float16 ::max (); } 215// Returns the lowest normal value. 216static Float16 lowest () {return Float16 ::lowest (); } 217}; 218 219template <> 220struct FloatProxyTraits < FloatE5M2 > { 221typedef uint8_t uint_type ; 222static bool isNan (FloatE5M2 f ) {return FloatE5M2 ::isNan (f ); } 223// Returns true if the given value is any kind of infinity. 224static bool isInfinity (FloatE5M2 f ) {return FloatE5M2 ::isInfinity (f ); } 225// Returns the maximum normal value. 226static FloatE5M2 max () {return FloatE5M2 ::max (); } 227// Returns the lowest normal value. 228static FloatE5M2 lowest () {return FloatE5M2 ::lowest (); } 229}; 230 231template <> 232struct FloatProxyTraits < FloatE4M3 > { 233typedef uint8_t uint_type ; 234static bool isNan (FloatE4M3 f ) {return FloatE4M3 ::isNan (f ); } 235// Returns true if the given value is any kind of infinity. 236static bool isInfinity (FloatE4M3 f ) {return FloatE4M3 ::isInfinity (f ); } 237// Returns the maximum normal value. 238static FloatE4M3 max () {return FloatE4M3 ::max (); } 239// Returns the lowest normal value. 240static FloatE4M3 lowest () {return FloatE4M3 ::lowest (); } 241}; 242 243template <> 244struct FloatProxyTraits < FloatE2M1 > { 245typedef uint8_t uint_type ; 246static bool isNan (FloatE2M1 f ) {return FloatE2M1 ::isNan (f ); } 247// Returns true if the given value is any kind of infinity. 248static bool isInfinity (FloatE2M1 f ) {return FloatE2M1 ::isInfinity (f ); } 249// Returns the maximum normal value. 250static FloatE2M1 max () {return FloatE2M1 ::max (); } 251// Returns the lowest normal value. 252static FloatE2M1 lowest () {return FloatE2M1 ::lowest (); } 253}; 254 255template <> 256struct FloatProxyTraits < FloatE3M2 > { 257typedef uint8_t uint_type ; 258static bool isNan (FloatE3M2 f ) {return FloatE3M2 ::isNan (f ); } 259// Returns true if the given value is any kind of infinity. 260static bool isInfinity (FloatE3M2 f ) {return FloatE3M2 ::isInfinity (f ); } 261// Returns the maximum normal value. 262static FloatE3M2 max () {return FloatE3M2 ::max (); } 263// Returns the lowest normal value. 264static FloatE3M2 lowest () {return FloatE3M2 ::lowest (); } 265}; 266 267template <> 268struct FloatProxyTraits < FloatE2M3 > { 269typedef uint8_t uint_type ; 270static bool isNan (FloatE2M3 f ) {return FloatE2M3 ::isNan (f ); } 271// Returns true if the given value is any kind of infinity. 272static bool isInfinity (FloatE2M3 f ) {return FloatE2M3 ::isInfinity (f ); } 273// Returns the maximum normal value. 274static FloatE2M3 max () {return FloatE2M3 ::max (); } 275// Returns the lowest normal value. 276static FloatE2M3 lowest () {return FloatE2M3 ::lowest (); } 277}; 278 279// Since copying a floating point number (especially if it is NaN) 280// does not guarantee that bits are preserved, this class lets us 281// store the type and use it as a float when necessary. 282template < typename T > 283class FloatProxy { 284public : 285typedef typename FloatProxyTraits < T > ::uint_type uint_type ; 286 287// Since this is to act similar to the normal floats, 288// do not initialize the data by default. 289FloatProxy () {} 290 291// Intentionally non-explicit. This is a proxy type so 292// implicit conversions allow us to use it more transparently. 293FloatProxy (T val ) {data_ = BitwiseCast < uint_type > (val ); } 294 295// Intentionally non-explicit. This is a proxy type so 296// implicit conversions allow us to use it more transparently. 297FloatProxy (uint_type val ) {data_ = val ; } 298 299// This is helpful to have and is guaranteed not to stomp bits. 300FloatProxy < T > operator - () const ; 301 302// Returns the data as a floating point value. 303T getAsFloat () const { return BitwiseCast < T > ( data_ ); } 304 305// Returns the raw data. 306uint_type data () const { return data_ ; } 307 308// Returns true if the value represents any type of NaN. 309bool isNan () { return FloatProxyTraits < T > :: isNan ( getAsFloat ()); } 310// Returns true if the value represents any type of infinity. 311bool isInfinity () { return FloatProxyTraits < T > :: isInfinity ( getAsFloat ()); } 312 313// Returns the maximum normal value. 314static FloatProxy < T > max () { 315return FloatProxy < T > ( FloatProxyTraits < T > :: max ()); 316} 317// Returns the lowest normal value. 318static FloatProxy < T > lowest () { 319return FloatProxy < T > ( FloatProxyTraits < T > :: lowest ()); 320} 321 322private : 323uint_type data_ ; 324}; 325 326template < typename T > 327bool operator == ( const FloatProxy < T >& first , const FloatProxy < T >& second ) { 328return first . data () == second . data (); 329} 330 331// Reads a FloatProxy value as a normal float from a stream. 332template < typename T > 333std :: istream & operator >>( std :: istream & is , FloatProxy < T >& value ) { 334T float_val ; 335is >> float_val ; 336value = FloatProxy < T > ( float_val ); 337return is ; 338} 339 340// This is an example traits. It is not meant to be used in practice, but will 341// be the default for any non-specialized type. 342template < typename T > 343struct HexFloatTraits { 344// Integer type that can store this hex-float. 345typedef void uint_type; 346// Signed integer type that can store this hex-float. 347typedef void int_type; 348// The numerical type that this HexFloat represents. 349typedef void underlying_type; 350// The type needed to construct the underlying type. 351typedef void native_type; 352// The number of bits that are actually relevant in the uint_type. 353// This allows us to deal with, for example, 24-bit values in a 32-bit 354// integer. 355static const uint32_t num_used_bits = 0 ; 356// Number of bits that represent the exponent. 357static const uint32_t num_exponent_bits = 0 ; 358// Number of bits that represent the fractional part. 359static const uint32_t num_fraction_bits = 0 ; 360// The bias of the exponent. (How much we need to subtract from the stored 361// value to get the correct value.) 362static const uint32_t exponent_bias = 0 ; 363static bool supportsInfinity () { return true; } 364}; 365 366// Traits for IEEE float. 367// 1 sign bit, 8 exponent bits, 23 fractional bits. 368template <> 369struct HexFloatTraits < FloatProxy < float>> { 370typedef uint32_t uint_type; 371typedef int32_t int_type; 372typedef FloatProxy < float > underlying_type; 373typedef float native_type; 374static const uint_type num_used_bits = 32 ; 375static const uint_type num_exponent_bits = 8 ; 376static const uint_type num_fraction_bits = 23 ; 377static const uint_type exponent_bias = 127 ; 378static bool supportsInfinity () { return true; } 379}; 380 381// Traits for IEEE double. 382// 1 sign bit, 11 exponent bits, 52 fractional bits. 383template <> 384struct HexFloatTraits < FloatProxy < double>> { 385typedef uint64_t uint_type; 386typedef int64_t int_type; 387typedef FloatProxy < double > underlying_type; 388typedef double native_type; 389static const uint_type num_used_bits = 64 ; 390static const uint_type num_exponent_bits = 11 ; 391static const uint_type num_fraction_bits = 52 ; 392static const uint_type exponent_bias = 1023 ; 393static bool supportsInfinity () { return true; } 394}; 395 396// Traits for IEEE half. 397// 1 sign bit, 5 exponent bits, 10 fractional bits. 398template <> 399struct HexFloatTraits < FloatProxy < Float16 >> { 400typedef uint16_t uint_type; 401typedef int16_t int_type; 402typedef uint16_t underlying_type; 403typedef uint16_t native_type; 404static const uint_type num_used_bits = 16 ; 405static const uint_type num_exponent_bits = 5 ; 406static const uint_type num_fraction_bits = 10 ; 407static const uint_type exponent_bias = 15 ; 408static bool supportsInfinity () { return true; } 409}; 410 411template <> 412struct HexFloatTraits < FloatProxy < FloatE5M2 >> { 413typedef uint8_t uint_type; 414typedef int8_t int_type; 415typedef uint8_t underlying_type; 416typedef uint8_t native_type; 417static const uint_type num_used_bits = 8 ; 418static const uint_type num_exponent_bits = 5 ; 419static const uint_type num_fraction_bits = 2 ; 420static const uint_type exponent_bias = 15 ; 421static bool supportsInfinity () { return true; } 422}; 423 424template <> 425struct HexFloatTraits < FloatProxy < FloatE4M3 >> { 426typedef uint8_t uint_type; 427typedef int8_t int_type; 428typedef uint8_t underlying_type; 429typedef uint8_t native_type; 430static const uint_type num_used_bits = 8 ; 431static const uint_type num_exponent_bits = 4 ; 432static const uint_type num_fraction_bits = 3 ; 433static const uint_type exponent_bias = 7 ; 434static bool supportsInfinity () { return false; } 435}; 436 437template <> 438struct HexFloatTraits < FloatProxy < FloatE2M1 >> { 439typedef uint8_t uint_type; 440typedef int8_t int_type; 441typedef uint8_t underlying_type; 442typedef uint8_t native_type; 443static const uint_type num_used_bits = 4 ; 444static const uint_type num_exponent_bits = 2 ; 445static const uint_type num_fraction_bits = 1 ; 446static const uint_type exponent_bias = 1 ; 447static bool supportsInfinity () { return false; } 448}; 449 450template <> 451struct HexFloatTraits < FloatProxy < FloatE3M2 >> { 452typedef uint8_t uint_type; 453typedef int8_t int_type; 454typedef uint8_t underlying_type; 455typedef uint8_t native_type; 456static const uint_type num_used_bits = 6 ; 457static const uint_type num_exponent_bits = 3 ; 458static const uint_type num_fraction_bits = 2 ; 459static const uint_type exponent_bias = 3 ; 460static bool supportsInfinity () { return false; } 461}; 462 463template <> 464struct HexFloatTraits < FloatProxy < FloatE2M3 >> { 465typedef uint8_t uint_type; 466typedef int8_t int_type; 467typedef uint8_t underlying_type; 468typedef uint8_t native_type; 469static const uint_type num_used_bits = 6 ; 470static const uint_type num_exponent_bits = 2 ; 471static const uint_type num_fraction_bits = 3 ; 472static const uint_type exponent_bias = 1 ; 473static bool supportsInfinity () { return false; } 474}; 475 476enum round_direction { 477kRoundToZero , 478kRoundToNearestEven , 479kRoundToPositiveInfinity , 480kRoundToNegativeInfinity 481}; 482 483// This is helpful to have and is guaranteed not to stomp bits. 484template < typename T > 485FloatProxy < T > FloatProxy < T > :: operator - () const { 486return static_cast < uint_type > ( data_ ^ 487( uint_type ( 0x1 ) << ( HexFloatTraits < FloatProxy < T >>:: num_used_bits - 1 ))); 488} 489 490// Template class that houses a floating pointer number. 491// It exposes a number of constants based on the provided traits to 492// assist in interpreting the bits of the value. 493template < typename T , typename Traits = HexFloatTraits < T >> 494class HexFloat { 495public : 496typedef typename Traits ::uint_type uint_type ; 497typedef typename Traits::int_type int_type; 498typedef typename Traits::underlying_type underlying_type; 499typedef typename Traits::native_type native_type; 500using Traits_T = Traits ; 501 502explicit HexFloat (T f ) : value_ ( f ) {} 503 504T value () const { return value_ ; } 505void set_value (T f ) { value_ = f ; } 506 507// These are all written like this because it is convenient to have 508// compile-time constants for all of these values. 509 510// Pass-through values to save typing. 511static const uint32_t num_used_bits = Traits :: num_used_bits ; 512static const uint32_t exponent_bias = Traits :: exponent_bias ; 513static const uint32_t num_exponent_bits = Traits :: num_exponent_bits ; 514static const uint32_t num_fraction_bits = Traits :: num_fraction_bits ; 515 516// Number of bits to shift left to set the highest relevant bit. 517static const uint32_t top_bit_left_shift = num_used_bits - 1 ; 518// How many nibbles (hex characters) the fractional part takes up. 519static const uint32_t fraction_nibbles = ( num_fraction_bits + 3 ) / 4 ; 520// If the fractional part does not fit evenly into a hex character (4-bits) 521// then we have to left-shift to get rid of leading 0s. This is the amount 522// we have to shift (might be 0). 523static const uint32_t num_overflow_bits = 524fraction_nibbles * 4 - num_fraction_bits ; 525 526// The representation of the fraction, not the actual bits. This 527// includes the leading bit that is usually implicit. 528static const uint_type fraction_represent_mask = 529spvutils :: SetBits < uint_type , 0 , 530num_fraction_bits + num_overflow_bits > :: get ; 531 532// The topmost bit in the nibble-aligned fraction. 533static const uint_type fraction_top_bit = 534uint_type ( 1 ) << ( num_fraction_bits + num_overflow_bits - 1 ); 535 536// The least significant bit in the exponent, which is also the bit 537// immediately to the left of the significand. 538static const uint_type first_exponent_bit = uint_type ( 1 ) 539<< ( num_fraction_bits ); 540 541// The mask for the encoded fraction. It does not include the 542// implicit bit. 543static const uint_type fraction_encode_mask = 544spvutils :: SetBits < uint_type , 0 , num_fraction_bits > :: get ; 545 546// The bit that is used as a sign. 547static const uint_type sign_mask = uint_type ( 1 ) << top_bit_left_shift ; 548 549// The set of all used bits 550static const uint_type used_bits_mask = 551( uint_type ( 1 ) << ( num_used_bits - 1 )) | 552(( uint_type ( 1 ) << ( num_used_bits - 1 )) - 1 ); 553 554// The bits that represent the exponent. 555static const uint_type exponent_mask = 556spvutils :: SetBits < uint_type , num_fraction_bits , num_exponent_bits > :: get ; 557 558// How far left the exponent is shifted. 559static const uint32_t exponent_left_shift = num_fraction_bits ; 560 561// How far from the right edge the fraction is shifted. 562static const uint32_t fraction_right_shift = 563static_cast < uint32_t > ( sizeof ( uint_type ) * 8 ) - num_fraction_bits ; 564 565// The maximum representable unbiased exponent. 566static const int_type max_exponent = 567( exponent_mask >> num_fraction_bits ) - exponent_bias ; 568// The minimum representable exponent for normalized numbers. 569static const int_type min_exponent = - static_cast < int_type > ( exponent_bias ); 570 571// Returns the bits associated with the value. 572uint_type getBits () const { return spvutils:: BitwiseCast < uint_type > ( value_ ); } 573 574// Returns the bits associated with the value, without the leading sign bit. 575uint_type getUnsignedBits () const { 576return static_cast < uint_type > ( spvutils :: BitwiseCast < uint_type > ( value_ ) & 577~ sign_mask ); 578} 579 580// Returns the bits associated with the exponent, shifted to start at the 581// lsb of the type. 582const uint_type getExponentBits () const { 583return static_cast < uint_type > (( getBits () & exponent_mask ) >> 584num_fraction_bits ); 585} 586 587// Returns the exponent in unbiased form. This is the exponent in the 588// human-friendly form. 589const int_type getUnbiasedExponent () const { 590return static_cast < int_type > ( getExponentBits () - exponent_bias ); 591} 592 593// Returns just the significand bits from the value. 594const uint_type getSignificandBits () const { 595return getBits () & fraction_encode_mask ; 596} 597 598// If the number was normalized, returns the unbiased exponent. 599// If the number was denormal, normalize the exponent first. 600const int_type getUnbiasedNormalizedExponent () const { 601if (( getBits () & ~ sign_mask ) == 0 ) { // special case if everything is 0 602return 0 ; 603} 604int_type exp = getUnbiasedExponent (); 605if ( exp == min_exponent ) { // We are in denorm land. 606uint_type significand_bits = getSignificandBits (); 607while (( significand_bits & ( first_exponent_bit >> 1 )) == 0 ) { 608significand_bits = static_cast < uint_type > ( significand_bits << 1 ); 609exp = static_cast < int_type > ( exp - 1 ); 610} 611significand_bits &= fraction_encode_mask ; 612} 613return exp ; 614} 615 616// Returns the signficand after it has been normalized. 617const uint_type getNormalizedSignificand () const { 618int_type unbiased_exponent = getUnbiasedNormalizedExponent (); 619uint_type significand = getSignificandBits (); 620for (int_type i = unbiased_exponent ; i <= min_exponent ; ++ i) { 621significand = static_cast < uint_type > ( significand << 1 ); 622} 623significand &= fraction_encode_mask ; 624return significand ; 625} 626 627// Returns true if this number represents a negative value. 628bool isNegative () const { return ( getBits () & sign_mask ) != 0 ; } 629 630// Sets this HexFloat from the individual components. 631// Note this assumes EVERY significand is normalized, and has an implicit 632// leading one. This means that the only way that this method will set 0, 633// is if you set a number so denormalized that it underflows. 634// Do not use this method with raw bits extracted from a subnormal number, 635// since subnormals do not have an implicit leading 1 in the significand. 636// The significand is also expected to be in the 637// lowest-most num_fraction_bits of the uint_type. 638// The exponent is expected to be unbiased, meaning an exponent of 639// 0 actually means 0. 640// If underflow_round_up is set, then on underflow, if a number is non-0 641// and would underflow, we round up to the smallest denorm. 642void setFromSignUnbiasedExponentAndNormalizedSignificand ( 643bool negative , int_type exponent , uint_type significand , 644bool round_denorm_up ) { 645bool significand_is_zero = significand == 0 ; 646 647if ( exponent <= min_exponent ) { 648// If this was denormalized, then we have to shift the bit on, meaning 649// the significand is not zero. 650significand_is_zero = false; 651significand |= first_exponent_bit ; 652significand = static_cast < uint_type > ( significand >> 1 ); 653} 654 655while ( exponent < min_exponent ) { 656significand = static_cast < uint_type > ( significand >> 1 ); 657++ exponent ; 658} 659 660if ( exponent == min_exponent ) { 661if ( significand == 0 && ! significand_is_zero && round_denorm_up ) { 662significand = static_cast < uint_type > ( 0x1 ); 663} 664} 665 666uint_type new_value = 0 ; 667if ( negative ) { 668new_value = static_cast < uint_type > ( new_value | sign_mask ); 669} 670exponent = static_cast < int_type > ( exponent + exponent_bias ); 671assert ( exponent >= 0 ); 672 673// put it all together 674exponent = static_cast < uint_type > (( exponent << exponent_left_shift ) & 675exponent_mask ); 676significand = static_cast < uint_type > ( significand & fraction_encode_mask ); 677new_value = static_cast < uint_type > ( new_value | ( exponent | significand )); 678value_ = BitwiseCast < T > ( new_value ); 679} 680 681// Increments the significand of this number by the given amount. 682// If this would spill the significand into the implicit bit, 683// carry is set to true and the significand is shifted to fit into 684// the correct location, otherwise carry is set to false. 685// All significands and to_increment are assumed to be within the bounds 686// for a valid significand. 687static uint_type incrementSignificand (uint_type significand , 688uint_type to_increment , bool * carry ) { 689significand = static_cast < uint_type > ( significand + to_increment ); 690* carry = false; 691if ( significand & first_exponent_bit ) { 692* carry = true; 693// The implicit 1-bit will have carried, so we should zero-out the 694// top bit and shift back. 695significand = static_cast < uint_type > ( significand & ~ first_exponent_bit ); 696significand = static_cast < uint_type > ( significand >> 1 ); 697} 698return significand ; 699} 700 701// These exist because MSVC throws warnings on negative right-shifts 702// even if they are not going to be executed. Eg: 703// constant_number < 0? 0: constant_number 704// These convert the negative left-shifts into right shifts. 705 706template < typename int_type > 707uint_type negatable_left_shift ( int_type N , uint_type val ) 708{ 709if ( N >= 0 ) 710return val << N ; 711 712return val >> - N ; 713} 714 715template < typename int_type > 716uint_type negatable_right_shift ( int_type N , uint_type val ) 717{ 718if ( N >= 0 ) 719return val >> N ; 720 721return val << - N ; 722} 723 724// Returns the significand, rounded to fit in a significand in 725// other_T. This is shifted so that the most significant 726// bit of the rounded number lines up with the most significant bit 727// of the returned significand. 728template < typename other_T > 729typename other_T ::uint_type getRoundedNormalizedSignificand ( 730round_direction dir , bool * carry_bit ) { 731typedef typename other_T::uint_type other_uint_type; 732static const int_type num_throwaway_bits = 733static_cast < int_type > ( num_fraction_bits ) - 734static_cast < int_type > ( other_T :: num_fraction_bits ); 735 736static const uint_type last_significant_bit = 737( num_throwaway_bits < 0 ) 738? 0 739: negatable_left_shift ( num_throwaway_bits , 1u ); 740static const uint_type first_rounded_bit = 741( num_throwaway_bits < 1 ) 742? 0 743: negatable_left_shift ( num_throwaway_bits - 1 , 1u ); 744 745static const uint_type throwaway_mask_bits = 746num_throwaway_bits > 0 ? num_throwaway_bits : 0 ; 747static const uint_type throwaway_mask = 748spvutils :: SetBits < uint_type , 0 , throwaway_mask_bits > :: get ; 749 750* carry_bit = false; 751other_uint_type out_val = 0 ; 752uint_type significand = getNormalizedSignificand (); 753// If we are up-casting, then we just have to shift to the right location. 754if ( num_throwaway_bits <= 0 ) { 755out_val = static_cast < other_uint_type > ( significand ); 756uint_type shift_amount = static_cast < uint_type > ( - num_throwaway_bits ); 757out_val = static_cast < other_uint_type > ( out_val << shift_amount ); 758return out_val ; 759} 760 761// If every non-representable bit is 0, then we don't have any casting to 762// do. 763if (( significand & throwaway_mask ) == 0 ) { 764return static_cast < other_uint_type > ( 765negatable_right_shift ( num_throwaway_bits , significand )); 766} 767 768bool round_away_from_zero = false; 769// We actually have to narrow the significand here, so we have to follow the 770// rounding rules. 771switch ( dir ) { 772case kRoundToZero : 773break ; 774case kRoundToPositiveInfinity : 775round_away_from_zero = ! isNegative (); 776break ; 777case kRoundToNegativeInfinity : 778round_away_from_zero = isNegative (); 779break ; 780case kRoundToNearestEven : 781// Have to round down, round bit is 0 782if (( first_rounded_bit & significand ) == 0 ) { 783break ; 784} 785if ((( significand & throwaway_mask ) & ~ first_rounded_bit ) != 0 ) { 786// If any subsequent bit of the rounded portion is non-0 then we round 787// up. 788round_away_from_zero = true; 789break ; 790} 791// We are exactly half-way between 2 numbers, pick even. 792if (( significand & last_significant_bit ) != 0 ) { 793// 1 for our last bit, round up. 794round_away_from_zero = true; 795break ; 796} 797break ; 798} 799 800if ( round_away_from_zero ) { 801return static_cast < other_uint_type > ( 802negatable_right_shift ( num_throwaway_bits , incrementSignificand ( 803significand , last_significant_bit , carry_bit ))); 804} else { 805return static_cast < other_uint_type > ( 806negatable_right_shift ( num_throwaway_bits , significand )); 807} 808} 809 810// Casts this value to another HexFloat. If the cast is widening, 811// then round_dir is ignored. If the cast is narrowing, then 812// the result is rounded in the direction specified. 813// This number will retain Nan and Inf values. 814// It will also saturate to Inf if the number overflows, and 815// underflow to (0 or min depending on rounding) if the number underflows. 816template < typename other_T > 817void castTo ( other_T & other , round_direction round_dir ) { 818other = other_T ( static_cast < typename other_T :: native_type > ( 0 )); 819bool negate = isNegative (); 820if ( getUnsignedBits () == 0 ) { 821if ( negate ) { 822other . set_value ( - other . value ()); 823} 824return ; 825} 826uint_type significand = getSignificandBits (); 827bool carried = false; 828typename other_T :: uint_type rounded_significand = 829getRoundedNormalizedSignificand < other_T > ( round_dir , & carried ); 830 831int_type exponent = getUnbiasedExponent (); 832if ( exponent == min_exponent ) { 833// If we are denormal, normalize the exponent, so that we can encode 834// easily. 835exponent = static_cast < int_type > ( exponent + 1 ); 836for (uint_type check_bit = first_exponent_bit >> 1 ; check_bit != 0 ; 837check_bit = static_cast < uint_type > ( check_bit >> 1 )) { 838exponent = static_cast < int_type > ( exponent - 1 ); 839if ( check_bit & significand ) break ; 840} 841} 842 843bool is_nan = 844( getBits () & exponent_mask ) == exponent_mask && significand != 0 ; 845bool is_inf = 846! is_nan && 847((( exponent + carried ) > static_cast < int_type > ( other_T :: exponent_bias ) && other_T :: Traits_T :: supportsInfinity ()) || 848(( exponent + carried ) > static_cast < int_type > ( other_T :: exponent_bias + 1 ) && ! other_T :: Traits_T :: supportsInfinity ()) || 849( significand == 0 && ( getBits () & exponent_mask ) == exponent_mask )); 850 851// If we are Nan or Inf we should pass that through. 852if ( is_inf ) { 853if ( other_T :: Traits_T :: supportsInfinity ()) { 854// encode as +/-inf 855other . set_value ( BitwiseCast < typename other_T :: underlying_type > ( 856static_cast < typename other_T :: uint_type > ( 857( negate ? other_T :: sign_mask : 0 ) | other_T :: exponent_mask ))); 858} else { 859// encode as +/-nan 860other . set_value ( BitwiseCast < typename other_T :: underlying_type > ( 861static_cast < typename other_T :: uint_type > ( other_T :: used_bits_mask & ( negate ? ~ 0 : ~ other_T :: sign_mask )))); 862} 863return ; 864} 865if ( is_nan ) { 866typename other_T :: uint_type shifted_significand ; 867shifted_significand = static_cast < typename other_T :: uint_type > ( 868negatable_left_shift ( 869static_cast < int_type > ( other_T :: num_fraction_bits ) - 870static_cast < int_type > ( num_fraction_bits ), significand )); 871 872// We are some sort of Nan. We try to keep the bit-pattern of the Nan 873// as close as possible. If we had to shift off bits so we are 0, then we 874// just set the last bit. 875other . set_value ( BitwiseCast < typename other_T :: underlying_type > ( 876static_cast < typename other_T :: uint_type > ( 877( negate ? other_T :: sign_mask : 0 ) | other_T :: exponent_mask | 878( shifted_significand == 0 ? 0x1 : shifted_significand )))); 879return ; 880} 881 882bool round_underflow_up = 883isNegative () ? round_dir == kRoundToNegativeInfinity 884: round_dir == kRoundToPositiveInfinity ; 885typedef typename other_T::int_type other_int_type; 886// setFromSignUnbiasedExponentAndNormalizedSignificand will 887// zero out any underflowing value (but retain the sign). 888other . setFromSignUnbiasedExponentAndNormalizedSignificand ( 889negate , static_cast < other_int_type > ( exponent ), rounded_significand , 890round_underflow_up ); 891return ; 892} 893 894private : 895T value_ ; 896 897static_assert ( num_used_bits == 898Traits :: num_exponent_bits + Traits :: num_fraction_bits + 1 , 899"The number of bits do not fit" ); 900static_assert ( sizeof ( T ) == sizeof ( uint_type ), "The type sizes do not match" ); 901}; 902 903// Returns 4 bits represented by the hex character. 904inline uint8_t get_nibble_from_character (int character ) { 905const char * dec = "0123456789" ; 906const char * lower = "abcdef" ; 907const char * upper = "ABCDEF" ; 908const char * p = nullptr ; 909if (( p = strchr ( dec , character ))) { 910return static_cast < uint8_t > ( p - dec ); 911} else if (( p = strchr ( lower , character ))) { 912return static_cast < uint8_t > ( p - lower + 0xa ); 913} else if (( p = strchr ( upper , character ))) { 914return static_cast < uint8_t > ( p - upper + 0xa ); 915} 916 917assert (false && "This was called with a non-hex character" ); 918return 0 ; 919} 920 921// Outputs the given HexFloat to the stream. 922template < typename T , typename Traits > 923std :: ostream & operator <<( std :: ostream & os , const HexFloat < T , Traits >& value ) { 924typedef HexFloat < T, Traits > HF ; 925typedef typename HF::uint_type uint_type; 926typedef typename HF::int_type int_type; 927 928static_assert (HF:: num_used_bits != 0 , 929"num_used_bits must be non-zero for a valid float" ); 930static_assert (HF:: num_exponent_bits != 0 , 931"num_exponent_bits must be non-zero for a valid float" ); 932static_assert (HF:: num_fraction_bits != 0 , 933"num_fractin_bits must be non-zero for a valid float" ); 934 935const uint_type bits = spvutils :: BitwiseCast < uint_type > ( value . value ()); 936const char * const sign = ( bits & HF :: sign_mask ) ? "-" : "" ; 937const uint_type exponent = static_cast < uint_type > ( 938( bits & HF :: exponent_mask ) >> HF :: num_fraction_bits ); 939 940uint_type fraction = static_cast < uint_type > (( bits & HF :: fraction_encode_mask ) 941<< HF :: num_overflow_bits ); 942 943const bool is_zero = exponent == 0 && fraction == 0 ; 944const bool is_denorm = exponent == 0 && ! is_zero ; 945 946// exponent contains the biased exponent we have to convert it back into 947// the normal range. 948int_type int_exponent = static_cast < int_type > ( exponent - HF :: exponent_bias ); 949// If the number is all zeros, then we actually have to NOT shift the 950// exponent. 951int_exponent = is_zero ? 0 : int_exponent ; 952 953// If we are denorm, then start shifting, and decreasing the exponent until 954// our leading bit is 1. 955 956if ( is_denorm ) { 957while (( fraction & HF :: fraction_top_bit ) == 0 ) { 958fraction = static_cast < uint_type > ( fraction << 1 ); 959int_exponent = static_cast < int_type > ( int_exponent - 1 ); 960} 961// Since this is denormalized, we have to consume the leading 1 since it 962// will end up being implicit. 963fraction = static_cast < uint_type > ( fraction << 1 ); // eat the leading 1 964fraction &= HF :: fraction_represent_mask ; 965} 966 967uint_type fraction_nibbles = HF :: fraction_nibbles ; 968// We do not have to display any trailing 0s, since this represents the 969// fractional part. 970while ( fraction_nibbles > 0 && ( fraction & 0xF ) == 0 ) { 971// Shift off any trailing values; 972fraction = static_cast < uint_type > ( fraction >> 4 ); 973-- fraction_nibbles ; 974} 975 976const auto saved_flags = os. flags (); 977const auto saved_fill = os. fill (); 978 979os << sign << "0x" << (is_zero ? '0' : '1' ); 980if (fraction_nibbles) { 981// Make sure to keep the leading 0s in place, since this is the fractional 982// part. 983os << "." << std:: setw (static_cast < int > (fraction_nibbles)) 984<< std:: setfill ( '0' ) << std::hex << fraction; 985} 986os << "p" << std::dec << (int_exponent >= 0 ? "+" : "" ) << int_exponent; 987 988os. flags (saved_flags); 989os. fill (saved_fill); 990 991return os; 992} 993 994// Returns true if negate_value is true and the next character on the 995// input stream is a plus or minus sign. In that case we also set the fail bit 996// on the stream and set the value to the zero value for its type. 997template < typename T , typename Traits > 998inline bool RejectParseDueToLeadingSign ( std ::istream & is, bool negate_value, 999HexFloat < T , Traits >& value) { 1000if (negate_value) { 1001auto next_char = is. peek (); 1002if (next_char == '-' || next_char == '+' ) { 1003// Fail the parse. Emulate standard behaviour by setting the value to 1004// the zero value, and set the fail bit on the stream. 1005value = HexFloat < T , Traits > (typename HexFloat < T , Traits > :: uint_type ( 0 )); 1006is. setstate (std::ios_base::failbit); 1007return true; 1008} 1009} 1010return false; 1011} 1012 1013// Parses a floating point number from the given stream and stores it into the 1014// value parameter. 1015// If negate_value is true then the number may not have a leading minus or 1016// plus, and if it successfully parses, then the number is negated before 1017// being stored into the value parameter. 1018// If the value cannot be correctly parsed or overflows the target floating 1019// point type, then set the fail bit on the stream. 1020// TODO(dneto): Promise C++11 standard behavior in how the value is set in 1021// the error case, but only after all target platforms implement it correctly. 1022// In particular, the Microsoft C++ runtime appears to be out of spec. 1023template < typename T , typename Traits > 1024inline std ::istream & ParseNormalFloat (std::istream & is, bool negate_value, 1025HexFloat < T , Traits >& value) { 1026if ( RejectParseDueToLeadingSign (is, negate_value, value)) { 1027return is; 1028} 1029T val; 1030is >> val; 1031if (negate_value) { 1032val = - val; 1033} 1034value. set_value (val); 1035// In the failure case, map -0.0 to 0.0. 1036if (is. fail () && value. getUnsignedBits () == 0u ) { 1037value = HexFloat < T , Traits > (typename HexFloat < T , Traits > :: uint_type ( 0 )); 1038} 1039if (val. isInfinity ()) { 1040// Fail the parse. Emulate standard behaviour by setting the value to 1041// the closest normal value, and set the fail bit on the stream. 1042value. set_value ((value. isNegative () || negate_value) ? T :: lowest () 1043: T :: max ()); 1044is. setstate (std::ios_base::failbit); 1045} 1046return is; 1047} 1048 1049// Specialization of ParseNormalFloat for FloatProxy<Float16> values. 1050// This will parse the float as it were a 32-bit floating point number, 1051// and then round it down to fit into a Float16 value. 1052// The number is rounded towards zero. 1053// If negate_value is true then the number may not have a leading minus or 1054// plus, and if it successfully parses, then the number is negated before 1055// being stored into the value parameter. 1056// If the value cannot be correctly parsed or overflows the target floating 1057// point type, then set the fail bit on the stream. 1058// TODO(dneto): Promise C++11 standard behavior in how the value is set in 1059// the error case, but only after all target platforms implement it correctly. 1060// In particular, the Microsoft C++ runtime appears to be out of spec. 1061template <> 1062inline std ::istream & 1063ParseNormalFloat < FloatProxy < Float16 > , HexFloatTraits < FloatProxy < Float16>> > ( 1064std::istream & is, bool negate_value, 1065HexFloat < FloatProxy < Float16 > , HexFloatTraits < FloatProxy < Float16>> >& value) { 1066// First parse as a 32-bit float. 1067HexFloat < FloatProxy < float>> float_val ( 0.0f ); 1068ParseNormalFloat (is, negate_value, float_val); 1069 1070// Then convert to 16-bit float, saturating at infinities, and 1071// rounding toward zero. 1072float_val. castTo (value, kRoundToZero); 1073 1074// Overflow on 16-bit behaves the same as for 32- and 64-bit: set the 1075// fail bit and set the lowest or highest value. 1076if (Float16:: isInfinity (value. value (). getAsFloat ())) { 1077value. set_value (value. isNegative () ? Float16:: lowest () : Float16:: max ()); 1078is. setstate (std::ios_base::failbit); 1079} 1080return is; 1081} 1082 1083// Reads a HexFloat from the given stream. 1084// If the float is not encoded as a hex-float then it will be parsed 1085// as a regular float. 1086// This may fail if your stream does not support at least one unget. 1087// Nan values can be encoded with "0x1.<not zero>p+exponent_bias". 1088// This would normally overflow a float and round to 1089// infinity but this special pattern is the exact representation for a NaN, 1090// and therefore is actually encoded as the correct NaN. To encode inf, 1091// either 0x0p+exponent_bias can be specified or any exponent greater than 1092// exponent_bias. 1093// Examples using IEEE 32-bit float encoding. 1094// 0x1.0p+128 (+inf) 1095// -0x1.0p-128 (-inf) 1096// 1097// 0x1.1p+128 (+Nan) 1098// -0x1.1p+128 (-Nan) 1099// 1100// 0x1p+129 (+inf) 1101// -0x1p+129 (-inf) 1102template < typename T , typename Traits > 1103std::istream & operator>>(std::istream & is, HexFloat < T , Traits >& value) { 1104using HF = HexFloat < T , Traits > ; 1105using uint_type = typename HF ::uint_type; 1106using int_type = typename HF ::int_type; 1107 1108value. set_value (static_cast < typename HF ::native_type > ( 0.f )); 1109 1110if (is. flags () & std::ios::skipws) { 1111// If the user wants to skip whitespace , then we should obey that. 1112while (std:: isspace (is. peek ())) { 1113is. get (); 1114} 1115} 1116 1117auto next_char = is. peek (); 1118bool negate_value = false; 1119 1120if (next_char != '-' && next_char != '0' ) { 1121return ParseNormalFloat (is, negate_value, value); 1122} 1123 1124if (next_char == '-' ) { 1125negate_value = true; 1126is. get (); 1127next_char = is. peek (); 1128} 1129 1130if (next_char == '0' ) { 1131is. get (); // We may have to unget this. 1132auto maybe_hex_start = is. peek (); 1133if (maybe_hex_start != 'x' && maybe_hex_start != 'X' ) { 1134is. unget (); 1135return ParseNormalFloat (is, negate_value, value); 1136} else { 1137is. get (); // Throw away the 'x'; 1138} 1139} else { 1140return ParseNormalFloat (is, negate_value, value); 1141} 1142 1143// This "looks" like a hex-float so treat it as one. 1144bool seen_p = false; 1145bool seen_dot = false; 1146uint_type fraction_index = 0 ; 1147 1148uint_type fraction = 0 ; 1149int_type exponent = HF ::exponent_bias; 1150 1151// Strip off leading zeros so we don't have to special-case them later. 1152while ((next_char = is. peek ()) == '0' ) { 1153is. get (); 1154} 1155 1156bool is_denorm = 1157true; // Assume denorm "representation" until we hear otherwise. 1158// NB: This does not mean the value is actually denorm, 1159// it just means that it was written 0. 1160bool bits_written = false; // Stays false until we write a bit. 1161while (!seen_p && !seen_dot) { 1162// Handle characters that are left of the fractional part. 1163if (next_char == '.' ) { 1164seen_dot = true; 1165} else if (next_char == 'p' ) { 1166seen_p = true; 1167} else if (:: isxdigit (next_char)) { 1168// We know this is not denormalized since we have stripped all leading 1169// zeroes and we are not a ".". 1170is_denorm = false; 1171int number = get_nibble_from_character (next_char); 1172for ( int i = 0 ; i < 4 ; ++ i, number <<= 1 ) { 1173uint_type write_bit = (number & 0x8 ) ? 0x1 : 0x0 ; 1174if (bits_written) { 1175// If we are here the bits represented belong in the fractional 1176// part of the float, and we have to adjust the exponent accordingly. 1177fraction = static_cast < uint_type > ( 1178fraction | 1179static_cast < uint_type > ( 1180write_bit << ( HF ::top_bit_left_shift - fraction_index ++ ))); 1181exponent = static_cast < int_type > (exponent + 1 ); 1182} 1183bits_written |= write_bit != 0 ; 1184} 1185} else { 1186// We have not found our exponent yet, so we have to fail. 1187is. setstate (std::ios::failbit); 1188return is; 1189} 1190is. get (); 1191next_char = is. peek (); 1192} 1193bits_written = false; 1194while (seen_dot && !seen_p) { 1195// Handle only fractional parts now. 1196if (next_char == 'p' ) { 1197seen_p = true; 1198} else if (:: isxdigit (next_char)) { 1199int number = get_nibble_from_character (next_char); 1200for ( int i = 0 ; i < 4 ; ++ i, number <<= 1 ) { 1201uint_type write_bit = (number & 0x8 ) ? 0x01 : 0x00 ; 1202bits_written |= write_bit != 0 ; 1203if (is_denorm && !bits_written) { 1204// Handle modifying the exponent here this way we can handle 1205// an arbitrary number of hex values without overflowing our 1206// integer. 1207exponent = static_cast < int_type > (exponent - 1 ); 1208} else { 1209fraction = static_cast < uint_type > ( 1210fraction | 1211static_cast < uint_type > ( 1212write_bit << ( HF ::top_bit_left_shift - fraction_index ++ ))); 1213} 1214} 1215} else { 1216// We still have not found our 'p' exponent yet, so this is not a valid 1217// hex-float. 1218is. setstate (std::ios::failbit); 1219return is; 1220} 1221is. get (); 1222next_char = is. peek (); 1223} 1224 1225bool seen_sign = false; 1226int8_t exponent_sign = 1 ; 1227int_type written_exponent = 0 ; 1228while (true) { 1229if ((next_char == '-' || next_char == '+' )) { 1230if (seen_sign) { 1231is. setstate (std::ios::failbit); 1232return is; 1233} 1234seen_sign = true; 1235exponent_sign = (next_char == '-' ) ? -1 : 1 ; 1236} else if (:: isdigit (next_char)) { 1237// Hex-floats express their exponent as decimal. 1238written_exponent = static_cast < int_type > (written_exponent * 10 ); 1239written_exponent = 1240static_cast < int_type > (written_exponent + (next_char - '0' )); 1241} else { 1242break ; 1243} 1244is. get (); 1245next_char = is. peek (); 1246} 1247 1248written_exponent = static_cast < int_type > (written_exponent * exponent_sign); 1249exponent = static_cast < int_type > (exponent + written_exponent); 1250 1251bool is_zero = is_denorm && (fraction == 0 ); 1252if (is_denorm && !is_zero) { 1253fraction = static_cast < uint_type > (fraction << 1 ); 1254exponent = static_cast < int_type > (exponent - 1 ); 1255} else if (is_zero) { 1256exponent = 0 ; 1257} 1258 1259if (exponent <= 0 && !is_zero) { 1260fraction = static_cast < uint_type > (fraction >> 1 ); 1261fraction |= static_cast < uint_type > ( 1 ) << HF ::top_bit_left_shift; 1262} 1263 1264fraction = (fraction >> HF ::fraction_right_shift) & HF ::fraction_encode_mask; 1265 1266const int_type max_exponent = 1267SetBits < uint_type, 0 , HF ::num_exponent_bits > ::get; 1268 1269// Handle actual denorm numbers 1270while (exponent < 0 && !is_zero) { 1271fraction = static_cast < uint_type > (fraction >> 1 ); 1272exponent = static_cast < int_type > (exponent + 1 ); 1273 1274fraction &= HF ::fraction_encode_mask; 1275if (fraction == 0 ) { 1276// We have underflowed our fraction. We should clamp to zero. 1277is_zero = true; 1278exponent = 0 ; 1279} 1280} 1281 1282// We have overflowed so we should be inf/-inf. 1283if (exponent > max_exponent) { 1284exponent = max_exponent; 1285fraction = 0 ; 1286} 1287 1288uint_type output_bits = static_cast < uint_type > ( 1289static_cast < uint_type > (negate_value ? 1 : 0 ) << HF ::top_bit_left_shift); 1290output_bits |= fraction; 1291 1292uint_type shifted_exponent = static_cast < uint_type > ( 1293static_cast < uint_type > (exponent << HF ::exponent_left_shift) & 1294HF ::exponent_mask); 1295output_bits |= shifted_exponent; 1296 1297T output_float = spvutils::BitwiseCast < T > (output_bits); 1298value. set_value (output_float); 1299 1300return is; 1301} 1302 1303// Writes a FloatProxy value to a stream. 1304// Zero and normal numbers are printed in the usual notation, but with 1305// enough digits to fully reproduce the value. Other values (subnormal, 1306// NaN, and infinity) are printed as a hex float. 1307template < typename T > 1308std::ostream & operator<<(std::ostream & os, const FloatProxy < T >& value) { 1309auto float_val = value. getAsFloat (); 1310switch (std:: fpclassify (float_val)) { 1311case FP_ZERO : 1312case FP_NORMAL : { 1313auto saved_precision = os. precision (); 1314os. precision (std::numeric_limits < T > ::digits10); 1315os << float_val; 1316os. precision (saved_precision); 1317} break ; 1318default : 1319os << HexFloat < FloatProxy < T >>(value); 1320break ; 1321} 1322return os; 1323} 1324 1325template <> 1326inline std ::ostream & operator<< < Float16 > (std::ostream & os, 1327const FloatProxy < Float16 >& value) { 1328os << HexFloat < FloatProxy < Float16>>(value); 1329return os; 1330} 1331} 1332 1333#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_