summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2011-03-08 08:06:44 +0000
committerMike Buland <eichlan@xagasoft.com>2011-03-08 08:06:44 +0000
commit8f53239f4ceccfd747283c8f0d7968fa40731faf (patch)
tree4a3fd32ee9f715cc224720b387aa5dd1512f3802
parentb8eaef64b48170467ee38b8399a951b967f468e6 (diff)
downloadlibbu++-8f53239f4ceccfd747283c8f0d7968fa40731faf.tar.gz
libbu++-8f53239f4ceccfd747283c8f0d7968fa40731faf.tar.bz2
libbu++-8f53239f4ceccfd747283c8f0d7968fa40731faf.tar.xz
libbu++-8f53239f4ceccfd747283c8f0d7968fa40731faf.zip
sigh, another program that's not realy a tool, it was the easiest place for it
I should add a new class of program to libbu++ or clear out most of my old tests or something. Anyway, almost fully C99 compliant float to normalized hex string and back functions in pure math. Really slick, really portable. they don't handle +/-NaN, +/-Inf, or the special alternate format for subnormal numbers, try entering a 0.0...01 where I cut out about 200 zeros, you'll see what I mean.
-rw-r--r--src/tools/float.cpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/tools/float.cpp b/src/tools/float.cpp
new file mode 100644
index 0000000..2c241f3
--- /dev/null
+++ b/src/tools/float.cpp
@@ -0,0 +1,130 @@
1#include <bu/sio.h>
2#include <bu/string.h>
3#include <stdlib.h>
4#include <math.h>
5
6using namespace Bu;
7
8Bu::String ftos( double dNum )
9{
10 if( dNum == 1.0 )
11 return "0x1p+0";
12 if( dNum == 0.0 )
13 return signbit(dNum)?"-0x0p+0":"0x0p+0";
14 if( dNum == -1.0 )
15 return "-0x1p+0";
16 Bu::String s("0x1.");
17 if( signbit(dNum) )
18 {
19 s.prepend("-");
20 dNum = -dNum;
21 }
22/*
23 for( int j = 0; j < 150 && dNum; j++ )
24 {
25 dNum = dNum*2;
26 sio << dNum << " -- " << (int)dNum << sio.nl;
27 if( (int)dNum == 0 )
28 s += '0';
29 else
30 {
31 s += '1';
32 dNum -= 1.0;
33 }
34 }
35 return s;
36 */
37 int iPower = 0;
38 if( dNum < 1.0 )
39 {
40 while( dNum < 1.0 )
41 {
42 dNum *= 2.0;
43 iPower--;
44 }
45 }
46 else if( dNum >= 2.0 )
47 {
48 while( dNum >= 2.0 )
49 {
50 dNum *= 0.5;
51 iPower++;
52 }
53 }
54 dNum -= (int)dNum;
55 for( int j = 0; j < 150 && dNum; j++ )
56 {
57 dNum = dNum*16.0;
58 s += "0123456789abcdef"[(int)dNum];
59 dNum -= (int)dNum;
60 }
61 s.formatAppend("p%+d", iPower );
62 return s;
63}
64
65double stof( const Bu::String &s )
66{
67 if( s == "0x1p+0" )
68 return 1.0;
69 if( s == "-0x1p+0" )
70 return -1.0;
71 if( s == "0x0p+0" )
72 return 0.0;
73 if( s == "-0x0p+0" )
74 return 0.0;
75 double dNum = 0.0;
76 int iPPos = s.getSize()-1;
77 for(; s[iPPos] != 'p'; iPPos--) { }
78 for( int i = iPPos-1; s[i] != '.'; i-- )
79 {
80 if( s[i]>='0' && s[i]<='9' )
81 {
82 dNum += s[i]-'0';
83 }
84 else if( s[i]>='a' && s[i]<='f' )
85 {
86 dNum += s[i]-'a'+10.0;
87 }
88 dNum *= 0.0625;
89 }
90
91 dNum += 1.0;
92
93 int iTop = strtol( s.getStr()+iPPos+1, NULL, 10 );
94 if( iTop < 0 )
95 {
96 for( int j = 0; j > iTop; j-- )
97 {
98 dNum *= 0.5;
99 }
100 }
101 else
102 {
103 for( int j = 0; j < iTop; j++ )
104 {
105 dNum *= 2.0;
106 }
107 }
108
109 if( s[0] == '-' )
110 return -dNum;
111 return dNum;
112}
113
114int main( int argc, char *argv[] )
115{
116 for( int j = 1; j < argc; j++ )
117 {
118 double dNum = strtod( argv[j], NULL );
119
120 String s = ftos( dNum );
121 sio << "in: " << dNum << sio.nl;
122 sio << "mine: " << s << sio.nl;
123 printf("printf: %a\n", dNum );
124 sio << "out: " << stof( s ) << sio.nl;
125 sio << "match: " << (stof( s ) == dNum) << sio.nl << sio.nl;
126 }
127
128 return 0;
129}
130