xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-tdiv_ui.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
1 /* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr_ui, mpz_tdiv_q_ui,
2    mpz_tdiv_r_ui, mpz_tdiv_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.h"
25 #include "gmp-impl.h"
26 #include "tests.h"
27 
28 void dump_abort (const char *, mpz_t, unsigned long);
29 void debug_mp (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 = 200000;
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_tdiv_qr_ui (quotient, remainder, dividend, divisor);
86       r_q = mpz_tdiv_q_ui (quotient2, dividend, divisor);
87       r_r = mpz_tdiv_r_ui (remainder2, dividend, divisor);
88       r = mpz_tdiv_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_tdiv_qr_ui and mpz_tdiv_q_ui differ",
94 		    dividend, divisor);
95       if (mpz_cmp (remainder, remainder2) != 0)
96 	dump_abort ("remainders from mpz_tdiv_qr_ui and mpz_tdiv_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 same sign as the dividend
106 	 (quotient rounded towards 0).  */
107       if (mpz_cmp_ui (remainder, 0) != 0)
108 	if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 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_tdiv_qr_ui is wrong",
122 		    dividend, divisor);
123       if (mpz_cmp_ui (remainder, r_q) != 0)
124 	dump_abort ("remainder returned from mpz_tdiv_q_ui is wrong",
125 		    dividend, divisor);
126       if (mpz_cmp_ui (remainder, r_r) != 0)
127 	dump_abort ("remainder returned from mpz_tdiv_r_ui is wrong",
128 		    dividend, divisor);
129       if (mpz_cmp_ui (remainder, r) != 0)
130 	dump_abort ("remainder returned from mpz_tdiv_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 (const 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