Coverage Report

Created: 2024-09-11 07:09

/src/spirv-tools/source/util/hex_float.h
Line
Count
Source (jump to first uncovered line)
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 SOURCE_UTIL_HEX_FLOAT_H_
16
#define SOURCE_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
#include <vector>
26
27
#include "source/util/bitutils.h"
28
29
#ifndef __GNUC__
30
#define GCC_VERSION 0
31
#else
32
#define GCC_VERSION \
33
  (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
34
#endif
35
36
namespace spvtools {
37
namespace utils {
38
39
class Float16 {
40
 public:
41
41.2k
  Float16(uint16_t v) : val(v) {}
42
  Float16() = default;
43
0
  static bool isNan(const Float16& val) {
44
0
    return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0);
45
0
  }
46
  // Returns true if the given value is any kind of infinity.
47
14.1k
  static bool isInfinity(const Float16& val) {
48
14.1k
    return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0);
49
14.1k
  }
50
0
  Float16(const Float16& other) { val = other.val; }
51
27.1k
  uint16_t get_value() const { return val; }
52
53
  // Returns the maximum normal value.
54
28
  static Float16 max() { return Float16(0x7bff); }
55
  // Returns the lowest normal value.
56
8
  static Float16 lowest() { return Float16(0xfbff); }
57
58
 private:
59
  uint16_t val;
60
};
61
62
// To specialize this type, you must override uint_type to define
63
// an unsigned integer that can fit your floating point type.
64
// You must also add a isNan function that returns true if
65
// a value is Nan.
66
template <typename T>
67
struct FloatProxyTraits {
68
  using uint_type = void;
69
};
70
71
template <>
72
struct FloatProxyTraits<float> {
73
  using uint_type = uint32_t;
74
0
  static bool isNan(float f) { return std::isnan(f); }
75
  // Returns true if the given value is any kind of infinity.
76
30.2k
  static bool isInfinity(float f) { return std::isinf(f); }
77
  // Returns the maximum normal value.
78
10
  static float max() { return std::numeric_limits<float>::max(); }
79
  // Returns the lowest normal value.
80
8
  static float lowest() { return std::numeric_limits<float>::lowest(); }
81
  // Returns the value as the native floating point format.
82
4.25M
  static float getAsFloat(const uint_type& t) { return BitwiseCast<float>(t); }
83
  // Returns the bits from the given floating pointer number.
84
2.46M
  static uint_type getBitsFromFloat(const float& t) {
85
2.46M
    return BitwiseCast<uint_type>(t);
86
2.46M
  }
87
  // Returns the bitwidth.
88
1.48M
  static uint32_t width() { return 32u; }
89
};
90
91
template <>
92
struct FloatProxyTraits<double> {
93
  using uint_type = uint64_t;
94
0
  static bool isNan(double f) { return std::isnan(f); }
95
  // Returns true if the given value is any kind of infinity.
96
6.46k
  static bool isInfinity(double f) { return std::isinf(f); }
97
  // Returns the maximum normal value.
98
6
  static double max() { return std::numeric_limits<double>::max(); }
99
  // Returns the lowest normal value.
100
6
  static double lowest() { return std::numeric_limits<double>::lowest(); }
101
  // Returns the value as the native floating point format.
102
26.7k
  static double getAsFloat(const uint_type& t) {
103
26.7k
    return BitwiseCast<double>(t);
104
26.7k
  }
105
  // Returns the bits from the given floating pointer number.
106
47.1k
  static uint_type getBitsFromFloat(const double& t) {
107
47.1k
    return BitwiseCast<uint_type>(t);
108
47.1k
  }
109
  // Returns the bitwidth.
110
0
  static uint32_t width() { return 64u; }
111
};
112
113
template <>
114
struct FloatProxyTraits<Float16> {
115
  using uint_type = uint16_t;
116
0
  static bool isNan(Float16 f) { return Float16::isNan(f); }
117
  // Returns true if the given value is any kind of infinity.
118
0
  static bool isInfinity(Float16 f) { return Float16::isInfinity(f); }
119
  // Returns the maximum normal value.
120
0
  static Float16 max() { return Float16::max(); }
121
  // Returns the lowest normal value.
122
0
  static Float16 lowest() { return Float16::lowest(); }
123
  // Returns the value as the native floating point format.
124
41.2k
  static Float16 getAsFloat(const uint_type& t) { return Float16(t); }
125
  // Returns the bits from the given floating pointer number.
126
36
  static uint_type getBitsFromFloat(const Float16& t) { return t.get_value(); }
127
  // Returns the bitwidth.
128
0
  static uint32_t width() { return 16u; }
129
};
130
131
// Since copying a floating point number (especially if it is NaN)
132
// does not guarantee that bits are preserved, this class lets us
133
// store the type and use it as a float when necessary.
134
template <typename T>
135
class FloatProxy {
136
 public:
137
  using uint_type = typename FloatProxyTraits<T>::uint_type;
138
139
  // Since this is to act similar to the normal floats,
140
  // do not initialize the data by default.
141
  FloatProxy() = default;
142
143
  // Intentionally non-explicit. This is a proxy type so
144
  // implicit conversions allow us to use it more transparently.
145
2.51M
  FloatProxy(T val) { data_ = FloatProxyTraits<T>::getBitsFromFloat(val); }
spvtools::utils::FloatProxy<float>::FloatProxy(float)
Line
Count
Source
145
2.46M
  FloatProxy(T val) { data_ = FloatProxyTraits<T>::getBitsFromFloat(val); }
spvtools::utils::FloatProxy<spvtools::utils::Float16>::FloatProxy(spvtools::utils::Float16)
Line
Count
Source
145
36
  FloatProxy(T val) { data_ = FloatProxyTraits<T>::getBitsFromFloat(val); }
spvtools::utils::FloatProxy<double>::FloatProxy(double)
Line
Count
Source
145
47.1k
  FloatProxy(T val) { data_ = FloatProxyTraits<T>::getBitsFromFloat(val); }
146
147
  // Intentionally non-explicit. This is a proxy type so
148
  // implicit conversions allow us to use it more transparently.
149
4.37M
  FloatProxy(uint_type val) { data_ = val; }
spvtools::utils::FloatProxy<spvtools::utils::Float16>::FloatProxy(unsigned short)
Line
Count
Source
149
226k
  FloatProxy(uint_type val) { data_ = val; }
spvtools::utils::FloatProxy<float>::FloatProxy(unsigned int)
Line
Count
Source
149
4.11M
  FloatProxy(uint_type val) { data_ = val; }
spvtools::utils::FloatProxy<double>::FloatProxy(unsigned long)
Line
Count
Source
149
37.6k
  FloatProxy(uint_type val) { data_ = val; }
150
151
  // This is helpful to have and is guaranteed not to stomp bits.
152
9.62k
  FloatProxy<T> operator-() const {
153
9.62k
    return static_cast<uint_type>(data_ ^
154
9.62k
                                  (uint_type(0x1) << (sizeof(T) * 8 - 1)));
155
9.62k
  }
spvtools::utils::FloatProxy<float>::operator-() const
Line
Count
Source
152
5.13k
  FloatProxy<T> operator-() const {
153
5.13k
    return static_cast<uint_type>(data_ ^
154
5.13k
                                  (uint_type(0x1) << (sizeof(T) * 8 - 1)));
155
5.13k
  }
spvtools::utils::FloatProxy<spvtools::utils::Float16>::operator-() const
Line
Count
Source
152
730
  FloatProxy<T> operator-() const {
153
730
    return static_cast<uint_type>(data_ ^
154
730
                                  (uint_type(0x1) << (sizeof(T) * 8 - 1)));
155
730
  }
spvtools::utils::FloatProxy<double>::operator-() const
Line
Count
Source
152
3.75k
  FloatProxy<T> operator-() const {
153
3.75k
    return static_cast<uint_type>(data_ ^
154
3.75k
                                  (uint_type(0x1) << (sizeof(T) * 8 - 1)));
155
3.75k
  }
156
157
  // Returns the data as a floating point value.
158
4.31M
  T getAsFloat() const { return FloatProxyTraits<T>::getAsFloat(data_); }
spvtools::utils::FloatProxy<float>::getAsFloat() const
Line
Count
Source
158
4.25M
  T getAsFloat() const { return FloatProxyTraits<T>::getAsFloat(data_); }
spvtools::utils::FloatProxy<spvtools::utils::Float16>::getAsFloat() const
Line
Count
Source
158
41.2k
  T getAsFloat() const { return FloatProxyTraits<T>::getAsFloat(data_); }
spvtools::utils::FloatProxy<double>::getAsFloat() const
Line
Count
Source
158
26.7k
  T getAsFloat() const { return FloatProxyTraits<T>::getAsFloat(data_); }
159
160
  // Returns the raw data.
161
2.93M
  uint_type data() const { return data_; }
spvtools::utils::FloatProxy<float>::data() const
Line
Count
Source
161
2.78M
  uint_type data() const { return data_; }
spvtools::utils::FloatProxy<spvtools::utils::Float16>::data() const
Line
Count
Source
161
131k
  uint_type data() const { return data_; }
spvtools::utils::FloatProxy<double>::data() const
Line
Count
Source
161
18.7k
  uint_type data() const { return data_; }
162
163
  // Returns a vector of words suitable for use in an Operand.
164
1.48M
  std::vector<uint32_t> GetWords() const {
165
1.48M
    std::vector<uint32_t> words;
166
1.48M
    if (FloatProxyTraits<T>::width() == 64) {
167
0
      FloatProxyTraits<double>::uint_type d = data();
168
0
      words.push_back(static_cast<uint32_t>(d));
169
0
      words.push_back(static_cast<uint32_t>(d >> 32));
170
1.48M
    } else {
171
1.48M
      words.push_back(static_cast<uint32_t>(data()));
172
1.48M
    }
173
1.48M
    return words;
174
1.48M
  }
Unexecuted instantiation: spvtools::utils::FloatProxy<double>::GetWords() const
spvtools::utils::FloatProxy<float>::GetWords() const
Line
Count
Source
164
1.48M
  std::vector<uint32_t> GetWords() const {
165
1.48M
    std::vector<uint32_t> words;
166
1.48M
    if (FloatProxyTraits<T>::width() == 64) {
167
0
      FloatProxyTraits<double>::uint_type d = data();
168
0
      words.push_back(static_cast<uint32_t>(d));
169
0
      words.push_back(static_cast<uint32_t>(d >> 32));
170
1.48M
    } else {
171
1.48M
      words.push_back(static_cast<uint32_t>(data()));
172
1.48M
    }
173
1.48M
    return words;
174
1.48M
  }
175
176
  // Returns true if the value represents any type of NaN.
177
  bool isNan() { return FloatProxyTraits<T>::isNan(getAsFloat()); }
178
  // Returns true if the value represents any type of infinity.
179
36.7k
  bool isInfinity() { return FloatProxyTraits<T>::isInfinity(getAsFloat()); }
spvtools::utils::FloatProxy<float>::isInfinity()
Line
Count
Source
179
30.2k
  bool isInfinity() { return FloatProxyTraits<T>::isInfinity(getAsFloat()); }
spvtools::utils::FloatProxy<double>::isInfinity()
Line
Count
Source
179
6.46k
  bool isInfinity() { return FloatProxyTraits<T>::isInfinity(getAsFloat()); }
180
181
  // Returns the maximum normal value.
182
16
  static FloatProxy<T> max() {
183
16
    return FloatProxy<T>(FloatProxyTraits<T>::max());
184
16
  }
spvtools::utils::FloatProxy<float>::max()
Line
Count
Source
182
10
  static FloatProxy<T> max() {
183
10
    return FloatProxy<T>(FloatProxyTraits<T>::max());
184
10
  }
spvtools::utils::FloatProxy<double>::max()
Line
Count
Source
182
6
  static FloatProxy<T> max() {
183
6
    return FloatProxy<T>(FloatProxyTraits<T>::max());
184
6
  }
185
  // Returns the lowest normal value.
186
14
  static FloatProxy<T> lowest() {
187
14
    return FloatProxy<T>(FloatProxyTraits<T>::lowest());
188
14
  }
spvtools::utils::FloatProxy<float>::lowest()
Line
Count
Source
186
8
  static FloatProxy<T> lowest() {
187
8
    return FloatProxy<T>(FloatProxyTraits<T>::lowest());
188
8
  }
spvtools::utils::FloatProxy<double>::lowest()
Line
Count
Source
186
6
  static FloatProxy<T> lowest() {
187
6
    return FloatProxy<T>(FloatProxyTraits<T>::lowest());
188
6
  }
189
190
 private:
191
  uint_type data_;
192
};
193
194
template <typename T>
195
bool operator==(const FloatProxy<T>& first, const FloatProxy<T>& second) {
196
  return first.data() == second.data();
197
}
198
199
// Reads a FloatProxy value as a normal float from a stream.
200
template <typename T>
201
36.7k
std::istream& operator>>(std::istream& is, FloatProxy<T>& value) {
202
36.7k
  T float_val = static_cast<T>(0.0);
203
36.7k
  is >> float_val;
204
36.7k
  value = FloatProxy<T>(float_val);
205
36.7k
  return is;
206
36.7k
}
std::__1::basic_istream<char, std::__1::char_traits<char> >& spvtools::utils::operator>><float>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, spvtools::utils::FloatProxy<float>&)
Line
Count
Source
201
30.2k
std::istream& operator>>(std::istream& is, FloatProxy<T>& value) {
202
30.2k
  T float_val = static_cast<T>(0.0);
203
30.2k
  is >> float_val;
204
30.2k
  value = FloatProxy<T>(float_val);
205
30.2k
  return is;
206
30.2k
}
std::__1::basic_istream<char, std::__1::char_traits<char> >& spvtools::utils::operator>><double>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, spvtools::utils::FloatProxy<double>&)
Line
Count
Source
201
6.46k
std::istream& operator>>(std::istream& is, FloatProxy<T>& value) {
202
6.46k
  T float_val = static_cast<T>(0.0);
203
6.46k
  is >> float_val;
204
6.46k
  value = FloatProxy<T>(float_val);
205
6.46k
  return is;
206
6.46k
}
207
208
// This is an example traits. It is not meant to be used in practice, but will
209
// be the default for any non-specialized type.
210
template <typename T>
211
struct HexFloatTraits {
212
  // Integer type that can store the bit representation of this hex-float.
213
  using uint_type = void;
214
  // Signed integer type that can store the bit representation of this
215
  // hex-float.
216
  using int_type = void;
217
  // The numerical type that this HexFloat represents.
218
  using underlying_type = void;
219
  // The type needed to construct the underlying type.
220
  using native_type = void;
221
  // The number of bits that are actually relevant in the uint_type.
222
  // This allows us to deal with, for example, 24-bit values in a 32-bit
223
  // integer.
224
  static const uint32_t num_used_bits = 0;
225
  // Number of bits that represent the exponent.
226
  static const uint32_t num_exponent_bits = 0;
227
  // Number of bits that represent the fractional part.
228
  static const uint32_t num_fraction_bits = 0;
229
  // The bias of the exponent. (How much we need to subtract from the stored
230
  // value to get the correct value.)
231
  static const uint32_t exponent_bias = 0;
232
};
233
234
// Traits for IEEE float.
235
// 1 sign bit, 8 exponent bits, 23 fractional bits.
236
template <>
237
struct HexFloatTraits<FloatProxy<float>> {
238
  using uint_type = uint32_t;
239
  using int_type = int32_t;
240
  using underlying_type = FloatProxy<float>;
241
  using native_type = float;
242
  static const uint_type num_used_bits = 32;
243
  static const uint_type num_exponent_bits = 8;
244
  static const uint_type num_fraction_bits = 23;
245
  static const uint_type exponent_bias = 127;
246
};
247
248
// Traits for IEEE double.
249
// 1 sign bit, 11 exponent bits, 52 fractional bits.
250
template <>
251
struct HexFloatTraits<FloatProxy<double>> {
252
  using uint_type = uint64_t;
253
  using int_type = int64_t;
254
  using underlying_type = FloatProxy<double>;
255
  using native_type = double;
256
  static const uint_type num_used_bits = 64;
257
  static const uint_type num_exponent_bits = 11;
258
  static const uint_type num_fraction_bits = 52;
259
  static const uint_type exponent_bias = 1023;
260
};
261
262
// Traits for IEEE half.
263
// 1 sign bit, 5 exponent bits, 10 fractional bits.
264
template <>
265
struct HexFloatTraits<FloatProxy<Float16>> {
266
  using uint_type = uint16_t;
267
  using int_type = int16_t;
268
  using underlying_type = uint16_t;
269
  using native_type = uint16_t;
270
  static const uint_type num_used_bits = 16;
271
  static const uint_type num_exponent_bits = 5;
272
  static const uint_type num_fraction_bits = 10;
273
  static const uint_type exponent_bias = 15;
274
};
275
276
enum class round_direction {
277
  kToZero,
278
  kToNearestEven,
279
  kToPositiveInfinity,
280
  kToNegativeInfinity,
281
  max = kToNegativeInfinity
282
};
283
284
// Template class that houses a floating pointer number.
285
// It exposes a number of constants based on the provided traits to
286
// assist in interpreting the bits of the value.
287
template <typename T, typename Traits = HexFloatTraits<T>>
288
class HexFloat {
289
 public:
290
  using uint_type = typename Traits::uint_type;
291
  using int_type = typename Traits::int_type;
292
  using underlying_type = typename Traits::underlying_type;
293
  using native_type = typename Traits::native_type;
294
295
600k
  explicit HexFloat(T f) : value_(f) {}
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::HexFloat(spvtools::utils::FloatProxy<float>)
Line
Count
Source
295
389k
  explicit HexFloat(T f) : value_(f) {}
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::HexFloat(spvtools::utils::FloatProxy<spvtools::utils::Float16>)
Line
Count
Source
295
172k
  explicit HexFloat(T f) : value_(f) {}
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >::HexFloat(spvtools::utils::FloatProxy<double>)
Line
Count
Source
295
38.9k
  explicit HexFloat(T f) : value_(f) {}
296
297
526k
  T value() const { return value_; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::value() const
Line
Count
Source
297
172k
  T value() const { return value_; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::value() const
Line
Count
Source
297
335k
  T value() const { return value_; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >::value() const
Line
Count
Source
297
18.5k
  T value() const { return value_; }
298
154k
  void set_value(T f) { value_ = f; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::set_value(spvtools::utils::FloatProxy<float>)
Line
Count
Source
298
70.9k
  void set_value(T f) { value_ = f; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::set_value(spvtools::utils::FloatProxy<spvtools::utils::Float16>)
Line
Count
Source
298
43.4k
  void set_value(T f) { value_ = f; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >::set_value(spvtools::utils::FloatProxy<double>)
Line
Count
Source
298
40.3k
  void set_value(T f) { value_ = f; }
299
300
  // These are all written like this because it is convenient to have
301
  // compile-time constants for all of these values.
302
303
  // Pass-through values to save typing.
304
  static const uint32_t num_used_bits = Traits::num_used_bits;
305
  static const uint32_t exponent_bias = Traits::exponent_bias;
306
  static const uint32_t num_exponent_bits = Traits::num_exponent_bits;
307
  static const uint32_t num_fraction_bits = Traits::num_fraction_bits;
308
309
  // Number of bits to shift left to set the highest relevant bit.
310
  static const uint32_t top_bit_left_shift = num_used_bits - 1;
311
  // How many nibbles (hex characters) the fractional part takes up.
312
  static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4;
313
  // If the fractional part does not fit evenly into a hex character (4-bits)
314
  // then we have to left-shift to get rid of leading 0s. This is the amount
315
  // we have to shift (might be 0).
316
  static const uint32_t num_overflow_bits =
317
      fraction_nibbles * 4 - num_fraction_bits;
318
319
  // The representation of the fraction, not the actual bits. This
320
  // includes the leading bit that is usually implicit.
321
  static const uint_type fraction_represent_mask =
322
      SetBits<uint_type, 0, num_fraction_bits + num_overflow_bits>::get;
323
324
  // The topmost bit in the nibble-aligned fraction.
325
  static const uint_type fraction_top_bit =
326
      uint_type(1) << (num_fraction_bits + num_overflow_bits - 1);
327
328
  // The least significant bit in the exponent, which is also the bit
329
  // immediately to the left of the significand.
330
  static const uint_type first_exponent_bit = uint_type(1)
331
                                              << (num_fraction_bits);
332
333
  // The mask for the encoded fraction. It does not include the
334
  // implicit bit.
335
  static const uint_type fraction_encode_mask =
336
      SetBits<uint_type, 0, num_fraction_bits>::get;
337
338
  // The bit that is used as a sign.
339
  static const uint_type sign_mask = uint_type(1) << top_bit_left_shift;
340
341
  // The bits that represent the exponent.
342
  static const uint_type exponent_mask =
343
      SetBits<uint_type, num_fraction_bits, num_exponent_bits>::get;
344
345
  // How far left the exponent is shifted.
346
  static const uint32_t exponent_left_shift = num_fraction_bits;
347
348
  // How far from the right edge the fraction is shifted.
349
  static const uint32_t fraction_right_shift =
350
      static_cast<uint32_t>(sizeof(uint_type) * 8) - num_fraction_bits;
351
352
  // The maximum representable unbiased exponent.
353
  static const int_type max_exponent =
354
      (exponent_mask >> num_fraction_bits) - exponent_bias;
355
  // The minimum representable exponent for normalized numbers.
356
  static const int_type min_exponent = -static_cast<int_type>(exponent_bias);
357
358
  // Returns the bits associated with the value.
359
106k
  uint_type getBits() const { return value_.data(); }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::getBits() const
Line
Count
Source
359
105k
  uint_type getBits() const { return value_.data(); }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::getBits() const
Line
Count
Source
359
1.12k
  uint_type getBits() const { return value_.data(); }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >::getBits() const
Line
Count
Source
359
12
  uint_type getBits() const { return value_.data(); }
360
361
  // Returns the bits associated with the value, without the leading sign bit.
362
25.4k
  uint_type getUnsignedBits() const {
363
25.4k
    return static_cast<uint_type>(value_.data() & ~sign_mask);
364
25.4k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::getUnsignedBits() const
Line
Count
Source
362
25.0k
  uint_type getUnsignedBits() const {
363
25.0k
    return static_cast<uint_type>(value_.data() & ~sign_mask);
364
25.0k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >::getUnsignedBits() const
Line
Count
Source
362
216
  uint_type getUnsignedBits() const {
363
216
    return static_cast<uint_type>(value_.data() & ~sign_mask);
364
216
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::getUnsignedBits() const
Line
Count
Source
362
264
  uint_type getUnsignedBits() const {
363
264
    return static_cast<uint_type>(value_.data() & ~sign_mask);
364
264
  }
365
366
  // Returns the bits associated with the exponent, shifted to start at the
367
  // lsb of the type.
368
24.9k
  const uint_type getExponentBits() const {
369
24.9k
    return static_cast<uint_type>((getBits() & exponent_mask) >>
370
24.9k
                                  num_fraction_bits);
371
24.9k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::getExponentBits() const
Line
Count
Source
368
24.7k
  const uint_type getExponentBits() const {
369
24.7k
    return static_cast<uint_type>((getBits() & exponent_mask) >>
370
24.7k
                                  num_fraction_bits);
371
24.7k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::getExponentBits() const
Line
Count
Source
368
228
  const uint_type getExponentBits() const {
369
228
    return static_cast<uint_type>((getBits() & exponent_mask) >>
370
228
                                  num_fraction_bits);
371
228
  }
372
373
  // Returns the exponent in unbiased form. This is the exponent in the
374
  // human-friendly form.
375
24.9k
  const int_type getUnbiasedExponent() const {
376
24.9k
    return static_cast<int_type>(getExponentBits() - exponent_bias);
377
24.9k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::getUnbiasedExponent() const
Line
Count
Source
375
24.7k
  const int_type getUnbiasedExponent() const {
376
24.7k
    return static_cast<int_type>(getExponentBits() - exponent_bias);
377
24.7k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::getUnbiasedExponent() const
Line
Count
Source
375
228
  const int_type getUnbiasedExponent() const {
376
228
    return static_cast<int_type>(getExponentBits() - exponent_bias);
377
228
  }
378
379
  // Returns just the significand bits from the value.
380
28.5k
  const uint_type getSignificandBits() const {
381
28.5k
    return getBits() & fraction_encode_mask;
382
28.5k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::getSignificandBits() const
Line
Count
Source
380
28.2k
  const uint_type getSignificandBits() const {
381
28.2k
    return getBits() & fraction_encode_mask;
382
28.2k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::getSignificandBits() const
Line
Count
Source
380
280
  const uint_type getSignificandBits() const {
381
280
    return getBits() & fraction_encode_mask;
382
280
  }
383
384
  // If the number was normalized, returns the unbiased exponent.
385
  // If the number was denormal, normalize the exponent first.
386
12.4k
  const int_type getUnbiasedNormalizedExponent() const {
387
12.4k
    if ((getBits() & ~sign_mask) == 0) {  // special case if everything is 0
388
0
      return 0;
389
0
    }
390
12.4k
    int_type exp = getUnbiasedExponent();
391
12.4k
    if (exp == min_exponent) {  // We are in denorm land.
392
3.61k
      uint_type significand_bits = getSignificandBits();
393
21.3k
      while ((significand_bits & (first_exponent_bit >> 1)) == 0) {
394
17.6k
        significand_bits = static_cast<uint_type>(significand_bits << 1);
395
17.6k
        exp = static_cast<int_type>(exp - 1);
396
17.6k
      }
397
3.61k
      significand_bits &= fraction_encode_mask;
398
3.61k
    }
399
12.4k
    return exp;
400
12.4k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::getUnbiasedNormalizedExponent() const
Line
Count
Source
386
12.3k
  const int_type getUnbiasedNormalizedExponent() const {
387
12.3k
    if ((getBits() & ~sign_mask) == 0) {  // special case if everything is 0
388
0
      return 0;
389
0
    }
390
12.3k
    int_type exp = getUnbiasedExponent();
391
12.3k
    if (exp == min_exponent) {  // We are in denorm land.
392
3.55k
      uint_type significand_bits = getSignificandBits();
393
21.0k
      while ((significand_bits & (first_exponent_bit >> 1)) == 0) {
394
17.5k
        significand_bits = static_cast<uint_type>(significand_bits << 1);
395
17.5k
        exp = static_cast<int_type>(exp - 1);
396
17.5k
      }
397
3.55k
      significand_bits &= fraction_encode_mask;
398
3.55k
    }
399
12.3k
    return exp;
400
12.3k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::getUnbiasedNormalizedExponent() const
Line
Count
Source
386
114
  const int_type getUnbiasedNormalizedExponent() const {
387
114
    if ((getBits() & ~sign_mask) == 0) {  // special case if everything is 0
388
0
      return 0;
389
0
    }
390
114
    int_type exp = getUnbiasedExponent();
391
114
    if (exp == min_exponent) {  // We are in denorm land.
392
52
      uint_type significand_bits = getSignificandBits();
393
214
      while ((significand_bits & (first_exponent_bit >> 1)) == 0) {
394
162
        significand_bits = static_cast<uint_type>(significand_bits << 1);
395
162
        exp = static_cast<int_type>(exp - 1);
396
162
      }
397
52
      significand_bits &= fraction_encode_mask;
398
52
    }
399
114
    return exp;
400
114
  }
401
402
  // Returns the signficand after it has been normalized.
403
12.4k
  const uint_type getNormalizedSignificand() const {
404
12.4k
    int_type unbiased_exponent = getUnbiasedNormalizedExponent();
405
12.4k
    uint_type significand = getSignificandBits();
406
33.7k
    for (int_type i = unbiased_exponent; i <= min_exponent; ++i) {
407
21.3k
      significand = static_cast<uint_type>(significand << 1);
408
21.3k
    }
409
12.4k
    significand &= fraction_encode_mask;
410
12.4k
    return significand;
411
12.4k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::getNormalizedSignificand() const
Line
Count
Source
403
12.3k
  const uint_type getNormalizedSignificand() const {
404
12.3k
    int_type unbiased_exponent = getUnbiasedNormalizedExponent();
405
12.3k
    uint_type significand = getSignificandBits();
406
33.4k
    for (int_type i = unbiased_exponent; i <= min_exponent; ++i) {
407
21.0k
      significand = static_cast<uint_type>(significand << 1);
408
21.0k
    }
409
12.3k
    significand &= fraction_encode_mask;
410
12.3k
    return significand;
411
12.3k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::getNormalizedSignificand() const
Line
Count
Source
403
114
  const uint_type getNormalizedSignificand() const {
404
114
    int_type unbiased_exponent = getUnbiasedNormalizedExponent();
405
114
    uint_type significand = getSignificandBits();
406
328
    for (int_type i = unbiased_exponent; i <= min_exponent; ++i) {
407
214
      significand = static_cast<uint_type>(significand << 1);
408
214
    }
409
114
    significand &= fraction_encode_mask;
410
114
    return significand;
411
114
  }
412
413
  // Returns true if this number represents a negative value.
414
25.2k
  bool isNegative() const { return (getBits() & sign_mask) != 0; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::isNegative() const
Line
Count
Source
414
24.8k
  bool isNegative() const { return (getBits() & sign_mask) != 0; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::isNegative() const
Line
Count
Source
414
368
  bool isNegative() const { return (getBits() & sign_mask) != 0; }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >::isNegative() const
Line
Count
Source
414
12
  bool isNegative() const { return (getBits() & sign_mask) != 0; }
415
416
  // Sets this HexFloat from the individual components.
417
  // Note this assumes EVERY significand is normalized, and has an implicit
418
  // leading one. This means that the only way that this method will set 0,
419
  // is if you set a number so denormalized that it underflows.
420
  // Do not use this method with raw bits extracted from a subnormal number,
421
  // since subnormals do not have an implicit leading 1 in the significand.
422
  // The significand is also expected to be in the
423
  // lowest-most num_fraction_bits of the uint_type.
424
  // The exponent is expected to be unbiased, meaning an exponent of
425
  // 0 actually means 0.
426
  // If underflow_round_up is set, then on underflow, if a number is non-0
427
  // and would underflow, we round up to the smallest denorm.
428
  void setFromSignUnbiasedExponentAndNormalizedSignificand(
429
      bool negative, int_type exponent, uint_type significand,
430
10.5k
      bool round_denorm_up) {
431
10.5k
    bool significand_is_zero = significand == 0;
432
433
10.5k
    if (exponent <= min_exponent) {
434
      // If this was denormalized, then we have to shift the bit on, meaning
435
      // the significand is not zero.
436
5.28k
      significand_is_zero = false;
437
5.28k
      significand |= first_exponent_bit;
438
5.28k
      significand = static_cast<uint_type>(significand >> 1);
439
5.28k
    }
440
441
449k
    while (exponent < min_exponent) {
442
439k
      significand = static_cast<uint_type>(significand >> 1);
443
439k
      ++exponent;
444
439k
    }
445
446
10.5k
    if (exponent == min_exponent) {
447
5.28k
      if (significand == 0 && !significand_is_zero && round_denorm_up) {
448
0
        significand = static_cast<uint_type>(0x1);
449
0
      }
450
5.28k
    }
451
452
10.5k
    uint_type new_value = 0;
453
10.5k
    if (negative) {
454
2.25k
      new_value = static_cast<uint_type>(new_value | sign_mask);
455
2.25k
    }
456
10.5k
    exponent = static_cast<int_type>(exponent + exponent_bias);
457
10.5k
    assert(exponent >= 0);
458
459
    // put it all together
460
10.5k
    exponent = static_cast<uint_type>((exponent << exponent_left_shift) &
461
10.5k
                                      exponent_mask);
462
10.5k
    significand = static_cast<uint_type>(significand & fraction_encode_mask);
463
10.5k
    new_value = static_cast<uint_type>(new_value | (exponent | significand));
464
10.5k
    value_ = T(new_value);
465
10.5k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::setFromSignUnbiasedExponentAndNormalizedSignificand(bool, short, unsigned short, bool)
Line
Count
Source
430
10.4k
      bool round_denorm_up) {
431
10.4k
    bool significand_is_zero = significand == 0;
432
433
10.4k
    if (exponent <= min_exponent) {
434
      // If this was denormalized, then we have to shift the bit on, meaning
435
      // the significand is not zero.
436
5.28k
      significand_is_zero = false;
437
5.28k
      significand |= first_exponent_bit;
438
5.28k
      significand = static_cast<uint_type>(significand >> 1);
439
5.28k
    }
440
441
449k
    while (exponent < min_exponent) {
442
439k
      significand = static_cast<uint_type>(significand >> 1);
443
439k
      ++exponent;
444
439k
    }
445
446
10.4k
    if (exponent == min_exponent) {
447
5.28k
      if (significand == 0 && !significand_is_zero && round_denorm_up) {
448
0
        significand = static_cast<uint_type>(0x1);
449
0
      }
450
5.28k
    }
451
452
10.4k
    uint_type new_value = 0;
453
10.4k
    if (negative) {
454
2.25k
      new_value = static_cast<uint_type>(new_value | sign_mask);
455
2.25k
    }
456
10.4k
    exponent = static_cast<int_type>(exponent + exponent_bias);
457
10.4k
    assert(exponent >= 0);
458
459
    // put it all together
460
10.4k
    exponent = static_cast<uint_type>((exponent << exponent_left_shift) &
461
10.4k
                                      exponent_mask);
462
10.4k
    significand = static_cast<uint_type>(significand & fraction_encode_mask);
463
10.4k
    new_value = static_cast<uint_type>(new_value | (exponent | significand));
464
10.4k
    value_ = T(new_value);
465
10.4k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::setFromSignUnbiasedExponentAndNormalizedSignificand(bool, int, unsigned int, bool)
Line
Count
Source
430
68
      bool round_denorm_up) {
431
68
    bool significand_is_zero = significand == 0;
432
433
68
    if (exponent <= min_exponent) {
434
      // If this was denormalized, then we have to shift the bit on, meaning
435
      // the significand is not zero.
436
0
      significand_is_zero = false;
437
0
      significand |= first_exponent_bit;
438
0
      significand = static_cast<uint_type>(significand >> 1);
439
0
    }
440
441
68
    while (exponent < min_exponent) {
442
0
      significand = static_cast<uint_type>(significand >> 1);
443
0
      ++exponent;
444
0
    }
445
446
68
    if (exponent == min_exponent) {
447
0
      if (significand == 0 && !significand_is_zero && round_denorm_up) {
448
0
        significand = static_cast<uint_type>(0x1);
449
0
      }
450
0
    }
451
452
68
    uint_type new_value = 0;
453
68
    if (negative) {
454
0
      new_value = static_cast<uint_type>(new_value | sign_mask);
455
0
    }
456
68
    exponent = static_cast<int_type>(exponent + exponent_bias);
457
68
    assert(exponent >= 0);
458
459
    // put it all together
460
68
    exponent = static_cast<uint_type>((exponent << exponent_left_shift) &
461
68
                                      exponent_mask);
462
68
    significand = static_cast<uint_type>(significand & fraction_encode_mask);
463
68
    new_value = static_cast<uint_type>(new_value | (exponent | significand));
464
68
    value_ = T(new_value);
465
68
  }
466
467
  // Increments the significand of this number by the given amount.
468
  // If this would spill the significand into the implicit bit,
469
  // carry is set to true and the significand is shifted to fit into
470
  // the correct location, otherwise carry is set to false.
471
  // All significands and to_increment are assumed to be within the bounds
472
  // for a valid significand.
473
  static uint_type incrementSignificand(uint_type significand,
474
0
                                        uint_type to_increment, bool* carry) {
475
0
    significand = static_cast<uint_type>(significand + to_increment);
476
0
    *carry = false;
477
0
    if (significand & first_exponent_bit) {
478
0
      *carry = true;
479
      // The implicit 1-bit will have carried, so we should zero-out the
480
      // top bit and shift back.
481
0
      significand = static_cast<uint_type>(significand & ~first_exponent_bit);
482
0
      significand = static_cast<uint_type>(significand >> 1);
483
0
    }
484
0
    return significand;
485
0
  }
Unexecuted instantiation: spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::incrementSignificand(unsigned int, unsigned int, bool*)
Unexecuted instantiation: spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::incrementSignificand(unsigned short, unsigned short, bool*)
486
487
#if GCC_VERSION == 40801
488
  // These exist because MSVC throws warnings on negative right-shifts
489
  // even if they are not going to be executed. Eg:
490
  // constant_number < 0? 0: constant_number
491
  // These convert the negative left-shifts into right shifts.
492
  template <int_type N>
493
  struct negatable_left_shift {
494
    static uint_type val(uint_type val) {
495
      if (N > 0) {
496
        return static_cast<uint_type>(val << N);
497
      } else {
498
        return static_cast<uint_type>(val >> N);
499
      }
500
    }
501
  };
502
503
  template <int_type N>
504
  struct negatable_right_shift {
505
    static uint_type val(uint_type val) {
506
      if (N > 0) {
507
        return static_cast<uint_type>(val >> N);
508
      } else {
509
        return static_cast<uint_type>(val << N);
510
      }
511
    }
512
  };
513
514
#else
515
  // These exist because MSVC throws warnings on negative right-shifts
516
  // even if they are not going to be executed. Eg:
517
  // constant_number < 0? 0: constant_number
518
  // These convert the negative left-shifts into right shifts.
519
  template <int_type N, typename enable = void>
520
  struct negatable_left_shift {
521
1.81k
    static uint_type val(uint_type val) {
522
1.81k
      return static_cast<uint_type>(val >> -N);
523
1.81k
    }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::negatable_left_shift<-13, void>::val(unsigned int)
Line
Count
Source
521
1.81k
    static uint_type val(uint_type val) {
522
1.81k
      return static_cast<uint_type>(val >> -N);
523
1.81k
    }
Unexecuted instantiation: spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::negatable_left_shift<(short)-13, void>::val(unsigned short)
Unexecuted instantiation: spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::negatable_left_shift<(short)-14, void>::val(unsigned short)
524
  };
525
526
  template <int_type N>
527
  struct negatable_left_shift<N, typename std::enable_if<N >= 0>::type> {
528
32
    static uint_type val(uint_type val) {
529
32
      return static_cast<uint_type>(val << N);
530
32
    }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::negatable_left_shift<13, void>::val(unsigned int)
Line
Count
Source
528
2
    static uint_type val(uint_type val) {
529
2
      return static_cast<uint_type>(val << N);
530
2
    }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::negatable_left_shift<12, void>::val(unsigned int)
Line
Count
Source
528
2
    static uint_type val(uint_type val) {
529
2
      return static_cast<uint_type>(val << N);
530
2
    }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::negatable_left_shift<(short)13, void>::val(unsigned short)
Line
Count
Source
528
28
    static uint_type val(uint_type val) {
529
28
      return static_cast<uint_type>(val << N);
530
28
    }
531
  };
532
533
  template <int_type N, typename enable = void>
534
  struct negatable_right_shift {
535
0
    static uint_type val(uint_type val) {
536
0
      return static_cast<uint_type>(val << -N);
537
0
    }
538
  };
539
540
  template <int_type N>
541
  struct negatable_right_shift<N, typename std::enable_if<N >= 0>::type> {
542
12.3k
    static uint_type val(uint_type val) {
543
12.3k
      return static_cast<uint_type>(val >> N);
544
12.3k
    }
545
  };
546
#endif
547
548
  // Returns the significand, rounded to fit in a significand in
549
  // other_T. This is shifted so that the most significant
550
  // bit of the rounded number lines up with the most significant bit
551
  // of the returned significand.
552
  template <typename other_T>
553
  typename other_T::uint_type getRoundedNormalizedSignificand(
554
12.4k
      round_direction dir, bool* carry_bit) {
555
12.4k
    using other_uint_type = typename other_T::uint_type;
556
12.4k
    static const int_type num_throwaway_bits =
557
12.4k
        static_cast<int_type>(num_fraction_bits) -
558
12.4k
        static_cast<int_type>(other_T::num_fraction_bits);
559
560
12.4k
    static const uint_type last_significant_bit =
561
12.4k
        (num_throwaway_bits < 0)
562
12.4k
            ? 0
563
12.4k
            : negatable_left_shift<num_throwaway_bits>::val(1u);
564
12.4k
    static const uint_type first_rounded_bit =
565
12.4k
        (num_throwaway_bits < 1)
566
12.4k
            ? 0
567
12.4k
            : negatable_left_shift<num_throwaway_bits - 1>::val(1u);
568
569
12.4k
    static const uint_type throwaway_mask_bits =
570
12.4k
        num_throwaway_bits > 0 ? num_throwaway_bits : 0;
571
12.4k
    static const uint_type throwaway_mask =
572
12.4k
        SetBits<uint_type, 0, throwaway_mask_bits>::get;
573
574
12.4k
    *carry_bit = false;
575
12.4k
    other_uint_type out_val = 0;
576
12.4k
    uint_type significand = getNormalizedSignificand();
577
    // If we are up-casting, then we just have to shift to the right location.
578
12.4k
    if (num_throwaway_bits <= 0) {
579
114
      out_val = static_cast<other_uint_type>(significand);
580
114
      uint_type shift_amount = static_cast<uint_type>(-num_throwaway_bits);
581
114
      out_val = static_cast<other_uint_type>(out_val << shift_amount);
582
114
      return out_val;
583
114
    }
584
585
    // If every non-representable bit is 0, then we don't have any casting to
586
    // do.
587
12.3k
    if ((significand & throwaway_mask) == 0) {
588
8.70k
      return static_cast<other_uint_type>(
589
8.70k
          negatable_right_shift<num_throwaway_bits>::val(significand));
590
8.70k
    }
591
592
3.65k
    bool round_away_from_zero = false;
593
    // We actually have to narrow the significand here, so we have to follow the
594
    // rounding rules.
595
3.65k
    switch (dir) {
596
3.65k
      case round_direction::kToZero:
597
3.65k
        break;
598
0
      case round_direction::kToPositiveInfinity:
599
0
        round_away_from_zero = !isNegative();
600
0
        break;
601
0
      case round_direction::kToNegativeInfinity:
602
0
        round_away_from_zero = isNegative();
603
0
        break;
604
0
      case round_direction::kToNearestEven:
605
        // Have to round down, round bit is 0
606
0
        if ((first_rounded_bit & significand) == 0) {
607
0
          break;
608
0
        }
609
0
        if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) {
610
          // If any subsequent bit of the rounded portion is non-0 then we round
611
          // up.
612
0
          round_away_from_zero = true;
613
0
          break;
614
0
        }
615
        // We are exactly half-way between 2 numbers, pick even.
616
0
        if ((significand & last_significant_bit) != 0) {
617
          // 1 for our last bit, round up.
618
0
          round_away_from_zero = true;
619
0
          break;
620
0
        }
621
0
        break;
622
3.65k
    }
623
624
3.65k
    if (round_away_from_zero) {
625
0
      return static_cast<other_uint_type>(
626
0
          negatable_right_shift<num_throwaway_bits>::val(incrementSignificand(
627
0
              significand, last_significant_bit, carry_bit)));
628
3.65k
    } else {
629
3.65k
      return static_cast<other_uint_type>(
630
3.65k
          negatable_right_shift<num_throwaway_bits>::val(significand));
631
3.65k
    }
632
3.65k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::uint_type spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::getRoundedNormalizedSignificand<spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > > >(spvtools::utils::round_direction, bool*)
Line
Count
Source
554
12.3k
      round_direction dir, bool* carry_bit) {
555
12.3k
    using other_uint_type = typename other_T::uint_type;
556
12.3k
    static const int_type num_throwaway_bits =
557
12.3k
        static_cast<int_type>(num_fraction_bits) -
558
12.3k
        static_cast<int_type>(other_T::num_fraction_bits);
559
560
12.3k
    static const uint_type last_significant_bit =
561
12.3k
        (num_throwaway_bits < 0)
562
12.3k
            ? 0
563
12.3k
            : negatable_left_shift<num_throwaway_bits>::val(1u);
564
12.3k
    static const uint_type first_rounded_bit =
565
12.3k
        (num_throwaway_bits < 1)
566
12.3k
            ? 0
567
12.3k
            : negatable_left_shift<num_throwaway_bits - 1>::val(1u);
568
569
12.3k
    static const uint_type throwaway_mask_bits =
570
12.3k
        num_throwaway_bits > 0 ? num_throwaway_bits : 0;
571
12.3k
    static const uint_type throwaway_mask =
572
12.3k
        SetBits<uint_type, 0, throwaway_mask_bits>::get;
573
574
12.3k
    *carry_bit = false;
575
12.3k
    other_uint_type out_val = 0;
576
12.3k
    uint_type significand = getNormalizedSignificand();
577
    // If we are up-casting, then we just have to shift to the right location.
578
12.3k
    if (num_throwaway_bits <= 0) {
579
0
      out_val = static_cast<other_uint_type>(significand);
580
0
      uint_type shift_amount = static_cast<uint_type>(-num_throwaway_bits);
581
0
      out_val = static_cast<other_uint_type>(out_val << shift_amount);
582
0
      return out_val;
583
0
    }
584
585
    // If every non-representable bit is 0, then we don't have any casting to
586
    // do.
587
12.3k
    if ((significand & throwaway_mask) == 0) {
588
8.70k
      return static_cast<other_uint_type>(
589
8.70k
          negatable_right_shift<num_throwaway_bits>::val(significand));
590
8.70k
    }
591
592
3.65k
    bool round_away_from_zero = false;
593
    // We actually have to narrow the significand here, so we have to follow the
594
    // rounding rules.
595
3.65k
    switch (dir) {
596
3.65k
      case round_direction::kToZero:
597
3.65k
        break;
598
0
      case round_direction::kToPositiveInfinity:
599
0
        round_away_from_zero = !isNegative();
600
0
        break;
601
0
      case round_direction::kToNegativeInfinity:
602
0
        round_away_from_zero = isNegative();
603
0
        break;
604
0
      case round_direction::kToNearestEven:
605
        // Have to round down, round bit is 0
606
0
        if ((first_rounded_bit & significand) == 0) {
607
0
          break;
608
0
        }
609
0
        if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) {
610
          // If any subsequent bit of the rounded portion is non-0 then we round
611
          // up.
612
0
          round_away_from_zero = true;
613
0
          break;
614
0
        }
615
        // We are exactly half-way between 2 numbers, pick even.
616
0
        if ((significand & last_significant_bit) != 0) {
617
          // 1 for our last bit, round up.
618
0
          round_away_from_zero = true;
619
0
          break;
620
0
        }
621
0
        break;
622
3.65k
    }
623
624
3.65k
    if (round_away_from_zero) {
625
0
      return static_cast<other_uint_type>(
626
0
          negatable_right_shift<num_throwaway_bits>::val(incrementSignificand(
627
0
              significand, last_significant_bit, carry_bit)));
628
3.65k
    } else {
629
3.65k
      return static_cast<other_uint_type>(
630
3.65k
          negatable_right_shift<num_throwaway_bits>::val(significand));
631
3.65k
    }
632
3.65k
  }
spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::uint_type spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::getRoundedNormalizedSignificand<spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > > >(spvtools::utils::round_direction, bool*)
Line
Count
Source
554
114
      round_direction dir, bool* carry_bit) {
555
114
    using other_uint_type = typename other_T::uint_type;
556
114
    static const int_type num_throwaway_bits =
557
114
        static_cast<int_type>(num_fraction_bits) -
558
114
        static_cast<int_type>(other_T::num_fraction_bits);
559
560
114
    static const uint_type last_significant_bit =
561
114
        (num_throwaway_bits < 0)
562
114
            ? 0
563
114
            : negatable_left_shift<num_throwaway_bits>::val(1u);
564
114
    static const uint_type first_rounded_bit =
565
114
        (num_throwaway_bits < 1)
566
114
            ? 0
567
114
            : negatable_left_shift<num_throwaway_bits - 1>::val(1u);
568
569
114
    static const uint_type throwaway_mask_bits =
570
114
        num_throwaway_bits > 0 ? num_throwaway_bits : 0;
571
114
    static const uint_type throwaway_mask =
572
114
        SetBits<uint_type, 0, throwaway_mask_bits>::get;
573
574
114
    *carry_bit = false;
575
114
    other_uint_type out_val = 0;
576
114
    uint_type significand = getNormalizedSignificand();
577
    // If we are up-casting, then we just have to shift to the right location.
578
114
    if (num_throwaway_bits <= 0) {
579
114
      out_val = static_cast<other_uint_type>(significand);
580
114
      uint_type shift_amount = static_cast<uint_type>(-num_throwaway_bits);
581
114
      out_val = static_cast<other_uint_type>(out_val << shift_amount);
582
114
      return out_val;
583
114
    }
584
585
    // If every non-representable bit is 0, then we don't have any casting to
586
    // do.
587
0
    if ((significand & throwaway_mask) == 0) {
588
0
      return static_cast<other_uint_type>(
589
0
          negatable_right_shift<num_throwaway_bits>::val(significand));
590
0
    }
591
592
0
    bool round_away_from_zero = false;
593
    // We actually have to narrow the significand here, so we have to follow the
594
    // rounding rules.
595
0
    switch (dir) {
596
0
      case round_direction::kToZero:
597
0
        break;
598
0
      case round_direction::kToPositiveInfinity:
599
0
        round_away_from_zero = !isNegative();
600
0
        break;
601
0
      case round_direction::kToNegativeInfinity:
602
0
        round_away_from_zero = isNegative();
603
0
        break;
604
0
      case round_direction::kToNearestEven:
605
        // Have to round down, round bit is 0
606
0
        if ((first_rounded_bit & significand) == 0) {
607
0
          break;
608
0
        }
609
0
        if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) {
610
          // If any subsequent bit of the rounded portion is non-0 then we round
611
          // up.
612
0
          round_away_from_zero = true;
613
0
          break;
614
0
        }
615
        // We are exactly half-way between 2 numbers, pick even.
616
0
        if ((significand & last_significant_bit) != 0) {
617
          // 1 for our last bit, round up.
618
0
          round_away_from_zero = true;
619
0
          break;
620
0
        }
621
0
        break;
622
0
    }
623
624
0
    if (round_away_from_zero) {
625
0
      return static_cast<other_uint_type>(
626
0
          negatable_right_shift<num_throwaway_bits>::val(incrementSignificand(
627
0
              significand, last_significant_bit, carry_bit)));
628
0
    } else {
629
0
      return static_cast<other_uint_type>(
630
0
          negatable_right_shift<num_throwaway_bits>::val(significand));
631
0
    }
632
0
  }
633
634
  // Casts this value to another HexFloat. If the cast is widening,
635
  // then round_dir is ignored. If the cast is narrowing, then
636
  // the result is rounded in the direction specified.
637
  // This number will retain Nan and Inf values.
638
  // It will also saturate to Inf if the number overflows, and
639
  // underflow to (0 or min depending on rounding) if the number underflows.
640
  template <typename other_T>
641
14.6k
  void castTo(other_T& other, round_direction round_dir) {
642
14.6k
    other = other_T(static_cast<typename other_T::native_type>(0));
643
14.6k
    bool negate = isNegative();
644
14.6k
    if (getUnsignedBits() == 0) {
645
2.18k
      if (negate) {
646
772
        other.set_value(-other.value());
647
772
      }
648
2.18k
      return;
649
2.18k
    }
650
12.4k
    uint_type significand = getSignificandBits();
651
12.4k
    bool carried = false;
652
12.4k
    typename other_T::uint_type rounded_significand =
653
12.4k
        getRoundedNormalizedSignificand<other_T>(round_dir, &carried);
654
655
12.4k
    int_type exponent = getUnbiasedExponent();
656
12.4k
    if (exponent == min_exponent) {
657
      // If we are denormal, normalize the exponent, so that we can encode
658
      // easily.
659
3.61k
      exponent = static_cast<int_type>(exponent + 1);
660
21.3k
      for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0;
661
21.3k
           check_bit = static_cast<uint_type>(check_bit >> 1)) {
662
21.3k
        exponent = static_cast<int_type>(exponent - 1);
663
21.3k
        if (check_bit & significand) break;
664
21.3k
      }
665
3.61k
    }
666
667
12.4k
    bool is_nan =
668
12.4k
        (getBits() & exponent_mask) == exponent_mask && significand != 0;
669
12.4k
    bool is_inf =
670
12.4k
        !is_nan &&
671
12.4k
        ((exponent + carried) > static_cast<int_type>(other_T::exponent_bias) ||
672
10.6k
         (significand == 0 && (getBits() & exponent_mask) == exponent_mask));
673
674
    // If we are Nan or Inf we should pass that through.
675
12.4k
    if (is_inf) {
676
72
      other.set_value(typename other_T::underlying_type(
677
72
          static_cast<typename other_T::uint_type>(
678
72
              (negate ? other_T::sign_mask : 0) | other_T::exponent_mask)));
679
72
      return;
680
72
    }
681
12.3k
    if (is_nan) {
682
1.84k
      typename other_T::uint_type shifted_significand;
683
1.84k
      shifted_significand = static_cast<typename other_T::uint_type>(
684
1.84k
          negatable_left_shift<
685
1.84k
              static_cast<int_type>(other_T::num_fraction_bits) -
686
1.84k
              static_cast<int_type>(num_fraction_bits)>::val(significand));
687
688
      // We are some sort of Nan. We try to keep the bit-pattern of the Nan
689
      // as close as possible. If we had to shift off bits so we are 0, then we
690
      // just set the last bit.
691
1.84k
      other.set_value(typename other_T::underlying_type(
692
1.84k
          static_cast<typename other_T::uint_type>(
693
1.84k
              (negate ? other_T::sign_mask : 0) | other_T::exponent_mask |
694
1.84k
              (shifted_significand == 0 ? 0x1 : shifted_significand))));
695
1.84k
      return;
696
1.84k
    }
697
698
10.5k
    bool round_underflow_up =
699
10.5k
        isNegative() ? round_dir == round_direction::kToNegativeInfinity
700
10.5k
                     : round_dir == round_direction::kToPositiveInfinity;
701
10.5k
    using other_int_type = typename other_T::int_type;
702
    // setFromSignUnbiasedExponentAndNormalizedSignificand will
703
    // zero out any underflowing value (but retain the sign).
704
10.5k
    other.setFromSignUnbiasedExponentAndNormalizedSignificand(
705
10.5k
        negate, static_cast<other_int_type>(exponent), rounded_significand,
706
10.5k
        round_underflow_up);
707
10.5k
    return;
708
12.3k
  }
void spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >::castTo<spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > > >(spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >&, spvtools::utils::round_direction)
Line
Count
Source
641
14.3k
  void castTo(other_T& other, round_direction round_dir) {
642
14.3k
    other = other_T(static_cast<typename other_T::native_type>(0));
643
14.3k
    bool negate = isNegative();
644
14.3k
    if (getUnsignedBits() == 0) {
645
2.03k
      if (negate) {
646
730
        other.set_value(-other.value());
647
730
      }
648
2.03k
      return;
649
2.03k
    }
650
12.3k
    uint_type significand = getSignificandBits();
651
12.3k
    bool carried = false;
652
12.3k
    typename other_T::uint_type rounded_significand =
653
12.3k
        getRoundedNormalizedSignificand<other_T>(round_dir, &carried);
654
655
12.3k
    int_type exponent = getUnbiasedExponent();
656
12.3k
    if (exponent == min_exponent) {
657
      // If we are denormal, normalize the exponent, so that we can encode
658
      // easily.
659
3.55k
      exponent = static_cast<int_type>(exponent + 1);
660
21.0k
      for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0;
661
21.0k
           check_bit = static_cast<uint_type>(check_bit >> 1)) {
662
21.0k
        exponent = static_cast<int_type>(exponent - 1);
663
21.0k
        if (check_bit & significand) break;
664
21.0k
      }
665
3.55k
    }
666
667
12.3k
    bool is_nan =
668
12.3k
        (getBits() & exponent_mask) == exponent_mask && significand != 0;
669
12.3k
    bool is_inf =
670
12.3k
        !is_nan &&
671
12.3k
        ((exponent + carried) > static_cast<int_type>(other_T::exponent_bias) ||
672
10.5k
         (significand == 0 && (getBits() & exponent_mask) == exponent_mask));
673
674
    // If we are Nan or Inf we should pass that through.
675
12.3k
    if (is_inf) {
676
54
      other.set_value(typename other_T::underlying_type(
677
54
          static_cast<typename other_T::uint_type>(
678
54
              (negate ? other_T::sign_mask : 0) | other_T::exponent_mask)));
679
54
      return;
680
54
    }
681
12.3k
    if (is_nan) {
682
1.81k
      typename other_T::uint_type shifted_significand;
683
1.81k
      shifted_significand = static_cast<typename other_T::uint_type>(
684
1.81k
          negatable_left_shift<
685
1.81k
              static_cast<int_type>(other_T::num_fraction_bits) -
686
1.81k
              static_cast<int_type>(num_fraction_bits)>::val(significand));
687
688
      // We are some sort of Nan. We try to keep the bit-pattern of the Nan
689
      // as close as possible. If we had to shift off bits so we are 0, then we
690
      // just set the last bit.
691
1.81k
      other.set_value(typename other_T::underlying_type(
692
1.81k
          static_cast<typename other_T::uint_type>(
693
1.81k
              (negate ? other_T::sign_mask : 0) | other_T::exponent_mask |
694
1.81k
              (shifted_significand == 0 ? 0x1 : shifted_significand))));
695
1.81k
      return;
696
1.81k
    }
697
698
10.4k
    bool round_underflow_up =
699
10.4k
        isNegative() ? round_dir == round_direction::kToNegativeInfinity
700
10.4k
                     : round_dir == round_direction::kToPositiveInfinity;
701
10.4k
    using other_int_type = typename other_T::int_type;
702
    // setFromSignUnbiasedExponentAndNormalizedSignificand will
703
    // zero out any underflowing value (but retain the sign).
704
10.4k
    other.setFromSignUnbiasedExponentAndNormalizedSignificand(
705
10.4k
        negate, static_cast<other_int_type>(exponent), rounded_significand,
706
10.4k
        round_underflow_up);
707
10.4k
    return;
708
12.3k
  }
void spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >::castTo<spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > > >(spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >&, spvtools::utils::round_direction)
Line
Count
Source
641
264
  void castTo(other_T& other, round_direction round_dir) {
642
264
    other = other_T(static_cast<typename other_T::native_type>(0));
643
264
    bool negate = isNegative();
644
264
    if (getUnsignedBits() == 0) {
645
150
      if (negate) {
646
42
        other.set_value(-other.value());
647
42
      }
648
150
      return;
649
150
    }
650
114
    uint_type significand = getSignificandBits();
651
114
    bool carried = false;
652
114
    typename other_T::uint_type rounded_significand =
653
114
        getRoundedNormalizedSignificand<other_T>(round_dir, &carried);
654
655
114
    int_type exponent = getUnbiasedExponent();
656
114
    if (exponent == min_exponent) {
657
      // If we are denormal, normalize the exponent, so that we can encode
658
      // easily.
659
52
      exponent = static_cast<int_type>(exponent + 1);
660
214
      for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0;
661
214
           check_bit = static_cast<uint_type>(check_bit >> 1)) {
662
214
        exponent = static_cast<int_type>(exponent - 1);
663
214
        if (check_bit & significand) break;
664
214
      }
665
52
    }
666
667
114
    bool is_nan =
668
114
        (getBits() & exponent_mask) == exponent_mask && significand != 0;
669
114
    bool is_inf =
670
114
        !is_nan &&
671
114
        ((exponent + carried) > static_cast<int_type>(other_T::exponent_bias) ||
672
86
         (significand == 0 && (getBits() & exponent_mask) == exponent_mask));
673
674
    // If we are Nan or Inf we should pass that through.
675
114
    if (is_inf) {
676
18
      other.set_value(typename other_T::underlying_type(
677
18
          static_cast<typename other_T::uint_type>(
678
18
              (negate ? other_T::sign_mask : 0) | other_T::exponent_mask)));
679
18
      return;
680
18
    }
681
96
    if (is_nan) {
682
28
      typename other_T::uint_type shifted_significand;
683
28
      shifted_significand = static_cast<typename other_T::uint_type>(
684
28
          negatable_left_shift<
685
28
              static_cast<int_type>(other_T::num_fraction_bits) -
686
28
              static_cast<int_type>(num_fraction_bits)>::val(significand));
687
688
      // We are some sort of Nan. We try to keep the bit-pattern of the Nan
689
      // as close as possible. If we had to shift off bits so we are 0, then we
690
      // just set the last bit.
691
28
      other.set_value(typename other_T::underlying_type(
692
28
          static_cast<typename other_T::uint_type>(
693
28
              (negate ? other_T::sign_mask : 0) | other_T::exponent_mask |
694
28
              (shifted_significand == 0 ? 0x1 : shifted_significand))));
695
28
      return;
696
28
    }
697
698
68
    bool round_underflow_up =
699
68
        isNegative() ? round_dir == round_direction::kToNegativeInfinity
700
68
                     : round_dir == round_direction::kToPositiveInfinity;
701
68
    using other_int_type = typename other_T::int_type;
702
    // setFromSignUnbiasedExponentAndNormalizedSignificand will
703
    // zero out any underflowing value (but retain the sign).
704
68
    other.setFromSignUnbiasedExponentAndNormalizedSignificand(
705
68
        negate, static_cast<other_int_type>(exponent), rounded_significand,
706
68
        round_underflow_up);
707
68
    return;
708
96
  }
709
710
 private:
711
  T value_;
712
713
  static_assert(num_used_bits ==
714
                    Traits::num_exponent_bits + Traits::num_fraction_bits + 1,
715
                "The number of bits do not fit");
716
  static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match");
717
};
718
719
// Returns 4 bits represented by the hex character.
720
45.2M
inline uint8_t get_nibble_from_character(int character) {
721
45.2M
  const char* dec = "0123456789";
722
45.2M
  const char* lower = "abcdef";
723
45.2M
  const char* upper = "ABCDEF";
724
45.2M
  const char* p = nullptr;
725
45.2M
  if ((p = strchr(dec, character))) {
726
40.4M
    return static_cast<uint8_t>(p - dec);
727
40.4M
  } else if ((p = strchr(lower, character))) {
728
4.31M
    return static_cast<uint8_t>(p - lower + 0xa);
729
4.31M
  } else if ((p = strchr(upper, character))) {
730
541k
    return static_cast<uint8_t>(p - upper + 0xa);
731
541k
  }
732
733
0
  assert(false && "This was called with a non-hex character");
734
0
  return 0;
735
0
}
736
737
// Outputs the given HexFloat to the stream.
738
template <typename T, typename Traits>
739
484k
std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
740
484k
  using HF = HexFloat<T, Traits>;
741
484k
  using uint_type = typename HF::uint_type;
742
484k
  using int_type = typename HF::int_type;
743
744
484k
  static_assert(HF::num_used_bits != 0,
745
484k
                "num_used_bits must be non-zero for a valid float");
746
484k
  static_assert(HF::num_exponent_bits != 0,
747
484k
                "num_exponent_bits must be non-zero for a valid float");
748
484k
  static_assert(HF::num_fraction_bits != 0,
749
484k
                "num_fractin_bits must be non-zero for a valid float");
750
751
484k
  const uint_type bits = value.value().data();
752
484k
  const char* const sign = (bits & HF::sign_mask) ? "-" : "";
753
484k
  const uint_type exponent = static_cast<uint_type>(
754
484k
      (bits & HF::exponent_mask) >> HF::num_fraction_bits);
755
756
484k
  uint_type fraction = static_cast<uint_type>((bits & HF::fraction_encode_mask)
757
484k
                                              << HF::num_overflow_bits);
758
759
484k
  const bool is_zero = exponent == 0 && fraction == 0;
760
484k
  const bool is_denorm = exponent == 0 && !is_zero;
761
762
  // exponent contains the biased exponent we have to convert it back into
763
  // the normal range.
764
484k
  int_type int_exponent = static_cast<int_type>(exponent - HF::exponent_bias);
765
  // If the number is all zeros, then we actually have to NOT shift the
766
  // exponent.
767
484k
  int_exponent = is_zero ? 0 : int_exponent;
768
769
  // If we are denorm, then start shifting, and decreasing the exponent until
770
  // our leading bit is 1.
771
772
484k
  if (is_denorm) {
773
3.64M
    while ((fraction & HF::fraction_top_bit) == 0) {
774
3.23M
      fraction = static_cast<uint_type>(fraction << 1);
775
3.23M
      int_exponent = static_cast<int_type>(int_exponent - 1);
776
3.23M
    }
777
    // Since this is denormalized, we have to consume the leading 1 since it
778
    // will end up being implicit.
779
407k
    fraction = static_cast<uint_type>(fraction << 1);  // eat the leading 1
780
407k
    fraction &= HF::fraction_represent_mask;
781
407k
  }
782
783
484k
  uint_type fraction_nibbles = HF::fraction_nibbles;
784
  // We do not have to display any trailing 0s, since this represents the
785
  // fractional part.
786
1.69M
  while (fraction_nibbles > 0 && (fraction & 0xF) == 0) {
787
    // Shift off any trailing values;
788
1.20M
    fraction = static_cast<uint_type>(fraction >> 4);
789
1.20M
    --fraction_nibbles;
790
1.20M
  }
791
792
484k
  const auto saved_flags = os.flags();
793
484k
  const auto saved_fill = os.fill();
794
795
484k
  os << sign << "0x" << (is_zero ? '0' : '1');
796
484k
  if (fraction_nibbles) {
797
    // Make sure to keep the leading 0s in place, since this is the fractional
798
    // part.
799
447k
    os << "." << std::setw(static_cast<int>(fraction_nibbles))
800
447k
       << std::setfill('0') << std::hex << fraction;
801
447k
  }
802
484k
  os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent;
803
804
484k
  os.flags(saved_flags);
805
484k
  os.fill(saved_fill);
806
807
484k
  return os;
808
484k
}
std::__1::basic_ostream<char, std::__1::char_traits<char> >& spvtools::utils::operator<< <spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > > const&)
Line
Count
Source
739
130k
std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
740
130k
  using HF = HexFloat<T, Traits>;
741
130k
  using uint_type = typename HF::uint_type;
742
130k
  using int_type = typename HF::int_type;
743
744
130k
  static_assert(HF::num_used_bits != 0,
745
130k
                "num_used_bits must be non-zero for a valid float");
746
130k
  static_assert(HF::num_exponent_bits != 0,
747
130k
                "num_exponent_bits must be non-zero for a valid float");
748
130k
  static_assert(HF::num_fraction_bits != 0,
749
130k
                "num_fractin_bits must be non-zero for a valid float");
750
751
130k
  const uint_type bits = value.value().data();
752
130k
  const char* const sign = (bits & HF::sign_mask) ? "-" : "";
753
130k
  const uint_type exponent = static_cast<uint_type>(
754
130k
      (bits & HF::exponent_mask) >> HF::num_fraction_bits);
755
756
130k
  uint_type fraction = static_cast<uint_type>((bits & HF::fraction_encode_mask)
757
130k
                                              << HF::num_overflow_bits);
758
759
130k
  const bool is_zero = exponent == 0 && fraction == 0;
760
130k
  const bool is_denorm = exponent == 0 && !is_zero;
761
762
  // exponent contains the biased exponent we have to convert it back into
763
  // the normal range.
764
130k
  int_type int_exponent = static_cast<int_type>(exponent - HF::exponent_bias);
765
  // If the number is all zeros, then we actually have to NOT shift the
766
  // exponent.
767
130k
  int_exponent = is_zero ? 0 : int_exponent;
768
769
  // If we are denorm, then start shifting, and decreasing the exponent until
770
  // our leading bit is 1.
771
772
130k
  if (is_denorm) {
773
295k
    while ((fraction & HF::fraction_top_bit) == 0) {
774
226k
      fraction = static_cast<uint_type>(fraction << 1);
775
226k
      int_exponent = static_cast<int_type>(int_exponent - 1);
776
226k
    }
777
    // Since this is denormalized, we have to consume the leading 1 since it
778
    // will end up being implicit.
779
68.9k
    fraction = static_cast<uint_type>(fraction << 1);  // eat the leading 1
780
68.9k
    fraction &= HF::fraction_represent_mask;
781
68.9k
  }
782
783
130k
  uint_type fraction_nibbles = HF::fraction_nibbles;
784
  // We do not have to display any trailing 0s, since this represents the
785
  // fractional part.
786
321k
  while (fraction_nibbles > 0 && (fraction & 0xF) == 0) {
787
    // Shift off any trailing values;
788
190k
    fraction = static_cast<uint_type>(fraction >> 4);
789
190k
    --fraction_nibbles;
790
190k
  }
791
792
130k
  const auto saved_flags = os.flags();
793
130k
  const auto saved_fill = os.fill();
794
795
130k
  os << sign << "0x" << (is_zero ? '0' : '1');
796
130k
  if (fraction_nibbles) {
797
    // Make sure to keep the leading 0s in place, since this is the fractional
798
    // part.
799
99.9k
    os << "." << std::setw(static_cast<int>(fraction_nibbles))
800
99.9k
       << std::setfill('0') << std::hex << fraction;
801
99.9k
  }
802
130k
  os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent;
803
804
130k
  os.flags(saved_flags);
805
130k
  os.fill(saved_fill);
806
807
130k
  return os;
808
130k
}
std::__1::basic_ostream<char, std::__1::char_traits<char> >& spvtools::utils::operator<< <spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > > const&)
Line
Count
Source
739
335k
std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
740
335k
  using HF = HexFloat<T, Traits>;
741
335k
  using uint_type = typename HF::uint_type;
742
335k
  using int_type = typename HF::int_type;
743
744
335k
  static_assert(HF::num_used_bits != 0,
745
335k
                "num_used_bits must be non-zero for a valid float");
746
335k
  static_assert(HF::num_exponent_bits != 0,
747
335k
                "num_exponent_bits must be non-zero for a valid float");
748
335k
  static_assert(HF::num_fraction_bits != 0,
749
335k
                "num_fractin_bits must be non-zero for a valid float");
750
751
335k
  const uint_type bits = value.value().data();
752
335k
  const char* const sign = (bits & HF::sign_mask) ? "-" : "";
753
335k
  const uint_type exponent = static_cast<uint_type>(
754
335k
      (bits & HF::exponent_mask) >> HF::num_fraction_bits);
755
756
335k
  uint_type fraction = static_cast<uint_type>((bits & HF::fraction_encode_mask)
757
335k
                                              << HF::num_overflow_bits);
758
759
335k
  const bool is_zero = exponent == 0 && fraction == 0;
760
335k
  const bool is_denorm = exponent == 0 && !is_zero;
761
762
  // exponent contains the biased exponent we have to convert it back into
763
  // the normal range.
764
335k
  int_type int_exponent = static_cast<int_type>(exponent - HF::exponent_bias);
765
  // If the number is all zeros, then we actually have to NOT shift the
766
  // exponent.
767
335k
  int_exponent = is_zero ? 0 : int_exponent;
768
769
  // If we are denorm, then start shifting, and decreasing the exponent until
770
  // our leading bit is 1.
771
772
335k
  if (is_denorm) {
773
3.21M
    while ((fraction & HF::fraction_top_bit) == 0) {
774
2.89M
      fraction = static_cast<uint_type>(fraction << 1);
775
2.89M
      int_exponent = static_cast<int_type>(int_exponent - 1);
776
2.89M
    }
777
    // Since this is denormalized, we have to consume the leading 1 since it
778
    // will end up being implicit.
779
325k
    fraction = static_cast<uint_type>(fraction << 1);  // eat the leading 1
780
325k
    fraction &= HF::fraction_represent_mask;
781
325k
  }
782
783
335k
  uint_type fraction_nibbles = HF::fraction_nibbles;
784
  // We do not have to display any trailing 0s, since this represents the
785
  // fractional part.
786
1.28M
  while (fraction_nibbles > 0 && (fraction & 0xF) == 0) {
787
    // Shift off any trailing values;
788
950k
    fraction = static_cast<uint_type>(fraction >> 4);
789
950k
    --fraction_nibbles;
790
950k
  }
791
792
335k
  const auto saved_flags = os.flags();
793
335k
  const auto saved_fill = os.fill();
794
795
335k
  os << sign << "0x" << (is_zero ? '0' : '1');
796
335k
  if (fraction_nibbles) {
797
    // Make sure to keep the leading 0s in place, since this is the fractional
798
    // part.
799
329k
    os << "." << std::setw(static_cast<int>(fraction_nibbles))
800
329k
       << std::setfill('0') << std::hex << fraction;
801
329k
  }
802
335k
  os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent;
803
804
335k
  os.flags(saved_flags);
805
335k
  os.fill(saved_fill);
806
807
335k
  return os;
808
335k
}
std::__1::basic_ostream<char, std::__1::char_traits<char> >& spvtools::utils::operator<< <spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > > const&)
Line
Count
Source
739
18.5k
std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
740
18.5k
  using HF = HexFloat<T, Traits>;
741
18.5k
  using uint_type = typename HF::uint_type;
742
18.5k
  using int_type = typename HF::int_type;
743
744
18.5k
  static_assert(HF::num_used_bits != 0,
745
18.5k
                "num_used_bits must be non-zero for a valid float");
746
18.5k
  static_assert(HF::num_exponent_bits != 0,
747
18.5k
                "num_exponent_bits must be non-zero for a valid float");
748
18.5k
  static_assert(HF::num_fraction_bits != 0,
749
18.5k
                "num_fractin_bits must be non-zero for a valid float");
750
751
18.5k
  const uint_type bits = value.value().data();
752
18.5k
  const char* const sign = (bits & HF::sign_mask) ? "-" : "";
753
18.5k
  const uint_type exponent = static_cast<uint_type>(
754
18.5k
      (bits & HF::exponent_mask) >> HF::num_fraction_bits);
755
756
18.5k
  uint_type fraction = static_cast<uint_type>((bits & HF::fraction_encode_mask)
757
18.5k
                                              << HF::num_overflow_bits);
758
759
18.5k
  const bool is_zero = exponent == 0 && fraction == 0;
760
18.5k
  const bool is_denorm = exponent == 0 && !is_zero;
761
762
  // exponent contains the biased exponent we have to convert it back into
763
  // the normal range.
764
18.5k
  int_type int_exponent = static_cast<int_type>(exponent - HF::exponent_bias);
765
  // If the number is all zeros, then we actually have to NOT shift the
766
  // exponent.
767
18.5k
  int_exponent = is_zero ? 0 : int_exponent;
768
769
  // If we are denorm, then start shifting, and decreasing the exponent until
770
  // our leading bit is 1.
771
772
18.5k
  if (is_denorm) {
773
132k
    while ((fraction & HF::fraction_top_bit) == 0) {
774
119k
      fraction = static_cast<uint_type>(fraction << 1);
775
119k
      int_exponent = static_cast<int_type>(int_exponent - 1);
776
119k
    }
777
    // Since this is denormalized, we have to consume the leading 1 since it
778
    // will end up being implicit.
779
13.0k
    fraction = static_cast<uint_type>(fraction << 1);  // eat the leading 1
780
13.0k
    fraction &= HF::fraction_represent_mask;
781
13.0k
  }
782
783
18.5k
  uint_type fraction_nibbles = HF::fraction_nibbles;
784
  // We do not have to display any trailing 0s, since this represents the
785
  // fractional part.
786
86.2k
  while (fraction_nibbles > 0 && (fraction & 0xF) == 0) {
787
    // Shift off any trailing values;
788
67.7k
    fraction = static_cast<uint_type>(fraction >> 4);
789
67.7k
    --fraction_nibbles;
790
67.7k
  }
791
792
18.5k
  const auto saved_flags = os.flags();
793
18.5k
  const auto saved_fill = os.fill();
794
795
18.5k
  os << sign << "0x" << (is_zero ? '0' : '1');
796
18.5k
  if (fraction_nibbles) {
797
    // Make sure to keep the leading 0s in place, since this is the fractional
798
    // part.
799
17.9k
    os << "." << std::setw(static_cast<int>(fraction_nibbles))
800
17.9k
       << std::setfill('0') << std::hex << fraction;
801
17.9k
  }
802
18.5k
  os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent;
803
804
18.5k
  os.flags(saved_flags);
805
18.5k
  os.fill(saved_fill);
806
807
18.5k
  return os;
808
18.5k
}
809
810
// Returns true if negate_value is true and the next character on the
811
// input stream is a plus or minus sign.  In that case we also set the fail bit
812
// on the stream and set the value to the zero value for its type.
813
template <typename T, typename Traits>
814
inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value,
815
36.7k
                                        HexFloat<T, Traits>& value) {
816
36.7k
  if (negate_value) {
817
8.87k
    auto next_char = is.peek();
818
8.87k
    if (next_char == '-' || next_char == '+') {
819
      // Fail the parse.  Emulate standard behaviour by setting the value to
820
      // the zero value, and set the fail bit on the stream.
821
24
      value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type{0});
822
24
      is.setstate(std::ios_base::failbit);
823
24
      return true;
824
24
    }
825
8.87k
  }
826
36.7k
  return false;
827
36.7k
}
bool spvtools::utils::RejectParseDueToLeadingSign<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, bool, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >&)
Line
Count
Source
815
30.3k
                                        HexFloat<T, Traits>& value) {
816
30.3k
  if (negate_value) {
817
5.11k
    auto next_char = is.peek();
818
5.11k
    if (next_char == '-' || next_char == '+') {
819
      // Fail the parse.  Emulate standard behaviour by setting the value to
820
      // the zero value, and set the fail bit on the stream.
821
20
      value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type{0});
822
20
      is.setstate(std::ios_base::failbit);
823
20
      return true;
824
20
    }
825
5.11k
  }
826
30.2k
  return false;
827
30.3k
}
bool spvtools::utils::RejectParseDueToLeadingSign<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, bool, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >&)
Line
Count
Source
815
6.47k
                                        HexFloat<T, Traits>& value) {
816
6.47k
  if (negate_value) {
817
3.76k
    auto next_char = is.peek();
818
3.76k
    if (next_char == '-' || next_char == '+') {
819
      // Fail the parse.  Emulate standard behaviour by setting the value to
820
      // the zero value, and set the fail bit on the stream.
821
4
      value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type{0});
822
4
      is.setstate(std::ios_base::failbit);
823
4
      return true;
824
4
    }
825
3.76k
  }
826
6.46k
  return false;
827
6.47k
}
828
829
// Parses a floating point number from the given stream and stores it into the
830
// value parameter.
831
// If negate_value is true then the number may not have a leading minus or
832
// plus, and if it successfully parses, then the number is negated before
833
// being stored into the value parameter.
834
// If the value cannot be correctly parsed or overflows the target floating
835
// point type, then set the fail bit on the stream.
836
// TODO(dneto): Promise C++11 standard behavior in how the value is set in
837
// the error case, but only after all target platforms implement it correctly.
838
// In particular, the Microsoft C++ runtime appears to be out of spec.
839
template <typename T, typename Traits>
840
inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value,
841
36.7k
                                      HexFloat<T, Traits>& value) {
842
36.7k
  if (RejectParseDueToLeadingSign(is, negate_value, value)) {
843
24
    return is;
844
24
  }
845
36.7k
  T val;
846
36.7k
  is >> val;
847
36.7k
  if (negate_value) {
848
8.85k
    val = -val;
849
8.85k
  }
850
36.7k
  value.set_value(val);
851
  // In the failure case, map -0.0 to 0.0.
852
36.7k
  if (is.fail() && value.getUnsignedBits() == 0u) {
853
10.4k
    value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type{0});
854
10.4k
  }
855
36.7k
  if (val.isInfinity()) {
856
    // Fail the parse.  Emulate standard behaviour by setting the value to
857
    // the closest normal value, and set the fail bit on the stream.
858
30
    value.set_value((value.isNegative() | negate_value) ? T::lowest()
859
30
                                                        : T::max());
860
30
    is.setstate(std::ios_base::failbit);
861
30
  }
862
36.7k
  return is;
863
36.7k
}
std::__1::basic_istream<char, std::__1::char_traits<char> >& spvtools::utils::ParseNormalFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, bool, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >&)
Line
Count
Source
841
30.3k
                                      HexFloat<T, Traits>& value) {
842
30.3k
  if (RejectParseDueToLeadingSign(is, negate_value, value)) {
843
20
    return is;
844
20
  }
845
30.2k
  T val;
846
30.2k
  is >> val;
847
30.2k
  if (negate_value) {
848
5.09k
    val = -val;
849
5.09k
  }
850
30.2k
  value.set_value(val);
851
  // In the failure case, map -0.0 to 0.0.
852
30.2k
  if (is.fail() && value.getUnsignedBits() == 0u) {
853
10.4k
    value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type{0});
854
10.4k
  }
855
30.2k
  if (val.isInfinity()) {
856
    // Fail the parse.  Emulate standard behaviour by setting the value to
857
    // the closest normal value, and set the fail bit on the stream.
858
18
    value.set_value((value.isNegative() | negate_value) ? T::lowest()
859
18
                                                        : T::max());
860
18
    is.setstate(std::ios_base::failbit);
861
18
  }
862
30.2k
  return is;
863
30.3k
}
std::__1::basic_istream<char, std::__1::char_traits<char> >& spvtools::utils::ParseNormalFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, bool, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >&)
Line
Count
Source
841
6.47k
                                      HexFloat<T, Traits>& value) {
842
6.47k
  if (RejectParseDueToLeadingSign(is, negate_value, value)) {
843
4
    return is;
844
4
  }
845
6.46k
  T val;
846
6.46k
  is >> val;
847
6.46k
  if (negate_value) {
848
3.75k
    val = -val;
849
3.75k
  }
850
6.46k
  value.set_value(val);
851
  // In the failure case, map -0.0 to 0.0.
852
6.46k
  if (is.fail() && value.getUnsignedBits() == 0u) {
853
64
    value = HexFloat<T, Traits>(typename HexFloat<T, Traits>::uint_type{0});
854
64
  }
855
6.46k
  if (val.isInfinity()) {
856
    // Fail the parse.  Emulate standard behaviour by setting the value to
857
    // the closest normal value, and set the fail bit on the stream.
858
12
    value.set_value((value.isNegative() | negate_value) ? T::lowest()
859
12
                                                        : T::max());
860
12
    is.setstate(std::ios_base::failbit);
861
12
  }
862
6.46k
  return is;
863
6.47k
}
864
865
// Specialization of ParseNormalFloat for FloatProxy<Float16> values.
866
// This will parse the float as it were a 32-bit floating point number,
867
// and then round it down to fit into a Float16 value.
868
// The number is rounded towards zero.
869
// If negate_value is true then the number may not have a leading minus or
870
// plus, and if it successfully parses, then the number is negated before
871
// being stored into the value parameter.
872
// If the value cannot be correctly parsed or overflows the target floating
873
// point type, then set the fail bit on the stream.
874
// TODO(dneto): Promise C++11 standard behavior in how the value is set in
875
// the error case, but only after all target platforms implement it correctly.
876
// In particular, the Microsoft C++ runtime appears to be out of spec.
877
template <>
878
inline std::istream&
879
ParseNormalFloat<FloatProxy<Float16>, HexFloatTraits<FloatProxy<Float16>>>(
880
    std::istream& is, bool negate_value,
881
14.1k
    HexFloat<FloatProxy<Float16>, HexFloatTraits<FloatProxy<Float16>>>& value) {
882
  // First parse as a 32-bit float.
883
14.1k
  HexFloat<FloatProxy<float>> float_val(0.0f);
884
14.1k
  ParseNormalFloat(is, negate_value, float_val);
885
886
  // Then convert to 16-bit float, saturating at infinities, and
887
  // rounding toward zero.
888
14.1k
  float_val.castTo(value, round_direction::kToZero);
889
890
  // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the
891
  // fail bit and set the lowest or highest value.
892
14.1k
  if (Float16::isInfinity(value.value().getAsFloat())) {
893
36
    value.set_value(value.isNegative() ? Float16::lowest() : Float16::max());
894
36
    is.setstate(std::ios_base::failbit);
895
36
  }
896
14.1k
  return is;
897
14.1k
}
898
899
namespace detail {
900
901
// Returns a new value formed from 'value' by setting 'bit' that is the
902
// 'n'th most significant bit (where 0 is the most significant bit).
903
// If 'bit' is zero or 'n' is more than the number of bits in the integer
904
// type, then return the original value.
905
template <typename UINT_TYPE>
906
UINT_TYPE set_nth_most_significant_bit(UINT_TYPE value, UINT_TYPE bit,
907
100M
                                       UINT_TYPE n) {
908
100M
  constexpr UINT_TYPE max_position = std::numeric_limits<UINT_TYPE>::digits - 1;
909
100M
  if ((bit != 0) && (n <= max_position)) {
910
166k
    return static_cast<UINT_TYPE>(value | (bit << (max_position - n)));
911
166k
  }
912
100M
  return value;
913
100M
}
unsigned short spvtools::utils::detail::set_nth_most_significant_bit<unsigned short>(unsigned short, unsigned short, unsigned short)
Line
Count
Source
907
3.73M
                                       UINT_TYPE n) {
908
3.73M
  constexpr UINT_TYPE max_position = std::numeric_limits<UINT_TYPE>::digits - 1;
909
3.73M
  if ((bit != 0) && (n <= max_position)) {
910
45.7k
    return static_cast<UINT_TYPE>(value | (bit << (max_position - n)));
911
45.7k
  }
912
3.68M
  return value;
913
3.73M
}
unsigned int spvtools::utils::detail::set_nth_most_significant_bit<unsigned int>(unsigned int, unsigned int, unsigned int)
Line
Count
Source
907
40.8M
                                       UINT_TYPE n) {
908
40.8M
  constexpr UINT_TYPE max_position = std::numeric_limits<UINT_TYPE>::digits - 1;
909
40.8M
  if ((bit != 0) && (n <= max_position)) {
910
26.4k
    return static_cast<UINT_TYPE>(value | (bit << (max_position - n)));
911
26.4k
  }
912
40.8M
  return value;
913
40.8M
}
unsigned long spvtools::utils::detail::set_nth_most_significant_bit<unsigned long>(unsigned long, unsigned long, unsigned long)
Line
Count
Source
907
55.6M
                                       UINT_TYPE n) {
908
55.6M
  constexpr UINT_TYPE max_position = std::numeric_limits<UINT_TYPE>::digits - 1;
909
55.6M
  if ((bit != 0) && (n <= max_position)) {
910
94.2k
    return static_cast<UINT_TYPE>(value | (bit << (max_position - n)));
911
94.2k
  }
912
55.5M
  return value;
913
55.6M
}
914
915
// Attempts to increment the argument.
916
// If it does not overflow, then increments the argument and returns true.
917
// If it would overflow, returns false.
918
template <typename INT_TYPE>
919
176M
bool saturated_inc(INT_TYPE& value) {
920
176M
  if (value == std::numeric_limits<INT_TYPE>::max()) {
921
716
    return false;
922
716
  }
923
176M
  value++;
924
176M
  return true;
925
176M
}
bool spvtools::utils::detail::saturated_inc<unsigned short>(unsigned short&)
Line
Count
Source
919
3.73M
bool saturated_inc(INT_TYPE& value) {
920
3.73M
  if (value == std::numeric_limits<INT_TYPE>::max()) {
921
714
    return false;
922
714
  }
923
3.73M
  value++;
924
3.73M
  return true;
925
3.73M
}
bool spvtools::utils::detail::saturated_inc<short>(short&)
Line
Count
Source
919
1.01M
bool saturated_inc(INT_TYPE& value) {
920
1.01M
  if (value == std::numeric_limits<INT_TYPE>::max()) {
921
2
    return false;
922
2
  }
923
1.01M
  value++;
924
1.01M
  return true;
925
1.01M
}
bool spvtools::utils::detail::saturated_inc<unsigned int>(unsigned int&)
Line
Count
Source
919
40.8M
bool saturated_inc(INT_TYPE& value) {
920
40.8M
  if (value == std::numeric_limits<INT_TYPE>::max()) {
921
0
    return false;
922
0
  }
923
40.8M
  value++;
924
40.8M
  return true;
925
40.8M
}
bool spvtools::utils::detail::saturated_inc<int>(int&)
Line
Count
Source
919
26.9M
bool saturated_inc(INT_TYPE& value) {
920
26.9M
  if (value == std::numeric_limits<INT_TYPE>::max()) {
921
0
    return false;
922
0
  }
923
26.9M
  value++;
924
26.9M
  return true;
925
26.9M
}
bool spvtools::utils::detail::saturated_inc<unsigned long>(unsigned long&)
Line
Count
Source
919
55.6M
bool saturated_inc(INT_TYPE& value) {
920
55.6M
  if (value == std::numeric_limits<INT_TYPE>::max()) {
921
0
    return false;
922
0
  }
923
55.6M
  value++;
924
55.6M
  return true;
925
55.6M
}
bool spvtools::utils::detail::saturated_inc<long>(long&)
Line
Count
Source
919
47.9M
bool saturated_inc(INT_TYPE& value) {
920
47.9M
  if (value == std::numeric_limits<INT_TYPE>::max()) {
921
0
    return false;
922
0
  }
923
47.9M
  value++;
924
47.9M
  return true;
925
47.9M
}
926
927
// Attempts to decrement the argument.
928
// If it does not underflow, then decrements the argument and returns true.
929
// If it would overflow, returns false.
930
template <typename INT_TYPE>
931
80.8M
bool saturated_dec(INT_TYPE& value) {
932
80.8M
  if (value == std::numeric_limits<INT_TYPE>::min()) {
933
6
    return false;
934
6
  }
935
80.8M
  value--;
936
80.8M
  return true;
937
80.8M
}
bool spvtools::utils::detail::saturated_dec<short>(short&)
Line
Count
Source
931
1.30M
bool saturated_dec(INT_TYPE& value) {
932
1.30M
  if (value == std::numeric_limits<INT_TYPE>::min()) {
933
6
    return false;
934
6
  }
935
1.30M
  value--;
936
1.30M
  return true;
937
1.30M
}
bool spvtools::utils::detail::saturated_dec<int>(int&)
Line
Count
Source
931
20.7M
bool saturated_dec(INT_TYPE& value) {
932
20.7M
  if (value == std::numeric_limits<INT_TYPE>::min()) {
933
0
    return false;
934
0
  }
935
20.7M
  value--;
936
20.7M
  return true;
937
20.7M
}
bool spvtools::utils::detail::saturated_dec<long>(long&)
Line
Count
Source
931
58.7M
bool saturated_dec(INT_TYPE& value) {
932
58.7M
  if (value == std::numeric_limits<INT_TYPE>::min()) {
933
0
    return false;
934
0
  }
935
58.7M
  value--;
936
58.7M
  return true;
937
58.7M
}
938
}  // namespace detail
939
940
// Reads a HexFloat from the given stream.
941
// If the float is not encoded as a hex-float then it will be parsed
942
// as a regular float.
943
// This may fail if your stream does not support at least one unget.
944
// Nan values can be encoded with "0x1.<not zero>p+exponent_bias".
945
// This would normally overflow a float and round to
946
// infinity but this special pattern is the exact representation for a NaN,
947
// and therefore is actually encoded as the correct NaN. To encode inf,
948
// either 0x0p+exponent_bias can be specified or any exponent greater than
949
// exponent_bias.
950
// Examples using IEEE 32-bit float encoding.
951
//    0x1.0p+128 (+inf)
952
//    -0x1.0p-128 (-inf)
953
//
954
//    0x1.1p+128 (+Nan)
955
//    -0x1.1p+128 (-Nan)
956
//
957
//    0x1p+129 (+inf)
958
//    -0x1p+129 (-inf)
959
template <typename T, typename Traits>
960
76.5k
std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
961
76.5k
  using HF = HexFloat<T, Traits>;
962
76.5k
  using uint_type = typename HF::uint_type;
963
76.5k
  using int_type = typename HF::int_type;
964
965
76.5k
  value.set_value(static_cast<typename HF::native_type>(0.f));
966
967
76.5k
  if (is.flags() & std::ios::skipws) {
968
    // If the user wants to skip whitespace , then we should obey that.
969
82.7k
    while (std::isspace(is.peek())) {
970
6.24k
      is.get();
971
6.24k
    }
972
76.5k
  }
973
974
76.5k
  auto next_char = is.peek();
975
76.5k
  bool negate_value = false;
976
977
76.5k
  if (next_char != '-' && next_char != '0') {
978
23.3k
    return ParseNormalFloat(is, negate_value, value);
979
23.3k
  }
980
981
53.2k
  if (next_char == '-') {
982
8.90k
    negate_value = true;
983
8.90k
    is.get();
984
8.90k
    next_char = is.peek();
985
8.90k
  }
986
987
53.2k
  if (next_char == '0') {
988
47.3k
    is.get();  // We may have to unget this.
989
47.3k
    auto maybe_hex_start = is.peek();
990
47.3k
    if (maybe_hex_start != 'x' && maybe_hex_start != 'X') {
991
7.55k
      is.unget();
992
7.55k
      return ParseNormalFloat(is, negate_value, value);
993
39.7k
    } else {
994
39.7k
      is.get();  // Throw away the 'x';
995
39.7k
    }
996
47.3k
  } else {
997
5.91k
    return ParseNormalFloat(is, negate_value, value);
998
5.91k
  }
999
1000
  // This "looks" like a hex-float so treat it as one.
1001
39.7k
  bool seen_p = false;
1002
39.7k
  bool seen_dot = false;
1003
1004
  // The mantissa bits, without the most significant 1 bit, and with the
1005
  // the most recently read bits in the least significant positions.
1006
39.7k
  uint_type fraction = 0;
1007
  // The number of mantissa bits that have been read, including the leading 1
1008
  // bit that is not written into 'fraction'.
1009
39.7k
  uint_type fraction_index = 0;
1010
1011
  // TODO(dneto): handle overflow and underflow
1012
39.7k
  int_type exponent = HF::exponent_bias;
1013
1014
  // Strip off leading zeros so we don't have to special-case them later.
1015
60.8k
  while ((next_char = is.peek()) == '0') {
1016
21.1k
    is.get();
1017
21.1k
  }
1018
1019
  // Does the mantissa, as written, have non-zero digits to the left of
1020
  // the decimal point.  Assume no until proven otherwise.
1021
39.7k
  bool has_integer_part = false;
1022
39.7k
  bool bits_written = false;  // Stays false until we write a bit.
1023
1024
  // Scan the mantissa hex digits until we see a '.' or the 'p' that
1025
  // starts the exponent.
1026
19.0M
  while (!seen_p && !seen_dot) {
1027
    // Handle characters that are left of the fractional part.
1028
19.0M
    if (next_char == '.') {
1029
25.2k
      seen_dot = true;
1030
18.9M
    } else if (next_char == 'p') {
1031
14.2k
      seen_p = true;
1032
18.9M
    } else if (::isxdigit(next_char)) {
1033
      // We have stripped all leading zeroes and we have not yet seen a ".".
1034
18.9M
      has_integer_part = true;
1035
18.9M
      int number = get_nibble_from_character(next_char);
1036
94.9M
      for (int i = 0; i < 4; ++i, number <<= 1) {
1037
75.9M
        uint_type write_bit = (number & 0x8) ? 0x1 : 0x0;
1038
75.9M
        if (bits_written) {
1039
          // If we are here the bits represented belong in the fractional
1040
          // part of the float, and we have to adjust the exponent accordingly.
1041
75.8M
          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
1042
75.8M
                                                          fraction_index);
1043
          // Increment the fraction index. If the input has bizarrely many
1044
          // significant digits, then silently drop them.
1045
75.8M
          detail::saturated_inc(fraction_index);
1046
75.8M
          if (!detail::saturated_inc(exponent)) {
1047
            // Overflow failure
1048
2
            is.setstate(std::ios::failbit);
1049
2
            return is;
1050
2
          }
1051
75.8M
        }
1052
        // Since this updated after setting fraction bits, this effectively
1053
        // drops the leading 1 bit.
1054
75.9M
        bits_written |= write_bit != 0;
1055
75.9M
      }
1056
18.9M
    } else {
1057
      // We have not found our exponent yet, so we have to fail.
1058
312
      is.setstate(std::ios::failbit);
1059
312
      return is;
1060
312
    }
1061
19.0M
    is.get();
1062
19.0M
    next_char = is.peek();
1063
19.0M
  }
1064
1065
  // Finished reading the part preceding any '.' or 'p'.
1066
1067
39.4k
  bits_written = false;
1068
26.3M
  while (seen_dot && !seen_p) {
1069
    // Handle only fractional parts now.
1070
26.3M
    if (next_char == 'p') {
1071
24.6k
      seen_p = true;
1072
26.2M
    } else if (::isxdigit(next_char)) {
1073
26.2M
      int number = get_nibble_from_character(next_char);
1074
131M
      for (int i = 0; i < 4; ++i, number <<= 1) {
1075
105M
        uint_type write_bit = (number & 0x8) ? 0x01 : 0x00;
1076
105M
        bits_written |= write_bit != 0;
1077
105M
        if ((!has_integer_part) && !bits_written) {
1078
          // Handle modifying the exponent here this way we can handle
1079
          // an arbitrary number of hex values without overflowing our
1080
          // integer.
1081
80.8M
          if (!detail::saturated_dec(exponent)) {
1082
            // Overflow failure
1083
6
            is.setstate(std::ios::failbit);
1084
6
            return is;
1085
6
          }
1086
80.8M
        } else {
1087
24.3M
          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
1088
24.3M
                                                          fraction_index);
1089
          // Increment the fraction index. If the input has bizarrely many
1090
          // significant digits, then silently drop them.
1091
24.3M
          detail::saturated_inc(fraction_index);
1092
24.3M
        }
1093
105M
      }
1094
26.2M
    } else {
1095
      // We still have not found our 'p' exponent yet, so this is not a valid
1096
      // hex-float.
1097
572
      is.setstate(std::ios::failbit);
1098
572
      return is;
1099
572
    }
1100
26.3M
    is.get();
1101
26.3M
    next_char = is.peek();
1102
26.3M
  }
1103
1104
  // Finished reading the part preceding 'p'.
1105
  // In hex floats syntax, the binary exponent is required.
1106
1107
38.8k
  bool seen_exponent_sign = false;
1108
38.8k
  int8_t exponent_sign = 1;
1109
38.8k
  bool seen_written_exponent_digits = false;
1110
  // The magnitude of the exponent, as written, or the sentinel value to signal
1111
  // overflow.
1112
38.8k
  int_type written_exponent = 0;
1113
  // A sentinel value signalling overflow of the magnitude of the written
1114
  // exponent.  We'll assume that -written_exponent_overflow is valid for the
1115
  // type. Later we may add 1 or subtract 1 from the adjusted exponent, so leave
1116
  // room for an extra 1.
1117
38.8k
  const int_type written_exponent_overflow =
1118
38.8k
      std::numeric_limits<int_type>::max() - 1;
1119
495k
  while (true) {
1120
495k
    if (!seen_written_exponent_digits &&
1121
495k
        (next_char == '-' || next_char == '+')) {
1122
16.5k
      if (seen_exponent_sign) {
1123
12
        is.setstate(std::ios::failbit);
1124
12
        return is;
1125
12
      }
1126
16.5k
      seen_exponent_sign = true;
1127
16.5k
      exponent_sign = (next_char == '-') ? -1 : 1;
1128
479k
    } else if (::isdigit(next_char)) {
1129
440k
      seen_written_exponent_digits = true;
1130
      // Hex-floats express their exponent as decimal.
1131
440k
      int_type digit =
1132
440k
          static_cast<int_type>(static_cast<int_type>(next_char) - '0');
1133
440k
      if (written_exponent >= (written_exponent_overflow - digit) / 10) {
1134
        // The exponent is very big. Saturate rather than overflow the exponent.
1135
        // signed integer, which would be undefined behaviour.
1136
65.8k
        written_exponent = written_exponent_overflow;
1137
374k
      } else {
1138
374k
        written_exponent = static_cast<int_type>(
1139
374k
            static_cast<int_type>(written_exponent * 10) + digit);
1140
374k
      }
1141
440k
    } else {
1142
38.8k
      break;
1143
38.8k
    }
1144
456k
    is.get();
1145
456k
    next_char = is.peek();
1146
456k
  }
1147
38.8k
  if (!seen_written_exponent_digits) {
1148
    // Binary exponent had no digits.
1149
112
    is.setstate(std::ios::failbit);
1150
112
    return is;
1151
112
  }
1152
1153
38.7k
  written_exponent = static_cast<int_type>(written_exponent * exponent_sign);
1154
  // Now fold in the exponent bias into the written exponent, updating exponent.
1155
  // But avoid undefined behaviour that would result from overflowing int_type.
1156
38.7k
  if (written_exponent >= 0 && exponent >= 0) {
1157
    // Saturate up to written_exponent_overflow.
1158
23.1k
    if (written_exponent_overflow - exponent > written_exponent) {
1159
17.6k
      exponent = static_cast<int_type>(written_exponent + exponent);
1160
17.6k
    } else {
1161
5.41k
      exponent = written_exponent_overflow;
1162
5.41k
    }
1163
23.1k
  } else if (written_exponent < 0 && exponent < 0) {
1164
    // Saturate down to -written_exponent_overflow.
1165
4.20k
    if (written_exponent_overflow + exponent > -written_exponent) {
1166
2.75k
      exponent = static_cast<int_type>(written_exponent + exponent);
1167
2.75k
    } else {
1168
1.44k
      exponent = static_cast<int_type>(-written_exponent_overflow);
1169
1.44k
    }
1170
11.4k
  } else {
1171
    // They're of opposing sign, so it's safe to add.
1172
11.4k
    exponent = static_cast<int_type>(written_exponent + exponent);
1173
11.4k
  }
1174
1175
38.7k
  bool is_zero = (!has_integer_part) && (fraction == 0);
1176
38.7k
  if ((!has_integer_part) && !is_zero) {
1177
13.7k
    fraction = static_cast<uint_type>(fraction << 1);
1178
13.7k
    exponent = static_cast<int_type>(exponent - 1);
1179
25.0k
  } else if (is_zero) {
1180
13.1k
    exponent = 0;
1181
13.1k
  }
1182
1183
38.7k
  if (exponent <= 0 && !is_zero) {
1184
8.67k
    fraction = static_cast<uint_type>(fraction >> 1);
1185
8.67k
    fraction |= static_cast<uint_type>(1) << HF::top_bit_left_shift;
1186
8.67k
  }
1187
1188
38.7k
  fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask;
1189
1190
38.7k
  const int_type max_exponent =
1191
38.7k
      SetBits<uint_type, 0, HF::num_exponent_bits>::get;
1192
1193
  // Handle denorm numbers
1194
219k
  while (exponent < 0 && !is_zero) {
1195
180k
    fraction = static_cast<uint_type>(fraction >> 1);
1196
180k
    exponent = static_cast<int_type>(exponent + 1);
1197
1198
180k
    fraction &= HF::fraction_encode_mask;
1199
180k
    if (fraction == 0) {
1200
      // We have underflowed our fraction. We should clamp to zero.
1201
6.71k
      is_zero = true;
1202
6.71k
      exponent = 0;
1203
6.71k
    }
1204
180k
  }
1205
1206
  // We have overflowed so we should be inf/-inf.
1207
38.7k
  if (exponent > max_exponent) {
1208
6.71k
    exponent = max_exponent;
1209
6.71k
    fraction = 0;
1210
6.71k
  }
1211
1212
38.7k
  uint_type output_bits = static_cast<uint_type>(
1213
38.7k
      static_cast<uint_type>(negate_value ? 1 : 0) << HF::top_bit_left_shift);
1214
38.7k
  output_bits |= fraction;
1215
1216
38.7k
  uint_type shifted_exponent = static_cast<uint_type>(
1217
38.7k
      static_cast<uint_type>(exponent << HF::exponent_left_shift) &
1218
38.7k
      HF::exponent_mask);
1219
38.7k
  output_bits |= shifted_exponent;
1220
1221
38.7k
  T output_float(output_bits);
1222
38.7k
  value.set_value(output_float);
1223
1224
38.7k
  return is;
1225
38.8k
}
std::__1::basic_istream<char, std::__1::char_traits<char> >& spvtools::utils::operator>><spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<spvtools::utils::Float16>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<spvtools::utils::Float16> > >&)
Line
Count
Source
960
27.6k
std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
961
27.6k
  using HF = HexFloat<T, Traits>;
962
27.6k
  using uint_type = typename HF::uint_type;
963
27.6k
  using int_type = typename HF::int_type;
964
965
27.6k
  value.set_value(static_cast<typename HF::native_type>(0.f));
966
967
27.6k
  if (is.flags() & std::ios::skipws) {
968
    // If the user wants to skip whitespace , then we should obey that.
969
29.9k
    while (std::isspace(is.peek())) {
970
2.29k
      is.get();
971
2.29k
    }
972
27.6k
  }
973
974
27.6k
  auto next_char = is.peek();
975
27.6k
  bool negate_value = false;
976
977
27.6k
  if (next_char != '-' && next_char != '0') {
978
9.47k
    return ParseNormalFloat(is, negate_value, value);
979
9.47k
  }
980
981
18.1k
  if (next_char == '-') {
982
3.45k
    negate_value = true;
983
3.45k
    is.get();
984
3.45k
    next_char = is.peek();
985
3.45k
  }
986
987
18.1k
  if (next_char == '0') {
988
15.5k
    is.get();  // We may have to unget this.
989
15.5k
    auto maybe_hex_start = is.peek();
990
15.5k
    if (maybe_hex_start != 'x' && maybe_hex_start != 'X') {
991
2.00k
      is.unget();
992
2.00k
      return ParseNormalFloat(is, negate_value, value);
993
13.5k
    } else {
994
13.5k
      is.get();  // Throw away the 'x';
995
13.5k
    }
996
15.5k
  } else {
997
2.64k
    return ParseNormalFloat(is, negate_value, value);
998
2.64k
  }
999
1000
  // This "looks" like a hex-float so treat it as one.
1001
13.5k
  bool seen_p = false;
1002
13.5k
  bool seen_dot = false;
1003
1004
  // The mantissa bits, without the most significant 1 bit, and with the
1005
  // the most recently read bits in the least significant positions.
1006
13.5k
  uint_type fraction = 0;
1007
  // The number of mantissa bits that have been read, including the leading 1
1008
  // bit that is not written into 'fraction'.
1009
13.5k
  uint_type fraction_index = 0;
1010
1011
  // TODO(dneto): handle overflow and underflow
1012
13.5k
  int_type exponent = HF::exponent_bias;
1013
1014
  // Strip off leading zeros so we don't have to special-case them later.
1015
26.0k
  while ((next_char = is.peek()) == '0') {
1016
12.5k
    is.get();
1017
12.5k
  }
1018
1019
  // Does the mantissa, as written, have non-zero digits to the left of
1020
  // the decimal point.  Assume no until proven otherwise.
1021
13.5k
  bool has_integer_part = false;
1022
13.5k
  bool bits_written = false;  // Stays false until we write a bit.
1023
1024
  // Scan the mantissa hex digits until we see a '.' or the 'p' that
1025
  // starts the exponent.
1026
283k
  while (!seen_p && !seen_dot) {
1027
    // Handle characters that are left of the fractional part.
1028
270k
    if (next_char == '.') {
1029
5.92k
      seen_dot = true;
1030
264k
    } else if (next_char == 'p') {
1031
7.48k
      seen_p = true;
1032
257k
    } else if (::isxdigit(next_char)) {
1033
      // We have stripped all leading zeroes and we have not yet seen a ".".
1034
257k
      has_integer_part = true;
1035
257k
      int number = get_nibble_from_character(next_char);
1036
1.28M
      for (int i = 0; i < 4; ++i, number <<= 1) {
1037
1.02M
        uint_type write_bit = (number & 0x8) ? 0x1 : 0x0;
1038
1.02M
        if (bits_written) {
1039
          // If we are here the bits represented belong in the fractional
1040
          // part of the float, and we have to adjust the exponent accordingly.
1041
1.01M
          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
1042
1.01M
                                                          fraction_index);
1043
          // Increment the fraction index. If the input has bizarrely many
1044
          // significant digits, then silently drop them.
1045
1.01M
          detail::saturated_inc(fraction_index);
1046
1.01M
          if (!detail::saturated_inc(exponent)) {
1047
            // Overflow failure
1048
2
            is.setstate(std::ios::failbit);
1049
2
            return is;
1050
2
          }
1051
1.01M
        }
1052
        // Since this updated after setting fraction bits, this effectively
1053
        // drops the leading 1 bit.
1054
1.02M
        bits_written |= write_bit != 0;
1055
1.02M
      }
1056
257k
    } else {
1057
      // We have not found our exponent yet, so we have to fail.
1058
98
      is.setstate(std::ios::failbit);
1059
98
      return is;
1060
98
    }
1061
270k
    is.get();
1062
270k
    next_char = is.peek();
1063
270k
  }
1064
1065
  // Finished reading the part preceding any '.' or 'p'.
1066
1067
13.4k
  bits_written = false;
1068
1.02M
  while (seen_dot && !seen_p) {
1069
    // Handle only fractional parts now.
1070
1.01M
    if (next_char == 'p') {
1071
5.78k
      seen_p = true;
1072
1.00M
    } else if (::isxdigit(next_char)) {
1073
1.00M
      int number = get_nibble_from_character(next_char);
1074
5.02M
      for (int i = 0; i < 4; ++i, number <<= 1) {
1075
4.01M
        uint_type write_bit = (number & 0x8) ? 0x01 : 0x00;
1076
4.01M
        bits_written |= write_bit != 0;
1077
4.01M
        if ((!has_integer_part) && !bits_written) {
1078
          // Handle modifying the exponent here this way we can handle
1079
          // an arbitrary number of hex values without overflowing our
1080
          // integer.
1081
1.30M
          if (!detail::saturated_dec(exponent)) {
1082
            // Overflow failure
1083
6
            is.setstate(std::ios::failbit);
1084
6
            return is;
1085
6
          }
1086
2.71M
        } else {
1087
2.71M
          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
1088
2.71M
                                                          fraction_index);
1089
          // Increment the fraction index. If the input has bizarrely many
1090
          // significant digits, then silently drop them.
1091
2.71M
          detail::saturated_inc(fraction_index);
1092
2.71M
        }
1093
4.01M
      }
1094
1.00M
    } else {
1095
      // We still have not found our 'p' exponent yet, so this is not a valid
1096
      // hex-float.
1097
134
      is.setstate(std::ios::failbit);
1098
134
      return is;
1099
134
    }
1100
1.01M
    is.get();
1101
1.01M
    next_char = is.peek();
1102
1.01M
  }
1103
1104
  // Finished reading the part preceding 'p'.
1105
  // In hex floats syntax, the binary exponent is required.
1106
1107
13.2k
  bool seen_exponent_sign = false;
1108
13.2k
  int8_t exponent_sign = 1;
1109
13.2k
  bool seen_written_exponent_digits = false;
1110
  // The magnitude of the exponent, as written, or the sentinel value to signal
1111
  // overflow.
1112
13.2k
  int_type written_exponent = 0;
1113
  // A sentinel value signalling overflow of the magnitude of the written
1114
  // exponent.  We'll assume that -written_exponent_overflow is valid for the
1115
  // type. Later we may add 1 or subtract 1 from the adjusted exponent, so leave
1116
  // room for an extra 1.
1117
13.2k
  const int_type written_exponent_overflow =
1118
13.2k
      std::numeric_limits<int_type>::max() - 1;
1119
88.3k
  while (true) {
1120
88.3k
    if (!seen_written_exponent_digits &&
1121
88.3k
        (next_char == '-' || next_char == '+')) {
1122
6.89k
      if (seen_exponent_sign) {
1123
4
        is.setstate(std::ios::failbit);
1124
4
        return is;
1125
4
      }
1126
6.89k
      seen_exponent_sign = true;
1127
6.89k
      exponent_sign = (next_char == '-') ? -1 : 1;
1128
81.4k
    } else if (::isdigit(next_char)) {
1129
68.1k
      seen_written_exponent_digits = true;
1130
      // Hex-floats express their exponent as decimal.
1131
68.1k
      int_type digit =
1132
68.1k
          static_cast<int_type>(static_cast<int_type>(next_char) - '0');
1133
68.1k
      if (written_exponent >= (written_exponent_overflow - digit) / 10) {
1134
        // The exponent is very big. Saturate rather than overflow the exponent.
1135
        // signed integer, which would be undefined behaviour.
1136
32.2k
        written_exponent = written_exponent_overflow;
1137
35.9k
      } else {
1138
35.9k
        written_exponent = static_cast<int_type>(
1139
35.9k
            static_cast<int_type>(written_exponent * 10) + digit);
1140
35.9k
      }
1141
68.1k
    } else {
1142
13.2k
      break;
1143
13.2k
    }
1144
75.0k
    is.get();
1145
75.0k
    next_char = is.peek();
1146
75.0k
  }
1147
13.2k
  if (!seen_written_exponent_digits) {
1148
    // Binary exponent had no digits.
1149
36
    is.setstate(std::ios::failbit);
1150
36
    return is;
1151
36
  }
1152
1153
13.2k
  written_exponent = static_cast<int_type>(written_exponent * exponent_sign);
1154
  // Now fold in the exponent bias into the written exponent, updating exponent.
1155
  // But avoid undefined behaviour that would result from overflowing int_type.
1156
13.2k
  if (written_exponent >= 0 && exponent >= 0) {
1157
    // Saturate up to written_exponent_overflow.
1158
6.24k
    if (written_exponent_overflow - exponent > written_exponent) {
1159
4.19k
      exponent = static_cast<int_type>(written_exponent + exponent);
1160
4.19k
    } else {
1161
2.05k
      exponent = written_exponent_overflow;
1162
2.05k
    }
1163
6.97k
  } else if (written_exponent < 0 && exponent < 0) {
1164
    // Saturate down to -written_exponent_overflow.
1165
1.44k
    if (written_exponent_overflow + exponent > -written_exponent) {
1166
918
      exponent = static_cast<int_type>(written_exponent + exponent);
1167
918
    } else {
1168
530
      exponent = static_cast<int_type>(-written_exponent_overflow);
1169
530
    }
1170
5.53k
  } else {
1171
    // They're of opposing sign, so it's safe to add.
1172
5.53k
    exponent = static_cast<int_type>(written_exponent + exponent);
1173
5.53k
  }
1174
1175
13.2k
  bool is_zero = (!has_integer_part) && (fraction == 0);
1176
13.2k
  if ((!has_integer_part) && !is_zero) {
1177
4.03k
    fraction = static_cast<uint_type>(fraction << 1);
1178
4.03k
    exponent = static_cast<int_type>(exponent - 1);
1179
9.19k
  } else if (is_zero) {
1180
3.27k
    exponent = 0;
1181
3.27k
  }
1182
1183
13.2k
  if (exponent <= 0 && !is_zero) {
1184
4.18k
    fraction = static_cast<uint_type>(fraction >> 1);
1185
4.18k
    fraction |= static_cast<uint_type>(1) << HF::top_bit_left_shift;
1186
4.18k
  }
1187
1188
13.2k
  fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask;
1189
1190
13.2k
  const int_type max_exponent =
1191
13.2k
      SetBits<uint_type, 0, HF::num_exponent_bits>::get;
1192
1193
  // Handle denorm numbers
1194
47.6k
  while (exponent < 0 && !is_zero) {
1195
34.3k
    fraction = static_cast<uint_type>(fraction >> 1);
1196
34.3k
    exponent = static_cast<int_type>(exponent + 1);
1197
1198
34.3k
    fraction &= HF::fraction_encode_mask;
1199
34.3k
    if (fraction == 0) {
1200
      // We have underflowed our fraction. We should clamp to zero.
1201
3.28k
      is_zero = true;
1202
3.28k
      exponent = 0;
1203
3.28k
    }
1204
34.3k
  }
1205
1206
  // We have overflowed so we should be inf/-inf.
1207
13.2k
  if (exponent > max_exponent) {
1208
3.15k
    exponent = max_exponent;
1209
3.15k
    fraction = 0;
1210
3.15k
  }
1211
1212
13.2k
  uint_type output_bits = static_cast<uint_type>(
1213
13.2k
      static_cast<uint_type>(negate_value ? 1 : 0) << HF::top_bit_left_shift);
1214
13.2k
  output_bits |= fraction;
1215
1216
13.2k
  uint_type shifted_exponent = static_cast<uint_type>(
1217
13.2k
      static_cast<uint_type>(exponent << HF::exponent_left_shift) &
1218
13.2k
      HF::exponent_mask);
1219
13.2k
  output_bits |= shifted_exponent;
1220
1221
13.2k
  T output_float(output_bits);
1222
13.2k
  value.set_value(output_float);
1223
1224
13.2k
  return is;
1225
13.2k
}
std::__1::basic_istream<char, std::__1::char_traits<char> >& spvtools::utils::operator>><spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<float>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<float> > >&)
Line
Count
Source
960
28.5k
std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
961
28.5k
  using HF = HexFloat<T, Traits>;
962
28.5k
  using uint_type = typename HF::uint_type;
963
28.5k
  using int_type = typename HF::int_type;
964
965
28.5k
  value.set_value(static_cast<typename HF::native_type>(0.f));
966
967
28.5k
  if (is.flags() & std::ios::skipws) {
968
    // If the user wants to skip whitespace , then we should obey that.
969
30.6k
    while (std::isspace(is.peek())) {
970
2.07k
      is.get();
971
2.07k
    }
972
28.5k
  }
973
974
28.5k
  auto next_char = is.peek();
975
28.5k
  bool negate_value = false;
976
977
28.5k
  if (next_char != '-' && next_char != '0') {
978
12.5k
    return ParseNormalFloat(is, negate_value, value);
979
12.5k
  }
980
981
16.0k
  if (next_char == '-') {
982
1.68k
    negate_value = true;
983
1.68k
    is.get();
984
1.68k
    next_char = is.peek();
985
1.68k
  }
986
987
16.0k
  if (next_char == '0') {
988
15.0k
    is.get();  // We may have to unget this.
989
15.0k
    auto maybe_hex_start = is.peek();
990
15.0k
    if (maybe_hex_start != 'x' && maybe_hex_start != 'X') {
991
2.70k
      is.unget();
992
2.70k
      return ParseNormalFloat(is, negate_value, value);
993
12.3k
    } else {
994
12.3k
      is.get();  // Throw away the 'x';
995
12.3k
    }
996
15.0k
  } else {
997
958
    return ParseNormalFloat(is, negate_value, value);
998
958
  }
999
1000
  // This "looks" like a hex-float so treat it as one.
1001
12.3k
  bool seen_p = false;
1002
12.3k
  bool seen_dot = false;
1003
1004
  // The mantissa bits, without the most significant 1 bit, and with the
1005
  // the most recently read bits in the least significant positions.
1006
12.3k
  uint_type fraction = 0;
1007
  // The number of mantissa bits that have been read, including the leading 1
1008
  // bit that is not written into 'fraction'.
1009
12.3k
  uint_type fraction_index = 0;
1010
1011
  // TODO(dneto): handle overflow and underflow
1012
12.3k
  int_type exponent = HF::exponent_bias;
1013
1014
  // Strip off leading zeros so we don't have to special-case them later.
1015
14.4k
  while ((next_char = is.peek()) == '0') {
1016
2.10k
    is.get();
1017
2.10k
  }
1018
1019
  // Does the mantissa, as written, have non-zero digits to the left of
1020
  // the decimal point.  Assume no until proven otherwise.
1021
12.3k
  bool has_integer_part = false;
1022
12.3k
  bool bits_written = false;  // Stays false until we write a bit.
1023
1024
  // Scan the mantissa hex digits until we see a '.' or the 'p' that
1025
  // starts the exponent.
1026
6.75M
  while (!seen_p && !seen_dot) {
1027
    // Handle characters that are left of the fractional part.
1028
6.74M
    if (next_char == '.') {
1029
11.6k
      seen_dot = true;
1030
6.73M
    } else if (next_char == 'p') {
1031
632
      seen_p = true;
1032
6.73M
    } else if (::isxdigit(next_char)) {
1033
      // We have stripped all leading zeroes and we have not yet seen a ".".
1034
6.73M
      has_integer_part = true;
1035
6.73M
      int number = get_nibble_from_character(next_char);
1036
33.6M
      for (int i = 0; i < 4; ++i, number <<= 1) {
1037
26.9M
        uint_type write_bit = (number & 0x8) ? 0x1 : 0x0;
1038
26.9M
        if (bits_written) {
1039
          // If we are here the bits represented belong in the fractional
1040
          // part of the float, and we have to adjust the exponent accordingly.
1041
26.9M
          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
1042
26.9M
                                                          fraction_index);
1043
          // Increment the fraction index. If the input has bizarrely many
1044
          // significant digits, then silently drop them.
1045
26.9M
          detail::saturated_inc(fraction_index);
1046
26.9M
          if (!detail::saturated_inc(exponent)) {
1047
            // Overflow failure
1048
0
            is.setstate(std::ios::failbit);
1049
0
            return is;
1050
0
          }
1051
26.9M
        }
1052
        // Since this updated after setting fraction bits, this effectively
1053
        // drops the leading 1 bit.
1054
26.9M
        bits_written |= write_bit != 0;
1055
26.9M
      }
1056
6.73M
    } else {
1057
      // We have not found our exponent yet, so we have to fail.
1058
56
      is.setstate(std::ios::failbit);
1059
56
      return is;
1060
56
    }
1061
6.74M
    is.get();
1062
6.74M
    next_char = is.peek();
1063
6.74M
  }
1064
1065
  // Finished reading the part preceding any '.' or 'p'.
1066
1067
12.3k
  bits_written = false;
1068
8.70M
  while (seen_dot && !seen_p) {
1069
    // Handle only fractional parts now.
1070
8.69M
    if (next_char == 'p') {
1071
11.3k
      seen_p = true;
1072
8.68M
    } else if (::isxdigit(next_char)) {
1073
8.68M
      int number = get_nibble_from_character(next_char);
1074
43.4M
      for (int i = 0; i < 4; ++i, number <<= 1) {
1075
34.7M
        uint_type write_bit = (number & 0x8) ? 0x01 : 0x00;
1076
34.7M
        bits_written |= write_bit != 0;
1077
34.7M
        if ((!has_integer_part) && !bits_written) {
1078
          // Handle modifying the exponent here this way we can handle
1079
          // an arbitrary number of hex values without overflowing our
1080
          // integer.
1081
20.7M
          if (!detail::saturated_dec(exponent)) {
1082
            // Overflow failure
1083
0
            is.setstate(std::ios::failbit);
1084
0
            return is;
1085
0
          }
1086
20.7M
        } else {
1087
13.9M
          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
1088
13.9M
                                                          fraction_index);
1089
          // Increment the fraction index. If the input has bizarrely many
1090
          // significant digits, then silently drop them.
1091
13.9M
          detail::saturated_inc(fraction_index);
1092
13.9M
        }
1093
34.7M
      }
1094
8.68M
    } else {
1095
      // We still have not found our 'p' exponent yet, so this is not a valid
1096
      // hex-float.
1097
282
      is.setstate(std::ios::failbit);
1098
282
      return is;
1099
282
    }
1100
8.69M
    is.get();
1101
8.69M
    next_char = is.peek();
1102
8.69M
  }
1103
1104
  // Finished reading the part preceding 'p'.
1105
  // In hex floats syntax, the binary exponent is required.
1106
1107
12.0k
  bool seen_exponent_sign = false;
1108
12.0k
  int8_t exponent_sign = 1;
1109
12.0k
  bool seen_written_exponent_digits = false;
1110
  // The magnitude of the exponent, as written, or the sentinel value to signal
1111
  // overflow.
1112
12.0k
  int_type written_exponent = 0;
1113
  // A sentinel value signalling overflow of the magnitude of the written
1114
  // exponent.  We'll assume that -written_exponent_overflow is valid for the
1115
  // type. Later we may add 1 or subtract 1 from the adjusted exponent, so leave
1116
  // room for an extra 1.
1117
12.0k
  const int_type written_exponent_overflow =
1118
12.0k
      std::numeric_limits<int_type>::max() - 1;
1119
107k
  while (true) {
1120
107k
    if (!seen_written_exponent_digits &&
1121
107k
        (next_char == '-' || next_char == '+')) {
1122
4.61k
      if (seen_exponent_sign) {
1123
4
        is.setstate(std::ios::failbit);
1124
4
        return is;
1125
4
      }
1126
4.60k
      seen_exponent_sign = true;
1127
4.60k
      exponent_sign = (next_char == '-') ? -1 : 1;
1128
102k
    } else if (::isdigit(next_char)) {
1129
90.6k
      seen_written_exponent_digits = true;
1130
      // Hex-floats express their exponent as decimal.
1131
90.6k
      int_type digit =
1132
90.6k
          static_cast<int_type>(static_cast<int_type>(next_char) - '0');
1133
90.6k
      if (written_exponent >= (written_exponent_overflow - digit) / 10) {
1134
        // The exponent is very big. Saturate rather than overflow the exponent.
1135
        // signed integer, which would be undefined behaviour.
1136
2.95k
        written_exponent = written_exponent_overflow;
1137
87.7k
      } else {
1138
87.7k
        written_exponent = static_cast<int_type>(
1139
87.7k
            static_cast<int_type>(written_exponent * 10) + digit);
1140
87.7k
      }
1141
90.6k
    } else {
1142
12.0k
      break;
1143
12.0k
    }
1144
95.2k
    is.get();
1145
95.2k
    next_char = is.peek();
1146
95.2k
  }
1147
12.0k
  if (!seen_written_exponent_digits) {
1148
    // Binary exponent had no digits.
1149
38
    is.setstate(std::ios::failbit);
1150
38
    return is;
1151
38
  }
1152
1153
11.9k
  written_exponent = static_cast<int_type>(written_exponent * exponent_sign);
1154
  // Now fold in the exponent bias into the written exponent, updating exponent.
1155
  // But avoid undefined behaviour that would result from overflowing int_type.
1156
11.9k
  if (written_exponent >= 0 && exponent >= 0) {
1157
    // Saturate up to written_exponent_overflow.
1158
7.60k
    if (written_exponent_overflow - exponent > written_exponent) {
1159
7.10k
      exponent = static_cast<int_type>(written_exponent + exponent);
1160
7.10k
    } else {
1161
500
      exponent = written_exponent_overflow;
1162
500
    }
1163
7.60k
  } else if (written_exponent < 0 && exponent < 0) {
1164
    // Saturate down to -written_exponent_overflow.
1165
1.61k
    if (written_exponent_overflow + exponent > -written_exponent) {
1166
891
      exponent = static_cast<int_type>(written_exponent + exponent);
1167
891
    } else {
1168
719
      exponent = static_cast<int_type>(-written_exponent_overflow);
1169
719
    }
1170
2.77k
  } else {
1171
    // They're of opposing sign, so it's safe to add.
1172
2.77k
    exponent = static_cast<int_type>(written_exponent + exponent);
1173
2.77k
  }
1174
1175
11.9k
  bool is_zero = (!has_integer_part) && (fraction == 0);
1176
11.9k
  if ((!has_integer_part) && !is_zero) {
1177
4.53k
    fraction = static_cast<uint_type>(fraction << 1);
1178
4.53k
    exponent = static_cast<int_type>(exponent - 1);
1179
7.45k
  } else if (is_zero) {
1180
5.14k
    exponent = 0;
1181
5.14k
  }
1182
1183
11.9k
  if (exponent <= 0 && !is_zero) {
1184
1.95k
    fraction = static_cast<uint_type>(fraction >> 1);
1185
1.95k
    fraction |= static_cast<uint_type>(1) << HF::top_bit_left_shift;
1186
1.95k
  }
1187
1188
11.9k
  fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask;
1189
1190
11.9k
  const int_type max_exponent =
1191
11.9k
      SetBits<uint_type, 0, HF::num_exponent_bits>::get;
1192
1193
  // Handle denorm numbers
1194
47.1k
  while (exponent < 0 && !is_zero) {
1195
35.1k
    fraction = static_cast<uint_type>(fraction >> 1);
1196
35.1k
    exponent = static_cast<int_type>(exponent + 1);
1197
1198
35.1k
    fraction &= HF::fraction_encode_mask;
1199
35.1k
    if (fraction == 0) {
1200
      // We have underflowed our fraction. We should clamp to zero.
1201
1.38k
      is_zero = true;
1202
1.38k
      exponent = 0;
1203
1.38k
    }
1204
35.1k
  }
1205
1206
  // We have overflowed so we should be inf/-inf.
1207
11.9k
  if (exponent > max_exponent) {
1208
1.55k
    exponent = max_exponent;
1209
1.55k
    fraction = 0;
1210
1.55k
  }
1211
1212
11.9k
  uint_type output_bits = static_cast<uint_type>(
1213
11.9k
      static_cast<uint_type>(negate_value ? 1 : 0) << HF::top_bit_left_shift);
1214
11.9k
  output_bits |= fraction;
1215
1216
11.9k
  uint_type shifted_exponent = static_cast<uint_type>(
1217
11.9k
      static_cast<uint_type>(exponent << HF::exponent_left_shift) &
1218
11.9k
      HF::exponent_mask);
1219
11.9k
  output_bits |= shifted_exponent;
1220
1221
11.9k
  T output_float(output_bits);
1222
11.9k
  value.set_value(output_float);
1223
1224
11.9k
  return is;
1225
12.0k
}
std::__1::basic_istream<char, std::__1::char_traits<char> >& spvtools::utils::operator>><spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, spvtools::utils::HexFloat<spvtools::utils::FloatProxy<double>, spvtools::utils::HexFloatTraits<spvtools::utils::FloatProxy<double> > >&)
Line
Count
Source
960
20.3k
std::istream& operator>>(std::istream& is, HexFloat<T, Traits>& value) {
961
20.3k
  using HF = HexFloat<T, Traits>;
962
20.3k
  using uint_type = typename HF::uint_type;
963
20.3k
  using int_type = typename HF::int_type;
964
965
20.3k
  value.set_value(static_cast<typename HF::native_type>(0.f));
966
967
20.3k
  if (is.flags() & std::ios::skipws) {
968
    // If the user wants to skip whitespace , then we should obey that.
969
22.2k
    while (std::isspace(is.peek())) {
970
1.87k
      is.get();
971
1.87k
    }
972
20.3k
  }
973
974
20.3k
  auto next_char = is.peek();
975
20.3k
  bool negate_value = false;
976
977
20.3k
  if (next_char != '-' && next_char != '0') {
978
1.32k
    return ParseNormalFloat(is, negate_value, value);
979
1.32k
  }
980
981
19.0k
  if (next_char == '-') {
982
3.76k
    negate_value = true;
983
3.76k
    is.get();
984
3.76k
    next_char = is.peek();
985
3.76k
  }
986
987
19.0k
  if (next_char == '0') {
988
16.7k
    is.get();  // We may have to unget this.
989
16.7k
    auto maybe_hex_start = is.peek();
990
16.7k
    if (maybe_hex_start != 'x' && maybe_hex_start != 'X') {
991
2.83k
      is.unget();
992
2.83k
      return ParseNormalFloat(is, negate_value, value);
993
13.8k
    } else {
994
13.8k
      is.get();  // Throw away the 'x';
995
13.8k
    }
996
16.7k
  } else {
997
2.31k
    return ParseNormalFloat(is, negate_value, value);
998
2.31k
  }
999
1000
  // This "looks" like a hex-float so treat it as one.
1001
13.8k
  bool seen_p = false;
1002
13.8k
  bool seen_dot = false;
1003
1004
  // The mantissa bits, without the most significant 1 bit, and with the
1005
  // the most recently read bits in the least significant positions.
1006
13.8k
  uint_type fraction = 0;
1007
  // The number of mantissa bits that have been read, including the leading 1
1008
  // bit that is not written into 'fraction'.
1009
13.8k
  uint_type fraction_index = 0;
1010
1011
  // TODO(dneto): handle overflow and underflow
1012
13.8k
  int_type exponent = HF::exponent_bias;
1013
1014
  // Strip off leading zeros so we don't have to special-case them later.
1015
20.3k
  while ((next_char = is.peek()) == '0') {
1016
6.46k
    is.get();
1017
6.46k
  }
1018
1019
  // Does the mantissa, as written, have non-zero digits to the left of
1020
  // the decimal point.  Assume no until proven otherwise.
1021
13.8k
  bool has_integer_part = false;
1022
13.8k
  bool bits_written = false;  // Stays false until we write a bit.
1023
1024
  // Scan the mantissa hex digits until we see a '.' or the 'p' that
1025
  // starts the exponent.
1026
12.0M
  while (!seen_p && !seen_dot) {
1027
    // Handle characters that are left of the fractional part.
1028
12.0M
    if (next_char == '.') {
1029
7.61k
      seen_dot = true;
1030
11.9M
    } else if (next_char == 'p') {
1031
6.11k
      seen_p = true;
1032
11.9M
    } else if (::isxdigit(next_char)) {
1033
      // We have stripped all leading zeroes and we have not yet seen a ".".
1034
11.9M
      has_integer_part = true;
1035
11.9M
      int number = get_nibble_from_character(next_char);
1036
59.9M
      for (int i = 0; i < 4; ++i, number <<= 1) {
1037
47.9M
        uint_type write_bit = (number & 0x8) ? 0x1 : 0x0;
1038
47.9M
        if (bits_written) {
1039
          // If we are here the bits represented belong in the fractional
1040
          // part of the float, and we have to adjust the exponent accordingly.
1041
47.9M
          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
1042
47.9M
                                                          fraction_index);
1043
          // Increment the fraction index. If the input has bizarrely many
1044
          // significant digits, then silently drop them.
1045
47.9M
          detail::saturated_inc(fraction_index);
1046
47.9M
          if (!detail::saturated_inc(exponent)) {
1047
            // Overflow failure
1048
0
            is.setstate(std::ios::failbit);
1049
0
            return is;
1050
0
          }
1051
47.9M
        }
1052
        // Since this updated after setting fraction bits, this effectively
1053
        // drops the leading 1 bit.
1054
47.9M
        bits_written |= write_bit != 0;
1055
47.9M
      }
1056
11.9M
    } else {
1057
      // We have not found our exponent yet, so we have to fail.
1058
158
      is.setstate(std::ios::failbit);
1059
158
      return is;
1060
158
    }
1061
12.0M
    is.get();
1062
12.0M
    next_char = is.peek();
1063
12.0M
  }
1064
1065
  // Finished reading the part preceding any '.' or 'p'.
1066
1067
13.7k
  bits_written = false;
1068
16.6M
  while (seen_dot && !seen_p) {
1069
    // Handle only fractional parts now.
1070
16.6M
    if (next_char == 'p') {
1071
7.46k
      seen_p = true;
1072
16.5M
    } else if (::isxdigit(next_char)) {
1073
16.5M
      int number = get_nibble_from_character(next_char);
1074
82.9M
      for (int i = 0; i < 4; ++i, number <<= 1) {
1075
66.3M
        uint_type write_bit = (number & 0x8) ? 0x01 : 0x00;
1076
66.3M
        bits_written |= write_bit != 0;
1077
66.3M
        if ((!has_integer_part) && !bits_written) {
1078
          // Handle modifying the exponent here this way we can handle
1079
          // an arbitrary number of hex values without overflowing our
1080
          // integer.
1081
58.7M
          if (!detail::saturated_dec(exponent)) {
1082
            // Overflow failure
1083
0
            is.setstate(std::ios::failbit);
1084
0
            return is;
1085
0
          }
1086
58.7M
        } else {
1087
7.65M
          fraction = detail::set_nth_most_significant_bit(fraction, write_bit,
1088
7.65M
                                                          fraction_index);
1089
          // Increment the fraction index. If the input has bizarrely many
1090
          // significant digits, then silently drop them.
1091
7.65M
          detail::saturated_inc(fraction_index);
1092
7.65M
        }
1093
66.3M
      }
1094
16.5M
    } else {
1095
      // We still have not found our 'p' exponent yet, so this is not a valid
1096
      // hex-float.
1097
156
      is.setstate(std::ios::failbit);
1098
156
      return is;
1099
156
    }
1100
16.6M
    is.get();
1101
16.6M
    next_char = is.peek();
1102
16.6M
  }
1103
1104
  // Finished reading the part preceding 'p'.
1105
  // In hex floats syntax, the binary exponent is required.
1106
1107
13.5k
  bool seen_exponent_sign = false;
1108
13.5k
  int8_t exponent_sign = 1;
1109
13.5k
  bool seen_written_exponent_digits = false;
1110
  // The magnitude of the exponent, as written, or the sentinel value to signal
1111
  // overflow.
1112
13.5k
  int_type written_exponent = 0;
1113
  // A sentinel value signalling overflow of the magnitude of the written
1114
  // exponent.  We'll assume that -written_exponent_overflow is valid for the
1115
  // type. Later we may add 1 or subtract 1 from the adjusted exponent, so leave
1116
  // room for an extra 1.
1117
13.5k
  const int_type written_exponent_overflow =
1118
13.5k
      std::numeric_limits<int_type>::max() - 1;
1119
299k
  while (true) {
1120
299k
    if (!seen_written_exponent_digits &&
1121
299k
        (next_char == '-' || next_char == '+')) {
1122
5.01k
      if (seen_exponent_sign) {
1123
4
        is.setstate(std::ios::failbit);
1124
4
        return is;
1125
4
      }
1126
5.01k
      seen_exponent_sign = true;
1127
5.01k
      exponent_sign = (next_char == '-') ? -1 : 1;
1128
294k
    } else if (::isdigit(next_char)) {
1129
281k
      seen_written_exponent_digits = true;
1130
      // Hex-floats express their exponent as decimal.
1131
281k
      int_type digit =
1132
281k
          static_cast<int_type>(static_cast<int_type>(next_char) - '0');
1133
281k
      if (written_exponent >= (written_exponent_overflow - digit) / 10) {
1134
        // The exponent is very big. Saturate rather than overflow the exponent.
1135
        // signed integer, which would be undefined behaviour.
1136
30.6k
        written_exponent = written_exponent_overflow;
1137
250k
      } else {
1138
250k
        written_exponent = static_cast<int_type>(
1139
250k
            static_cast<int_type>(written_exponent * 10) + digit);
1140
250k
      }
1141
281k
    } else {
1142
13.5k
      break;
1143
13.5k
    }
1144
286k
    is.get();
1145
286k
    next_char = is.peek();
1146
286k
  }
1147
13.5k
  if (!seen_written_exponent_digits) {
1148
    // Binary exponent had no digits.
1149
38
    is.setstate(std::ios::failbit);
1150
38
    return is;
1151
38
  }
1152
1153
13.5k
  written_exponent = static_cast<int_type>(written_exponent * exponent_sign);
1154
  // Now fold in the exponent bias into the written exponent, updating exponent.
1155
  // But avoid undefined behaviour that would result from overflowing int_type.
1156
13.5k
  if (written_exponent >= 0 && exponent >= 0) {
1157
    // Saturate up to written_exponent_overflow.
1158
9.25k
    if (written_exponent_overflow - exponent > written_exponent) {
1159
6.40k
      exponent = static_cast<int_type>(written_exponent + exponent);
1160
6.40k
    } else {
1161
2.85k
      exponent = written_exponent_overflow;
1162
2.85k
    }
1163
9.25k
  } else if (written_exponent < 0 && exponent < 0) {
1164
    // Saturate down to -written_exponent_overflow.
1165
1.14k
    if (written_exponent_overflow + exponent > -written_exponent) {
1166
948
      exponent = static_cast<int_type>(written_exponent + exponent);
1167
948
    } else {
1168
200
      exponent = static_cast<int_type>(-written_exponent_overflow);
1169
200
    }
1170
3.12k
  } else {
1171
    // They're of opposing sign, so it's safe to add.
1172
3.12k
    exponent = static_cast<int_type>(written_exponent + exponent);
1173
3.12k
  }
1174
1175
13.5k
  bool is_zero = (!has_integer_part) && (fraction == 0);
1176
13.5k
  if ((!has_integer_part) && !is_zero) {
1177
5.15k
    fraction = static_cast<uint_type>(fraction << 1);
1178
5.15k
    exponent = static_cast<int_type>(exponent - 1);
1179
8.37k
  } else if (is_zero) {
1180
4.74k
    exponent = 0;
1181
4.74k
  }
1182
1183
13.5k
  if (exponent <= 0 && !is_zero) {
1184
2.53k
    fraction = static_cast<uint_type>(fraction >> 1);
1185
2.53k
    fraction |= static_cast<uint_type>(1) << HF::top_bit_left_shift;
1186
2.53k
  }
1187
1188
13.5k
  fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask;
1189
1190
13.5k
  const int_type max_exponent =
1191
13.5k
      SetBits<uint_type, 0, HF::num_exponent_bits>::get;
1192
1193
  // Handle denorm numbers
1194
124k
  while (exponent < 0 && !is_zero) {
1195
110k
    fraction = static_cast<uint_type>(fraction >> 1);
1196
110k
    exponent = static_cast<int_type>(exponent + 1);
1197
1198
110k
    fraction &= HF::fraction_encode_mask;
1199
110k
    if (fraction == 0) {
1200
      // We have underflowed our fraction. We should clamp to zero.
1201
2.04k
      is_zero = true;
1202
2.04k
      exponent = 0;
1203
2.04k
    }
1204
110k
  }
1205
1206
  // We have overflowed so we should be inf/-inf.
1207
13.5k
  if (exponent > max_exponent) {
1208
2.00k
    exponent = max_exponent;
1209
2.00k
    fraction = 0;
1210
2.00k
  }
1211
1212
13.5k
  uint_type output_bits = static_cast<uint_type>(
1213
13.5k
      static_cast<uint_type>(negate_value ? 1 : 0) << HF::top_bit_left_shift);
1214
13.5k
  output_bits |= fraction;
1215
1216
13.5k
  uint_type shifted_exponent = static_cast<uint_type>(
1217
13.5k
      static_cast<uint_type>(exponent << HF::exponent_left_shift) &
1218
13.5k
      HF::exponent_mask);
1219
13.5k
  output_bits |= shifted_exponent;
1220
1221
13.5k
  T output_float(output_bits);
1222
13.5k
  value.set_value(output_float);
1223
1224
13.5k
  return is;
1225
13.5k
}
1226
1227
// Writes a FloatProxy value to a stream.
1228
// Zero and normal numbers are printed in the usual notation, but with
1229
// enough digits to fully reproduce the value.  Other values (subnormal,
1230
// NaN, and infinity) are printed as a hex float.
1231
template <typename T>
1232
476k
std::ostream& operator<<(std::ostream& os, const FloatProxy<T>& value) {
1233
476k
  auto float_val = value.getAsFloat();
1234
476k
  switch (std::fpclassify(float_val)) {
1235
15.1k
    case FP_ZERO:
1236
122k
    case FP_NORMAL: {
1237
122k
      auto saved_precision = os.precision();
1238
122k
      os.precision(std::numeric_limits<T>::max_digits10);
1239
122k
      os << float_val;
1240
122k
      os.precision(saved_precision);
1241
122k
    } break;
1242
353k
    default:
1243
353k
      os << HexFloat<FloatProxy<T>>(value);
1244
353k
      break;
1245
476k
  }
1246
476k
  return os;
1247
476k
}
std::__1::basic_ostream<char, std::__1::char_traits<char> >& spvtools::utils::operator<< <float>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, spvtools::utils::FloatProxy<float> const&)
Line
Count
Source
1232
456k
std::ostream& operator<<(std::ostream& os, const FloatProxy<T>& value) {
1233
456k
  auto float_val = value.getAsFloat();
1234
456k
  switch (std::fpclassify(float_val)) {
1235
14.7k
    case FP_ZERO:
1236
121k
    case FP_NORMAL: {
1237
121k
      auto saved_precision = os.precision();
1238
121k
      os.precision(std::numeric_limits<T>::max_digits10);
1239
121k
      os << float_val;
1240
121k
      os.precision(saved_precision);
1241
121k
    } break;
1242
335k
    default:
1243
335k
      os << HexFloat<FloatProxy<T>>(value);
1244
335k
      break;
1245
456k
  }
1246
456k
  return os;
1247
456k
}
std::__1::basic_ostream<char, std::__1::char_traits<char> >& spvtools::utils::operator<< <double>(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, spvtools::utils::FloatProxy<double> const&)
Line
Count
Source
1232
20.2k
std::ostream& operator<<(std::ostream& os, const FloatProxy<T>& value) {
1233
20.2k
  auto float_val = value.getAsFloat();
1234
20.2k
  switch (std::fpclassify(float_val)) {
1235
355
    case FP_ZERO:
1236
1.70k
    case FP_NORMAL: {
1237
1.70k
      auto saved_precision = os.precision();
1238
1.70k
      os.precision(std::numeric_limits<T>::max_digits10);
1239
1.70k
      os << float_val;
1240
1.70k
      os.precision(saved_precision);
1241
1.70k
    } break;
1242
18.5k
    default:
1243
18.5k
      os << HexFloat<FloatProxy<T>>(value);
1244
18.5k
      break;
1245
20.2k
  }
1246
20.2k
  return os;
1247
20.2k
}
1248
1249
template <>
1250
inline std::ostream& operator<<<Float16>(std::ostream& os,
1251
130k
                                         const FloatProxy<Float16>& value) {
1252
130k
  os << HexFloat<FloatProxy<Float16>>(value);
1253
130k
  return os;
1254
130k
}
1255
1256
}  // namespace utils
1257
}  // namespace spvtools
1258
1259
#endif  // SOURCE_UTIL_HEX_FLOAT_H_