/*
This file is part of liberferfc.
Copyright 2009-2010 by
Laboratoire de l'Informatique du Parallélisme, UMR CNRS - ENS Lyon -
UCB Lyon 1 - INRIA 5668,
and by LORIA (CNRS, INPL, INRIA, UHP, U-Nancy 2).
It has been written by S. Chevillard.
Liberferfc is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Liberferfc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with liberferfc. If not, see .
*/
#include
#include
#include
#include
#include "erferfc.h"
#define NUMBER_OF_CHECKS 2000
#define MAXIMAL_PREC 1000.
int initialization(gmp_randstate_t state) {
mpz_t zseed;
const char seed[] = "SPMf2e3u9rfwFzXtHhmM45nNPej1dGbpsKmpsFzs2TLZ4XvJur4ITPIOgCn8rRKkEKvVKCJRorbTVIeq3N3jBqrvfsTB67MK";
gmp_randinit_default(state);
mpz_init(zseed);
mpz_set_str (zseed, seed, 62);
gmp_randseed(state, zseed);
srand(mpz_get_ui(zseed));
mpz_clear(zseed);
return 0;
}
/* Tests the implementation of mp_erfc */
/* We call mp_erfc with several values of x */
/* and several precisions prec. */
/* Each time, we check by comparing with mpfr_erfc */
/* computed with 50 guard bits. If the test fails, */
/* it does not necessarily mean that mp_erfc is wrong */
/* but most likely it is. */
int main(void) {
int i;
int test = 1;
mp_prec_t prec;
mpfr_t x,yref, epsilon;
mpfr_t *y;
gmp_randstate_t state;
initialization(state);
mpfr_init(x);
mpfr_init(yref);
mpfr_init(epsilon);
/* Special values */
mpfr_set_prec(x, 30);
mpfr_set_inf(x, 1);
y = mp_erfc(x, 30);
if (mpfr_cmp_si(*y, 0)!=0) { test = 0; printf("Wrong value at +oo\n"); }
mpfr_clear(*y);
free(y);
mpfr_set_inf(x, -1);
y = mp_erfc(x, 30);
if (mpfr_cmp_si(*y, 2)!=0) { test = 0; printf("Wrong value at -oo\n"); }
mpfr_clear(*y);
free(y);
mpfr_set_ui(x, 0, GMP_RNDN);
y = mp_erfc(x, 30);
if (mpfr_cmp_si(*y, 1)!=0) { test = 0; printf("Wrong value at 0\n"); }
mpfr_clear(*y);
free(y);
mpfr_set_nan(x);
y = mp_erfc(x, 30);
if (!mpfr_nan_p(*y)) { test = 0; printf("Wrong value at NaN\n"); }
mpfr_clear(*y);
free(y);
for(i=0; i< NUMBER_OF_CHECKS; i++) {
/* prec uniformly distributed in [MPFR_PREC_MIN, MAXIMAL_PREC+MPFR_PREC_MIN] */
prec = MPFR_PREC_MIN+(mp_prec_t)(MAXIMAL_PREC*(double)rand()/(double)(RAND_MAX));
mpfr_set_prec(x, prec);
mpfr_urandomb (x, state); /* x uniformly distributed in [0,1] */
mpfr_mul_ui(x, x, 2, GMP_RNDN); /* x uniformly distributed in [0,2] */
mpfr_sub_ui(x, x, 1, GMP_RNDN); /* x uniformly distributed in [-1, 1] */
mpfr_mul_ui(x, x, 20, GMP_RNDN); /* x uniformly distributed in [-20, 20] */
prec = MPFR_PREC_MIN+(mp_prec_t)(MAXIMAL_PREC*(double)rand()/(double)(RAND_MAX));
mpfr_set_prec(yref, prec+50);
mpfr_set_prec(epsilon, prec+50);
y = mp_erfc(x, prec);
mpfr_erfc(yref, x, GMP_RNDN);
mpfr_sub(epsilon, *y, yref, GMP_RNDN);
mpfr_div(epsilon, epsilon, yref, GMP_RNDN);
if (mpfr_get_exp(epsilon) > -(signed)prec) {
test = 0;
printf("Test %d failed:\n", i);
printf("Precision of x: %lu\n", (unsigned long)mpfr_get_prec(x));
printf("x = "); mpfr_out_str(stdout, 2, 0, x, GMP_RNDN); printf("\n");
printf("x ~ "); mpfr_out_str(stdout, 10, 10, x, GMP_RNDN); printf("\n");
printf("Required precision: %lu\n", (unsigned long)prec);
printf("Working precision: %lu\n", (unsigned long)mpfr_get_prec(*y));
printf("y = "); mpfr_out_str(stdout, 2, 0, *y, GMP_RNDN); printf("\n");
printf("True value = "); mpfr_out_str(stdout, 2, 0, yref, GMP_RNDN); printf("\n");
printf("y ~ "); mpfr_out_str(stdout, 10, 10, *y, GMP_RNDN); printf("\n");
printf("True value = "); mpfr_out_str(stdout, 10, 10, yref, GMP_RNDN); printf("\n");
printf("Actual accuracy 2^{%ld} (should be smaller than 2^{%ld})\n\n", mpfr_get_exp(epsilon), -(long)prec);
}
mpfr_clear(*y);
free(y);
}
if (test) printf("All tests succeed!\n");
gmp_randclear(state);
mpfr_clear(x);
mpfr_clear(yref);
mpfr_clear(epsilon);
mpfr_free_cache();
return 0;
}