/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
and support for XFmode IEEE extended real floating point arithmetic.
Contributed by Stephen L. Moshier (moshier@world.std.com).
Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* To enable support of XFmode extended real floating point, define
LONG_DOUBLE_TYPE_SIZE 96 in the tm.h file (m68k.h or i386.h).
To support cross compilation between IEEE and VAX floating
point formats, define REAL_ARITHMETIC in the tm.h file.
In either case the machine files (tm.h) must not contain any code
that tries to use host floating point arithmetic to convert
REAL_VALUE_TYPEs from `double' to `float', pass them to fprintf,
etc. In cross-compile situations a REAL_VALUE_TYPE may not
be intelligible to the host computer's native arithmetic.
The emulator defaults to the host's floating point format so that
its decimal conversion functions can be used if desired (see
The first part of this file interfaces gcc to ieee.c, which is a
floating point arithmetic suite that was not written with gcc in
mind. The interface is followed by ieee.c itself and related
items. Avoid changing ieee.c unless you have suitable test
programs available. A special version of the PARANOIA floating
point arithmetic tester, modified for this purpose, can be found
on usc.edu : /pub/C-numanal/ieeetest.zoo. Some tutorial
information on ieee.c is given in my book: S. L. Moshier,
_Methods and Programs for Mathematical Functions_, Prentice-Hall
or Simon & Schuster Int'l, 1989. A library of XFmode elementary
transcendental functions can be obtained by ftp from
research.att.com: netlib/cephes/ldouble.shar.Z */
/* Type of computer arithmetic.
* Only one of DEC, MIEEE, IBMPC, or UNK should get defined.
/* `MIEEE' refers generically to big-endian IEEE floating-point data
structure. This definition should work in SFmode `float' type and
DFmode `double' type on virtually all big-endian IEEE machines.
If LONG_DOUBLE_TYPE_SIZE has been defined to be 96, then MIEEE
also invokes the particular XFmode (`long double' type) data
structure used by the Motorola 680x0 series processors.
`IBMPC' refers generally to little-endian IEEE machines. In this
case, if LONG_DOUBLE_TYPE_SIZE has been defined to be 96, then
IBMPC also invokes the particular XFmode `long double' data
structure used by the Intel 80x86 series processors.
`DEC' refers specifically to the Digital Equipment Corp PDP-11
and VAX floating point data structure. This model currently
supports no type wider than DFmode.
If LONG_DOUBLE_TYPE_SIZE = 64 (the default, unless tm.h defines it)
then `long double' and `double' are both implemented, but they
both mean DFmode. In this case, the software floating-point
support available here is activated by writing
The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support
(Not Yet Implemented) and may deactivate XFmode since
`long double' is used to refer to both modes. */
/* The following converts gcc macros into the ones used by this file. */
/* REAL_ARITHMETIC defined means that macros in real.h are
defined to call emulator functions. */
#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
/* PDP-11, Pro350, VAX: */
#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
/* Motorola IEEE, high order words come first (Sun workstation): */
#else /* not big-endian */
/* Intel IEEE, low order words come first:
#else /* it's not IEEE either */
/* UNKnown arithmetic. We don't support this and can't go on. */
/* REAL_ARITHMETIC not defined means that the *host's* data
structure will be used. It may differ by endian-ness from the
target machine's structure and will get its ends swapped
accordingly (but not here). Probably only the decimal <-> binary
functions in this file will actually be used in this case. */
#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
#ifdef HOST_WORDS_BIG_ENDIAN
#else /* not big-endian */
#else /* it's not IEEE either */
#endif /* REAL_ARITHMETIC not defined */
/* Define INFINITY for support of infinity.
Define NANS for support of Not-a-Number's (NaN's). */
/* Support of NaNs requires support of infinity. */
* Include file for extended precision arithmetic programs.
/* Number of 16 bit words in external e type format */
/* Number of 16 bit words in internal format */
/* Array offset to exponent */
/* Array offset to high guard word */
/* Number of bits of precision */
#define NBITS ((NI-4)*16)
/* Maximum number of decimal digits in ASCII conversion
#define NDEC (NBITS*8/27)
/* The exponent of 1.0 */
/* Find a host integer type that is at least 16 bits wide,
and another type at least twice whatever that size is. */
#if HOST_BITS_PER_CHAR >= 16
#define EMUSHORT_SIZE HOST_BITS_PER_CHAR
#define EMULONG_SIZE (2 * HOST_BITS_PER_CHAR)
#if HOST_BITS_PER_SHORT >= 16
#define EMUSHORT_SIZE HOST_BITS_PER_SHORT
#define EMULONG_SIZE (2 * HOST_BITS_PER_SHORT)
#if HOST_BITS_PER_INT >= 16
#define EMUSHORT_SIZE HOST_BITS_PER_INT
#define EMULONG_SIZE (2 * HOST_BITS_PER_INT)
#if HOST_BITS_PER_LONG >= 16
#define EMUSHORT_SIZE HOST_BITS_PER_LONG
#define EMULONG_SIZE (2 * HOST_BITS_PER_LONG)
/* You will have to modify this program to have a smaller unit size. */
#if HOST_BITS_PER_SHORT >= EMULONG_SIZE
#if HOST_BITS_PER_INT >= EMULONG_SIZE
#if HOST_BITS_PER_LONG >= EMULONG_SIZE
#if HOST_BITS_PER_LONG_LONG >= EMULONG_SIZE
#define EMULONG long long int
/* You will have to modify this program to have a smaller unit size. */
/* The host interface doesn't work if no 16-bit size exists. */
/* OK to continue compilation. */
/* Construct macros to translate between REAL_VALUE_TYPE and e type.
In GET_REAL and PUT_REAL, r and e are pointers.
A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations
in memory, with no holes. */
#if LONG_DOUBLE_TYPE_SIZE == 96
#define GET_REAL(r,e) bcopy (r, e, 2*NE)
#define PUT_REAL(e,r) bcopy (e, r, 2*NE)
/* Emulator uses target format internally
but host stores it in host endian-ness. */
#if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN
#define GET_REAL(r,e) e53toe ((r), (e))
#define PUT_REAL(e,r) etoe53 ((e), (r))
#else /* endian-ness differs */
/* emulator uses target endian-ness internally */
w[3] = ((EMUSHORT *) r)[0]; \
w[2] = ((EMUSHORT *) r)[1]; \
w[1] = ((EMUSHORT *) r)[2]; \
w[0] = ((EMUSHORT *) r)[3]; \
e53toe (w, (e)); } while (0)
*((EMUSHORT *) r) = w[3]; \
*((EMUSHORT *) r + 1) = w[2]; \
*((EMUSHORT *) r + 2) = w[1]; \
*((EMUSHORT *) r + 3) = w[0]; } while (0)
#endif /* endian-ness differs */
#else /* not REAL_ARITHMETIC */
/* emulator uses host format */
#define GET_REAL(r,e) e53toe ((r), (e))
#define PUT_REAL(e,r) etoe53 ((e), (r))
#endif /* not REAL_ARITHMETIC */
extern int extra_warnings
;
int ecmp (), enormlz (), eshift ();
int eisneg (), eisinf (), eisnan (), eiisinf (), eiisnan ();
void eadd (), esub (), emul (), ediv ();
void eshup1 (), eshup8 (), eshup6 (), eshdn1 (), eshdn8 (), eshdn6 ();
void eabs (), eneg (), emov (), eclear (), einfin (), efloor ();
void eldexp (), efrexp (), eifrac (), euifrac (), ltoe (), ultoe ();
void eround (), ereal_to_decimal (), eiinfin (), einan ();
void esqrt (), elog (), eexp (), etanh (), epow ();
void asctoe (), asctoe24 (), asctoe53 (), asctoe64 ();
void etoasc (), e24toasc (), e53toasc (), e64toasc ();
void etoe64 (), etoe53 (), etoe24 (), e64toe (), e53toe (), e24toe ();
void mtherr (), make_nan ();
extern unsigned EMUSHORT ezero
[], ehalf
[], eone
[], etwo
[];
extern unsigned EMUSHORT elog2
[], esqrt2
[];
/* Pack output array with 32-bit numbers obtained from
array containing 16-bit numbers, swapping ends if required. */
/* Swap halfwords in the third long. */
th
= (unsigned long) e
[4] & 0xffff;
t
= (unsigned long) e
[5] & 0xffff;
/* fall into the double case */
/* swap halfwords in the second word */
th
= (unsigned long) e
[2] & 0xffff;
t
= (unsigned long) e
[3] & 0xffff;
/* fall into the float case */
/* swap halfwords in the first word */
th
= (unsigned long) e
[0] & 0xffff;
t
= (unsigned long) e
[1] & 0xffff;
/* Pack the output array without swapping. */
Each element of the input REAL_VALUE_TYPE array has 16 bit useful bits
th
= (unsigned long) e
[5] & 0xffff;
t
= (unsigned long) e
[4] & 0xffff;
/* fall into the double case */
/* pack the second long */
th
= (unsigned long) e
[3] & 0xffff;
t
= (unsigned long) e
[2] & 0xffff;
/* fall into the float case */
/* pack the first long */
th
= (unsigned long) e
[1] & 0xffff;
t
= (unsigned long) e
[0] & 0xffff;
/* This is the implementation of the REAL_ARITHMETIC macro.
earith (value
, icode
, r1
, r2
)
unsigned EMUSHORT d1
[NE
], d2
[NE
], v
[NE
];
/* Return NaN input back to the caller. */
code
= (enum tree_code
) icode
;
esub (d2
, d1
, v
); /* d1 - d2 */
if (ecmp (d2
, ezero
) == 0)
ediv (d2
, d1
, v
); /* d1/d2 */
case MIN_EXPR
: /* min (d1,d2) */
case MAX_EXPR
: /* max (d1,d2) */
/* Truncate REAL_VALUE_TYPE toward zero to signed HOST_WIDE_INT
* implements REAL_VALUE_RNDZINT (x) (etrunci (x))
unsigned EMUSHORT f
[NE
], g
[NE
];
/* Truncate REAL_VALUE_TYPE toward zero to unsigned HOST_WIDE_INT
* implements REAL_VALUE_UNSIGNED_RNDZINT (x) (etruncui (x))
unsigned EMUSHORT f
[NE
], g
[NE
];
/* This is the REAL_VALUE_ATOF function.
* It converts a decimal string to binary, rounding off
* as indicated by the machine_mode argument. Then it
* promotes the rounded value to REAL_VALUE_TYPE.
unsigned EMUSHORT tem
[NE
], e
[NE
];
/* Expansion of REAL_NEGATE.
* implements REAL_VALUE_FIX (x) (eroundi (x))
* The type of rounding is left unspecified by real.h.
* It is implemented here as round to nearest (add .5 and chop).
unsigned EMUSHORT f
[NE
], g
[NE
];
warning ("conversion from NaN to int");
/* Round real to nearest unsigned int
* implements REAL_VALUE_UNSIGNED_FIX (x) ((unsigned int) eroundi (x))
* Negative input returns zero.
* The type of rounding is left unspecified by real.h.
* It is implemented here as round to nearest (add .5 and chop).
unsigned EMUSHORT f
[NE
], g
[NE
];
warning ("conversion from NaN to unsigned int");
return ((unsigned int)l
);
/* REAL_VALUE_FROM_INT macro.
unsigned EMUSHORT df
[NE
], dg
[NE
];
/* complement and add 1 */
eldexp (eone
, HOST_BITS_PER_LONG
, df
);
/* REAL_VALUE_FROM_UNSIGNED_INT macro.
ereal_from_uint (d
, i
, j
)
unsigned EMUSHORT df
[NE
], dg
[NE
];
eldexp (eone
, HOST_BITS_PER_LONG
, df
);
/* REAL_VALUE_TO_INT macro
ereal_to_int (low
, high
, rr
)
unsigned EMUSHORT d
[NE
], df
[NE
], dg
[NE
], dh
[NE
];
warning ("conversion from NaN to int");
/* convert positive value */
eldexp (eone
, HOST_BITS_PER_LONG
, df
);
ediv (df
, d
, dg
); /* dg = d / 2^32 is the high word */
emul (df
, dh
, dg
); /* fractional part is the low word */
/* complement and add 1 */
/* REAL_VALUE_LDEXP macro.
unsigned EMUSHORT e
[NE
], y
[NE
];
/* These routines are conditionally compiled because functions
* of the same names may be defined in fold-const.c. */
/* Check for infinity in a REAL_VALUE_TYPE. */
/* Check whether a REAL_VALUE_TYPE item is a NaN. */
/* Check for a negative REAL_VALUE_TYPE number.
* this means strictly less than zero, not -0.
if (ecmp (e
, ezero
) == -1)
/* Expansion of REAL_VALUE_TRUNCATE.
* The result is in floating point, rounded to nearest or even.
real_value_truncate (mode
, arg
)
unsigned EMUSHORT e
[NE
], t
[NE
];
#endif /* REAL_ARITHMETIC defined */
/* Target values are arrays of host longs. A long is guaranteed
to be at least 32 bits wide. */
unsigned EMUSHORT ex
[NE
], ey
[NE
];
unsigned EMUSHORT ex
[NE
];
/* End of REAL_ARITHMETIC interface */
* Extended precision IEEE binary floating point arithmetic routines
* Numbers are stored in C language as arrays of 16-bit unsigned
* short integers. The arguments of the routines are pointers to
* External e type data structure, simulates Intel 8087 chip
* temporary real format but possibly with a larger significand:
* NE-1 significand words (least significant word first,
* most significant bit is normally set)
* exponent (value = EXONE for 1.0,
* Internal data structure of a number (a "word" is 16 bits):
* ei[0] sign word (0 for positive, 0xffff for negative)
* ei[1] biased exponent (value = EXONE for the number 1.0)
* ei[2] high guard word (always zero after normalization)
* to ei[NI-2] significand (NI-4 significand words,
* most significant word first,
* most significant bit is set)
* ei[NI-1] low guard word (0x8000 bit is rounding place)
* Routines for external format numbers
* asctoe (string, e) ASCII string to extended double e type
* asctoe64 (string, &d) ASCII string to long double
* asctoe53 (string, &d) ASCII string to double
* asctoe24 (string, &f) ASCII string to single
* asctoeg (string, e, prec) ASCII string to specified precision
* e24toe (&f, e) IEEE single precision to e type
* e53toe (&d, e) IEEE double precision to e type
* e64toe (&d, e) IEEE long double precision to e type
* eabs (e) absolute value
* eadd (a, b, c) c = b + a
* ecmp (a, b) Returns 1 if a > b, 0 if a == b,
* -1 if a < b, -2 if either a or b is a NaN.
* ediv (a, b, c) c = b / a
* efloor (a, b) truncate to integer, toward -infinity
* efrexp (a, exp, s) extract exponent and significand
* eifrac (e, &l, frac) e to long integer and e type fraction
* euifrac (e, &l, frac) e to unsigned long integer and e type fraction
* einfin (e) set e to infinity, leaving its sign alone
* eldexp (a, n, b) multiply by 2**n
* emul (a, b, c) c = b * a
* eround (a, b) b = nearest integer value to a
* esub (a, b, c) c = b - a
* e24toasc (&f, str, n) single to ASCII string, n digits after decimal
* e53toasc (&d, str, n) double to ASCII string, n digits after decimal
* e64toasc (&d, str, n) long double to ASCII string
* etoasc (e, str, n) e to ASCII string, n digits after decimal
* etoe24 (e, &f) convert e type to IEEE single precision
* etoe53 (e, &d) convert e type to IEEE double precision
* etoe64 (e, &d) convert e type to IEEE long double precision
* ltoe (&l, e) long (32 bit) integer to e type
* ultoe (&l, e) unsigned long (32 bit) integer to e type
* eisneg (e) 1 if sign bit of e != 0, else 0
* eisinf (e) 1 if e has maximum exponent (non-IEEE)
* eisnan (e) 1 if e is a NaN
* Routines for internal format numbers
* eaddm (ai, bi) add significands, bi = bi + ai
* ecleazs (ei) set ei = 0 but leave its sign alone
* ecmpm (ai, bi) compare significands, return 1, 0, or -1
* edivm (ai, bi) divide significands, bi = bi / ai
* emdnorm (ai,l,s,exp) normalize and round off
* emovi (a, ai) convert external a to internal ai
* emovo (ai, a) convert internal ai to external a
* emovz (ai, bi) bi = ai, low guard word of bi = 0
* emulm (ai, bi) multiply significands, bi = bi * ai
* enormlz (ei) left-justify the significand
* eshdn1 (ai) shift significand and guards down 1 bit
* eshdn8 (ai) shift down 8 bits
* eshdn6 (ai) shift down 16 bits
* eshift (ai, n) shift ai n bits up (or down if n < 0)
* eshup1 (ai) shift significand and guards up 1 bit
* eshup8 (ai) shift up 8 bits
* eshup6 (ai) shift up 16 bits
* esubm (ai, bi) subtract significands, bi = bi - ai
* eiisinf (ai) 1 if infinite
* eiisnan (ai) 1 if a NaN
* einan (ai) set ai = NaN
* eiinfin (ai) set ai = infinity
* The result is always normalized and rounded to NI-4 word precision
* after each arithmetic operation.
* Exception flags are NOT fully supported.
* Signaling NaN's are NOT supported; they are treated the same
* Define INFINITY for support of infinity; otherwise a
* saturation arithmetic is implemented.
* Define NANS for support of Not-a-Number items; otherwise the
* arithmetic will never produce a NaN output, and might be confused
* If NaN's are supported, the output of `ecmp (a,b)' is -2 if
* either a or b is a NaN. This means asking `if (ecmp (a,b) < 0)'
* may not be legitimate. Use `if (ecmp (a,b) == -1)' for `less than'
* Denormals are always supported here where appropriate (e.g., not
* for conversion to DEC numbers).
* Common include file for math routines
* This file contains definitions for error codes that are
* passed to the common error handling routine mtherr
* The file also includes a conditional assembly definition
* for the type of computer arithmetic (Intel IEEE, DEC, Motorola
* For Digital Equipment PDP-11 and VAX computers, certain
* IBM systems, and others that use numbers with a 56-bit
* significand, the symbol DEC should be defined. In this
* mode, most floating point constants are given as arrays
* of octal integers to eliminate decimal to binary conversion
* errors that might be introduced by the compiler.
* For computers, such as IBM PC, that follow the IEEE
* Standard for Binary Floating Point Arithmetic (ANSI/IEEE
* Std 754-1985), the symbol IBMPC or MIEEE should be defined.
* These numbers have 53-bit significands. In this mode, constants
* are provided as arrays of hexadecimal 16 bit integers.
* To accommodate other types of computer arithmetic, all
* constants are also provided in a normal decimal radix
* which one can hope are correctly converted to a suitable
* format by the available C language compiler. To invoke
* this mode, the symbol UNK is defined.
* An important difference among these modes is a predefined
* set of machine arithmetic constants for each. The numbers
* MACHEP (the machine roundoff error), MAXNUM (largest number
* represented), and several other parameters are preset by
* the configuration symbol. Check the file const.c to
* ensure that these values are correct for your computer.
* For ANSI C compatibility, define ANSIC equal to 1. Currently
* this affects only the atan2 function and others that use it.
/* Constant definitions for math error conditions. */
#define DOMAIN 1 /* argument domain error */
#define SING 2 /* argument singularity */
#define OVERFLOW 3 /* overflow range error */
#define UNDERFLOW 4 /* underflow range error */
#define TLOSS 5 /* total loss of precision */
#define PLOSS 6 /* partial loss of precision */
#define INVALID 7 /* NaN-producing operation */
/* e type constants used by high precision check routines */
unsigned EMUSHORT ezero
[NE
] =
0, 0000000, 0000000, 0000000, 0000000, 0000000,};
extern unsigned EMUSHORT ezero
[];
unsigned EMUSHORT ehalf
[NE
] =
0, 0000000, 0000000, 0000000, 0100000, 0x3ffe,};
extern unsigned EMUSHORT ehalf
[];
unsigned EMUSHORT eone
[NE
] =
0, 0000000, 0000000, 0000000, 0100000, 0x3fff,};
extern unsigned EMUSHORT eone
[];
unsigned EMUSHORT etwo
[NE
] =
0, 0000000, 0000000, 0000000, 0100000, 0040000,};
extern unsigned EMUSHORT etwo
[];
unsigned EMUSHORT e32
[NE
] =
0, 0000000, 0000000, 0000000, 0100000, 0040004,};
extern unsigned EMUSHORT e32
[];
/* 6.93147180559945309417232121458176568075500134360255E-1 */
unsigned EMUSHORT elog2
[NE
] =
0xc9e4, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
extern unsigned EMUSHORT elog2
[];
/* 1.41421356237309504880168872420969807856967187537695E0 */
unsigned EMUSHORT esqrt2
[NE
] =
0x597e, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
extern unsigned EMUSHORT esqrt2
[];
* 1.12837916709551257389615890312154517168810125865800E0 */
unsigned EMUSHORT eoneopi
[NE
] =
0x71d5, 0x688d, 0012333, 0135202, 0110156, 0x3fff,};
extern unsigned EMUSHORT eoneopi
[];
/* 3.14159265358979323846264338327950288419716939937511E0 */
unsigned EMUSHORT epi
[NE
] =
0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
extern unsigned EMUSHORT epi
[];
/* 5.7721566490153286060651209008240243104215933593992E-1 */
unsigned EMUSHORT eeul
[NE
] =
0xd1be, 0xc7a4, 0076660, 0063743, 0111704, 0x3ffe,};
extern unsigned EMUSHORT eeul
[];
/* Control register for rounding precision.
* This can be set to 80 (if NE=6), 64, 56, 53, or 24 bits.
void eaddm (), esubm (), emdnorm (), asctoeg ();
static void toe24 (), toe53 (), toe64 ();
void eremain (), einit (), eiremain ();
int ecmpm (), edivm (), emulm ();
void emovi (), emovo (), emovz (), ecleaz (), ecleazs (), eadd1 ();
void etodec (), todec (), dectoe ();
; Clear out entire external format number.
register unsigned EMUSHORT
*x
;
/* Move external format number from a to b.
register unsigned EMUSHORT
*a
, *b
;
; Absolute value of external format number
unsigned EMUSHORT x
[]; /* x is the memory address of a short */
x
[NE
- 1] &= 0x7fff; /* sign is top bit of last word of external format */
; Negate external format number
; unsigned EMUSHORT x[NE];
x
[NE
- 1] ^= 0x8000; /* Toggle the sign bit */
/* Return 1 if external format number is negative,
* else return zero, including when it is a NaN.
/* Return 1 if external format number is infinity.
if ((x
[NE
- 1] & 0x7fff) == 0x7fff)
/* Check if e-type number is not a number.
The bit pattern is one that we defined, so we know for sure how to
/* NaN has maximum exponent */
if ((x
[NE
- 1] & 0x7fff) != 0x7fff)
/* ... and non-zero significand field. */
for (i
= 0; i
< NE
- 1; i
++)
/* Fill external format number with infinity pattern (IEEE)
or largest possible number (non-IEEE).
Before calling einfin, you should either call eclear
or set up the sign bit by hand. */
register unsigned EMUSHORT
*x
;
for (i
= 0; i
< NE
- 1; i
++)
for (i
= 0; i
< NE
- 1; i
++)
This generates Intel's quiet NaN pattern for extended real.
The exponent is 7fff, the leading mantissa word is c000. */
register unsigned EMUSHORT
*x
;
for (i
= 0; i
< NE
- 2; i
++)
/* Move in external format number,
* converting it to internal format.
unsigned EMUSHORT
*a
, *b
;
register unsigned EMUSHORT
*p
, *q
;
p
= a
+ (NE
- 1); /* point to last word of external number */
*q
++ &= 0x7fff; /* delete the sign bit */
if ((*(q
- 1) & 0x7fff) == 0x7fff)
/* clear high guard word */
/* move in the significand */
for (i
= 0; i
< NE
- 1; i
++)
/* clear low guard word */
/* Move internal format number out,
* converting it to external format.
unsigned EMUSHORT
*a
, *b
;
register unsigned EMUSHORT
*p
, *q
;
q
= b
+ (NE
- 1); /* point to output exponent */
/* combine sign and exponent */
/* skip over guard word */
/* move the significand */
for (i
= 0; i
< NE
- 1; i
++)
/* Clear out internal format number.
register unsigned EMUSHORT
*xi
;
/* same, but don't touch the sign. */
register unsigned EMUSHORT
*xi
;
for (i
= 0; i
< NI
- 1; i
++)
/* Move internal format number from a to b.
register unsigned EMUSHORT
*a
, *b
;
for (i
= 0; i
< NI
- 1; i
++)
/* clear low guard word */
/* Generate internal format NaN.
The explicit pattern for this is maximum exponent and
top two significand bits set. */
/* Return nonzero if internal format number is a NaN. */
if ((x
[E
] & 0x7fff) == 0x7fff)
for (i
= M
+ 1; i
< NI
; i
++)
/* Fill internal format number with infinity pattern.
This has maximum exponent and significand all zeros. */
/* Return nonzero if internal format number is infinite. */
if ((x
[E
] & 0x7fff) == 0x7fff)
; Compare significands of numbers in internal format.
; Guard words are included in the comparison.
; unsigned EMUSHORT a[NI], b[NI];
register unsigned EMUSHORT
*a
, *b
;
a
+= M
; /* skip up to significand area */
; Shift significand down by 1 bit
register unsigned EMUSHORT
*x
;
register unsigned EMUSHORT bits
;
x
+= M
; /* point to significand area */
; Shift significand up by 1 bit
register unsigned EMUSHORT
*x
;
register unsigned EMUSHORT bits
;
; Shift significand down by 8 bits
register unsigned EMUSHORT
*x
;
register unsigned EMUSHORT newbyt
, oldbyt
;
; Shift significand up by 8 bits
register unsigned EMUSHORT
*x
;
register unsigned EMUSHORT newbyt
, oldbyt
;
; Shift significand up by 16 bits
register unsigned EMUSHORT
*x
;
register unsigned EMUSHORT
*p
;
for (i
= M
; i
< NI
- 1; i
++)
; Shift significand down by 16 bits
register unsigned EMUSHORT
*x
;
register unsigned EMUSHORT
*p
;
for (i
= M
; i
< NI
- 1; i
++)
unsigned EMUSHORT
*x
, *y
;
register unsigned EMULONG a
;
a
= (unsigned EMULONG
) (*x
) + (unsigned EMULONG
) (*y
) + carry
;
*y
= (unsigned EMUSHORT
) a
;
unsigned EMUSHORT
*x
, *y
;
a
= (unsigned EMULONG
) (*y
) - (unsigned EMULONG
) (*x
) - carry
;
*y
= (unsigned EMUSHORT
) a
;
/* Divide significands */
static unsigned EMUSHORT equot
[NI
];
unsigned EMUSHORT den
[], num
[];
register unsigned EMUSHORT
*p
, *q
;
/* Use faster compare and subtraction if denominator
* has only 15 bits of significance.
for (i
= M
+ 3; i
< NI
; i
++)
if ((den
[M
+ 1] & 1) != 0)
for (i
= 0; i
< NBITS
+ 2; i
++)
/* The number of quotient bits to calculate is
* NBITS + 1 scaling guard bit + 1 roundoff bit.
for (i
= 0; i
< NBITS
+ 2; i
++)
if (ecmpm (den
, num
) <= 0)
j
= 1; /* quotient bit = 1 */
/* test for nonzero remainder after roundoff bit */
/* Multiply significands */
unsigned EMUSHORT a
[], b
[];
unsigned EMUSHORT
*p
, *q
;
while (*p
== 0) /* significand is not supposed to be all zero */
/* remember if there were any nonzero bits shifted out */
/* return flag for lost nonzero bits */
* Normalize and round off.
* The internal format number to be rounded is "s".
* Input "lost" indicates whether or not the number is exact.
* This is the so-called sticky bit.
* Input "subflg" indicates whether the number was obtained
* by a subtraction operation. In that case if lost is nonzero
* then the number is slightly smaller than indicated.
* Input "exp" is the biased exponent, which may be negative.
* the exponent field of "s" is ignored but is replaced by
* "exp" as adjusted by normalization and rounding.
* Input "rcntrl" is the rounding control.
static unsigned EMUSHORT rmsk
= 0;
static unsigned EMUSHORT rmbit
= 0;
static unsigned EMUSHORT rebit
= 0;
static unsigned EMUSHORT rbit
[NI
];
emdnorm (s
, lost
, subflg
, exp
, rcntrl
)
/* a blank significand could mean either zero or infinity. */
if ((j
> NBITS
) && (exp
< 32767))
if (exp
> (EMULONG
) (-NBITS
- 1))
/* Round off, unless told not to by rcntrl. */
/* Set up rounding parameters if the control register changed. */
rw
= NI
- 1; /* low guard word */
/* These tests assume NI = 8 */
if ((s
[re
] & rebit
) == 0)
if ((rndprc
< 64) && (exp
<= 0))
{ /* overflow on roundoff */
for (i
= 2; i
< NI
- 1; i
++)
warning ("floating point overflow");
for (i
= M
+ 1; i
< NI
- 1; i
++)
s
[1] = (unsigned EMUSHORT
) exp
;
; Subtract external format numbers.
; unsigned EMUSHORT a[NE], b[NE], c[NE];
; esub (a, b, c); c = b - a
unsigned EMUSHORT
*a
, *b
, *c
;
/* Infinity minus infinity is a NaN.
Test for subtracting infinities of the same sign. */
if (eisinf (a
) && eisinf (b
)
&& ((eisneg (a
) ^ eisneg (b
)) == 0))
mtherr ("esub", INVALID
);
; unsigned EMUSHORT a[NE], b[NE], c[NE];
; eadd (a, b, c); c = b + a
unsigned EMUSHORT
*a
, *b
, *c
;
/* NaN plus anything is a NaN. */
/* Infinity minus infinity is a NaN.
Test for adding infinities of opposite signs. */
if (eisinf (a
) && eisinf (b
)
&& ((eisneg (a
) ^ eisneg (b
)) != 0))
mtherr ("esub", INVALID
);
unsigned EMUSHORT
*a
, *b
, *c
;
unsigned EMUSHORT ai
[NI
], bi
[NI
], ci
[NI
];
{ /* put the larger number in bi */
if (lt
< (EMULONG
) (-NBITS
- 1))
goto done
; /* answer same as larger addend */
lost
= eshift (ai
, k
); /* shift the smaller number down */
/* exponents were the same, so must compare significands */
{ /* the numbers are identical in magnitude */
/* if different signs, result is zero */
/* if same sign, result is double */
/* double denomalized tiny number */
if ((bi
[E
] == 0) && ((bi
[3] & 0x8000) == 0))
/* add 1 to exponent unless both are zero! */
for (j
= 1; j
< NI
- 1; j
++)
/* This could overflow, but let emovo take care of that. */
bi
[E
] = (unsigned EMUSHORT
) ltb
;
{ /* put the larger number in bi */
emdnorm (bi
, lost
, subflg
, ltb
, 64);
; unsigned EMUSHORT a[NE], b[NE], c[NE];
; ediv (a, b, c); c = b / a
unsigned EMUSHORT
*a
, *b
, *c
;
unsigned EMUSHORT ai
[NI
], bi
[NI
];
/* Return any NaN input. */
/* Zero over zero, or infinity over infinity, is a NaN. */
if (((ecmp (a
, ezero
) == 0) && (ecmp (b
, ezero
) == 0))
|| (eisinf (a
) && eisinf (b
)))
mtherr ("ediv", INVALID
);
/* Infinity over anything else is infinity. */
if (eisneg (a
) ^ eisneg (b
))
*(c
+ (NE
- 1)) = 0x8000;
/* Anything else over infinity is zero. */
{ /* See if numerator is zero. */
for (i
= 1; i
< NI
- 1; i
++)
{ /* possible divide by zero */
for (i
= 1; i
< NI
- 1; i
++)
*(c
+ (NE
- 1)) = 0x8000;
/* Divide by zero is not an invalid operation.
It is a divide-by-zero operation! */
emdnorm (bi
, i
, 0, lt
, 64);
; unsigned EMUSHORT a[NE], b[NE], c[NE];
; emul (a, b, c); c = b * a
unsigned EMUSHORT
*a
, *b
, *c
;
unsigned EMUSHORT ai
[NI
], bi
[NI
];
/* NaN times anything is the same NaN. */
/* Zero times infinity is a NaN. */
if ((eisinf (a
) && (ecmp (b
, ezero
) == 0))
|| (eisinf (b
) && (ecmp (a
, ezero
) == 0)))
mtherr ("emul", INVALID
);
/* Infinity times anything else is infinity. */
if (eisinf (a
) || eisinf (b
))
if (eisneg (a
) ^ eisneg (b
))
*(c
+ (NE
- 1)) = 0x8000;
for (i
= 1; i
< NI
- 1; i
++)
for (i
= 1; i
< NI
- 1; i
++)
/* Multiply significands */
lt
= lta
+ ltb
- (EXONE
- 1);
emdnorm (bi
, j
, 0, lt
, 64);
/* calculate sign of product */
; Convert IEEE double precision to e type
; unsigned EMUSHORT x[N+2];
unsigned EMUSHORT
*pe
, *y
;
dectoe (pe
, y
); /* see etodec.c */
register unsigned EMUSHORT r
;
register unsigned EMUSHORT
*e
, *p
;
unsigned EMUSHORT yy
[NI
];
denorm
= 0; /* flag if denormalized number */
yy
[M
] = (r
& 0x0f) | 0x10;
r
&= ~0x800f; /* strip sign and 4 significand bits */
if (((pe
[3] & 0xf) != 0) || (pe
[2] != 0)
|| (pe
[1] != 0) || (pe
[0] != 0))
if (((pe
[0] & 0xf) != 0) || (pe
[1] != 0)
|| (pe
[2] != 0) || (pe
[3] != 0))
/* If zero exponent, then the significand is denormalized.
* So, take back the understood high significand bit. */
{ /* if zero exponent, then normalize the significand */
if ((k
= enormlz (yy
)) > NBITS
)
yy
[E
] -= (unsigned EMUSHORT
) (k
- 1);
unsigned EMUSHORT
*pe
, *y
;
unsigned EMUSHORT yy
[NI
];
unsigned EMUSHORT
*e
, *p
, *q
;
for (i
= 0; i
< NE
- 5; i
++)
; Convert IEEE single precision to e type
; unsigned EMUSHORT x[N+2];
unsigned EMUSHORT
*pe
, *y
;
register unsigned EMUSHORT r
;
register unsigned EMUSHORT
*e
, *p
;
unsigned EMUSHORT yy
[NI
];
denorm
= 0; /* flag if denormalized number */
yy
[M
] = (r
& 0x7f) | 0200;
r
&= ~0x807f; /* strip sign and 7 significand bits */
if (((pe
[0] & 0x7f) != 0) || (pe
[1] != 0))
if (((pe
[1] & 0x7f) != 0) || (pe
[0] != 0))
/* If zero exponent, then the significand is denormalized.
* So, take back the understood high significand bit. */
{ /* if zero exponent, then normalize the significand */
if ((k
= enormlz (yy
)) > NBITS
)
yy
[E
] -= (unsigned EMUSHORT
) (k
- 1);
unsigned EMUSHORT
*x
, *e
;
unsigned EMUSHORT xi
[NI
];
/* adjust exponent for offset */
/* round off to nearest or even */
emdnorm (xi
, 0, 0, exp
, 64);
/* move out internal format to ieee long double */
unsigned EMUSHORT
*a
, *b
;
register unsigned EMUSHORT
*p
, *q
;
q
= b
+ 4; /* point to output exponent */
#if LONG_DOUBLE_TYPE_SIZE == 96
/* Clear the last two bytes of 12-byte Intel format */
/* combine sign and exponent */
/* skip over guard word */
/* move the significand */
; e type to IEEE double precision
; unsigned EMUSHORT x[NE];
unsigned EMUSHORT
*x
, *e
;
etodec (x
, e
); /* see etodec.c */
unsigned EMUSHORT
*x
, *y
;
unsigned EMUSHORT
*x
, *e
;
unsigned EMUSHORT xi
[NI
];
/* adjust exponent for offsets */
exp
= (EMULONG
) xi
[E
] - (EXONE
- 0x3ff);
/* round off to nearest or even */
emdnorm (xi
, 0, 0, exp
, 64);
unsigned EMUSHORT
*x
, *y
;
*y
= 0; /* output high order */
*y
= 0x8000; /* output sign bit */
if (i
>= (unsigned int) 2047)
{ /* Saturate at largest number less than infinity. */
*y
|= (unsigned EMUSHORT
) 0x7fef;
i
|= *p
++ & (unsigned EMUSHORT
) 0x0f; /* *p = xi[M] */
*y
|= (unsigned EMUSHORT
) i
; /* high order output already has sign bit set */
; e type to IEEE single precision
; unsigned EMUSHORT x[N+2];
unsigned EMUSHORT
*x
, *e
;
unsigned EMUSHORT xi
[NI
];
/* adjust exponent for offsets */
exp
= (EMULONG
) xi
[E
] - (EXONE
- 0177);
/* round off to nearest or even */
emdnorm (xi
, 0, 0, exp
, 64);
unsigned EMUSHORT
*x
, *y
;
*y
= 0; /* output high order */
*y
= 0x8000; /* output sign bit */
/* Handle overflow cases. */
*y
|= (unsigned EMUSHORT
) 0x7f80;
*y
|= (unsigned EMUSHORT
) 0x7f7f;
i
|= *p
++ & (unsigned EMUSHORT
) 0x7f; /* *p = xi[M] */
*y
|= i
; /* high order output already has sign bit set */
/* Compare two e type numbers.
* unsigned EMUSHORT a[NE], b[NE];
* -2 if either a or b is a NaN.
unsigned EMUSHORT
*a
, *b
;
unsigned EMUSHORT ai
[NI
], bi
[NI
];
register unsigned EMUSHORT
*p
, *q
;
if (eisnan (a
) || eisnan (b
))
{ /* the signs are different */
for (i
= 1; i
< NI
- 1; i
++)
/* both are the same sign */
return (0); /* equality */
return (msign
); /* p is bigger */
return (-msign
); /* p is littler */
/* Find nearest integer to x = floor (x + 0.5)
* unsigned EMUSHORT x[NE], y[NE]
unsigned EMUSHORT
*x
, *y
;
; convert long integer to e type
; unsigned EMUSHORT x[NE];
; note &l is the memory address of l
long *lp
; /* lp is the memory address of a long integer */
unsigned EMUSHORT
*y
; /* y is the address of a short */
unsigned EMUSHORT yi
[NI
];
ll
= (unsigned long) (-(*lp
));
yi
[0] = 0xffff; /* put correct sign in the e type number */
ll
= (unsigned long) (*lp
);
/* move the long integer to yi significand area */
#if HOST_BITS_PER_LONG == 64
yi
[M
] = (unsigned EMUSHORT
) (ll
>> 48);
yi
[M
+ 1] = (unsigned EMUSHORT
) (ll
>> 32);
yi
[M
+ 2] = (unsigned EMUSHORT
) (ll
>> 16);
yi
[M
+ 3] = (unsigned EMUSHORT
) ll
;
yi
[E
] = EXONE
+ 47; /* exponent if normalize shift count were 0 */
yi
[M
] = (unsigned EMUSHORT
) (ll
>> 16);
yi
[M
+ 1] = (unsigned EMUSHORT
) ll
;
yi
[E
] = EXONE
+ 15; /* exponent if normalize shift count were 0 */
if ((k
= enormlz (yi
)) > NBITS
)/* normalize the significand */
ecleaz (yi
); /* it was zero */
yi
[E
] -= (unsigned EMUSHORT
) k
;/* subtract shift count from exponent */
emovo (yi
, y
); /* output the answer */
; convert unsigned long integer to e type
; unsigned EMUSHORT x[NE];
; note &l is the memory address of l
unsigned long *lp
; /* lp is the memory address of a long integer */
unsigned EMUSHORT
*y
; /* y is the address of a short */
unsigned EMUSHORT yi
[NI
];
/* move the long integer to ayi significand area */
#if HOST_BITS_PER_LONG == 64
yi
[M
] = (unsigned EMUSHORT
) (ll
>> 48);
yi
[M
+ 1] = (unsigned EMUSHORT
) (ll
>> 32);
yi
[M
+ 2] = (unsigned EMUSHORT
) (ll
>> 16);
yi
[M
+ 3] = (unsigned EMUSHORT
) ll
;
yi
[E
] = EXONE
+ 47; /* exponent if normalize shift count were 0 */
yi
[M
] = (unsigned EMUSHORT
) (ll
>> 16);
yi
[M
+ 1] = (unsigned EMUSHORT
) ll
;
yi
[E
] = EXONE
+ 15; /* exponent if normalize shift count were 0 */
if ((k
= enormlz (yi
)) > NBITS
)/* normalize the significand */
ecleaz (yi
); /* it was zero */
yi
[E
] -= (unsigned EMUSHORT
) k
; /* subtract shift count from exponent */
emovo (yi
, y
); /* output the answer */
; Find long integer and fractional parts
; unsigned EMUSHORT x[NE], frac[NE];
The integer output has the sign of the input. The fraction is
the positive fractional part of abs (x).
unsigned EMUSHORT xi
[NI
];
k
= (int) xi
[E
] - (EXONE
- 1);
/* if exponent <= 0, integer = 0 and real output is fraction */
if (k
> (HOST_BITS_PER_LONG
- 1))
/* long integer overflow: output large integer
*i
= ((unsigned long) 1) << (HOST_BITS_PER_LONG
- 1);
*i
= (((unsigned long) 1) << (HOST_BITS_PER_LONG
- 1)) - 1;
warning ("overflow on truncation to integer");
/* Shift more than 16 bits: first shift up k-16 mod 16,
then shift up by 16's. */
/* shift not more than 16 bits */
*i
= (long) xi
[M
] & 0xffff;
if ((k
= enormlz (xi
)) > NBITS
)
xi
[E
] -= (unsigned EMUSHORT
) k
;
/* Find unsigned long integer and fractional parts.
A negative e type input yields integer output = 0
unsigned EMUSHORT xi
[NI
];
k
= (int) xi
[E
] - (EXONE
- 1);
/* if exponent <= 0, integer = 0 and argument is fraction */
if (k
> HOST_BITS_PER_LONG
)
/* Long integer overflow: output large integer
Note, the BSD microvax compiler says that ~(0UL)
warning ("overflow on truncation to unsigned integer");
/* Shift more than 16 bits: first shift up k-16 mod 16,
then shift up by 16's. */
/* shift not more than 16 bits */
*i
= (long) xi
[M
] & 0xffff;
if (xi
[0]) /* A negative value yields unsigned integer 0. */
if ((k
= enormlz (xi
)) > NBITS
)
xi
[E
] -= (unsigned EMUSHORT
) k
;
; Shifts significand area up or down by the number of bits
; given by the variable sc.
lost
|= *p
; /* remember lost bits */
; Shift normalizes the significand area pointed to by argument
; shift count (up = positive) is returned.
register unsigned EMUSHORT
*p
;
return (0); /* already normalized */
/* With guard word, there are NBITS+16 bits available.
* return true if all are zero.
/* see if high byte is zero */
while ((*p
& 0xff00) == 0)
/* now shift 1 bit at a time */
while ((*p
& 0x8000) == 0)
mtherr ("enormlz", UNDERFLOW
);
/* Normalize by shifting down out of the high guard word
mtherr ("enormlz", OVERFLOW
);
/* Convert e type number to decimal format ASCII string.
* The constants are for 64 bit precision.
static unsigned EMUSHORT etens
[NTEN
+ 1][NE
] =
{0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */
{0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */
{0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
{0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
{0xddbc, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
{0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
{0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
{0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
{0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
{0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
{0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
{0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
{0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */
static unsigned EMUSHORT emtens
[NTEN
+ 1][NE
] =
{0x2de4, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */
{0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */
{0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
{0x7133, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
{0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
{0xac7d, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
{0x3f24, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
{0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
{0x4c2f, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
{0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
{0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
{0x3d71, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
{0xcccd, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */
e24toasc (x
, string
, ndigs
)
etoasc (w
, string
, ndigs
);
e53toasc (x
, string
, ndigs
)
etoasc (w
, string
, ndigs
);
e64toasc (x
, string
, ndigs
)
etoasc (w
, string
, ndigs
);
static char wstring
[80]; /* working storage for ASCII output */
etoasc (x
, string
, ndigs
)
unsigned EMUSHORT y
[NI
], t
[NI
], u
[NI
], w
[NI
];
unsigned EMUSHORT
*p
, *r
, *ten
;
int i
, j
, k
, expon
, rndsav
;
sprintf (wstring
, " NaN ");
rndprc
= NBITS
; /* set to full precision */
emov (x
, y
); /* retain external format */
/* Test for zero exponent */
for (k
= 0; k
< NE
- 1; k
++)
goto tnzro
; /* denormalized number */
goto isone
; /* legal all zeros */
sprintf (wstring
, " -Infinity ");
sprintf (wstring
, " Infinity ");
/* Test for exponent nonzero but significand denormalized.
* This is an error condition.
if ((y
[NE
- 1] != 0) && ((y
[NE
- 2] & 0x8000) == 0))
mtherr ("etoasc", DOMAIN
);
sprintf (wstring
, "NaN");
{ /* Number is greater than 1 */
/* Convert significand to an integer and strip trailing decimal zeros. */
u
[NE
- 1] = EXONE
+ NBITS
- 1;
for (j
= 0; j
< NE
- 1; j
++)
/* Rescale from integer significand */
u
[NE
- 1] += y
[NE
- 1] - (unsigned int) (EXONE
+ NBITS
- 1);
/* An unordered compare result shouldn't happen here. */
while (ecmp (ten
, u
) <= 0)
{ /* Number is less than 1.0 */
/* Pad significand with trailing decimal zeros. */
while ((y
[NE
- 2] & 0x8000) == 0)
for (i
= 0; i
< NDEC
+ 1; i
++)
if ((w
[NI
- 1] & 0x7) != 0)
if (eone
[NE
- 1] <= u
[1])
while (ecmp (eone
, w
) > 0)
/* Find the first (leading) digit. */
while ((digit
== 0) && (ecmp (y
, ezero
) != 0))
/* Examine number of digits requested by caller. */
*s
++ = (char )digit
+ '0';
/* Generate digits after the decimal point. */
for (k
= 0; k
<= ndigs
; k
++)
/* multiply current number by 10, without normalizing */
*s
++ = (char) equot
[NI
- 1] + '0';
/* round off the ASCII string */
/* Test for critical rounding case in ASCII output. */
if (ecmp (t
, ezero
) != 0)
goto roun
; /* round to nearest */
goto doexp
; /* round to even */
/* Round up and propagate carry-outs */
/* Carry out to most significant digit? */
/* Most significant digit carries to 10? */
/* Round up and carry out from less significant digits */
sprintf (ss, "e+%d", expon);
sprintf (ss, "e%d", expon);
sprintf (ss
, "e%d", expon
);
/* copy out the working string */
while (*ss
== ' ') /* strip possible leading space */
while ((*s
++ = *ss
++) != '\0')
; ASCTOQ.MAC LATEST REV: 11 JAN 84
; Convert ASCII string to quadruple precision floating point
; Numeric input is free field decimal number
; with max of 15 digits with or without
; decimal point entered as ASCII from teletype.
; Entering E after the number followed by a second
; number causes the second number to be interpreted
; as a power of 10 to be multiplied by the first number
; (i.e., "scientific" notation).
/* ASCII to long double */
/* ASCII to super double */
/* Space to make a copy of the input string: */
unsigned EMUSHORT yy
[NI
], xt
[NI
], tt
[NI
];
int esign
, decflg
, sgnflg
, nexp
, exp
, prec
, lost
;
unsigned EMUSHORT nsign
, *p
;
/* Copy the input string. */
while (*s
== ' ') /* skip leading spaces */
if ((*sp
++ = *s
++) == '\0')
rndprc
= NBITS
; /* Set to full precision */
if ((k
>= 0) && (k
<= 9))
/* Ignore leading zeros */
if ((prec
== 0) && (decflg
== 0) && (k
== 0))
/* Identify and strip trailing zeros after the decimal point. */
if ((trail
== 0) && (decflg
!= 0))
while ((*sp
>= '0') && (*sp
<= '9'))
/* Check for syntax error */
if ((c
!= 'e') && (c
!= 'E') && (c
!= '\0')
&& (c
!= '\n') && (c
!= '\r') && (c
!= ' ')
/* If enough digits were given to more than fill up the yy register,
* continuing until overflow into the high guard word yy[2]
* guarantees that there will be a roundoff bit at the top
* of the low guard word after normalization.
nexp
+= 1; /* count digits after decimal point */
eshup1 (yy
); /* multiply current number by 10 */
xt
[NI
- 2] = (unsigned EMUSHORT
) k
;
case '.': /* decimal point */
mtherr ("asctoe", DOMAIN
);
/* Exponent interpretation */
while ((*s
>= '0') && (*s
<= '9'))
yy
[E
] = 0x7fff; /* infinity */
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
while ((nexp
> 0) && (yy
[2] == 0))
if ((k
= enormlz (yy
)) > NBITS
)
lexp
= (EXONE
- 1 + NBITS
) - k
;
emdnorm (yy
, lost
, 0, lexp
, 64);
/* convert to external format */
/* Multiply by 10**nexp. If precision is 64 bits,
* the maximum relative error incurred in forming 10**n
* for 0 <= n <= 324 is 8.2e-20, at 10**180.
* For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947.
* For 0 >= n >= -999, it is -1.55e-19 at 10**-435.
{ /* Punt. Can't handle this without 2 divides. */
/* Round and convert directly to the destination type */
emdnorm (yy
, k
, 0, lexp
, 64);
todec (yy
, y
); /* see etodec.c */
/* y = largest integer not greater than x
* (truncated toward minus infinity)
* unsigned EMUSHORT x[NE], y[NE]
static unsigned EMUSHORT bmask
[] =
unsigned EMUSHORT x
[], y
[];
register unsigned EMUSHORT
*p
;
emov (x
, f
); /* leave in external format */
e
= (expon
& 0x7fff) - (EXONE
- 1);
/* number of bits to clear out */
/* clear the remaining bits */
/* truncate negatives toward minus infinity */
if ((unsigned EMUSHORT
) expon
& (unsigned EMUSHORT
) 0x8000)
for (i
= 0; i
< NE
- 1; i
++)
/* unsigned EMUSHORT x[], s[];
* Returns s and exp such that s * 2**exp = x and .5 <= s < 1.
* For example, 1.1 = 0.55 * 2**1
* Handles denormalized numbers properly using long integer exp.
unsigned EMUSHORT xi
[NI
];
li
= (EMULONG
) ((EMUSHORT
) xi
[1]);
*exp
= (int) (li
- 0x3ffe);
/* unsigned EMUSHORT x[], y[];
* Returns y = x * 2**pwr2.
unsigned EMUSHORT xi
[NI
];
emdnorm (xi
, i
, i
, li
, 64);
/* c = remainder after dividing b by a
* Least significant integer quotient bits left in equot[].
unsigned EMUSHORT a
[], b
[], c
[];
unsigned EMUSHORT den
[NI
], num
[NI
];
|| (ecmp (a
, ezero
) == 0)
if (ecmp (a
, ezero
) == 0)
mtherr ("eremain", SING
);
/* Sign of remainder = sign of quotient */
unsigned EMUSHORT den
[], num
[];
if (ecmpm (den
, num
) <= 0)
emdnorm (num
, 0, 0, ln
, 0);
* Library common error handling routine
* This routine may be called to report one of the following
* error conditions (in the include file mconf.h).
* Mnemonic Value Significance
* DOMAIN 1 argument domain error
* SING 2 function singularity
* OVERFLOW 3 overflow range error
* UNDERFLOW 4 underflow range error
* TLOSS 5 total loss of precision
* PLOSS 6 partial loss of precision
* INVALID 7 NaN - producing operation
* EDOM 33 Unix domain error code
* ERANGE 34 Unix range error code
* The default version of the file prints the function name,
* passed to it by the pointer fctnam, followed by the
* error condition. The display is directed to the standard
* output device. The routine then returns to the calling
* program. Users may wish to modify the program to abort by
* calling exit under severe error conditions such as domain
* Since all error conditions pass control to this function,
* the display may be easily changed, eliminated, or directed
* to an error logging device.
Cephes Math Library Release 2.0: April, 1987
Copyright 1984, 1987 by Stephen L. Moshier
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
/* Notice: the order of appearance of the following
* messages is bound to the error codes defined
static char *ermsg
[NMSGS
] =
"unknown", /* error code 0 */
"domain", /* error code 1 */
"singularity", /* et seq. */
"total loss of precision",
"partial loss of precision",
/* Display string passed by calling program,
* which is supposed to be the name of the
* function in which the error occurred.
/* Display error message defined
if ((code
<= 0) || (code
>= NMSGS
))
sprintf (errstr
, " %s %s error", name
, ermsg
[code
]);
/* Set global error message word */
; convert DEC double precision to e type
register unsigned EMUSHORT r
, *p
;
ecleaz (y
); /* start with a zero */
p
= y
; /* point to our number */
r
= *d
; /* get DEC exponent word */
if (*d
& (unsigned int) 0x8000)
*p
= 0xffff; /* fill in our sign */
++p
; /* bump pointer to our exponent word */
r
&= 0x7fff; /* strip the sign bit */
if (r
== 0) /* answer = 0 if high order DEC word = 0 */
r
>>= 7; /* shift exponent word down 7 bits */
r
+= EXONE
- 0201; /* subtract DEC exponent offset */
/* add our e type exponent offset */
*p
++ = r
; /* to form our exponent */
r
= *d
++; /* now do the high order mantissa */
r
&= 0177; /* strip off the DEC exponent and sign bits */
r
|= 0200; /* the DEC understood high order mantissa bit */
*p
++ = r
; /* put result in our high guard word */
*p
++ = *d
++; /* fill in the rest of our mantissa */
eshdn8 (y
); /* shift our mantissa down 8 bits */
; convert e type to DEC double precision
static unsigned EMUSHORT decbit
[NI
] = {0, 0, 0, 0, 0, 0, 0200, 0};
unsigned EMUSHORT
*x
, *d
;
unsigned EMUSHORT xi
[NI
];
register unsigned EMUSHORT r
;
/* check all less significant bits */
for (j
= M
+ 5; j
< NI
; j
++)
unsigned EMUSHORT
*x
, *d
;
unsigned EMUSHORT xi
[NI
];
exp
= (EMULONG
) xi
[E
] - (EXONE
- 0201); /* adjust exponent for offsets */
/* round off to nearest or even */
emdnorm (xi
, 0, 0, exp
, 64);
unsigned EMUSHORT
*x
, *y
;
/* Output a binary NaN bit pattern in the target machine's format. */
/* If special NaN bit patterns are required, define them in tm.h
as arrays of unsigned 16-bit shorts. Otherwise, use the default
unsigned EMUSHORT TFnan
[8] =
{0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
unsigned EMUSHORT TFnan
[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0xffff};
unsigned EMUSHORT XFnan
[6] = {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
unsigned EMUSHORT XFnan
[6] = {0, 0, 0, 0xc000, 0xffff, 0};
unsigned EMUSHORT DFnan
[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
unsigned EMUSHORT DFnan
[4] = {0, 0, 0, 0xfff8};
unsigned EMUSHORT SFnan
[2] = {0x7fff, 0xffff};
unsigned EMUSHORT SFnan
[2] = {0, 0xffc0};
/* Possibly the `reserved operand' patterns on a VAX can be
used like NaN's, but probably not in the same way as IEEE. */
/* Convert an SFmode target `float' value to a REAL_VALUE_TYPE.
This is the inverse of the function `etarsingle' invoked by
REAL_VALUE_TO_TARGET_SINGLE. */
/* Convert 32 bit integer to array of 16 bit pieces in target machine order.
This is the inverse operation to what the function `endian' does. */
s
[0] = (unsigned EMUSHORT
) (f
>> 16);
s
[1] = (unsigned EMUSHORT
) f
;
s
[0] = (unsigned EMUSHORT
) f
;
s
[1] = (unsigned EMUSHORT
) (f
>> 16);
/* Convert and promote the target float to E-type. */
/* Output E-type to REAL_VALUE_TYPE. */
/* Convert a DFmode target `double' value to a REAL_VALUE_TYPE.
This is the inverse of the function `etardouble' invoked by
REAL_VALUE_TO_TARGET_DOUBLE.
The DFmode is stored as an array of longs (i.e., HOST_WIDE_INTs)
with 32 bits of the value per each long. The first element
of the input array holds the bits that would come first in the
target computer's memory. */
/* Convert array of 32 bit pieces to equivalent array of 16 bit pieces.
This is the inverse of `endian'. */
s
[0] = (unsigned EMUSHORT
) (d
[0] >> 16);
s
[1] = (unsigned EMUSHORT
) d
[0];
s
[2] = (unsigned EMUSHORT
) (d
[1] >> 16);
s
[3] = (unsigned EMUSHORT
) d
[1];
s
[0] = (unsigned EMUSHORT
) d
[0];
s
[1] = (unsigned EMUSHORT
) (d
[0] >> 16);
s
[2] = (unsigned EMUSHORT
) d
[1];
s
[3] = (unsigned EMUSHORT
) (d
[1] >> 16);
/* Convert target double to E-type. */
/* Output E-type to REAL_VALUE_TYPE. */
#endif /* EMU_NON_COMPILE not defined */