1 /*- 2 * ==================================================== 3 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 4 * 5 * Developed at SunPro, a Sun Microsystems, Inc. business. 6 * Permission to use, copy, modify, and distribute this 7 * software is freely granted, provided that this notice 8 * is preserved. 9 * ==================================================== 10 */ 11 12 /* s_sincosf.c -- float version of s_sincos.c. 13 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 14 * Optimized by Bruce D. Evans. 15 * Merged s_sinf.c and s_cosf.c by Steven G. Kargl. 16 */ 17 18 #include <sys/cdefs.h> 19 #include <float.h> 20 21 #include "math.h" 22 #define INLINE_REM_PIO2F 23 #include "math_private.h" 24 #include "e_rem_pio2f.c" 25 #include "k_sincosf.h" 26 27 /* Small multiples of pi/2 rounded to double precision. */ 28 static const double 29 p1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */ 30 p2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */ 31 p3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */ 32 p4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */ 33 34 void 35 sincosf(float x, float *sn, float *cs) 36 { 37 float c, s; 38 double y; 39 int32_t n, hx, ix; 40 41 GET_FLOAT_WORD(hx, x); 42 ix = hx & 0x7fffffff; 43 44 if (ix <= 0x3f490fda) { /* |x| ~<= pi/4 */ 45 if (ix < 0x39800000) { /* |x| < 2**-12 */ 46 if ((int)x == 0) { 47 *sn = x; /* x with inexact if x != 0 */ 48 *cs = 1; 49 return; 50 } 51 } 52 __kernel_sincosdf(x, sn, cs); 53 return; 54 } 55 56 if (ix <= 0x407b53d1) { /* |x| ~<= 5*pi/4 */ 57 if (ix <= 0x4016cbe3) { /* |x| ~<= 3pi/4 */ 58 if (hx > 0) { 59 __kernel_sincosdf(x - p1pio2, cs, sn); 60 *cs = -*cs; 61 } else { 62 __kernel_sincosdf(x + p1pio2, cs, sn); 63 *sn = -*sn; 64 } 65 } else { 66 if (hx > 0) 67 __kernel_sincosdf(x - p2pio2, sn, cs); 68 else 69 __kernel_sincosdf(x + p2pio2, sn, cs); 70 *sn = -*sn; 71 *cs = -*cs; 72 } 73 return; 74 } 75 76 if (ix <= 0x40e231d5) { /* |x| ~<= 9*pi/4 */ 77 if (ix <= 0x40afeddf) { /* |x| ~<= 7*pi/4 */ 78 if (hx > 0) { 79 __kernel_sincosdf(x - p3pio2, cs, sn); 80 *sn = -*sn; 81 } else { 82 __kernel_sincosdf(x + p3pio2, cs, sn); 83 *cs = -*cs; 84 } 85 } else { 86 if (hx > 0) 87 __kernel_sincosdf(x - p4pio2, sn, cs); 88 else 89 __kernel_sincosdf(x + p4pio2, sn, cs); 90 } 91 return; 92 } 93 94 /* If x = Inf or NaN, then sin(x) = NaN and cos(x) = NaN. */ 95 if (ix >= 0x7f800000) { 96 *sn = x - x; 97 *cs = x - x; 98 return; 99 } 100 101 /* Argument reduction. */ 102 n = __ieee754_rem_pio2f(x, &y); 103 __kernel_sincosdf(y, &s, &c); 104 105 switch(n & 3) { 106 case 0: 107 *sn = s; 108 *cs = c; 109 break; 110 case 1: 111 *sn = c; 112 *cs = -s; 113 break; 114 case 2: 115 *sn = -s; 116 *cs = -c; 117 break; 118 default: 119 *sn = -c; 120 *cs = s; 121 } 122 } 123 124 125