Tester for exploring the mapping of a float to a real
[ipdf/code.git] / src / tests / represent.cpp
1 #include "main.h"
2 #include "real.h"
3 #include <cmath>
4 #include <cassert>
5 #include <list>
6
7 using namespace std;
8 using namespace IPDF;
9
10 /**
11  * This "tester" lets us construct Reals out of Floating Points with arbitrary sizes (but must be less than 64 bits currently)
12  * Eventually it will also go the other way
13  * This is originally for conceptual understanding but will ultimately become useful later on.
14  */
15
16
17 /**
18  * From http://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer
19  */
20 long CountBits(long n) 
21 {     
22         unsigned int c; // c accumulates the total bits set in v
23         for (c = 0; n; c++)
24                 n &= n - 1; // clear the least significant bit set
25         return c;
26 }
27
28 /**
29  * Converts data represented as an (se, e, m, sm) floating point number to a Real.
30  * se = sign of exponent (1 bit)
31  * e = exponent (EMAX bits)
32  * m = mantissa (PREC bits)
33  * sm = sign of mantissa (1 bit)
34  * Total 1+EMAX+PREC+1 must not exceed 64 (at least, for the moment)
35  */
36 template <unsigned EMAX, unsigned PREC, unsigned BASE = 2> Real BitsToReal(void * data)
37 {
38         if (PREC + EMAX > 62) // we need 1 bit for the sign of the exponent, 1 bit for the sign
39                 Fatal("Can't do more than 62 bits (asked for %d + %d = %d)", PREC, EMAX, PREC+EMAX);
40         
41         // memcpy needs a whole number of bytes
42         // This means we need to do tricky bit shifting to get rid of parts of the exp/mantissa that overlap
43         size_t ebytes = ceil(double(EMAX+1.0) / 8.0);   
44         size_t mbytes = ceil(double(PREC+1.0)/8.0);
45         size_t moffset = floor(double(EMAX+1.0) / 8.0); // offset to start of mantissa (nearest byte)
46         //Debug("ebytes %d, mbytes %d, moffset %d", ebytes, mbytes, moffset);
47
48         // Get the exponent and its sign
49         uint64_t exponent = 0L;
50         bool exp_sign = false;
51
52         memcpy(&exponent, data, ebytes); // Copy exponent
53         //Debug("exponent + garbage: %x", exponent);
54         exp_sign = (1L << (8*ebytes-1)) & exponent;
55         exponent &= ~(1L << (8*ebytes-1)); // mask out the sign
56         //Debug("exponent - masked sign: %x", exponent);
57         exponent = exponent >> (PREC+1); // shift out the extra bits (part of mantissa)
58         assert(CountBits(exponent) <= EMAX); //TODO: Remove once sure it actually works //TODO: Need more reliable sanity checks probably
59
60         // Get the mantissa and its sign
61         uint64_t mantissa = 0L;
62         bool sign = false;
63
64         memcpy(&mantissa, ((uint8_t*)(data) + moffset), mbytes); // copy data
65         //Debug("mantissa + garbage: %x", mantissa);
66         sign = mantissa & (1L); // get sign
67         mantissa = mantissa >> 1; // discard sign
68         mantissa = (mantissa << (8*sizeof(mantissa) - PREC)) >> (8*sizeof(mantissa) - PREC);
69         assert(CountBits(mantissa) <= PREC);
70         
71         /*
72         Debug("EMAX %u, PREC %u, BASE %u", EMAX, PREC, BASE);
73         Debug("EXP: %x", exponent);
74         Debug("MANTISSA: %x", mantissa);
75         Debug("EXP_SIGN: %x", (uint8_t)exp_sign);
76         Debug("MANTISSA_SIGN: %x", (uint8_t)sign);
77         */
78
79         Real Q = (exp_sign) ? pow(Real(BASE), -Real(exponent)) : pow(Real(BASE), Real(exponent));
80         Real x = Real(mantissa) * Q;
81         return (sign) ? -x : x;
82 }
83
84 /**
85  * Performs the inverse of BitsToReal
86  */
87 template <int EMAX, int PREC, int BASE = 2> void BitsFromReal(const Real & x, void * data)
88 {
89         bool sign;
90         uint64_t mantissa;
91         uint64_t exponent;
92         if (PREC + EMAX > 62)
93                 Fatal("Can't do more than 62 bits (asked for %d + %d = %d)", PREC, EMAX, PREC+EMAX);
94         
95         //TODO: Implement
96         
97 }
98
99
100
101 int main(int argc, char ** argv)
102 {
103         printf("# Convert custom floats to a Real\n");
104         printf("# a\thex(a)\tReal(a)\tdelta(last2)\n");
105
106         typedef pair<uint8_t, Real> Pear;
107         list<Pear> space;
108
109         for (uint8_t a = 0x00; a < 0xFF; ++a)
110         {
111                 Real x = BitsToReal<2,4>(&a);
112                 space.push_back(pair<uint8_t, Real>(a, x));
113         }
114         space.sort([=](const Pear & a, const Pear & b){return a.second < b.second;});
115         Real prev;
116         for (list<Pear>::iterator i = space.begin(); i != space.end(); ++i)
117         {
118                 printf("%u\t%x\t%f", i->first, i->first, Float(i->second));
119                 if (i != space.begin())
120                 {
121                         printf("\t%f\n", Float(i->second - prev));
122                 }       
123                 prev = i->second;        
124         }
125 }

UCC git Repository :: git.ucc.asn.au