source: trunk/third/gmp/tests/mpz/t-cdiv_ui.c @ 18191

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