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