github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpz/t-root.c (about)

     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  }