sincosf.c 2.5 KB
Newer Older
N
nsz 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/* origin: FreeBSD /usr/src/lib/msun/src/s_sinf.c */
/*
 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
 * Optimized by Bruce D. Evans.
 */
/*
 * ====================================================
 * 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.
 * ====================================================
 */

#include "libm.h"

/* Small multiples of pi/2 rounded to double precision. */
static const double
s1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */
s2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */
s3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */
s4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */

void sincosf(float x, float *sin, float *cos)
{
S
Szabolcs Nagy 已提交
28 29 30 31
	double y;
	float_t s, c;
	uint32_t ix;
	unsigned n, sign;
N
nsz 已提交
32

S
Szabolcs Nagy 已提交
33 34 35
	GET_FLOAT_WORD(ix, x);
	sign = ix >> 31;
	ix &= 0x7fffffff;
N
nsz 已提交
36 37 38 39 40

	/* |x| ~<= pi/4 */
	if (ix <= 0x3f490fda) {
		/* |x| < 2**-12 */
		if (ix < 0x39800000) {
S
Szabolcs Nagy 已提交
41 42 43 44
			/* raise inexact if x!=0 and underflow if subnormal */
			FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
			*sin = x;
			*cos = 1.0f;
N
nsz 已提交
45 46 47 48 49 50 51 52
			return;
		}
		*sin = __sindf(x);
		*cos = __cosdf(x);
		return;
	}

	/* |x| ~<= 5*pi/4 */
53
	if (ix <= 0x407b53d1) {
N
nsz 已提交
54
		if (ix <= 0x4016cbe3) {  /* |x| ~<= 3pi/4 */
S
Szabolcs Nagy 已提交
55
			if (sign) {
N
nsz 已提交
56 57
				*sin = -__cosdf(x + s1pio2);
				*cos = __sindf(x + s1pio2);
S
Szabolcs Nagy 已提交
58 59 60
			} else {
				*sin = __cosdf(s1pio2 - x);
				*cos = __sindf(s1pio2 - x);
N
nsz 已提交
61 62 63
			}
			return;
		}
S
Szabolcs Nagy 已提交
64 65 66
		/* -sin(x+c) is not correct if x+c could be 0: -0 vs +0 */
		*sin = -__sindf(sign ? x + s2pio2 : x - s2pio2);
		*cos = -__cosdf(sign ? x + s2pio2 : x - s2pio2);
N
nsz 已提交
67 68 69 70 71 72
		return;
	}

	/* |x| ~<= 9*pi/4 */
	if (ix <= 0x40e231d5) {
		if (ix <= 0x40afeddf) {  /* |x| ~<= 7*pi/4 */
S
Szabolcs Nagy 已提交
73 74 75 76
			if (sign) {
				*sin = __cosdf(x + s3pio2);
				*cos = -__sindf(x + s3pio2);
			} else {
N
nsz 已提交
77 78 79 80 81
				*sin = -__cosdf(x - s3pio2);
				*cos = __sindf(x - s3pio2);
			}
			return;
		}
S
Szabolcs Nagy 已提交
82 83
		*sin = __sindf(sign ? x + s4pio2 : x - s4pio2);
		*cos = __cosdf(sign ? x + s4pio2 : x - s4pio2);
N
nsz 已提交
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
		return;
	}

	/* sin(Inf or NaN) is NaN */
	if (ix >= 0x7f800000) {
		*sin = *cos = x - x;
		return;
	}

	/* general argument reduction needed */
	n = __rem_pio2f(x, &y);
	s = __sindf(y);
	c = __cosdf(y);
	switch (n&3) {
	case 0:
		*sin = s;
		*cos = c;
		break;
	case 1:
		*sin = c;
		*cos = -s;
		break;
	case 2:
		*sin = -s;
		*cos = -c;
		break;
	case 3:
	default:
		*sin = -c;
		*cos = s;
		break;
	}
}