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

     1  /* Reference mpz functions.
     2  
     3  Copyright 1997, 1999-2002 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  /* always do assertion checking */
    21  #define WANT_ASSERT  1
    22  
    23  #include <stdio.h>
    24  #include <stdlib.h> /* for free */
    25  #include "gmp.h"
    26  #include "gmp-impl.h"
    27  #include "longlong.h"
    28  #include "tests.h"
    29  
    30  
    31  /* Change this to "#define TRACE(x) x" for some traces. */
    32  #define TRACE(x)
    33  
    34  
    35  /* FIXME: Shouldn't use plain mpz functions in a reference routine. */
    36  void
    37  refmpz_combit (mpz_ptr r, unsigned long bit)
    38  {
    39    if (mpz_tstbit (r, bit))
    40      mpz_clrbit (r, bit);
    41    else
    42      mpz_setbit (r, bit);
    43  }
    44  
    45  
    46  unsigned long
    47  refmpz_hamdist (mpz_srcptr x, mpz_srcptr y)
    48  {
    49    mp_size_t      xsize, ysize, tsize;
    50    mp_ptr         xp, yp;
    51    unsigned long  ret;
    52  
    53    if ((SIZ(x) < 0 && SIZ(y) >= 0)
    54        || (SIZ(y) < 0 && SIZ(x) >= 0))
    55      return ULONG_MAX;
    56  
    57    xsize = ABSIZ(x);
    58    ysize = ABSIZ(y);
    59    tsize = MAX (xsize, ysize);
    60  
    61    xp = refmpn_malloc_limbs (tsize);
    62    refmpn_zero (xp, tsize);
    63    refmpn_copy (xp, PTR(x), xsize);
    64  
    65    yp = refmpn_malloc_limbs (tsize);
    66    refmpn_zero (yp, tsize);
    67    refmpn_copy (yp, PTR(y), ysize);
    68  
    69    if (SIZ(x) < 0)
    70      refmpn_neg (xp, xp, tsize);
    71  
    72    if (SIZ(x) < 0)
    73      refmpn_neg (yp, yp, tsize);
    74  
    75    ret = refmpn_hamdist (xp, yp, tsize);
    76  
    77    free (xp);
    78    free (yp);
    79    return ret;
    80  }
    81  
    82  
    83  /* (0/b), with mpz b; is 1 if b=+/-1, 0 otherwise */
    84  #define JACOBI_0Z(b)  JACOBI_0LS (PTR(b)[0], SIZ(b))
    85  
    86  /* (a/b) effect due to sign of b: mpz/mpz */
    87  #define JACOBI_BSGN_ZZ_BIT1(a, b)   JACOBI_BSGN_SS_BIT1 (SIZ(a), SIZ(b))
    88  
    89  /* (a/b) effect due to sign of a: mpz/unsigned-mpz, b odd;
    90     is (-1/b) if a<0, or +1 if a>=0 */
    91  #define JACOBI_ASGN_ZZU_BIT1(a, b)  JACOBI_ASGN_SU_BIT1 (SIZ(a), PTR(b)[0])
    92  
    93  int
    94  refmpz_kronecker (mpz_srcptr a_orig, mpz_srcptr b_orig)
    95  {
    96    unsigned long  twos;
    97    mpz_t  a, b;
    98    int    result_bit1 = 0;
    99  
   100    if (mpz_sgn (b_orig) == 0)
   101      return JACOBI_Z0 (a_orig);  /* (a/0) */
   102  
   103    if (mpz_sgn (a_orig) == 0)
   104      return JACOBI_0Z (b_orig);  /* (0/b) */
   105  
   106    if (mpz_even_p (a_orig) && mpz_even_p (b_orig))
   107      return 0;
   108  
   109    if (mpz_cmp_ui (b_orig, 1) == 0)
   110      return 1;
   111  
   112    mpz_init_set (a, a_orig);
   113    mpz_init_set (b, b_orig);
   114  
   115    if (mpz_sgn (b) < 0)
   116      {
   117        result_bit1 ^= JACOBI_BSGN_ZZ_BIT1 (a, b);
   118        mpz_neg (b, b);
   119      }
   120    if (mpz_even_p (b))
   121      {
   122        twos = mpz_scan1 (b, 0L);
   123        mpz_tdiv_q_2exp (b, b, twos);
   124        result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, PTR(a)[0]);
   125      }
   126  
   127    if (mpz_sgn (a) < 0)
   128      {
   129        result_bit1 ^= JACOBI_N1B_BIT1 (PTR(b)[0]);
   130        mpz_neg (a, a);
   131      }
   132    if (mpz_even_p (a))
   133      {
   134        twos = mpz_scan1 (a, 0L);
   135        mpz_tdiv_q_2exp (a, a, twos);
   136        result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, PTR(b)[0]);
   137      }
   138  
   139    for (;;)
   140      {
   141        ASSERT (mpz_odd_p (a));
   142        ASSERT (mpz_odd_p (b));
   143        ASSERT (mpz_sgn (a) > 0);
   144        ASSERT (mpz_sgn (b) > 0);
   145  
   146        TRACE (printf ("top\n");
   147  	     mpz_trace (" a", a);
   148  	     mpz_trace (" b", b));
   149  
   150        if (mpz_cmp (a, b) < 0)
   151  	{
   152  	  TRACE (printf ("swap\n"));
   153  	  mpz_swap (a, b);
   154  	  result_bit1 ^= JACOBI_RECIP_UU_BIT1 (PTR(a)[0], PTR(b)[0]);
   155  	}
   156  
   157        if (mpz_cmp_ui (b, 1) == 0)
   158  	break;
   159  
   160        mpz_sub (a, a, b);
   161        TRACE (printf ("sub\n");
   162  	     mpz_trace (" a", a));
   163        if (mpz_sgn (a) == 0)
   164  	goto zero;
   165  
   166        twos = mpz_scan1 (a, 0L);
   167        mpz_fdiv_q_2exp (a, a, twos);
   168        TRACE (printf ("twos %lu\n", twos);
   169  	     mpz_trace (" a", a));
   170        result_bit1 ^= JACOBI_TWOS_U_BIT1 (twos, PTR(b)[0]);
   171      }
   172  
   173    mpz_clear (a);
   174    mpz_clear (b);
   175    return JACOBI_BIT1_TO_PN (result_bit1);
   176  
   177   zero:
   178    mpz_clear (a);
   179    mpz_clear (b);
   180    return 0;
   181  }
   182  
   183  /* Same as mpz_kronecker, but ignoring factors of 2 on b */
   184  int
   185  refmpz_jacobi (mpz_srcptr a, mpz_srcptr b)
   186  {
   187    ASSERT_ALWAYS (mpz_sgn (b) > 0);
   188    ASSERT_ALWAYS (mpz_odd_p (b));
   189  
   190    return refmpz_kronecker (a, b);
   191  }
   192  
   193  /* Legendre symbol via powm. p must be an odd prime. */
   194  int
   195  refmpz_legendre (mpz_srcptr a, mpz_srcptr p)
   196  {
   197    int res;
   198  
   199    mpz_t r;
   200    mpz_t e;
   201  
   202    ASSERT_ALWAYS (mpz_sgn (p) > 0);
   203    ASSERT_ALWAYS (mpz_odd_p (p));
   204  
   205    mpz_init (r);
   206    mpz_init (e);
   207  
   208    mpz_fdiv_r (r, a, p);
   209  
   210    mpz_set (e, p);
   211    mpz_sub_ui (e, e, 1);
   212    mpz_fdiv_q_2exp (e, e, 1);
   213    mpz_powm (r, r, e, p);
   214  
   215    /* Normalize to a more or less symmetric range around zero */
   216    if (mpz_cmp (r, e) > 0)
   217      mpz_sub (r, r, p);
   218  
   219    ASSERT_ALWAYS (mpz_cmpabs_ui (r, 1) <= 0);
   220  
   221    res = mpz_sgn (r);
   222  
   223    mpz_clear (r);
   224    mpz_clear (e);
   225  
   226    return res;
   227  }
   228  
   229  
   230  int
   231  refmpz_kronecker_ui (mpz_srcptr a, unsigned long b)
   232  {
   233    mpz_t  bz;
   234    int    ret;
   235    mpz_init_set_ui (bz, b);
   236    ret = refmpz_kronecker (a, bz);
   237    mpz_clear (bz);
   238    return ret;
   239  }
   240  
   241  int
   242  refmpz_kronecker_si (mpz_srcptr a, long b)
   243  {
   244    mpz_t  bz;
   245    int    ret;
   246    mpz_init_set_si (bz, b);
   247    ret = refmpz_kronecker (a, bz);
   248    mpz_clear (bz);
   249    return ret;
   250  }
   251  
   252  int
   253  refmpz_ui_kronecker (unsigned long a, mpz_srcptr b)
   254  {
   255    mpz_t  az;
   256    int    ret;
   257    mpz_init_set_ui (az, a);
   258    ret = refmpz_kronecker (az, b);
   259    mpz_clear (az);
   260    return ret;
   261  }
   262  
   263  int
   264  refmpz_si_kronecker (long a, mpz_srcptr b)
   265  {
   266    mpz_t  az;
   267    int    ret;
   268    mpz_init_set_si (az, a);
   269    ret = refmpz_kronecker (az, b);
   270    mpz_clear (az);
   271    return ret;
   272  }
   273  
   274  
   275  void
   276  refmpz_pow_ui (mpz_ptr w, mpz_srcptr b, unsigned long e)
   277  {
   278    mpz_t          s, t;
   279    unsigned long  i;
   280  
   281    mpz_init_set_ui (t, 1L);
   282    mpz_init_set (s, b);
   283  
   284    if ((e & 1) != 0)
   285      mpz_mul (t, t, s);
   286  
   287    for (i = 2; i <= e; i <<= 1)
   288      {
   289        mpz_mul (s, s, s);
   290        if ((i & e) != 0)
   291  	mpz_mul (t, t, s);
   292      }
   293  
   294    mpz_set (w, t);
   295  
   296    mpz_clear (s);
   297    mpz_clear (t);
   298  }