Home | History | Annotate | Line # | Download | only in tests
      1 /* ttan -- test file for mpc_tan.
      2 
      3 Copyright (C) 2008, 2011, 2012, 2013, 2020 INRIA
      4 
      5 This file is part of GNU MPC.
      6 
      7 GNU MPC is free software; you can redistribute it and/or modify it under
      8 the terms of the GNU Lesser General Public License as published by the
      9 Free Software Foundation; either version 3 of the License, or (at your
     10 option) any later version.
     11 
     12 GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
     13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
     15 more details.
     16 
     17 You should have received a copy of the GNU Lesser General Public License
     18 along with this program. If not, see http://www.gnu.org/licenses/ .
     19 */
     20 
     21 #include <stdlib.h>
     22 #include "mpc-tests.h"
     23 
     24 static void
     25 pure_real_argument (void)
     26 {
     27   /* tan(x -i*0) = tan(x) -i*0 */
     28   /* tan(x +i*0) = tan(x) +i*0 */
     29   mpfr_t x;
     30   mpfr_t tan_x;
     31   mpc_t z;
     32   mpc_t tan_z;
     33 
     34   mpfr_init2 (x, 79);
     35   mpfr_init2 (tan_x, 113);
     36   mpc_init2 (z, 79);
     37   mpc_init2 (tan_z, 113);
     38 
     39   /* tan(1 +i*0) = tan(1) +i*0 */
     40   mpc_set_ui_ui (z, 1, 0, MPC_RNDNN);
     41   mpfr_set_ui (x, 1, MPFR_RNDN);
     42   mpfr_tan (tan_x, x, MPFR_RNDN);
     43   mpc_tan (tan_z, z, MPC_RNDNN);
     44   if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
     45       || !mpfr_zero_p (mpc_imagref (tan_z)) || mpfr_signbit (mpc_imagref (tan_z)))
     46     {
     47       printf ("mpc_tan(1 + i * 0) failed\n");
     48       exit (1);
     49     }
     50 
     51   /* tan(1 -i*0) = tan(1) -i*0 */
     52   mpc_conj (z, z, MPC_RNDNN);
     53   mpc_tan (tan_z, z, MPC_RNDNN);
     54   if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
     55       || !mpfr_zero_p (mpc_imagref (tan_z)) || !mpfr_signbit (mpc_imagref (tan_z)))
     56     {
     57       printf ("mpc_tan(1 - i * 0) failed\n");
     58       exit (1);
     59     }
     60 
     61   /* tan(Pi/2 +i*0) = +Inf +i*0 */
     62   mpfr_const_pi (x, MPFR_RNDN);
     63   mpfr_div_2ui (x, x, 1, MPFR_RNDN);
     64   mpfr_set (mpc_realref (z), x, MPFR_RNDN);
     65   mpfr_set_ui (mpc_imagref (z), 0, MPFR_RNDN);
     66   mpfr_tan (tan_x, x, MPFR_RNDN);
     67   mpc_tan (tan_z, z, MPC_RNDNN);
     68   if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
     69       || !mpfr_zero_p (mpc_imagref (tan_z)) || mpfr_signbit (mpc_imagref (tan_z)))
     70     {
     71       printf ("mpc_tan(Pi/2 + i * 0) failed\n");
     72       exit (1);
     73     }
     74 
     75   /* tan(Pi/2 -i*0) = +Inf -i*0 */
     76   mpc_conj (z, z, MPC_RNDNN);
     77   mpc_tan (tan_z, z, MPC_RNDNN);
     78   if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
     79       || !mpfr_zero_p (mpc_imagref (tan_z)) || !mpfr_signbit (mpc_imagref (tan_z)))
     80     {
     81       printf ("mpc_tan(Pi/2 - i * 0) failed\n");
     82       exit (1);
     83     }
     84 
     85   /* tan(-Pi/2 +i*0) = -Inf +i*0 */
     86   mpfr_neg (x, x, MPFR_RNDN);
     87   mpc_neg (z, z, MPC_RNDNN);
     88   mpfr_tan (tan_x, x, MPFR_RNDN);
     89   mpc_tan (tan_z, z, MPC_RNDNN);
     90   if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
     91       || !mpfr_zero_p (mpc_imagref (tan_z)) || mpfr_signbit (mpc_imagref (tan_z)))
     92     {
     93       printf ("mpc_tan(-Pi/2 + i * 0) failed\n");
     94       exit (1);
     95     }
     96 
     97   /* tan(-Pi/2 -i*0) = -Inf -i*0 */
     98   mpc_conj (z, z, MPC_RNDNN);
     99   mpc_tan (tan_z, z, MPC_RNDNN);
    100   if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
    101       || !mpfr_zero_p (mpc_imagref (tan_z)) || !mpfr_signbit (mpc_imagref (tan_z)))
    102     {
    103       printf ("mpc_tan(-Pi/2 - i * 0) failed\n");
    104       exit (1);
    105     }
    106 
    107   mpc_clear (tan_z);
    108   mpc_clear (z);
    109   mpfr_clear (tan_x);
    110   mpfr_clear (x);
    111 }
    112 
    113 static void
    114 pure_imaginary_argument (void)
    115 {
    116   /* tan(-0 +i*y) = -0 +i*tanh(y) */
    117   /* tan(+0 +i*y) = +0 +i*tanh(y) */
    118   mpfr_t y;
    119   mpfr_t tanh_y;
    120   mpc_t z;
    121   mpc_t tan_z;
    122   mpfr_prec_t prec = (mpfr_prec_t) 111;
    123 
    124   mpfr_init2 (y, 2);
    125   mpfr_init2 (tanh_y, prec);
    126   mpc_init2 (z, 2);
    127   mpc_init2 (tan_z, prec);
    128 
    129   /* tan(0 +i) = +0 +i*tanh(1) */
    130   mpc_set_ui_ui (z, 0, 1, MPC_RNDNN);
    131   mpfr_set_ui (y, 1, MPFR_RNDN);
    132   mpfr_tanh (tanh_y, y, MPFR_RNDN);
    133   mpc_tan (tan_z, z, MPC_RNDNN);
    134   if (mpfr_cmp (mpc_imagref (tan_z), tanh_y) != 0
    135       || !mpfr_zero_p (mpc_realref (tan_z)) || mpfr_signbit (mpc_realref (tan_z)))
    136     {
    137       mpc_t c99;
    138 
    139       mpc_init2 (c99, prec);
    140       mpfr_set_ui (mpc_realref (c99), 0, MPFR_RNDN);
    141       mpfr_set (mpc_imagref (c99), tanh_y, MPFR_RNDN);
    142 
    143       TEST_FAILED ("mpc_tan", z, tan_z, c99, MPC_RNDNN);
    144     }
    145 
    146   /* tan(0 -i) = +0 +i*tanh(-1) */
    147   mpc_conj (z, z, MPC_RNDNN);
    148   mpfr_neg (tanh_y, tanh_y, MPFR_RNDN);
    149   mpc_tan (tan_z, z, MPC_RNDNN);
    150   if (mpfr_cmp (mpc_imagref (tan_z), tanh_y) != 0
    151       || !mpfr_zero_p (mpc_realref (tan_z)) || mpfr_signbit (mpc_realref (tan_z)))
    152     {
    153       mpc_t c99;
    154 
    155       mpc_init2 (c99, prec);
    156       mpfr_set_ui (mpc_realref (c99), 0, MPFR_RNDN);
    157       mpfr_set (mpc_imagref (c99), tanh_y, MPFR_RNDN);
    158 
    159       TEST_FAILED ("mpc_tan", z, tan_z, c99, MPC_RNDNN);
    160     }
    161 
    162   /* tan(-0 +i) = -0 +i*tanh(1) */
    163   mpc_neg (z, z, MPC_RNDNN);
    164   mpfr_neg (tanh_y, tanh_y, MPFR_RNDN);
    165   mpc_tan (tan_z, z, MPC_RNDNN);
    166   if (mpfr_cmp (mpc_imagref (tan_z), tanh_y) != 0
    167       || !mpfr_zero_p (mpc_realref (tan_z)) || !mpfr_signbit (mpc_realref (tan_z)))
    168     {
    169       mpc_t c99;
    170 
    171       mpc_init2 (c99, prec);
    172       mpfr_set_ui (mpc_realref (c99), 0, MPFR_RNDN);
    173       mpfr_set (mpc_imagref (c99), tanh_y, MPFR_RNDN);
    174 
    175       TEST_FAILED ("mpc_tan", z, tan_z, c99, MPC_RNDNN);
    176     }
    177 
    178   /* tan(-0 -i) = -0 +i*tanh(-1) */
    179   mpc_conj (z, z, MPC_RNDNN);
    180   mpfr_neg (tanh_y, tanh_y, MPFR_RNDN);
    181   mpc_tan (tan_z, z, MPC_RNDNN);
    182   if (mpfr_cmp (mpc_imagref (tan_z), tanh_y) != 0
    183       || !mpfr_zero_p (mpc_realref (tan_z)) || !mpfr_signbit (mpc_realref (tan_z)))
    184     {
    185       mpc_t c99;
    186 
    187       mpc_init2 (c99, prec);
    188       mpfr_set_ui (mpc_realref (c99), 0, MPFR_RNDN);
    189       mpfr_set (mpc_imagref (c99), tanh_y, MPFR_RNDN);
    190 
    191       TEST_FAILED ("mpc_tan", z, tan_z, c99, MPC_RNDNN);
    192     }
    193 
    194   mpc_clear (tan_z);
    195   mpc_clear (z);
    196   mpfr_clear (tanh_y);
    197   mpfr_clear (y);
    198 }
    199 
    200 /* test with reduced exponent range */
    201 static void
    202 bug20200211 (void)
    203 {
    204   mpfr_exp_t emin = mpfr_get_emin ();
    205   mpc_t x, z, zr;
    206 
    207   mpfr_set_emin (-148);
    208   mpc_init2 (x, 24);
    209   mpc_init2 (z, 24);
    210   mpc_init2 (zr, 24);
    211   mpfr_set_flt (mpc_realref (x), 0x3.b32d48p24, MPFR_RNDN);
    212   mpfr_set_flt (mpc_imagref (x), -0x48.08bd0p0, MPFR_RNDN);
    213   mpc_tan (z, x, MPC_RNDNN);
    214   /* the real part should be 1.8638349976774607754968796608e-63,
    215      but since that underflows, we should get +0 */
    216   mpfr_set_flt (mpc_realref (zr), +0.0f, MPFR_RNDN);
    217   mpfr_set_flt (mpc_imagref (zr), -1.0f, MPFR_RNDN);
    218   if (mpc_cmp (z, zr))
    219     {
    220       printf ("Incorrect tangent with reduced exponent range:\n");
    221       mpfr_printf ("Expected (%Re,%Re)\n", mpc_realref (zr), mpc_imagref (zr));
    222       mpfr_printf ("Got      (%Re,%Re)\n", mpc_realref (z), mpc_imagref (z));
    223       exit (1);
    224     }
    225   mpc_clear (x);
    226   mpc_clear (z);
    227   mpc_clear (zr);
    228   mpfr_set_emin (emin);
    229 }
    230 
    231 /* test failing with gcc 5.4.0, line 127 of tan.dat */
    232 static void
    233 bug20200301 (void)
    234 {
    235   mpc_t x, z, zr;
    236   int inex;
    237 
    238   mpc_init2 (x, 53);
    239   mpc_init2 (z, 53);
    240   mpc_init2 (zr, 53);
    241   mpfr_set_d (mpc_realref (x), 0x4580CBF242683p-3, MPFR_RNDN);
    242   mpfr_set_d (mpc_imagref (x), -0x1B3E8A3660D279p-3, MPFR_RNDN);
    243   inex = mpc_tan (z, x, MPC_RNDNN);
    244   mpfr_set_d (mpc_realref (zr), -0.0, MPFR_RNDN);
    245   mpfr_set_d (mpc_imagref (zr), -1.0, MPFR_RNDN);
    246   if (mpc_cmp (z, zr) != 0 || mpfr_signbit (mpc_realref (z)) == 0 ||
    247       MPC_INEX_RE(inex) <= 0 || MPC_INEX_IM(inex) >= 0)
    248     {
    249       printf ("Incorrect tangent (bug20200301):\n");
    250       mpfr_printf ("Expected (%Re,%Re)\n", mpc_realref (zr), mpc_imagref (zr));
    251       mpfr_printf ("Got      (%Re,%Re)\n", mpc_realref (z), mpc_imagref (z));
    252       mpfr_printf ("expected ternary value (+1, -1)\n");
    253       mpfr_printf ("got      ternary value (%d, %d)\n", MPC_INEX_RE(inex),
    254                    MPC_INEX_IM(inex));
    255       exit (1);
    256     }
    257   mpc_clear (x);
    258   mpc_clear (z);
    259   mpc_clear (zr);
    260 }
    261 
    262 #define MPC_FUNCTION_CALL                                       \
    263   P[0].mpc_inex = mpc_tan (P[1].mpc, P[2].mpc, P[3].mpc_rnd)
    264 #define MPC_FUNCTION_CALL_REUSE_OP1                             \
    265   P[0].mpc_inex = mpc_tan (P[1].mpc, P[1].mpc, P[3].mpc_rnd)
    266 
    267 #include "data_check.tpl"
    268 #include "tgeneric.tpl"
    269 
    270 int
    271 main (void)
    272 {
    273   test_start ();
    274 
    275   bug20200301 ();
    276   bug20200211 ();
    277 
    278   data_check_template ("tan.dsc", "tan.dat");
    279 
    280   tgeneric_template ("tan.dsc", 2, 512, 7, 4);
    281 
    282   /* FIXME: remove them? */
    283   pure_real_argument ();
    284   pure_imaginary_argument ();
    285 
    286   test_end ();
    287 
    288   return 0;
    289 }
    290