/* Test mpq_get_d and mpq_set_d
Copyright 1991 , 1993 , 1994 , 1996 , 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
8
#endif
/* VAX D floats only have an 8 bit signed exponent, so anything 2^128 or
bigger will overflow, that being 4 limbs. */
#if defined (__vax) ||
defined (__vax__) && SIZE >
4
#undef SIZE
#define SIZE
4
#define EPSIZE
3
#else
#define EPSIZE SIZE
#endif
void dump (mpq_t);
void
check_monotonic (
int argc,
char **argv)
{
mpq_t a;
mp_size_t size;
int reps =
100 ;
int i, j;
double last_d, new_d;
mpq_t qlast_d, qnew_d;
mpq_t eps;
if (argc ==
2 )
reps = atoi (argv[
1 ]);
/* The idea here is to test the monotonousness of mpq_get_d by adding
numbers to the numerator and denominator. */
mpq_init (a);
mpq_init (eps);
mpq_init (qlast_d);
mpq_init (qnew_d);
for (i =
0 ; i < reps; i++)
{
size = urandom () % SIZE - SIZE/
2 ;
mpz_random2 (mpq_numref (a), size);
do
{
size = urandom () % SIZE - SIZE/
2 ;
mpz_random2 (mpq_denref (a), size);
}
while (mpz_cmp_ui (mpq_denref (a),
0 ) ==
0 );
mpq_canonicalize (a);
last_d = mpq_get_d (a);
mpq_set_d (qlast_d, last_d);
for (j =
0 ; j <
10 ; j++)
{
size = urandom () % EPSIZE +
1 ;
mpz_random2 (mpq_numref (eps), size);
size = urandom () % EPSIZE +
1 ;
mpz_random2 (mpq_denref (eps), size);
mpq_canonicalize (eps);
mpq_add (a, a, eps);
mpq_canonicalize (a);
new_d = mpq_get_d (a);
if (last_d > new_d)
{
printf (
"\nERROR (test %d/%d): bad mpq_get_d results\n" , i, j);
printf (
"last: %.16g\n" , last_d);
printf (
" new: %.16g\n" , new_d); dump (a);
abort ();
}
mpq_set_d (qnew_d, new_d);
MPQ_CHECK_FORMAT (qnew_d);
if (mpq_cmp (qlast_d, qnew_d) >
0 )
{
printf (
"ERROR (test %d/%d): bad mpq_set_d results\n" , i, j);
printf (
"last: %.16g\n" , last_d); dump (qlast_d);
printf (
" new: %.16g\n" , new_d); dump (qnew_d);
abort ();
}
last_d = new_d;
mpq_set (qlast_d, qnew_d);
}
}
mpq_clear (a);
mpq_clear (eps);
mpq_clear (qlast_d);
mpq_clear (qnew_d);
}
double
my_ldexp (
double d,
int e)
{
for (;;)
{
if (e >
0 )
{
if (e >=
16 )
{
d *=
65536 .
0 ;
e -=
16 ;
}
else
{
d *=
2 .
0 ;
e -=
1 ;
}
}
else if (e <
0 )
{
if (e <= -
16 )
{
d /=
65536 .
0 ;
e +=
16 ;
}
else
{
d /=
2 .
0 ;
e +=
1 ;
}
}
else
return d;
}
}
#define MAXEXP
500
#if defined (__vax) ||
defined (__vax__)
#undef MAXEXP
#define MAXEXP
30
#endif
void
check_random (
int argc,
char **argv)
{
gmp_randstate_ptr rands = RANDS;
double d;
mpq_t q;
mpz_t a, t;
int exp;
int test, reps =
100000 ;
if (argc ==
2 )
reps =
100 * atoi (argv[
1 ]);
mpq_init (q);
mpz_init (a);
mpz_init (t);
for (test =
0 ; test < reps; test++)
{
mpz_rrandomb (a, rands,
53 );
mpz_urandomb (t, rands,
32 );
exp = mpz_get_ui (t) % (
2 *MAXEXP) - MAXEXP;
d = my_ldexp (mpz_get_d (a), exp);
mpq_set_d (q, d);
/* Check that n/d = a * 2^exp, or
d*a 2^{exp} = n */
mpz_mul (t, a, mpq_denref (q));
if (exp >
0 )
mpz_mul_2exp (t, t, exp);
else
{
if (!mpz_divisible_2exp_p (t, -exp))
goto fail;
mpz_div_2exp (t, t, -exp);
}
if (mpz_cmp (t, mpq_numref (q)) !=
0 )
{
fail:
printf (
"ERROR (check_random test %d): bad mpq_set_d results\n" , test);
printf (
"%.16g\n" , d);
gmp_printf (
"%Qd\n" , q);
abort ();
}
}
mpq_clear (q);
mpz_clear (t);
mpz_clear (a);
}
void
dump (mpq_t x)
{
mpz_out_str (stdout,
10 , mpq_numref (x));
printf (
"/" );
mpz_out_str (stdout,
10 , mpq_denref (x));
printf (
"\n" );
}
/* Check various values 2^n and 1/2^n. */
void
check_onebit (
void )
{
static const long data[] = {
-
3 *GMP_NUMB_BITS-
1 , -
3 *GMP_NUMB_BITS, -
3 *GMP_NUMB_BITS+
1 ,
-
2 *GMP_NUMB_BITS-
1 , -
2 *GMP_NUMB_BITS, -
2 *GMP_NUMB_BITS+
1 ,
-GMP_NUMB_BITS-
1 , -GMP_NUMB_BITS, -GMP_NUMB_BITS+
1 ,
-
5 , -
2 , -
1 ,
0 ,
1 ,
2 ,
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 ,
};
int i, neg;
long exp, l;
mpq_t q;
double got, want;
mpq_init (q);
for (i =
0 ; i < numberof (data); i++)
{
exp = data[i];
mpq_set_ui (q,
1 L,
1 L);
if (exp >=
0 )
mpq_mul_2exp (q, q, exp);
else
mpq_div_2exp (q, q, -exp);
want =
1 .
0 ;
for (l =
0 ; l < exp; l++)
want *=
2 .
0 ;
for (l =
0 ; l > exp; l--)
want /=
2 .
0 ;
for (neg =
0 ; neg <=
1 ; neg++)
{
if (neg)
{
mpq_neg (q, q);
want = -want;
}
got = mpq_get_d (q);
if (got != want)
{
printf (
"mpq_get_d wrong on %s2**%ld\n" , neg ?
"-" :
"" , exp);
mpq_trace (
" q " , q);
d_trace (
" want " , want);
d_trace (
" got " , got);
abort();
}
}
}
mpq_clear (q);
}
int
main (
int argc,
char **argv)
{
tests_start ();
check_onebit ();
check_monotonic (argc, argv);
check_random (argc, argv);
tests_end ();
exit (
0 );
}
Messung V0.5 in Prozent C=97 H=96 G=96
¤ Dauer der Verarbeitung: 0.4 Sekunden
¤
*© Formatika GbR, Deutschland