/* ARM gcc 2.95.4 was seen generating bad code for ulong->double conversions, resulting in for instance 0x81c25113 incorrectly converted. This test exercises that value, to see mpn_get_d has avoided the problem. */ void check_0x81c25113 (void) { #if GMP_NUMB_BITS >= 32 double want = 2176995603.0; double got; mp_limb_t np[4]; mp_size_t nsize; long exp; if (tests_dbl_mant_bits() < 32) return; for (nsize = 1; nsize <= numberof (np); nsize++) { refmpn_zero (np, nsize-1); np[nsize-1] = CNST_LIMB(0x81c25113); exp = - (nsize-1) * GMP_NUMB_BITS; got = mpn_get_d (np, nsize, (mp_size_t) 0, exp); if (got != want) { printf ("mpn_get_d wrong on 2176995603 (0x81c25113)\n"); printf (" nsize %ld\n", (long) nsize); printf (" exp %ld\n", exp); d_trace (" got ", got); d_trace (" want ", want); abort (); } } #endif }
void check_twobits (void) { #define TWOBITS(a, b) \ ((CNST_LIMB(1) << (a)) | (CNST_LIMB(1) << (b))) refmpn_zero (x, SIZE); x[0] = TWOBITS (1, 0); check (); refmpn_zero (x, SIZE); x[0] = TWOBITS (GMP_NUMB_BITS-1, 1); check (); refmpn_zero (x, SIZE); x[0] = CNST_LIMB(1); x[1] = CNST_LIMB(1); check (); refmpn_zero (x, SIZE); x[0] = CNST_LIMB(1) << (GMP_NUMB_BITS-1); x[1] = CNST_LIMB(1); check (); refmpn_zero (x, SIZE); x[1] = TWOBITS (1, 0); check (); refmpn_zero (x, SIZE); x[1] = CNST_LIMB(1); x[2] = CNST_LIMB(1); check (); }
/* This is unused, it takes too long, especially on 64-bit systems. */ void check_twobits_exhaustive (void) { unsigned long i, j; for (i = 0; i < GMP_NUMB_BITS * SIZE; i++) { for (j = 0; j < GMP_NUMB_BITS * SIZE; j++) { refmpn_zero (x, SIZE); refmpn_setbit (x, i); refmpn_setbit (x, j); check (); } } }
/* 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); }
/* 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 (void) { mp_limb_t wp[100], xp[100], yp[100]; mp_size_t size = 100; refmpn_zero (xp, size); refmpn_zero (yp, size); refmpn_zero (wp, size); pre ("mpn_add_n"); mpn_add_n (wp, xp, yp, size); post (); #if HAVE_NATIVE_mpn_add_nc pre ("mpn_add_nc"); mpn_add_nc (wp, xp, yp, size, CNST_LIMB(0)); post (); #endif #if HAVE_NATIVE_mpn_addlsh1_n pre ("mpn_addlsh1_n"); mpn_addlsh1_n (wp, xp, yp, size); post (); #endif #if HAVE_NATIVE_mpn_and_n pre ("mpn_and_n"); mpn_and_n (wp, xp, yp, size); post (); #endif #if HAVE_NATIVE_mpn_andn_n pre ("mpn_andn_n"); mpn_andn_n (wp, xp, yp, size); post (); #endif pre ("mpn_addmul_1"); mpn_addmul_1 (wp, xp, size, yp[0]); post (); #if HAVE_NATIVE_mpn_addmul_1c pre ("mpn_addmul_1c"); mpn_addmul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); post (); #endif #if HAVE_NATIVE_mpn_com_n pre ("mpn_com_n"); mpn_com_n (wp, xp, size); post (); #endif #if HAVE_NATIVE_mpn_copyd pre ("mpn_copyd"); mpn_copyd (wp, xp, size); post (); #endif #if HAVE_NATIVE_mpn_copyi pre ("mpn_copyi"); mpn_copyi (wp, xp, size); post (); #endif pre ("mpn_divexact_1"); mpn_divexact_1 (wp, xp, size, CNST_LIMB(123)); post (); pre ("mpn_divexact_by3c"); mpn_divexact_by3c (wp, xp, size, CNST_LIMB(0)); post (); pre ("mpn_divrem_1"); mpn_divrem_1 (wp, (mp_size_t) 0, xp, size, CNST_LIMB(123)); post (); #if HAVE_NATIVE_mpn_divrem_1c pre ("mpn_divrem_1c"); mpn_divrem_1c (wp, (mp_size_t) 0, xp, size, CNST_LIMB(123), CNST_LIMB(122)); post (); #endif pre ("mpn_gcd_1"); xp[0] |= 1; notdead += (unsigned long) mpn_gcd_1 (xp, size, CNST_LIMB(123)); post (); #if HAVE_NATIVE_mpn_gcd_finda pre ("mpn_gcd_finda"); xp[0] |= 1; xp[1] |= 1; notdead += mpn_gcd_finda (xp); post (); #endif pre ("mpn_hamdist"); notdead += mpn_hamdist (xp, yp, size); post (); #if HAVE_NATIVE_mpn_ior_n pre ("mpn_ior_n"); mpn_ior_n (wp, xp, yp, size); post (); #endif #if HAVE_NATIVE_mpn_iorn_n pre ("mpn_iorn_n"); mpn_iorn_n (wp, xp, yp, size); post (); #endif pre ("mpn_lshift"); mpn_lshift (wp, xp, size, 1); post (); pre ("mpn_mod_1"); notdead += mpn_mod_1 (xp, size, CNST_LIMB(123)); post (); #if HAVE_NATIVE_mpn_mod_1c pre ("mpn_mod_1c"); notdead += mpn_mod_1c (xp, size, CNST_LIMB(123), CNST_LIMB(122)); post (); #endif #if GMP_NUMB_BITS % 4 == 0 pre ("mpn_mod_34lsub1"); notdead += mpn_mod_34lsub1 (xp, size); post (); #endif pre ("mpn_modexact_1_odd"); notdead += mpn_modexact_1_odd (xp, size, CNST_LIMB(123)); post (); pre ("mpn_modexact_1c_odd"); notdead += mpn_modexact_1c_odd (xp, size, CNST_LIMB(123), CNST_LIMB(456)); post (); pre ("mpn_mul_1"); mpn_mul_1 (wp, xp, size, yp[0]); post (); #if HAVE_NATIVE_mpn_mul_1c pre ("mpn_mul_1c"); mpn_mul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); post (); #endif #if HAVE_NATIVE_mpn_mul_2 pre ("mpn_mul_2"); mpn_mul_2 (wp, xp, size-1, yp); post (); #endif pre ("mpn_mul_basecase"); mpn_mul_basecase (wp, xp, (mp_size_t) 3, yp, (mp_size_t) 3); post (); #if HAVE_NATIVE_mpn_nand_n pre ("mpn_nand_n"); mpn_nand_n (wp, xp, yp, size); post (); #endif #if HAVE_NATIVE_mpn_nior_n pre ("mpn_nior_n"); mpn_nior_n (wp, xp, yp, size); post (); #endif pre ("mpn_popcount"); notdead += mpn_popcount (xp, size); post (); pre ("mpn_preinv_mod_1"); notdead += mpn_preinv_mod_1 (xp, size, GMP_NUMB_MAX, refmpn_invert_limb (GMP_NUMB_MAX)); post (); #if USE_PREINV_DIVREM_1 || HAVE_NATIVE_mpn_preinv_divrem_1 pre ("mpn_preinv_divrem_1"); mpn_preinv_divrem_1 (wp, (mp_size_t) 0, xp, size, GMP_NUMB_MAX, refmpn_invert_limb (GMP_NUMB_MAX), 0); post (); #endif #if HAVE_NATIVE_mpn_rsh1add_n pre ("mpn_rsh1add_n"); mpn_rsh1add_n (wp, xp, yp, size); post (); #endif #if HAVE_NATIVE_mpn_rsh1sub_n pre ("mpn_rsh1sub_n"); mpn_rsh1sub_n (wp, xp, yp, size); post (); #endif pre ("mpn_rshift"); mpn_rshift (wp, xp, size, 1); post (); pre ("mpn_sqr_basecase"); mpn_sqr_basecase (wp, xp, (mp_size_t) 3); post (); pre ("mpn_submul_1"); mpn_submul_1 (wp, xp, size, yp[0]); post (); #if HAVE_NATIVE_mpn_submul_1c pre ("mpn_submul_1c"); mpn_submul_1c (wp, xp, size, yp[0], CNST_LIMB(0)); post (); #endif pre ("mpn_sub_n"); mpn_sub_n (wp, xp, yp, size); post (); #if HAVE_NATIVE_mpn_sub_nc pre ("mpn_sub_nc"); mpn_sub_nc (wp, xp, yp, size, CNST_LIMB(0)); post (); #endif #if HAVE_NATIVE_mpn_sublsh1_n pre ("mpn_sublsh1_n"); mpn_sublsh1_n (wp, xp, yp, size); post (); #endif #if HAVE_NATIVE_mpn_udiv_qrnnd pre ("mpn_udiv_qrnnd"); mpn_udiv_qrnnd (&wp[0], CNST_LIMB(122), xp[0], CNST_LIMB(123)); post (); #endif #if HAVE_NATIVE_mpn_udiv_qrnnd_r pre ("mpn_udiv_qrnnd_r"); mpn_udiv_qrnnd (CNST_LIMB(122), xp[0], CNST_LIMB(123), &wp[0]); post (); #endif #if HAVE_NATIVE_mpn_umul_ppmm pre ("mpn_umul_ppmm"); mpn_umul_ppmm (&wp[0], xp[0], yp[0]); post (); #endif #if HAVE_NATIVE_mpn_umul_ppmm_r pre ("mpn_umul_ppmm_r"); mpn_umul_ppmm_r (&wp[0], xp[0], yp[0]); post (); #endif #if HAVE_NATIVE_mpn_xor_n pre ("mpn_xor_n"); mpn_xor_n (wp, xp, yp, size); post (); #endif #if HAVE_NATIVE_mpn_xnor_n pre ("mpn_xnor_n"); mpn_xnor_n (wp, xp, yp, size); post (); #endif }
void check_z (void) { static const struct { const char *fmt; const char *z; const char *want; } data[] = { { "%Zd", "0", "0" }, { "%Zd", "1", "1" }, { "%Zd", "123", "123" }, { "%Zd", "-1", "-1" }, { "%Zd", "-123", "-123" }, { "%+Zd", "0", "+0" }, { "%+Zd", "123", "+123" }, { "%+Zd", "-123", "-123" }, { "%Zx", "123", "7b" }, { "%ZX", "123", "7B" }, { "%Zx", "-123", "-7b" }, { "%ZX", "-123", "-7B" }, { "%Zo", "123", "173" }, { "%Zo", "-123", "-173" }, { "%#Zx", "0", "0" }, { "%#ZX", "0", "0" }, { "%#Zx", "123", "0x7b" }, { "%#ZX", "123", "0X7B" }, { "%#Zx", "-123", "-0x7b" }, { "%#ZX", "-123", "-0X7B" }, { "%#Zo", "0", "0" }, { "%#Zo", "123", "0173" }, { "%#Zo", "-123", "-0173" }, { "%10Zd", "0", " 0" }, { "%10Zd", "123", " 123" }, { "%10Zd", "-123", " -123" }, { "%-10Zd", "0", "0 " }, { "%-10Zd", "123", "123 " }, { "%-10Zd", "-123", "-123 " }, { "%+10Zd", "123", " +123" }, { "%+-10Zd", "123", "+123 " }, { "%+10Zd", "-123", " -123" }, { "%+-10Zd", "-123", "-123 " }, { "%08Zd", "0", "00000000" }, { "%08Zd", "123", "00000123" }, { "%08Zd", "-123", "-0000123" }, { "%+08Zd", "0", "+0000000" }, { "%+08Zd", "123", "+0000123" }, { "%+08Zd", "-123", "-0000123" }, { "%#08Zx", "0", "00000000" }, { "%#08Zx", "123", "0x00007b" }, { "%#08Zx", "-123", "-0x0007b" }, { "%+#08Zx", "0", "+0000000" }, { "%+#08Zx", "123", "+0x0007b" }, { "%+#08Zx", "-123", "-0x0007b" }, { "%.0Zd", "0", "" }, { "%.1Zd", "0", "0" }, { "%.2Zd", "0", "00" }, { "%.3Zd", "0", "000" }, }; int i, j; mpz_t z; char *nfmt; mp_size_t nsize, zeros; mpz_init (z); for (i = 0; i < numberof (data); i++) { mpz_set_str_or_abort (z, data[i].z, 0); /* don't try negatives or forced sign in hex or octal */ if (mpz_fits_slong_p (z) && ! (hex_or_octal_p (data[i].fmt) && (strchr (data[i].fmt, '+') != NULL || mpz_sgn(z) < 0))) { check_plain (data[i].want, data[i].fmt, mpz_get_si (z)); } check_one (data[i].want, data[i].fmt, z); /* Same again, with %N and possibly some high zero limbs */ nfmt = __gmp_allocate_strdup (data[i].fmt); for (j = 0; nfmt[j] != '\0'; j++) if (nfmt[j] == 'Z') nfmt[j] = 'N'; for (zeros = 0; zeros <= 3; zeros++) { nsize = ABSIZ(z)+zeros; MPZ_REALLOC (z, nsize); nsize = (SIZ(z) >= 0 ? nsize : -nsize); refmpn_zero (PTR(z)+ABSIZ(z), zeros); check_one (data[i].want, nfmt, PTR(z), nsize); } __gmp_free_func (nfmt, strlen(nfmt)+1); } mpz_clear (z); }