Math128: 128-bit Integer Math Library
[Query Object Framework]


Detailed Description

Quick-n-dirty 128-bit integer math lib. Things seem to mostly work, and have been tested, but not comprehensively tested.


Data Structures

struct  qofint128

Functions

gboolean equal128 (qofint128 a, qofint128 b)
int cmp128 (qofint128 a, qofint128 b)
qofint128 shift128 (qofint128 x)
qofint128 shiftleft128 (qofint128 x)
qofint128 inc128 (qofint128 a)
qofint128 add128 (qofint128 a, qofint128 b)
qofint128 mult128 (gint64 a, gint64 b)
qofint128 div128 (qofint128 n, gint64 d)
gint64 rem128 (qofint128 n, gint64 d)
guint64 gcf64 (guint64 num, guint64 denom)
qofint128 lcm128 (guint64 a, guint64 b)


Function Documentation

qofint128 add128 ( qofint128  a,
qofint128  b 
) [inline]

Add a pair of 128-bit numbers, returning a 128-bit number

Definition at line 294 of file qofmath128.c.

00295 {
00296   qofint128 sum;
00297   if (a.isneg == b.isneg)
00298   {
00299     sum.isneg = a.isneg;
00300     sum.hi = a.hi + b.hi;
00301     sum.lo = a.lo + b.lo;
00302     if ((sum.lo < a.lo) || (sum.lo < b.lo))
00303     {
00304      sum.hi ++;
00305     }
00306     sum.isbig = sum.hi || (sum.lo >> 63);
00307     return sum;
00308   }
00309   if ((b.hi > a.hi) ||
00310      ((b.hi == a.hi) && (b.lo > a.lo)))
00311   {
00312     qofint128 tmp = a;
00313     a = b;
00314     b = tmp;
00315   }
00316 
00317   sum.isneg = a.isneg;
00318   sum.hi = a.hi - b.hi;
00319   sum.lo = a.lo - b.lo;
00320 
00321   if (sum.lo > a.lo)
00322   {
00323     sum.hi --;
00324   }
00325 
00326   sum.isbig = sum.hi || (sum.lo >> 63);
00327   return sum;
00328 }

int cmp128 ( qofint128  a,
qofint128  b 
) [inline]

Return returns 1 if a>b, -1 if b>a, 0 if a == b

Definition at line 242 of file qofmath128.c.

00243 {
00244    if ((0 == a.isneg) && b.isneg) return 1;
00245    if (a.isneg && (0 == b.isneg)) return -1;
00246    if (0 == a.isneg)
00247    {
00248      if (a.hi > b.hi) return 1;
00249      if (a.hi < b.hi) return -1;
00250      if (a.lo > b.lo) return 1;
00251      if (a.lo < b.lo) return -1;
00252      return 0;
00253    }
00254 
00255    if (a.hi > b.hi) return -1;
00256    if (a.hi < b.hi) return 1;
00257    if (a.lo > b.lo) return -1;
00258    if (a.lo < b.lo) return 1;
00259    return 0;
00260 }

qofint128 div128 ( qofint128  n,
gint64  d 
) [inline]

Divide a signed 128-bit number by a signed 64-bit, returning a signed 128-bit number.

Definition at line 180 of file qofmath128.c.

00181 {
00182   qofint128 quotient;
00183   int i;
00184   guint64 remainder = 0;
00185 
00186   quotient = n;
00187   if (0 > d)
00188   {
00189     d = -d;
00190     quotient.isneg = !quotient.isneg;
00191   }
00192 
00193   /* Use grade-school long division algorithm */
00194   for (i=0; i<128; i++)
00195   {
00196     guint64 sbit = HIBIT & quotient.hi;
00197     remainder <<= 1;
00198     if (sbit) remainder |= 1;
00199     quotient = shiftleft128 (quotient);
00200     if (remainder >= d)
00201     {
00202        remainder -= d;
00203        quotient.lo |= 1;
00204     }
00205   }
00206 
00207   /* compute the carry situation */
00208   quotient.isbig = (quotient.hi || (quotient.lo >> 63));
00209 
00210   return quotient;
00211 }

gboolean equal128 ( qofint128  a,
qofint128  b 
) [inline]

Return true of two numbers are equal

Definition at line 232 of file qofmath128.c.

00233 {
00234         if (a.lo != b.lo) return 0;
00235         if (a.hi != b.hi) return 0;
00236         if (a.isneg != b.isneg) return 0;
00237         return 1;
00238 }

guint64 gcf64 ( guint64  num,
guint64  denom 
) [inline]

Return the greatest common factor of two 64-bit numbers

Definition at line 264 of file qofmath128.c.

00265 {
00266   guint64   t;
00267 
00268   t =  num % denom;
00269   num = denom;
00270   denom = t;
00271 
00272   /* The strategy is to use Euclid's algorithm */
00273   while (0 != denom) 
00274   {
00275     t = num % denom;
00276     num = denom;
00277     denom = t;
00278   }
00279   /* num now holds the GCD (Greatest Common Divisor) */
00280   return num;
00281 }

qofint128 inc128 ( qofint128  a  )  [inline]

increment a 128-bit number by one

Definition at line 153 of file qofmath128.c.

00154 {
00155   if (0 == a.isneg)
00156   {
00157     a.lo ++;
00158     if (0 == a.lo)
00159     {
00160       a.hi ++;
00161     }
00162   }
00163   else
00164   {
00165     if (0 == a.lo)
00166     {
00167       a.hi --;
00168     }
00169     a.lo --;
00170   }
00171 
00172   a.isbig = (a.hi != 0) || (a.lo >> 63);
00173   return a;
00174 }

qofint128 lcm128 ( guint64  a,
guint64  b 
) [inline]

Return the least common multiple of two 64-bit numbers.

Definition at line 285 of file qofmath128.c.

00286 {
00287   guint64 gcf = gcf64 (a,b);
00288   b /= gcf;
00289   return mult128 (a,b);
00290 }

qofint128 mult128 ( gint64  a,
gint64  b 
) [inline]

Multiply a pair of signed 64-bit numbers, returning a signed 128-bit number.

Definition at line 41 of file qofmath128.c.

00042 {
00043   qofint128 prod;
00044   guint64 a0, a1;
00045   guint64 b0, b1;
00046   guint64 d, d0, d1;
00047   guint64 e, e0, e1;
00048   guint64 f, f0, f1;
00049   guint64 g, g0, g1;
00050   guint64 sum, carry, roll, pmax;
00051 
00052   prod.isneg = 0;
00053   if (0>a)
00054   {
00055     prod.isneg = !prod.isneg;
00056     a = -a;
00057   }
00058 
00059   if (0>b)
00060   {
00061     prod.isneg = !prod.isneg;
00062     b = -b;
00063   }
00064 
00065   a1 = a >> 32;
00066   a0 = a - (a1<<32);
00067 
00068   b1 = b >> 32;
00069   b0 = b - (b1<<32);
00070 
00071   d = a0*b0;
00072   d1 = d >> 32;
00073   d0 = d - (d1<<32);
00074 
00075   e = a0*b1;
00076   e1 = e >> 32;
00077   e0 = e - (e1<<32);
00078 
00079   f = a1*b0;
00080   f1 = f >> 32;
00081   f0 = f - (f1<<32);
00082 
00083   g = a1*b1;
00084   g1 = g >> 32;
00085   g0 = g - (g1<<32);
00086 
00087   sum = d1+e0+f0;
00088   carry = 0;
00089   /* Can't say 1<<32 cause cpp will goof it up; 1ULL<<32 might work */
00090   roll = 1<<30;
00091   roll <<= 2;
00092 
00093   pmax = roll-1;
00094   while (pmax < sum)
00095   {
00096     sum -= roll;
00097     carry ++;
00098   }
00099 
00100   prod.lo = d0 + (sum<<32);
00101   prod.hi = carry + e1 + f1 + g0 + (g1<<32);
00102   // prod.isbig = (prod.hi || (sum >> 31));
00103   prod.isbig = prod.hi || (prod.lo >> 63);
00104 
00105   return prod;
00106 }

gint64 rem128 ( qofint128  n,
gint64  d 
) [inline]

Return the remainder of a signed 128-bit number modulo a signed 64-bit. That is, return nd in 128-bit math. I beleive that ths algo is overflow-free, but should be audited some more ...

Definition at line 219 of file qofmath128.c.

00220 {
00221   qofint128 quotient = div128 (n,d);
00222 
00223   qofint128 mu = mult128 (quotient.lo, d);
00224 
00225   gint64 nn = 0x7fffffffffffffffULL & n.lo;
00226   gint64 rr = 0x7fffffffffffffffULL & mu.lo;
00227   return nn - rr;
00228 }

qofint128 shift128 ( qofint128  x  )  [inline]

Shift right by one bit (i.e. divide by two)

Definition at line 110 of file qofmath128.c.

00111 {
00112   guint64 sbit = x.hi & 0x1;
00113   x.hi >>= 1;
00114   x.lo >>= 1;
00115   x.isbig = 0;
00116   if (sbit)
00117   {
00118     x.lo |= HIBIT;
00119     x.isbig = 1;
00120     return x;
00121   }
00122   if (x.hi)
00123   {
00124     x.isbig = 1;
00125   }
00126   return x;
00127 }

qofint128 shiftleft128 ( qofint128  x  )  [inline]

Shift leftt by one bit (i.e. multiply by two)

Definition at line 131 of file qofmath128.c.

00132 {
00133   guint64 sbit;
00134   sbit = x.lo & HIBIT;
00135   x.hi <<= 1;
00136   x.lo <<= 1;
00137   x.isbig = 0;
00138   if (sbit)
00139   {
00140     x.hi |= 1;
00141     x.isbig = 1;
00142     return x;
00143   }
00144   if (x.hi)
00145   {
00146     x.isbig = 1;
00147   }
00148   return x;
00149 }


Generated on Fri Oct 10 05:06:59 2008 for GnuCash by  doxygen 1.5.2