__vcos.c revision 25c28e83beb90e7c80452a7c818c5e6f73a07dc8
/*
* 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 HI(x) *(1+(int*)x)
#define LO(x) *(unsigned*)x
#else
#define HI(x) *(int*)x
#define LO(x) *(1+(unsigned*)x)
#endif
#ifdef __RESTRICT
#define restrict _Restrict
#else
#define restrict
#endif
/*
* vcos.1.c
*
* Vector cosine function. Just slight modifications to vsin.8.c, mainly
* in the primary range part.
*
* Modification to primary range processing. If an argument that does not
* fall in the primary range is encountered, then processing is continued
* in the medium range.
*
*/
extern const double __vlibm_TBL_sincos_hi[], __vlibm_TBL_sincos_lo[];
static const double
one = 1.0,
pp1 = -1.666666666605760465276263943134982554676e-0001,
pp2 = 8.333261209690963126718376566146180944442e-0003,
qq1 = -4.999999999977710986407023955908711557870e-0001,
qq2 = 4.166654863857219350645055881018842089580e-0002,
-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_vcos_big(int, double *, int, double *, int, int);
/*
* y[i*stridey] := cos( x[i*stridex] ), for i = 0..n.
*
* Calls __vlibm_vcos_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
int stridey)
{
volatile int v __GNU_UNUSED;
nsave = n;
xsave = x;
ysave = y;
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;
goto MEDIUM;
}
if (hx0 < 0x3e400000) {
/* Too small. cos x ~ 1. */
v = *x;
*y = 1.0;
x += stridex;
y += stridey;
i = 0;
if (--n <= 0)
break;
goto LOOP0;
}
x0 = *x;
py0 = y;
x += stridex;
y += stridey;
i = 1;
if (--n <= 0)
break;
LOOP1: /* Get second arg, same as above. */
if (hx1 > 0x3fe921fb)
{
biguns = 2;
goto MEDIUM;
}
if (hx1 < 0x3e400000)
{
v = *x;
*y = 1.0;
x += stridex;
y += stridey;
i = 1;
if (--n <= 0)
break;
goto LOOP1;
}
x1 = *x;
py1 = y;
x += stridex;
y += stridey;
i = 2;
if (--n <= 0)
break;
LOOP2: /* Get third arg, same as above. */
if (hx2 > 0x3fe921fb)
{
biguns = 3;
goto MEDIUM;
}
if (hx2 < 0x3e400000)
{
v = *x;
*y = 1.0;
x += stridex;
y += stridey;
i = 2;
if (--n <= 0)
break;
goto LOOP2;
}
x2 = *x;
py2 = y;
/*
* 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) sin_hi(t) */
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7: /* All are < 5/32 */
break;
}
x += stridex;
y += stridey;
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 */
return;
/*
* Take care of BIGUNS.
*
* We have jumped here in the middle of processing after having
* encountered a medium range argument. Therefore things are in a
* bit of a tizzy.
*/
if (biguns == 3)
{
biguns = 0;
goto loop2;
}
else if (biguns == 2)
{
biguns = 0;
goto loop1;
}
biguns = 0;
do
{
unsigned hx;
/*
* Find 3 more to work on: Not already done, not too big.
*/
hx &= ~0x80000000;
{
{
x0 = *x;
}
else
biguns = 1;
x += stridex;
y += stridey;
i = 0;
if (--n <= 0)
break;
goto loop0;
}
x0 = *x;
py0 = y;
x += stridex;
y += stridey;
i = 1;
if (--n <= 0)
break;
hx &= ~0x80000000;
if (hx > 0x413921fb)
{
if (hx >= 0x7ff00000)
{
x1 = *x;
}
else
biguns = 1;
x += stridex;
y += stridey;
i = 1;
if (--n <= 0)
break;
goto loop1;
}
x1 = *x;
py1 = y;
x += stridex;
y += stridey;
i = 2;
if (--n <= 0)
break;
hx &= ~0x80000000;
if (hx > 0x413921fb)
{
if (hx >= 0x7ff00000)
{
x2 = *x;
}
else
biguns = 1;
x += stridex;
y += stridey;
i = 2;
if (--n <= 0)
break;
goto loop2;
}
x2 = *x;
py2 = y;
switch (i)
{
case 0:
xsb0 |= 1;
xsb1 |= 1;
xsb2 |= 1;
break;
case 1:
y0_or_zero[0] = y0;
xsb1 |= 1;
xsb2 |= 1;
break;
case 2:
y1_or_zero[0] = y1;
xsb0 |= 1;
xsb2 |= 1;
break;
case 3:
y0_or_zero[0] = y0;
y1_or_zero[0] = y1;
xsb2 |= 1;
break;
case 4:
y2_or_zero[0] = y2;
xsb0 |= 1;
xsb1 |= 1;
break;
case 5:
y0_or_zero[0] = y0;
y2_or_zero[0] = y2;
xsb1 |= 1;
break;
case 6:
y1_or_zero[0] = y1;
y2_or_zero[0] = y2;
xsb0 |= 1;
break;
case 7:
y0_or_zero[0] = y0;
y1_or_zero[0] = y1;
y2_or_zero[0] = y2;
break;
}
x += stridex;
y += stridey;
i = 0;
} while (--n > 0);
if (i > 0)
{
if (i > 1)
{
{
y1_or_zero[0] = y1;
}
else
{
xsb1 |= 1;
}
}
{
y0_or_zero[0] = y0;
}
else
{
xsb0 |= 1;
}
}
if (biguns)
}