Home | History | Annotate | Line # | Download | only in mpz
      1 /* Test mpz_perfect_power_p.
      2 
      3    Contributed to the GNU project by Torbjorn Granlund and Martin Boij.
      4 
      5 Copyright 2008-2010, 2014 Free Software Foundation, Inc.
      6 
      7 This file is part of the GNU MP Library test suite.
      8 
      9 The GNU MP Library test suite is free software; you can redistribute it
     10 and/or modify it under the terms of the GNU General Public License as
     11 published by the Free Software Foundation; either version 3 of the License,
     12 or (at your option) any later version.
     13 
     14 The GNU MP Library test suite is distributed in the hope that it will be
     15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
     17 Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License along with
     20 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
     21 
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 
     25 #include "gmp-impl.h"
     26 #include "tests.h"
     27 
     28 struct
     29 {
     30   const char *num_as_str;
     31   char want;
     32 } static tests[] =
     33   {
     34     { "0", 1},
     35     { "1", 1},
     36     {"-1", 1},
     37     { "2", 0},
     38     {"-2", 0},
     39     { "3", 0},
     40     {"-3", 0},
     41     { "4", 1},
     42     {"-4", 0},
     43     { "64", 1},
     44     {"-64", 1},
     45     { "128", 1},
     46     {"-128", 1},
     47     { "256", 1},
     48     {"-256", 0},
     49     { "512", 1},
     50     {"-512", 1},
     51     { "0x4000000", 1},
     52     {"-0x4000000", 1},
     53     { "0x3cab640", 1},
     54     {"-0x3cab640", 0},
     55     { "0x3e23840", 1},
     56     {"-0x3e23840", 0},
     57     { "0x3d3a7ed1", 1},
     58     {"-0x3d3a7ed1", 1},
     59     { "0x30a7a6000", 1},
     60     {"-0x30a7a6000", 1},
     61     { "0xf33e5a5a59", 1},
     62     {"-0xf33e5a5a59", 0},
     63     { "0xed1b1182118135d", 1},
     64     {"-0xed1b1182118135d", 1},
     65     { "0xe71f6eb7689cc276b2f1", 1},
     66     {"-0xe71f6eb7689cc276b2f1", 0},
     67     { "0x12644507fe78cf563a4b342c92e7da9fe5e99cb75a01", 1},
     68     {"-0x12644507fe78cf563a4b342c92e7da9fe5e99cb75a01", 0},
     69     { "0x1ff2e7c581bb0951df644885bd33f50e472b0b73a204e13cbe98fdb424d66561e4000000", 1},
     70     {"-0x1ff2e7c581bb0951df644885bd33f50e472b0b73a204e13cbe98fdb424d66561e4000000", 1},
     71     { "0x2b9b44db2d91a6f8165c8c7339ef73633228ea29e388592e80354e4380004aad84000000", 1},
     72     {"-0x2b9b44db2d91a6f8165c8c7339ef73633228ea29e388592e80354e4380004aad84000000", 1},
     73     { "0x28d5a2b8f330910a9d3cda06036ae0546442e5b1a83b26a436efea5b727bf1bcbe7e12b47d81", 1},
     74     {"-0x28d5a2b8f330910a9d3cda06036ae0546442e5b1a83b26a436efea5b727bf1bcbe7e12b47d81", 1},
     75     {NULL, 0}
     76   };
     77 
     78 
     79 void
     80 check_tests ()
     81 {
     82   mpz_t x;
     83   int i;
     84   int got, want;
     85 
     86   mpz_init (x);
     87 
     88   for (i = 0; tests[i].num_as_str != NULL; i++)
     89     {
     90       mpz_set_str (x, tests[i].num_as_str, 0);
     91       got = mpz_perfect_power_p (x);
     92       want = tests[i].want;
     93       if (got != want)
     94 	{
     95 	  fprintf (stderr, "mpz_perfect_power_p returns %d when %d was expected\n", got, want);
     96 	  fprintf (stderr, "fault operand: %s\n", tests[i].num_as_str);
     97 	  abort ();
     98 	}
     99     }
    100 
    101   mpz_clear (x);
    102 }
    103 
    104 #define NRP 15
    105 
    106 void
    107 check_random (int reps)
    108 {
    109   mpz_t n, np, temp, primes[NRP];
    110   int i, j, k, unique, destroy, res;
    111   unsigned long int nrprimes, primebits;
    112   mp_limb_t g, exp[NRP], e;
    113   gmp_randstate_ptr rands;
    114 
    115   rands = RANDS;
    116 
    117   mpz_init (n);
    118   mpz_init (np);
    119   mpz_init (temp);
    120 
    121   for (i = 0; i < NRP; i++)
    122     mpz_init (primes[i]);
    123 
    124   for (i = 0; i < reps; i++)
    125     {
    126       mpz_urandomb (np, rands, 32);
    127       nrprimes = mpz_get_ui (np) % NRP + 1; /* 1-NRP unique primes */
    128 
    129       mpz_urandomb (np, rands, 32);
    130       g = mpz_get_ui (np) % 32 + 2; /* gcd 2-33 */
    131 
    132       for (j = 0; j < nrprimes;)
    133 	{
    134 	  mpz_urandomb (np, rands, 32);
    135 	  primebits = mpz_get_ui (np) % 100 + 3; /* 3-102 bit primes */
    136 	  mpz_urandomb (primes[j], rands, primebits);
    137 	  mpz_nextprime (primes[j], primes[j]);
    138 	  unique = 1;
    139 	  for (k = 0; k < j; k++)
    140 	    {
    141 	      if (mpz_cmp (primes[j], primes[k]) == 0)
    142 		{
    143 		  unique = 0;
    144 		  break;
    145 		}
    146 	    }
    147 	  if (unique)
    148 	    {
    149 	      mpz_urandomb (np, rands, 32);
    150 	      e = 371 / (10 * primebits) + mpz_get_ui (np) % 11 + 1; /* Magic constants */
    151 	      exp[j++] = g * e;
    152 	    }
    153 	}
    154 
    155       if (nrprimes > 1)
    156 	{
    157 	  /* Destroy d exponents, d in [1, nrprimes - 1] */
    158 	  if (nrprimes == 2)
    159 	    {
    160 	      destroy = 1;
    161 	    }
    162 	  else
    163 	    {
    164 	      mpz_urandomb (np, rands, 32);
    165 	      destroy = mpz_get_ui (np) % (nrprimes - 2);
    166 	    }
    167 
    168 	  g = exp[destroy];
    169 	  for (k = destroy + 1; k < nrprimes; k++)
    170 	    g = mpn_gcd_1 (&g, 1, exp[k]);
    171 
    172 	  for (j = 0; j < destroy; j++)
    173 	    {
    174 	      mpz_urandomb (np, rands, 32);
    175 	      e = mpz_get_ui (np) % 50 + 1;
    176 	      while (mpn_gcd_1 (&g, 1, e) > 1)
    177 		e++;
    178 
    179 	      exp[j] = e;
    180 	    }
    181 	}
    182 
    183       /* Compute n */
    184       mpz_pow_ui (n, primes[0], exp[0]);
    185       for (j = 1; j < nrprimes; j++)
    186 	{
    187 	  mpz_pow_ui (temp, primes[j], exp[j]);
    188 	  mpz_mul (n, n, temp);
    189 	}
    190 
    191       res = mpz_perfect_power_p (n);
    192 
    193       if (nrprimes == 1)
    194 	{
    195 	if (res == 0 && exp[0] > 1)
    196 	  {
    197 	    printf("n is a perfect power, perfpow_p disagrees\n");
    198 	    gmp_printf("n = %Zu\nprimes[0] = %Zu\nexp[0] = %lu\n", n, primes[0], exp[0]);
    199 	    abort ();
    200 	  }
    201 	else if (res == 1 && exp[0] == 1)
    202 	  {
    203 	    gmp_printf("n = %Zu\n", n);
    204 	    printf("n is now a prime number, but perfpow_p still believes n is a perfect power\n");
    205 	    abort ();
    206 	  }
    207 	}
    208       else
    209 	{
    210 	  if (res == 1 && destroy != 0)
    211 	    {
    212 	      gmp_printf("n = %Zu\nn was destroyed, but perfpow_p still believes n is a perfect power\n", n);
    213 	      abort ();
    214 	    }
    215 	  else if (res == 0 && destroy == 0)
    216 	    {
    217 	      gmp_printf("n = %Zu\nn is a perfect power, perfpow_p disagrees\n", n);
    218 	      abort ();
    219 	    }
    220 	}
    221     }
    222 
    223   mpz_clear (n);
    224   mpz_clear (np);
    225   mpz_clear (temp);
    226   for (i = 0; i < NRP; i++)
    227     mpz_clear (primes[i]);
    228 }
    229 
    230 int
    231 main (int argc, char **argv)
    232 {
    233   int n_tests;
    234 
    235   tests_start ();
    236   mp_trace_base = -16;
    237 
    238   check_tests ();
    239 
    240   n_tests = 500;
    241   if (argc == 2)
    242     n_tests = atoi (argv[1]);
    243   check_random (n_tests);
    244 
    245   tests_end ();
    246   exit (0);
    247 }
    248