s_sinf.c revision 152647
1261287Sdes/* s_sinf.c -- float version of s_sin.c.
2261287Sdes * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3261287Sdes */
4261287Sdes
5261287Sdes/*
6261287Sdes * ====================================================
7261287Sdes * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8261287Sdes *
9261287Sdes * Developed at SunPro, a Sun Microsystems, Inc. business.
10261287Sdes * Permission to use, copy, modify, and distribute this
11261287Sdes * software is freely granted, provided that this notice
12261287Sdes * is preserved.
13261287Sdes * ====================================================
14261287Sdes */
15261287Sdes
16261287Sdes#ifndef lint
17261287Sdesstatic char rcsid[] = "$FreeBSD: head/lib/msun/src/s_sinf.c 152647 2005-11-21 04:57:12Z bde $";
18261287Sdes#endif
19261287Sdes
20261287Sdes#include "math.h"
21261287Sdes#define	INLINE_KERNEL_COSF
22261287Sdes#define	INLINE_KERNEL_SINF
23261287Sdes#include "math_private.h"
24261287Sdes#include "k_cosf.c"
25261287Sdes#include "k_sinf.c"
26261287Sdes
27261287Sdes/* Small multiples of pi/2 rounded to double precision. */
28261287Sdesstatic const double
29261287Sdess1pio2 = 1*M_PI_2,			/* 0x3FF921FB, 0x54442D18 */
30261287Sdess2pio2 = 2*M_PI_2,			/* 0x400921FB, 0x54442D18 */
31261287Sdess3pio2 = 3*M_PI_2,			/* 0x4012D97C, 0x7F3321D2 */
32261287Sdess4pio2 = 4*M_PI_2;			/* 0x401921FB, 0x54442D18 */
33261287Sdes
34261287Sdesstatic inline float
35261287Sdes__kernel_cosdf(double x)
36261287Sdes{
37261287Sdes	return __kernel_cosf((float)x, x - (float)x);
38261287Sdes}
39261287Sdes
40261287Sdesstatic inline float
41261287Sdes__kernel_sindf(double x)
42261287Sdes{
43261287Sdes	return __kernel_sinf((float)x, x - (float)x, 1);
44261287Sdes}
45261287Sdes
46261287Sdesfloat
47261287Sdessinf(float x)
48261287Sdes{
49261287Sdes	float y[2];
50261287Sdes	int32_t n, hx, ix;
51261287Sdes
52261287Sdes	GET_FLOAT_WORD(hx,x);
53261287Sdes	ix = hx & 0x7fffffff;
54261287Sdes
55261287Sdes	if(ix <= 0x3f490fda) {		/* |x| ~<= pi/4 */
56261287Sdes	    if(ix<0x39800000)		/* |x| < 2**-12 */
57261287Sdes		if(((int)x)==0) return x;	/* x with inexact if x != 0 */
58261287Sdes	    return __kernel_sinf(x,0.0,0);
59261287Sdes	}
60261287Sdes	if(ix<=0x407b53d1) {		/* |x| <= ~5*pi/4 */
61261287Sdes	    if(ix<=0x4016cbe3) {	/* |x| <= ~3pi/4 */
62261287Sdes		if(hx>0)
63261287Sdes		    return __kernel_cosdf(x - s1pio2);
64261287Sdes		else
65261287Sdes		    return -__kernel_cosdf(x + s1pio2);
66261287Sdes	    } else
67261287Sdes		return -__kernel_sindf(x + (hx > 0 ? -s2pio2 : s2pio2));
68261287Sdes	}
69261287Sdes	if(ix<=0x40e231d5) {		/* |x| <= ~9*pi/4 */
70261287Sdes	    if(ix<=0x40afeddf) {	/* |x| <= ~7*pi/4 */
71261287Sdes		if(hx>0)
72261287Sdes		    return -__kernel_cosdf(x - s3pio2);
73261287Sdes		else
74261287Sdes		    return __kernel_cosdf(x + s3pio2);
75261287Sdes	    } else
76261287Sdes		return __kernel_sindf(x + (hx > 0 ? -s4pio2 : s4pio2));
77261287Sdes	}
78261287Sdes
79261287Sdes    /* sin(Inf or NaN) is NaN */
80261287Sdes	else if (ix>=0x7f800000) return x-x;
81261287Sdes
82261287Sdes    /* general argument reduction needed */
83261287Sdes	else {
84261287Sdes	    n = __ieee754_rem_pio2f(x,y);
85261287Sdes	    switch(n&3) {
86261287Sdes		case 0: return  __kernel_sinf(y[0],y[1],1);
87261287Sdes		case 1: return  __kernel_cosf(y[0],y[1]);
88261287Sdes		case 2: return -__kernel_sinf(y[0],y[1],1);
89261287Sdes		default:
90261287Sdes			return -__kernel_cosf(y[0],y[1]);
91261287Sdes	    }
92261287Sdes	}
93261287Sdes}
94261287Sdes