125c28e8Piotr Jasiukajtis/*
225c28e8Piotr Jasiukajtis * CDDL HEADER START
325c28e8Piotr Jasiukajtis *
425c28e8Piotr Jasiukajtis * The contents of this file are subject to the terms of the
525c28e8Piotr Jasiukajtis * Common Development and Distribution License (the "License").
625c28e8Piotr Jasiukajtis * You may not use this file except in compliance with the License.
725c28e8Piotr Jasiukajtis *
825c28e8Piotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925c28e8Piotr Jasiukajtis * or http://www.opensolaris.org/os/licensing.
1025c28e8Piotr Jasiukajtis * See the License for the specific language governing permissions
1125c28e8Piotr Jasiukajtis * and limitations under the License.
1225c28e8Piotr Jasiukajtis *
1325c28e8Piotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each
1425c28e8Piotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525c28e8Piotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the
1625c28e8Piotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying
1725c28e8Piotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner]
1825c28e8Piotr Jasiukajtis *
1925c28e8Piotr Jasiukajtis * CDDL HEADER END
2025c28e8Piotr Jasiukajtis */
2125c28e8Piotr Jasiukajtis/*
2225c28e8Piotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
2325c28e8Piotr Jasiukajtis */
2425c28e8Piotr Jasiukajtis/*
2525c28e8Piotr Jasiukajtis * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
2625c28e8Piotr Jasiukajtis * Use is subject to license terms.
2725c28e8Piotr Jasiukajtis */
2825c28e8Piotr Jasiukajtis
2925c28e8Piotr Jasiukajtis/*
3025c28e8Piotr Jasiukajtis * __vsincosf: single precision vector sincos
3125c28e8Piotr Jasiukajtis *
3225c28e8Piotr Jasiukajtis * Algorithm:
3325c28e8Piotr Jasiukajtis *
3425c28e8Piotr Jasiukajtis * For |x| < pi/4, approximate sin(x) by a polynomial x+x*z*(S0+
3525c28e8Piotr Jasiukajtis * z*(S1+z*S2)) and cos(x) by a polynomial 1+z*(-1/2+z*(C0+z*(C1+
3625c28e8Piotr Jasiukajtis * z*C2))), where z = x*x, all evaluated in double precision.
3725c28e8Piotr Jasiukajtis *
3825c28e8Piotr Jasiukajtis * Accuracy:
3925c28e8Piotr Jasiukajtis *
4025c28e8Piotr Jasiukajtis * The largest error is less than 0.6 ulps.
4125c28e8Piotr Jasiukajtis */
4225c28e8Piotr Jasiukajtis
4325c28e8Piotr Jasiukajtis#include <sys/isa_defs.h>
4425c28e8Piotr Jasiukajtis
4525c28e8Piotr Jasiukajtis#ifdef _LITTLE_ENDIAN
4625c28e8Piotr Jasiukajtis#define	HI(x)	*(1+(int *)&x)
4725c28e8Piotr Jasiukajtis#define	LO(x)	*(unsigned *)&x
4825c28e8Piotr Jasiukajtis#else
4925c28e8Piotr Jasiukajtis#define	HI(x)	*(int *)&x
5025c28e8Piotr Jasiukajtis#define	LO(x)	*(1+(unsigned *)&x)
5125c28e8Piotr Jasiukajtis#endif
5225c28e8Piotr Jasiukajtis
5325c28e8Piotr Jasiukajtis#ifdef __RESTRICT
5425c28e8Piotr Jasiukajtis#define	restrict _Restrict
5525c28e8Piotr Jasiukajtis#else
5625c28e8Piotr Jasiukajtis#define	restrict
5725c28e8Piotr Jasiukajtis#endif
5825c28e8Piotr Jasiukajtis
5925c28e8Piotr Jasiukajtisextern int __vlibm_rem_pio2m(double *, double *, int, int, int);
6025c28e8Piotr Jasiukajtis
6125c28e8Piotr Jasiukajtisstatic const double C[] = {
6225c28e8Piotr Jasiukajtis	-1.66666552424430847168e-01,	/* 2^ -3 * -1.5555460000000 */
6325c28e8Piotr Jasiukajtis	8.33219196647405624390e-03,	/* 2^ -7 *  1.11077E0000000 */
6425c28e8Piotr Jasiukajtis	-1.95187909412197768688e-04,	/* 2^-13 * -1.9956B60000000 */
6525c28e8Piotr Jasiukajtis	1.0,
6625c28e8Piotr Jasiukajtis	-0.5,
6725c28e8Piotr Jasiukajtis	4.16666455566883087158e-02,	/* 2^ -5 *  1.55554A0000000 */
6825c28e8Piotr Jasiukajtis	-1.38873036485165357590e-03,	/* 2^-10 * -1.6C0C1E0000000 */
6925c28e8Piotr Jasiukajtis	2.44309903791872784495e-05,	/* 2^-16 *  1.99E24E0000000 */
7025c28e8Piotr Jasiukajtis	0.636619772367581343075535,	/* 2^ -1  * 1.45F306DC9C883 */
7125c28e8Piotr Jasiukajtis	6755399441055744.0,		/* 2^ 52  * 1.8000000000000 */
7225c28e8Piotr Jasiukajtis	1.570796326734125614166,	/* 2^  0  * 1.921FB54400000 */
7325c28e8Piotr Jasiukajtis	6.077100506506192601475e-11,	/* 2^-34  * 1.0B4611A626331 */
7425c28e8Piotr Jasiukajtis};
7525c28e8Piotr Jasiukajtis
7625c28e8Piotr Jasiukajtis#define	S0	C[0]
7725c28e8Piotr Jasiukajtis#define	S1	C[1]
7825c28e8Piotr Jasiukajtis#define	S2	C[2]
7925c28e8Piotr Jasiukajtis#define	one	C[3]
8025c28e8Piotr Jasiukajtis#define	mhalf	C[4]
8125c28e8Piotr Jasiukajtis#define	C0	C[5]
8225c28e8Piotr Jasiukajtis#define	C1	C[6]
8325c28e8Piotr Jasiukajtis#define	C2	C[7]
8425c28e8Piotr Jasiukajtis#define	invpio2	C[8]
8525c28e8Piotr Jasiukajtis#define	c3two51	C[9]
8625c28e8Piotr Jasiukajtis#define	pio2_1  C[10]
8725c28e8Piotr Jasiukajtis#define	pio2_t	C[11]
8825c28e8Piotr Jasiukajtis
8925c28e8Piotr Jasiukajtis#define	PREPROCESS(N, sindex, cindex, label)				\
9025c28e8Piotr Jasiukajtis	hx = *(int *)x;							\
9125c28e8Piotr Jasiukajtis	ix = hx & 0x7fffffff;						\
9225c28e8Piotr Jasiukajtis	t = *x;								\
9325c28e8Piotr Jasiukajtis	x += stridex;							\
9425c28e8Piotr Jasiukajtis	if (ix <= 0x3f490fdb) { /* |x| < pi/4 */			\
9525c28e8Piotr Jasiukajtis		if (ix == 0) {						\
9625c28e8Piotr Jasiukajtis			s[sindex] = t;					\
9725c28e8Piotr Jasiukajtis			c[cindex] = one;				\
9825c28e8Piotr Jasiukajtis			goto label;					\
9925c28e8Piotr Jasiukajtis		}							\
10025c28e8Piotr Jasiukajtis		y##N = (double)t;					\
10125c28e8Piotr Jasiukajtis		n##N = 0;						\
10225c28e8Piotr Jasiukajtis	} else if (ix <= 0x49c90fdb) { /* |x| < 2^19*pi */		\
10325c28e8Piotr Jasiukajtis		y##N = (double)t;					\
10425c28e8Piotr Jasiukajtis		medium = 1;						\
10525c28e8Piotr Jasiukajtis	} else {							\
10625c28e8Piotr Jasiukajtis		if (ix >= 0x7f800000) { /* inf or nan */		\
10725c28e8Piotr Jasiukajtis			s[sindex] = c[cindex] = t / t;			\
10825c28e8Piotr Jasiukajtis			goto label;					\
10925c28e8Piotr Jasiukajtis		}							\
11025c28e8Piotr Jasiukajtis		z##N = y##N = (double)t;				\
11125c28e8Piotr Jasiukajtis		hx = HI(y##N);						\
11225c28e8Piotr Jasiukajtis		n##N = ((hx >> 20) & 0x7ff) - 1046;			\
11325c28e8Piotr Jasiukajtis		HI(z##N) = (hx & 0xfffff) | 0x41600000;			\
11425c28e8Piotr Jasiukajtis		n##N = __vlibm_rem_pio2m(&z##N, &y##N, n##N, 1, 0);	\
11525c28e8Piotr Jasiukajtis		if (hx < 0) {						\
11625c28e8Piotr Jasiukajtis			y##N = -y##N;					\
11725c28e8Piotr Jasiukajtis			n##N = -n##N;					\
11825c28e8Piotr Jasiukajtis		}							\
11925c28e8Piotr Jasiukajtis		z##N = y##N * y##N;					\
12025c28e8Piotr Jasiukajtis		f##N = (float)(y##N + y##N * z##N * (S0 + z##N *	\
12125c28e8Piotr Jasiukajtis		    (S1 + z##N * S2)));					\
12225c28e8Piotr Jasiukajtis		g##N = (float)(one + z##N * (mhalf + z##N * (C0 +	\
12325c28e8Piotr Jasiukajtis		    z##N * (C1 + z##N * C2))));				\
12425c28e8Piotr Jasiukajtis		if (n##N & 2) {						\
12525c28e8Piotr Jasiukajtis			f##N = -f##N;					\
12625c28e8Piotr Jasiukajtis			g##N = -g##N;					\
12725c28e8Piotr Jasiukajtis		}							\
12825c28e8Piotr Jasiukajtis		if (n##N & 1) {						\
12925c28e8Piotr Jasiukajtis			s[sindex] = g##N;				\
13025c28e8Piotr Jasiukajtis			c[cindex] = -f##N;				\
13125c28e8Piotr Jasiukajtis		} else {						\
13225c28e8Piotr Jasiukajtis			s[sindex] = f##N;				\
13325c28e8Piotr Jasiukajtis			c[cindex] = g##N;				\
13425c28e8Piotr Jasiukajtis		}							\
13525c28e8Piotr Jasiukajtis		goto label;						\
13625c28e8Piotr Jasiukajtis	}
13725c28e8Piotr Jasiukajtis
13825c28e8Piotr Jasiukajtis#define	PROCESS(N)							\
13925c28e8Piotr Jasiukajtis	if (medium) {							\
14025c28e8Piotr Jasiukajtis		z##N = y##N * invpio2 + c3two51;			\
14125c28e8Piotr Jasiukajtis		n##N = LO(z##N);					\
14225c28e8Piotr Jasiukajtis		z##N -= c3two51;					\
14325c28e8Piotr Jasiukajtis		y##N = (y##N - z##N * pio2_1) - z##N * pio2_t;		\
14425c28e8Piotr Jasiukajtis	}								\
14525c28e8Piotr Jasiukajtis	z##N = y##N * y##N;						\
14625c28e8Piotr Jasiukajtis	f##N = (float)(y##N + y##N * z##N * (S0 + z##N * (S1 + z##N * S2)));\
14725c28e8Piotr Jasiukajtis	g##N = (float)(one + z##N * (mhalf + z##N * (C0 + z##N *	\
14825c28e8Piotr Jasiukajtis	    (C1 + z##N * C2))));					\
14925c28e8Piotr Jasiukajtis	if (n##N & 2) {							\
15025c28e8Piotr Jasiukajtis		f##N = -f##N;						\
15125c28e8Piotr Jasiukajtis		g##N = -g##N;						\
15225c28e8Piotr Jasiukajtis	}								\
15325c28e8Piotr Jasiukajtis	if (n##N & 1) {							\
15425c28e8Piotr Jasiukajtis		*s = g##N;						\
15525c28e8Piotr Jasiukajtis		*c = -f##N;						\
15625c28e8Piotr Jasiukajtis	} else {							\
15725c28e8Piotr Jasiukajtis		*s = f##N;						\
15825c28e8Piotr Jasiukajtis		*c = g##N;						\
15925c28e8Piotr Jasiukajtis	}								\
16025c28e8Piotr Jasiukajtis	s += strides;							\
16125c28e8Piotr Jasiukajtis	c += stridec
16225c28e8Piotr Jasiukajtis
16325c28e8Piotr Jasiukajtisvoid
16425c28e8Piotr Jasiukajtis__vsincosf(int n, float *restrict x, int stridex,
16525c28e8Piotr Jasiukajtis    float *restrict s, int strides, float *restrict c, int stridec)
16625c28e8Piotr Jasiukajtis{
16725c28e8Piotr Jasiukajtis	double		y0, y1, y2, y3;
16825c28e8Piotr Jasiukajtis	double		z0, z1, z2, z3;
16925c28e8Piotr Jasiukajtis	float		f0, f1, f2, f3, t;
17025c28e8Piotr Jasiukajtis	float		g0, g1, g2, g3;
17125c28e8Piotr Jasiukajtis	int		n0 = 0, n1 = 0, n2 = 0, n3, hx, ix, medium;
17225c28e8Piotr Jasiukajtis
17325c28e8Piotr Jasiukajtis	s -= strides;
17425c28e8Piotr Jasiukajtis	c -= stridec;
17525c28e8Piotr Jasiukajtis
17625c28e8Piotr Jasiukajtis	for (;;) {
17725c28e8Piotr Jasiukajtisbegin:
17825c28e8Piotr Jasiukajtis		s += strides;
17925c28e8Piotr Jasiukajtis		c += stridec;
18025c28e8Piotr Jasiukajtis
18125c28e8Piotr Jasiukajtis		if (--n < 0)
18225c28e8Piotr Jasiukajtis			break;
18325c28e8Piotr Jasiukajtis
18425c28e8Piotr Jasiukajtis		medium = 0;
18525c28e8Piotr Jasiukajtis		PREPROCESS(0, 0, 0, begin);
18625c28e8Piotr Jasiukajtis
18725c28e8Piotr Jasiukajtis		if (--n < 0)
18825c28e8Piotr Jasiukajtis			goto process1;
18925c28e8Piotr Jasiukajtis
19025c28e8Piotr Jasiukajtis		PREPROCESS(1, strides, stridec, process1);
19125c28e8Piotr Jasiukajtis
19225c28e8Piotr Jasiukajtis		if (--n < 0)
19325c28e8Piotr Jasiukajtis			goto process2;
19425c28e8Piotr Jasiukajtis
19525c28e8Piotr Jasiukajtis		PREPROCESS(2, (strides << 1), (stridec << 1), process2);
19625c28e8Piotr Jasiukajtis
19725c28e8Piotr Jasiukajtis		if (--n < 0)
19825c28e8Piotr Jasiukajtis			goto process3;
19925c28e8Piotr Jasiukajtis
20025c28e8Piotr Jasiukajtis		PREPROCESS(3, (strides << 1) + strides,
20125c28e8Piotr Jasiukajtis		    (stridec << 1) + stridec, process3);
20225c28e8Piotr Jasiukajtis
20325c28e8Piotr Jasiukajtis		if (medium) {
20425c28e8Piotr Jasiukajtis			z0 = y0 * invpio2 + c3two51;
20525c28e8Piotr Jasiukajtis			z1 = y1 * invpio2 + c3two51;
20625c28e8Piotr Jasiukajtis			z2 = y2 * invpio2 + c3two51;
20725c28e8Piotr Jasiukajtis			z3 = y3 * invpio2 + c3two51;
20825c28e8Piotr Jasiukajtis
20925c28e8Piotr Jasiukajtis			n0 = LO(z0);
21025c28e8Piotr Jasiukajtis			n1 = LO(z1);
21125c28e8Piotr Jasiukajtis			n2 = LO(z2);
21225c28e8Piotr Jasiukajtis			n3 = LO(z3);
21325c28e8Piotr Jasiukajtis
21425c28e8Piotr Jasiukajtis			z0 -= c3two51;
21525c28e8Piotr Jasiukajtis			z1 -= c3two51;
21625c28e8Piotr Jasiukajtis			z2 -= c3two51;
21725c28e8Piotr Jasiukajtis			z3 -= c3two51;
21825c28e8Piotr Jasiukajtis
21925c28e8Piotr Jasiukajtis			y0 = (y0 - z0 * pio2_1) - z0 * pio2_t;
22025c28e8Piotr Jasiukajtis			y1 = (y1 - z1 * pio2_1) - z1 * pio2_t;
22125c28e8Piotr Jasiukajtis			y2 = (y2 - z2 * pio2_1) - z2 * pio2_t;
22225c28e8Piotr Jasiukajtis			y3 = (y3 - z3 * pio2_1) - z3 * pio2_t;
22325c28e8Piotr Jasiukajtis		}
22425c28e8Piotr Jasiukajtis
22525c28e8Piotr Jasiukajtis		z0 = y0 * y0;
22625c28e8Piotr Jasiukajtis		z1 = y1 * y1;
22725c28e8Piotr Jasiukajtis		z2 = y2 * y2;
22825c28e8Piotr Jasiukajtis		z3 = y3 * y3;
22925c28e8Piotr Jasiukajtis
23025c28e8Piotr Jasiukajtis		f0 = (float)(y0 + y0 * z0 * (S0 + z0 * (S1 + z0 * S2)));
23125c28e8Piotr Jasiukajtis		f1 = (float)(y1 + y1 * z1 * (S0 + z1 * (S1 + z1 * S2)));
23225c28e8Piotr Jasiukajtis		f2 = (float)(y2 + y2 * z2 * (S0 + z2 * (S1 + z2 * S2)));
23325c28e8Piotr Jasiukajtis		f3 = (float)(y3 + y3 * z3 * (S0 + z3 * (S1 + z3 * S2)));
23425c28e8Piotr Jasiukajtis
23525c28e8Piotr Jasiukajtis		g0 = (float)(one + z0 * (mhalf + z0 * (C0 + z0 *
23625c28e8Piotr Jasiukajtis		    (C1 + z0 * C2))));
23725c28e8Piotr Jasiukajtis		g1 = (float)(one + z1 * (mhalf + z1 * (C0 + z1 *
23825c28e8Piotr Jasiukajtis		    (C1 + z1 * C2))));
23925c28e8Piotr Jasiukajtis		g2 = (float)(one + z2 * (mhalf + z2 * (C0 + z2 *
24025c28e8Piotr Jasiukajtis		    (C1 + z2 * C2))));
24125c28e8Piotr Jasiukajtis		g3 = (float)(one + z3 * (mhalf + z3 * (C0 + z3 *
24225c28e8Piotr Jasiukajtis		    (C1 + z3 * C2))));
24325c28e8Piotr Jasiukajtis
24425c28e8Piotr Jasiukajtis		if (n0 & 2) {
24525c28e8Piotr Jasiukajtis			f0 = -f0;
24625c28e8Piotr Jasiukajtis			g0 = -g0;
24725c28e8Piotr Jasiukajtis		}
24825c28e8Piotr Jasiukajtis		if (n1 & 2) {
24925c28e8Piotr Jasiukajtis			f1 = -f1;
25025c28e8Piotr Jasiukajtis			g1 = -g1;
25125c28e8Piotr Jasiukajtis		}
25225c28e8Piotr Jasiukajtis		if (n2 & 2) {
25325c28e8Piotr Jasiukajtis			f2 = -f2;
25425c28e8Piotr Jasiukajtis			g2 = -g2;
25525c28e8Piotr Jasiukajtis		}
25625c28e8Piotr Jasiukajtis		if (n3 & 2) {
25725c28e8Piotr Jasiukajtis			f3 = -f3;
25825c28e8Piotr Jasiukajtis			g3 = -g3;
25925c28e8Piotr Jasiukajtis		}
26025c28e8Piotr Jasiukajtis
26125c28e8Piotr Jasiukajtis		if (n0 & 1) {
26225c28e8Piotr Jasiukajtis			*s = g0;
26325c28e8Piotr Jasiukajtis			*c = -f0;
26425c28e8Piotr Jasiukajtis		} else {
26525c28e8Piotr Jasiukajtis			*s = f0;
26625c28e8Piotr Jasiukajtis			*c = g0;
26725c28e8Piotr Jasiukajtis		}
26825c28e8Piotr Jasiukajtis		s += strides;
26925c28e8Piotr Jasiukajtis		c += stridec;
27025c28e8Piotr Jasiukajtis
27125c28e8Piotr Jasiukajtis		if (n1 & 1) {
27225c28e8Piotr Jasiukajtis			*s = g1;
27325c28e8Piotr Jasiukajtis			*c = -f1;
27425c28e8Piotr Jasiukajtis		} else {
27525c28e8Piotr Jasiukajtis			*s = f1;
27625c28e8Piotr Jasiukajtis			*c = g1;
27725c28e8Piotr Jasiukajtis		}
27825c28e8Piotr Jasiukajtis		s += strides;
27925c28e8Piotr Jasiukajtis		c += stridec;
28025c28e8Piotr Jasiukajtis
28125c28e8Piotr Jasiukajtis		if (n2 & 1) {
28225c28e8Piotr Jasiukajtis			*s = g2;
28325c28e8Piotr Jasiukajtis			*c = -f2;
28425c28e8Piotr Jasiukajtis		} else {
28525c28e8Piotr Jasiukajtis			*s = f2;
28625c28e8Piotr Jasiukajtis			*c = g2;
28725c28e8Piotr Jasiukajtis		}
28825c28e8Piotr Jasiukajtis		s += strides;
28925c28e8Piotr Jasiukajtis		c += stridec;
29025c28e8Piotr Jasiukajtis
29125c28e8Piotr Jasiukajtis		if (n3 & 1) {
29225c28e8Piotr Jasiukajtis			*s = g3;
29325c28e8Piotr Jasiukajtis			*c = -f3;
29425c28e8Piotr Jasiukajtis		} else {
29525c28e8Piotr Jasiukajtis			*s = f3;
29625c28e8Piotr Jasiukajtis			*c = g3;
29725c28e8Piotr Jasiukajtis		}
29825c28e8Piotr Jasiukajtis		continue;
29925c28e8Piotr Jasiukajtis
30025c28e8Piotr Jasiukajtisprocess1:
30125c28e8Piotr Jasiukajtis		PROCESS(0);
30225c28e8Piotr Jasiukajtis		continue;
30325c28e8Piotr Jasiukajtis
30425c28e8Piotr Jasiukajtisprocess2:
30525c28e8Piotr Jasiukajtis		PROCESS(0);
30625c28e8Piotr Jasiukajtis		PROCESS(1);
30725c28e8Piotr Jasiukajtis		continue;
30825c28e8Piotr Jasiukajtis
30925c28e8Piotr Jasiukajtisprocess3:
31025c28e8Piotr Jasiukajtis		PROCESS(0);
31125c28e8Piotr Jasiukajtis		PROCESS(1);
31225c28e8Piotr Jasiukajtis		PROCESS(2);
31325c28e8Piotr Jasiukajtis	}
31425c28e8Piotr Jasiukajtis}
315