aboutsummaryrefslogtreecommitdiff
path: root/tests/tsin_cos.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tsin_cos.c')
-rw-r--r--tests/tsin_cos.c725
1 files changed, 725 insertions, 0 deletions
diff --git a/tests/tsin_cos.c b/tests/tsin_cos.c
new file mode 100644
index 0000000..380a333
--- /dev/null
+++ b/tests/tsin_cos.c
@@ -0,0 +1,725 @@
+/* Test file for mpfr_sin_cos.
+
+Copyright 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+Contributed by the AriC and Caramel projects, INRIA.
+
+This file is part of the GNU MPFR Library.
+
+The GNU MPFR Library 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.
+
+The GNU 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 Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
+http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mpfr-test.h"
+
+static void
+large_test (char *X, int prec, int N)
+{
+ int i;
+ mpfr_t x, s, c;
+
+ mpfr_init2 (x, prec);
+ mpfr_init2 (s, prec);
+ mpfr_init2 (c, prec);
+ mpfr_set_str (x, X, 10, MPFR_RNDN);
+
+ for (i = 0; i < N; i++)
+ mpfr_sin_cos (s, c, x, MPFR_RNDN);
+
+ mpfr_clear (x);
+ mpfr_clear (s);
+ mpfr_clear (c);
+}
+
+static void
+check53 (const char *xs, const char *sin_xs, const char *cos_xs,
+ mpfr_rnd_t rnd_mode)
+{
+ mpfr_t xx, s, c;
+
+ mpfr_inits2 (53, xx, s, c, (mpfr_ptr) 0);
+ mpfr_set_str1 (xx, xs); /* should be exact */
+ mpfr_sin_cos (s, c, xx, rnd_mode);
+ if (mpfr_cmp_str1 (s, sin_xs))
+ {
+ printf ("mpfr_sin_cos failed for x=%s, rnd=%s\n",
+ xs, mpfr_print_rnd_mode (rnd_mode));
+ printf ("mpfr_sin_cos gives sin(x)=");
+ mpfr_out_str(stdout, 10, 0, s, MPFR_RNDN);
+ printf(", expected %s\n", sin_xs);
+ exit (1);
+ }
+ if (mpfr_cmp_str1 (c, cos_xs))
+ {
+ printf ("mpfr_sin_cos failed for x=%s, rnd=%s\n",
+ xs, mpfr_print_rnd_mode (rnd_mode));
+ printf ("mpfr_sin_cos gives cos(x)=");
+ mpfr_out_str(stdout, 10, 0, c, MPFR_RNDN);
+ printf(", expected %s\n", cos_xs);
+ exit (1);
+ }
+ mpfr_clears (xx, s, c, (mpfr_ptr) 0);
+}
+
+static void
+check53sin (const char *xs, const char *sin_xs, mpfr_rnd_t rnd_mode)
+{
+ mpfr_t xx, s, c;
+
+ mpfr_inits2 (53, xx, s, c, (mpfr_ptr) 0);
+ mpfr_set_str1 (xx, xs); /* should be exact */
+ mpfr_sin_cos (s, c, xx, rnd_mode);
+ if (mpfr_cmp_str1 (s, sin_xs))
+ {
+ printf ("mpfr_sin_cos failed for x=%s, rnd=%s\n",
+ xs, mpfr_print_rnd_mode (rnd_mode));
+ printf ("mpfr_sin_cos gives sin(x)=");
+ mpfr_out_str(stdout, 10, 0, s, MPFR_RNDN);
+ printf(", expected %s\n", sin_xs);
+ exit (1);
+ }
+ mpfr_clears (xx, s, c, (mpfr_ptr) 0);
+}
+
+static void
+check53cos (const char *xs, const char *cos_xs, mpfr_rnd_t rnd_mode)
+{
+ mpfr_t xx, c, s;
+
+ mpfr_inits2 (53, xx, s, c, (mpfr_ptr) 0);
+ mpfr_set_str1 (xx, xs); /* should be exact */
+ mpfr_sin_cos (s, c, xx, rnd_mode);
+ if (mpfr_cmp_str1 (c, cos_xs))
+ {
+ printf ("mpfr_sin_cos failed for x=%s, rnd=%s\n",
+ xs, mpfr_print_rnd_mode (rnd_mode));
+ printf ("mpfr_sin_cos gives cos(x)=");
+ mpfr_out_str(stdout, 10, 0, c, MPFR_RNDN);
+ printf(", expected %s\n", cos_xs);
+ exit (1);
+ }
+ mpfr_clears (xx, s, c, (mpfr_ptr) 0);
+}
+
+static void
+check_nans (void)
+{
+ mpfr_t x, s, c;
+
+ mpfr_init2 (x, 123L);
+ mpfr_init2 (s, 123L);
+ mpfr_init2 (c, 123L);
+
+ /* sin(NaN)==NaN, cos(NaN)==NaN */
+ mpfr_set_nan (x);
+ mpfr_sin_cos (s, c, x, MPFR_RNDN);
+ MPFR_ASSERTN (mpfr_nan_p (s));
+ MPFR_ASSERTN (mpfr_nan_p (c));
+
+ /* sin(+Inf)==NaN, cos(+Inf)==NaN */
+ mpfr_set_inf (x, 1);
+ mpfr_sin_cos (s, c, x, MPFR_RNDN);
+ MPFR_ASSERTN (mpfr_nan_p (s));
+ MPFR_ASSERTN (mpfr_nan_p (c));
+
+ /* sin(-Inf)==NaN, cos(-Inf)==NaN */
+ mpfr_set_inf (x, -1);
+ mpfr_sin_cos (s, c, x, MPFR_RNDN);
+ MPFR_ASSERTN (mpfr_nan_p (s));
+ MPFR_ASSERTN (mpfr_nan_p (c));
+
+ /* check zero */
+ mpfr_set_ui (x, 0, MPFR_RNDN);
+ mpfr_sin_cos (s, c, x, MPFR_RNDN);
+ MPFR_ASSERTN (mpfr_cmp_ui (s, 0) == 0 && MPFR_IS_POS (s));
+ MPFR_ASSERTN (mpfr_cmp_ui (c, 1) == 0);
+ mpfr_neg (x, x, MPFR_RNDN);
+ mpfr_sin_cos (s, c, x, MPFR_RNDN);
+ MPFR_ASSERTN (mpfr_cmp_ui (s, 0) == 0 && MPFR_IS_NEG (s));
+ MPFR_ASSERTN (mpfr_cmp_ui (c, 1) == 0);
+
+ /* coverage test */
+ mpfr_set_prec (x, 2);
+ mpfr_set_ui (x, 4, MPFR_RNDN);
+ mpfr_set_prec (s, 2);
+ mpfr_set_prec (c, 2);
+ mpfr_sin_cos (s, c, x, MPFR_RNDN);
+ MPFR_ASSERTN (mpfr_cmp_si_2exp (s, -3, -2) == 0);
+ MPFR_ASSERTN (mpfr_cmp_si_2exp (c, -3, -2) == 0);
+
+ mpfr_clear (x);
+ mpfr_clear (s);
+ mpfr_clear (c);
+}
+
+static void
+overflowed_sin_cos0 (void)
+{
+ mpfr_t x, y, z;
+ int emax, inex, rnd, err = 0;
+ mpfr_exp_t old_emax;
+
+ old_emax = mpfr_get_emax ();
+
+ mpfr_init2 (x, 8);
+ mpfr_init2 (y, 8);
+ mpfr_init2 (z, 8);
+
+ for (emax = -1; emax <= 0; emax++)
+ {
+ mpfr_set_ui_2exp (z, 1, emax, MPFR_RNDN);
+ mpfr_nextbelow (z);
+ set_emax (emax); /* 1 is not representable. */
+ /* and if emax < 0, 1 - eps is not representable either. */
+ RND_LOOP (rnd)
+ {
+ mpfr_set_si (x, 0, MPFR_RNDN);
+ mpfr_neg (x, x, MPFR_RNDN);
+ mpfr_clear_flags ();
+ inex = mpfr_sin_cos (x, y, x, (mpfr_rnd_t) rnd);
+ if (! mpfr_overflow_p ())
+ {
+ printf ("Error in overflowed_sin_cos0 (rnd = %s):\n"
+ " The overflow flag is not set.\n",
+ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
+ err = 1;
+ }
+ if (! (mpfr_zero_p (x) && MPFR_SIGN (x) < 0))
+ {
+ printf ("Error in overflowed_sin_cos0 (rnd = %s):\n"
+ " Got sin = ", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
+ mpfr_print_binary (x);
+ printf (" instead of -0.\n");
+ err = 1;
+ }
+ if (rnd == MPFR_RNDZ || rnd == MPFR_RNDD)
+ {
+ if (inex == 0)
+ {
+ printf ("Error in overflowed_sin_cos0 (rnd = %s):\n"
+ " The inexact value must be non-zero.\n",
+ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
+ err = 1;
+ }
+ if (! mpfr_equal_p (y, z))
+ {
+ printf ("Error in overflowed_sin_cos0 (rnd = %s):\n"
+ " Got cos = ",
+ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
+ mpfr_print_binary (y);
+ printf (" instead of 0.11111111E%d.\n", emax);
+ err = 1;
+ }
+ }
+ else
+ {
+ if (inex == 0)
+ {
+ printf ("Error in overflowed_sin_cos0 (rnd = %s):\n"
+ " The inexact value must be non-zero.\n",
+ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
+ err = 1;
+ }
+ if (! (mpfr_inf_p (y) && MPFR_SIGN (y) > 0))
+ {
+ printf ("Error in overflowed_sin_cos0 (rnd = %s):\n"
+ " Got cos = ",
+ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
+ mpfr_print_binary (y);
+ printf (" instead of +Inf.\n");
+ err = 1;
+ }
+ }
+ }
+ set_emax (old_emax);
+ }
+
+ if (err)
+ exit (1);
+ mpfr_clear (x);
+ mpfr_clear (y);
+ mpfr_clear (z);
+}
+
+static void
+tiny (void)
+{
+ mpfr_t x, s, c;
+ int i, inex;
+
+ mpfr_inits2 (64, x, s, c, (mpfr_ptr) 0);
+
+ for (i = -1; i <= 1; i += 2)
+ {
+ mpfr_set_si (x, i, MPFR_RNDN);
+ mpfr_set_exp (x, mpfr_get_emin ());
+ inex = mpfr_sin_cos (s, c, x, MPFR_RNDN);
+ MPFR_ASSERTN (inex != 0);
+ MPFR_ASSERTN (mpfr_equal_p (s, x));
+ MPFR_ASSERTN (!mpfr_nan_p (c) && mpfr_cmp_ui (c, 1) == 0);
+ }
+
+ mpfr_clears (x, s, c, (mpfr_ptr) 0);
+}
+
+/* bug found in nightly tests */
+static void
+test20071214 (void)
+{
+ mpfr_t a, b;
+ int inex;
+
+ mpfr_init2 (a, 4);
+ mpfr_init2 (b, 4);
+
+ mpfr_set_ui_2exp (a, 3, -4, MPFR_RNDN);
+ inex = mpfr_sin_cos (a, b, a, MPFR_RNDD);
+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 11, -6) == 0);
+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (b, 15, -4) == 0);
+ MPFR_ASSERTN(inex == 10);
+
+ mpfr_set_ui_2exp (a, 3, -4, MPFR_RNDN);
+ inex = mpfr_sin_cos (a, b, a, MPFR_RNDU);
+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 3, -4) == 0);
+ MPFR_ASSERTN(mpfr_cmp_ui (b, 1) == 0);
+ MPFR_ASSERTN(inex == 5);
+
+ mpfr_set_ui_2exp (a, 3, -4, MPFR_RNDN);
+ inex = mpfr_sin_cos (a, b, a, MPFR_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 3, -4) == 0);
+ MPFR_ASSERTN(mpfr_cmp_ui (b, 1) == 0);
+ MPFR_ASSERTN(inex == 5);
+
+ mpfr_clear (a);
+ mpfr_clear (b);
+}
+
+/* check that mpfr_sin_cos and test_mpfr_sincos_fast agree */
+static void
+test_mpfr_sincos_fast (void)
+{
+ mpfr_t x, y, z, yref, zref, h;
+ mpfr_prec_t p = 1000;
+ int i, inex, inexref;
+ mpfr_rnd_t r;
+
+ mpfr_init2 (x, p);
+ mpfr_init2 (y, p);
+ mpfr_init2 (z, p);
+ mpfr_init2 (yref, p);
+ mpfr_init2 (zref, p);
+ mpfr_init2 (h, p);
+ mpfr_set_ui (x, 0, MPFR_RNDN);
+ /* we generate a random value x, compute sin(x) and cos(x) with both
+ mpfr_sin_cos and mpfr_sincos_fast, and check the values and the flags
+ agree */
+ for (i = 0; i < 100; i++)
+ {
+ mpfr_urandomb (h, RANDS);
+ mpfr_add (x, x, h, MPFR_RNDN);
+ r = RND_RAND ();
+ inexref = mpfr_sin_cos (yref, zref, x, r);
+ inex = mpfr_sincos_fast (y, z, x, r);
+ if (mpfr_cmp (y, yref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree\n");
+ printf ("x="); mpfr_dump (x);
+ printf ("rnd=%s\n", mpfr_print_rnd_mode (r));
+ printf ("yref="); mpfr_dump (yref);
+ printf ("y="); mpfr_dump (y);
+ exit (1);
+ }
+ if (mpfr_cmp (z, zref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree\n");
+ printf ("x="); mpfr_dump (x);
+ printf ("rnd=%s\n", mpfr_print_rnd_mode (r));
+ printf ("zref="); mpfr_dump (zref);
+ printf ("z="); mpfr_dump (z);
+ exit (1);
+ }
+ if (inex != inexref)
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree\n");
+ printf ("x="); mpfr_dump (x);
+ printf ("rnd=%s\n", mpfr_print_rnd_mode (r));
+ printf ("inexref=%d inex=%d\n", inexref, inex);
+ exit (1);
+ }
+ }
+ mpfr_clear (x);
+ mpfr_clear (y);
+ mpfr_clear (z);
+ mpfr_clear (yref);
+ mpfr_clear (zref);
+ mpfr_clear (h);
+}
+
+static void
+bug20091007 (void)
+{
+ mpfr_t x, y, z, yref, zref;
+ mpfr_prec_t p = 1000;
+ int inex, inexref;
+ mpfr_rnd_t r = MPFR_RNDZ;
+
+ mpfr_init2 (x, p);
+ mpfr_init2 (y, p);
+ mpfr_init2 (z, p);
+ mpfr_init2 (yref, p);
+ mpfr_init2 (zref, p);
+
+ mpfr_set_str (x, "1.9ecdc22ba77a5ab2560f7e84289e2a328906f47377ea3fd4c82d1bb2f13ee05c032cffc1933eadab7b0a5498e03e3bd0508968e59c25829d97a0b54f20cd4662c8dfffa54e714de41fc8ee3e0e0b244d110a194db05b70022b7d77f88955d415b09f17dd404576098dc51a583a3e49c35839551646e880c7eb790a01a4@1", 16, MPFR_RNDN);
+ inexref = mpfr_sin_cos (yref, zref, x, r);
+ inex = mpfr_sincos_fast (y, z, x, r);
+
+ if (mpfr_cmp (y, yref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091007)\n");
+ printf ("yref="); mpfr_dump (yref);
+ printf ("y="); mpfr_dump (y);
+ exit (1);
+ }
+ if (mpfr_cmp (z, zref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091007)\n");
+ printf ("zref="); mpfr_dump (zref);
+ printf ("z="); mpfr_dump (z);
+ exit (1);
+ }
+ if (inex != inexref)
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091007)\n");
+ printf ("inexref=%d inex=%d\n", inexref, inex);
+ exit (1);
+ }
+
+ mpfr_clear (x);
+ mpfr_clear (y);
+ mpfr_clear (z);
+ mpfr_clear (yref);
+ mpfr_clear (zref);
+}
+
+/* Note: with the sin_cos.c code before r6507, the disagreement occurs
+ only on the return ("inexact") value, which is new in r6444. */
+static void
+bug20091008 (void)
+{
+ mpfr_t x, y, z, yref, zref;
+ mpfr_prec_t p = 1000;
+ int inex, inexref;
+ mpfr_rnd_t r = MPFR_RNDN;
+
+ mpfr_init2 (x, p);
+ mpfr_init2 (y, p);
+ mpfr_init2 (z, p);
+ mpfr_init2 (yref, p);
+ mpfr_init2 (zref, p);
+
+ mpfr_set_str (x, "c.91813724e28ef6a711d33e6505984699daef7fe93636c1ed5d0168bc96989cc6802f7f9e405c902ec62fb90cd39c9d21084c8ad8b5af4c4aa87bf402e2e4a78e6fe1ffeb6dbbbdbbc2983c196c518966ccc1e094ed39ee77984ef2428069d65de37928e75247edbe7007245e682616b5ebbf05f2fdefc74ad192024f10", 16, MPFR_RNDN);
+ inexref = mpfr_sin_cos (yref, zref, x, r);
+ inex = mpfr_sincos_fast (y, z, x, r);
+
+ if (mpfr_cmp (y, yref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091008)\n");
+ printf ("yref="); mpfr_dump (yref);
+ printf ("y="); mpfr_dump (y);
+ exit (1);
+ }
+ if (mpfr_cmp (z, zref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091008)\n");
+ printf ("zref="); mpfr_dump (zref);
+ printf ("z="); mpfr_dump (z);
+ exit (1);
+ }
+ /* sin(x) is rounded up, cos(x) is rounded up too, thus we should get 5
+ for the return value */
+ if (inex != inexref)
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091008)\n");
+ printf ("inexref=%d inex=%d (5 expected)\n", inexref, inex);
+ exit (1);
+ }
+
+ mpfr_clear (x);
+ mpfr_clear (y);
+ mpfr_clear (z);
+ mpfr_clear (yref);
+ mpfr_clear (zref);
+}
+
+static void
+bug20091013 (void)
+{
+ mpfr_t x, y, z, yref, zref;
+ mpfr_prec_t p = 1000;
+ int inex, inexref;
+ mpfr_rnd_t r = MPFR_RNDN;
+
+ mpfr_init2 (x, p);
+ mpfr_init2 (y, p);
+ mpfr_init2 (z, p);
+ mpfr_init2 (yref, p);
+ mpfr_init2 (zref, p);
+
+ mpfr_set_str (x, "3.240ff3fdcb1ee7cd667b96287593ae24e20fb63ed7c2d5bf4bd0f2cc5509283b04e7628e66382605f14ed5967cef15296041539a1bdaa626c777c7fbb6f2068414759b78cee14f37848689b3a170f583656be4e0837f464d8210556a3a822d4ecfdd59f4e0d5fdb76bf7e15b8a57234e2160b98e14c17bbdf27c4643b8@1", 16, MPFR_RNDN);
+ inexref = mpfr_sin_cos (yref, zref, x, r);
+ inex = mpfr_sincos_fast (y, z, x, r);
+
+ if (mpfr_cmp (y, yref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091013)\n");
+ printf ("yref="); mpfr_dump (yref);
+ printf ("y="); mpfr_dump (y);
+ exit (1);
+ }
+ if (mpfr_cmp (z, zref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091013)\n");
+ printf ("zref="); mpfr_dump (zref);
+ printf ("z="); mpfr_dump (z);
+ exit (1);
+ }
+ /* sin(x) is rounded down and cos(x) is rounded down, thus we should get
+ 2+4*2 = 10 as return value */
+ if (inex != inexref)
+ {
+ printf ("mpfr_sin_cos and mpfr_sincos_fast disagree (bug20091013)\n");
+ printf ("inexref=%d inex=%d (10 expected)\n", inexref, inex);
+ exit (1);
+ }
+
+ mpfr_clear (x);
+ mpfr_clear (y);
+ mpfr_clear (z);
+ mpfr_clear (yref);
+ mpfr_clear (zref);
+}
+
+/* Bug reported by Laurent Fousse for the 2.4 branch.
+ No problem in the trunk.
+ https://sympa.inria.fr/sympa/arc/mpfr/2009-11/msg00044.html */
+static void
+bug20091122 (void)
+{
+ mpfr_t x, y, z, yref, zref;
+ mpfr_prec_t p = 3;
+ mpfr_rnd_t r = MPFR_RNDN;
+
+ mpfr_init2 (x, 5);
+ mpfr_init2 (y, p);
+ mpfr_init2 (z, p);
+ mpfr_init2 (yref, p);
+ mpfr_init2 (zref, p);
+
+ mpfr_set_str (x, "0.11111E49", 2, MPFR_RNDN);
+ mpfr_sin_cos (yref, zref, x, r);
+
+ mpfr_sin (y, x, r);
+ mpfr_cos (z, x, r);
+
+ if (! mpfr_equal_p (y, yref))
+ {
+ printf ("mpfr_sin_cos and mpfr_sin disagree (bug20091122)\n");
+ printf ("yref = "); mpfr_dump (yref);
+ printf ("y = "); mpfr_dump (y);
+ exit (1);
+ }
+ if (! mpfr_equal_p (z, zref))
+ {
+ printf ("mpfr_sin_cos and mpfr_cos disagree (bug20091122)\n");
+ printf ("zref = "); mpfr_dump (zref);
+ printf ("z = "); mpfr_dump (z);
+ exit (1);
+ }
+
+ mpfr_clear (x);
+ mpfr_clear (y);
+ mpfr_clear (z);
+ mpfr_clear (yref);
+ mpfr_clear (zref);
+}
+
+static void
+consistency (void)
+{
+ mpfr_t x, s1, s2, c1, c2;
+ mpfr_exp_t emin, emax;
+ mpfr_rnd_t rnd;
+ unsigned int flags_sin, flags_cos, flags, flags_before, flags_ref;
+ int inex_sin, is, inex_cos, ic, inex, inex_ref;
+ int i;
+
+ emin = mpfr_get_emin ();
+ emax = mpfr_get_emax ();
+
+ for (i = 0; i <= 10000; i++)
+ {
+ mpfr_init2 (x, MPFR_PREC_MIN + (randlimb () % 8));
+ mpfr_inits2 (MPFR_PREC_MIN + (randlimb () % 8), s1, s2, c1, c2,
+ (mpfr_ptr) 0);
+ if (i < 8 * MPFR_RND_MAX)
+ {
+ int j = i / MPFR_RND_MAX;
+ if (j & 1)
+ mpfr_set_emin (MPFR_EMIN_MIN);
+ mpfr_set_si (x, (j & 2) ? 1 : -1, MPFR_RNDN);
+ mpfr_set_exp (x, mpfr_get_emin ());
+ rnd = (mpfr_rnd_t) (i % MPFR_RND_MAX);
+ flags_before = 0;
+ if (j & 4)
+ mpfr_set_emax (-17);
+ }
+ else
+ {
+ tests_default_random (x, 256, -5, 50);
+ rnd = RND_RAND ();
+ flags_before = (randlimb () & 1) ?
+ (unsigned int) (MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE) :
+ (unsigned int) 0;
+ }
+ __gmpfr_flags = flags_before;
+ inex_sin = mpfr_sin (s1, x, rnd);
+ is = inex_sin < 0 ? 2 : inex_sin > 0 ? 1 : 0;
+ flags_sin = __gmpfr_flags;
+ __gmpfr_flags = flags_before;
+ inex_cos = mpfr_cos (c1, x, rnd);
+ ic = inex_cos < 0 ? 2 : inex_cos > 0 ? 1 : 0;
+ flags_cos = __gmpfr_flags;
+ __gmpfr_flags = flags_before;
+ inex = mpfr_sin_cos (s2, c2, x, rnd);
+ flags = __gmpfr_flags;
+ inex_ref = is + 4 * ic;
+ flags_ref = flags_sin | flags_cos;
+ if (!(mpfr_equal_p (s1, s2) && mpfr_equal_p (c1, c2)) ||
+ inex != inex_ref || flags != flags_ref)
+ {
+ printf ("mpfr_sin_cos and mpfr_sin/mpfr_cos disagree on %s,"
+ " i = %d\nx = ", mpfr_print_rnd_mode (rnd), i);
+ mpfr_dump (x);
+ printf ("s1 = ");
+ mpfr_dump (s1);
+ printf ("s2 = ");
+ mpfr_dump (s2);
+ printf ("c1 = ");
+ mpfr_dump (c1);
+ printf ("c2 = ");
+ mpfr_dump (c2);
+ printf ("inex_sin = %d (s = %d), inex_cos = %d (c = %d), "
+ "inex = %d (expected %d)\n",
+ inex_sin, is, inex_cos, ic, inex, inex_ref);
+ printf ("flags_sin = 0x%x, flags_cos = 0x%x, "
+ "flags = 0x%x (expected 0x%x)\n",
+ flags_sin, flags_cos, flags, flags_ref);
+ exit (1);
+ }
+ mpfr_clears (x, s1, s2, c1, c2, (mpfr_ptr) 0);
+ mpfr_set_emin (emin);
+ mpfr_set_emax (emax);
+ }
+}
+
+static void
+coverage_01032011 (void)
+{
+ mpfr_t val, cval, sval, svalf;
+ int status_f, status;
+
+ mpfr_init2 (val, MPFR_PREC_MIN);
+ mpfr_init2 (cval, MPFR_PREC_MIN);
+ mpfr_init2 (sval, MPFR_PREC_MIN);
+ mpfr_init2 (svalf, MPFR_PREC_MIN);
+
+ mpfr_set_str1 (val, "-0.7");
+
+ status_f = mpfr_sincos_fast (svalf, NULL, val, MPFR_RNDN);
+ status = mpfr_sin_cos (sval, cval, val, MPFR_RNDN);
+ if (! mpfr_equal_p (svalf, sval) || SIGN (status_f) != SIGN (status))
+ {
+ printf ("mpfr_sincos_fast differ from mpfr_sin_cos result:\n"
+ " sin fast is ");
+ mpfr_dump (svalf);
+ printf (" sin is ");
+ mpfr_dump (sval);
+ printf ("status_f = %d, status = %d\n", status_f, status);
+ exit (1);
+ }
+
+ mpfr_clears(val, cval, sval, svalf, (mpfr_ptr) 0);
+}
+
+/* tsin_cos prec [N] performs N tests with prec bits */
+int
+main (int argc, char *argv[])
+{
+ tests_start_mpfr ();
+
+ if (argc > 1)
+ {
+ if (argc != 3 && argc != 4)
+ {
+ fprintf (stderr, "Usage: tsin_cos x prec [n]\n");
+ exit (1);
+ }
+ large_test (argv[1], atoi (argv[2]), (argc > 3) ? atoi (argv[3]) : 1);
+ goto end;
+ }
+
+ bug20091013 ();
+ bug20091008 ();
+ bug20091007 ();
+ bug20091122 ();
+ consistency ();
+
+ test_mpfr_sincos_fast ();
+
+ check_nans ();
+
+ /* worst case from PhD thesis of Vincent Lefe`vre: x=8980155785351021/2^54 */
+ check53 ("4.984987858808754279e-1", "4.781075595393330379e-1",
+ "8.783012931285841817e-1", MPFR_RNDN);
+ check53 ("4.984987858808754279e-1", "4.781075595393329824e-1",
+ "8.783012931285840707e-1", MPFR_RNDD);
+ check53 ("4.984987858808754279e-1", "4.781075595393329824e-1",
+ "8.783012931285840707e-1", MPFR_RNDZ);
+ check53 ("4.984987858808754279e-1", "4.781075595393330379e-1",
+ "8.783012931285841817e-1", MPFR_RNDU);
+ check53 ("1.00031274099908640274", "8.416399183372403892e-1",
+ "0.540039116973283217504", MPFR_RNDN);
+ check53 ("1.00229256850978698523", "8.427074524447979442e-1",
+ "0.538371757797526551137", MPFR_RNDZ);
+ check53 ("1.00288304857059840103", "8.430252033025980029e-1",
+ "0.537874062022526966409", MPFR_RNDZ);
+ check53 ("1.00591265847407274059", "8.446508805292128885e-1",
+ "0.53531755997839769456", MPFR_RNDN);
+
+ /* check one argument only */
+ check53sin ("1.00591265847407274059", "8.446508805292128885e-1", MPFR_RNDN);
+ check53cos ("1.00591265847407274059", "0.53531755997839769456", MPFR_RNDN);
+
+ overflowed_sin_cos0 ();
+ tiny ();
+ test20071214 ();
+
+ coverage_01032011 ();
+
+ end:
+ tests_end_mpfr ();
+ return 0;
+}