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.
18 * From http://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer
20 long CountBits(long n)
22 unsigned int c; // c accumulates the total bits set in v
24 n &= n - 1; // clear the least significant bit set
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)
36 template <unsigned EMAX, unsigned PREC, unsigned BASE = 2> Real BitsToReal(void * data)
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);
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);
48 // Get the exponent and its sign
49 uint64_t exponent = 0L;
50 bool exp_sign = false;
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
60 // Get the mantissa and its sign
61 uint64_t mantissa = 0L;
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);
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);
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;
85 * Performs the inverse of BitsToReal
87 template <int EMAX, int PREC, int BASE = 2> void BitsFromReal(const Real & x, void * data)
93 Fatal("Can't do more than 62 bits (asked for %d + %d = %d)", PREC, EMAX, PREC+EMAX);
101 int main(int argc, char ** argv)
103 printf("# Convert custom floats to a Real\n");
104 printf("# a\thex(a)\tReal(a)\tdelta(last2)\n");
106 typedef pair<uint8_t, Real> Pear;
109 for (uint8_t a = 0x00; a < 0xFF; ++a)
111 Real x = BitsToReal<2,4>(&a);
112 space.push_back(pair<uint8_t, Real>(a, x));
114 space.sort([=](const Pear & a, const Pear & b){return a.second < b.second;});
116 for (list<Pear>::iterator i = space.begin(); i != space.end(); ++i)
118 printf("%u\t%x\t%f", i->first, i->first, Float(i->second));
119 if (i != space.begin())
121 printf("\t%f\n", Float(i->second - prev));