[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     ! 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>