Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

bigfix.cpp

Go to the documentation of this file.
00001 // bigfix.cpp
00002 //
00003 // Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 #include <math.h>
00011 #include <stdio.h>
00012 #include "bigfix.h"
00013 
00014 
00015 /*** Constructors ***/
00016 
00017 // Create a BigFix initialized to zero
00018 BigFix::BigFix()
00019 {
00020     for (int i = 0; i < N_WORDS; i++)
00021         n[i] = 0;
00022 }
00023 
00024 
00025 BigFix::BigFix(int i)
00026 {
00027     n[N_WORDS / 2] = (unsigned short) (i & 0xffff);
00028     n[N_WORDS / 2 + 1] = (unsigned short) ((i >> 16) & 0xffff);
00029 
00030     // Sign extend if negative
00031     if (i < 0)
00032     {
00033         for (int j = N_WORDS / 2 + 2; j < N_WORDS; j++)
00034             n[j] = 0xffff;
00035     }
00036 }
00037 
00038 
00039 BigFix::BigFix(double d)
00040 {
00041     int sign = 1;
00042 
00043     if (d < 0)
00044     {
00045         sign = -1;
00046         d = -d;
00047     }
00048 
00049     double e = floor(d / (65536.0 * 65536.0 * 65536.0));
00050 
00051     // Check for overflow
00052     if (e < 32767)
00053     {
00054         n[7] = (unsigned short) e;
00055         d -= n[7] * 65536.0 * 65536.0 * 65536.0;
00056         n[6] = (unsigned short) (d / (65536.0 * 65536.0));
00057         d -= n[6] * 65536.0 * 65536.0;
00058         n[5] = (unsigned short) (d / 65536.0);
00059         d -= n[5] * 65536.0;
00060         n[4] = (unsigned short) d;
00061         d -= n[4];
00062         n[3] = (unsigned short) (d * 65536.0);
00063         d -= n[3] / 65536.0;
00064         n[2] = (unsigned short) (d * 65536.0 * 65536.0);
00065         d -= n[2] / (65536.0 * 65536.0);
00066         n[1] = (unsigned short) (d * 65536.0 * 65536.0 * 65536.0);
00067         d -= n[1] / (65536.0 * 65536.0 * 65536.0);
00068         n[0] = (unsigned short) (d * 65536.0 * 65536.0 * 65536.0 * 65536.0);
00069     }
00070 
00071     if (sign < 0)
00072         *this = -*this;
00073 }
00074 
00075 
00076 BigFix::operator double() const
00077 {
00078     double d = 0;
00079     double e = 1.0 / (65536.0 * 65536.0 * 65536.0 * 65536.0);
00080     BigFix f;
00081 
00082     if ((n[N_WORDS - 1] & 0x8000) == 0)
00083         f = *this;
00084     else
00085         f = -*this;
00086 
00087     for (int i = 0; i < N_WORDS; i++)
00088     {
00089         d += e * f.n[i];
00090         e *= 65536;
00091     }
00092 
00093     return ((n[N_WORDS - 1] & 0x8000) == 0) ? d : -d;
00094 }
00095 
00096 
00097 BigFix::operator float() const
00098 {
00099     return (float) (double) *this;
00100 }
00101 
00102 
00103 BigFix BigFix::operator-() const
00104 {
00105     int i;
00106     BigFix f;
00107 
00108     for (i = 0; i < N_WORDS; i++)
00109         f.n[i] = ~n[i];
00110 
00111     unsigned int carry = 1;
00112     i = 0;
00113     while (carry != 0 && i < N_WORDS)
00114     {
00115         unsigned int m = f.n[i] + carry;
00116         f.n[i] = (unsigned short) (m & 0xffff);
00117         carry = m >> 16;
00118         i++;
00119     }
00120 
00121     return f;
00122 }
00123 
00124 
00125 BigFix operator+(BigFix a, BigFix b)
00126 {
00127     unsigned int carry = 0;
00128     BigFix c;
00129 
00130     for (int i = 0; i < N_WORDS; i++)
00131     {
00132         unsigned int m = a.n[i] + b.n[i] + carry;
00133         c.n[i] = (unsigned short) (m & 0xffff);
00134         carry = m >> 16;
00135     }
00136 
00137     return c;
00138 }
00139 
00140 
00141 BigFix operator-(BigFix a, BigFix b)
00142 {
00143     return a + -b;
00144 }
00145 
00146 
00147 BigFix operator*(BigFix a, BigFix b)
00148 {
00149     return BigFix();
00150 }
00151 
00152 
00153 bool operator==(BigFix a, BigFix b)
00154 {
00155     for (int i = 0; i < N_WORDS; i++)
00156         if (a.n[i] != b.n[i])
00157             return false;
00158     return true;
00159 }
00160 
00161 
00162 bool operator!=(BigFix a, BigFix b)
00163 {
00164     return !(a == b);
00165 }
00166 
00167 
00168 int BigFix::sign()
00169 {
00170     if ((n[N_WORDS - 1] & 0x8000) != 0)
00171         return -1;
00172 
00173     for (int i = 0; i < N_WORDS - 1; i++)
00174         if (n[N_WORDS] != 0)
00175             return 1;
00176 
00177     return 0;
00178 }
00179 
00180 
00181 // For debugging
00182 void BigFix::dump()
00183 {
00184     for (int i = 7; i >= 0; i--)
00185         printf("%04x ", n[i]);
00186     printf("\n");
00187 }
00188 
00189 
00190 
00191 static unsigned char alphabet[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00192 
00193 BigFix::BigFix(const std::string& val)
00194 {
00195     static char inalphabet[256], decoder[256];
00196     int i, bits, c, char_count, errors = 0;
00197 
00198     for (i = (sizeof alphabet) - 1; i >= 0 ; i--)
00199     {
00200         inalphabet[alphabet[i]] = 1;
00201         decoder[alphabet[i]] = i;
00202     }
00203 
00204     for (i = 0; i < 8 ; i++)
00205         n[i] = 0;
00206 
00207     char_count = 0;
00208     bits = 0;
00209 
00210     i = 0;
00211 
00212     for (int j = 0; j < (int)val.length(); j++)
00213     {
00214         c = val[j];
00215         if (c == '=')
00216             break;
00217         if (c > 255 || !inalphabet[c])
00218             continue;
00219         bits += decoder[c];
00220         char_count++;
00221         if (char_count == 4)
00222         {
00223             n[i/2] >>= 8;
00224             n[i/2] += (bits >> 8) & 0xff00;
00225             i++;
00226             n[i/2] >>= 8;
00227             n[i/2] += bits & 0xff00;
00228             i++;
00229             n[i/2] >>= 8;
00230             n[i/2] += (bits << 8) & 0xff00;
00231             i++;
00232             bits = 0;
00233             char_count = 0;
00234         }
00235         else
00236         {
00237             bits <<= 6;
00238         }
00239     }
00240 
00241     switch (char_count)
00242     {
00243     case 2:
00244         n[i/2] >>= 8;
00245         n[i/2] += (bits >> 2) & 0xff00;
00246         i++;
00247         break;
00248     case 3:
00249         n[i/2] >>= 8;
00250         n[i/2] += (bits >> 8) & 0xff00;
00251         i++;
00252         n[i/2] >>= 8;
00253         n[i/2] += bits & 0xff00;
00254         i++;
00255         break;
00256     }
00257 
00258     if (i & 1)
00259         n[i/2] >>= 8;
00260 }
00261 
00262 
00263 std::string BigFix::toString()
00264 {
00265 
00266     std::string encoded("");
00267     int bits, c, char_count, started, i, j;
00268 
00269     char_count = 0;
00270     bits = 0;
00271     started = 0;
00272 
00273     // Find first significant (non null) byte
00274     i = 16;
00275     do {
00276         i--;
00277         c = n[i/2];
00278         if (i & 1) c >>= 8;
00279         c &= 0xff;
00280     } while ((c == 0) && (i != 0));
00281 
00282     if (i == 0)
00283         return encoded;
00284 
00285     // Then we encode starting by the LSB (i+1 bytes to encode)
00286     j = 0;
00287     while (j <= i)
00288     {
00289         c = n[j/2];
00290         if ( j & 1 ) c >>= 8;
00291         c &= 0xff;
00292         j++;
00293         bits += c;
00294         char_count++;
00295         if (char_count == 3)
00296         {
00297             encoded += alphabet[bits >> 18];
00298             encoded += alphabet[(bits >> 12) & 0x3f];
00299             encoded += alphabet[(bits >> 6) & 0x3f];
00300             encoded += alphabet[bits & 0x3f];
00301             bits = 0;
00302             char_count = 0;
00303         }
00304         else
00305         {
00306             bits <<= 8;
00307         }
00308     }
00309 
00310     if (char_count != 0)
00311     {
00312         bits <<= 16 - (8 * char_count);
00313         encoded += alphabet[bits >> 18];
00314         encoded += alphabet[(bits >> 12) & 0x3f];
00315         if (char_count != 1)
00316             encoded += alphabet[(bits >> 6) & 0x3f];
00317     }
00318 
00319     return encoded;
00320 }
00321 
00322 

Generated on Sat Jan 14 22:30:32 2006 for Celestia by  doxygen 1.4.1