xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-tdiv.c (revision 4391d5e9d4f291db41e3b3ba26a01b5e51364aae)
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