Numworks Epsilon  1.4.1
Graphing Calculator Operating System
ieee754.h
Go to the documentation of this file.
1 #ifndef POINCARE_IEEE754_H
2 #define POINCARE_IEEE754_H
3 
4 #include <assert.h>
5 #include <stdint.h>
6 #include <stddef.h>
7 #include <cmath>
8 
9 namespace Poincare {
10 
11 /* This class describes the IEEE 754 float representation.
12  * Float numbers are 32(64)-bit values, stored as follow:
13  * sign: 1 bit (1 bit)
14  * exponent: 8 bits (11 bits)
15  * mantissa: 23 bits (52 bits)
16  */
17 
18 template<typename T>
19 class IEEE754 {
20 public:
22  return ((1 <<(k_exponentNbBits-1))-1);
23  }
24  static uint16_t maxExponent() {
25  return ((1<<k_exponentNbBits)-1);
26  }
27  static int size() {
28  assert(k_totalNumberOfBits == 8*sizeof(T));
29  return k_totalNumberOfBits;
30  }
31  static T buildFloat(bool sign, uint16_t exponent, uint64_t mantissa) {
32  static uint64_t oneOnMantissaBits = ((uint64_t)1 << k_mantissaNbBits)-1;
33  uint_float u;
34  u.ui = 0;
35  u.ui |= ((uint64_t)sign << (size()-k_signNbBits));
36  u.ui |= ((uint64_t)exponent << k_mantissaNbBits);
37  u.ui |= ((uint64_t)mantissa >> (size()-k_mantissaNbBits-1) & oneOnMantissaBits);
38  /* So far, we just cast the Integer in float. To round it to the closest
39  * float, we increment the mantissa (and sometimes the exponent if the
40  * mantissa was full of 1) if the next mantissa bit is 1. */
41  if (((uint64_t)mantissa >> (size()-k_mantissaNbBits-2)) & 1) {
42  u.ui += 1;
43  }
44  return u.f;
45  }
46  static int exponent(T f) {
47  uint_float u;
48  u.f = f;
49  uint16_t oneOnExponentsBits = (1 << k_exponentNbBits)-1;
50  int exp = (u.ui >> k_mantissaNbBits) & oneOnExponentsBits;
51  exp -= exponentOffset();
52  return exp;
53  }
54  static int exponentBase10(T f) {
55  static T k_log10base2 = 3.321928094887362347870319429489390175864831393024580612054;
56  if (f == 0.0) {
57  return 0;
58  }
59  T exponentBase2 = exponent(f);
60  /* Compute the exponent in base 10 from exponent in base 2:
61  * f = m1*2^e1
62  * f = m2*10^e2
63  * --> f = m1*10^(e1/log(10,2))
64  * --> f = m1*10^x*10^(e1/log(10,2)-x), with x in [-1,1]
65  * Thus e2 = e1/log(10,2)-x,
66  * with x such as 1 <= m1*10^x < 9 and e1/log(10,2)-x is round.
67  * Knowing that the equation 1 <= m1*10^x < 10 with 1<=m1<2 has its solution
68  * in -0.31 < x < 1, we get:
69  * e2 = [e1/log(10,2)] or e2 = [e1/log(10,2)]-1 depending on m1. */
70  int exponentBase10 = std::round(exponentBase2/k_log10base2);
71  if (std::pow(10.0, exponentBase10) > std::fabs(f)) {
73  }
74  return exponentBase10;
75  }
76 private:
77  union uint_float {
78  uint64_t ui;
79  T f;
80  };
81  constexpr static size_t k_signNbBits = 1;
82  constexpr static size_t k_exponentNbBits = sizeof(T) == sizeof(float) ? 8 : 11;
83  constexpr static size_t k_mantissaNbBits = sizeof(T) == sizeof(float) ? 23 : 52;
84  constexpr static size_t k_totalNumberOfBits = k_signNbBits+k_exponentNbBits+k_mantissaNbBits;
85 };
86 
87 }
88 
89 #endif
#define exp(x)
Definition: math.h:176
#define assert(e)
Definition: assert.h:9
static uint16_t maxExponent()
Definition: ieee754.h:24
#define T(x)
Definition: events.cpp:26
static uint16_t exponentOffset()
Definition: ieee754.h:21
unsigned short uint16_t
Definition: stdint.h:5
static T buildFloat(bool sign, uint16_t exponent, uint64_t mantissa)
Definition: ieee754.h:31
#define fabs(x)
Definition: math.h:178
static int exponent(T f)
Definition: ieee754.h:46
#define round(x)
Definition: math.h:192
unsigned long long uint64_t
Definition: stdint.h:7
#define pow(x, y)
Definition: math.h:190
static int exponentBase10(T f)
Definition: ieee754.h:54
static int size()
Definition: ieee754.h:27