t-invert.c revision 1.1.1.3 1 1.1 mrg /* Test mpz_invert.
2 1.1 mrg
3 1.1.1.2 mrg Copyright 1991, 1993, 1994, 1996, 1997, 2000-2005, 2008, 2009, 2012, 2014 Free
4 1.1.1.2 mrg Software Foundation, Inc.
5 1.1 mrg
6 1.1 mrg This file is part of the GNU MP Library test suite.
7 1.1 mrg
8 1.1 mrg The GNU MP Library test suite is free software; you can redistribute it
9 1.1 mrg and/or modify it under the terms of the GNU General Public License as
10 1.1 mrg published by the Free Software Foundation; either version 3 of the License,
11 1.1 mrg or (at your option) any later version.
12 1.1 mrg
13 1.1 mrg The GNU MP Library test suite is distributed in the hope that it will be
14 1.1 mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 1.1 mrg Public License for more details.
17 1.1 mrg
18 1.1 mrg You should have received a copy of the GNU General Public License along with
19 1.1.1.2 mrg the GNU MP Library test suite. If not, see https://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-impl.h"
25 1.1 mrg #include "tests.h"
26 1.1 mrg
27 1.1 mrg int
28 1.1 mrg main (int argc, char **argv)
29 1.1 mrg {
30 1.1 mrg mpz_t a, m, ainv, t;
31 1.1 mrg int test, r;
32 1.1 mrg gmp_randstate_ptr rands;
33 1.1 mrg mpz_t bs;
34 1.1 mrg unsigned long bsi, size_range;
35 1.1 mrg int reps = 1000;
36 1.1 mrg
37 1.1 mrg tests_start ();
38 1.1 mrg TESTS_REPS (reps, argv, argc);
39 1.1 mrg
40 1.1 mrg rands = RANDS;
41 1.1 mrg
42 1.1 mrg mpz_init (bs);
43 1.1 mrg mpz_init (a);
44 1.1 mrg mpz_init (m);
45 1.1 mrg mpz_init (ainv);
46 1.1 mrg mpz_init (t);
47 1.1 mrg
48 1.1 mrg for (test = 0; test < reps; test++)
49 1.1 mrg {
50 1.1 mrg mpz_urandomb (bs, rands, 32);
51 1.1 mrg size_range = mpz_get_ui (bs) % 16 + 2;
52 1.1 mrg
53 1.1 mrg mpz_urandomb (bs, rands, size_range);
54 1.1 mrg mpz_rrandomb (a, rands, mpz_get_ui (bs));
55 1.1 mrg do {
56 1.1 mrg mpz_urandomb (bs, rands, size_range);
57 1.1 mrg mpz_rrandomb (m, rands, mpz_get_ui (bs));
58 1.1 mrg } while (mpz_sgn (m) == 0);
59 1.1 mrg
60 1.1 mrg mpz_urandomb (bs, rands, 8);
61 1.1 mrg bsi = mpz_get_ui (bs);
62 1.1 mrg
63 1.1 mrg if ((bsi & 1) != 0)
64 1.1 mrg mpz_neg (a, a);
65 1.1 mrg if ((bsi & 2) != 0)
66 1.1 mrg mpz_neg (m, m);
67 1.1 mrg
68 1.1 mrg r = mpz_invert (ainv, a, m);
69 1.1 mrg if (r != 0)
70 1.1 mrg {
71 1.1 mrg MPZ_CHECK_FORMAT (ainv);
72 1.1 mrg
73 1.1.1.2 mrg if (mpz_cmp_ui (ainv, 0) < 0 || mpz_cmpabs (ainv, m) >= 0)
74 1.1 mrg {
75 1.1 mrg fprintf (stderr, "ERROR in test %d\n", test);
76 1.1 mrg gmp_fprintf (stderr, "Inverse out of range.\n");
77 1.1 mrg gmp_fprintf (stderr, "a = %Zx\n", a);
78 1.1.1.2 mrg gmp_fprintf (stderr, "1/a = %Zx\n", ainv);
79 1.1 mrg gmp_fprintf (stderr, "m = %Zx\n", m);
80 1.1 mrg abort ();
81 1.1 mrg }
82 1.1 mrg
83 1.1 mrg mpz_mul (t, ainv, a);
84 1.1 mrg mpz_mod (t, t, m);
85 1.1 mrg
86 1.1.1.2 mrg if (mpz_cmp_ui (t, mpz_cmpabs_ui (m, 1) != 0) != 0)
87 1.1 mrg {
88 1.1 mrg fprintf (stderr, "ERROR in test %d\n", test);
89 1.1 mrg gmp_fprintf (stderr, "a^(-1)*a != 1 (mod m)\n");
90 1.1 mrg gmp_fprintf (stderr, "a = %Zx\n", a);
91 1.1 mrg gmp_fprintf (stderr, "m = %Zx\n", m);
92 1.1 mrg abort ();
93 1.1 mrg }
94 1.1 mrg }
95 1.1 mrg else /* Inverse deos not exist */
96 1.1 mrg {
97 1.1 mrg mpz_gcd (t, a, m);
98 1.1 mrg if (mpz_cmp_ui (t, 1) == 0)
99 1.1 mrg {
100 1.1 mrg fprintf (stderr, "ERROR in test %d\n", test);
101 1.1 mrg gmp_fprintf (stderr, "Inverse exists, but was not found.\n");
102 1.1 mrg gmp_fprintf (stderr, "a = %Zx\n", a);
103 1.1 mrg gmp_fprintf (stderr, "m = %Zx\n", m);
104 1.1 mrg abort ();
105 1.1 mrg }
106 1.1 mrg }
107 1.1 mrg }
108 1.1 mrg
109 1.1 mrg mpz_clear (bs);
110 1.1 mrg mpz_clear (a);
111 1.1 mrg mpz_clear (m);
112 1.1 mrg mpz_clear (ainv);
113 1.1 mrg mpz_clear (t);
114 1.1 mrg
115 1.1 mrg tests_end ();
116 1.1 mrg exit (0);
117 1.1 mrg }
118