mpz_perfect_power_p corrections and new test program

This commit is contained in:
jasonmoxham 2008-12-26 17:41:36 +00:00
parent 0c01599cab
commit c9dd7aea90
4 changed files with 180 additions and 26 deletions

View File

@ -3,6 +3,8 @@
Copyright 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
Copyright 2008 Jason Moxham
This file is part of the GNU MP Library.
The GNU MP Library is free software; you can redistribute it and/or modify
@ -81,8 +83,8 @@ mpz_perfect_power_p (mpz_srcptr u)
if (n2 == 1)
return 0; /* 2 divides exactly once. */
if (n2 != 0 && (n2 & 1) == 0 && usize < 0)
return 0; /* 2 has even multiplicity with negative U */
if (n2 > 1 && POW2_P(n2) && usize < 0)
return 0; /* 2 has power of two multiplicity with negative U */
TMP_MARK;
@ -117,10 +119,10 @@ mpz_perfect_power_p (mpz_srcptr u)
n++;
}
if ((n & 1) == 0 && usize < 0)
if ( POW2_P(n) && usize < 0)
{
TMP_FREE;
return 0; /* even multiplicity with negative U, reject */
return 0; /* power of two multiplicity with negative U, reject */
}
n2 = gcd (n2, n);
@ -133,6 +135,7 @@ mpz_perfect_power_p (mpz_srcptr u)
if (mpz_cmpabs_ui (u2, 1) == 0)
{
TMP_FREE;
if(usize<0 && POW2_P(n2))return 0;/* factoring completed; not consistent power */
return 1; /* factoring completed; consistent power */
}
@ -161,7 +164,7 @@ mpz_perfect_power_p (mpz_srcptr u)
TMP_FREE;
return 1;
}
if (mpz_cmp_ui (q, SMALLEST_OMITTED_PRIME) < 0)
if (mpz_cmpabs_ui (q, SMALLEST_OMITTED_PRIME) < 0)
{
TMP_FREE;
return 0;
@ -173,7 +176,7 @@ mpz_perfect_power_p (mpz_srcptr u)
unsigned long int nth;
/* We found some factors above. We just need to consider values of n
that divides n2. */
for (nth = 2; nth <= n2; nth++)
for (nth = usize < 0 ? 3 : 2; nth <= n2; nth++)
{
if (! isprime (nth))
continue;
@ -189,7 +192,7 @@ mpz_perfect_power_p (mpz_srcptr u)
TMP_FREE;
return 1;
}
if (mpz_cmp_ui (q, SMALLEST_OMITTED_PRIME) < 0)
if (mpz_cmpabs_ui (q, SMALLEST_OMITTED_PRIME) < 0)
{
TMP_FREE;
return 0;
@ -201,6 +204,7 @@ mpz_perfect_power_p (mpz_srcptr u)
}
n2prime:
if(n2==2 && usize<0){TMP_FREE;return 0;}
exact = mpz_root (NULL, u2, n2);
TMP_FREE;
return exact;

View File

@ -3,6 +3,8 @@
# Copyright 1996, 1997, 1999, 2000, 2001, 2002, 2003 Free Software
# Foundation, Inc.
#
# Copyright 2008 Jason Moxham
#
# This file is part of the GNU MP Library.
#
# The GNU MP Library is free software; you can redistribute it and/or modify
@ -32,7 +34,7 @@ check_PROGRAMS = t-addsub t-cmp t-mul t-mul_i t-tdiv t-tdiv_ui t-fdiv \
t-fac_ui t-fib_ui t-lucnum_ui t-scan t-fits \
t-divis t-divis_2exp t-cong t-cong_2exp t-sizeinbase t-set_str \
t-aorsmul t-cmp_d t-cmp_si t-hamdist t-oddeven t-popcount t-set_f \
t-io_raw t-import t-export t-pprime_p
t-io_raw t-import t-export t-pprime_p t-perfpow
TESTS = $(check_PROGRAMS)

View File

@ -17,6 +17,8 @@
# Copyright 1996, 1997, 1999, 2000, 2001, 2002, 2003 Free Software
# Foundation, Inc.
#
# Copyright 2008 Jason Moxham
#
# This file is part of the GNU MP Library.
#
# The GNU MP Library is free software; you can redistribute it and/or modify
@ -73,7 +75,8 @@ check_PROGRAMS = t-addsub$(EXEEXT) t-cmp$(EXEEXT) t-mul$(EXEEXT) \
t-set_str$(EXEEXT) t-aorsmul$(EXEEXT) t-cmp_d$(EXEEXT) \
t-cmp_si$(EXEEXT) t-hamdist$(EXEEXT) t-oddeven$(EXEEXT) \
t-popcount$(EXEEXT) t-set_f$(EXEEXT) t-io_raw$(EXEEXT) \
t-import$(EXEEXT) t-export$(EXEEXT) t-pprime_p$(EXEEXT)
t-import$(EXEEXT) t-export$(EXEEXT) t-pprime_p$(EXEEXT) \
t-perfpow$(EXEEXT)
subdir = tests/mpz
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -284,6 +287,11 @@ t_oddeven_OBJECTS = t-oddeven$U.$(OBJEXT)
t_oddeven_LDADD = $(LDADD)
t_oddeven_DEPENDENCIES = $(top_builddir)/tests/libtests.la \
$(top_builddir)/libgmp.la
t_perfpow_SOURCES = t-perfpow.c
t_perfpow_OBJECTS = t-perfpow$U.$(OBJEXT)
t_perfpow_LDADD = $(LDADD)
t_perfpow_DEPENDENCIES = $(top_builddir)/tests/libtests.la \
$(top_builddir)/libgmp.la
t_perfsqr_SOURCES = t-perfsqr.c
t_perfsqr_OBJECTS = t-perfsqr$U.$(OBJEXT)
t_perfsqr_LDADD = $(LDADD)
@ -382,10 +390,10 @@ SOURCES = bit.c convert.c dive.c dive_ui.c io.c logic.c reuse.c \
t-fib_ui.c t-fits.c t-gcd.c t-gcd_ui.c t-get_d.c \
t-get_d_2exp.c t-get_si.c t-hamdist.c t-import.c t-inp_str.c \
t-io_raw.c t-jac.c t-lcm.c t-lucnum_ui.c t-mul.c t-mul_i.c \
t-oddeven.c t-perfsqr.c t-popcount.c t-pow.c t-powm.c \
t-powm_ui.c t-pprime_p.c t-root.c t-scan.c t-set_d.c t-set_f.c \
t-set_si.c t-set_str.c t-sizeinbase.c t-sqrtrem.c t-tdiv.c \
t-tdiv_ui.c
t-oddeven.c t-perfpow.c t-perfsqr.c t-popcount.c t-pow.c \
t-powm.c t-powm_ui.c t-pprime_p.c t-root.c t-scan.c t-set_d.c \
t-set_f.c t-set_si.c t-set_str.c t-sizeinbase.c t-sqrtrem.c \
t-tdiv.c t-tdiv_ui.c
DIST_SOURCES = bit.c convert.c dive.c dive_ui.c io.c logic.c reuse.c \
t-addsub.c t-aorsmul.c t-bin.c t-cdiv_ui.c t-cmp.c t-cmp_d.c \
t-cmp_si.c t-cong.c t-cong_2exp.c t-div_2exp.c t-divis.c \
@ -393,10 +401,10 @@ DIST_SOURCES = bit.c convert.c dive.c dive_ui.c io.c logic.c reuse.c \
t-fib_ui.c t-fits.c t-gcd.c t-gcd_ui.c t-get_d.c \
t-get_d_2exp.c t-get_si.c t-hamdist.c t-import.c t-inp_str.c \
t-io_raw.c t-jac.c t-lcm.c t-lucnum_ui.c t-mul.c t-mul_i.c \
t-oddeven.c t-perfsqr.c t-popcount.c t-pow.c t-powm.c \
t-powm_ui.c t-pprime_p.c t-root.c t-scan.c t-set_d.c t-set_f.c \
t-set_si.c t-set_str.c t-sizeinbase.c t-sqrtrem.c t-tdiv.c \
t-tdiv_ui.c
t-oddeven.c t-perfpow.c t-perfsqr.c t-popcount.c t-pow.c \
t-powm.c t-powm_ui.c t-pprime_p.c t-root.c t-scan.c t-set_d.c \
t-set_f.c t-set_si.c t-set_str.c t-sizeinbase.c t-sqrtrem.c \
t-tdiv.c t-tdiv_ui.c
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -717,6 +725,9 @@ t-mul_i$(EXEEXT): $(t_mul_i_OBJECTS) $(t_mul_i_DEPENDENCIES)
t-oddeven$(EXEEXT): $(t_oddeven_OBJECTS) $(t_oddeven_DEPENDENCIES)
@rm -f t-oddeven$(EXEEXT)
$(LINK) $(t_oddeven_LDFLAGS) $(t_oddeven_OBJECTS) $(t_oddeven_LDADD) $(LIBS)
t-perfpow$(EXEEXT): $(t_perfpow_OBJECTS) $(t_perfpow_DEPENDENCIES)
@rm -f t-perfpow$(EXEEXT)
$(LINK) $(t_perfpow_LDFLAGS) $(t_perfpow_OBJECTS) $(t_perfpow_LDADD) $(LIBS)
t-perfsqr$(EXEEXT): $(t_perfsqr_OBJECTS) $(t_perfsqr_DEPENDENCIES)
@rm -f t-perfsqr$(EXEEXT)
$(LINK) $(t_perfsqr_LDFLAGS) $(t_perfsqr_OBJECTS) $(t_perfsqr_LDADD) $(LIBS)
@ -865,6 +876,8 @@ t-mul_i_.c: t-mul_i.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/t-mul_i.c; then echo $(srcdir)/t-mul_i.c; else echo t-mul_i.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
t-oddeven_.c: t-oddeven.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/t-oddeven.c; then echo $(srcdir)/t-oddeven.c; else echo t-oddeven.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
t-perfpow_.c: t-perfpow.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/t-perfpow.c; then echo $(srcdir)/t-perfpow.c; else echo t-perfpow.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
t-perfsqr_.c: t-perfsqr.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/t-perfsqr.c; then echo $(srcdir)/t-perfsqr.c; else echo t-perfsqr.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
t-popcount_.c: t-popcount.c $(ANSI2KNR)
@ -916,15 +929,16 @@ t-hamdist_.lo t-import_.$(OBJEXT) t-import_.lo t-inp_str_.$(OBJEXT) \
t-inp_str_.lo t-io_raw_.$(OBJEXT) t-io_raw_.lo t-jac_.$(OBJEXT) \
t-jac_.lo t-lcm_.$(OBJEXT) t-lcm_.lo t-lucnum_ui_.$(OBJEXT) \
t-lucnum_ui_.lo t-mul_.$(OBJEXT) t-mul_.lo t-mul_i_.$(OBJEXT) \
t-mul_i_.lo t-oddeven_.$(OBJEXT) t-oddeven_.lo t-perfsqr_.$(OBJEXT) \
t-perfsqr_.lo t-popcount_.$(OBJEXT) t-popcount_.lo t-pow_.$(OBJEXT) \
t-pow_.lo t-powm_.$(OBJEXT) t-powm_.lo t-powm_ui_.$(OBJEXT) \
t-powm_ui_.lo t-pprime_p_.$(OBJEXT) t-pprime_p_.lo t-root_.$(OBJEXT) \
t-root_.lo t-scan_.$(OBJEXT) t-scan_.lo t-set_d_.$(OBJEXT) t-set_d_.lo \
t-set_f_.$(OBJEXT) t-set_f_.lo t-set_si_.$(OBJEXT) t-set_si_.lo \
t-set_str_.$(OBJEXT) t-set_str_.lo t-sizeinbase_.$(OBJEXT) \
t-sizeinbase_.lo t-sqrtrem_.$(OBJEXT) t-sqrtrem_.lo t-tdiv_.$(OBJEXT) \
t-tdiv_.lo t-tdiv_ui_.$(OBJEXT) t-tdiv_ui_.lo : $(ANSI2KNR)
t-mul_i_.lo t-oddeven_.$(OBJEXT) t-oddeven_.lo t-perfpow_.$(OBJEXT) \
t-perfpow_.lo t-perfsqr_.$(OBJEXT) t-perfsqr_.lo t-popcount_.$(OBJEXT) \
t-popcount_.lo t-pow_.$(OBJEXT) t-pow_.lo t-powm_.$(OBJEXT) t-powm_.lo \
t-powm_ui_.$(OBJEXT) t-powm_ui_.lo t-pprime_p_.$(OBJEXT) \
t-pprime_p_.lo t-root_.$(OBJEXT) t-root_.lo t-scan_.$(OBJEXT) \
t-scan_.lo t-set_d_.$(OBJEXT) t-set_d_.lo t-set_f_.$(OBJEXT) \
t-set_f_.lo t-set_si_.$(OBJEXT) t-set_si_.lo t-set_str_.$(OBJEXT) \
t-set_str_.lo t-sizeinbase_.$(OBJEXT) t-sizeinbase_.lo \
t-sqrtrem_.$(OBJEXT) t-sqrtrem_.lo t-tdiv_.$(OBJEXT) t-tdiv_.lo \
t-tdiv_ui_.$(OBJEXT) t-tdiv_ui_.lo : $(ANSI2KNR)
mostlyclean-libtool:
-rm -f *.lo

134
tests/mpz/t-perfpow.c Normal file
View File

@ -0,0 +1,134 @@
/* Exercise mpz_perfect_power_p
Copyright 2008 Jason Moxham
This file is part of the MPIR Library.
The MPIR Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.
The MPIR Library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the MPIR Library; see the file COPYING.LIB. If not, write
to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include "gmp.h"
#include "gmp-impl.h"
#include "tests.h"
int
perfpow_ref (mpz_t x)
{
mpz_t y, q, r;
unsigned long i;
int ret = 0;
if (mpz_cmp_ui (x, 0) == 0 || mpz_cmp_ui (x, 1) == 0
|| mpz_cmp_si (x, -1) == 0)
return 1;
mpz_init_set (y, x);
mpz_init (q);
mpz_init (r);
mpz_abs (y, y);
for (i = 2;; i++)
{
mpz_root (q, y, i);
mpz_pow_ui (r, q, i);
if (mpz_cmp (r, y) == 0 && (i % 2 == 1 || SIZ (x) > 0))
{
ret = 1;
break;
}
if (mpz_cmp_ui (q, 1) <= 0)
break;
}
mpz_clear (y);
mpz_clear (q);
mpz_clear (r);
return ret;
}
int
main (void)
{
int i, r1, r2, j, a, b, c, d;
mpz_t x, m;
tests_start ();
mpz_init (x);
mpz_init (m);
/* check small values */
for (i = -10000; i < 10000; i++)
{
mpz_set_si (x, i);
r1 = mpz_perfect_power_p (x);
r2 = perfpow_ref (x);
if (r1 != r2)
{
printf ("mpz_perfect_power_p wrong on %d got %d want %d\n", i, r1,
r2);
abort ();
}
}
/* check (-1)^i.2^a.3^b.5^c.x^d where x is big */
/* 1.0.0.0.5 picked up one error
1.10.6.0.0 picked up another error
want a good selection of powers to try all possibilitys
*/
for (i = 1; i <= 2; i++)
{
for (d = 0; d < 10; d++)
{
for (a = 0; a < 11; a++)
{
for (b = 0; b < 11; b++)
{
for (c = 0; c < 11; c++)
{
mpz_set_ui (x, 1);
mpz_set_si (m, -1);
for (j = 0; j < i; j++)
mpz_mul (x, x, m);
mpz_set_ui (m, 2);
for (j = 0; j < a; j++)
mpz_mul (x, x, m);
mpz_set_ui (m, 3);
for (j = 0; j < b; j++)
mpz_mul (x, x, m);
mpz_set_ui (m, 5);
for (j = 0; j < c; j++)
mpz_mul (x, x, m);
mpz_set_ui (m, 117039007);
for (j = 0; j < d; j++)
mpz_mul (x, x, m);
r1 = mpz_perfect_power_p (x);
r2 = perfpow_ref (x);
if (r1 != r2)
{
printf
("mpz_perfect_power_p wrong on %d.%d.%d.%d.%d got %d want %d\n",
i, a, b, c, d, r1, r2);
abort ();
}
}
}
}
}
}
mpz_clear (x);
mpz_clear (m);
tests_end ();
exit (0);
}