Add quadtree back to the Makefile
[ipdf/code.git] / src / tests / represent.cpp
index 52b8c62..b893f97 100644 (file)
@@ -70,13 +70,8 @@ template <size_t EMAX, size_t PREC, size_t BASE = 2> Real BitsToReal(void * data
 
        // Calculate the actual mantissa from the IEEE style encoding of the mantissa (sigh)
        // This is obviously horribly inefficient but I guess that encoding not designed for ... whatever it is I'm doing here
-       Real M = (exponent != 0);
-       for (size_t i = 1; i < PREC; ++i)
-       {
-               if ((mantissa >> PREC-i) & 1)
-                       M += Real(1) / powl(BASE, i);
-       }
-       
+       // NOW WITH LESS TERRIBLE LOOPING THAT GIVES SLIGHTLY WRONG RESULTS! Order a copy today.
+       Real M = (((exponent != 0) << PREC) + (uint64_t)(mantissa))/powl(BASE,PREC);
        
        //Debug("Mantissa: %x = %lf", mantissa, Float(M));
        //Debug("Exponent: %x = %u => %lf", exponent, exponent, Float(Real(exponent + 1) - Real(1LL << (EMAX-1))));
@@ -87,100 +82,156 @@ template <size_t EMAX, size_t PREC, size_t BASE = 2> Real BitsToReal(void * data
        return (sign) ? -x : x;
 }
 
+/**
+ * Modifies fraction to contain the fractional part of x
+ * Returns position of the first '1' bit
+ */
+size_t Fraction(Real x, uint64_t & fraction)
+{
+       x = abs(x) - (uint64_t)(abs(x));
+       fraction = 0LL;
+       size_t offset = 0;
+       for (size_t i = 0; i < 8*sizeof(fraction); ++i)
+       {
+               x *= 2;
+               if (x >= 1.0)
+               {
+                       offset = (offset == 0) ? i : offset;
+                       fraction |= (1LL << (8*sizeof(fraction)-1-i));
+                       x -= 1.0;
+               }
+               if (x <= 0.0)
+                       break;
+       }
+       return fraction;
+}
+
+/**
+ * Copy mantissa and exponent into data
+ */
+template <size_t EMAX, size_t PREC, size_t BASE = 2> void BitsFromRepr(bool sign, uint64_t mantissa, uint64_t exponent, void * data)
+{
+       uint8_t * c = (uint8_t*)(data);
+       size_t i = 0;
+       for (i = 0; i < PREC; ++i)
+       {
+               *c |= ((mantissa >> i) & 1) << (i%8);
+               if ((i+1) % 8 == 0) 
+               {
+                       ++c;
+               }
+       }
+       for (; i < PREC+EMAX; ++i)
+       {
+               *c |= ((exponent >> (i-PREC)) & 1) << (i%8);
+               if ((i+1) % 8 == 0) 
+               {
+                       ++c;
+               }
+       }
+       *c |= (sign << (i%8));
+}
+
+
+
 
 /**
  * Performs the inverse of BitsToReal
  * Hopefully
  * It chooses the normalised representation
  */
-template <size_t EMAX, size_t PREC, size_t BASE = 2> void BitsFromReal(const Real & x, void * data)
+template <size_t EMAX, size_t PREC, size_t BASE = 2> void BitsFromReal(Real x, void * data)
 {
        if (PREC + EMAX > 62)
                Fatal("Can't do more than 62 bits (asked for %d + %d = %d)", PREC, EMAX, PREC+EMAX);
 
        uint64_t integer = (uint64_t)(abs(x));
-       uint64_t fraction = 0L;
-       int64_t exponent = 0L;
-
-       int64_t exp_bias = (1LL << (EMAX-1) - 1);
-
-       Real f = Real(abs(x)) - Real(integer);
-       //f = 0.375; integer = 12;
-       // Get active fractional bits
-       for (size_t i = 0; i <= PREC && f > 0; ++i)
+       uint64_t fraction = 0LL;
+       const size_t max_bits = 8*sizeof(uint64_t);
+       bool sign = (x < 0);
+       x = abs(x) - integer;
+       
+       size_t fraction_leading_zeroes = max_bits;
+       for (size_t i = 0; i < max_bits; ++i)
        {
-               //Debug("%d, %lf", i, Float(f));
-               if (f >= 1)
-               {       
-                       fraction |= (1LL << (PREC-i));
-                       f -= 1.0L;      
-                       //Debug("1");
+               x *= 2;
+               if (x >= 1.0)
+               {
+                       if (fraction_leading_zeroes > i)
+                               fraction_leading_zeroes = i;
+                       x -= 1;
+                       fraction |= (1LL << (max_bits-1-i));
                }
-               //else
-                       //Debug("0");
-               f *= 2.0L;
+               if (x <= 0.0)
+                       break;
+       }
+
+       uint64_t mantissa = 0LL;
+       int64_t biased_exponent = 0LL;
+       
+       size_t integer_leading_zeroes = 0;
+       for (integer_leading_zeroes = 0; integer_leading_zeroes < max_bits; ++integer_leading_zeroes)
+       {
+               if ((integer >> (max_bits-1-integer_leading_zeroes)) & 1LL)
+                       break;
        }
 
-       //Debug("Integer: %lx", integer);
-       int offset = 0; while ((integer >> (offset++) != 0) && (offset < 8*sizeof(integer))); --offset;
-       //Debug("Offset: %d", offset);
-       //Debug("Fraction: %lx", fraction);     
-       exponent += offset-1;
-       uint64_t mantissa = fraction;   
-       if (offset > 0)
+       // 0|011 11|00 0000 0001
+       // 0001
+       // 0000 0000 0100
+       // 10000 0000 0100
+       if (integer != 0)
        {
-               //Debug("Mantissa %.2lx", mantissa);    
-               mantissa = (integer << PREC) | fraction;
-               //Debug("Mantissa %.2lx", mantissa);    
-               mantissa = mantissa >> (offset-1);
-               //Debug("Mantissa %.2lx", mantissa);    
-               //mantissa = mantissa >> (offset-1);
+               mantissa = (integer << (integer_leading_zeroes));
+               mantissa |= (fraction >> (max_bits - integer_leading_zeroes));
        }
        else
        {
-               mantissa = mantissa << 1;
+               mantissa = (fraction << (fraction_leading_zeroes));
        }
-       //Debug("Mantissa %.2lx", mantissa);    
+       //Debug("Mantissa with fraction %.16lx (%.16lx >><>?<< %lu)", mantissa, fraction, fraction_leading_zeroes);
+       mantissa = (mantissa >> (max_bits - PREC - 1));
+       //Debug("Mantissa is %.16lx (%.16lx . %.16lx)", mantissa, fraction, integer);
+       biased_exponent = (integer != 0) ? (max_bits - integer_leading_zeroes) : (-fraction_leading_zeroes);
+       if (biased_exponent < -(1LL << (EMAX-1))+1)
+       {
+               //Debug("Denormalising for glory or death! %li , %li", biased_exponent, -(1LL << (EMAX-1)) - biased_exponent + 1);
+               mantissa = mantissa >> (-(1LL << (EMAX-1)) - biased_exponent + 1);
+               biased_exponent = -(1LL << (EMAX-1))+1;
+       }
+       //Debug("Biased exponent is %li", biased_exponent);
 
-       //Debug("Exponent: %lx %li", exponent, exponent);
-       if (exponent < -exp_bias)
+       // If the unbiased exponent would be non-zero, the IEEE has the leading 1 as implied; remove it and decrease exponent to compensate
+       if (biased_exponent != -(1LL << (EMAX-1))+1)
+       {
+               //Debug("Implied 1 in mantissa %.16lx", mantissa);
+               mantissa &= ~(1LL << (PREC));
+               //Debug("Implied 1 in mantissa %.16lx", mantissa);
+               biased_exponent -= 1;
+       }
+       else
        {
-               mantissa = mantissa >> (-exp_bias - exponent);
-               exponent = -exp_bias;
+               mantissa >>= 1;
        }
-       //Debug("Exponent: %lx %li", exponent, exponent);       
-       exponent = exp_bias + exponent;
-       //Real(exponent + 1) - Real(1LL << (EMAX-1))
-       //Debug("Exponent: %lx %li", exponent, exponent);
+       //Debug("%.16lx", mantissa);
+
+       uint64_t exponent = (uint64_t)(biased_exponent + (1LL << (EMAX-1))-1); // offset the exponent
+
+       // Debug
+       /*
        Real M = (exponent != 0);
        for (size_t i = 1; i < PREC; ++i)
        {
                if ((mantissa >> PREC-i) & 1)
                        M += Real(1) / powl(BASE, i);
        }
-       //Debug("M is %lf", Float(M));
 
-       // Now copy the bits in (fun times)
-       uint8_t * c = (uint8_t*)(data);
-       size_t i = 0;
-       for (i = 0; i < PREC; ++i)
-       {
-               *c |= ((mantissa >> i) & 1) << (i%8);
-               if ((i+1) % 8 == 0) 
-               {
-                       ++c;
-               }
-       }
-       for (; i < PREC+EMAX; ++i)
-       {
-               *c |= ((exponent >> (i-PREC)) & 1) << (i%8);
-               if ((i+1) % 8 == 0) 
-               {
-                       ++c;
-               }
-       }
-       *c |= ((x < 0) << (i%8));
-       
+       Debug("Exponent: %lx %lu -> %li", exponent, exponent, biased_exponent);
+       Debug("Mantissa: %lx -> %f", mantissa, Float(M));
+       Debug("Both: %lx", mantissa | (exponent << (PREC)));
+       */
+       // Now copy the bits in
+       BitsFromRepr<EMAX, PREC, BASE>(sign, mantissa, exponent, data);
        
 }
 
@@ -191,17 +242,21 @@ int main(int argc, char ** argv)
        printf("# Convert custom floats to a Real\n");
        printf("# a\thex(a)\tReal(a)\tdelta(last2)\n");
 
-       typedef pair<uint8_t, Real> Pear;
+       typedef uint8_t Bits;
+       typedef pair<Bits, Real> Pear;
+       const uint8_t E = 3;
+       const uint8_t P = 4;
+       
        list<Pear> space;
-       uint8_t a0 = 0x00;
-       for (uint8_t a = a0; a < a0+0xFF; ++a)
+       Bits a0 = 0x00;
+       for (Bits a = a0; a < 0xFF; ++a)
        {
-               Real x = BitsToReal<2,5>(&a);
-               uint8_t b = 0; BitsFromReal<2,5>(x, &b);
-               Real y = BitsToReal<2,5>(&b);
+               Real x = BitsToReal<E,P>(&a);
+               Bits b = 0; BitsFromReal<E,P>(x, &b);
+               Real y = BitsToReal<E,P>(&b);
                if (y != x)
                {
-                       Warn("%x -> %lf -> %x -> %lf", a, Float(x), b, Float(y));
+                       Fatal("%x -> %.10lf -> %x -> %.10lf", a, Float(x), b, Float(y));
                }
                space.push_back(Pear(a, x));
        }
@@ -216,3 +271,7 @@ int main(int argc, char ** argv)
                prev = i->second;        
        }
 }
+
+//0|011 11|00 0000 0001 
+
+//0|000 01|00 0000 0000

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