1 /* Fpu087.c
2  * This file contains routines to replace fpu087.asm.
3  *
4  * This file Copyright 1991 Ken Shirriff.  It may be used according to the
5  * fractint license conditions, blah blah blah.
6  */
7 
8 
9 #include "port.h"
10 #include "prototyp.h"
11 
12 /*
13  *----------------------------------------------------------------------
14  *
15  * xxx086 --
16  *
17  *	Simulate integer math routines using floating point.
18  *	This will of course slow things down, so this should all be
19  *	changed at some point.
20  *
21  *----------------------------------------------------------------------
22  */
23 
24 LDBL _2_ = 2.0;
25 LDBL _1_ = 1.0;
26 LDBL PointFive = 0.5;
27 LDBL infinity = 1.0E+300;
28 
FPUaptan387(LDBL * y,LDBL * x,LDBL * atan)29 void FPUaptan387(LDBL *y, LDBL *x, LDBL *atan)
30 {
31     if (isnan(*x) || isnan(*y) || isinf(*x) || isinf(*y))
32       *atan = 1.0;
33     else
34       *atan = (LDBL)atan2l(*y,*x);
35 }
36 
FPUcplxmul(_CMPLX * x,_CMPLX * y,_CMPLX * z)37 void FPUcplxmul(_CMPLX *x, _CMPLX *y, _CMPLX *z)
38 {
39     LDBL tx, ty;
40     if (y->y == 0.0) { /* y is real */
41       tx = (LDBL)x->x * (LDBL)y->x;
42       ty = (LDBL)x->y * (LDBL)y->x;
43     }
44     else if (x->y == 0.0) { /* x is real */
45       tx = (LDBL)x->x * (LDBL)y->x;
46       ty = (LDBL)x->x * (LDBL)y->y;
47     }
48     else {
49       tx = (LDBL)x->x * (LDBL)y->x - (LDBL)x->y * (LDBL)y->y;
50       ty = (LDBL)x->x * (LDBL)y->y + (LDBL)x->y * (LDBL)y->x;
51     }
52     if (isnan(ty) || isinf(ty))
53       z->y = infinity;
54     else
55       z->y = (LDBL)ty;
56     if (isnan(tx) || isinf(tx))
57       z->x = infinity;
58     else
59       z->x = (LDBL)tx;
60 }
61 
FPUcplxdiv(_CMPLX * x,_CMPLX * y,_CMPLX * z)62 void FPUcplxdiv(_CMPLX *x, _CMPLX *y, _CMPLX *z)
63 {
64     LDBL mod,tx,yxmod,yymod, yx, yy;
65     yx = y->x;
66     yy = y->y;
67     mod = yx * yx + yy * yy;
68     if (mod == 0.0 || fabsl(mod) <= LDBL_MIN) {
69       z->x = infinity;
70       z->y = infinity;
71       overflow = 1;
72       return;
73     }
74 
75     if (yy == 0.0) { /* if y is real */
76       z->x = (LDBL)x->x / yx;
77       z->y = (LDBL)x->y / yx;
78     }
79     else {
80         yxmod = yx/mod;
81         yymod = - yy/mod;
82         tx = x->x * yxmod - x->y * yymod;
83         z->y = (LDBL)(x->x * yymod + x->y * yxmod);
84         z->x = (LDBL)tx;
85     }
86 }
87 
FPUsincos(LDBL * Angle,LDBL * Sin,LDBL * Cos)88 void FPUsincos(LDBL *Angle, LDBL *Sin, LDBL *Cos)
89 {
90   if (isnan(*Angle) || isinf(*Angle)){
91     *Sin = 0.0;
92     *Cos = 1.0;
93   } else {
94     *Sin = (LDBL)sinl(*Angle);
95     *Cos = (LDBL)cosl(*Angle);
96   }
97 }
98 
FPUsinhcosh(LDBL * Angle,LDBL * Sinh,LDBL * Cosh)99 void FPUsinhcosh(LDBL *Angle, LDBL *Sinh, LDBL *Cosh)
100 {
101   if (isnan(*Angle) || isinf(*Angle)){
102     *Sinh = 1.0;
103     *Cosh = 1.0;
104   } else {
105     *Sinh = (LDBL)sinhl(*Angle);
106     *Cosh = (LDBL)coshl(*Angle);
107   }
108   if (isnan(*Sinh) || isinf(*Sinh))
109     *Sinh = 1.0;
110   if (isnan(*Cosh) || isinf(*Cosh))
111     *Cosh = 1.0;
112 }
113 
FPUcplxlog(_CMPLX * x,_CMPLX * z)114 void FPUcplxlog(_CMPLX *x, _CMPLX *z)
115 {
116     LDBL mod, xx, xy;
117     xx = x->x;
118     xy = x->y;
119     if (xx == 0.0 && xy == 0.0) {
120         z->x = z->y = 0.0;
121         return;
122     }
123     else if(xy == 0.0) { /* x is real */
124         z->x = logl(xx);
125         z->y = 0.0;
126         return;
127     }
128     mod = xx*xx + xy*xy;
129     if (isnan(mod) || islessequal(mod,0) || isinf(mod))
130       z->x = 0.5;
131     else
132       z->x = (LDBL)(0.5 * logl(mod));
133     if (isnan(xx) || isnan(xy) || isinf(xx) || isinf(xy))
134       z->y = 1.0;
135     else
136       z->y = (LDBL)atan2l(xy,xx);
137 }
138 
FPUcplxexp387(_CMPLX * x,_CMPLX * z)139 void FPUcplxexp387(_CMPLX *x, _CMPLX *z)
140 {
141     LDBL pwr,y;
142     y = x->y;
143     pwr = expl(x->x);
144     if (isnan(pwr) || isinf(pwr))
145       pwr = 1.0;
146     if (y == 0.0) { /* x is real */
147       z->x = pwr;
148       z->y = 0.0;
149     }
150     else {
151       z->x = (LDBL)(pwr*cosl(y));
152       z->y = (LDBL)(pwr*sinl(y));
153     }
154 }
155 
156 /* Integer Routines */
SinCos086(long x,long * sinx,long * cosx)157 void SinCos086(long x, long *sinx, long *cosx)
158 {
159     double a;
160     a = x/(double)(1<<16);
161     *sinx = (long) (sin(a)*(double)(1<<16));
162     *cosx = (long) (cos(a)*(double)(1<<16));
163 }
164 
SinhCosh086(long x,long * sinx,long * cosx)165 void SinhCosh086(long x, long *sinx, long *cosx)
166 {
167     double a;
168     a = x/(double)(1<<16);
169     *sinx = (long) (sinh(a)*(double)(1<<16));
170     *cosx = (long) (cosh(a)*(double)(1<<16));
171 }
172 
Exp086(x)173 long Exp086(x)
174 long x;
175 {
176     return (long) (exp((double)x/(double)(1<<16))*(double)(1<<16));
177 }
178 
179 #define em2float(l) (*(float *)&(l))
180 #define float2em(f) (*(long *)&(f))
181 
182 /*
183  * Input is a 16 bit offset number.  Output is shifted by Fudge.
184  */
ExpFudged(x,Fudge)185 unsigned long ExpFudged(x, Fudge)
186 long x;
187 int Fudge;
188 {
189     return (long) (exp((double)x/(double)(1<<16))*(double)(1<<Fudge));
190 }
191 
192 /* This multiplies two e/m numbers and returns an e/m number. */
r16Mul(x,y)193 long r16Mul(x,y)
194 long x,y;
195 {
196     float f;
197     f = em2float(x)*em2float(y);
198     return float2em(f);
199 }
200 
201 /* This takes an exp/mant number and returns a shift-16 number */
LogFloat14(x)202 long LogFloat14(x)
203 unsigned long x;
204 {
205     return log((double)em2float(x))*(1<<16);
206 }
207 
208 /* This divides two e/m numbers and returns an e/m number. */
RegDivFloat(x,y)209 long RegDivFloat(x,y)
210 long x,y;
211 {
212     float f;
213     f = em2float(x)/em2float(y);
214     return float2em(f);
215 }
216 
217 /*
218  * This routine on the IBM converts shifted integer x,FudgeFact to
219  * the 4 byte number: exp,mant,mant,mant
220  * Instead of using exp/mant format, we'll just use floats.
221  * Note: If sizeof(float) != sizeof(long), we're hosed.
222  */
RegFg2Float(x,FudgeFact)223 long RegFg2Float(x,FudgeFact)
224 long x;
225 int FudgeFact;
226 {
227     float f;
228     long l;
229     f = x/(float)(1<<FudgeFact);
230     l = float2em(f);
231     return l;
232 }
233 
234 /*
235  * This converts em to shifted integer format.
236  */
RegFloat2Fg(x,Fudge)237 long RegFloat2Fg(x,Fudge)
238 long x;
239 int Fudge;
240 {
241     return em2float(x)*(float)(1<<Fudge);
242 }
243 
RegSftFloat(x,Shift)244 long RegSftFloat(x, Shift)
245 long x;
246 int Shift;
247 {
248     float f;
249     f = em2float(x);
250     if (Shift>0) {
251 	f *= (1 << Shift);
252     } else {
253 	f /= (1 << -Shift);
254     }
255     return float2em(f);
256 }
257