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