Home | History | Annotate | Line # | Download | only in generic
pow_1.c revision 1.1.1.2
      1      1.1  mrg /* mpn_pow_1 -- Compute powers R = U^exp.
      2      1.1  mrg 
      3      1.1  mrg    THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY.  THEY'RE ALMOST
      4      1.1  mrg    CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
      5      1.1  mrg    FUTURE GNU MP RELEASES.
      6      1.1  mrg 
      7  1.1.1.2  mrg Copyright 2002, 2014 Free Software Foundation, Inc.
      8      1.1  mrg 
      9      1.1  mrg This file is part of the GNU MP Library.
     10      1.1  mrg 
     11  1.1.1.2  mrg The GNU MP Library is free software; you can redistribute it and/or modify
     12  1.1.1.2  mrg it under the terms of either:
     13  1.1.1.2  mrg 
     14  1.1.1.2  mrg   * the GNU Lesser General Public License as published by the Free
     15  1.1.1.2  mrg     Software Foundation; either version 3 of the License, or (at your
     16  1.1.1.2  mrg     option) any later version.
     17  1.1.1.2  mrg 
     18  1.1.1.2  mrg or
     19  1.1.1.2  mrg 
     20  1.1.1.2  mrg   * the GNU General Public License as published by the Free Software
     21  1.1.1.2  mrg     Foundation; either version 2 of the License, or (at your option) any
     22  1.1.1.2  mrg     later version.
     23  1.1.1.2  mrg 
     24  1.1.1.2  mrg or both in parallel, as here.
     25      1.1  mrg 
     26      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     27  1.1.1.2  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     28  1.1.1.2  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     29      1.1  mrg for more details.
     30      1.1  mrg 
     31  1.1.1.2  mrg You should have received copies of the GNU General Public License and the
     32  1.1.1.2  mrg GNU Lesser General Public License along with the GNU MP Library.  If not,
     33  1.1.1.2  mrg see https://www.gnu.org/licenses/.  */
     34      1.1  mrg 
     35      1.1  mrg 
     36      1.1  mrg #include "gmp.h"
     37      1.1  mrg #include "gmp-impl.h"
     38      1.1  mrg #include "longlong.h"
     39      1.1  mrg 
     40      1.1  mrg mp_size_t
     41      1.1  mrg mpn_pow_1 (mp_ptr rp, mp_srcptr bp, mp_size_t bn, mp_limb_t exp, mp_ptr tp)
     42      1.1  mrg {
     43      1.1  mrg   mp_limb_t x;
     44      1.1  mrg   int cnt, i;
     45      1.1  mrg   mp_size_t rn;
     46      1.1  mrg   int par;
     47      1.1  mrg 
     48      1.1  mrg   ASSERT (bn >= 1);
     49      1.1  mrg   /* FIXME: Add operand overlap criteria */
     50      1.1  mrg 
     51      1.1  mrg   if (exp <= 1)
     52      1.1  mrg     {
     53      1.1  mrg       if (exp == 0)
     54      1.1  mrg 	{
     55      1.1  mrg 	  rp[0] = 1;
     56      1.1  mrg 	  return 1;
     57      1.1  mrg 	}
     58      1.1  mrg       else
     59      1.1  mrg 	{
     60      1.1  mrg 	  MPN_COPY (rp, bp, bn);
     61      1.1  mrg 	  return bn;
     62      1.1  mrg 	}
     63      1.1  mrg     }
     64      1.1  mrg 
     65      1.1  mrg   /* Count number of bits in exp, and compute where to put initial square in
     66      1.1  mrg      order to magically get results in the entry rp.  Use simple code,
     67      1.1  mrg      optimized for small exp.  For large exp, the bignum operations will take
     68      1.1  mrg      so much time that the slowness of this code will be negligible.  */
     69      1.1  mrg   par = 0;
     70      1.1  mrg   cnt = GMP_LIMB_BITS;
     71  1.1.1.2  mrg   x = exp;
     72  1.1.1.2  mrg   do
     73      1.1  mrg     {
     74  1.1.1.2  mrg       par ^= x;
     75      1.1  mrg       cnt--;
     76  1.1.1.2  mrg       x >>= 1;
     77  1.1.1.2  mrg     } while (x != 0);
     78      1.1  mrg   exp <<= cnt;
     79      1.1  mrg 
     80      1.1  mrg   if (bn == 1)
     81      1.1  mrg     {
     82      1.1  mrg       mp_limb_t bl = bp[0];
     83      1.1  mrg 
     84      1.1  mrg       if ((cnt & 1) != 0)
     85      1.1  mrg 	MP_PTR_SWAP (rp, tp);
     86      1.1  mrg 
     87      1.1  mrg       mpn_sqr (rp, bp, bn);
     88      1.1  mrg       rn = 2 * bn; rn -= rp[rn - 1] == 0;
     89      1.1  mrg 
     90      1.1  mrg       for (i = GMP_LIMB_BITS - cnt - 1;;)
     91      1.1  mrg 	{
     92      1.1  mrg 	  exp <<= 1;
     93      1.1  mrg 	  if ((exp & GMP_LIMB_HIGHBIT) != 0)
     94      1.1  mrg 	    {
     95      1.1  mrg 	      rp[rn] = mpn_mul_1 (rp, rp, rn, bl);
     96      1.1  mrg 	      rn += rp[rn] != 0;
     97      1.1  mrg 	    }
     98      1.1  mrg 
     99      1.1  mrg 	  if (--i == 0)
    100      1.1  mrg 	    break;
    101      1.1  mrg 
    102      1.1  mrg 	  mpn_sqr (tp, rp, rn);
    103      1.1  mrg 	  rn = 2 * rn; rn -= tp[rn - 1] == 0;
    104      1.1  mrg 	  MP_PTR_SWAP (rp, tp);
    105      1.1  mrg 	}
    106      1.1  mrg     }
    107      1.1  mrg   else
    108      1.1  mrg     {
    109      1.1  mrg       if (((par ^ cnt) & 1) == 0)
    110      1.1  mrg 	MP_PTR_SWAP (rp, tp);
    111      1.1  mrg 
    112      1.1  mrg       mpn_sqr (rp, bp, bn);
    113      1.1  mrg       rn = 2 * bn; rn -= rp[rn - 1] == 0;
    114      1.1  mrg 
    115      1.1  mrg       for (i = GMP_LIMB_BITS - cnt - 1;;)
    116      1.1  mrg 	{
    117      1.1  mrg 	  exp <<= 1;
    118      1.1  mrg 	  if ((exp & GMP_LIMB_HIGHBIT) != 0)
    119      1.1  mrg 	    {
    120      1.1  mrg 	      rn = rn + bn - (mpn_mul (tp, rp, rn, bp, bn) == 0);
    121      1.1  mrg 	      MP_PTR_SWAP (rp, tp);
    122      1.1  mrg 	    }
    123      1.1  mrg 
    124      1.1  mrg 	  if (--i == 0)
    125      1.1  mrg 	    break;
    126      1.1  mrg 
    127      1.1  mrg 	  mpn_sqr (tp, rp, rn);
    128      1.1  mrg 	  rn = 2 * rn; rn -= tp[rn - 1] == 0;
    129      1.1  mrg 	  MP_PTR_SWAP (rp, tp);
    130      1.1  mrg 	}
    131      1.1  mrg     }
    132      1.1  mrg 
    133      1.1  mrg   return rn;
    134      1.1  mrg }
    135