blob: 652bfcb945887d271087f0f51e98dcb8739dab86 [file] [log] [blame]
Austin Schuhdace2a62020-08-18 10:56:48 -07001/* Exercise mpz_fac_ui and mpz_bin_uiui.
2
3Copyright 2000-2002, 2012, 2013, 2017-2018 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19
20#include <stdio.h>
21#include <stdlib.h>
22
23#include "testutils.h"
24
25/* Usage: t-fac_ui [x|num]
26
27 With no arguments testing goes up to the initial value of "limit" below.
28 With a number argument tests are carried that far, or with a literal "x"
29 tests are continued without limit (this being meant only for development
30 purposes). */
31
32void
33try_mpz_bin_uiui (mpz_srcptr want, unsigned long n, unsigned long k)
34{
35 mpz_t got;
36
37 mpz_init (got);
38 mpz_bin_uiui (got, n, k);
39 if (mpz_cmp (got, want) != 0)
40 {
41 printf ("mpz_bin_uiui wrong\n");
42 printf (" n=%lu\n", n);
43 printf (" k=%lu\n", k);
44 printf (" got="); mpz_out_str (stdout, 10, got); printf ("\n");
45 printf (" want="); mpz_out_str (stdout, 10, want); printf ("\n");
46 abort();
47 }
48 mpz_clear (got);
49}
50
51/* Test all bin(n,k) cases, with 0 <= k <= n + 1 <= count. */
52void
53bin_smallexaustive (unsigned int count)
54{
55 mpz_t want;
56 unsigned long n, k;
57
58 mpz_init (want);
59
60 for (n = 0; n < count; n++)
61 {
62 mpz_set_ui (want, 1);
63 for (k = 0; k <= n; k++)
64 {
65 try_mpz_bin_uiui (want, n, k);
66 mpz_mul_ui (want, want, n - k);
67 mpz_fdiv_q_ui (want, want, k + 1);
68 }
69 try_mpz_bin_uiui (want, n, k);
70 }
71
72 mpz_clear (want);
73}
74
75/* Test all fac(n) cases, with 0 <= n <= limit. */
76void
77fac_smallexaustive (unsigned int limit)
78{
79 mpz_t f, r;
80 unsigned long n;
81 mpz_init_set_si (f, 1); /* 0! = 1 */
82 mpz_init (r);
83
84 for (n = 0; n < limit; n++)
85 {
86 mpz_fac_ui (r, n);
87
88 if (mpz_cmp (f, r) != 0)
89 {
90 printf ("mpz_fac_ui(%lu) wrong\n", n);
91 printf (" got "); mpz_out_str (stdout, 10, r); printf("\n");
92 printf (" want "); mpz_out_str (stdout, 10, f); printf("\n");
93 abort ();
94 }
95
96 mpz_mul_ui (f, f, n+1); /* (n+1)! = n! * (n+1) */
97 }
98
99 mpz_clear (f);
100 mpz_clear (r);
101}
102
103void checkWilson (mpz_t f, unsigned long n)
104{
105 unsigned long m, a;
106
107 mpz_2fac_ui (f, 2 * n - 1);
108
109 a = mpz_fdiv_q_ui (f, f, n);
110 m = mpz_fdiv_ui (f, n);
111 if ((m != n - 1) || (a != 0))
112 {
113 printf ("mpz_2fac_ui(%lu) wrong\n", 2 * n - 1);
114 printf (" Wilson's theorem not verified: got (%lu, %lu), expected (0, %lu).\n", a, m, n - 1);
115 abort ();
116 }
117
118 mpz_fac_ui (f, n - 1);
119 m = mpz_fdiv_ui (f, n);
120 if ( m != n - 1)
121 {
122 printf ("mpz_fac_ui(%lu) wrong\n", n - 1);
123 printf (" Wilson's theorem not verified: got %lu, expected %lu.\n",m ,n - 1);
124 abort ();
125 }
126}
127
128void
129checkprimes (unsigned long p1, unsigned long p2, unsigned long p3)
130{
131 mpz_t b, f;
132
133 if (p1 - 1 != p2 - 1 + p3 - 1)
134 {
135 printf ("checkprimes(%lu, %lu, %lu) wrong\n", p1, p2, p3);
136 printf (" %lu - 1 != %lu - 1 + %lu - 1 \n", p1, p2, p3);
137 abort ();
138 }
139
140 mpz_init (b);
141 mpz_init (f);
142
143 checkWilson (b, p1); /* b = (p1-1)! */
144 checkWilson (f, p2); /* f = (p2-1)! */
145 mpz_divexact (b, b, f);
146 checkWilson (f, p3); /* f = (p3-1)! */
147 mpz_divexact (b, b, f); /* b = (p1-1)!/((p2-1)!(p3-1)!) */
148 mpz_bin_uiui (f, p1 - 1, p2 - 1);
149 if (mpz_cmp (f, b) != 0)
150 {
151 printf ("checkprimes(%lu, %lu, %lu) wrong\n", p1, p2, p3);
152 printf (" got "); mpz_out_str (stdout, 10, b); printf("\n");
153 printf (" want "); mpz_out_str (stdout, 10, f); printf("\n");
154 abort ();
155 }
156
157 mpz_clear (b);
158 mpz_clear (f);
159
160}
161
162void
163testmain (int argc, char *argv[])
164{
165 unsigned long limit = 128;
166
167 if (argc > 1 && argv[1][0] == 'x')
168 limit = ~ limit;
169 else if (argc > 1)
170 limit = atoi (argv[1]);
171
172 checkprimes(1009, 733, 277);
173 fac_smallexaustive (limit);
174 bin_smallexaustive (limit);
175}