int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
{
   mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
   int err;

   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
      return err;
   }

   /* initialize, (u1,u2,u3) = (1,0,a) */
   mp_set(&u1, 1);
   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }

   /* initialize, (v1,v2,v3) = (0,1,b) */
   mp_set(&v2, 1);
   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }

   /* loop while v3 != 0 */
   while (mp_iszero(&v3) == MP_NO) {
       /* q = u3/v3 */
       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }

       /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }

       /* (u1,u2,u3) = (v1,v2,v3) */
       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }

       /* (v1,v2,v3) = (t1,t2,t3) */
       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
   }

   /* make sure U3 >= 0 */
   if (u3.sign == MP_NEG) {
      mp_neg(&u1, &u1);
      mp_neg(&u2, &u2);
      mp_neg(&u3, &u3);
   }

   /* copy result out */
   if (U1 != NULL) { mp_exch(U1, &u1); }
   if (U2 != NULL) { mp_exch(U2, &u2); }
   if (U3 != NULL) { mp_exch(U3, &u3); }

   err = MP_OKAY;
_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
   return err;
}
Exemple #2
0
/* Used with boxing. Gets an integer value, for representations that can
 * hold one. */
static INTVAL get_int(PARROT_INTERP, STable *st, void *data) {
    INTVAL ret;
    mp_int *i = &((P6bigintBody *)data)->i;
    if (MP_LT == mp_cmp_d(i, 0)) {
        mp_neg(i, i);
        ret = mp_get_long(i);
        mp_neg(i, i);
        return -ret;
    }
    else {
        return mp_get_long(i);
    }
}
Exemple #3
0
static void two_complement_bitop(mp_int *a, mp_int *b, mp_int *c,
        int (*mp_bitop)(mp_int *, mp_int *, mp_int *)) {
    mp_int d;
    if (SIGN(a) ^ SIGN(b)) {
        /* exactly one of them is negative, so need to perform
         * some magic. tommath stores a sign bit, but Perl 6 expects
         * 2's complement */
        mp_init(&d);
        if (MP_NEG == SIGN(a)) {
            grow_and_negate(a, USED(b), &d);
            mp_bitop(&d, b, c);
        } else {
            grow_and_negate(b, USED(a), &d);
            mp_bitop(a, &d, c);
        }
        if (DIGIT(c, USED(c) - 1) & ((mp_digit)1<<(mp_digit)(DIGIT_BIT - 1))) {
            grow_and_negate(c, c->used, &d);
            mp_copy(&d, c);
            mp_neg(c, c);
        }
        mp_clear(&d);
    } else {
        mp_bitop(a, b, c);
    }

}
Exemple #4
0
/* Used with boxing. Sets an integer value, for representations that can hold
 * one. */
static void set_int(PARROT_INTERP, STable *st, void *data, INTVAL value) {
    mp_int *i = &((P6bigintBody *)data)->i;
    if (value >= 0) {
        mp_set_long(i, value);
    }
    else {
        mp_set_long(i, -value);
        mp_neg(i, i);
    }
}
extern void
TclBNInitBignumFromWideInt(
    mp_int *a,			/* Bignum to initialize */
    Tcl_WideInt v)		/* Initial value */
{
    if (v < (Tcl_WideInt)0) {
	TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)(-v));
	mp_neg(a, a);
    } else {
	TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)v);
    }
}
Exemple #6
0
/* Converts a possibly-signed digit string into a large binary number.
   Returns assumed radix, derived from suffix 'h','o',b','.' */
int str2reg(unitptr reg, string digitstr)
{
    unit temp[MAX_UNIT_PRECISION], base[MAX_UNIT_PRECISION];
    int c, i;
    boolean minus = FALSE;
    short radix;		/* base 2-16 */

    mp_init(reg, 0);

    i = string_length(digitstr);
    if (i == 0)
	return (10);		/* empty string, assume radix 10 */
    c = digitstr[i - 1];	/* get last char in string */

    switch (c) {		/* classify radix select suffix character */
    case '.':
	radix = 10;
	break;
    case 'H':
    case 'h':
	radix = 16;
	break;
    case 'O':
    case 'o':
	radix = 8;
	break;
    case 'B':			/* caution! 'b' is a hex digit! */
    case 'b':
	radix = 2;
	break;
    default:
	radix = 10;
	break;
    }

    mp_init(base, radix);
    if ((minus = (*digitstr == '-')) != 0)
	digitstr++;
    while ((c = *digitstr++) != 0) {
	if (c == ',')
	    continue;		/* allow commas in number */
	c = ctox(c);
	if ((c < 0) || (c >= radix))
	    break;		/* scan terminated by any non-digit */
	mp_mult(temp, reg, base);
	mp_move(reg, temp);
	mp_init(temp, c);
	mp_add(reg, temp);
    }
    if (minus)
	mp_neg(reg);
    return (radix);
}				/* str2reg */
Exemple #7
0
/* b = ~a */
int mp_com(mp_int * a, mp_int * b)
{
  int     res;
  
  // -x == ~x + 1 (2's complement), hence ~x == -x - 1
  if ((res = mp_neg(a, b)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_sub_d(b, 1, b)) != MP_OKAY) {
    return res;
  }

  return MP_OKAY;
}
Exemple #8
0
static void from_num(MVMnum64 d, mp_int *a) {
    MVMnum64 d_digit = pow(2, DIGIT_BIT);
    MVMnum64 da      = fabs(d);
    MVMnum64 upper;
    MVMnum64 lower;
    MVMnum64 lowest;
    MVMnum64 rest;
    int      digits  = 0;

    mp_zero(a);

    while (da > d_digit * d_digit * d_digit) {;
        da /= d_digit;
        digits++;
    }
    mp_grow(a, digits + 3);

    /* populate the top 3 digits */
    upper = da / (d_digit*d_digit);
    rest = fmod(da, d_digit*d_digit);
    lower = rest / d_digit;
    lowest = fmod(rest,d_digit );
    if (upper >= 1) {
        mp_set_long(a, (unsigned long) upper);
        mp_mul_2d(a, DIGIT_BIT , a);
        DIGIT(a, 0) = (mp_digit) lower;
        mp_mul_2d(a, DIGIT_BIT , a);
    } else {
        if (lower >= 1) {
            mp_set_long(a, (unsigned long) lower);
            mp_mul_2d(a, DIGIT_BIT , a);
            a->used = 2;
        } else {
            a->used = 1;
        }
    }
    DIGIT(a, 0) = (mp_digit) lowest;

    /* shift the rest */
    mp_mul_2d(a, DIGIT_BIT * digits, a);
    if (d < 0)
        mp_neg(a, a);
    mp_clamp(a);
    mp_shrink(a);
}
Exemple #9
0
/* Stores an int64 in a bigint result body, either as a 32-bit smallint if it
 * is in range, or a big integer if not. */
static void store_int64_result(MVMP6bigintBody *body, MVMint64 result) {
    if (MVM_IS_32BIT_INT(result)) {
        body->u.smallint.flag = MVM_BIGINT_32_FLAG;
        body->u.smallint.value = (MVMint32)result;
    }
    else {
        mp_int *i = MVM_malloc(sizeof(mp_int));
        mp_init(i);
        if (result >= 0) {
            MVM_bigint_mp_set_uint64(i, (MVMuint64)result);
        }
        else {
            MVM_bigint_mp_set_uint64(i, (MVMuint64)-result);
            mp_neg(i, i);
        }
        body->u.bigint = i;
    }
}
Exemple #10
0
static void two_complement_bitop(mp_int *a, mp_int *b, mp_int *c,
				 int (*mp_bitop)(mp_int *, mp_int *, mp_int *)) {

    mp_int d;
    mp_int e;
    mp_int *f;
    mp_int *g;

    f = a;
    g = b;
    if (MP_NEG == SIGN(a)) {
        mp_init(&d);
        grow_and_negate(a, USED(b), &d);
        f = &d;
    }
    if (MP_NEG == SIGN(b)) {
        mp_init(&e);
        grow_and_negate(b, USED(a), &e);
        g = &e;
    }
    /* f and g now guaranteed to each point to positive bigints containing
     * a 2s compliment representation of the values in a and b.  If either
     * a or b was negative, the representation is one tomath "digit" longer
     * than it need be and sign extended.
     */
    mp_bitop(f, g, c);
    if (f == &d) mp_clear(&d);
    if (g == &e) mp_clear(&e);
    /* Use the fact that tomath clamps to detect results that should be
     * signed.  If we created extra tomath "digits" and they resulted in
     * sign bits of 0, they have been clamped away.  If the resulting sign
     * bits were 1, they remain, and c will have more digits than either of
     * original operands.  Note this only works because we do not
     * support NOR/NAND/NXOR, and so two zero sign bits can never create 1s.
     */
    if (USED(c) > MAX(USED(a),USED(b))) {
        int i;
        for (i = 0; i < USED(c); i++) {
            DIGIT(c, i) = (~DIGIT(c, i)) & MP_MASK;
        }
        mp_add_d(c, 1, c);
	mp_neg(c, c);
    }
}
Exemple #11
0
/* Forces a bigint, even if we only have a smallint. Takes a parameter that
 * indicates where to allocate a temporary mp_int if needed. */
static mp_int * force_bigint(const MVMP6bigintBody *body, mp_int **tmp) {
    if (MVM_BIGINT_IS_BIG(body)) {
        return body->u.bigint;
    }
    else {
        MVMint32 value = body->u.smallint.value;
        mp_int *i = MVM_malloc(sizeof(mp_int));
        mp_init(i);
        if (value >= 0) {
            mp_set_long(i, value);
        }
        else {
            mp_set_long(i, -value);
            mp_neg(i, i);
        }
        while (*tmp)
            tmp++;
        *tmp = i;
        return i;
    }
}
Exemple #12
0
int pb_sub(pb_poly *a, pb_poly *b, pb_poly *c)
{
   int neg, err, x, y, z, characteristic;
   pb_poly *tmp;

   /* grow c to be the max size */
   y = MAX(a->used, b->used);
   if (c->alloc < y) {
      if ((err = pb_grow(c, y)) != MP_OKAY) {
         return err;
      }
   }
   
   /* do we need to concern char */
   characteristic = mp_iszero(&(c->characteristic));

   /* sub the terms */
   z = MIN(a->used, b->used);
   for (x = 0; x < z; x++) {
       if ((err = mp_sub(&(a->terms[x]), &(b->terms[x]), &(c->terms[x]))) != MP_OKAY) {
          return err;
       }
       if (characteristic == MP_NO) {
          if ((err = mp_mod(&(c->terms[x]), &(c->characteristic), &(c->terms[x]))) != MP_OKAY) {
             return err;
          }
       }
   }

   /* excess digits? */
   if (y != z) {
       if (a->used == y) {
          tmp = a;
          neg = 0;
       } else {
          tmp = b;
          neg = 1;
       }
       for (x = z; x < y; x++) {
          if (characteristic == MP_NO) {
             if ((err = mp_mod(&(tmp->terms[x]), &(c->characteristic), &(c->terms[x]))) != MP_OKAY) {
                return err;
             }
             if (neg) {
                if ((err = mp_sub(&(c->characteristic), &(c->terms[x]), &(c->terms[x]))) != MP_OKAY) {
                   return err;
                }
             }
          } else {
             if (neg) {
                if ((err = mp_neg(&(tmp->terms[x]), &(c->terms[x]))) != MP_OKAY) {
                   return err; 
                }
             } else {
                if ((err = mp_copy(&(tmp->terms[x]), &(c->terms[x]))) != MP_OKAY) {
                   return err;
                }
             }
          }
       }
   }
   
   /* zero excess */
   for (x = y; x < c->used; x++) {
       mp_zero(&(c->terms[x]));
   }
   c->used = y;
   pb_clamp(c);

   return MP_OKAY;
}
Exemple #13
0
int main(void)
{
   unsigned rr;
   int cnt, ix;
#if LTM_DEMO_TEST_VS_MTEST
   unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n,
      gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n;
   char* ret;
#else
   unsigned long s, t;
   unsigned long long q, r;
   mp_digit mp;
   int i, n, err, should;
#endif

   if (mp_init_multi(&a, &b, &c, &d, &e, &f, NULL)!= MP_OKAY)
     return EXIT_FAILURE;

   atexit(_cleanup);

#if defined(LTM_DEMO_REAL_RAND)
   if (!fd_urandom) {
      fd_urandom = fopen("/dev/urandom", "r");
      if (!fd_urandom) {
#if !defined(_WIN32)
         fprintf(stderr, "\ncould not open /dev/urandom\n");
#endif
      }
   }
#endif
   srand(LTM_DEMO_RAND_SEED);

#ifdef MP_8BIT
   printf("Digit size 8 Bit \n");
#endif
#ifdef MP_16BIT
   printf("Digit size 16 Bit \n");
#endif
#ifdef MP_32BIT
   printf("Digit size 32 Bit \n");
#endif
#ifdef MP_64BIT
   printf("Digit size 64 Bit \n");
#endif
   printf("Size of mp_digit: %u\n", (unsigned int)sizeof(mp_digit));
   printf("Size of mp_word: %u\n", (unsigned int)sizeof(mp_word));
   printf("DIGIT_BIT: %d\n", DIGIT_BIT);
   printf("MP_PREC: %d\n", MP_PREC);

#if LTM_DEMO_TEST_VS_MTEST == 0
   // trivial stuff
   // a: 0->5
   mp_set_int(&a, 5);
   // a: 5-> b: -5
   mp_neg(&a, &b);
   if (mp_cmp(&a, &b) != MP_GT) {
      return EXIT_FAILURE;
   }
   if (mp_cmp(&b, &a) != MP_LT) {
      return EXIT_FAILURE;
   }
   // a: 5-> a: -5
   mp_neg(&a, &a);
   if (mp_cmp(&b, &a) != MP_EQ) {
      return EXIT_FAILURE;
   }
   // a: -5-> b: 5
   mp_abs(&a, &b);
   if (mp_isneg(&b) != MP_NO) {
      return EXIT_FAILURE;
   }
   // a: -5-> b: -4
   mp_add_d(&a, 1, &b);
   if (mp_isneg(&b) != MP_YES) {
      return EXIT_FAILURE;
   }
   if (mp_get_int(&b) != 4) {
      return EXIT_FAILURE;
   }
   // a: -5-> b: 1
   mp_add_d(&a, 6, &b);
   if (mp_get_int(&b) != 1) {
      return EXIT_FAILURE;
   }
   // a: -5-> a: 1
   mp_add_d(&a, 6, &a);
   if (mp_get_int(&a) != 1) {
      return EXIT_FAILURE;
   }
   mp_zero(&a);
   // a: 0-> a: 6
   mp_add_d(&a, 6, &a);
   if (mp_get_int(&a) != 6) {
      return EXIT_FAILURE;
   }


   mp_set_int(&a, 0);
   mp_set_int(&b, 1);
   if ((err = mp_jacobi(&a, &b, &i)) != MP_OKAY) {
      printf("Failed executing mp_jacobi(0 | 1) %s.\n", mp_error_to_string(err));
      return EXIT_FAILURE;
   }
   if (i != 1) {
      printf("Failed trivial mp_jacobi(0 | 1) %d != 1\n", i);
      return EXIT_FAILURE;
   }
   for (cnt = 0; cnt < (int)(sizeof(jacobi)/sizeof(jacobi[0])); ++cnt) {
      mp_set_int(&b, jacobi[cnt].n);
      /* only test positive values of a */
      for (n = -5; n <= 10; ++n) {
         mp_set_int(&a, abs(n));
         should = MP_OKAY;
         if (n < 0) {
            mp_neg(&a, &a);
            /* Until #44 is fixed the negative a's must fail */
            should = MP_VAL;
         }
         if ((err = mp_jacobi(&a, &b, &i)) != should) {
            printf("Failed executing mp_jacobi(%d | %lu) %s.\n", n, jacobi[cnt].n, mp_error_to_string(err));
            return EXIT_FAILURE;
         }
         if (err == MP_OKAY && i != jacobi[cnt].c[n + 5]) {
            printf("Failed trivial mp_jacobi(%d | %lu) %d != %d\n", n, jacobi[cnt].n, i, jacobi[cnt].c[n + 5]);
            return EXIT_FAILURE;
         }
      }
   }

   // test mp_get_int
   printf("\n\nTesting: mp_get_int");
   for (i = 0; i < 1000; ++i) {
      t = ((unsigned long) rand () * rand () + 1) & 0xFFFFFFFF;
      mp_set_int (&a, t);
      if (t != mp_get_int (&a)) {
         printf ("\nmp_get_int() bad result!");
         return EXIT_FAILURE;
      }
   }
   mp_set_int(&a, 0);
   if (mp_get_int(&a) != 0) {
      printf("\nmp_get_int() bad result!");
      return EXIT_FAILURE;
   }
   mp_set_int(&a, 0xffffffff);
   if (mp_get_int(&a) != 0xffffffff) {
      printf("\nmp_get_int() bad result!");
      return EXIT_FAILURE;
   }

   printf("\n\nTesting: mp_get_long\n");
   for (i = 0; i < (int)(sizeof(unsigned long)*CHAR_BIT) - 1; ++i) {
      t = (1ULL << (i+1)) - 1;
      if (!t)
         t = -1;
      printf(" t = 0x%lx i = %d\r", t, i);
      do {
         if (mp_set_long(&a, t) != MP_OKAY) {
            printf("\nmp_set_long() error!");
            return EXIT_FAILURE;
         }
         s = mp_get_long(&a);
         if (s != t) {
            printf("\nmp_get_long() bad result! 0x%lx != 0x%lx", s, t);
            return EXIT_FAILURE;
         }
         t <<= 1;
      } while(t);
   }

   printf("\n\nTesting: mp_get_long_long\n");
   for (i = 0; i < (int)(sizeof(unsigned long long)*CHAR_BIT) - 1; ++i) {
      r = (1ULL << (i+1)) - 1;
      if (!r)
         r = -1;
      printf(" r = 0x%llx i = %d\r", r, i);
      do {
         if (mp_set_long_long(&a, r) != MP_OKAY) {
            printf("\nmp_set_long_long() error!");
            return EXIT_FAILURE;
         }
         q = mp_get_long_long(&a);
         if (q != r) {
            printf("\nmp_get_long_long() bad result! 0x%llx != 0x%llx", q, r);
            return EXIT_FAILURE;
         }
         r <<= 1;
      } while(r);
   }

   // test mp_sqrt
   printf("\n\nTesting: mp_sqrt\n");
   for (i = 0; i < 1000; ++i) {
      printf ("%6d\r", i);
      fflush (stdout);
      n = (rand () & 15) + 1;
      mp_rand (&a, n);
      if (mp_sqrt (&a, &b) != MP_OKAY) {
         printf ("\nmp_sqrt() error!");
         return EXIT_FAILURE;
      }
      mp_n_root_ex (&a, 2, &c, 0);
      mp_n_root_ex (&a, 2, &d, 1);
      if (mp_cmp_mag (&c, &d) != MP_EQ) {
         printf ("\nmp_n_root_ex() bad result!");
         return EXIT_FAILURE;
      }
      if (mp_cmp_mag (&b, &c) != MP_EQ) {
         printf ("mp_sqrt() bad result!\n");
         return EXIT_FAILURE;
      }
   }

   printf("\n\nTesting: mp_is_square\n");
   for (i = 0; i < 1000; ++i) {
      printf ("%6d\r", i);
      fflush (stdout);

      /* test mp_is_square false negatives */
      n = (rand () & 7) + 1;
      mp_rand (&a, n);
      mp_sqr (&a, &a);
      if (mp_is_square (&a, &n) != MP_OKAY) {
         printf ("\nfn:mp_is_square() error!");
         return EXIT_FAILURE;
      }
      if (n == 0) {
         printf ("\nfn:mp_is_square() bad result!");
         return EXIT_FAILURE;
      }

      /* test for false positives */
      mp_add_d (&a, 1, &a);
      if (mp_is_square (&a, &n) != MP_OKAY) {
         printf ("\nfp:mp_is_square() error!");
         return EXIT_FAILURE;
      }
      if (n == 1) {
         printf ("\nfp:mp_is_square() bad result!");
         return EXIT_FAILURE;
      }

   }
   printf("\n\n");

   // r^2 = n (mod p)
   for (i = 0; i < (int)(sizeof(sqrtmod_prime)/sizeof(sqrtmod_prime[0])); ++i) {
      mp_set_int(&a, sqrtmod_prime[i].p);
      mp_set_int(&b, sqrtmod_prime[i].n);
      if (mp_sqrtmod_prime(&b, &a, &c) != MP_OKAY) {
         printf("Failed executing %d. mp_sqrtmod_prime\n", (i+1));
         return EXIT_FAILURE;
      }
      if (mp_cmp_d(&c, sqrtmod_prime[i].r) != MP_EQ) {
         printf("Failed %d. trivial mp_sqrtmod_prime\n", (i+1));
         ndraw(&c, "r");
         return EXIT_FAILURE;
      }
   }

   /* test for size */
   for (ix = 10; ix < 128; ix++) {
      printf ("Testing (not safe-prime): %9d bits    \r", ix);
      fflush (stdout);
      err = mp_prime_random_ex (&a, 8, ix,
                                (rand () & 1) ? 0 : LTM_PRIME_2MSB_ON, myrng,
                                NULL);
      if (err != MP_OKAY) {
         printf ("failed with err code %d\n", err);
         return EXIT_FAILURE;
      }
      if (mp_count_bits (&a) != ix) {
         printf ("Prime is %d not %d bits!!!\n", mp_count_bits (&a), ix);
         return EXIT_FAILURE;
      }
   }
   printf("\n");

   for (ix = 16; ix < 128; ix++) {
      printf ("Testing (    safe-prime): %9d bits    \r", ix);
      fflush (stdout);
      err = mp_prime_random_ex (
            &a, 8, ix, ((rand () & 1) ? 0 : LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE,
            myrng, NULL);
      if (err != MP_OKAY) {
         printf ("failed with err code %d\n", err);
         return EXIT_FAILURE;
      }
      if (mp_count_bits (&a) != ix) {
         printf ("Prime is %d not %d bits!!!\n", mp_count_bits (&a), ix);
         return EXIT_FAILURE;
      }
      /* let's see if it's really a safe prime */
      mp_sub_d (&a, 1, &a);
      mp_div_2 (&a, &a);
      mp_prime_is_prime (&a, 8, &cnt);
      if (cnt != MP_YES) {
         printf ("sub is not prime!\n");
         return EXIT_FAILURE;
      }
   }

   printf("\n\n");

   // test montgomery
   printf("Testing: montgomery...\n");
   for (i = 1; i <= 10; i++) {
      if (i == 10)
         i = 1000;
      printf(" digit size: %2d\r", i);
      fflush(stdout);
      for (n = 0; n < 1000; n++) {
         mp_rand(&a, i);
         a.dp[0] |= 1;

         // let's see if R is right
         mp_montgomery_calc_normalization(&b, &a);
         mp_montgomery_setup(&a, &mp);

         // now test a random reduction
         for (ix = 0; ix < 100; ix++) {
             mp_rand(&c, 1 + abs(rand()) % (2*i));
             mp_copy(&c, &d);
             mp_copy(&c, &e);

             mp_mod(&d, &a, &d);
             mp_montgomery_reduce(&c, &a, mp);
             mp_mulmod(&c, &b, &a, &c);

             if (mp_cmp(&c, &d) != MP_EQ) {
printf("d = e mod a, c = e MOD a\n");
mp_todecimal(&a, buf); printf("a = %s\n", buf);
mp_todecimal(&e, buf); printf("e = %s\n", buf);
mp_todecimal(&d, buf); printf("d = %s\n", buf);
mp_todecimal(&c, buf); printf("c = %s\n", buf);
printf("compare no compare!\n"); return EXIT_FAILURE; }
             /* only one big montgomery reduction */
             if (i > 10)
             {
                n = 1000;
                ix = 100;
             }
         }
      }
   }

   printf("\n\n");

   mp_read_radix(&a, "123456", 10);
   mp_toradix_n(&a, buf, 10, 3);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 4);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 30);
   printf("a == %s\n", buf);


#if 0
   for (;;) {
      fgets(buf, sizeof(buf), stdin);
      mp_read_radix(&a, buf, 10);
      mp_prime_next_prime(&a, 5, 1);
      mp_toradix(&a, buf, 10);
      printf("%s, %lu\n", buf, a.dp[0] & 3);
   }
#endif

   /* test mp_cnt_lsb */
   printf("\n\nTesting: mp_cnt_lsb");
   mp_set(&a, 1);
   for (ix = 0; ix < 1024; ix++) {
      if (mp_cnt_lsb (&a) != ix) {
         printf ("Failed at %d, %d\n", ix, mp_cnt_lsb (&a));
         return EXIT_FAILURE;
      }
      mp_mul_2 (&a, &a);
   }

/* test mp_reduce_2k */
   printf("\n\nTesting: mp_reduce_2k\n");
   for (cnt = 3; cnt <= 128; ++cnt) {
      mp_digit tmp;

      mp_2expt (&a, cnt);
      mp_sub_d (&a, 2, &a); /* a = 2**cnt - 2 */

      printf ("\r %4d bits", cnt);
      printf ("(%d)", mp_reduce_is_2k (&a));
      mp_reduce_2k_setup (&a, &tmp);
      printf ("(%lu)", (unsigned long) tmp);
      for (ix = 0; ix < 1000; ix++) {
         if (!(ix & 127)) {
            printf (".");
            fflush (stdout);
         }
         mp_rand (&b, (cnt / DIGIT_BIT + 1) * 2);
         mp_copy (&c, &b);
         mp_mod (&c, &a, &c);
         mp_reduce_2k (&b, &a, 2);
         if (mp_cmp (&c, &b)) {
            printf ("FAILED\n");
            return EXIT_FAILURE;
         }
      }
   }

/* test mp_div_3  */
   printf("\n\nTesting: mp_div_3...\n");
   mp_set(&d, 3);
   for (cnt = 0; cnt < 10000;) {
      mp_digit r2;

      if (!(++cnt & 127))
      {
        printf("%9d\r", cnt);
        fflush(stdout);
      }
      mp_rand(&a, abs(rand()) % 128 + 1);
      mp_div(&a, &d, &b, &e);
      mp_div_3(&a, &c, &r2);

      if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
	 printf("\nmp_div_3 => Failure\n");
      }
   }
   printf("\nPassed div_3 testing");

/* test the DR reduction */
   printf("\n\nTesting: mp_dr_reduce...\n");
   for (cnt = 2; cnt < 32; cnt++) {
      printf ("\r%d digit modulus", cnt);
      mp_grow (&a, cnt);
      mp_zero (&a);
      for (ix = 1; ix < cnt; ix++) {
         a.dp[ix] = MP_MASK;
      }
      a.used = cnt;
      a.dp[0] = 3;

      mp_rand (&b, cnt - 1);
      mp_copy (&b, &c);

      rr = 0;
      do {
         if (!(rr & 127)) {
            printf (".");
            fflush (stdout);
         }
         mp_sqr (&b, &b);
         mp_add_d (&b, 1, &b);
         mp_copy (&b, &c);

         mp_mod (&b, &a, &b);
         mp_dr_setup(&a, &mp),
         mp_dr_reduce (&c, &a, mp);

         if (mp_cmp (&b, &c) != MP_EQ) {
            printf ("Failed on trial %u\n", rr);
            return EXIT_FAILURE;
         }
      } while (++rr < 500);
      printf (" passed");
      fflush (stdout);
   }

#if LTM_DEMO_TEST_REDUCE_2K_L
/* test the mp_reduce_2k_l code */
#if LTM_DEMO_TEST_REDUCE_2K_L == 1
/* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */
   mp_2expt(&a, 1024);
   mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16);
   mp_sub(&a, &b, &a);
#elif LTM_DEMO_TEST_REDUCE_2K_L == 2
/*  p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F  */
   mp_2expt(&a, 2048);
   mp_read_radix(&b,
		 "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F",
		 16);
   mp_sub(&a, &b, &a);
#else
#error oops
#endif

   mp_todecimal(&a, buf);
   printf("\n\np==%s\n", buf);
/* now mp_reduce_is_2k_l() should return */
   if (mp_reduce_is_2k_l(&a) != 1) {
      printf("mp_reduce_is_2k_l() return 0, should be 1\n");
      return EXIT_FAILURE;
   }
   mp_reduce_2k_setup_l(&a, &d);
   /* now do a million square+1 to see if it varies */
   mp_rand(&b, 64);
   mp_mod(&b, &a, &b);
   mp_copy(&b, &c);
   printf("Testing: mp_reduce_2k_l...");
   fflush(stdout);
   for (cnt = 0; cnt < (int)(1UL << 20); cnt++) {
      mp_sqr(&b, &b);
      mp_add_d(&b, 1, &b);
      mp_reduce_2k_l(&b, &a, &d);
      mp_sqr(&c, &c);
      mp_add_d(&c, 1, &c);
      mp_mod(&c, &a, &c);
      if (mp_cmp(&b, &c) != MP_EQ) {
	 printf("mp_reduce_2k_l() failed at step %d\n", cnt);
	 mp_tohex(&b, buf);
	 printf("b == %s\n", buf);
	 mp_tohex(&c, buf);
	 printf("c == %s\n", buf);
	 return EXIT_FAILURE;
      }
   }
   printf("...Passed\n");
#endif /* LTM_DEMO_TEST_REDUCE_2K_L */

#else

   div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
      sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
      sub_d_n = 0;

   /* force KARA and TOOM to enable despite cutoffs */
   KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8;
   TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16;

   for (;;) {
      /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
      switch (abs(rand()) % 7) {
      case 0:
	 mp_clear(&a);
	 mp_init(&a);
	 break;
      case 1:
	 mp_clear(&b);
	 mp_init(&b);
	 break;
      case 2:
	 mp_clear(&c);
	 mp_init(&c);
	 break;
      case 3:
	 mp_clear(&d);
	 mp_init(&d);
	 break;
      case 4:
	 mp_clear(&e);
	 mp_init(&e);
	 break;
      case 5:
	 mp_clear(&f);
	 mp_init(&f);
	 break;
      case 6:
	 break;			/* don't clear any */
      }


      printf
	 ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ",
	  add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n,
	  expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
      ret=fgets(cmd, 4095, stdin); if(!ret){_panic(__LINE__);}
      cmd[strlen(cmd) - 1] = 0;
      printf("%-6s ]\r", cmd);
      fflush(stdout);
      if (!strcmp(cmd, "mul2d")) {
	 ++mul2d_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 sscanf(buf, "%d", &rr);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);

	 mp_mul_2d(&a, rr, &a);
	 a.sign = b.sign;
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("mul2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "div2d")) {
	 ++div2d_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 sscanf(buf, "%d", &rr);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);

	 mp_div_2d(&a, rr, &a, &e);
	 a.sign = b.sign;
	 if (a.used == b.used && a.used == 0) {
	    a.sign = b.sign = MP_ZPOS;
	 }
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("div2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "add")) {
	 ++add_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_add(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("add %lu failure!\n", add_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }

	 /* test the sign/unsigned storage functions */

	 rr = mp_signed_bin_size(&c);
	 mp_to_signed_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_signed_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mp_signed_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }


	 rr = mp_unsigned_bin_size(&c);
	 mp_to_unsigned_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp_mag(&c, &d) != MP_EQ) {
	    printf("mp_unsigned_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }

      } else if (!strcmp(cmd, "sub")) {
	 ++sub_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_sub(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("sub %lu failure!\n", sub_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "mul")) {
	 ++mul_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_mul(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mul %lu failure!\n", mul_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "div")) {
	 ++div_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&d, buf, 64);

	 mp_div(&a, &b, &e, &f);
	 if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
	    printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e),
		   mp_cmp(&d, &f));
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    draw(&f);
	    return EXIT_FAILURE;
	 }

      } else if (!strcmp(cmd, "sqr")) {
	 ++sqr_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_copy(&a, &c);
	 mp_sqr(&c, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sqr %lu failure!\n", sqr_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "gcd")) {
	 ++gcd_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_gcd(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("gcd %lu failure!\n", gcd_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "lcm")) {
	 ++lcm_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_lcm(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("lcm %lu failure!\n", lcm_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "expt")) {
	 ++expt_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&d, buf, 64);
	 mp_copy(&a, &e);
	 mp_exptmod(&e, &b, &c, &e);
	 if (mp_cmp(&d, &e) != MP_EQ) {
	    printf("expt %lu failure!\n", expt_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "invmod")) {
	 ++inv_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&c, buf, 64);
	 mp_invmod(&a, &b, &d);
	 mp_mulmod(&d, &a, &b, &e);
	 if (mp_cmp_d(&e, 1) != MP_EQ) {
	    printf("inv [wrong value from MPI?!] failure\n");
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    mp_gcd(&a, &b, &e);
	    draw(&e);
	    return EXIT_FAILURE;
	 }

      } else if (!strcmp(cmd, "div2")) {
	 ++div2_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_div_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("div_2 %lu failure\n", div2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "mul2")) {
	 ++mul2_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_mul_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("mul_2 %lu failure\n", mul2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "add_d")) {
	 ++add_d_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 sscanf(buf, "%d", &ix);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_add_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("add_d %lu failure\n", add_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "sub_d")) {
	 ++sub_d_n;
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&a, buf, 64);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 sscanf(buf, "%d", &ix);
	 ret=fgets(buf, 4095, stdin); if(!ret){_panic(__LINE__);}
	 mp_read_radix(&b, buf, 64);
	 mp_sub_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sub_d %lu failure\n", sub_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return EXIT_FAILURE;
	 }
      } else if (!strcmp(cmd, "exit")) {
         printf("\nokay, exiting now\n");
         break;
      }
   }
#endif
   return 0;
}
Exemple #14
0
static int neg(void *a, void *b)
{
   LTC_ARGCHK(a != NULL);
   LTC_ARGCHK(b != NULL);
   return mpi_to_ltc_error(mp_neg(a, b));
}
int mp_toom_cook_5_mul(mp_int *a, mp_int *b, mp_int *c)
{
   mp_int w1, w2, w3, w4, w5, w6, w7, w8, w9;
   mp_int tmp1, tmp2;
   mp_int a0, a1, a2, a3, a4;
   mp_int b0, b1, b2, b3, b4;
   int e = MP_OKAY;
   int B, count, sign;

   B = (MAX(a->used, b->used)) / 5;


   sign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS;
   if (MIN(a->used, b->used) < TOOM_COOK_5_MUL_CO) {
      if ((e = mp_mul(a, b, c)) != MP_OKAY) {
         return e;
      }
      c->sign = sign;
      return MP_OKAY;
   }



   if ((e =
           mp_init_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2,
                         //&a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4,
                         NULL)) != MP_OKAY) {
      goto ERR0;
      //goto ERR;
   }

   if ((e = mp_init_size(&a0, B)) != MP_OKAY) {
      goto ERRa0;
   }
   if ((e = mp_init_size(&a1, B)) != MP_OKAY) {
      goto ERRa1;
   }
   if ((e = mp_init_size(&a2, B)) != MP_OKAY) {
      goto ERRa2;
   }
   if ((e = mp_init_size(&a3, B)) != MP_OKAY) {
      goto ERRa3;
   }
   if ((e = mp_init_size(&a4, B)) != MP_OKAY) {
      goto ERRa4;
   }

   if ((e = mp_init_size(&b0, B)) != MP_OKAY) {
      goto ERRb0;
   }
   if ((e = mp_init_size(&b1, B)) != MP_OKAY) {
      goto ERRb1;
   }
   if ((e = mp_init_size(&b2, B)) != MP_OKAY) {
      goto ERRb2;
   }
   if ((e = mp_init_size(&b3, B)) != MP_OKAY) {
      goto ERRb3;
   }
   if ((e = mp_init_size(&b4, B)) != MP_OKAY) {
      goto ERRb4;
   }
   // A = a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0
   for (count = 0; count < a->used; count++) {
      switch (count / B) {
      case 0:
         a0.dp[count] = a->dp[count];
         a0.used++;
         break;
      case 1:
         a1.dp[count - B] = a->dp[count];
         a1.used++;
         break;
      case 2:
         a2.dp[count - 2 * B] = a->dp[count];
         a2.used++;
         break;
      case 3:
         a3.dp[count - 3 * B] = a->dp[count];
         a3.used++;
         break;
      case 4:
         a4.dp[count - 4 * B] = a->dp[count];
         a4.used++;
         break;
      default:
         a4.dp[count - 4 * B] = a->dp[count];
         a4.used++;
         break;
      }
   }
   mp_clamp(&a0);
   mp_clamp(&a1);
   mp_clamp(&a2);
   mp_clamp(&a3);
   mp_clamp(&a4);
   // B = b4*x^4 + b3*x^3 + b2*x^2 + b1*x + b0
   for (count = 0; count < b->used; count++) {
      switch (count / B) {
      case 0:
         b0.dp[count] = b->dp[count];
         b0.used++;
         break;
      case 1:
         b1.dp[count - B] = b->dp[count];
         b1.used++;
         break;
      case 2:
         b2.dp[count - 2 * B] = b->dp[count];
         b2.used++;
         break;
      case 3:
         b3.dp[count - 3 * B] = b->dp[count];
         b3.used++;
         break;
      case 4:
         b4.dp[count - 4 * B] = b->dp[count];
         b4.used++;
         break;
      default:
         b4.dp[count - 4 * B] = b->dp[count];
         b4.used++;
         break;
      }
   }
   mp_clamp(&b0);
   mp_clamp(&b1);
   mp_clamp(&b2);
   mp_clamp(&b3);
   mp_clamp(&b4);


   /*
     if ((e = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
     }

     if ((e = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a1, B);
     mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

     if ((e = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a2, B * 2);
     mp_mod_2d(&a2, DIGIT_BIT * B, &a2);

     if ((e = mp_copy(a, &a3)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a3, B * 3);

     mp_mod_2d(&a3, DIGIT_BIT * B, &a3);

     if ((e = mp_copy(a, &a4)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a4, B * 4);



     if ((e = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
       goto ERR;
     }

     if ((e = mp_copy(a, &b1)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b1, B);
     mp_mod_2d(&b1, DIGIT_BIT * B, &b1);

     if ((e = mp_copy(b, &b2)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b2, B * 2);
     mp_mod_2d(&b2, DIGIT_BIT * B, &b2);

     if ((e = mp_copy(b, &b3)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b3, B * 3);

     mp_mod_2d(&b3, DIGIT_BIT * B, &b3);

     if ((e = mp_copy(b, &b4)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b4, B * 4);
   */

// S1 = a4*b4
   if ((e = mp_mul(&a4, &b4, &w1)) != MP_OKAY) {
      goto ERR;
   }
// S9 = a0*b0
   if ((e = mp_mul(&a0, &b0, &w9)) != MP_OKAY) {
      goto ERR;
   }

// S2 = (a0- 2*a1 +4*a2 -8*a3 +16*a4)

   if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 2*a1     = tmp1
   if ((e = mp_sub(&a0, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 = a0 - tmp1 = w2
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 4*a2     = tmp1
   if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 = w2 + tmp1 = w2
   if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 8*a3     = tmp1
   if ((e = mp_sub(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 -8*a3 = w2 - tmp1 = w2
   if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 16*a4     = tmp1
   if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 -8*a3 +16*a4 = w2 + tmp1 = w2

//    * (b0- 2*b1 +4*b2 -8*b3 +16*b4)
   if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w2, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S5 = (a0+ 2*a1+ 4*a2+ 8*a3+ 16*a4)
   if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a0, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// *(b0+ 2*b1+ 4*b2+ 8*b3+ 16*b4)
   if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w5, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S3 = (a4+ 2*a3+ 4*a2+ 8*a1+ 16*a0)
   if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a4, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// *    (b4+ 2*b3+ 4*b2+ 8*b1+ 16*b0)
   if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b4, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w3, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S8 = (a4- 2*a3+ 4*a2- 8*a1+ 16*a0)
   if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&a4, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
//*     (b4- 2*b3+ 4*b2- 8*b1+ 16*b0)
   if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&b4, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w8, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S4 = (a0+ 4*a1+ 16*a2+ 64*a3+ 256*a4)
   if ((e = mp_mul_2d(&a1, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a0, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a3, 6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a4, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
//*     (b0+ 4*b1+ 16*b2+ 64*b3+ 256*b4)
   if ((e = mp_mul_2d(&b1, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w4, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S6 = (a0- a1+ a2- a3 +a4)
   if ((e = mp_sub(&a0, &a1, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w6, &a2, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w6, &a3, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w6, &a4, &w6)) != MP_OKAY) {
      goto ERR;
   }
// *    (b0- b1+ b2- b3+ b4)
   if ((e = mp_sub(&b0, &b1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp1, &b3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp1, &w6, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S7 = (a0+ a1+ a2+ a3+ a4)
   if ((e = mp_add(&a0, &a1, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a2, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a3, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a4, &w7)) != MP_OKAY) {
      goto ERR;
   }
// *    (b0+ b1+ b2+ b3+ b4)
   if ((e = mp_add(&b0, &b1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp1, &w7, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S6 -= S7
   if ((e = mp_sub(&w6, &w7, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S2 -= S5
   if ((e = mp_sub(&w2, &w5, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= S9
   if ((e = mp_sub(&w4, &w9, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (2^16*S1)
   if ((e = mp_mul_2d(&w1, 16, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= S3
   if ((e = mp_sub(&w8, &w3, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S6 /= 2
   if ((e = mp_div_2d(&w6, 1, &w6, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S5 *= 2
   if ((e = mp_mul_2d(&w5, 1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S5 += S2
   if ((e = mp_add(&w5, &w2, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S2 = -S2
   if ((e = mp_neg(&w2, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S8 = -S8
   if ((e = mp_neg(&w8, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S7 += S6
   if ((e = mp_add(&w7, &w6, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S6 = -S6
   if ((e = mp_neg(&w6, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S7
   if ((e = mp_sub(&w3, &w7, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S5 -= (512*S7)
   if ((e = mp_mul_2d(&w7, 9, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S3 *= 2
   if ((e = mp_mul_2d(&w3, 1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S8
   if ((e = mp_sub(&w3, &w8, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S1
   if ((e = mp_sub(&w7, &w1, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S9
   if ((e = mp_sub(&w7, &w9, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S8 += S2
   if ((e = mp_add(&w8, &w2, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S5 += S3
   if ((e = mp_add(&w5, &w3, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= (80*S6)
   if ((e = mp_mul_d(&w6, 80, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= (510*S9)
   if ((e = mp_mul_d(&w9, 510, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= S2
   if ((e = mp_sub(&w4, &w2, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S3 *= 3
   if ((e = mp_mul_d(&w3, 3, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S3 += S5
   if ((e = mp_add(&w3, &w5, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S8 /= 180 \\ division by 180
   if ((e = mp_div_d(&w8, 180, &w8, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S5 += (378*S7)
   if ((e = mp_mul_d(&w7, 378, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S2 /= 4
   if ((e = mp_div_2d(&w2, 2, &w2, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S6 -= S2
   if ((e = mp_sub(&w6, &w2, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S5 /= (-72) \\ division by -72
   if ((e = mp_div_d(&w5, 72, &w5, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w5.sign == MP_ZPOS)
      (&w5)->sign = MP_NEG;
   (&w5)->sign = MP_ZPOS;
// S3 /= (-360) \\ division by -360
   if ((e = mp_div_d(&w3, 360, &w3, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w3.sign == MP_ZPOS)
      (&w3)->sign = MP_NEG;
   (&w3)->sign = MP_ZPOS;
// S2 -= S8
   if ((e = mp_sub(&w2, &w8, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S3
   if ((e = mp_sub(&w7, &w3, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (256*S5)
   if ((e = mp_mul_2d(&w5, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S5
   if ((e = mp_sub(&w3, &w5, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (4096*S3)
   if ((e = mp_mul_2d(&w3, 12, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (16*S7)
   if ((e = mp_mul_2d(&w7, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 += (256*S6)
   if ((e = mp_mul_2d(&w6, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S6 += S2
   if ((e = mp_add(&w6, &w2, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S2 *= 180
   if ((e = mp_mul_d(&w2, 180, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S2 += S4
   if ((e = mp_add(&w2, &w4, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S2 /= 11340 \\ division by 11340
   if ((e = mp_div_d(&w2, 11340, &w2, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S4 += (720*S6)
   if ((e = mp_mul_d(&w6, 720, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 /= (-2160) \\ division by -2160
   if ((e = mp_div_d(&w4, 2160, &w4, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w4.sign == MP_ZPOS)
      (&w4)->sign = MP_NEG;
   (&w4)->sign = MP_ZPOS;
// S6 -= S4
   if ((e = mp_sub(&w6, &w4, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= S2
   if ((e = mp_sub(&w8, &w2, &w8)) != MP_OKAY) {
      goto ERR;
   }
// P = S1*x^8 + S2*x^7 + S3*x^6 + S4*x^5 + S5*x^4 + S6*x^3 + S7*x^2 + S8*x + S9
   if ((e = mp_copy(&w9, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w8, B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w7, 2 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w7, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w6, 3 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w5, 4 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w5, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w4, 5 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w3, 6 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w2, 7 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w1, 8 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w1, c)) != MP_OKAY) {
      goto ERR;
   }
// P - A*B \\ == zero
   c->sign = sign;
ERR:

ERRb4:
   mp_clear(&b4);
ERRb3:
   mp_clear(&b3);
ERRb2:
   mp_clear(&b2);
ERRb1:
   mp_clear(&b1);
ERRb0:
   mp_clear(&b0);
ERRa4:
   mp_clear(&a4);
ERRa3:
   mp_clear(&a3);
ERRa2:
   mp_clear(&a2);
ERRa1:
   mp_clear(&a1);
ERRa0:
   mp_clear(&a0);

ERR0:

   mp_clear_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2,
                  // &a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4,
                  NULL);
   return e;
}
Exemple #16
0
term_t bin2term(apr_byte_t **data, int *bytes_left, atoms_t *atoms, heap_t *heap)
{

#define require(__n) \
	do { \
		if (*bytes_left < __n) \
			return noval; \
		(*bytes_left) -= __n; \
	} while (0)

#define get_byte() (*(*data)++)

	require(1);
	switch (get_byte())
	{
	case 97:
	{
		require(1);
		return tag_int(get_byte());
	}
	case 98:
	{
		int a, b, c, d;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		return int_to_term((a << 24) | (b << 16) | (c << 8) | d, heap);
	}
	case 99:
	{
		double value;
		require(31);
		sscanf((const char *)*data, "%lf", &value);
		(*data) += 31;
		return heap_float(heap, value);
	}
	case 100:
	{
		int a, b;
		int len;
		cstr_t *s;
		int index;
		require(2);
		a = get_byte();
		b = get_byte();
		len = ((a << 8) | b);
		if (len > 255)
			return noval;
		require(len);
		s = (cstr_t *)heap_alloc(heap, sizeof(cstr_t) + len);
		s->size = len;
		memcpy(s->data, *data, len);
		index = atoms_set(atoms, s);
		(*data) += len;
		return tag_atom(index);
	}
	case 104:
	{
		int arity, i;
		term_t tuple;
		term_box_t *tbox;
		require(1);
		arity = get_byte();
		tuple = heap_tuple(heap, arity);
		tbox = peel(tuple);
		for (i = 0; i < arity; i++)
		{
			term_t e = bin2term(data, bytes_left, atoms, heap);
			if (e == noval)
				return noval;
			tbox->tuple.elts[i] = e;
		}
		return tuple;
	}
	case 105:
	{
		int a, b, c, d;
		int arity, i;
		term_t tuple;
		term_box_t *tbox;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		arity = ((a << 24) | (b << 16) | (c << 8) | d);
		tuple = heap_tuple(heap, arity);
		tbox = peel(tuple);
		for (i = 0; i < arity; i++)
		{
			term_t e = bin2term(data, bytes_left, atoms, heap);
			if (e == noval)
				return noval;
			tbox->tuple.elts[i] = e;
		}
		return tuple;
	}
	case 106:
	{
		return nil;
	}
	case 107:
	{
		int a, b;
		int len, i;
		term_t cons = nil;
		require(2);
		a = get_byte();
		b = get_byte();
		len = ((a << 8) | b);
		require(len);
		i = len-1;
		while (i >= 0)
			cons = heap_cons2(heap, tag_int((*data)[i--]), cons);
		(*data) += len;
		return cons;
	}
	case 108:
	{
		int a, b, c, d;
		int len, i;
		term_t *es;
		term_t tail;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		len = ((a << 24) | (b << 16) | (c << 8) | d);
		es = (term_t *)heap_alloc(heap, len*sizeof(term_t));
		for (i = 0; i < len; i++)
		{
			term_t e = bin2term(data, bytes_left, atoms, heap);
			if (e == noval)
				return noval;
			es[i] = e;
		}
		tail = bin2term(data, bytes_left, atoms, heap);
		if (tail == noval)
			return noval;
		i = len-1;
		while (i >= 0)
			tail = heap_cons2(heap, es[i--], tail);
		return tail;
	}
	case 109:
	{
		int a, b, c, d;
		int len;
		term_t bin;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		len = ((a << 24) | (b << 16) | (c << 8) | d);
		require(len);
		bin = heap_binary(heap, len*8, (*data));
		(*data) += len;
		return bin;
	}
	case 110:
	{
		int len;
		int sign;
		mp_size prec;
		mp_int mp;
		mp_err rs;
		require(1);
		len = get_byte();
		sign = get_byte();
		require(len);
		prec = (len + (MP_DIGIT_SIZE-1)) / MP_DIGIT_SIZE;
		mp_init_size(&mp, prec, heap);
		//TODO: use mp_read_signed_bin
		rs = mp_read_unsigned_bin_lsb(&mp, *data, len, heap);
		if (rs != MP_OKAY)
			return noval;
		(*data) += len;
		if (sign == 1)
			mp_neg(&mp, &mp, heap);
		return mp_to_term(mp);
	}
	case 111:
	{
		int a, b, c, d;
		int len;
		int sign;
		mp_size prec;
		mp_int mp;
		mp_err rs;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		len = ((a << 24) | (b << 16) | (c << 8) | d);
		require(1);
		sign = get_byte();
		require(len);
		prec = (len + (MP_DIGIT_SIZE-1)) / MP_DIGIT_SIZE;
		mp_init_size(&mp, prec, heap);
		rs = mp_read_unsigned_bin_lsb(&mp, *data, len, heap);
		if (rs != MP_OKAY)
			return noval;
		(*data) += len;
		if (sign == 1)
			mp_neg(&mp, &mp, heap);
		return mp_to_term(mp);
	}
	default:
		return noval;	// only a subset of tags are supported; inspired by BERT
	}
}
Exemple #17
0
  Integer* Integer::from_cstr(STATE, const char* str, const char* end,
                              int base, Object* strict)
  {
    if(base == 1 || base > 36) return nil<Integer>();

    // Skip any combination of leading whitespace and underscores.  Leading
    // whitespace is OK in strict mode, but underscores are not.
    while(isspace(*str) || *str == '_') {
      if(*str == '_') {
        if(CBOOL(strict)) {
          return nil<Integer>();
        } else {
          return Fixnum::from(0);
        }
      }

      str++;
    }

    bool negative = false;

    if(*str == '-') {
      str++;
      negative = true;
    } else if(*str == '+') {
      str++;
    }

    int detected_base = 0;
    const char* str_start = str;

    /* Try to detect a base prefix. We have to do this even though we might
     * have been told the base, we have to know if we should discard the bytes
     * that make up the prefix if it's redundant with the passed in base.
     *
     * For example, if base == 16 and str == "0xa", we return 10.  But if base
     * == 10 and str == "0xa", we fail because we rewind and try to process 0x
     * as part of the base 10 string.
     */
    if(*str == '0') {
      str++;
      switch(*str++) {
      case 'b': case 'B':
        detected_base = 2;
        break;
      case 'o': case 'O':
        detected_base = 8;
        break;
      case 'd': case 'D':
        detected_base = 10;
        break;
      case 'x': case 'X':
        detected_base = 16;
        break;
      default:
        // If passed "017" and a base of 0, that is octal 15.  Otherwise, it
        // is whatever those digits would be in the specified base.
        str--;
        detected_base = 8;
      }
    }

    // If base is less than 0, then it's just a hint for how to process it
    // if there is no base detected.
    if(base < 0) {
      if(detected_base == 0) {
        // Ok, no detected because, use the base hint and start over.
        base = -base;
        str = str_start;
      } else {
        base = detected_base;
      }

    // If 0 was passed in as the base, we use the detected base.
    } else if(base == 0) {

      // Default to 10 if there is no input and no detected base.
      if(detected_base == 0) {
        base = 10;
        str = str_start;

      } else {
        base = detected_base;
      }

    // If the passed in base and the detected base contradict each other, then
    // rewind and process the whole string as digits of the passed in base.
    } else if(base != detected_base) {
      // Rewind the stream and try and consume the prefix as digits in the
      // number.
      str = str_start;
    }

    int max_digits = DIGIT_BIT / digit_bits[base];
    int count = 0;

    int digit = 0;
    mp_digit shift = base, value = 0;
    mp_int a = { 0, 0, 0, 0, 0, };

    for( ; str < end; str++) {
      digit = digit_value[int(*str)];

      if(digit >= 0 && digit < base) {
        if(++count <= max_digits) {
          value = value * base + digit;
        } else {
          if(!mp_isinitialized(&a)) {
            mp_init_set_long(XST, &a, value);
            for(int i = 0; i < max_digits - 1; i++) {
              shift *= base;
            }
          } else {
            mp_mul_d(XST, &a, shift, &a);
            mp_add_d(XST, &a, value, &a);
          }

          value = digit;
          count = 1;
        }

        continue;
      }

      // An underscore is valid iff it is followed by a valid character for
      // this base.
      if(*str == '_') {
        if(!*(str + 1) || *(str + 1) == '_') goto error_check;

        continue;
      }

      if(digit >= base) goto error_check;

      // Consume any whitespace characters.
      if(digit < -1) {
        while(digit_value[int(*++str)] < -1) /* skip whitespace */ ;

        goto error_check;
      }

      // Done parsing.
      break;
    }

error_check:

    if(str < end && CBOOL(strict)) {
      if(mp_isinitialized(&a)) mp_clear(&a);
      return nil<Integer>();
    }

    if(!mp_isinitialized(&a)) {
      if(value < FIXNUM_MAX) {
        Fixnum* result = Fixnum::from(value);
        if(negative) {
          return result->neg(state);
        } else {
          return result;
        }
      }

      mp_init_set_long(XST, &a, value);
    } else {
      shift = base;
      for(int i = 0; i < count - 1; i++) {
        shift *= base;
      }

      mp_mul_d(XST, &a, shift, &a);
      mp_add_d(XST, &a, value, &a);
    }

    if(negative) {
      mp_neg(XST, &a, &a);
    }

    Integer* result = Bignum::from(state, &a);
    mp_clear(&a);

    return result;
  }
Exemple #18
0
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
 * R can be identical. Uses affine coordinates. Assumes input is already
 * field-encoded using field_enc, and returns output that is still
 * field-encoded. */
mp_err
ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
                  mp_int *rx, mp_int *ry, const ECGroup *group)
{
    mp_err res = MP_OKAY;
    mp_int k, k3, qx, qy, sx, sy;
    int b1, b3, i, l;

    MP_DIGITS(&k) = 0;
    MP_DIGITS(&k3) = 0;
    MP_DIGITS(&qx) = 0;
    MP_DIGITS(&qy) = 0;
    MP_DIGITS(&sx) = 0;
    MP_DIGITS(&sy) = 0;
    MP_CHECKOK(mp_init(&k));
    MP_CHECKOK(mp_init(&k3));
    MP_CHECKOK(mp_init(&qx));
    MP_CHECKOK(mp_init(&qy));
    MP_CHECKOK(mp_init(&sx));
    MP_CHECKOK(mp_init(&sy));

    /* if n = 0 then r = inf */
    if (mp_cmp_z(n) == 0) {
        mp_zero(rx);
        mp_zero(ry);
        res = MP_OKAY;
        goto CLEANUP;
    }
    /* Q = P, k = n */
    MP_CHECKOK(mp_copy(px, &qx));
    MP_CHECKOK(mp_copy(py, &qy));
    MP_CHECKOK(mp_copy(n, &k));
    /* if n < 0 then Q = -Q, k = -k */
    if (mp_cmp_z(n) < 0) {
        MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth));
        MP_CHECKOK(mp_neg(&k, &k));
    }
#ifdef ECL_DEBUG /* basic double and add method */
    l = mpl_significant_bits(&k) - 1;
    MP_CHECKOK(mp_copy(&qx, &sx));
    MP_CHECKOK(mp_copy(&qy, &sy));
    for (i = l - 1; i >= 0; i--) {
        /* S = 2S */
        MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
        /* if k_i = 1, then S = S + Q */
        if (mpl_get_bit(&k, i) != 0) {
            MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
        }
    }
#else /* double and add/subtract method from \
               * standard */
    /* k3 = 3 * k */
    MP_CHECKOK(mp_set_int(&k3, 3));
    MP_CHECKOK(mp_mul(&k, &k3, &k3));
    /* S = Q */
    MP_CHECKOK(mp_copy(&qx, &sx));
    MP_CHECKOK(mp_copy(&qy, &sy));
    /* l = index of high order bit in binary representation of 3*k */
    l = mpl_significant_bits(&k3) - 1;
    /* for i = l-1 downto 1 */
    for (i = l - 1; i >= 1; i--) {
        /* S = 2S */
        MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
        b3 = MP_GET_BIT(&k3, i);
        b1 = MP_GET_BIT(&k, i);
        /* if k3_i = 1 and k_i = 0, then S = S + Q */
        if ((b3 == 1) && (b1 == 0)) {
            MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
            /* if k3_i = 0 and k_i = 1, then S = S - Q */
        } else if ((b3 == 0) && (b1 == 1)) {
            MP_CHECKOK(group->point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
        }
    }
#endif
    /* output S */
    MP_CHECKOK(mp_copy(&sx, rx));
    MP_CHECKOK(mp_copy(&sy, ry));

CLEANUP:
    mp_clear(&k);
    mp_clear(&k3);
    mp_clear(&qx);
    mp_clear(&qy);
    mp_clear(&sx);
    mp_clear(&sy);
    return res;
}