bigfix.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:11k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // bigfix.cpp
  2. //
  3. // Copyright (C) 2007-2008, Chris Laurel <claurel@shatters.net>
  4. //
  5. // 128-bit fixed point (64.64) numbers for high-precision celestial
  6. // coordinates.  When you need millimeter accurate navigation across a scale
  7. // of thousands of light years, double precision floating point numbers
  8. // are inadequate.
  9. //
  10. // This program is free software; you can redistribute it and/or
  11. // modify it under the terms of the GNU General Public License
  12. // as published by the Free Software Foundation; either version 2
  13. // of the License, or (at your option) any later version.
  14. #include <math.h>
  15. #include <stdio.h>
  16. #include "bigfix.h"
  17. static const double POW2_31 = 2147483648.0;
  18. static const double POW2_32 = 4294967296.0;
  19. static const double POW2_64 = POW2_32 * POW2_32;
  20. static const double WORD0_FACTOR = 1.0 / POW2_64;
  21. static const double WORD1_FACTOR = 1.0 / POW2_32;
  22. static const double WORD2_FACTOR = 1.0;
  23. static const double WORD3_FACTOR = POW2_32;
  24. /*** Constructors ***/
  25. /*
  26. // Compute the additive inverse of a 128-bit twos complement value
  27. // represented by two 64-bit values.
  28. inline void negate128(uint64& hi, uint64& lo)
  29. {
  30.     // For a twos-complement number, -n = ~n + 1
  31.     hi = ~hi;
  32.     lo = ~lo;
  33.     lo++;
  34.     if (lo == 0)
  35.         hi++;
  36. }
  37. */
  38. // Create a BigFix initialized to zero
  39. BigFix::BigFix()
  40. {
  41.     hi = 0;
  42.     lo = 0;
  43. }
  44. BigFix::BigFix(uint64 i)
  45. {
  46.     hi = i;
  47.     lo = 0;
  48. }
  49. BigFix::BigFix(double d)
  50. {
  51.     bool isNegative = false;
  52.     // Handle negative values by inverting them before conversion,
  53.     // then inverting the converted value.
  54.     if (d < 0)
  55.     {
  56. isNegative = true;
  57. d = -d;
  58.     }
  59.     
  60.     // Need to break the number into 32-bit chunks because a 64-bit
  61.     // integer has more bits of precision than a double.
  62.     double e = floor(d * (1.0 / WORD3_FACTOR));
  63.     if (e < POW2_31)
  64.     {
  65. uint32 w3 = (uint32) e;
  66. d -= w3 * WORD3_FACTOR;
  67. uint32 w2 = (uint32) (d * (1.0 / WORD2_FACTOR));
  68. d -= w2 * WORD2_FACTOR;
  69. uint32 w1 = (uint32) (d * (1.0 / WORD1_FACTOR));
  70. d -= w1 * WORD1_FACTOR;
  71. uint32 w0 = (uint32) (d * (1.0 / WORD0_FACTOR));
  72.         hi = ((uint64) w3 << 32) | w2;
  73.         lo = ((uint64) w1 << 32) | w0;
  74.     }
  75.     if (isNegative)
  76.         negate128(hi, lo);
  77. }
  78. BigFix::operator double() const
  79. {
  80.     // Handle negative values by inverting them before conversion,
  81.     // then inverting the converted value.
  82.     int sign = 1;
  83.     uint64 l = lo;
  84.     uint64 h = hi;
  85.     if (isNegative())
  86.     {
  87.         negate128(h, l);
  88.         sign = -1;
  89.     }
  90.     // Need to break the number into 32-bit chunks because a 64-bit
  91.     // integer has more bits of precision than a double.
  92.     uint32 w0 = l & 0xffffffff;
  93.     uint32 w1 = l >> 32;
  94.     uint32 w2 = h & 0xffffffff;
  95.     uint32 w3 = h >> 32;
  96.     double d;
  97.     d = (w0 * WORD0_FACTOR +
  98.          w1 * WORD1_FACTOR +
  99.          w2 * WORD2_FACTOR +
  100.          w3 * WORD3_FACTOR) * sign;
  101.     return d;
  102. }
  103. BigFix::operator float() const
  104. {
  105.     return (float) (double) *this;
  106. }
  107. bool operator==(const BigFix& a, const BigFix& b)
  108. {
  109.     return a.hi == b.hi && a.lo == b.lo;
  110. }
  111. bool operator!=(const BigFix& a, const BigFix& b)
  112. {
  113.     return a.hi != b.hi || a.lo != b.lo;
  114. }
  115. bool operator<(const BigFix& a, const BigFix& b)
  116. {
  117.     if (a.isNegative() == b.isNegative())
  118.     {
  119.         if (a.hi == b.hi)
  120.             return a.lo < b.lo;
  121.         else
  122.             return a.hi < b.hi;
  123.     }
  124.     else
  125.     {
  126.         return a.isNegative();
  127.     }
  128. }
  129. bool operator>(const BigFix& a, const BigFix& b)
  130. {
  131.     return b < a;
  132. }
  133. // TODO: probably faster to do this by converting the double to fixed
  134. // point and using the fix*fix multiplication.
  135. BigFix operator*(BigFix f, double d)
  136. {
  137.     // Need to break the number into 32-bit chunks because a 64-bit
  138.     // integer has more bits of precision than a double.
  139.     uint32 w0 = f.lo & 0xffffffff;
  140.     uint32 w1 = f.lo >> 32;
  141.     uint32 w2 = f.hi & 0xffffffff;
  142.     uint32 w3 = f.hi >> 32;
  143.     return BigFix(w0 * d * WORD0_FACTOR) +
  144.            BigFix(w1 * d * WORD1_FACTOR) +
  145.            BigFix(w2 * d * WORD2_FACTOR) +
  146.            BigFix(w3 * d * WORD3_FACTOR);
  147. }
  148. /*! Multiply two BigFix values together. This function does not check for
  149.  *  overflow. This is not a problem in Celestia, where it is used exclusively
  150.  *  in multiplications where one multiplicand has absolute value <= 1.0.
  151.  */
  152. BigFix operator*(const BigFix& a, const BigFix& b)
  153. {
  154.     // Multiply two fixed point values together using partial products.
  155.     uint64 ah = a.hi;
  156.     uint64 al = a.lo;
  157.     if (a.isNegative())
  158.         BigFix::negate128(ah, al);
  159.     uint64 bh = b.hi;
  160.     uint64 bl = b.lo;
  161.     if (b.isNegative())
  162.         BigFix::negate128(bh, bl);
  163.     // Break the values down into 32-bit words so that the partial products
  164.     // will fit into 64-bit words.
  165.     uint64 aw[4];
  166.     aw[0] = al & 0xffffffff;
  167.     aw[1] = al >> 32;
  168.     aw[2] = ah & 0xffffffff;
  169.     aw[3] = ah >> 32;
  170.     uint64 bw[4];
  171.     bw[0] = bl & 0xffffffff;
  172.     bw[1] = bl >> 32;
  173.     bw[2] = bh & 0xffffffff;
  174.     bw[3] = bh >> 32;
  175.     // Set the high and low non-zero words; this will
  176.     // speed up multiplicatoin of integers and values
  177.     // less than one.
  178.     unsigned int hiworda = ah == 0 ? 1 : 3;
  179.     unsigned int loworda = al == 0 ? 2 : 0;
  180.     unsigned int hiwordb = bh == 0 ? 1 : 3;
  181.     unsigned int lowordb = bl == 0 ? 2 : 0;
  182.     uint32 result[8];
  183.     unsigned int i;
  184.     for (i = 0; i < 8; i++)
  185.         result[i] = 0;
  186.     for (i = lowordb; i <= hiwordb; i++)
  187.     {
  188.         uint32 carry = 0;
  189.         unsigned int j;
  190.         for (j = loworda; j <= hiworda; j++)
  191.         {
  192.             uint64 partialProd = aw[j] * bw[i];
  193.             // This sum will never overflow. Let N = 2^32;
  194.             // the max value of the partial product is (N-1)^2.
  195.             // The max values of result[i + j] and carry are
  196.             // N-1. Thus the max value of the sum is
  197.             // (N-1)^2 + 2(N-1) = (N^2 - 2N + 1) + 2(N-1) = N^2-1
  198.             uint64 q = (uint64) result[i + j] + partialProd + (uint64) carry;
  199.             carry = (uint32) (q >> 32);
  200.             result[i + j] = (uint32) (q & 0xffffffff);
  201.         }
  202.         result[i + j] = carry;
  203.     }
  204.     // TODO: check for overflow
  205.     // (as simple as result[0] != 0 || result[1] != 0 || highbit(result[2]))
  206.     BigFix c;
  207.     c.lo = (uint64) result[2] + ((uint64) result[3] << 32);
  208.     c.hi = (uint64) result[4] + ((uint64) result[5] << 32);
  209.     bool resultNegative = a.isNegative() != b.isNegative();
  210.     if (resultNegative)
  211.         return -c;
  212.     else
  213.         return c;
  214. }
  215. int BigFix::sign() const
  216. {
  217.     
  218.     if (hi == 0 && lo == 0)
  219.         return 0;
  220.     else if (hi > INT64_MAX)
  221.         return -1;
  222.     else
  223.         return 1;
  224. }
  225. // For debugging
  226. void BigFix::dump()
  227. {
  228.     printf("%08x %08x %08x %08x",
  229.            (uint32) (hi >> 32),
  230.            (uint32) (hi & 0xffffffff),
  231.            (uint32) (lo >> 32),
  232.            (uint32) (lo & 0xffffffff));
  233. }
  234. #if 0
  235. int main(int argc, char* argv[])
  236. {
  237.     if (argc != 3)
  238.         return 1;
  239.     double a = 0.0;
  240.     if (sscanf(argv[1], "%lf", &a) != 1)
  241.         return 1;
  242.     double b = 0.0;
  243.     if (sscanf(argv[2], "%lf", &b) != 1)
  244.         return 1;
  245.     printf("    sum:n%fn%fn", a + b, (double) (BigFix(a) + BigFix(b)));
  246.     printf("   diff:n%fn%fn", a - b, (double) (BigFix(a) - BigFix(b)));
  247.     printf("product:n%fn%fn", a * b, (double) (BigFix(a) * BigFix(b)));
  248.     printf("     lt: %u %un", a < b, BigFix(a) < BigFix(b));
  249.     return 0;
  250. }
  251. #endif
  252. static unsigned char alphabet[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  253. BigFix::BigFix(const std::string& val)
  254. {
  255.     static char inalphabet[256], decoder[256];
  256.     int i, bits, c, char_count;
  257.     for (i = (sizeof alphabet) - 1; i >= 0 ; i--)
  258.     {
  259.         inalphabet[alphabet[i]] = 1;
  260.         decoder[alphabet[i]] = i;
  261.     }
  262.     uint16 n[8];
  263.     // Code from original BigFix class to convert base64 string into
  264.     // array of 8 16-bit values.
  265.     for (i = 0; i < 8 ; i++)
  266.         n[i] = 0;
  267.     char_count = 0;
  268.     bits = 0;
  269.     i = 0;
  270.     for (int j = 0; j < (int) val.length(); j++)
  271.     {
  272.         c = val[j];
  273.         if (c == '=')
  274.             break;
  275.         if (c > 255 || !inalphabet[c])
  276.             continue;
  277.         bits += decoder[c];
  278.         char_count++;
  279.         if (char_count == 4)
  280.         {
  281.             n[i/2] >>= 8;
  282.             n[i/2] += (bits >> 8) & 0xff00;
  283.             i++;
  284.             n[i/2] >>= 8;
  285.             n[i/2] += bits & 0xff00;
  286.             i++;
  287.             n[i/2] >>= 8;
  288.             n[i/2] += (bits << 8) & 0xff00;
  289.             i++;
  290.             bits = 0;
  291.             char_count = 0;
  292.         }
  293.         else
  294.         {
  295.             bits <<= 6;
  296.         }
  297.     }
  298.     switch (char_count)
  299.     {
  300.     case 2:
  301.         n[i/2] >>= 8;
  302.         n[i/2] += (bits >> 2) & 0xff00;
  303.         i++;
  304.         break;
  305.     case 3:
  306.         n[i/2] >>= 8;
  307.         n[i/2] += (bits >> 8) & 0xff00;
  308.         i++;
  309.         n[i/2] >>= 8;
  310.         n[i/2] += bits & 0xff00;
  311.         i++;
  312.         break;
  313.     }
  314.     if (i & 1)
  315.         n[i/2] >>= 8;
  316.     // Now, convert the 8 16-bit values to a 2 64-bit values
  317.     lo = ((uint64) n[0] |
  318.           ((uint64) n[1] << 16) |
  319.           ((uint64) n[2] << 32) |
  320.           ((uint64) n[3] << 48));
  321.     hi = ((uint64) n[4] |
  322.           ((uint64) n[5] << 16) |
  323.           ((uint64) n[6] << 32) |
  324.           ((uint64) n[7] << 48));
  325. }
  326. std::string BigFix::toString()
  327. {
  328.     // Old BigFix class used 8 16-bit words. The bulk of this function
  329.     // is copied from that class, so first we'll convert from two
  330.     // 64-bit words to 8 16-bit words so that the old code can work
  331.     // as-is.
  332.     unsigned short n[8];
  333.     n[0] = lo & 0xffff;
  334.     n[1] = (lo >> 16) & 0xffff;
  335.     n[2] = (lo >> 32) & 0xffff;
  336.     n[3] = (lo >> 48) & 0xffff;
  337.     n[4] = hi & 0xffff;
  338.     n[5] = (hi >> 16) & 0xffff;
  339.     n[6] = (hi >> 32) & 0xffff;
  340.     n[7] = (hi >> 48) & 0xffff;
  341.     // Conversion using code from the original BigFix class.
  342.     std::string encoded("");
  343.     int bits, c, char_count, started, i, j;
  344.     char_count = 0;
  345.     bits = 0;
  346.     started = 0;
  347.     // Find first significant (non null) byte
  348.     i = 16;
  349.     do {
  350.         i--;
  351.         c = n[i/2];
  352.         if (i & 1) c >>= 8;
  353.         c &= 0xff;
  354.     } while ((c == 0) && (i != 0));
  355.     if (i == 0)
  356.         return encoded;
  357.     // Then we encode starting by the LSB (i+1 bytes to encode)
  358.     j = 0;
  359.     while (j <= i)
  360.     {
  361.         c = n[j/2];
  362.         if ( j & 1 ) c >>= 8;
  363.         c &= 0xff;
  364.         j++;
  365.         bits += c;
  366.         char_count++;
  367.         if (char_count == 3)
  368.         {
  369.             encoded += alphabet[bits >> 18];
  370.             encoded += alphabet[(bits >> 12) & 0x3f];
  371.             encoded += alphabet[(bits >> 6) & 0x3f];
  372.             encoded += alphabet[bits & 0x3f];
  373.             bits = 0;
  374.             char_count = 0;
  375.         }
  376.         else
  377.         {
  378.             bits <<= 8;
  379.         }
  380.     }
  381.     if (char_count != 0)
  382.     {
  383.         bits <<= 16 - (8 * char_count);
  384.         encoded += alphabet[bits >> 18];
  385.         encoded += alphabet[(bits >> 12) & 0x3f];
  386.         if (char_count != 1)
  387.             encoded += alphabet[(bits >> 6) & 0x3f];
  388.     }
  389.     return encoded;
  390. }