(root)/
gmp-6.3.0/
tests/
mpz/
t-pow.c
       1  /* Test mpz_pow_ui and mpz_ui_pow_ui.
       2  
       3  Copyright 1997, 1999-2001 Free Software Foundation, Inc.
       4  
       5  This file is part of the GNU MP Library test suite.
       6  
       7  The GNU MP Library test suite is free software; you can redistribute it
       8  and/or modify it under the terms of the GNU General Public License as
       9  published by the Free Software Foundation; either version 3 of the License,
      10  or (at your option) any later version.
      11  
      12  The GNU MP Library test suite is distributed in the hope that it will be
      13  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
      15  Public License for more details.
      16  
      17  You should have received a copy of the GNU General Public License along with
      18  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
      19  
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  
      23  #include "gmp-impl.h"
      24  #include "tests.h"
      25  
      26  
      27  void
      28  check_one (mpz_srcptr want, mpz_srcptr base, unsigned long exp)
      29  {
      30    mpz_t  got;
      31  
      32    mpz_init (got);
      33  
      34    MPZ_CHECK_FORMAT (want);
      35  
      36    mpz_pow_ui (got, base, exp);
      37    if (mpz_cmp (got, want))
      38      {
      39        printf ("mpz_pow_ui wrong\n");
      40        mpz_trace ("  base", base);
      41        printf    ("  exp = %lu (0x%lX)\n", exp, exp);
      42        mpz_trace ("  got ", got);
      43        mpz_trace ("  want", want);
      44        abort ();
      45      }
      46  
      47    mpz_set (got, base);
      48    mpz_pow_ui (got, got, exp);
      49    if (mpz_cmp (got, want))
      50      {
      51        printf ("mpz_pow_ui wrong\n");
      52        mpz_trace ("  base", base);
      53        printf    ("  exp = %lu (0x%lX)\n", exp, exp);
      54        mpz_trace ("  got ", got);
      55        mpz_trace ("  want", want);
      56        abort ();
      57      }
      58  
      59    if (mpz_fits_ulong_p (base))
      60      {
      61        unsigned long  base_u = mpz_get_ui (base);
      62        mpz_ui_pow_ui (got, base_u, exp);
      63        if (mpz_cmp (got, want))
      64  	{
      65  	  printf    ("mpz_ui_pow_ui wrong\n");
      66  	  printf    ("  base=%lu (0x%lX)\n", base_u, base_u);
      67  	  printf    ("  exp = %lu (0x%lX)\n", exp, exp);
      68  	  mpz_trace ("  got ", got);
      69  	  mpz_trace ("  want", want);
      70  	  abort ();
      71  	}
      72      }
      73  
      74    mpz_clear (got);
      75  }
      76  
      77  void
      78  check_base (mpz_srcptr base)
      79  {
      80    unsigned long  exp;
      81    mpz_t          want;
      82  
      83    mpz_init (want);
      84    mpz_set_ui (want, 1L);
      85  
      86    for (exp = 0; exp < 20; exp++)
      87      {
      88        check_one (want, base, exp);
      89        mpz_mul (want, want, base);
      90      }
      91  
      92    mpz_clear (want);
      93  }
      94  
      95  void
      96  check_various (void)
      97  {
      98    static const struct {
      99      const char *base;
     100    } data[] = {
     101      { "0" },
     102      { "1" },
     103      { "2" },
     104      { "3" },
     105      { "4" },
     106      { "5" },
     107      { "6" },
     108      { "10" },
     109      { "15" },
     110      { "16" },
     111  
     112      { "0x1F" },
     113      { "0xFF" },
     114      { "0x1001" },
     115      { "0xFFFF" },
     116      { "0x10000001" },
     117      { "0x1000000000000001" },
     118  
     119      /* actual size closest to estimate */
     120      { "0xFFFFFFFF" },
     121      { "0xFFFFFFFFFFFFFFFF" },
     122  
     123      /* same after rshift */
     124      { "0xFFFFFFFF0" },
     125      { "0xFFFFFFFF00" },
     126      { "0xFFFFFFFFFFFFFFFF0" },
     127      { "0xFFFFFFFFFFFFFFFF00" },
     128  
     129      /* change from 2 limbs to 1 after rshift */
     130      { "0x180000000" },
     131      { "0x18000000000000000" },
     132  
     133      /* change from 3 limbs to 2 after rshift */
     134      { "0x18000000100000000" },
     135      { "0x180000000000000010000000000000000" },
     136  
     137      /* handling of absolute value */
     138      { "-0x80000000" },
     139      { "-0x8000000000000000" },
     140  
     141      /* low zero limb, and size>2, checking argument overlap detection */
     142      { "0x3000000000000000300000000000000030000000000000000" },
     143    };
     144  
     145    mpz_t  base;
     146    int    i;
     147  
     148    mpz_init (base);
     149  
     150    for (i = 0; i < numberof (data); i++)
     151      {
     152        mpz_set_str_or_abort (base, data[i].base, 0);
     153        check_base (base);
     154      }
     155  
     156    mpz_clear (base);
     157  }
     158  
     159  void
     160  check_random (int reps)
     161  {
     162    mpz_t              base, want;
     163    mp_size_t          base_size;
     164    int                i;
     165    unsigned long      size_range, exp;
     166    gmp_randstate_ptr  rands = RANDS;
     167  
     168    mpz_init (base);
     169    mpz_init (want);
     170  
     171    for (i = 0; i < reps; i++)
     172      {
     173        /* exponentially random 0 to 2^13 bits for base */
     174        mpz_urandomb (want, rands, 32);
     175        size_range = mpz_get_ui (want) % 12 + 2;
     176        mpz_urandomb (want, rands, size_range);
     177        base_size = mpz_get_ui (want);
     178        mpz_rrandomb (base, rands, base_size);
     179  
     180        /* randomly signed base */
     181        mpz_urandomb (want, rands, 2);
     182        if ((mpz_get_ui (want) & 1) != 0)
     183  	mpz_neg (base, base);
     184  
     185        /* random 5 bits for exponent */
     186        mpz_urandomb (want, rands, 5L);
     187        exp = mpz_get_ui (want);
     188  
     189        refmpz_pow_ui (want, base, exp);
     190        check_one (want, base, exp);
     191      }
     192  
     193    mpz_clear (base);
     194    mpz_clear (want);
     195  }
     196  
     197  int
     198  main (int argc, char **argv)
     199  {
     200    int reps = 5000;
     201  
     202    /* dummy call to drag in refmpn.o for testing mpz/n_pow_ui.c with
     203       refmpn_mul_2 */
     204    refmpn_zero_p (NULL, (mp_size_t) 0);
     205  
     206    tests_start ();
     207    mp_trace_base = -16;
     208  
     209    if (argc == 2)
     210       reps = atoi (argv[1]);
     211  
     212    check_various ();
     213    check_random (reps);
     214  
     215    tests_end ();
     216    exit (0);
     217  }