1  /* Copyright (C) 2007  Free Software Foundation.
       2  
       3     Verify that built-in math function constant folding of constant
       4     arguments is correctly performed by the compiler.  This testcase is
       5     for functionality that was available as of mpfr-2.3.0.
       6  
       7     Origin: Kaveh R. Ghazi,  April 23, 2007.  */
       8  
       9  /* { dg-do link } */
      10  
      11  /* All references to link_error should go away at compile-time.  */
      12  extern void link_error(int);
      13  
      14  /* Return TRUE if the sign of X != sign of Y.  This is important when
      15     comparing signed zeros.  */
      16  #define CKSGN_F(X,Y) \
      17    (__builtin_copysignf(1.0F,(X)) != __builtin_copysignf(1.0F,(Y)))
      18  #define CKSGN(X,Y) \
      19    (__builtin_copysign(1.0,(X)) != __builtin_copysign(1.0,(Y)))
      20  #define CKSGN_L(X,Y) \
      21    (__builtin_copysignl(1.0L,(X)) != __builtin_copysignl(1.0L,(Y)))
      22  
      23  /* Test that FUNC(ARG) == (RES).  */
      24  #define TESTIT(FUNC,ARG,RES) do { \
      25    if (__builtin_##FUNC##f(ARG##F) != RES##F \
      26        || CKSGN_F(__builtin_##FUNC##f(ARG##F),RES##F)) \
      27      link_error(__LINE__); \
      28    if (__builtin_##FUNC(ARG) != RES \
      29        || CKSGN(__builtin_##FUNC(ARG),RES)) \
      30      link_error(__LINE__); \
      31    if (__builtin_##FUNC##l(ARG##L) != RES##L \
      32        || CKSGN_L(__builtin_##FUNC##l(ARG##L),RES##L)) \
      33      link_error(__LINE__); \
      34    } while (0)
      35  
      36  /* Range test, check that (LOW) < FUNC(ARG) < (HI).  */
      37  #define TESTIT_R(FUNC,ARG,LOW,HI) do { \
      38    if (__builtin_##FUNC##f(ARG) <= (LOW) || __builtin_##FUNC##f(ARG) >= (HI)) \
      39      link_error(__LINE__); \
      40    if (__builtin_##FUNC(ARG) <= (LOW) || __builtin_##FUNC(ARG) >= (HI)) \
      41      link_error(__LINE__); \
      42    if (__builtin_##FUNC##l(ARG) <= (LOW) || __builtin_##FUNC##l(ARG) >= (HI)) \
      43      link_error(__LINE__); \
      44    } while (0)
      45  
      46  /* Test that FUNC(ARG1, ARG2) == (RES).  */
      47  #define TESTIT2(FUNC,ARG1,ARG2,RES) do { \
      48    if (__builtin_##FUNC##f(ARG1, ARG2##F) != RES##F \
      49        || CKSGN_F(__builtin_##FUNC##f(ARG1,ARG2##F),RES##F)) \
      50      link_error(__LINE__); \
      51    if (__builtin_##FUNC(ARG1, ARG2) != RES \
      52        || CKSGN(__builtin_##FUNC(ARG1,ARG2),RES)) \
      53      link_error(__LINE__); \
      54    if (__builtin_##FUNC##l(ARG1, ARG2##L) != RES##L \
      55        || CKSGN_L(__builtin_##FUNC##l(ARG1,ARG2##L),RES##L)) \
      56      link_error(__LINE__); \
      57    } while (0)
      58  
      59  /* Range test, check that (LOW) < FUNC(ARG1,ARG2) < (HI).  */
      60  #define TESTIT2_R(FUNC,ARG1,ARG2,LOW,HI) do { \
      61    if (__builtin_##FUNC##f(ARG1, ARG2##F) <= (LOW) \
      62        || __builtin_##FUNC##f(ARG1, ARG2##F) >= (HI)) \
      63      link_error(__LINE__); \
      64    if (__builtin_##FUNC(ARG1, ARG2) <= (LOW) \
      65        || __builtin_##FUNC(ARG1, ARG2) >= (HI)) \
      66      link_error(__LINE__); \
      67    if (__builtin_##FUNC##l(ARG1, ARG2##L) <= (LOW) \
      68        || __builtin_##FUNC##l(ARG1, ARG2##L) >= (HI)) \
      69      link_error(__LINE__); \
      70    } while (0)
      71  
      72  /* Test that remquo(ARG0, ARG1, &ARG_Q) == RES and ARG_Q == RES_Q.
      73     Also test remainder/drem (ARG0,ARG1) == RES.  */
      74  #define TESTIT2_REMQUO(ARG0,ARG1,ARG_Q,RES,RES_Q) do { \
      75    ARG_Q = 12345; \
      76    if (__builtin_remquof(ARG0##F, ARG1##F, &ARG_Q) != RES##F \
      77        || CKSGN_F(__builtin_remquof(ARG0##F, ARG1##F, &ARG_Q),RES##F) \
      78        || ARG_Q != RES_Q \
      79        || __builtin_remainderf(ARG0##F, ARG1##F) != RES##F \
      80        || CKSGN_F(__builtin_remainderf(ARG0##F, ARG1##F),RES##F) \
      81        || __builtin_dremf(ARG0##F, ARG1##F) != RES##F \
      82        || CKSGN_F(__builtin_dremf(ARG0##F, ARG1##F),RES##F)) \
      83      link_error(__LINE__); \
      84    ARG_Q = 12345; \
      85    if (__builtin_remquo(ARG0, ARG1, &ARG_Q) != RES \
      86        || CKSGN(__builtin_remquo(ARG0, ARG1, &ARG_Q),RES) \
      87        || ARG_Q != RES_Q \
      88        || __builtin_remainder(ARG0, ARG1) != RES \
      89        || CKSGN(__builtin_remainder(ARG0, ARG1),RES) \
      90        || __builtin_drem(ARG0, ARG1) != RES \
      91        || CKSGN(__builtin_drem(ARG0, ARG1),RES)) \
      92      link_error(__LINE__); \
      93    ARG_Q = 12345; \
      94    if (__builtin_remquol(ARG0##L, ARG1##L, &ARG_Q) != RES##L \
      95        || CKSGN_L(__builtin_remquol(ARG0##L, ARG1##L, &ARG_Q),RES##L) \
      96        || ARG_Q != RES_Q \
      97        || __builtin_remainderl(ARG0##L, ARG1##L) != RES##L \
      98        || CKSGN_L(__builtin_remainderl(ARG0##L, ARG1##L),RES##L) \
      99        || __builtin_dreml(ARG0##L, ARG1##L) != RES##L \
     100        || CKSGN_L(__builtin_dreml(ARG0##L, ARG1##L),RES##L)) \
     101      link_error(__LINE__); \
     102    } while (0)
     103  
     104  /* Test that FUNC(ARG,&SG) == (RES) && SG == RES_SG.  */
     105  #define TESTIT_LGAMMA_REENT(FUNC,ARG,RES,RES_SG) do { \
     106    int sg; \
     107    sg = 123; \
     108    if (__builtin_##FUNC##f_r(ARG##F,&sg) != RES##F \
     109        || sg != RES_SG \
     110        || CKSGN_F(__builtin_##FUNC##f_r(ARG##F,&sg),RES##F)) \
     111      link_error(__LINE__); \
     112    sg = 123; \
     113    if (__builtin_##FUNC##_r(ARG,&sg) != RES \
     114        || sg != RES_SG \
     115        || CKSGN(__builtin_##FUNC##_r(ARG,&sg),RES)) \
     116      link_error(__LINE__); \
     117    sg = 123; \
     118    if (__builtin_##FUNC##l_r(ARG##L,&sg) != RES##L \
     119        || sg != RES_SG \
     120        || CKSGN_L(__builtin_##FUNC##l_r(ARG##L,&sg),RES##L)) \
     121      link_error(__LINE__); \
     122    } while (0)
     123  
     124  /* Range test, check that (LOW) < FUNC(ARG,&SG) < (HI), and also test
     125     that SG == RES_SG.  */
     126  #define TESTIT_LGAMMA_REENT_R(FUNC,ARG,LOW,HI,RES_SG) do { \
     127    int sg; \
     128    sg = 123; \
     129    if (__builtin_##FUNC##f_r(ARG,&sg) <= (LOW) || __builtin_##FUNC##f_r(ARG,&sg) >= (HI) \
     130        || sg != RES_SG) \
     131      link_error(__LINE__); \
     132    sg = 123; \
     133    if (__builtin_##FUNC##_r(ARG,&sg) <= (LOW) || __builtin_##FUNC##_r(ARG,&sg) >= (HI) \
     134        || sg != RES_SG) \
     135      link_error(__LINE__); \
     136    sg = 123; \
     137    if (__builtin_##FUNC##l_r(ARG,&sg) <= (LOW) || __builtin_##FUNC##l_r(ARG,&sg) >= (HI) \
     138        || sg != RES_SG) \
     139      link_error(__LINE__); \
     140    } while (0)
     141  
     142  int main (void)
     143  {
     144  #ifdef __OPTIMIZE__
     145    int q;
     146  #endif
     147  
     148    TESTIT (j0, 0.0, 1.0); /* j0(0) == 1 */
     149    TESTIT (j0, -0.0, 1.0); /* j0(-0) == 1 */
     150    TESTIT_R (j0, 1.0, 0.765, 0.766); /* j0(1) == 0.7651... */
     151    TESTIT_R (j0, -1.0, 0.765, 0.766); /* j0(-1) == 0.7651... */
     152  
     153    TESTIT (j1, 0.0, 0.0); /* j1(0) == 0 */
     154    TESTIT (j1, -0.0, -0.0); /* j1(-0) == -0 */
     155    TESTIT_R (j1, 1.0, 0.44, 0.45); /* j1(1) == 0.440... */
     156    TESTIT_R (j1, -1.0, -0.45, -0.44); /* j1(-1) == -0.440... */
     157  
     158    TESTIT2 (jn, 5, 0.0, 0.0); /* jn(5,0) == 0 */
     159    TESTIT2 (jn, 5, -0.0, -0.0); /* jn(5,-0) == -0 */
     160    TESTIT2 (jn, 6, 0.0, 0.0); /* jn(6,0) == 0 */
     161    TESTIT2 (jn, 6, -0.0, 0.0); /* jn(6,-0) == 0 */
     162  
     163    TESTIT2 (jn, -5, 0.0, -0.0); /* jn(-5,0) == -0 */
     164    TESTIT2 (jn, -5, -0.0, 0.0); /* jn(-5,-0) == 0 */
     165    TESTIT2 (jn, -6, 0.0, 0.0); /* jn(-6,0) == 0 */
     166    TESTIT2 (jn, -6, -0.0, 0.0); /* jn(-6,-0) == 0 */
     167  
     168    TESTIT2_R (jn, 2, 1.0, 0.11, 0.12); /* jn(2,1) == 0.114... */
     169    TESTIT2_R (jn, 2, -1.0, 0.11, 0.12); /* jn(2,-1) == 0.114... */
     170    TESTIT2_R (jn, 3, 5.0, 0.36, 0.37); /* jn(3,5) == 0.364... */
     171    TESTIT2_R (jn, 3, -5.0, -0.37, -0.36); /* jn(3,-5) == -0.364... */
     172  
     173    TESTIT2_R (jn, -2, 1.0, 0.11, 0.12); /* jn(-2,1) == 0.114... */
     174    TESTIT2_R (jn, -2, -1.0, 0.11, 0.12); /* jn(-2,-1) == 0.114... */
     175    TESTIT2_R (jn, -3, 5.0, -0.37, -0.36); /* jn(-3,5) == -0.364... */
     176    TESTIT2_R (jn, -3, -5.0, 0.36, 0.37); /* jn(-3,-5) == 0.364... */
     177  
     178    TESTIT2_R (jn, 4, 3.5, 0.20, 0.21); /* jn(4,3.5) == 0.204... */
     179    TESTIT2_R (jn, 4, -3.5, 0.20, 0.21); /* jn(4,-3.5) == 0.204... */
     180    TESTIT2_R (jn, 5, 4.6, 0.20, 0.21); /* jn(5,4.6) == 0.207... */
     181    TESTIT2_R (jn, 5, -4.6, -0.21, -0.20); /* jn(5,-4.6) == -0.207... */
     182  
     183    TESTIT2_R (jn, -4, 3.5, 0.20, 0.21); /* jn(-4,3.5) == 0.204... */
     184    TESTIT2_R (jn, -4, -3.5, 0.20, 0.21); /* jn(-4,-3.5) == 0.204... */
     185    TESTIT2_R (jn, -5, 4.6, -0.21, -0.20); /* jn(-5,4.6) == -0.207... */
     186    TESTIT2_R (jn, -5, -4.6, 0.20, 0.21); /* jn(-5,-4.6) == 0.207... */
     187  
     188    TESTIT_R (y0, 5.0, -0.31, -0.30); /* y0(5) == -0.308... */
     189    TESTIT_R (y0, 0.1, -1.54, -1.53); /* y0(0.1) == -1.534... */
     190  
     191    TESTIT_R (y1, 5.0, 0.14, 0.15); /* y1(5) == 0.147... */
     192    TESTIT_R (y1, 0.1, -6.46, -6.45); /* y1(0.1) == -6.458... */
     193  
     194    TESTIT2_R (yn, -1, 3.0, -0.33, -0.32); /* yn(-1,3) == -0.324... */
     195    TESTIT2_R (yn, -1, 0.25, 2.70, 2.71); /* yn(-1,0.25) == 2.704... */
     196  
     197    TESTIT2_R (yn, 2, 4.0, 0.21, 0.22); /* yn(2,4) == 0.215... */
     198    TESTIT2_R (yn, 2, 0.9, -1.95, -1.94); /* yn(2,0.9) == -1.945... */
     199    TESTIT2_R (yn, -2, 4.0, 0.21, 0.22); /* yn(-2,4) == 0.215... */
     200    TESTIT2_R (yn, -2, 0.9, -1.95, -1.94); /* yn(-2,0.9) == -1.945... */
     201  
     202    TESTIT2_R (yn, 3, 6.0, 0.32, 0.33); /* yn(3,6) == 0.328... */
     203    TESTIT2_R (yn, 3, 0.89, -8.03, -8.02); /* yn(3,0.89) == -8.020... */
     204    TESTIT2_R (yn, -3, 8.0, -0.03, -0.02); /* yn(-3,8) == -0.026... */
     205    TESTIT2_R (yn, -3, 0.99, 5.98, 5.99); /* yn(-3,0.99) == 5.982... */
     206  
     207  #ifdef __OPTIMIZE__
     208    /* These tests rely on propagating the variable q, which happens
     209       only when optimization is turned on.  This macro also tests
     210       remainder/drem.  */
     211    TESTIT2_REMQUO (0.0, 1.0, q, 0.0, 0); /* remquo(0,1,&q)==0, q==0 */
     212    TESTIT2_REMQUO (1.0, 1.0, q, 0.0, 1); /* remquo(1,1,&q)==0, q==1 */
     213    TESTIT2_REMQUO (2.0, 1.0, q, 0.0, 2); /* remquo(2,1,&q)==0, q==2 */
     214    TESTIT2_REMQUO (-0.0, 1.0, q, -0.0, 0); /* remquo(-0,1,&q)==-0, q==0 */
     215    TESTIT2_REMQUO (-1.0, 1.0, q, -0.0, -1); /* remquo(-1,1,&q)==-0, q==-1 */
     216    TESTIT2_REMQUO (-2.0, 1.0, q, -0.0, -2); /* remquo(-2,1,&q)==-0, q==-2 */
     217  
     218    TESTIT2_REMQUO (0.0, -1.0, q, 0.0, 0); /* remquo(0,-1,&q)==0, q==0 */
     219    TESTIT2_REMQUO (1.0, -1.0, q, 0.0, -1); /* remquo(1,-1,&q)==0, q==-1 */
     220    TESTIT2_REMQUO (2.0, -1.0, q, 0.0, -2); /* remquo(2,-1,&q)==0, q==-2 */
     221    TESTIT2_REMQUO (-0.0, -1.0, q, -0.0, 0); /* remquo(-0,-1,&q)==-0, q==0 */
     222    TESTIT2_REMQUO (-1.0, -1.0, q, -0.0, 1); /* remquo(-1,-1,&q)==-0, q==1 */
     223    TESTIT2_REMQUO (-2.0, -1.0, q, -0.0, 2); /* remquo(-2,-1,&q)==-0, q==2 */
     224  
     225    TESTIT2_REMQUO (1.0, 2.0, q, 1.0, 0); /* remquo(1,2,&q)==1, q==0 */
     226    TESTIT2_REMQUO (3.0, 2.0, q, -1.0, 2); /* remquo(3,2,&q)==-1, q==2 */
     227    TESTIT2_REMQUO (5.0, 2.0, q, 1.0, 2); /* remquo(5,2,&q)==1, q==2 */
     228    TESTIT2_REMQUO (-1.0, 2.0, q, -1.0, 0); /* remquo(-1,2,&q)==-1, q==0 */
     229    TESTIT2_REMQUO (-3.0, 2.0, q, 1.0, -2); /* remquo(-3,2,&q)==1, q==-2 */
     230    TESTIT2_REMQUO (-5.0, 2.0, q, -1.0, -2); /* remquo(-5,2,&q)==-1, q==-2 */
     231  
     232    TESTIT2_REMQUO (1.0, -2.0, q, 1.0, 0); /* remquo(1,-2,&q)==1, q==0 */
     233    TESTIT2_REMQUO (3.0, -2.0, q, -1.0, -2); /* remquo(3,-2,&q)==-1, q==-2 */
     234    TESTIT2_REMQUO (5.0, -2.0, q, 1.0, -2); /* remquo(5,-2,&q)==1, q==-2 */
     235    TESTIT2_REMQUO (-1.0, -2.0, q, -1.0, 0); /* remquo(-1,-2,&q)==-1, q==0 */
     236    TESTIT2_REMQUO (-3.0, -2.0, q, 1.0, 2); /* remquo(-3,-2,&q)==1, q==2 */
     237    TESTIT2_REMQUO (-5.0, -2.0, q, -1.0, 2); /* remquo(-5,-2,&q)==-1, q==2 */
     238  
     239    /* Test that the maximum possible value can be generated into the
     240       int quotient, and check for wrap around (modulo) when that value
     241       is exceeded.  We can only check for this when the mantissa has
     242       enough bits to hold an INT_MAX value with complete precision.  */
     243  
     244  #define MAXIT(FUNC,X,R) do { \
     245    q = 12345; \
     246    if (__builtin_##FUNC((X), 1, &q) != 0 || q != (R)) \
     247      link_error (__LINE__); \
     248  } while (0)
     249    
     250    if (sizeof(int)*__CHAR_BIT__ <= __FLT_MANT_DIG__)
     251    {
     252      MAXIT(remquof, __INT_MAX__-1.0F, __INT_MAX__-1);
     253      MAXIT(remquof, __INT_MAX__+0.0F, __INT_MAX__);
     254      MAXIT(remquof, __INT_MAX__+1.0F, 0);
     255      MAXIT(remquof, __INT_MAX__+2.0F, 1);
     256  
     257      MAXIT(remquof, -(__INT_MAX__-1.0F), -(__INT_MAX__-1));
     258      MAXIT(remquof, -(__INT_MAX__+0.0F), -__INT_MAX__);
     259      MAXIT(remquof, -(__INT_MAX__+1.0F), 0);
     260      MAXIT(remquof, -(__INT_MAX__+2.0F), -1);
     261    }
     262  
     263    if (sizeof(int)*__CHAR_BIT__ <= __DBL_MANT_DIG__)
     264    {
     265      MAXIT(remquo, __INT_MAX__-1.0, __INT_MAX__-1);
     266      MAXIT(remquo, __INT_MAX__+0.0, __INT_MAX__);
     267      MAXIT(remquo, __INT_MAX__+1.0, 0);
     268      MAXIT(remquo, __INT_MAX__+2.0, 1);
     269  
     270      MAXIT(remquo, -(__INT_MAX__-1.0), -(__INT_MAX__-1));
     271      MAXIT(remquo, -(__INT_MAX__+0.0), -__INT_MAX__);
     272      MAXIT(remquo, -(__INT_MAX__+1.0), 0);
     273      MAXIT(remquo, -(__INT_MAX__+2.0), -1);
     274    }
     275  
     276    if (sizeof(int)*__CHAR_BIT__ <= __LDBL_MANT_DIG__)
     277    {
     278      MAXIT(remquo, __INT_MAX__-1.0L, __INT_MAX__-1);
     279      MAXIT(remquo, __INT_MAX__+0.0L, __INT_MAX__);
     280      MAXIT(remquo, __INT_MAX__+1.0L, 0);
     281      MAXIT(remquo, __INT_MAX__+2.0L, 1);
     282  
     283      MAXIT(remquol, -(__INT_MAX__-1.0L), -(__INT_MAX__-1));
     284      MAXIT(remquol, -(__INT_MAX__+0.0L), -__INT_MAX__);
     285      MAXIT(remquol, -(__INT_MAX__+1.0L), 0);
     286      MAXIT(remquol, -(__INT_MAX__+2.0L), -1);
     287    }
     288  
     289    /* These tests rely on propagating the variable sg which contains
     290       signgam.  This happens only when optimization is turned on.  */
     291    TESTIT_LGAMMA_REENT_R (lgamma, -2.5, -0.06, -0.05, -1); /* lgamma_r(-2.5) == -0.056... */
     292    TESTIT_LGAMMA_REENT_R (lgamma, -1.5, 0.86, 0.87, 1); /* lgamma_r(-1.5) == 0.860... */
     293    TESTIT_LGAMMA_REENT_R (lgamma, -0.5, 1.26, 1.27, -1); /* lgamma_r(-0.5) == 1.265... */
     294    TESTIT_LGAMMA_REENT_R (lgamma, 0.5, 0.57, 0.58, 1); /* lgamma_r(0.5) == 0.572... */
     295    TESTIT_LGAMMA_REENT (lgamma, 1.0, 0.0, 1); /* lgamma_r(1) == 0 */
     296    TESTIT_LGAMMA_REENT_R (lgamma, 1.5, -0.13, -0.12, 1); /* lgamma_r(1.5) == -0.120... */
     297    TESTIT_LGAMMA_REENT (lgamma, 2.0, 0.0, 1); /* lgamma_r(2) == 0 */
     298    TESTIT_LGAMMA_REENT_R (lgamma, 2.5, 0.28, 0.29, 1); /* lgamma_r(2.5) == 0.284... */
     299  
     300    TESTIT_LGAMMA_REENT_R (gamma, -2.5, -0.06, -0.05, -1); /* gamma_r(-2.5) == -0.056... */
     301    TESTIT_LGAMMA_REENT_R (gamma, -1.5, 0.86, 0.87, 1); /* gamma_r(-1.5) == 0.860... */
     302    TESTIT_LGAMMA_REENT_R (gamma, -0.5, 1.26, 1.27, -1); /* gamma_r(-0.5) == 1.265... */
     303    TESTIT_LGAMMA_REENT_R (gamma, 0.5, 0.57, 0.58, 1); /* gamma_r(0.5) == 0.572... */
     304    TESTIT_LGAMMA_REENT (gamma, 1.0, 0.0, 1); /* gamma_r(1) == 0 */
     305    TESTIT_LGAMMA_REENT_R (gamma, 1.5, -0.13, -0.12, 1); /* gamma_r(1.5) == -0.120... */
     306    TESTIT_LGAMMA_REENT (gamma, 2.0, 0.0, 1); /* gamma_r(2) == 0 */
     307    TESTIT_LGAMMA_REENT_R (gamma, 2.5, 0.28, 0.29, 1); /* gamma_r(2.5) == 0.284... */
     308  #endif
     309    
     310    return 0;
     311  }