2 * Sources of the "FLOATING POINT ARITHMETIC" group instructions
5 /* $Id: do_fpar.c,v 2.6 1994/06/24 10:46:21 ceriel Exp $ */
23 #define MAXDOUBLE DBL_MAX
24 #else /* not __STDC__ */
25 #if defined(vax) || defined(pdp) || defined(__vax) || defined(__pdp)
26 #define MAXDOUBLE 1.701411834604692293e+38
28 #define MAXDOUBLE 1.7976931348623157e+308
30 #endif /* not __STDC__ */
31 #define SMALL (1.0/MAXDOUBLE)
33 PRIVATE double adf(), sbf(), mlf(), dvf();
34 PRIVATE double ttttp();
35 PRIVATE double floor(), fabs();
43 /* ADF w: Floating add (*) */
45 double t = fpop(arg_wf(l));
47 LOG(("@F6 DoADF(%ld)", l));
49 fpush(adf(fpop(l), t), l);
58 /* SBF w: Floating subtract (*) */
60 double t = fpop(arg_wf(l));
62 LOG(("@F6 DoSBF(%ld)", l));
64 fpush(sbf(fpop(l), t), l);
73 /* MLF w: Floating multiply (*) */
75 double t = fpop(arg_wf(l));
77 LOG(("@F6 DoMLF(%ld)", l));
79 fpush(mlf(fpop(l), t), l);
88 /* DVF w: Floating divide (*) */
90 double t = fpop(arg_wf(l));
92 LOG(("@F6 DoDVF(%ld)", l));
94 fpush(dvf(fpop(l), t), l);
103 /* NGF w: Floating negate (*) */
105 double t = fpop(arg_wf(l));
107 LOG(("@F6 DoNGF(%ld)", l));
118 /* FIF w: Floating multiply and split integer and fraction part (*) */
120 double t = fpop(arg_wf(l));
122 LOG(("@F6 DoFIF(%ld)", l));
133 /* FEF w: Split floating number in exponent and fraction part (*) */
135 LOG(("@F6 DoFEF(%ld)", l));
137 fef(fpop(arg_wf(l)), l);
145 /* Service routines */
147 PRIVATE double adf(f1, f2) /* returns f1 + f2 */
150 if (must_test && !(IgnMask&BIT(EFOVFL))) {
151 if (f1 > 0.0 && f2 > 0.0) {
152 if (MAXDOUBLE - f1 < f2) {
157 else if (f1 < 0.0 && f2 < 0.0) {
158 if (-(MAXDOUBLE + f1) > f2) {
167 PRIVATE double sbf(f1, f2) /* returns f1 - f2 */
170 if (must_test && !(IgnMask&BIT(EFOVFL))) {
171 if (f2 < 0.0 && f1 > 0.0) {
172 if (MAXDOUBLE - f1 < -f2) {
177 else if (f2 > 0.0 && f1 < 0.0) {
178 if (f2 - MAXDOUBLE > f1) {
187 PRIVATE double mlf(f1, f2) /* returns f1 * f2 */
190 double ff1 = fabs(f1), ff2 = fabs(f2);
192 if (f1 == 0.0 || f2 == 0.0)
195 if ((ff1 >= 1.0 && ff2 <= 1.0) || (ff2 >= 1.0 && ff1 <= 1.0))
198 if (must_test && !(IgnMask&BIT(EFUNFL))) {
199 if (ff1 < 1.0 && ff2 < 1.0) {
200 if (SMALL / ff1 > ff2) {
208 if (must_test && !(IgnMask&BIT(EFOVFL))) {
209 if (MAXDOUBLE / ff1 < ff2) {
217 PRIVATE double dvf(f1, f2) /* returns f1 / f2 */
220 double ff1 = fabs(f1), ff2 = fabs(f2);
223 if (!(IgnMask&BIT(EFDIVZ))) {
232 if ((ff2 >= 1.0 && ff1 >= 1.0) || (ff1 <= 1.0 && ff2 <= 1.0))
235 if (must_test && !(IgnMask&BIT(EFUNFL))) {
236 if (ff2 > 1.0 && ff1 < 1.0) {
237 if (SMALL / ff2 > ff1) {
245 if (must_test && !(IgnMask&BIT(EFOVFL))) {
246 if (MAXDOUBLE * ff2 < ff1) {
254 PRIVATE fif(f1, f2, n)
258 double f = mlf(f1, f2);
259 double fl = floor(fabs(f));
261 fpush(fabs(f) - fl, n); /* push fraction */
262 fpush((f < 0.0) ? -fl : fl, n); /* push integer-part */
269 register long exponent, sign = (long) (f < 0.0);
277 for (f = fabs(f), exponent = 0; f >= 1.0; exponent++)
280 for (; f < 0.5; exponent--)
283 fpush((sign) ? -f : f, n); /* push mantissa */
284 wpush(exponent); /* push exponent */
287 /* floating point service routines, to avoid having to use -lm */
289 PRIVATE double fabs(f)
292 return (f < 0.0 ? -f : f);
295 PRIVATE double floor(f)
299 register int sign = 1;
301 /* eliminate the sign */
306 /* get the largest power of 2 <= f */
312 /* reconstruct f by deminishing powers of 2 */
320 /* undo the sign elimination */
330 PRIVATE double ttttp(f, n) /* times ten to the power */
344 /* Str2double is used to initialize the global data area with floats;
345 we do not use, e.g., sscanf(), to be able to check the grammar of
346 the string and to give warnings.
349 double str2double(str)
353 register int sign = 1; /* either +1 or -1 */
354 register int frac = 0; /* how far in fraction part ? */
355 register int ex; /* to store exponent */
356 double mantissa = 0.0; /* to store mantissa */
357 double d; /* double to be returned */
369 if ('0' <= b && b <= '9') {
370 mantissa = (double) (b-'0');
373 /* part before dot cannot be empty */
381 LOG((" q9 str2double : (before while) mantissa = %20.20g", mantissa));
383 while ((b = *str++) != 'e' && b != 'E' && b != '\0') {
388 else { /* there already was a '.' in input */
392 else if ('0' <= b && b <= '9') {
393 double bval = b - '0';
397 adf(mantissa, ttttp(bval, -frac));
402 adf(mlf(mantissa, 10.0), bval);
408 LOG((" q9 str2double : (inside while) mantissa = %20.20g",
411 LOG((" q9 str2double : mantissa = %10.10g", mantissa));
412 mantissa = sign * mantissa;
415 /* else we have b == 'e' or b== 'E' */
417 /* Optional sign for exponent */
433 if ('0' <= b && b <= '9') {
434 ex = 10*ex + (b-'0');
439 } while ((b = *str++) != '\0');
440 LOG((" q9 str2double : exponent = %d", ex));
442 /* Construct total value of float */
444 d = ttttp(mantissa, ex);
448 fatal("Float garbled in loadfile");
455 fatal("attempt to execute a floating point instruction on an EM machine without FP");