xref: /original-bsd/usr.bin/f77/libF77/r_tan.c (revision 1897046e)
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