/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/isa_defs.h>
#include <sys/ccompile.h>
#ifdef _LITTLE_ENDIAN
#define LO(x) *(unsigned*)x
#else
#define HI(x) *(int*)x
#endif
#ifdef __RESTRICT
#define restrict _Restrict
#else
#define restrict
#endif
/*
*
* Vector sine and cosine function. Just slight modifications to vcos.c.
*/
extern const double __vlibm_TBL_sincos_hi[], __vlibm_TBL_sincos_lo[];
static const double
-4.999999999999931701464060878888294524481e-0001 },
4.166666666394861917535640593963708222319e-0002 },
-1.388888552656142867832756687736851681462e-0003 },
2.478519423681460796618128289454530524759e-0005 };
/* Don't __ the following; acomp will handle it */
extern double fabs(double);
extern void __vlibm_vsincos_big(int, double *, int, double *, int, double *, int, int);
/*
* y[i*stridey] := sin( x[i*stridex] ), for i = 0..n.
* c[i*stridec] := cos( x[i*stridex] ), for i = 0..n.
*
* Calls __vlibm_vsincos_big to handle all elts which have abs >~ 1.647e+06.
* Argument reduction is done here for elts pi/4 < arg < 1.647e+06.
*
* elts < 2^-27 use the approximation 1.0 ~ cos(x).
*/
void
double * restrict y, int stridey,
double * restrict c, int stridec)
{
volatile int v __GNU_UNUSED;
nsave = n;
xsave = x;
ysave = y;
csave = c;
biguns = 0;
do /* MAIN LOOP */
{
/* Gotos here so _break_ exits MAIN LOOP. */
LOOP0: /* Find first arg in right range. */
if (hx0 > 0x3fe921fb) {
/* Too big: arg reduction needed, so leave for second part */
biguns = 1;
x += stridex;
y += stridey;
c += stridec;
i = 0;
if (--n <= 0)
break;
goto LOOP0;
}
if (hx0 < 0x3e400000) {
/* Too small. cos x ~ 1, sin x ~ x. */
v = *x;
*c = 1.0;
*y = *x;
x += stridex;
y += stridey;
c += stridec;
i = 0;
if (--n <= 0)
break;
goto LOOP0;
}
x0 = *x;
py0 = y;
pc0 = c;
x += stridex;
y += stridey;
c += stridec;
i = 1;
if (--n <= 0)
break;
LOOP1: /* Get second arg, same as above. */
if (hx1 > 0x3fe921fb)
{
biguns = 1;
x += stridex;
y += stridey;
c += stridec;
i = 1;
if (--n <= 0)
break;
goto LOOP1;
}
if (hx1 < 0x3e400000)
{
v = *x;
*c = 1.0;
*y = *x;
x += stridex;
y += stridey;
c += stridec;
i = 1;
if (--n <= 0)
break;
goto LOOP1;
}
x1 = *x;
py1 = y;
pc1 = c;
x += stridex;
y += stridey;
c += stridec;
i = 2;
if (--n <= 0)
break;
LOOP2: /* Get third arg, same as above. */
if (hx2 > 0x3fe921fb)
{
biguns = 1;
x += stridex;
y += stridey;
c += stridec;
i = 2;
if (--n <= 0)
break;
goto LOOP2;
}
if (hx2 < 0x3e400000)
{
v = *x;
*c = 1.0;
*y = *x;
x += stridex;
y += stridey;
c += stridec;
i = 2;
if (--n <= 0)
break;
goto LOOP2;
}
x2 = *x;
py2 = y;
pc2 = c;
/*
* 0x3fc40000 = 5/32 ~ 0.15625
* Get msb after subtraction. Will be 1 only if
* hx0 - 5/32 is negative.
*/
switch (i)
{
case 0: /* All are > 5/32 */
/* cos_lo(t) */
break;
case 1:
/* cos_lo(t) */
break;
case 2:
/* cos_lo(t) */
break;
case 3:
break;
case 4:
/* cos_lo(t) */
break;
case 5:
break;
case 6:
break;
case 7: /* All are < 5/32 */
break;
}
x += stridex;
y += stridey;
c += stridec;
i = 0;
} while (--n > 0); /* END MAIN LOOP */
/*
* CLEAN UP last 0, 1, or 2 elts.
*/
if (i > 0) /* Clean up elts at tail. i < 3. */
{
if (i > 1)
{
if (hx1 < 0x3fc40000)
{
}
else
{
}
}
if (hx0 < 0x3fc40000)
{
}
else
{
}
} /* END CLEAN UP */
if (!biguns)
return;
/*
* Take care of BIGUNS.
*/
n = nsave;
x = xsave;
y = ysave;
c = csave;
biguns = 0;
do
{
unsigned hx;
/*
* Find 3 more to work on: Not already done, not too big.
*/
hx &= ~0x80000000;
{
x += stridex;
y += stridey;
c += stridec;
i = 0;
if (--n <= 0)
break;
goto loop0;
}
{
{
x0 = *x;
}
else {
biguns = 1;
}
x += stridex;
y += stridey;
c += stridec;
i = 0;
if (--n <= 0)
break;
goto loop0;
}
x0 = *x;
py0 = y;
pc0 = c;
x += stridex;
y += stridey;
c += stridec;
i = 1;
if (--n <= 0)
break;
hx &= ~0x80000000;
if (hx <= 0x3fe921fb)
{
x += stridex;
y += stridey;
c += stridec;
i = 1;
if (--n <= 0)
break;
goto loop1;
}
if (hx > 0x413921fb)
{
if (hx >= 0x7ff00000)
{
x1 = *x;
}
else {
biguns = 1;
}
x += stridex;
y += stridey;
c += stridec;
i = 1;
if (--n <= 0)
break;
goto loop1;
}
x1 = *x;
py1 = y;
pc1 = c;
x += stridex;
y += stridey;
c += stridec;
i = 2;
if (--n <= 0)
break;
hx &= ~0x80000000;
if (hx <= 0x3fe921fb)
{
x += stridex;
y += stridey;
c += stridec;
i = 2;
if (--n <= 0)
break;
goto loop2;
}
if (hx > 0x413921fb)
{
if (hx >= 0x7ff00000)
{
x2 = *x;
}
else {
biguns = 1;
}
x += stridex;
y += stridey;
c += stridec;
i = 2;
if (--n <= 0)
break;
goto loop2;
}
x2 = *x;
py2 = y;
pc2 = c;
n0 &= 3;
n1 &= 3;
n2 &= 3;
switch (i)
{
case 0:
xsb0 |= 1;
xsb1 |= 1;
xsb2 |= 1;
break;
case 1:
y2_or_zero[0] = y2;
xsb0 |= 1;
xsb1 |= 1;
break;
case 2:
y1_or_zero[0] = y1;
xsb0 |= 1;
xsb2 |= 1;
break;
case 3:
y1_or_zero[0] = y1;
y2_or_zero[0] = y2;
xsb0 |= 1;
break;
case 4:
y0_or_zero[0] = y0;
xsb1 |= 1;
xsb2 |= 1;
break;
case 5:
y0_or_zero[0] = y0;
y2_or_zero[0] = y2;
xsb1 |= 1;
break;
case 6:
y0_or_zero[0] = y0;
y1_or_zero[0] = y1;
xsb2 |= 1;
break;
case 7:
y0_or_zero[0] = y0;
y1_or_zero[0] = y1;
y2_or_zero[0] = y2;
break;
}
x += stridex;
y += stridey;
c += stridec;
i = 0;
} while (--n > 0);
if (i > 0)
{
if (i > 1)
{
n1 &= 3;
{
y1_or_zero[0] = y1;
}
else
{
xsb1 |= 1;
}
}
n0 &= 3;
{
y0_or_zero[0] = y0;
}
else
{
xsb0 |= 1;
}
}
if (biguns) {
}
}