(root)/
mpfr-4.2.1/
tests/
tcosu.c
       1  /* Test file for mpfr_cosu.
       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_cosu (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_cosu (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_cosu (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_cosu (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_cosu (y, x, 1, MPFR_RNDN);
      57    MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
      58    MPFR_ASSERTN(inexact == 0);
      59  
      60    /* check x = -0 */
      61    mpfr_set_zero (x, -1);
      62    inexact = mpfr_cosu (y, x, 1, MPFR_RNDN);
      63    MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
      64    MPFR_ASSERTN(inexact == 0);
      65  
      66    /* check x/u = 2^16, for example x=3*2^16 and u=3 */
      67    mpfr_set_ui_2exp (x, 3, 16, MPFR_RNDN);
      68    inexact = mpfr_cosu (y, x, 3, MPFR_RNDN);
      69    MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
      70    MPFR_ASSERTN(inexact == 0);
      71  
      72    /* check x/u = -2^16, for example x=-3*2^16 and u=3 */
      73    mpfr_set_si_2exp (x, -3, 16, MPFR_RNDN);
      74    inexact = mpfr_cosu (y, x, 3, MPFR_RNDN);
      75    MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
      76    MPFR_ASSERTN(inexact == 0);
      77  
      78    mpfr_clear (x);
      79    mpfr_clear (y);
      80  }
      81  
      82  static void
      83  test_exact (void)
      84  {
      85    mpfr_t x, y;
      86    int inexact;
      87  
      88    mpfr_init (x);
      89    mpfr_init (y);
      90  
      91    /* check 2*pi*x/u = pi/2 thus x/u = 1/4, for example x=1 and u=4 */
      92    mpfr_set_ui (x, 1, MPFR_RNDN);
      93    inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
      94    MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
      95    MPFR_ASSERTN(inexact == 0);
      96  
      97    /* check 2*pi*x/u = pi thus x/u = 1/2, for example x=2 and u=4 */
      98    mpfr_set_ui (x, 2, MPFR_RNDN);
      99    inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
     100    MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0);
     101  
     102    /* check 2*pi*x/u = 3*pi/2 thus x/u = 3/4, for example x=3 and u=4 */
     103    mpfr_set_ui (x, 3, MPFR_RNDN);
     104    inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
     105    MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
     106    MPFR_ASSERTN(inexact == 0);
     107  
     108    /* check 2*pi*x/u = 2*pi thus x/u = 1, for example x=4 and u=4 */
     109    mpfr_set_ui (x, 4, MPFR_RNDN);
     110    inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
     111    MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0);
     112  
     113    /* check 2*pi*x/u = -pi/2 thus x/u = -1/4, for example x=-1 and u=4 */
     114    mpfr_set_si (x, -1, MPFR_RNDN);
     115    inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
     116    MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
     117    MPFR_ASSERTN(inexact == 0);
     118  
     119    /* check 2*pi*x/u = -pi thus x/u = -1/2, for example x=-2 and u=4 */
     120    mpfr_set_si (x, -2, MPFR_RNDN);
     121    inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
     122    MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0);
     123  
     124    /* check 2*pi*x/u = -3*pi/2 thus x/u = -3/4, for example x=-3 and u=4 */
     125    mpfr_set_si (x, -3, MPFR_RNDN);
     126    inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
     127    MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
     128    MPFR_ASSERTN(inexact == 0);
     129  
     130    /* check 2*pi*x/u = -2*pi thus x/u = -1, for example x=-4 and u=4 */
     131    mpfr_set_si (x, -4, MPFR_RNDN);
     132    inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
     133    MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0);
     134  
     135    /* check 2*pi*x/u = pi/3, for example x=1 and u=6 */
     136    mpfr_set_ui (x, 1, MPFR_RNDN);
     137    inexact = mpfr_cosu (y, x, 6, MPFR_RNDN);
     138    MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0 && inexact == 0);
     139  
     140    /* check 2*pi*x/u = 2*pi/3, for example x=2 and u=6 */
     141    mpfr_set_ui (x, 2, MPFR_RNDN);
     142    inexact = mpfr_cosu (y, x, 6, MPFR_RNDN);
     143    MPFR_ASSERTN(mpfr_cmp_si_2exp (y, -1, -1) == 0 && inexact == 0);
     144  
     145    /* check 2*pi*x/u = 4*pi/3, for example x=4 and u=6 */
     146    mpfr_set_ui (x, 4, MPFR_RNDN);
     147    inexact = mpfr_cosu (y, x, 6, MPFR_RNDN);
     148    MPFR_ASSERTN(mpfr_cmp_si_2exp (y, -1, -1) == 0 && inexact == 0);
     149  
     150    /* check 2*pi*x/u = 5*pi/3, for example x=5 and u=6 */
     151    mpfr_set_ui (x, 5, MPFR_RNDN);
     152    inexact = mpfr_cosu (y, x, 6, MPFR_RNDN);
     153    MPFR_ASSERTN(mpfr_cmp_ui_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_cosu (y, x, 42, MPFR_RNDN);
     171    /* y should be cos(2*17*pi/42) rounded to nearest */
     172    mpfr_set_str (z, "-0xd.38462625fd3ap-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 the following Sage code:
     183  # generate N random tests for f, with precision p, u < U, and |x| < 2^K
     184  # f might be cos (for cosu), sin (for sinu) or tan (for tanu)
     185  # gen_random(cos,10,53,100,20)
     186  def gen_random(f,N,p,U,K):
     187     R = RealField(p)
     188     for n in range(N):
     189        u = ZZ.random_element(U)
     190        x = R.random_element()*2^K
     191        q = p
     192        while true:
     193           q += 10
     194           RI = RealIntervalField(q)
     195           y = RI(f(2*pi*x.exact_rational()/u))
     196           if R(y.lower().exact_rational()) == R(y.upper().exact_rational()):
     197              break
     198        y = R(y.lower().exact_rational())
     199        print (x.hex(), u, y.hex()) */
     200  static void
     201  test_large (void)
     202  {
     203    static struct {
     204      const char *x;
     205      unsigned long u;
     206      const char *y;
     207    } t[] = {
     208      { "0xd.ddfeb0f4a01fp+16", 72, "0x4.8e54ce9b84d78p-4" },
     209      { "-0xb.ccb63f74f9abp+16", 36, "-0xb.cce98d64941bp-4" },
     210      { "0x9.8451e45ed4bap+16", 26, "-0xb.b205cfe8a13cp-4" },
     211      { "-0x7.6b4c16c45445p+16", 60, "-0x7.dee04000f4934p-4" },
     212      { "0x1.bb80916be884p+16", 43, "-0xc.059d9c8f1b7fp-4" },
     213      { "-0x5.4d3623b69226p+16", 1, "0xa.3cb353892757p-4" },
     214      { "0xd.1c59eab5a14bp+16", 58, "0x1.02978f1c99614p-4" },
     215      { "-0xf.bb1f858b9949p+16", 33, "-0x3.b53e5214db138p-4" },
     216      { "-0x2.9bcda761bb7p+16", 55, "-0x6.e6c08e7d92898p-4" },
     217      { "-0x9.f8f40e2c50f9p+16", 73, "0x7.0e0ff5e4dccbp-4" }
     218    };
     219    int i;
     220    mpfr_t x, y, z;
     221  
     222    mpfr_inits2 (53, x, y, z, (mpfr_ptr) 0);
     223    for (i = 0; i < numberof (t); i++)
     224      {
     225        mpfr_set_str (x, t[i].x, 0, MPFR_RNDN);
     226        mpfr_set_str (y, t[i].y, 0, MPFR_RNDN);
     227        mpfr_cosu (z, x, t[i].u, MPFR_RNDN);
     228        MPFR_ASSERTN (mpfr_equal_p (y, z));
     229      }
     230    mpfr_clears (x, y, z, (mpfr_ptr) 0);
     231  }
     232  
     233  #define TEST_FUNCTION mpfr_cosu
     234  #define ULONG_ARG2
     235  #include "tgeneric.c"
     236  
     237  static int
     238  mpfr_cos2pi (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t r)
     239  {
     240    return mpfr_cosu (y, x, 1, r);
     241  }
     242  
     243  int
     244  main (void)
     245  {
     246    tests_start_mpfr ();
     247  
     248    test_singular ();
     249    test_exact ();
     250    test_regular ();
     251    test_large ();
     252  
     253    /* Note: since the value of u can be large (up to 2^64 - 1 on 64-bit
     254       machines), the cos argument can be very small, yielding a special
     255       case in small precision. Thus it is better to use a maximum
     256       precision (second test_generic argument) that is large enough. */
     257    test_generic (MPFR_PREC_MIN, 200, 1000);
     258  
     259    data_check ("data/cos2pi", mpfr_cos2pi, "mpfr_cos2pi");
     260  
     261    tests_end_mpfr ();
     262    return 0;
     263  }