Coverage Report

Created: 2024-09-08 06:19

/src/arduinojson/src/ArduinoJson/Numbers/FloatTraits.hpp
Line
Count
Source (jump to first uncovered line)
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2024, Benoit BLANCHON
3
// MIT License
4
5
#pragma once
6
7
#include <stddef.h>  // for size_t
8
#include <stdint.h>
9
10
#include <ArduinoJson/Configuration.hpp>
11
#include <ArduinoJson/Polyfills/alias_cast.hpp>
12
#include <ArduinoJson/Polyfills/math.hpp>
13
#include <ArduinoJson/Polyfills/pgmspace_generic.hpp>
14
#include <ArduinoJson/Polyfills/preprocessor.hpp>
15
#include <ArduinoJson/Polyfills/type_traits.hpp>
16
17
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
18
19
template <typename T, size_t = sizeof(T)>
20
struct FloatTraits {};
21
22
template <typename T>
23
struct FloatTraits<T, 8 /*64bits*/> {
24
  typedef uint64_t mantissa_type;
25
  static const short mantissa_bits = 52;
26
  static const mantissa_type mantissa_max =
27
      (mantissa_type(1) << mantissa_bits) - 1;
28
29
  typedef int16_t exponent_type;
30
  static const exponent_type exponent_max = 308;
31
32
0
  static pgm_ptr<T> positiveBinaryPowersOfTen() {
33
0
    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  //
34
0
        uint64_t, factors,
35
0
        {
36
0
            0x4024000000000000,  // 1e1
37
0
            0x4059000000000000,  // 1e2
38
0
            0x40C3880000000000,  // 1e4
39
0
            0x4197D78400000000,  // 1e8
40
0
            0x4341C37937E08000,  // 1e16
41
0
            0x4693B8B5B5056E17,  // 1e32
42
0
            0x4D384F03E93FF9F5,  // 1e64
43
0
            0x5A827748F9301D32,  // 1e128
44
0
            0x75154FDD7F73BF3C,  // 1e256
45
0
        });
46
0
    return pgm_ptr<T>(reinterpret_cast<const T*>(factors));
47
0
  }
48
49
0
  static pgm_ptr<T> negativeBinaryPowersOfTen() {
50
0
    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  //
51
0
        uint64_t, factors,
52
0
        {
53
0
            0x3FB999999999999A,  // 1e-1
54
0
            0x3F847AE147AE147B,  // 1e-2
55
0
            0x3F1A36E2EB1C432D,  // 1e-4
56
0
            0x3E45798EE2308C3A,  // 1e-8
57
0
            0x3C9CD2B297D889BC,  // 1e-16
58
0
            0x3949F623D5A8A733,  // 1e-32
59
0
            0x32A50FFD44F4A73D,  // 1e-64
60
0
            0x255BBA08CF8C979D,  // 1e-128
61
0
            0x0AC8062864AC6F43   // 1e-256
62
0
        });
63
0
    return pgm_ptr<T>(reinterpret_cast<const T*>(factors));
64
0
  }
65
66
  static T nan() {
67
    return forge(0x7ff8000000000000);
68
  }
69
70
0
  static T inf() {
71
0
    return forge(0x7ff0000000000000);
72
0
  }
73
74
  static T highest() {
75
    return forge(0x7FEFFFFFFFFFFFFF);
76
  }
77
78
  template <typename TOut>  // int64_t
79
  static T highest_for(
80
      enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
81
                      sizeof(TOut) == 8,
82
                  signed>* = 0) {
83
    return forge(0x43DFFFFFFFFFFFFF);  //  9.2233720368547748e+18
84
  }
85
86
  template <typename TOut>  // uint64_t
87
  static T highest_for(
88
      enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
89
                      sizeof(TOut) == 8,
90
                  unsigned>* = 0) {
91
    return forge(0x43EFFFFFFFFFFFFF);  //  1.8446744073709549568e+19
92
  }
93
94
  static T lowest() {
95
    return forge(0xFFEFFFFFFFFFFFFF);
96
  }
97
98
  // constructs a double floating point values from its binary representation
99
  // we use this function to workaround platforms with single precision literals
100
  // (for example, when -fsingle-precision-constant is passed to GCC)
101
0
  static T forge(uint64_t bits) {
102
0
    return alias_cast<T>(bits);
103
0
  }
104
};
105
106
template <typename T>
107
struct FloatTraits<T, 4 /*32bits*/> {
108
  typedef uint32_t mantissa_type;
109
  static const short mantissa_bits = 23;
110
  static const mantissa_type mantissa_max =
111
      (mantissa_type(1) << mantissa_bits) - 1;
112
113
  typedef int8_t exponent_type;
114
  static const exponent_type exponent_max = 38;
115
116
0
  static pgm_ptr<T> positiveBinaryPowersOfTen() {
117
0
    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
118
0
                                     {
119
0
                                         0x41200000,  // 1e1f
120
0
                                         0x42c80000,  // 1e2f
121
0
                                         0x461c4000,  // 1e4f
122
0
                                         0x4cbebc20,  // 1e8f
123
0
                                         0x5a0e1bca,  // 1e16f
124
0
                                         0x749dc5ae   // 1e32f
125
0
                                     });
126
0
    return pgm_ptr<T>(reinterpret_cast<const T*>(factors));
127
0
  }
128
129
0
  static pgm_ptr<T> negativeBinaryPowersOfTen() {
130
0
    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
131
0
                                     {
132
0
                                         0x3dcccccd,  // 1e-1f
133
0
                                         0x3c23d70a,  // 1e-2f
134
0
                                         0x38d1b717,  // 1e-4f
135
0
                                         0x322bcc77,  // 1e-8f
136
0
                                         0x24e69595,  // 1e-16f
137
0
                                         0x0a4fb11f   // 1e-32f
138
0
                                     });
139
0
    return pgm_ptr<T>(reinterpret_cast<const T*>(factors));
140
0
  }
141
142
301
  static T forge(uint32_t bits) {
143
301
    return alias_cast<T>(bits);
144
301
  }
145
146
  static T nan() {
147
    return forge(0x7fc00000);
148
  }
149
150
  static T inf() {
151
    return forge(0x7f800000);
152
  }
153
154
  static T highest() {
155
    return forge(0x7f7fffff);
156
  }
157
158
  template <typename TOut>  // int32_t
159
  static T highest_for(
160
      enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
161
                      sizeof(TOut) == 4,
162
                  signed>* = 0) {
163
    return forge(0x4EFFFFFF);  // 2.14748352E9
164
  }
165
166
  template <typename TOut>  // uint32_t
167
  static T highest_for(
168
      enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
169
                      sizeof(TOut) == 4,
170
                  unsigned>* = 0) {
171
    return forge(0x4F7FFFFF);  // 4.29496704E9
172
  }
173
174
  template <typename TOut>  // int64_t
175
  static T highest_for(
176
      enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
177
                      sizeof(TOut) == 8,
178
301
                  signed>* = 0) {
179
301
    return forge(0x5EFFFFFF);  // 9.22337148709896192E18
180
301
  }
181
182
  template <typename TOut>  // uint64_t
183
  static T highest_for(
184
      enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
185
                      sizeof(TOut) == 8,
186
                  unsigned>* = 0) {
187
    return forge(0x5F7FFFFF);  // 1.844674297419792384E19
188
  }
189
190
  static T lowest() {
191
    return forge(0xFf7fffff);
192
  }
193
};
194
195
template <typename TFloat, typename TExponent>
196
0
inline TFloat make_float(TFloat m, TExponent e) {
197
0
  using traits = FloatTraits<TFloat>;
198
0
199
0
  auto powersOfTen = e > 0 ? traits::positiveBinaryPowersOfTen()
200
0
                           : traits::negativeBinaryPowersOfTen();
201
0
  if (e <= 0)
202
0
    e = TExponent(-e);
203
0
204
0
  for (uint8_t index = 0; e != 0; index++) {
205
0
    if (e & 1)
206
0
      m *= powersOfTen[index];
207
0
    e >>= 1;
208
0
  }
209
0
  return m;
210
0
}
Unexecuted instantiation: double ArduinoJson::V710HB42::detail::make_float<double, int>(double, int)
Unexecuted instantiation: float ArduinoJson::V710HB42::detail::make_float<float, int>(float, int)
211
212
ARDUINOJSON_END_PRIVATE_NAMESPACE