(root)/
mpfr-4.2.1/
tests/
thypot.c
       1  /* Test file for mpfr_hypot.
       2  
       3  Copyright 2001-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  /* Non-zero when extended exponent range */
      26  static int ext = 0;
      27  
      28  static void
      29  special (void)
      30  {
      31    mpfr_t x, y, z;
      32  
      33    mpfr_init (x);
      34    mpfr_init (y);
      35    mpfr_init (z);
      36  
      37    mpfr_set_nan (x);
      38    mpfr_set_ui (y, 0, MPFR_RNDN);
      39    mpfr_hypot (z, x, x, MPFR_RNDN);
      40    MPFR_ASSERTN(mpfr_nan_p (z));
      41    mpfr_hypot (z, x, y, MPFR_RNDN);
      42    MPFR_ASSERTN(mpfr_nan_p (z));
      43    mpfr_hypot (z, y, x, MPFR_RNDN);
      44    MPFR_ASSERTN(mpfr_nan_p (z));
      45  
      46    mpfr_set_inf (x, 1);
      47    mpfr_set_inf (y, -1);
      48    mpfr_hypot (z, x, y, MPFR_RNDN);
      49    MPFR_ASSERTN(mpfr_inf_p (z) && mpfr_sgn (z) > 0);
      50  
      51    mpfr_set_inf (x, -1);
      52    mpfr_set_nan (y);
      53    mpfr_hypot (z, x, y, MPFR_RNDN);
      54    MPFR_ASSERTN(mpfr_inf_p (z) && mpfr_sgn (z) > 0);
      55  
      56    mpfr_set_nan (x);
      57    mpfr_set_inf (y, -1);
      58    mpfr_hypot (z, x, y, MPFR_RNDN);
      59    MPFR_ASSERTN(mpfr_inf_p (z) && mpfr_sgn (z) > 0);
      60  
      61    mpfr_clear (x);
      62    mpfr_clear (y);
      63    mpfr_clear (z);
      64  }
      65  
      66  static void
      67  test_large (void)
      68  {
      69    mpfr_t x, y, z, t;
      70  
      71    mpfr_init (x);
      72    mpfr_init (y);
      73    mpfr_init (z);
      74    mpfr_init (t);
      75  
      76    mpfr_set_ui (x, 21, MPFR_RNDN);
      77    mpfr_set_ui (y, 28, MPFR_RNDN);
      78    mpfr_set_ui (z, 35, MPFR_RNDN);
      79  
      80    mpfr_mul_2ui (x, x, MPFR_EMAX_DEFAULT-6, MPFR_RNDN);
      81    mpfr_mul_2ui (y, y, MPFR_EMAX_DEFAULT-6, MPFR_RNDN);
      82    mpfr_mul_2ui (z, z, MPFR_EMAX_DEFAULT-6, MPFR_RNDN);
      83  
      84    mpfr_hypot (t, x, y, MPFR_RNDN);
      85    if (mpfr_cmp (z, t))
      86      {
      87        printf ("Error in test_large: got\n");
      88        mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN);
      89        printf ("\ninstead of\n");
      90        mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
      91        printf ("\n");
      92        exit (1);
      93      }
      94  
      95    mpfr_set_prec (x, 53);
      96    mpfr_set_prec (t, 53);
      97    mpfr_set_prec (y, 53);
      98    mpfr_set_str_binary (x, "0.11101100011110000011101000010101010011001101000001100E-1021");
      99    mpfr_set_str_binary (y, "0.11111001010011000001110110001101011100001000010010100E-1021");
     100    mpfr_hypot (t, x, y, MPFR_RNDN);
     101    mpfr_set_str_binary (z, "0.101010111100110111101110111110100110010011001010111E-1020");
     102    if (mpfr_cmp (z, t))
     103      {
     104        printf ("Error in test_large: got\n");
     105        mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN);
     106        printf ("\ninstead of\n");
     107        mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
     108        printf ("\n");
     109        exit (1);
     110      }
     111  
     112    mpfr_set_prec (x, 240);
     113    mpfr_set_prec (y, 22);
     114    mpfr_set_prec (z, 2);
     115    mpfr_set_prec (t, 2);
     116    mpfr_set_str_binary (x, "0.100111011010010010110100000100000001100010011100110101101111111101011110111011011101010110100101111000111100010100110000100101011110111011100110100110100101110101101100011000001100000001111101110100100100011011011010110111100110010101000111e-7");
     117    mpfr_set_str_binary (y, "0.1111000010000011000111E-10");
     118    mpfr_hypot (t, x, y, MPFR_RNDN);
     119    mpfr_set_str_binary (z, "0.11E-7");
     120    if (mpfr_cmp (z, t))
     121      {
     122        printf ("Error in test_large: got\n");
     123        mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN);
     124        printf ("\ninstead of\n");
     125        mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
     126        printf ("\n");
     127        exit (1);
     128      }
     129  
     130    mpfr_clear (x);
     131    mpfr_clear (y);
     132    mpfr_clear (z);
     133    mpfr_clear (t);
     134  }
     135  
     136  static void
     137  test_small (void)
     138  {
     139    mpfr_t x, y, z1, z2;
     140    int inex1, inex2;
     141    unsigned int flags;
     142  
     143    /* Test hypot(x,x) with x = 2^(emin-1). Result is x * sqrt(2). */
     144    mpfr_inits2 (8, x, y, z1, z2, (mpfr_ptr) 0);
     145    mpfr_set_si_2exp (x, 1, mpfr_get_emin () - 1, MPFR_RNDN);
     146    mpfr_set_si_2exp (y, 1, mpfr_get_emin () - 1, MPFR_RNDN);
     147    mpfr_set_ui (z1, 2, MPFR_RNDN);
     148    inex1 = mpfr_sqrt (z1, z1, MPFR_RNDN);
     149    inex2 = mpfr_mul (z1, z1, x, MPFR_RNDN);
     150    MPFR_ASSERTN (inex2 == 0);
     151    mpfr_clear_flags ();
     152    inex2 = mpfr_hypot (z2, x, y, MPFR_RNDN);
     153    flags = __gmpfr_flags;
     154    if (mpfr_cmp (z1, z2) != 0)
     155      {
     156        printf ("Error in test_small%s\nExpected ",
     157                ext ? ", extended exponent range" : "");
     158        mpfr_out_str (stdout, 2, 0, z1, MPFR_RNDN);
     159        printf ("\nGot      ");
     160        mpfr_out_str (stdout, 2, 0, z2, MPFR_RNDN);
     161        printf ("\n");
     162        exit (1);
     163      }
     164    if (! SAME_SIGN (inex1, inex2))
     165      {
     166        printf ("Bad ternary value in test_small%s\nExpected %d, got %d\n",
     167                ext ? ", extended exponent range" : "", inex1, inex2);
     168        exit (1);
     169      }
     170    if (flags != MPFR_FLAGS_INEXACT)
     171      {
     172        printf ("Bad flags in test_small%s\nExpected %u, got %u\n",
     173                ext ? ", extended exponent range" : "",
     174                (unsigned int) MPFR_FLAGS_INEXACT, flags);
     175        exit (1);
     176      }
     177    mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0);
     178  }
     179  
     180  static void
     181  test_large_small (void)
     182  {
     183    mpfr_t x, y, z;
     184    int inexact, inex2, r;
     185  
     186    mpfr_init2 (x, 3);
     187    mpfr_init2 (y, 2);
     188    mpfr_init2 (z, 2);
     189  
     190    mpfr_set_ui_2exp (x, 1, mpfr_get_emax () / 2, MPFR_RNDN);
     191    mpfr_set_ui_2exp (y, 1, -1, MPFR_RNDN);
     192    inexact = mpfr_hypot (z, x, y, MPFR_RNDN);
     193    if (inexact >= 0 || mpfr_cmp (x, z))
     194      {
     195        printf ("Error 1 in test_large_small%s\n",
     196                ext ? ", extended exponent range" : "");
     197        exit (1);
     198      }
     199  
     200    mpfr_mul_ui (x, x, 5, MPFR_RNDN);
     201    inexact = mpfr_hypot (z, x, y, MPFR_RNDN);
     202    if (mpfr_cmp (x, z) >= 0)
     203      {
     204        printf ("Error 2 in test_large_small%s\n",
     205                ext ? ", extended exponent range" : "");
     206        printf ("x = ");
     207        mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
     208        printf ("\n");
     209        printf ("y = ");
     210        mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
     211        printf ("\n");
     212        printf ("z = ");
     213        mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
     214        printf (" (in precision 2) instead of\n    ");
     215        mpfr_out_str (stdout, 2, 2, x, MPFR_RNDU);
     216        printf ("\n");
     217        exit (1);
     218      }
     219  
     220    RND_LOOP(r)
     221      {
     222        mpfr_set_ui_2exp (x, 1, mpfr_get_emax () - 1, MPFR_RNDN);
     223        mpfr_set_ui_2exp (y, 1, mpfr_get_emin (), MPFR_RNDN);
     224        inexact = mpfr_hypot (z, x, y, (mpfr_rnd_t) r);
     225        inex2 = mpfr_add_ui (y, x, 1, (mpfr_rnd_t) r);
     226        if (! mpfr_equal_p (y, z) || ! SAME_SIGN (inexact, inex2))
     227          {
     228            printf ("Error 3 in test_large_small, %s%s\n",
     229                    mpfr_print_rnd_mode ((mpfr_rnd_t) r),
     230                    ext ? ", extended exponent range" : "");
     231            printf ("Expected ");
     232            mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
     233            printf (", inex = %d\n", inex2);
     234            printf ("Got      ");
     235            mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
     236            printf (", inex = %d\n", inexact);
     237            exit (1);
     238          }
     239      }
     240  
     241    mpfr_clear (x);
     242    mpfr_clear (y);
     243    mpfr_clear (z);
     244  }
     245  
     246  static void
     247  check_overflow (void)
     248  {
     249    mpfr_t x, y;
     250    int inex, r;
     251  
     252    mpfr_inits2 (8, x, y, (mpfr_ptr) 0);
     253    mpfr_set_ui (x, 1, MPFR_RNDN);
     254    mpfr_setmax (x, mpfr_get_emax ());
     255  
     256    RND_LOOP(r)
     257      {
     258        mpfr_clear_overflow ();
     259        inex = mpfr_hypot (y, x, x, (mpfr_rnd_t) r);
     260        if (!mpfr_overflow_p ())
     261          {
     262            printf ("No overflow in check_overflow for %s%s\n",
     263                    mpfr_print_rnd_mode ((mpfr_rnd_t) r),
     264                    ext ? ", extended exponent range" : "");
     265            exit (1);
     266          }
     267        MPFR_ASSERTN (MPFR_IS_POS (y));
     268        if (r == MPFR_RNDZ || r == MPFR_RNDD)
     269          {
     270            MPFR_ASSERTN (inex < 0);
     271            MPFR_ASSERTN (!mpfr_inf_p (y));
     272            mpfr_nexttoinf (y);
     273          }
     274        else
     275          {
     276            MPFR_ASSERTN (inex > 0);
     277          }
     278        MPFR_ASSERTN (mpfr_inf_p (y));
     279      }
     280  
     281    mpfr_clears (x, y, (mpfr_ptr) 0);
     282  }
     283  
     284  #define TWO_ARGS
     285  #define TEST_FUNCTION mpfr_hypot
     286  #include "tgeneric.c"
     287  
     288  static void
     289  alltst (void)
     290  {
     291    mpfr_exp_t emin, emax;
     292  
     293    ext = 0;
     294    test_small ();
     295    test_large_small ();
     296    check_overflow ();
     297  
     298    emin = mpfr_get_emin ();
     299    emax = mpfr_get_emax ();
     300    set_emin (MPFR_EMIN_MIN);
     301    set_emax (MPFR_EMAX_MAX);
     302    if (mpfr_get_emin () != emin || mpfr_get_emax () != emax)
     303      {
     304        ext = 1;
     305        test_small ();
     306        test_large_small ();
     307        check_overflow ();
     308        set_emin (emin);
     309        set_emax (emax);
     310      }
     311  }
     312  
     313  /* Test failing with GMP_CHECK_RANDOMIZE=1513841234 (overflow flag not set).
     314     The bug was in fact in mpfr_nexttoinf which didn't set the overflow flag. */
     315  static void
     316  bug20171221 (void)
     317  {
     318    mpfr_t x, u, y;
     319    int inex;
     320    mpfr_exp_t emax;
     321  
     322    mpfr_init2 (x, 12);
     323    mpfr_init2 (u, 12);
     324    mpfr_init2 (y, 11);
     325    mpfr_set_str_binary (x, "0.111111111110E0");
     326    mpfr_set_str_binary (u, "0.111011110100E-177");
     327    emax = mpfr_get_emax ();
     328    set_emax (0);
     329    mpfr_clear_flags ();
     330    inex = mpfr_hypot (y, x, u, MPFR_RNDU);
     331    MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
     332    MPFR_ASSERTN(inex > 0);
     333    MPFR_ASSERTN(mpfr_inexflag_p ());
     334    MPFR_ASSERTN(mpfr_overflow_p ());
     335    set_emax (emax);
     336    mpfr_clear (x);
     337    mpfr_clear (u);
     338    mpfr_clear (y);
     339  }
     340  
     341  /* check overflow for x=0xf.ffffffffffff8p+1020 and u=0xf.fffffp+124
     342     with rounding upwards and emax=1024 (as in binary64) */
     343  static void
     344  test_overflow (void)
     345  {
     346    mpfr_t x, u, y;
     347    int inex;
     348    mpfr_exp_t emax;
     349  
     350    mpfr_init2 (x, 53);
     351    mpfr_init2 (u, 53);
     352    mpfr_init2 (y, 53);
     353    mpfr_set_str (x, "0xf.ffffffffffff8p+1020", 16, MPFR_RNDN);
     354    mpfr_set_str (u, "0xf.fffffp+124", 16, MPFR_RNDN);
     355    emax = mpfr_get_emax ();
     356    set_emax (1024);
     357    mpfr_clear_flags ();
     358    inex = mpfr_hypot (y, x, u, MPFR_RNDU);
     359    MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
     360    MPFR_ASSERTN(inex > 0);
     361    MPFR_ASSERTN(mpfr_inexflag_p ());
     362    MPFR_ASSERTN(mpfr_overflow_p ());
     363    set_emax (emax);
     364    mpfr_clear (x);
     365    mpfr_clear (u);
     366    mpfr_clear (y);
     367  }
     368  
     369  int
     370  main (int argc, char *argv[])
     371  {
     372    tests_start_mpfr ();
     373  
     374    bug20171221 ();
     375    special ();
     376  
     377    test_large ();
     378    alltst ();
     379    test_overflow ();
     380  
     381    test_generic (MPFR_PREC_MIN, 100, 10);
     382  
     383    tests_end_mpfr ();
     384    return 0;
     385  }