1/* Test file for mpfr_asin.
2
3Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4Contributed by the Arenaire and Cacao projects, INRIA.
5
6This file is part of the GNU MPFR Library.
7
8The GNU MPFR Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MPFR Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#include <stdio.h>
24#include <stdlib.h>
25
26#include "mpfr-test.h"
27
28#define TEST_FUNCTION mpfr_asin
29#define TEST_RANDOM_EMAX 7
30#include "tgeneric.c"
31
32static void
33special (void)
34{
35  mpfr_t x, y;
36  int r;
37
38  mpfr_init (x);
39  mpfr_init (y);
40
41  /* asin(NaN) = NaN */
42  mpfr_set_nan (x);
43  mpfr_asin (y, x, MPFR_RNDN);
44  if (!mpfr_nan_p (y))
45    {
46      printf ("Error: mpfr_asin (NaN) <> NaN\n");
47      exit (1);
48    }
49
50  /* asin(+/-Inf) = NaN */
51  mpfr_set_inf (x, 1);
52  mpfr_asin (y, x, MPFR_RNDN);
53  if (!mpfr_nan_p (y))
54    {
55      printf ("Error: mpfr_asin (+Inf) <> NaN\n");
56      exit (1);
57    }
58  mpfr_set_inf (x, -1);
59  mpfr_asin (y, x, MPFR_RNDN);
60  if (!mpfr_nan_p (y))
61    {
62      printf ("Error: mpfr_asin (-Inf) <> NaN\n");
63      exit (1);
64    }
65
66  /* asin(+/-2) = NaN */
67  mpfr_set_ui (x, 2, MPFR_RNDN);
68  mpfr_asin (y, x, MPFR_RNDN);
69  if (!mpfr_nan_p (y))
70    {
71      printf ("Error: mpfr_asin (+2) <> NaN\n");
72      exit (1);
73    }
74  mpfr_set_si (x, -2, MPFR_RNDN);
75  mpfr_asin (y, x, MPFR_RNDN);
76  if (!mpfr_nan_p (y))
77    {
78      printf ("Error: mpfr_asin (-2) <> NaN\n");
79      exit (1);
80    }
81
82  /* asin(+/-0) = +/-0 */
83  mpfr_set_ui (x, 0, MPFR_RNDN);
84  mpfr_asin (y, x, MPFR_RNDN);
85  if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0)
86    {
87      printf ("Error: mpfr_asin (+0) <> +0\n");
88      exit (1);
89    }
90  mpfr_neg (x, x, MPFR_RNDN);
91  mpfr_asin (y, x, MPFR_RNDN);
92  if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) > 0)
93    {
94      printf ("Error: mpfr_asin (-0) <> -0\n");
95      exit (1);
96    }
97
98  /* asin(1) = Pi/2 */
99  for (r = 0; r < MPFR_RND_MAX; r++)
100    {
101      mpfr_set_ui (x, 1, MPFR_RNDN); /* exact */
102      mpfr_asin (y, x, (mpfr_rnd_t) r);
103      mpfr_const_pi (x, (mpfr_rnd_t) r);
104      mpfr_div_2exp (x, x, 1, MPFR_RNDN); /* exact */
105      if (mpfr_cmp (x, y))
106        {
107          printf ("Error: asin(1) != Pi/2 for rnd=%s\n",
108                  mpfr_print_rnd_mode ((mpfr_rnd_t) r));
109          exit (1);
110        }
111    }
112
113  /* asin(-1) = -Pi/2 */
114  for (r = 0; r < MPFR_RND_MAX; r++)
115    {
116      mpfr_set_si (x, -1, MPFR_RNDN); /* exact */
117      mpfr_asin (y, x, (mpfr_rnd_t) r);
118      mpfr_const_pi (x, MPFR_INVERT_RND((mpfr_rnd_t) r));
119      mpfr_neg (x, x, MPFR_RNDN); /* exact */
120      mpfr_div_2exp (x, x, 1, MPFR_RNDN); /* exact */
121      if (mpfr_cmp (x, y))
122        {
123          printf ("Error: asin(-1) != -Pi/2 for rnd=%s\n",
124                  mpfr_print_rnd_mode ((mpfr_rnd_t) r));
125          exit (1);
126        }
127    }
128
129  mpfr_set_prec (x, 32);
130  mpfr_set_prec (y, 32);
131
132  mpfr_set_str_binary (x, "0.1101110111111111001011101000101");
133  mpfr_asin (x, x, MPFR_RNDN);
134  mpfr_set_str_binary (y, "1.00001100101011000001111100111");
135  if (mpfr_cmp (x, y))
136    {
137      printf ("Error: mpfr_asin (1)\n");
138      exit (1);
139    }
140
141  mpfr_set_str_binary (x, "-0.01110111000011101010111100000101");
142  mpfr_asin (x, x, MPFR_RNDN);
143  mpfr_set_str_binary (y, "-0.0111101111010100011111110101");
144  if (mpfr_cmp (x, y))
145    {
146      printf ("Error: mpfr_asin (2)\n");
147      mpfr_print_binary (x); printf ("\n");
148      mpfr_print_binary (y); printf ("\n");
149      exit (1);
150    }
151
152  mpfr_set_prec (x, 9);
153  mpfr_set_prec (y, 19);
154  mpfr_set_str_binary (x, "0.110000000E-6");
155  mpfr_asin (y, x, MPFR_RNDD);
156  mpfr_set_prec (x, 19);
157  mpfr_set_str_binary (x, "0.1100000000000001001E-6");
158  if (mpfr_cmp (x, y))
159    {
160      printf ("Error: mpfr_asin (3)\n");
161      mpfr_dump (x);
162      mpfr_dump (y);
163      exit (1);
164    }
165
166  mpfr_clear (x);
167  mpfr_clear (y);
168}
169
170static void
171special_overflow (void)
172{
173  mpfr_t x, y;
174  mpfr_exp_t emin, emax;
175
176  emin = mpfr_get_emin ();
177  emax = mpfr_get_emax ();
178
179  set_emin (-125);
180  set_emax (128);
181  mpfr_init2 (x, 24);
182  mpfr_init2 (y, 48);
183  mpfr_set_str_binary (x, "0.101100100000000000110100E0");
184  mpfr_asin (y, x, MPFR_RNDN);
185  if (mpfr_cmp_str (y, "0.110001001101001111110000010110001000111011001000E0",
186                    2, MPFR_RNDN))
187    {
188      printf("Special Overflow error.\n");
189      mpfr_dump (y);
190      exit (1);
191    }
192  mpfr_clear (y);
193  mpfr_clear (x);
194  set_emin (emin);
195  set_emax (emax);
196}
197
198/* bug reported by Kevin Rauch on 15 December 2007 */
199static void
200test20071215 (void)
201{
202  mpfr_t x, y;
203
204  mpfr_init (x);
205  mpfr_init (y);
206
207  mpfr_set_ui (x, 0, MPFR_RNDN);
208  mpfr_neg (x, x, MPFR_RNDN);
209  mpfr_set_ui (y, 1, MPFR_RNDN);
210  mpfr_asin (y, x, MPFR_RNDN);
211  MPFR_ASSERTN(mpfr_zero_p (y) && MPFR_IS_NEG(y));
212
213  mpfr_set_ui (x, 0, MPFR_RNDN);
214  mpfr_set_si (y, -1, MPFR_RNDN);
215  mpfr_asin (y, x, MPFR_RNDN);
216  MPFR_ASSERTN(mpfr_zero_p (y) && MPFR_IS_POS(y));
217
218  mpfr_clear (x);
219  mpfr_clear (y);
220}
221
222static void
223reduced_expo_range (void)
224{
225  mpfr_exp_t emin, emax;
226  mpfr_t x, y, ex_y;
227  int inex, ex_inex;
228  unsigned int flags, ex_flags;
229
230  emin = mpfr_get_emin ();
231  emax = mpfr_get_emax ();
232
233  mpfr_inits2 (4, x, y, ex_y, (mpfr_ptr) 0);
234  mpfr_set_str (x, "-0.1e1", 2, MPFR_RNDN);
235
236  mpfr_set_emin (1);
237  mpfr_set_emax (1);
238  mpfr_clear_flags ();
239  inex = mpfr_asin (y, x, MPFR_RNDA);
240  flags = __gmpfr_flags;
241  mpfr_set_emin (emin);
242  mpfr_set_emax (emax);
243
244  mpfr_set_str (ex_y, "-0.1101e1", 2, MPFR_RNDN);
245  ex_inex = -1;
246  ex_flags = MPFR_FLAGS_INEXACT;
247
248  if (SIGN (inex) != ex_inex || flags != ex_flags ||
249      ! mpfr_equal_p (y, ex_y))
250    {
251      printf ("Error in reduced_expo_range\non x = ");
252      mpfr_dump (x);
253      printf ("Expected y = ");
254      mpfr_out_str (stdout, 2, 0, ex_y, MPFR_RNDN);
255      printf ("\n         inex = %d, flags = %u\n", ex_inex, ex_flags);
256      printf ("Got      y = ");
257      mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
258      printf ("\n         inex = %d, flags = %u\n", SIGN (inex), flags);
259      exit (1);
260    }
261
262  mpfr_clears (x, y, ex_y, (mpfr_ptr) 0);
263}
264
265int
266main (void)
267{
268  tests_start_mpfr ();
269
270  special ();
271  special_overflow ();
272  reduced_expo_range ();
273
274  test_generic (2, 100, 15);
275
276  tests_end_mpfr ();
277
278  data_check ("data/asin", mpfr_asin, "mpfr_asin");
279  bad_cases (mpfr_asin, mpfr_sin, "mpfr_asin", 256, -40, 1, 4, 128, 800, 30);
280
281  test20071215 ();
282
283  tests_end_mpfr ();
284  return 0;
285}
286