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