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