Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FloatTraits.hpp Source File

FloatTraits.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <stddef.h>  // for size_t
00008 #include <stdint.h>
00009 
00010 #include <ArduinoJson/Configuration.hpp>
00011 #include <ArduinoJson/Polyfills/alias_cast.hpp>
00012 #include <ArduinoJson/Polyfills/math.hpp>
00013 #include <ArduinoJson/Polyfills/preprocessor.hpp>
00014 #include <ArduinoJson/Polyfills/static_array.hpp>
00015 
00016 namespace ARDUINOJSON_NAMESPACE {
00017 
00018 template <typename T, size_t = sizeof(T)>
00019 struct FloatTraits {};
00020 
00021 template <typename T>
00022 struct FloatTraits<T, 8 /*64bits*/> {
00023   typedef uint64_t mantissa_type;
00024   static const short mantissa_bits = 52;
00025   static const mantissa_type mantissa_max =
00026       (mantissa_type(1) << mantissa_bits) - 1;
00027 
00028   typedef int16_t exponent_type;
00029   static const exponent_type exponent_max = 308;
00030 
00031   template <typename TExponent>
00032   static T make_float(T m, TExponent e) {
00033     if (e > 0) {
00034       for (uint8_t index = 0; e != 0; index++) {
00035         if (e & 1)
00036           m *= positiveBinaryPowerOfTen(index);
00037         e >>= 1;
00038       }
00039     } else {
00040       e = TExponent(-e);
00041       for (uint8_t index = 0; e != 0; index++) {
00042         if (e & 1)
00043           m *= negativeBinaryPowerOfTen(index);
00044         e >>= 1;
00045       }
00046     }
00047     return m;
00048   }
00049 
00050   static T positiveBinaryPowerOfTen(int index) {
00051     ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
00052         uint32_t, factors,
00053         ARDUINOJSON_EXPAND18({
00054             0x40240000, 0x00000000,  // 1e1
00055             0x40590000, 0x00000000,  // 1e2
00056             0x40C38800, 0x00000000,  // 1e4
00057             0x4197D784, 0x00000000,  // 1e8
00058             0x4341C379, 0x37E08000,  // 1e16
00059             0x4693B8B5, 0xB5056E17,  // 1e32
00060             0x4D384F03, 0xE93FF9F5,  // 1e64
00061             0x5A827748, 0xF9301D32,  // 1e128
00062             0x75154FDD, 0x7F73BF3C   // 1e256
00063         }));
00064     return forge(
00065         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
00066         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
00067   }
00068 
00069   static T negativeBinaryPowerOfTen(int index) {
00070     ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
00071         uint32_t, factors,
00072         ARDUINOJSON_EXPAND18({
00073             0x3FB99999, 0x9999999A,  // 1e-1
00074             0x3F847AE1, 0x47AE147B,  // 1e-2
00075             0x3F1A36E2, 0xEB1C432D,  // 1e-4
00076             0x3E45798E, 0xE2308C3A,  // 1e-8
00077             0x3C9CD2B2, 0x97D889BC,  // 1e-16
00078             0x3949F623, 0xD5A8A733,  // 1e-32
00079             0x32A50FFD, 0x44F4A73D,  // 1e-64
00080             0x255BBA08, 0xCF8C979D,  // 1e-128
00081             0x0AC80628, 0x64AC6F43   // 1e-256
00082         }));
00083     return forge(
00084         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
00085         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
00086   }
00087 
00088   static T negativeBinaryPowerOfTenPlusOne(int index) {
00089     ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
00090         uint32_t, factors,
00091         ARDUINOJSON_EXPAND18({
00092             0x3FF00000, 0x00000000,  // 1e0
00093             0x3FB99999, 0x9999999A,  // 1e-1
00094             0x3F50624D, 0xD2F1A9FC,  // 1e-3
00095             0x3E7AD7F2, 0x9ABCAF48,  // 1e-7
00096             0x3CD203AF, 0x9EE75616,  // 1e-15
00097             0x398039D6, 0x65896880,  // 1e-31
00098             0x32DA53FC, 0x9631D10D,  // 1e-63
00099             0x25915445, 0x81B7DEC2,  // 1e-127
00100             0x0AFE07B2, 0x7DD78B14   // 1e-255
00101         }));
00102     return forge(
00103         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
00104         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
00105   }
00106 
00107   static T nan() {
00108     return forge(0x7ff80000, 0x00000000);
00109   }
00110 
00111   static T inf() {
00112     return forge(0x7ff00000, 0x00000000);
00113   }
00114 
00115   static T highest() {
00116     return forge(0x7FEFFFFF, 0xFFFFFFFF);
00117   }
00118 
00119   static T lowest() {
00120     return forge(0xFFEFFFFF, 0xFFFFFFFF);
00121   }
00122 
00123   // constructs a double floating point values from its binary representation
00124   // we use this function to workaround platforms with single precision literals
00125   // (for example, when -fsingle-precision-constant is passed to GCC)
00126   static T forge(uint32_t msb, uint32_t lsb) {
00127     return alias_cast<T>((uint64_t(msb) << 32) | lsb);
00128   }
00129 };
00130 
00131 template <typename T>
00132 struct FloatTraits<T, 4 /*32bits*/> {
00133   typedef uint32_t mantissa_type;
00134   static const short mantissa_bits = 23;
00135   static const mantissa_type mantissa_max =
00136       (mantissa_type(1) << mantissa_bits) - 1;
00137 
00138   typedef int8_t exponent_type;
00139   static const exponent_type exponent_max = 38;
00140 
00141   template <typename TExponent>
00142   static T make_float(T m, TExponent e) {
00143     if (e > 0) {
00144       for (uint8_t index = 0; e != 0; index++) {
00145         if (e & 1)
00146           m *= positiveBinaryPowerOfTen(index);
00147         e >>= 1;
00148       }
00149     } else {
00150       e = -e;
00151       for (uint8_t index = 0; e != 0; index++) {
00152         if (e & 1)
00153           m *= negativeBinaryPowerOfTen(index);
00154         e >>= 1;
00155       }
00156     }
00157     return m;
00158   }
00159 
00160   static T positiveBinaryPowerOfTen(int index) {
00161     ARDUINOJSON_DEFINE_STATIC_ARRAY(
00162         T, factors,
00163         ARDUINOJSON_EXPAND6({1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}));
00164     return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
00165   }
00166 
00167   static T negativeBinaryPowerOfTen(int index) {
00168     ARDUINOJSON_DEFINE_STATIC_ARRAY(
00169         T, factors,
00170         ARDUINOJSON_EXPAND6({1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}));
00171     return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
00172   }
00173 
00174   static T negativeBinaryPowerOfTenPlusOne(int index) {
00175     ARDUINOJSON_DEFINE_STATIC_ARRAY(
00176         T, factors,
00177         ARDUINOJSON_EXPAND6({1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}));
00178     return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
00179   }
00180 
00181   static T forge(uint32_t bits) {
00182     return alias_cast<T>(bits);
00183   }
00184 
00185   static T nan() {
00186     return forge(0x7fc00000);
00187   }
00188 
00189   static T inf() {
00190     return forge(0x7f800000);
00191   }
00192 
00193   static T highest() {
00194     return forge(0x7f7fffff);
00195   }
00196 
00197   static T lowest() {
00198     return forge(0xFf7fffff);
00199   }
00200 };
00201 }  // namespace ARDUINOJSON_NAMESPACE