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