1 /* Test file for mpfr_sinu. 2 3 Copyright 2020-2023 Free Software Foundation, Inc. 4 Contributed by the AriC and Caramba projects, INRIA. 5 6 This file is part of the GNU MPFR Library. 7 8 The GNU MPFR Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MPFR Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23 #include "mpfr-test.h" 24 25 static void 26 test_singular (void) 27 { 28 mpfr_t x, y; 29 int inexact; 30 31 mpfr_init (x); 32 mpfr_init (y); 33 34 /* check u = 0 */ 35 mpfr_set_ui (x, 17, MPFR_RNDN); 36 inexact = mpfr_sinu (y, x, 0, MPFR_RNDN); 37 MPFR_ASSERTN(mpfr_nan_p (y)); 38 39 /* check x = NaN */ 40 mpfr_set_nan (x); 41 inexact = mpfr_sinu (y, x, 1, MPFR_RNDN); 42 MPFR_ASSERTN(mpfr_nan_p (y)); 43 44 /* check x = +Inf */ 45 mpfr_set_inf (x, 1); 46 inexact = mpfr_sinu (y, x, 1, MPFR_RNDN); 47 MPFR_ASSERTN(mpfr_nan_p (y)); 48 49 /* check x = -Inf */ 50 mpfr_set_inf (x, -1); 51 inexact = mpfr_sinu (y, x, 1, MPFR_RNDN); 52 MPFR_ASSERTN(mpfr_nan_p (y)); 53 54 /* check x = +0 */ 55 mpfr_set_zero (x, 1); 56 inexact = mpfr_sinu (y, x, 1, MPFR_RNDN); 57 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0); 58 MPFR_ASSERTN(inexact == 0); 59 60 /* check x = -0 */ 61 mpfr_set_zero (x, -1); 62 inexact = mpfr_sinu (y, x, 1, MPFR_RNDN); 63 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0); 64 MPFR_ASSERTN(inexact == 0); 65 66 mpfr_clear (x); 67 mpfr_clear (y); 68 } 69 70 static void 71 test_exact (void) 72 { 73 mpfr_t x, y; 74 int inexact; 75 76 mpfr_init (x); 77 mpfr_init (y); 78 79 /* check 2*pi*x/u = pi/2 thus x/u = 1/4, for example x=1 and u=4 */ 80 mpfr_set_ui (x, 1, MPFR_RNDN); 81 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN); 82 MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0); 83 84 /* check 2*pi*x/u = pi thus x/u = 1/2, for example x=2 and u=4 */ 85 mpfr_set_ui (x, 2, MPFR_RNDN); 86 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN); 87 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0); 88 MPFR_ASSERTN(inexact == 0); 89 90 /* check 2*pi*x/u = 3*pi/2 thus x/u = 3/4, for example x=3 and u=4 */ 91 mpfr_set_ui (x, 3, MPFR_RNDN); 92 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN); 93 MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0); 94 95 /* check 2*pi*x/u = 2*pi thus x/u = 1, for example x=4 and u=4 */ 96 mpfr_set_ui (x, 4, MPFR_RNDN); 97 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN); 98 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0); 99 MPFR_ASSERTN(inexact == 0); 100 101 /* check x/u = 2^16, for example x=3*2^16 and u=3 */ 102 mpfr_set_ui_2exp (x, 3, 16, MPFR_RNDN); 103 inexact = mpfr_sinu (y, x, 3, MPFR_RNDN); 104 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0); 105 MPFR_ASSERTN(inexact == 0); 106 107 /* check 2*pi*x/u = -pi/2 thus x/u = -1/4, for example x=-1 and u=4 */ 108 mpfr_set_si (x, -1, MPFR_RNDN); 109 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN); 110 MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0); 111 112 /* check 2*pi*x/u = -pi thus x/u = -1/2, for example x=-2 and u=4 */ 113 mpfr_set_si (x, -2, MPFR_RNDN); 114 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN); 115 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0); 116 MPFR_ASSERTN(inexact == 0); 117 118 /* check 2*pi*x/u = -3*pi/2 thus x/u = -3/4, for example x=-3 and u=4 */ 119 mpfr_set_si (x, -3, MPFR_RNDN); 120 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN); 121 MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0); 122 123 /* check 2*pi*x/u = -2*pi thus x/u = -1, for example x=-4 and u=4 */ 124 mpfr_set_si (x, -4, MPFR_RNDN); 125 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN); 126 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0); 127 MPFR_ASSERTN(inexact == 0); 128 129 /* check x/u = -2^16, for example x=-3*2^16 and u=3 */ 130 mpfr_set_si_2exp (x, -3, 16, MPFR_RNDN); 131 inexact = mpfr_sinu (y, x, 3, MPFR_RNDN); 132 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0); 133 MPFR_ASSERTN(inexact == 0); 134 135 /* check 2*pi*x/u = pi/6, for example x=1 and u=12 */ 136 mpfr_set_ui (x, 1, MPFR_RNDN); 137 inexact = mpfr_sinu (y, x, 12, MPFR_RNDN); 138 MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0 && inexact == 0); 139 140 /* check 2*pi*x/u = 5*pi/6, for example x=5 and u=12 */ 141 mpfr_set_ui (x, 5, MPFR_RNDN); 142 inexact = mpfr_sinu (y, x, 12, MPFR_RNDN); 143 MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0 && inexact == 0); 144 145 /* check 2*pi*x/u = 7*pi/6, for example x=5 and u=12 */ 146 mpfr_set_ui (x, 7, MPFR_RNDN); 147 inexact = mpfr_sinu (y, x, 12, MPFR_RNDN); 148 MPFR_ASSERTN(mpfr_cmp_si_2exp (y, -1, -1) == 0 && inexact == 0); 149 150 /* check 2*pi*x/u = 11*pi/6, for example x=5 and u=12 */ 151 mpfr_set_ui (x, 11, MPFR_RNDN); 152 inexact = mpfr_sinu (y, x, 12, MPFR_RNDN); 153 MPFR_ASSERTN(mpfr_cmp_si_2exp (y, -1, -1) == 0 && inexact == 0); 154 155 mpfr_clear (x); 156 mpfr_clear (y); 157 } 158 159 static void 160 test_regular (void) 161 { 162 mpfr_t x, y, z; 163 int inexact; 164 165 mpfr_init2 (x, 53); 166 mpfr_init2 (y, 53); 167 mpfr_init2 (z, 53); 168 169 mpfr_set_ui (x, 17, MPFR_RNDN); 170 inexact = mpfr_sinu (y, x, 42, MPFR_RNDN); 171 /* y should be sin(2*17*pi/42) rounded to nearest */ 172 mpfr_set_str (z, "0x9.035be4a906768p-4", 16, MPFR_RNDN); 173 MPFR_ASSERTN(mpfr_equal_p (y, z)); 174 MPFR_ASSERTN(inexact > 0); 175 176 mpfr_clear (x); 177 mpfr_clear (y); 178 mpfr_clear (z); 179 } 180 181 /* Check argument reduction with large hard-coded inputs. The following 182 values were generated with gen_random(sin,10,53,100,20), where the 183 Sage code for gen_random is given in the tcosu.c file. */ 184 static void 185 test_large (void) 186 { 187 static struct { 188 const char *x; 189 unsigned long u; 190 const char *y; 191 } t[] = { 192 { "-0x4.338bcaf01cb4p+16", 37, "0xa.a85c8758c1228p-4" }, 193 { "-0x6.01aa844d11acp+16", 12, "0x4.46e2cea96ee2cp-4" }, 194 { "-0x7.997759de3b3dp+16", 35, "0xf.144b13bc0b008p-4" }, 195 { "-0xc.74f72253bc7ep+16", 74, "-0x9.1c24e8ac6fb48p-4" }, 196 { "-0x4.ea97564d3ecp+12", 93, "0x3.2d49033cc4556p-4" }, 197 { "0xc.1cd85e0766ffp+16", 48, "-0xd.74b642b1c7368p-4" }, 198 { "0xe.add2f0441bap+16", 82, "-0xf.fc35c5a5e1448p-4" }, 199 { "0xc.8feb943a0fe5p+16", 43, "-0x5.8af3e0e11b794p-4" }, 200 { "-0xd.d61b06ace6d9p+16", 55, "0xa.175c9f7e4ede8p-4" }, 201 { "0xb.cf036b4e5fap+12", 46, "0x1.b7128e1975d9ap-4" }, 202 /* The following case does not come from the random values. 203 Here, x mod u may need more precision than x. */ 204 { "0x3.p+16", 99, "-0xb.e4a8a986c9fd03ap-5" } 205 }; 206 int i; 207 mpfr_t x, y, z; 208 209 mpfr_inits2 (53, x, y, z, (mpfr_ptr) 0); 210 for (i = 0; i < numberof (t); i++) 211 { 212 mpfr_set_str (x, t[i].x, 0, MPFR_RNDN); 213 mpfr_set_str (y, t[i].y, 0, MPFR_RNDN); 214 mpfr_sinu (z, x, t[i].u, MPFR_RNDN); 215 MPFR_ASSERTN (mpfr_equal_p (y, z)); 216 /* Same test after reducing the precision of x to its minimum one. */ 217 mpfr_prec_round (x, mpfr_min_prec (x), MPFR_RNDN); 218 mpfr_sinu (z, x, t[i].u, MPFR_RNDN); 219 MPFR_ASSERTN (mpfr_equal_p (y, z)); 220 mpfr_prec_round (x, 53, MPFR_RNDN); 221 } 222 mpfr_clears (x, y, z, (mpfr_ptr) 0); 223 } 224 225 #define TEST_FUNCTION mpfr_sinu 226 #define ULONG_ARG2 227 #include "tgeneric.c" 228 229 static int 230 mpfr_sin2pi (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t r) 231 { 232 return mpfr_sinu (y, x, 1, r); 233 } 234 235 int 236 main (void) 237 { 238 tests_start_mpfr (); 239 240 test_singular (); 241 test_exact (); 242 test_regular (); 243 test_large (); 244 245 test_generic (MPFR_PREC_MIN, 100, 1000); 246 247 data_check ("data/sin2pi", mpfr_sin2pi, "mpfr_sin2pi"); 248 249 tests_end_mpfr (); 250 return 0; 251 } 252