[BACK]Return to ui_pow_ui.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpz

Diff for /OpenXM_contrib/gmp/mpz/Attic/ui_pow_ui.c between version 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2000/09/09 14:13:00 version 1.1.1.3, 2003/08/25 16:06:34
Line 1 
Line 1 
 /* mpz_ui_pow_ui(res, base, exp) -- Set RES to BASE**EXP.  /* mpz_ui_pow_ui -- ulong raised to ulong.
   
 Copyright (C) 1991, 1993, 1994, 1996, 1997, 2000 Free Software Foundation,  Copyright 2001, 2002 Free Software Foundation, Inc.
 Inc.  
   
 This file is part of the GNU MP Library.  This file is part of the GNU MP Library.
   
Line 22  MA 02111-1307, USA. */
Line 21  MA 02111-1307, USA. */
   
 #include "gmp.h"  #include "gmp.h"
 #include "gmp-impl.h"  #include "gmp-impl.h"
 #include "longlong.h"  
   
   
 static void mpz_pow2 _PROTO ((mpz_ptr r, mp_limb_t blimb, unsigned long int e, mp_limb_t rl));  
   
 void  void
 #if __STDC__  mpz_ui_pow_ui (mpz_ptr r, unsigned long b, unsigned long e)
 mpz_ui_pow_ui (mpz_ptr r, unsigned long int b, unsigned long int e)  
 #else  
 mpz_ui_pow_ui (r, b, e)  
      mpz_ptr r;  
      unsigned long int b;  
      unsigned long int e;  
 #endif  
 {  {
   mp_limb_t blimb = b;  #if GMP_NAIL_BITS != 0
   mp_limb_t rl;    if (b > GMP_NUMB_MAX)
   
   if (e == 0)  
     {      {
       /* For x^0 we return 1, even if x is 0.  */        mp_limb_t bb[2];
       r->_mp_d[0] = 1;        bb[0] = b & GMP_NUMB_MASK;
       r->_mp_size = 1;        bb[1] = b >> GMP_NUMB_BITS;
       return;        mpz_n_pow_ui (r, bb, (mp_size_t) 2, e);
     }      }
     else
   /* Compute b^e as (b^n)^(e div n) * b^(e mod n), where n is chosen such that  #endif
      the latter factor is the largest number small enough to fit in a limb.  */  
   
   rl = 1;  
   while (e != 0 && blimb < ((mp_limb_t) 1 << BITS_PER_MP_LIMB/2))  
     {      {
       if ((e & 1) != 0)  #ifdef _LONG_LONG_LIMB
         rl = rl * blimb;        /* i386 gcc 2.95.3 doesn't recognise blimb can be eliminated when
       blimb = blimb * blimb;           mp_limb_t is an unsigned long, so only use a separate blimb when
       e = e >> 1;           necessary.  */
     }        mp_limb_t  blimb = b;
         mpz_n_pow_ui (r, &blimb, (mp_size_t) (b != 0), e);
   /* rl is now b^(e mod n).  (I.e., the latter factor above.)  */  
   
   if (e == 0)  
     {  
       r->_mp_d[0] = rl;  
       r->_mp_size = rl != 0;  
       return;  
     }  
   
   mpz_pow2 (r, blimb, e, rl);  
 }  
   
 /* Multi-precision part of expontialization code.  */  
 static void  
 #if __STDC__  
 mpz_pow2 (mpz_ptr r, mp_limb_t blimb, unsigned long int e, mp_limb_t rl)  
 #else  #else
 mpz_pow2 (r, blimb, e, rl)        mpz_n_pow_ui (r, &b,     (mp_size_t) (b != 0), e);
      mpz_ptr r;  
      mp_limb_t blimb;  
      unsigned long int e;  
      mp_limb_t rl;  
 #endif  #endif
 {  
   mp_ptr rp, tp;  
   mp_size_t ralloc, rsize;  
   int cnt, i;  
   TMP_DECL (marker);  
   
   TMP_MARK (marker);  
   
   /* Over-estimate temporary space requirements somewhat.  */  
   count_leading_zeros (cnt, blimb);  
   ralloc = e - cnt * e / BITS_PER_MP_LIMB + 1;  
   
   /* The two areas are used to alternatingly hold the input and receive the  
      product for mpn_mul.  (Needed since mpn_mul_n requires that the product  
      is distinct from either input operand.)  */  
   rp = (mp_ptr) TMP_ALLOC (ralloc * BYTES_PER_MP_LIMB);  
   tp = (mp_ptr) TMP_ALLOC (ralloc * BYTES_PER_MP_LIMB);  
   
   rp[0] = blimb;  
   rsize = 1;  
   
   count_leading_zeros (cnt, e);  
   for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)  
     {  
       mpn_mul_n (tp, rp, rp, rsize);  
       rsize = 2 * rsize;  
       rsize -= tp[rsize - 1] == 0;  
       MP_PTR_SWAP (rp, tp);  
   
       if ((e & ((mp_limb_t) 1 << i)) != 0)  
         {  
           mp_limb_t cy;  
           cy = mpn_mul_1 (rp, rp, rsize, blimb);  
           rp[rsize] = cy;  
           rsize += cy != 0;  
         }  
     }      }
   
   /* We will need rsize or rsize+1 limbs for the result.  */  
   if (r->_mp_alloc <= rsize)  
     _mpz_realloc (r, rsize + 1);  
   
   /* Multiply the two factors (in rp,rsize and rl) and put the final result  
      in place.  */  
   {  
     mp_limb_t cy;  
     cy = mpn_mul_1 (r->_mp_d, rp, rsize, rl);  
     (r->_mp_d)[rsize] = cy;  
     rsize += cy != 0;  
   }  
   
   r->_mp_size = rsize;  
   TMP_FREE (marker);  
 }  }
   

Legend:
Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>