-/* 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