void mulint ( lrs_mp a, lrs_mp b, lrs_mp c ) /* multiply two integers a*b --> c */ /***Handbook of Algorithms and Data Structures, p239 ***/ { long nlength, i, j, la, lb; /*** b and c may coincide ***/ la = length ( a ); lb = length ( b ); nlength = la + lb - 2; if ( nlength > lrs_digits ) digits_overflow(); for ( i = 0; i < la - 2; i++ ) c[lb + i] = 0; for ( i = lb - 1; i > 0; i-- ) { for ( j = 2; j < la; j++ ) if ( ( c[i + j - 1] += b[i] * a[j] ) > MAXD - ( BASE - 1 ) * ( BASE - 1 ) - MAXD / BASE ) { c[i + j - 1] -= ( MAXD / BASE ) * BASE; c[i + j] += MAXD / BASE; } c[i] = b[i] * a[1]; } storelength ( c, nlength ); storesign ( c, sign ( a ) == sign ( b ) ? POS : NEG ); normalize ( c ); }
void linint ( lrs_mp a, long ka, lrs_mp b, long kb ) /*compute a*ka+b*kb --> a */ /***Handbook of Algorithms and Data Structures P.239 ***/ { long i, la, lb; la = length ( a ); lb = length ( b ); for ( i = 1; i < la; i++ ) a[i] *= ka; if ( sign ( a ) != sign ( b ) ) kb = ( -kb ); if ( lb > la ) { storelength ( a, lb ); for ( i = la; i < lb; i++ ) a[i] = 0; } for ( i = 1; i < lb; i++ ) a[i] += kb * b[i]; normalize ( a ); }
void normalize ( lrs_mp a ) { long cy, i, la; la = length ( a ); start: cy = 0; for ( i = 1; i < la; i++ ) { cy = ( a[i] += cy ) / BASE; a[i] -= cy * BASE; if ( a[i] < 0 ) { a[i] += BASE; cy--; } } while ( cy > 0 ) { a[i++] = cy % BASE; cy /= BASE; } if ( cy < 0 ) { a[la - 1] += cy * BASE; for ( i = 1; i < la; i++ ) a[i] = ( -a[i] ); storesign ( a, sign ( a ) == POS ? NEG : POS ); goto start; } while ( a[i - 1] == 0 && i > 2 ) i--; if ( i > lrs_record_digits ) { if ( ( lrs_record_digits = i ) > lrs_digits ) digits_overflow(); }; storelength ( a, i ); if ( i == 2 && a[1] == 0 ) storesign ( a, POS ); } /* end of normalize */
void itomp (long in, lrs_mp a) /* convert integer i to multiple precision with base BASE */ { long i; a[0] = 2; /* initialize to zero */ for (i = 1; i < lrs_digits; i++) a[i] = 0; if (in < 0) { storesign (a, NEG); in = in * (-1); } i = 0; while (in != 0) { i++; a[i] = in - BASE * (in / BASE); in = in / BASE; storelength (a, i + 1); } } /* end of itomp */
void gcd ( lrs_mp u, lrs_mp v ) /*returns u=gcd(u,v) destroying v */ /*Euclid's algorithm. Knuth, II, p.320 modified to avoid copies r=u,u=v,v=r Switches to single precision when possible for greater speed */ { lrs_mp r; unsigned long ul, vl; long i; static unsigned long maxspval = MAXD; /* Max value for the last digit to guarantee */ /* fitting into a single long integer. */ static long maxsplen; /* Maximum digits for a number that will fit */ /* into a single long integer. */ static long firstime = TRUE; if ( firstime ) { /* initialize constants */ for ( maxsplen = 2; maxspval >= BASE; maxsplen++ ) maxspval /= BASE; firstime = FALSE; } if ( greater ( v, u ) ) goto bigv; bigu: if ( zero ( v ) ) return; if ( ( i = length ( u ) ) < maxsplen || ( i == maxsplen && u[maxsplen - 1] < maxspval ) ) goto quickfinish; divint ( u, v, r ); normalize ( u ); bigv: if ( zero ( u ) ) { copy ( u, v ); return; } if ( ( i = length ( v ) ) < maxsplen || ( i == maxsplen && v[maxsplen - 1] < maxspval ) ) goto quickfinish; divint ( v, u, r ); normalize ( v ); goto bigu; /* Base 10000 only at the moment */ /* when u and v are small enough, transfer to single precision integers */ /* and finish with euclid's algorithm, then transfer back to lrs_mp */ quickfinish: ul = vl = 0; for ( i = length ( u ) - 1; i > 0; i-- ) ul = BASE * ul + u[i]; for ( i = length ( v ) - 1; i > 0; i-- ) vl = BASE * vl + v[i]; if ( ul > vl ) goto qv; qu: if ( !vl ) { for ( i = 1; ul; i++ ) { u[i] = ul % BASE; ul = ul / BASE; } storelength ( u, i ); return; } ul %= vl; qv: if ( !ul ) { for ( i = 1; vl; i++ ) { u[i] = vl % BASE; vl = vl / BASE; } storelength ( u, i ); return; } vl %= ul; goto qu; }
void divint ( lrs_mp a, lrs_mp b, lrs_mp c ) { /* c=a/b, a contains remainder on return */ long cy, la, lb, lc, d1, s, t, sig; long i, j, qh; /* figure out and save sign, do everything with positive numbers */ sig = sign ( a ) * sign ( b ); la = length ( a ); lb = length ( b ); lc = la - lb + 2; if ( la < lb ) { storelength ( c, TWO ); storesign ( c, POS ); c[1] = 0; normalize ( c ); return; } for ( i = 1; i < lc; i++ ) c[i] = 0; storelength ( c, lc ); storesign ( c, ( sign ( a ) == sign ( b ) ) ? POS : NEG ); /******************************/ /* division by a single word: */ /* do it directly */ /******************************/ if ( lb == 2 ) { cy = 0; t = b[1]; for ( i = la - 1; i > 0; i-- ) { cy = cy * BASE + a[i]; a[i] = 0; cy -= ( c[i] = cy / t ) * t; } a[1] = cy; storesign ( a, ( cy == 0 ) ? POS : sign ( a ) ); storelength ( a, TWO ); /* set sign of c to sig (**mod**) */ storesign ( c, sig ); normalize ( c ); return; } else { /* mp's are actually DIGITS+1 in length, so if length of a or b = */ /* DIGITS, there will still be room after normalization. */ /****************************************************/ /* Step D1 - normalize numbers so b > floor(BASE/2) */ d1 = BASE / ( b[lb - 1] + 1 ); if ( d1 > 1 ) { cy = 0; for ( i = 1; i < la; i++ ) { cy = ( a[i] = a[i] * d1 + cy ) / BASE; a[i] %= BASE; } a[i] = cy; cy = 0; for ( i = 1; i < lb; i++ ) { cy = ( b[i] = b[i] * d1 + cy ) / BASE; b[i] %= BASE; } b[i] = cy; } else { a[la] = 0; /* if la or lb = DIGITS this won't work */ b[lb] = 0; } /*********************************************/ /* Steps D2 & D7 - start and end of the loop */ for ( j = 0; j <= la - lb; j++ ) { /*************************************/ /* Step D3 - determine trial divisor */ if ( a[la - j] == b[lb - 1] ) qh = BASE - 1; else { s = ( a[la - j] * BASE + a[la - j - 1] ); qh = s / b[lb - 1]; while ( qh * b[lb - 2] > ( s - qh * b[lb - 1] ) * BASE + a[la - j - 2] ) qh--; } /*******************************************************/ /* Step D4 - divide through using qh as quotient digit */ cy = 0; for ( i = 1; i <= lb; i++ ) { s = qh * b[i] + cy; a[la - j - lb + i] -= s % BASE; cy = s / BASE; if ( a[la - j - lb + i] < 0 ) { a[la - j - lb + i] += BASE; cy++; } } /*****************************************************/ /* Step D6 - adjust previous step if qh is 1 too big */ if ( cy ) { qh--; cy = 0; for ( i = 1; i <= lb; i++ ) { /* add a back in */ a[la - j - lb + i] += b[i] + cy; cy = a[la - j - lb + i] / BASE; a[la - j - lb + i] %= BASE; } } /***********************************************************************/ /* Step D5 - write final value of qh. Saves calculating array indices */ /* to do it here instead of before D6 */ c[la - lb - j + 1] = qh; } /**********************************************************************/ /* Step D8 - unnormalize a and b to get correct remainder and divisor */ for ( i = lc; c[i - 1] == 0 && i > 2; i-- ); /* strip excess 0's from quotient */ storelength ( c, i ); if ( i == 2 && c[1] == 0 ) storesign ( c, POS ); cy = 0; for ( i = lb - 1; i >= 1; i-- ) { cy = ( a[i] += cy * BASE ) % d1; a[i] /= d1; } for ( i = la; a[i - 1] == 0 && i > 2; i-- ); /* strip excess 0's from quotient */ storelength ( a, i ); if ( i == 2 && a[1] == 0 ) storesign ( a, POS ); if ( cy ) fprintf ( lrs_ofp, "divide error" ); for ( i = lb - 1; i >= 1; i-- ) { cy = ( b[i] += cy * BASE ) % d1; b[i] /= d1; } } }