Upload Tizen:Base source
[external/gmp.git] / tests / mpz / t-cdiv_ui.c
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 }