예제 #1
0
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 );
}
예제 #2
0
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 );
}
예제 #3
0
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 */
예제 #4
0
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 */
예제 #5
0
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;
}
예제 #6
0
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;
    }
  }
}