1 1.1 mrg /* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr_ui, mpz_fdiv_q_ui, 2 1.1 mrg mpz_fdiv_r_ui, mpz_fdiv_ui, mpz_mul_ui. 3 1.1 mrg 4 1.1.1.3 mrg Copyright 1993, 1994, 1996, 2000-2002 Free Software Foundation, Inc. 5 1.1 mrg 6 1.1.1.2 mrg This file is part of the GNU MP Library test suite. 7 1.1 mrg 8 1.1.1.2 mrg The GNU MP Library test suite is free software; you can redistribute it 9 1.1.1.2 mrg and/or modify it under the terms of the GNU General Public License as 10 1.1.1.2 mrg published by the Free Software Foundation; either version 3 of the License, 11 1.1.1.2 mrg or (at your option) any later version. 12 1.1.1.2 mrg 13 1.1.1.2 mrg The GNU MP Library test suite is distributed in the hope that it will be 14 1.1.1.2 mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1.1.2 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 16 1.1.1.2 mrg Public License for more details. 17 1.1 mrg 18 1.1.1.2 mrg You should have received a copy of the GNU General Public License along with 19 1.1.1.3 mrg the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 20 1.1 mrg 21 1.1 mrg #include <stdio.h> 22 1.1 mrg #include <stdlib.h> 23 1.1 mrg 24 1.1 mrg #include "gmp-impl.h" 25 1.1 mrg #include "tests.h" 26 1.1 mrg 27 1.1.1.2 mrg void dump_abort (const char *, mpz_t, unsigned long); 28 1.1.1.2 mrg void debug_mp (mpz_t, int); 29 1.1 mrg 30 1.1 mrg int 31 1.1 mrg main (int argc, char **argv) 32 1.1 mrg { 33 1.1 mrg mpz_t dividend; 34 1.1 mrg mpz_t quotient, remainder; 35 1.1 mrg mpz_t quotient2, remainder2; 36 1.1 mrg mpz_t temp; 37 1.1 mrg mp_size_t dividend_size; 38 1.1 mrg unsigned long divisor; 39 1.1 mrg int i; 40 1.1 mrg int reps = 10000; 41 1.1 mrg gmp_randstate_ptr rands; 42 1.1 mrg mpz_t bs; 43 1.1 mrg unsigned long bsi, size_range; 44 1.1 mrg unsigned long r_rq, r_q, r_r, r; 45 1.1 mrg 46 1.1 mrg tests_start (); 47 1.1 mrg rands = RANDS; 48 1.1 mrg 49 1.1 mrg mpz_init (bs); 50 1.1 mrg 51 1.1 mrg if (argc == 2) 52 1.1 mrg reps = atoi (argv[1]); 53 1.1 mrg 54 1.1 mrg mpz_init (dividend); 55 1.1 mrg mpz_init (quotient); 56 1.1 mrg mpz_init (remainder); 57 1.1 mrg mpz_init (quotient2); 58 1.1 mrg mpz_init (remainder2); 59 1.1 mrg mpz_init (temp); 60 1.1 mrg 61 1.1 mrg for (i = 0; i < reps; i++) 62 1.1 mrg { 63 1.1 mrg mpz_urandomb (bs, rands, 32); 64 1.1 mrg size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */ 65 1.1 mrg 66 1.1 mrg do 67 1.1 mrg { 68 1.1 mrg mpz_rrandomb (bs, rands, 64); 69 1.1 mrg divisor = mpz_get_ui (bs); 70 1.1 mrg } 71 1.1 mrg while (divisor == 0); 72 1.1 mrg 73 1.1 mrg mpz_urandomb (bs, rands, size_range); 74 1.1 mrg dividend_size = mpz_get_ui (bs); 75 1.1 mrg mpz_rrandomb (dividend, rands, dividend_size); 76 1.1 mrg 77 1.1 mrg mpz_urandomb (bs, rands, 2); 78 1.1 mrg bsi = mpz_get_ui (bs); 79 1.1 mrg if ((bsi & 1) != 0) 80 1.1 mrg mpz_neg (dividend, dividend); 81 1.1 mrg 82 1.1 mrg /* printf ("%ld\n", SIZ (dividend)); */ 83 1.1 mrg 84 1.1 mrg r_rq = mpz_fdiv_qr_ui (quotient, remainder, dividend, divisor); 85 1.1 mrg r_q = mpz_fdiv_q_ui (quotient2, dividend, divisor); 86 1.1 mrg r_r = mpz_fdiv_r_ui (remainder2, dividend, divisor); 87 1.1 mrg r = mpz_fdiv_ui (dividend, divisor); 88 1.1 mrg 89 1.1 mrg /* First determine that the quotients and remainders computed 90 1.1 mrg with different functions are equal. */ 91 1.1 mrg if (mpz_cmp (quotient, quotient2) != 0) 92 1.1 mrg dump_abort ("quotients from mpz_fdiv_qr_ui and mpz_fdiv_q_ui differ", 93 1.1 mrg dividend, divisor); 94 1.1 mrg if (mpz_cmp (remainder, remainder2) != 0) 95 1.1 mrg dump_abort ("remainders from mpz_fdiv_qr_ui and mpz_fdiv_r_ui differ", 96 1.1 mrg dividend, divisor); 97 1.1 mrg 98 1.1 mrg /* Check if the sign of the quotient is correct. */ 99 1.1 mrg if (mpz_cmp_ui (quotient, 0) != 0) 100 1.1 mrg if ((mpz_cmp_ui (quotient, 0) < 0) 101 1.1 mrg != (mpz_cmp_ui (dividend, 0) < 0)) 102 1.1 mrg dump_abort ("quotient sign wrong", dividend, divisor); 103 1.1 mrg 104 1.1 mrg /* Check if the remainder has the same sign as the (positive) divisor 105 1.1 mrg (quotient rounded towards minus infinity). */ 106 1.1 mrg if (mpz_cmp_ui (remainder, 0) != 0) 107 1.1 mrg if (mpz_cmp_ui (remainder, 0) < 0) 108 1.1 mrg dump_abort ("remainder sign wrong", dividend, divisor); 109 1.1 mrg 110 1.1 mrg mpz_mul_ui (temp, quotient, divisor); 111 1.1 mrg mpz_add (temp, temp, remainder); 112 1.1 mrg if (mpz_cmp (temp, dividend) != 0) 113 1.1 mrg dump_abort ("n mod d != n - [n/d]*d", dividend, divisor); 114 1.1 mrg 115 1.1 mrg mpz_abs (remainder, remainder); 116 1.1 mrg if (mpz_cmp_ui (remainder, divisor) >= 0) 117 1.1 mrg dump_abort ("remainder greater than divisor", dividend, divisor); 118 1.1 mrg 119 1.1 mrg if (mpz_cmp_ui (remainder, r_rq) != 0) 120 1.1 mrg dump_abort ("remainder returned from mpz_fdiv_qr_ui is wrong", 121 1.1 mrg dividend, divisor); 122 1.1 mrg if (mpz_cmp_ui (remainder, r_q) != 0) 123 1.1 mrg dump_abort ("remainder returned from mpz_fdiv_q_ui is wrong", 124 1.1 mrg dividend, divisor); 125 1.1 mrg if (mpz_cmp_ui (remainder, r_r) != 0) 126 1.1 mrg dump_abort ("remainder returned from mpz_fdiv_r_ui is wrong", 127 1.1 mrg dividend, divisor); 128 1.1 mrg if (mpz_cmp_ui (remainder, r) != 0) 129 1.1 mrg dump_abort ("remainder returned from mpz_fdiv_ui is wrong", 130 1.1 mrg dividend, divisor); 131 1.1 mrg } 132 1.1 mrg 133 1.1 mrg mpz_clear (bs); 134 1.1 mrg mpz_clear (dividend); 135 1.1 mrg mpz_clear (quotient); 136 1.1 mrg mpz_clear (remainder); 137 1.1 mrg mpz_clear (quotient2); 138 1.1 mrg mpz_clear (remainder2); 139 1.1 mrg mpz_clear (temp); 140 1.1 mrg 141 1.1 mrg tests_end (); 142 1.1 mrg exit (0); 143 1.1 mrg } 144 1.1 mrg 145 1.1 mrg void 146 1.1.1.2 mrg dump_abort (const char *str, mpz_t dividend, unsigned long divisor) 147 1.1 mrg { 148 1.1 mrg fprintf (stderr, "ERROR: %s\n", str); 149 1.1 mrg fprintf (stderr, "dividend = "); debug_mp (dividend, -16); 150 1.1 mrg fprintf (stderr, "divisor = %lX\n", divisor); 151 1.1 mrg abort(); 152 1.1 mrg } 153 1.1 mrg 154 1.1 mrg void 155 1.1 mrg debug_mp (mpz_t x, int base) 156 1.1 mrg { 157 1.1 mrg mpz_out_str (stderr, base, x); fputc ('\n', stderr); 158 1.1 mrg } 159