1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 /*
  26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  27  * Use is subject to license terms.
  28  */
  29 
  30 #include <sys/isa_defs.h>
  31 
  32 #ifdef _LITTLE_ENDIAN
  33 #define HI(x)   *(1+(int*)x)
  34 #define LO(x)   *(unsigned*)x
  35 #else
  36 #define HI(x)   *(int*)x
  37 #define LO(x)   *(1+(unsigned*)x)
  38 #endif
  39 
  40 #ifdef __RESTRICT
  41 #define restrict _Restrict
  42 #else
  43 #define restrict
  44 #endif
  45 
  46 extern const double __vlibm_TBL_sincos_hi[], __vlibm_TBL_sincos_lo[];
  47 extern int __vlibm_rem_pio2m( double *, double *, int, int, int );
  48 
  49 static const double
  50         zero    = 0.0,
  51         one             = 1.0,
  52         two24   = 16777216.0,
  53         pp1             = -1.666666666605760465276263943134982554676e-0001,
  54         pp2             =  8.333261209690963126718376566146180944442e-0003,
  55         p1              = -1.666666666666629669805215138920301589656e-0001,
  56         p2              =  8.333333332390951295683993455280336376663e-0003,
  57         p3              = -1.984126237997976692791551778230098403960e-0004,
  58         p4              =  2.753403624854277237649987622848330351110e-0006,
  59         qq1             = -4.999999999977710986407023955908711557870e-0001,
  60         qq2             =  4.166654863857219350645055881018842089580e-0002,
  61         q1              = -4.999999999999931701464060878888294524481e-0001,
  62         q2              =  4.166666666394861917535640593963708222319e-0002,
  63         q3              = -1.388888552656142867832756687736851681462e-0003,
  64         q4              =  2.478519423681460796618128289454530524759e-0005;
  65 
  66 void
  67 __vlibm_vsincos_bigf( int n, float * restrict x, int stridex,
  68         float * restrict ss, int stridess, float * restrict cc, int stridecc )
  69 {
  70         for ( ; n--; x += stridex, ss += stridess, cc += stridecc )
  71         {
  72                 double          ts, tc, tx, tt[3], ty[2], t, w, z, c, s;
  73                 unsigned        hx, xsb;
  74                 int                     e0, nx, j;
  75 
  76                 tx = *x;
  77                 hx = HI(&tx);
  78                 xsb = hx & 0x80000000;
  79                 hx &= ~0x80000000;
  80                 if ( hx <= 0x413921fb || hx >= 0x7ff00000 )
  81                         continue;
  82                 e0 = ( hx >> 20 ) - 1046;
  83                 HI(&tx) = 0x41600000 | ( hx & 0xfffff );
  84 
  85                 tt[0] = (double)( (int) tx );
  86                 tx = ( tx - tt[0] ) * two24;
  87                 if ( tx != zero )
  88                 {
  89                         nx = 2;
  90                         tt[1] = (double)( (int) tx );
  91                         tt[2] = ( tx - tt[1] ) * two24;
  92                         if ( tt[2] != zero )
  93                                 nx = 3;
  94                 }
  95                 else
  96                 {
  97                         nx = 1;
  98                         tt[1] = tt[2] = zero;
  99                 }
 100                 nx = __vlibm_rem_pio2m( tt, ty, e0, nx, 2 );
 101                 if ( xsb )
 102                 {
 103                         nx = -nx;
 104                         ty[0] = -ty[0];
 105                         ty[1] = -ty[1];
 106                 }
 107 
 108                 /* now nx and ty[*] are the quadrant and reduced arg */
 109                 xsb = 0;
 110                 hx = HI(&ty[0]);
 111                 if ( hx & 0x80000000 )
 112                 {
 113                         ty[0] = -ty[0];
 114                         ty[1] = -ty[1];
 115                         hx &= ~0x80000000;
 116                         xsb = 1;
 117                 }
 118                 if ( hx < 0x3fc40000 )
 119                 {
 120                         z = ty[0] * ty[0];
 121                         t = z * ( q1 + z * ( q2 + z * ( q3 + z * q4 ) ) );
 122                         c = one + t;
 123 
 124                         t = z * ( p1 + z * ( p2 + z * ( p3 + z * p4 ) ) );
 125                         s = ty[0] + ( ty[1] + ty[0] * t );
 126                 }
 127                 else {
 128                         j = ( hx + 0x4000 ) & 0x7fff8000;
 129                         HI(&t) = j;
 130                         LO(&t) = 0;
 131                         ty[0] = ( ty[0] - t ) + ty[1];
 132                         z = ty[0] * ty[0];
 133                         t = z * ( qq1 + z * qq2 );
 134                         w = ty[0] * ( one + z * ( pp1 + z * pp2 ) );
 135                         j = ( ( j - 0x3fc40000 ) >> 13 ) & ~3;
 136 
 137                         c = __vlibm_TBL_sincos_hi[j+1];
 138                         tc = __vlibm_TBL_sincos_lo[j+1] - ( __vlibm_TBL_sincos_hi[j] * w - c * t );
 139                         c += tc;
 140 
 141                         s = __vlibm_TBL_sincos_hi[j];
 142                         ts = ( __vlibm_TBL_sincos_hi[j+1] * w + s * t ) + __vlibm_TBL_sincos_lo[j];
 143                         s += ts;
 144                 }
 145                 if ( xsb ) {
 146                         s = -s;
 147                 }
 148 
 149                 switch ( nx & 3 ) {
 150                 case 0:
 151                         *ss = s;
 152                         *cc = c;
 153                         break;
 154 
 155                 case 1:
 156                         *ss = c;
 157                         *cc = -s;
 158                         break;
 159 
 160                 case 2:
 161                         *ss = -s;
 162                         *cc = -c;
 163                         break;
 164 
 165                 case 3:
 166                         *ss = -c;
 167                         *cc = s;
 168                         break;
 169                 }
 170         }
 171 }