yum-mirror/glslang

git clone https://git.yummers.dev/yum-mirror/glslang

Jeff BolzImplement GL_EXT_ocp_microscaling_types62f5430e

main
47.0 KiB1333 linesraw
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 {
31 public:
32  Float16(uint16_t v) : val(v) {}
33  Float16() {}
34  static bool isNan(const Float16& val) {
35    return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0);
36  }
37  // Returns true if the given value is any kind of infinity.
38  static bool isInfinity(const Float16& val) {
39    return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0);
40  }
41  Float16(const Float16& other) { val = other.val; }
42  uint16_t get_value() const { return val; }
43
44  // Returns the maximum normal value.
45  static Float16 max() { return Float16(0x7bff); }
46  // Returns the lowest normal value.
47  static Float16 lowest() { return Float16(0xfbff); }
48
49 private:
50  uint16_t val;
51};
52
53class FloatE5M2 {
54 public:
55  FloatE5M2(uint8_t v) : val(v) {}
56  FloatE5M2() {}
57  static bool isNan(const FloatE5M2& val) {
58    return ((val.val & 0x7C) == 0x7C) && ((val.val & 0x3) != 0);
59  }
60  // Returns true if the given value is any kind of infinity.
61  static bool isInfinity(const FloatE5M2& val) {
62    return ((val.val & 0x7C) == 0x7C) && ((val.val & 0x3) == 0);
63  }
64  FloatE5M2(const FloatE5M2& other) { val = other.val; }
65  uint8_t get_value() const { return val; }
66
67  // Returns the maximum normal value.
68  static FloatE5M2 max() { return FloatE5M2(0x7B); }
69  // Returns the lowest normal value.
70  static FloatE5M2 lowest() { return FloatE5M2(0xFB); }
71
72 private:
73  uint8_t val;
74};
75
76class FloatE4M3 {
77 public:
78  FloatE4M3(uint8_t v) : val(v) {}
79  FloatE4M3() {}
80  static bool isNan(const FloatE4M3& val) {
81    return (val.val & 0x7F) == 0x7F;
82  }
83  // Returns true if the given value is any kind of infinity.
84  static bool isInfinity(const FloatE4M3&) {
85    return false;
86  }
87  FloatE4M3(const FloatE4M3& other) { val = other.val; }
88  uint8_t get_value() const { return val; }
89
90  // Returns the maximum normal value.
91  static FloatE4M3 max() { return FloatE4M3(0x7E); }
92  // Returns the lowest normal value.
93  static FloatE4M3 lowest() { return FloatE4M3(0xFE); }
94
95 private:
96  uint8_t val;
97};
98
99class FloatE2M1 {
100 public:
101  FloatE2M1(uint8_t v) : val(v) {}
102  FloatE2M1() {}
103  static bool isNan(const FloatE2M1& val) {
104    static_cast<void>(val);
105    return false;
106  }
107  // Returns true if the given value is any kind of infinity.
108  static bool isInfinity(const FloatE2M1& val) {
109    static_cast<void>(val);
110    return false;
111  }
112  FloatE2M1(const FloatE2M1& other) { val = other.val; }
113  uint8_t get_value() const { return val; }
114
115  // Returns the maximum normal value.
116  static FloatE2M1 max() { return FloatE2M1(0x7); }
117  // Returns the lowest normal value.
118  static FloatE2M1 lowest() { return FloatE2M1(0xF); }
119
120 private:
121  uint8_t val;
122};
123
124class FloatE3M2 {
125 public:
126  FloatE3M2(uint8_t v) : val(v) {}
127  FloatE3M2() {}
128  static bool isNan(const FloatE3M2& val) {
129    static_cast<void>(val);
130    return false;
131  }
132  // Returns true if the given value is any kind of infinity.
133  static bool isInfinity(const FloatE3M2& val) {
134    static_cast<void>(val);
135    return false;
136  }
137  FloatE3M2(const FloatE3M2& other) { val = other.val; }
138  uint8_t get_value() const { return val; }
139
140  // Returns the maximum normal value.
141  static FloatE3M2 max() { return FloatE3M2(0x1F); }
142  // Returns the lowest normal value.
143  static FloatE3M2 lowest() { return FloatE3M2(0x3F); }
144
145 private:
146  uint8_t val;
147};
148
149class FloatE2M3 {
150 public:
151  FloatE2M3(uint8_t v) : val(v) {}
152  FloatE2M3() {}
153  static bool isNan(const FloatE2M3& val) {
154    static_cast<void>(val);
155    return false;
156  }
157  // Returns true if the given value is any kind of infinity.
158  static bool isInfinity(const FloatE2M3& val) {
159    static_cast<void>(val);
160    return false;
161  }
162  FloatE2M3(const FloatE2M3& other) { val = other.val; }
163  uint8_t get_value() const { return val; }
164
165  // Returns the maximum normal value.
166  static FloatE2M3 max() { return FloatE2M3(0x1F); }
167  // Returns the lowest normal value.
168  static FloatE2M3 lowest() { return FloatE2M3(0x3F); }
169
170 private:
171  uint8_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 {
180  typedef void uint_type;
181};
182
183template <>
184struct FloatProxyTraits<float> {
185  typedef uint32_t uint_type;
186  static bool isNan(float f) { return std::isnan(f); }
187  // Returns true if the given value is any kind of infinity.
188  static bool isInfinity(float f) { return std::isinf(f); }
189  // Returns the maximum normal value.
190  static float max() { return std::numeric_limits<float>::max(); }
191  // Returns the lowest normal value.
192  static float lowest() { return std::numeric_limits<float>::lowest(); }
193};
194
195template <>
196struct FloatProxyTraits<double> {
197  typedef uint64_t uint_type;
198  static bool isNan(double f) { return std::isnan(f); }
199  // Returns true if the given value is any kind of infinity.
200  static bool isInfinity(double f) { return std::isinf(f); }
201  // Returns the maximum normal value.
202  static double max() { return std::numeric_limits<double>::max(); }
203  // Returns the lowest normal value.
204  static double lowest() { return std::numeric_limits<double>::lowest(); }
205};
206
207template <>
208struct FloatProxyTraits<Float16> {
209  typedef uint16_t uint_type;
210  static bool isNan(Float16 f) { return Float16::isNan(f); }
211  // Returns true if the given value is any kind of infinity.
212  static bool isInfinity(Float16 f) { return Float16::isInfinity(f); }
213  // Returns the maximum normal value.
214  static Float16 max() { return Float16::max(); }
215  // Returns the lowest normal value.
216  static Float16 lowest() { return Float16::lowest(); }
217};
218
219template <>
220struct FloatProxyTraits<FloatE5M2> {
221  typedef uint8_t uint_type;
222  static bool isNan(FloatE5M2 f) { return FloatE5M2::isNan(f); }
223  // Returns true if the given value is any kind of infinity.
224  static bool isInfinity(FloatE5M2 f) { return FloatE5M2::isInfinity(f); }
225  // Returns the maximum normal value.
226  static FloatE5M2 max() { return FloatE5M2::max(); }
227  // Returns the lowest normal value.
228  static FloatE5M2 lowest() { return FloatE5M2::lowest(); }
229};
230
231template <>
232struct FloatProxyTraits<FloatE4M3> {
233  typedef uint8_t uint_type;
234  static bool isNan(FloatE4M3 f) { return FloatE4M3::isNan(f); }
235  // Returns true if the given value is any kind of infinity.
236  static bool isInfinity(FloatE4M3 f) { return FloatE4M3::isInfinity(f); }
237  // Returns the maximum normal value.
238  static FloatE4M3 max() { return FloatE4M3::max(); }
239  // Returns the lowest normal value.
240  static FloatE4M3 lowest() { return FloatE4M3::lowest(); }
241};
242
243template <>
244struct FloatProxyTraits<FloatE2M1> {
245  typedef uint8_t uint_type;
246  static bool isNan(FloatE2M1 f) { return FloatE2M1::isNan(f); }
247  // Returns true if the given value is any kind of infinity.
248  static bool isInfinity(FloatE2M1 f) { return FloatE2M1::isInfinity(f); }
249  // Returns the maximum normal value.
250  static FloatE2M1 max() { return FloatE2M1::max(); }
251  // Returns the lowest normal value.
252  static FloatE2M1 lowest() { return FloatE2M1::lowest(); }
253};
254
255template <>
256struct FloatProxyTraits<FloatE3M2> {
257  typedef uint8_t uint_type;
258  static bool isNan(FloatE3M2 f) { return FloatE3M2::isNan(f); }
259  // Returns true if the given value is any kind of infinity.
260  static bool isInfinity(FloatE3M2 f) { return FloatE3M2::isInfinity(f); }
261  // Returns the maximum normal value.
262  static FloatE3M2 max() { return FloatE3M2::max(); }
263  // Returns the lowest normal value.
264  static FloatE3M2 lowest() { return FloatE3M2::lowest(); }
265};
266
267template <>
268struct FloatProxyTraits<FloatE2M3> {
269  typedef uint8_t uint_type;
270  static bool isNan(FloatE2M3 f) { return FloatE2M3::isNan(f); }
271  // Returns true if the given value is any kind of infinity.
272  static bool isInfinity(FloatE2M3 f) { return FloatE2M3::isInfinity(f); }
273  // Returns the maximum normal value.
274  static FloatE2M3 max() { return FloatE2M3::max(); }
275  // Returns the lowest normal value.
276  static 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 {
284 public:
285  typedef 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.
289  FloatProxy() {}
290
291  // Intentionally non-explicit. This is a proxy type so
292  // implicit conversions allow us to use it more transparently.
293  FloatProxy(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.
297  FloatProxy(uint_type val) { data_ = val; }
298
299  // This is helpful to have and is guaranteed not to stomp bits.
300  FloatProxy<T> operator-() const;
301
302  // Returns the data as a floating point value.
303  T getAsFloat() const { return BitwiseCast<T>(data_); }
304
305  // Returns the raw data.
306  uint_type data() const { return data_; }
307
308  // Returns true if the value represents any type of NaN.
309  bool isNan() { return FloatProxyTraits<T>::isNan(getAsFloat()); }
310  // Returns true if the value represents any type of infinity.
311  bool isInfinity() { return FloatProxyTraits<T>::isInfinity(getAsFloat()); }
312
313  // Returns the maximum normal value.
314  static FloatProxy<T> max() {
315    return FloatProxy<T>(FloatProxyTraits<T>::max());
316  }
317  // Returns the lowest normal value.
318  static FloatProxy<T> lowest() {
319    return FloatProxy<T>(FloatProxyTraits<T>::lowest());
320  }
321
322 private:
323  uint_type data_;
324};
325
326template <typename T>
327bool operator==(const FloatProxy<T>& first, const FloatProxy<T>& second) {
328  return 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) {
334  T float_val;
335  is >> float_val;
336  value = FloatProxy<T>(float_val);
337  return 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.
345  typedef void uint_type;
346  // Signed integer type that can store this hex-float.
347  typedef void int_type;
348  // The numerical type that this HexFloat represents.
349  typedef void underlying_type;
350  // The type needed to construct the underlying type.
351  typedef 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.
355  static const uint32_t num_used_bits = 0;
356  // Number of bits that represent the exponent.
357  static const uint32_t num_exponent_bits = 0;
358  // Number of bits that represent the fractional part.
359  static 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.)
362  static const uint32_t exponent_bias = 0;
363  static 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>> {
370  typedef uint32_t uint_type;
371  typedef int32_t int_type;
372  typedef FloatProxy<float> underlying_type;
373  typedef float native_type;
374  static const uint_type num_used_bits = 32;
375  static const uint_type num_exponent_bits = 8;
376  static const uint_type num_fraction_bits = 23;
377  static const uint_type exponent_bias = 127;
378  static 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>> {
385  typedef uint64_t uint_type;
386  typedef int64_t int_type;
387  typedef FloatProxy<double> underlying_type;
388  typedef double native_type;
389  static const uint_type num_used_bits = 64;
390  static const uint_type num_exponent_bits = 11;
391  static const uint_type num_fraction_bits = 52;
392  static const uint_type exponent_bias = 1023;
393  static 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>> {
400  typedef uint16_t uint_type;
401  typedef int16_t int_type;
402  typedef uint16_t underlying_type;
403  typedef uint16_t native_type;
404  static const uint_type num_used_bits = 16;
405  static const uint_type num_exponent_bits = 5;
406  static const uint_type num_fraction_bits = 10;
407  static const uint_type exponent_bias = 15;
408  static bool supportsInfinity() { return true; }
409};
410
411template <>
412struct HexFloatTraits<FloatProxy<FloatE5M2>> {
413  typedef uint8_t uint_type;
414  typedef int8_t int_type;
415  typedef uint8_t underlying_type;
416  typedef uint8_t native_type;
417  static const uint_type num_used_bits = 8;
418  static const uint_type num_exponent_bits = 5;
419  static const uint_type num_fraction_bits = 2;
420  static const uint_type exponent_bias = 15;
421  static bool supportsInfinity() { return true; }
422};
423
424template <>
425struct HexFloatTraits<FloatProxy<FloatE4M3>> {
426  typedef uint8_t uint_type;
427  typedef int8_t int_type;
428  typedef uint8_t underlying_type;
429  typedef uint8_t native_type;
430  static const uint_type num_used_bits = 8;
431  static const uint_type num_exponent_bits = 4;
432  static const uint_type num_fraction_bits = 3;
433  static const uint_type exponent_bias = 7;
434  static bool supportsInfinity() { return false; }
435};
436
437template <>
438struct HexFloatTraits<FloatProxy<FloatE2M1>> {
439  typedef uint8_t uint_type;
440  typedef int8_t int_type;
441  typedef uint8_t underlying_type;
442  typedef uint8_t native_type;
443  static const uint_type num_used_bits = 4;
444  static const uint_type num_exponent_bits = 2;
445  static const uint_type num_fraction_bits = 1;
446  static const uint_type exponent_bias = 1;
447  static bool supportsInfinity() { return false; }
448};
449
450template <>
451struct HexFloatTraits<FloatProxy<FloatE3M2>> {
452  typedef uint8_t uint_type;
453  typedef int8_t int_type;
454  typedef uint8_t underlying_type;
455  typedef uint8_t native_type;
456  static const uint_type num_used_bits = 6;
457  static const uint_type num_exponent_bits = 3;
458  static const uint_type num_fraction_bits = 2;
459  static const uint_type exponent_bias = 3;
460  static bool supportsInfinity() { return false; }
461};
462
463template <>
464struct HexFloatTraits<FloatProxy<FloatE2M3>> {
465  typedef uint8_t uint_type;
466  typedef int8_t int_type;
467  typedef uint8_t underlying_type;
468  typedef uint8_t native_type;
469  static const uint_type num_used_bits = 6;
470  static const uint_type num_exponent_bits = 2;
471  static const uint_type num_fraction_bits = 3;
472  static const uint_type exponent_bias = 1;
473  static bool supportsInfinity() { return false; }
474};
475
476enum round_direction {
477  kRoundToZero,
478  kRoundToNearestEven,
479  kRoundToPositiveInfinity,
480  kRoundToNegativeInfinity
481};
482
483// This is helpful to have and is guaranteed not to stomp bits.
484template <typename T>
485FloatProxy<T> FloatProxy<T>::operator-() const {
486  return 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 {
495 public:
496  typedef typename Traits::uint_type uint_type;
497  typedef typename Traits::int_type int_type;
498  typedef typename Traits::underlying_type underlying_type;
499  typedef typename Traits::native_type native_type;
500  using Traits_T = Traits;
501
502  explicit HexFloat(T f) : value_(f) {}
503
504  T value() const { return value_; }
505  void 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.
511  static const uint32_t num_used_bits = Traits::num_used_bits;
512  static const uint32_t exponent_bias = Traits::exponent_bias;
513  static const uint32_t num_exponent_bits = Traits::num_exponent_bits;
514  static const uint32_t num_fraction_bits = Traits::num_fraction_bits;
515
516  // Number of bits to shift left to set the highest relevant bit.
517  static const uint32_t top_bit_left_shift = num_used_bits - 1;
518  // How many nibbles (hex characters) the fractional part takes up.
519  static 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).
523  static const uint32_t num_overflow_bits =
524      fraction_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.
528  static const uint_type fraction_represent_mask =
529      spvutils::SetBits<uint_type, 0,
530                        num_fraction_bits + num_overflow_bits>::get;
531
532  // The topmost bit in the nibble-aligned fraction.
533  static const uint_type fraction_top_bit =
534      uint_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.
538  static 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.
543  static const uint_type fraction_encode_mask =
544      spvutils::SetBits<uint_type, 0, num_fraction_bits>::get;
545
546  // The bit that is used as a sign.
547  static const uint_type sign_mask = uint_type(1) << top_bit_left_shift;
548
549  // The set of all used bits
550  static 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.
555  static const uint_type exponent_mask =
556      spvutils::SetBits<uint_type, num_fraction_bits, num_exponent_bits>::get;
557
558  // How far left the exponent is shifted.
559  static const uint32_t exponent_left_shift = num_fraction_bits;
560
561  // How far from the right edge the fraction is shifted.
562  static const uint32_t fraction_right_shift =
563      static_cast<uint32_t>(sizeof(uint_type) * 8) - num_fraction_bits;
564
565  // The maximum representable unbiased exponent.
566  static const int_type max_exponent =
567      (exponent_mask >> num_fraction_bits) - exponent_bias;
568  // The minimum representable exponent for normalized numbers.
569  static const int_type min_exponent = -static_cast<int_type>(exponent_bias);
570
571  // Returns the bits associated with the value.
572  uint_type getBits() const { return spvutils::BitwiseCast<uint_type>(value_); }
573
574  // Returns the bits associated with the value, without the leading sign bit.
575  uint_type getUnsignedBits() const {
576    return 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.
582  const uint_type getExponentBits() const {
583    return static_cast<uint_type>((getBits() & exponent_mask) >>
584                                  num_fraction_bits);
585  }
586
587  // Returns the exponent in unbiased form. This is the exponent in the
588  // human-friendly form.
589  const int_type getUnbiasedExponent() const {
590    return static_cast<int_type>(getExponentBits() - exponent_bias);
591  }
592
593  // Returns just the significand bits from the value.
594  const uint_type getSignificandBits() const {
595    return 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.
600  const int_type getUnbiasedNormalizedExponent() const {
601    if ((getBits() & ~sign_mask) == 0) {  // special case if everything is 0
602      return 0;
603    }
604    int_type exp = getUnbiasedExponent();
605    if (exp == min_exponent) {  // We are in denorm land.
606      uint_type significand_bits = getSignificandBits();
607      while ((significand_bits & (first_exponent_bit >> 1)) == 0) {
608        significand_bits = static_cast<uint_type>(significand_bits << 1);
609        exp = static_cast<int_type>(exp - 1);
610      }
611      significand_bits &= fraction_encode_mask;
612    }
613    return exp;
614  }
615
616  // Returns the signficand after it has been normalized.
617  const uint_type getNormalizedSignificand() const {
618    int_type unbiased_exponent = getUnbiasedNormalizedExponent();
619    uint_type significand = getSignificandBits();
620    for (int_type i = unbiased_exponent; i <= min_exponent; ++i) {
621      significand = static_cast<uint_type>(significand << 1);
622    }
623    significand &= fraction_encode_mask;
624    return significand;
625  }
626
627  // Returns true if this number represents a negative value.
628  bool 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.
642  void setFromSignUnbiasedExponentAndNormalizedSignificand(
643      bool negative, int_type exponent, uint_type significand,
644      bool round_denorm_up) {
645    bool significand_is_zero = significand == 0;
646
647    if (exponent <= min_exponent) {
648      // If this was denormalized, then we have to shift the bit on, meaning
649      // the significand is not zero.
650      significand_is_zero = false;
651      significand |= first_exponent_bit;
652      significand = static_cast<uint_type>(significand >> 1);
653    }
654
655    while (exponent < min_exponent) {
656      significand = static_cast<uint_type>(significand >> 1);
657      ++exponent;
658    }
659
660    if (exponent == min_exponent) {
661      if (significand == 0 && !significand_is_zero && round_denorm_up) {
662        significand = static_cast<uint_type>(0x1);
663      }
664    }
665
666    uint_type new_value = 0;
667    if (negative) {
668      new_value = static_cast<uint_type>(new_value | sign_mask);
669    }
670    exponent = static_cast<int_type>(exponent + exponent_bias);
671    assert(exponent >= 0);
672
673    // put it all together
674    exponent = static_cast<uint_type>((exponent << exponent_left_shift) &
675                                      exponent_mask);
676    significand = static_cast<uint_type>(significand & fraction_encode_mask);
677    new_value = static_cast<uint_type>(new_value | (exponent | significand));
678    value_ = 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.
687  static uint_type incrementSignificand(uint_type significand,
688                                        uint_type to_increment, bool* carry) {
689    significand = static_cast<uint_type>(significand + to_increment);
690    *carry = false;
691    if (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.
695      significand = static_cast<uint_type>(significand & ~first_exponent_bit);
696      significand = static_cast<uint_type>(significand >> 1);
697    }
698    return 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
706  template <typename int_type>
707  uint_type negatable_left_shift(int_type N, uint_type val)
708  {
709    if(N >= 0)
710      return val << N;
711
712    return val >> -N;
713  }
714
715  template <typename int_type>
716  uint_type negatable_right_shift(int_type N, uint_type val)
717  {
718    if(N >= 0)
719      return val >> N;
720
721    return 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.
728  template <typename other_T>
729  typename other_T::uint_type getRoundedNormalizedSignificand(
730      round_direction dir, bool* carry_bit) {
731    typedef typename other_T::uint_type other_uint_type;
732    static const int_type num_throwaway_bits =
733        static_cast<int_type>(num_fraction_bits) -
734        static_cast<int_type>(other_T::num_fraction_bits);
735
736    static const uint_type last_significant_bit =
737        (num_throwaway_bits < 0)
738            ? 0
739            : negatable_left_shift(num_throwaway_bits, 1u);
740    static const uint_type first_rounded_bit =
741        (num_throwaway_bits < 1)
742            ? 0
743            : negatable_left_shift(num_throwaway_bits - 1, 1u);
744
745    static const uint_type throwaway_mask_bits =
746        num_throwaway_bits > 0 ? num_throwaway_bits : 0;
747    static const uint_type throwaway_mask =
748        spvutils::SetBits<uint_type, 0, throwaway_mask_bits>::get;
749
750    *carry_bit = false;
751    other_uint_type out_val = 0;
752    uint_type significand = getNormalizedSignificand();
753    // If we are up-casting, then we just have to shift to the right location.
754    if (num_throwaway_bits <= 0) {
755      out_val = static_cast<other_uint_type>(significand);
756      uint_type shift_amount = static_cast<uint_type>(-num_throwaway_bits);
757      out_val = static_cast<other_uint_type>(out_val << shift_amount);
758      return out_val;
759    }
760
761    // If every non-representable bit is 0, then we don't have any casting to
762    // do.
763    if ((significand & throwaway_mask) == 0) {
764      return static_cast<other_uint_type>(
765          negatable_right_shift(num_throwaway_bits, significand));
766    }
767
768    bool round_away_from_zero = false;
769    // We actually have to narrow the significand here, so we have to follow the
770    // rounding rules.
771    switch (dir) {
772      case kRoundToZero:
773        break;
774      case kRoundToPositiveInfinity:
775        round_away_from_zero = !isNegative();
776        break;
777      case kRoundToNegativeInfinity:
778        round_away_from_zero = isNegative();
779        break;
780      case kRoundToNearestEven:
781        // Have to round down, round bit is 0
782        if ((first_rounded_bit & significand) == 0) {
783          break;
784        }
785        if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) {
786          // If any subsequent bit of the rounded portion is non-0 then we round
787          // up.
788          round_away_from_zero = true;
789          break;
790        }
791        // We are exactly half-way between 2 numbers, pick even.
792        if ((significand & last_significant_bit) != 0) {
793          // 1 for our last bit, round up.
794          round_away_from_zero = true;
795          break;
796        }
797        break;
798    }
799
800    if (round_away_from_zero) {
801      return static_cast<other_uint_type>(
802          negatable_right_shift(num_throwaway_bits, incrementSignificand(
803              significand, last_significant_bit, carry_bit)));
804    } else {
805      return static_cast<other_uint_type>(
806          negatable_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.
816  template <typename other_T>
817  void castTo(other_T& other, round_direction round_dir) {
818    other = other_T(static_cast<typename other_T::native_type>(0));
819    bool negate = isNegative();
820    if (getUnsignedBits() == 0) {
821      if (negate) {
822        other.set_value(-other.value());
823      }
824      return;
825    }
826    uint_type significand = getSignificandBits();
827    bool carried = false;
828    typename other_T::uint_type rounded_significand =
829        getRoundedNormalizedSignificand<other_T>(round_dir, &carried);
830
831    int_type exponent = getUnbiasedExponent();
832    if (exponent == min_exponent) {
833      // If we are denormal, normalize the exponent, so that we can encode
834      // easily.
835      exponent = static_cast<int_type>(exponent + 1);
836      for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0;
837           check_bit = static_cast<uint_type>(check_bit >> 1)) {
838        exponent = static_cast<int_type>(exponent - 1);
839        if (check_bit & significand) break;
840      }
841    }
842
843    bool is_nan =
844        (getBits() & exponent_mask) == exponent_mask && significand != 0;
845    bool 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.
852    if (is_inf) {
853      if (other_T::Traits_T::supportsInfinity()) {
854        // encode as +/-inf
855        other.set_value(BitwiseCast<typename other_T::underlying_type>(
856            static_cast<typename other_T::uint_type>(
857                (negate ? other_T::sign_mask : 0) | other_T::exponent_mask)));
858      } else {
859        // encode as +/-nan
860        other.set_value(BitwiseCast<typename other_T::underlying_type>(
861             static_cast<typename other_T::uint_type>(other_T::used_bits_mask & (negate ? ~0 : ~other_T::sign_mask))));
862      }
863      return;
864    }
865    if (is_nan) {
866      typename other_T::uint_type shifted_significand;
867      shifted_significand = static_cast<typename other_T::uint_type>(
868          negatable_left_shift(
869              static_cast<int_type>(other_T::num_fraction_bits) -
870              static_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.
875      other.set_value(BitwiseCast<typename other_T::underlying_type>(
876          static_cast<typename other_T::uint_type>(
877              (negate ? other_T::sign_mask : 0) | other_T::exponent_mask |
878              (shifted_significand == 0 ? 0x1 : shifted_significand))));
879      return;
880    }
881
882    bool round_underflow_up =
883        isNegative() ? round_dir == kRoundToNegativeInfinity
884                     : round_dir == kRoundToPositiveInfinity;
885    typedef typename other_T::int_type other_int_type;
886    // setFromSignUnbiasedExponentAndNormalizedSignificand will
887    // zero out any underflowing value (but retain the sign).
888    other.setFromSignUnbiasedExponentAndNormalizedSignificand(
889        negate, static_cast<other_int_type>(exponent), rounded_significand,
890        round_underflow_up);
891    return;
892  }
893
894 private:
895  T value_;
896
897  static_assert(num_used_bits ==
898                    Traits::num_exponent_bits + Traits::num_fraction_bits + 1,
899                "The number of bits do not fit");
900  static_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) {
905  const char* dec = "0123456789";
906  const char* lower = "abcdef";
907  const char* upper = "ABCDEF";
908  const char* p = nullptr;
909  if ((p = strchr(dec, character))) {
910    return static_cast<uint8_t>(p - dec);
911  } else if ((p = strchr(lower, character))) {
912    return static_cast<uint8_t>(p - lower + 0xa);
913  } else if ((p = strchr(upper, character))) {
914    return static_cast<uint8_t>(p - upper + 0xa);
915  }
916
917  assert(false && "This was called with a non-hex character");
918  return 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) {
924  typedef HexFloat<T, Traits> HF;
925  typedef typename HF::uint_type uint_type;
926  typedef typename HF::int_type int_type;
927
928  static_assert(HF::num_used_bits != 0,
929                "num_used_bits must be non-zero for a valid float");
930  static_assert(HF::num_exponent_bits != 0,
931                "num_exponent_bits must be non-zero for a valid float");
932  static_assert(HF::num_fraction_bits != 0,
933                "num_fractin_bits must be non-zero for a valid float");
934
935  const uint_type bits = spvutils::BitwiseCast<uint_type>(value.value());
936  const char* const sign = (bits & HF::sign_mask) ? "-" : "";
937  const uint_type exponent = static_cast<uint_type>(
938      (bits & HF::exponent_mask) >> HF::num_fraction_bits);
939
940  uint_type fraction = static_cast<uint_type>((bits & HF::fraction_encode_mask)
941                                              << HF::num_overflow_bits);
942
943  const bool is_zero = exponent == 0 && fraction == 0;
944  const 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.
948  int_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.
951  int_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
956  if (is_denorm) {
957    while ((fraction & HF::fraction_top_bit) == 0) {
958      fraction = static_cast<uint_type>(fraction << 1);
959      int_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.
963    fraction = static_cast<uint_type>(fraction << 1);  // eat the leading 1
964    fraction &= HF::fraction_represent_mask;
965  }
966
967  uint_type fraction_nibbles = HF::fraction_nibbles;
968  // We do not have to display any trailing 0s, since this represents the
969  // fractional part.
970  while (fraction_nibbles > 0 && (fraction & 0xF) == 0) {
971    // Shift off any trailing values;
972    fraction = static_cast<uint_type>(fraction >> 4);
973    --fraction_nibbles;
974  }
975
976  const auto saved_flags = os.flags();
977  const auto saved_fill = os.fill();
978
979  os << sign << "0x" << (is_zero ? '0' : '1');
980  if (fraction_nibbles) {
981    // Make sure to keep the leading 0s in place, since this is the fractional
982    // part.
983    os << "." << std::setw(static_cast<int>(fraction_nibbles))
984       << std::setfill('0') << std::hex << fraction;
985  }
986  os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent;
987
988  os.flags(saved_flags);
989  os.fill(saved_fill);
990
991  return 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,
999                                        HexFloat<T, Traits>& value) {
1000  if (negate_value) {
1001    auto next_char = is.peek();
1002    if (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.
1005      value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type(0));
1006      is.setstate(std::ios_base::failbit);
1007      return true;
1008    }
1009  }
1010  return 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,
1025                                      HexFloat<T, Traits>& value) {
1026  if (RejectParseDueToLeadingSign(is, negate_value, value)) {
1027    return is;
1028  }
1029  T val;
1030  is >> val;
1031  if (negate_value) {
1032    val = -val;
1033  }
1034  value.set_value(val);
1035  // In the failure case, map -0.0 to 0.0.
1036  if (is.fail() && value.getUnsignedBits() == 0u) {
1037    value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type(0));
1038  }
1039  if (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.
1042    value.set_value((value.isNegative() || negate_value) ? T::lowest()
1043                                                         : T::max());
1044    is.setstate(std::ios_base::failbit);
1045  }
1046  return 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>>>(
1064    std::istream& is, bool negate_value,
1065    HexFloat<FloatProxy<Float16>, HexFloatTraits<FloatProxy<Float16>>>& value) {
1066  // First parse as a 32-bit float.
1067  HexFloat<FloatProxy<float>> float_val(0.0f);
1068  ParseNormalFloat(is, negate_value, float_val);
1069
1070  // Then convert to 16-bit float, saturating at infinities, and
1071  // rounding toward zero.
1072  float_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.
1076  if (Float16::isInfinity(value.value().getAsFloat())) {
1077    value.set_value(value.isNegative() ? Float16::lowest() : Float16::max());
1078    is.setstate(std::ios_base::failbit);
1079  }
1080  return 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) {
1104  using HF = HexFloat<T, Traits>;
1105  using uint_type = typename HF::uint_type;
1106  using int_type = typename HF::int_type;
1107
1108  value.set_value(static_cast<typename HF::native_type>(0.f));
1109
1110  if (is.flags() & std::ios::skipws) {
1111    // If the user wants to skip whitespace , then we should obey that.
1112    while (std::isspace(is.peek())) {
1113      is.get();
1114    }
1115  }
1116
1117  auto next_char = is.peek();
1118  bool negate_value = false;
1119
1120  if (next_char != '-' && next_char != '0') {
1121    return ParseNormalFloat(is, negate_value, value);
1122  }
1123
1124  if (next_char == '-') {
1125    negate_value = true;
1126    is.get();
1127    next_char = is.peek();
1128  }
1129
1130  if (next_char == '0') {
1131    is.get();  // We may have to unget this.
1132    auto maybe_hex_start = is.peek();
1133    if (maybe_hex_start != 'x' && maybe_hex_start != 'X') {
1134      is.unget();
1135      return ParseNormalFloat(is, negate_value, value);
1136    } else {
1137      is.get();  // Throw away the 'x';
1138    }
1139  } else {
1140    return ParseNormalFloat(is, negate_value, value);
1141  }
1142
1143  // This "looks" like a hex-float so treat it as one.
1144  bool seen_p = false;
1145  bool seen_dot = false;
1146  uint_type fraction_index = 0;
1147
1148  uint_type fraction = 0;
1149  int_type exponent = HF::exponent_bias;
1150
1151  // Strip off leading zeros so we don't have to special-case them later.
1152  while ((next_char = is.peek()) == '0') {
1153    is.get();
1154  }
1155
1156  bool is_denorm =
1157      true;  // 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.
1160  bool bits_written = false;  // Stays false until we write a bit.
1161  while (!seen_p && !seen_dot) {
1162    // Handle characters that are left of the fractional part.
1163    if (next_char == '.') {
1164      seen_dot = true;
1165    } else if (next_char == 'p') {
1166      seen_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 ".".
1170      is_denorm = false;
1171      int number = get_nibble_from_character(next_char);
1172      for (int i = 0; i < 4; ++i, number <<= 1) {
1173        uint_type write_bit = (number & 0x8) ? 0x1 : 0x0;
1174        if (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.
1177          fraction = static_cast<uint_type>(
1178              fraction |
1179              static_cast<uint_type>(
1180                  write_bit << (HF::top_bit_left_shift - fraction_index++)));
1181          exponent = static_cast<int_type>(exponent + 1);
1182        }
1183        bits_written |= write_bit != 0;
1184      }
1185    } else {
1186      // We have not found our exponent yet, so we have to fail.
1187      is.setstate(std::ios::failbit);
1188      return is;
1189    }
1190    is.get();
1191    next_char = is.peek();
1192  }
1193  bits_written = false;
1194  while (seen_dot && !seen_p) {
1195    // Handle only fractional parts now.
1196    if (next_char == 'p') {
1197      seen_p = true;
1198    } else if (::isxdigit(next_char)) {
1199      int number = get_nibble_from_character(next_char);
1200      for (int i = 0; i < 4; ++i, number <<= 1) {
1201        uint_type write_bit = (number & 0x8) ? 0x01 : 0x00;
1202        bits_written |= write_bit != 0;
1203        if (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.
1207          exponent = static_cast<int_type>(exponent - 1);
1208        } else {
1209          fraction = static_cast<uint_type>(
1210              fraction |
1211              static_cast<uint_type>(
1212                  write_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.
1218      is.setstate(std::ios::failbit);
1219      return is;
1220    }
1221    is.get();
1222    next_char = is.peek();
1223  }
1224
1225  bool seen_sign = false;
1226  int8_t exponent_sign = 1;
1227  int_type written_exponent = 0;
1228  while (true) {
1229    if ((next_char == '-' || next_char == '+')) {
1230      if (seen_sign) {
1231        is.setstate(std::ios::failbit);
1232        return is;
1233      }
1234      seen_sign = true;
1235      exponent_sign = (next_char == '-') ? -1 : 1;
1236    } else if (::isdigit(next_char)) {
1237      // Hex-floats express their exponent as decimal.
1238      written_exponent = static_cast<int_type>(written_exponent * 10);
1239      written_exponent =
1240          static_cast<int_type>(written_exponent + (next_char - '0'));
1241    } else {
1242      break;
1243    }
1244    is.get();
1245    next_char = is.peek();
1246  }
1247
1248  written_exponent = static_cast<int_type>(written_exponent * exponent_sign);
1249  exponent = static_cast<int_type>(exponent + written_exponent);
1250
1251  bool is_zero = is_denorm && (fraction == 0);
1252  if (is_denorm && !is_zero) {
1253    fraction = static_cast<uint_type>(fraction << 1);
1254    exponent = static_cast<int_type>(exponent - 1);
1255  } else if (is_zero) {
1256    exponent = 0;
1257  }
1258
1259  if (exponent <= 0 && !is_zero) {
1260    fraction = static_cast<uint_type>(fraction >> 1);
1261    fraction |= static_cast<uint_type>(1) << HF::top_bit_left_shift;
1262  }
1263
1264  fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask;
1265
1266  const int_type max_exponent =
1267      SetBits<uint_type, 0, HF::num_exponent_bits>::get;
1268
1269  // Handle actual denorm numbers
1270  while (exponent < 0 && !is_zero) {
1271    fraction = static_cast<uint_type>(fraction >> 1);
1272    exponent = static_cast<int_type>(exponent + 1);
1273
1274    fraction &= HF::fraction_encode_mask;
1275    if (fraction == 0) {
1276      // We have underflowed our fraction. We should clamp to zero.
1277      is_zero = true;
1278      exponent = 0;
1279    }
1280  }
1281
1282  // We have overflowed so we should be inf/-inf.
1283  if (exponent > max_exponent) {
1284    exponent = max_exponent;
1285    fraction = 0;
1286  }
1287
1288  uint_type output_bits = static_cast<uint_type>(
1289      static_cast<uint_type>(negate_value ? 1 : 0) << HF::top_bit_left_shift);
1290  output_bits |= fraction;
1291
1292  uint_type shifted_exponent = static_cast<uint_type>(
1293      static_cast<uint_type>(exponent << HF::exponent_left_shift) &
1294      HF::exponent_mask);
1295  output_bits |= shifted_exponent;
1296
1297  T output_float = spvutils::BitwiseCast<T>(output_bits);
1298  value.set_value(output_float);
1299
1300  return 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) {
1309  auto float_val = value.getAsFloat();
1310  switch (std::fpclassify(float_val)) {
1311    case FP_ZERO:
1312    case FP_NORMAL: {
1313      auto saved_precision = os.precision();
1314      os.precision(std::numeric_limits<T>::digits10);
1315      os << float_val;
1316      os.precision(saved_precision);
1317    } break;
1318    default:
1319      os << HexFloat<FloatProxy<T>>(value);
1320      break;
1321  }
1322  return os;
1323}
1324
1325template <>
1326inline std::ostream& operator<<<Float16>(std::ostream& os,
1327                                         const FloatProxy<Float16>& value) {
1328  os << HexFloat<FloatProxy<Float16>>(value);
1329  return os;
1330}
1331}
1332
1333#endif  // LIBSPIRV_UTIL_HEX_FLOAT_H_