summaryrefslogtreecommitdiff
path: root/mpfr/tests/tdiv.c
diff options
context:
space:
mode:
Diffstat (limited to 'mpfr/tests/tdiv.c')
-rw-r--r--mpfr/tests/tdiv.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/mpfr/tests/tdiv.c b/mpfr/tests/tdiv.c
new file mode 100644
index 000000000..a7de5dde9
--- /dev/null
+++ b/mpfr/tests/tdiv.c
@@ -0,0 +1,152 @@
+/* Test file for mpfr_div.
+
+Copyright (C) 1999 PolKA project, Inria Lorraine and Loria
+
+This file is part of the MPFR Library.
+
+The MPFR Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+The MPFR Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with the MPFR Library; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "mpfr.h"
+#include "mpfr-impl.h"
+#ifdef IRIX64
+#include <sys/fpu.h>
+#endif
+
+extern int isnan();
+
+/* #define DEBUG */
+
+#define check(n,d,r) check4(n,d,r,53)
+
+void check4(N, D, rnd_mode, p) double N, D; unsigned char rnd_mode; int p;
+{
+ mpfr_t q, n, d; double Q,Q2;
+
+#ifdef DEBUG
+ printf("N=%1.20e D=%1.20e rnd_mode=%d\n",N,D,rnd_mode);
+#endif
+ mpfr_init2(q, p); mpfr_init2(n, p); mpfr_init2(d, p);
+ mpfr_set_d(n, N, rnd_mode);
+ mpfr_set_d(d, D, rnd_mode);
+ mpfr_div(q, n, d, rnd_mode);
+ mpfr_set_machine_rnd_mode(rnd_mode);
+ Q = N/D;
+ Q2 = mpfr_get_d(q);
+#ifdef DEBUG
+ printf("expected quotient is %1.20e, got %1.20e (%d ulp)\n",Q,Q2,
+ ulp(Q2,Q));
+ mpfr_print_raw(q); putchar('\n');
+#endif
+ if (Q!=Q2 && (!isnan(Q) || !isnan(Q2))) {
+ printf("mpfr_div failed for n=%1.20e, d=%1.20e, rnd_mode=%d\n",N,D,rnd_mode);
+ printf("expected quotient is %1.20e, got %1.20e (%d ulp)\n",Q,Q2,
+ ulp(Q2,Q));
+ exit(1);
+ }
+ mpfr_clear(q); mpfr_clear(n); mpfr_clear(d);
+}
+
+void check24(float N, float D, unsigned char rnd_mode)
+{
+ mpfr_t q, n, d; float Q,Q2;
+
+ mpfr_init2(q, 24); mpfr_init2(n, 24); mpfr_init2(d, 24);
+ mpfr_set_d(n, N, rnd_mode);
+ mpfr_set_d(d, D, rnd_mode);
+ mpfr_div(q, n, d, rnd_mode);
+ mpfr_set_machine_rnd_mode(rnd_mode);
+ Q = N/D;
+ Q2 = mpfr_get_d(q);
+ if (Q!=Q2 && (!isnan(Q) || !isnan(Q2))) {
+ printf("mpfr_div failed for n=%1.10e, d=%1.10e, prec=24, rnd_mode=%d\n",N,D,rnd_mode);
+ printf("expected quotient is %1.10e, got %1.10e\n",Q,Q2);
+ exit(1);
+ }
+ mpfr_clear(q); mpfr_clear(n); mpfr_clear(d);
+}
+
+/* the following examples come from the paper "Number-theoretic Test
+ Generation for Directed Rounding" from Michael Parks, Table 2 */
+void check_float()
+{
+ int i; float b=8388608.0; /* 2^23 */
+
+ for (i=0;i<4;i++) {
+ check24(b*8388610.0, 8388609.0, i);
+ check24(b*16777215.0, 16777213.0, i);
+ check24(b*8388612.0, 8388611.0, i);
+ check24(b*12582914.0, 12582911.0, i);
+ check24(12582913.0, 12582910.0, i);
+ check24(b*16777215.0, 8388609.0, i);
+ check24(b*8388612.0, 8388609.0, i);
+ check24(b*12582914.0, 8388610.0, i);
+ check24(b*12582913.0, 8388610.0, i);
+ }
+}
+
+void check_convergence()
+{
+ mpfr_t x, y;
+
+ mpfr_init2(x, 130);
+ mpfr_set_str_raw(x, "0.1011111101011010101000001010011111101000011100011101010011111011000011001010000000111100100111110011001010110100100001001000111001E6944");
+ mpfr_init_set_ui(y, 5, 130, GMP_RNDN);
+ mpfr_div(x, x, y, GMP_RNDD); /* exact division */
+ mpfr_clear(x); mpfr_clear(y);
+}
+
+int main(int argc, char *argv[])
+{
+ int i, N; double n, d, e;
+#ifdef IRIX64
+ /* to get denormalized numbers on IRIX64 */
+ union fpc_csr exp;
+ exp.fc_word = get_fpc_csr();
+ exp.fc_struct.flush = 0;
+ set_fpc_csr(exp.fc_word);
+#endif
+
+ N = (argc>1) ? atoi(argv[1]) : 100000;
+ check_float(); /* checks single precision */
+ check_convergence();
+ check(0.0, 1.0, 1);
+ check(-7.49889692246885910000e+63, 4.88168664502887320000e+306, GMP_RNDD);
+ check(-1.33225773037748601769e+199, 3.63449540676937123913e+79, GMP_RNDZ);
+ d = 1.0; for (i=0;i<52;i++) d *= 2.0;
+ check4(4.0, d, GMP_RNDZ, 62);
+ check4(1.0, 2.10263340267725788209e+187, 2, 65);
+ check4(2.44394909079968374564e-150, 2.10263340267725788209e+187, 2, 65);
+ /* the following tests when d is an exact power of two */
+ check(9.89438396044940256501e-134, 5.93472984109987421717e-67, 2);
+ check(9.89438396044940256501e-134, -5.93472984109987421717e-67, 2);
+ check(-4.53063926135729747564e-308, 7.02293374921793516813e-84, 3);
+ check(6.25089225176473806123e-01, -2.35527154824420243364e-230, 3);
+ check(6.52308934689126000000e+15, -1.62063546601505417497e+273, 0);
+ check(1.04636807108079349236e-189, 3.72295730823253012954e-292, 1);
+ srand48(getpid());
+ for (i=0;i<N;i++) {
+ do { n = drand(); d = drand(); e = fabs(n)/fabs(d); }
+ /* smallest normalized is 2^(-1022), largest is 2^(1023)*(2-2^(-52)) */
+ while (e>=1.7976931348623157081e308 || e<2.225073858507201383e-308);
+ check(n, d, rand() % 4);
+ }
+ exit (0);
+}