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,90 @@
## Process this file with automake to generate Makefile.in
# 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/.
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 = t-iset t-lc2exp t-mt t-rand t-urbui t-urmui t-urndmm
TESTS = $(check_PROGRAMS)
EXTRA_PROGRAMS = findlc gen gen.static spect stat
gen_static_SOURCES = gen.c
gen_static_LDFLAGS = -static
findlc_LDADD = libstat.la
spect_LDADD = libstat.la
stat_LDADD = libstat.la
EXTRA_LTLIBRARIES = libstat.la
libstat_la_SOURCES = gmpstat.h statlib.c zdiv_round.c
libstat_la_LIBADD = $(top_builddir)/libgmp.la $(LIBM)
CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES)
allprogs: $(EXTRA_PROGRAMS)
$(top_builddir)/tests/libtests.la:
cd $(top_builddir)/tests; $(MAKE) $(AM_MAKEFLAGS) libtests.la
manual-test: gen$(EXEEXT) stat$(EXEEXT)
@(echo -n '16i: '; ./gen -f mpz_urandomb -z 16 1000 \
| ./stat -i 0xffff | grep '^[0-9]')
@(echo -n '32i: '; ./gen -f mpz_urandomb -z 32 1000 \
| ./stat -i 0xffffffff | grep '^[0-9]')
@(echo -n '33i: '; ./gen -f mpz_urandomb -z 33 1000 \
| ./stat -i 0x1ffffffff | grep '^[0-9]')
@(echo -n '64i: '; ./gen -f mpz_urandomb -z 64 1000 \
| ./stat -i 0xffffffffffffffff | grep '^[0-9]')
@(echo -n '128i: '; ./gen -f mpz_urandomb -z 128 1000 \
| ./stat -i 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF | grep '^[0-9]')
@(echo -n '16f: '; ./gen -f mpf_urandomb -z 16 1000 \
| ./stat | grep '^[0-9]')
@(echo -n '32f: '; ./gen -f mpf_urandomb -z 32 1000 \
| ./stat | grep '^[0-9]')
@(echo -n '33f: '; ./gen -f mpf_urandomb -z 33 1000 \
| ./stat | grep '^[0-9]')
@(echo -n '64f: '; ./gen -f mpf_urandomb -z 64 1000 \
| ./stat | grep '^[0-9]')
@(echo -n '128f: '; ./gen -f mpf_urandomb -z 128 1000 \
| ./stat | grep '^[0-9]')
manual-bigtest: gen$(EXEEXT) stat$(EXEEXT)
@(echo '16i: '; ./gen -f mpz_urandomb -z 16 50000 \
| ./stat -2 1000 -i 0xffff | grep '^K[mp]')
@(echo '32i: '; ./gen -f mpz_urandomb -z 32 50000 \
| ./stat -2 1000 -i 0xffffffff | grep '^K[mp]')
@(echo '33i: '; ./gen -f mpz_urandomb -z 33 50000 \
| ./stat -2 1000 -i 0x1ffffffff | grep '^K[mp]')
@(echo '64i: '; ./gen -f mpz_urandomb -z 64 50000 \
| ./stat -2 1000 -i 0xffffffffffffffff | grep '^K[mp]')
@(echo '128i: '; ./gen -f mpz_urandomb -z 128 50000 \
| ./stat -2 1000 -i 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF | grep '^K[mp]')
@(echo '16f: '; ./gen -f mpf_urandomb -z 16 50000 \
| ./stat -2 1000 | grep '^K[mp]')
@(echo '32f: '; ./gen -f mpf_urandomb -z 32 50000 \
| ./stat -2 1000 | grep '^K[mp]')
@(echo '33f: '; ./gen -f mpf_urandomb -z 33 50000 \
| ./stat -2 1000 | grep '^K[mp]')
@(echo '64f: '; ./gen -f mpf_urandomb -z 64 50000 \
| ./stat -2 1000 | grep '^K[mp]')
@(echo '128f: '; ./gen -f mpf_urandomb -z 128 50000 \
| ./stat -2 1000 | grep '^K[mp]')

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,251 @@
/*
Copyright 2000 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 <unistd.h>
#include <signal.h>
#include <math.h>
#include "gmpstat.h"
#define RCSID(msg) \
static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
RCSID("$Id$");
int g_debug = 0;
static mpz_t a;
static void
sh_status (int sig)
{
printf ("sh_status: signal %d caught. dumping status.\n", sig);
printf (" a = ");
mpz_out_str (stdout, 10, a);
printf ("\n");
fflush (stdout);
if (SIGSEGV == sig) /* remove SEGV handler */
signal (SIGSEGV, SIG_DFL);
}
/* Input is a modulus (m). We shall find multiplier (a) and adder (c)
conforming to the rules found in the first comment block in file
mpz/urandom.c.
Then run a spectral test on the generator and discard any
multipliers not passing. */
/* TODO:
. find a better algorithm than a+=8; bigger jumps perhaps?
*/
void
mpz_true_random (mpz_t s, unsigned long int nbits)
{
#if __FreeBSD__
FILE *fs;
char c[1];
int i;
mpz_set_ui (s, 0);
for (i = 0; i < nbits; i += 8)
{
for (;;)
{
int nread;
fs = fopen ("/dev/random", "r");
nread = fread (c, 1, 1, fs);
fclose (fs);
if (nread != 0)
break;
sleep (1);
}
mpz_mul_2exp (s, s, 8);
mpz_add_ui (s, s, ((unsigned long int) c[0]) & 0xff);
printf ("%d random bits\n", i + 8);
}
if (nbits % 8 != 0)
mpz_mod_2exp (s, s, nbits);
#endif
}
int
main (int argc, char *argv[])
{
const char usage[] = "usage: findlc [-dv] m2exp [low_merit [high_merit]]\n";
int f;
int v_lose, m_lose, v_best, m_best;
int c;
int debug = 1;
int cnt_high_merit;
mpz_t m;
unsigned long int m2exp;
#define DIMS 6 /* dimensions run in spectral test */
mpf_t v[DIMS-1]; /* spectral test result (there's no v
for 1st dimension */
mpf_t f_merit, low_merit, high_merit;
mpz_t acc, minus8;
mpz_t min, max;
mpz_t s;
mpz_init (m);
mpz_init (a);
for (f = 0; f < DIMS-1; f++)
mpf_init (v[f]);
mpf_init (f_merit);
mpf_init_set_d (low_merit, .1);
mpf_init_set_d (high_merit, .1);
while ((c = getopt (argc, argv, "a:di:hv")) != -1)
switch (c)
{
case 'd': /* debug */
g_debug++;
break;
case 'v': /* print version */
puts (rcsid[1]);
exit (0);
case 'h':
case '?':
default:
fputs (usage, stderr);
exit (1);
}
argc -= optind;
argv += optind;
if (argc < 1)
{
fputs (usage, stderr);
exit (1);
}
/* Install signal handler. */
if (SIG_ERR == signal (SIGSEGV, sh_status))
{
perror ("signal (SIGSEGV)");
exit (1);
}
if (SIG_ERR == signal (SIGHUP, sh_status))
{
perror ("signal (SIGHUP)");
exit (1);
}
printf ("findlc: version: %s\n", rcsid[1]);
m2exp = atol (argv[0]);
mpz_init_set_ui (m, 1);
mpz_mul_2exp (m, m, m2exp);
printf ("m = 0x");
mpz_out_str (stdout, 16, m);
puts ("");
if (argc > 1) /* have low_merit */
mpf_set_str (low_merit, argv[1], 0);
if (argc > 2) /* have high_merit */
mpf_set_str (high_merit, argv[2], 0);
if (debug)
{
fprintf (stderr, "low_merit = ");
mpf_out_str (stderr, 10, 2, low_merit);
fprintf (stderr, "; high_merit = ");
mpf_out_str (stderr, 10, 2, high_merit);
fputs ("\n", stderr);
}
mpz_init (minus8);
mpz_set_si (minus8, -8L);
mpz_init_set_ui (acc, 0);
mpz_init (s);
mpz_init_set_d (min, 0.01 * pow (2.0, (double) m2exp));
mpz_init_set_d (max, 0.99 * pow (2.0, (double) m2exp));
mpz_true_random (s, m2exp); /* Start. */
mpz_setbit (s, 0); /* Make it odd. */
v_best = m_best = 2*(DIMS-1);
for (;;)
{
mpz_add (acc, acc, s);
mpz_mod_2exp (acc, acc, m2exp);
#if later
mpz_and_si (a, acc, -8L);
#else
mpz_and (a, acc, minus8);
#endif
mpz_add_ui (a, a, 5);
if (mpz_cmp (a, min) <= 0 || mpz_cmp (a, max) >= 0)
continue;
spectral_test (v, DIMS, a, m);
for (f = 0, v_lose = m_lose = 0, cnt_high_merit = DIMS-1;
f < DIMS-1; f++)
{
merit (f_merit, f + 2, v[f], m);
if (mpf_cmp_ui (v[f], 1 << (30 / (f + 2) + (f == 2))) < 0)
v_lose++;
if (mpf_cmp (f_merit, low_merit) < 0)
m_lose++;
if (mpf_cmp (f_merit, high_merit) >= 0)
cnt_high_merit--;
}
if (0 == v_lose && 0 == m_lose)
{
mpz_out_str (stdout, 10, a); puts (""); fflush (stdout);
if (0 == cnt_high_merit)
break; /* leave loop */
}
if (v_lose < v_best)
{
v_best = v_lose;
printf ("best (v_lose=%d; m_lose=%d): ", v_lose, m_lose);
mpz_out_str (stdout, 10, a); puts (""); fflush (stdout);
}
if (m_lose < m_best)
{
m_best = m_lose;
printf ("best (v_lose=%d; m_lose=%d): ", v_lose, m_lose);
mpz_out_str (stdout, 10, a); puts (""); fflush (stdout);
}
}
mpz_clear (m);
mpz_clear (a);
for (f = 0; f < DIMS-1; f++)
mpf_clear (v[f]);
mpf_clear (f_merit);
mpf_clear (low_merit);
mpf_clear (high_merit);
printf ("done.\n");
return 0;
}

View File

@@ -0,0 +1,480 @@
/* gen.c -- Generate pseudorandom numbers.
Copyright 1999, 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/. */
/* Examples:
$ gen 10
10 integers 0 <= X < 2^32 generated by mpz_urandomb()
$ gen -f mpf_urandomb 10
10 real numbers 0 <= X < 1
$ gen -z 127 10
10 integers 0 <= X < 2^127
$ gen -f mpf_urandomb -x .9,1 10
10 real numbers 0 <= X < .9
$ gen -s 1 10
10 integers, sequence seeded with 1
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#if !HAVE_DECL_OPTARG
extern char *optarg;
extern int optind, opterr;
#endif
#include "gmp-impl.h"
int main (argc, argv)
int argc;
char *argv[];
{
const char usage[] =
"usage: gen [-bhpq] [-a n] [-c a,c,m2exp] [-C a,c,m] [-f func] [-g alg] [-m n] [-s n] " \
"[-x f,t] [-z n] [n]\n" \
" n number of random numbers to generate\n" \
" -a n ASCII output in radix n (default, with n=10)\n" \
" -b binary output\n" \
" -c a,c,m2exp use supplied LC scheme\n" \
" -f func random function, one of\n" \
" mpz_urandomb (default), mpz_urandomm, mpf_urandomb, rand, random\n" \
" -g alg algorithm, one of mt (default), lc\n" \
" -h print this text and exit\n" \
" -m n maximum size of generated number plus 1 (0<= X < n) for mpz_urandomm\n" \
" -p print used seed on stderr\n" \
" -q quiet, no output\n" \
" -s n initial seed (default: output from time(3))\n" \
" -x f,t exclude all numbers f <= x <= t\n" \
" -z n size in bits of generated numbers (0<= X <2^n) (default 32)\n" \
"";
unsigned long int f;
unsigned long int n = 0;
unsigned long int seed;
unsigned long int m2exp = 0;
unsigned int size = 32;
int seed_from_user = 0;
int ascout = 1, binout = 0, printseed = 0;
int output_radix = 10;
int lc_scheme_from_user = 0;
int quiet_flag = 0;
mpz_t z_seed;
mpz_t z1;
mpf_t f1;
gmp_randstate_t rstate;
int c, i;
double drand;
long lrand;
int do_exclude = 0;
mpf_t f_xf, f_xt; /* numbers to exclude from sequence */
char *str_xf, *str_xt; /* numbers to exclude from sequence */
char *str_a, *str_adder, *str_m;
mpz_t z_a, z_m, z_mmax;
unsigned long int ul_adder;
enum
{
RFUNC_mpz_urandomb = 0,
RFUNC_mpz_urandomm,
RFUNC_mpf_urandomb,
RFUNC_rand,
RFUNC_random,
} rfunc = RFUNC_mpz_urandomb;
char *rfunc_str[] = { "mpz_urandomb", "mpz_urandomm", "mpf_urandomb",
"rand", "random" };
enum
{
RNG_MT = 0,
RNG_LC
};
gmp_randalg_t ralg = RNG_MT;
/* Texts for the algorithms. The index of each must match the
corresponding algorithm in the enum above. */
char *ralg_str[] = { "mt", "lc" };
mpf_init (f_xf);
mpf_init (f_xt);
mpf_init (f1);
mpz_init (z1);
mpz_init (z_seed);
mpz_init_set_ui (z_mmax, 0);
while ((c = getopt (argc, argv, "a:bc:f:g:hm:n:pqs:z:x:")) != -1)
switch (c)
{
case 'a':
ascout = 1;
binout = 0;
output_radix = atoi (optarg);
break;
case 'b':
ascout = 0;
binout = 1;
break;
case 'c': /* User supplied LC scheme: a,c,m2exp */
if (NULL == (str_a = strtok (optarg, ","))
|| NULL == (str_adder = strtok (NULL, ","))
|| NULL == (str_m = strtok (NULL, ",")))
{
fprintf (stderr, "gen: bad LC scheme parameters: %s\n", optarg);
exit (1);
}
#ifdef HAVE_STRTOUL
ul_adder = strtoul (str_adder, NULL, 0);
#elif HAVE_STRTOL
ul_adder = (unsigned long int) strtol (str_adder, NULL, 0);
#else
ul_adder = (unsigned long int) atoi (str_adder);
#endif
if (mpz_init_set_str (z_a, str_a, 0))
{
fprintf (stderr, "gen: bad LC scheme parameter `a': %s\n", str_a);
exit (1);
}
if (ULONG_MAX == ul_adder)
{
fprintf (stderr, "gen: bad LC scheme parameter `c': %s\n",
str_adder);
exit (1);
}
m2exp = atol (str_m);
lc_scheme_from_user = 1;
break;
case 'f':
rfunc = -1;
for (f = 0; f < sizeof (rfunc_str) / sizeof (*rfunc_str); f++)
if (!strcmp (optarg, rfunc_str[f]))
{
rfunc = f;
break;
}
if (rfunc == -1)
{
fputs (usage, stderr);
exit (1);
}
break;
case 'g': /* algorithm */
ralg = -1;
for (f = 0; f < sizeof (ralg_str) / sizeof (*ralg_str); f++)
if (!strcmp (optarg, ralg_str[f]))
{
ralg = f;
break;
}
if (ralg == -1)
{
fputs (usage, stderr);
exit (1);
}
break;
case 'm': /* max for mpz_urandomm() */
if (mpz_set_str (z_mmax, optarg, 0))
{
fprintf (stderr, "gen: bad max value: %s\n", optarg);
exit (1);
}
break;
case 'p': /* print seed on stderr */
printseed = 1;
break;
case 'q': /* quiet */
quiet_flag = 1;
break;
case 's': /* user provided seed */
if (mpz_set_str (z_seed, optarg, 0))
{
fprintf (stderr, "gen: bad seed argument %s\n", optarg);
exit (1);
}
seed_from_user = 1;
break;
case 'z':
size = atoi (optarg);
if (size < 1)
{
fprintf (stderr, "gen: bad size argument (-z %u)\n", size);
exit (1);
}
break;
case 'x': /* Exclude. from,to */
str_xf = optarg;
str_xt = strchr (optarg, ',');
if (NULL == str_xt)
{
fprintf (stderr, "gen: bad exclusion parameters: %s\n", optarg);
exit (1);
}
*str_xt++ = '\0';
do_exclude = 1;
break;
case 'h':
case '?':
default:
fputs (usage, stderr);
exit (1);
}
argc -= optind;
argv += optind;
if (! seed_from_user)
mpz_set_ui (z_seed, (unsigned long int) time (NULL));
seed = mpz_get_ui (z_seed);
if (printseed)
{
fprintf (stderr, "gen: seed used: ");
mpz_out_str (stderr, output_radix, z_seed);
fprintf (stderr, "\n");
}
mpf_set_prec (f1, size);
/* init random state and plant seed */
switch (rfunc)
{
case RFUNC_mpf_urandomb:
#if 0
/* Don't init a too small generator. */
size = PREC (f1) * GMP_LIMB_BITS;
/* Fall through. */
#endif
case RFUNC_mpz_urandomb:
case RFUNC_mpz_urandomm:
switch (ralg)
{
case RNG_MT:
gmp_randinit_mt (rstate);
break;
case RNG_LC:
if (! lc_scheme_from_user)
gmp_randinit_lc_2exp_size (rstate, MIN (128, size));
else
gmp_randinit_lc_2exp (rstate, z_a, ul_adder, m2exp);
break;
default:
fprintf (stderr, "gen: unsupported algorithm\n");
exit (1);
}
gmp_randseed (rstate, z_seed);
break;
case RFUNC_rand:
srand (seed);
break;
case RFUNC_random:
#ifdef __FreeBSD__ /* FIXME */
if (seed_from_user)
srandom (seed);
else
srandomdev ();
#else
fprintf (stderr, "gen: unsupported algorithm\n");
#endif
break;
default:
fprintf (stderr, "gen: random function not implemented\n");
exit (1);
}
/* set up excludes */
if (do_exclude)
switch (rfunc)
{
case RFUNC_mpf_urandomb:
if (mpf_set_str (f_xf, str_xf, 10) ||
mpf_set_str (f_xt, str_xt, 10))
{
fprintf (stderr, "gen: bad exclusion-from (\"%s\") " \
"or exclusion-to (\"%s\") string. no exclusion done.\n",
str_xf, str_xt);
do_exclude = 0;
}
break;
default:
fprintf (stderr, "gen: exclusion not implemented for chosen " \
"randomization function. all numbers included in sequence.\n");
}
/* generate and print */
if (argc > 0)
{
#if HAVE_STRTOUL
n = strtoul (argv[0], (char **) NULL, 10);
#elif HAVE_STRTOL
n = (unsigned long int) strtol (argv[0], (char **) NULL, 10);
#else
n = (unsigned long int) atoi (argv[0]);
#endif
}
for (f = 0; n == 0 || f < n; f++)
{
switch (rfunc)
{
case RFUNC_mpz_urandomb:
mpz_urandomb (z1, rstate, size);
if (quiet_flag)
break;
if (binout)
{
/*fwrite ((unsigned int *) z1->_mp_d, 4, 1, stdout);*/
fprintf (stderr, "gen: binary output for mpz_urandom* is broken\n");
exit (1);
}
else
{
mpz_out_str (stdout, output_radix, z1);
puts ("");
}
break;
case RFUNC_mpz_urandomm:
mpz_urandomm (z1, rstate, z_mmax);
if (quiet_flag)
break;
if (binout)
{
/*fwrite ((unsigned int *) z1->_mp_d, 4, 1, stdout);*/
fprintf (stderr, "gen: binary output for mpz_urandom* is broken\n");
exit (1);
}
else
{
mpz_out_str (stdout, output_radix, z1);
puts ("");
}
break;
case RFUNC_mpf_urandomb:
mpf_urandomb (f1, rstate, size);
if (do_exclude)
if (mpf_cmp (f1, f_xf) >= 0 && mpf_cmp (f1, f_xt) <= 0)
break;
if (quiet_flag)
break;
if (binout)
{
fprintf (stderr, "gen: binary output for floating point numbers "\
"not implemented\n");
exit (1);
}
else
{
mpf_out_str (stdout, output_radix, 0, f1);
puts ("");
}
break;
case RFUNC_rand:
i = rand ();
#ifdef FLOAT_OUTPUT
if (i)
drand = (double) i / (double) RAND_MAX;
else
drand = 0.0;
if (quiet_flag)
break;
if (binout)
fwrite (&drand, sizeof (drand), 1, stdout);
else
printf ("%e\n", drand);
#else
if (quiet_flag)
break;
if (binout)
fwrite (&i, sizeof (i), 1, stdout);
else
printf ("%d\n", i);
#endif
break;
case RFUNC_random:
lrand = random ();
if (lrand)
drand = (double) lrand / (double) 0x7fffffff;
else
drand = 0;
if (quiet_flag)
break;
if (binout)
fwrite (&drand, sizeof (drand), 1, stdout);
else
printf ("%e\n", drand);
break;
default:
fprintf (stderr, "gen: random function not implemented\n");
exit (1);
}
}
/* clean up */
switch (rfunc)
{
case RFUNC_mpz_urandomb:
case RFUNC_mpf_urandomb:
gmp_randclear (rstate);
break;
default:
break;
}
mpf_clear (f1);
mpf_clear (f_xf);
mpf_clear (f_xt);
mpz_clear (z1);
mpz_clear (z_seed);
return 0;
}
static void *debug_dummyz = mpz_dump;
static void *debug_dummyf = mpf_dump;

View File

@@ -0,0 +1,75 @@
/* gmpstat.h */
/*
Copyright 1999 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/. */
/* This file requires the following header files: gmp.h */
#ifndef __GMPSTAT_H__
#define __GMPSTAT_H__
/* Global debug flag. FIXME: Remove. */
extern int g_debug;
#define DEBUG_1 0
#define DEBUG_2 1
/* Max number of dimensions in spectral test. FIXME: Makw dynamic. */
#define GMP_SPECT_MAXT 10
void
mpf_freqt (mpf_t Kp,
mpf_t Km,
mpf_t X[],
const unsigned long int n);
unsigned long int
mpz_freqt (mpf_t V,
mpz_t X[],
unsigned int imax,
const unsigned long int n);
/* Low level functions. */
void
ks (mpf_t Kp,
mpf_t Km,
mpf_t X[],
void (P) (mpf_t, mpf_t),
const unsigned long int n);
void
ks_table (mpf_t p, mpf_t val, const unsigned int n);
void
x2_table (double t[],
unsigned int v);
void
spectral_test (mpf_t rop[], unsigned int T, mpz_t a, mpz_t m);
void
vz_dot (mpz_t rop, mpz_t V1[], mpz_t V2[], unsigned int n);
void
f_floor (mpf_t rop, mpf_t op);
void
merit (mpf_t rop, unsigned int t, mpf_t v, mpz_t m);
double
merit_u (unsigned int t, mpf_t v, mpz_t m);
/* From separate source files: */
void zdiv_round (mpz_t rop, mpz_t n, mpz_t d);
#endif /* !__GMPSTAT_H__ */

View File

@@ -0,0 +1,136 @@
/* spect.c -- the spectral test */
/*
Copyright 1999 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/. */
/* T is upper dimension. Z_A is the LC multiplier, which is
relatively prime to Z_M, the LC modulus. The result is put in
rop[] with v[t] in rop[t-2]. */
/* BUGS: Due to lazy allocation scheme, maximum T is hard coded to MAXT. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include "gmpstat.h"
int g_debug = 0;
int
main (int argc, char *argv[])
{
const char usage[] = "usage: spect [-d] a m n\n";
int c;
unsigned int n;
mpz_t a, m;
mpf_t res[GMP_SPECT_MAXT], res_min[GMP_SPECT_MAXT], f_tmp;
int f;
mpz_init (a);
mpz_init (m);
for (f = 0; f < GMP_SPECT_MAXT; f++)
{
mpf_init (res[f]);
mpf_init (res_min[f]);
}
mpf_init (f_tmp);
mpf_set_ui (res_min[0], 32768); /* 2^15 */
mpf_set_ui (res_min[1], 1024); /* 2^10 */
mpf_set_ui (res_min[2], 256); /* 2^8 */
mpf_set_ui (res_min[3], 64); /* 2^6 */
mpf_set_ui (res_min[4], 32); /* 2^5 */
while ((c = getopt (argc, argv, "dh")) != -1)
switch (c)
{
case 'd': /* debug */
g_debug++;
break;
case 'h':
default:
fputs (usage, stderr);
exit (1);
}
argc -= optind;
argv += optind;
if (argc < 3)
{
fputs (usage, stderr);
exit (1);
}
mpz_set_str (a, argv[0], 0);
mpz_set_str (m, argv[1], 0);
n = (unsigned int) atoi (argv[2]);
if (n + 1 > GMP_SPECT_MAXT)
n = GMP_SPECT_MAXT + 1;
spectral_test (res, n, a, m);
for (f = 0; f < n - 1; f++)
{
/* print v */
printf ("%d: v = ", f + 2);
mpf_out_str (stdout, 10, 4, res[f]);
#ifdef PRINT_RAISED_BY_TWO_AS_WELL
printf (" (^2 = ");
mpf_mul (f_tmp, res[f], res[f]);
mpf_out_str (stdout, 10, 4, f_tmp);
printf (")");
#endif /* PRINT_RAISED_BY_TWO_AS_WELL */
/* print merit */
printf (" m = ");
merit (f_tmp, f + 2, res[f], m);
mpf_out_str (stdout, 10, 4, f_tmp);
if (mpf_cmp (res[f], res_min[f]) < 0)
printf ("\t*** v too low ***");
if (mpf_get_d (f_tmp) < .1)
printf ("\t*** merit too low ***");
puts ("");
}
mpz_clear (a);
mpz_clear (m);
for (f = 0; f < GMP_SPECT_MAXT; f++)
{
mpf_clear (res[f]);
mpf_clear (res_min[f]);
}
mpf_clear (f_tmp);
return 0;
}
void
debug_foo()
{
if (0)
{
mpz_dump (0);
mpf_dump (0);
}
}

View File

@@ -0,0 +1,406 @@
/* stat.c -- statistical tests of random number sequences. */
/*
Copyright 1999, 2000 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/. */
/* Examples:
$ gen 1000 | stat
Test 1000 real numbers.
$ gen 30000 | stat -2 1000
Test 1000 real numbers 30 times and then test the 30 results in a
``second level''.
$ gen -f mpz_urandomb 1000 | stat -i 0xffffffff
Test 1000 integers 0 <= X <= 2^32-1.
$ gen -f mpz_urandomb -z 34 1000 | stat -i 0x3ffffffff
Test 1000 integers 0 <= X <= 2^34-1.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include "gmpstat.h"
#if !HAVE_DECL_OPTARG
extern char *optarg;
extern int optind, opterr;
#endif
#define FVECSIZ (100000L)
int g_debug = 0;
static void
print_ks_results (mpf_t f_p, mpf_t f_p_prob,
mpf_t f_m, mpf_t f_m_prob,
FILE *fp)
{
double p, pp, m, mp;
p = mpf_get_d (f_p);
m = mpf_get_d (f_m);
pp = mpf_get_d (f_p_prob);
mp = mpf_get_d (f_m_prob);
fprintf (fp, "%.4f (%.0f%%)\t", p, pp * 100.0);
fprintf (fp, "%.4f (%.0f%%)\n", m, mp * 100.0);
}
static void
print_x2_table (unsigned int v, FILE *fp)
{
double t[7];
int f;
fprintf (fp, "Chi-square table for v=%u\n", v);
fprintf (fp, "1%%\t5%%\t25%%\t50%%\t75%%\t95%%\t99%%\n");
x2_table (t, v);
for (f = 0; f < 7; f++)
fprintf (fp, "%.2f\t", t[f]);
fputs ("\n", fp);
}
/* Pks () -- Distribution function for KS results with a big n (like 1000
or so): F(x) = 1 - pow(e, -2*x^2) [Knuth, vol 2, p.51]. */
/* gnuplot: plot [0:1] Pks(x), Pks(x) = 1-exp(-2*x**2) */
static void
Pks (mpf_t p, mpf_t x)
{
double dt; /* temp double */
mpf_set (p, x);
mpf_mul (p, p, p); /* p = x^2 */
mpf_mul_ui (p, p, 2); /* p = 2*x^2 */
mpf_neg (p, p); /* p = -2*x^2 */
/* No pow() in gmp. Use doubles. */
/* FIXME: Use exp()? */
dt = pow (M_E, mpf_get_d (p));
mpf_set_d (p, dt);
mpf_ui_sub (p, 1, p);
}
/* f_freq() -- frequency test on real numbers 0<=f<1*/
static void
f_freq (const unsigned l1runs, const unsigned l2runs,
mpf_t fvec[], const unsigned long n)
{
unsigned f;
mpf_t f_p, f_p_prob;
mpf_t f_m, f_m_prob;
mpf_t *l1res; /* level 1 result array */
mpf_init (f_p); mpf_init (f_m);
mpf_init (f_p_prob); mpf_init (f_m_prob);
/* Allocate space for 1st level results. */
l1res = (mpf_t *) malloc (l2runs * 2 * sizeof (mpf_t));
if (NULL == l1res)
{
fprintf (stderr, "stat: malloc failure\n");
exit (1);
}
printf ("\nEquidistribution/Frequency test on real numbers (0<=X<1):\n");
printf ("\tKp\t\tKm\n");
for (f = 0; f < l2runs; f++)
{
/* f_printvec (fvec, n); */
mpf_freqt (f_p, f_m, fvec + f * n, n);
/* what's the probability of getting these results? */
ks_table (f_p_prob, f_p, n);
ks_table (f_m_prob, f_m, n);
if (l1runs == 0)
{
/*printf ("%u:\t", f + 1);*/
print_ks_results (f_p, f_p_prob, f_m, f_m_prob, stdout);
}
else
{
/* save result */
mpf_init_set (l1res[f], f_p);
mpf_init_set (l1res[f + l2runs], f_m);
}
}
/* Now, apply the KS test on the results from the 1st level rounds
with the distribution
F(x) = 1 - pow(e, -2*x^2) [Knuth, vol 2, p.51] */
if (l1runs != 0)
{
/*printf ("-------------------------------------\n");*/
/* The Kp's. */
ks (f_p, f_m, l1res, Pks, l2runs);
ks_table (f_p_prob, f_p, l2runs);
ks_table (f_m_prob, f_m, l2runs);
printf ("Kp:\t");
print_ks_results (f_p, f_p_prob, f_m, f_m_prob, stdout);
/* The Km's. */
ks (f_p, f_m, l1res + l2runs, Pks, l2runs);
ks_table (f_p_prob, f_p, l2runs);
ks_table (f_m_prob, f_m, l2runs);
printf ("Km:\t");
print_ks_results (f_p, f_p_prob, f_m, f_m_prob, stdout);
}
mpf_clear (f_p); mpf_clear (f_m);
mpf_clear (f_p_prob); mpf_clear (f_m_prob);
free (l1res);
}
/* z_freq(l1runs, l2runs, zvec, n, max) -- frequency test on integers
0<=z<=MAX */
static void
z_freq (const unsigned l1runs,
const unsigned l2runs,
mpz_t zvec[],
const unsigned long n,
unsigned int max)
{
mpf_t V; /* result */
double d_V; /* result as a double */
mpf_init (V);
printf ("\nEquidistribution/Frequency test on integers (0<=X<=%u):\n", max);
print_x2_table (max, stdout);
mpz_freqt (V, zvec, max, n);
d_V = mpf_get_d (V);
printf ("V = %.2f (n = %lu)\n", d_V, n);
mpf_clear (V);
}
unsigned int stat_debug = 0;
int
main (argc, argv)
int argc;
char *argv[];
{
const char usage[] =
"usage: stat [-d] [-2 runs] [-i max | -r max] [file]\n" \
" file filename\n" \
" -2 runs perform 2-level test with RUNS runs on 1st level\n" \
" -d increase debugging level\n" \
" -i max input is integers 0 <= Z <= MAX\n" \
" -r max input is real numbers 0 <= R < 1 and use MAX as\n" \
" maximum value when converting real numbers to integers\n" \
"";
mpf_t fvec[FVECSIZ];
mpz_t zvec[FVECSIZ];
unsigned long int f, n, vecentries;
char *filen;
FILE *fp;
int c;
int omitoutput = 0;
int realinput = -1; /* 1: input is real numbers 0<=R<1;
0: input is integers 0 <= Z <= MAX. */
long l1runs = 0, /* 1st level runs */
l2runs = 1; /* 2nd level runs */
mpf_t f_temp;
mpz_t z_imax; /* max value when converting between
real number and integer. */
mpf_t f_imax_plus1; /* f_imax + 1 stored in an mpf_t for
convenience */
mpf_t f_imax_minus1; /* f_imax - 1 stored in an mpf_t for
convenience */
mpf_init (f_temp);
mpz_init_set_ui (z_imax, 0x7fffffff);
mpf_init (f_imax_plus1);
mpf_init (f_imax_minus1);
while ((c = getopt (argc, argv, "d2:i:r:")) != -1)
switch (c)
{
case '2':
l1runs = atol (optarg);
l2runs = -1; /* set later on */
break;
case 'd': /* increase debug level */
stat_debug++;
break;
case 'i':
if (1 == realinput)
{
fputs ("stat: options -i and -r are mutually exclusive\n", stderr);
exit (1);
}
if (mpz_set_str (z_imax, optarg, 0))
{
fprintf (stderr, "stat: bad max value %s\n", optarg);
exit (1);
}
realinput = 0;
break;
case 'r':
if (0 == realinput)
{
fputs ("stat: options -i and -r are mutually exclusive\n", stderr);
exit (1);
}
if (mpz_set_str (z_imax, optarg, 0))
{
fprintf (stderr, "stat: bad max value %s\n", optarg);
exit (1);
}
realinput = 1;
break;
case 'o':
omitoutput = atoi (optarg);
break;
case '?':
default:
fputs (usage, stderr);
exit (1);
}
argc -= optind;
argv += optind;
if (argc < 1)
fp = stdin;
else
filen = argv[0];
if (fp != stdin)
if (NULL == (fp = fopen (filen, "r")))
{
perror (filen);
exit (1);
}
if (-1 == realinput)
realinput = 1; /* default is real numbers */
/* read file and fill appropriate vec */
if (1 == realinput) /* real input */
{
for (f = 0; f < FVECSIZ ; f++)
{
mpf_init (fvec[f]);
if (!mpf_inp_str (fvec[f], fp, 10))
break;
}
}
else /* integer input */
{
for (f = 0; f < FVECSIZ ; f++)
{
mpz_init (zvec[f]);
if (!mpz_inp_str (zvec[f], fp, 10))
break;
}
}
vecentries = n = f; /* number of entries read */
fclose (fp);
if (FVECSIZ == f)
fprintf (stderr, "stat: warning: discarding input due to lazy allocation "\
"of only %ld entries. sorry.\n", FVECSIZ);
printf ("Got %lu numbers.\n", n);
/* convert and fill the other vec */
/* since fvec[] contains 0<=f<1 and we want ivec[] to contain
0<=z<=imax and we are truncating all fractions when
converting float to int, we have to add 1 to imax.*/
mpf_set_z (f_imax_plus1, z_imax);
mpf_add_ui (f_imax_plus1, f_imax_plus1, 1);
if (1 == realinput) /* fill zvec[] */
{
for (f = 0; f < n; f++)
{
mpf_mul (f_temp, fvec[f], f_imax_plus1);
mpz_init (zvec[f]);
mpz_set_f (zvec[f], f_temp); /* truncating fraction */
if (stat_debug > 1)
{
mpz_out_str (stderr, 10, zvec[f]);
fputs ("\n", stderr);
}
}
}
else /* integer input; fill fvec[] */
{
/* mpf_set_z (f_imax_minus1, z_imax);
mpf_sub_ui (f_imax_minus1, f_imax_minus1, 1);*/
for (f = 0; f < n; f++)
{
mpf_init (fvec[f]);
mpf_set_z (fvec[f], zvec[f]);
mpf_div (fvec[f], fvec[f], f_imax_plus1);
if (stat_debug > 1)
{
mpf_out_str (stderr, 10, 0, fvec[f]);
fputs ("\n", stderr);
}
}
}
/* 2 levels? */
if (1 != l2runs)
{
l2runs = n / l1runs;
printf ("Doing %ld second level rounds "\
"with %ld entries in each round", l2runs, l1runs);
if (n % l1runs)
printf (" (discarding %ld entr%s)", n % l1runs,
n % l1runs == 1 ? "y" : "ies");
puts (".");
n = l1runs;
}
#ifndef DONT_FFREQ
f_freq (l1runs, l2runs, fvec, n);
#endif
#ifdef DO_ZFREQ
z_freq (l1runs, l2runs, zvec, n, mpz_get_ui (z_imax));
#endif
mpf_clear (f_temp); mpz_clear (z_imax);
mpf_clear (f_imax_plus1);
mpf_clear (f_imax_minus1);
for (f = 0; f < vecentries; f++)
{
mpf_clear (fvec[f]);
mpz_clear (zvec[f]);
}
return 0;
}

View File

@@ -0,0 +1,836 @@
/* statlib.c -- Statistical functions for testing the randomness of
number sequences. */
/*
Copyright 1999, 2000 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/. */
/* The theories for these functions are taken from D. Knuth's "The Art
of Computer Programming: Volume 2, Seminumerical Algorithms", Third
Edition, Addison Wesley, 1998. */
/* Implementation notes.
The Kolmogorov-Smirnov test.
Eq. (13) in Knuth, p. 50, says that if X1, X2, ..., Xn are independent
observations arranged into ascending order
Kp = sqr(n) * max(j/n - F(Xj)) for all 1<=j<=n
Km = sqr(n) * max(F(Xj) - (j-1)/n)) for all 1<=j<=n
where F(x) = Pr(X <= x) = probability that (X <= x), which for a
uniformly distributed random real number between zero and one is
exactly the number itself (x).
The answer to exercise 23 gives the following implementation, which
doesn't need the observations to be sorted in ascending order:
for (k = 0; k < m; k++)
a[k] = 1.0
b[k] = 0.0
c[k] = 0
for (each observation Xj)
Y = F(Xj)
k = floor (m * Y)
a[k] = min (a[k], Y)
b[k] = max (b[k], Y)
c[k] += 1
j = 0
rp = rm = 0
for (k = 0; k < m; k++)
if (c[k] > 0)
rm = max (rm, a[k] - j/n)
j += c[k]
rp = max (rp, j/n - b[k])
Kp = sqr (n) * rp
Km = sqr (n) * rm
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "gmpstat.h"
/* ks (Kp, Km, X, P, n) -- Perform a Kolmogorov-Smirnov test on the N
real numbers between zero and one in vector X. P is the
distribution function, called for each entry in X, which should
calculate the probability of X being greater than or equal to any
number in the sequence. (For a uniformly distributed sequence of
real numbers between zero and one, this is simply equal to X.) The
result is put in Kp and Km. */
void
ks (mpf_t Kp,
mpf_t Km,
mpf_t X[],
void (P) (mpf_t, mpf_t),
unsigned long int n)
{
mpf_t Kt; /* temp */
mpf_t f_x;
mpf_t f_j; /* j */
mpf_t f_jnq; /* j/n or (j-1)/n */
unsigned long int j;
/* Sort the vector in ascending order. */
qsort (X, n, sizeof (__mpf_struct), mpf_cmp);
/* K-S test. */
/* Kp = sqr(n) * max(j/n - F(Xj)) for all 1<=j<=n
Km = sqr(n) * max(F(Xj) - (j-1)/n)) for all 1<=j<=n
*/
mpf_init (Kt); mpf_init (f_x); mpf_init (f_j); mpf_init (f_jnq);
mpf_set_ui (Kp, 0); mpf_set_ui (Km, 0);
for (j = 1; j <= n; j++)
{
P (f_x, X[j-1]);
mpf_set_ui (f_j, j);
mpf_div_ui (f_jnq, f_j, n);
mpf_sub (Kt, f_jnq, f_x);
if (mpf_cmp (Kt, Kp) > 0)
mpf_set (Kp, Kt);
if (g_debug > DEBUG_2)
{
printf ("j=%lu ", j);
printf ("P()="); mpf_out_str (stdout, 10, 2, f_x); printf ("\t");
printf ("jnq="); mpf_out_str (stdout, 10, 2, f_jnq); printf (" ");
printf ("diff="); mpf_out_str (stdout, 10, 2, Kt); printf (" ");
printf ("Kp="); mpf_out_str (stdout, 10, 2, Kp); printf ("\t");
}
mpf_sub_ui (f_j, f_j, 1);
mpf_div_ui (f_jnq, f_j, n);
mpf_sub (Kt, f_x, f_jnq);
if (mpf_cmp (Kt, Km) > 0)
mpf_set (Km, Kt);
if (g_debug > DEBUG_2)
{
printf ("jnq="); mpf_out_str (stdout, 10, 2, f_jnq); printf (" ");
printf ("diff="); mpf_out_str (stdout, 10, 2, Kt); printf (" ");
printf ("Km="); mpf_out_str (stdout, 10, 2, Km); printf (" ");
printf ("\n");
}
}
mpf_sqrt_ui (Kt, n);
mpf_mul (Kp, Kp, Kt);
mpf_mul (Km, Km, Kt);
mpf_clear (Kt); mpf_clear (f_x); mpf_clear (f_j); mpf_clear (f_jnq);
}
/* ks_table(val, n) -- calculate probability for Kp/Km less than or
equal to VAL with N observations. See [Knuth section 3.3.1] */
void
ks_table (mpf_t p, mpf_t val, const unsigned int n)
{
/* We use Eq. (27), Knuth p.58, skipping O(1/n) for simplicity.
This shortcut will result in too high probabilities, especially
when n is small.
Pr(Kp(n) <= s) = 1 - pow(e, -2*s^2) * (1 - 2/3*s/sqrt(n) + O(1/n)) */
/* We have 's' in variable VAL and store the result in P. */
mpf_t t1, t2;
mpf_init (t1); mpf_init (t2);
/* t1 = 1 - 2/3 * s/sqrt(n) */
mpf_sqrt_ui (t1, n);
mpf_div (t1, val, t1);
mpf_mul_ui (t1, t1, 2);
mpf_div_ui (t1, t1, 3);
mpf_ui_sub (t1, 1, t1);
/* t2 = pow(e, -2*s^2) */
#ifndef OLDGMP
mpf_pow_ui (t2, val, 2); /* t2 = s^2 */
mpf_set_d (t2, exp (-(2.0 * mpf_get_d (t2))));
#else
/* hmmm, gmp doesn't have pow() for floats. use doubles. */
mpf_set_d (t2, pow (M_E, -(2 * pow (mpf_get_d (val), 2))));
#endif
/* p = 1 - t1 * t2 */
mpf_mul (t1, t1, t2);
mpf_ui_sub (p, 1, t1);
mpf_clear (t1); mpf_clear (t2);
}
static double x2_table_X[][7] = {
{ -2.33, -1.64, -.674, 0.0, 0.674, 1.64, 2.33 }, /* x */
{ 5.4289, 2.6896, .454276, 0.0, .454276, 2.6896, 5.4289} /* x^2 */
};
#define _2D3 ((double) .6666666666)
/* x2_table (t, v, n) -- return chi-square table row for V in T[]. */
void
x2_table (double t[],
unsigned int v)
{
int f;
/* FIXME: Do a table lookup for v <= 30 since the following formula
[Knuth, vol 2, 3.3.1] is only good for v > 30. */
/* value = v + sqrt(2*v) * X[p] + (2/3) * X[p]^2 - 2/3 + O(1/sqrt(t) */
/* NOTE: The O() term is ignored for simplicity. */
for (f = 0; f < 7; f++)
t[f] =
v +
sqrt (2 * v) * x2_table_X[0][f] +
_2D3 * x2_table_X[1][f] - _2D3;
}
/* P(p, x) -- Distribution function. Calculate the probability of X
being greater than or equal to any number in the sequence. For a
random real number between zero and one given by a uniformly
distributed random number generator, this is simply equal to X. */
static void
P (mpf_t p, mpf_t x)
{
mpf_set (p, x);
}
/* mpf_freqt() -- Frequency test using KS on N real numbers between zero
and one. See [Knuth vol 2, p.61]. */
void
mpf_freqt (mpf_t Kp,
mpf_t Km,
mpf_t X[],
const unsigned long int n)
{
ks (Kp, Km, X, P, n);
}
/* The Chi-square test. Eq. (8) in Knuth vol. 2 says that if Y[]
holds the observations and p[] is the probability for.. (to be
continued!)
V = 1/n * sum((s=1 to k) Y[s]^2 / p[s]) - n */
void
x2 (mpf_t V, /* result */
unsigned long int X[], /* data */
unsigned int k, /* #of categories */
void (P) (mpf_t, unsigned long int, void *), /* probability func */
void *x, /* extra user data passed to P() */
unsigned long int n) /* #of samples */
{
unsigned int f;
mpf_t f_t, f_t2; /* temp floats */
mpf_init (f_t); mpf_init (f_t2);
mpf_set_ui (V, 0);
for (f = 0; f < k; f++)
{
if (g_debug > DEBUG_2)
fprintf (stderr, "%u: P()=", f);
mpf_set_ui (f_t, X[f]);
mpf_mul (f_t, f_t, f_t); /* f_t = X[f]^2 */
P (f_t2, f, x); /* f_t2 = Pr(f) */
if (g_debug > DEBUG_2)
mpf_out_str (stderr, 10, 2, f_t2);
mpf_div (f_t, f_t, f_t2);
mpf_add (V, V, f_t);
if (g_debug > DEBUG_2)
{
fprintf (stderr, "\tV=");
mpf_out_str (stderr, 10, 2, V);
fprintf (stderr, "\t");
}
}
if (g_debug > DEBUG_2)
fprintf (stderr, "\n");
mpf_div_ui (V, V, n);
mpf_sub_ui (V, V, n);
mpf_clear (f_t); mpf_clear (f_t2);
}
/* Pzf(p, s, x) -- Probability for category S in mpz_freqt(). It's
1/d for all S. X is a pointer to an unsigned int holding 'd'. */
static void
Pzf (mpf_t p, unsigned long int s, void *x)
{
mpf_set_ui (p, 1);
mpf_div_ui (p, p, *((unsigned int *) x));
}
/* mpz_freqt(V, X, imax, n) -- Frequency test on integers. [Knuth,
vol 2, 3.3.2]. Keep IMAX low on this one, since we loop from 0 to
IMAX. 128 or 256 could be nice.
X[] must not contain numbers outside the range 0 <= X <= IMAX.
Return value is number of observations actually used, after
discarding entries out of range.
Since X[] contains integers between zero and IMAX, inclusive, we
have IMAX+1 categories.
Note that N should be at least 5*IMAX. Result is put in V and can
be compared to output from x2_table (v=IMAX). */
unsigned long int
mpz_freqt (mpf_t V,
mpz_t X[],
unsigned int imax,
const unsigned long int n)
{
unsigned long int *v; /* result */
unsigned int f;
unsigned int d; /* number of categories = imax+1 */
unsigned int uitemp;
unsigned long int usedn;
d = imax + 1;
v = (unsigned long int *) calloc (imax + 1, sizeof (unsigned long int));
if (NULL == v)
{
fprintf (stderr, "mpz_freqt(): out of memory\n");
exit (1);
}
/* count */
usedn = n; /* actual number of observations */
for (f = 0; f < n; f++)
{
uitemp = mpz_get_ui(X[f]);
if (uitemp > imax) /* sanity check */
{
if (g_debug)
fprintf (stderr, "mpz_freqt(): warning: input insanity: %u, "\
"ignored.\n", uitemp);
usedn--;
continue;
}
v[uitemp]++;
}
if (g_debug > DEBUG_2)
{
fprintf (stderr, "counts:\n");
for (f = 0; f <= imax; f++)
fprintf (stderr, "%u:\t%lu\n", f, v[f]);
}
/* chi-square with k=imax+1 and P(x)=1/(imax+1) for all x.*/
x2 (V, v, d, Pzf, (void *) &d, usedn);
free (v);
return (usedn);
}
/* debug dummy to drag in dump funcs */
void
foo_debug ()
{
if (0)
{
mpf_dump (0);
#ifndef OLDGMP
mpz_dump (0);
#endif
}
}
/* merit (rop, t, v, m) -- calculate merit for spectral test result in
dimension T, see Knuth p. 105. BUGS: Only valid for 2 <= T <=
6. */
void
merit (mpf_t rop, unsigned int t, mpf_t v, mpz_t m)
{
int f;
mpf_t f_m, f_const, f_pi;
mpf_init (f_m);
mpf_set_z (f_m, m);
mpf_init_set_d (f_const, M_PI);
mpf_init_set_d (f_pi, M_PI);
switch (t)
{
case 2: /* PI */
break;
case 3: /* PI * 4/3 */
mpf_mul_ui (f_const, f_const, 4);
mpf_div_ui (f_const, f_const, 3);
break;
case 4: /* PI^2 * 1/2 */
mpf_mul (f_const, f_const, f_pi);
mpf_div_ui (f_const, f_const, 2);
break;
case 5: /* PI^2 * 8/15 */
mpf_mul (f_const, f_const, f_pi);
mpf_mul_ui (f_const, f_const, 8);
mpf_div_ui (f_const, f_const, 15);
break;
case 6: /* PI^3 * 1/6 */
mpf_mul (f_const, f_const, f_pi);
mpf_mul (f_const, f_const, f_pi);
mpf_div_ui (f_const, f_const, 6);
break;
default:
fprintf (stderr,
"spect (merit): can't calculate merit for dimensions > 6\n");
mpf_set_ui (f_const, 0);
break;
}
/* rop = v^t */
mpf_set (rop, v);
for (f = 1; f < t; f++)
mpf_mul (rop, rop, v);
mpf_mul (rop, rop, f_const);
mpf_div (rop, rop, f_m);
mpf_clear (f_m);
mpf_clear (f_const);
mpf_clear (f_pi);
}
double
merit_u (unsigned int t, mpf_t v, mpz_t m)
{
mpf_t rop;
double res;
mpf_init (rop);
merit (rop, t, v, m);
res = mpf_get_d (rop);
mpf_clear (rop);
return res;
}
/* f_floor (rop, op) -- Set rop = floor (op). */
void
f_floor (mpf_t rop, mpf_t op)
{
mpz_t z;
mpz_init (z);
/* No mpf_floor(). Convert to mpz and back. */
mpz_set_f (z, op);
mpf_set_z (rop, z);
mpz_clear (z);
}
/* vz_dot (rop, v1, v2, nelem) -- compute dot product of z-vectors V1,
V2. N is number of elements in vectors V1 and V2. */
void
vz_dot (mpz_t rop, mpz_t V1[], mpz_t V2[], unsigned int n)
{
mpz_t t;
mpz_init (t);
mpz_set_ui (rop, 0);
while (n--)
{
mpz_mul (t, V1[n], V2[n]);
mpz_add (rop, rop, t);
}
mpz_clear (t);
}
void
spectral_test (mpf_t rop[], unsigned int T, mpz_t a, mpz_t m)
{
/* Knuth "Seminumerical Algorithms, Third Edition", section 3.3.4
(pp. 101-103). */
/* v[t] = min { sqrt (x[1]^2 + ... + x[t]^2) |
x[1] + a*x[2] + ... + pow (a, t-1) * x[t] is congruent to 0 (mod m) } */
/* Variables. */
unsigned int ui_t;
unsigned int ui_i, ui_j, ui_k, ui_l;
mpf_t f_tmp1, f_tmp2;
mpz_t tmp1, tmp2, tmp3;
mpz_t U[GMP_SPECT_MAXT][GMP_SPECT_MAXT],
V[GMP_SPECT_MAXT][GMP_SPECT_MAXT],
X[GMP_SPECT_MAXT],
Y[GMP_SPECT_MAXT],
Z[GMP_SPECT_MAXT];
mpz_t h, hp, r, s, p, pp, q, u, v;
/* GMP inits. */
mpf_init (f_tmp1);
mpf_init (f_tmp2);
for (ui_i = 0; ui_i < GMP_SPECT_MAXT; ui_i++)
{
for (ui_j = 0; ui_j < GMP_SPECT_MAXT; ui_j++)
{
mpz_init_set_ui (U[ui_i][ui_j], 0);
mpz_init_set_ui (V[ui_i][ui_j], 0);
}
mpz_init_set_ui (X[ui_i], 0);
mpz_init_set_ui (Y[ui_i], 0);
mpz_init (Z[ui_i]);
}
mpz_init (tmp1);
mpz_init (tmp2);
mpz_init (tmp3);
mpz_init (h);
mpz_init (hp);
mpz_init (r);
mpz_init (s);
mpz_init (p);
mpz_init (pp);
mpz_init (q);
mpz_init (u);
mpz_init (v);
/* Implementation inits. */
if (T > GMP_SPECT_MAXT)
T = GMP_SPECT_MAXT; /* FIXME: Lazy. */
/* S1 [Initialize.] */
ui_t = 2 - 1; /* NOTE: `t' in description == ui_t + 1
for easy indexing */
mpz_set (h, a);
mpz_set (hp, m);
mpz_set_ui (p, 1);
mpz_set_ui (pp, 0);
mpz_set (r, a);
mpz_pow_ui (s, a, 2);
mpz_add_ui (s, s, 1); /* s = 1 + a^2 */
/* S2 [Euclidean step.] */
while (1)
{
if (g_debug > DEBUG_1)
{
mpz_mul (tmp1, h, pp);
mpz_mul (tmp2, hp, p);
mpz_sub (tmp1, tmp1, tmp2);
if (mpz_cmpabs (m, tmp1))
{
printf ("***BUG***: h*pp - hp*p = ");
mpz_out_str (stdout, 10, tmp1);
printf ("\n");
}
}
if (g_debug > DEBUG_2)
{
printf ("hp = ");
mpz_out_str (stdout, 10, hp);
printf ("\nh = ");
mpz_out_str (stdout, 10, h);
printf ("\n");
fflush (stdout);
}
if (mpz_sgn (h))
mpz_tdiv_q (q, hp, h); /* q = floor(hp/h) */
else
mpz_set_ui (q, 1);
if (g_debug > DEBUG_2)
{
printf ("q = ");
mpz_out_str (stdout, 10, q);
printf ("\n");
fflush (stdout);
}
mpz_mul (tmp1, q, h);
mpz_sub (u, hp, tmp1); /* u = hp - q*h */
mpz_mul (tmp1, q, p);
mpz_sub (v, pp, tmp1); /* v = pp - q*p */
mpz_pow_ui (tmp1, u, 2);
mpz_pow_ui (tmp2, v, 2);
mpz_add (tmp1, tmp1, tmp2);
if (mpz_cmp (tmp1, s) < 0)
{
mpz_set (s, tmp1); /* s = u^2 + v^2 */
mpz_set (hp, h); /* hp = h */
mpz_set (h, u); /* h = u */
mpz_set (pp, p); /* pp = p */
mpz_set (p, v); /* p = v */
}
else
break;
}
/* S3 [Compute v2.] */
mpz_sub (u, u, h);
mpz_sub (v, v, p);
mpz_pow_ui (tmp1, u, 2);
mpz_pow_ui (tmp2, v, 2);
mpz_add (tmp1, tmp1, tmp2);
if (mpz_cmp (tmp1, s) < 0)
{
mpz_set (s, tmp1); /* s = u^2 + v^2 */
mpz_set (hp, u);
mpz_set (pp, v);
}
mpf_set_z (f_tmp1, s);
mpf_sqrt (rop[ui_t - 1], f_tmp1);
/* S4 [Advance t.] */
mpz_neg (U[0][0], h);
mpz_set (U[0][1], p);
mpz_neg (U[1][0], hp);
mpz_set (U[1][1], pp);
mpz_set (V[0][0], pp);
mpz_set (V[0][1], hp);
mpz_neg (V[1][0], p);
mpz_neg (V[1][1], h);
if (mpz_cmp_ui (pp, 0) > 0)
{
mpz_neg (V[0][0], V[0][0]);
mpz_neg (V[0][1], V[0][1]);
mpz_neg (V[1][0], V[1][0]);
mpz_neg (V[1][1], V[1][1]);
}
while (ui_t + 1 != T) /* S4 loop */
{
ui_t++;
mpz_mul (r, a, r);
mpz_mod (r, r, m);
/* Add new row and column to U and V. They are initialized with
all elements set to zero, so clearing is not necessary. */
mpz_neg (U[ui_t][0], r); /* U: First col in new row. */
mpz_set_ui (U[ui_t][ui_t], 1); /* U: Last col in new row. */
mpz_set (V[ui_t][ui_t], m); /* V: Last col in new row. */
/* "Finally, for 1 <= i < t,
set q = round (vi1 * r / m),
vit = vi1*r - q*m,
and Ut=Ut+q*Ui */
for (ui_i = 0; ui_i < ui_t; ui_i++)
{
mpz_mul (tmp1, V[ui_i][0], r); /* tmp1=vi1*r */
zdiv_round (q, tmp1, m); /* q=round(vi1*r/m) */
mpz_mul (tmp2, q, m); /* tmp2=q*m */
mpz_sub (V[ui_i][ui_t], tmp1, tmp2);
for (ui_j = 0; ui_j <= ui_t; ui_j++) /* U[t] = U[t] + q*U[i] */
{
mpz_mul (tmp1, q, U[ui_i][ui_j]); /* tmp=q*uij */
mpz_add (U[ui_t][ui_j], U[ui_t][ui_j], tmp1); /* utj = utj + q*uij */
}
}
/* s = min (s, zdot (U[t], U[t]) */
vz_dot (tmp1, U[ui_t], U[ui_t], ui_t + 1);
if (mpz_cmp (tmp1, s) < 0)
mpz_set (s, tmp1);
ui_k = ui_t;
ui_j = 0; /* WARNING: ui_j no longer a temp. */
/* S5 [Transform.] */
if (g_debug > DEBUG_2)
printf ("(t, k, j, q1, q2, ...)\n");
do
{
if (g_debug > DEBUG_2)
printf ("(%u, %u, %u", ui_t + 1, ui_k + 1, ui_j + 1);
for (ui_i = 0; ui_i <= ui_t; ui_i++)
{
if (ui_i != ui_j)
{
vz_dot (tmp1, V[ui_i], V[ui_j], ui_t + 1); /* tmp1=dot(Vi,Vj). */
mpz_abs (tmp2, tmp1);
mpz_mul_ui (tmp2, tmp2, 2); /* tmp2 = 2*abs(dot(Vi,Vj) */
vz_dot (tmp3, V[ui_j], V[ui_j], ui_t + 1); /* tmp3=dot(Vj,Vj). */
if (mpz_cmp (tmp2, tmp3) > 0)
{
zdiv_round (q, tmp1, tmp3); /* q=round(Vi.Vj/Vj.Vj) */
if (g_debug > DEBUG_2)
{
printf (", ");
mpz_out_str (stdout, 10, q);
}
for (ui_l = 0; ui_l <= ui_t; ui_l++)
{
mpz_mul (tmp1, q, V[ui_j][ui_l]);
mpz_sub (V[ui_i][ui_l], V[ui_i][ui_l], tmp1); /* Vi=Vi-q*Vj */
mpz_mul (tmp1, q, U[ui_i][ui_l]);
mpz_add (U[ui_j][ui_l], U[ui_j][ui_l], tmp1); /* Uj=Uj+q*Ui */
}
vz_dot (tmp1, U[ui_j], U[ui_j], ui_t + 1); /* tmp1=dot(Uj,Uj) */
if (mpz_cmp (tmp1, s) < 0) /* s = min(s,dot(Uj,Uj)) */
mpz_set (s, tmp1);
ui_k = ui_j;
}
else if (g_debug > DEBUG_2)
printf (", #"); /* 2|Vi.Vj| <= Vj.Vj */
}
else if (g_debug > DEBUG_2)
printf (", *"); /* i == j */
}
if (g_debug > DEBUG_2)
printf (")\n");
/* S6 [Advance j.] */
if (ui_j == ui_t)
ui_j = 0;
else
ui_j++;
}
while (ui_j != ui_k); /* S5 */
/* From Knuth p. 104: "The exhaustive search in steps S8-S10
reduces the value of s only rarely." */
#ifdef DO_SEARCH
/* S7 [Prepare for search.] */
/* Find minimum in (x[1], ..., x[t]) satisfying condition
x[k]^2 <= f(y[1], ...,y[t]) * dot(V[k],V[k]) */
ui_k = ui_t;
if (g_debug > DEBUG_2)
{
printf ("searching...");
/*for (f = 0; f < ui_t*/
fflush (stdout);
}
/* Z[i] = floor (sqrt (floor (dot(V[i],V[i]) * s / m^2))); */
mpz_pow_ui (tmp1, m, 2);
mpf_set_z (f_tmp1, tmp1);
mpf_set_z (f_tmp2, s);
mpf_div (f_tmp1, f_tmp2, f_tmp1); /* f_tmp1 = s/m^2 */
for (ui_i = 0; ui_i <= ui_t; ui_i++)
{
vz_dot (tmp1, V[ui_i], V[ui_i], ui_t + 1);
mpf_set_z (f_tmp2, tmp1);
mpf_mul (f_tmp2, f_tmp2, f_tmp1);
f_floor (f_tmp2, f_tmp2);
mpf_sqrt (f_tmp2, f_tmp2);
mpz_set_f (Z[ui_i], f_tmp2);
}
/* S8 [Advance X[k].] */
do
{
if (g_debug > DEBUG_2)
{
printf ("X[%u] = ", ui_k);
mpz_out_str (stdout, 10, X[ui_k]);
printf ("\tZ[%u] = ", ui_k);
mpz_out_str (stdout, 10, Z[ui_k]);
printf ("\n");
fflush (stdout);
}
if (mpz_cmp (X[ui_k], Z[ui_k]))
{
mpz_add_ui (X[ui_k], X[ui_k], 1);
for (ui_i = 0; ui_i <= ui_t; ui_i++)
mpz_add (Y[ui_i], Y[ui_i], U[ui_k][ui_i]);
/* S9 [Advance k.] */
while (++ui_k <= ui_t)
{
mpz_neg (X[ui_k], Z[ui_k]);
mpz_mul_ui (tmp1, Z[ui_k], 2);
for (ui_i = 0; ui_i <= ui_t; ui_i++)
{
mpz_mul (tmp2, tmp1, U[ui_k][ui_i]);
mpz_sub (Y[ui_i], Y[ui_i], tmp2);
}
}
vz_dot (tmp1, Y, Y, ui_t + 1);
if (mpz_cmp (tmp1, s) < 0)
mpz_set (s, tmp1);
}
}
while (--ui_k);
#endif /* DO_SEARCH */
mpf_set_z (f_tmp1, s);
mpf_sqrt (rop[ui_t - 1], f_tmp1);
#ifdef DO_SEARCH
if (g_debug > DEBUG_2)
printf ("done.\n");
#endif /* DO_SEARCH */
} /* S4 loop */
/* Clear GMP variables. */
mpf_clear (f_tmp1);
mpf_clear (f_tmp2);
for (ui_i = 0; ui_i < GMP_SPECT_MAXT; ui_i++)
{
for (ui_j = 0; ui_j < GMP_SPECT_MAXT; ui_j++)
{
mpz_clear (U[ui_i][ui_j]);
mpz_clear (V[ui_i][ui_j]);
}
mpz_clear (X[ui_i]);
mpz_clear (Y[ui_i]);
mpz_clear (Z[ui_i]);
}
mpz_clear (tmp1);
mpz_clear (tmp2);
mpz_clear (tmp3);
mpz_clear (h);
mpz_clear (hp);
mpz_clear (r);
mpz_clear (s);
mpz_clear (p);
mpz_clear (pp);
mpz_clear (q);
mpz_clear (u);
mpz_clear (v);
return;
}

View File

@@ -0,0 +1,67 @@
/* Test gmp_randinit_set.
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"
/* expect after a gmp_randinit_set that the new and old generators will
produce the same sequence of numbers */
void
check_one (const char *name, gmp_randstate_ptr src)
{
gmp_randstate_t dst;
mpz_t sz, dz;
int i;
gmp_randinit_set (dst, src);
mpz_init (sz);
mpz_init (dz);
for (i = 0; i < 20; i++)
{
mpz_urandomb (sz, src, 123);
mpz_urandomb (dz, dst, 123);
if (mpz_cmp (sz, dz) != 0)
{
printf ("gmp_randinit_set didn't duplicate randstate\n");
printf (" algorithm: %s\n", name);
gmp_printf (" from src: %#Zx\n", sz);
gmp_printf (" from dst: %#Zx\n", dz);
abort ();
}
}
mpz_clear (sz);
mpz_clear (dz);
gmp_randclear (dst);
}
int
main (int argc, char *argv[])
{
tests_start ();
call_rand_algs (check_one);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,216 @@
/* Exercise the lc2exp random functions.
Copyright 2002, 2011 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"
/* a=0 and c=0 produces zero results always. */
void
check_zero (unsigned long m2exp)
{
gmp_randstate_t r;
mpz_t a;
unsigned long c;
int i;
mpz_init_set_ui (a, 0L);
c = 0L;
gmp_randinit_lc_2exp (r, a, c, m2exp);
gmp_randseed_ui (r, 0L);
for (i = 0; i < 5; i++)
{
mpz_urandomb (a, r, 123L);
if (mpz_sgn (a) != 0)
{
printf ("check_zero m2exp=%lu: didn't get zero\n", m2exp);
gmp_printf (" rand=%#Zx\n", a);
abort ();
}
}
mpz_clear (a);
gmp_randclear (r);
}
/* negative a */
void
check_nega (void)
{
gmp_randstate_t r;
mpz_t a;
unsigned long c, m2exp;
int i;
mpz_init (a);
mpz_setbit (a, 1000L);
mpz_neg (a, a);
c = 0L;
m2exp = 45L;
gmp_randinit_lc_2exp (r, a, c, m2exp);
gmp_randseed_ui (r, 0L);
for (i = 0; i < 5; i++)
{
mpz_urandomb (a, r, 123L);
if (mpz_sgn (a) != 0)
printf ("check_nega m2exp=%lu: didn't get zero\n", m2exp);
}
mpz_clear (a);
gmp_randclear (r);
}
void
check_bigc (void)
{
gmp_randstate_t r;
mpz_t a;
unsigned long c, m2exp, bits;
int i;
mpz_init_set_ui (a, 0L);
c = ULONG_MAX;
m2exp = 8;
gmp_randinit_lc_2exp (r, a, c, m2exp);
gmp_randseed_ui (r, 0L);
for (i = 0; i < 20; i++)
{
bits = 123L;
mpz_urandomb (a, r, bits);
if (mpz_sgn (a) < 0 || mpz_sizeinbase (a, 2) > bits)
{
printf ("check_bigc: mpz_urandomb out of range\n");
printf (" m2exp=%lu\n", m2exp);
gmp_printf (" rand=%#ZX\n", a);
gmp_printf (" sizeinbase2=%u\n", mpz_sizeinbase (a, 2));
abort ();
}
}
mpz_clear (a);
gmp_randclear (r);
}
void
check_bigc1 (void)
{
gmp_randstate_t r;
mpz_t a;
unsigned long c, m2exp;
int i;
mpz_init_set_ui (a, 0L);
c = ULONG_MAX;
m2exp = 2;
gmp_randinit_lc_2exp (r, a, c, m2exp);
gmp_randseed_ui (r, 0L);
for (i = 0; i < 20; i++)
{
mpz_urandomb (a, r, 1L);
if (mpz_cmp_ui (a, 1L) != 0)
{
printf ("check_bigc1: mpz_urandomb didn't give 1\n");
printf (" m2exp=%lu\n", m2exp);
gmp_printf (" got rand=%#ZX\n", a);
abort ();
}
}
mpz_clear (a);
gmp_randclear (r);
}
/* Checks parameters which triggered an assertion failure in the past.
Happened when limbs(a)+limbs(c) < bits_to_limbs(m2exp). */
void
check_bigm (void)
{
gmp_randstate_t rstate;
mpz_t a;
mpz_init_set_ui (a, 5L);
gmp_randinit_lc_2exp (rstate, a, 1L, 384L);
mpz_urandomb (a, rstate, 20L);
gmp_randclear (rstate);
mpz_clear (a);
}
/* Checks for seeds bigger than the modulus. */
void
check_bigs (void)
{
gmp_randstate_t rstate;
mpz_t sd, a;
int i;
mpz_init (sd);
mpz_setbit (sd, 300L);
mpz_sub_ui (sd, sd, 1L);
mpz_clrbit (sd, 13L);
mpz_init_set_ui (a, 123456789L);
gmp_randinit_lc_2exp (rstate, a, 5L, 64L);
for (i = 0; i < 20; i++)
{
mpz_neg (sd, sd);
gmp_randseed (rstate, sd);
mpz_mul_ui (sd, sd, 7L);
mpz_urandomb (a, rstate, 80L);
}
gmp_randclear (rstate);
mpz_clear (a);
mpz_clear (sd);
}
int
main (void)
{
tests_start ();
check_zero (2L);
check_zero (7L);
check_zero (32L);
check_zero (64L);
check_zero (1000L);
check_nega ();
check_bigc ();
check_bigc1 ();
check_bigm ();
check_bigs ();
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,82 @@
/* Test the Mersenne Twister random number generator.
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 "gmp-impl.h"
#include "tests.h"
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
/* Test that the sequence without seeding equals the sequence with the
default seed. */
int
chk_default_seed (void)
{
gmp_randstate_t r1, r2;
mpz_t a, b;
int i;
int ok = TRUE;
mpz_init2 (a, 19936L);
mpz_init2 (b, 19936L);
gmp_randinit_mt (r1);
gmp_randinit_mt (r2);
gmp_randseed_ui (r2, 5489L); /* Must match DEFAULT_SEED in randmt.c */
for (i = 0; i < 3; i++)
{
/* Extract one whole buffer per iteration. */
mpz_urandomb (a, r1, 19936L);
mpz_urandomb (b, r2, 19936L);
if (mpz_cmp (a, b) != 0)
{
ok = FALSE;
printf ("Default seed fails in iteration %d\n", i);
break;
}
}
gmp_randclear (r1);
gmp_randclear (r2);
mpz_clear (a);
mpz_clear (b);
return ok;
}
int
main (int argc, char *argv[])
{
int ok;
tests_start ();
ok = chk_default_seed ();
tests_end ();
if (ok)
return 0; /* pass */
else
return 1; /* fail */
}

View File

@@ -0,0 +1,290 @@
/* t-rand -- Test random number generators. */
/*
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 <stdlib.h>
#include <stdio.h>
#include "gmp.h"
#define SEED 1
#define BASE 16
#define ENTS 10 /* Number of entries in array when
printing. */
/* These were generated by this very program. Do not edit! */
/* Integers. */
const char *z1[ENTS] = {"0", "1", "1", "1", "1", "0", "1", "1", "1", "1"};
const char *z2[ENTS] = {"0", "3", "1", "3", "3", "0", "3", "3", "3", "1"};
const char *z3[ENTS] = {"4", "3", "1", "7", "3", "0", "3", "3", "3", "1"};
const char *z4[ENTS] = {"c", "3", "1", "f", "b", "8", "3", "3", "3", "1"};
const char *z5[ENTS] = {"1c", "13", "11", "1f", "b", "18", "3", "13", "3", "1"};
const char *z10[ENTS] = {"29c", "213", "f1", "17f", "12b", "178", "383", "d3", "3a3", "281"};
const char *z15[ENTS] = {"29c", "1a13", "74f1", "257f", "592b", "4978", "4783", "7cd3", "5ba3", "4681"};
const char *z16[ENTS] = {"29c", "9a13", "74f1", "a57f", "d92b", "4978", "c783", "fcd3", "5ba3", "c681"};
const char *z17[ENTS] = {"51e", "f17a", "54ff", "1a335", "cf65", "5d6f", "583f", "618f", "1bc6", "98ff"};
const char *z31[ENTS] = {"3aecd515", "13ae8ec6", "518c8090", "81ca077", "70b7134", "7ee78d71", "323a7636", "2122cb1a", "19811941", "41fd605"};
const char *z32[ENTS] = {"baecd515", "13ae8ec6", "518c8090", "881ca077", "870b7134", "7ee78d71", "323a7636", "a122cb1a", "99811941", "841fd605"};
const char *z33[ENTS] = {"1faf4cca", "15d6ef83b", "9095fe72", "1b6a3dff6", "b17cbddd", "16e5209d4", "6f65b12c", "493bbbc6", "abf2a5d5", "6d491a3c"};
const char *z63[ENTS] = {"48a74f367fa7b5c8", "3ba9e9dc1b263076", "1e0ac84e7678e0fb", "11416581728b3e35", "36ab610523f0f1f7", "3e540e8e95c0eb4b", "439ae16057dbc9d3", "734fb260db243950", "7d3a317effc289bf", "1d80301fb3d1a0d1"};
const char *z64[ENTS] = {"48a74f367fa7b5c8", "bba9e9dc1b263076", "9e0ac84e7678e0fb", "11416581728b3e35", "b6ab610523f0f1f7", "be540e8e95c0eb4b", "439ae16057dbc9d3", "f34fb260db243950", "fd3a317effc289bf", "1d80301fb3d1a0d1"};
const char *z65[ENTS] = {"1ff77710d846d49f0", "1b1411701d709ee10", "31ffa81a208b6af4", "446638d431d3c681", "df5c569d5baa8b55", "197d99ea9bf28e5a0", "191ade09edd94cfae", "194acefa6dde5e18d", "1afc1167c56272d92", "d092994da72f206f"};
const char *z127[ENTS] = {"2f66ba932aaf58a071fd8f0742a99a0c", "73cfa3c664c9c1753507ca60ec6b8425", "53ea074ca131dec12cd68b8aa8e20278", "3cf5ac8c343532f8a53cc0eb47581f73", "50c11d5869e208aa1b9aa317b8c2d0a9", "b23163c892876472b1ef19642eace09", "489f4c03d41f87509c8d6c90ce674f95", "2ab8748c96aa6762ea1932b44c9d7164", "98cb5591fc05ad31afbbc1d67b90edd", "77848bb991fd0be331adcf1457fbc672"};
const char *z128[ENTS] = {"af66ba932aaf58a071fd8f0742a99a0c", "73cfa3c664c9c1753507ca60ec6b8425", "53ea074ca131dec12cd68b8aa8e20278", "3cf5ac8c343532f8a53cc0eb47581f73", "50c11d5869e208aa1b9aa317b8c2d0a9", "8b23163c892876472b1ef19642eace09", "489f4c03d41f87509c8d6c90ce674f95", "aab8748c96aa6762ea1932b44c9d7164", "98cb5591fc05ad31afbbc1d67b90edd", "f7848bb991fd0be331adcf1457fbc672"};
/* Floats. */
const char *f1[ENTS] = {"0.@0", "0.8@0", "0.8@0", "0.8@0", "0.8@0", "0.@0", "0.8@0", "0.8@0", "0.8@0", "0.8@0"};
const char *f2[ENTS] = {"0.@0", "0.c@0", "0.4@0", "0.c@0", "0.c@0", "0.@0", "0.c@0", "0.c@0", "0.c@0", "0.4@0"};
const char *f3[ENTS] = {"0.8@0", "0.6@0", "0.2@0", "0.e@0", "0.6@0", "0.@0", "0.6@0", "0.6@0", "0.6@0", "0.2@0"};
const char *f4[ENTS] = {"0.c@0", "0.3@0", "0.1@0", "0.f@0", "0.b@0", "0.8@0", "0.3@0", "0.3@0", "0.3@0", "0.1@0"};
const char *f5[ENTS] = {"0.e@0", "0.98@0", "0.88@0", "0.f8@0", "0.58@0", "0.c@0", "0.18@0", "0.98@0", "0.18@0", "0.8@-1"};
const char *f10[ENTS] = {"0.a7@0", "0.84c@0", "0.3c4@0", "0.5fc@0", "0.4ac@0", "0.5e@0", "0.e0c@0", "0.34c@0", "0.e8c@0", "0.a04@0"};
const char *f15[ENTS] = {"0.538@-1", "0.3426@0", "0.e9e2@0", "0.4afe@0", "0.b256@0", "0.92f@0", "0.8f06@0", "0.f9a6@0", "0.b746@0", "0.8d02@0"};
const char *f16[ENTS] = {"0.29c@-1", "0.9a13@0", "0.74f1@0", "0.a57f@0", "0.d92b@0", "0.4978@0", "0.c783@0", "0.fcd3@0", "0.5ba3@0", "0.c681@0"};
const char *f17[ENTS] = {"0.28f@-1", "0.78bd@0", "0.2a7f8@0", "0.d19a8@0", "0.67b28@0", "0.2eb78@0", "0.2c1f8@0", "0.30c78@0", "0.de3@-1", "0.4c7f8@0"};
const char *f31[ENTS] = {"0.75d9aa2a@0", "0.275d1d8c@0", "0.a319012@0", "0.103940ee@0", "0.e16e268@-1", "0.fdcf1ae2@0", "0.6474ec6c@0", "0.42459634@0", "0.33023282@0", "0.83fac0a@-1"};
const char *f32[ENTS] = {"0.baecd515@0", "0.13ae8ec6@0", "0.518c809@0", "0.881ca077@0", "0.870b7134@0", "0.7ee78d71@0", "0.323a7636@0", "0.a122cb1a@0", "0.99811941@0", "0.841fd605@0"};
const char *f33[ENTS] = {"0.fd7a665@-1", "0.aeb77c1d8@0", "0.484aff39@0", "0.db51effb@0", "0.58be5eee8@0", "0.b72904ea@0", "0.37b2d896@0", "0.249ddde3@0", "0.55f952ea8@0", "0.36a48d1e@0"};
const char *f63[ENTS] = {"0.914e9e6cff4f6b9@0", "0.7753d3b8364c60ec@0", "0.3c15909cecf1c1f6@0", "0.2282cb02e5167c6a@0", "0.6d56c20a47e1e3ee@0", "0.7ca81d1d2b81d696@0", "0.8735c2c0afb793a6@0", "0.e69f64c1b64872a@0", "0.fa7462fdff85137e@0", "0.3b00603f67a341a2@0"};
const char *f64[ENTS] = {"0.48a74f367fa7b5c8@0", "0.bba9e9dc1b263076@0", "0.9e0ac84e7678e0fb@0", "0.11416581728b3e35@0", "0.b6ab610523f0f1f7@0", "0.be540e8e95c0eb4b@0", "0.439ae16057dbc9d3@0", "0.f34fb260db24395@0", "0.fd3a317effc289bf@0", "0.1d80301fb3d1a0d1@0"};
const char *f65[ENTS] = {"0.ffbbb886c236a4f8@0", "0.d8a08b80eb84f708@0", "0.18ffd40d1045b57a@0", "0.22331c6a18e9e3408@0", "0.6fae2b4eadd545aa8@0", "0.cbeccf54df9472d@0", "0.c8d6f04f6eca67d7@0", "0.ca5677d36ef2f0c68@0", "0.d7e08b3e2b1396c9@0", "0.68494ca6d39790378@0"};
const char *f127[ENTS] = {"0.5ecd7526555eb140e3fb1e0e85533418@0", "0.e79f478cc99382ea6a0f94c1d8d7084a@0", "0.a7d40e994263bd8259ad171551c404f@0", "0.79eb5918686a65f14a7981d68eb03ee6@0", "0.a1823ab0d3c411543735462f7185a152@0", "0.16462c791250ec8e563de32c85d59c12@0", "0.913e9807a83f0ea1391ad9219cce9f2a@0", "0.5570e9192d54cec5d4326568993ae2c8@0", "0.13196ab23f80b5a635f7783acf721dba@0", "0.ef09177323fa17c6635b9e28aff78ce4@0"};
const char *f128[ENTS] = {"0.af66ba932aaf58a071fd8f0742a99a0c@0", "0.73cfa3c664c9c1753507ca60ec6b8425@0", "0.53ea074ca131dec12cd68b8aa8e20278@0", "0.3cf5ac8c343532f8a53cc0eb47581f73@0", "0.50c11d5869e208aa1b9aa317b8c2d0a9@0", "0.8b23163c892876472b1ef19642eace09@0", "0.489f4c03d41f87509c8d6c90ce674f95@0", "0.aab8748c96aa6762ea1932b44c9d7164@0", "0.98cb5591fc05ad31afbbc1d67b90edd@-1", "0.f7848bb991fd0be331adcf1457fbc672@0"};
struct rt
{
const char **s;
int nbits;
};
static struct rt zarr[] =
{
{z1, 1},
{z2, 2},
{z3, 3},
{z4, 4},
{z5, 5},
{z10, 10},
{z15, 15},
{z16, 16},
{z17, 17},
{z31, 31},
{z32, 32},
{z33, 33},
{z63, 63},
{z64, 64},
{z65, 65},
{z127, 127},
{z128, 128},
{NULL, 0}
};
static struct rt farr[] =
{
{f1, 1},
{f2, 2},
{f3, 3},
{f4, 4},
{f5, 5},
{f10, 10},
{f15, 15},
{f16, 16},
{f17, 17},
{f31, 31},
{f32, 32},
{f33, 33},
{f63, 63},
{f64, 64},
{f65, 65},
{f127, 127},
{f128, 128},
{NULL, 0}
};
int
main (int argc, char *argv[])
{
static char usage[] = "\
usage: t-rand [function nbits]\n\
function is one of z, f\n\
nbits is number of bits\n\
";
gmp_randstate_t rstate;
mpz_t z, rz;
mpf_t f, rf;
enum { Z, F } func = Z;
int nbits = 1;
int verify_mode_flag = 1;
int i;
struct rt *a;
if (argc > 1)
{
if (argc < 3)
{
fputs (usage, stderr);
exit (1);
}
verify_mode_flag = 0;
if (*argv[1] == 'z')
func = Z;
if (*argv[1] == 'f')
func = F;
nbits = atoi (argv[2]);
}
mpz_init (rz);
if (verify_mode_flag)
{
#ifdef VERBOSE
printf ("%s: verifying random numbers: ", argv[0]);
#endif
/* Test z. */
mpz_init (z);
for (a = zarr; a->s != NULL; a++)
{
gmp_randinit (rstate, GMP_RAND_ALG_LC, a->nbits);
if (gmp_errno != GMP_ERROR_NONE)
exit (1);
gmp_randseed_ui (rstate, SEED);
for (i = 0; i < ENTS; i++)
{
mpz_urandomb (rz, rstate, a->nbits);
mpz_set_str (z, a->s[i], BASE);
if (mpz_cmp (z, rz) != 0)
{
printf ("z%d: ", a->nbits);
mpz_out_str (stdout, BASE, rz);
printf (" should be ");
mpz_out_str (stdout, BASE, z);
puts ("");
exit (1);
}
}
#ifdef VERBOSE
printf ("z%d ", a->nbits);
#endif
gmp_randclear (rstate);
}
mpz_clear (z);
/* Test f. */
for (a = farr; a->s != NULL; a++)
{
gmp_randinit (rstate, GMP_RAND_ALG_LC, a->nbits);
if (gmp_errno != GMP_ERROR_NONE)
exit (1);
gmp_randseed_ui (rstate, SEED);
mpf_init2 (f, a->nbits);
mpf_init2 (rf, a->nbits);
for (i = 0; i < ENTS; i++)
{
mpf_urandomb (rf, rstate, a->nbits);
mpf_set_str (f, a->s[i], BASE);
if (mpf_cmp (f, rf) != 0)
{
printf ("f%d: ", a->nbits);
mpf_out_str (stdout, BASE, a->nbits, rf);
printf (" should be ");
mpf_out_str (stdout, BASE, a->nbits, f);
puts ("");
exit (1);
}
}
#ifdef VERBOSE
printf ("f%d ", a->nbits);
#endif
gmp_randclear (rstate);
mpf_clear (f);
mpf_clear (rf);
}
#ifdef VERBOSE
puts ("");
#endif
}
else /* Print mode. */
{
gmp_randinit (rstate, GMP_RAND_ALG_LC, nbits);
if (gmp_errno != GMP_ERROR_NONE)
exit (1);
gmp_randseed_ui (rstate, SEED);
switch (func)
{
case Z:
printf ("char *z%d[ENTS] = {", nbits);
for (i = 0; i < ENTS; i++)
{
mpz_urandomb (rz, rstate, nbits);
printf ("\"");
mpz_out_str (stdout, BASE, rz);
printf ("\"");
if (i != ENTS - 1)
printf (", ");
}
printf ("};\n");
printf (" {z%d, %d},\n", nbits, nbits);
break;
case F:
printf ("char *f%d[ENTS] = {", nbits);
mpf_init2 (rf, nbits);
for (i = 0; i < ENTS; i++)
{
mpf_urandomb (rf, rstate, nbits);
printf ("\"");
mpf_out_str (stdout, BASE, nbits, rf);
printf ("\"");
if (i != ENTS - 1)
printf (", ");
}
printf ("};\n");
printf (" {f%d, %d},\n", nbits, nbits);
mpf_clear (rf);
break;
default:
exit (1);
}
gmp_randclear (rstate);
}
mpz_clear (rz);
return 0;
}

View File

@@ -0,0 +1,64 @@
/* Test gmp_urandomb_ui.
Copyright 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 "gmp-impl.h"
#include "tests.h"
/* Expect numbers generated by rstate to obey the number of bits requested.
No point testing bits==BITS_PER_ULONG, since any return is acceptable in
that case. */
void
check_one (const char *name, gmp_randstate_ptr rstate)
{
unsigned long bits, limit, got;
int i;
for (bits = 0; bits < BITS_PER_ULONG; bits++)
{
/* will demand got < limit */
limit = (1UL << bits);
for (i = 0; i < 5; i++)
{
got = gmp_urandomb_ui (rstate, bits);
if (got >= limit)
{
printf ("Return value out of range:\n");
printf (" algorithm: %s\n", name);
printf (" bits: %lu\n", bits);
printf (" limit: %#lx\n", limit);
printf (" got: %#lx\n", got);
abort ();
}
}
}
}
int
main (int argc, char *argv[])
{
tests_start ();
call_rand_algs (check_one);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,74 @@
/* Test gmp_urandomm_ui.
Copyright 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 "gmp-impl.h"
#include "tests.h"
/* Expect numbers generated by rstate to obey the limit requested. */
void
check_one (const char *name, gmp_randstate_ptr rstate)
{
static const unsigned long n_table[] = {
1, 2, 3, 4, 5, 6, 7, 8,
123, 456, 789,
255, 256, 257,
1023, 1024, 1025,
32767, 32768, 32769,
ULONG_MAX/2-2, ULONG_MAX/2-1, ULONG_MAX/2, ULONG_MAX/2+1, ULONG_MAX/2+2,
ULONG_MAX-2, ULONG_MAX-1, ULONG_MAX,
};
unsigned long got, n;
int i, j;
for (i = 0; i < numberof (n_table); i++)
{
n = n_table[i];
for (j = 0; j < 5; j++)
{
got = gmp_urandomm_ui (rstate, n);
if (got >= n)
{
printf ("Return value out of range:\n");
printf (" algorithm: %s\n", name);
printf (" n: %#lx\n", n);
printf (" got: %#lx\n", got);
abort ();
}
}
}
}
int
main (int argc, char *argv[])
{
tests_start ();
call_rand_algs (check_one);
tests_end ();
exit (0);
}

View File

@@ -0,0 +1,158 @@
/* Test mpz_urandomm.
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 "gmp-impl.h"
#include "tests.h"
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
int
check_params (void)
{
gmp_randstate_t r1, r2;
mpz_t a, b, m;
int i;
int result;
result = TRUE;
mpz_init (a);
mpz_init (b);
mpz_init (m);
if (result)
{
/* Test the consistency between urandomm and urandomb. */
gmp_randinit_default (r1);
gmp_randinit_default (r2);
gmp_randseed_ui (r1, 85L);
gmp_randseed_ui (r2, 85L);
mpz_set_ui (m, 0L);
mpz_setbit (m, 80L);
for (i = 0; i < 100; i++)
{
mpz_urandomm (a, r1, m);
mpz_urandomb (b, r2, 80L);
if (mpz_cmp (a, b) != 0)
{
result = FALSE;
printf ("mpz_urandomm != mpz_urandomb\n");
break;
}
}
gmp_randclear (r1);
gmp_randclear (r2);
}
if (result)
{
/* Test that mpz_urandomm returns the correct result with a
broken LC. */
mpz_set_ui (a, 0L);
gmp_randinit_lc_2exp (r1, a, 0xffL, 8L);
mpz_set_ui (m, 5L);
/* Warning: This code hangs in gmp 4.1 and below */
for (i = 0; i < 100; i++)
{
mpz_urandomm (a, r1, m);
if (mpz_cmp_ui (a, 2L) != 0)
{
result = FALSE;
gmp_printf ("mpz_urandomm returns %Zd instead of 2\n", a);
break;
}
}
gmp_randclear (r1);
}
if (result)
{
/* Test that the results are always in range for either
positive or negative values of m. */
gmp_randinit_default (r1);
mpz_set_ui (m, 5L);
mpz_set_si (b, -5L);
for (i = 0; i < 100; i++)
{
mpz_urandomm (a, r1, m);
if (mpz_cmp_ui (a, 5L) >= 0 || mpz_sgn (a) < 0)
{
result = FALSE;
gmp_printf ("Out-of-range or non-positive value: %Zd\n", a);
break;
}
mpz_urandomm (a, r1, b);
if (mpz_cmp_ui (a, 5L) >= 0 || mpz_sgn (a) < 0)
{
result = FALSE;
gmp_printf ("Out-of-range or non-positive value (from negative modulus): %Zd\n", a);
break;
}
}
gmp_randclear (r1);
}
if (result)
{
/* Test that m=1 forces always result=0. */
gmp_randinit_default (r1);
mpz_set_ui (m, 1L);
for (i = 0; i < 100; i++)
{
mpz_urandomm (a, r1, m);
if (mpz_sgn (a) != 0)
{
result = FALSE;
gmp_printf ("mpz_urandomm fails with m=1 (result=%Zd)\n", a);
break;
}
}
gmp_randclear (r1);
}
mpz_clear (a);
mpz_clear (b);
mpz_clear (m);
return result;
}
int
main (int argc, char *argv[])
{
int result = TRUE;
tests_start ();
if (result)
if (!check_params ())
result = FALSE;
tests_end ();
if (result)
return 0; /* pass */
else
return 1; /* fail */
}

View File

@@ -0,0 +1,43 @@
/* zdiv_round() -- divide integers, round to nearest */
/*
Copyright 1999 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/. */
void
zdiv_round (mpz_t rop, mpz_t n, mpz_t d)
{
mpf_t f_n, f_d;
mpf_init (f_n);
mpf_init (f_d);
mpf_set_z (f_d, d);
mpf_set_z (f_n, n);
mpf_div (f_n, f_n, f_d);
mpf_set_d (f_d, .5);
if (mpf_sgn (f_n) < 0)
mpf_neg (f_d, f_d);
mpf_add (f_n, f_n, f_d);
mpz_set_f (rop, f_n);
mpf_clear (f_n);
mpf_clear (f_d);
return;
}