(root)/
gmp-6.3.0/
tests/
mpz/
t-cong_2exp.c
       1  /* test mpz_congruent_2exp_p */
       2  
       3  /*
       4  Copyright 2001, 2013 Free Software 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  #include "gmp-impl.h"
      24  #include "tests.h"
      25  
      26  
      27  void
      28  check_one (mpz_srcptr a, mpz_srcptr c, unsigned long d, int want)
      29  {
      30    mpz_t  diff, d2exp;
      31    int    got;
      32    int    swap;
      33  
      34    for (swap = 0; swap <= 1; swap++)
      35      {
      36        got = (mpz_congruent_2exp_p (a, c, d) != 0);
      37        if (want != got)
      38          {
      39            mpz_init (diff);
      40            mpz_init (d2exp);
      41  
      42            mpz_sub (diff, a, c);
      43            mpz_set_ui (d2exp, 1L);
      44            mpz_mul_2exp (d2exp, d2exp, d);
      45  
      46            printf ("mpz_congruent_2exp_p wrong\n");
      47            printf ("   expected %d got %d\n", want, got);
      48            mpz_trace ("   a", a);
      49            mpz_trace ("   c", c);
      50            mpz_trace (" a-c", diff);
      51            mpz_trace (" 2^d", d2exp);
      52            printf    ("   d=%lu\n", d);
      53  
      54            mp_trace_base = -16;
      55            mpz_trace ("   a", a);
      56            mpz_trace ("   c", c);
      57            mpz_trace (" a-c", diff);
      58            mpz_trace (" 2^d", d2exp);
      59            printf    ("   d=0x%lX\n", d);
      60            abort ();
      61          }
      62  
      63        MPZ_SRCPTR_SWAP (a, c);
      64      }
      65  }
      66  
      67  
      68  void
      69  check_data (void)
      70  {
      71    static const struct {
      72      const char     *a;
      73      const char     *c;
      74      unsigned long  d;
      75      int            want;
      76  
      77    } data[] = {
      78  
      79      /* anything is congruent mod 1 */
      80      { "0", "0", 0, 1 },
      81      { "1", "0", 0, 1 },
      82      { "0", "1", 0, 1 },
      83      { "123", "-456", 0, 1 },
      84      { "0x123456789123456789", "0x987654321987654321", 0, 1 },
      85      { "0xfffffffffffffffffffffffffffffff7", "-0x9", 129, 0 },
      86      { "0xfffffffffffffffffffffffffffffff6", "-0xa", 128, 1 },
      87  
      88    };
      89  
      90    mpz_t   a, c;
      91    int     i;
      92  
      93    mpz_init (a);
      94    mpz_init (c);
      95  
      96    for (i = 0; i < numberof (data); i++)
      97      {
      98        mpz_set_str_or_abort (a, data[i].a, 0);
      99        mpz_set_str_or_abort (c, data[i].c, 0);
     100        check_one (a, c, data[i].d, data[i].want);
     101      }
     102  
     103    mpz_clear (a);
     104    mpz_clear (c);
     105  }
     106  
     107  
     108  void
     109  check_random (int reps)
     110  {
     111    gmp_randstate_ptr rands = RANDS;
     112    unsigned long  d;
     113    mpz_t  a, c, ra, rc;
     114    int    i;
     115  
     116    mpz_init (a);
     117    mpz_init (c);
     118    mpz_init (ra);
     119    mpz_init (rc);
     120  
     121    for (i = 0; i < reps; i++)
     122      {
     123        mpz_errandomb (a, rands, 8*GMP_LIMB_BITS);
     124        mpz_errandomb (c, rands, 8*GMP_LIMB_BITS);
     125        d = urandom() % (8*GMP_LIMB_BITS);
     126  
     127        mpz_mul_2exp (a, a, urandom() % (2*GMP_LIMB_BITS));
     128        mpz_mul_2exp (c, c, urandom() % (2*GMP_LIMB_BITS));
     129  
     130        mpz_negrandom (a, rands);
     131        mpz_negrandom (c, rands);
     132  
     133        mpz_fdiv_r_2exp (ra, a, d);
     134        mpz_fdiv_r_2exp (rc, c, d);
     135  
     136        mpz_sub (ra, ra, rc);
     137        if (mpz_cmp_ui (ra, 0) != 0)
     138  	{
     139  	  check_one (a, c, d, 0);
     140  	  mpz_sub (a, a, ra);
     141  	}
     142        check_one (a, c, d, 1);
     143        if (d != 0)
     144  	{
     145  	  mpz_combit (a, urandom() % d);
     146  	  check_one (a, c, d, 0);
     147  	}
     148      }
     149  
     150    mpz_clear (a);
     151    mpz_clear (c);
     152    mpz_clear (ra);
     153    mpz_clear (rc);
     154  }
     155  
     156  void
     157  check_random_bits (int reps)
     158  {
     159    mp_bitcnt_t ea, ec, en, d;
     160    mp_bitcnt_t m = 10 * GMP_LIMB_BITS;
     161    mpz_t  a, c;
     162    int    i;
     163  
     164    mpz_init2 (a, m + 1);
     165    mpz_init2 (c, m);
     166  
     167    for (i = 0; i < reps; i++)
     168      {
     169        d  = urandom() % m;
     170        ea = urandom() % m;
     171        ec = urandom() % m;
     172        en = urandom() % m;
     173  
     174        mpz_set_ui (c, 0);
     175        mpz_setbit (c, en);
     176  
     177        mpz_set_ui (a, 0);
     178        mpz_setbit (a, ec);
     179        mpz_sub (c , a, c);
     180  
     181        mpz_set_ui (a, 0);
     182        mpz_setbit (a, ea);
     183        mpz_add (a , a, c);
     184  
     185        check_one (a, c, d, ea >= d);
     186      }
     187  
     188    mpz_clear (a);
     189    mpz_clear (c);
     190  }
     191  
     192  
     193  int
     194  main (int argc, char *argv[])
     195  {
     196    int    reps = 5000;
     197  
     198    tests_start ();
     199    TESTS_REPS (reps, argv, argc);
     200  
     201    check_data ();
     202    check_random (reps);
     203    check_random_bits (reps);
     204  
     205    tests_end ();
     206    exit (0);
     207  }