]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/ieee754/flt-32/s_cosf.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / ieee754 / flt-32 / s_cosf.c
index dfe576c7be452d877489106432633213a45e0984..63426070cca38302d7bce8e0c83b12c1fa110ad9 100644 (file)
@@ -1,56 +1,87 @@
-/* s_cosf.c -- float version of s_cos.c.
- * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
- */
-
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: s_cosf.c,v 1.4 1995/05/10 20:47:03 jtc Exp $";
-#endif
+/* Compute cosine of argument.
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
 
-#include <errno.h>
-#include "math.h"
-#include "math_private.h"
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
-static const float one=1.0;
+#include <stdint.h>
+#include <math.h>
+#include <math-barriers.h>
+#include <libm-alias-float.h>
+#include "math_config.h"
+#include "s_sincosf.h"
+
+#ifndef COSF
+# define COSF_FUNC __cosf
+#else
+# define COSF_FUNC COSF
+#endif
 
-float __cosf(float x)
+/* Fast cosf implementation.  Worst-case ULP is 0.5607, maximum relative
+   error is 0.5303 * 2^-23.  A single-step range reduction is used for
+   small values.  Large inputs have their range reduced using fast integer
+   arithmetic.
+*/
+float
+COSF_FUNC (float y)
 {
-       float y[2],z=0.0;
-       int32_t n,ix;
-
-       GET_FLOAT_WORD(ix,x);
-
-    /* |x| ~< pi/4 */
-       ix &= 0x7fffffff;
-       if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
-
-    /* cos(Inf or NaN) is NaN */
-       else if (ix>=0x7f800000) {
-         if (ix == 0x7f800000)
-           __set_errno (EDOM);
-         return x-x;
-       }
-
-    /* argument reduction needed */
-       else {
-           n = __ieee754_rem_pio2f(x,y);
-           switch(n&3) {
-               case 0: return  __kernel_cosf(y[0],y[1]);
-               case 1: return -__kernel_sinf(y[0],y[1],1);
-               case 2: return -__kernel_cosf(y[0],y[1]);
-               default:
-                       return  __kernel_sinf(y[0],y[1],1);
-           }
-       }
+  double x = y;
+  double s;
+  int n;
+  const sincos_t *p = &__sincosf_table[0];
+
+  if (abstop12 (y) < abstop12 (pio4))
+    {
+      double x2 = x * x;
+
+      if (__glibc_unlikely (abstop12 (y) < abstop12 (0x1p-12f)))
+       return 1.0f;
+
+      return sinf_poly (x, x2, p, 1);
+    }
+  else if (__glibc_likely (abstop12 (y) < abstop12 (120.0f)))
+    {
+      x = reduce_fast (x, p, &n);
+
+      /* Setup the signs for sin and cos.  */
+      s = p->sign[n & 3];
+
+      if (n & 2)
+       p = &__sincosf_table[1];
+
+      return sinf_poly (x * s, x * x, p, n ^ 1);
+    }
+  else if (abstop12 (y) < abstop12 (INFINITY))
+    {
+      uint32_t xi = asuint (y);
+      int sign = xi >> 31;
+
+      x = reduce_large (xi, &n);
+
+      /* Setup signs for sin and cos - include original sign.  */
+      s = p->sign[(n + sign) & 3];
+
+      if ((n + sign) & 2)
+       p = &__sincosf_table[1];
+
+      return sinf_poly (x * s, x * x, p, n ^ 1);
+    }
+  else
+    return __math_invalidf (y);
 }
-weak_alias (__cosf, cosf)
+
+#ifndef COSF
+libm_alias_float (__cos, cos)
+#endif