t-minvert.c revision 1.1.1.2
1/* Copyright 2013-2015 Free Software Foundation, Inc. 2 3This file is part of the GNU MP Library test suite. 4 5The GNU MP Library test suite is free software; you can redistribute it 6and/or modify it under the terms of the GNU General Public License as 7published by the Free Software Foundation; either version 3 of the License, 8or (at your option) any later version. 9 10The GNU MP Library test suite is distributed in the hope that it will be 11useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 13Public License for more details. 14 15You should have received a copy of the GNU General Public License along with 16the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 17 18#include <stdio.h> 19#include <stdlib.h> /* for strtol */ 20 21#include "gmp-impl.h" 22#include "longlong.h" 23#include "tests/tests.h" 24 25#define MAX_SIZE 50 26 27#define COUNT 200 28 29static void 30mpz_to_mpn (mp_ptr ap, mp_size_t an, const mpz_t b) 31{ 32 mp_size_t bn = mpz_size (b); 33 ASSERT_ALWAYS (bn <= an); 34 MPN_COPY_INCR (ap, mpz_limbs_read (b), bn); 35 MPN_ZERO (ap + bn, an - bn); 36} 37 38int 39mpz_eq_mpn (mp_ptr ap, mp_size_t an, const mpz_t b) 40{ 41 mp_size_t bn = mpz_size (b); 42 43 return (bn >= 0 && bn <= an 44 && mpn_cmp (ap, mpz_limbs_read (b), bn) == 0 45 && (an == bn || mpn_zero_p (ap + bn, an - bn))); 46} 47 48static mp_bitcnt_t 49bit_size (mp_srcptr xp, mp_size_t n) 50{ 51 MPN_NORMALIZE (xp, n); 52 return n > 0 ? mpn_sizeinbase (xp, n, 2) : 0; 53} 54 55int 56main (int argc, char **argv) 57{ 58 gmp_randstate_ptr rands; 59 long count = COUNT; 60 mp_ptr mp; 61 mp_ptr ap; 62 mp_ptr tp; 63 mp_ptr scratch; 64 mpz_t m, a, r, g; 65 int test; 66 mp_limb_t ran; 67 mp_size_t itch; 68 TMP_DECL; 69 70 tests_start (); 71 rands = RANDS; 72 73 74 TMP_MARK; 75 mpz_init (m); 76 mpz_init (a); 77 mpz_init (r); 78 mpz_init (g); 79 80 TESTS_REPS (count, argv, argc); 81 82 mp = TMP_ALLOC_LIMBS (MAX_SIZE); 83 ap = TMP_ALLOC_LIMBS (MAX_SIZE); 84 tp = TMP_ALLOC_LIMBS (MAX_SIZE); 85 scratch = TMP_ALLOC_LIMBS (mpn_sec_invert_itch (MAX_SIZE) + 1); 86 87 for (test = 0; test < count; test++) 88 { 89 mp_bitcnt_t bits; 90 int rres, tres; 91 mp_size_t n; 92 93 bits = urandom () % (GMP_NUMB_BITS * MAX_SIZE) + 1; 94 95 if (test & 1) 96 mpz_rrandomb (m, rands, bits); 97 else 98 mpz_urandomb (m, rands, bits); 99 if (test & 2) 100 mpz_rrandomb (a, rands, bits); 101 else 102 mpz_urandomb (a, rands, bits); 103 104 mpz_setbit (m, 0); 105 if (test & 4) 106 { 107 /* Ensure it really is invertible */ 108 if (mpz_sgn (a) == 0) 109 mpz_set_ui (a, 1); 110 else 111 for (;;) 112 { 113 mpz_gcd (g, a, m); 114 if (mpz_cmp_ui (g, 1) == 0) 115 break; 116 mpz_remove (a, a, g); 117 } 118 } 119 120 rres = mpz_invert (r, a, m); 121 if ( (test & 4) && !rres) 122 { 123 gmp_fprintf (stderr, "test %d: Not invertible!\n" 124 "m = %Zd\n" 125 "a = %Zd\n", test, m, a); 126 abort (); 127 } 128 ASSERT_ALWAYS (! (test & 4) || rres); 129 130 n = (bits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS; 131 ASSERT_ALWAYS (n <= MAX_SIZE); 132 itch = mpn_sec_invert_itch (n); 133 scratch[itch] = ran = urandom (); 134 135 mpz_to_mpn (ap, n, a); 136 mpz_to_mpn (mp, n, m); 137 tres = mpn_sec_invert (tp, ap, mp, n, 138 bit_size (ap, n) + bit_size (mp, n), 139 scratch); 140 141 if (rres != tres || (rres == 1 && !mpz_eq_mpn (tp, n, r)) || ran != scratch[itch]) 142 { 143 gmp_fprintf (stderr, "Test %d failed.\n" 144 "m = %Zd\n" 145 "a = %Zd\n", test, m, a); 146 fprintf (stderr, "ref ret: %d\n" 147 "got ret: %d\n", rres, tres); 148 if (rres) 149 gmp_fprintf (stderr, "ref: %Zd\n", r); 150 if (tres) 151 gmp_fprintf (stderr, "got: %Nd\n", tp, n); 152 if (ran != scratch[itch]) 153 fprintf (stderr, "scratch[itch] changed.\n"); 154 abort (); 155 } 156 } 157 158 TMP_FREE; 159 160 mpz_clear (m); 161 mpz_clear (a); 162 mpz_clear (r); 163 mpz_clear (g); 164 165 tests_end (); 166 return 0; 167} 168