Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
## Process this file with automake to generate Makefile.in
# Copyright 1996, 1997, 1999-2003, 2009, 2012 Free Software Foundation, Inc.
#
# This file is part of the GNU MP Library test suite.
#
# The GNU MP Library test suite is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of the License,
# or (at your option) any later version.
#
# The GNU MP Library test suite 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 General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/.
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tests
AM_LDFLAGS = -no-install
LDADD = $(top_builddir)/tests/libtests.la $(top_builddir)/libgmp.la
check_PROGRAMS = reuse t-addsub t-cmp t-mul t-mul_i t-tdiv t-tdiv_ui t-fdiv \
t-fdiv_ui t-cdiv_ui t-gcd t-gcd_ui t-lcm t-invert dive dive_ui t-sqrtrem \
convert io t-inp_str logic t-bit t-powm t-powm_ui t-pow t-div_2exp \
t-root t-perfsqr t-perfpow t-jac t-bin t-get_d t-get_d_2exp t-get_si \
t-set_d t-set_si t-lucm \
t-fac_ui t-mfac_uiui t-primorial_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-nextprime t-remove t-limbs
TESTS = $(check_PROGRAMS)
# Temporary files used by the tests. Removed automatically if the tests
# pass, but ensure they're cleaned if they fail.
#
CLEANFILES = *.tmp
$(top_builddir)/tests/libtests.la:
cd $(top_builddir)/tests; $(MAKE) $(AM_MAKEFLAGS) libtests.la

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,186 @@
/* Test conversion using mpz_get_str and mpz_set_str.
Copyright 1993, 1994, 1996, 1999-2002, 2006, 2007, 2020 Free Software
Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for strlen */
#include <ctype.h> /* for tolower */
#include "gmp-impl.h"
#include "tests.h"
void debug_mp (mpz_t, int);
static int str_casecmp (const char *, const char *);
void
string_urandomb (char *bp, size_t len, int base, gmp_randstate_ptr rands)
{
mpz_t bs;
unsigned long bsi;
int d, l;
const char *collseq = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
mpz_init (bs);
mpz_urandomb (bs, rands, 32);
bsi = mpz_get_ui (bs);
d = bsi % base;
while (len != 0)
{
l = (bsi >> 16) % 20;
l = MIN (l, len);
memset (bp, collseq[d], l);
len -= l;
bp += l;
mpz_urandomb (bs, rands, 32);
bsi = mpz_get_ui (bs);
d = bsi & 0xfff;
if (d >= base)
d = 0;
}
bp[0] = '\0';
mpz_clear (bs);
}
int
main (int argc, char **argv)
{
mpz_t op1, op2;
mp_size_t size;
int i;
int reps = 2000;
char *str, *buf, *bp;
int base;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
size_t len;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mpz_init (bs);
mpz_init (op1);
mpz_init (op2);
for (i = 0; i < reps; i++)
{
/* 1. Generate random mpz_t and convert to a string and back to mpz_t
again. */
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 17 + 2; /* 2..18 */
mpz_urandomb (bs, rands, size_range); /* 3..262144 bits */
size = mpz_get_ui (bs);
mpz_rrandomb (op1, rands, size);
mpz_urandomb (bs, rands, 1);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (op1, op1);
mpz_urandomb (bs, rands, 32);
bsi = mpz_get_ui (bs);
base = bsi % 62 + 1;
if (base == 1)
base = 0;
str = mpz_get_str ((char *) 0, base, op1);
mpz_set_str_or_abort (op2, str, base);
if (mpz_cmp (op1, op2))
{
fprintf (stderr, "ERROR, op1 and op2 different in test %d\n", i);
fprintf (stderr, "str = %s\n", str);
fprintf (stderr, "base = %d\n", base);
fprintf (stderr, "op1 = "); debug_mp (op1, -16);
fprintf (stderr, "op2 = "); debug_mp (op2, -16);
abort ();
}
(*__gmp_free_func) (str, strlen (str) + 1);
/* 2. Generate random string and convert to mpz_t and back to a string
again. */
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 16 + 1; /* 1..16 */
mpz_urandomb (bs, rands, size_range); /* 1..65536 digits */
len = mpz_get_ui (bs) + 1;
buf = (char *) (*__gmp_allocate_func) (len + 1);
if (base == 0)
base = 10;
string_urandomb (buf, len, base, rands);
mpz_set_str_or_abort (op1, buf, base);
str = mpz_get_str ((char *) 0, base, op1);
/* Skip over leading zeros, but don't leave the string at zero length. */
for (bp = buf; bp[0] == '0' && bp[1] != '\0'; bp++)
;
if (str_casecmp (str, bp) != 0)
{
fprintf (stderr, "ERROR, str and buf different in test %d\n", i);
fprintf (stderr, "str = %s\n", str);
fprintf (stderr, "buf = %s\n", buf);
fprintf (stderr, "base = %d\n", base);
fprintf (stderr, "op1 = "); debug_mp (op1, -16);
abort ();
}
(*__gmp_free_func) (buf, len + 1);
(*__gmp_free_func) (str, strlen (str) + 1);
}
mpz_clear (bs);
mpz_clear (op1);
mpz_clear (op2);
tests_end ();
exit (0);
}
/* This is similar to POSIX strcasecmp except that we don't do the comparison
with unsigned char. We avoid strcasecmp for C standard conformance. */
static int
str_casecmp (const char *s1, const char *s2)
{
size_t i;
for (i = 0;; i++)
{
int c1 = s1[i];
int c2 = s2[i];
if (c1 == 0 || tolower (c1) != tolower (c2))
return c1 - c2;
}
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,100 @@
/* Test mpz_mul, mpz_divexact.
Copyright 1996, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
int
main (int argc, char **argv)
{
mpz_t op1, op2;
mpz_t prod, quot;
mp_size_t size;
int i;
int reps = 5000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mp_trace_base = -16;
mpz_init (bs);
mpz_init (op1);
mpz_init (op2);
mpz_init (prod);
mpz_init (quot);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 17 + 2; /* 0..2047 bit operands */
mpz_urandomb (bs, rands, size_range);
size = mpz_get_ui (bs);
mpz_rrandomb (op1, rands, size);
do
{
mpz_urandomb (bs, rands, size_range);
size = mpz_get_ui (bs);
mpz_rrandomb (op2, rands, size);
}
while (mpz_sgn (op2) == 0);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (op1, op1);
if ((bsi & 2) != 0)
mpz_neg (op2, op2);
mpz_mul (prod, op1, op2);
mpz_divexact (quot, prod, op2);
MPZ_CHECK_FORMAT (quot);
if (mpz_cmp (quot, op1) != 0)
{
printf ("Wrong results:\n");
mpz_trace (" got ", quot);
mpz_trace (" want ", op1);
mpz_trace (" dividend", prod);
mpz_trace (" divisor ", op2);
abort ();
}
}
mpz_clear (bs);
mpz_clear (op1);
mpz_clear (op2);
mpz_clear (prod);
mpz_clear (quot);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,86 @@
/* Test mpz_divexact_ui.
Copyright 1996, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_random (int argc, char *argv[])
{
gmp_randstate_ptr rands = RANDS;
int reps = 500000;
mpz_t a, q, got;
int i, qneg;
unsigned long d;
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (a);
mpz_init (q);
mpz_init (got);
for (i = 0; i < reps; i++)
{
do
d = (unsigned long) urandom();
while (d == 0);
mpz_erandomb (q, rands, 512);
mpz_mul_ui (a, q, d);
for (qneg = 0; qneg <= 1; qneg++)
{
mpz_divexact_ui (got, a, d);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, q) != 0)
{
printf ("mpz_divexact_ui wrong\n");
mpz_trace (" a", a);
printf (" d=%lu\n", d);
mpz_trace (" q", q);
mpz_trace (" got", got);
abort ();
}
mpz_neg (q, q);
mpz_neg (a, a);
}
}
mpz_clear (a);
mpz_clear (q);
mpz_clear (got);
}
int
main (int argc, char **argv)
{
tests_start ();
check_random (argc, argv);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,151 @@
/* Test conversion and I/O using mpz_out_str and mpz_inp_str.
Copyright 1993, 1994, 1996, 2000, 2001, 2012, 2020 Free Software
Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#if HAVE_UNISTD_H
#include <unistd.h> /* for unlink */
#endif
#include "gmp-impl.h"
#include "tests.h"
#define FILENAME "io.tmp"
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stdout, base, x); fputc ('\n', stdout);
}
int
main (int argc, char **argv)
{
mpz_t op1, op2;
mp_size_t size;
int i;
int reps = 10000;
FILE *fp;
int base, base_out;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
size_t nread;
tests_start ();
rands = RANDS;
mpz_init (bs);
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (op1);
mpz_init (op2);
fp = fopen (FILENAME, "w+");
if (mpz_out_str (fp, 63, op1) != 0)
{
printf ("mpz_out_str did not return 0 (error) with base > 62\n");
abort ();
}
if (mpz_out_str (fp, -37, op1) != 0)
{
printf ("mpz_out_str did not return 0 (error) with base < -37\n");
abort ();
}
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 10 + 2;
mpz_urandomb (bs, rands, size_range);
size = mpz_get_ui (bs);
mpz_rrandomb (op1, rands, size);
mpz_urandomb (bs, rands, 1);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (op1, op1);
mpz_urandomb (bs, rands, 16);
bsi = mpz_get_ui (bs);
base = bsi % 62 + 1;
if (base == 1)
base = 0;
if (i % 2 == 0 && base <= 36)
base_out = -base;
else
base_out = base;
rewind (fp);
if (mpz_out_str (fp, base_out, op1) == 0
|| putc (' ', fp) == EOF
|| fflush (fp) != 0)
{
printf ("mpz_out_str write error\n");
abort ();
}
rewind (fp);
nread = mpz_inp_str (op2, fp, base);
if (nread == 0)
{
if (ferror (fp))
printf ("mpz_inp_str stream read error\n");
else
printf ("mpz_inp_str data conversion error\n");
abort ();
}
if (nread != ftell(fp))
{
printf ("mpz_inp_str nread doesn't match ftell\n");
printf (" nread %lu\n", (unsigned long) nread);
printf (" ftell %ld\n", ftell(fp));
abort ();
}
if (mpz_cmp (op1, op2))
{
printf ("ERROR\n");
printf ("op1 = "); debug_mp (op1, -16);
printf ("op2 = "); debug_mp (op2, -16);
printf ("base = %d\n", base);
abort ();
}
}
fclose (fp);
unlink (FILENAME);
mpz_clear (bs);
mpz_clear (op1);
mpz_clear (op2);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,194 @@
/* Test mpz_com, mpz_and, mpz_ior, and mpz_xor.
Copyright 1993, 1994, 1996, 1997, 2001, 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void dump_abort (void);
void debug_mp (mpz_t, int);
int
main (int argc, char **argv)
{
mpz_t x, y, r1, r2;
mpz_t t1, t2, t3;
mp_size_t xsize, ysize;
int i;
int reps = 100000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
rands = RANDS;
mpz_init (bs);
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (x);
mpz_init (y);
mpz_init (r1);
mpz_init (r2);
mpz_init (t1);
mpz_init (t2);
mpz_init (t3);
mpz_set_si (x, -1);
mpz_set_ui (y, 0);
for (i = 0; i < 300; i++)
{
mpz_mul_2exp (x, x, 1);
mpz_and (r1, x, x);
MPZ_CHECK_FORMAT (r1);
if (mpz_cmp (r1, x) != 0)
dump_abort ();
mpz_ior (r2, x, x);
MPZ_CHECK_FORMAT (r2);
if (mpz_cmp (r2, x) != 0)
dump_abort ();
mpz_xor (t1, x, x);
MPZ_CHECK_FORMAT (t1);
if (mpz_cmp_si (t1, 0) != 0)
dump_abort ();
mpz_ior (t1, x, y);
MPZ_CHECK_FORMAT (t1);
if (mpz_cmp (t1, x) != 0)
dump_abort ();
mpz_xor (t2, x, y);
MPZ_CHECK_FORMAT (t2);
if (mpz_cmp (t2, x) != 0)
dump_abort ();
mpz_com (t2, x);
MPZ_CHECK_FORMAT (t2);
mpz_xor (t3, t2, x);
MPZ_CHECK_FORMAT (t3);
if (mpz_cmp_si (t3, -1) != 0)
dump_abort ();
}
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 8 + 2;
mpz_urandomb (bs, rands, size_range);
xsize = mpz_get_ui (bs);
mpz_rrandomb (x, rands, xsize);
mpz_urandomb (bs, rands, 1);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (x, x);
mpz_urandomb (bs, rands, size_range);
ysize = mpz_get_ui (bs);
mpz_rrandomb (y, rands, ysize);
mpz_urandomb (bs, rands, 1);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (y, y);
mpz_com (r1, x);
MPZ_CHECK_FORMAT (r1);
mpz_com (r1, r1);
MPZ_CHECK_FORMAT (r1);
if (mpz_cmp (r1, x) != 0)
dump_abort ();
mpz_com (r1, y);
MPZ_CHECK_FORMAT (r1);
mpz_com (r2, r1);
MPZ_CHECK_FORMAT (r2);
if (mpz_cmp (r2, y) != 0)
dump_abort ();
mpz_com (t1, x);
MPZ_CHECK_FORMAT (t1);
mpz_com (t2, y);
MPZ_CHECK_FORMAT (t2);
mpz_and (t3, t1, t2);
MPZ_CHECK_FORMAT (t3);
mpz_com (r1, t3);
MPZ_CHECK_FORMAT (r1);
mpz_ior (r2, x, y);
MPZ_CHECK_FORMAT (r2);
if (mpz_cmp (r1, r2) != 0)
dump_abort ();
mpz_com (t1, x);
MPZ_CHECK_FORMAT (t1);
mpz_com (t2, y);
MPZ_CHECK_FORMAT (t2);
mpz_ior (t3, t1, t2);
MPZ_CHECK_FORMAT (t3);
mpz_com (r1, t3);
MPZ_CHECK_FORMAT (r1);
mpz_and (r2, x, y);
MPZ_CHECK_FORMAT (r2);
if (mpz_cmp (r1, r2) != 0)
dump_abort ();
mpz_ior (t1, x, y);
MPZ_CHECK_FORMAT (t1);
mpz_and (t2, x, y);
MPZ_CHECK_FORMAT (t2);
mpz_com (t3, t2);
MPZ_CHECK_FORMAT (t3);
mpz_and (r1, t1, t3);
MPZ_CHECK_FORMAT (r1);
mpz_xor (r2, x, y);
MPZ_CHECK_FORMAT (r2);
if (mpz_cmp (r1, r2) != 0)
dump_abort ();
}
mpz_clear (bs);
mpz_clear (x);
mpz_clear (y);
mpz_clear (r1);
mpz_clear (r2);
mpz_clear (t1);
mpz_clear (t2);
mpz_clear (t3);
tests_end ();
exit (0);
}
void
dump_abort ()
{
abort();
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,786 @@
/* Test that routines allow reusing a source variable as destination.
Test all relevant functions except:
mpz_bin_ui
mpz_nextprime
mpz_mul_si
mpz_addmul_ui (should this really allow a+=a*c?)
Copyright 1996, 1999-2002, 2009, 2012, 2013, 2016, 2020 Free Software
Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "gmp-impl.h"
#include "tests.h"
#if __GMP_LIBGMP_DLL
/* FIXME: When linking to a DLL libgmp, mpz_add etc can't be used as
initializers for global variables because they're effectively global
variables (function pointers) themselves. Perhaps calling a test
function successively with mpz_add etc would be better. */
int
main (void)
{
printf ("Test suppressed for windows DLL\n");
exit (0);
}
#else /* ! DLL_EXPORT */
void dump (const char *, mpz_t, mpz_t, mpz_t);
typedef void (*dss_func) (mpz_ptr, mpz_srcptr, mpz_srcptr);
typedef void (*dsi_func) (mpz_ptr, mpz_srcptr, unsigned long int);
typedef unsigned long int (*dsi_div_func) (mpz_ptr, mpz_srcptr, unsigned long int);
typedef unsigned long int (*ddsi_div_func) (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int);
typedef void (*ddss_div_func) (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr);
typedef void (*ds_func) (mpz_ptr, mpz_srcptr);
void
mpz_xinvert (mpz_ptr r, mpz_srcptr a, mpz_srcptr b)
{
int res;
res = mpz_invert (r, a, b);
if (res == 0)
mpz_set_ui (r, 0);
}
struct {
dss_func fptr;
const char *fname;
int isdivision;
int isslow;
} static dss[] =
{ { mpz_add, "mpz_add", 0, 0 },
{ mpz_sub, "mpz_sub", 0, 0 },
{ mpz_mul, "mpz_mul", 0, 0 },
{ mpz_cdiv_q, "mpz_cdiv_q", 1, 0 },
{ mpz_cdiv_r, "mpz_cdiv_r", 1, 0 },
{ mpz_fdiv_q, "mpz_fdiv_q", 1, 0 },
{ mpz_fdiv_r, "mpz_fdiv_r", 1, 0 },
{ mpz_tdiv_q, "mpz_tdiv_q", 1, 0 },
{ mpz_tdiv_r, "mpz_tdiv_r", 1, 0 },
{ mpz_mod, "mpz_mod", 1, 0 },
{ mpz_xinvert, "mpz_xinvert", 1, 1 },
{ mpz_gcd, "mpz_gcd", 0, 1 },
{ mpz_lcm, "mpz_lcm", 0, 1 },
{ mpz_and, "mpz_and", 0, 0 },
{ mpz_ior, "mpz_ior", 0, 0 },
{ mpz_xor, "mpz_xor", 0, 0 }
};
struct {
dsi_func fptr;
const char *fname;
int mod;
} static dsi[] =
{
/* Don't change order here without changing the code in main(). */
{ mpz_add_ui, "mpz_add_ui", 0 },
{ mpz_mul_ui, "mpz_mul_ui", 0 },
{ mpz_sub_ui, "mpz_sub_ui", 0 },
{ mpz_fdiv_q_2exp, "mpz_fdiv_q_2exp", 0x1000 },
{ mpz_fdiv_r_2exp, "mpz_fdiv_r_2exp", 0x1000 },
{ mpz_cdiv_q_2exp, "mpz_cdiv_q_2exp", 0x1000 },
{ mpz_cdiv_r_2exp, "mpz_cdiv_r_2exp", 0x1000 },
{ mpz_tdiv_q_2exp, "mpz_tdiv_q_2exp", 0x1000 },
{ mpz_tdiv_r_2exp, "mpz_tdiv_r_2exp", 0x1000 },
{ mpz_mul_2exp, "mpz_mul_2exp", 0x100 },
{ mpz_pow_ui, "mpz_pow_ui", 0x10 }
};
struct {
dsi_div_func fptr;
const char *fname;
} static dsi_div[] =
{
{ mpz_cdiv_q_ui, "mpz_cdiv_q_ui" },
{ mpz_cdiv_r_ui, "mpz_cdiv_r_ui" },
{ mpz_fdiv_q_ui, "mpz_fdiv_q_ui" },
{ mpz_fdiv_r_ui, "mpz_fdiv_r_ui" },
{ mpz_tdiv_q_ui, "mpz_tdiv_q_ui" },
{ mpz_tdiv_r_ui, "mpz_tdiv_r_ui" }
};
struct {
ddsi_div_func fptr;
const char *fname;
int isslow;
} static ddsi_div[] =
{
{ mpz_cdiv_qr_ui, "mpz_cdiv_qr_ui", 0 },
{ mpz_fdiv_qr_ui, "mpz_fdiv_qr_ui", 0 },
{ mpz_tdiv_qr_ui, "mpz_tdiv_qr_ui", 0 },
};
struct {
ddss_div_func fptr;
const char *fname;
int isslow;
} static ddss_div[] =
{
{ mpz_cdiv_qr, "mpz_cdiv_qr", 0 },
{ mpz_fdiv_qr, "mpz_fdiv_qr", 0 },
{ mpz_tdiv_qr, "mpz_tdiv_qr", 0 },
};
struct {
ds_func fptr;
const char *fname;
int nonneg;
} static ds[] =
{
{ mpz_abs, "mpz_abs", 0 },
{ mpz_com, "mpz_com", 0 },
{ mpz_neg, "mpz_neg", 0 },
{ mpz_sqrt, "mpz_sqrt", 1 },
};
#define FAIL(class,indx,op1,op2,op3) \
do { \
dump (class[indx].fname, op1, op2, op3); \
exit (1); \
} while (0)
#define FAIL2(fname,op1,op2,op3) \
do { \
dump (#fname, op1, op2, op3); \
exit (1); \
} while (0)
void
realloc_if_reducing (mpz_ptr r)
{
if (ABSIZ(r) < ALLOC(r))
_mpz_realloc (r, ABSIZ(r));
}
#define INVOKE_RRS(desc,r1,r2,i1) \
do { \
if (pass & 1) realloc_if_reducing (r1); \
if (pass & 2) realloc_if_reducing (r2); \
(desc).fptr (r1, r2, i1); \
} while (0)
#define INVOKE_RS(desc,r1,i1) \
do { \
if (pass & 1) realloc_if_reducing (r1); \
(desc).fptr (r1, i1); \
} while (0)
#define INVOKE_RRSS(desc,r1,r2,i1,i2) \
do { \
if (pass & 1) realloc_if_reducing (r1); \
if (pass & 2) realloc_if_reducing (r2); \
(desc).fptr (r1, r2, i1, i2); \
} while (0)
#define INVOKE_RSS(desc,r1,i1,i2) \
do { \
if (pass & 1) realloc_if_reducing (r1); \
(desc).fptr (r1, i1, i2); \
} while (0)
int
main (int argc, char **argv)
{
int i;
unsigned int pass, reps = 400;
mpz_t in1, in2, in3;
unsigned long int in2i;
mpz_t res1, res2, res3;
mpz_t ref1, ref2, ref3;
mpz_t t;
unsigned long int r1, r2;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mpz_init (bs);
mpz_init (in1);
mpz_init (in2);
mpz_init (in3);
mpz_init (ref1);
mpz_init (ref2);
mpz_init (ref3);
mpz_init (res1);
mpz_init (res2);
mpz_init (res3);
mpz_init (t);
mpz_set_ui (res1, 1); /* force allocation */
mpz_set_ui (res2, 1); /* force allocation */
mpz_set_ui (res3, 1); /* force allocation */
for (pass = 1; pass <= reps; pass++)
{
#ifndef VERBOSE
if (isatty (STDOUT_FILENO))
{
printf ("\r%d/%d passes", pass, reps);
fflush (stdout);
}
#endif
mpz_urandomb (bs, rands, 32);
/* Make size_range gradually bigger with each pass. */
size_range = mpz_get_ui (bs) % (pass * 15 / reps + 1) + 8;
#define MAKE_RANDOM_OP(in, size_range, s) \
do { \
mpz_urandomb (bs, rands, size_range); \
if (((pass >> s) & 3) == 3) /* conditional exponential dist */ \
mpz_urandomb (bs, rands, mpz_get_ui (bs) % (size_range - 7) + 7); \
mpz_rrandomb (in, rands, mpz_get_ui (bs)); \
} while (0)
MAKE_RANDOM_OP (in1, size_range, 0);
MAKE_RANDOM_OP (in2, size_range, 2);
MAKE_RANDOM_OP (in3, size_range, 4);
#undef MAKE_RANDOM_OP
#ifdef VERBOSE
printf("%9d%9d%8d\n",
mpz_sizeinbase(in1,2),
mpz_sizeinbase(in2,2),
mpz_sizeinbase(in3,2));
#endif
mpz_urandomb (bs, rands, 3);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (in1, in1);
if ((bsi & 2) != 0)
mpz_neg (in2, in2);
if ((bsi & 4) != 0)
mpz_neg (in3, in3);
for (i = 0; i < numberof (dss); i++)
{
if (dss[i].isdivision && mpz_sgn (in2) == 0)
continue;
if (dss[i].isslow && size_range > 19)
continue;
(dss[i].fptr) (ref1, in1, in2);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
INVOKE_RSS (dss[i], res1, res1, in2);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL (dss, i, in1, in2, NULL);
mpz_set (res1, in2);
INVOKE_RSS (dss[i], res1, in1, res1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL (dss, i, in1, in2, NULL);
}
for (i = 0; i < numberof (ddss_div); i++)
{
if (mpz_sgn (in2) == 0)
continue;
(ddss_div[i].fptr) (ref1, ref2, in1, in2);
MPZ_CHECK_FORMAT (ref1);
MPZ_CHECK_FORMAT (ref2);
mpz_set (res1, in1);
mpz_clobber (res2);
INVOKE_RRSS (ddss_div[i], res1, res2, res1, in2);
MPZ_CHECK_FORMAT (res1);
MPZ_CHECK_FORMAT (res2);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
FAIL (ddss_div, i, in1, in2, NULL);
mpz_clobber (res1);
mpz_set (res2, in1);
INVOKE_RRSS (ddss_div[i], res1, res2, res2, in2);
MPZ_CHECK_FORMAT (res1);
MPZ_CHECK_FORMAT (res2);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
FAIL (ddss_div, i, in1, in2, NULL);
mpz_set (res1, in2);
mpz_clobber (res2);
INVOKE_RRSS (ddss_div[i], res1, res2, in1, res1);
MPZ_CHECK_FORMAT (res1);
MPZ_CHECK_FORMAT (res2);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
FAIL (ddss_div, i, in1, in2, NULL);
mpz_clobber (res1);
mpz_set (res2, in2);
INVOKE_RRSS (ddss_div[i], res1, res2, in1, res2);
MPZ_CHECK_FORMAT (res1);
MPZ_CHECK_FORMAT (res2);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
FAIL (ddss_div, i, in1, in2, NULL);
}
for (i = 0; i < numberof (ds); i++)
{
if (ds[i].nonneg && mpz_sgn (in1) < 0)
continue;
(ds[i].fptr) (ref1, in1);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
INVOKE_RS (ds[i], res1, res1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL (ds, i, in1, in2, NULL);
}
in2i = mpz_get_ui (in2);
for (i = 0; i < numberof (dsi); i++)
{
if (dsi[i].mod != 0)
in2i = mpz_get_ui (in2) % dsi[i].mod;
(dsi[i].fptr) (ref1, in1, in2i);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
INVOKE_RRS (dsi[i], res1, res1, in2i);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL (dsi, i, in1, in2, NULL);
}
if (in2i != 0) /* Don't divide by 0. */
{
for (i = 0; i < numberof (dsi_div); i++)
{
r1 = (dsi_div[i].fptr) (ref1, in1, in2i);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
r2 = (dsi_div[i].fptr) (res1, res1, in2i);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0 || r1 != r2)
FAIL (dsi_div, i, in1, in2, NULL);
}
for (i = 0; i < numberof (ddsi_div); i++)
{
r1 = (ddsi_div[i].fptr) (ref1, ref2, in1, in2i);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
mpz_clobber (res2);
r2 = (ddsi_div[i].fptr) (res1, res2, res1, in2i);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
FAIL (ddsi_div, i, in1, in2, NULL);
mpz_clobber (res1);
mpz_set (res2, in1);
(ddsi_div[i].fptr) (res1, res2, res2, in2i);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
FAIL (ddsi_div, i, in1, in2, NULL);
}
}
if (mpz_sgn (in1) >= 0)
{
mpz_sqrtrem (ref1, ref2, in1);
MPZ_CHECK_FORMAT (ref1);
MPZ_CHECK_FORMAT (ref2);
mpz_set (res1, in1);
mpz_sqrtrem (res1, res2, res1);
MPZ_CHECK_FORMAT (res1);
MPZ_CHECK_FORMAT (res2);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
mpz_set (res2, in1);
mpz_sqrtrem (res1, res2, res2);
MPZ_CHECK_FORMAT (res1);
MPZ_CHECK_FORMAT (res2);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
mpz_set (res1, in1);
mpz_sqrtrem (res1, res1, res1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref2, res1) != 0)
FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
}
if (mpz_sgn (in1) >= 0)
{
mpz_root (ref1, in1, in2i % 0x100 + 1);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
mpz_root (res1, res1, in2i % 0x100 + 1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_root, in1, in2, NULL);
}
if (mpz_sgn (in1) >= 0)
{
mpz_rootrem (ref1, ref2, in1, in2i % 0x100 + 1);
MPZ_CHECK_FORMAT (ref1);
MPZ_CHECK_FORMAT (ref2);
mpz_set (res1, in1);
mpz_rootrem (res1, res2, res1, in2i % 0x100 + 1);
MPZ_CHECK_FORMAT (res1);
MPZ_CHECK_FORMAT (res2);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
FAIL2 (mpz_rootrem, in1, in2, NULL);
mpz_set (res2, in1);
mpz_rootrem (res1, res2, res2, in2i % 0x100 + 1);
MPZ_CHECK_FORMAT (res1);
MPZ_CHECK_FORMAT (res2);
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
FAIL2 (mpz_rootrem, in1, in2, NULL);
}
if (size_range < 18) /* run fewer tests since gcdext is slow */
{
mpz_gcdext (ref1, ref2, ref3, in1, in2);
MPZ_CHECK_FORMAT (ref1);
MPZ_CHECK_FORMAT (ref2);
MPZ_CHECK_FORMAT (ref3);
#define GCDEXT_CHECK3(i1, i2) do { \
mpz_gcdext (res1, res2, res3, i1, i2); \
MPZ_CHECK_FORMAT (res1); \
MPZ_CHECK_FORMAT (res2); \
MPZ_CHECK_FORMAT (res3); \
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 \
|| mpz_cmp (ref3, res3) != 0) \
FAIL2 (mpz_gcdext, i1, i2, NULL); \
} while (0)
#define GCDEXT_CHECK2(i1, i2) do { \
mpz_gcdext (res1, res2, NULL, i1, i2); \
MPZ_CHECK_FORMAT (res1); \
MPZ_CHECK_FORMAT (res2); \
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) \
FAIL2 (mpz_gcdext, i1, i2, NULL); \
} while (0)
mpz_set (res1, in1);
mpz_clobber (res2);
mpz_clobber (res3);
GCDEXT_CHECK3 (res1, in2);
mpz_clobber (res1);
mpz_set (res2, in1);
mpz_clobber (res3);
GCDEXT_CHECK3 (res2, in2);
mpz_clobber (res1);
mpz_clobber (res2);
mpz_set (res3, in1);
GCDEXT_CHECK3 (res3, in2);
mpz_set (res1, in2);
mpz_clobber (res2);
mpz_clobber (res3);
GCDEXT_CHECK3 (in1, res1);
mpz_clobber (res1);
mpz_set (res2, in2);
mpz_clobber (res3);
GCDEXT_CHECK3 (in1, res2);
mpz_clobber (res1);
mpz_clobber (res2);
mpz_set (res3, in2);
GCDEXT_CHECK3 (in1, res3);
mpz_set (res1, in1);
mpz_set (res2, in2);
mpz_clobber (res3);
GCDEXT_CHECK3 (res1, res2);
mpz_set (res1, in1);
mpz_clobber (res2);
mpz_set (res3, in2);
GCDEXT_CHECK3 (res1, res3);
mpz_clobber (res1);
mpz_set (res2, in1);
mpz_set (res3, in2);
GCDEXT_CHECK3 (res2, res3);
mpz_set (res1, in2);
mpz_set (res2, in1);
mpz_clobber (res3);
GCDEXT_CHECK3 (res2, res1);
mpz_set (res1, in2);
mpz_clobber (res2);
mpz_set (res3, in1);
GCDEXT_CHECK3 (res3, res1);
mpz_clobber (res1);
mpz_set (res2, in2);
mpz_set (res3, in1);
GCDEXT_CHECK3(res3, res2);
mpz_set (res1, in1);
mpz_clobber (res2);
GCDEXT_CHECK2 (res1, in2);
mpz_clobber (res1);
mpz_set (res2, in1);
GCDEXT_CHECK2 (res2, in2);
mpz_set (res1, in2);
mpz_clobber (res2);
GCDEXT_CHECK2 (in1, res1);
mpz_clobber (res1);
mpz_set (res2, in2);
GCDEXT_CHECK2 (in1, res2);
#undef GCDEXT_CHECK
/* Identical inputs, gcd(in1, in1). Then the result should be
gcd = abs(in1), s = 0, t = sgn(in1). */
mpz_abs (ref1, in1);
mpz_set_ui (ref2, 0);
mpz_set_si (ref3, mpz_sgn (in1));
#define GCDEXT_CHECK_SAME3(in) do { \
mpz_gcdext (res1, res2, res3, in, in); \
MPZ_CHECK_FORMAT (res1); \
MPZ_CHECK_FORMAT (res2); \
MPZ_CHECK_FORMAT (res3); \
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 \
|| mpz_cmp (ref3, res3) != 0) \
FAIL2 (mpz_gcdext, in, in, NULL); \
} while (0)
#define GCDEXT_CHECK_SAME2(in) do { \
mpz_gcdext (res1, res2, NULL, in, in); \
MPZ_CHECK_FORMAT (res1); \
MPZ_CHECK_FORMAT (res2); \
if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) \
FAIL2 (mpz_gcdext, in, in, NULL); \
} while (0)
mpz_set (res1, in1);
mpz_clobber (res2);
mpz_clobber (res3);
GCDEXT_CHECK_SAME3 (res1);
mpz_clobber (res1);
mpz_set (res2, in1);
mpz_clobber (res3);
GCDEXT_CHECK_SAME3 (res2);
mpz_clobber (res1);
mpz_clobber (res2);
mpz_set (res3, in1);
GCDEXT_CHECK_SAME3 (res3);
mpz_set (res1, in1);
mpz_clobber (res2);
mpz_clobber (res3);
GCDEXT_CHECK_SAME2 (res1);
mpz_clobber (res1);
mpz_set (res2, in1);
mpz_clobber (res3);
GCDEXT_CHECK_SAME2 (res2);
#undef GCDEXT_CHECK_SAME
}
/* Don't run mpz_powm for huge exponents or when undefined. */
if (size_range < 17 && mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0
&& (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3)))
{
mpz_powm (ref1, in1, in2, in3);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
mpz_powm (res1, res1, in2, in3);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_powm, in1, in2, in3);
mpz_set (res1, in2);
mpz_powm (res1, in1, res1, in3);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_powm, in1, in2, in3);
mpz_set (res1, in3);
mpz_powm (res1, in1, in2, res1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_powm, in1, in2, in3);
}
/* Don't run mpz_powm_ui when undefined. */
if (size_range < 17 && mpz_sgn (in3) != 0)
{
mpz_powm_ui (ref1, in1, in2i, in3);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
mpz_powm_ui (res1, res1, in2i, in3);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_powm_ui, in1, in2, in3);
mpz_set (res1, in3);
mpz_powm_ui (res1, in1, in2i, res1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_powm_ui, in1, in2, in3);
}
{
r1 = mpz_gcd_ui (ref1, in1, in2i);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
r2 = mpz_gcd_ui (res1, res1, in2i);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_gcd_ui, in1, in2, NULL);
}
if (mpz_sgn (in2) != 0)
{
/* Test mpz_remove */
mp_bitcnt_t refretval, retval;
refretval = mpz_remove (ref1, in1, in2);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, in1);
retval = mpz_remove (res1, res1, in2);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0 || refretval != retval)
FAIL2 (mpz_remove, in1, in2, NULL);
mpz_set (res1, in2);
retval = mpz_remove (res1, in1, res1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0 || refretval != retval)
FAIL2 (mpz_remove, in1, in2, NULL);
}
if (mpz_sgn (in2) != 0)
{
/* Test mpz_divexact */
mpz_mul (t, in1, in2);
mpz_divexact (ref1, t, in2);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, t);
mpz_divexact (res1, res1, in2);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_divexact, t, in2, NULL);
mpz_set (res1, in2);
mpz_divexact (res1, t, res1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_divexact, t, in2, NULL);
}
if (mpz_sgn (in2) > 0)
{
/* Test mpz_divexact_gcd, same as mpz_divexact */
mpz_mul (t, in1, in2);
mpz_divexact_gcd (ref1, t, in2);
MPZ_CHECK_FORMAT (ref1);
mpz_set (res1, t);
mpz_divexact_gcd (res1, res1, in2);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_divexact_gcd, t, in2, NULL);
mpz_set (res1, in2);
mpz_divexact_gcd (res1, t, res1);
MPZ_CHECK_FORMAT (res1);
if (mpz_cmp (ref1, res1) != 0)
FAIL2 (mpz_divexact_gcd, t, in2, NULL);
}
}
if (isatty (STDOUT_FILENO))
printf ("\r%20s", "");
mpz_clear (bs);
mpz_clear (in1);
mpz_clear (in2);
mpz_clear (in3);
mpz_clear (ref1);
mpz_clear (ref2);
mpz_clear (ref3);
mpz_clear (res1);
mpz_clear (res2);
mpz_clear (res3);
mpz_clear (t);
if (isatty (STDOUT_FILENO))
printf ("\r");
tests_end ();
exit (0);
}
void
dump (const char *name, mpz_t in1, mpz_t in2, mpz_t in3)
{
printf ("failure in %s (", name);
mpz_out_str (stdout, -16, in1);
if (in2 != NULL)
{
printf (" ");
mpz_out_str (stdout, -16, in2);
}
if (in3 != NULL)
{
printf (" ");
mpz_out_str (stdout, -16, in3);
}
printf (")\n");
}
#endif /* ! DLL_EXPORT */

View File

@@ -0,0 +1,121 @@
/* Test mpz_add, mpz_sub, mpz_add_ui, mpz_sub_ui, and mpz_ui_sub.
Copyright 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "longlong.h"
#include "tests.h"
void debug_mp (mpz_t, int);
void dump_abort (int, const char *, mpz_t, mpz_t);
int
main (int argc, char **argv)
{
mpz_t op1, op2, r1, r2;
mp_size_t op1n, op2n;
unsigned long int op2long;
int i;
int reps = 100000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
rands = RANDS;
mpz_init (bs);
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (op1);
mpz_init (op2);
mpz_init (r1);
mpz_init (r2);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 10 + 2;
mpz_urandomb (bs, rands, size_range);
op1n = mpz_get_ui (bs);
mpz_rrandomb (op1, rands, op1n);
mpz_urandomb (bs, rands, size_range);
op2n = mpz_get_ui (bs);
mpz_rrandomb (op2, rands, op2n);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (op1, op1);
if ((bsi & 2) != 0)
mpz_neg (op2, op2);
/* printf ("%ld %ld\n", SIZ (multiplier), SIZ (multiplicand)); */
mpz_add (r1, op1, op2);
mpz_sub (r2, r1, op2);
if (mpz_cmp (r2, op1) != 0)
dump_abort (i, "mpz_add or mpz_sub incorrect", op1, op2);
if (mpz_fits_ulong_p (op2))
{
op2long = mpz_get_ui (op2);
mpz_add_ui (r1, op1, op2long);
mpz_sub_ui (r2, r1, op2long);
if (mpz_cmp (r2, op1) != 0)
dump_abort (i, "mpz_add_ui or mpz_sub_ui incorrect", op1, op2);
mpz_ui_sub (r1, op2long, op1);
mpz_sub_ui (r2, op1, op2long);
mpz_neg (r2, r2);
if (mpz_cmp (r1, r2) != 0)
dump_abort (i, "mpz_add_ui or mpz_ui_sub incorrect", op1, op2);
}
}
mpz_clear (bs);
mpz_clear (op1);
mpz_clear (op2);
mpz_clear (r1);
mpz_clear (r2);
tests_end ();
exit (0);
}
void
dump_abort (int i, const char *s, mpz_t op1, mpz_t op2)
{
fprintf (stderr, "ERROR: %s in test %d\n", s, i);
fprintf (stderr, "op1 = "); debug_mp (op1, -16);
fprintf (stderr, "op2 = "); debug_mp (op2, -16);
abort();
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,464 @@
/* Test mpz_addmul, mpz_addmul_ui, mpz_submul, mpz_submul_ui.
Copyright 2001, 2002, 2022 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gmp-impl.h"
#include "tests.h"
#define M GMP_NUMB_MAX
void
check_one_inplace (mpz_srcptr w, mpz_srcptr y)
{
mpz_t want, got;
mpz_init (want);
mpz_init (got);
mpz_mul (want, w, y);
mpz_add (want, w, want);
mpz_set (got, w);
mpz_addmul (got, got, y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_addmul inplace fail\n");
fail:
mpz_trace ("w", w);
mpz_trace ("y", y);
mpz_trace ("want", want);
mpz_trace ("got ", got);
abort ();
}
mpz_mul (want, w, y);
mpz_sub (want, w, want);
mpz_set (got, w);
mpz_submul (got, got, y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_submul inplace fail\n");
goto fail;
}
mpz_clear (want);
mpz_clear (got);
}
void
check_one_ui_inplace (mpz_ptr w, unsigned long y)
{
mpz_t want, got;
mpz_init (want);
mpz_init (got);
mpz_mul_ui (want, w, (unsigned long) y);
mpz_add (want, w, want);
mpz_set (got, w);
mpz_addmul_ui (got, got, (unsigned long) y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_addmul_ui fail\n");
fail:
mpz_trace ("w", w);
printf ("y=0x%lX %lu\n", y, y);
mpz_trace ("want", want);
mpz_trace ("got ", got);
abort ();
}
mpz_mul_ui (want, w, y);
mpz_sub (want, w, want);
mpz_set (got, w);
mpz_submul_ui (got, got, y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_submul_ui fail\n");
goto fail;
}
mpz_clear (want);
mpz_clear (got);
}
void
check_all_inplace (mpz_ptr w, mpz_ptr y)
{
int wneg, yneg;
MPZ_CHECK_FORMAT (w);
MPZ_CHECK_FORMAT (y);
for (wneg = 0; wneg < 2; wneg++)
{
for (yneg = 0; yneg < 2; yneg++)
{
check_one_inplace (w, y);
if (mpz_fits_ulong_p (y))
check_one_ui_inplace (w, mpz_get_ui (y));
mpz_neg (y, y);
}
mpz_neg (w, w);
}
}
void
check_one (mpz_srcptr w, mpz_srcptr x, mpz_srcptr y)
{
mpz_t want, got;
mpz_init (want);
mpz_init (got);
mpz_mul (want, x, y);
mpz_add (want, w, want);
mpz_set (got, w);
mpz_addmul (got, x, y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_addmul fail\n");
fail:
mpz_trace ("w", w);
mpz_trace ("x", x);
mpz_trace ("y", y);
mpz_trace ("want", want);
mpz_trace ("got ", got);
abort ();
}
mpz_sub (want, want, w);
mpz_sub (want, w, want);
mpz_set (got, w);
mpz_submul (got, x, y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_submul fail\n");
goto fail;
}
mpz_clear (want);
mpz_clear (got);
}
void
check_sqr (mpz_srcptr w, mpz_srcptr x)
{
mpz_t want, got;
mpz_init (want);
mpz_init (got);
mpz_mul (want, x, x);
mpz_add (want, w, want);
mpz_set (got, w);
mpz_addmul (got, x, x);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_addmul xx fail\n");
sqrfail:
mpz_trace ("w", w);
mpz_trace ("x", x);
mpz_trace ("want", want);
mpz_trace ("got ", got);
abort ();
}
mpz_sub (want, want, w);
mpz_sub (want, w, want);
mpz_set (got, w);
mpz_submul (got, x, x);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_submul xx fail\n");
goto sqrfail;
}
mpz_clear (want);
mpz_clear (got);
}
void
check_one_ui (mpz_ptr w, mpz_ptr x, unsigned long y)
{
mpz_t want, got;
mpz_init (want);
mpz_init (got);
mpz_mul_ui (want, x, (unsigned long) y);
mpz_add (want, w, want);
mpz_set (got, w);
mpz_addmul_ui (got, x, (unsigned long) y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_addmul_ui fail\n");
fail:
mpz_trace ("w", w);
mpz_trace ("x", x);
printf ("y=0x%lX %lu\n", y, y);
mpz_trace ("want", want);
mpz_trace ("got ", got);
abort ();
}
mpz_mul_ui (want, x, y);
mpz_sub (want, w, want);
mpz_set (got, w);
mpz_submul_ui (got, x, y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (want, got) != 0)
{
printf ("mpz_submul_ui fail\n");
goto fail;
}
mpz_clear (want);
mpz_clear (got);
}
void
check_all (mpz_ptr w, mpz_ptr x, mpz_ptr y)
{
int swap, wneg, xneg, yneg;
MPZ_CHECK_FORMAT (w);
MPZ_CHECK_FORMAT (x);
MPZ_CHECK_FORMAT (y);
for (swap = 0; swap < 2; swap++)
{
for (wneg = 0; wneg < 2; wneg++)
{
for (xneg = 0; xneg < 2; xneg++)
{
for (yneg = 0; yneg < 2; yneg++)
{
check_one (w, x, y);
if (mpz_fits_ulong_p (y))
check_one_ui (w, x, mpz_get_ui (y));
mpz_neg (y, y);
}
check_sqr (w, x);
mpz_neg (x, x);
}
mpz_neg (w, w);
}
mpz_swap (x, y);
}
}
void
check_data_inplace_ui (void)
{
static const struct {
mp_limb_t w[6];
unsigned long y;
} data[] = {
{ { 0 }, 0 },
{ { 0 }, 1 },
{ { 1 }, 1 },
{ { 2 }, 1 },
{ { 123 }, 1 },
{ { 123 }, ULONG_MAX },
{ { M }, 1 },
{ { M }, ULONG_MAX },
{ { 123, 456 }, 1 },
{ { M, M }, 1 },
{ { 123, 456 }, ULONG_MAX },
{ { M, M }, ULONG_MAX },
{ { 123, 456, 789 }, 1 },
{ { M, M, M }, 1 },
{ { 123, 456, 789 }, ULONG_MAX },
{ { M, M, M }, ULONG_MAX },
};
mpz_t w, y;
int i;
mpz_init (w);
mpz_init (y);
for (i = 0; i < numberof (data); i++)
{
mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w));
mpz_set_ui (y, data[i].y);
check_all_inplace (w, y);
}
mpz_clear (w);
mpz_clear (y);
}
void
check_data (void)
{
static const struct {
mp_limb_t w[6];
mp_limb_t x[6];
mp_limb_t y[6];
} data[] = {
/* reducing to zero */
{ { 1 }, { 1 }, { 1 } },
{ { 2 }, { 1 }, { 2 } },
{ { 0,1 }, { 0,1 }, { 1 } },
/* reducing to 1 */
{ { 0,1 }, { M }, { 1 } },
{ { 0,0,1 }, { M,M }, { 1 } },
{ { 0,0,0,1 }, { M,M,M }, { 1 } },
{ { 0,0,0,0,1 }, { M,M,M,M }, { 1 } },
/* reducing to -1 */
{ { M }, { 0,1 }, { 1 } },
{ { M,M }, { 0,0,1 }, { 1 } },
{ { M,M,M }, { 0,0,0,1 }, { 1 } },
{ { M,M,M,M }, { 0,0,0,0,1 }, { 1 } },
/* carry out of addmul */
{ { M }, { 1 }, { 1 } },
{ { M,M }, { 1 }, { 1 } },
{ { M,M,M }, { 1 }, { 1 } },
/* borrow from submul */
{ { 0,1 }, { 1 }, { 1 } },
{ { 0,0,1 }, { 1 }, { 1 } },
{ { 0,0,0,1 }, { 1 }, { 1 } },
/* borrow from submul */
{ { 0,0,1 }, { 0,1 }, { 1 } },
{ { 0,0,0,1 }, { 0,1 }, { 1 } },
{ { 0,0,0,0,1 }, { 0,1 }, { 1 } },
/* more borrow from submul */
{ { M }, { 0,1 }, { 1 } },
{ { M }, { 0,0,1 }, { 1 } },
{ { M }, { 0,0,0,1 }, { 1 } },
{ { M }, { 0,0,0,0,1 }, { 1 } },
/* big borrow from submul */
{ { 0,0,1 }, { M,M }, { M } },
{ { 0,0,0,1 }, { M,M }, { M } },
{ { 0,0,0,0,1 }, { M,M }, { M } },
/* small w */
{ { 0,1 }, { M,M }, { M } },
{ { 0,1 }, { M,M,M }, { M } },
{ { 0,1 }, { M,M,M,M }, { M } },
{ { 0,1 }, { M,M,M,M,M }, { M } },
};
mpz_t w, x, y;
int i;
mpz_init (w);
mpz_init (x);
mpz_init (y);
for (i = 0; i < numberof (data); i++)
{
mpz_set_n (w, data[i].w, (mp_size_t) numberof(data[i].w));
mpz_set_n (x, data[i].x, (mp_size_t) numberof(data[i].x));
mpz_set_n (y, data[i].y, (mp_size_t) numberof(data[i].y));
check_all (w, x, y);
}
mpz_clear (w);
mpz_clear (x);
mpz_clear (y);
}
void
check_random (int argc, char *argv[])
{
gmp_randstate_ptr rands = RANDS;
mpz_t w, x, y;
int i, reps = 2000;
mpz_init (w);
mpz_init (x);
mpz_init (y);
if (argc == 2)
reps = atoi (argv[1]);
for (i = 0; i < reps; i++)
{
mpz_errandomb (w, rands, 5*GMP_LIMB_BITS);
mpz_errandomb (x, rands, 5*GMP_LIMB_BITS);
mpz_errandomb (y, rands, 5*GMP_LIMB_BITS);
check_all (w, x, y);
check_all_inplace (w, y);
mpz_errandomb (w, rands, 5*GMP_LIMB_BITS);
mpz_errandomb (x, rands, 5*GMP_LIMB_BITS);
mpz_errandomb (y, rands, BITS_PER_ULONG);
check_all (w, x, y);
check_all_inplace (w, y);
}
mpz_clear (w);
mpz_clear (x);
mpz_clear (y);
}
int
main (int argc, char *argv[])
{
tests_start ();
mp_trace_base = -16;
check_data ();
check_data_inplace_ui ();
check_random (argc, argv);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,328 @@
/* Exercise mpz_bin_ui and mpz_bin_uiui.
Copyright 2000, 2001, 2010, 2012, 2018, 2020 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Default number of generated tests. */
#define COUNT 700
void
try_mpz_bin_ui (mpz_srcptr want, mpz_srcptr n, unsigned long k)
{
mpz_t got;
mpz_init (got);
mpz_bin_ui (got, n, k);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_bin_ui wrong\n");
printf (" n="); mpz_out_str (stdout, 10, n); printf ("\n");
printf (" k=%lu\n", k);
printf (" got="); mpz_out_str (stdout, 10, got); printf ("\n");
printf (" want="); mpz_out_str (stdout, 10, want); printf ("\n");
abort();
}
mpz_clear (got);
}
void
try_mpz_bin_uiui (mpz_srcptr want, unsigned long n, unsigned long k)
{
mpz_t got;
mpz_init (got);
mpz_bin_uiui (got, n, k);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_bin_uiui wrong\n");
printf (" n=%lu\n", n);
printf (" k=%lu\n", k);
printf (" got="); mpz_out_str (stdout, 10, got); printf ("\n");
printf (" want="); mpz_out_str (stdout, 10, want); printf ("\n");
abort();
}
mpz_clear (got);
}
void
samples (void)
{
static const struct {
const char *n;
unsigned long k;
const char *want;
} data[] = {
{ "0", 123456, "0" },
{ "1", 543210, "0" },
{ "2", 123321, "0" },
{ "3", 234567, "0" },
{ "10", 23456, "0" },
/* negatives, using bin(-n,k)=bin(n+k-1,k) */
{ "-1", 0, "1" },
{ "-1", 1, "-1" },
{ "-1", 2, "1" },
{ "-1", 3, "-1" },
{ "-1", 4, "1" },
{ "-2", 0, "1" },
{ "-2", 1, "-2" },
{ "-2", 2, "3" },
{ "-2", 3, "-4" },
{ "-2", 4, "5" },
{ "-2", 5, "-6" },
{ "-2", 6, "7" },
{ "-3", 0, "1" },
{ "-3", 1, "-3" },
{ "-3", 2, "6" },
{ "-3", 3, "-10" },
{ "-3", 4, "15" },
{ "-3", 5, "-21" },
{ "-3", 6, "28" },
/* A few random values */
{ "41", 20, "269128937220" },
{ "62", 37, "147405545359541742" },
{ "50", 18, "18053528883775" },
{ "149", 21, "19332950844468483467894649" },
};
mpz_t n, want;
int i;
mpz_init (n);
mpz_init (want);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (n, data[i].n, 0);
mpz_set_str_or_abort (want, data[i].want, 0);
try_mpz_bin_ui (want, n, data[i].k);
if (mpz_fits_ulong_p (n))
try_mpz_bin_uiui (want, mpz_get_ui (n), data[i].k);
}
mpz_clear (n);
mpz_clear (want);
}
/* Test some bin(2k,k) cases. This produces some biggish numbers to
exercise the limb accumulating code. */
void
twos (int count)
{
mpz_t n, want;
unsigned long k;
mpz_init (n);
mpz_init_set_ui (want, (unsigned long) 2);
for (k = 1; k < count; k++)
{
mpz_set_ui (n, 2*k);
try_mpz_bin_ui (want, n, k);
try_mpz_bin_uiui (want, 2*k, k);
mpz_mul_ui (want, want, 2*(2*k+1));
mpz_fdiv_q_ui (want, want, k+1);
}
mpz_clear (n);
mpz_clear (want);
}
/* Test some random bin(n,k) cases. This produces some biggish
numbers to exercise the limb accumulating code. */
void
randomwalk (int count)
{
mpz_t n_z, want, tmp;
unsigned long n, k, i, r;
int tests;
gmp_randstate_ptr rands;
rands = RANDS;
mpz_init (n_z);
k = 3;
n = 12;
mpz_init_set_ui (want, (unsigned long) 220); /* binomial(12,3) = 220 */
for (tests = 1; tests < count; tests++)
{
r = gmp_urandomm_ui (rands, 62) + 1;
for (i = r & 7; i > 0; i--)
{
n++; k++;
mpz_mul_ui (want, want, n);
mpz_divexact_ui (want, want, k);
}
for (i = r >> 3; i > 0; i--)
{
n++;
mpz_mul_ui (want, want, n);
mpz_divexact_ui (want, want, n - k);
}
mpz_set_ui (n_z, n);
try_mpz_bin_ui (want, n_z, k);
try_mpz_bin_uiui (want, n, k);
}
k = 2;
mpz_urandomb (n_z, rands, 200);
mpz_mul (want, n_z, n_z); /* want = n_z ^ 2 */
mpz_sub (want, want, n_z); /* want = n_z ^ 2 - n_z = n_z (n_z- 1) */
mpz_tdiv_q_2exp (want, want, 1); /* want = n_z (n_z- 1) / 2 = binomial (n_z, 2) */
mpz_init (tmp);
for (tests = 1; tests < count; tests++)
{
r = gmp_urandomm_ui (rands, 62) + 1;
for (i = r & 7; i > 0; i--)
{
k++;
mpz_add_ui (n_z, n_z, 1);
mpz_mul (want, want, n_z);
mpz_divexact_ui (want, want, k);
}
for (i = r >> 3; i > 0; i--)
{
mpz_add_ui (n_z, n_z, 1);
mpz_mul (want, want, n_z);
mpz_sub_ui (tmp, n_z, k);
mpz_divexact (want, want, tmp);
}
try_mpz_bin_ui (want, n_z, k);
}
mpz_clear (tmp);
mpz_clear (n_z);
mpz_clear (want);
}
/* Test some random bin(n,k) cases. This produces some biggish
numbers to exercise the limb accumulating code. */
void
randomwalk_down (int count)
{
mpz_t n_z, want, tmp;
unsigned long n, k, i, r;
int tests;
gmp_randstate_ptr rands;
rands = RANDS;
mpz_init (n_z);
mpz_init (tmp);
k = 2;
n = ULONG_MAX;
mpz_init_set_ui (want, n);
mpz_mul_ui (want, want, n >> 1);
for (tests = 1; tests < count; tests++)
{
r = gmp_urandomm_ui (rands, 62) + 1;
for (i = r & 7; i > 0; i--)
{
mpz_mul_ui (want, want, n - k);
++k;
mpz_divexact_ui (want, want, k);
}
for (i = r >> 3; i > 0; i--)
{
mpz_mul_ui (want, want, n - k);
mpz_divexact_ui (want, want, n);
--n;
}
mpz_set_ui (n_z, n);
try_mpz_bin_ui (want, n_z, n - k);
try_mpz_bin_uiui (want, n, n - k);
}
mpz_clear (tmp);
mpz_clear (n_z);
mpz_clear (want);
}
/* Test all bin(n,k) cases, with 0 <= k <= n + 1 <= count. */
void
smallexaustive (unsigned int count)
{
mpz_t n_z, want;
unsigned long n, k;
mpz_init (n_z);
mpz_init (want);
for (n = 0; n < count; n++)
{
mpz_set_ui (want, (unsigned long) 1);
mpz_set_ui (n_z, n);
for (k = 0; k <= n; k++)
{
try_mpz_bin_ui (want, n_z, k);
try_mpz_bin_uiui (want, n, k);
mpz_mul_ui (want, want, n - k);
mpz_fdiv_q_ui (want, want, k + 1);
}
try_mpz_bin_ui (want, n_z, k);
try_mpz_bin_uiui (want, n, k);
}
mpz_clear (n_z);
mpz_clear (want);
}
int
main (int argc, char **argv)
{
int count;
count = COUNT;
TESTS_REPS (count, argv, argc);
tests_start ();
samples ();
smallexaustive (count >> 4);
twos (count >> 1);
randomwalk (count - (count >> 1));
randomwalk_down (count >> 1);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,405 @@
/* Test mpz_setbit, mpz_clrbit, mpz_tstbit.
Copyright 1997, 2000-2003, 2012, 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
#ifndef SIZE
#define SIZE 4
#endif
void
debug_mp (mpz_srcptr x, int base)
{
mpz_out_str (stdout, base, x); fputc ('\n', stdout);
}
/* exercise the case where mpz_clrbit or mpz_combit ends up extending a
value like -2^(k*GMP_NUMB_BITS-1) when clearing bit k*GMP_NUMB_BITS-1. */
/* And vice-versa. */
void
check_clr_extend (void)
{
mpz_t got, want;
unsigned long i;
int f;
mpz_init (got);
mpz_init (want);
for (i = 1; i < 5; i++)
{
for (f = 0; f <= 1; f++)
{
/* lots of 1 bits in _mp_d */
mpz_set_si (got, 1L);
mpz_mul_2exp (got, got, 10*GMP_NUMB_BITS);
mpz_sub_ui (got, got, 1L);
/* value -2^(n-1) representing ..11100..00 */
mpz_set_si (got, -1L);
mpz_mul_2exp (got, got, i*GMP_NUMB_BITS-1);
/* complement bit n, giving ..11000..00 which is -2^n */
if (f == 0)
mpz_clrbit (got, i*GMP_NUMB_BITS-1);
else
mpz_combit (got, i*GMP_NUMB_BITS-1);
MPZ_CHECK_FORMAT (got);
mpz_set_si (want, -1L);
mpz_mul_2exp (want, want, i*GMP_NUMB_BITS);
if (mpz_cmp (got, want) != 0)
{
if (f == 0)
printf ("mpz_clrbit: ");
else
printf ("mpz_combit: ");
printf ("wrong after extension\n");
mpz_trace ("got ", got);
mpz_trace ("want", want);
abort ();
}
/* complement bit n, going back to ..11100..00 which is -2^(n-1) */
if (f == 0)
mpz_setbit (got, i*GMP_NUMB_BITS-1);
else
mpz_combit (got, i*GMP_NUMB_BITS-1);
MPZ_CHECK_FORMAT (got);
mpz_set_si (want, -1L);
mpz_mul_2exp (want, want, i*GMP_NUMB_BITS - 1);
if (mpz_cmp (got, want) != 0)
{
if (f == 0)
printf ("mpz_setbit: ");
else
printf ("mpz_combit: ");
printf ("wrong after shrinking\n");
mpz_trace ("got ", got);
mpz_trace ("want", want);
abort ();
}
}
}
mpz_clear (got);
mpz_clear (want);
}
void
check_com_negs (void)
{
static const struct {
unsigned long bit;
mp_size_t inp_size;
mp_limb_t inp_n[5];
mp_size_t want_size;
mp_limb_t want_n[5];
} data[] = {
{ GMP_NUMB_BITS, 2, { 1, 1 }, 1, { 1 } },
{ GMP_NUMB_BITS+1, 2, { 1, 1 }, 2, { 1, 3 } },
{ GMP_NUMB_BITS, 2, { 0, 1 }, 2, { 0, 2 } },
{ GMP_NUMB_BITS+1, 2, { 0, 1 }, 2, { 0, 3 } },
};
mpz_t inp, got, want;
int i;
mpz_init (got);
mpz_init (want);
mpz_init (inp);
for (i = 0; i < numberof (data); i++)
{
mpz_set_n (inp, data[i].inp_n, data[i].inp_size);
mpz_neg (inp, inp);
mpz_set_n (want, data[i].want_n, data[i].want_size);
mpz_neg (want, want);
mpz_set (got, inp);
mpz_combit (got, data[i].bit);
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_combit: wrong on neg data[%d]\n", i);
mpz_trace ("inp ", inp);
printf ("bit %lu\n", data[i].bit);
mpz_trace ("got ", got);
mpz_trace ("want", want);
abort ();
}
}
mpz_clear (inp);
mpz_clear (got);
mpz_clear (want);
}
/* See that mpz_tstbit matches a twos complement calculated explicitly, for
various low zeros. */
void
check_tstbit (void)
{
#define MAX_ZEROS 3
#define NUM_LIMBS 3
mp_limb_t pos[1+NUM_LIMBS+MAX_ZEROS];
mp_limb_t neg[1+NUM_LIMBS+MAX_ZEROS];
mpz_t z;
unsigned long i;
int zeros, low1;
int got, want;
mpz_init (z);
for (zeros = 0; zeros <= MAX_ZEROS; zeros++)
{
MPN_ZERO (pos, numberof(pos));
mpn_random2 (pos+zeros, (mp_size_t) NUM_LIMBS);
for (low1 = 0; low1 <= 1; low1++)
{
if (low1)
pos[0] |= 1;
refmpn_neg (neg, pos, (mp_size_t) numberof(neg));
mpz_set_n (z, neg, (mp_size_t) numberof(neg));
mpz_neg (z, z);
for (i = 0; i < numberof(pos)*GMP_NUMB_BITS; i++)
{
got = mpz_tstbit (z, i);
want = refmpn_tstbit (pos, i);
if (got != want)
{
printf ("wrong at bit %lu, with %d zeros\n", i, zeros);
printf ("z neg "); debug_mp (z, -16);
mpz_set_n (z, pos, (mp_size_t) numberof(pos));
printf ("pos "); debug_mp (z, -16);
mpz_set_n (z, neg, (mp_size_t) numberof(neg));
printf ("neg "); debug_mp (z, -16);
exit (1);
}
}
}
}
mpz_clear (z);
}
void
check_single (void)
{
mpz_t x;
int limb, offset, initial;
unsigned long bit;
mpz_init (x);
for (limb = 0; limb < 4; limb++)
{
for (offset = (limb==0 ? 0 : -2); offset <= 2; offset++)
{
for (initial = 1; initial >= -1; initial--)
{
mpz_set_si (x, (long) initial);
bit = (unsigned long) limb*GMP_LIMB_BITS + offset;
mpz_clrbit (x, bit);
MPZ_CHECK_FORMAT (x);
if (mpz_tstbit (x, bit) != 0)
{
printf ("check_single(): expected 0\n");
abort ();
}
mpz_setbit (x, bit);
MPZ_CHECK_FORMAT (x);
if (mpz_tstbit (x, bit) != 1)
{
printf ("check_single(): expected 1\n");
abort ();
}
mpz_clrbit (x, bit);
MPZ_CHECK_FORMAT (x);
if (mpz_tstbit (x, bit) != 0)
{
printf ("check_single(): expected 0\n");
abort ();
}
mpz_combit (x, bit);
MPZ_CHECK_FORMAT (x);
if (mpz_tstbit (x, bit) != 1)
{
printf ("check_single(): expected 1\n");
abort ();
}
mpz_combit (x, bit);
MPZ_CHECK_FORMAT (x);
if (mpz_tstbit (x, bit) != 0)
{
printf ("check_single(): expected 0\n");
abort ();
}
}
}
}
mpz_clear (x);
}
void
check_random (int argc, char *argv[])
{
mpz_t x, s0, s1, s2, s3, m;
mp_size_t xsize;
int i;
int reps = 100000;
int bit0, bit1, bit2, bit3;
unsigned long int bitindex;
const char *s = "";
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (x);
mpz_init (s0);
mpz_init (s1);
mpz_init (s2);
mpz_init (s3);
mpz_init (m);
for (i = 0; i < reps; i++)
{
xsize = urandom () % (2 * SIZE) - SIZE;
mpz_random2 (x, xsize);
bitindex = urandom () % SIZE;
mpz_set (s0, x);
bit0 = mpz_tstbit (x, bitindex);
mpz_setbit (x, bitindex);
MPZ_CHECK_FORMAT (x);
mpz_set (s1, x);
bit1 = mpz_tstbit (x, bitindex);
mpz_clrbit (x, bitindex);
MPZ_CHECK_FORMAT (x);
mpz_set (s2, x);
bit2 = mpz_tstbit (x, bitindex);
mpz_combit (x, bitindex);
MPZ_CHECK_FORMAT (x);
mpz_set (s3, x);
bit3 = mpz_tstbit (x, bitindex);
#define FAIL(str) do { s = str; goto fail; } while (0)
if (bit1 != 1) FAIL ("bit1 != 1");
if (bit2 != 0) FAIL ("bit2 != 0");
if (bit3 != 1) FAIL ("bit3 != 1");
if (bit0 == 0)
{
if (mpz_cmp (s0, s1) == 0 || mpz_cmp (s0, s2) != 0 || mpz_cmp (s0, s3) == 0)
abort ();
}
else
{
if (mpz_cmp (s0, s1) != 0 || mpz_cmp (s0, s2) == 0 || mpz_cmp (s0, s3) != 0)
abort ();
}
if (mpz_cmp (s1, s2) == 0 || mpz_cmp (s1, s3) != 0)
abort ();
if (mpz_cmp (s2, s3) == 0)
abort ();
mpz_combit (x, bitindex);
MPZ_CHECK_FORMAT (x);
if (mpz_cmp (s2, x) != 0)
abort ();
mpz_clrbit (x, bitindex);
MPZ_CHECK_FORMAT (x);
if (mpz_cmp (s2, x) != 0)
abort ();
mpz_ui_pow_ui (m, 2L, bitindex);
MPZ_CHECK_FORMAT (m);
mpz_ior (x, s0, m);
MPZ_CHECK_FORMAT (x);
if (mpz_cmp (x, s3) != 0)
abort ();
mpz_com (m, m);
MPZ_CHECK_FORMAT (m);
mpz_and (x, s0, m);
MPZ_CHECK_FORMAT (x);
if (mpz_cmp (x, s2) != 0)
abort ();
}
mpz_clear (x);
mpz_clear (s0);
mpz_clear (s1);
mpz_clear (s2);
mpz_clear (s3);
mpz_clear (m);
return;
fail:
printf ("%s\n", s);
printf ("bitindex = %lu\n", bitindex);
printf ("x = "); mpz_out_str (stdout, -16, x); printf (" hex\n");
exit (1);
}
int
main (int argc, char *argv[])
{
tests_start ();
mp_trace_base = -16;
check_clr_extend ();
check_com_negs ();
check_tstbit ();
check_random (argc, argv);
check_single ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,158 @@
/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_cdiv_qr_ui, mpz_cdiv_q_ui,
mpz_cdiv_r_ui, , mpz_cdiv_ui, mpz_mul_ui.
Copyright 1993, 1994, 1996, 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void dump_abort (const char *, mpz_t, unsigned long);
void debug_mp (mpz_t, int);
int
main (int argc, char **argv)
{
mpz_t dividend;
mpz_t quotient, remainder;
mpz_t quotient2, remainder2;
mpz_t temp;
mp_size_t dividend_size;
unsigned long divisor;
int i;
int reps = 10000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
unsigned long r_rq, r_q, r_r, r;
tests_start ();
rands = RANDS;
mpz_init (bs);
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (dividend);
mpz_init (quotient);
mpz_init (remainder);
mpz_init (quotient2);
mpz_init (remainder2);
mpz_init (temp);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */
do
{
mpz_rrandomb (bs, rands, 64);
divisor = mpz_get_ui (bs);
}
while (divisor == 0);
mpz_urandomb (bs, rands, size_range);
dividend_size = mpz_get_ui (bs);
mpz_rrandomb (dividend, rands, dividend_size);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (dividend, dividend);
/* printf ("%ld\n", SIZ (dividend)); */
r_rq = mpz_cdiv_qr_ui (quotient, remainder, dividend, divisor);
r_q = mpz_cdiv_q_ui (quotient2, dividend, divisor);
r_r = mpz_cdiv_r_ui (remainder2, dividend, divisor);
r = mpz_cdiv_ui (dividend, divisor);
/* First determine that the quotients and remainders computed
with different functions are equal. */
if (mpz_cmp (quotient, quotient2) != 0)
dump_abort ("quotients from mpz_cdiv_qr_ui and mpz_cdiv_q_ui differ",
dividend, divisor);
if (mpz_cmp (remainder, remainder2) != 0)
dump_abort ("remainders from mpz_cdiv_qr_ui and mpz_cdiv_r_ui differ",
dividend, divisor);
/* Check if the sign of the quotient is correct. */
if (mpz_cmp_ui (quotient, 0) != 0)
if ((mpz_cmp_ui (quotient, 0) < 0)
!= (mpz_cmp_ui (dividend, 0) < 0))
dump_abort ("quotient sign wrong", dividend, divisor);
/* Check if the remainder has the opposite sign as the (positive) divisor
(quotient rounded towards minus infinity). */
if (mpz_cmp_ui (remainder, 0) != 0)
if (mpz_cmp_ui (remainder, 0) > 0)
dump_abort ("remainder sign wrong", dividend, divisor);
mpz_mul_ui (temp, quotient, divisor);
mpz_add (temp, temp, remainder);
if (mpz_cmp (temp, dividend) != 0)
dump_abort ("n mod d != n - [n/d]*d", dividend, divisor);
mpz_abs (remainder, remainder);
if (mpz_cmp_ui (remainder, divisor) >= 0)
dump_abort ("remainder greater than divisor", dividend, divisor);
if (mpz_cmp_ui (remainder, r_rq) != 0)
dump_abort ("remainder returned from mpz_cdiv_qr_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r_q) != 0)
dump_abort ("remainder returned from mpz_cdiv_q_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r_r) != 0)
dump_abort ("remainder returned from mpz_cdiv_r_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r) != 0)
dump_abort ("remainder returned from mpz_cdiv_ui is wrong",
dividend, divisor);
}
mpz_clear (bs);
mpz_clear (dividend);
mpz_clear (quotient);
mpz_clear (remainder);
mpz_clear (quotient2);
mpz_clear (remainder2);
mpz_clear (temp);
tests_end ();
exit (0);
}
void
dump_abort (const char *str, mpz_t dividend, unsigned long divisor)
{
fprintf (stderr, "ERROR: %s\n", str);
fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
fprintf (stderr, "divisor = %lX\n", divisor);
abort();
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,181 @@
/* Test mpz_cmp and mpz_cmpabs.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Nothing sophisticated here, just exercise some combinations of sizes and
signs. */
void
check_one (mpz_ptr x, mpz_ptr y, int want_cmp, int want_cmpabs)
{
int got;
got = mpz_cmp (x, y);
if (( got < 0) != (want_cmp < 0)
|| (got == 0) != (want_cmp == 0)
|| (got > 0) != (want_cmp > 0))
{
printf ("mpz_cmp got %d want %d\n", got, want_cmp);
mpz_trace ("x", x);
mpz_trace ("y", y);
abort ();
}
got = mpz_cmpabs (x, y);
if (( got < 0) != (want_cmpabs < 0)
|| (got == 0) != (want_cmpabs == 0)
|| (got > 0) != (want_cmpabs > 0))
{
printf ("mpz_cmpabs got %d want %d\n", got, want_cmpabs);
mpz_trace ("x", x);
mpz_trace ("y", y);
abort ();
}
}
void
check_all (mpz_ptr x, mpz_ptr y, int want_cmp, int want_cmpabs)
{
check_one (x, y, want_cmp, want_cmpabs);
check_one (y, x, -want_cmp, -want_cmpabs);
mpz_neg (x, x);
mpz_neg (y, y);
want_cmp = -want_cmp;
check_one (x, y, want_cmp, want_cmpabs);
check_one (y, x, -want_cmp, -want_cmpabs);
}
#define SET1(z,size, n) \
SIZ(z) = size; PTR(z)[0] = n
#define SET2(z,size, n1,n0) \
SIZ(z) = size; PTR(z)[1] = n1; PTR(z)[0] = n0
#define SET4(z,size, n3,n2,n1,n0) \
SIZ(z) = size; PTR(z)[3] = n3; PTR(z)[2] = n2; PTR(z)[1] = n1; PTR(z)[0] = n0
void
check_various (void)
{
mpz_t x, y;
mpz_init (x);
mpz_init (y);
mpz_realloc (x, (mp_size_t) 20);
mpz_realloc (y, (mp_size_t) 20);
/* 0 cmp 0, junk in low limbs */
SET1 (x,0, 123);
SET1 (y,0, 456);
check_all (x, y, 0, 0);
/* 123 cmp 0 */
SET1 (x,1, 123);
SET1 (y,0, 456);
check_all (x, y, 1, 1);
/* 123:456 cmp 0 */
SET2 (x,2, 456,123);
SET1 (y,0, 9999);
check_all (x, y, 1, 1);
/* 123 cmp 123 */
SET1(x,1, 123);
SET1(y,1, 123);
check_all (x, y, 0, 0);
/* -123 cmp 123 */
SET1(x,-1, 123);
SET1(y,1, 123);
check_all (x, y, -1, 0);
/* 123 cmp 456 */
SET1(x,1, 123);
SET1(y,1, 456);
check_all (x, y, -1, -1);
/* -123 cmp 456 */
SET1(x,-1, 123);
SET1(y,1, 456);
check_all (x, y, -1, -1);
/* 123 cmp -456 */
SET1(x,1, 123);
SET1(y,-1, 456);
check_all (x, y, 1, -1);
/* 1:0 cmp 1:0 */
SET2 (x,2, 1,0);
SET2 (y,2, 1,0);
check_all (x, y, 0, 0);
/* -1:0 cmp 1:0 */
SET2 (x,-2, 1,0);
SET2 (y,2, 1,0);
check_all (x, y, -1, 0);
/* 2:0 cmp 1:0 */
SET2 (x,2, 2,0);
SET2 (y,2, 1,0);
check_all (x, y, 1, 1);
/* 4:3:2:1 cmp 2:1 */
SET4 (x,4, 4,3,2,1);
SET2 (y,2, 2,1);
check_all (x, y, 1, 1);
/* -4:3:2:1 cmp 2:1 */
SET4 (x,-4, 4,3,2,1);
SET2 (y,2, 2,1);
check_all (x, y, -1, 1);
mpz_clear (x);
mpz_clear (y);
}
int
main (void)
{
tests_start ();
mp_trace_base = -16;
check_various ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,292 @@
/* Test mpz_cmp_d and mpz_cmpabs_d.
Copyright 2001-2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gmp-impl.h"
#include "tests.h"
/* FIXME: Not sure if the tests here are exhaustive. Ought to try to get
each possible exit from mpz_cmp_d (and mpz_cmpabs_d) exercised. */
#define SGN(n) ((n) > 0 ? 1 : (n) < 0 ? -1 : 0)
void
check_one (const char *name, mpz_srcptr x, double y, int cmp, int cmpabs)
{
int got;
got = mpz_cmp_d (x, y);
if (SGN(got) != cmp)
{
int i;
printf ("mpz_cmp_d wrong (from %s)\n", name);
printf (" got %d\n", got);
printf (" want %d\n", cmp);
fail:
mpz_trace (" x", x);
printf (" y %g\n", y);
mp_trace_base=-16;
mpz_trace (" x", x);
printf (" y %g\n", y);
printf (" y");
for (i = 0; i < sizeof(y); i++)
printf (" %02X", (unsigned) ((unsigned char *) &y)[i]);
printf ("\n");
abort ();
}
got = mpz_cmpabs_d (x, y);
if (SGN(got) != cmpabs)
{
printf ("mpz_cmpabs_d wrong\n");
printf (" got %d\n", got);
printf (" want %d\n", cmpabs);
goto fail;
}
}
void
check_data (void)
{
static const struct {
const char *x;
double y;
int cmp, cmpabs;
} data[] = {
{ "0", 0.0, 0, 0 },
{ "1", 0.0, 1, 1 },
{ "-1", 0.0, -1, 1 },
{ "1", 0.5, 1, 1 },
{ "-1", -0.5, -1, 1 },
{ "0", 1.0, -1, -1 },
{ "0", -1.0, 1, -1 },
{ "0x1000000000000000000000000000000000000000000000000", 1.0, 1, 1 },
{ "-0x1000000000000000000000000000000000000000000000000", 1.0, -1, 1 },
{ "0", 1e100, -1, -1 },
{ "0", -1e100, 1, -1 },
{ "2", 1.5, 1, 1 },
{ "2", -1.5, 1, 1 },
{ "-2", 1.5, -1, 1 },
{ "-2", -1.5, -1, 1 },
};
mpz_t x;
int i;
mpz_init (x);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (x, data[i].x, 0);
check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs);
}
mpz_clear (x);
}
/* Equality of integers with up to 53 bits */
void
check_onebits (void)
{
mpz_t x, x2;
double y;
int i;
mpz_init_set_ui (x, 0L);
mpz_init (x2);
for (i = 0; i < 512; i++)
{
mpz_mul_2exp (x, x, 1);
mpz_add_ui (x, x, 1L);
y = mpz_get_d (x);
mpz_set_d (x2, y);
/* stop if any truncation is occurring */
if (mpz_cmp (x, x2) != 0)
break;
check_one ("check_onebits", x, y, 0, 0);
check_one ("check_onebits", x, -y, 1, 0);
mpz_neg (x, x);
check_one ("check_onebits", x, y, -1, 0);
check_one ("check_onebits", x, -y, 0, 0);
mpz_neg (x, x);
}
mpz_clear (x);
mpz_clear (x2);
}
/* With the mpz differing by 1, in a limb position possibly below the double */
void
check_low_z_one (void)
{
mpz_t x;
double y;
unsigned long i;
mpz_init (x);
/* FIXME: It'd be better to base this on the float format. */
#if defined (__vax) || defined (__vax__)
#define LIM 127 /* vax fp numbers have limited range */
#else
#define LIM 512
#endif
for (i = 1; i < LIM; i++)
{
mpz_set_ui (x, 1L);
mpz_mul_2exp (x, x, i);
y = mpz_get_d (x);
check_one ("check_low_z_one", x, y, 0, 0);
check_one ("check_low_z_one", x, -y, 1, 0);
mpz_neg (x, x);
check_one ("check_low_z_one", x, y, -1, 0);
check_one ("check_low_z_one", x, -y, 0, 0);
mpz_neg (x, x);
mpz_sub_ui (x, x, 1);
check_one ("check_low_z_one", x, y, -1, -1);
check_one ("check_low_z_one", x, -y, 1, -1);
mpz_neg (x, x);
check_one ("check_low_z_one", x, y, -1, -1);
check_one ("check_low_z_one", x, -y, 1, -1);
mpz_neg (x, x);
mpz_add_ui (x, x, 2);
check_one ("check_low_z_one", x, y, 1, 1);
check_one ("check_low_z_one", x, -y, 1, 1);
mpz_neg (x, x);
check_one ("check_low_z_one", x, y, -1, 1);
check_one ("check_low_z_one", x, -y, -1, 1);
mpz_neg (x, x);
}
mpz_clear (x);
}
/* Comparing 1 and 1+2^-n. "y" is volatile to make gcc store and fetch it,
which forces it to a 64-bit double, whereas on x86 it would otherwise
remain on the float stack as an 80-bit long double. */
void
check_one_2exp (void)
{
double e;
mpz_t x;
volatile double y;
int i;
mpz_init (x);
e = 1.0;
for (i = 0; i < 128; i++)
{
e /= 2.0;
y = 1.0 + e;
if (y == 1.0)
break;
mpz_set_ui (x, 1L);
check_one ("check_one_2exp", x, y, -1, -1);
check_one ("check_one_2exp", x, -y, 1, -1);
mpz_set_si (x, -1L);
check_one ("check_one_2exp", x, y, -1, -1);
check_one ("check_one_2exp", x, -y, 1, -1);
}
mpz_clear (x);
}
void
check_infinity (void)
{
mpz_t x;
double y = tests_infinity_d ();
if (y == 0.0)
return;
mpz_init (x);
/* 0 cmp inf */
mpz_set_ui (x, 0L);
check_one ("check_infinity", x, y, -1, -1);
check_one ("check_infinity", x, -y, 1, -1);
/* 123 cmp inf */
mpz_set_ui (x, 123L);
check_one ("check_infinity", x, y, -1, -1);
check_one ("check_infinity", x, -y, 1, -1);
/* -123 cmp inf */
mpz_set_si (x, -123L);
check_one ("check_infinity", x, y, -1, -1);
check_one ("check_infinity", x, -y, 1, -1);
/* 2^5000 cmp inf */
mpz_set_ui (x, 1L);
mpz_mul_2exp (x, x, 5000L);
check_one ("check_infinity", x, y, -1, -1);
check_one ("check_infinity", x, -y, 1, -1);
/* -2^5000 cmp inf */
mpz_neg (x, x);
check_one ("check_infinity", x, y, -1, -1);
check_one ("check_infinity", x, -y, 1, -1);
mpz_clear (x);
}
int
main (int argc, char *argv[])
{
tests_start ();
check_data ();
check_onebits ();
check_low_z_one ();
check_one_2exp ();
check_infinity ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,101 @@
/* Test mpz_cmp_si.
Copyright 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
#define SGN(x) ((x) < 0 ? -1 : (x) == 0 ? 0 : 1)
void
check_data (void)
{
static const struct {
const char *a, *b;
int want;
} data[] = {
{ "0", "1", -1 },
{ "0", "0", 0 },
{ "0", "-1", 1 },
{ "1", "1", 0 },
{ "1", "0", 1 },
{ "1", "-1", 1 },
{ "-1", "1", -1 },
{ "-1", "0", -1 },
{ "-1", "-1", 0 },
{ "0", "-0x80000000", 1 },
{ "0x80000000", "-0x80000000", 1 },
{ "0x80000001", "-0x80000000", 1 },
{ "-0x80000000", "-0x80000000", 0 },
{ "-0x80000001", "-0x80000000", -1 },
{ "0", "-0x8000000000000000", 1 },
{ "0x8000000000000000", "-0x8000000000000000", 1 },
{ "0x8000000000000001", "-0x8000000000000000", 1 },
{ "-0x8000000000000000", "-0x8000000000000000", 0 },
{ "-0x8000000000000001", "-0x8000000000000000", -1 },
};
mpz_t a, bz;
long b;
int got;
int i;
mpz_init (a);
mpz_init (bz);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (a, data[i].a, 0);
mpz_set_str_or_abort (bz, data[i].b, 0);
if (mpz_fits_slong_p (bz))
{
b = mpz_get_si (bz);
got = mpz_cmp_si (a, b);
if (SGN (got) != data[i].want)
{
printf ("mpz_cmp_si wrong on data[%d]\n", i);
printf (" a="); mpz_out_str (stdout, 10, a); printf ("\n");
printf (" b=%ld\n", b);
printf (" got=%d\n", got);
printf (" want=%d\n", data[i].want);
abort();
}
}
}
mpz_clear (a);
mpz_clear (bz);
}
int
main (void)
{
tests_start ();
check_data ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,226 @@
/* test mpz_congruent_p and mpz_congruent_ui_p
Copyright 2001, 2002, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_one (mpz_srcptr a, mpz_srcptr c, mpz_srcptr d, int want)
{
int got;
int swap;
for (swap = 0; swap <= 1; swap++)
{
got = (mpz_congruent_p (a, c, d) != 0);
if (want != got)
{
printf ("mpz_congruent_p wrong\n");
printf (" expected %d got %d\n", want, got);
mpz_trace (" a", a);
mpz_trace (" c", c);
mpz_trace (" d", d);
mp_trace_base = -16;
mpz_trace (" a", a);
mpz_trace (" c", c);
mpz_trace (" d", d);
abort ();
}
if (mpz_fits_ulong_p (c) && mpz_fits_ulong_p (d))
{
unsigned long uc = mpz_get_ui (c);
unsigned long ud = mpz_get_ui (d);
got = (mpz_congruent_ui_p (a, uc, ud) != 0);
if (want != got)
{
printf ("mpz_congruent_ui_p wrong\n");
printf (" expected %d got %d\n", want, got);
mpz_trace (" a", a);
printf (" c=%lu\n", uc);
printf (" d=%lu\n", ud);
mp_trace_base = -16;
mpz_trace (" a", a);
printf (" c=0x%lX\n", uc);
printf (" d=0x%lX\n", ud);
abort ();
}
}
MPZ_SRCPTR_SWAP (a, c);
}
}
void
check_data (void)
{
static const struct {
const char *a;
const char *c;
const char *d;
int want;
} data[] = {
/* strict equality mod 0 */
{ "0", "0", "0", 1 },
{ "11", "11", "0", 1 },
{ "3", "11", "0", 0 },
/* anything congruent mod 1 */
{ "0", "0", "1", 1 },
{ "1", "0", "1", 1 },
{ "0", "1", "1", 1 },
{ "123", "456", "1", 1 },
{ "0x123456789123456789", "0x987654321987654321", "1", 1 },
/* csize==1, dsize==2 changing to 1 after stripping 2s */
{ "0x3333333333333333", "0x33333333",
"0x180000000", 1 },
{ "0x33333333333333333333333333333333", "0x3333333333333333",
"0x18000000000000000", 1 },
/* another dsize==2 becoming 1, with opposite signs this time */
{ "0x444444441",
"-0x22222221F",
"0x333333330", 1 },
{ "0x44444444444444441",
"-0x2222222222222221F",
"0x33333333333333330", 1 },
};
mpz_t a, c, d;
int i;
mpz_init (a);
mpz_init (c);
mpz_init (d);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (a, data[i].a, 0);
mpz_set_str_or_abort (c, data[i].c, 0);
mpz_set_str_or_abort (d, data[i].d, 0);
check_one (a, c, d, data[i].want);
}
mpz_clear (a);
mpz_clear (c);
mpz_clear (d);
}
void
check_random (int argc, char *argv[])
{
gmp_randstate_ptr rands = RANDS;
mpz_t a, c, d, ra, rc;
int i;
int want;
int reps = 10000;
mpz_t bs;
unsigned long size_range, size;
if (argc >= 2)
reps = atoi (argv[1]);
mpz_init (bs);
mpz_init (a);
mpz_init (c);
mpz_init (d);
mpz_init (ra);
mpz_init (rc);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */
mpz_urandomb (bs, rands, size_range);
size = mpz_get_ui (bs);
mpz_rrandomb (a, rands, size);
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */
mpz_urandomb (bs, rands, size_range);
size = mpz_get_ui (bs);
mpz_rrandomb (c, rands, size);
do
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 16 + 1; /* 0..65536 bit operands */
mpz_urandomb (bs, rands, size_range);
size = mpz_get_ui (bs);
mpz_rrandomb (d, rands, size);
}
while (SIZ(d) == 0);
mpz_negrandom (a, rands);
MPZ_CHECK_FORMAT (a);
mpz_negrandom (c, rands);
MPZ_CHECK_FORMAT (c);
mpz_negrandom (d, rands);
mpz_fdiv_r (ra, a, d);
mpz_fdiv_r (rc, c, d);
want = (mpz_cmp (ra, rc) == 0);
check_one (a, c, d, want);
mpz_sub (ra, ra, rc);
mpz_sub (a, a, ra);
MPZ_CHECK_FORMAT (a);
check_one (a, c, d, 1);
if (! mpz_pow2abs_p (d))
{
refmpz_combit (a, urandom() % (8*GMP_LIMB_BITS));
check_one (a, c, d, 0);
}
}
mpz_clear (bs);
mpz_clear (a);
mpz_clear (c);
mpz_clear (d);
mpz_clear (ra);
mpz_clear (rc);
}
int
main (int argc, char *argv[])
{
tests_start ();
check_data ();
check_random (argc, argv);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,207 @@
/* test mpz_congruent_2exp_p */
/*
Copyright 2001, 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_one (mpz_srcptr a, mpz_srcptr c, unsigned long d, int want)
{
mpz_t diff, d2exp;
int got;
int swap;
for (swap = 0; swap <= 1; swap++)
{
got = (mpz_congruent_2exp_p (a, c, d) != 0);
if (want != got)
{
mpz_init (diff);
mpz_init (d2exp);
mpz_sub (diff, a, c);
mpz_set_ui (d2exp, 1L);
mpz_mul_2exp (d2exp, d2exp, d);
printf ("mpz_congruent_2exp_p wrong\n");
printf (" expected %d got %d\n", want, got);
mpz_trace (" a", a);
mpz_trace (" c", c);
mpz_trace (" a-c", diff);
mpz_trace (" 2^d", d2exp);
printf (" d=%lu\n", d);
mp_trace_base = -16;
mpz_trace (" a", a);
mpz_trace (" c", c);
mpz_trace (" a-c", diff);
mpz_trace (" 2^d", d2exp);
printf (" d=0x%lX\n", d);
abort ();
}
MPZ_SRCPTR_SWAP (a, c);
}
}
void
check_data (void)
{
static const struct {
const char *a;
const char *c;
unsigned long d;
int want;
} data[] = {
/* anything is congruent mod 1 */
{ "0", "0", 0, 1 },
{ "1", "0", 0, 1 },
{ "0", "1", 0, 1 },
{ "123", "-456", 0, 1 },
{ "0x123456789123456789", "0x987654321987654321", 0, 1 },
{ "0xfffffffffffffffffffffffffffffff7", "-0x9", 129, 0 },
{ "0xfffffffffffffffffffffffffffffff6", "-0xa", 128, 1 },
};
mpz_t a, c;
int i;
mpz_init (a);
mpz_init (c);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (a, data[i].a, 0);
mpz_set_str_or_abort (c, data[i].c, 0);
check_one (a, c, data[i].d, data[i].want);
}
mpz_clear (a);
mpz_clear (c);
}
void
check_random (int reps)
{
gmp_randstate_ptr rands = RANDS;
unsigned long d;
mpz_t a, c, ra, rc;
int i;
mpz_init (a);
mpz_init (c);
mpz_init (ra);
mpz_init (rc);
for (i = 0; i < reps; i++)
{
mpz_errandomb (a, rands, 8*GMP_LIMB_BITS);
mpz_errandomb (c, rands, 8*GMP_LIMB_BITS);
d = urandom() % (8*GMP_LIMB_BITS);
mpz_mul_2exp (a, a, urandom() % (2*GMP_LIMB_BITS));
mpz_mul_2exp (c, c, urandom() % (2*GMP_LIMB_BITS));
mpz_negrandom (a, rands);
mpz_negrandom (c, rands);
mpz_fdiv_r_2exp (ra, a, d);
mpz_fdiv_r_2exp (rc, c, d);
mpz_sub (ra, ra, rc);
if (mpz_cmp_ui (ra, 0) != 0)
{
check_one (a, c, d, 0);
mpz_sub (a, a, ra);
}
check_one (a, c, d, 1);
if (d != 0)
{
mpz_combit (a, urandom() % d);
check_one (a, c, d, 0);
}
}
mpz_clear (a);
mpz_clear (c);
mpz_clear (ra);
mpz_clear (rc);
}
void
check_random_bits (int reps)
{
mp_bitcnt_t ea, ec, en, d;
mp_bitcnt_t m = 10 * GMP_LIMB_BITS;
mpz_t a, c;
int i;
mpz_init2 (a, m + 1);
mpz_init2 (c, m);
for (i = 0; i < reps; i++)
{
d = urandom() % m;
ea = urandom() % m;
ec = urandom() % m;
en = urandom() % m;
mpz_set_ui (c, 0);
mpz_setbit (c, en);
mpz_set_ui (a, 0);
mpz_setbit (a, ec);
mpz_sub (c , a, c);
mpz_set_ui (a, 0);
mpz_setbit (a, ea);
mpz_add (a , a, c);
check_one (a, c, d, ea >= d);
}
mpz_clear (a);
mpz_clear (c);
}
int
main (int argc, char *argv[])
{
int reps = 5000;
tests_start ();
TESTS_REPS (reps, argv, argc);
check_data ();
check_random (reps);
check_random_bits (reps);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,223 @@
/* Test mpz_[cft]div_[qr]_2exp.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* If the remainder is in the correct range and q*d+r is correct, then q
must have rounded correctly. */
void
check_one (mpz_srcptr a, unsigned long d)
{
mpz_t q, r, p, d2exp;
int inplace;
mpz_init (d2exp);
mpz_init (q);
mpz_init (r);
mpz_init (p);
mpz_set_ui (d2exp, 1L);
mpz_mul_2exp (d2exp, d2exp, d);
#define INPLACE(fun,dst,src,d) \
if (inplace) \
{ \
mpz_set (dst, src); \
fun (dst, dst, d); \
} \
else \
fun (dst, src, d);
for (inplace = 0; inplace <= 1; inplace++)
{
INPLACE (mpz_fdiv_q_2exp, q, a, d);
INPLACE (mpz_fdiv_r_2exp, r, a, d);
mpz_mul_2exp (p, q, d);
mpz_add (p, p, r);
if (mpz_sgn (r) < 0 || mpz_cmp (r, d2exp) >= 0)
{
printf ("mpz_fdiv_r_2exp result out of range\n");
goto error;
}
if (mpz_cmp (p, a) != 0)
{
printf ("mpz_fdiv_[qr]_2exp doesn't multiply back\n");
goto error;
}
INPLACE (mpz_cdiv_q_2exp, q, a, d);
INPLACE (mpz_cdiv_r_2exp, r, a, d);
mpz_mul_2exp (p, q, d);
mpz_add (p, p, r);
if (mpz_sgn (r) > 0 || mpz_cmpabs (r, d2exp) >= 0)
{
printf ("mpz_cdiv_r_2exp result out of range\n");
goto error;
}
if (mpz_cmp (p, a) != 0)
{
printf ("mpz_cdiv_[qr]_2exp doesn't multiply back\n");
goto error;
}
INPLACE (mpz_tdiv_q_2exp, q, a, d);
INPLACE (mpz_tdiv_r_2exp, r, a, d);
mpz_mul_2exp (p, q, d);
mpz_add (p, p, r);
if (mpz_sgn (r) != 0 && mpz_sgn (r) != mpz_sgn (a))
{
printf ("mpz_tdiv_r_2exp result wrong sign\n");
goto error;
}
if (mpz_cmpabs (r, d2exp) >= 0)
{
printf ("mpz_tdiv_r_2exp result out of range\n");
goto error;
}
if (mpz_cmp (p, a) != 0)
{
printf ("mpz_tdiv_[qr]_2exp doesn't multiply back\n");
goto error;
}
}
mpz_clear (d2exp);
mpz_clear (q);
mpz_clear (r);
mpz_clear (p);
return;
error:
mpz_trace ("a", a);
printf ("d=%lu\n", d);
mpz_trace ("q", q);
mpz_trace ("r", r);
mpz_trace ("p", p);
mp_trace_base = -16;
mpz_trace ("a", a);
printf ("d=0x%lX\n", d);
mpz_trace ("q", q);
mpz_trace ("r", r);
mpz_trace ("p", p);
abort ();
}
void
check_all (mpz_ptr a, unsigned long d)
{
check_one (a, d);
mpz_neg (a, a);
check_one (a, d);
}
void
check_various (void)
{
static const unsigned long table[] = {
0, 1, 2, 3, 4, 5,
GMP_NUMB_BITS-1, GMP_NUMB_BITS, GMP_NUMB_BITS+1,
2*GMP_NUMB_BITS-1, 2*GMP_NUMB_BITS, 2*GMP_NUMB_BITS+1,
3*GMP_NUMB_BITS-1, 3*GMP_NUMB_BITS, 3*GMP_NUMB_BITS+1,
4*GMP_NUMB_BITS-1, 4*GMP_NUMB_BITS, 4*GMP_NUMB_BITS+1
};
int i, j;
unsigned long n, d;
mpz_t a;
mpz_init (a);
/* a==0, and various d */
mpz_set_ui (a, 0L);
for (i = 0; i < numberof (table); i++)
check_one (a, table[i]);
/* a==2^n, and various d */
for (i = 0; i < numberof (table); i++)
{
n = table[i];
mpz_set_ui (a, 1L);
mpz_mul_2exp (a, a, n);
for (j = 0; j < numberof (table); j++)
{
d = table[j];
check_all (a, d);
}
}
mpz_clear (a);
}
void
check_random (int argc, char *argv[])
{
gmp_randstate_ptr rands = RANDS;
int reps = 100;
mpz_t a;
unsigned long d;
int i;
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (a);
for (i = 0; i < reps; i++)
{
/* exponentially within 2 to 257 bits */
mpz_erandomb (a, rands, urandom () % 8 + 2);
d = urandom () % 256;
check_all (a, d);
}
mpz_clear (a);
}
int
main (int argc, char *argv[])
{
tests_start ();
check_various ();
check_random (argc, argv);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,166 @@
/* test mpz_divisible_p and mpz_divisible_ui_p
Copyright 2001, 2009 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_one (mpz_srcptr a, mpz_srcptr d, int want)
{
int got;
if (mpz_fits_ulong_p (d))
{
unsigned long u = mpz_get_ui (d);
got = (mpz_divisible_ui_p (a, u) != 0);
if (want != got)
{
printf ("mpz_divisible_ui_p wrong\n");
printf (" expected %d got %d\n", want, got);
mpz_trace (" a", a);
printf (" d=%lu\n", u);
mp_trace_base = -16;
mpz_trace (" a", a);
printf (" d=0x%lX\n", u);
abort ();
}
}
got = (mpz_divisible_p (a, d) != 0);
if (want != got)
{
printf ("mpz_divisible_p wrong\n");
printf (" expected %d got %d\n", want, got);
mpz_trace (" a", a);
mpz_trace (" d", d);
mp_trace_base = -16;
mpz_trace (" a", a);
mpz_trace (" d", d);
abort ();
}
}
void
check_data (void)
{
static const struct {
const char *a;
const char *d;
int want;
} data[] = {
{ "0", "0", 1 },
{ "17", "0", 0 },
{ "0", "1", 1 },
{ "123", "1", 1 },
{ "-123", "1", 1 },
{ "0", "2", 1 },
{ "1", "2", 0 },
{ "2", "2", 1 },
{ "-2", "2", 1 },
{ "0x100000000000000000000000000000000", "2", 1 },
{ "0x100000000000000000000000000000001", "2", 0 },
{ "0x3333333333333333", "3", 1 },
{ "0x3333333333333332", "3", 0 },
{ "0x33333333333333333333333333333333", "3", 1 },
{ "0x33333333333333333333333333333332", "3", 0 },
/* divisor changes from 2 to 1 limb after stripping 2s */
{ "0x3333333300000000", "0x180000000", 1 },
{ "0x33333333333333330000000000000000", "0x18000000000000000", 1 },
{ "0x133333333333333330000000000000000", "0x18000000000000000", 0 },
};
mpz_t a, d;
int i;
mpz_init (a);
mpz_init (d);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (a, data[i].a, 0);
mpz_set_str_or_abort (d, data[i].d, 0);
check_one (a, d, data[i].want);
}
mpz_clear (a);
mpz_clear (d);
}
void
check_random (int reps)
{
gmp_randstate_ptr rands = RANDS;
mpz_t a, d, r;
int i;
int want;
mpz_init (a);
mpz_init (d);
mpz_init (r);
for (i = 0; i < reps; i++)
{
mpz_erandomb (a, rands, 1 << 19);
mpz_erandomb_nonzero (d, rands, 1 << 18);
mpz_fdiv_r (r, a, d);
want = (mpz_sgn (r) == 0);
check_one (a, d, want);
mpz_sub (a, a, r);
check_one (a, d, 1);
if (mpz_cmpabs_ui (d, 1L) == 0)
continue;
mpz_add_ui (a, a, 1L);
check_one (a, d, 0);
}
mpz_clear (a);
mpz_clear (d);
mpz_clear (r);
}
int
main (int argc, char *argv[])
{
int reps = 100;
tests_start ();
TESTS_REPS (reps, argv, argc);
check_data ();
check_random (reps);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,132 @@
/* test mpz_divisible_2exp_p */
/*
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_one (mpz_srcptr a, unsigned long d, int want)
{
int got;
got = (mpz_divisible_2exp_p (a, d) != 0);
if (want != got)
{
printf ("mpz_divisible_2exp_p wrong\n");
printf (" expected %d got %d\n", want, got);
mpz_trace (" a", a);
printf (" d=%lu\n", d);
mp_trace_base = -16;
mpz_trace (" a", a);
printf (" d=0x%lX\n", d);
abort ();
}
}
void
check_data (void)
{
static const struct {
const char *a;
unsigned long d;
int want;
} data[] = {
{ "0", 0, 1 },
{ "0", 1, 1 },
{ "0", 2, 1 },
{ "0", 3, 1 },
{ "1", 0, 1 },
{ "1", 1, 0 },
{ "1", 2, 0 },
{ "1", 3, 0 },
{ "1", 10000, 0 },
{ "4", 0, 1 },
{ "4", 1, 1 },
{ "4", 2, 1 },
{ "4", 3, 0 },
{ "4", 4, 0 },
{ "4", 10000, 0 },
{ "0x80000000", 31, 1 },
{ "0x80000000", 32, 0 },
{ "0x80000000", 64, 0 },
{ "0x100000000", 32, 1 },
{ "0x100000000", 33, 0 },
{ "0x100000000", 64, 0 },
{ "0x8000000000000000", 63, 1 },
{ "0x8000000000000000", 64, 0 },
{ "0x8000000000000000", 128, 0 },
{ "0x10000000000000000", 64, 1 },
{ "0x10000000000000000", 65, 0 },
{ "0x10000000000000000", 128, 0 },
{ "0x10000000000000000", 256, 0 },
{ "0x10000000000000000100000000", 32, 1 },
{ "0x10000000000000000100000000", 33, 0 },
{ "0x10000000000000000100000000", 64, 0 },
{ "0x1000000000000000010000000000000000", 64, 1 },
{ "0x1000000000000000010000000000000000", 65, 0 },
{ "0x1000000000000000010000000000000000", 128, 0 },
{ "0x1000000000000000010000000000000000", 256, 0 },
{ "0x1000000000000000010000000000000000", 1024, 0 },
};
mpz_t a, d;
int i;
mpz_init (a);
mpz_init (d);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (a, data[i].a, 0);
check_one (a, data[i].d, data[i].want);
mpz_neg (a, a);
check_one (a, data[i].d, data[i].want);
}
mpz_clear (a);
mpz_clear (d);
}
int
main (int argc, char *argv[])
{
tests_start ();
check_data ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,205 @@
/* Test mpz_export.
Copyright 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_data (void)
{
static const struct {
const char *src;
size_t want_count;
int order;
size_t size;
int endian;
int nail;
char want_data[64];
} data[] = {
{ "0", 0,1, 1,1, 0 },
{ "0", 0,1, 2,1, 0 },
{ "0", 0,1, 3,1, 0 },
{ "0x12345678", 4,1, 1,1, 0, { '\022', '\064', '\126', '\170' } },
{ "0x12345678", 1,1, 4,1, 0, { '\022', '\064', '\126', '\170' } },
{ "0x12345678", 1,-1, 4,1, 0, { '\022', '\064', '\126', '\170' } },
{ "0x12345678", 4,-1, 1,-1, 0, { '\170', '\126', '\064', '\022' } },
{ "0x12345678", 1,1, 4,-1, 0, { '\170', '\126', '\064', '\022' } },
{ "0x12345678", 1,-1, 4,-1, 0, { '\170', '\126', '\064', '\022' } },
{ "0x15", 5,1, 1,1, 7, { '\001', '\000', '\001', '\000', '\001' } },
{ "0x1FFFFFFFFFFF", 3,1, 2,1, 1, {
'\177','\377', '\177','\377', '\177','\377' } },
{ "0x1FFFFFFFFFFF", 3,1, 2,-1, 1, {
'\377','\177', '\377','\177', '\377','\177' } },
{ "0x7", 3,1, 2,1, 15, {
'\000','\001', '\000','\001', '\000','\001' } },
{ "0x7", 3,1, 2,-1, 15, {
'\001','\000', '\001','\000', '\001','\000' } },
{ "0x24", 3,1, 2,1, 14, { '\000','\002', '\000','\001', '\000','\000' }},
{ "0x24", 3,1, 2,-1, 14, { '\002','\000', '\001','\000', '\000','\000' }},
{ "0x24", 3,-1, 2,-1, 14, { '\000','\000', '\001','\000', '\002','\000' }},
{ "0x24", 3,-1, 2,1, 14, { '\000','\000', '\000','\001', '\000','\002' }},
{ "0x123456789ABC", 3,1, 2,1, 0, {
'\022','\064', '\126','\170', '\232','\274' } },
{ "0x123456789ABC", 3,-1, 2,1, 0, {
'\232','\274', '\126','\170', '\022','\064' } },
{ "0x123456789ABC", 3,1, 2,-1, 0, {
'\064','\022', '\170','\126', '\274','\232' } },
{ "0x123456789ABC", 3,-1, 2,-1, 0, {
'\274','\232', '\170','\126', '\064','\022' } },
{ "0x112233445566778899AABBCC", 3,1, 4,1, 0,
{ '\021','\042','\063','\104',
'\125','\146','\167','\210',
'\231','\252','\273','\314' } },
{ "0x112233445566778899AABBCC", 3,-1, 4,1, 0,
{ '\231','\252','\273','\314',
'\125','\146','\167','\210',
'\021','\042','\063','\104' } },
{ "0x112233445566778899AABBCC", 3,1, 4,-1, 0,
{ '\104','\063','\042','\021',
'\210','\167','\146','\125',
'\314','\273','\252','\231' } },
{ "0x112233445566778899AABBCC", 3,-1, 4,-1, 0,
{ '\314','\273','\252','\231',
'\210','\167','\146','\125',
'\104','\063','\042','\021' } },
{ "0x100120023003400450056006700780089009A00AB00BC00C", 3,1, 8,1, 0,
{ '\020','\001','\040','\002','\060','\003','\100','\004',
'\120','\005','\140','\006','\160','\007','\200','\010',
'\220','\011','\240','\012','\260','\013','\300','\014' } },
{ "0x100120023003400450056006700780089009A00AB00BC00C", 3,-1, 8,1, 0,
{ '\220','\011','\240','\012','\260','\013','\300','\014',
'\120','\005','\140','\006','\160','\007','\200','\010',
'\020','\001','\040','\002','\060','\003','\100','\004' } },
{ "0x100120023003400450056006700780089009A00AB00BC00C", 3,1, 8,-1, 0,
{ '\004','\100','\003','\060','\002','\040','\001','\020',
'\010','\200','\007','\160','\006','\140','\005','\120',
'\014','\300','\013','\260','\012','\240','\011','\220' } },
{ "0x100120023003400450056006700780089009A00AB00BC00C", 3,-1, 8,-1, 0,
{ '\014','\300','\013','\260','\012','\240','\011','\220',
'\010','\200','\007','\160','\006','\140','\005','\120',
'\004','\100','\003','\060','\002','\040','\001','\020' } },
{ "0x155555555555555555555555", 3,1, 4,1, 1,
{ '\125','\125','\125','\125',
'\052','\252','\252','\252',
'\125','\125','\125','\125' } },
{ "0x155555555555555555555555", 3,-1, 4,1, 1,
{ '\125','\125','\125','\125',
'\052','\252','\252','\252',
'\125','\125','\125','\125' } },
{ "0x155555555555555555555555", 3,1, 4,-1, 1,
{ '\125','\125','\125','\125',
'\252','\252','\252','\052',
'\125','\125','\125','\125' } },
{ "0x155555555555555555555555", 3,-1, 4,-1, 1,
{ '\125','\125','\125','\125',
'\252','\252','\252','\052',
'\125','\125','\125','\125' } },
};
char buf[sizeof(data[0].src) + sizeof (mp_limb_t) + 128];
char *got_data;
void *ret;
size_t align, got_count, j;
int i, error = 0;
mpz_t src;
mpz_init (src);
for (i = 0; i < numberof (data); i++)
{
for (align = 0; align < sizeof (mp_limb_t); align++)
{
mpz_set_str_or_abort (src, data[i].src, 0);
MPZ_CHECK_FORMAT (src);
got_data = buf + align;
ASSERT_ALWAYS (data[i].want_count * data[i].size + align
<= sizeof (buf));
memset (got_data, '\0', data[i].want_count * data[i].size);
ret = mpz_export (got_data, &got_count, data[i].order,
data[i].size, data[i].endian, data[i].nail, src);
if (ret != got_data)
{
printf ("return doesn't equal given pointer\n");
error = 1;
}
if (got_count != data[i].want_count)
{
printf ("wrong count\n");
error = 1;
}
if (memcmp (got_data, data[i].want_data, got_count * data[i].size) != 0)
{
printf ("wrong result data\n");
error = 1;
}
if (error)
{
printf (" at data[%d] align=%d\n", i, (int) align);
printf (" src \"%s\"\n", data[i].src);
mpz_trace (" src", src);
printf (" order=%d size=%lu endian=%d nail=%u\n",
data[i].order,
(unsigned long) data[i].size, data[i].endian, data[i].nail);
printf (" want count %lu\n", (unsigned long) data[i].want_count);
printf (" got count %lu\n", (unsigned long) got_count);
printf (" want");
for (j = 0; j < data[i].want_count*data[i].size; j++)
printf (" 0x%02X,", (unsigned) (unsigned char) data[i].want_data[j]);
printf ("\n");
printf (" got ");
for (j = 0; j < got_count*data[i].size; j++)
printf (" 0x%02X,", (unsigned) (unsigned char) got_data[j]);
printf ("\n");
abort ();
}
}
}
mpz_clear (src);
}
int
main (void)
{
tests_start ();
mp_trace_base = -16;
check_data ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,108 @@
/* Exercise mpz_fac_ui and mpz_2fac_ui.
Copyright 2000-2002, 2012, 2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Usage: t-fac_ui [x|num]
With no arguments testing goes up to the initial value of "limit" below.
With a number argument tests are carried that far, or with a literal "x"
tests are continued without limit (this being meant only for development
purposes). */
int
main (int argc, char *argv[])
{
unsigned long n, m;
unsigned long limit = 2222;
mpz_t df[2], f, r;
tests_start ();
if (argc > 1 && argv[1][0] == 'x')
limit = ULONG_MAX;
else
TESTS_REPS (limit, argv, argc);
/* for small limb testing */
limit = MIN (limit, MP_LIMB_T_MAX);
mpz_init_set_ui (df[0], 1); /* 0!! = 1 */
mpz_init_set_ui (df[1], 1); /* -1!! = 1 */
mpz_init_set_ui (f, 1); /* 0! = 1 */
mpz_init (r);
for (n = 0, m = 0; n < limit; n++)
{
mpz_fac_ui (r, n);
MPZ_CHECK_FORMAT (r);
if (mpz_cmp (f, r) != 0)
{
printf ("mpz_fac_ui(%lu) wrong\n", n);
printf (" got "); mpz_out_str (stdout, 10, r); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, f); printf("\n");
abort ();
}
mpz_2fac_ui (r, n);
MPZ_CHECK_FORMAT (r);
if (mpz_cmp (df[m], r) != 0)
{
printf ("mpz_2fac_ui(%lu) wrong\n", n);
printf (" got "); mpz_out_str (stdout, 10, r); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, df[m]); printf("\n");
abort ();
}
m ^= 1;
mpz_mul_ui (df[m], df[m], n+1); /* (n+1)!! = (n-1)!! * (n+1) */
mpz_mul_ui (f, f, n+1); /* (n+1)! = n! * (n+1) */
}
n = 2097169; /* a prime = 1 mod 4*/
if (n / 2 > MP_LIMB_T_MAX)
n = 131041; /* a smaller prime :-) */
mpz_fac_ui (f, n / 2); /* ((n-1)/2)! */
m = mpz_fdiv_ui (f, n); /* ((n-1)/2)! mod n*/
mpz_set_ui (f, m);
mpz_mul_ui (f, f, m); /* (((n-1)/2)!)^2 */
m = mpz_fdiv_ui (f, n); /* (((n-1)/2)!)^2 mod n*/
if ( m != n - 1)
{
printf ("mpz_fac_ui(%lu) wrong\n", n / 2);
printf (" al-Haytham's theorem not verified: got %lu, expected %lu.\n", m, n - 1);
abort ();
}
mpz_clear (df[0]);
mpz_clear (df[1]);
mpz_clear (f);
mpz_clear (r);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,146 @@
/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr, mpz_fdiv_q,
mpz_fdiv_r, mpz_mul.
Copyright 1993, 1994, 1996, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void dump_abort (mpz_t, mpz_t);
void debug_mp (mpz_t, int);
int
main (int argc, char **argv)
{
mpz_t dividend, divisor;
mpz_t quotient, remainder;
mpz_t quotient2, remainder2;
mpz_t temp;
mp_size_t dividend_size, divisor_size;
int i;
int reps = 1000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
rands = RANDS;
mpz_init (bs);
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (dividend);
mpz_init (divisor);
mpz_init (quotient);
mpz_init (remainder);
mpz_init (quotient2);
mpz_init (remainder2);
mpz_init (temp);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 16 + 2; /* 0..131071 bit operands */
do
{
mpz_urandomb (bs, rands, size_range);
divisor_size = mpz_get_ui (bs);
mpz_rrandomb (divisor, rands, divisor_size);
}
while (mpz_sgn (divisor) == 0);
mpz_urandomb (bs, rands, size_range);
dividend_size = mpz_get_ui (bs) + divisor_size;
mpz_rrandomb (dividend, rands, dividend_size);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (dividend, dividend);
if ((bsi & 2) != 0)
mpz_neg (divisor, divisor);
/* printf ("%ld %ld\n", SIZ (dividend), SIZ (divisor)); */
mpz_fdiv_qr (quotient, remainder, dividend, divisor);
mpz_fdiv_q (quotient2, dividend, divisor);
mpz_fdiv_r (remainder2, dividend, divisor);
/* First determine that the quotients and remainders computed
with different functions are equal. */
if (mpz_cmp (quotient, quotient2) != 0)
dump_abort (dividend, divisor);
if (mpz_cmp (remainder, remainder2) != 0)
dump_abort (dividend, divisor);
/* Check if the sign of the quotient is correct. */
if (mpz_cmp_ui (quotient, 0) != 0)
if ((mpz_cmp_ui (quotient, 0) < 0)
!= ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
dump_abort (dividend, divisor);
/* Check if the remainder has the same sign as the divisor
(quotient rounded towards minus infinity). */
if (mpz_cmp_ui (remainder, 0) != 0)
if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (divisor, 0) < 0))
dump_abort (dividend, divisor);
mpz_mul (temp, quotient, divisor);
mpz_add (temp, temp, remainder);
if (mpz_cmp (temp, dividend) != 0)
dump_abort (dividend, divisor);
mpz_abs (temp, divisor);
mpz_abs (remainder, remainder);
if (mpz_cmp (remainder, temp) >= 0)
dump_abort (dividend, divisor);
}
mpz_clear (bs);
mpz_clear (dividend);
mpz_clear (divisor);
mpz_clear (quotient);
mpz_clear (remainder);
mpz_clear (quotient2);
mpz_clear (remainder2);
mpz_clear (temp);
tests_end ();
exit (0);
}
void
dump_abort (mpz_t dividend, mpz_t divisor)
{
fprintf (stderr, "ERROR\n");
fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
fprintf (stderr, "divisor = "); debug_mp (divisor, -16);
abort();
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,158 @@
/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_fdiv_qr_ui, mpz_fdiv_q_ui,
mpz_fdiv_r_ui, mpz_fdiv_ui, mpz_mul_ui.
Copyright 1993, 1994, 1996, 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void dump_abort (const char *, mpz_t, unsigned long);
void debug_mp (mpz_t, int);
int
main (int argc, char **argv)
{
mpz_t dividend;
mpz_t quotient, remainder;
mpz_t quotient2, remainder2;
mpz_t temp;
mp_size_t dividend_size;
unsigned long divisor;
int i;
int reps = 10000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
unsigned long r_rq, r_q, r_r, r;
tests_start ();
rands = RANDS;
mpz_init (bs);
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (dividend);
mpz_init (quotient);
mpz_init (remainder);
mpz_init (quotient2);
mpz_init (remainder2);
mpz_init (temp);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */
do
{
mpz_rrandomb (bs, rands, 64);
divisor = mpz_get_ui (bs);
}
while (divisor == 0);
mpz_urandomb (bs, rands, size_range);
dividend_size = mpz_get_ui (bs);
mpz_rrandomb (dividend, rands, dividend_size);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (dividend, dividend);
/* printf ("%ld\n", SIZ (dividend)); */
r_rq = mpz_fdiv_qr_ui (quotient, remainder, dividend, divisor);
r_q = mpz_fdiv_q_ui (quotient2, dividend, divisor);
r_r = mpz_fdiv_r_ui (remainder2, dividend, divisor);
r = mpz_fdiv_ui (dividend, divisor);
/* First determine that the quotients and remainders computed
with different functions are equal. */
if (mpz_cmp (quotient, quotient2) != 0)
dump_abort ("quotients from mpz_fdiv_qr_ui and mpz_fdiv_q_ui differ",
dividend, divisor);
if (mpz_cmp (remainder, remainder2) != 0)
dump_abort ("remainders from mpz_fdiv_qr_ui and mpz_fdiv_r_ui differ",
dividend, divisor);
/* Check if the sign of the quotient is correct. */
if (mpz_cmp_ui (quotient, 0) != 0)
if ((mpz_cmp_ui (quotient, 0) < 0)
!= (mpz_cmp_ui (dividend, 0) < 0))
dump_abort ("quotient sign wrong", dividend, divisor);
/* Check if the remainder has the same sign as the (positive) divisor
(quotient rounded towards minus infinity). */
if (mpz_cmp_ui (remainder, 0) != 0)
if (mpz_cmp_ui (remainder, 0) < 0)
dump_abort ("remainder sign wrong", dividend, divisor);
mpz_mul_ui (temp, quotient, divisor);
mpz_add (temp, temp, remainder);
if (mpz_cmp (temp, dividend) != 0)
dump_abort ("n mod d != n - [n/d]*d", dividend, divisor);
mpz_abs (remainder, remainder);
if (mpz_cmp_ui (remainder, divisor) >= 0)
dump_abort ("remainder greater than divisor", dividend, divisor);
if (mpz_cmp_ui (remainder, r_rq) != 0)
dump_abort ("remainder returned from mpz_fdiv_qr_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r_q) != 0)
dump_abort ("remainder returned from mpz_fdiv_q_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r_r) != 0)
dump_abort ("remainder returned from mpz_fdiv_r_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r) != 0)
dump_abort ("remainder returned from mpz_fdiv_ui is wrong",
dividend, divisor);
}
mpz_clear (bs);
mpz_clear (dividend);
mpz_clear (quotient);
mpz_clear (remainder);
mpz_clear (quotient2);
mpz_clear (remainder2);
mpz_clear (temp);
tests_end ();
exit (0);
}
void
dump_abort (const char *str, mpz_t dividend, unsigned long divisor)
{
fprintf (stderr, "ERROR: %s\n", str);
fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
fprintf (stderr, "divisor = %lX\n", divisor);
abort();
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,155 @@
/* Test mpz_fib_ui and mpz_fib2_ui.
Copyright 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Usage: t-fib_ui [x|num]
Run with no arguments, tests goes up to the initial value of "limit"
below. With a number argument tests are carried up that far, or with a
literal "x" tests are continued without limit (this being only meant for
development purposes).
The size tests performed are designed to partially replicate what will be
going on in mpz_fib_ui. There's plenty of ASSERTs there, but of course
they're not normally enabled.
Misfeatures:
The tests on MPN_FIB2_SIZE are a bit useless, since that macro includes a
+2 for the internal purposes of mpn_fib2_ui. It's probably better to
give mpn_fib2_ui a run with assertion checking enabled. */
#define MPZ_FIB_SIZE_FLOAT(n) \
((mp_size_t) ((n) * 0.6942419 / GMP_NUMB_BITS + 1))
void
check_fib_table (void)
{
int i;
mp_limb_t want;
ASSERT_ALWAYS (FIB_TABLE(-1) == 1);
ASSERT_ALWAYS (FIB_TABLE(0) == 0);
for (i = 1; i <= FIB_TABLE_LIMIT; i++)
{
want = FIB_TABLE(i-1) + FIB_TABLE(i-2);
if (FIB_TABLE(i) != want)
{
printf ("FIB_TABLE(%d) wrong\n", i);
gmp_printf (" got %#Nx\n", &FIB_TABLE(i), 1);
gmp_printf (" want %#Nx\n", &want, 1);
abort ();
}
}
}
int
main (int argc, char *argv[])
{
unsigned long n;
unsigned long limit = 100 * GMP_LIMB_BITS;
mpz_t want_fn, want_fn1, got_fn, got_fn1;
tests_start ();
mp_trace_base = -16;
if (argc > 1 && argv[1][0] == 'x')
limit = ULONG_MAX;
else
TESTS_REPS (limit, argv, argc);
check_fib_table ();
/* start at n==0 */
mpz_init_set_ui (want_fn1, 1); /* F[-1] */
mpz_init_set_ui (want_fn, 0); /* F[0] */
mpz_init (got_fn);
mpz_init (got_fn1);
for (n = 0; n < limit; n++)
{
/* check our float formula seems right */
if (MPZ_FIB_SIZE_FLOAT (n) < SIZ(want_fn))
{
printf ("MPZ_FIB_SIZE_FLOAT wrong at n=%lu\n", n);
printf (" MPZ_FIB_SIZE_FLOAT %ld\n", MPZ_FIB_SIZE_FLOAT (n));
printf (" SIZ(want_fn) %d\n", SIZ(want_fn));
abort ();
}
/* check MPN_FIB2_SIZE seems right, compared to actual size and
compared to our float formula */
if (MPN_FIB2_SIZE (n) < MPZ_FIB_SIZE_FLOAT (n))
{
printf ("MPN_FIB2_SIZE wrong at n=%lu\n", n);
printf (" MPN_FIB2_SIZE %ld\n", MPN_FIB2_SIZE (n));
printf (" MPZ_FIB_SIZE_FLOAT %ld\n", MPZ_FIB_SIZE_FLOAT (n));
abort ();
}
if (MPN_FIB2_SIZE (n) < SIZ(want_fn))
{
printf ("MPN_FIB2_SIZE wrong at n=%lu\n", n);
printf (" MPN_FIB2_SIZE %ld\n", MPN_FIB2_SIZE (n));
printf (" SIZ(want_fn) %d\n", SIZ(want_fn));
abort ();
}
mpz_fib2_ui (got_fn, got_fn1, n);
MPZ_CHECK_FORMAT (got_fn);
MPZ_CHECK_FORMAT (got_fn1);
if (mpz_cmp (got_fn, want_fn) != 0 || mpz_cmp (got_fn1, want_fn1) != 0)
{
printf ("mpz_fib2_ui(%lu) wrong\n", n);
mpz_trace ("want fn ", want_fn);
mpz_trace ("got fn ", got_fn);
mpz_trace ("want fn1", want_fn1);
mpz_trace ("got fn1", got_fn1);
abort ();
}
mpz_fib_ui (got_fn, n);
MPZ_CHECK_FORMAT (got_fn);
if (mpz_cmp (got_fn, want_fn) != 0)
{
printf ("mpz_fib_ui(%lu) wrong\n", n);
mpz_trace ("want fn", want_fn);
mpz_trace ("got fn", got_fn);
abort ();
}
mpz_add (want_fn1, want_fn1, want_fn); /* F[n+1] = F[n] + F[n-1] */
mpz_swap (want_fn1, want_fn);
}
mpz_clear (want_fn);
mpz_clear (want_fn1);
mpz_clear (got_fn);
mpz_clear (got_fn1);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,197 @@
/* Test mpz_fits_*_p */
/*
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Nothing sophisticated here, just exercise mpz_fits_*_p on a small amount
of data. */
#define EXPECT_S(fun,name,answer) \
got = fun (z); \
if (got != answer) \
{ \
printf ("%s (%s) got %d want %d\n", name, expr, got, answer); \
printf (" z size %d\n", SIZ(z)); \
printf (" z dec "); mpz_out_str (stdout, 10, z); printf ("\n"); \
printf (" z hex "); mpz_out_str (stdout, 16, z); printf ("\n"); \
error = 1; \
}
#define EXPECT(fun,answer) EXPECT_S(fun,#fun,answer)
int
main (void)
{
mpz_t z;
int got;
const char *expr;
int error = 0;
tests_start ();
mpz_init (z);
mpz_set_ui (z, 0L);
expr = "0";
EXPECT (mpz_fits_ulong_p, 1);
EXPECT (mpz_fits_uint_p, 1);
EXPECT (mpz_fits_ushort_p, 1);
EXPECT (mpz_fits_slong_p, 1);
EXPECT (mpz_fits_sint_p, 1);
EXPECT (mpz_fits_sshort_p, 1);
mpz_set_ui (z, 1L);
expr = "1";
EXPECT (mpz_fits_ulong_p, 1);
EXPECT (mpz_fits_uint_p, 1);
EXPECT (mpz_fits_ushort_p, 1);
EXPECT (mpz_fits_slong_p, 1);
EXPECT (mpz_fits_sint_p, 1);
EXPECT (mpz_fits_sshort_p, 1);
mpz_set_si (z, -1L);
expr = "-1";
EXPECT (mpz_fits_ulong_p, 0);
EXPECT (mpz_fits_uint_p, 0);
EXPECT (mpz_fits_ushort_p, 0);
EXPECT (mpz_fits_slong_p, 1);
EXPECT (mpz_fits_sint_p, 1);
EXPECT (mpz_fits_sshort_p, 1);
mpz_set_ui (z, 1L);
mpz_mul_2exp (z, z, 5L*GMP_LIMB_BITS);
expr = "2^(5*BPML)";
EXPECT (mpz_fits_ulong_p, 0);
EXPECT (mpz_fits_uint_p, 0);
EXPECT (mpz_fits_ushort_p, 0);
EXPECT (mpz_fits_slong_p, 0);
EXPECT (mpz_fits_sint_p, 0);
EXPECT (mpz_fits_sshort_p, 0);
mpz_set_ui (z, (unsigned long) USHRT_MAX);
expr = "USHRT_MAX";
EXPECT (mpz_fits_ulong_p, 1);
EXPECT (mpz_fits_uint_p, 1);
EXPECT (mpz_fits_ushort_p, 1);
mpz_set_ui (z, (unsigned long) USHRT_MAX);
mpz_add_ui (z, z, 1L);
expr = "USHRT_MAX + 1";
EXPECT (mpz_fits_ushort_p, 0);
mpz_set_ui (z, (unsigned long) UINT_MAX);
expr = "UINT_MAX";
EXPECT (mpz_fits_ulong_p, 1);
EXPECT (mpz_fits_uint_p, 1);
mpz_set_ui (z, (unsigned long) UINT_MAX);
mpz_add_ui (z, z, 1L);
expr = "UINT_MAX + 1";
EXPECT (mpz_fits_uint_p, 0);
mpz_set_ui (z, ULONG_MAX);
expr = "ULONG_MAX";
EXPECT (mpz_fits_ulong_p, 1);
mpz_set_ui (z, ULONG_MAX);
mpz_add_ui (z, z, 1L);
expr = "ULONG_MAX + 1";
EXPECT (mpz_fits_ulong_p, 0);
mpz_set_si (z, (long) SHRT_MAX);
expr = "SHRT_MAX";
EXPECT (mpz_fits_slong_p, 1);
EXPECT (mpz_fits_sint_p, 1);
EXPECT (mpz_fits_sshort_p, 1);
mpz_set_si (z, (long) SHRT_MAX);
mpz_add_ui (z, z, 1L);
expr = "SHRT_MAX + 1";
EXPECT (mpz_fits_sshort_p, 0);
mpz_set_si (z, (long) INT_MAX);
expr = "INT_MAX";
EXPECT (mpz_fits_slong_p, 1);
EXPECT (mpz_fits_sint_p, 1);
mpz_set_si (z, (long) INT_MAX);
mpz_add_ui (z, z, 1L);
expr = "INT_MAX + 1";
EXPECT (mpz_fits_sint_p, 0);
mpz_set_si (z, LONG_MAX);
expr = "LONG_MAX";
EXPECT (mpz_fits_slong_p, 1);
mpz_set_si (z, LONG_MAX);
mpz_add_ui (z, z, 1L);
expr = "LONG_MAX + 1";
EXPECT (mpz_fits_slong_p, 0);
mpz_set_si (z, (long) SHRT_MIN);
expr = "SHRT_MIN";
EXPECT (mpz_fits_slong_p, 1);
EXPECT (mpz_fits_sint_p, 1);
EXPECT (mpz_fits_sshort_p, 1);
mpz_set_si (z, (long) SHRT_MIN);
mpz_sub_ui (z, z, 1L);
expr = "SHRT_MIN + 1";
EXPECT (mpz_fits_sshort_p, 0);
mpz_set_si (z, (long) INT_MIN);
expr = "INT_MIN";
EXPECT (mpz_fits_slong_p, 1);
EXPECT (mpz_fits_sint_p, 1);
mpz_set_si (z, (long) INT_MIN);
mpz_sub_ui (z, z, 1L);
expr = "INT_MIN + 1";
EXPECT (mpz_fits_sint_p, 0);
mpz_set_si (z, LONG_MIN);
expr = "LONG_MIN";
EXPECT (mpz_fits_slong_p, 1);
mpz_set_si (z, LONG_MIN);
mpz_sub_ui (z, z, 1L);
expr = "LONG_MIN + 1";
EXPECT (mpz_fits_slong_p, 0);
if (error)
abort ();
mpz_clear (z);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,467 @@
/* Test mpz_gcd, mpz_gcdext, and mpz_gcd_ui.
Copyright 1991, 1993, 1994, 1996, 1997, 2000-2005, 2008, 2009, 2012 Free
Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void one_test (mpz_t, mpz_t, mpz_t, int);
void debug_mp (mpz_t, int);
static int gcdext_valid_p (const mpz_t, const mpz_t, const mpz_t, const mpz_t);
/* Keep one_test's variables global, so that we don't need
to reinitialize them for each test. */
mpz_t gcd1, gcd2, s, temp1, temp2, temp3;
#define MAX_SCHOENHAGE_THRESHOLD HGCD_REDUCE_THRESHOLD
/* Define this to make all operands be large enough for Schoenhage gcd
to be used. */
#ifndef WHACK_SCHOENHAGE
#define WHACK_SCHOENHAGE 0
#endif
#if WHACK_SCHOENHAGE
#define MIN_OPERAND_BITSIZE (MAX_SCHOENHAGE_THRESHOLD * GMP_NUMB_BITS)
#else
#define MIN_OPERAND_BITSIZE 1
#endif
void
check_data (void)
{
static const struct {
const char *a;
const char *b;
const char *want;
} data[] = {
/* This tickled a bug in gmp 4.1.2 mpn/x86/k6/gcd_finda.asm. */
{ "0x3FFC000007FFFFFFFFFF00000000003F83FFFFFFFFFFFFFFF80000000000000001",
"0x1FFE0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC000000000000000000000001",
"5" }
};
mpz_t a, b, got, want;
int i;
mpz_inits (a, b, got, want, NULL);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (a, data[i].a, 0);
mpz_set_str_or_abort (b, data[i].b, 0);
mpz_set_str_or_abort (want, data[i].want, 0);
mpz_gcd (got, a, b);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_gcd wrong on data[%d]\n", i);
printf (" a %s\n", data[i].a);
printf (" b %s\n", data[i].b);
mpz_trace (" a", a);
mpz_trace (" b", b);
mpz_trace (" want", want);
mpz_trace (" got ", got);
abort ();
}
}
mpz_clears (a, b, got, want, NULL);
}
void
make_chain_operands (mpz_t ref, mpz_t a, mpz_t b, gmp_randstate_t rs, int nb1, int nb2, int chain_len)
{
mpz_t bs, temp1, temp2;
int j;
mpz_inits (bs, temp1, temp2, NULL);
/* Generate a division chain backwards, allowing otherwise unlikely huge
quotients. */
mpz_set_ui (a, 0);
mpz_urandomb (bs, rs, 32);
mpz_urandomb (bs, rs, mpz_get_ui (bs) % nb1 + 1);
mpz_rrandomb (b, rs, mpz_get_ui (bs));
mpz_add_ui (b, b, 1);
mpz_set (ref, b);
for (j = 0; j < chain_len; j++)
{
mpz_urandomb (bs, rs, 32);
mpz_urandomb (bs, rs, mpz_get_ui (bs) % nb2 + 1);
mpz_rrandomb (temp2, rs, mpz_get_ui (bs) + 1);
mpz_add_ui (temp2, temp2, 1);
mpz_mul (temp1, b, temp2);
mpz_add (a, a, temp1);
mpz_urandomb (bs, rs, 32);
mpz_urandomb (bs, rs, mpz_get_ui (bs) % nb2 + 1);
mpz_rrandomb (temp2, rs, mpz_get_ui (bs) + 1);
mpz_add_ui (temp2, temp2, 1);
mpz_mul (temp1, a, temp2);
mpz_add (b, b, temp1);
}
mpz_clears (bs, temp1, temp2, NULL);
}
/* Test operands from a table of seed data. This variant creates the operands
using plain ol' mpz_rrandomb. This is a hack for better coverage of the gcd
code, which depends on that the random number generators give the exact
numbers we expect. */
void
check_kolmo1 (void)
{
static const struct {
unsigned int seed;
int nb;
const char *want;
} data[] = {
{ 59618, 38208, "5"},
{ 76521, 49024, "3"},
{ 85869, 54976, "1"},
{ 99449, 63680, "1"},
{112453, 72000, "1"}
};
gmp_randstate_t rs;
mpz_t bs, a, b, want;
int i, unb, vnb, nb;
gmp_randinit_default (rs);
mpz_inits (bs, a, b, want, NULL);
for (i = 0; i < numberof (data); i++)
{
nb = data[i].nb;
gmp_randseed_ui (rs, data[i].seed);
mpz_urandomb (bs, rs, 32);
unb = mpz_get_ui (bs) % nb;
mpz_urandomb (bs, rs, 32);
vnb = mpz_get_ui (bs) % nb;
mpz_rrandomb (a, rs, unb);
mpz_rrandomb (b, rs, vnb);
mpz_set_str_or_abort (want, data[i].want, 0);
one_test (a, b, want, -1);
}
mpz_clears (bs, a, b, want, NULL);
gmp_randclear (rs);
}
/* Test operands from a table of seed data. This variant creates the operands
using a division chain. This is a hack for better coverage of the gcd
code, which depends on that the random number generators give the exact
numbers we expect. */
void
check_kolmo2 (void)
{
static const struct {
unsigned int seed;
int nb, chain_len;
} data[] = {
{ 917, 15, 5 },
{ 1032, 18, 6 },
{ 1167, 18, 6 },
{ 1174, 18, 6 },
{ 1192, 18, 6 },
};
gmp_randstate_t rs;
mpz_t bs, a, b, want;
int i;
gmp_randinit_default (rs);
mpz_inits (bs, a, b, want, NULL);
for (i = 0; i < numberof (data); i++)
{
gmp_randseed_ui (rs, data[i].seed);
make_chain_operands (want, a, b, rs, data[i].nb, data[i].nb, data[i].chain_len);
one_test (a, b, want, -1);
}
mpz_clears (bs, a, b, want, NULL);
gmp_randclear (rs);
}
int
main (int argc, char **argv)
{
mpz_t op1, op2, ref;
int i, chain_len;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
long int reps = 200;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mpz_inits (bs, op1, op2, ref, gcd1, gcd2, temp1, temp2, temp3, s, NULL);
check_data ();
check_kolmo1 ();
check_kolmo2 ();
/* Testcase to exercise the u0 == u1 case in mpn_gcdext_lehmer_n. */
/* mpz_set_ui (op2, GMP_NUMB_MAX); */ /* FIXME: Huge limb doesn't always fit */
mpz_set_ui (op2, 0);
mpz_setbit (op2, GMP_NUMB_BITS);
mpz_sub_ui (op2, op2, 1);
mpz_mul_2exp (op1, op2, 100);
mpz_add (op1, op1, op2);
mpz_mul_ui (op2, op2, 2);
one_test (op1, op2, NULL, -1);
for (i = 0; i < reps; i++)
{
/* Generate plain operands with unknown gcd. These types of operands
have proven to trigger certain bugs in development versions of the
gcd code. The "hgcd->row[3].rsize > M" ASSERT is not triggered by
the division chain code below, but that is most likely just a result
of that other ASSERTs are triggered before it. */
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 17 + 2;
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (op1, rands, mpz_get_ui (bs) + MIN_OPERAND_BITSIZE);
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (op2, rands, mpz_get_ui (bs) + MIN_OPERAND_BITSIZE);
mpz_urandomb (bs, rands, 8);
bsi = mpz_get_ui (bs);
if ((bsi & 0x3c) == 4)
mpz_mul (op1, op1, op2); /* make op1 a multiple of op2 */
else if ((bsi & 0x3c) == 8)
mpz_mul (op2, op1, op2); /* make op2 a multiple of op1 */
if ((bsi & 1) != 0)
mpz_neg (op1, op1);
if ((bsi & 2) != 0)
mpz_neg (op2, op2);
one_test (op1, op2, NULL, i);
/* Generate a division chain backwards, allowing otherwise unlikely huge
quotients. */
mpz_urandomb (bs, rands, 32);
chain_len = mpz_get_ui (bs) % LOG2C (GMP_NUMB_BITS * MAX_SCHOENHAGE_THRESHOLD);
mpz_urandomb (bs, rands, 32);
chain_len = mpz_get_ui (bs) % (1 << chain_len) / 32;
make_chain_operands (ref, op1, op2, rands, 16, 12, chain_len);
one_test (op1, op2, ref, i);
}
/* Check that we can use NULL as first argument of mpz_gcdext. */
mpz_set_si (op1, -10);
mpz_set_si (op2, 0);
mpz_gcdext (NULL, temp1, temp2, op1, op2);
ASSERT_ALWAYS (mpz_cmp_si (temp1, -1) == 0);
ASSERT_ALWAYS (mpz_cmp_si (temp2, 0) == 0);
mpz_set_si (op2, 6);
mpz_gcdext (NULL, temp1, temp2, op1, op2);
ASSERT_ALWAYS (mpz_cmp_si (temp1, 1) == 0);
ASSERT_ALWAYS (mpz_cmp_si (temp2, 2) == 0);
mpz_clears (bs, op1, op2, ref, gcd1, gcd2, temp1, temp2, temp3, s, NULL);
tests_end ();
exit (0);
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}
void
one_test (mpz_t op1, mpz_t op2, mpz_t ref, int i)
{
/*
printf ("%d %d %d\n", SIZ (op1), SIZ (op2), ref != NULL ? SIZ (ref) : 0);
fflush (stdout);
*/
/*
fprintf (stderr, "op1="); debug_mp (op1, -16);
fprintf (stderr, "op2="); debug_mp (op2, -16);
*/
mpz_gcdext (gcd1, s, NULL, op1, op2);
MPZ_CHECK_FORMAT (gcd1);
MPZ_CHECK_FORMAT (s);
if (ref && mpz_cmp (ref, gcd1) != 0)
{
fprintf (stderr, "ERROR in test %d\n", i);
fprintf (stderr, "mpz_gcdext returned incorrect result\n");
fprintf (stderr, "op1="); debug_mp (op1, -16);
fprintf (stderr, "op2="); debug_mp (op2, -16);
fprintf (stderr, "expected result:\n"); debug_mp (ref, -16);
fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd1, -16);
abort ();
}
if (!gcdext_valid_p(op1, op2, gcd1, s))
{
fprintf (stderr, "ERROR in test %d\n", i);
fprintf (stderr, "mpz_gcdext returned invalid result\n");
fprintf (stderr, "op1="); debug_mp (op1, -16);
fprintf (stderr, "op2="); debug_mp (op2, -16);
fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd1, -16);
fprintf (stderr, "s="); debug_mp (s, -16);
abort ();
}
mpz_gcd (gcd2, op1, op2);
MPZ_CHECK_FORMAT (gcd2);
if (mpz_cmp (gcd2, gcd1) != 0)
{
fprintf (stderr, "ERROR in test %d\n", i);
fprintf (stderr, "mpz_gcd returned incorrect result\n");
fprintf (stderr, "op1="); debug_mp (op1, -16);
fprintf (stderr, "op2="); debug_mp (op2, -16);
fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16);
fprintf (stderr, "mpz_gcd returns:\n"); debug_mp (gcd2, -16);
abort ();
}
/* This should probably move to t-gcd_ui.c */
if (mpz_fits_ulong_p (op1) || mpz_fits_ulong_p (op2))
{
if (mpz_fits_ulong_p (op1))
mpz_gcd_ui (gcd2, op2, mpz_get_ui (op1));
else
mpz_gcd_ui (gcd2, op1, mpz_get_ui (op2));
if (mpz_cmp (gcd2, gcd1))
{
fprintf (stderr, "ERROR in test %d\n", i);
fprintf (stderr, "mpz_gcd_ui returned incorrect result\n");
fprintf (stderr, "op1="); debug_mp (op1, -16);
fprintf (stderr, "op2="); debug_mp (op2, -16);
fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16);
fprintf (stderr, "mpz_gcd_ui returns:\n"); debug_mp (gcd2, -16);
abort ();
}
}
mpz_gcdext (gcd2, temp1, temp2, op1, op2);
MPZ_CHECK_FORMAT (gcd2);
MPZ_CHECK_FORMAT (temp1);
MPZ_CHECK_FORMAT (temp2);
mpz_mul (temp1, temp1, op1);
mpz_mul (temp2, temp2, op2);
mpz_add (temp1, temp1, temp2);
if (mpz_cmp (gcd1, gcd2) != 0
|| mpz_cmp (gcd2, temp1) != 0)
{
fprintf (stderr, "ERROR in test %d\n", i);
fprintf (stderr, "mpz_gcdext returned incorrect result\n");
fprintf (stderr, "op1="); debug_mp (op1, -16);
fprintf (stderr, "op2="); debug_mp (op2, -16);
fprintf (stderr, "expected result:\n"); debug_mp (gcd1, -16);
fprintf (stderr, "mpz_gcdext returns:\n");debug_mp (gcd2, -16);
abort ();
}
}
/* Called when g is supposed to be gcd(a,b), and g = s a + t b, for some t.
Uses temp1, temp2 and temp3. */
static int
gcdext_valid_p (const mpz_t a, const mpz_t b, const mpz_t g, const mpz_t s)
{
/* It's not clear that gcd(0,0) is well defined, but we allow it and require that
gcd(0,0) = 0. */
if (mpz_sgn (g) < 0)
return 0;
if (mpz_sgn (a) == 0)
{
/* Must have g == abs (b). Any value for s is in some sense "correct",
but it makes sense to require that s == 0. */
return mpz_cmpabs (g, b) == 0 && mpz_sgn (s) == 0;
}
else if (mpz_sgn (b) == 0)
{
/* Must have g == abs (a), s == sign (a) */
return mpz_cmpabs (g, a) == 0 && mpz_cmp_si (s, mpz_sgn (a)) == 0;
}
if (mpz_sgn (g) <= 0)
return 0;
mpz_tdiv_qr (temp1, temp3, a, g);
if (mpz_sgn (temp3) != 0)
return 0;
mpz_tdiv_qr (temp2, temp3, b, g);
if (mpz_sgn (temp3) != 0)
return 0;
/* Require that 2 |s| < |b/g|, or |s| == 1. */
if (mpz_cmpabs_ui (s, 1) > 0)
{
mpz_mul_2exp (temp3, s, 1);
if (mpz_cmpabs (temp3, temp2) >= 0)
return 0;
}
/* Compute the other cofactor. */
mpz_mul(temp2, s, a);
mpz_sub(temp2, g, temp2);
mpz_tdiv_qr(temp2, temp3, temp2, b);
if (mpz_sgn (temp3) != 0)
return 0;
/* Require that 2 |t| < |a/g| or |t| == 1*/
if (mpz_cmpabs_ui (temp2, 1) > 0)
{
mpz_mul_2exp (temp2, temp2, 1);
if (mpz_cmpabs (temp2, temp1) >= 0)
return 0;
}
return 1;
}

View File

@@ -0,0 +1,156 @@
/* Test mpz_gcd_ui.
Copyright 2003 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Check mpz_gcd_ui doesn't try to return a value out of range.
This was wrong in gmp 4.1.2 with a long long limb. */
static void
check_ui_range (void)
{
unsigned long got;
mpz_t x;
int i;
mpz_init_set_ui (x, ULONG_MAX);
for (i = 0; i < 20; i++)
{
mpz_mul_2exp (x, x, 1L);
got = mpz_gcd_ui (NULL, x, 0L);
if (got != 0)
{
printf ("mpz_gcd_ui (ULONG_MAX*2^%d, 0)\n", i);
printf (" return %#lx\n", got);
printf (" should be 0\n");
abort ();
}
}
mpz_clear (x);
}
static void
check_ui_factors (void)
{
#define NUM_FACTORS 9
static const char* factors[NUM_FACTORS] = {
"641", "274177", "3", "5", "17", "257", "65537",
"59649589127497217", "1238926361552897" };
unsigned long got;
mpz_t x, b, d, f, g;
int i, j;
gmp_randstate_ptr rands;
if (GMP_NUMB_BITS < 5 || GMP_NUMB_BITS == 8
|| GMP_NUMB_BITS == 16 || GMP_NUMB_BITS > 511)
{
printf ("No usable factors for 2^%i+1.\n", GMP_NUMB_BITS);
return;
}
mpz_init (x);
mpz_init (d);
mpz_init (f);
mpz_init (g);
mpz_setbit (x, GMP_NUMB_BITS);
mpz_add_ui (x, x, 1);
for (i = 0; i < NUM_FACTORS; ++i)
{
mpz_set_str (f, factors[i], 10);
if (mpz_divisible_p (x, f))
{
mpz_mul_2exp (f, f, 1);
/* d is an odd multiple of the factor f, exactly filling a limb. */
mpz_sub (d, x, f);
/* f = 2^GMP_NUMB_BITS mod d. */
mpz_sub_ui (f, f, 1);
break;
}
}
mpz_gcd (g, f, d);
if (mpz_even_p (d) || mpz_cmp (d, f) <= 0 || mpz_cmp_ui (g, 1) != 0)
{
printf ("No usable factor found.\n");
abort ();
}
rands = RANDS;
mpz_mul_ui (x, d, gmp_urandomm_ui (rands, 30000) + 1);
mpz_init (b);
mpz_setbit (b, GMP_NUMB_BITS - 1);
for (j = 0; j < 4; ++j)
{
mpz_add (x, x, b);
for (i = 1; i >= -1; --i)
{
if (mpz_fits_ulong_p (d)
&& ((got = mpz_gcd_ui (NULL, x, mpz_get_ui (d)))
!= (i != 0 ? 1 : mpz_get_ui (d))))
{
printf ("mpz_gcd_ui (f, kV+%i*2^%i, V): error (j = %i)\n", i, GMP_NUMB_BITS - 1, j);
printf (" return %#lx\n", got);
printf (" should be %#lx\n", (i != 0 ? 1 : mpz_get_ui (d)));
abort ();
}
mpz_gcd (g, x, d);
if ((mpz_cmp_ui (g, 1) == 0) != (i != 0))
{
printf ("mpz_gcd (f, kV+%i*2^%i, V): error (j = %i)\n", i, GMP_NUMB_BITS - 1, j);
printf (" should%s be one.\n",(i != 0 ? "" : " not"));
abort ();
}
mpz_sub (x, x, b);
}
/* Back to the original x. */
mpz_addmul_ui (x, b, 2);
mpz_mul (b, b, f);
mpz_mod (b, b, d);
}
mpz_clear (g);
mpz_clear (x);
mpz_clear (f);
mpz_clear (d);
mpz_clear (b);
}
int
main (void)
{
tests_start ();
check_ui_range ();
check_ui_factors ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,80 @@
/* Test mpz_get_d.
Copyright 2002, 2012, 2020 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_onebit (void)
{
int i;
mpz_t z;
double got, want;
/* FIXME: It'd be better to base this on the float format. */
#if defined (__vax) || defined (__vax__)
int limit = 127 - 1; /* vax fp numbers have limited range */
#else
int limit = 512;
#endif
mpz_init (z);
got = mpz_get_d (z);
if (got != 0)
{
printf ("mpz_get_d wrong on zero\n");
abort();
}
mpz_set_ui (z, 1L);
want = 1.0;
for (i = 0; i < limit; i++)
{
got = mpz_get_d (z);
if (got != want)
{
printf ("mpz_get_d wrong on 2**%d\n", i);
mpz_trace (" z ", z);
printf (" want %.20g\n", want);
printf (" got %.20g\n", got);
abort();
}
mpz_mul_2exp (z, z, 1L);
want *= 2.0;
}
mpz_clear (z);
}
int
main (void)
{
tests_start ();
check_onebit ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,222 @@
/* Test mpz_get_d_2exp.
Copyright 2002, 2003, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
static void
check_zero (void)
{
mpz_t z;
double got, want;
long got_exp, want_exp;
mpz_init_set_ui (z, 0);
want = 0.0;
want_exp = 0;
got = mpz_get_d_2exp (&got_exp, z);
if (got != want || got_exp != want_exp)
{
printf ("mpz_get_d_2exp wrong on zero\n");
mpz_trace (" z ", z);
d_trace (" want ", want);
d_trace (" got ", got);
printf (" want exp %ld\n", want_exp);
printf (" got exp %ld\n", got_exp);
abort();
}
mpz_clear (z);
}
static void
check_onebit (void)
{
static const unsigned long data[] = {
1, 32, 52, 53, 54, 63, 64, 65, 128, 256, 511, 512, 513
};
mpz_t z;
double got, want;
long got_exp, want_exp;
int i;
mpz_init (z);
for (i = 0; i < numberof (data); i++)
{
mpz_set_ui (z, 1L);
mpz_mul_2exp (z, z, data[i]);
want = 0.5;
want_exp = data[i] + 1;
got = mpz_get_d_2exp (&got_exp, z);
if (got != want || got_exp != want_exp)
{
printf ("mpz_get_d_2exp wrong on 2**%ld\n", data[i]);
mpz_trace (" z ", z);
d_trace (" want ", want);
d_trace (" got ", got);
printf (" want exp %ld\n", want_exp);
printf (" got exp %ld\n", got_exp);
abort();
}
mpz_set_si (z, -1L);
mpz_mul_2exp (z, z, data[i]);
want = -0.5;
want_exp = data[i] + 1;
got = mpz_get_d_2exp (&got_exp, z);
if (got != want || got_exp != want_exp)
{
printf ("mpz_get_d_2exp wrong on -2**%ld\n", data[i]);
mpz_trace (" z ", z);
d_trace (" want ", want);
d_trace (" got ", got);
printf (" want exp %ld\n", want_exp);
printf (" got exp %ld\n", got_exp);
abort();
}
}
mpz_clear (z);
}
/* Check that hardware rounding doesn't make mpz_get_d_2exp return a value
outside its defined range. */
static void
check_round (void)
{
static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 };
mpz_t z;
double got;
long got_exp;
int i, rnd_mode, old_rnd_mode;
mpz_init (z);
old_rnd_mode = tests_hardware_getround ();
for (rnd_mode = 0; rnd_mode < 4; rnd_mode++)
{
tests_hardware_setround (rnd_mode);
for (i = 0; i < numberof (data); i++)
{
mpz_set_ui (z, 1L);
mpz_mul_2exp (z, z, data[i]);
mpz_sub_ui (z, z, 1L);
got = mpz_get_d_2exp (&got_exp, z);
if (got < 0.5 || got >= 1.0)
{
printf ("mpz_get_d_2exp wrong on 2**%lu-1\n", data[i]);
printf ("result out of range, expect 0.5 <= got < 1.0\n");
printf (" rnd_mode = %d\n", rnd_mode);
printf (" data[i] = %lu\n", data[i]);
mpz_trace (" z ", z);
d_trace (" got ", got);
printf (" got exp %ld\n", got_exp);
abort();
}
mpz_neg (z, z);
got = mpz_get_d_2exp (&got_exp, z);
if (got <= -1.0 || got > -0.5)
{
printf ("mpz_get_d_2exp wrong on -2**%lu-1\n", data[i]);
printf ("result out of range, expect -1.0 < got <= -0.5\n");
printf (" rnd_mode = %d\n", rnd_mode);
printf (" data[i] = %lu\n", data[i]);
mpz_trace (" z ", z);
d_trace (" got ", got);
printf (" got exp %ld\n", got_exp);
abort();
}
}
}
mpz_clear (z);
tests_hardware_setround (old_rnd_mode);
}
static void
check_rand (void)
{
gmp_randstate_ptr rands = RANDS;
int i;
mpz_t z;
double got;
long got_exp;
unsigned long bits;
mpz_init (z);
for (i = 0; i < 200; i++)
{
bits = gmp_urandomm_ui (rands, 512L);
mpz_urandomb (z, rands, bits);
got = mpz_get_d_2exp (&got_exp, z);
if (mpz_sgn (z) == 0)
continue;
bits = mpz_sizeinbase (z, 2);
if (got < 0.5 || got >= 1.0)
{
printf ("mpz_get_d_2exp out of range, expect 0.5 <= got < 1.0\n");
mpz_trace (" z ", z);
d_trace (" got ", got);
printf (" got exp %ld\n", got_exp);
abort();
}
/* FIXME: If mpz_get_d_2exp rounds upwards we might have got_exp ==
bits+1, so leave this test disabled until we decide if that's what
should happen, or not. */
#if 0
if (got_exp != bits)
{
printf ("mpz_get_d_2exp wrong exponent\n", i);
mpz_trace (" z ", z);
d_trace (" bits ", bits);
d_trace (" got ", got);
printf (" got exp %ld\n", got_exp);
abort();
}
#endif
}
mpz_clear (z);
}
int
main (void)
{
tests_start ();
mp_trace_base = -16;
check_zero ();
check_onebit ();
check_round ();
check_rand ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,121 @@
/* Exercise mpz_get_si.
Copyright 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_data (void)
{
static const struct {
const char *n;
long want;
} data[] = {
{ "0", 0L },
{ "1", 1L },
{ "-1", -1L },
{ "2", 2L },
{ "-2", -2L },
{ "12345", 12345L },
{ "-12345", -12345L },
};
int i;
mpz_t n;
long got;
mpz_init (n);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (n, data[i].n, 0);
got = mpz_get_si (n);
if (got != data[i].want)
{
printf ("mpz_get_si wrong at data[%d]\n", i);
printf (" n \"%s\" (", data[i].n);
mpz_out_str (stdout, 10, n); printf (", hex ");
mpz_out_str (stdout, 16, n); printf (")\n");
printf (" got %ld (0x%lX)\n", got, got);
printf (" want %ld (0x%lX)\n", data[i].want, data[i].want);
abort();
}
}
mpz_clear (n);
}
void
check_max (void)
{
mpz_t n;
long want;
long got;
mpz_init (n);
#define CHECK_MAX(name) \
if (got != want) \
{ \
printf ("mpz_get_si wrong on %s\n", name); \
printf (" n "); \
mpz_out_str (stdout, 10, n); printf (", hex "); \
mpz_out_str (stdout, 16, n); printf ("\n"); \
printf (" got %ld, hex %lX\n", got, got); \
printf (" want %ld, hex %lX\n", want, want); \
abort(); \
}
want = LONG_MAX;
mpz_set_si (n, want);
got = mpz_get_si (n);
CHECK_MAX ("LONG_MAX");
want = LONG_MIN;
mpz_set_si (n, want);
got = mpz_get_si (n);
CHECK_MAX ("LONG_MIN");
/* The following checks that -0x100000000 gives -0x80000000. This doesn't
actually fit in a long and the result from mpz_get_si() is undefined,
but -0x80000000 is what comes out currently, and it should be that
value irrespective of the mp_limb_t size (long or long long). */
want = LONG_MIN;
mpz_mul_2exp (n, n, 1);
CHECK_MAX ("-0x100...00");
mpz_clear (n);
}
int
main (void)
{
tests_start ();
check_data ();
check_max ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,123 @@
/* Test mpz_hamdist.
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_twobits (void)
{
unsigned long i, j, got, want;
mpz_t x, y;
mpz_init (x);
mpz_init (y);
for (i = 0; i < 5 * GMP_NUMB_BITS; i++)
{
for (j = 0; j < 5 * GMP_NUMB_BITS; j++)
{
mpz_set_ui (x, 0L);
mpz_setbit (x, i);
mpz_set_ui (y, 0L);
mpz_setbit (y, j);
want = 2 * (i != j);
got = mpz_hamdist (x, y);
if (got != want)
{
printf ("mpz_hamdist wrong on 2 bits pos/pos\n");
wrong:
printf (" i %lu\n", i);
printf (" j %lu\n", j);
printf (" got %lu\n", got);
printf (" want %lu\n", want);
mpz_trace (" x ", x);
mpz_trace (" y ", y);
abort();
}
mpz_neg (x, x);
mpz_neg (y, y);
want = ABS ((long) (i-j));
got = mpz_hamdist (x, y);
if (got != want)
{
printf ("mpz_hamdist wrong on 2 bits neg/neg\n");
goto wrong;
}
}
}
mpz_clear (x);
mpz_clear (y);
}
void
check_rand (void)
{
gmp_randstate_ptr rands = RANDS;
unsigned long got, want;
int i;
mpz_t x, y;
mpz_init (x);
mpz_init (y);
for (i = 0; i < 2000; i++)
{
mpz_erandomb (x, rands, 6 * GMP_NUMB_BITS);
mpz_negrandom (x, rands);
mpz_mul_2exp (x, x, urandom() % (4 * GMP_NUMB_BITS));
mpz_erandomb (y, rands, 6 * GMP_NUMB_BITS);
mpz_negrandom (y, rands);
mpz_mul_2exp (y, y, urandom() % (4 * GMP_NUMB_BITS));
want = refmpz_hamdist (x, y);
got = mpz_hamdist (x, y);
if (got != want)
{
printf ("mpz_hamdist wrong on random\n");
printf (" got %lu\n", got);
printf (" want %lu\n", want);
mpz_trace (" x ", x);
mpz_trace (" y ", y);
abort();
}
}
mpz_clear (x);
mpz_clear (y);
}
int
main (void)
{
tests_start ();
mp_trace_base = -16;
check_twobits ();
check_rand ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,175 @@
/* Test mpz_import.
Copyright 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_data (void)
{
static const struct {
const char *want;
size_t count;
int order;
size_t size;
int endian;
int nail;
char src[64];
} data[] = {
{ "0", 0,1, 1,1, 0 },
{ "0", 1,1, 0,1, 0 },
{ "0x12345678", 4,1, 1,1, 0, { '\22', '\64', '\126', '\170' } },
{ "0x12345678", 1,1, 4,1, 0, { '\22', '\64', '\126', '\170' } },
{ "0x12345678", 1,-1, 4,1, 0, { '\22', '\64', '\126', '\170' } },
{ "0x12345678", 4,-1, 1,-1, 0, { '\170', '\126', '\064', '\22' } },
{ "0x12345678", 1,1, 4,-1, 0, { '\170', '\126', '\064', '\22' } },
{ "0x12345678", 1,-1, 4,-1, 0, { '\170', '\126', '\064', '\22' } },
{ "0", 5,1, 1,1, 7, { '\376', '\376', '\376', '\376', '\376' } },
{ "0", 5,-1, 1,1, 7, { '\376', '\376', '\376', '\376', '\376' } },
{ "0x15", 5,1, 1,1, 7, { '\377', '\376', '\377', '\376', '\377' } },
{ "0", 3,1, 2,1, 1, { '\200','\000', '\200','\000', '\200','\000' }},
{ "0", 3,1, 2,-1, 1, { '\000','\200', '\000','\200', '\000','\200' }},
{ "0", 3,1, 2,1, 15, { '\377','\376', '\377','\376', '\377','\376' }},
{ "0x2A", 3,1, 2,1, 14, { '\377','\376', '\377','\376', '\377','\376' } },
{ "0x06", 3,1, 2,1, 14, { '\377','\374', '\377','\375', '\377','\376' } },
{ "0x24", 3,-1, 2,1, 14, { '\377','\374', '\377','\375', '\377','\376' } },
{ "0x123456789ABC", 3,1, 2,1, 0, {
'\022','\064', '\126','\170', '\232','\274' } },
{ "0x123456789ABC", 3,-1, 2,1, 0, {
'\232','\274', '\126','\170', '\022','\064' } },
{ "0x123456789ABC", 3,1, 2,-1, 0, {
'\064','\022', '\170','\126', '\274','\232' } },
{ "0x123456789ABC", 3,-1, 2,-1, 0, {
'\274','\232', '\170','\126', '\064','\022' } },
{ "0x112233445566778899AABBCC", 3,1, 4,1, 0,
{ '\021','\042','\063','\104',
'\125','\146','\167','\210',
'\231','\252','\273','\314' } },
{ "0x112233445566778899AABBCC", 3,-1, 4,1, 0,
{ '\231','\252','\273','\314',
'\125','\146','\167','\210',
'\021','\042','\063','\104' } },
{ "0x112233445566778899AABBCC", 3,1, 4,-1, 0,
{ '\104','\063','\042','\021',
'\210','\167','\146','\125',
'\314','\273','\252','\231' } },
{ "0x112233445566778899AABBCC", 3,-1, 4,-1, 0,
{ '\314','\273','\252','\231',
'\210','\167','\146','\125',
'\104','\063','\042','\021' } },
{ "0x100120023003400450056006700780089009A00AB00BC00C", 3,1, 8,1, 0,
{ '\020','\001','\040','\002','\060','\003','\100','\004',
'\120','\005','\140','\006','\160','\007','\200','\010',
'\220','\011','\240','\012','\260','\013','\300','\014' } },
{ "0x100120023003400450056006700780089009A00AB00BC00C", 3,-1, 8,1, 0,
{ '\220','\011','\240','\012','\260','\013','\300','\014',
'\120','\005','\140','\006','\160','\007','\200','\010',
'\020','\001','\040','\002','\060','\003','\100','\004' } },
{ "0x100120023003400450056006700780089009A00AB00BC00C", 3,1, 8,-1, 0,
{ '\004','\100','\003','\060','\002','\040','\001','\020',
'\010','\200','\007','\160','\006','\140','\005','\120',
'\014','\300','\013','\260','\012','\240','\011','\220' } },
{ "0x100120023003400450056006700780089009A00AB00BC00C", 3,-1, 8,-1, 0,
{ '\014','\300','\013','\260','\012','\240','\011','\220',
'\010','\200','\007','\160','\006','\140','\005','\120',
'\004','\100','\003','\060','\002','\040','\001','\020' } },
{ "0x155555555555555555555555", 3,1, 4,1, 1,
{ '\325','\125','\125','\125',
'\252','\252','\252','\252',
'\325','\125','\125','\125' } },
{ "0x155555555555555555555555", 3,-1, 4,1, 1,
{ '\325','\125','\125','\125',
'\252','\252','\252','\252',
'\325','\125','\125','\125' } },
{ "0x155555555555555555555555", 3,1, 4,-1, 1,
{ '\125','\125','\125','\325',
'\252','\252','\252','\252',
'\125','\125','\125','\325' } },
{ "0x155555555555555555555555", 3,-1, 4,-1, 1,
{ '\125','\125','\125','\325',
'\252','\252','\252','\252',
'\125','\125','\125','\325' } },
};
char buf[sizeof(data[0].src) + sizeof (mp_limb_t)];
char *src;
size_t align;
int i;
mpz_t got, want;
mpz_init (got);
mpz_init (want);
for (i = 0; i < numberof (data); i++)
{
for (align = 0; align < sizeof (mp_limb_t); align++)
{
mpz_set_str_or_abort (want, data[i].want, 0);
src = buf + align;
memcpy (src, data[i].src, data[i].count * data[i].size);
mpz_set_ui (got, 0L);
mpz_import (got, data[i].count, data[i].order,
data[i].size, data[i].endian, data[i].nail, src);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, want) != 0)
{
printf ("wrong at data[%d]\n", i);
printf (" count=%lu order=%d size=%lu endian=%d nail=%u align=%lu\n",
(unsigned long) data[i].count, data[i].order,
(unsigned long) data[i].size, data[i].endian, data[i].nail,
(unsigned long) align);
mpz_trace (" got ", got);
mpz_trace (" want", want);
abort ();
}
}
}
mpz_clear (got);
mpz_clear (want);
}
int
main (void)
{
tests_start ();
mp_trace_base = -16;
check_data ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,198 @@
/* Test mpz_inp_str.
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h> /* for unlink */
#endif
#include "gmp-impl.h"
#include "tests.h"
#define FILENAME "t-inp_str.tmp"
void
check_data (void)
{
static const struct {
const char *inp;
int base;
const char *want;
int want_nread;
} data[] = {
{ "0", 10, "0", 1 },
{ "abc", 10, "0", 0 },
{ "0xf", 10, "0", 1 },
{ "ghi", 16, "0", 0 },
{ "100", 90, "0", 0 },
{ "ff", 16, "255", 2 },
{ "-ff", 16, "-255", 3 },
{ "FF", 16, "255", 2 },
{ "-FF", 16, "-255", 3 },
{ "z", 36, "35", 1 },
{ "Z", 36, "35", 1 },
{ "1B", 59, "70", 2 },
{ "a", 60, "36", 1 },
{ "A", 61, "10", 1 },
{ "0x0", 0, "0", 3 },
{ "0X10", 0, "16", 4 },
{ "-0X0", 0, "0", 4 },
{ "-0x10", 0, "-16", 5 },
{ "0b0", 0, "0", 3 },
{ "0B10", 0, "2", 4 },
{ "-0B0", 0, "0", 4 },
{ "-0b10", 0, "-2", 5 },
{ "00", 0, "0", 2 },
{ "010", 0, "8", 3 },
{ "-00", 0, "0", 3 },
{ "-010", 0, "-8", 4 },
{ "0x", 0, "0", 2 },
{ "0", 0, "0", 1 },
{ " 030", 10, "30", 4 },
};
mpz_t got, want;
long ftell_nread;
int i, pre, post, j, got_nread, want_nread;
FILE *fp;
mpz_init (got);
mpz_init (want);
for (i = 0; i < numberof (data); i++)
{
for (pre = 0; pre <= 3; pre++)
{
for (post = 0; post <= 2; post++)
{
mpz_set_str_or_abort (want, data[i].want, 0);
MPZ_CHECK_FORMAT (want);
/* create the file new each time to ensure its length is what
we want */
fp = fopen (FILENAME, "w+");
ASSERT_ALWAYS (fp != NULL);
for (j = 0; j < pre; j++)
putc (' ', fp);
fputs (data[i].inp, fp);
for (j = 0; j < post; j++)
putc (' ', fp);
fflush (fp);
ASSERT_ALWAYS (! ferror(fp));
rewind (fp);
got_nread = mpz_inp_str (got, fp, data[i].base);
if (got_nread != 0)
{
ftell_nread = ftell (fp);
if (got_nread != ftell_nread)
{
printf ("mpz_inp_str nread wrong\n");
printf (" inp \"%s\"\n", data[i].inp);
printf (" base %d\n", data[i].base);
printf (" pre %d\n", pre);
printf (" post %d\n", post);
printf (" got_nread %d\n", got_nread);
printf (" ftell_nread %ld\n", ftell_nread);
abort ();
}
}
/* if data[i].inp is a whole string to read and there's no post
whitespace then expect to have EOF */
if (post == 0 && data[i].want_nread == strlen(data[i].inp))
{
int c = getc(fp);
if (c != EOF)
{
printf ("mpz_inp_str didn't read to EOF\n");
printf (" inp \"%s\"\n", data[i].inp);
printf (" base %d\n", data[i].base);
printf (" pre %d\n", pre);
printf (" post %d\n", post);
printf (" c '%c' %#x\n", c, c);
abort ();
}
}
/* only expect "pre" included in the count when non-zero */
want_nread = data[i].want_nread;
if (want_nread != 0)
want_nread += pre;
if (got_nread != want_nread)
{
printf ("mpz_inp_str nread wrong\n");
printf (" inp \"%s\"\n", data[i].inp);
printf (" base %d\n", data[i].base);
printf (" pre %d\n", pre);
printf (" post %d\n", post);
printf (" got_nread %d\n", got_nread);
printf (" want_nread %d\n", want_nread);
abort ();
}
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_inp_str wrong result\n");
printf (" inp \"%s\"\n", data[i].inp);
printf (" base %d\n", data[i].base);
mpz_trace (" got ", got);
mpz_trace (" want", want);
abort ();
}
ASSERT_ALWAYS (fclose (fp) == 0);
}
}
}
mpz_clear (got);
mpz_clear (want);
}
int
main (void)
{
tests_start ();
check_data ();
unlink (FILENAME);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,117 @@
/* Test mpz_invert.
Copyright 1991, 1993, 1994, 1996, 1997, 2000-2005, 2008, 2009, 2012, 2014 Free
Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
int
main (int argc, char **argv)
{
mpz_t a, m, ainv, t;
int test, r;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
int reps = 1000;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mpz_init (bs);
mpz_init (a);
mpz_init (m);
mpz_init (ainv);
mpz_init (t);
for (test = 0; test < reps; test++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 16 + 2;
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (a, rands, mpz_get_ui (bs));
do {
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (m, rands, mpz_get_ui (bs));
} while (mpz_sgn (m) == 0);
mpz_urandomb (bs, rands, 8);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (a, a);
if ((bsi & 2) != 0)
mpz_neg (m, m);
r = mpz_invert (ainv, a, m);
if (r != 0)
{
MPZ_CHECK_FORMAT (ainv);
if (mpz_cmp_ui (ainv, 0) < 0 || mpz_cmpabs (ainv, m) >= 0)
{
fprintf (stderr, "ERROR in test %d\n", test);
gmp_fprintf (stderr, "Inverse out of range.\n");
gmp_fprintf (stderr, "a = %Zx\n", a);
gmp_fprintf (stderr, "1/a = %Zx\n", ainv);
gmp_fprintf (stderr, "m = %Zx\n", m);
abort ();
}
mpz_mul (t, ainv, a);
mpz_mod (t, t, m);
if (mpz_cmp_ui (t, mpz_cmpabs_ui (m, 1) != 0) != 0)
{
fprintf (stderr, "ERROR in test %d\n", test);
gmp_fprintf (stderr, "a^(-1)*a != 1 (mod m)\n");
gmp_fprintf (stderr, "a = %Zx\n", a);
gmp_fprintf (stderr, "m = %Zx\n", m);
abort ();
}
}
else /* Inverse deos not exist */
{
mpz_gcd (t, a, m);
if (mpz_cmp_ui (t, 1) == 0)
{
fprintf (stderr, "ERROR in test %d\n", test);
gmp_fprintf (stderr, "Inverse exists, but was not found.\n");
gmp_fprintf (stderr, "a = %Zx\n", a);
gmp_fprintf (stderr, "m = %Zx\n", m);
abort ();
}
}
}
mpz_clear (bs);
mpz_clear (a);
mpz_clear (m);
mpz_clear (ainv);
mpz_clear (t);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,286 @@
/* Test mpz_inp_raw and mpz_out_raw.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "gmp-impl.h"
#include "tests.h"
#define FILENAME "t-io_raw.tmp"
/* In the fopen, "b" selects binary mode on DOS systems, meaning no
conversion of '\n' to and from CRLF. It's believed systems without such
nonsense will simply ignore the "b", but in case that's not so a plain
"w+" is attempted if "w+b" fails. */
FILE *
fopen_wplusb_or_die (const char *filename)
{
FILE *fp;
fp = fopen (filename, "w+b");
if (fp == NULL)
fp = fopen (filename, "w+");
if (fp == NULL)
{
printf ("Cannot create file %s\n", filename);
abort ();
}
return fp;
}
/* use 0x80 to check nothing bad happens with sign extension etc */
#define BYTEVAL(i) (((i) + 1) | 0x80)
void
check_in (void)
{
int i, j, zeros, neg, error = 0;
mpz_t want, got;
size_t want_ret, got_ret;
mp_size_t size;
FILE *fp;
mpz_init (want);
mpz_init (got);
for (i = 0; i < 32; i++)
{
for (zeros = 0; zeros < 8; zeros++)
{
for (neg = 0; neg <= 1; neg++)
{
want_ret = i + zeros + 4;
/* need this to get the twos complement right */
ASSERT_ALWAYS (sizeof (size) >= 4);
size = i + zeros;
if (neg)
size = -size;
fp = fopen_wplusb_or_die (FILENAME);
for (j = 3; j >= 0; j--)
ASSERT_ALWAYS (putc ((size >> (j*8)) & 0xFF, fp) != EOF);
for (j = 0; j < zeros; j++)
ASSERT_ALWAYS (putc ('\0', fp) != EOF);
for (j = 0; j < i; j++)
ASSERT_ALWAYS (putc (BYTEVAL (j), fp) != EOF);
/* and some trailing garbage */
ASSERT_ALWAYS (putc ('x', fp) != EOF);
ASSERT_ALWAYS (putc ('y', fp) != EOF);
ASSERT_ALWAYS (putc ('z', fp) != EOF);
ASSERT_ALWAYS (fflush (fp) == 0);
rewind (fp);
got_ret = mpz_inp_raw (got, fp);
ASSERT_ALWAYS (! ferror(fp));
ASSERT_ALWAYS (fclose (fp) == 0);
MPZ_CHECK_FORMAT (got);
if (got_ret != want_ret)
{
printf ("check_in: return value wrong\n");
error = 1;
}
if (mpz_cmp (got, want) != 0)
{
printf ("check_in: result wrong\n");
error = 1;
}
if (error)
{
printf (" i=%d zeros=%d neg=%d\n", i, zeros, neg);
printf (" got_ret %lu\n", (unsigned long) got_ret);
printf (" want_ret %lu\n", (unsigned long) want_ret);
mpz_trace (" got ", got);
mpz_trace (" want ", want);
abort ();
}
mpz_neg (want, want);
}
}
mpz_mul_2exp (want, want, 8);
mpz_add_ui (want, want, (unsigned long) BYTEVAL (i));
}
mpz_clear (want);
mpz_clear (got);
}
void
check_out (void)
{
int i, j, neg, error = 0;
mpz_t z;
char want[256], got[256], *p;
size_t want_len, got_ret, got_read;
mp_size_t size;
FILE *fp;
mpz_init (z);
for (i = 0; i < 32; i++)
{
for (neg = 0; neg <= 1; neg++)
{
want_len = i + 4;
/* need this to get the twos complement right */
ASSERT_ALWAYS (sizeof (size) >= 4);
size = i;
if (neg)
size = -size;
p = want;
for (j = 3; j >= 0; j--)
*p++ = size >> (j*8);
for (j = 0; j < i; j++)
*p++ = BYTEVAL (j);
ASSERT_ALWAYS (p <= want + sizeof (want));
fp = fopen_wplusb_or_die (FILENAME);
got_ret = mpz_out_raw (fp, z);
ASSERT_ALWAYS (fflush (fp) == 0);
rewind (fp);
got_read = fread (got, 1, sizeof(got), fp);
ASSERT_ALWAYS (! ferror(fp));
ASSERT_ALWAYS (fclose (fp) == 0);
if (got_ret != want_len)
{
printf ("check_out: wrong return value\n");
error = 1;
}
if (got_read != want_len)
{
printf ("check_out: wrong number of bytes read back\n");
error = 1;
}
if (memcmp (want, got, want_len) != 0)
{
printf ("check_out: wrong data\n");
error = 1;
}
if (error)
{
printf (" i=%d neg=%d\n", i, neg);
mpz_trace (" z", z);
printf (" got_ret %lu\n", (unsigned long) got_ret);
printf (" got_read %lu\n", (unsigned long) got_read);
printf (" want_len %lu\n", (unsigned long) want_len);
printf (" want");
for (j = 0; j < want_len; j++)
printf (" %02X", (unsigned) (unsigned char) want[j]);
printf ("\n");
printf (" got ");
for (j = 0; j < want_len; j++)
printf (" %02X", (unsigned) (unsigned char) got[j]);
printf ("\n");
abort ();
}
mpz_neg (z, z);
}
mpz_mul_2exp (z, z, 8);
mpz_add_ui (z, z, (unsigned long) BYTEVAL (i));
}
mpz_clear (z);
}
void
check_rand (void)
{
gmp_randstate_ptr rands = RANDS;
int i, error = 0;
mpz_t got, want;
size_t inp_ret, out_ret;
FILE *fp;
mpz_init (want);
mpz_init (got);
for (i = 0; i < 500; i++)
{
mpz_erandomb (want, rands, 10*GMP_LIMB_BITS);
mpz_negrandom (want, rands);
fp = fopen_wplusb_or_die (FILENAME);
out_ret = mpz_out_raw (fp, want);
ASSERT_ALWAYS (fflush (fp) == 0);
rewind (fp);
inp_ret = mpz_inp_raw (got, fp);
ASSERT_ALWAYS (fclose (fp) == 0);
MPZ_CHECK_FORMAT (got);
if (inp_ret != out_ret)
{
printf ("check_rand: different inp/out return values\n");
error = 1;
}
if (mpz_cmp (got, want) != 0)
{
printf ("check_rand: wrong result\n");
error = 1;
}
if (error)
{
printf (" out_ret %lu\n", (unsigned long) out_ret);
printf (" inp_ret %lu\n", (unsigned long) inp_ret);
mpz_trace (" want", want);
mpz_trace (" got ", got);
abort ();
}
}
mpz_clear (got);
mpz_clear (want);
}
int
main (void)
{
tests_start ();
mp_trace_base = -16;
check_in ();
check_out ();
check_rand ();
unlink (FILENAME);
tests_end ();
exit (0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
/* Test mpz_lcm and mpz_lcm_ui.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_all (mpz_ptr want, mpz_srcptr x_orig, mpz_srcptr y_orig)
{
mpz_t got, x, y;
int negx, negy, swap, inplace;
mpz_init (got);
mpz_init_set (x, x_orig);
mpz_init_set (y, y_orig);
for (swap = 0; swap < 2; swap++)
{
mpz_swap (x, y);
for (negx = 0; negx < 2; negx++)
{
mpz_neg (x, x);
for (negy = 0; negy < 2; negy++)
{
mpz_neg (y, y);
for (inplace = 0; inplace <= 1; inplace++)
{
if (inplace)
{ mpz_set (got, x); mpz_lcm (got, got, y); }
else
mpz_lcm (got, x, y);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_lcm wrong, inplace=%d\n", inplace);
fail:
mpz_trace ("x", x);
mpz_trace ("y", y);
mpz_trace ("got", got);
mpz_trace ("want", want);
abort ();
}
if (mpz_fits_ulong_p (y))
{
unsigned long yu = mpz_get_ui (y);
if (inplace)
{ mpz_set (got, x); mpz_lcm_ui (got, got, yu); }
else
mpz_lcm_ui (got, x, yu);
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_lcm_ui wrong, inplace=%d\n", inplace);
printf ("yu=%lu\n", yu);
goto fail;
}
}
}
}
}
}
mpz_clear (got);
mpz_clear (x);
mpz_clear (y);
}
void
check_primes (void)
{
static unsigned long prime[] = {
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,
191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,
281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,
389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,
};
mpz_t want, x, y;
int i;
mpz_init (want);
mpz_init (x);
mpz_init (y);
/* Check zeros. */
mpz_set_ui (want, 0);
mpz_set_ui (x, 1);
check_all (want, want, want);
check_all (want, want, x);
check_all (want, x, want);
/* New prime each time. */
mpz_set_ui (want, 1L);
for (i = 0; i < numberof (prime); i++)
{
mpz_set (x, want);
mpz_set_ui (y, prime[i]);
mpz_mul_ui (want, want, prime[i]);
check_all (want, x, y);
}
/* Old prime each time. */
mpz_set (x, want);
for (i = 0; i < numberof (prime); i++)
{
mpz_set_ui (y, prime[i]);
check_all (want, x, y);
}
/* One old, one new each time. */
mpz_set_ui (want, prime[0]);
for (i = 1; i < numberof (prime); i++)
{
mpz_set (x, want);
mpz_set_ui (y, prime[i] * prime[i-1]);
mpz_mul_ui (want, want, prime[i]);
check_all (want, x, y);
}
/* Triplets with A,B in x and B,C in y. */
mpz_set_ui (want, 1L);
mpz_set_ui (x, 1L);
mpz_set_ui (y, 1L);
for (i = 0; i+2 < numberof (prime); i += 3)
{
mpz_mul_ui (want, want, prime[i]);
mpz_mul_ui (want, want, prime[i+1]);
mpz_mul_ui (want, want, prime[i+2]);
mpz_mul_ui (x, x, prime[i]);
mpz_mul_ui (x, x, prime[i+1]);
mpz_mul_ui (y, y, prime[i+1]);
mpz_mul_ui (y, y, prime[i+2]);
check_all (want, x, y);
}
mpz_clear (want);
mpz_clear (x);
mpz_clear (y);
}
int
main (int argc, char *argv[])
{
tests_start ();
check_primes ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,232 @@
/* Test mpz_limbs_* functions
Copyright 2013 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdlib.h>
#include <stdio.h>
#include "gmp-impl.h"
#include "tests.h"
#define COUNT 100
#define BITSIZE 500
/* Like mpz_add. For simplicity, support positive inputs only. */
static void
alt_add (mpz_ptr r, mpz_srcptr a, mpz_srcptr b)
{
mp_size_t an = mpz_size (a);
mp_size_t bn = mpz_size (b);
mp_ptr rp;
ASSERT (an > 0);
ASSERT (bn > 0);
if (an < bn)
{
MP_SIZE_T_SWAP (an, bn);
MPZ_SRCPTR_SWAP (a, b);
}
rp = mpz_limbs_modify (r, an + 1);
rp[an] = mpn_add (rp, mpz_limbs_read (a), an, mpz_limbs_read (b), bn);
mpz_limbs_finish (r, an + 1);
}
static void
check_funcs (const char *name,
void (*f)(mpz_ptr, mpz_srcptr, mpz_srcptr),
void (*ref_f)(mpz_ptr, mpz_srcptr, mpz_srcptr),
mpz_srcptr a, mpz_srcptr b)
{
mpz_t r, ref;
mpz_inits (r, ref, NULL);
ref_f (ref, a, b);
MPZ_CHECK_FORMAT (ref);
f (r, a, b);
MPZ_CHECK_FORMAT (r);
if (mpz_cmp (r, ref) != 0)
{
printf ("%s failed, abits %u, bbits %u\n",
name,
(unsigned) mpz_sizeinbase (a, 2),
(unsigned) mpz_sizeinbase (b, 2));
gmp_printf ("a = %Zx\n", a);
gmp_printf ("b = %Zx\n", b);
gmp_printf ("r = %Zx (bad)\n", r);
gmp_printf ("ref = %Zx\n", ref);
abort ();
}
mpz_clears (r, ref, NULL);
}
static void
check_add (void)
{
gmp_randstate_ptr rands = RANDS;
mpz_t bs, a, b;
unsigned i;
mpz_inits (bs, a, b, NULL);
for (i = 0; i < COUNT; i++)
{
mpz_urandomb (bs, rands, 32);
mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE);
mpz_urandomb (bs, rands, 32);
mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE);
check_funcs ("add", alt_add, mpz_add, a, b);
}
mpz_clears (bs, a, b, NULL);
}
static void
alt_mul (mpz_ptr r, mpz_srcptr a, mpz_srcptr b)
{
mp_size_t an = mpz_size (a);
mp_size_t bn = mpz_size (b);
mp_srcptr ap, bp;
TMP_DECL;
TMP_MARK;
ASSERT (an > 0);
ASSERT (bn > 0);
if (an < bn)
{
MP_SIZE_T_SWAP (an, bn);
MPZ_SRCPTR_SWAP (a, b);
}
/* NOTE: This copying seems unnecessary; better to allocate new
result area, and free the old area when done. */
if (r == a)
{
mp_ptr tp = TMP_ALLOC_LIMBS (an);
MPN_COPY (tp, mpz_limbs_read (a), an);
ap = tp;
bp = (a == b) ? ap : mpz_limbs_read (b);
}
else if (r == b)
{
mp_ptr tp = TMP_ALLOC_LIMBS (bn);
MPN_COPY (tp, mpz_limbs_read (b), bn);
bp = tp;
ap = mpz_limbs_read (a);
}
else
{
ap = mpz_limbs_read (a);
bp = mpz_limbs_read (b);
}
mpn_mul (mpz_limbs_write (r, an + bn),
ap, an, bp, bn);
mpz_limbs_finish (r, an + bn);
}
void
check_mul (void)
{
gmp_randstate_ptr rands = RANDS;
mpz_t bs, a, b;
unsigned i;
mpz_inits (bs, a, b, NULL);
for (i = 0; i < COUNT; i++)
{
mpz_urandomb (bs, rands, 32);
mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE);
mpz_urandomb (bs, rands, 32);
mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE);
check_funcs ("mul", alt_mul, mpz_mul, a, b);
}
mpz_clears (bs, a, b, NULL);
}
#define MAX_SIZE 100
static void
check_roinit (void)
{
gmp_randstate_ptr rands = RANDS;
mpz_t bs, a, b, r, ref;
unsigned i;
mpz_inits (bs, a, b, r, ref, NULL);
for (i = 0; i < COUNT; i++)
{
mp_srcptr ap, bp;
mp_size_t an, bn;
mpz_urandomb (bs, rands, 32);
mpz_rrandomb (a, rands, 1 + mpz_get_ui (bs) % BITSIZE);
mpz_urandomb (bs, rands, 32);
mpz_rrandomb (b, rands, 1 + mpz_get_ui (bs) % BITSIZE);
an = mpz_size (a);
ap = mpz_limbs_read (a);
bn = mpz_size (b);
bp = mpz_limbs_read (b);
mpz_add (ref, a, b);
{
mpz_t a1, b1;
#if __STDC_VERSION__ >= 199901
const mpz_t a2 = MPZ_ROINIT_N ( (mp_ptr) ap, an);
const mpz_t b2 = MPZ_ROINIT_N ( (mp_ptr) bp, bn);
mpz_set_ui (r, 0);
mpz_add (r, a2, b2);
if (mpz_cmp (r, ref) != 0)
{
printf ("MPZ_ROINIT_N failed\n");
gmp_printf ("a = %Zx\n", a);
gmp_printf ("b = %Zx\n", b);
gmp_printf ("r = %Zx (bad)\n", r);
gmp_printf ("ref = %Zx\n", ref);
abort ();
}
#endif
mpz_set_ui (r, 0);
mpz_add (r, mpz_roinit_n (a1, ap, an), mpz_roinit_n (b1, bp, bn));
if (mpz_cmp (r, ref) != 0)
{
printf ("mpz_roinit_n failed\n");
gmp_printf ("a = %Zx\n", a);
gmp_printf ("b = %Zx\n", b);
gmp_printf ("r = %Zx (bad)\n", r);
gmp_printf ("ref = %Zx\n", ref);
abort ();
}
}
}
mpz_clears (bs, a, b, r, ref, NULL);
}
int
main (int argc, char *argv[])
{
tests_start ();
tests_end ();
check_add ();
check_mul ();
check_roinit ();
return 0;
}

View File

@@ -0,0 +1,144 @@
/* Test mpz_powm, mpz_lucas_mod.
Copyright 1991, 1993, 1994, 1996, 1999-2001, 2009, 2012, 2018 Free Software
Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gmp-impl.h"
#include "tests.h"
void debug_mp (mpz_t, int);
#define SIZEM 8
/* FIXME: Should we implement another sequence to test lucas mod? */
/* Eg: a generalisation of what we use for Fibonacci: */
/* U_{2n-1} = U_n^2 - Q*U_{n-1}^2 */
/* U_{2n+1} = D*U_n^2 + Q*U_{2n-1} + 2*Q^n ; whith D = (P^2-4*Q) */
/* P*U_{2n} = U_{2n+1} + Q*U_{2n-1} */
int
main (int argc, char **argv)
{
mpz_t base, exp, mod;
mpz_t r1, r2, t1, t2;
mp_size_t exp_size, mod_size;
int i, res;
int reps = 1000;
long Q;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mpz_init (bs);
mpz_init (base);
mpz_init (exp);
mpz_init (mod);
mpz_init (r1);
mpz_init (r2);
mpz_init (t1);
mpz_init (t2);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % SIZEM + 1;
do /* Loop until base >= 2 and fits in a long. */
{
mpz_urandomb (base, rands, BITS_PER_ULONG - 2);
}
while (mpz_cmp_ui (base, 2) < 0 || mpz_fits_slong_p (base) == 0);
Q = mpz_get_ui (base);
do
{
++size_range;
size_range = MIN (size_range, SIZEM);
mpz_urandomb (bs, rands, size_range);
mod_size = mpz_get_ui (bs);
mpz_rrandomb (mod, rands, mod_size);
mpz_add_ui (mod, mod, 16);
}
while (mpz_gcd_ui (NULL, mod, Q) != 1);
mod_size = mpz_sizeinbase (mod, 2) - 3;
mpz_urandomb (bs, rands, 32);
exp_size = mpz_get_ui (bs) % mod_size + 2;
mpz_tdiv_q_2exp (exp, mod, exp_size);
mpz_add_ui (exp, exp, 1);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
{
mpz_neg (base, base);
Q = -Q;
}
res = mpz_lucas_mod (t1, r2, Q, exp_size, mod, t2, r1);
if (res && ++reps)
continue;
MPZ_CHECK_FORMAT (r2);
if (mpz_cmp_ui (r2, 0) < 0)
mpz_add (r2, r2, mod);
mpz_powm (r1, base, exp, mod);
if (mpz_cmp (r1, r2) != 0)
{
fprintf (stderr, "\nIncorrect results in test %d for operands:\n", i);
debug_mp (base, -16);
debug_mp (exp, -16);
debug_mp (mod, -16);
fprintf (stderr, "mpz_powm result:\n");
debug_mp (r1, -16);
fprintf (stderr, "mpz_lucas_mod result (%d) Q=%ld:\n", res, Q);
debug_mp (r2, -16);
abort ();
}
}
mpz_clear (bs);
mpz_clear (base);
mpz_clear (exp);
mpz_clear (mod);
mpz_clear (r1);
mpz_clear (r2);
mpz_clear (t1);
mpz_clear (t2);
tests_end ();
exit (0);
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,96 @@
/* Test mpz_lucnum_ui and mpz_lucnum2_ui.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Usage: t-lucnum_ui [n]
Test up to L[n], or if n is omitted then the default limit below. A
literal "x" for the limit means continue forever, this being meant only
for development. */
void
check_sequence (int argc, char *argv[])
{
unsigned long n;
unsigned long limit = 100 * GMP_LIMB_BITS;
mpz_t want_ln, want_ln1, got_ln, got_ln1;
if (argc > 1 && argv[1][0] == 'x')
limit = ULONG_MAX;
else
TESTS_REPS (limit, argv, argc);
/* start at n==0 */
mpz_init_set_si (want_ln1, -1); /* L[-1] */
mpz_init_set_ui (want_ln, 2); /* L[0] */
mpz_init (got_ln);
mpz_init (got_ln1);
for (n = 0; n < limit; n++)
{
mpz_lucnum2_ui (got_ln, got_ln1, n);
MPZ_CHECK_FORMAT (got_ln);
MPZ_CHECK_FORMAT (got_ln1);
if (mpz_cmp (got_ln, want_ln) != 0 || mpz_cmp (got_ln1, want_ln1) != 0)
{
printf ("mpz_lucnum2_ui(%lu) wrong\n", n);
mpz_trace ("want ln ", want_ln);
mpz_trace ("got ln ", got_ln);
mpz_trace ("want ln1", want_ln1);
mpz_trace ("got ln1", got_ln1);
abort ();
}
mpz_lucnum_ui (got_ln, n);
MPZ_CHECK_FORMAT (got_ln);
if (mpz_cmp (got_ln, want_ln) != 0)
{
printf ("mpz_lucnum_ui(%lu) wrong\n", n);
mpz_trace ("want ln", want_ln);
mpz_trace ("got ln", got_ln);
abort ();
}
mpz_add (want_ln1, want_ln1, want_ln); /* L[n+1] = L[n] + L[n-1] */
mpz_swap (want_ln1, want_ln);
}
mpz_clear (want_ln);
mpz_clear (want_ln1);
mpz_clear (got_ln);
mpz_clear (got_ln1);
}
int
main (int argc, char *argv[])
{
tests_start ();
mp_trace_base = -16;
check_sequence (argc, argv);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,135 @@
/* Exercise mpz_mfac_uiui.
Copyright 2000-2002, 2012 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Usage: t-mfac_uiui [x|num]
With no arguments testing goes up to the initial value of "limit" below.
With a number argument tests are carried that far, or with a literal "x"
tests are continued without limit (this being meant only for development
purposes). */
#define MULTIFAC_WHEEL (2*3*11)
#define MULTIFAC_WHEEL2 (5*13)
int
main (int argc, char *argv[])
{
mpz_t ref[MULTIFAC_WHEEL], ref2[MULTIFAC_WHEEL2], res;
unsigned long n, j, m, m2;
unsigned long limit = 2222, step = 1;
tests_start ();
if (argc > 1 && argv[1][0] == 'x')
limit = ULONG_MAX;
else
TESTS_REPS (limit, argv, argc);
/* for small limb testing */
limit = MIN (limit, MP_LIMB_T_MAX);
for (m = 0; m < MULTIFAC_WHEEL; m++)
mpz_init_set_ui(ref [m],1);
for (m2 = 0; m2 < MULTIFAC_WHEEL2; m2++)
mpz_init_set_ui(ref2 [m2],1);
mpz_init (res);
m = 0;
m2 = 0;
for (n = 0; n <= limit;)
{
mpz_mfac_uiui (res, n, MULTIFAC_WHEEL);
MPZ_CHECK_FORMAT (res);
if (mpz_cmp (ref[m], res) != 0)
{
printf ("mpz_mfac_uiui(%lu,%d) wrong\n", n, MULTIFAC_WHEEL);
printf (" got "); mpz_out_str (stdout, 10, res); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, ref[m]); printf("\n");
abort ();
}
mpz_mfac_uiui (res, n, MULTIFAC_WHEEL2);
MPZ_CHECK_FORMAT (res);
if (mpz_cmp (ref2[m2], res) != 0)
{
printf ("mpz_mfac_uiui(%lu,%d) wrong\n", n, MULTIFAC_WHEEL2);
printf (" got "); mpz_out_str (stdout, 10, res); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, ref2[m2]); printf("\n");
abort ();
}
if (n + step <= limit)
for (j = 0; j < step; j++) {
n++; m++; m2++;
if (m >= MULTIFAC_WHEEL) m -= MULTIFAC_WHEEL;
if (m2 >= MULTIFAC_WHEEL2) m2 -= MULTIFAC_WHEEL2;
mpz_mul_ui (ref[m], ref[m], n); /* Compute a reference, with current library */
mpz_mul_ui (ref2[m2], ref2[m2], n); /* Compute a reference, with current library */
}
else n += step;
}
mpz_fac_ui (ref[0], n);
mpz_mfac_uiui (res, n, 1);
MPZ_CHECK_FORMAT (res);
if (mpz_cmp (ref[0], res) != 0)
{
printf ("mpz_mfac_uiui(%lu,1) wrong\n", n);
printf (" got "); mpz_out_str (stdout, 10, res); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, ref[0]); printf("\n");
abort ();
}
mpz_2fac_ui (ref[0], n);
mpz_mfac_uiui (res, n, 2);
MPZ_CHECK_FORMAT (res);
if (mpz_cmp (ref[0], res) != 0)
{
printf ("mpz_mfac_uiui(%lu,1) wrong\n", n);
printf (" got "); mpz_out_str (stdout, 10, res); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, ref[0]); printf("\n");
abort ();
}
n++;
mpz_2fac_ui (ref[0], n);
mpz_mfac_uiui (res, n, 2);
MPZ_CHECK_FORMAT (res);
if (mpz_cmp (ref[0], res) != 0)
{
printf ("mpz_mfac_uiui(%lu,2) wrong\n", n);
printf (" got "); mpz_out_str (stdout, 10, res); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, ref[0]); printf("\n");
abort ();
}
for (m = 0; m < MULTIFAC_WHEEL; m++)
mpz_clear (ref[m]);
for (m2 = 0; m2 < MULTIFAC_WHEEL2; m2++)
mpz_clear (ref2[m2]);
mpz_clear (res);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,221 @@
/* Test mpz_cmp, mpz_mul.
Copyright 1991, 1993, 1994, 1996, 1997, 2000-2004 Free Software Foundation,
Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "longlong.h"
#include "tests.h"
void debug_mp (mpz_t);
static void refmpz_mul (mpz_t, const mpz_t, const mpz_t);
void dump_abort (int, const char *, mpz_t, mpz_t, mpz_t, mpz_t);
#define FFT_MIN_BITSIZE 100000
char *extra_fft;
void
one (int i, mpz_t multiplicand, mpz_t multiplier)
{
mpz_t product, ref_product;
mpz_init (product);
mpz_init (ref_product);
/* Test plain multiplication comparing results against reference code. */
mpz_mul (product, multiplier, multiplicand);
refmpz_mul (ref_product, multiplier, multiplicand);
if (mpz_cmp (product, ref_product))
dump_abort (i, "incorrect plain product",
multiplier, multiplicand, product, ref_product);
/* Test squaring, comparing results against plain multiplication */
mpz_mul (product, multiplier, multiplier);
mpz_set (multiplicand, multiplier);
mpz_mul (ref_product, multiplier, multiplicand);
if (mpz_cmp (product, ref_product))
dump_abort (i, "incorrect square product",
multiplier, multiplier, product, ref_product);
mpz_clear (product);
mpz_clear (ref_product);
}
int
main (int argc, char **argv)
{
mpz_t op1, op2;
int i;
int fft_max_2exp;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range, fsize_range;
tests_start ();
rands = RANDS;
extra_fft = getenv ("GMP_CHECK_FFT");
fft_max_2exp = 0;
if (extra_fft != NULL)
{
fft_max_2exp = atoi (extra_fft);
printf ("GMP_CHECK_FFT=%d (include this in bug reports)\n", fft_max_2exp);
}
if (fft_max_2exp <= 1) /* compat with old use of GMP_CHECK_FFT */
fft_max_2exp = 22; /* default limit, good for any machine */
mpz_init (bs);
mpz_init (op1);
mpz_init (op2);
fsize_range = 4 << 8; /* a fraction 1/256 of size_range */
for (i = 0;; i++)
{
size_range = fsize_range >> 8;
fsize_range = fsize_range * 33 / 32;
if (size_range > fft_max_2exp)
break;
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (op1, rands, mpz_get_ui (bs));
if (i & 1)
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (op2, rands, mpz_get_ui (bs));
mpz_urandomb (bs, rands, 4);
bsi = mpz_get_ui (bs);
if ((bsi & 0x3) == 0)
mpz_neg (op1, op1);
if ((bsi & 0xC) == 0)
mpz_neg (op2, op2);
/* printf ("%d %d\n", SIZ (op1), SIZ (op2)); */
one (i, op2, op1);
}
for (i = -50; i < 0; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % fft_max_2exp;
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (op1, rands, mpz_get_ui (bs) + FFT_MIN_BITSIZE);
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (op2, rands, mpz_get_ui (bs) + FFT_MIN_BITSIZE);
/* printf ("%d: %d %d\n", i, SIZ (op1), SIZ (op2)); */
fflush (stdout);
one (-1, op2, op1);
}
mpz_clear (bs);
mpz_clear (op1);
mpz_clear (op2);
tests_end ();
exit (0);
}
static void
refmpz_mul (mpz_t w, const mpz_t u, const mpz_t v)
{
mp_size_t usize = u->_mp_size;
mp_size_t vsize = v->_mp_size;
mp_size_t wsize;
mp_size_t sign_product;
mp_ptr up, vp;
mp_ptr wp;
mp_size_t talloc;
sign_product = usize ^ vsize;
usize = ABS (usize);
vsize = ABS (vsize);
if (usize == 0 || vsize == 0)
{
SIZ (w) = 0;
return;
}
talloc = usize + vsize;
up = u->_mp_d;
vp = v->_mp_d;
wp = __GMP_ALLOCATE_FUNC_LIMBS (talloc);
if (usize > vsize)
refmpn_mul (wp, up, usize, vp, vsize);
else
refmpn_mul (wp, vp, vsize, up, usize);
wsize = usize + vsize;
wsize -= wp[wsize - 1] == 0;
MPZ_REALLOC (w, wsize);
MPN_COPY (PTR(w), wp, wsize);
SIZ(w) = sign_product < 0 ? -wsize : wsize;
__GMP_FREE_FUNC_LIMBS (wp, talloc);
}
void
dump_abort (int i, const char *s,
mpz_t op1, mpz_t op2, mpz_t product, mpz_t ref_product)
{
mp_size_t b, e;
fprintf (stderr, "ERROR: %s in test %d\n", s, i);
fprintf (stderr, "op1 = "); debug_mp (op1);
fprintf (stderr, "op2 = "); debug_mp (op2);
fprintf (stderr, " product = "); debug_mp (product);
fprintf (stderr, "ref_product = "); debug_mp (ref_product);
for (b = 0; b < ABSIZ(ref_product); b++)
if (PTR(ref_product)[b] != PTR(product)[b])
break;
for (e = ABSIZ(ref_product) - 1; e >= 0; e--)
if (PTR(ref_product)[e] != PTR(product)[e])
break;
printf ("ERRORS in %ld--%ld\n", b, e);
abort();
}
void
debug_mp (mpz_t x)
{
size_t siz = mpz_sizeinbase (x, 16);
if (siz > 65)
{
mpz_t q;
mpz_init (q);
mpz_tdiv_q_2exp (q, x, 4 * (mpz_sizeinbase (x, 16) - 25));
gmp_fprintf (stderr, "%ZX...", q);
mpz_tdiv_r_2exp (q, x, 4 * 25);
gmp_fprintf (stderr, "%025ZX [%d]\n", q, (int) siz);
mpz_clear (q);
}
else
{
gmp_fprintf (stderr, "%ZX\n", x);
}
}

View File

@@ -0,0 +1,134 @@
/* Test mpz_mul_ui and mpz_mul_si.
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
mpz_t got, want, x;
void
compare_si (long y)
{
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_mul_si wrong\n");
mpz_trace (" x", x);
printf (" y=%ld (0x%lX)\n", y, y);
mpz_trace (" got ", got);
mpz_trace (" want", want);
abort ();
}
}
void
compare_ui (unsigned long y)
{
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_mul_ui wrong\n");
mpz_trace (" x", x);
printf (" y=%lu (0x%lX)\n", y, y);
mpz_trace (" got ", got);
mpz_trace (" want", want);
abort ();
}
}
void
check_samples (void)
{
{
long y;
mpz_set_ui (x, 1L);
y = 0;
mpz_mul_si (got, x, y);
mpz_set_si (want, y);
compare_si (y);
mpz_set_ui (x, 1L);
y = 1;
mpz_mul_si (got, x, y);
mpz_set_si (want, y);
compare_si (y);
mpz_set_ui (x, 1L);
y = -1;
mpz_mul_si (got, x, y);
mpz_set_si (want, y);
compare_si (y);
mpz_set_ui (x, 1L);
y = LONG_MIN;
mpz_mul_si (got, x, y);
mpz_set_si (want, y);
compare_si (y);
mpz_set_ui (x, 1L);
y = LONG_MAX;
mpz_mul_si (got, x, y);
mpz_set_si (want, y);
compare_si (y);
}
{
unsigned long y;
mpz_set_ui (x, 1L);
y = 0;
mpz_mul_ui (got, x, y);
mpz_set_ui (want, y);
compare_ui (y);
mpz_set_ui (x, 1L);
y = 1;
mpz_mul_ui (got, x, y);
mpz_set_ui (want, y);
compare_ui (y);
mpz_set_ui (x, 1L);
y = ULONG_MAX;
mpz_mul_ui (got, x, y);
mpz_set_ui (want, y);
compare_ui (y);
}
}
int
main (int argc, char **argv)
{
tests_start ();
mpz_init (x);
mpz_init (got);
mpz_init (want);
check_samples ();
mpz_clear (x);
mpz_clear (got);
mpz_clear (want);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,459 @@
/* Test mpz_nextprime.
Copyright 2009, 2015, 2018, 2020 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
refmpz_nextprime (mpz_ptr p, mpz_srcptr t)
{
mpz_add_ui (p, t, 1L);
while (! mpz_probab_prime_p (p, 10))
mpz_add_ui (p, p, 1L);
}
void
refmpz_prevprime (mpz_ptr p, mpz_srcptr t)
{
if (mpz_cmp_ui(t, 2) <= 0)
return;
mpz_sub_ui (p, t, 1L);
while (! mpz_probab_prime_p (p, 10))
mpz_sub_ui (p, p, 1L);
}
void
test_largegap (mpz_t low, const int gap)
{
mpz_t t, nxt;
mpz_init (t);
mpz_init (nxt);
mpz_nextprime(nxt, low);
mpz_sub(t, nxt, low);
if (mpz_cmp_ui(t, gap) != 0)
{
gmp_printf ("nextprime gap %Zd => %Zd != %d\n", low, nxt, gap);
abort ();
}
mpz_prevprime(t, nxt);
if (mpz_cmp(t, low) != 0)
{
gmp_printf ("prevprime gap %Zd => %Zd != %d\n", nxt, t, gap);
abort ();
}
mpz_clear (t);
mpz_clear (nxt);
}
void
test_largegaps ()
{
mpz_t n;
mpz_init (n);
// largest gap with start < 2^32.
mpz_set_str (n, "3842610773", 10);
test_largegap (n, 336);
// largest gap with start < 2^64.
mpz_set_str (n, "18361375334787046697", 10);
test_largegap (n, 1550);
// test high merit primegap in the P30 digit range.
mpz_set_str (n, "3001549619028223830552751967", 10);
test_largegap (n, 2184);
// test high merit primegap in the P100 range.
mpz_primorial_ui (n, 257);
mpz_divexact_ui (n, n, 5610);
mpz_mul_ui (n, n, 4280516017UL);
mpz_sub_ui (n, n, 2560);
test_largegap (n, 9006);
// test high merit primegap in the P200 range.
mpz_primorial_ui (n, 409);
mpz_divexact_ui (n, n, 30);
mpz_mul_ui (n, n, 3483347771UL);
mpz_sub_ui (n, n, 7016);
test_largegap (n, 15900);
mpz_clear (n);
}
void
test_bitboundaries ()
{
mpz_t n;
mpz_init (n);
mpz_set_str (n, "0xfff1", 0);
test_largegap (n, 16);
mpz_set_str (n, "0xfffffffb", 0);
test_largegap (n, 20);
mpz_set_str (n, "0xffffffffffc5", 0);
test_largegap (n, 80);
mpz_set_str (n, "0xffffffffffffffc5", 0);
test_largegap (n, 72);
mpz_set_str (n, "0xffffffffffffffffffbf", 0);
test_largegap (n, 78);
mpz_set_str (n, "0xffffffffffffffffffffffef", 0);
test_largegap (n, 78);
mpz_set_str (n, "0xffffffffffffffffffffffffffb5", 0);
test_largegap (n, 100);
mpz_set_str (n, "0xffffffffffffffffffffffffffffff61", 0);
test_largegap (n, 210);
mpz_set_str (n, "0xffffffffffffffffffffffffffffffffffffffffffffff13", 0);
test_largegap (n, 370);
mpz_clear (n);
}
void
run (const char *start, int reps, const char *end, short diffs[])
{
mpz_t x, y;
int i;
mpz_init_set_str (x, start, 0);
mpz_init (y);
for (i = 0; i < reps; i++)
{
mpz_nextprime (y, x);
mpz_sub (x, y, x);
if (diffs != NULL &&
(! mpz_fits_sshort_p (x) || diffs[i] != (short) mpz_get_ui (x)))
{
gmp_printf ("diff list discrepancy\n");
abort ();
}
mpz_swap (x, y);
}
mpz_set_str (y, end, 0);
if (mpz_cmp (x, y) != 0)
{
gmp_printf ("got %Zd\n", x);
gmp_printf ("want %Zd\n", y);
abort ();
}
mpz_clear (y);
mpz_clear (x);
}
void
run_p (const char *start, int reps, const char *end, short diffs[])
{
mpz_t x, y;
int i;
mpz_init_set_str (x, end, 0);
mpz_init (y);
// Last rep doesn't share same data with nextprime
for (i = 0; i < reps - 1; i++)
{
mpz_prevprime (y, x);
mpz_sub (x, x, y);
if (diffs != NULL &&
(! mpz_fits_sshort_p (x) || diffs[reps - i - 1] != (short) mpz_get_ui (x)))
{
gmp_printf ("diff list discrepancy %Zd, %d vs %d\n",
y, diffs[i], mpz_get_ui (x));
abort ();
}
mpz_swap (x, y);
}
// starts aren't always prime, so check that result is less than or equal
mpz_prevprime(x, x);
mpz_set_str(y, start, 0);
if (mpz_cmp (x, y) > 0)
{
gmp_printf ("got %Zd\n", x);
gmp_printf ("want %Zd\n", y);
abort ();
}
mpz_clear (y);
mpz_clear (x);
}
extern short diff1[];
extern short diff3[];
extern short diff4[];
extern short diff5[];
extern short diff6[];
void
test_ref (gmp_randstate_ptr rands, int reps,
void (*func)(mpz_t, const mpz_t),
void(*ref_func)(mpz_t, const mpz_t))
{
int i;
mpz_t bs, x, test_p, ref_p;
unsigned long size_range;
mpz_init (bs);
mpz_init (x);
mpz_init (test_p);
mpz_init (ref_p);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 8 + 2; /* 0..1024 bit operands */
mpz_urandomb (bs, rands, size_range);
mpz_rrandomb (x, rands, mpz_get_ui (bs));
func (test_p, x);
ref_func (ref_p, x);
if (mpz_cmp (test_p, ref_p) != 0)
{
gmp_printf ("start %Zd\n", x);
gmp_printf ("got %Zd\n", test_p);
gmp_printf ("want %Zd\n", ref_p);
abort ();
}
}
mpz_clear (bs);
mpz_clear (x);
mpz_clear (test_p);
mpz_clear (ref_p);
}
void
test_nextprime(gmp_randstate_ptr rands, int reps)
{
run ("2", 1000, "0x1ef7", diff1);
run ("3", 1000 - 1, "0x1ef7", NULL);
run ("0x8a43866f5776ccd5b02186e90d28946aeb0ed914", 50,
"0x8a43866f5776ccd5b02186e90d28946aeb0eeec5", diff3);
run ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C", 50, /* 2^148 - 148 */
"0x100000000000000000000000000000000010ab", diff4);
run ("0x1c2c26be55317530311facb648ea06b359b969715db83292ab8cf898d8b1b", 50,
"0x1c2c26be55317530311facb648ea06b359b969715db83292ab8cf898da957", diff5);
run ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80", 50, /* 2^128 - 128 */
"0x10000000000000000000000000000155B", diff6);
test_ref(
rands, reps,
(void (*)(mpz_t, const mpz_t)) mpz_nextprime,
refmpz_nextprime);
}
void
test_prevprime (gmp_randstate_ptr rands, int reps)
{
long i;
int retval;
mpz_t n, prvp;
mpz_init (n);
mpz_init (prvp);
/* Test mpz_prevprime(n <= 2) returns 0, leaves rop unchanged. */
{
int temp = 123;
mpz_set_ui (prvp, temp);
for (i = 0; i <= 2; i++)
{
mpz_set_si(n, i);
retval = mpz_prevprime (prvp, n);
if ( retval != 0 || mpz_cmp_ui (prvp, temp) != 0 )
{
gmp_printf ("mpz_prevprime(%Zd) return (%d) rop (%Zd)\n", n, retval, prvp);
abort ();
}
}
}
mpz_clear (n);
mpz_clear (prvp);
run_p ("2", 1000, "0x1ef7", diff1);
run_p ("3", 1000 - 1, "0x1ef7", NULL);
run_p ("0x8a43866f5776ccd5b02186e90d28946aeb0ed914", 50,
"0x8a43866f5776ccd5b02186e90d28946aeb0eeec5", diff3);
run_p ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C", 50, /* 2^148 - 148 */
"0x100000000000000000000000000000000010ab", diff4);
run_p ("0x1c2c26be55317530311facb648ea06b359b969715db83292ab8cf898d8b1b", 50,
"0x1c2c26be55317530311facb648ea06b359b969715db83292ab8cf898da957", diff5);
run_p ("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80", 50, /* 2^128 - 128 */
"0x10000000000000000000000000000155B", diff6);
// Cast away int return from mpz_prevprime for test ref.
test_ref(
rands, reps,
(void (*)(mpz_t, const mpz_t)) mpz_prevprime,
refmpz_prevprime);
}
int
main (int argc, char **argv)
{
gmp_randstate_ptr rands;
int reps = 20;
tests_start();
rands = RANDS;
TESTS_REPS (reps, argv, argc);
test_nextprime(rands, reps);
test_prevprime(rands, reps);
test_largegaps ();
test_bitboundaries ();
tests_end ();
return 0;
}
short diff1[] =
{
1,2,2,4,2,4,2,4,6,2,6,4,2,4,6,6,
2,6,4,2,6,4,6,8,4,2,4,2,4,14,4,6,
2,10,2,6,6,4,6,6,2,10,2,4,2,12,12,4,
2,4,6,2,10,6,6,6,2,6,4,2,10,14,4,2,
4,14,6,10,2,4,6,8,6,6,4,6,8,4,8,10,
2,10,2,6,4,6,8,4,2,4,12,8,4,8,4,6,
12,2,18,6,10,6,6,2,6,10,6,6,2,6,6,4,
2,12,10,2,4,6,6,2,12,4,6,8,10,8,10,8,
6,6,4,8,6,4,8,4,14,10,12,2,10,2,4,2,
10,14,4,2,4,14,4,2,4,20,4,8,10,8,4,6,
6,14,4,6,6,8,6,12,4,6,2,10,2,6,10,2,
10,2,6,18,4,2,4,6,6,8,6,6,22,2,10,8,
10,6,6,8,12,4,6,6,2,6,12,10,18,2,4,6,
2,6,4,2,4,12,2,6,34,6,6,8,18,10,14,4,
2,4,6,8,4,2,6,12,10,2,4,2,4,6,12,12,
8,12,6,4,6,8,4,8,4,14,4,6,2,4,6,2,
6,10,20,6,4,2,24,4,2,10,12,2,10,8,6,6,
6,18,6,4,2,12,10,12,8,16,14,6,4,2,4,2,
10,12,6,6,18,2,16,2,22,6,8,6,4,2,4,8,
6,10,2,10,14,10,6,12,2,4,2,10,12,2,16,2,
6,4,2,10,8,18,24,4,6,8,16,2,4,8,16,2,
4,8,6,6,4,12,2,22,6,2,6,4,6,14,6,4,
2,6,4,6,12,6,6,14,4,6,12,8,6,4,26,18,
10,8,4,6,2,6,22,12,2,16,8,4,12,14,10,2,
4,8,6,6,4,2,4,6,8,4,2,6,10,2,10,8,
4,14,10,12,2,6,4,2,16,14,4,6,8,6,4,18,
8,10,6,6,8,10,12,14,4,6,6,2,28,2,10,8,
4,14,4,8,12,6,12,4,6,20,10,2,16,26,4,2,
12,6,4,12,6,8,4,8,22,2,4,2,12,28,2,6,
6,6,4,6,2,12,4,12,2,10,2,16,2,16,6,20,
16,8,4,2,4,2,22,8,12,6,10,2,4,6,2,6,
10,2,12,10,2,10,14,6,4,6,8,6,6,16,12,2,
4,14,6,4,8,10,8,6,6,22,6,2,10,14,4,6,
18,2,10,14,4,2,10,14,4,8,18,4,6,2,4,6,
2,12,4,20,22,12,2,4,6,6,2,6,22,2,6,16,
6,12,2,6,12,16,2,4,6,14,4,2,18,24,10,6,
2,10,2,10,2,10,6,2,10,2,10,6,8,30,10,2,
10,8,6,10,18,6,12,12,2,18,6,4,6,6,18,2,
10,14,6,4,2,4,24,2,12,6,16,8,6,6,18,16,
2,4,6,2,6,6,10,6,12,12,18,2,6,4,18,8,
24,4,2,4,6,2,12,4,14,30,10,6,12,14,6,10,
12,2,4,6,8,6,10,2,4,14,6,6,4,6,2,10,
2,16,12,8,18,4,6,12,2,6,6,6,28,6,14,4,
8,10,8,12,18,4,2,4,24,12,6,2,16,6,6,14,
10,14,4,30,6,6,6,8,6,4,2,12,6,4,2,6,
22,6,2,4,18,2,4,12,2,6,4,26,6,6,4,8,
10,32,16,2,6,4,2,4,2,10,14,6,4,8,10,6,
20,4,2,6,30,4,8,10,6,6,8,6,12,4,6,2,
6,4,6,2,10,2,16,6,20,4,12,14,28,6,20,4,
18,8,6,4,6,14,6,6,10,2,10,12,8,10,2,10,
8,12,10,24,2,4,8,6,4,8,18,10,6,6,2,6,
10,12,2,10,6,6,6,8,6,10,6,2,6,6,6,10,
8,24,6,22,2,18,4,8,10,30,8,18,4,2,10,6,
2,6,4,18,8,12,18,16,6,2,12,6,10,2,10,2,
6,10,14,4,24,2,16,2,10,2,10,20,4,2,4,8,
16,6,6,2,12,16,8,4,6,30,2,10,2,6,4,6,
6,8,6,4,12,6,8,12,4,14,12,10,24,6,12,6,
2,22,8,18,10,6,14,4,2,6,10,8,6,4,6,30,
14,10,2,12,10,2,16,2,18,24,18,6,16,18,6,2,
18,4,6,2,10,8,10,6,6,8,4,6,2,10,2,12,
4,6,6,2,12,4,14,18,4,6,20,4,8,6,4,8,
4,14,6,4,14,12,4,2,30,4,24,6,6,12,12,14,
6,4,2,4,18,6,12,8
};
short diff3[] =
{
33,32,136,116,24,22,104,114,76,278,238,162,36,44,388,134,
130,26,312,42,138,28,24,80,138,108,270,12,330,130,98,102,
162,34,36,170,90,34,14,6,24,66,154,218,70,132,188,88,
80,82
};
short diff4[] =
{
239,92,64,6,104,24,46,258,68,18,54,100,68,154,26,4,
38,142,168,42,18,26,286,104,136,116,40,2,28,110,52,78,
104,24,54,96,4,626,196,24,56,36,52,102,48,156,26,18,
42,40
};
short diff5[] =
{
268,120,320,184,396,2,94,108,20,318,274,14,64,122,220,108,
18,174,6,24,348,32,64,116,268,162,20,156,28,110,52,428,
196,14,262,30,194,120,300,66,268,12,428,370,212,198,192,130,
30,80
};
short diff6[] =
{
179,30,84,108,112,36,42,110,52,132,60,30,326,114,496,92,100,
272,36,54,90,4,2,24,40,398,150,72,60,16,8,4,80,16,2,342,112,
14,136,236,40,18,50,192,198,204,40,266,42,274
};

View File

@@ -0,0 +1,87 @@
/* Test mpz_odd_p and mpz_even_p.
Copyright 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_data (void)
{
static const struct {
const char *n;
int odd, even;
} data[] = {
{ "0", 0, 1 },
{ "1", 1, 0 },
{ "2", 0, 1 },
{ "3", 1, 0 },
{ "4", 0, 1 },
{ "-4", 0, 1 },
{ "-3", 1, 0 },
{ "-2", 0, 1 },
{ "-1", 1, 0 },
{ "0x1000000000000000000000000000000000000000000000000000", 0, 1 },
{ "0x1000000000000000000000000000000000000000000000000001", 1, 0 },
{ "0x1000000000000000000000000000000000000000000000000002", 0, 1 },
{ "0x1000000000000000000000000000000000000000000000000003", 1, 0 },
{ "-0x1000000000000000000000000000000000000000000000000004", 0, 1 },
{ "-0x1000000000000000000000000000000000000000000000000003", 1, 0 },
{ "-0x1000000000000000000000000000000000000000000000000002", 0, 1 },
{ "-0x1000000000000000000000000000000000000000000000000001", 1, 0 },
};
mpz_t n;
int i;
mpz_init (n);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (n, data[i].n, 0);
if ((mpz_odd_p (n) != 0) != data[i].odd)
{
printf ("mpz_odd_p wrong on data[%d]\n", i);
abort();
}
if ((mpz_even_p (n) != 0) != data[i].even)
{
printf ("mpz_even_p wrong on data[%d]\n", i);
abort();
}
}
mpz_clear (n);
}
int
main (void)
{
tests_start ();
check_data ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,247 @@
/* Test mpz_perfect_power_p.
Contributed to the GNU project by Torbjorn Granlund and Martin Boij.
Copyright 2008-2010, 2014 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
struct
{
const char *num_as_str;
char want;
} static tests[] =
{
{ "0", 1},
{ "1", 1},
{"-1", 1},
{ "2", 0},
{"-2", 0},
{ "3", 0},
{"-3", 0},
{ "4", 1},
{"-4", 0},
{ "64", 1},
{"-64", 1},
{ "128", 1},
{"-128", 1},
{ "256", 1},
{"-256", 0},
{ "512", 1},
{"-512", 1},
{ "0x4000000", 1},
{"-0x4000000", 1},
{ "0x3cab640", 1},
{"-0x3cab640", 0},
{ "0x3e23840", 1},
{"-0x3e23840", 0},
{ "0x3d3a7ed1", 1},
{"-0x3d3a7ed1", 1},
{ "0x30a7a6000", 1},
{"-0x30a7a6000", 1},
{ "0xf33e5a5a59", 1},
{"-0xf33e5a5a59", 0},
{ "0xed1b1182118135d", 1},
{"-0xed1b1182118135d", 1},
{ "0xe71f6eb7689cc276b2f1", 1},
{"-0xe71f6eb7689cc276b2f1", 0},
{ "0x12644507fe78cf563a4b342c92e7da9fe5e99cb75a01", 1},
{"-0x12644507fe78cf563a4b342c92e7da9fe5e99cb75a01", 0},
{ "0x1ff2e7c581bb0951df644885bd33f50e472b0b73a204e13cbe98fdb424d66561e4000000", 1},
{"-0x1ff2e7c581bb0951df644885bd33f50e472b0b73a204e13cbe98fdb424d66561e4000000", 1},
{ "0x2b9b44db2d91a6f8165c8c7339ef73633228ea29e388592e80354e4380004aad84000000", 1},
{"-0x2b9b44db2d91a6f8165c8c7339ef73633228ea29e388592e80354e4380004aad84000000", 1},
{ "0x28d5a2b8f330910a9d3cda06036ae0546442e5b1a83b26a436efea5b727bf1bcbe7e12b47d81", 1},
{"-0x28d5a2b8f330910a9d3cda06036ae0546442e5b1a83b26a436efea5b727bf1bcbe7e12b47d81", 1},
{NULL, 0}
};
void
check_tests ()
{
mpz_t x;
int i;
int got, want;
mpz_init (x);
for (i = 0; tests[i].num_as_str != NULL; i++)
{
mpz_set_str (x, tests[i].num_as_str, 0);
got = mpz_perfect_power_p (x);
want = tests[i].want;
if (got != want)
{
fprintf (stderr, "mpz_perfect_power_p returns %d when %d was expected\n", got, want);
fprintf (stderr, "fault operand: %s\n", tests[i].num_as_str);
abort ();
}
}
mpz_clear (x);
}
#define NRP 15
void
check_random (int reps)
{
mpz_t n, np, temp, primes[NRP];
int i, j, k, unique, destroy, res;
unsigned long int nrprimes, primebits;
mp_limb_t g, exp[NRP], e;
gmp_randstate_ptr rands;
rands = RANDS;
mpz_init (n);
mpz_init (np);
mpz_init (temp);
for (i = 0; i < NRP; i++)
mpz_init (primes[i]);
for (i = 0; i < reps; i++)
{
mpz_urandomb (np, rands, 32);
nrprimes = mpz_get_ui (np) % NRP + 1; /* 1-NRP unique primes */
mpz_urandomb (np, rands, 32);
g = mpz_get_ui (np) % 32 + 2; /* gcd 2-33 */
for (j = 0; j < nrprimes;)
{
mpz_urandomb (np, rands, 32);
primebits = mpz_get_ui (np) % 100 + 3; /* 3-102 bit primes */
mpz_urandomb (primes[j], rands, primebits);
mpz_nextprime (primes[j], primes[j]);
unique = 1;
for (k = 0; k < j; k++)
{
if (mpz_cmp (primes[j], primes[k]) == 0)
{
unique = 0;
break;
}
}
if (unique)
{
mpz_urandomb (np, rands, 32);
e = 371 / (10 * primebits) + mpz_get_ui (np) % 11 + 1; /* Magic constants */
exp[j++] = g * e;
}
}
if (nrprimes > 1)
{
/* Destroy d exponents, d in [1, nrprimes - 1] */
if (nrprimes == 2)
{
destroy = 1;
}
else
{
mpz_urandomb (np, rands, 32);
destroy = mpz_get_ui (np) % (nrprimes - 2);
}
g = exp[destroy];
for (k = destroy + 1; k < nrprimes; k++)
g = mpn_gcd_1 (&g, 1, exp[k]);
for (j = 0; j < destroy; j++)
{
mpz_urandomb (np, rands, 32);
e = mpz_get_ui (np) % 50 + 1;
while (mpn_gcd_1 (&g, 1, e) > 1)
e++;
exp[j] = e;
}
}
/* Compute n */
mpz_pow_ui (n, primes[0], exp[0]);
for (j = 1; j < nrprimes; j++)
{
mpz_pow_ui (temp, primes[j], exp[j]);
mpz_mul (n, n, temp);
}
res = mpz_perfect_power_p (n);
if (nrprimes == 1)
{
if (res == 0 && exp[0] > 1)
{
printf("n is a perfect power, perfpow_p disagrees\n");
gmp_printf("n = %Zu\nprimes[0] = %Zu\nexp[0] = %lu\n", n, primes[0], exp[0]);
abort ();
}
else if (res == 1 && exp[0] == 1)
{
gmp_printf("n = %Zu\n", n);
printf("n is now a prime number, but perfpow_p still believes n is a perfect power\n");
abort ();
}
}
else
{
if (res == 1 && destroy != 0)
{
gmp_printf("n = %Zu\nn was destroyed, but perfpow_p still believes n is a perfect power\n", n);
abort ();
}
else if (res == 0 && destroy == 0)
{
gmp_printf("n = %Zu\nn is a perfect power, perfpow_p disagrees\n", n);
abort ();
}
}
}
mpz_clear (n);
mpz_clear (np);
mpz_clear (temp);
for (i = 0; i < NRP; i++)
mpz_clear (primes[i]);
}
int
main (int argc, char **argv)
{
int n_tests;
tests_start ();
mp_trace_base = -16;
check_tests ();
n_tests = 500;
if (argc == 2)
n_tests = atoi (argv[1]);
check_random (n_tests);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,154 @@
/* Test mpz_perfect_square_p.
Copyright 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
#include "mpn/perfsqr.h"
/* check_modulo() exercises mpz_perfect_square_p on squares which cover each
possible quadratic residue to each divisor used within
mpn_perfect_square_p, ensuring those residues aren't incorrectly claimed
to be non-residues.
Each divisor is taken separately. It's arranged that n is congruent to 0
modulo the other divisors, 0 of course being a quadratic residue to any
modulus.
The values "(j*others)^2" cover all quadratic residues mod divisor[i],
but in no particular order. j is run from 1<=j<=divisor[i] so that zero
is excluded. A literal n==0 doesn't reach the residue tests. */
void
check_modulo (void)
{
static const unsigned long divisor[] = PERFSQR_DIVISORS;
unsigned long i, j;
mpz_t alldiv, others, n;
mpz_init (alldiv);
mpz_init (others);
mpz_init (n);
/* product of all divisors */
mpz_set_ui (alldiv, 1L);
for (i = 0; i < numberof (divisor); i++)
mpz_mul_ui (alldiv, alldiv, divisor[i]);
for (i = 0; i < numberof (divisor); i++)
{
/* product of all divisors except i */
mpz_set_ui (others, 1L);
for (j = 0; j < numberof (divisor); j++)
if (i != j)
mpz_mul_ui (others, others, divisor[j]);
for (j = 1; j <= divisor[i]; j++)
{
/* square */
mpz_mul_ui (n, others, j);
mpz_mul (n, n, n);
if (! mpz_perfect_square_p (n))
{
printf ("mpz_perfect_square_p got 0, want 1\n");
mpz_trace (" n", n);
abort ();
}
}
}
mpz_clear (alldiv);
mpz_clear (others);
mpz_clear (n);
}
/* Exercise mpz_perfect_square_p compared to what mpz_sqrt says. */
void
check_sqrt (int reps)
{
mpz_t x2, x2t, x;
mp_size_t x2n;
int res;
int i;
/* int cnt = 0; */
gmp_randstate_ptr rands = RANDS;
mpz_t bs;
mpz_init (bs);
mpz_init (x2);
mpz_init (x);
mpz_init (x2t);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 9);
x2n = mpz_get_ui (bs);
mpz_rrandomb (x2, rands, x2n);
/* mpz_out_str (stdout, -16, x2); puts (""); */
res = mpz_perfect_square_p (x2);
mpz_sqrt (x, x2);
mpz_mul (x2t, x, x);
if (res != (mpz_cmp (x2, x2t) == 0))
{
printf ("mpz_perfect_square_p and mpz_sqrt differ\n");
mpz_trace (" x ", x);
mpz_trace (" x2 ", x2);
mpz_trace (" x2t", x2t);
printf (" mpz_perfect_square_p %d\n", res);
printf (" mpz_sqrt %d\n", mpz_cmp (x2, x2t) == 0);
abort ();
}
/* cnt += res != 0; */
}
/* printf ("%d/%d perfect squares\n", cnt, reps); */
mpz_clear (bs);
mpz_clear (x2);
mpz_clear (x);
mpz_clear (x2t);
}
int
main (int argc, char **argv)
{
int reps = 200000;
tests_start ();
mp_trace_base = -16;
if (argc == 2)
reps = atoi (argv[1]);
check_modulo ();
check_sqrt (reps);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,167 @@
/* Test mpz_popcount.
Copyright 2001, 2005 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_onebit (void)
{
mpz_t n;
unsigned long i, got;
mpz_init (n);
for (i = 0; i < 5 * GMP_LIMB_BITS; i++)
{
mpz_setbit (n, i);
got = mpz_popcount (n);
if (got != 1)
{
printf ("mpz_popcount wrong on single bit at %lu\n", i);
printf (" got %lu, want 1\n", got);
abort();
}
mpz_clrbit (n, i);
}
mpz_clear (n);
}
void
check_data (void)
{
static const struct {
const char *n;
unsigned long want;
} data[] = {
{ "-1", ~ (unsigned long) 0 },
{ "-12345678", ~ (unsigned long) 0 },
{ "0", 0 },
{ "1", 1 },
{ "3", 2 },
{ "5", 2 },
{ "0xFFFF", 16 },
{ "0xFFFFFFFF", 32 },
{ "0xFFFFFFFFFFFFFFFF", 64 },
{ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 128 },
};
unsigned long got;
int i;
mpz_t n;
mpz_init (n);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (n, data[i].n, 0);
got = mpz_popcount (n);
if (got != data[i].want)
{
printf ("mpz_popcount wrong at data[%d]\n", i);
printf (" n \"%s\"\n", data[i].n);
printf (" "); mpz_out_str (stdout, 10, n); printf ("\n");
printf (" 0x"); mpz_out_str (stdout, 16, n); printf ("\n");
printf (" got %lu\n", got);
printf (" want %lu\n", data[i].want);
abort ();
}
}
mpz_clear (n);
}
unsigned long
refmpz_popcount (mpz_t arg)
{
mp_size_t n, i;
unsigned long cnt;
mp_limb_t x;
n = SIZ(arg);
if (n < 0)
return ~(unsigned long) 0;
cnt = 0;
for (i = 0; i < n; i++)
{
x = PTR(arg)[i];
while (x != 0)
{
cnt += (x & 1);
x >>= 1;
}
}
return cnt;
}
void
check_random (void)
{
gmp_randstate_ptr rands;
mpz_t bs;
mpz_t arg;
unsigned long arg_size, size_range;
unsigned long got, ref;
int i;
rands = RANDS;
mpz_init (bs);
mpz_init (arg);
for (i = 0; i < 10000; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 11 + 2; /* 0..4096 bit operands */
mpz_urandomb (bs, rands, size_range);
arg_size = mpz_get_ui (bs);
mpz_rrandomb (arg, rands, arg_size);
got = mpz_popcount (arg);
ref = refmpz_popcount (arg);
if (got != ref)
{
printf ("mpz_popcount wrong on random\n");
printf (" "); mpz_out_str (stdout, 10, arg); printf ("\n");
printf (" 0x"); mpz_out_str (stdout, 16, arg); printf ("\n");
printf (" got %lu\n", got);
printf (" want %lu\n", ref);
abort ();
}
}
mpz_clear (arg);
mpz_clear (bs);
}
int
main (void)
{
tests_start ();
check_onebit ();
check_data ();
check_random ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,217 @@
/* Test mpz_pow_ui and mpz_ui_pow_ui.
Copyright 1997, 1999-2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_one (mpz_srcptr want, mpz_srcptr base, unsigned long exp)
{
mpz_t got;
mpz_init (got);
MPZ_CHECK_FORMAT (want);
mpz_pow_ui (got, base, exp);
if (mpz_cmp (got, want))
{
printf ("mpz_pow_ui wrong\n");
mpz_trace (" base", base);
printf (" exp = %lu (0x%lX)\n", exp, exp);
mpz_trace (" got ", got);
mpz_trace (" want", want);
abort ();
}
mpz_set (got, base);
mpz_pow_ui (got, got, exp);
if (mpz_cmp (got, want))
{
printf ("mpz_pow_ui wrong\n");
mpz_trace (" base", base);
printf (" exp = %lu (0x%lX)\n", exp, exp);
mpz_trace (" got ", got);
mpz_trace (" want", want);
abort ();
}
if (mpz_fits_ulong_p (base))
{
unsigned long base_u = mpz_get_ui (base);
mpz_ui_pow_ui (got, base_u, exp);
if (mpz_cmp (got, want))
{
printf ("mpz_ui_pow_ui wrong\n");
printf (" base=%lu (0x%lX)\n", base_u, base_u);
printf (" exp = %lu (0x%lX)\n", exp, exp);
mpz_trace (" got ", got);
mpz_trace (" want", want);
abort ();
}
}
mpz_clear (got);
}
void
check_base (mpz_srcptr base)
{
unsigned long exp;
mpz_t want;
mpz_init (want);
mpz_set_ui (want, 1L);
for (exp = 0; exp < 20; exp++)
{
check_one (want, base, exp);
mpz_mul (want, want, base);
}
mpz_clear (want);
}
void
check_various (void)
{
static const struct {
const char *base;
} data[] = {
{ "0" },
{ "1" },
{ "2" },
{ "3" },
{ "4" },
{ "5" },
{ "6" },
{ "10" },
{ "15" },
{ "16" },
{ "0x1F" },
{ "0xFF" },
{ "0x1001" },
{ "0xFFFF" },
{ "0x10000001" },
{ "0x1000000000000001" },
/* actual size closest to estimate */
{ "0xFFFFFFFF" },
{ "0xFFFFFFFFFFFFFFFF" },
/* same after rshift */
{ "0xFFFFFFFF0" },
{ "0xFFFFFFFF00" },
{ "0xFFFFFFFFFFFFFFFF0" },
{ "0xFFFFFFFFFFFFFFFF00" },
/* change from 2 limbs to 1 after rshift */
{ "0x180000000" },
{ "0x18000000000000000" },
/* change from 3 limbs to 2 after rshift */
{ "0x18000000100000000" },
{ "0x180000000000000010000000000000000" },
/* handling of absolute value */
{ "-0x80000000" },
{ "-0x8000000000000000" },
/* low zero limb, and size>2, checking argument overlap detection */
{ "0x3000000000000000300000000000000030000000000000000" },
};
mpz_t base;
int i;
mpz_init (base);
for (i = 0; i < numberof (data); i++)
{
mpz_set_str_or_abort (base, data[i].base, 0);
check_base (base);
}
mpz_clear (base);
}
void
check_random (int reps)
{
mpz_t base, want;
mp_size_t base_size;
int i;
unsigned long size_range, exp;
gmp_randstate_ptr rands = RANDS;
mpz_init (base);
mpz_init (want);
for (i = 0; i < reps; i++)
{
/* exponentially random 0 to 2^13 bits for base */
mpz_urandomb (want, rands, 32);
size_range = mpz_get_ui (want) % 12 + 2;
mpz_urandomb (want, rands, size_range);
base_size = mpz_get_ui (want);
mpz_rrandomb (base, rands, base_size);
/* randomly signed base */
mpz_urandomb (want, rands, 2);
if ((mpz_get_ui (want) & 1) != 0)
mpz_neg (base, base);
/* random 5 bits for exponent */
mpz_urandomb (want, rands, 5L);
exp = mpz_get_ui (want);
refmpz_pow_ui (want, base, exp);
check_one (want, base, exp);
}
mpz_clear (base);
mpz_clear (want);
}
int
main (int argc, char **argv)
{
int reps = 5000;
/* dummy call to drag in refmpn.o for testing mpz/n_pow_ui.c with
refmpn_mul_2 */
refmpn_zero_p (NULL, (mp_size_t) 0);
tests_start ();
mp_trace_base = -16;
if (argc == 2)
reps = atoi (argv[1]);
check_various ();
check_random (reps);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,263 @@
/* Test mpz_powm, mpz_mul, mpz_mod, mpz_mod_ui, mpz_div_ui.
Copyright 1991, 1993, 1994, 1996, 1999-2001, 2009, 2012, 2019 Free
Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gmp-impl.h"
#include "tests.h"
void debug_mp (mpz_t, int);
#define SIZEM 13
/* Check that all sizes up to just above MUL_TOOM22_THRESHOLD have been tested
a few times. FIXME: If SIZEM is set too low, this will never happen. */
int
allsizes_seen (unsigned int *allsizes)
{
mp_size_t i;
for (i = 1; i < MUL_TOOM22_THRESHOLD + 4; i++)
if (allsizes[i] < 4)
return 0;
return 1;
}
void
small_2pow (unsigned long reps)
{
mpz_t du, exp, mod;
mpz_t r1;
unsigned long m, e, r;
mp_limb_t b0 = 2;
mpz_roinit_n (du, &b0, 1);
mpz_init (exp);
mpz_init (mod);
mpz_init (r1);
for (m = 3; m * m < reps; m += 2)
{
mpz_set_ui (mod, m);
r = 1;
for (e = 0; e < m; e += 1)
{
mpz_set_ui (exp, e);
mpz_powm (r1, du, exp, mod);
MPZ_CHECK_FORMAT (r1);
if (mpz_cmp_ui (r1, r) != 0)
{
fprintf (stderr, "\nIncorrect result for operands:\n");
debug_mp (du, -16);
debug_mp (exp, -16);
debug_mp (mod, -16);
fprintf (stderr, "mpz_powm result:\n");
debug_mp (r1, -16);
fprintf (stderr, "Should be 2 ^ 0x%lx = 0x%lx (mod 0x%lx)\n", e, r, m);
abort ();
}
if (r > (m >> 1))
r = (r << 1) - m;
else
r = r << 1;
}
}
mpz_clear (exp);
mpz_clear (mod);
mpz_clear (r1);
}
int
main (int argc, char **argv)
{
mpz_t base, exp, mod;
mpz_t r1, r2, t1, exp2, base2;
mp_size_t base_size, exp_size, mod_size;
int i;
int reps = 1000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
unsigned int allsizes[1 << (SIZEM + 2 - 1)];
tests_start ();
TESTS_REPS (reps, argv, argc);
small_2pow ((unsigned int) reps);
rands = RANDS;
mpz_init (bs);
mpz_init (base);
mpz_init (exp);
mpz_init (mod);
mpz_init (r1);
mpz_init (r2);
mpz_init (t1);
mpz_init (exp2);
mpz_init (base2);
memset (allsizes, 0, (1 << (SIZEM + 2 - 1)) * sizeof (int));
reps += reps >> 3;
for (i = 0; i < reps || ! allsizes_seen (allsizes); i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % SIZEM + 2;
if ((i & 7) == 0)
{
mpz_set_ui (exp, 1);
do /* Loop until mathematically well-defined. */
{
mpz_urandomb (bs, rands, size_range / 2 + 2);
base_size = mpz_get_ui (bs);
mpz_rrandomb (base, rands, base_size);
}
while (mpz_cmp_ui (base, 0) == 0);
mpz_urandomb (bs, rands, size_range / 2);
mod_size = mpz_get_ui (bs);
mod_size = MIN (mod_size, base_size);
mpz_rrandomb (mod, rands, mod_size);
mpz_urandomb (bs, rands, size_range);
mod_size = mpz_get_ui (bs) + base_size + 2;
if ((i & 8) == 0)
mod_size += GMP_NUMB_BITS - mod_size % GMP_NUMB_BITS;
mpz_setbit (mod, mod_size);
mpz_sub (base, base, mod);
}
else
{
do /* Loop until mathematically well-defined. */
{
if ((i & 7) == 4)
mpz_set_ui (base, 2);
else
{
mpz_urandomb (bs, rands, size_range);
base_size = mpz_get_ui (bs);
mpz_rrandomb (base, rands, base_size);
}
mpz_urandomb (bs, rands, 7L);
exp_size = mpz_get_ui (bs);
mpz_rrandomb (exp, rands, exp_size);
}
while (mpz_cmp_ui (base, 0) == 0 && mpz_cmp_ui (exp, 0) == 0);
do
{
mpz_urandomb (bs, rands, size_range);
mod_size = mpz_get_ui (bs);
mpz_rrandomb (mod, rands, mod_size);
}
while (mpz_cmp_ui (mod, 0) == 0);
allsizes[SIZ(mod)] += 1;
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (base, base);
/* printf ("%ld %ld %ld\n", SIZ (base), SIZ (exp), SIZ (mod)); */
}
mpz_set_ui (r2, 1);
mpz_mod (base2, base, mod);
mpz_set (exp2, exp);
mpz_mod (r2, r2, mod);
for (;;)
{
if (mpz_tstbit (exp2, 0))
{
mpz_mul (r2, r2, base2);
mpz_mod (r2, r2, mod);
}
if (mpz_cmp_ui (exp2, 1) <= 0)
break;
mpz_mul (base2, base2, base2);
mpz_mod (base2, base2, mod);
mpz_tdiv_q_2exp (exp2, exp2, 1);
}
mpz_powm (r1, base, exp, mod);
MPZ_CHECK_FORMAT (r1);
if (mpz_cmp (r1, r2) != 0)
{
fprintf (stderr, "\nIncorrect results in test %d for operands:\n", i);
debug_mp (base, -16);
debug_mp (exp, -16);
debug_mp (mod, -16);
fprintf (stderr, "mpz_powm result:\n");
debug_mp (r1, -16);
fprintf (stderr, "reference result:\n");
debug_mp (r2, -16);
abort ();
}
if (mpz_tdiv_ui (mod, 2) == 0)
continue;
mpz_powm_sec (r1, base, exp, mod);
MPZ_CHECK_FORMAT (r1);
if (mpz_cmp (r1, r2) != 0)
{
fprintf (stderr, "\nIncorrect results in test %d for operands:\n", i);
debug_mp (base, -16);
debug_mp (exp, -16);
debug_mp (mod, -16);
fprintf (stderr, "mpz_powm_sec result:\n");
debug_mp (r1, -16);
fprintf (stderr, "reference result:\n");
debug_mp (r2, -16);
abort ();
}
}
mpz_clear (bs);
mpz_clear (base);
mpz_clear (exp);
mpz_clear (mod);
mpz_clear (r1);
mpz_clear (r2);
mpz_clear (t1);
mpz_clear (exp2);
mpz_clear (base2);
tests_end ();
exit (0);
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,127 @@
/* Test mpz_powm_ui, mpz_mul, mpz_mod.
Copyright 1991, 1993, 1994, 1996, 1997, 2000-2002, 2013 Free Software
Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
int
main (int argc, char **argv)
{
mpz_t base, exp, mod;
mpz_t r1, r2, base2;
mp_size_t base_size, exp_size, mod_size;
unsigned long int exp2;
int i;
int reps = 100;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
rands = RANDS;
TESTS_REPS (reps, argv, argc);
mpz_inits (bs, base, exp, mod, r1, r2, base2, NULL);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 18 + 2;
do /* Loop until mathematically well-defined. */
{
mpz_urandomb (bs, rands, size_range);
base_size = mpz_get_ui (bs);
mpz_rrandomb (base, rands, base_size);
mpz_urandomb (bs, rands, 6L);
exp_size = mpz_get_ui (bs);
mpz_rrandomb (exp, rands, exp_size);
exp2 = mpz_getlimbn (exp, (mp_size_t) 0);
}
while (mpz_cmp_ui (base, 0) == 0 && exp2 == 0);
do
{
mpz_urandomb (bs, rands, size_range);
mod_size = mpz_get_ui (bs);
mpz_rrandomb (mod, rands, mod_size);
}
while (mpz_cmp_ui (mod, 0) == 0);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (base, base);
/* printf ("%ld %ld\n", SIZ (base), SIZ (mod)); */
#if 0
putc ('\n', stderr);
gmp_fprintf (stderr, "B = 0x%Zx\n", base);
gmp_fprintf (stderr, "M = 0x%Zx\n", mod);
#endif
exp2 = mpz_getlimbn (exp, (mp_size_t) 0);
mpz_set_ui (r2, 1);
mpz_set (base2, base);
mpz_mod (r2, r2, mod); /* needed when exp==0 and mod==1 */
while (exp2 != 0)
{
if (exp2 % 2 != 0)
{
mpz_mul (r2, r2, base2);
mpz_mod (r2, r2, mod);
}
mpz_mul (base2, base2, base2);
mpz_mod (base2, base2, mod);
exp2 = exp2 / 2;
}
exp2 = mpz_getlimbn (exp, (mp_size_t) 0);
mpz_powm_ui (r1, base, exp2, mod);
MPZ_CHECK_FORMAT (r1);
#if 0
gmp_fprintf (stderr, "R = 0x%Zx\n", r1);
gmp_fprintf (stderr, "REF = 0x%Zx\n", r2);
#endif
if (mpz_cmp (r1, r2) != 0)
{
fprintf (stderr, "\ntest %d: Incorrect results for operands:\n", i);
gmp_fprintf (stderr, "B = 0x%Zx\n", base);
gmp_fprintf (stderr, "E = 0x%Zx\n", exp);
gmp_fprintf (stderr, "M = 0x%Zx\n", mod);
gmp_fprintf (stderr, "R = 0x%Zx\n", r1);
gmp_fprintf (stderr, "REF = 0x%Zx\n", r2);
abort ();
}
}
mpz_clears (bs, base, exp, mod, r1, r2, base2, NULL);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,243 @@
/* Exercise mpz_probab_prime_p.
Copyright 2002, 2018-2019, 2022 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Enhancements:
- Test some big primes don't come back claimed to be composite.
- Test some big composites don't come back claimed to be certainly prime.
- Test some big composites with small factors are identified as certainly
composite. */
/* return 2 if prime, 0 if composite */
int
isprime (unsigned long n)
{
if (n < 4)
return (n & 2);
if ((n & 1) == 0)
return 0;
for (unsigned long i = 3; i*i <= n; i+=2)
if ((n % i) == 0)
return 0;
return 2;
}
void
check_one (mpz_srcptr n, int want)
{
int got;
got = mpz_probab_prime_p (n, 25);
/* "definitely prime" (2) is fine if we only wanted "probably prime" (1) */
if ((got != want) && (got != want * 2))
{
printf ("mpz_probab_prime_p\n");
mpz_trace (" n ", n);
printf (" got =%d", got);
printf (" want=%d", want);
abort ();
}
}
void
check_pn (mpz_ptr n, int want)
{
check_one (n, want);
mpz_neg (n, n);
check_one (n, want);
}
/* expect certainty for small n */
void
check_small (void)
{
mpz_t n;
long i;
mpz_init (n);
for (i = 0; i < 300; i++)
{
mpz_set_si (n, i);
check_pn (n, isprime (i));
}
mpz_clear (n);
}
void
check_composites (int count)
{
int i;
mpz_t a, b, n, bs;
unsigned long size_range, size;
gmp_randstate_ptr rands = RANDS;
mpz_init (a);
mpz_init (b);
mpz_init (n);
mpz_init (bs);
static const char * const composites[] = {
"225670644213750121", /* n=61*C16, if D < 61, (n/D) = 1. */
"2386342059899637841", /* n=61*C17, if D < 61, (n/D) = 1. */
"1194649", /* A square, but strong base-2 pseudoprime, */
"12327121", /* another base-2 pseudoprime square. */
"18446744066047760377", /* Should trigger Fibonacci's test; */
"10323769", /* &3==1, Lucas' test with D=37; */
"1397419", /* &3==3, Lucas' test with D=43; */
"11708069165918597341", /* &3==1, Lucas' test with large D=107; */
"395009109077493751", /* &3==3, Lucas' test with large D=113. */
NULL
};
for (i = 0; composites[i]; i++)
{
mpz_set_str_or_abort (n, composites[i], 0);
check_one (n, 0);
}
for (i = 0; i < count; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 13 + 1; /* 0..8192 bit operands */
mpz_urandomb (bs, rands, size_range);
size = mpz_get_ui (bs);
mpz_rrandomb (a, rands, size);
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 13 + 1; /* 0..8192 bit operands */
mpz_rrandomb (b, rands, size);
/* Exclude trivial factors */
if (mpz_cmp_ui (a, 1) == 0)
mpz_set_ui (a, 2);
if (mpz_cmp_ui (b, 1) == 0)
mpz_set_ui (b, 2);
mpz_mul (n, a, b);
check_pn (n, 0);
}
mpz_clear (a);
mpz_clear (b);
mpz_clear (n);
mpz_clear (bs);
}
static void
check_primes (void)
{
static const char * const primes[] = {
"2", "53", "1234567891",
"2055693949", "1125899906842597", "16412292043871650369",
"18446744075358702679", /* Lucas' test with large D=107. */
/* diffie-hellman-group1-sha1, also "Well known group 2" in RFC
2412, 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
"FFFFFFFFFFFFFFFF",
NULL
};
mpz_t n;
int i;
mpz_init (n);
for (i = 0; primes[i]; i++)
{
mpz_set_str_or_abort (n, primes[i], 0);
check_one (n, 1);
}
mpz_clear (n);
}
static void
check_fermat_mersenne (int count)
{
int fermat_exponents [] = {1, 2, 4, 8, 16};
int mersenne_exponents [] = {2, 3, 5, 7, 13, 17, 19, 31, 61, 89,
107, 127, 521, 607, 1279, 2203, 2281,
3217, 4253, 4423, 9689, 9941, 11213,
19937, 21701, 23209, 44497, 86243};
mpz_t pp;
int i, j, want;
mpz_init (pp);
count = MIN (110000, count);
for (i=1; i<count; ++i)
{
mpz_set_ui (pp, 1);
mpz_setbit (pp, i); /* 2^i + 1 */
want = 0;
for (j = 0; j < numberof (fermat_exponents); j++)
if (fermat_exponents[j] == i)
{
/* Fermat's primes are small enough for a definite answer. */
want = 2;
break;
}
check_one (pp, want);
mpz_sub_ui (pp, pp, 2); /* 2^i - 1 */
want = 0;
for (j = 0; j < numberof (mersenne_exponents); j++)
if (mersenne_exponents[j] == i)
{
want = 1 << (i < 50);
break;
}
check_one (pp, want);
}
mpz_clear (pp);
}
int
main (int argc, char **argv)
{
int count = 1000;
TESTS_REPS (count, argv, argc);
tests_start ();
check_small ();
check_fermat_mersenne (count >> 3);
check_composites (count);
check_primes ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,145 @@
/* Exercise mpz_primorial_ui.
Copyright 2000-2002, 2012, 2015 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Usage: t-primorial_ui [x|num]
With no arguments testing goes up to the initial value of "limit" below.
With a number argument tests are carried that far, or with a literal "x"
tests are continued without limit (this being meant only for development
purposes). */
static int isprime (unsigned long int t);
int
main (int argc, char *argv[])
{
unsigned long n;
unsigned long limit = 2222;
gmp_randstate_ptr rands;
mpz_t f, r, bs;
tests_start ();
rands = RANDS;
if (argc > 1 && argv[1][0] == 'x')
limit = ULONG_MAX;
else
TESTS_REPS (limit, argv, argc);
/* for small limb testing */
limit = MIN (limit, MP_LIMB_T_MAX);
mpz_init_set_ui (f, 1); /* 0# = 1 */
mpz_init (r);
n = 0;
do
{
mpz_primorial_ui (r, n);
MPZ_CHECK_FORMAT (r);
if (mpz_cmp (f, r) != 0)
{
printf ("mpz_primorial_ui(%lu) wrong\n", n);
printf (" got "); mpz_out_str (stdout, 10, r); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, f); printf("\n");
abort ();
}
if (isprime (++n))
mpz_mul_ui (f, f, n); /* p# = (p-1)# * (p) */
if (n%16 == 0) { mpz_clear (r); mpz_init (r); }
} while (n < limit);
n = 0; limit =1;
mpz_init (bs);
do
{
unsigned long i, d;
mpz_urandomb (bs, rands, 21);
i = mpz_get_ui (bs);
mpz_urandomb (bs, rands, 9);
d = mpz_get_ui (bs) + 3*64;
mpz_primorial_ui (f, i);
MPZ_CHECK_FORMAT (f);
mpz_primorial_ui (r, i+d);
MPZ_CHECK_FORMAT (r);
do {
if (isprime (++i))
mpz_mul_ui (f, f, i);
} while (--d != 0);
if (mpz_cmp (f, r) != 0)
{
printf ("mpz_primorial_ui(%lu) wrong\n", i);
printf (" got "); mpz_out_str (stdout, 10, r); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, f); printf("\n");
abort ();
}
} while (++n < limit);
/* Chech a single "big" value, modulo a larger prime */
n = 2095637;
mpz_primorial_ui (r, n);
mpz_set_ui (f, 13);
mpz_setbit (f, 64); /* f = 2^64 + 13 */
mpz_tdiv_r (r, r, f);
mpz_set_str (f, "BAFCBF3C95B217D5", 16);
if (mpz_cmp (f, r) != 0)
{
printf ("mpz_primorial_ui(%lu) wrong\n", n);
printf (" got "); mpz_out_str (stdout, 10, r); printf("\n");
printf (" want "); mpz_out_str (stdout, 10, f); printf("\n");
abort ();
}
mpz_clear (bs);
mpz_clear (f);
mpz_clear (r);
tests_end ();
exit (0);
}
static int
isprime (unsigned long int t)
{
unsigned long int q, r, d;
if (t < 3 || (t & 1) == 0)
return t == 2;
for (d = 3, r = 1; r != 0; d += 2)
{
q = t / d;
r = t - q * d;
if (q < d)
return 1;
}
return 0;
}

View File

@@ -0,0 +1,146 @@
/* Test mpz_remove.
Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2009, 2012, 2013 Free
Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void debug_mp (mpz_t);
unsigned long int mpz_refremove (mpz_t, const mpz_t, const mpz_t);
int
main (int argc, char **argv)
{
unsigned long int exp;
mpz_t t, dest, refdest, dividend, divisor;
mp_size_t dividend_size, divisor_size;
int i;
int reps = 1000;
unsigned long int pwr, refpwr;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long size_range;
tests_start ();
rands = RANDS;
if (argc == 2)
reps = atoi (argv[1]);
mpz_inits (bs, t, dest, refdest, dividend, divisor, NULL);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 18 + 1; /* 1..524288 bit operands */
do
{
mpz_urandomb (bs, rands, size_range);
divisor_size = mpz_get_ui (bs);
mpz_rrandomb (divisor, rands, divisor_size);
}
while (mpz_sgn (divisor) == 0);
mpz_urandomb (bs, rands, size_range);
dividend_size = mpz_get_ui (bs) + divisor_size;
mpz_rrandomb (dividend, rands, dividend_size);
mpz_urandomb (bs, rands, 32);
exp = mpz_get_ui (bs) % (5 + 10000 / mpz_sizeinbase (divisor, 2));
if (mpz_get_ui (bs) & 2)
mpz_neg (divisor, divisor);
mpz_pow_ui (t, divisor, exp);
mpz_mul (dividend, dividend, t);
refpwr = mpz_refremove (refdest, dividend, divisor);
pwr = mpz_remove (dest, dividend, divisor);
if (refpwr != pwr || mpz_cmp (refdest, dest) != 0)
{
fprintf (stderr, "ERROR after %d tests\n", i);
fprintf (stderr, "refpower = %lu\n", refpwr);
fprintf (stderr, " power = %lu\n", pwr);
fprintf (stderr, " op1 = "); debug_mp (dividend);
fprintf (stderr, " op2 = "); debug_mp (divisor);
fprintf (stderr, "refdest = "); debug_mp (refdest);
fprintf (stderr, " dest = "); debug_mp (dest);
abort ();
}
}
mpz_clears (bs, t, dest, refdest, dividend, divisor, NULL);
tests_end ();
exit (0);
}
unsigned long int
mpz_refremove (mpz_t dest, const mpz_t src, const mpz_t f)
{
unsigned long int pwr;
pwr = 0;
mpz_set (dest, src);
if (mpz_cmpabs_ui (f, 1) > 0)
{
mpz_t rem, x;
mpz_init (x);
mpz_init (rem);
for (;; pwr++)
{
mpz_tdiv_qr (x, rem, dest, f);
if (mpz_cmp_ui (rem, 0) != 0)
break;
mpz_swap (dest, x);
}
mpz_clear (x);
mpz_clear (rem);
}
return pwr;
}
void
debug_mp (mpz_t x)
{
size_t siz = mpz_sizeinbase (x, 16);
if (siz > 65)
{
mpz_t q;
mpz_init (q);
mpz_tdiv_q_2exp (q, x, 4 * (mpz_sizeinbase (x, 16) - 25));
gmp_fprintf (stderr, "%ZX...", q);
mpz_tdiv_r_2exp (q, x, 4 * 25);
gmp_fprintf (stderr, "%025ZX [%d]\n", q, (int) siz);
mpz_clear (q);
}
else
{
gmp_fprintf (stderr, "%ZX\n", x);
}
}

View File

@@ -0,0 +1,174 @@
/* Test mpz_root, mpz_rootrem, and mpz_perfect_power_p.
Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2009, 2015 Free Software
Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void debug_mp (mpz_t, int);
void
check_one (mpz_t root1, mpz_t x2, unsigned long nth, int res, int i)
{
mpz_t temp, temp2;
mpz_t root2, rem2;
mpz_init (root2);
mpz_init (rem2);
mpz_init (temp);
mpz_init (temp2);
MPZ_CHECK_FORMAT (root1);
mpz_rootrem (root2, rem2, x2, nth);
MPZ_CHECK_FORMAT (root2);
MPZ_CHECK_FORMAT (rem2);
mpz_pow_ui (temp, root1, nth);
MPZ_CHECK_FORMAT (temp);
mpz_add (temp2, temp, rem2);
/* Is power of result > argument? */
if (mpz_cmp (root1, root2) != 0 || mpz_cmp (x2, temp2) != 0 || mpz_cmpabs (temp, x2) > 0 || res == mpz_cmp_ui (rem2, 0))
{
fprintf (stderr, "ERROR after test %d\n", i);
debug_mp (x2, 10);
debug_mp (root1, 10);
debug_mp (root2, 10);
fprintf (stderr, "nth: %lu ,res: %i\n", nth, res);
abort ();
}
if (nth > 1 && mpz_cmp_ui (temp, 1L) > 0 && ! mpz_perfect_power_p (temp))
{
fprintf (stderr, "ERROR in mpz_perfect_power_p after test %d\n", i);
debug_mp (temp, 10);
debug_mp (root1, 10);
fprintf (stderr, "nth: %lu\n", nth);
abort ();
}
if (nth <= 10000 && mpz_sgn(x2) > 0) /* skip too expensive test */
{
mpz_add_ui (temp2, root1, 1L);
mpz_pow_ui (temp2, temp2, nth);
MPZ_CHECK_FORMAT (temp2);
/* Is square of (result + 1) <= argument? */
if (mpz_cmp (temp2, x2) <= 0)
{
fprintf (stderr, "ERROR after test %d\n", i);
debug_mp (x2, 10);
debug_mp (root1, 10);
fprintf (stderr, "nth: %lu\n", nth);
abort ();
}
}
mpz_clear (root2);
mpz_clear (rem2);
mpz_clear (temp);
mpz_clear (temp2);
}
int
main (int argc, char **argv)
{
mpz_t x2;
mpz_t root1;
mp_size_t x2_size;
int i, res;
int reps = 500;
unsigned long nth;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mpz_init (bs);
mpz_init (x2);
mpz_init (root1);
/* This triggers a gcc 4.3.2 bug */
mpz_set_str (x2, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000002", 16);
res = mpz_root (root1, x2, 2);
check_one (root1, x2, 2, res, -1);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 17 + 2;
mpz_urandomb (bs, rands, size_range);
x2_size = mpz_get_ui (bs) + 10;
mpz_rrandomb (x2, rands, x2_size);
mpz_urandomb (bs, rands, 15);
nth = mpz_getlimbn (bs, 0) % mpz_sizeinbase (x2, 2) + 2;
res = mpz_root (root1, x2, nth);
mpz_urandomb (bs, rands, 4);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
{
/* With 50% probability, set x2 near a perfect power. */
mpz_pow_ui (x2, root1, nth);
if ((bsi & 2) != 0)
{
mpz_sub_ui (x2, x2, bsi >> 2);
mpz_abs (x2, x2);
}
else
mpz_add_ui (x2, x2, bsi >> 2);
res = mpz_root (root1, x2, nth);
}
check_one (root1, x2, nth, res, i);
if (((nth & 1) != 0) && ((bsi & 2) != 0))
{
mpz_neg (x2, x2);
mpz_neg (root1, root1);
check_one (root1, x2, nth, res, i);
}
}
mpz_clear (bs);
mpz_clear (x2);
mpz_clear (root1);
tests_end ();
exit (0);
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,131 @@
/* Tests of mpz_scan0 and mpz_scan1.
Copyright 2000-2003 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
unsigned long
refmpz_scan (mpz_srcptr z, unsigned long i, int sought)
{
unsigned long z_bits = (unsigned long) ABSIZ(z) * GMP_NUMB_BITS;
do
{
if (mpz_tstbit (z, i) == sought)
return i;
i++;
}
while (i <= z_bits);
return ULONG_MAX;
}
unsigned long
refmpz_scan0 (mpz_srcptr z, unsigned long starting_bit)
{
return refmpz_scan (z, starting_bit, 0);
}
unsigned long
refmpz_scan1 (mpz_srcptr z, unsigned long starting_bit)
{
return refmpz_scan (z, starting_bit, 1);
}
void
check_ref (void)
{
static const int offset[] = {
-2, -1, 0, 1, 2, 3
};
mpz_t z;
int test, neg, sought, oindex, o;
mp_size_t size, isize;
unsigned long start, got, want;
mpz_init (z);
for (test = 0; test < 5; test++)
{
for (size = 0; size < 5; size++)
{
mpz_random2 (z, size);
for (neg = 0; neg <= 1; neg++)
{
if (neg)
mpz_neg (z, z);
for (isize = 0; isize <= size; isize++)
{
for (oindex = 0; oindex < numberof (offset); oindex++)
{
o = offset[oindex];
if ((int) isize*GMP_NUMB_BITS < -o)
continue; /* start would be negative */
start = isize*GMP_NUMB_BITS + o;
for (sought = 0; sought <= 1; sought++)
{
if (sought == 0)
{
got = mpz_scan0 (z, start);
want = refmpz_scan0 (z, start);
}
else
{
got = mpz_scan1 (z, start);
want = refmpz_scan1 (z, start);
}
if (got != want)
{
printf ("wrong at test=%d, size=%ld, neg=%d, start=%lu, sought=%d\n",
test, size, neg, start, sought);
printf (" z 0x");
mpz_out_str (stdout, -16, z);
printf ("\n");
printf (" got=%lu, want=%lu\n", got, want);
exit (1);
}
}
}
}
}
}
}
mpz_clear (z);
}
int
main (int argc, char *argv[])
{
tests_start ();
check_ref ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,139 @@
/* Test mpz_set_d and mpz_init_set_d.
Copyright 2000-2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_data (void)
{
static const struct {
double d;
mp_size_t want_size;
mp_limb_t want_data[2];
} data[] = {
{ 0.0, 0 },
{ 1.0, 1, { 1 } },
{ -1.0, -1, { 1 } },
{ 123.0, 1, { 123 } },
{ -123.0, -1, { 123 } },
{ 1e-1, 0, { 0 } },
{ -1e-1, 0, { 0 } },
{ 2.328306436538696e-10, 0, { 0 } },
{ -2.328306436538696e-10, 0, { 0 } },
{ 5.421010862427522e-20, 0, { 0 } },
{ -5.421010862427522e-20, 0, { 0 } },
{ 2.938735877055719e-39, 0, { 0 } },
{ -2.938735877055719e-39, 0, { 0 } },
};
mpz_t z;
int i;
for (i = 0; i < numberof (data); i++)
{
mpz_init (z);
mpz_set_d (z, data[i].d);
MPZ_CHECK_FORMAT (z);
if (z->_mp_size != data[i].want_size
|| refmpn_cmp_allowzero (z->_mp_d, data[i].want_data,
ABS (data[i].want_size)) != 0)
{
printf ("mpz_set_d wrong on data[%d]\n", i);
bad:
d_trace (" d ", data[i].d);
printf (" got size %ld\n", (long) z->_mp_size);
printf (" want size %ld\n", (long) data[i].want_size);
mpn_trace (" got z", z->_mp_d, z->_mp_size);
mpn_trace (" want z", data[i].want_data, data[i].want_size);
abort();
}
mpz_clear (z);
mpz_init_set_d (z, data[i].d);
MPZ_CHECK_FORMAT (z);
if (z->_mp_size != data[i].want_size
|| refmpn_cmp_allowzero (z->_mp_d, data[i].want_data,
ABS (data[i].want_size)) != 0)
{
printf ("mpz_init_set_d wrong on data[%d]\n", i);
goto bad;
}
mpz_clear (z);
}
}
/* Try mpz_set_d on values 2^i+1, while such a value fits a double. */
void
check_2n_plus_1 (void)
{
volatile double p, d, diff;
mpz_t want, got;
int i;
mpz_init (want);
mpz_init (got);
p = 1.0;
mpz_set_ui (want, 2L); /* gives 3 on first step */
for (i = 1; i < 500; i++)
{
mpz_mul_2exp (want, want, 1L);
mpz_sub_ui (want, want, 1L); /* want = 2^i+1 */
p *= 2.0; /* p = 2^i */
d = p + 1.0;
diff = d - p;
if (diff != 1.0)
break; /* rounding occurred, stop now */
mpz_set_d (got, d);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, want) != 0)
{
printf ("mpz_set_d wrong on 2^%d+1\n", i);
d_trace (" d ", d);
mpz_trace (" got ", got);
mpz_trace (" want ", want);
abort ();
}
}
mpz_clear (want);
mpz_clear (got);
}
int
main (void)
{
tests_start ();
check_data ();
check_2n_plus_1 ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,125 @@
/* Test mpz_set_f.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_one (mpz_srcptr z)
{
static const int shift[] = {
0, 1, GMP_LIMB_BITS, 2*GMP_LIMB_BITS, 5*GMP_LIMB_BITS
};
int sh, shneg, neg;
mpf_t f;
mpz_t got, want;
mpf_init2 (f, mpz_sizeinbase(z,2));
mpz_init (got);
mpz_init (want);
for (sh = 0; sh < numberof(shift); sh++)
{
for (shneg = 0; shneg <= 1; shneg++)
{
for (neg = 0; neg <= 1; neg++)
{
mpf_set_z (f, z);
mpz_set (want, z);
if (neg)
{
mpf_neg (f, f);
mpz_neg (want, want);
}
if (shneg)
{
mpz_tdiv_q_2exp (want, want, shift[sh]);
mpf_div_2exp (f, f, shift[sh]);
}
else
{
mpz_mul_2exp (want, want, shift[sh]);
mpf_mul_2exp (f, f, shift[sh]);
}
mpz_set_f (got, f);
MPZ_CHECK_FORMAT (got);
if (mpz_cmp (got, want) != 0)
{
printf ("wrong result\n");
printf (" shift %d\n", shneg ? -shift[sh] : shift[sh]);
printf (" neg %d\n", neg);
mpf_trace (" f", f);
mpz_trace (" got", got);
mpz_trace (" want", want);
abort ();
}
}
}
}
mpf_clear (f);
mpz_clear (got);
mpz_clear (want);
}
void
check_various (void)
{
mpz_t z;
mpz_init (z);
mpz_set_ui (z, 0L);
check_one (z);
mpz_set_si (z, 123L);
check_one (z);
mpz_rrandomb (z, RANDS, 2*GMP_LIMB_BITS);
check_one (z);
mpz_rrandomb (z, RANDS, 5*GMP_LIMB_BITS);
check_one (z);
mpz_clear (z);
}
int
main (int argc, char *argv[])
{
#if GMP_NAIL_BITS == 0
tests_start ();
mp_trace_base = 16;
check_various ();
tests_end ();
#endif
exit (0);
}

View File

@@ -0,0 +1,96 @@
/* Test mpz_set_si and mpz_init_set_si.
Copyright 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_data (void)
{
#if GMP_NUMB_BITS <= BITS_PER_ULONG
#define ENTRY(n) { n, { n, 0 } }
#else
#define ENTRY(n) { n, { (n) & GMP_NUMB_MASK, (n) >> GMP_NUMB_BITS } }
#endif
static const struct {
long n;
mp_size_t want_size;
mp_limb_t want_data[2];
} data[] = {
{ 0L, 0 },
{ 1L, 1, { 1 } },
{ -1L, -1, { 1 } },
#if GMP_NUMB_BITS >= BITS_PER_ULONG
{ LONG_MAX, 1, { LONG_MAX, 0 } },
{ -LONG_MAX, -1, { LONG_MAX, 0 } },
{ LONG_HIGHBIT, -1, { ULONG_HIGHBIT, 0 } },
#else
{ LONG_MAX, 2, { LONG_MAX & GMP_NUMB_MASK, LONG_MAX >> GMP_NUMB_BITS } },
{ -LONG_MAX, -2, { LONG_MAX & GMP_NUMB_MASK, LONG_MAX >> GMP_NUMB_BITS }},
{ LONG_HIGHBIT, -2, { 0, ULONG_HIGHBIT >> GMP_NUMB_BITS } },
#endif
};
mpz_t n;
int i;
for (i = 0; i < numberof (data); i++)
{
mpz_init (n);
mpz_set_si (n, data[i].n);
MPZ_CHECK_FORMAT (n);
if (n->_mp_size != data[i].want_size
|| refmpn_cmp_allowzero (n->_mp_d, data[i].want_data,
ABS (data[i].want_size)) != 0)
{
printf ("mpz_set_si wrong on data[%d]\n", i);
abort();
}
mpz_clear (n);
mpz_init_set_si (n, data[i].n);
MPZ_CHECK_FORMAT (n);
if (n->_mp_size != data[i].want_size
|| refmpn_cmp_allowzero (n->_mp_d, data[i].want_data,
ABS (data[i].want_size)) != 0)
{
printf ("mpz_init_set_si wrong on data[%d]\n", i);
abort();
}
mpz_clear (n);
}
}
int
main (void)
{
tests_start ();
check_data ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,108 @@
/* Test mpz_set_str.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void
check_one (mpz_srcptr want, int fail, int base, const char *str)
{
mpz_t got;
MPZ_CHECK_FORMAT (want);
mp_trace_base = (base == 0 ? 16 : base);
mpz_init (got);
if (mpz_set_str (got, str, base) != fail)
{
printf ("mpz_set_str unexpectedly failed\n");
printf (" base %d\n", base);
printf (" str \"%s\"\n", str);
abort ();
}
MPZ_CHECK_FORMAT (got);
if (fail == 0 && mpz_cmp (got, want) != 0)
{
printf ("mpz_set_str wrong\n");
printf (" base %d\n", base);
printf (" str \"%s\"\n", str);
mpz_trace ("got ", got);
mpz_trace ("want", want);
abort ();
}
mpz_clear (got);
}
void
check_samples (void)
{
mpz_t z;
mpz_init (z);
mpz_set_ui (z, 0L);
check_one (z, 0, 0, "0 ");
check_one (z, 0, 0, " 0 0 0 ");
check_one (z, 0, 0, " -0B 0 ");
check_one (z, 0, 0, " 0X 0 ");
check_one (z, 0, 10, "0 ");
check_one (z, 0, 10, "-0 ");
check_one (z, 0, 10, " 0 000 000 ");
mpz_set_ui (z, 123L);
check_one (z, 0, 0, "123 ");
check_one (z, 0, 0, "123 ");
check_one (z, 0, 0, "0173 ");
check_one (z, 0, 0, " 0b 1 11 10 11 ");
check_one (z, 0, 0, " 0x 7b ");
check_one (z, 0, 0, "0x7B");
check_one (z, 0, 10, "123 ");
check_one (z, 0, 10, "123 ");
check_one (z, 0, 0, " 123 ");
check_one (z, 0, 0, " 123 ");
check_one (z, 0, 10, " 0000123 ");
check_one (z, 0, 10, " 123 ");
check_one (z,-1, 10, "1%");
check_one (z,-1, 0, "3!");
check_one (z,-1, 0, "0123456789");
check_one (z,-1, 0, "13579BDF");
check_one (z,-1, 0, "0b0102");
check_one (z,-1, 0, "0x010G");
check_one (z,-1, 37,"0x010G");
check_one (z,-1, 99,"0x010G");
mpz_clear (z);
}
int
main (void)
{
tests_start ();
check_samples ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,89 @@
/* Test mpz_sizeinbase.
Copyright 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
#if 0
/* Disabled due to the bogosity of trying to fake an _mp_d pointer to
below an object. Has been seen to fail on a hppa system and on ia64. */
/* Create a fake mpz consisting of just a single 1 bit, with totbits being
the total number of bits, inclusive of that 1 bit. */
void
mpz_fake_bits (mpz_ptr z, unsigned long totbits)
{
static mp_limb_t n;
unsigned long zero_bits, zero_limbs;
zero_bits = totbits - 1;
zero_limbs = zero_bits / GMP_NUMB_BITS;
zero_bits %= GMP_NUMB_BITS;
SIZ(z) = zero_limbs + 1;
PTR(z) = (&n) - (SIZ(z) - 1);
n = CNST_LIMB(1) << zero_bits;
ASSERT_ALWAYS (mpz_sizeinbase (z, 2) == totbits);
}
/* This was seen to fail on a GNU/Linux powerpc32 with gcc 2.95.2,
apparently due to a doubtful value of mp_bases[10].chars_per_bit_exactly
(0X1.34413509F79FDP-2 whereas 0X1.34413509F79FFP-2 is believed correct).
Presumably this is a glibc problem when gcc converts the decimal string
in mp_bases.c, or maybe it's only a function of the rounding mode during
compilation. */
void
check_sample (void)
{
unsigned long totbits = 198096465;
int base = 10;
size_t want = 59632979;
size_t got;
mpz_t z;
mpz_fake_bits (z, totbits);
got = mpz_sizeinbase (z, base);
if (got != want)
{
printf ("mpz_sizeinbase\n");
printf (" base %d\n", base);
printf (" totbits %lu\n", totbits);
printf (" got %u\n", got);
printf (" want %u\n", want);
abort ();
}
}
#endif
int
main (void)
{
tests_start ();
/* check_sample (); */
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,122 @@
/* Test mpz_add, mpz_add_ui, mpz_cmp, mpz_cmp, mpz_mul, mpz_sqrtrem.
Copyright 1991, 1993, 1994, 1996, 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void dump_abort (mpz_t, mpz_t, mpz_t);
void debug_mp (mpz_t, int);
int
main (int argc, char **argv)
{
mpz_t x2;
mpz_t x, rem;
mpz_t temp, temp2;
mp_size_t x2_size;
int i;
int reps = 1000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long size_range;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mpz_init (bs);
mpz_init (x2);
mpz_init (x);
mpz_init (rem);
mpz_init (temp);
mpz_init (temp2);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 17 + 2; /* 0..262144 bit operands */
mpz_urandomb (bs, rands, size_range);
x2_size = mpz_get_ui (bs);
mpz_rrandomb (x2, rands, x2_size);
/* printf ("%ld\n", SIZ (x2)); */
mpz_sqrt (temp, x2);
MPZ_CHECK_FORMAT (temp);
mpz_sqrtrem (x, rem, x2);
MPZ_CHECK_FORMAT (x);
MPZ_CHECK_FORMAT (rem);
/* Are results different? */
if (mpz_cmp (temp, x) != 0)
dump_abort (x2, x, rem);
mpz_mul (temp, x, x);
/* Is square of result > argument? */
if (mpz_cmp (temp, x2) > 0)
dump_abort (x2, x, rem);
mpz_add_ui (temp2, x, 1);
mpz_mul (temp2, temp2, temp2);
/* Is square of (result + 1) <= argument? */
if (mpz_cmp (temp2, x2) <= 0)
dump_abort (x2, x, rem);
mpz_add (temp2, temp, rem);
/* Is the remainder wrong? */
if (mpz_cmp (x2, temp2) != 0)
dump_abort (x2, x, rem);
}
mpz_clear (bs);
mpz_clear (x2);
mpz_clear (x);
mpz_clear (rem);
mpz_clear (temp);
mpz_clear (temp2);
tests_end ();
exit (0);
}
void
dump_abort (mpz_t x2, mpz_t x, mpz_t rem)
{
fprintf (stderr, "ERROR\n");
fprintf (stderr, "x2 = "); debug_mp (x2, -16);
fprintf (stderr, "x = "); debug_mp (x, -16);
fprintf (stderr, "remainder = "); debug_mp (rem, -16);
abort();
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,145 @@
/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr, mpz_tdiv_q,
mpz_tdiv_r, mpz_mul.
Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void dump_abort (mpz_t, mpz_t);
void debug_mp (mpz_t, int);
int
main (int argc, char **argv)
{
mpz_t dividend, divisor;
mpz_t quotient, remainder;
mpz_t quotient2, remainder2;
mpz_t temp;
mp_size_t dividend_size, divisor_size;
int i;
int reps = 1000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
tests_start ();
TESTS_REPS (reps, argv, argc);
rands = RANDS;
mpz_init (bs);
mpz_init (dividend);
mpz_init (divisor);
mpz_init (quotient);
mpz_init (remainder);
mpz_init (quotient2);
mpz_init (remainder2);
mpz_init (temp);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 18 + 2; /* 0..524288 bit operands */
do
{
mpz_urandomb (bs, rands, size_range);
divisor_size = mpz_get_ui (bs);
mpz_rrandomb (divisor, rands, divisor_size);
}
while (mpz_sgn (divisor) == 0);
mpz_urandomb (bs, rands, size_range);
dividend_size = mpz_get_ui (bs) + divisor_size;
mpz_rrandomb (dividend, rands, dividend_size);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (dividend, dividend);
if ((bsi & 2) != 0)
mpz_neg (divisor, divisor);
/* printf ("%ld %ld\n", SIZ (dividend), SIZ (divisor)); */
mpz_tdiv_qr (quotient, remainder, dividend, divisor);
mpz_tdiv_q (quotient2, dividend, divisor);
mpz_tdiv_r (remainder2, dividend, divisor);
/* First determine that the quotients and remainders computed
with different functions are equal. */
if (mpz_cmp (quotient, quotient2) != 0)
dump_abort (dividend, divisor);
if (mpz_cmp (remainder, remainder2) != 0)
dump_abort (dividend, divisor);
/* Check if the sign of the quotient is correct. */
if (mpz_cmp_ui (quotient, 0) != 0)
if ((mpz_cmp_ui (quotient, 0) < 0)
!= ((mpz_cmp_ui (dividend, 0) ^ mpz_cmp_ui (divisor, 0)) < 0))
dump_abort (dividend, divisor);
/* Check if the remainder has the same sign as the dividend
(quotient rounded towards 0). */
if (mpz_cmp_ui (remainder, 0) != 0)
if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0))
dump_abort (dividend, divisor);
mpz_mul (temp, quotient, divisor);
mpz_add (temp, temp, remainder);
if (mpz_cmp (temp, dividend) != 0)
dump_abort (dividend, divisor);
mpz_abs (temp, divisor);
mpz_abs (remainder, remainder);
if (mpz_cmp (remainder, temp) >= 0)
dump_abort (dividend, divisor);
}
mpz_clear (bs);
mpz_clear (dividend);
mpz_clear (divisor);
mpz_clear (quotient);
mpz_clear (remainder);
mpz_clear (quotient2);
mpz_clear (remainder2);
mpz_clear (temp);
tests_end ();
exit (0);
}
void
dump_abort (mpz_t dividend, mpz_t divisor)
{
fprintf (stderr, "ERROR\n");
fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
fprintf (stderr, "divisor = "); debug_mp (divisor, -16);
abort();
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}

View File

@@ -0,0 +1,158 @@
/* Test mpz_abs, mpz_add, mpz_cmp, mpz_cmp_ui, mpz_tdiv_qr_ui, mpz_tdiv_q_ui,
mpz_tdiv_r_ui, mpz_tdiv_ui, mpz_mul_ui.
Copyright 1993, 1994, 1996, 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite 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 General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
void dump_abort (const char *, mpz_t, unsigned long);
void debug_mp (mpz_t, int);
int
main (int argc, char **argv)
{
mpz_t dividend;
mpz_t quotient, remainder;
mpz_t quotient2, remainder2;
mpz_t temp;
mp_size_t dividend_size;
unsigned long divisor;
int i;
int reps = 200000;
gmp_randstate_ptr rands;
mpz_t bs;
unsigned long bsi, size_range;
unsigned long r_rq, r_q, r_r, r;
tests_start ();
rands = RANDS;
mpz_init (bs);
if (argc == 2)
reps = atoi (argv[1]);
mpz_init (dividend);
mpz_init (quotient);
mpz_init (remainder);
mpz_init (quotient2);
mpz_init (remainder2);
mpz_init (temp);
for (i = 0; i < reps; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */
do
{
mpz_rrandomb (bs, rands, 64);
divisor = mpz_get_ui (bs);
}
while (divisor == 0);
mpz_urandomb (bs, rands, size_range);
dividend_size = mpz_get_ui (bs);
mpz_rrandomb (dividend, rands, dividend_size);
mpz_urandomb (bs, rands, 2);
bsi = mpz_get_ui (bs);
if ((bsi & 1) != 0)
mpz_neg (dividend, dividend);
/* printf ("%ld\n", SIZ (dividend)); */
r_rq = mpz_tdiv_qr_ui (quotient, remainder, dividend, divisor);
r_q = mpz_tdiv_q_ui (quotient2, dividend, divisor);
r_r = mpz_tdiv_r_ui (remainder2, dividend, divisor);
r = mpz_tdiv_ui (dividend, divisor);
/* First determine that the quotients and remainders computed
with different functions are equal. */
if (mpz_cmp (quotient, quotient2) != 0)
dump_abort ("quotients from mpz_tdiv_qr_ui and mpz_tdiv_q_ui differ",
dividend, divisor);
if (mpz_cmp (remainder, remainder2) != 0)
dump_abort ("remainders from mpz_tdiv_qr_ui and mpz_tdiv_r_ui differ",
dividend, divisor);
/* Check if the sign of the quotient is correct. */
if (mpz_cmp_ui (quotient, 0) != 0)
if ((mpz_cmp_ui (quotient, 0) < 0)
!= (mpz_cmp_ui (dividend, 0) < 0))
dump_abort ("quotient sign wrong", dividend, divisor);
/* Check if the remainder has the same sign as the dividend
(quotient rounded towards 0). */
if (mpz_cmp_ui (remainder, 0) != 0)
if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0))
dump_abort ("remainder sign wrong", dividend, divisor);
mpz_mul_ui (temp, quotient, divisor);
mpz_add (temp, temp, remainder);
if (mpz_cmp (temp, dividend) != 0)
dump_abort ("n mod d != n - [n/d]*d", dividend, divisor);
mpz_abs (remainder, remainder);
if (mpz_cmp_ui (remainder, divisor) >= 0)
dump_abort ("remainder greater than divisor", dividend, divisor);
if (mpz_cmp_ui (remainder, r_rq) != 0)
dump_abort ("remainder returned from mpz_tdiv_qr_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r_q) != 0)
dump_abort ("remainder returned from mpz_tdiv_q_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r_r) != 0)
dump_abort ("remainder returned from mpz_tdiv_r_ui is wrong",
dividend, divisor);
if (mpz_cmp_ui (remainder, r) != 0)
dump_abort ("remainder returned from mpz_tdiv_ui is wrong",
dividend, divisor);
}
mpz_clear (bs);
mpz_clear (dividend);
mpz_clear (quotient);
mpz_clear (remainder);
mpz_clear (quotient2);
mpz_clear (remainder2);
mpz_clear (temp);
tests_end ();
exit (0);
}
void
dump_abort (const char *str, mpz_t dividend, unsigned long divisor)
{
fprintf (stderr, "ERROR: %s\n", str);
fprintf (stderr, "dividend = "); debug_mp (dividend, -16);
fprintf (stderr, "divisor = %lX\n", divisor);
abort();
}
void
debug_mp (mpz_t x, int base)
{
mpz_out_str (stderr, base, x); fputc ('\n', stderr);
}