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