Home | History | Annotate | Line # | Download | only in mpz
t-root.c revision 1.1.1.3
      1 /* Test mpz_root, mpz_rootrem, and mpz_perfect_power_p.
      2 
      3 Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2009, 2015 Free Software
      4 Foundation, Inc.
      5 
      6 This file is part of the GNU MP Library test suite.
      7 
      8 The GNU MP Library test suite is free software; you can redistribute it
      9 and/or modify it under the terms of the GNU General Public License as
     10 published by the Free Software Foundation; either version 3 of the License,
     11 or (at your option) any later version.
     12 
     13 The GNU MP Library test suite is distributed in the hope that it will be
     14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
     16 Public License for more details.
     17 
     18 You should have received a copy of the GNU General Public License along with
     19 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
     20 
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 
     24 #include "gmp.h"
     25 #include "gmp-impl.h"
     26 #include "tests.h"
     27 
     28 void debug_mp (mpz_t, int);
     29 
     30 void
     31 check_one (mpz_t root1, mpz_t x2, unsigned long nth, int res, int i)
     32 {
     33   mpz_t temp, temp2;
     34   mpz_t root2, rem2;
     35 
     36   mpz_init (root2);
     37   mpz_init (rem2);
     38   mpz_init (temp);
     39   mpz_init (temp2);
     40 
     41   MPZ_CHECK_FORMAT (root1);
     42 
     43   mpz_rootrem (root2, rem2, x2, nth);
     44   MPZ_CHECK_FORMAT (root2);
     45   MPZ_CHECK_FORMAT (rem2);
     46 
     47   mpz_pow_ui (temp, root1, nth);
     48   MPZ_CHECK_FORMAT (temp);
     49 
     50   mpz_add (temp2, temp, rem2);
     51 
     52   /* Is power of result > argument?  */
     53   if (mpz_cmp (root1, root2) != 0 || mpz_cmp (x2, temp2) != 0 || mpz_cmpabs (temp, x2) > 0 || res == mpz_cmp_ui (rem2, 0))
     54     {
     55       fprintf (stderr, "ERROR after test %d\n", i);
     56       debug_mp (x2, 10);
     57       debug_mp (root1, 10);
     58       debug_mp (root2, 10);
     59       fprintf (stderr, "nth: %lu ,res: %i\n", nth, res);
     60       abort ();
     61     }
     62 
     63   if (nth > 1 && mpz_cmp_ui (temp, 1L) > 0 && ! mpz_perfect_power_p (temp))
     64     {
     65       fprintf (stderr, "ERROR in mpz_perfect_power_p after test %d\n", i);
     66       debug_mp (temp, 10);
     67       debug_mp (root1, 10);
     68       fprintf (stderr, "nth: %lu\n", nth);
     69       abort ();
     70     }
     71 
     72   if (nth <= 10000 && mpz_sgn(x2) > 0)		/* skip too expensive test */
     73     {
     74       mpz_add_ui (temp2, root1, 1L);
     75       mpz_pow_ui (temp2, temp2, nth);
     76       MPZ_CHECK_FORMAT (temp2);
     77 
     78       /* Is square of (result + 1) <= argument?  */
     79       if (mpz_cmp (temp2, x2) <= 0)
     80 	{
     81 	  fprintf (stderr, "ERROR after test %d\n", i);
     82 	  debug_mp (x2, 10);
     83 	  debug_mp (root1, 10);
     84 	  fprintf (stderr, "nth: %lu\n", nth);
     85 	  abort ();
     86 	}
     87     }
     88 
     89   mpz_clear (root2);
     90   mpz_clear (rem2);
     91   mpz_clear (temp);
     92   mpz_clear (temp2);
     93 }
     94 
     95 int
     96 main (int argc, char **argv)
     97 {
     98   mpz_t x2;
     99   mpz_t root1;
    100   mp_size_t x2_size;
    101   int i, res;
    102   int reps = 500;
    103   unsigned long nth;
    104   gmp_randstate_ptr rands;
    105   mpz_t bs;
    106   unsigned long bsi, size_range;
    107 
    108   tests_start ();
    109   TESTS_REPS (reps, argv, argc);
    110 
    111   rands = RANDS;
    112 
    113   mpz_init (bs);
    114 
    115   mpz_init (x2);
    116   mpz_init (root1);
    117 
    118   /* This triggers a gcc 4.3.2 bug */
    119   mpz_set_str (x2, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000002", 16);
    120   res = mpz_root (root1, x2, 2);
    121   check_one (root1, x2, 2, res, -1);
    122 
    123   for (i = 0; i < reps; i++)
    124     {
    125       mpz_urandomb (bs, rands, 32);
    126       size_range = mpz_get_ui (bs) % 17 + 2;
    127 
    128       mpz_urandomb (bs, rands, size_range);
    129       x2_size = mpz_get_ui (bs) + 10;
    130       mpz_rrandomb (x2, rands, x2_size);
    131 
    132       mpz_urandomb (bs, rands, 15);
    133       nth = mpz_getlimbn (bs, 0) % mpz_sizeinbase (x2, 2) + 2;
    134 
    135       res = mpz_root (root1, x2, nth);
    136 
    137       mpz_urandomb (bs, rands, 4);
    138       bsi = mpz_get_ui (bs);
    139       if ((bsi & 1) != 0)
    140 	{
    141 	  /* With 50% probability, set x2 near a perfect power.  */
    142 	  mpz_pow_ui (x2, root1, nth);
    143 	  if ((bsi & 2) != 0)
    144 	    {
    145 	      mpz_sub_ui (x2, x2, bsi >> 2);
    146 	      mpz_abs (x2, x2);
    147 	    }
    148 	  else
    149 	    mpz_add_ui (x2, x2, bsi >> 2);
    150 	  res = mpz_root (root1, x2, nth);
    151 	}
    152 
    153       check_one (root1, x2, nth, res, i);
    154 
    155       if (((nth & 1) != 0) && ((bsi & 2) != 0))
    156 	{
    157 	  mpz_neg (x2, x2);
    158 	  mpz_neg (root1, root1);
    159 	  check_one (root1, x2, nth, res, i);
    160 	}
    161     }
    162 
    163   mpz_clear (bs);
    164   mpz_clear (x2);
    165   mpz_clear (root1);
    166 
    167   tests_end ();
    168   exit (0);
    169 }
    170 
    171 void
    172 debug_mp (mpz_t x, int base)
    173 {
    174   mpz_out_str (stderr, base, x); fputc ('\n', stderr);
    175 }
    176