Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
33
 
34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
42
 
43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
45
 
46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
49
 
50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
53
 
54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/**********************************************************************
62
$Author: release $
63
$Date: 1998/01/17 15:55:47 $
64
$Revision: 1.1.1.1 $
65
$Log: flpt.c,v $
66
 * Revision 1.1.1.1  1998/01/17  15:55:47  release
67
 * First version to be checked into rolling release.
68
 *
69
 * Revision 1.4  1996/01/10  14:58:48  currie
70
 * BIGEND var params chars & shorts
71
 *
72
 * Revision 1.3  1995/09/11  13:58:37  currie
73
 * gcc pedantry
74
 *
75
 * Revision 1.2  1995/08/09  08:59:57  currie
76
 * round bug
77
 *
78
 * Revision 1.1  1995/04/06  10:44:05  currie
79
 * Initial revision
80
 *
81
***********************************************************************/
82
 
83
 
84
 
85
/***********************************************************************
86
                                flpt.c
87
 
88
  Routines for handling the internal floating point representation.
89
 
90
 ***********************************************************************/
91
#include "config.h"
92
#include <limits.h>
93
#include "common_types.h"
94
#include "flpttypes.h"
95
#include "exp.h"
96
#include "xalloc.h"
97
#include "szs_als.h"
98
#include "messages_c.h"
99
#include "basicread.h"
100
#include "installglob.h"
101
 
102
 
103
#include "flpt.h"
104
 
105
/* MACROS */
106
 
107
#define MAX_USEFUL_DECEXP 10000
7 7u83 108
/* plenty big enough for IEEE and VAX */
2 7u83 109
#define initial_flpts 50
110
#define extra_flpts 50
111
 
112
 
113
 
114
/***********************************************************************
115
          ---------- Floating point emulator code ----------
116
 NB - lines which assume the use of an ASCII character set are accompanied
117
      by the comment ASCII
118
 ***********************************************************************/
119
 
120
typedef struct _dbl {
7 7u83 121
  /* Double precision type - used for internal working */
122
  Fdig mant[2 * MANT_SIZE];
123
  int  sign;
2 7u83 124
  int  exp;
7 7u83 125
} dbl;
2 7u83 126
 
127
/* The current rounding rule. This may be one of the following :
128
     R2ZERO - round towards zero.
129
     R2PINF - round towards positive infinity.
130
     R2NINF - round towards negative infinity.
131
     R2NEAR - round to nearest integer.
132
 It should be set using the "set_round" function.
133
*/
134
 
135
/* IDENTITIES */
136
 
7 7u83 137
static Fdig bitround[16] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
2 7u83 138
			     0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000,
139
			     0x4000, 0x8000};
7 7u83 140
static Fdig bitmask[17] = {0xffff, 0xfffe, 0xfffc, 0xfff8,
2 7u83 141
			    0xfff0, 0xffe0, 0xffc0, 0xff80,
142
			    0xff00, 0xfe00, 0xfc00, 0xf800,
143
			    0xf000, 0xe000, 0xc000, 0x8000, 0x0};
144
 
145
static flt powers[16] = {
146
	{{10, 0, 0, 0, 0, 0, 0, 0},1, 0},
147
	{{100, 0, 0, 0, 0, 0, 0, 0},1, 0},
148
	{{1000, 0, 0, 0, 0, 0, 0, 0},1, 0},
149
	{{10000, 0, 0, 0, 0, 0, 0, 0},1, 0},
150
	{{1, 34464, 0, 0, 0, 0, 0, 0},1, 1},
151
	{{15, 16960, 0, 0, 0, 0, 0, 0},1, 1},
152
	{{152, 38528, 0, 0, 0, 0, 0, 0},1, 1},
153
	{{1525, 57600, 0, 0, 0, 0, 0, 0},1, 1},
154
	{{15258, 51712, 0, 0, 0, 0, 0, 0},1, 1},
155
	{{2, 21515, 58368, 0, 0, 0, 0, 0},1, 2},
156
	{{23, 18550, 59392, 0, 0, 0, 0, 0},1, 2},
157
	{{232, 54437, 4096, 0, 0, 0, 0, 0},1, 2},
158
	{{2328, 20082, 40960, 0, 0, 0, 0, 0},1, 2},
159
	{{23283, 4218, 16384, 0, 0, 0, 0, 0},1, 2},
160
	{{3, 36222, 42182, 32768, 0, 0, 0, 0},1, 3},
161
	{{35, 34546, 28609, 0, 0, 0, 0, 0},1, 3}
162
};
163
 
164
static int two_powers[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
165
			    2048, 4096, 8192, 16384, 32768};
7 7u83 166
static int round_type = R2NEAR;
2 7u83 167
 
168
/* VARIABLES */
169
/* All variables initialised */
170
 
7 7u83 171
int tot_flpts;		/* total number of floating point numbers */
172
int flptfree;		/* floating point free list */
173
int flpt_left;		/* number of floating point numbers left */
2 7u83 174
 
7 7u83 175
flt *flptnos;		/* the extendable array of floating point numbers */
2 7u83 176
 
177
int fzero_no;
178
int fone_no;
179
 
180
 
181
/* PROCEDURES */
182
 
7 7u83 183
flpt new_flpt(void);
2 7u83 184
 
185
/* ----- internal functions ----- */
186
 
187
 
7 7u83 188
/* "f1" and "f2" are two legal single precision numbers. The result is -1, 0 or
189
 * +1 depending on whether the magnitude of "f1" is less than, equal to or
190
 * greater than that of "f2" */
191
 
192
static int
193
mag_cmp(flt f1, flt f2)
2 7u83 194
{
7 7u83 195
  int i;
2 7u83 196
  if (f1.sign == 0) {
197
    if (f2.sign == 0) {
7 7u83 198
      return(0);
2 7u83 199
    }
7 7u83 200
    return(-1);
2 7u83 201
  }
202
  if (f2.sign == 0) {
7 7u83 203
    return(1);
2 7u83 204
  }
205
  if (f1.exp != f2.exp) {
7 7u83 206
    return((f1.exp < f2.exp) ? -1 : 1);
2 7u83 207
  }
208
  for (i = 0; i < MANT_SIZE; i++) {
209
    if ((f1.mant[i]) != (f2.mant[i])) {
7 7u83 210
      return(((f1.mant[i]) < (f2.mant[i])) ? -1 : 1);
2 7u83 211
    }
212
  }
7 7u83 213
  return(0);
2 7u83 214
}
215
 
216
 
7 7u83 217
/* "d1" and "d2" are two legal double precision numbers. The result is -1, 0 or
218
 * +1 depending on whether the magnitude of "d1" is less than, equal to or
219
 * greater than that of "d2" */
220
 
221
static int
222
dbl_mag_cmp (dbl d1, dbl d2)
2 7u83 223
{
7 7u83 224
  int i;
2 7u83 225
  if (d1.sign == 0) {
226
    if (d2.sign == 0) {
7 7u83 227
      return(0);
2 7u83 228
    }
7 7u83 229
    return(-1);
2 7u83 230
  }
231
  if (d2.sign == 0) {
7 7u83 232
    return(1);
2 7u83 233
  }
234
  if (d1.exp != d2.exp) {
7 7u83 235
    return((d1.exp < d2.exp) ? -1 : 1);
2 7u83 236
  }
237
  for (i = 0; i < (2 * MANT_SIZE); i++) {
238
    if ((d1.mant[i]) != (d2.mant[i])) {
7 7u83 239
      return(((d1.mant[i]) < (d2.mant[i]))? -1 : 1);
2 7u83 240
    }
241
  }
7 7u83 242
  return(0);
2 7u83 243
}
244
 
245
 
7 7u83 246
/* "f" is a pointer to a legal single precision number. "c" is a character
247
 * value from 0 to FBASE-1. On return, the single precision number pointed to
248
 * by "f" will have been modified as if "c" were the digit following the least
249
 * significant digit of the number pointed to by "f" and the number has been
250
 * rounded according to the current rounding rule */
251
static void
252
flt_int_round(flt *f, unsigned int ic)
2 7u83 253
{
7 7u83 254
  int i;
2 7u83 255
  switch (round_type) {
7 7u83 256
  default:
257
  case R2ZERO:
258
    return;
259
  case R2PINF:
260
    if (((f->sign) != 1) || (ic == 0))
2 7u83 261
      return;
7 7u83 262
    break;
263
  case R2NINF:
264
    if (((f->sign) != -1) || (ic == 0))
265
      return;
266
    break;
267
  case R2NEAR:
268
    if (ic < (unsigned int)(FBASE / 2)) {
269
      return;
270
    }
271
    break;
2 7u83 272
  }
273
  ic = 1;
274
  for (i = (MANT_SIZE - 1); i >= 0; i--) {
7 7u83 275
    (f->mant)[i] = (unsigned short)((ic += (unsigned int)((f->mant)[i])) % FBASE);
276
    /* CAST:jmf: unsigned short since FBASE <= MAX_USHORT+1 */
2 7u83 277
    if ((ic /= FBASE) == 0) {
278
      return;
279
    }
280
  }
7 7u83 281
  (f->exp)++;
282
  (f->mant)[0] = 1;
2 7u83 283
  for (i = 1; i < MANT_SIZE; i++) {
7 7u83 284
    (f->mant)[i] = 0;
2 7u83 285
  }
286
}
287
 
288
 
7 7u83 289
/* "d" is a legal double precision number.  "f" is a pointer to a single
290
 * precision number. On return, the number pointed to by "f" contains the value
291
 * of "d" but to less precision. The current rounding rule is used to truncate
292
 * the mantissa */
293
static void
294
dbl2float(dbl d, flt *f)
2 7u83 295
{
7 7u83 296
  int i;
297
  (f->sign) = d.sign;
298
  (f->exp) = d.exp;
2 7u83 299
  for (i = 0; i < MANT_SIZE; i++) {
7 7u83 300
    (f->mant)[i] = d.mant[i];
2 7u83 301
  }
7 7u83 302
  flt_int_round(f, (unsigned int)d.mant[MANT_SIZE]);
2 7u83 303
}
304
 
305
 
7 7u83 306
/* "f" is a legal single precision number.  "d" is a pointer to a double
307
 * precision number. On return, the number pointed to by "d" will contain the
308
 * value of "f" */
309
 
310
static void
311
flt2double(flt f, dbl *d)
2 7u83 312
{
7 7u83 313
  int i;
314
  (d->sign) = f.sign;
315
  (d->exp) = f.exp;
2 7u83 316
  for (i = 0; i < MANT_SIZE; i++) {
7 7u83 317
    (d->mant)[i] = f.mant[i];
2 7u83 318
  }
319
  for (i = MANT_SIZE; i < (2 * MANT_SIZE); i++) {
7 7u83 320
    (d->mant)[i] = 0;
2 7u83 321
  }
322
}
323
 
324
 
7 7u83 325
/* "d" is a pointer to a legal double precision number. "dist" is a int with
326
 * value greater than zero. On return, the number pointed to by "d" keeps the
327
 * same value ( although some loss of precision may occur ) but is no longer in
328
 * normalised form. The mantissa is shifted right "dist" places, and the
329
 * exponent is adjusted to keep the value the same */
330
 
331
static void
332
shift_right(dbl *d, int dist)
2 7u83 333
{
7 7u83 334
  int i;
335
  int j = (2 * MANT_SIZE) - 1 - dist;
2 7u83 336
  for (i = (2 * MANT_SIZE) - 1; i >= 0; i--, j--) {
7 7u83 337
    (d->mant)[i] = (unsigned short)((j >= 0) ? ((d->mant)[j]) : 0);
2 7u83 338
  }
7 7u83 339
  (d->exp) += dist;
2 7u83 340
}
341
 
342
 
7 7u83 343
/* "d1" and "d2" are double precision numbers, with the same exponent and
344
 * opposite (non-zero) signs. "res" is a pointer to a single precision number,
345
 * whose exponent has been set to the same value as "d1" and "d2". On return,
346
 * the number pointed to by "res" is the result of adding "d1" to "d2" and
347
 * rounding it by the current rounding rule. The return value is either OKAY or
348
 * EXP2BIG ( in which case the value of the number pointed to by "res" is
349
 * undefined ) */
350
static int
351
sub_mantissas(dbl d1, dbl d2, flt *res)
2 7u83 352
{
7 7u83 353
  dbl *dp1 = &d1, *dp2 = &d2, rdbl;
2 7u83 354
  unsigned int  c = 0;
7 7u83 355
  int i, cmp = dbl_mag_cmp(d1, d2);
2 7u83 356
  if (cmp == 0) {
7 7u83 357
    (res->sign) = 0;
358
    (res->exp) = 0;
2 7u83 359
    for (i = 0; i < MANT_SIZE; i++) {
7 7u83 360
      (res->mant)[i] = 0;
2 7u83 361
    }
7 7u83 362
    return(OKAY);
363
  } else if (cmp == -1) {
364
    dp1 = &d2;
365
    dp2 = &d1;
2 7u83 366
  }
7 7u83 367
  rdbl.exp = (res->exp);
2 7u83 368
  for (i = (2 * MANT_SIZE) - 1; i >= 0; i--) {
7 7u83 369
    int s = (int)(((dp1->mant)[i]) - ((dp2->mant)[i]) - c);
2 7u83 370
    c = 0;
371
    if (s < 0) {
372
      c = 1;
373
      s += FBASE;
374
    }
375
    rdbl.mant[i] = (unsigned short)s;	/* CAST:jmf: */
376
  }
7 7u83 377
  rdbl.sign = (dp1->sign);
2 7u83 378
  while ((rdbl.mant[0]) == 0) {
379
    for (i = 1; i < (2 * MANT_SIZE); i++) {
380
      rdbl.mant[i - 1] = rdbl.mant[i];
381
    }
382
    rdbl.mant[(2 * MANT_SIZE) - 1] = 0;
383
    if ((--rdbl.exp) < E_MIN) {
7 7u83 384
      return(EXP2BIG);
2 7u83 385
    }
386
  }
7 7u83 387
  dbl2float(rdbl, res);
388
  return(OKAY);
2 7u83 389
}
390
 
391
 
7 7u83 392
/* "d1" and "d2" are double precision numbers, with the same exponent and
393
 * non-zero signs. "res" is a pointer to a single precision number which has
394
 * the same exponent as "d1" and "d2". On return, the number pointed to by
395
 * "res" will be the result of adding "d1" to "d2" and rounding it according to
396
 * the current rounding rule. The return value will be either OKAY or EXP2BIG (
397
 * in which case the value of the number pointed to by "res" is undefined ) */
398
static int
399
add_mantissas(dbl d1, dbl d2, flt * res)
2 7u83 400
{
7 7u83 401
  int i;
402
  unsigned int c;
2 7u83 403
  if (d1.sign == d2.sign) {
404
    dbl rdbl;
7 7u83 405
    (res->sign) = d1.sign;
406
    flt2double(*res, &rdbl);
2 7u83 407
    c = 0;
408
    for (i = (2 * MANT_SIZE) - 1; i >= 0; i--) {
409
      c += (unsigned int)(d1.mant[i] + d2.mant[i]);
410
      rdbl.mant[i] = (unsigned short)(c % FBASE);	/* CAST:jmf: */
411
      c /= FBASE;
412
    }
413
    if (c) {
414
      for (i = (2 * MANT_SIZE) - 1; i > 0; i--) {
415
	rdbl.mant[i] = rdbl.mant[i - 1];
416
      }
417
      rdbl.mant[0] = (unsigned short)c;	/* CAST:jmf: */
7 7u83 418
      if (((++rdbl.exp) >= E_MAX) || (rdbl.exp <= E_MIN)) {
419
	return(EXP2BIG);
2 7u83 420
      }
421
    }
7 7u83 422
    dbl2float(rdbl, res);
423
    return(OKAY);
2 7u83 424
  }
7 7u83 425
  return(sub_mantissas(d1, d2, res));
2 7u83 426
}
427
 
428
 
429
/* ----- "public" emulator functions ----- */
430
 
7 7u83 431
/* "f" is a pointer to a single precision number. On return, the number pointed
432
 * to by "f" will have the value zero */
433
void
434
flt_zero(flt *f)
2 7u83 435
{
7 7u83 436
  int i;
437
  (f->sign) = 0;
438
  (f->exp) = 0;
2 7u83 439
  for (i = 0; i < MANT_SIZE; i++) {
7 7u83 440
    (f->mant)[i] = 0;
2 7u83 441
  }
442
}
443
 
444
 
7 7u83 445
/* "f" is a legal single precision number.  "res" is a pointer to a single
446
 * precision number. On return, the number pointed to by "res" is the same as
447
 * "f" */
448
void
449
flt_copy(flt f, flt *res)
2 7u83 450
{
7 7u83 451
  int i;
452
  (res->sign) = f.sign;
453
  (res->exp) = f.exp;
2 7u83 454
  for (i = 0; i < MANT_SIZE; i++) {
7 7u83 455
    (res->mant)[i] = f.mant[i];
2 7u83 456
  }
457
  return;
458
}
459
 
460
 
7 7u83 461
/* "f1" and "f2" are legal single precision numbers. "res" is a pointer to a
462
 * single precision number. On return, if the result is OKAY, then the number
463
 * pointed to by "res" will contain the value of adding "f1" to "f2". If the
464
 * result is EXP2BIG, then the value of the number pointed to by "res" is
465
 * undefined */
466
int
467
flt_add(flt f1, flt f2, flt *res)
2 7u83 468
{
469
  dbl d1, d2;
470
  if (f1.sign == 0) {
7 7u83 471
    flt_copy(f2, res);
472
    return(OKAY);
473
  } else if (f2.sign == 0) {
474
    flt_copy(f1, res);
475
    return(OKAY);
2 7u83 476
  }
7 7u83 477
  flt2double(f1, &d1);
478
  flt2double(f2, &d2);
2 7u83 479
  if (d1.exp < d2.exp) {
7 7u83 480
    shift_right(&d1, d2.exp - d1.exp);
481
  } else if (d1.exp > d2.exp) {
482
    shift_right(&d2, d1.exp - d2.exp);
2 7u83 483
  }
7 7u83 484
  (res->exp) = d1.exp;
485
  return(add_mantissas(d1, d2, res));
2 7u83 486
}
487
 
488
 
7 7u83 489
/* "f1" and "f2" are legal single precision numbers. "res" is a pointer to a
490
 * single precision number. On return, if the result is OKAY, then the number
491
 * pointed to by "res" will contain the value of subtracting "f2" from "f1". If
492
 * the result is EXP2BIG, then the value of the number pointed to by "res" is
493
 * undefined */
494
int
495
flt_sub(flt f1, flt f2, flt *res)
2 7u83 496
{
497
  f2.sign = -f2.sign;
7 7u83 498
  return(flt_add(f1, f2, res));
2 7u83 499
}
500
 
7 7u83 501
 
2 7u83 502
#if FBASE == 10
503
 
7 7u83 504
/* "f1" and "f2" are legal single precision numbers. "res" is a pointer to a
505
 * single precision number. On return, if the result is OKAY, then the number
506
 * pointed to by "res" will contain the value of multiplying "f1" by "f2".  If
507
 * the result is EXP2BIG, then the value of the number pointed to by "res" is
508
 * undefined */
509
int
510
flt_mul(flt f1, flt f2, flt *res)
2 7u83 511
{
512
  dbl rdbl;
7 7u83 513
  int i, j;
2 7u83 514
  unsigned int c = 0;
515
  unsigned int acc[2 * MANT_SIZE];
516
  if ((f1.sign == 0) || (f2.sign == 0)) {
7 7u83 517
    flt_zero(res);
518
    return(OKAY);
2 7u83 519
  }
7 7u83 520
  rdbl.sign = ((f1.sign == f2.sign)? 1 : -1);
2 7u83 521
  rdbl.exp = (f1.exp + f2.exp + 1);
7 7u83 522
  if ((rdbl.exp >= E_MAX) || (rdbl.exp <= E_MIN)) {
523
    return(EXP2BIG);
2 7u83 524
  }
525
  for (i = 0; i < (2 * MANT_SIZE); i++) {
526
    acc[i] = 0;
527
  }
528
  for (i = MANT_SIZE - 1; i >= 0; i--) {
529
    for (j = MANT_SIZE - 1; j >= 0; j--) {
530
      acc[i + j + 1] += (f1.mant[i] * f2.mant[j]);
531
    }
532
  }
533
  for (i = (2 * MANT_SIZE) - 1; i >= 0; i--) {
534
    c += acc[i];
535
    rdbl.mant[i] = (c % FBASE);
536
    c /= FBASE;
537
  }
538
  while (rdbl.mant[0] == 0) {
539
    for (i = 1; i < (2 * MANT_SIZE); i++) {
540
      rdbl.mant[i - 1] = rdbl.mant[i];
541
    }
542
    rdbl.mant[(2 * MANT_SIZE) - 1] = 0;
543
    if ((--rdbl.exp) <= E_MIN) {
7 7u83 544
      return(EXP2BIG);
2 7u83 545
    }
546
  }
7 7u83 547
  dbl2float(rdbl, res);
548
  return(OKAY);
2 7u83 549
}
550
#else
7 7u83 551
/* "f1" and "f2" are legal single precision numbers. "res" is a pointer to a
552
 * single precision number. On return, if the result is OKAY, then the number
553
 * pointed to by "res" will contain the value of multiplying "f1" by "f2".  If
554
 * the result is EXP2BIG, then the value of the number pointed to by "res" is
555
 * undefined */
556
 
557
int
558
flt_mul(flt f1, flt f2, flt *res)
2 7u83 559
{
560
  dbl rdbl;
7 7u83 561
  int i, j, k;
2 7u83 562
  unsigned int acc[2 * MANT_SIZE];
563
  if ((f1.sign == 0) || (f2.sign == 0)) {
7 7u83 564
    flt_zero(res);
565
    return(OKAY);
2 7u83 566
  }
7 7u83 567
  rdbl.sign = ((f1.sign == f2.sign)? 1 : -1);
2 7u83 568
  rdbl.exp = (f1.exp + f2.exp + 1);
7 7u83 569
  if ((rdbl.exp >= E_MAX) || (rdbl.exp <= E_MIN)) {
570
    return(EXP2BIG);
2 7u83 571
  }
572
  for (i = 0; i < (2 * MANT_SIZE); i++) {
573
    acc[i] = 0;
574
  }
575
  SET(acc);
576
 
577
  for (i = MANT_SIZE - 1; i >= 0; i--) {
578
    for (j = MANT_SIZE - 1; j >= 0; j--) {
579
      unsigned int temp = (unsigned int)(f1.mant[i] * f2.mant[j]);
580
      unsigned int atl;
581
      for (k = i + j + 1; temp != 0; --k) {
582
	atl = acc[k] + (temp & 0xffff);
583
	acc[k] = atl & 0xffff;
584
	temp = (atl >> 16) + (temp >> 16);
7 7u83 585
      }
586
    }
587
  }
2 7u83 588
 
589
  for (i = (2 * MANT_SIZE) - 1; i >= 0; i--) {
590
    rdbl.mant[i] = (unsigned short)(acc[i]);	/* CAST:jmf: */
7 7u83 591
  }
2 7u83 592
 
593
  while (rdbl.mant[0] == 0) {
594
    for (i = 1; i < (2 * MANT_SIZE); i++) {
595
      rdbl.mant[i - 1] = rdbl.mant[i];
596
    }
597
    rdbl.mant[(2 * MANT_SIZE) - 1] = 0;
598
    if ((--rdbl.exp) <= E_MIN) {
7 7u83 599
      return(EXP2BIG);
2 7u83 600
    }
7 7u83 601
  }
2 7u83 602
 
7 7u83 603
  dbl2float(rdbl, res);
604
  return(OKAY);
2 7u83 605
}
606
#endif
607
 
7 7u83 608
 
2 7u83 609
#if FBASE == 10
610
 
7 7u83 611
/* "f1" and "f2" are legal single precision numbers, and "f2" is non-zero.
612
 * "res" is a pointer to a single precision number. On return, if the result is
613
 * OKAY, then the number pointed to by "res" contains the result of dividing
614
 * "f1" by "f2". If the result is EXP2BIG or DIVBY0 then the contents of the
615
 * number pointed to by "res" are undefined */
616
int
617
flt_div(flt f1, flt f2, flt *res)
2 7u83 618
{
619
  dbl rdbl;
7 7u83 620
  int i = 0;
2 7u83 621
  flt f3;
622
  if (f2.sign == 0) {
7 7u83 623
    return(DIVBY0);
2 7u83 624
  }
625
  if (f1.sign == 0) {
7 7u83 626
    flt_zero(res);
627
    return(OKAY);
2 7u83 628
  }
629
  rdbl.sign = ((f1.sign == f2.sign) ? 1 : -1);
630
  rdbl.exp = (f1.exp - f2.exp);
7 7u83 631
  if ((rdbl.exp >= E_MAX) || (rdbl.exp <= E_MIN)) {
632
    return(EXP2BIG);
2 7u83 633
  }
634
  f1.sign = 1;
635
  f2.sign = 1;
636
  f1.exp = 0;
637
  f2.exp = 0;
7 7u83 638
  flt_copy(f1, &f3);
2 7u83 639
  while (i < (2 * MANT_SIZE)) {
7 7u83 640
    int count = -1;
2 7u83 641
    while (f3.sign != -1) {
7 7u83 642
      if (flt_sub(f3, f2, &f3) != OKAY) {
643
	return(EXP2BIG);
2 7u83 644
      }
645
      count++;
646
    }
7 7u83 647
    if (flt_add(f3, f2, &f3) != OKAY) {
648
      return(EXP2BIG);
2 7u83 649
    }
650
    rdbl.mant[i++] = count;
651
    if (f3.sign == 0) {
652
      break;
653
    }
654
    if ((--f2.exp) <= E_MIN) {
7 7u83 655
      return(EXP2BIG);
2 7u83 656
    }
657
  }
658
  while (i < (2 * MANT_SIZE)) {
659
    rdbl.mant[i++] = 0;
660
  }
661
  while (rdbl.mant[0] == 0) {
662
    for (i = 1; i < (2 * MANT_SIZE); i++) {
663
      rdbl.mant[i - 1] = rdbl.mant[i];
664
    }
665
    rdbl.mant[(2 * MANT_SIZE) - 1] = 0;
666
    if ((--rdbl.exp) <= E_MIN) {
7 7u83 667
      return(EXP2BIG);
2 7u83 668
    }
669
  }
7 7u83 670
  dbl2float(rdbl, res);
671
  return(OKAY);
2 7u83 672
}
673
 
674
#else
675
 
7 7u83 676
int
677
flt_div(flt f1, flt f2, flt *res)
2 7u83 678
{
679
  Fdig a1[MANT_SIZE+1];
680
  Fdig a2[MANT_SIZE+1];
681
  Fdig r[MANT_SIZE+1];
682
  int bit_diff = 0;
683
  int i;
684
  int t, s;
685
  unsigned int c = 0;
686
  int bit, bitpos;
687
  int sg;
688
  int keep_on;
689
  int final_expt = f1.exp - f2.exp;
690
  int final_shift = 0;
691
  unsigned int k;
692
 
693
  if (f2.sign == 0) {
7 7u83 694
    return(DIVBY0);
695
  }
2 7u83 696
 
697
  if (f1.sign == 0) {
7 7u83 698
    flt_zero(res);
699
    return(OKAY);
700
  }
2 7u83 701
 
702
  for (i = 0; i < MANT_SIZE; ++i) {
703
    a1[i] = f1.mant[i];
704
    a2[i] = f2.mant[i];
705
    r[i] = 0;
7 7u83 706
  }
2 7u83 707
  a1[MANT_SIZE] = 0;
708
  a2[MANT_SIZE] = 0;
709
  r[MANT_SIZE] = 0;
710
 
7 7u83 711
  /* Shift first digit of a1 or a2 right until a1[0] < a2[0] and a1[0] >=
712
   * 2*a2[0] Count the places in bit_diff.  */
2 7u83 713
  t = (int)(a1[0]);
714
  s = (int)(a2[0]);
715
  if (t >= s) {
7 7u83 716
    for (; t >= s; ++bit_diff) {
717
      t >>= 1;
718
    }
719
  } else {
720
    for (; t < s; --bit_diff) {
721
      s >>= 1;
722
    }
723
    ++bit_diff;
2 7u83 724
  }
725
 
726
 
7 7u83 727
  /* Shift a1 bit_diff places right if bit_diff positive.
728
     Shift a2 -bit_diff places right if bit_diff negative.
729
   */
2 7u83 730
  if (bit_diff > 0) {
7 7u83 731
    for (i = 0; i < (MANT_SIZE + 1); ++i) {
2 7u83 732
      c = (unsigned int)(a1[i] + (c << 16));
733
      a1[i] = (unsigned short)(c >> bit_diff);	/* CAST:jmf: */
7 7u83 734
      c &= (unsigned int)((1 << (bit_diff + 1)) -1);
735
    }
736
  } else if (bit_diff < 0) {
737
    for (i = 0; i < (MANT_SIZE + 1); ++i) {
2 7u83 738
      c = (unsigned int)(a2[i] + (c << 16));
739
      a2[i] = (unsigned short)(c >> -bit_diff);	/* CAST:jmf: */
7 7u83 740
      c &= (unsigned int)((1 << (-bit_diff + 1)) -1);
741
    }
742
  }
2 7u83 743
 
7 7u83 744
  /* do the division */
2 7u83 745
  bit = 0;	/* current bit of result */
746
  bitpos = 0;	/* current digit of result */
747
  sg = 1;	/* 1 means subtract, 0 means add */
748
  keep_on = 1;
749
  while (keep_on) {
750
    c = 0;
7 7u83 751
    /* subtract or add */
2 7u83 752
    if (sg) {
753
      for (i = MANT_SIZE; i >= 0; --i) {
754
	c = (unsigned int)(a1[i] - a2[i] + c);
755
	a1[i] = (unsigned short)(c & 0xffff);	/* CAST:jmf: */
7 7u83 756
	if (c & 0x10000) {
2 7u83 757
	  c = (unsigned int)(-1);
7 7u83 758
	} else {
2 7u83 759
	  c = 0;
7 7u83 760
	}
761
      }
762
      sg = (c)? 0 : 1;
763
    } else {
2 7u83 764
      for (i = MANT_SIZE; i >= 0; --i) {
765
	c = (unsigned int)(a1[i] + a2[i] + c);
766
	a1[i] = (unsigned short)(c & 0xffff);	/* CAST:jmf: */
7 7u83 767
	if (c & 0x10000) {
2 7u83 768
	  c = 1;
7 7u83 769
	} else {
2 7u83 770
	  c = 0;
7 7u83 771
	}
772
      }
773
      sg = (c)? 1 : 0;
774
    }
2 7u83 775
    if (sg) {
776
      r[bitpos] = (unsigned short)((int)r[bitpos] | (1 << bit));
7 7u83 777
      /* CAST:jmf: */
778
    }
2 7u83 779
    if (bit == 0) {
780
      bit = 15;
781
      ++bitpos;
7 7u83 782
    } else {
783
      --bit;
2 7u83 784
    }
785
    keep_on = 0;
7 7u83 786
    /* shift f2 right one place, if zero keep_on = 0 */
2 7u83 787
    c = 0;
7 7u83 788
    for (i = 0; i < (MANT_SIZE + 1); ++i) {
2 7u83 789
      c = (unsigned int)(a2[i] + (c << 16));
7 7u83 790
      if (c) {
2 7u83 791
	keep_on = 1;
7 7u83 792
      }
2 7u83 793
      a2[i] = (unsigned short)(c >> 1);	/* CAST:jmf: */
794
      c &= 1;
7 7u83 795
    }
796
  }
2 7u83 797
 
7 7u83 798
  /* correct line-up of r */
2 7u83 799
  if (bit_diff > 0) {
800
    final_shift = bit_diff;
7 7u83 801
  } else {
2 7u83 802
    --final_expt;
7 7u83 803
    if (bit_diff > -16) {
2 7u83 804
      final_shift = 16 + bit_diff;
7 7u83 805
    }
806
  }
2 7u83 807
  k = (unsigned int)((((int)r[MANT_SIZE] << final_shift) & 0x8000) >> 15);
7 7u83 808
  /* (int) coercion OK because r is shorter */
2 7u83 809
  k = (unsigned int)(k + (r[MANT_SIZE] >> (16 - final_shift)));
810
  for (i = MANT_SIZE-1; i >= 0; --i) {
811
    k = (unsigned int)((r[i] << final_shift) + k);
812
    res ->mant[i] = (unsigned short)(k & 0xffff);;	/* CAST:jmf: */
813
    k >>= 16;
7 7u83 814
  }
2 7u83 815
 
816
  if (res->mant[0] == 0) {
7 7u83 817
    for (i = 0; i < MANT_SIZE - 1; ++i) {
818
      res->mant[i] = res->mant[i + 1];
819
    }
820
    res->mant[MANT_SIZE - 1] = 0;
2 7u83 821
    --final_expt;
7 7u83 822
  }
2 7u83 823
 
7 7u83 824
  res->exp = final_expt;
825
  res->sign = (f1.sign == f2.sign) ? 1 : -1;
2 7u83 826
  return OKAY;
827
}
828
 
829
#endif
830
 
7 7u83 831
/* "f1" and "f2" are legal single precision numbers. The return value will be
832
 * -1, 0 or 1 depending whether "f1" is less than, equal to or greater than
833
 * "f2" */
834
int
835
flt_cmp(flt f1, flt f2)
2 7u83 836
{
7 7u83 837
  int ret;
2 7u83 838
  if (f1.sign < f2.sign) {
7 7u83 839
    return(-1);
2 7u83 840
  }
841
  if (f1.sign > f2.sign) {
7 7u83 842
    return(1);
2 7u83 843
  }
7 7u83 844
  ret = mag_cmp(f1, f2);
845
  return((f1.sign == -1) ? -ret : ret);
2 7u83 846
}
847
 
848
 
7 7u83 849
/* "f" is a legal single precision number.  "res" is a pointer to a single
850
 * precision number. On return, the number pointed to by "res" will be the
851
 * integer value of "f" rounded using the current rounding rule */
852
void
853
flt_round(flt f, flt *res)
2 7u83 854
{
7 7u83 855
  int i;
856
  unsigned int ex;
2 7u83 857
  if (f.exp < -1) {
7 7u83 858
    flt_zero(res);
2 7u83 859
    return;
860
  }
7 7u83 861
  flt_copy(f, res);
2 7u83 862
  if ((f.exp + 1) >= MANT_SIZE) {
863
    return;
864
  }
7 7u83 865
  ex = ((res->mant)[f.exp + 1]);
2 7u83 866
  for (i = f.exp + 1; i < MANT_SIZE; i++) {
7 7u83 867
    (res->mant)[i] = 0;
2 7u83 868
  }
869
  if (f.exp == -1) {
7 7u83 870
    (res->sign) = 0;
871
    (res->exp) = 0;
2 7u83 872
  }
873
  switch (round_type) {
7 7u83 874
  default:
875
  case R2ZERO:
876
    return;
877
  case R2PINF:
878
    if ((f.sign != 1) || (ex == 0)) {
2 7u83 879
      return;
7 7u83 880
    }
881
    break;
882
  case R2NINF:
883
    if ((f.sign != -1) || (ex == 0)) {
884
      return;
885
    }
886
    break;
887
  case R2NEAR:
888
    if (ex < (unsigned int)(FBASE/2)) {
889
      return;
890
    }
891
    break;
2 7u83 892
  }
893
  ex = 1;
894
  for (i = f.exp; i >= 0; i--) {
7 7u83 895
    (res->mant)[i] =
896
	(unsigned short)((ex = ex + (unsigned int)((res->mant)[i])) % FBASE);
897
    /* CAST:jmf */
2 7u83 898
    if ((ex /= FBASE) == 0) {
899
      return;
900
    }
901
  }
902
  if (f.exp != -1) {
7 7u83 903
    (res->exp) ++;
904
  } else {
905
    (res->sign) = f.sign;
2 7u83 906
  }
7 7u83 907
  (res->mant)[0] = 1;
2 7u83 908
  for (i = 1; i < MANT_SIZE; i++) {
7 7u83 909
    (res->mant)[i] = 0;
2 7u83 910
  }
911
}
912
 
913
 
7 7u83 914
/* "f" is a legal single precision number.  "res" is a pointer to a single
915
 * precision number. On return, the number pointed to by "res" will be the
916
 * integer value of "f" rounded towards zero */
917
void
918
flt_trunc(flt f, flt *res)
2 7u83 919
{
7 7u83 920
  int i;
2 7u83 921
  if (f.exp < 0) {
7 7u83 922
    flt_zero(res);
2 7u83 923
    return;
924
  }
7 7u83 925
  flt_copy(f, res);
2 7u83 926
  for (i = f.exp + 1; i < MANT_SIZE; i++) {
7 7u83 927
   (res->mant)[i] = 0;
2 7u83 928
  }
929
}
930
 
931
 
7 7u83 932
/* "s" is a pointer to an array of characters.  "f" is a pointer to a single
933
 * precision number.  "ret" is NULL, or a pointer to a pointer to a character.
934
 * On return, if the return value is OKAY, then the number pointed to by "f" is
935
 * the floating point number represented in the string "s". If "ret" was not
936
 * NULL, then it will point to a pointer to the next character in "s" not used
937
 * in the number. If the return value is SYNTAX or EXP2BIG, then the value of
938
 * the number pointed to by "f" is undefined. In this case, if "ret" was not
939
 * NULL, then it will point to a pointer to the start of the string.  Leading
940
 * white space in the string will be ignored. Numbers have the following form :
941
 * [+-]?(([0-9]+(\.[0-9]*)?)|([0-9]*\.[0-9]+))([Ee][+-]?[0-9]+)?
2 7u83 942
*/
943
 
944
#if FBASE == 10
945
 
7 7u83 946
int
947
str2flt(char *s, flt *f, char **r)
2 7u83 948
{
7 7u83 949
  int i = 0, ids = -1, rounded = 0, mant_empty = 1, zero = 1;
950
  (f->sign) = 1;
951
  (f->exp) = 0;
2 7u83 952
  if (r) {
953
    *r = s;
954
  }
955
  while ((*s) && (' ' == (*s))) {
956
    s++;
957
  }
958
  if (*s == '-') {
7 7u83 959
    (f->sign) = -1;
2 7u83 960
    s++;
7 7u83 961
  } else if (*s == '+') {
962
    s++;
2 7u83 963
  }
964
  while (*s == '0') {
965
    mant_empty = 0;
966
    s++;
967
  }
968
  while (*s >= '0' && *s <= '9') {
969
    mant_empty = 0;
970
    zero = 0;
971
    if (i < MANT_SIZE) {
7 7u83 972
      (f->mant)[i++] = ((*s) - '0');/* ASCII */
973
    } else if (!rounded) {
974
      flt_int_round(f,(*s) - '0');
975
      rounded = 1;		/* ASCII */
2 7u83 976
    }
977
    if (ids >= E_MAX) {
7 7u83 978
      return(EXP2BIG);
2 7u83 979
    }
980
    ids++;
981
    s++;
982
  }
983
  if (*s == '.') {
984
    s++;
985
    if (zero) {
986
      while (*s == '0') {
987
	if (ids <= E_MIN) {
7 7u83 988
	  return(EXP2BIG);
2 7u83 989
	}
990
	ids--;
991
	s++;
992
	mant_empty = 0;
993
      }
994
    }
995
    while (*s >= '0' && *s <= '9') {
996
      if (i < MANT_SIZE) {
7 7u83 997
	(f->mant)[i++] = ((*s) - '0');/* ASCII */
998
      } else if (!rounded) {
999
	flt_int_round(f,(*s) - '0');
1000
	rounded = 1;		/* ASCII */
2 7u83 1001
      }
1002
      s++;
1003
      zero = 0;
1004
      mant_empty = 0;
1005
    }
1006
  }
1007
  while (i < MANT_SIZE) {
7 7u83 1008
    (f->mant)[i++] = 0;
2 7u83 1009
  }
1010
  if ((*s == 'E') || (*s == 'e')) {
7 7u83 1011
    int e_sign = 1, exp_empty = 1;
1012
    int e = 0;
2 7u83 1013
    if (*++s == '-') {
1014
      e_sign = -1;
1015
      s++;
7 7u83 1016
    } else if (*s == '+') {
1017
      s++;
2 7u83 1018
    }
1019
    while ((*s) && (*s >= '0' && *s <= '9')) {
1020
      if (e >= (E_MAX / 10)) {
7 7u83 1021
	return(EXP2BIG);
2 7u83 1022
      }
1023
      e = e * 10 + ((*s++) - '0');
1024
      exp_empty = 0;		/* ASCII */
1025
    }
1026
    if (exp_empty) {
7 7u83 1027
      return(SYNTAX);
2 7u83 1028
    }
1029
    e *= e_sign;
7 7u83 1030
    (f->exp) += (e + ids);
1031
  } else {
1032
    (f->exp) += ids;
2 7u83 1033
  }
7 7u83 1034
  if (((f->exp) >= E_MAX) || ((f->exp) <= E_MIN)) {
1035
    return(EXP2BIG);
2 7u83 1036
  }
1037
  if (zero) {
7 7u83 1038
    (f->sign) = 0;
1039
    (f->exp) = 0;
2 7u83 1040
  }
1041
  if (mant_empty) {
7 7u83 1042
    return(SYNTAX);
2 7u83 1043
  }
1044
  if (r) {
1045
    *r = s;
1046
  }
7 7u83 1047
  return(OKAY);
2 7u83 1048
}
1049
 
1050
#endif
1051
 
1052
 
1053
/***********************************************************************
1054
          ========== interface to  TDF translator ==========
1055
 ***********************************************************************/
1056
 
1057
/* memory allocation */
1058
 
7 7u83 1059
void
1060
init_flpt(void)
2 7u83 1061
{
1062
  /* initialise */
7 7u83 1063
  int i;
1064
  flt *fzr;
1065
  flt *forf;
1066
  flptnos = (flt *)xcalloc(initial_flpts, sizeof(flt));
2 7u83 1067
  tot_flpts = initial_flpts;
7 7u83 1068
  for (i = 1; i < tot_flpts; ++i) {
2 7u83 1069
    flptnos[i].exp = i - 1;
7 7u83 1070
  }
2 7u83 1071
  flptfree = tot_flpts - 1;
1072
  flpt_left = tot_flpts;
1073
 
1074
  fzero_no = new_flpt();
1075
  fone_no = new_flpt();
1076
  fzr = &flptnos[fzero_no];
7 7u83 1077
  fzr->sign = 0;
1078
  fzr->exp = 0;
2 7u83 1079
  forf = &flptnos[fone_no];
7 7u83 1080
  forf->sign = 1;
1081
  forf->exp = 0;
2 7u83 1082
  for (i = 0; i < MANT_SIZE; i++) {
7 7u83 1083
    (fzr->mant)[i] = 0;
1084
    (forf->mant)[i] = 0;
1085
  }
1086
  (forf->mant)[0] = 1;
2 7u83 1087
 
1088
  return;
1089
}
1090
 
7 7u83 1091
 
1092
void
1093
more_flpts(void)
2 7u83 1094
{
1095
  /* extend the floating point array */
7 7u83 1096
  int i;
2 7u83 1097
  tot_flpts += extra_flpts;
7 7u83 1098
  flptnos = (flt *)xrealloc((void*)(CH flptnos),
1099
			    TOSZ(tot_flpts *(int)sizeof(flt)));
1100
  for (i = tot_flpts - extra_flpts + 1; i < tot_flpts; ++i) {
2 7u83 1101
    flptnos[i].exp = i - 1;
7 7u83 1102
  }
2 7u83 1103
  flptfree = tot_flpts - 1;
1104
  flpt_left = extra_flpts;
1105
  return;
1106
}
1107
 
7 7u83 1108
 
1109
flpt
1110
new_flpt(void)
2 7u83 1111
{
1112
  /* allocate space for a new floating point number */
1113
  flpt r = flptfree;
1114
  flptfree = flptnos[r].exp;
7 7u83 1115
  if (--flpt_left == 0) {
1116
    more_flpts();
1117
  }
1118
  return(r);
2 7u83 1119
}
1120
 
7 7u83 1121
 
1122
void
1123
flpt_ret(flpt f)
2 7u83 1124
{
1125
  /* return a floating point number to free */
1126
  flptnos[f].exp = flptfree;
1127
  flptfree = f;
1128
  ++flpt_left;
1129
  return;
1130
}
1131
 
1132
 
1133
/***********************************************************************/
1134
 
1135
/* do the test testno on and and b deliver
1136
   1 if true, 0 otherwise */
7 7u83 1137
 
1138
int
1139
cmpflpt(flpt a, flpt b, int testno)
2 7u83 1140
{
7 7u83 1141
  int res = flt_cmp(flptnos[a], flptnos[b]);
2 7u83 1142
 
1143
  switch (testno) {
7 7u83 1144
  case 1:
1145
    return(res == 1);
1146
  case 2:
1147
    return(res != -1);
1148
  case 3:
1149
    return(res == -1);
1150
  case 4:
1151
    return(res != 1);
1152
  case 5:
1153
    return(res == 0);
1154
  default:
1155
    return(res != 0);
1156
  }
2 7u83 1157
}
1158
 
1159
 
1160
#if FBASE == 10
1161
 
7 7u83 1162
flpt
1163
floatrep(int n)
2 7u83 1164
{
7 7u83 1165
  flpt res = new_flpt();
1166
  char *pr = intchars(n);
1167
  /* this is wrong for unsigned integers */
2 7u83 1168
  flt fr;
7 7u83 1169
  IGNORE str2flt(pr, &fr,(char **)0);
2 7u83 1170
  flptnos[res] = fr;
7 7u83 1171
  return(res);
2 7u83 1172
}
1173
 
7 7u83 1174
 
1175
flpt
1176
floatrep_unsigned(unsigned int n)
2 7u83 1177
{
1178
  failer("floatrep_unsigned not used");
1179
  return 0;
1180
}
1181
 
7 7u83 1182
 
1183
int
1184
flpt_bits(floating_variety fv)
2 7u83 1185
{
1186
  return 0;
1187
}
1188
 
7 7u83 1189
 
1190
void
1191
flpt_round(int round_t, int posn, flt *res)
2 7u83 1192
{
1193
  return;
1194
}
1195
 
1196
#else
1197
 
7 7u83 1198
 
1199
static flpt
1200
floatrep_aux(int n, int sign)
2 7u83 1201
{
7 7u83 1202
  flpt res = new_flpt();
2 7u83 1203
  flt fr;
1204
  unsigned int mask = 0xffff;
1205
  int i;
1206
  int supp = 1;
1207
  int index = 0;
1208
 
1209
  flt_zero(&fr);
7 7u83 1210
  if (n == 0) {
2 7u83 1211
    flptnos[res] = fr;
7 7u83 1212
    return(res);
1213
  }
2 7u83 1214
 
1215
  fr.sign = sign;
1216
 
7 7u83 1217
  for (i = 1; i >= 0; --i) {
1218
    int t = (int)((n >> (i * 16)) & (int)mask);
1219
    if (supp && t) {
2 7u83 1220
      supp = 0;
1221
      fr.exp = i;
7 7u83 1222
    }
2 7u83 1223
    if (!supp) {
1224
      fr.mant[index++] = (unsigned short)t;	/* CAST:jmf: */
7 7u83 1225
    }
1226
  }
2 7u83 1227
 
1228
  flptnos[res] = fr;
7 7u83 1229
  return(res);
2 7u83 1230
}
1231
 
7 7u83 1232
 
1233
flpt
1234
floatrep(int n)
2 7u83 1235
{
7 7u83 1236
  if (n < 0) {
2 7u83 1237
    return floatrep_aux(-n, -1);
7 7u83 1238
  }
2 7u83 1239
  return floatrep_aux(n, 1);
1240
}
1241
 
7 7u83 1242
 
1243
flpt
1244
floatrep_unsigned(unsigned int n)
2 7u83 1245
{
1246
  return floatrep_aux((int)n, 1);
1247
}
1248
 
7 7u83 1249
 
1250
void
1251
flpt_newdig(unsigned int dig, flt *res, int base)
2 7u83 1252
{
1253
  int i;
1254
  unsigned int c = 0;
1255
 
7 7u83 1256
  if (dig != 0) {
1257
    res->sign = 1;
1258
  }
2 7u83 1259
 
1260
  i = MANT_SIZE - 1;
1261
 
7 7u83 1262
  for (; i >= 0; --i) {
1263
    c = (unsigned int)(((int)res->mant[i] * base) + (int)c);
1264
    res->mant[i] = (unsigned short)(c % FBASE);	/* CAST:jmf: */
2 7u83 1265
    c = c / FBASE;
7 7u83 1266
  }
2 7u83 1267
  if (c) {
7 7u83 1268
    ++res->exp;
1269
    i = res->exp;
1270
    if (i >= MANT_SIZE) {
2 7u83 1271
      i = MANT_SIZE - 1;
7 7u83 1272
    }
1273
    for (; i >= 0; --i)
1274
      res->mant[i] = res->mant[i - 1];
1275
    res->mant[0] = (unsigned short)c;	/* CAST:jmf: */
1276
  }
2 7u83 1277
 
7 7u83 1278
  if (res->exp >= MANT_SIZE)
2 7u83 1279
    return;
1280
 
1281
  c = dig;
7 7u83 1282
  for (i = res->exp; c && i >= 0; --i) {
1283
    c = (unsigned int)(res->mant[i] + c);
1284
    res->mant[i] = (unsigned short)(c % FBASE);	/* CAST:jmf: */
2 7u83 1285
    c = c / FBASE;
7 7u83 1286
  }
2 7u83 1287
  if (c) {
7 7u83 1288
    ++res->exp;
1289
    i = res->exp;
1290
    if (i >= MANT_SIZE) {
2 7u83 1291
      i = MANT_SIZE - 1;
7 7u83 1292
    }
1293
    for (; i >= 0; --i)
1294
      res->mant[i] = res->mant[i-1];
1295
    res->mant[0] = (unsigned short)c;	/* CAST:jmf: */
1296
  }
2 7u83 1297
  return;
1298
}
1299
 
1300
 
7 7u83 1301
void
1302
flpt_scale(int expt, flt *res, int base)
2 7u83 1303
{
1304
  flt ft;
1305
 
1306
  if (base == 10) {
1307
    if (expt > 0) {
1308
      if (expt > MAX_USEFUL_DECEXP) {
7 7u83 1309
	failer(BIG_FLPT);
2 7u83 1310
	exit(EXIT_FAILURE);
7 7u83 1311
	/* UNREACHED */
1312
      }
2 7u83 1313
      while (expt > 16) {
7 7u83 1314
	IGNORE flt_mul(*res, powers[15], &ft); /* cannot fail */
1315
	flt_copy(ft, res);
1316
	expt -= 16;
1317
      }
1318
      IGNORE flt_mul(*res, powers[expt - 1], &ft); /* cannot fail */
2 7u83 1319
      flt_copy(ft, res);
7 7u83 1320
    } else if (expt < 0) {
2 7u83 1321
      if (expt < - MAX_USEFUL_DECEXP) {
7 7u83 1322
	flt_zero(res);
1323
	return;
1324
      }
2 7u83 1325
      while (expt < -16) {
7 7u83 1326
	IGNORE flt_div(*res, powers[15], &ft); /* cannot fail */
1327
	flt_copy(ft, res);
1328
	expt += 16;
1329
      }
2 7u83 1330
      IGNORE flt_div(*res, powers[-1 - expt], &ft); /* cannot fail */
1331
      flt_copy(ft, res);
7 7u83 1332
    }
1333
  } else {
1334
    if (base == 4) {
2 7u83 1335
      expt += expt;
7 7u83 1336
    }
1337
    if (base == 8) {
2 7u83 1338
      expt *= 3;
7 7u83 1339
    }
1340
    if (base == 16) {
2 7u83 1341
      expt *= 4;
7 7u83 1342
    }
2 7u83 1343
 
1344
    if (expt > 0) {
1345
      res->exp += (expt / 16);
1346
      expt = expt % 16;
7 7u83 1347
      if (expt != 0) {
1348
	flpt_newdig((unsigned int)0, res, two_powers[expt]);
1349
      }
2 7u83 1350
      return;
7 7u83 1351
    } else if (expt < 0) {
2 7u83 1352
      int temp = ((-expt) / 16);
7 7u83 1353
      expt = (-expt)% 16;
1354
      if (expt == 0) {
2 7u83 1355
	res->exp -= temp;
7 7u83 1356
      } else {
1357
	flpt_newdig((unsigned int)0, res, two_powers[16 - expt]);
2 7u83 1358
	res->exp -= (temp+1);
7 7u83 1359
      }
1360
    }
1361
  }
2 7u83 1362
  return;
1363
}
1364
 
7 7u83 1365
 
1366
/* posn is the number of bits to be left correct after the rounding operation */
1367
 
1368
void
1369
flpt_round(int round_t, int posn, flt * res)
2 7u83 1370
{
7 7u83 1371
  unsigned int c = res->mant[0];
2 7u83 1372
  unsigned int mask;
1373
  int ndig0 = 0;
1374
  int i, bitpos;
1375
  int digpos = 0;
1376
  int bits_discarded = 0;
1377
 
7 7u83 1378
  if (res->sign == 0) {
2 7u83 1379
    return;
7 7u83 1380
  }
2 7u83 1381
 
7 7u83 1382
  for (mask = FBASE - 1; mask & c; mask <<= 1) {
1383
    ++ndig0;
1384
  }
2 7u83 1385
 
1386
  bitpos = ndig0 - posn;
1387
 
7 7u83 1388
  while (bitpos < 1) {
2 7u83 1389
    bitpos += FBITS;
1390
    ++digpos;
1391
  };
1392
 
1393
  --bitpos;
1394
 
7 7u83 1395
  /* digpos holds the number of the FBASE digit to be rounded, bitpos holds the
1396
   * number of the bit within that digit to have one added */
2 7u83 1397
 
7 7u83 1398
  for (i = digpos + 1; i < MANT_SIZE; ++i) {
1399
    if (res->mant[i]) {
2 7u83 1400
      bits_discarded = 1;
7 7u83 1401
      res->mant[i] = 0;
1402
    }
1403
  }
2 7u83 1404
 
1405
  switch (round_t) {
7 7u83 1406
  default:
1407
  case R2ZERO:
1408
    res->mant[digpos] =
1409
	(unsigned short)(res->mant[digpos] & bitmask[bitpos + 1]);
1410
    return;
1411
  case R2PINF:
1412
    if (res->sign != 1 ||
1413
	(!bits_discarded && ((res->mant[digpos] & bitmask[bitpos + 1]) ==
1414
			     (int)res->mant[digpos]))) {
1415
      res->mant[digpos] =
1416
	  (unsigned short)(res->mant[digpos] & bitmask[bitpos + 1]);
1417
 
2 7u83 1418
      return;
7 7u83 1419
    }
1420
    res->mant[digpos] = (unsigned short)(res->mant[digpos] | bitround[bitpos]);
1421
    break;
1422
  case R2NINF:
1423
    if (res->sign == 1 ||
1424
	(!bits_discarded && ((res->mant[digpos] & bitmask[bitpos + 1]) ==
1425
			     (int)res->mant[digpos]))) {
1426
      res->mant[digpos] = (unsigned short)((int)res->mant[digpos] &
1427
					   (int)bitmask[bitpos + 1]);
2 7u83 1428
 
7 7u83 1429
      return;
1430
    }
1431
    res->mant[digpos] = (unsigned short)((int)res->mant[digpos] |
1432
					 (int)bitround[bitpos]);
1433
    break;
1434
  case R2NEAR:
1435
    break;
1436
  }
2 7u83 1437
 
7 7u83 1438
  res->mant[digpos] = (unsigned short)((int)res->mant[digpos] &
1439
				       (int)bitmask[bitpos]);
2 7u83 1440
 
7 7u83 1441
  c = bitround[bitpos];
1442
  for (i = digpos; c && i >= 0; --i) {
1443
    c = (unsigned int)((int)res->mant[i] + (int)c);
1444
    res->mant[i] = (unsigned short)(c % FBASE);	/* CAST:jmf: */
1445
    c = c / FBASE;
1446
  }
1447
  if (c) {
1448
    ++res->exp;
1449
    i = res->exp;
1450
    if (i >= MANT_SIZE) {
1451
      i = MANT_SIZE - 1;
1452
    }
1453
    for (; i >= 0; --i) {
1454
      res->mant[i] = res->mant[i-1];
1455
    }
1456
    res-> mant[0] = (unsigned short)c;
1457
  }
1458
  res->mant[digpos+ (int)c] = (unsigned short)((int)res->mant[digpos + (int)c] &
1459
					       (int)bitmask[bitpos + 1]);
2 7u83 1460
  return;
1461
}
1462
 
7 7u83 1463
 
1464
int
1465
flpt_bits(floating_variety fv)
2 7u83 1466
{
7 7u83 1467
  switch (fv)
1468
  {
1469
  case 0: return FLOAT_BITS;
1470
	  /* FLOAT_BITS is defined in config.h 24 for IEEE */
1471
  case 1: return DOUBLE_BITS;
1472
	  /* FLOAT_BITS is defined in config.h 53 for IEEE */
1473
  case 2: return LDOUBLE_BITS;
1474
	  /* FLOAT_BITS is defined in config.h 64 for IEEE */
1475
  }
2 7u83 1476
  return 0;
1477
}
1478
 
7 7u83 1479
 
1480
int
1481
flpt_round_to_integer(int rndmd, flt *f)
2 7u83 1482
{
7 7u83 1483
  unsigned int c = f->mant[0];
2 7u83 1484
  unsigned int mask;
1485
  int ndig0 = 0;
1486
  int intbits;
1487
  int res;
1488
 
7 7u83 1489
  if (f->sign == 0) {
2 7u83 1490
    return 0;
7 7u83 1491
  }
2 7u83 1492
 
1493
  for (mask = FBASE - 1; mask & c; mask <<= 1)
7 7u83 1494
    ++ndig0;
1495
  intbits = ndig0 + (f->exp * FBITS);
2 7u83 1496
 
7 7u83 1497
  if (intbits >= 0) {
2 7u83 1498
    flpt_round(rndmd, intbits, f);
7 7u83 1499
  } else {
1500
    switch (rndmd)EXHAUSTIVE {
1501
    case R2ZERO:
1502
      break;
1503
    case R2PINF:
1504
      if (f->sign == 1) {
1505
	flt_copy(flptnos[fone_no], f);
1506
      } else {
1507
	flt_zero(f);
1508
      }
1509
      break;
1510
    case R2NINF:
1511
      if (f->sign == -1) {
1512
	flt_copy(flptnos[fone_no], f);
1513
	f->sign = -1;
1514
      } else {
1515
	flt_zero(f);
1516
      }
1517
      break;
1518
    case R2NEAR:
1519
      break;
1520
    }
1521
  }
2 7u83 1522
 
1523
 
7 7u83 1524
  /*
2 7u83 1525
#if has64bits
7 7u83 1526
  if (f->exp > 3) {
2 7u83 1527
    int ij;
7 7u83 1528
    f->mant[0] = f->mant[f->exp - 3];
1529
    f->mant[1] = f->mant[f->exp - 2];
1530
    f->mant[2] = f->mant[f->exp - 1];
1531
    f->mant[3] = f->mant[f->exp];
1532
    for (ij = 4; ij <= f->exp; ++ij) {
1533
      f->mant[ij] = 0;
1534
    }
1535
    f->exp = 3;
1536
  }
2 7u83 1537
#else
7 7u83 1538
  if (f->exp > 1) {
1539
    f->mant[0] = f->mant[f->exp - 1];
1540
    f->mant[1] = f->mant[f->exp];
1541
    f->exp = 1;
1542
  }
2 7u83 1543
#endif
7 7u83 1544
   */
1545
  if (f->exp == 1) {
1546
    res = ((int)f->mant[1] + ((int)f->mant[0] << 16));
1547
  } else {
1548
    res = (int)(f->mant[0]);
1549
  }
1550
  return res * f->sign;  /* this is only valid for 32-bit results */
2 7u83 1551
}
1552
 
7 7u83 1553
 
1554
/* convert flt* to IEEE representation in ints.  sw is 0 for single, 1 for
1555
 * double, 2 for extended */
1556
r2l
1557
real2longs_IEEE(flt *fp, int sw)
2 7u83 1558
{
1559
  r2l res;
1560
  flt f;
7 7u83 1561
  unsigned int c = fp->mant[0];
2 7u83 1562
  unsigned int mask;
1563
  int ndig0 = 0;
1564
  int expt;
1565
  int bias, expt_size, precision;
1566
  unsigned int sig1, sig2 = 0, sig3 = 0, sig4 = 0;
1567
  int i, index;
1568
  res.i1 = 0;
1569
  res.i2 = 0;
1570
  res.i3 = 0;
1571
  res.i4 = 0;
1572
 
7 7u83 1573
  if (fp->sign == 0) {
2 7u83 1574
    return res;
7 7u83 1575
  }
2 7u83 1576
 
1577
  f = *fp;
1578
 
7 7u83 1579
  switch (sw)EXHAUSTIVE {
1580
  case 0:
1581
    bias = 127;
1582
    expt_size = 8;
1583
    precision = 24;
1584
    break;
1585
  case 1:
1586
    bias = 1023;
1587
    expt_size = 11;
1588
    precision = 53;
1589
    break;
1590
  case 2:
1591
    bias = 16383;
1592
    expt_size = 15;
1593
    precision = LDOUBLE_BITS;
1594
    break;
1595
  }
1596
 
1597
  for (mask = FBASE - 1; mask & c; mask <<= 1) {
1598
    ++ndig0;
1599
  }
1600
  expt = ndig0 + (f.exp * FBITS) - 1;
1601
 
1602
  if (expt < (1-bias-precision)) {
1603
    /* 0 - underflowed */
1604
    return res;
1605
  }
1606
 
1607
  if (expt > bias) {
1608
    if (flpt_const_overflow_fail) {
1609
      failer(BIG_FLPT);
1610
      exit(EXIT_FAILURE);
1611
    }
1612
    switch (sw) {
2 7u83 1613
    case 0:
7 7u83 1614
      if (f.sign == -1) {
1615
	res.i1 = 0x80000000;
1616
      }
1617
      res.i1 += 0x7f800000;
1618
      return res;
2 7u83 1619
    case 1:
7 7u83 1620
      if (f.sign == -1) {
1621
	res.i2 = 0x80000000;
1622
      }
1623
      res.i2 += 0x7ff00000;
1624
      return res;
2 7u83 1625
    case 2:
1626
#if is80x86
7 7u83 1627
      if (f.sign == -1) {
1628
	res.i3 = 0x8000;
1629
      }
1630
      res.i3 += 0x7fff;
1631
      res.i2 = 0x80000000;
1632
      return res;
2 7u83 1633
#else
1634
#if issparc || ishppa
7 7u83 1635
      if (f.sign == -1) {
1636
	res.i4 = 0x8000;
1637
      }
1638
      res.i4 += 0x7fff;
1639
      return res;
2 7u83 1640
#else
1641
      failer("long double not implemented");
1642
      return res;
1643
#endif
1644
#endif
7 7u83 1645
    }
1646
  }
2 7u83 1647
 
7 7u83 1648
  expt += bias;
1649
  i = precision - ndig0;;
1650
  sig1 = f.mant[0];
1651
  index = 1;
1652
  while (i >= 16) {
1653
    sig4 <<= 16;
1654
    sig4 += (sig3 >> 16);
1655
    sig3 <<= 16;
1656
    sig3 += (sig2 >> 16);
1657
    sig2 <<= 16;
1658
    sig2 += (sig1 >> 16);
1659
    sig1 <<= 16;
1660
    sig1 = (unsigned int)(sig1 + f.mant[index++]);
1661
    i -= 16;
1662
  }
1663
  if (i != 0) {
1664
    sig4 <<= i;
1665
    sig4 += (sig3 >> (32-i));
1666
    sig3 <<= i;
1667
    sig3 += (sig2 >> (32-i));
1668
    sig2 <<= i;
1669
    sig2 += (sig1 >> (32-i));
1670
    sig1 <<= i;
1671
    sig1 = (unsigned int)(sig1 + (f.mant[index] >> (16 - i)));
1672
  }
2 7u83 1673
 
7 7u83 1674
  if (expt < 1) {
1675
    int places = 1 - expt;
1676
    while (places >= 32) {
1677
      sig1 = sig2;
1678
      sig2 = sig3;
1679
      sig3 = sig4;
1680
      sig4 = 0;
1681
      places -= 32;
2 7u83 1682
    }
7 7u83 1683
    if (places > 0) {
1684
      sig1 = (sig1 >> places) + (sig2 << (32 - places));
1685
      sig2 = (sig2 >> places) + (sig3 << (32 - places));
1686
      sig3 = (sig3 >> places) + (sig4 << (32 - places));
1687
      sig4 >>= places;
1688
    }
1689
    expt = 0;
1690
  } else {
1691
    expt &= ((1 << (expt_size+1)) -1);
1692
  }
2 7u83 1693
 
7 7u83 1694
  switch (sw) {
1695
  case 0:
1696
    if (f.sign == -1) {
1697
      res.i1 = 0x80000000;
1698
    }
1699
    res.i1 += (expt << 23);
1700
    res.i1 += (int)(sig1 & 0x007fffff);
1701
    break;
1702
  case 1:
1703
    if (f.sign == -1) {
1704
      res.i2 = 0x80000000;
1705
    }
1706
    res.i2 += (expt << 20);
1707
    res.i2 += (int)(sig2 & 0xfffff);
1708
    res.i1 = (int)sig1;
1709
    break;
1710
  case 2:
2 7u83 1711
#if is80x86
7 7u83 1712
    res.i1 = (int)sig1;
1713
    res.i2 = (int)sig2;
1714
    if (f.sign == -1) {
1715
      res.i3 = 0x8000;
1716
    }
1717
    res.i3 += expt;
1718
    UNUSED(sig3);
1719
    UNUSED(sig4);
1720
    break;
2 7u83 1721
#else
1722
#if issparc || ishppa
7 7u83 1723
    if (f.sign == -1) {
1724
      res.i4 = 0x80000000;
1725
    }
1726
    res.i4 += (expt << 16);
1727
    res.i4 += (int)(sig4 & 0xffff);
1728
    res.i3 = (int)sig3;
1729
    res.i2 = (int)sig2;
1730
    res.i1 = (int)sig1;
1731
    break;
2 7u83 1732
#else
7 7u83 1733
    failer("long double not implemented");
1734
    return res;
2 7u83 1735
#endif
1736
#endif
7 7u83 1737
  }
2 7u83 1738
 
1739
  return res;
1740
}
1741
 
1742
#endif