Home | History | Annotate | Line # | Download | only in mpz
      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