aboutsummaryrefslogtreecommitdiff
path: root/c++-libbu++/src/float.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'c++-libbu++/src/float.cpp')
-rw-r--r--c++-libbu++/src/float.cpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/c++-libbu++/src/float.cpp b/c++-libbu++/src/float.cpp
new file mode 100644
index 0000000..c01d824
--- /dev/null
+++ b/c++-libbu++/src/float.cpp
@@ -0,0 +1,130 @@
1#include "gats/float.h"
2#include "gats/integer.h"
3
4#include <bu/formatter.h>
5#include <math.h>
6
7#include <bu/sio.h>
8using namespace Bu;
9Gats::Float::Float() :
10 fVal( 0.0 )
11{
12}
13
14Gats::Float::Float( double f ) :
15 fVal( f )
16{
17}
18
19Gats::Float::~Float()
20{
21}
22
23Gats::Object *Gats::Float::clone() const
24{
25 return new Gats::Float( fVal );
26}
27
28void Gats::Float::write( Bu::Stream &rOut ) const
29{
30 if( fVal == 0.0 )
31 {
32 if( signbit( fVal ) )
33 rOut.write("FZ", 2 );
34 else
35 rOut.write("Fz", 2 );
36 }
37 else if( !isfinite( fVal ) )
38 {
39 if( isnan( fVal ) )
40 {
41 if( signbit( fVal ) )
42 rOut.write("FN", 2 );
43 else
44 rOut.write("Fn", 2 );
45 }
46 else
47 {
48 if( signbit( fVal ) )
49 rOut.write("FI", 2 );
50 else
51 rOut.write("Fi", 2 );
52 }
53 }
54 else
55 {
56 rOut.write("f", 1 );
57 double d = fVal;
58 bool bNeg = false;
59 int64_t iScale=0;
60 if( signbit( d ) )
61 {
62 bNeg = true;
63 d = -d;
64 }
65
66 iScale = log( d ) / 0x1.62e42fefa39efp+2; // log( 256.0 )
67 if( iScale < 0 ) iScale--;
68 d /= pow( 256.0, iScale );
69
70 Bu::String s;
71 s += (uint8_t)(d);
72 d -= (int)d;
73 for( int j = 0; j < 150 && d; j++ )
74 {
75 d = d*256.0;
76 s += (uint8_t)d;
77 d -= (int)d;
78 }
79 Gats::Integer::writePackedInt( rOut, bNeg?-s.getSize():s.getSize() );
80 rOut.write( s.getStr(), s.getSize() );
81 Gats::Integer::writePackedInt( rOut, iScale );
82 }
83}
84
85void Gats::Float::read( Bu::Stream &rIn, char cType )
86{
87 if( cType == 'F' )
88 {
89 char buf;
90 rIn.read( &buf, 1 );
91 switch( buf )
92 {
93 case 'N': fVal = -NAN; break;
94 case 'n': fVal = NAN; break;
95 case 'I': fVal = -INFINITY; break;
96 case 'i': fVal = INFINITY; break;
97 case 'Z': fVal = -0.0; break;
98 case 'z': fVal = 0.0; break;
99 }
100 }
101 else if( cType == 'f' )
102 {
103 int64_t iStr;
104 Gats::Integer::readPackedInt( rIn, iStr );
105 bool bNeg = false;
106 if( iStr < 0 )
107 {
108 bNeg = true;
109 iStr = -iStr;
110 }
111 Bu::String s( iStr );
112 rIn.read( s.getStr(), iStr );
113 fVal = 0.0;
114 for( int j = iStr-1; j > 0; j-- )
115 {
116 fVal = (fVal+(uint8_t)s[j])*0x1p-8;
117 }
118 fVal += (uint8_t)s[0];
119 int64_t iScale;
120 Gats::Integer::readPackedInt( rIn, iScale );
121 fVal *= pow( 256.0, iScale );
122 if( bNeg ) fVal = -fVal;
123 }
124}
125
126Bu::Formatter &operator<<( Bu::Formatter &f, const Gats::Float &flt )
127{
128 return f << "(float) " << flt.getValue();
129}
130