Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cFloatDeco.h
Go to the documentation of this file.
1 //
5 //
6 #ifndef _INC_cFloatDeco_H
7 #define _INC_cFloatDeco_H
8 #ifndef NO_PRAGMA_ONCE
9 #pragma once
10 #endif
11 
12 #include "cFloat.h"
13 #include "StrConst.h"
14 #include "cDebugAssert.h" // ASSERT
15 
16 namespace Gray
17 {
18  // _umul128 TODO MulDiv ?
19 
21  {
25 
26  public:
27  static const double k_PowersOf10[9];
28 
29  static const UINT32 k_Exp10[10];
30 
31  static const UINT64 k_MANT_MASK_X = CUINT64(00100000, 00000000); // Extra hidden bit. k_MANT_MASK+1
32 
33  UINT64 m_uMant;
34  int m_iExp2;
35 
36  public:
37  cFloatDeco() noexcept
38  : m_uMant(0), m_iExp2(0)
39  {}
40 
41  cFloatDeco(UINT64 uMan, int iExp2) noexcept
42  : m_uMant(uMan), m_iExp2(iExp2)
43  {}
44 
45  cFloatDeco(double d) noexcept
46  {
48  static const int k_DpExponentBias = 0x3FF + cFloat64::k_MANT_BITS;
49 
50  cFloat64 u(d);
51 
52  const int iExpBiased = (u.m_v.u_qw & cFloat64::k_EXP_MASK) >> cFloat64::k_MANT_BITS;
53  const UINT64 nMantSig = u.get_Mantissa();
54  if (iExpBiased != 0)
55  {
56  m_uMant = nMantSig + k_MANT_MASK_X;
57  m_iExp2 = iExpBiased - k_DpExponentBias;
58  }
59  else
60  {
61  m_uMant = nMantSig;
62  m_iExp2 = 1 - k_DpExponentBias;
63  }
64  }
65 
66  cFloatDeco operator-(const cFloatDeco& rhs) const
67  {
70  ASSERT(m_iExp2 == rhs.m_iExp2);
71  ASSERT(m_uMant >= rhs.m_uMant);
72  return cFloatDeco(m_uMant - rhs.m_uMant, m_iExp2);
73  }
74 
75  cFloatDeco operator*(const cFloatDeco& rhs) const
76  {
78 
79  UINT64 h;
80 #if defined(_MSC_VER) && defined(_M_AMD64)
81  UINT64 l = _umul128(m_uMant, rhs.m_uMant, &h);
82  if (l & (UINT64(1) << 63)) // rounding
83  h++;
84 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
85  unsigned __int128 p = static_cast<unsigned __int128>(m_uMant) * static_cast<unsigned __int128>(rhs.m_uMant);
86  h = p >> 64;
87  UINT64 l = static_cast<UINT64>(p);
88  if (l & (UINT64(1) << 63)) // rounding
89  h++;
90 #else
91  const UINT64 M32 = 0xFFFFFFFF;
92  const UINT64 a = m_uMant >> 32;
93  const UINT64 b = m_uMant & M32;
94  const UINT64 c = rhs.m_uMant >> 32;
95  const UINT64 d = rhs.m_uMant & M32;
96  const UINT64 ac = a * c;
97  const UINT64 bc = b * c;
98  const UINT64 ad = a * d;
99  const UINT64 bd = b * d;
100  UINT64 tmp = (bd >> 32) + (ad & M32) + (bc & M32);
101  tmp += 1U << 31;
102  h = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
103 #endif
104  return cFloatDeco(h, m_iExp2 + rhs.m_iExp2 + 64);
105  }
106 
108  {
111  ASSERT(m_uMant != 0);
112  BIT_ENUM_t nBit = 64 - cBits::Highest1Bit(m_uMant);
113  return cFloatDeco(m_uMant << nBit, m_iExp2 - nBit);
114  }
115 
116  void NormalizedBoundaries(cFloatDeco* minus, cFloatDeco* plus) const
117  {
118  cFloatDeco pl = cFloatDeco((m_uMant << 1) + 1, m_iExp2 - 1).Normalize();
119  cFloatDeco mi = (m_uMant == k_MANT_MASK_X) ? cFloatDeco((m_uMant << 2) - 1, m_iExp2 - 2) : cFloatDeco((m_uMant << 1) - 1, m_iExp2 - 1);
120  mi.m_uMant <<= mi.m_iExp2 - pl.m_iExp2;
121  mi.m_iExp2 = pl.m_iExp2;
122  *plus = pl;
123  *minus = mi;
124  }
125 
126 #if 0
127  double get_Double() const
128  {
130  cFloat64 f(sdfsdf);
131  return f.m_v.u_d;
132  }
133 #endif
134 
135  static inline unsigned GetCountDecimalDigit32(UINT32 n) noexcept
136  {
140  if (n < 10) return 1;
141  if (n < 100) return 2;
142  if (n < 1000) return 3;
143  if (n < 10000) return 4;
144  if (n < 100000) return 5;
145  if (n < 1000000) return 6;
146  if (n < 10000000) return 7;
147  if (n < 100000000) return 8;
148  if (n < 1000000000) return 9;
149  return 10;
150  }
151 
152  static cFloatDeco GRAYCALL GetCachedPower(int nExp2, OUT int* pnExp10);
153  static double GRAYCALL toDouble(UINT32 frac1, UINT32 frac2, int nExp10);
154 
155  static void GRAYCALL GrisuRound(char* pszOut, StrLen_t len, UINT64 delta, UINT64 rest, UINT64 ten_kappa, UINT64 wp_w);
156  static StrLen_t GRAYCALL Grisu2(double dVal, char* pszOut, OUT int* pnExp10);
157 
158  static StrLen_t GRAYCALL MantRound(char* pszOut, StrLen_t nMantLength);
159  static StrLen_t GRAYCALL MantAdjust(char* pszOut, StrLen_t nMantLength, StrLen_t nMantLengthNew);
160 
161  static StrLen_t GRAYCALL FormatE(char* pszOut, StrLen_t nMantLength, int nExp10, char chE);
162  static StrLen_t GRAYCALL FormatF(char* pszOut, StrLen_t nMantLength, int nExp10, int iDecPlacesWanted);
163  };
164 }
165 
166 #endif
#define GRAYCORE_LINK
Definition: GrayCore.h:47
#define GRAYCALL
declare calling convention for static functions so everyone knows the arg passing scheme....
Definition: GrayCore.h:36
#define CUINT64(h, l)
Definition: cBits.h:39
#define ASSERT(exp)
Definition: cDebugAssert.h:87
Definition: cFloat.h:83
cUnion64 m_v
holds the float64.
Definition: cFloat.h:89
static const UINT64 k_EXP_MASK
11 bits = signed exponent (base 2)
Definition: cFloat.h:93
UINT64 get_Mantissa() const noexcept
Definition: cFloat.h:140
static const UINT32 k_MANT_BITS
52 bits = fractional mantissa
Definition: cFloat.h:96
Definition: cFloatDeco.h:21
cFloatDeco(double d) noexcept
Definition: cFloatDeco.h:45
cFloatDeco operator-(const cFloatDeco &rhs) const
Definition: cFloatDeco.h:66
int m_iExp2
Hold base 2 Biased Exponent.
Definition: cFloatDeco.h:34
cFloatDeco(UINT64 uMan, int iExp2) noexcept
Definition: cFloatDeco.h:41
static unsigned GetCountDecimalDigit32(UINT32 n) noexcept
Definition: cFloatDeco.h:135
cFloatDeco operator*(const cFloatDeco &rhs) const
Definition: cFloatDeco.h:75
cFloatDeco() noexcept
Definition: cFloatDeco.h:37
UINT64 m_uMant
Hold Mantissa.
Definition: cFloatDeco.h:33
cFloatDeco Normalize() const
Definition: cFloatDeco.h:107
void NormalizedBoundaries(cFloatDeco *minus, cFloatDeco *plus) const
Definition: cFloatDeco.h:116
< The main namespace for all Core functions.
Definition: GrayCore.cpp:14
int StrLen_t
the length of a string in chars (bytes for UTF8, wchar_t for UNICODE). or offset in characters....
Definition: StrConst.h:32
unsigned int BIT_ENUM_t
Enumerate number of bits or address a single bit in some array of bits.
Definition: cBits.h:20
static BIT_ENUM_t Highest1Bit(TYPE nMask) noexcept
Definition: cBits.h:108
UINT64 u_qw
64 bits = QuadPart = ULONGLONG.
Definition: cTypes.h:122