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