/* Print "name=value\n" to stdout for a limb, nail doesn't have to be zero. */ void mp_limb_trace (const char *name, mp_limb_t n) { #if GMP_NAIL_BITS != 0 mp_limb_t a[2]; a[0] = n & GMP_NUMB_MASK; a[1] = n >> GMP_NUMB_BITS; mpn_trace (name, a, (mp_size_t) 2); #else mpn_trace (name, &n, (mp_size_t) 1); #endif }
void check_data (void) { static const struct { double d; mp_size_t want_size; mp_limb_t want_data[2]; } data[] = { { 0.0, 0 }, { 1.0, 1, { 1 } }, { -1.0, -1, { 1 } }, { 123.0, 1, { 123 } }, { -123.0, -1, { 123 } }, }; mpz_t z; int i; for (i = 0; i < numberof (data); i++) { mpz_init (z); mpz_set_d (z, data[i].d); MPZ_CHECK_FORMAT (z); if (z->_mp_size != data[i].want_size || refmpn_cmp_allowzero (z->_mp_d, data[i].want_data, ABS (data[i].want_size)) != 0) { printf ("mpz_set_d wrong on data[%d]\n", i); bad: d_trace (" d ", data[i].d); printf (" got size %ld\n", (long) z->_mp_size); printf (" want size %ld\n", (long) data[i].want_size); mpn_trace (" got z", z->_mp_d, z->_mp_size); mpn_trace (" want z", data[i].want_data, data[i].want_size); abort(); } mpz_clear (z); mpz_init_set_d (z, data[i].d); MPZ_CHECK_FORMAT (z); if (z->_mp_size != data[i].want_size || refmpn_cmp_allowzero (z->_mp_d, data[i].want_data, ABS (data[i].want_size)) != 0) { printf ("mpz_init_set_d wrong on data[%d]\n", i); goto bad; } mpz_clear (z); } }
void check_print (mpf_srcptr src, mpf_srcptr got, mpf_srcptr want) { mp_trace_base = 16; mpf_trace ("src ", src); mpf_trace ("got ", got); mpf_trace ("want", want); printf ("got size=%d exp=%ld\n", SIZ(got), EXP(got)); mpn_trace (" limbs=", PTR(got), (mp_size_t) ABSIZ(got)); printf ("want size=%d exp=%ld\n", SIZ(want), EXP(want)); mpn_trace (" limbs=", PTR(want), (mp_size_t) ABSIZ(want)); }
void check_one (const char *name, int i, mp_srcptr src, mp_limb_t n, mp_srcptr got, mp_srcptr want, mp_size_t size) { if (! refmpn_equal_anynail (got, want, size)) { printf ("Wrong at %s i=%d\n", name, i); mpn_trace (" src", src, size); mpn_trace (" n", &n, (mp_size_t) 1); mpn_trace (" got", got, size); mpn_trace (" want", want, size); abort (); } }
/* Print "namenum=value\n" to stdout for an mpn style ptr,size. "name" should have a "%d" to get the number. */ void mpn_tracen (const char *name, int num, mp_srcptr ptr, mp_size_t size) { if (name != NULL && name[0] != '\0') { printf (name, num); putchar ('='); } mpn_trace (NULL, ptr, size); }
void check (void) { unsigned long i, got, want; x[SIZE] = 1; for (i = 0; i < SIZE*GMP_NUMB_BITS; i++) { got = refmpn_scan1 (x, i); want = mpn_scan1 (x, i); if (got != want) { printf ("mpn_scan1\n"); printf (" i %lu\n", i); printf (" got %lu\n", got); printf (" want %lu\n", want); mpn_trace (" x ", x, SIZE); abort (); } } x[SIZE] = 0; for (i = 0; i < SIZE*GMP_NUMB_BITS; i++) { got = refmpn_scan0 (x, i); want = mpn_scan0 (x, i); if (got != want) { printf ("mpn_scan0\n"); printf (" i %lu\n", i); printf (" got %lu\n", got); printf (" want %lu\n", want); mpn_trace (" x ", x, SIZE); abort (); } } }
/* Exercise values 2^n+1, while such a value fits the mantissa of a double. */ void check_twobit (void) { int i, mant_bits; double got, want; mp_size_t nsize, sign; mp_ptr np; mant_bits = tests_dbl_mant_bits (); if (mant_bits == 0) return; np = refmpn_malloc_limbs (BITS_TO_LIMBS (mant_bits)); want = 3.0; for (i = 1; i < mant_bits; i++) { nsize = BITS_TO_LIMBS (i+1); refmpn_zero (np, nsize); np[i/GMP_NUMB_BITS] = CNST_LIMB(1) << (i % GMP_NUMB_BITS); np[0] |= 1; for (sign = 0; sign >= -1; sign--) { got = mpn_get_d (np, nsize, sign, 0); if (got != want) { printf ("mpn_get_d wrong on 2^%d + 1\n", i); printf (" sign %ld\n", (long) sign); mpn_trace (" n ", np, nsize); printf (" nsize %ld\n", (long) nsize); d_trace (" want ", want); d_trace (" got ", got); abort(); } want = -want; } want = 2.0 * want - 1.0; } free (np); }
void verify (const char *name, int i, mp_srcptr src, mp_limb_t n, mp_limb_t got_c, mp_limb_t want_c, mp_srcptr got, mp_srcptr want, mp_size_t size) { if (got[size] != MAGIC) { printf ("Overwrite at %s i=%d\n", name, i); abort (); } if (got_c != want_c || ! refmpn_equal_anynail (got, want, size)) { printf ("Wrong at %s i=%d size=%ld\n", name, i, size); mpn_trace (" src", src, size); mpn_trace (" n", &n, (mp_size_t) 1); mpn_trace (" got", got, size); mpn_trace (" want", want, size); mpn_trace (" got c", &got_c, (mp_size_t) 1); mpn_trace ("want c", &want_c, (mp_size_t) 1); abort (); } }
void check_limbdata (void) { #define M GMP_NUMB_MAX static const struct { mp_exp_t exp; mp_size_t size; mp_limb_t d[10]; unsigned long want; } data[] = { /* in the comments here, a "_" indicates a digit (ie. limb) position not included in the d data, and therefore zero */ { 0, 0, { 0 }, 0L }, /* 0 */ { 1, 1, { 1 }, 1L }, /* 1 */ { 1, -1, { 1 }, -1L }, /* -1 */ { 0, 1, { 1 }, 0L }, /* .1 */ { 0, -1, { 1 }, 0L }, /* -.1 */ { -1, 1, { 1 }, 0L }, /* ._1 */ { -1, -1, { 1 }, 0L }, /* -._1 */ { -999, 1, { 1 }, 0L }, /* .___1 small */ { MP_EXP_T_MIN, 1, { 1 }, 0L }, /* .____1 very small */ { 999, 1, { 1 }, 0L }, /* 1____. big */ { MP_EXP_T_MAX, 1, { 1 }, 0L }, /* 1_____. very big */ { 1, 2, { 999, 2 }, 2L }, /* 2.9 */ { 5, 8, { 7, 8, 9, 3, 0, 0, 0, 1 }, 3L }, /* 10003.987 */ { 2, 2, { M, M }, LONG_MAX }, /* FF. */ { 2, 2, { M, M, M }, LONG_MAX }, /* FF.F */ { 3, 3, { M, M, M }, LONG_MAX }, /* FFF. */ #if GMP_NUMB_BITS >= BITS_PER_ULONG /* normal case, numb bigger than long */ { 2, 1, { 1 }, 0L }, /* 1_. */ { 2, 2, { 0, 1 }, 0L }, /* 10. */ { 2, 2, { 999, 1 }, 999L }, /* 19. */ { 3, 2, { 999, 1 }, 0L }, /* 19_. */ #else /* nails case, numb smaller than long */ { 2, 1, { 1 }, 1L << GMP_NUMB_BITS }, /* 1_. */ { 3, 1, { 1 }, 0L }, /* 1__. */ { 2, 2, { 99, 1 }, 99L + (1L << GMP_NUMB_BITS) }, /* 19. */ { 3, 2, { 1, 99 }, 1L << GMP_NUMB_BITS }, /* 91_. */ { 3, 3, { 0, 1, 99 }, 1L << GMP_NUMB_BITS }, /* 910. */ #endif }; mpf_t f; unsigned long got; int i; mp_limb_t buf[20 + numberof(data[i].d)]; for (i = 0; i < numberof (data); i++) { refmpn_fill (buf, 10, CNST_LIMB(0xDEADBEEF)); refmpn_copy (buf+10, data[i].d, ABS(data[i].size)); refmpn_fill (buf+10+ABS(data[i].size), 10, CNST_LIMB(0xDEADBEEF)); PTR(f) = buf+10; EXP(f) = data[i].exp; SIZ(f) = data[i].size; PREC(f) = numberof (data[i].d); MPF_CHECK_FORMAT (f); got = mpf_get_si (f); if (got != data[i].want) { printf ("mpf_get_si wrong at limb data[%d]\n", i); mpf_trace (" f", f); mpn_trace (" d", data[i].d, data[i].size); printf (" size %ld\n", (long) data[i].size); printf (" exp %ld\n", (long) data[i].exp); printf (" got %lu (0x%lX)\n", got, got); printf (" want %lu (0x%lX)\n", data[i].want, data[i].want); abort(); } } }
/* Exercise various 2^n values, with various exponents and positive and negative. */ void check_onebit (void) { static const int bit_table[] = { 0, 1, 2, 3, GMP_NUMB_BITS - 2, GMP_NUMB_BITS - 1, GMP_NUMB_BITS, GMP_NUMB_BITS + 1, GMP_NUMB_BITS + 2, 2 * GMP_NUMB_BITS - 2, 2 * GMP_NUMB_BITS - 1, 2 * GMP_NUMB_BITS, 2 * GMP_NUMB_BITS + 1, 2 * GMP_NUMB_BITS + 2, 3 * GMP_NUMB_BITS - 2, 3 * GMP_NUMB_BITS - 1, 3 * GMP_NUMB_BITS, 3 * GMP_NUMB_BITS + 1, 3 * GMP_NUMB_BITS + 2, 4 * GMP_NUMB_BITS - 2, 4 * GMP_NUMB_BITS - 1, 4 * GMP_NUMB_BITS, 4 * GMP_NUMB_BITS + 1, 4 * GMP_NUMB_BITS + 2, 5 * GMP_NUMB_BITS - 2, 5 * GMP_NUMB_BITS - 1, 5 * GMP_NUMB_BITS, 5 * GMP_NUMB_BITS + 1, 5 * GMP_NUMB_BITS + 2, 6 * GMP_NUMB_BITS - 2, 6 * GMP_NUMB_BITS - 1, 6 * GMP_NUMB_BITS, 6 * GMP_NUMB_BITS + 1, 6 * GMP_NUMB_BITS + 2, }; static const int exp_table[] = { 0, -100, -10, -1, 1, 10, 100, }; /* FIXME: It'd be better to base this on the float format. */ int limit = 511; int bit_i, exp_i, i; double got, want; mp_size_t nsize, sign; long bit, exp, want_bit; mp_limb_t np[20]; for (bit_i = 0; bit_i < numberof (bit_table); bit_i++) { bit = bit_table[bit_i]; nsize = BITS_TO_LIMBS (bit+1); refmpn_zero (np, nsize); np[bit/GMP_NUMB_BITS] = CNST_LIMB(1) << (bit % GMP_NUMB_BITS); for (exp_i = 0; exp_i < numberof (exp_table); exp_i++) { exp = exp_table[exp_i]; want_bit = bit + exp; if (want_bit > limit || want_bit < -limit) continue; want = 1.0; for (i = 0; i < want_bit; i++) want *= 2.0; for (i = 0; i > want_bit; i--) want *= 0.5; for (sign = 0; sign >= -1; sign--, want = -want) { got = mpn_get_d (np, nsize, sign, exp); if (got != want) { printf ("mpn_get_d wrong on 2^n\n"); printf (" bit %ld\n", bit); printf (" exp %ld\n", exp); printf (" want_bit %ld\n", want_bit); printf (" sign %ld\n", (long) sign); mpn_trace (" n ", np, nsize); printf (" nsize %ld\n", (long) nsize); d_trace (" want ", want); d_trace (" got ", got); abort(); } } } } }
void check_rand (void) { gmp_randstate_t rands; int rep, i; unsigned long mant_bits; long exp, exp_min, exp_max; double got, want, d; mp_size_t nalloc, nsize, sign; mp_limb_t nhigh_mask; mp_ptr np; gmp_randinit_default(rands); mant_bits = tests_dbl_mant_bits (); if (mant_bits == 0) return; /* Allow for vax D format with exponent 127 to -128 only. FIXME: Do something to probe for a valid exponent range. */ exp_min = -100 - mant_bits; exp_max = 100 - mant_bits; /* space for mant_bits */ nalloc = BITS_TO_LIMBS (mant_bits); np = refmpn_malloc_limbs (nalloc); nhigh_mask = MP_LIMB_T_MAX >> (GMP_NAIL_BITS + nalloc * GMP_NUMB_BITS - mant_bits); for (rep = 0; rep < 200; rep++) { /* random exp_min to exp_max, inclusive */ exp = exp_min + (long) gmp_urandomm_ui (rands, exp_max - exp_min + 1); /* mant_bits worth of random at np */ if (rep & 1) mpn_randomb (np, rands, nalloc); else mpn_rrandom (np, rands,nalloc); nsize = nalloc; np[nsize-1] &= nhigh_mask; MPN_NORMALIZE (np, nsize); if (nsize == 0) continue; sign = (mp_size_t) gmp_urandomb_ui (rands, 1L) - 1; /* want = {np,nsize}, converting one bit at a time */ want = 0.0; for (i = 0, d = 1.0; i < mant_bits; i++, d *= 2.0) if (np[i/GMP_NUMB_BITS] & (CNST_LIMB(1) << (i%GMP_NUMB_BITS))) want += d; if (sign < 0) want = -want; /* want = want * 2^exp */ for (i = 0; i < exp; i++) want *= 2.0; for (i = 0; i > exp; i--) want *= 0.5; got = mpn_get_d (np, nsize, sign, exp); if (got != want) { printf ("mpn_get_d wrong on random data\n"); printf (" sign %ld\n", (long) sign); mpn_trace (" n ", np, nsize); printf (" nsize %ld\n", (long) nsize); printf (" exp %ld\n", exp); d_trace (" want ", want); d_trace (" got ", got); abort(); } } free (np); gmp_randclear(rands); }
void check_data (void) { static const struct { mp_limb_t n[1]; mp_size_t nsize; mp_limb_t d; mp_size_t qxn; mp_limb_t want_q[5]; mp_limb_t want_r; } data[] = { { { 0 }, 1, 1, 0, { 0 }, 0}, { { 5 }, 1, 2, 0, { 2 }, 1}, #if GMP_NUMB_BITS == 32 { { 0x3C }, 1, 0xF2, 1, { 0x3F789854, 0 }, 0x98 }, #endif #if GMP_NUMB_BITS == 64 { { 0x3C }, 1, 0xF2, 1, { CNST_LIMB(0x3F789854A0CB1B81), 0 }, 0x0E }, /* This case exposed some wrong code generated by SGI cc on mips64 irix 6.5 with -n32 -O2, in the fractional loop for normalized divisor using udiv_qrnnd_preinv. A test "x>al" in one of the sub_ddmmss expansions came out wrong, leading to an incorrect quotient. */ { { CNST_LIMB(0x3C00000000000000) }, 1, CNST_LIMB(0xF200000000000000), 1, { CNST_LIMB(0x3F789854A0CB1B81), 0 }, CNST_LIMB(0x0E00000000000000) }, #endif }; mp_limb_t dinv, got_r, got_q[numberof(data[0].want_q)]; mp_size_t qsize; int i, shift; for (i = 0; i < numberof (data); i++) { qsize = data[i].nsize + data[i].qxn; ASSERT_ALWAYS (qsize <= numberof (got_q)); got_r = mpn_divrem_1 (got_q, data[i].qxn, data[i].n, data[i].nsize, data[i].d); if (got_r != data[i].want_r || refmpn_cmp (got_q, data[i].want_q, qsize) != 0) { printf ("mpn_divrem_1 wrong at data[%d]\n", i); bad: mpn_trace (" n", data[i].n, data[i].nsize); printf (" nsize=%ld\n", (long) data[i].nsize); mp_limb_trace (" d", data[i].d); printf (" qxn=%ld\n", (long) data[i].qxn); mpn_trace (" want q", data[i].want_q, qsize); mpn_trace (" got q", got_q, qsize); mp_limb_trace (" want r", data[i].want_r); mp_limb_trace (" got r", got_r); abort (); } /* test if available */ #if USE_PREINV_DIVREM_1 || HAVE_NATIVE_mpn_preinv_divrem_1 shift = refmpn_count_leading_zeros (data[i].d); dinv = refmpn_invert_limb (data[i].d << shift); got_r = mpn_preinv_divrem_1 (got_q, data[i].qxn, data[i].n, data[i].nsize, data[i].d, dinv, shift); if (got_r != data[i].want_r || refmpn_cmp (got_q, data[i].want_q, qsize) != 0) { printf ("mpn_preinv divrem_1 wrong at data[%d]\n", i); printf (" shift=%d\n", shift); mp_limb_trace (" dinv", dinv); goto bad; } #endif } }