1/* test mpz_divisible_p and mpz_divisible_ui_p
2
3Copyright 2001, 2009 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library.
6
7The GNU MP Library is free software; you can redistribute it and/or modify
8it under the terms of the GNU Lesser General Public License as published by
9the Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12The GNU MP Library is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15License for more details.
16
17You should have received a copy of the GNU Lesser General Public License
18along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
19
20#include <stdio.h>
21#include <stdlib.h>
22
23#include "gmp.h"
24#include "gmp-impl.h"
25#include "tests.h"
26
27
28void
29check_one (mpz_srcptr a, mpz_srcptr d, int want)
30{
31  int   got;
32
33  if (mpz_fits_ulong_p (d))
34    {
35      unsigned long  u = mpz_get_ui (d);
36      got = (mpz_divisible_ui_p (a, u) != 0);
37      if (want != got)
38        {
39          printf ("mpz_divisible_ui_p wrong\n");
40          printf ("   expected %d got %d\n", want, got);
41          mpz_trace ("   a", a);
42          printf ("   d=%lu\n", u);
43          mp_trace_base = -16;
44          mpz_trace ("   a", a);
45          printf ("   d=0x%lX\n", u);
46          abort ();
47        }
48    }
49
50  got = (mpz_divisible_p (a, d) != 0);
51  if (want != got)
52    {
53      printf ("mpz_divisible_p wrong\n");
54      printf ("   expected %d got %d\n", want, got);
55      mpz_trace ("   a", a);
56      mpz_trace ("   d", d);
57      mp_trace_base = -16;
58      mpz_trace ("   a", a);
59      mpz_trace ("   d", d);
60      abort ();
61    }
62}
63
64void
65check_data (void)
66{
67  static const struct {
68    const char *a;
69    const char *d;
70    int        want;
71
72  } data[] = {
73
74    { "0",    "1", 1 },
75    { "123",  "1", 1 },
76    { "-123", "1", 1 },
77
78    { "0",  "2", 1 },
79    { "1",  "2", 0 },
80    { "2",  "2", 1 },
81    { "-2", "2", 1 },
82    { "0x100000000000000000000000000000000", "2", 1 },
83    { "0x100000000000000000000000000000001", "2", 0 },
84
85    { "0x3333333333333333", "3", 1 },
86    { "0x3333333333333332", "3", 0 },
87    { "0x33333333333333333333333333333333", "3", 1 },
88    { "0x33333333333333333333333333333332", "3", 0 },
89
90    /* divisor changes from 2 to 1 limb after stripping 2s */
91    {          "0x3333333300000000",         "0x180000000",         1 },
92    {  "0x33333333333333330000000000000000", "0x18000000000000000", 1 },
93    { "0x133333333333333330000000000000000", "0x18000000000000000", 0 },
94  };
95
96  mpz_t   a, d;
97  int     i;
98
99  mpz_init (a);
100  mpz_init (d);
101
102  for (i = 0; i < numberof (data); i++)
103    {
104      mpz_set_str_or_abort (a, data[i].a, 0);
105      mpz_set_str_or_abort (d, data[i].d, 0);
106      check_one (a, d, data[i].want);
107    }
108
109  mpz_clear (a);
110  mpz_clear (d);
111}
112
113void
114check_random (int reps)
115{
116  gmp_randstate_ptr rands = RANDS;
117  mpz_t   a, d, r;
118  int     i;
119  int     want;
120
121  mpz_init (a);
122  mpz_init (d);
123  mpz_init (r);
124
125  for (i = 0; i < reps; i++)
126    {
127      mpz_erandomb (a, rands, 1 << 19);
128      mpz_erandomb_nonzero (d, rands, 1 << 18);
129
130      mpz_fdiv_r (r, a, d);
131
132      want = (mpz_sgn (r) == 0);
133      check_one (a, d, want);
134
135      mpz_sub (a, a, r);
136      check_one (a, d, 1);
137
138      if (mpz_cmpabs_ui (d, 1L) == 0)
139        continue;
140
141      mpz_add_ui (a, a, 1L);
142      check_one (a, d, 0);
143    }
144
145  mpz_clear (a);
146  mpz_clear (d);
147  mpz_clear (r);
148}
149
150
151int
152main (int argc, char *argv[])
153{
154  int  reps = 100;
155
156  tests_start ();
157
158  if (argc == 2)
159    reps = atoi (argv[1]);
160
161  check_data ();
162  check_random (reps);
163
164  tests_end ();
165  exit (0);
166}
167