]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - math/s_csinhf.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / math / s_csinhf.c
index e4bb7042682a13e58e7748f70d8ac6c234df496e..a0458cfd0a7c99e56460723985fe063964fd38d1 100644 (file)
@@ -1,5 +1,5 @@
 /* Complex sine hyperbole function for float.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #include <complex.h>
 #include <fenv.h>
 #include <math.h>
-
-#include "math_private.h"
-
+#include <math_private.h>
+#include <float.h>
 
 __complex__ float
 __csinhf (__complex__ float x)
@@ -35,23 +33,63 @@ __csinhf (__complex__ float x)
 
   __real__ x = fabsf (__real__ x);
 
-  if (rcls >= FP_ZERO)
+  if (__glibc_likely (rcls >= FP_ZERO))
     {
       /* Real part is finite.  */
-      if (icls >= FP_ZERO)
+      if (__glibc_likely (icls >= FP_ZERO))
        {
          /* Imaginary part is finite.  */
-         float sinh_val = __ieee754_sinhf (__real__ x);
-         float cosh_val = __ieee754_coshf (__real__ x);
+         const int t = (int) ((FLT_MAX_EXP - 1) * M_LN2);
          float sinix, cosix;
 
-         __sincosf (__imag__ x, &sinix, &cosix);
-
-         __real__ retval = sinh_val * cosix;
-         __imag__ retval = cosh_val * sinix;
+         if (__glibc_likely (fabsf (__imag__ x) > FLT_MIN))
+           {
+             __sincosf (__imag__ x, &sinix, &cosix);
+           }
+         else
+           {
+             sinix = __imag__ x;
+             cosix = 1.0f;
+           }
 
          if (negate)
-           __real__ retval = -__real__ retval;
+           cosix = -cosix;
+
+         if (fabsf (__real__ x) > t)
+           {
+             float exp_t = __ieee754_expf (t);
+             float rx = fabsf (__real__ x);
+             if (signbit (__real__ x))
+               cosix = -cosix;
+             rx -= t;
+             sinix *= exp_t / 2.0f;
+             cosix *= exp_t / 2.0f;
+             if (rx > t)
+               {
+                 rx -= t;
+                 sinix *= exp_t;
+                 cosix *= exp_t;
+               }
+             if (rx > t)
+               {
+                 /* Overflow (original real part of x > 3t).  */
+                 __real__ retval = FLT_MAX * cosix;
+                 __imag__ retval = FLT_MAX * sinix;
+               }
+             else
+               {
+                 float exp_val = __ieee754_expf (rx);
+                 __real__ retval = exp_val * cosix;
+                 __imag__ retval = exp_val * sinix;
+               }
+           }
+         else
+           {
+             __real__ retval = __ieee754_sinhf (__real__ x) * cosix;
+             __imag__ retval = __ieee754_coshf (__real__ x) * sinix;
+           }
+
+         math_check_force_underflow_complex (retval);
        }
       else
        {
@@ -61,37 +99,35 @@ __csinhf (__complex__ float x)
              __real__ retval = __copysignf (0.0, negate ? -1.0 : 1.0);
              __imag__ retval = __nanf ("") + __nanf ("");
 
-#ifdef FE_INVALID
              if (icls == FP_INFINITE)
                feraiseexcept (FE_INVALID);
-#endif
            }
          else
            {
              __real__ retval = __nanf ("");
              __imag__ retval = __nanf ("");
 
-#ifdef FE_INVALID
              feraiseexcept (FE_INVALID);
-#endif
            }
        }
     }
-  else if (rcls == FP_INFINITE)
+  else if (__glibc_likely (rcls == FP_INFINITE))
     {
       /* Real part is infinite.  */
-      if (icls == FP_ZERO)
-       {
-         /* Imaginary part is 0.0.  */
-         __real__ retval = negate ? -HUGE_VALF : HUGE_VALF;
-         __imag__ retval = __imag__ x;
-       }
-      else if (icls > FP_ZERO)
+      if (__glibc_likely (icls > FP_ZERO))
        {
          /* Imaginary part is finite.  */
          float sinix, cosix;
 
-         __sincosf (__imag__ x, &sinix, &cosix);
+         if (__glibc_likely (fabsf (__imag__ x) > FLT_MIN))
+           {
+             __sincosf (__imag__ x, &sinix, &cosix);
+           }
+         else
+           {
+             sinix = __imag__ x;
+             cosix = 1.0f;
+           }
 
          __real__ retval = __copysignf (HUGE_VALF, cosix);
          __imag__ retval = __copysignf (HUGE_VALF, sinix);
@@ -99,6 +135,12 @@ __csinhf (__complex__ float x)
          if (negate)
            __real__ retval = -__real__ retval;
        }
+      else if (icls == FP_ZERO)
+       {
+         /* Imaginary part is 0.0.  */
+         __real__ retval = negate ? -HUGE_VALF : HUGE_VALF;
+         __imag__ retval = __imag__ x;
+       }
       else
        {
          /* The addition raises the invalid exception.  */