1 /* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_cdiv_qr_ui, mpz_cdiv_q_ui, 2 mpz_cdiv_r_ui, , mpz_cdiv_ui, mpz_mul_ui. 3 4 Copyright 1993, 1994, 1996, 2000, 2001, 2002 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 ((char *, mpz_t, unsigned long)); 29 void debug_mp __GMP_PROTO ((mpz_t, int)); 30 31 int 32 main (int argc, char **argv) 33 { 34 mpz_t dividend; 35 mpz_t quotient, remainder; 36 mpz_t quotient2, remainder2; 37 mpz_t temp; 38 mp_size_t dividend_size; 39 unsigned long divisor; 40 int i; 41 int reps = 10000; 42 gmp_randstate_ptr rands; 43 mpz_t bs; 44 unsigned long bsi, size_range; 45 unsigned long r_rq, r_q, r_r, r; 46 47 tests_start (); 48 rands = RANDS; 49 50 mpz_init (bs); 51 52 if (argc == 2) 53 reps = atoi (argv[1]); 54 55 mpz_init (dividend); 56 mpz_init (quotient); 57 mpz_init (remainder); 58 mpz_init (quotient2); 59 mpz_init (remainder2); 60 mpz_init (temp); 61 62 for (i = 0; i < reps; i++) 63 { 64 mpz_urandomb (bs, rands, 32); 65 size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */ 66 67 do 68 { 69 mpz_rrandomb (bs, rands, 64); 70 divisor = mpz_get_ui (bs); 71 } 72 while (divisor == 0); 73 74 mpz_urandomb (bs, rands, size_range); 75 dividend_size = mpz_get_ui (bs); 76 mpz_rrandomb (dividend, rands, dividend_size); 77 78 mpz_urandomb (bs, rands, 2); 79 bsi = mpz_get_ui (bs); 80 if ((bsi & 1) != 0) 81 mpz_neg (dividend, dividend); 82 83 /* printf ("%ld\n", SIZ (dividend)); */ 84 85 r_rq = mpz_cdiv_qr_ui (quotient, remainder, dividend, divisor); 86 r_q = mpz_cdiv_q_ui (quotient2, dividend, divisor); 87 r_r = mpz_cdiv_r_ui (remainder2, dividend, divisor); 88 r = mpz_cdiv_ui (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 ("quotients from mpz_cdiv_qr_ui and mpz_cdiv_q_ui differ", 94 dividend, divisor); 95 if (mpz_cmp (remainder, remainder2) != 0) 96 dump_abort ("remainders from mpz_cdiv_qr_ui and mpz_cdiv_r_ui differ", 97 dividend, divisor); 98 99 /* Check if the sign of the quotient is correct. */ 100 if (mpz_cmp_ui (quotient, 0) != 0) 101 if ((mpz_cmp_ui (quotient, 0) < 0) 102 != (mpz_cmp_ui (dividend, 0) < 0)) 103 dump_abort ("quotient sign wrong", dividend, divisor); 104 105 /* Check if the remainder has the opposite sign as the (positive) divisor 106 (quotient rounded towards minus infinity). */ 107 if (mpz_cmp_ui (remainder, 0) != 0) 108 if (mpz_cmp_ui (remainder, 0) > 0) 109 dump_abort ("remainder sign wrong", dividend, divisor); 110 111 mpz_mul_ui (temp, quotient, divisor); 112 mpz_add (temp, temp, remainder); 113 if (mpz_cmp (temp, dividend) != 0) 114 dump_abort ("n mod d != n - [n/d]*d", dividend, divisor); 115 116 mpz_abs (remainder, remainder); 117 if (mpz_cmp_ui (remainder, divisor) >= 0) 118 dump_abort ("remainder greater than divisor", dividend, divisor); 119 120 if (mpz_cmp_ui (remainder, r_rq) != 0) 121 dump_abort ("remainder returned from mpz_cdiv_qr_ui is wrong", 122 dividend, divisor); 123 if (mpz_cmp_ui (remainder, r_q) != 0) 124 dump_abort ("remainder returned from mpz_cdiv_q_ui is wrong", 125 dividend, divisor); 126 if (mpz_cmp_ui (remainder, r_r) != 0) 127 dump_abort ("remainder returned from mpz_cdiv_r_ui is wrong", 128 dividend, divisor); 129 if (mpz_cmp_ui (remainder, r) != 0) 130 dump_abort ("remainder returned from mpz_cdiv_ui is wrong", 131 dividend, divisor); 132 } 133 134 mpz_clear (bs); 135 mpz_clear (dividend); 136 mpz_clear (quotient); 137 mpz_clear (remainder); 138 mpz_clear (quotient2); 139 mpz_clear (remainder2); 140 mpz_clear (temp); 141 142 tests_end (); 143 exit (0); 144 } 145 146 void 147 dump_abort (char *str, mpz_t dividend, unsigned long divisor) 148 { 149 fprintf (stderr, "ERROR: %s\n", str); 150 fprintf (stderr, "dividend = "); debug_mp (dividend, -16); 151 fprintf (stderr, "divisor = %lX\n", divisor); 152 abort(); 153 } 154 155 void 156 debug_mp (mpz_t x, int base) 157 { 158 mpz_out_str (stderr, base, x); fputc ('\n', stderr); 159 } 160