(root)/
glibc-2.38/
math/
s_cexp_template.c
       1  /* Return value of complex exponential function for a float type.
       2     Copyright (C) 1997-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <complex.h>
      20  #include <fenv.h>
      21  #include <math.h>
      22  #include <math_private.h>
      23  #include <math-underflow.h>
      24  #include <float.h>
      25  
      26  CFLOAT
      27  M_DECL_FUNC (__cexp) (CFLOAT x)
      28  {
      29    CFLOAT retval;
      30    int rcls = fpclassify (__real__ x);
      31    int icls = fpclassify (__imag__ x);
      32  
      33    if (__glibc_likely (rcls >= FP_ZERO))
      34      {
      35        /* Real part is finite.  */
      36        if (__glibc_likely (icls >= FP_ZERO))
      37  	{
      38  	  /* Imaginary part is finite.  */
      39  	  const int t = (int) ((M_MAX_EXP - 1) * M_MLIT (M_LN2));
      40  	  FLOAT sinix, cosix;
      41  
      42  	  if (__glibc_likely (M_FABS (__imag__ x) > M_MIN))
      43  	    {
      44  	      M_SINCOS (__imag__ x, &sinix, &cosix);
      45  	    }
      46  	  else
      47  	    {
      48  	      sinix = __imag__ x;
      49  	      cosix = 1;
      50  	    }
      51  
      52  	  if (__real__ x > t)
      53  	    {
      54  	      FLOAT exp_t = M_EXP (t);
      55  	      __real__ x -= t;
      56  	      sinix *= exp_t;
      57  	      cosix *= exp_t;
      58  	      if (__real__ x > t)
      59  		{
      60  		  __real__ x -= t;
      61  		  sinix *= exp_t;
      62  		  cosix *= exp_t;
      63  		}
      64  	    }
      65  	  if (__real__ x > t)
      66  	    {
      67  	      /* Overflow (original real part of x > 3t).  */
      68  	      __real__ retval = M_MAX * cosix;
      69  	      __imag__ retval = M_MAX * sinix;
      70  	    }
      71  	  else
      72  	    {
      73  	      FLOAT exp_val = M_EXP (__real__ x);
      74  	      __real__ retval = exp_val * cosix;
      75  	      __imag__ retval = exp_val * sinix;
      76  	    }
      77  	  math_check_force_underflow_complex (retval);
      78  	}
      79        else
      80  	{
      81  	  /* If the imaginary part is +-inf or NaN and the real part
      82  	     is not +-inf the result is NaN + iNaN.  */
      83  	  __real__ retval = M_NAN;
      84  	  __imag__ retval = M_NAN;
      85  
      86  	  feraiseexcept (FE_INVALID);
      87  	}
      88      }
      89    else if (__glibc_likely (rcls == FP_INFINITE))
      90      {
      91        /* Real part is infinite.  */
      92        if (__glibc_likely (icls >= FP_ZERO))
      93  	{
      94  	  /* Imaginary part is finite.  */
      95  	  FLOAT value = signbit (__real__ x) ? 0 : M_HUGE_VAL;
      96  
      97  	  if (icls == FP_ZERO)
      98  	    {
      99  	      /* Imaginary part is 0.0.  */
     100  	      __real__ retval = value;
     101  	      __imag__ retval = __imag__ x;
     102  	    }
     103  	  else
     104  	    {
     105  	      FLOAT sinix, cosix;
     106  
     107  	      if (__glibc_likely (M_FABS (__imag__ x) > M_MIN))
     108  		{
     109  		  M_SINCOS (__imag__ x, &sinix, &cosix);
     110  		}
     111  	      else
     112  		{
     113  		  sinix = __imag__ x;
     114  		  cosix = 1;
     115  		}
     116  
     117  	      __real__ retval = M_COPYSIGN (value, cosix);
     118  	      __imag__ retval = M_COPYSIGN (value, sinix);
     119  	    }
     120  	}
     121        else if (signbit (__real__ x) == 0)
     122  	{
     123  	  __real__ retval = M_HUGE_VAL;
     124  	  __imag__ retval = __imag__ x - __imag__ x;
     125  	}
     126        else
     127  	{
     128  	  __real__ retval = 0;
     129  	  __imag__ retval = M_COPYSIGN (0, __imag__ x);
     130  	}
     131      }
     132    else
     133      {
     134        /* If the real part is NaN the result is NaN + iNaN unless the
     135  	 imaginary part is zero.  */
     136        __real__ retval = M_NAN;
     137        if (icls == FP_ZERO)
     138  	__imag__ retval = __imag__ x;
     139        else
     140  	{
     141  	  __imag__ retval = M_NAN;
     142  
     143  	  if (rcls != FP_NAN || icls != FP_NAN)
     144  	    feraiseexcept (FE_INVALID);
     145  	}
     146      }
     147  
     148    return retval;
     149  }
     150  declare_mgen_alias (__cexp, cexp)