void prime_factor_multiplicities(map_integer_uint &primes_mul, const Integer &n) { integer_class sqrtN; integer_class _n = n.as_integer_class(); unsigned count; if (_n == 0) return; if (_n < 0) _n *= -1; sqrtN = mp_sqrt(_n); auto limit = mp_get_ui(sqrtN); if (not mp_fits_ulong_p(sqrtN) or limit > std::numeric_limits<unsigned>::max()) throw SymEngineException("N too large to factor"); Sieve::iterator pi(limit); unsigned p; while ((p = pi.next_prime()) <= limit) { count = 0; while (_n % p == 0) { // when a prime factor is found, we divide ++count; // _n by that prime as much as we can _n = _n / p; } if (count > 0) { insert(primes_mul, integer(p), count); if (_n == 1) break; } } if (not(_n == 1)) insert(primes_mul, integer(std::move(_n)), 1); }
void prime_factors(std::vector<RCP<const Integer>> &prime_list, const Integer &n) { integer_class sqrtN; integer_class _n = n.as_integer_class(); if (_n == 0) return; if (_n < 0) _n *= -1; sqrtN = mp_sqrt(_n); auto limit = mp_get_ui(sqrtN); if (not mp_fits_ulong_p(sqrtN) or limit > std::numeric_limits<unsigned>::max()) throw SymEngineException("N too large to factor"); Sieve::iterator pi(limit); unsigned p; while ((p = pi.next_prime()) <= limit) { while (_n % p == 0) { prime_list.push_back(integer(p)); _n = _n / p; } if (_n == 1) break; } if (not(_n == 1)) prime_list.push_back(integer(std::move(_n))); }
void mpi_sqrt(const mpi *a, mpi *r) { ASSERT(a != r); if (a->size == 0) { mpi_zero(r); return; } const mp_size rsize = (a->size + 1) / 2; MPI_MIN_ALLOC(r, rsize); mp_sqrt(a->digits, a->size, r->digits); r->size = mp_rsize(r->digits, rsize); r->sign = a->sign; }
RCP<const Integer> isqrt(const Integer &n) { return integer(mp_sqrt(n.as_integer_class())); }
/* Store non-zero to ret if arg is square, and zero if not */ int mp_is_square(mp_int *arg,int *ret) { int res; mp_digit c; mp_int t; unsigned long r; /* Default to Non-square :) */ *ret = MP_NO; if (arg->sign == MP_NEG) { return MP_VAL; } /* digits used? (TSD) */ if (arg->used == 0) { return MP_OKAY; } /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */ if (rem_128[127 & DIGIT(arg,0)] == 1) { return MP_OKAY; } /* Next check mod 105 (3*5*7) */ if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) { return res; } if (rem_105[c] == 1) { return MP_OKAY; } /* product of primes less than 2^31 */ if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) { return res; } if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) { goto ERR; } r = mp_get_int(&t); /* Check for other prime modules, note it's not an ERROR but we must * free "t" so the easiest way is to goto ERR. We know that res * is already equal to MP_OKAY from the mp_mod call */ if ( (1L<<(r%11)) & 0x5C4L ) goto ERR; if ( (1L<<(r%13)) & 0x9E4L ) goto ERR; if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR; if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR; if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR; if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR; if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR; /* Final check - is sqr(sqrt(arg)) == arg ? */ if ((res = mp_sqrt(arg,&t)) != MP_OKAY) { goto ERR; } if ((res = mp_sqr(&t,&t)) != MP_OKAY) { goto ERR; } *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO; ERR:mp_clear(&t); return res; }
/* * Try to find the two primes based on 2 exponents plus either a prime * or a modulus. * * In: e, d and either p or n (depending on the setting of hasModulus). * Out: p,q. * * Step 1, Since d = e**-1 mod phi, we know that d*e == 1 mod phi, or * d*e = 1+k*phi, or d*e-1 = k*phi. since d is less than phi and e is * usually less than d, then k must be an integer between e-1 and 1 * (probably on the order of e). * Step 1a, If we were passed just a prime, we can divide k*phi by that * prime-1 and get k*(q-1). This will reduce the size of our division * through the rest of the loop. * Step 2, Loop through the values k=e-1 to 1 looking for k. k should be on * the order or e, and e is typically small. This may take a while for * a large random e. We are looking for a k that divides kphi * evenly. Once we find a k that divides kphi evenly, we assume it * is the true k. It's possible this k is not the 'true' k but has * swapped factors of p-1 and/or q-1. Because of this, we * tentatively continue Steps 3-6 inside this loop, and may return looking * for another k on failure. * Step 3, Calculate are tentative phi=kphi/k. Note: real phi is (p-1)*(q-1). * Step 4a, if we have a prime, kphi is already k*(q-1), so phi is or tenative * q-1. q = phi+1. If k is correct, q should be the right length and * prime. * Step 4b, It's possible q-1 and k could have swapped factors. We now have a * possible solution that meets our criteria. It may not be the only * solution, however, so we keep looking. If we find more than one, * we will fail since we cannot determine which is the correct * solution, and returning the wrong modulus will compromise both * moduli. If no other solution is found, we return the unique solution. * Step 5a, If we have the modulus (n=pq), then use the following formula to * calculate s=(p+q): , phi = (p-1)(q-1) = pq -p-q +1 = n-s+1. so * s=n-phi+1. * Step 5b, Use n=pq and s=p+q to solve for p and q as follows: * since q=s-p, then n=p*(s-p)= sp - p^2, rearranging p^2-s*p+n = 0. * from the quadratic equation we have p=1/2*(s+sqrt(s*s-4*n)) and * q=1/2*(s-sqrt(s*s-4*n)) if s*s-4*n is a perfect square, we are DONE. * If it is not, continue in our look looking for another k. NOTE: the * code actually distributes the 1/2 and results in the equations: * sqrt = sqrt(s/2*s/2-n), p=s/2+sqrt, q=s/2-sqrt. The algebra saves us * and extra divide by 2 and a multiply by 4. * * This will return p & q. q may be larger than p in the case that p was given * and it was the smaller prime. */ static mp_err rsa_get_primes_from_exponents(mp_int *e, mp_int *d, mp_int *p, mp_int *q, mp_int *n, PRBool hasModulus, unsigned int keySizeInBits) { mp_int kphi; /* k*phi */ mp_int k; /* current guess at 'k' */ mp_int phi; /* (p-1)(q-1) */ mp_int s; /* p+q/2 (s/2 in the algebra) */ mp_int r; /* remainder */ mp_int tmp; /* p-1 if p is given, n+1 is modulus is given */ mp_int sqrt; /* sqrt(s/2*s/2-n) */ mp_err err = MP_OKAY; unsigned int order_k; MP_DIGITS(&kphi) = 0; MP_DIGITS(&phi) = 0; MP_DIGITS(&s) = 0; MP_DIGITS(&k) = 0; MP_DIGITS(&r) = 0; MP_DIGITS(&tmp) = 0; MP_DIGITS(&sqrt) = 0; CHECK_MPI_OK( mp_init(&kphi) ); CHECK_MPI_OK( mp_init(&phi) ); CHECK_MPI_OK( mp_init(&s) ); CHECK_MPI_OK( mp_init(&k) ); CHECK_MPI_OK( mp_init(&r) ); CHECK_MPI_OK( mp_init(&tmp) ); CHECK_MPI_OK( mp_init(&sqrt) ); /* our algorithm looks for a factor k whose maximum size is dependent * on the size of our smallest exponent, which had better be the public * exponent (if it's the private, the key is vulnerable to a brute force * attack). * * since our factor search is linear, we need to limit the maximum * size of the public key. this should not be a problem normally, since * public keys are usually small. * * if we want to handle larger public key sizes, we should have * a version which tries to 'completely' factor k*phi (where completely * means 'factor into primes, or composites with which are products of * large primes). Once we have all the factors, we can sort them out and * try different combinations to form our phi. The risk is if (p-1)/2, * (q-1)/2, and k are all large primes. In any case if the public key * is small (order of 20 some bits), then a linear search for k is * manageable. */ if (mpl_significant_bits(e) > 23) { err=MP_RANGE; goto cleanup; } /* calculate k*phi = e*d - 1 */ CHECK_MPI_OK( mp_mul(e, d, &kphi) ); CHECK_MPI_OK( mp_sub_d(&kphi, 1, &kphi) ); /* kphi is (e*d)-1, which is the same as k*(p-1)(q-1) * d < (p-1)(q-1), therefor k must be less than e-1 * We can narrow down k even more, though. Since p and q are odd and both * have their high bit set, then we know that phi must be on order of * keySizeBits. */ order_k = (unsigned)mpl_significant_bits(&kphi) - keySizeInBits; /* for (k=kinit; order(k) >= order_k; k--) { */ /* k=kinit: k can't be bigger than kphi/2^(keySizeInBits -1) */ CHECK_MPI_OK( mp_2expt(&k,keySizeInBits-1) ); CHECK_MPI_OK( mp_div(&kphi, &k, &k, NULL)); if (mp_cmp(&k,e) >= 0) { /* also can't be bigger then e-1 */ CHECK_MPI_OK( mp_sub_d(e, 1, &k) ); } /* calculate our temp value */ /* This saves recalculating this value when the k guess is wrong, which * is reasonably frequent. */ /* for the modulus case, tmp = n+1 (used to calculate p+q = tmp - phi) */ /* for the prime case, tmp = p-1 (used to calculate q-1= phi/tmp) */ if (hasModulus) { CHECK_MPI_OK( mp_add_d(n, 1, &tmp) ); } else { CHECK_MPI_OK( mp_sub_d(p, 1, &tmp) ); CHECK_MPI_OK(mp_div(&kphi,&tmp,&kphi,&r)); if (mp_cmp_z(&r) != 0) { /* p-1 doesn't divide kphi, some parameter wasn't correct */ err=MP_RANGE; goto cleanup; } mp_zero(q); /* kphi is now k*(q-1) */ } /* rest of the for loop */ for (; (err == MP_OKAY) && (mpl_significant_bits(&k) >= order_k); err = mp_sub_d(&k, 1, &k)) { /* looking for k as a factor of kphi */ CHECK_MPI_OK(mp_div(&kphi,&k,&phi,&r)); if (mp_cmp_z(&r) != 0) { /* not a factor, try the next one */ continue; } /* we have a possible phi, see if it works */ if (!hasModulus) { if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits/2) { /* phi is not the right size */ continue; } /* phi should be divisible by 2, since * q is odd and phi=(q-1). */ if (mpp_divis_d(&phi,2) == MP_NO) { /* phi is not divisible by 4 */ continue; } /* we now have a candidate for the second prime */ CHECK_MPI_OK(mp_add_d(&phi, 1, &tmp)); /* check to make sure it is prime */ err = rsa_is_prime(&tmp); if (err != MP_OKAY) { if (err == MP_NO) { /* No, then we still have the wrong phi */ err = MP_OKAY; continue; } goto cleanup; } /* * It is possible that we have the wrong phi if * k_guess*(q_guess-1) = k*(q-1) (k and q-1 have swapped factors). * since our q_quess is prime, however. We have found a valid * rsa key because: * q is the correct order of magnitude. * phi = (p-1)(q-1) where p and q are both primes. * e*d mod phi = 1. * There is no way to know from the info given if this is the * original key. We never want to return the wrong key because if * two moduli with the same factor is known, then euclid's gcd * algorithm can be used to find that factor. Even though the * caller didn't pass the original modulus, it doesn't mean the * modulus wasn't known or isn't available somewhere. So to be safe * if we can't be sure we have the right q, we don't return any. * * So to make sure we continue looking for other valid q's. If none * are found, then we can safely return this one, otherwise we just * fail */ if (mp_cmp_z(q) != 0) { /* this is the second valid q, don't return either, * just fail */ err = MP_RANGE; break; } /* we only have one q so far, save it and if no others are found, * it's safe to return it */ CHECK_MPI_OK(mp_copy(&tmp, q)); continue; } /* test our tentative phi */ /* phi should be the correct order */ if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits) { /* phi is not the right size */ continue; } /* phi should be divisible by 4, since * p and q are odd and phi=(p-1)(q-1). */ if (mpp_divis_d(&phi,4) == MP_NO) { /* phi is not divisible by 4 */ continue; } /* n was given, calculate s/2=(p+q)/2 */ CHECK_MPI_OK( mp_sub(&tmp, &phi, &s) ); CHECK_MPI_OK( mp_div_2(&s, &s) ); /* calculate sqrt(s/2*s/2-n) */ CHECK_MPI_OK(mp_sqr(&s,&sqrt)); CHECK_MPI_OK(mp_sub(&sqrt,n,&r)); /* r as a tmp */ CHECK_MPI_OK(mp_sqrt(&r,&sqrt)); /* make sure it's a perfect square */ /* r is our original value we took the square root of */ /* q is the square of our tentative square root. They should be equal*/ CHECK_MPI_OK(mp_sqr(&sqrt,q)); /* q as a tmp */ if (mp_cmp(&r,q) != 0) { /* sigh according to the doc, mp_sqrt could return sqrt-1 */ CHECK_MPI_OK(mp_add_d(&sqrt,1,&sqrt)); CHECK_MPI_OK(mp_sqr(&sqrt,q)); if (mp_cmp(&r,q) != 0) { /* s*s-n not a perfect square, this phi isn't valid, find * another.*/ continue; } } /* NOTE: In this case we know we have the one and only answer. * "Why?", you ask. Because: * 1) n is a composite of two large primes (or it wasn't a * valid RSA modulus). * 2) If we know any number such that x^2-n is a perfect square * and x is not (n+1)/2, then we can calculate 2 non-trivial * factors of n. * 3) Since we know that n has only 2 non-trivial prime factors, * we know the two factors we have are the only possible factors. */ /* Now we are home free to calculate p and q */ /* p = s/2 + sqrt, q= s/2 - sqrt */ CHECK_MPI_OK(mp_add(&s,&sqrt,p)); CHECK_MPI_OK(mp_sub(&s,&sqrt,q)); break; } if ((unsigned)mpl_significant_bits(&k) < order_k) { if (hasModulus || (mp_cmp_z(q) == 0)) { /* If we get here, something was wrong with the parameters we * were given */ err = MP_RANGE; } } cleanup: mp_clear(&kphi); mp_clear(&phi); mp_clear(&s); mp_clear(&k); mp_clear(&r); mp_clear(&tmp); mp_clear(&sqrt); return err; }
/* Sets ret to nonzero value if arg is square, 0 if not Sets t to the square root of arg if one is available, 0 if not */ static int mp_issquare(mp_int *arg, int *ret, mp_int *t) { int res; mp_digit c; mp_int tmp; unsigned long r; /* Default to Non-square :) */ *ret = MP_NO; if (arg->sign == MP_NEG) { return MP_VAL; } /* digits used? (TSD) */ if (arg->used == 0) { return MP_OKAY; } /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */ if (rem_128[127 & DIGIT(arg, 0)] == 1) { mp_set_int(t, (mp_digit)(0)); return MP_OKAY; } /* Next check mod 105 (3*5*7) */ if ((res = mp_mod_d(arg, 105, &c)) != MP_OKAY) { mp_set_int(t, (mp_digit)(0)); return res; } if (rem_105[c] == 1) { mp_set_int(t, (mp_digit)(0)); return MP_OKAY; } if ((res = mp_init_set_int(t, 11L * 13L * 17L * 19L * 23L * 29L * 31L)) != MP_OKAY) { mp_set_int(t, (mp_digit)(0)); return res; } if ((res = mp_mod(arg, t, t)) != MP_OKAY) { goto ERR; } r = mp_get_int(t); /* Check for other prime modules. We know that res * is already equal to MP_OKAY from the mp_mod call */ if ((1L << (r % 11)) & 0x5C4L) goto ERR; if ((1L << (r % 13)) & 0x9E4L) goto ERR; if ((1L << (r % 17)) & 0x5CE8L) goto ERR; if ((1L << (r % 19)) & 0x4F50CL) goto ERR; if ((1L << (r % 23)) & 0x7ACCA0L) goto ERR; if ((1L << (r % 29)) & 0xC2EDD0CL) goto ERR; if ((1L << (r % 31)) & 0x6DE2B848L) goto ERR; /* Final check - is sqr(sqrt(arg)) == arg ? */ if ((res = mp_sqrt(arg, t)) != MP_OKAY) { goto ERR; } mp_init(&tmp); if ((res = mp_sqr(t, &tmp)) != MP_OKAY) { goto ERR; } *ret = (mp_cmp_mag(&tmp, arg) == MP_EQ) ? MP_YES : MP_NO; mp_clear(&tmp); return res; ERR: mp_set_int(t, (mp_digit)(0)); mp_clear(&tmp); return res; }
int main(void) { mp_int a, b, c, d, e, f; 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, t; unsigned rr; int i, n, err, cnt, ix, old_kara_m, old_kara_s; mp_digit mp; mp_init(&a); mp_init(&b); mp_init(&c); mp_init(&d); mp_init(&e); mp_init(&f); srand(time(NULL)); #if 0 // test montgomery printf("Testing montgomery...\n"); for (i = 1; i < 10; i++) { printf("Testing digit size: %d\n", i); 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"); exit(EXIT_FAILURE); } } } } printf("done\n"); // test mp_get_int printf("Testing: mp_get_int\n"); 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("mp_get_int() bad result!\n"); return 1; } } mp_set_int(&a, 0); if (mp_get_int(&a) != 0) { printf("mp_get_int() bad result!\n"); return 1; } mp_set_int(&a, 0xffffffff); if (mp_get_int(&a) != 0xffffffff) { printf("mp_get_int() bad result!\n"); return 1; } // test mp_sqrt printf("Testing: 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("mp_sqrt() error!\n"); return 1; } mp_n_root(&a, 2, &a); if (mp_cmp_mag(&b, &a) != MP_EQ) { printf("mp_sqrt() bad result!\n"); return 1; } } printf("\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("fn:mp_is_square() error!\n"); return 1; } if (n == 0) { printf("fn:mp_is_square() bad result!\n"); return 1; } /* test for false positives */ mp_add_d(&a, 1, &a); if (mp_is_square(&a, &n) != MP_OKAY) { printf("fp:mp_is_square() error!\n"); return 1; } if (n == 1) { printf("fp:mp_is_square() bad result!\n"); return 1; } } printf("\n\n"); /* 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) ? LTM_PRIME_2MSB_OFF : 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; } } 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) ? LTM_PRIME_2MSB_OFF : 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"); 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("testing mp_cnt_lsb...\n"); 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 0; } mp_mul_2(&a, &a); } /* test mp_reduce_2k */ printf("Testing 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("\nTesting %4d bits", cnt); printf("(%d)", mp_reduce_is_2k(&a)); mp_reduce_2k_setup(&a, &tmp); printf("(%d)", 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"); exit(0); } } } /* test mp_div_3 */ printf("Testing mp_div_3...\n"); mp_set(&d, 3); for (cnt = 0; cnt < 10000;) { mp_digit r1, r2; if (!(++cnt & 127)) printf("%9d\r", cnt); 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("\n\nmp_div_3 => Failure\n"); } } printf("\n\nPassed div_3 testing\n"); /* test the DR reduction */ printf("testing mp_dr_reduce...\n"); for (cnt = 2; cnt < 32; cnt++) { printf("%d digit modulus\n", 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("%9lu\r", rr); fflush(stdout); } mp_sqr(&b, &b); mp_add_d(&b, 1, &b); mp_copy(&b, &c); mp_mod(&b, &a, &b); mp_dr_reduce(&c, &a, (((mp_digit) 1) << DIGIT_BIT) - a.dp[0]); if (mp_cmp(&b, &c) != MP_EQ) { printf("Failed on trial %lu\n", rr); exit(-1); } } while (++rr < 500); printf("Passed DR test for %d digits\n", cnt); } #endif /* test the mp_reduce_2k_l code */ #if 0 #if 0 /* 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 1 /* 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); #endif mp_todecimal(&a, buf); printf("p==%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 < (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 %lu\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 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); fgets(cmd, 4095, stdin); cmd[strlen(cmd) - 1] = 0; printf("%s ]\r", cmd); fflush(stdout); if (!strcmp(cmd, "mul2d")) { ++mul2d_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); sscanf(buf, "%d", &rr); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "div2d")) { ++div2d_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); sscanf(buf, "%d", &rr); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "add")) { ++add_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64); fgets(buf, 4095, stdin); 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 0; } /* 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 0; } 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 0; } } else if (!strcmp(cmd, "sub")) { ++sub_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "mul")) { ++mul_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "div")) { ++div_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&c, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "sqr")) { ++sqr_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "gcd")) { ++gcd_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "lcm")) { ++lcm_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "expt")) { ++expt_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&c, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "invmod")) { ++inv_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); mp_read_radix(&b, buf, 64); fgets(buf, 4095, stdin); 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); mp_gcd(&a, &b, &e); draw(&e); return 0; } } else if (!strcmp(cmd, "div2")) { ++div2_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "mul2")) { ++mul2_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "add_d")) { ++add_d_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); sscanf(buf, "%d", &ix); fgets(buf, 4095, stdin); 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 0; } } else if (!strcmp(cmd, "sub_d")) { ++sub_d_n; fgets(buf, 4095, stdin); mp_read_radix(&a, buf, 64); fgets(buf, 4095, stdin); sscanf(buf, "%d", &ix); fgets(buf, 4095, stdin); 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 0; } } } return 0; }
int main() { int nfft, log2_nfft, radix, log10_radix, n, npow, nprc; double err, d_time, n_op; int *a, *b, *c, *e, *i1, *i2, *ip; double *d1, *d2, *d3, *w; time_t t_1, t_2; FILE *f_log, *f_out; f_log = fopen("pi.log", "w"); printf("PI calculation to estimate the FFT benchmarks\n"); fprintf(f_log, "PI calculation to estimate the FFT benchmarks\n"); printf("length of FFT =?\n"); scanf("%d", &nfft); printf("initializing...\n"); for (log2_nfft = 1; (1 << log2_nfft) < nfft; log2_nfft++); nfft = 1 << log2_nfft; n = nfft + 2; ip = (int *) malloc((3 + (int) sqrt(0.5 * nfft)) * sizeof(int)); w = (double *) malloc(nfft / 2 * sizeof(double)); a = (int *) malloc((n + 2) * sizeof(int)); b = (int *) malloc((n + 2) * sizeof(int)); c = (int *) malloc((n + 2) * sizeof(int)); e = (int *) malloc((n + 2) * sizeof(int)); i1 = (int *) malloc((n + 2) * sizeof(int)); i2 = (int *) malloc((n + 2) * sizeof(int)); d1 = (double *) malloc((nfft + 2) * sizeof(double)); d2 = (double *) malloc((nfft + 2) * sizeof(double)); d3 = (double *) malloc((nfft + 2) * sizeof(double)); if (d3 == NULL) { printf("Allocation Failure!\n"); exit(1); } ip[0] = 0; /* ---- radix test ---- */ log10_radix = 1; radix = 10; err = mp_mul_radix_test(n, radix, nfft, d1, ip, w); err += DBL_EPSILON * (n * radix * radix / 4); while (100 * err < DBL_ERROR_MARGIN && radix <= INT_MAX / 20) { err *= 100; log10_radix++; radix *= 10; } printf("nfft= %d\nradix= %d\nerror_margin= %g\n", nfft, radix, err); fprintf(f_log, "nfft= %d\nradix= %d\nerror_margin= %g\n", nfft, radix, err); printf("calculating %d digits of PI...\n", log10_radix * (n - 2)); fprintf(f_log, "calculating %d digits of PI...\n", log10_radix * (n - 2)); /* ---- time check ---- */ time(&t_1); /* * ---- a formula based on the AGM (Arithmetic-Geometric Mean) ---- * c = sqrt(0.125); * a = 1 + 3 * c; * b = sqrt(a); * e = b - 0.625; * b = 2 * b; * c = e - c; * a = a + e; * npow = 4; * do { * npow = 2 * npow; * e = (a + b) / 2; * b = sqrt(a * b); * e = e - b; * b = 2 * b; * c = c - e; * a = e + b; * } while (e > SQRT_SQRT_EPSILON); * e = e * e / 4; * a = a + b; * pi = (a * a - e - e / 2) / (a * c - e) / npow; * ---- modification ---- * This is a modified version of Gauss-Legendre formula * (by T.Ooura). It is faster than original version. * ---- reference ---- * 1. E.Salamin, * Computation of PI Using Arithmetic-Geometric Mean, * Mathematics of Computation, Vol.30 1976. * 2. R.P.Brent, * Fast Multiple-Precision Evaluation of Elementary Functions, * J. ACM 23 1976. * 3. D.Takahasi, Y.Kanada, * Calculation of PI to 51.5 Billion Decimal Digits on * Distributed Memoriy Parallel Processors, * Transactions of Information Processing Society of Japan, * Vol.39 No.7 1998. * 4. T.Ooura, * Improvement of the PI Calculation Algorithm and * Implementation of Fast Multiple-Precision Computation, * Information Processing Society of Japan SIG Notes, * 98-HPC-74, 1998. */ /* ---- c = sqrt(0.125) ---- */ mp_sscanf(n, log10_radix, "0.125", a); mp_sqrt(n, radix, a, c, i1, i2, nfft, d1, d2, ip, w); /* ---- a = 1 + 3 * c ---- */ mp_imul(n, radix, c, 3, e); mp_sscanf(n, log10_radix, "1", a); mp_add(n, radix, a, e, a); /* ---- b = sqrt(a) ---- */ mp_sqrt(n, radix, a, b, i1, i2, nfft, d1, d2, ip, w); /* ---- e = b - 0.625 ---- */ mp_sscanf(n, log10_radix, "0.625", e); mp_sub(n, radix, b, e, e); /* ---- b = 2 * b ---- */ mp_add(n, radix, b, b, b); /* ---- c = e - c ---- */ mp_sub(n, radix, e, c, c); /* ---- a = a + e ---- */ mp_add(n, radix, a, e, a); printf("AGM iteration\n"); fprintf(f_log, "AGM iteration\n"); npow = 4; do { npow *= 2; /* ---- e = (a + b) / 2 ---- */ mp_add(n, radix, a, b, e); mp_idiv_2(n, radix, e, e); /* ---- b = sqrt(a * b) ---- */ mp_mul(n, radix, a, b, a, i1, nfft, d1, d2, d3, ip, w); mp_sqrt(n, radix, a, b, i1, i2, nfft, d1, d2, ip, w); /* ---- e = e - b ---- */ mp_sub(n, radix, e, b, e); /* ---- b = 2 * b ---- */ mp_add(n, radix, b, b, b); /* ---- c = c - e ---- */ mp_sub(n, radix, c, e, c); /* ---- a = e + b ---- */ mp_add(n, radix, e, b, a); /* ---- convergence check ---- */ nprc = -e[1]; if (e[0] == 0) { nprc = n; } printf("precision= %d\n", 4 * nprc * log10_radix); fprintf(f_log, "precision= %d\n", 4 * nprc * log10_radix); } while (4 * nprc <= n); /* ---- e = e * e / 4 (half precision) ---- */ mp_idiv_2(n, radix, e, e); mp_squh(n, radix, e, e, nfft, d1, ip, w); /* ---- a = a + b ---- */ mp_add(n, radix, a, b, a); /* ---- a = (a * a - e - e / 2) / (a * c - e) / npow ---- */ mp_mul(n, radix, a, c, c, i1, nfft, d1, d2, d3, ip, w); mp_sub(n, radix, c, e, c); mp_inv(n, radix, c, b, i1, i2, nfft, d1, d2, ip, w); mp_squ(n, radix, a, a, i1, nfft, d1, d2, ip, w); mp_sub(n, radix, a, e, a); mp_idiv_2(n, radix, e, e); mp_sub(n, radix, a, e, a); mp_mul(n, radix, a, b, a, i1, nfft, d1, d2, d3, ip, w); mp_idiv(n, radix, a, npow, a); /* ---- time check ---- */ time(&t_2); /* ---- output ---- */ f_out = fopen("pi.dat", "w"); printf("writing pi.dat...\n"); mp_fprintf(n - 1, log10_radix, a, f_out); fclose(f_out); free(d3); free(d2); free(d1); free(i2); free(i1); free(e); free(c); free(b); free(a); free(w); free(ip); /* ---- benchmark ---- */ n_op = 50.0 * nfft * log2_nfft * log2_nfft; printf("floating point operation: %g op.\n", n_op); fprintf(f_log, "floating point operation: %g op.\n", n_op); /* ---- difftime ---- */ d_time = difftime(t_2, t_1); printf("execution time: %g sec. (real time)\n", d_time); fprintf(f_log, "execution time: %g sec. (real time)\n", d_time); fclose(f_log); return 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; }
int main(int argc, char *argv[]) { int ix; mp_int a, b, c, d; mp_digit r; mp_err res; if(argc < 3) { fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]); return 1; } printf("Test 3: Multiplication and division\n\n"); srand(time(NULL)); mp_init(&a); mp_init(&b); mp_read_radix(&a, argv[1], 10); mp_read_radix(&b, argv[2], 10); printf("a = "); mp_print(&a, stdout); fputc('\n', stdout); printf("b = "); mp_print(&b, stdout); fputc('\n', stdout); mp_init(&c); printf("\nc = a * b\n"); mp_mul(&a, &b, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = b * 32523\n"); mp_mul_d(&b, 32523, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); mp_init(&d); printf("\nc = a / b, d = a mod b\n"); mp_div(&a, &b, &c, &d); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("d = "); mp_print(&d, stdout); fputc('\n', stdout); ix = rand() % 256; printf("\nc = a / %d, r = a mod %d\n", ix, ix); mp_div_d(&a, (mp_digit)ix, &c, &r); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("r = %04X\n", r); #if EXPT printf("\nc = a ** b\n"); mp_expt(&a, &b, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); #endif ix = rand() % 256; printf("\nc = 2^%d\n", ix); mp_2expt(&c, ix); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); #if SQRT printf("\nc = sqrt(a)\n"); if((res = mp_sqrt(&a, &c)) != MP_OKAY) { printf("mp_sqrt: %s\n", mp_strerror(res)); } else { printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); mp_sqr(&c, &c); printf("c^2 = "); mp_print(&c, stdout); fputc('\n', stdout); } #endif mp_clear(&d); mp_clear(&c); mp_clear(&b); mp_clear(&a); return 0; }