1 /*- 2 * Copyright (c) 1980 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)r_tan.c 5.5 (Berkeley) 04/12/91"; 10 #endif /* not lint */ 11 12 #ifndef tahoe 13 float r_tan(x) 14 float *x; 15 { 16 double tan(); 17 return( tan(*x) ); 18 } 19 20 #else tahoe 21 22 /* 23 SINGLE PRECISION floating point tangent 24 25 sin/cos is used after argument reduction to [0,pi/4] range. 26 since x is in this range, tan(x) is in [0,1] range and 27 no overflow can occur here. 28 */ 29 30 #include <errno.h> 31 32 int errno; 33 static double invpi = 1.27323954473516268; /* 4/pi */ 34 35 #ifndef __GNUC__ 36 fortran float sin(), cos(); 37 #else 38 #define sin(x) \ 39 ({ \ 40 float __result; \ 41 asm("ldd %1; cvdf; sinf; stf %0" : "=rm" (__result) : "rm" (x)); \ 42 __result; \ 43 }) 44 #define cos(x) \ 45 ({ \ 46 float __result; \ 47 asm("ldd %1; cvdf; cosf; stf %0" : "=rm" (__result) : "rm" (x)); \ 48 __result; \ 49 }) 50 #endif 51 52 float 53 r_tan(parg) 54 float *parg; 55 { 56 double arg; 57 double modf(); 58 float flmax_(); 59 double temp, e, x, xsq; 60 int sign; 61 int flag, i; 62 63 arg = *parg; 64 flag = 0; 65 sign = 1.; 66 if(arg < 0.){ /* tan(-arg) = -tan(arg) */ 67 arg = -arg; 68 sign = -1.; 69 } 70 arg = arg*invpi; /*overflow?*/ 71 x = modf(arg,&e); 72 i = e; 73 switch(i%4) { 74 case 1: /* 2nd octant: tan(x) = 1/tan(1-x) */ 75 x = 1. - x; 76 flag = 1; 77 break; 78 79 case 2: /* 3rd octant: tan(x) = -1/tan(x) */ 80 sign = - sign; 81 flag = 1; 82 break; 83 84 case 3: /* 4th octant: tan(x) = -tan(1-x) */ 85 x = 1. - x; 86 sign = - sign; 87 break; 88 89 case 0: /* 1st octant */ 90 break; 91 } 92 x = x/invpi; 93 94 temp = sin(x)/cos(x); 95 96 if(flag == 1) { 97 if(temp == 0.) { /* check for singular "point" */ 98 errno = ERANGE; 99 if (sign>0) 100 return(flmax_()); 101 return(-flmax_()); 102 } 103 temp = 1./temp; 104 } 105 return(sign*temp); 106 } 107 108 #endif tahoe 109