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-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
main(int argc,char ** argv)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_cdiv_qr_ui (quotient, remainder, dividend, divisor);
85       r_q = mpz_cdiv_q_ui (quotient2, dividend, divisor);
86       r_r = mpz_cdiv_r_ui (remainder2, dividend, divisor);
87       r = mpz_cdiv_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_cdiv_qr_ui and mpz_cdiv_q_ui differ",
93                         dividend, divisor);
94       if (mpz_cmp (remainder, remainder2) != 0)
95           dump_abort ("remainders from mpz_cdiv_qr_ui and mpz_cdiv_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 opposite 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_cdiv_qr_ui is wrong",
121                         dividend, divisor);
122       if (mpz_cmp_ui (remainder, r_q) != 0)
123           dump_abort ("remainder returned from mpz_cdiv_q_ui is wrong",
124                         dividend, divisor);
125       if (mpz_cmp_ui (remainder, r_r) != 0)
126           dump_abort ("remainder returned from mpz_cdiv_r_ui is wrong",
127                         dividend, divisor);
128       if (mpz_cmp_ui (remainder, r) != 0)
129           dump_abort ("remainder returned from mpz_cdiv_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
dump_abort(const char * str,mpz_t dividend,unsigned long divisor)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
debug_mp(mpz_t x,int base)155 debug_mp (mpz_t x, int base)
156 {
157   mpz_out_str (stderr, base, x); fputc ('\n', stderr);
158 }
159