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