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

Annotation of OpenXM_contrib/gmp/mpz/perfpow.c, Revision 1.1.1.1

1.1       maekawa     1: /* mpz_perfect_power_p(arg) -- Return non-zero if ARG is a perfect power,
                      2:    zero otherwise.
                      3:
                      4: Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
                      5:
                      6: This file is part of the GNU MP Library.
                      7:
                      8: The GNU MP Library is free software; you can redistribute it and/or modify
                      9: it under the terms of the GNU Lesser General Public License as published by
                     10: the Free Software Foundation; either version 2.1 of the License, or (at your
                     11: option) any later version.
                     12:
                     13: The GNU MP Library is distributed in the hope that it will be useful, but
                     14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15: or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
                     16: License for more details.
                     17:
                     18: You should have received a copy of the GNU Lesser General Public License
                     19: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     21: MA 02111-1307, USA. */
                     22:
                     23: /*
                     24:   We are to determine if c is a perfect power, c = a ^ b.
                     25:   Assume c is divisible by 2^n and that codd = c/2^n is odd.
                     26:   Assume a is divisible by 2^m and that aodd = a/2^m is odd.
                     27:   It is always true that m divides n.
                     28:
                     29:   * If n is prime, either 1) a is 2*aodd and b = n
                     30:                       or 2) a = c and b = 1.
                     31:     So for n prime, we readily have a solution.
                     32:   * If n is factorable into the non-trivial factors p1,p2,...
                     33:     Since m divides n, m has a subset of n's factors and b = n / m.
                     34:
                     35:     BUG: Should handle negative numbers, since they can be odd perfect powers.
                     36: */
                     37:
                     38: /* This is a naive approach to recognizing perfect powers.
                     39:    Many things can be improved.  In particular, we should use p-adic
                     40:    arithmetic for computing possible roots.  */
                     41:
                     42: #include <stdio.h> /* for NULL */
                     43: #include "gmp.h"
                     44: #include "gmp-impl.h"
                     45: #include "longlong.h"
                     46:
                     47: static unsigned long int gcd _PROTO ((unsigned long int a, unsigned long int b));
                     48: static int isprime _PROTO ((unsigned long int t));
                     49:
                     50: static const unsigned short primes[] =
                     51: {  2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
                     52:   59, 61, 67, 71, 73, 79, 83, 89, 97,101,103,107,109,113,127,131,
                     53:  137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,
                     54:  227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,
                     55:  313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,
                     56:  419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,
                     57:  509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,
                     58:  617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,
                     59:  727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,
                     60:  829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,
                     61:  947,953,967,971,977,983,991,997,0
                     62: };
                     63: #define SMALLEST_OMITTED_PRIME 1009
                     64:
                     65:
                     66: int
                     67: #if __STDC__
                     68: mpz_perfect_power_p (mpz_srcptr u)
                     69: #else
                     70: mpz_perfect_power_p (u)
                     71:      mpz_srcptr u;
                     72: #endif
                     73: {
                     74:   unsigned long int prime;
                     75:   unsigned long int n, n2;
                     76:   int i;
                     77:   unsigned long int rem;
                     78:   mpz_t u2, q;
                     79:   int exact;
                     80:   mp_size_t uns;
                     81:   TMP_DECL (marker);
                     82:
                     83:   if (mpz_cmp_ui (u, 1) <= 0)
                     84:     return 0;
                     85:
                     86:   n2 = mpz_scan1 (u, 0);
                     87:   if (n2 == 1)
                     88:     return 0;
                     89:
                     90:   TMP_MARK (marker);
                     91:
                     92:   uns = ABSIZ (u) - n2 / BITS_PER_MP_LIMB;
                     93:   MPZ_TMP_INIT (q, uns);
                     94:   MPZ_TMP_INIT (u2, uns);
                     95:
                     96:   mpz_tdiv_q_2exp (u2, u, n2);
                     97:
                     98:   if (isprime (n2))
                     99:     goto n2prime;
                    100:
                    101:   for (i = 1; primes[i] != 0; i++)
                    102:     {
                    103:       prime = primes[i];
                    104:       rem = mpz_tdiv_ui (u2, prime);
                    105:       if (rem == 0)            /* divisable? */
                    106:        {
                    107:          rem = mpz_tdiv_q_ui (q, u2, prime * prime);
                    108:          if (rem != 0)
                    109:            {
                    110:              TMP_FREE (marker);
                    111:              return 0;
                    112:            }
                    113:          mpz_swap (q, u2);
                    114:          for (n = 2;;)
                    115:            {
                    116:              rem = mpz_tdiv_q_ui (q, u2, prime);
                    117:              if (rem != 0)
                    118:                break;
                    119:              mpz_swap (q, u2);
                    120:              n++;
                    121:            }
                    122:
                    123:          n2 = gcd (n2, n);
                    124:          if (n2 == 1)
                    125:            {
                    126:              TMP_FREE (marker);
                    127:              return 0;
                    128:            }
                    129:
                    130:          /* As soon as n2 becomes a prime number, stop factoring.
                    131:             Either we have u=x^n2 or u is not a perfect power.  */
                    132:          if (isprime (n2))
                    133:            goto n2prime;
                    134:        }
                    135:     }
                    136:
                    137:   if (mpz_cmp_ui (u2, 1) == 0)
                    138:     {
                    139:       TMP_FREE (marker);
                    140:       return 1;
                    141:     }
                    142:
                    143:   if (n2 == 0)
                    144:     {
                    145:       unsigned long int nth;
                    146:       /* We did not find any factors above.  We have to consider all values
                    147:         of n.  */
                    148:       for (nth = 2;; nth++)
                    149:        {
                    150:          if (! isprime (nth))
                    151:            continue;
                    152: #if 0
                    153:          exact = mpz_padic_root (q, u2, nth, PTH);
                    154:          if (exact)
                    155: #endif
                    156:            exact = mpz_root (q, u2, nth);
                    157:          if (exact)
                    158:            {
                    159:              TMP_FREE (marker);
                    160:              return 1;
                    161:            }
                    162:          if (mpz_cmp_ui (q, SMALLEST_OMITTED_PRIME) < 0)
                    163:            {
                    164:              TMP_FREE (marker);
                    165:              return 0;
                    166:            }
                    167:        }
                    168:     }
                    169:   else
                    170:     {
                    171:       unsigned long int nth;
                    172:       /* We found some factors above.  We just need to consider values of n
                    173:         that divides n2.  */
                    174:       for (nth = 2; nth <= n2; nth++)
                    175:        {
                    176:          if (! isprime (nth))
                    177:            continue;
                    178:          if (n2 % nth != 0)
                    179:            continue;
                    180: #if 0
                    181:          exact = mpz_padic_root (q, u2, nth, PTH);
                    182:          if (exact)
                    183: #endif
                    184:            exact = mpz_root (q, u2, nth);
                    185:          if (exact)
                    186:            {
                    187:              TMP_FREE (marker);
                    188:              return 1;
                    189:            }
                    190:          if (mpz_cmp_ui (q, SMALLEST_OMITTED_PRIME) < 0)
                    191:            {
                    192:              TMP_FREE (marker);
                    193:              return 0;
                    194:            }
                    195:        }
                    196:
                    197:       TMP_FREE (marker);
                    198:       return 0;
                    199:     }
                    200:
                    201: n2prime:
                    202:   exact = mpz_root (NULL, u2, n2);
                    203:   TMP_FREE (marker);
                    204:   return exact;
                    205: }
                    206:
                    207: static unsigned long int
                    208: #if __STDC__
                    209: gcd (unsigned long int a, unsigned long int b)
                    210: #else
                    211: gcd (a, b)
                    212:      unsigned long int a, b;
                    213: #endif
                    214: {
                    215:   int an2, bn2, n2;
                    216:
                    217:   if (a == 0)
                    218:     return b;
                    219:   if (b == 0)
                    220:     return a;
                    221:
                    222:   count_trailing_zeros (an2, a);
                    223:   a >>= an2;
                    224:
                    225:   count_trailing_zeros (bn2, b);
                    226:   b >>= bn2;
                    227:
                    228:   n2 = MIN (an2, bn2);
                    229:
                    230:   while (a != b)
                    231:     {
                    232:       if (a > b)
                    233:        {
                    234:          a -= b;
                    235:          do
                    236:            a >>= 1;
                    237:          while ((a & 1) == 0);
                    238:        }
                    239:       else /*  b > a.  */
                    240:        {
                    241:          b -= a;
                    242:          do
                    243:            b >>= 1;
                    244:          while ((b & 1) == 0);
                    245:        }
                    246:     }
                    247:
                    248:   return a << n2;
                    249: }
                    250:
                    251: static int
                    252: #if __STDC__
                    253: isprime (unsigned long int t)
                    254: #else
                    255: isprime (t)
                    256:      unsigned long int t;
                    257: #endif
                    258: {
                    259:   unsigned long int q, r, d;
                    260:
                    261:   if (t < 3 || (t & 1) == 0)
                    262:     return t == 2;
                    263:
                    264:   for (d = 3, r = 1; r != 0; d += 2)
                    265:     {
                    266:       q = t / d;
                    267:       r = t - q * d;
                    268:       if (q < d)
                    269:        return 1;
                    270:     }
                    271:   return 0;
                    272: }

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