home *** CD-ROM | disk | FTP | other *** search
- /* 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)
- any later version.
-
- 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. */
-
- #include <stdio.h>
- #include <errno.h>
- #include "config.h"
- #include "tree.h"
-
- #ifndef errno
- extern int errno;
- #endif
-
- /* 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, VAX and IBM 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
- real.h).
-
- 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, IBM, 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.
-
- `IBM' refers specifically to the IBM System/370 and compatible
- floating point data structure. This model currently supports
- no type wider than DFmode. The IBM conversions were contributed by
- frank@atom.ansto.gov.au (Frank Crawford).
-
- 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
- #define REAL_ARITHMETIC
- in tm.h.
-
- The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support
- and may deactivate XFmode since `long double' is used to refer
- to both modes.
-
- The macros FLOAT_WORDS_BIG_ENDIAN, HOST_FLOAT_WORDS_BIG_ENDIAN,
- contributed by Richard Earnshaw <Richard.Earnshaw@cl.cam.ac.uk>,
- separate the floating point unit's endian-ness from that of
- the integer addressing. This permits one to define a big-endian
- FPU on a little-endian machine (e.g., ARM). An extension to
- BYTES_BIG_ENDIAN may be required for some machines in the future.
- These optional macros may be defined in tm.h. In real.h, they
- default to WORDS_BIG_ENDIAN, etc., so there is no need to define
- them for any normal host or target machine on which the floats
- and the integers have the same endian-ness. */
-
-
- /* 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. */
- #ifdef REAL_ARITHMETIC
-
- #if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
- /* PDP-11, Pro350, VAX: */
- #define DEC 1
- #else /* it's not VAX */
- #if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
- /* IBM System/370 style */
- #define IBM 1
- #else /* it's also not an IBM */
- #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- #if FLOAT_WORDS_BIG_ENDIAN
- /* Motorola IEEE, high order words come first (Sun workstation): */
- #define MIEEE 1
- #else /* not big-endian */
- /* Intel IEEE, low order words come first:
- */
- #define IBMPC 1
- #endif /* big-endian */
- #else /* it's not IEEE either */
- /* UNKnown arithmetic. We don't support this and can't go on. */
- unknown arithmetic type
- #define UNK 1
- #endif /* not IEEE */
- #endif /* not IBM */
- #endif /* not VAX */
-
- #else
- /* 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
- #define DEC 1
- #else /* it's not VAX */
- #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
- /* IBM System/370 style */
- #define IBM 1
- #else /* it's also not an IBM */
- #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- #if HOST_FLOAT_WORDS_BIG_ENDIAN
- #define MIEEE 1
- #else /* not big-endian */
- #define IBMPC 1
- #endif /* big-endian */
- #else /* it's not IEEE either */
- unknown arithmetic type
- #define UNK 1
- #endif /* not IEEE */
- #endif /* not IBM */
- #endif /* not VAX */
-
- #endif /* REAL_ARITHMETIC not defined */
-
- /* Define INFINITY for support of infinity.
- Define NANS for support of Not-a-Number's (NaN's). */
- #if !defined(DEC) && !defined(IBM)
- #define INFINITY
- #define NANS
- #endif
-
- /* Support of NaNs requires support of infinity. */
- #ifdef NANS
- #ifndef INFINITY
- #define INFINITY
- #endif
- #endif
-
- /* 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 char
- #define EMUSHORT_SIZE HOST_BITS_PER_CHAR
- #define EMULONG_SIZE (2 * HOST_BITS_PER_CHAR)
- #else
- #if HOST_BITS_PER_SHORT >= 16
- #define EMUSHORT short
- #define EMUSHORT_SIZE HOST_BITS_PER_SHORT
- #define EMULONG_SIZE (2 * HOST_BITS_PER_SHORT)
- #else
- #if HOST_BITS_PER_INT >= 16
- #define EMUSHORT int
- #define EMUSHORT_SIZE HOST_BITS_PER_INT
- #define EMULONG_SIZE (2 * HOST_BITS_PER_INT)
- #else
- #if HOST_BITS_PER_LONG >= 16
- #define EMUSHORT long
- #define EMUSHORT_SIZE HOST_BITS_PER_LONG
- #define EMULONG_SIZE (2 * HOST_BITS_PER_LONG)
- #else
- /* You will have to modify this program to have a smaller unit size. */
- #define EMU_NON_COMPILE
- #endif
- #endif
- #endif
- #endif
-
- #if HOST_BITS_PER_SHORT >= EMULONG_SIZE
- #define EMULONG short
- #else
- #if HOST_BITS_PER_INT >= EMULONG_SIZE
- #define EMULONG int
- #else
- #if HOST_BITS_PER_LONG >= EMULONG_SIZE
- #define EMULONG long
- #else
- #if HOST_BITS_PER_LONG_LONG >= EMULONG_SIZE
- #define EMULONG long long int
- #else
- /* You will have to modify this program to have a smaller unit size. */
- #define EMU_NON_COMPILE
- #endif
- #endif
- #endif
- #endif
-
-
- /* The host interface doesn't work if no 16-bit size exists. */
- #if EMUSHORT_SIZE != 16
- #define EMU_NON_COMPILE
- #endif
-
- /* OK to continue compilation. */
- #ifndef EMU_NON_COMPILE
-
- /* 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
- /* Number of 16 bit words in external e type format */
- #define NE 6
- #define MAXDECEXP 4932
- #define MINDECEXP -4956
- #define GET_REAL(r,e) bcopy (r, e, 2*NE)
- #define PUT_REAL(e,r) bcopy (e, r, 2*NE)
- #else /* no XFmode */
- #if LONG_DOUBLE_TYPE_SIZE == 128
- #define NE 10
- #define MAXDECEXP 4932
- #define MINDECEXP -4977
- #define GET_REAL(r,e) bcopy (r, e, 2*NE)
- #define PUT_REAL(e,r) bcopy (e, r, 2*NE)
- #else
- #define NE 6
- #define MAXDECEXP 4932
- #define MINDECEXP -4956
- #ifdef REAL_ARITHMETIC
- /* Emulator uses target format internally
- but host stores it in host endian-ness. */
-
- #if HOST_FLOAT_WORDS_BIG_ENDIAN == FLOAT_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 */
- #define GET_REAL(r,e) \
- do { EMUSHORT w[4]; \
- 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)
-
- #define PUT_REAL(e,r) \
- do { EMUSHORT w[4]; \
- etoe53 ((e), w); \
- *((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 */
- #endif /* not TFmode */
- #endif /* no XFmode */
-
-
- /* Number of 16 bit words in internal format */
- #define NI (NE+3)
-
- /* Array offset to exponent */
- #define E 1
-
- /* Array offset to high guard word */
- #define M 2
-
- /* Number of bits of precision */
- #define NBITS ((NI-4)*16)
-
- /* Maximum number of decimal digits in ASCII conversion
- * = NBITS*log10(2)
- */
- #define NDEC (NBITS*8/27)
-
- /* The exponent of 1.0 */
- #define EXONE (0x3fff)
-
- void warning ();
- 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 ereal_to_decimal (), eiinfin (), einan ();
- void esqrt (), elog (), eexp (), etanh (), epow ();
- void asctoe (), asctoe24 (), asctoe53 (), asctoe64 (), asctoe113 ();
- void etoasc (), e24toasc (), e53toasc (), e64toasc (), e113toasc ();
- void etoe64 (), etoe53 (), etoe24 (), e64toe (), e53toe (), e24toe ();
- void etoe113 (), e113toe ();
- void mtherr (), make_nan ();
- void enan ();
- extern unsigned EMUSHORT ezero[], ehalf[], eone[], etwo[];
- extern unsigned EMUSHORT elog2[], esqrt2[];
-
- /* Copy 32-bit numbers obtained from array containing 16-bit numbers,
- swapping ends if required, into output array of longs. The
- result is normally passed to fprintf by the ASM_OUTPUT_ macros. */
- void
- endian (e, x, mode)
- unsigned EMUSHORT e[];
- long x[];
- enum machine_mode mode;
- {
- unsigned long th, t;
-
- #if FLOAT_WORDS_BIG_ENDIAN
- switch (mode)
- {
-
- case TFmode:
- /* Swap halfwords in the fourth long. */
- th = (unsigned long) e[6] & 0xffff;
- t = (unsigned long) e[7] & 0xffff;
- t |= th << 16;
- x[3] = (long) t;
-
- case XFmode:
-
- /* Swap halfwords in the third long. */
- th = (unsigned long) e[4] & 0xffff;
- t = (unsigned long) e[5] & 0xffff;
- t |= th << 16;
- x[2] = (long) t;
- /* fall into the double case */
-
- case DFmode:
-
- /* swap halfwords in the second word */
- th = (unsigned long) e[2] & 0xffff;
- t = (unsigned long) e[3] & 0xffff;
- t |= th << 16;
- x[1] = (long) t;
- /* fall into the float case */
-
- case SFmode:
-
- /* swap halfwords in the first word */
- th = (unsigned long) e[0] & 0xffff;
- t = (unsigned long) e[1] & 0xffff;
- t |= th << 16;
- x[0] = t;
- break;
-
- default:
- abort ();
- }
-
- #else
-
- /* Pack the output array without swapping. */
-
- switch (mode)
- {
-
- case TFmode:
-
- /* Pack the fourth long. */
- th = (unsigned long) e[7] & 0xffff;
- t = (unsigned long) e[6] & 0xffff;
- t |= th << 16;
- x[3] = (long) t;
-
- case XFmode:
-
- /* Pack the third long.
- Each element of the input REAL_VALUE_TYPE array has 16 useful bits
- in it. */
- th = (unsigned long) e[5] & 0xffff;
- t = (unsigned long) e[4] & 0xffff;
- t |= th << 16;
- x[2] = (long) t;
- /* fall into the double case */
-
- case DFmode:
-
- /* pack the second long */
- th = (unsigned long) e[3] & 0xffff;
- t = (unsigned long) e[2] & 0xffff;
- t |= th << 16;
- x[1] = (long) t;
- /* fall into the float case */
-
- case SFmode:
-
- /* pack the first long */
- th = (unsigned long) e[1] & 0xffff;
- t = (unsigned long) e[0] & 0xffff;
- t |= th << 16;
- x[0] = t;
- break;
-
- default:
- abort ();
- }
-
- #endif
- }
-
-
- /* This is the implementation of the REAL_ARITHMETIC macro.
- */
- void
- earith (value, icode, r1, r2)
- REAL_VALUE_TYPE *value;
- int icode;
- REAL_VALUE_TYPE *r1;
- REAL_VALUE_TYPE *r2;
- {
- unsigned EMUSHORT d1[NE], d2[NE], v[NE];
- enum tree_code code;
-
- GET_REAL (r1, d1);
- GET_REAL (r2, d2);
- #ifdef NANS
- /* Return NaN input back to the caller. */
- if (eisnan (d1))
- {
- PUT_REAL (d1, value);
- return;
- }
- if (eisnan (d2))
- {
- PUT_REAL (d2, value);
- return;
- }
- #endif
- code = (enum tree_code) icode;
- switch (code)
- {
- case PLUS_EXPR:
- eadd (d2, d1, v);
- break;
-
- case MINUS_EXPR:
- esub (d2, d1, v); /* d1 - d2 */
- break;
-
- case MULT_EXPR:
- emul (d2, d1, v);
- break;
-
- case RDIV_EXPR:
- #ifndef REAL_INFINITY
- if (ecmp (d2, ezero) == 0)
- {
- #ifdef NANS
- enan (v);
- break;
- #else
- abort ();
- #endif
- }
- #endif
- ediv (d2, d1, v); /* d1/d2 */
- break;
-
- case MIN_EXPR: /* min (d1,d2) */
- if (ecmp (d1, d2) < 0)
- emov (d1, v);
- else
- emov (d2, v);
- break;
-
- case MAX_EXPR: /* max (d1,d2) */
- if (ecmp (d1, d2) > 0)
- emov (d1, v);
- else
- emov (d2, v);
- break;
- default:
- emov (ezero, v);
- break;
- }
- PUT_REAL (v, value);
- }
-
-
- /* Truncate REAL_VALUE_TYPE toward zero to signed HOST_WIDE_INT
- * implements REAL_VALUE_RNDZINT (x) (etrunci (x))
- */
- REAL_VALUE_TYPE
- etrunci (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT f[NE], g[NE];
- REAL_VALUE_TYPE r;
- HOST_WIDE_INT l;
-
- GET_REAL (&x, g);
- #ifdef NANS
- if (eisnan (g))
- return (x);
- #endif
- eifrac (g, &l, f);
- ltoe (&l, g);
- PUT_REAL (g, &r);
- return (r);
- }
-
-
- /* Truncate REAL_VALUE_TYPE toward zero to unsigned HOST_WIDE_INT
- * implements REAL_VALUE_UNSIGNED_RNDZINT (x) (etruncui (x))
- */
- REAL_VALUE_TYPE
- etruncui (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT f[NE], g[NE];
- REAL_VALUE_TYPE r;
- unsigned HOST_WIDE_INT l;
-
- GET_REAL (&x, g);
- #ifdef NANS
- if (eisnan (g))
- return (x);
- #endif
- euifrac (g, &l, f);
- ultoe (&l, g);
- PUT_REAL (g, &r);
- return (r);
- }
-
-
- /* 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.
- */
- REAL_VALUE_TYPE
- ereal_atof (s, t)
- char *s;
- enum machine_mode t;
- {
- unsigned EMUSHORT tem[NE], e[NE];
- REAL_VALUE_TYPE r;
-
- switch (t)
- {
- case SFmode:
- asctoe24 (s, tem);
- e24toe (tem, e);
- break;
- case DFmode:
- asctoe53 (s, tem);
- e53toe (tem, e);
- break;
- case XFmode:
- asctoe64 (s, tem);
- e64toe (tem, e);
- break;
- case TFmode:
- asctoe113 (s, tem);
- e113toe (tem, e);
- break;
- default:
- asctoe (s, e);
- }
- PUT_REAL (e, &r);
- return (r);
- }
-
-
- /* Expansion of REAL_NEGATE.
- */
- REAL_VALUE_TYPE
- ereal_negate (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT e[NE];
- REAL_VALUE_TYPE r;
-
- GET_REAL (&x, e);
- #ifdef NANS
- if (eisnan (e))
- return (x);
- #endif
- eneg (e);
- PUT_REAL (e, &r);
- return (r);
- }
-
-
- /* Round real toward zero to HOST_WIDE_INT
- * implements REAL_VALUE_FIX (x).
- */
- HOST_WIDE_INT
- efixi (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT f[NE], g[NE];
- HOST_WIDE_INT l;
-
- GET_REAL (&x, f);
- #ifdef NANS
- if (eisnan (f))
- {
- warning ("conversion from NaN to int");
- return (-1);
- }
- #endif
- eifrac (f, &l, g);
- return l;
- }
-
- /* Round real toward zero to unsigned HOST_WIDE_INT
- * implements REAL_VALUE_UNSIGNED_FIX (x).
- * Negative input returns zero.
- */
- unsigned HOST_WIDE_INT
- efixui (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT f[NE], g[NE];
- unsigned HOST_WIDE_INT l;
-
- GET_REAL (&x, f);
- #ifdef NANS
- if (eisnan (f))
- {
- warning ("conversion from NaN to unsigned int");
- return (-1);
- }
- #endif
- euifrac (f, &l, g);
- return l;
- }
-
-
- /* REAL_VALUE_FROM_INT macro.
- */
- void
- ereal_from_int (d, i, j)
- REAL_VALUE_TYPE *d;
- HOST_WIDE_INT i, j;
- {
- unsigned EMUSHORT df[NE], dg[NE];
- HOST_WIDE_INT low, high;
- int sign;
-
- sign = 0;
- low = i;
- if ((high = j) < 0)
- {
- sign = 1;
- /* complement and add 1 */
- high = ~high;
- if (low)
- low = -low;
- else
- high += 1;
- }
- eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
- ultoe (&high, dg);
- emul (dg, df, dg);
- ultoe (&low, df);
- eadd (df, dg, dg);
- if (sign)
- eneg (dg);
- PUT_REAL (dg, d);
- }
-
-
- /* REAL_VALUE_FROM_UNSIGNED_INT macro.
- */
- void
- ereal_from_uint (d, i, j)
- REAL_VALUE_TYPE *d;
- unsigned HOST_WIDE_INT i, j;
- {
- unsigned EMUSHORT df[NE], dg[NE];
- unsigned HOST_WIDE_INT low, high;
-
- low = i;
- high = j;
- eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
- ultoe (&high, dg);
- emul (dg, df, dg);
- ultoe (&low, df);
- eadd (df, dg, dg);
- PUT_REAL (dg, d);
- }
-
-
- /* REAL_VALUE_TO_INT macro
- */
- void
- ereal_to_int (low, high, rr)
- HOST_WIDE_INT *low, *high;
- REAL_VALUE_TYPE rr;
- {
- unsigned EMUSHORT d[NE], df[NE], dg[NE], dh[NE];
- int s;
-
- GET_REAL (&rr, d);
- #ifdef NANS
- if (eisnan (d))
- {
- warning ("conversion from NaN to int");
- *low = -1;
- *high = -1;
- return;
- }
- #endif
- /* convert positive value */
- s = 0;
- if (eisneg (d))
- {
- eneg (d);
- s = 1;
- }
- eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
- ediv (df, d, dg); /* dg = d / 2^32 is the high word */
- euifrac (dg, high, dh);
- emul (df, dh, dg); /* fractional part is the low word */
- euifrac (dg, low, dh);
- if (s)
- {
- /* complement and add 1 */
- *high = ~(*high);
- if (*low)
- *low = -(*low);
- else
- *high += 1;
- }
- }
-
-
- /* REAL_VALUE_LDEXP macro.
- */
- REAL_VALUE_TYPE
- ereal_ldexp (x, n)
- REAL_VALUE_TYPE x;
- int n;
- {
- unsigned EMUSHORT e[NE], y[NE];
- REAL_VALUE_TYPE r;
-
- GET_REAL (&x, e);
- #ifdef NANS
- if (eisnan (e))
- return (x);
- #endif
- eldexp (e, n, y);
- PUT_REAL (y, &r);
- return (r);
- }
-
- /* These routines are conditionally compiled because functions
- * of the same names may be defined in fold-const.c. */
- #ifdef REAL_ARITHMETIC
-
- /* Check for infinity in a REAL_VALUE_TYPE. */
- int
- target_isinf (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT e[NE];
-
- #ifdef INFINITY
- GET_REAL (&x, e);
- return (eisinf (e));
- #else
- return 0;
- #endif
- }
-
-
- /* Check whether a REAL_VALUE_TYPE item is a NaN. */
-
- int
- target_isnan (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT e[NE];
-
- #ifdef NANS
- GET_REAL (&x, e);
- return (eisnan (e));
- #else
- return (0);
- #endif
- }
-
-
- /* Check for a negative REAL_VALUE_TYPE number.
- * this means strictly less than zero, not -0.
- */
-
- int
- target_negative (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT e[NE];
-
- GET_REAL (&x, e);
- if (ecmp (e, ezero) == -1)
- return (1);
- return (0);
- }
-
- /* Expansion of REAL_VALUE_TRUNCATE.
- * The result is in floating point, rounded to nearest or even.
- */
- REAL_VALUE_TYPE
- real_value_truncate (mode, arg)
- enum machine_mode mode;
- REAL_VALUE_TYPE arg;
- {
- unsigned EMUSHORT e[NE], t[NE];
- REAL_VALUE_TYPE r;
-
- GET_REAL (&arg, e);
- #ifdef NANS
- if (eisnan (e))
- return (arg);
- #endif
- eclear (t);
- switch (mode)
- {
- case TFmode:
- etoe113 (e, t);
- e113toe (t, t);
- break;
-
- case XFmode:
- etoe64 (e, t);
- e64toe (t, t);
- break;
-
- case DFmode:
- etoe53 (e, t);
- e53toe (t, t);
- break;
-
- case SFmode:
- etoe24 (e, t);
- e24toe (t, t);
- break;
-
- case SImode:
- r = etrunci (arg);
- return (r);
-
- default:
- abort ();
- }
- PUT_REAL (t, &r);
- return (r);
- }
-
- #endif /* REAL_ARITHMETIC defined */
-
- /* Used for debugging--print the value of R in human-readable format
- on stderr. */
-
- void
- debug_real (r)
- REAL_VALUE_TYPE r;
- {
- char dstr[30];
-
- REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);
- fprintf (stderr, "%s", dstr);
- }
-
-
- /* Target values are arrays of host longs. A long is guaranteed
- to be at least 32 bits wide. */
-
- /* 128-bit long double */
- void
- etartdouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
- {
- unsigned EMUSHORT e[NE];
-
- GET_REAL (&r, e);
- etoe113 (e, e);
- endian (e, l, TFmode);
- }
-
- /* 80-bit long double */
- void
- etarldouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
- {
- unsigned EMUSHORT e[NE];
-
- GET_REAL (&r, e);
- etoe64 (e, e);
- endian (e, l, XFmode);
- }
-
- void
- etardouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
- {
- unsigned EMUSHORT e[NE];
-
- GET_REAL (&r, e);
- etoe53 (e, e);
- endian (e, l, DFmode);
- }
-
- long
- etarsingle (r)
- REAL_VALUE_TYPE r;
- {
- unsigned EMUSHORT e[NE];
- unsigned long l;
-
- GET_REAL (&r, e);
- etoe24 (e, e);
- endian (e, &l, SFmode);
- return ((long) l);
- }
-
- void
- ereal_to_decimal (x, s)
- REAL_VALUE_TYPE x;
- char *s;
- {
- unsigned EMUSHORT e[NE];
-
- GET_REAL (&x, e);
- etoasc (e, s, 20);
- }
-
- int
- ereal_cmp (x, y)
- REAL_VALUE_TYPE x, y;
- {
- unsigned EMUSHORT ex[NE], ey[NE];
-
- GET_REAL (&x, ex);
- GET_REAL (&y, ey);
- return (ecmp (ex, ey));
- }
-
- int
- ereal_isneg (x)
- REAL_VALUE_TYPE x;
- {
- unsigned EMUSHORT ex[NE];
-
- GET_REAL (&x, ex);
- return (eisneg (ex));
- }
-
- /* End of REAL_ARITHMETIC interface */
-
- /* ieee.c
- *
- * 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
- * the arrays.
- *
- *
- * 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,
- * top bit is the sign)
- *
- *
- * 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)
- * ei[3]
- * 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
- * e113toe (&d, e) 128-bit long double precision to e type
- * eabs (e) absolute value
- * eadd (a, b, c) c = b + a
- * eclear (e) e = 0
- * 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 HOST_WIDE_INT and e type fraction
- * euifrac (e, &l, frac) e to unsigned HOST_WIDE_INT and e type fraction
- * einfin (e) set e to infinity, leaving its sign alone
- * eldexp (a, n, b) multiply by 2**n
- * emov (a, b) b = a
- * emul (a, b, c) c = b * a
- * eneg (e) e = -e
- * 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) 80-bit long double to ASCII string
- * e113toasc (&d, str, n) 128-bit 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) HOST_WIDE_INT to e type
- * ultoe (&l, e) unsigned HOST_WIDE_INT to e type
- * eisneg (e) 1 if sign bit of e != 0, else 0
- * eisinf (e) 1 if e has maximum exponent (non-IEEE)
- * or is infinite (IEEE)
- * eisnan (e) 1 if e is a NaN
- *
- *
- * Routines for internal format numbers
- *
- * eaddm (ai, bi) add significands, bi = bi + ai
- * ecleaz (ei) ei = 0
- * 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
- * as quiet NaN's.
- *
- * 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
- * by a NaN input.
- * 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'
- * if in doubt.
- *
- * Denormals are always supported here where appropriate (e.g., not
- * for conversion to DEC numbers).
- *
- */
-
-
- /* mconf.h
- *
- * Common include file for math routines
- *
- *
- *
- * SYNOPSIS:
- *
- * #include "mconf.h"
- *
- *
- *
- * DESCRIPTION:
- *
- * This file contains definitions for error codes that are
- * passed to the common error handling routine mtherr
- * (which see).
- *
- * The file also includes a conditional assembly definition
- * for the type of computer arithmetic (Intel IEEE, DEC, Motorola
- * IEEE, or UNKnown).
- *
- * 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 */
-
- #if LONG_DOUBLE_TYPE_SIZE == 128
- /* 0.0 */
- unsigned EMUSHORT ezero[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
- extern unsigned EMUSHORT ezero[];
-
- /* 5.0E-1 */
- unsigned EMUSHORT ehalf[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3ffe,};
- extern unsigned EMUSHORT ehalf[];
-
- /* 1.0E0 */
- unsigned EMUSHORT eone[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
- extern unsigned EMUSHORT eone[];
-
- /* 2.0E0 */
- unsigned EMUSHORT etwo[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4000,};
- extern unsigned EMUSHORT etwo[];
-
- /* 3.2E1 */
- unsigned EMUSHORT e32[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4004,};
- extern unsigned EMUSHORT e32[];
-
- /* 6.93147180559945309417232121458176568075500134360255E-1 */
- unsigned EMUSHORT elog2[NE] =
- {0x40f3, 0xf6af, 0x03f2, 0xb398,
- 0xc9e3, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
- extern unsigned EMUSHORT elog2[];
-
- /* 1.41421356237309504880168872420969807856967187537695E0 */
- unsigned EMUSHORT esqrt2[NE] =
- {0x1d6f, 0xbe9f, 0x754a, 0x89b3,
- 0x597d, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
- extern unsigned EMUSHORT esqrt2[];
-
- /* 3.14159265358979323846264338327950288419716939937511E0 */
- unsigned EMUSHORT epi[NE] =
- {0x2902, 0x1cd1, 0x80dc, 0x628b,
- 0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
- extern unsigned EMUSHORT epi[];
-
- #else
- /* LONG_DOUBLE_TYPE_SIZE is other than 128 */
- unsigned EMUSHORT ezero[NE] =
- {0, 0000000, 0000000, 0000000, 0000000, 0000000,};
- unsigned EMUSHORT ehalf[NE] =
- {0, 0000000, 0000000, 0000000, 0100000, 0x3ffe,};
- unsigned EMUSHORT eone[NE] =
- {0, 0000000, 0000000, 0000000, 0100000, 0x3fff,};
- unsigned EMUSHORT etwo[NE] =
- {0, 0000000, 0000000, 0000000, 0100000, 0040000,};
- unsigned EMUSHORT e32[NE] =
- {0, 0000000, 0000000, 0000000, 0100000, 0040004,};
- unsigned EMUSHORT elog2[NE] =
- {0xc9e4, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
- unsigned EMUSHORT esqrt2[NE] =
- {0x597e, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
- unsigned EMUSHORT epi[NE] =
- {0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
- #endif
-
-
-
- /* Control register for rounding precision.
- * This can be set to 113 (if NE=10), 80 (if NE=6), 64, 56, 53, or 24 bits.
- */
- int rndprc = NBITS;
- extern int rndprc;
-
- void eaddm (), esubm (), emdnorm (), asctoeg ();
- static void toe24 (), toe53 (), toe64 (), toe113 ();
- void eremain (), einit (), eiremain ();
- int ecmpm (), edivm (), emulm ();
- void emovi (), emovo (), emovz (), ecleaz (), ecleazs (), eadd1 ();
- #ifdef DEC
- void etodec (), todec (), dectoe ();
- #endif
- #ifdef IBM
- void etoibm (), toibm (), ibmtoe ();
- #endif
-
-
- void
- einit ()
- {
- }
-
- /*
- ; Clear out entire external format number.
- ;
- ; unsigned EMUSHORT x[];
- ; eclear (x);
- */
-
- void
- eclear (x)
- register unsigned EMUSHORT *x;
- {
- register int i;
-
- for (i = 0; i < NE; i++)
- *x++ = 0;
- }
-
-
-
- /* Move external format number from a to b.
- *
- * emov (a, b);
- */
-
- void
- emov (a, b)
- register unsigned EMUSHORT *a, *b;
- {
- register int i;
-
- for (i = 0; i < NE; i++)
- *b++ = *a++;
- }
-
-
- /*
- ; Absolute value of external format number
- ;
- ; EMUSHORT x[NE];
- ; eabs (x);
- */
-
- void
- eabs (x)
- 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];
- ; eneg (x);
- */
-
- void
- eneg (x)
- unsigned EMUSHORT x[];
- {
-
- #ifdef NANS
- if (eisnan (x))
- return;
- #endif
- 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.
- */
- int
- eisneg (x)
- unsigned EMUSHORT x[];
- {
-
- #ifdef NANS
- if (eisnan (x))
- return (0);
- #endif
- if (x[NE - 1] & 0x8000)
- return (1);
- else
- return (0);
- }
-
-
- /* Return 1 if external format number is infinity.
- * else return zero.
- */
- int
- eisinf (x)
- unsigned EMUSHORT x[];
- {
-
- #ifdef NANS
- if (eisnan (x))
- return (0);
- #endif
- if ((x[NE - 1] & 0x7fff) == 0x7fff)
- return (1);
- else
- return (0);
- }
-
-
- /* Check if e-type number is not a number.
- The bit pattern is one that we defined, so we know for sure how to
- detect it. */
-
- int
- eisnan (x)
- unsigned EMUSHORT x[];
- {
-
- #ifdef NANS
- int i;
- /* NaN has maximum exponent */
- if ((x[NE - 1] & 0x7fff) != 0x7fff)
- return (0);
- /* ... and non-zero significand field. */
- for (i = 0; i < NE - 1; i++)
- {
- if (*x++ != 0)
- return (1);
- }
- #endif
- return (0);
- }
-
- /* Fill external format number with infinity pattern (IEEE)
- or largest possible number (non-IEEE). */
-
- void
- einfin (x)
- register unsigned EMUSHORT *x;
- {
- register int i;
-
- #ifdef INFINITY
- for (i = 0; i < NE - 1; i++)
- *x++ = 0;
- *x |= 32767;
- #else
- for (i = 0; i < NE - 1; i++)
- *x++ = 0xffff;
- *x |= 32766;
- if (rndprc < NBITS)
- {
- if (rndprc == 113)
- {
- *(x - 9) = 0;
- *(x - 8) = 0;
- }
- if (rndprc == 64)
- {
- *(x - 5) = 0;
- }
- if (rndprc == 53)
- {
- *(x - 4) = 0xf800;
- }
- else
- {
- *(x - 4) = 0;
- *(x - 3) = 0;
- *(x - 2) = 0xff00;
- }
- }
- #endif
- }
-
-
- /* Output an e-type NaN.
- This generates Intel's quiet NaN pattern for extended real.
- The exponent is 7fff, the leading mantissa word is c000. */
-
- void
- enan (x)
- register unsigned EMUSHORT *x;
- {
- register int i;
-
- for (i = 0; i < NE - 2; i++)
- *x++ = 0;
- *x++ = 0xc000;
- *x = 0x7fff;
- }
-
-
- /* Move in external format number,
- * converting it to internal format.
- */
- void
- emovi (a, b)
- unsigned EMUSHORT *a, *b;
- {
- register unsigned EMUSHORT *p, *q;
- int i;
-
- q = b;
- p = a + (NE - 1); /* point to last word of external number */
- /* get the sign bit */
- if (*p & 0x8000)
- *q++ = 0xffff;
- else
- *q++ = 0;
- /* get the exponent */
- *q = *p--;
- *q++ &= 0x7fff; /* delete the sign bit */
- #ifdef INFINITY
- if ((*(q - 1) & 0x7fff) == 0x7fff)
- {
- #ifdef NANS
- if (eisnan (a))
- {
- *q++ = 0;
- for (i = 3; i < NI; i++)
- *q++ = *p--;
- return;
- }
- #endif
- for (i = 2; i < NI; i++)
- *q++ = 0;
- return;
- }
- #endif
- /* clear high guard word */
- *q++ = 0;
- /* move in the significand */
- for (i = 0; i < NE - 1; i++)
- *q++ = *p--;
- /* clear low guard word */
- *q = 0;
- }
-
-
- /* Move internal format number out,
- * converting it to external format.
- */
- void
- emovo (a, b)
- unsigned EMUSHORT *a, *b;
- {
- register unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT i;
-
- p = a;
- q = b + (NE - 1); /* point to output exponent */
- /* combine sign and exponent */
- i = *p++;
- if (i)
- *q-- = *p++ | 0x8000;
- else
- *q-- = *p++;
- #ifdef INFINITY
- if (*(p - 1) == 0x7fff)
- {
- #ifdef NANS
- if (eiisnan (a))
- {
- enan (b);
- return;
- }
- #endif
- einfin (b);
- return;
- }
- #endif
- /* skip over guard word */
- ++p;
- /* move the significand */
- for (i = 0; i < NE - 1; i++)
- *q-- = *p++;
- }
-
-
-
-
- /* Clear out internal format number.
- */
-
- void
- ecleaz (xi)
- register unsigned EMUSHORT *xi;
- {
- register int i;
-
- for (i = 0; i < NI; i++)
- *xi++ = 0;
- }
-
-
- /* same, but don't touch the sign. */
-
- void
- ecleazs (xi)
- register unsigned EMUSHORT *xi;
- {
- register int i;
-
- ++xi;
- for (i = 0; i < NI - 1; i++)
- *xi++ = 0;
- }
-
-
-
- /* Move internal format number from a to b.
- */
- void
- emovz (a, b)
- register unsigned EMUSHORT *a, *b;
- {
- register int i;
-
- for (i = 0; i < NI - 1; i++)
- *b++ = *a++;
- /* clear low guard word */
- *b = 0;
- }
-
- /* Generate internal format NaN.
- The explicit pattern for this is maximum exponent and
- top two significand bits set. */
-
- void
- einan (x)
- unsigned EMUSHORT x[];
- {
-
- ecleaz (x);
- x[E] = 0x7fff;
- x[M + 1] = 0xc000;
- }
-
- /* Return nonzero if internal format number is a NaN. */
-
- int
- eiisnan (x)
- unsigned EMUSHORT x[];
- {
- int i;
-
- if ((x[E] & 0x7fff) == 0x7fff)
- {
- for (i = M + 1; i < NI; i++)
- {
- if (x[i] != 0)
- return (1);
- }
- }
- return (0);
- }
-
- /* Fill internal format number with infinity pattern.
- This has maximum exponent and significand all zeros. */
-
- void
- eiinfin (x)
- unsigned EMUSHORT x[];
- {
-
- ecleaz (x);
- x[E] = 0x7fff;
- }
-
- /* Return nonzero if internal format number is infinite. */
-
- int
- eiisinf (x)
- unsigned EMUSHORT x[];
- {
-
- #ifdef NANS
- if (eiisnan (x))
- return (0);
- #endif
- if ((x[E] & 0x7fff) == 0x7fff)
- return (1);
- return (0);
- }
-
-
- /*
- ; Compare significands of numbers in internal format.
- ; Guard words are included in the comparison.
- ;
- ; unsigned EMUSHORT a[NI], b[NI];
- ; cmpm (a, b);
- ;
- ; for the significands:
- ; returns +1 if a > b
- ; 0 if a == b
- ; -1 if a < b
- */
- int
- ecmpm (a, b)
- register unsigned EMUSHORT *a, *b;
- {
- int i;
-
- a += M; /* skip up to significand area */
- b += M;
- for (i = M; i < NI; i++)
- {
- if (*a++ != *b++)
- goto difrnt;
- }
- return (0);
-
- difrnt:
- if (*(--a) > *(--b))
- return (1);
- else
- return (-1);
- }
-
-
- /*
- ; Shift significand down by 1 bit
- */
-
- void
- eshdn1 (x)
- register unsigned EMUSHORT *x;
- {
- register unsigned EMUSHORT bits;
- int i;
-
- x += M; /* point to significand area */
-
- bits = 0;
- for (i = M; i < NI; i++)
- {
- if (*x & 1)
- bits |= 1;
- *x >>= 1;
- if (bits & 2)
- *x |= 0x8000;
- bits <<= 1;
- ++x;
- }
- }
-
-
-
- /*
- ; Shift significand up by 1 bit
- */
-
- void
- eshup1 (x)
- register unsigned EMUSHORT *x;
- {
- register unsigned EMUSHORT bits;
- int i;
-
- x += NI - 1;
- bits = 0;
-
- for (i = M; i < NI; i++)
- {
- if (*x & 0x8000)
- bits |= 1;
- *x <<= 1;
- if (bits & 2)
- *x |= 1;
- bits <<= 1;
- --x;
- }
- }
-
-
-
- /*
- ; Shift significand down by 8 bits
- */
-
- void
- eshdn8 (x)
- register unsigned EMUSHORT *x;
- {
- register unsigned EMUSHORT newbyt, oldbyt;
- int i;
-
- x += M;
- oldbyt = 0;
- for (i = M; i < NI; i++)
- {
- newbyt = *x << 8;
- *x >>= 8;
- *x |= oldbyt;
- oldbyt = newbyt;
- ++x;
- }
- }
-
- /*
- ; Shift significand up by 8 bits
- */
-
- void
- eshup8 (x)
- register unsigned EMUSHORT *x;
- {
- int i;
- register unsigned EMUSHORT newbyt, oldbyt;
-
- x += NI - 1;
- oldbyt = 0;
-
- for (i = M; i < NI; i++)
- {
- newbyt = *x >> 8;
- *x <<= 8;
- *x |= oldbyt;
- oldbyt = newbyt;
- --x;
- }
- }
-
- /*
- ; Shift significand up by 16 bits
- */
-
- void
- eshup6 (x)
- register unsigned EMUSHORT *x;
- {
- int i;
- register unsigned EMUSHORT *p;
-
- p = x + M;
- x += M + 1;
-
- for (i = M; i < NI - 1; i++)
- *p++ = *x++;
-
- *p = 0;
- }
-
- /*
- ; Shift significand down by 16 bits
- */
-
- void
- eshdn6 (x)
- register unsigned EMUSHORT *x;
- {
- int i;
- register unsigned EMUSHORT *p;
-
- x += NI - 1;
- p = x + 1;
-
- for (i = M; i < NI - 1; i++)
- *(--p) = *(--x);
-
- *(--p) = 0;
- }
-
- /*
- ; Add significands
- ; x + y replaces y
- */
-
- void
- eaddm (x, y)
- unsigned EMUSHORT *x, *y;
- {
- register unsigned EMULONG a;
- int i;
- unsigned int carry;
-
- x += NI - 1;
- y += NI - 1;
- carry = 0;
- for (i = M; i < NI; i++)
- {
- a = (unsigned EMULONG) (*x) + (unsigned EMULONG) (*y) + carry;
- if (a & 0x10000)
- carry = 1;
- else
- carry = 0;
- *y = (unsigned EMUSHORT) a;
- --x;
- --y;
- }
- }
-
- /*
- ; Subtract significands
- ; y - x replaces y
- */
-
- void
- esubm (x, y)
- unsigned EMUSHORT *x, *y;
- {
- unsigned EMULONG a;
- int i;
- unsigned int carry;
-
- x += NI - 1;
- y += NI - 1;
- carry = 0;
- for (i = M; i < NI; i++)
- {
- a = (unsigned EMULONG) (*y) - (unsigned EMULONG) (*x) - carry;
- if (a & 0x10000)
- carry = 1;
- else
- carry = 0;
- *y = (unsigned EMUSHORT) a;
- --x;
- --y;
- }
- }
-
-
- static unsigned EMUSHORT equot[NI];
-
-
- #if 0
- /* Radix 2 shift-and-add versions of multiply and divide */
-
-
- /* Divide significands */
-
- int
- edivm (den, num)
- unsigned EMUSHORT den[], num[];
- {
- int i;
- register unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT j;
-
- p = &equot[0];
- *p++ = num[0];
- *p++ = num[1];
-
- for (i = M; i < NI; i++)
- {
- *p++ = 0;
- }
-
- /* Use faster compare and subtraction if denominator
- * has only 15 bits of significance.
- */
- p = &den[M + 2];
- if (*p++ == 0)
- {
- for (i = M + 3; i < NI; i++)
- {
- if (*p++ != 0)
- goto fulldiv;
- }
- if ((den[M + 1] & 1) != 0)
- goto fulldiv;
- eshdn1 (num);
- eshdn1 (den);
-
- p = &den[M + 1];
- q = &num[M + 1];
-
- for (i = 0; i < NBITS + 2; i++)
- {
- if (*p <= *q)
- {
- *q -= *p;
- j = 1;
- }
- else
- {
- j = 0;
- }
- eshup1 (equot);
- equot[NI - 2] |= j;
- eshup1 (num);
- }
- goto divdon;
- }
-
- /* The number of quotient bits to calculate is
- * NBITS + 1 scaling guard bit + 1 roundoff bit.
- */
- fulldiv:
-
- p = &equot[NI - 2];
- for (i = 0; i < NBITS + 2; i++)
- {
- if (ecmpm (den, num) <= 0)
- {
- esubm (den, num);
- j = 1; /* quotient bit = 1 */
- }
- else
- j = 0;
- eshup1 (equot);
- *p |= j;
- eshup1 (num);
- }
-
- divdon:
-
- eshdn1 (equot);
- eshdn1 (equot);
-
- /* test for nonzero remainder after roundoff bit */
- p = &num[M];
- j = 0;
- for (i = M; i < NI; i++)
- {
- j |= *p++;
- }
- if (j)
- j = 1;
-
-
- for (i = 0; i < NI; i++)
- num[i] = equot[i];
- return ((int) j);
- }
-
-
- /* Multiply significands */
- int
- emulm (a, b)
- unsigned EMUSHORT a[], b[];
- {
- unsigned EMUSHORT *p, *q;
- int i, j, k;
-
- equot[0] = b[0];
- equot[1] = b[1];
- for (i = M; i < NI; i++)
- equot[i] = 0;
-
- p = &a[NI - 2];
- k = NBITS;
- while (*p == 0) /* significand is not supposed to be all zero */
- {
- eshdn6 (a);
- k -= 16;
- }
- if ((*p & 0xff) == 0)
- {
- eshdn8 (a);
- k -= 8;
- }
-
- q = &equot[NI - 1];
- j = 0;
- for (i = 0; i < k; i++)
- {
- if (*p & 1)
- eaddm (b, equot);
- /* remember if there were any nonzero bits shifted out */
- if (*q & 1)
- j |= 1;
- eshdn1 (a);
- eshdn1 (equot);
- }
-
- for (i = 0; i < NI; i++)
- b[i] = equot[i];
-
- /* return flag for lost nonzero bits */
- return (j);
- }
-
- #else
-
- /* Radix 65536 versions of multiply and divide */
-
-
- /* Multiply significand of e-type number b
- by 16-bit quantity a, e-type result to c. */
-
- void
- m16m (a, b, c)
- unsigned short a;
- unsigned short b[], c[];
- {
- register unsigned short *pp;
- register unsigned long carry;
- unsigned short *ps;
- unsigned short p[NI];
- unsigned long aa, m;
- int i;
-
- aa = a;
- pp = &p[NI-2];
- *pp++ = 0;
- *pp = 0;
- ps = &b[NI-1];
-
- for (i=M+1; i<NI; i++)
- {
- if (*ps == 0)
- {
- --ps;
- --pp;
- *(pp-1) = 0;
- }
- else
- {
- m = (unsigned long) aa * *ps--;
- carry = (m & 0xffff) + *pp;
- *pp-- = (unsigned short)carry;
- carry = (carry >> 16) + (m >> 16) + *pp;
- *pp = (unsigned short)carry;
- *(pp-1) = carry >> 16;
- }
- }
- for (i=M; i<NI; i++)
- c[i] = p[i];
- }
-
-
- /* Divide significands. Neither the numerator nor the denominator
- is permitted to have its high guard word nonzero. */
-
- int
- edivm (den, num)
- unsigned short den[], num[];
- {
- int i;
- register unsigned short *p;
- unsigned long tnum;
- unsigned short j, tdenm, tquot;
- unsigned short tprod[NI+1];
-
- p = &equot[0];
- *p++ = num[0];
- *p++ = num[1];
-
- for (i=M; i<NI; i++)
- {
- *p++ = 0;
- }
- eshdn1 (num);
- tdenm = den[M+1];
- for (i=M; i<NI; i++)
- {
- /* Find trial quotient digit (the radix is 65536). */
- tnum = (((unsigned long) num[M]) << 16) + num[M+1];
-
- /* Do not execute the divide instruction if it will overflow. */
- if ((tdenm * 0xffffL) < tnum)
- tquot = 0xffff;
- else
- tquot = tnum / tdenm;
- /* Multiply denominator by trial quotient digit. */
- m16m (tquot, den, tprod);
- /* The quotient digit may have been overestimated. */
- if (ecmpm (tprod, num) > 0)
- {
- tquot -= 1;
- esubm (den, tprod);
- if (ecmpm (tprod, num) > 0)
- {
- tquot -= 1;
- esubm (den, tprod);
- }
- }
- esubm (tprod, num);
- equot[i] = tquot;
- eshup6(num);
- }
- /* test for nonzero remainder after roundoff bit */
- p = &num[M];
- j = 0;
- for (i=M; i<NI; i++)
- {
- j |= *p++;
- }
- if (j)
- j = 1;
-
- for (i=0; i<NI; i++)
- num[i] = equot[i];
-
- return ((int)j);
- }
-
-
-
- /* Multiply significands */
- int
- emulm (a, b)
- unsigned short a[], b[];
- {
- unsigned short *p, *q;
- unsigned short pprod[NI];
- unsigned short j;
- int i;
-
- equot[0] = b[0];
- equot[1] = b[1];
- for (i=M; i<NI; i++)
- equot[i] = 0;
-
- j = 0;
- p = &a[NI-1];
- q = &equot[NI-1];
- for (i=M+1; i<NI; i++)
- {
- if (*p == 0)
- {
- --p;
- }
- else
- {
- m16m (*p--, b, pprod);
- eaddm(pprod, equot);
- }
- j |= *q;
- eshdn6(equot);
- }
-
- for (i=0; i<NI; i++)
- b[i] = equot[i];
-
- /* return flag for lost nonzero bits */
- return ((int)j);
- }
- #endif
-
-
- /*
- * 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.
- */
-
- /* For future reference: In order for emdnorm to round off denormal
- significands at the right point, the input exponent must be
- adjusted to be the actual value it would have after conversion to
- the final floating point type. This adjustment has been
- implemented for all type conversions (etoe53, etc.) and decimal
- conversions, but not for the arithmetic functions (eadd, etc.).
- Data types having standard 15-bit exponents are not affected by
- this, but SFmode and DFmode are affected. For example, ediv with
- rndprc = 24 will not round correctly to 24-bit precision if the
- result is denormal. */
-
- static int rlast = -1;
- static int rw = 0;
- static unsigned EMUSHORT rmsk = 0;
- static unsigned EMUSHORT rmbit = 0;
- static unsigned EMUSHORT rebit = 0;
- static int re = 0;
- static unsigned EMUSHORT rbit[NI];
-
- void
- emdnorm (s, lost, subflg, exp, rcntrl)
- unsigned EMUSHORT s[];
- int lost;
- int subflg;
- EMULONG exp;
- int rcntrl;
- {
- int i, j;
- unsigned EMUSHORT r;
-
- /* Normalize */
- j = enormlz (s);
-
- /* a blank significand could mean either zero or infinity. */
- #ifndef INFINITY
- if (j > NBITS)
- {
- ecleazs (s);
- return;
- }
- #endif
- exp -= j;
- #ifndef INFINITY
- if (exp >= 32767L)
- goto overf;
- #else
- if ((j > NBITS) && (exp < 32767))
- {
- ecleazs (s);
- return;
- }
- #endif
- if (exp < 0L)
- {
- if (exp > (EMULONG) (-NBITS - 1))
- {
- j = (int) exp;
- i = eshift (s, j);
- if (i)
- lost = 1;
- }
- else
- {
- ecleazs (s);
- return;
- }
- }
- /* Round off, unless told not to by rcntrl. */
- if (rcntrl == 0)
- goto mdfin;
- /* Set up rounding parameters if the control register changed. */
- if (rndprc != rlast)
- {
- ecleaz (rbit);
- switch (rndprc)
- {
- default:
- case NBITS:
- rw = NI - 1; /* low guard word */
- rmsk = 0xffff;
- rmbit = 0x8000;
- re = rw - 1;
- rebit = 1;
- break;
- case 113:
- rw = 10;
- rmsk = 0x7fff;
- rmbit = 0x4000;
- rebit = 0x8000;
- re = rw;
- break;
- case 64:
- rw = 7;
- rmsk = 0xffff;
- rmbit = 0x8000;
- re = rw - 1;
- rebit = 1;
- break;
- /* For DEC or IBM arithmetic */
- case 56:
- rw = 6;
- rmsk = 0xff;
- rmbit = 0x80;
- rebit = 0x100;
- re = rw;
- break;
- case 53:
- rw = 6;
- rmsk = 0x7ff;
- rmbit = 0x0400;
- rebit = 0x800;
- re = rw;
- break;
- case 24:
- rw = 4;
- rmsk = 0xff;
- rmbit = 0x80;
- rebit = 0x100;
- re = rw;
- break;
- }
- rbit[re] = rebit;
- rlast = rndprc;
- }
-
- /* Shift down 1 temporarily if the data structure has an implied
- most significant bit and the number is denormal. */
- if ((exp <= 0) && (rndprc != 64) && (rndprc != NBITS))
- {
- lost |= s[NI - 1] & 1;
- eshdn1 (s);
- }
- /* Clear out all bits below the rounding bit,
- remembering in r if any were nonzero. */
- r = s[rw] & rmsk;
- if (rndprc < NBITS)
- {
- i = rw + 1;
- while (i < NI)
- {
- if (s[i])
- r |= 1;
- s[i] = 0;
- ++i;
- }
- }
- s[rw] &= ~rmsk;
- if ((r & rmbit) != 0)
- {
- if (r == rmbit)
- {
- if (lost == 0)
- { /* round to even */
- if ((s[re] & rebit) == 0)
- goto mddone;
- }
- else
- {
- if (subflg != 0)
- goto mddone;
- }
- }
- eaddm (rbit, s);
- }
- mddone:
- if ((exp <= 0) && (rndprc != 64) && (rndprc != NBITS))
- {
- eshup1 (s);
- }
- if (s[2] != 0)
- { /* overflow on roundoff */
- eshdn1 (s);
- exp += 1;
- }
- mdfin:
- s[NI - 1] = 0;
- if (exp >= 32767L)
- {
- #ifndef INFINITY
- overf:
- #endif
- #ifdef INFINITY
- s[1] = 32767;
- for (i = 2; i < NI - 1; i++)
- s[i] = 0;
- if (extra_warnings)
- warning ("floating point overflow");
- #else
- s[1] = 32766;
- s[2] = 0;
- for (i = M + 1; i < NI - 1; i++)
- s[i] = 0xffff;
- s[NI - 1] = 0;
- if ((rndprc < 64) || (rndprc == 113))
- {
- s[rw] &= ~rmsk;
- if (rndprc == 24)
- {
- s[5] = 0;
- s[6] = 0;
- }
- }
- #endif
- return;
- }
- if (exp < 0)
- s[1] = 0;
- else
- s[1] = (unsigned EMUSHORT) exp;
- }
-
-
-
- /*
- ; Subtract external format numbers.
- ;
- ; unsigned EMUSHORT a[NE], b[NE], c[NE];
- ; esub (a, b, c); c = b - a
- */
-
- static int subflg = 0;
-
- void
- esub (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
- {
-
- #ifdef NANS
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
- /* 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);
- enan (c);
- return;
- }
- #endif
- subflg = 1;
- eadd1 (a, b, c);
- }
-
-
- /*
- ; Add.
- ;
- ; unsigned EMUSHORT a[NE], b[NE], c[NE];
- ; eadd (a, b, c); c = b + a
- */
- void
- eadd (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
- {
-
- #ifdef NANS
- /* NaN plus anything is a NaN. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
- /* 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);
- enan (c);
- return;
- }
- #endif
- subflg = 0;
- eadd1 (a, b, c);
- }
-
- void
- eadd1 (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
- {
- unsigned EMUSHORT ai[NI], bi[NI], ci[NI];
- int i, lost, j, k;
- EMULONG lt, lta, ltb;
-
- #ifdef INFINITY
- if (eisinf (a))
- {
- emov (a, c);
- if (subflg)
- eneg (c);
- return;
- }
- if (eisinf (b))
- {
- emov (b, c);
- return;
- }
- #endif
- emovi (a, ai);
- emovi (b, bi);
- if (subflg)
- ai[0] = ~ai[0];
-
- /* compare exponents */
- lta = ai[E];
- ltb = bi[E];
- lt = lta - ltb;
- if (lt > 0L)
- { /* put the larger number in bi */
- emovz (bi, ci);
- emovz (ai, bi);
- emovz (ci, ai);
- ltb = bi[E];
- lt = -lt;
- }
- lost = 0;
- if (lt != 0L)
- {
- if (lt < (EMULONG) (-NBITS - 1))
- goto done; /* answer same as larger addend */
- k = (int) lt;
- lost = eshift (ai, k); /* shift the smaller number down */
- }
- else
- {
- /* exponents were the same, so must compare significands */
- i = ecmpm (ai, bi);
- if (i == 0)
- { /* the numbers are identical in magnitude */
- /* if different signs, result is zero */
- if (ai[0] != bi[0])
- {
- eclear (c);
- return;
- }
- /* if same sign, result is double */
- /* double denomalized tiny number */
- if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0))
- {
- eshup1 (bi);
- goto done;
- }
- /* add 1 to exponent unless both are zero! */
- for (j = 1; j < NI - 1; j++)
- {
- if (bi[j] != 0)
- {
- /* This could overflow, but let emovo take care of that. */
- ltb += 1;
- break;
- }
- }
- bi[E] = (unsigned EMUSHORT) ltb;
- goto done;
- }
- if (i > 0)
- { /* put the larger number in bi */
- emovz (bi, ci);
- emovz (ai, bi);
- emovz (ci, ai);
- }
- }
- if (ai[0] == bi[0])
- {
- eaddm (ai, bi);
- subflg = 0;
- }
- else
- {
- esubm (ai, bi);
- subflg = 1;
- }
- emdnorm (bi, lost, subflg, ltb, 64);
-
- done:
- emovo (bi, c);
- }
-
-
-
- /*
- ; Divide.
- ;
- ; unsigned EMUSHORT a[NE], b[NE], c[NE];
- ; ediv (a, b, c); c = b / a
- */
- void
- ediv (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
- {
- unsigned EMUSHORT ai[NI], bi[NI];
- int i;
- EMULONG lt, lta, ltb;
-
- #ifdef NANS
- /* Return any NaN input. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
- /* 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);
- enan (c);
- return;
- }
- #endif
- /* Infinity over anything else is infinity. */
- #ifdef INFINITY
- if (eisinf (b))
- {
- if (eisneg (a) ^ eisneg (b))
- *(c + (NE - 1)) = 0x8000;
- else
- *(c + (NE - 1)) = 0;
- einfin (c);
- return;
- }
- /* Anything else over infinity is zero. */
- if (eisinf (a))
- {
- eclear (c);
- return;
- }
- #endif
- emovi (a, ai);
- emovi (b, bi);
- lta = ai[E];
- ltb = bi[E];
- if (bi[E] == 0)
- { /* See if numerator is zero. */
- for (i = 1; i < NI - 1; i++)
- {
- if (bi[i] != 0)
- {
- ltb -= enormlz (bi);
- goto dnzro1;
- }
- }
- eclear (c);
- return;
- }
- dnzro1:
-
- if (ai[E] == 0)
- { /* possible divide by zero */
- for (i = 1; i < NI - 1; i++)
- {
- if (ai[i] != 0)
- {
- lta -= enormlz (ai);
- goto dnzro2;
- }
- }
- if (ai[0] == bi[0])
- *(c + (NE - 1)) = 0;
- else
- *(c + (NE - 1)) = 0x8000;
- /* Divide by zero is not an invalid operation.
- It is a divide-by-zero operation! */
- einfin (c);
- mtherr ("ediv", SING);
- return;
- }
- dnzro2:
-
- i = edivm (ai, bi);
- /* calculate exponent */
- lt = ltb - lta + EXONE;
- emdnorm (bi, i, 0, lt, 64);
- /* set the sign */
- if (ai[0] == bi[0])
- bi[0] = 0;
- else
- bi[0] = 0Xffff;
- emovo (bi, c);
- }
-
-
-
- /*
- ; Multiply.
- ;
- ; unsigned EMUSHORT a[NE], b[NE], c[NE];
- ; emul (a, b, c); c = b * a
- */
- void
- emul (a, b, c)
- unsigned EMUSHORT *a, *b, *c;
- {
- unsigned EMUSHORT ai[NI], bi[NI];
- int i, j;
- EMULONG lt, lta, ltb;
-
- #ifdef NANS
- /* NaN times anything is the same NaN. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
- /* Zero times infinity is a NaN. */
- if ((eisinf (a) && (ecmp (b, ezero) == 0))
- || (eisinf (b) && (ecmp (a, ezero) == 0)))
- {
- mtherr ("emul", INVALID);
- enan (c);
- return;
- }
- #endif
- /* Infinity times anything else is infinity. */
- #ifdef INFINITY
- if (eisinf (a) || eisinf (b))
- {
- if (eisneg (a) ^ eisneg (b))
- *(c + (NE - 1)) = 0x8000;
- else
- *(c + (NE - 1)) = 0;
- einfin (c);
- return;
- }
- #endif
- emovi (a, ai);
- emovi (b, bi);
- lta = ai[E];
- ltb = bi[E];
- if (ai[E] == 0)
- {
- for (i = 1; i < NI - 1; i++)
- {
- if (ai[i] != 0)
- {
- lta -= enormlz (ai);
- goto mnzer1;
- }
- }
- eclear (c);
- return;
- }
- mnzer1:
-
- if (bi[E] == 0)
- {
- for (i = 1; i < NI - 1; i++)
- {
- if (bi[i] != 0)
- {
- ltb -= enormlz (bi);
- goto mnzer2;
- }
- }
- eclear (c);
- return;
- }
- mnzer2:
-
- /* Multiply significands */
- j = emulm (ai, bi);
- /* calculate exponent */
- lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, 64);
- /* calculate sign of product */
- if (ai[0] == bi[0])
- bi[0] = 0;
- else
- bi[0] = 0xffff;
- emovo (bi, c);
- }
-
-
-
-
- /*
- ; Convert IEEE double precision to e type
- ; double d;
- ; unsigned EMUSHORT x[N+2];
- ; e53toe (&d, x);
- */
- void
- e53toe (pe, y)
- unsigned EMUSHORT *pe, *y;
- {
- #ifdef DEC
-
- dectoe (pe, y); /* see etodec.c */
-
- #else
- #ifdef IBM
-
- ibmtoe (pe, y, DFmode);
-
- #else
- register unsigned EMUSHORT r;
- register unsigned EMUSHORT *e, *p;
- unsigned EMUSHORT yy[NI];
- int denorm, k;
-
- e = pe;
- denorm = 0; /* flag if denormalized number */
- ecleaz (yy);
- #ifdef IBMPC
- e += 3;
- #endif
- r = *e;
- yy[0] = 0;
- if (r & 0x8000)
- yy[0] = 0xffff;
- yy[M] = (r & 0x0f) | 0x10;
- r &= ~0x800f; /* strip sign and 4 significand bits */
- #ifdef INFINITY
- if (r == 0x7ff0)
- {
- #ifdef NANS
- #ifdef IBMPC
- if (((pe[3] & 0xf) != 0) || (pe[2] != 0)
- || (pe[1] != 0) || (pe[0] != 0))
- {
- enan (y);
- return;
- }
- #else
- if (((pe[0] & 0xf) != 0) || (pe[1] != 0)
- || (pe[2] != 0) || (pe[3] != 0))
- {
- enan (y);
- return;
- }
- #endif
- #endif /* NANS */
- eclear (y);
- einfin (y);
- if (yy[0])
- eneg (y);
- return;
- }
- #endif /* INFINITY */
- r >>= 4;
- /* If zero exponent, then the significand is denormalized.
- * So, take back the understood high significand bit. */
- if (r == 0)
- {
- denorm = 1;
- yy[M] &= ~0x10;
- }
- r += EXONE - 01777;
- yy[E] = r;
- p = &yy[M + 1];
- #ifdef IBMPC
- *p++ = *(--e);
- *p++ = *(--e);
- *p++ = *(--e);
- #endif
- #ifdef MIEEE
- ++e;
- *p++ = *e++;
- *p++ = *e++;
- *p++ = *e++;
- #endif
- eshift (yy, -5);
- if (denorm)
- { /* if zero exponent, then normalize the significand */
- if ((k = enormlz (yy)) > NBITS)
- ecleazs (yy);
- else
- yy[E] -= (unsigned EMUSHORT) (k - 1);
- }
- emovo (yy, y);
- #endif /* not IBM */
- #endif /* not DEC */
- }
-
- void
- e64toe (pe, y)
- unsigned EMUSHORT *pe, *y;
- {
- unsigned EMUSHORT yy[NI];
- unsigned EMUSHORT *e, *p, *q;
- int i;
-
- e = pe;
- p = yy;
- for (i = 0; i < NE - 5; i++)
- *p++ = 0;
- #ifdef IBMPC
- for (i = 0; i < 5; i++)
- *p++ = *e++;
- #endif
- /* This precision is not ordinarily supported on DEC or IBM. */
- #ifdef DEC
- for (i = 0; i < 5; i++)
- *p++ = *e++;
- #endif
- #ifdef IBM
- p = &yy[0] + (NE - 1);
- *p-- = *e++;
- ++e;
- for (i = 0; i < 5; i++)
- *p-- = *e++;
- #endif
- #ifdef MIEEE
- p = &yy[0] + (NE - 1);
- *p-- = *e++;
- ++e;
- for (i = 0; i < 4; i++)
- *p-- = *e++;
- #endif
- p = yy;
- q = y;
- #ifdef INFINITY
- if (*p == 0x7fff)
- {
- #ifdef NANS
- #ifdef IBMPC
- for (i = 0; i < 4; i++)
- {
- if (pe[i] != 0)
- {
- enan (y);
- return;
- }
- }
- #else
- for (i = 1; i <= 4; i++)
- {
- if (pe[i] != 0)
- {
- enan (y);
- return;
- }
- }
- #endif
- #endif /* NANS */
- eclear (y);
- einfin (y);
- if (*p & 0x8000)
- eneg (y);
- return;
- }
- #endif /* INFINITY */
- for (i = 0; i < NE; i++)
- *q++ = *p++;
- }
-
-
- void
- e113toe (pe, y)
- unsigned EMUSHORT *pe, *y;
- {
- register unsigned EMUSHORT r;
- unsigned EMUSHORT *e, *p;
- unsigned EMUSHORT yy[NI];
- int denorm, i;
-
- e = pe;
- denorm = 0;
- ecleaz (yy);
- #ifdef IBMPC
- e += 7;
- #endif
- r = *e;
- yy[0] = 0;
- if (r & 0x8000)
- yy[0] = 0xffff;
- r &= 0x7fff;
- #ifdef INFINITY
- if (r == 0x7fff)
- {
- #ifdef NANS
- #ifdef IBMPC
- for (i = 0; i < 7; i++)
- {
- if (pe[i] != 0)
- {
- enan (y);
- return;
- }
- }
- #else
- for (i = 1; i < 8; i++)
- {
- if (pe[i] != 0)
- {
- enan (y);
- return;
- }
- }
- #endif
- #endif /* NANS */
- eclear (y);
- einfin (y);
- if (yy[0])
- eneg (y);
- return;
- }
- #endif /* INFINITY */
- yy[E] = r;
- p = &yy[M + 1];
- #ifdef IBMPC
- for (i = 0; i < 7; i++)
- *p++ = *(--e);
- #endif
- #ifdef MIEEE
- ++e;
- for (i = 0; i < 7; i++)
- *p++ = *e++;
- #endif
- /* If denormal, remove the implied bit; else shift down 1. */
- if (r == 0)
- {
- yy[M] = 0;
- }
- else
- {
- yy[M] = 1;
- eshift (yy, -1);
- }
- emovo (yy, y);
- }
-
-
- /*
- ; Convert IEEE single precision to e type
- ; float d;
- ; unsigned EMUSHORT x[N+2];
- ; dtox (&d, x);
- */
- void
- e24toe (pe, y)
- unsigned EMUSHORT *pe, *y;
- {
- #ifdef IBM
-
- ibmtoe (pe, y, SFmode);
-
- #else
- register unsigned EMUSHORT r;
- register unsigned EMUSHORT *e, *p;
- unsigned EMUSHORT yy[NI];
- int denorm, k;
-
- e = pe;
- denorm = 0; /* flag if denormalized number */
- ecleaz (yy);
- #ifdef IBMPC
- e += 1;
- #endif
- #ifdef DEC
- e += 1;
- #endif
- r = *e;
- yy[0] = 0;
- if (r & 0x8000)
- yy[0] = 0xffff;
- yy[M] = (r & 0x7f) | 0200;
- r &= ~0x807f; /* strip sign and 7 significand bits */
- #ifdef INFINITY
- if (r == 0x7f80)
- {
- #ifdef NANS
- #ifdef MIEEE
- if (((pe[0] & 0x7f) != 0) || (pe[1] != 0))
- {
- enan (y);
- return;
- }
- #else
- if (((pe[1] & 0x7f) != 0) || (pe[0] != 0))
- {
- enan (y);
- return;
- }
- #endif
- #endif /* NANS */
- eclear (y);
- einfin (y);
- if (yy[0])
- eneg (y);
- return;
- }
- #endif /* INFINITY */
- r >>= 7;
- /* If zero exponent, then the significand is denormalized.
- * So, take back the understood high significand bit. */
- if (r == 0)
- {
- denorm = 1;
- yy[M] &= ~0200;
- }
- r += EXONE - 0177;
- yy[E] = r;
- p = &yy[M + 1];
- #ifdef IBMPC
- *p++ = *(--e);
- #endif
- #ifdef DEC
- *p++ = *(--e);
- #endif
- #ifdef MIEEE
- ++e;
- *p++ = *e++;
- #endif
- eshift (yy, -8);
- if (denorm)
- { /* if zero exponent, then normalize the significand */
- if ((k = enormlz (yy)) > NBITS)
- ecleazs (yy);
- else
- yy[E] -= (unsigned EMUSHORT) (k - 1);
- }
- emovo (yy, y);
- #endif /* not IBM */
- }
-
-
- void
- etoe113 (x, e)
- unsigned EMUSHORT *x, *e;
- {
- unsigned EMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- #ifdef NANS
- if (eisnan (x))
- {
- make_nan (e, TFmode);
- return;
- }
- #endif
- emovi (x, xi);
- exp = (EMULONG) xi[E];
- #ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
- #endif
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 113;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- nonorm:
- toe113 (xi, e);
- }
-
- /* move out internal format to ieee long double */
- static void
- toe113 (a, b)
- unsigned EMUSHORT *a, *b;
- {
- register unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT i;
-
- #ifdef NANS
- if (eiisnan (a))
- {
- make_nan (b, TFmode);
- return;
- }
- #endif
- p = a;
- #ifdef MIEEE
- q = b;
- #else
- q = b + 7; /* point to output exponent */
- #endif
-
- /* If not denormal, delete the implied bit. */
- if (a[E] != 0)
- {
- eshup1 (a);
- }
- /* combine sign and exponent */
- i = *p++;
- #ifdef MIEEE
- if (i)
- *q++ = *p++ | 0x8000;
- else
- *q++ = *p++;
- #else
- if (i)
- *q-- = *p++ | 0x8000;
- else
- *q-- = *p++;
- #endif
- /* skip over guard word */
- ++p;
- /* move the significand */
- #ifdef MIEEE
- for (i = 0; i < 7; i++)
- *q++ = *p++;
- #else
- for (i = 0; i < 7; i++)
- *q-- = *p++;
- #endif
- }
-
- void
- etoe64 (x, e)
- unsigned EMUSHORT *x, *e;
- {
- unsigned EMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- #ifdef NANS
- if (eisnan (x))
- {
- make_nan (e, XFmode);
- return;
- }
- #endif
- emovi (x, xi);
- /* adjust exponent for offset */
- exp = (EMULONG) xi[E];
- #ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
- #endif
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 64;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- nonorm:
- toe64 (xi, e);
- }
-
- /* move out internal format to ieee long double */
- static void
- toe64 (a, b)
- unsigned EMUSHORT *a, *b;
- {
- register unsigned EMUSHORT *p, *q;
- unsigned EMUSHORT i;
-
- #ifdef NANS
- if (eiisnan (a))
- {
- make_nan (b, XFmode);
- return;
- }
- #endif
- p = a;
- #if defined(MIEEE) || defined(IBM)
- q = b;
- #else
- q = b + 4; /* point to output exponent */
- #if LONG_DOUBLE_TYPE_SIZE == 96
- /* Clear the last two bytes of 12-byte Intel format */
- *(q+1) = 0;
- #endif
- #endif
-
- /* combine sign and exponent */
- i = *p++;
- #if defined(MIEEE) || defined(IBM)
- if (i)
- *q++ = *p++ | 0x8000;
- else
- *q++ = *p++;
- *q++ = 0;
- #else
- if (i)
- *q-- = *p++ | 0x8000;
- else
- *q-- = *p++;
- #endif
- /* skip over guard word */
- ++p;
- /* move the significand */
- #if defined(MIEEE) || defined(IBM)
- for (i = 0; i < 4; i++)
- *q++ = *p++;
- #else
- for (i = 0; i < 4; i++)
- *q-- = *p++;
- #endif
- }
-
-
- /*
- ; e type to IEEE double precision
- ; double d;
- ; unsigned EMUSHORT x[NE];
- ; etoe53 (x, &d);
- */
-
- #ifdef DEC
-
- void
- etoe53 (x, e)
- unsigned EMUSHORT *x, *e;
- {
- etodec (x, e); /* see etodec.c */
- }
-
- static void
- toe53 (x, y)
- unsigned EMUSHORT *x, *y;
- {
- todec (x, y);
- }
-
- #else
- #ifdef IBM
-
- void
- etoe53 (x, e)
- unsigned EMUSHORT *x, *e;
- {
- etoibm (x, e, DFmode);
- }
-
- static void
- toe53 (x, y)
- unsigned EMUSHORT *x, *y;
- {
- toibm (x, y, DFmode);
- }
-
- #else /* it's neither DEC nor IBM */
-
- void
- etoe53 (x, e)
- unsigned EMUSHORT *x, *e;
- {
- unsigned EMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- #ifdef NANS
- if (eisnan (x))
- {
- make_nan (e, DFmode);
- return;
- }
- #endif
- emovi (x, xi);
- /* adjust exponent for offsets */
- exp = (EMULONG) xi[E] - (EXONE - 0x3ff);
- #ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
- #endif
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 53;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- nonorm:
- toe53 (xi, e);
- }
-
-
- static void
- toe53 (x, y)
- unsigned EMUSHORT *x, *y;
- {
- unsigned EMUSHORT i;
- unsigned EMUSHORT *p;
-
- #ifdef NANS
- if (eiisnan (x))
- {
- make_nan (y, DFmode);
- return;
- }
- #endif
- p = &x[0];
- #ifdef IBMPC
- y += 3;
- #endif
- *y = 0; /* output high order */
- if (*p++)
- *y = 0x8000; /* output sign bit */
-
- i = *p++;
- if (i >= (unsigned int) 2047)
- { /* Saturate at largest number less than infinity. */
- #ifdef INFINITY
- *y |= 0x7ff0;
- #ifdef IBMPC
- *(--y) = 0;
- *(--y) = 0;
- *(--y) = 0;
- #endif
- #ifdef MIEEE
- ++y;
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
- #endif
- #else
- *y |= (unsigned EMUSHORT) 0x7fef;
- #ifdef IBMPC
- *(--y) = 0xffff;
- *(--y) = 0xffff;
- *(--y) = 0xffff;
- #endif
- #ifdef MIEEE
- ++y;
- *y++ = 0xffff;
- *y++ = 0xffff;
- *y++ = 0xffff;
- #endif
- #endif
- return;
- }
- if (i == 0)
- {
- eshift (x, 4);
- }
- else
- {
- i <<= 4;
- eshift (x, 5);
- }
- i |= *p++ & (unsigned EMUSHORT) 0x0f; /* *p = xi[M] */
- *y |= (unsigned EMUSHORT) i; /* high order output already has sign bit set */
- #ifdef IBMPC
- *(--y) = *p++;
- *(--y) = *p++;
- *(--y) = *p;
- #endif
- #ifdef MIEEE
- ++y;
- *y++ = *p++;
- *y++ = *p++;
- *y++ = *p++;
- #endif
- }
-
- #endif /* not IBM */
- #endif /* not DEC */
-
-
-
- /*
- ; e type to IEEE single precision
- ; float d;
- ; unsigned EMUSHORT x[N+2];
- ; xtod (x, &d);
- */
- #ifdef IBM
-
- void
- etoe24 (x, e)
- unsigned EMUSHORT *x, *e;
- {
- etoibm (x, e, SFmode);
- }
-
- static void
- toe24 (x, y)
- unsigned EMUSHORT *x, *y;
- {
- toibm (x, y, SFmode);
- }
-
- #else
-
- void
- etoe24 (x, e)
- unsigned EMUSHORT *x, *e;
- {
- EMULONG exp;
- unsigned EMUSHORT xi[NI];
- int rndsav;
-
- #ifdef NANS
- if (eisnan (x))
- {
- make_nan (e, SFmode);
- return;
- }
- #endif
- emovi (x, xi);
- /* adjust exponent for offsets */
- exp = (EMULONG) xi[E] - (EXONE - 0177);
- #ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
- #endif
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 24;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- nonorm:
- toe24 (xi, e);
- }
-
- static void
- toe24 (x, y)
- unsigned EMUSHORT *x, *y;
- {
- unsigned EMUSHORT i;
- unsigned EMUSHORT *p;
-
- #ifdef NANS
- if (eiisnan (x))
- {
- make_nan (y, SFmode);
- return;
- }
- #endif
- p = &x[0];
- #ifdef IBMPC
- y += 1;
- #endif
- #ifdef DEC
- y += 1;
- #endif
- *y = 0; /* output high order */
- if (*p++)
- *y = 0x8000; /* output sign bit */
-
- i = *p++;
- /* Handle overflow cases. */
- if (i >= 255)
- {
- #ifdef INFINITY
- *y |= (unsigned EMUSHORT) 0x7f80;
- #ifdef IBMPC
- *(--y) = 0;
- #endif
- #ifdef DEC
- *(--y) = 0;
- #endif
- #ifdef MIEEE
- ++y;
- *y = 0;
- #endif
- #else /* no INFINITY */
- *y |= (unsigned EMUSHORT) 0x7f7f;
- #ifdef IBMPC
- *(--y) = 0xffff;
- #endif
- #ifdef DEC
- *(--y) = 0xffff;
- #endif
- #ifdef MIEEE
- ++y;
- *y = 0xffff;
- #endif
- #ifdef ERANGE
- errno = ERANGE;
- #endif
- #endif /* no INFINITY */
- return;
- }
- if (i == 0)
- {
- eshift (x, 7);
- }
- else
- {
- i <<= 7;
- eshift (x, 8);
- }
- i |= *p++ & (unsigned EMUSHORT) 0x7f; /* *p = xi[M] */
- *y |= i; /* high order output already has sign bit set */
- #ifdef IBMPC
- *(--y) = *p;
- #endif
- #ifdef DEC
- *(--y) = *p;
- #endif
- #ifdef MIEEE
- ++y;
- *y = *p;
- #endif
- }
- #endif /* not IBM */
-
- /* Compare two e type numbers.
- *
- * unsigned EMUSHORT a[NE], b[NE];
- * 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.
- */
- int
- ecmp (a, b)
- unsigned EMUSHORT *a, *b;
- {
- unsigned EMUSHORT ai[NI], bi[NI];
- register unsigned EMUSHORT *p, *q;
- register int i;
- int msign;
-
- #ifdef NANS
- if (eisnan (a) || eisnan (b))
- return (-2);
- #endif
- emovi (a, ai);
- p = ai;
- emovi (b, bi);
- q = bi;
-
- if (*p != *q)
- { /* the signs are different */
- /* -0 equals + 0 */
- for (i = 1; i < NI - 1; i++)
- {
- if (ai[i] != 0)
- goto nzro;
- if (bi[i] != 0)
- goto nzro;
- }
- return (0);
- nzro:
- if (*p == 0)
- return (1);
- else
- return (-1);
- }
- /* both are the same sign */
- if (*p == 0)
- msign = 1;
- else
- msign = -1;
- i = NI - 1;
- do
- {
- if (*p++ != *q++)
- {
- goto diff;
- }
- }
- while (--i > 0);
-
- return (0); /* equality */
-
-
-
- diff:
-
- if (*(--p) > *(--q))
- return (msign); /* p is bigger */
- else
- return (-msign); /* p is littler */
- }
-
-
-
-
- /* Find nearest integer to x = floor (x + 0.5)
- *
- * unsigned EMUSHORT x[NE], y[NE]
- * eround (x, y);
- */
- void
- eround (x, y)
- unsigned EMUSHORT *x, *y;
- {
- eadd (ehalf, x, y);
- efloor (y, y);
- }
-
-
-
-
- /*
- ; convert HOST_WIDE_INT to e type
- ;
- ; HOST_WIDE_INT l;
- ; unsigned EMUSHORT x[NE];
- ; ltoe (&l, x);
- ; note &l is the memory address of l
- */
- void
- ltoe (lp, y)
- HOST_WIDE_INT *lp;
- unsigned EMUSHORT *y;
- {
- unsigned EMUSHORT yi[NI];
- unsigned HOST_WIDE_INT ll;
- int k;
-
- ecleaz (yi);
- if (*lp < 0)
- {
- /* make it positive */
- ll = (unsigned HOST_WIDE_INT) (-(*lp));
- yi[0] = 0xffff; /* put correct sign in the e type number */
- }
- else
- {
- ll = (unsigned HOST_WIDE_INT) (*lp);
- }
- /* move the long integer to yi significand area */
- #if HOST_BITS_PER_WIDE_INT == 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 */
- #else
- yi[M] = (unsigned EMUSHORT) (ll >> 16);
- yi[M + 1] = (unsigned EMUSHORT) ll;
- yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
- #endif
-
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
- else
- yi[E] -= (unsigned EMUSHORT) k;/* subtract shift count from exponent */
- emovo (yi, y); /* output the answer */
- }
-
- /*
- ; convert unsigned HOST_WIDE_INT to e type
- ;
- ; unsigned HOST_WIDE_INT l;
- ; unsigned EMUSHORT x[NE];
- ; ltox (&l, x);
- ; note &l is the memory address of l
- */
- void
- ultoe (lp, y)
- unsigned HOST_WIDE_INT *lp;
- unsigned EMUSHORT *y;
- {
- unsigned EMUSHORT yi[NI];
- unsigned HOST_WIDE_INT ll;
- int k;
-
- ecleaz (yi);
- ll = *lp;
-
- /* move the long integer to ayi significand area */
- #if HOST_BITS_PER_WIDE_INT == 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 */
- #else
- yi[M] = (unsigned EMUSHORT) (ll >> 16);
- yi[M + 1] = (unsigned EMUSHORT) ll;
- yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
- #endif
-
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
- else
- yi[E] -= (unsigned EMUSHORT) k; /* subtract shift count from exponent */
- emovo (yi, y); /* output the answer */
- }
-
-
- /*
- ; Find signed HOST_WIDE_INT integer and floating point fractional parts
-
- ; HOST_WIDE_INT i;
- ; unsigned EMUSHORT x[NE], frac[NE];
- ; xifrac (x, &i, frac);
-
- The integer output has the sign of the input. The fraction is
- the positive fractional part of abs (x).
- */
- void
- eifrac (x, i, frac)
- unsigned EMUSHORT *x;
- HOST_WIDE_INT *i;
- unsigned EMUSHORT *frac;
- {
- unsigned EMUSHORT xi[NI];
- int j, k;
- unsigned HOST_WIDE_INT ll;
-
- emovi (x, xi);
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- /* if exponent <= 0, integer = 0 and real output is fraction */
- *i = 0L;
- emovo (xi, frac);
- return;
- }
- if (k > (HOST_BITS_PER_WIDE_INT - 1))
- {
- /* long integer overflow: output large integer
- and correct fraction */
- if (xi[0])
- *i = ((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1);
- else
- *i = (((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1)) - 1;
- eshift (xi, k);
- if (extra_warnings)
- warning ("overflow on truncation to integer");
- }
- else if (k > 16)
- {
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- eshift (xi, j);
- ll = xi[M];
- k -= j;
- do
- {
- eshup6 (xi);
- ll = (ll << 16) | xi[M];
- }
- while ((k -= 16) > 0);
- *i = ll;
- if (xi[0])
- *i = -(*i);
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
- *i = (HOST_WIDE_INT) xi[M] & 0xffff;
- if (xi[0])
- *i = -(*i);
- }
- xi[0] = 0;
- xi[E] = EXONE - 1;
- xi[M] = 0;
- if ((k = enormlz (xi)) > NBITS)
- ecleaz (xi);
- else
- xi[E] -= (unsigned EMUSHORT) k;
-
- emovo (xi, frac);
- }
-
-
- /* Find unsigned HOST_WIDE_INT integer and floating point fractional parts.
- A negative e type input yields integer output = 0
- but correct fraction. */
-
- void
- euifrac (x, i, frac)
- unsigned EMUSHORT *x;
- unsigned HOST_WIDE_INT *i;
- unsigned EMUSHORT *frac;
- {
- unsigned HOST_WIDE_INT ll;
- unsigned EMUSHORT xi[NI];
- int j, k;
-
- emovi (x, xi);
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- /* if exponent <= 0, integer = 0 and argument is fraction */
- *i = 0L;
- emovo (xi, frac);
- return;
- }
- if (k > HOST_BITS_PER_WIDE_INT)
- {
- /* Long integer overflow: output large integer
- and correct fraction.
- Note, the BSD microvax compiler says that ~(0UL)
- is a syntax error. */
- *i = ~(0L);
- eshift (xi, k);
- if (extra_warnings)
- warning ("overflow on truncation to unsigned integer");
- }
- else if (k > 16)
- {
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- eshift (xi, j);
- ll = xi[M];
- k -= j;
- do
- {
- eshup6 (xi);
- ll = (ll << 16) | xi[M];
- }
- while ((k -= 16) > 0);
- *i = ll;
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
- *i = (HOST_WIDE_INT) xi[M] & 0xffff;
- }
-
- if (xi[0]) /* A negative value yields unsigned integer 0. */
- *i = 0L;
-
- xi[0] = 0;
- xi[E] = EXONE - 1;
- xi[M] = 0;
- if ((k = enormlz (xi)) > NBITS)
- ecleaz (xi);
- else
- xi[E] -= (unsigned EMUSHORT) k;
-
- emovo (xi, frac);
- }
-
-
-
- /*
- ; Shift significand
- ;
- ; Shifts significand area up or down by the number of bits
- ; given by the variable sc.
- */
- int
- eshift (x, sc)
- unsigned EMUSHORT *x;
- int sc;
- {
- unsigned EMUSHORT lost;
- unsigned EMUSHORT *p;
-
- if (sc == 0)
- return (0);
-
- lost = 0;
- p = x + NI - 1;
-
- if (sc < 0)
- {
- sc = -sc;
- while (sc >= 16)
- {
- lost |= *p; /* remember lost bits */
- eshdn6 (x);
- sc -= 16;
- }
-
- while (sc >= 8)
- {
- lost |= *p & 0xff;
- eshdn8 (x);
- sc -= 8;
- }
-
- while (sc > 0)
- {
- lost |= *p & 1;
- eshdn1 (x);
- sc -= 1;
- }
- }
- else
- {
- while (sc >= 16)
- {
- eshup6 (x);
- sc -= 16;
- }
-
- while (sc >= 8)
- {
- eshup8 (x);
- sc -= 8;
- }
-
- while (sc > 0)
- {
- eshup1 (x);
- sc -= 1;
- }
- }
- if (lost)
- lost = 1;
- return ((int) lost);
- }
-
-
-
- /*
- ; normalize
- ;
- ; Shift normalizes the significand area pointed to by argument
- ; shift count (up = positive) is returned.
- */
- int
- enormlz (x)
- unsigned EMUSHORT x[];
- {
- register unsigned EMUSHORT *p;
- int sc;
-
- sc = 0;
- p = &x[M];
- if (*p != 0)
- goto normdn;
- ++p;
- if (*p & 0x8000)
- return (0); /* already normalized */
- while (*p == 0)
- {
- eshup6 (x);
- sc += 16;
- /* With guard word, there are NBITS+16 bits available.
- * return true if all are zero.
- */
- if (sc > NBITS)
- return (sc);
- }
- /* see if high byte is zero */
- while ((*p & 0xff00) == 0)
- {
- eshup8 (x);
- sc += 8;
- }
- /* now shift 1 bit at a time */
- while ((*p & 0x8000) == 0)
- {
- eshup1 (x);
- sc += 1;
- if (sc > NBITS)
- {
- mtherr ("enormlz", UNDERFLOW);
- return (sc);
- }
- }
- return (sc);
-
- /* Normalize by shifting down out of the high guard word
- of the significand */
- normdn:
-
- if (*p & 0xff00)
- {
- eshdn8 (x);
- sc -= 8;
- }
- while (*p != 0)
- {
- eshdn1 (x);
- sc -= 1;
-
- if (sc < -NBITS)
- {
- mtherr ("enormlz", OVERFLOW);
- return (sc);
- }
- }
- return (sc);
- }
-
-
-
-
- /* Convert e type number to decimal format ASCII string.
- * The constants are for 64 bit precision.
- */
-
- #define NTEN 12
- #define MAXP 4096
-
- #if LONG_DOUBLE_TYPE_SIZE == 128
- static unsigned EMUSHORT etens[NTEN + 1][NE] =
- {
- {0x6576, 0x4a92, 0x804a, 0x153f,
- 0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */
- {0x6a32, 0xce52, 0x329a, 0x28ce,
- 0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */
- {0x526c, 0x50ce, 0xf18b, 0x3d28,
- 0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
- {0x9c66, 0x58f8, 0xbc50, 0x5c54,
- 0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
- {0x851e, 0xeab7, 0x98fe, 0x901b,
- 0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
- {0x0235, 0x0137, 0x36b1, 0x336c,
- 0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
- {0x50f8, 0x25fb, 0xc76b, 0x6b71,
- 0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */
- };
-
- static unsigned EMUSHORT emtens[NTEN + 1][NE] =
- {
- {0x2030, 0xcffc, 0xa1c3, 0x8123,
- 0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */
- {0x8264, 0xd2cb, 0xf2ea, 0x12d4,
- 0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */
- {0xf53f, 0xf698, 0x6bd3, 0x0158,
- 0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
- {0xe731, 0x04d4, 0xe3f2, 0xd332,
- 0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
- {0xa23e, 0x5308, 0xfefb, 0x1155,
- 0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
- {0xe26d, 0xdbde, 0xd05d, 0xb3f6,
- 0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
- {0x2a20, 0x6224, 0x47b3, 0x98d7,
- 0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
- {0x0b5b, 0x4af2, 0xa581, 0x18ed,
- 0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
- {0xbf71, 0xa9b3, 0x7989, 0xbe68,
- 0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
- {0x3d4d, 0x7c3d, 0x36ba, 0x0d2b,
- 0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
- {0xc155, 0xa4a8, 0x404e, 0x6113,
- 0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
- {0xd70a, 0x70a3, 0x0a3d, 0xa3d7,
- 0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
- {0xcccd, 0xcccc, 0xcccc, 0xcccc,
- 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */
- };
- #else
- /* LONG_DOUBLE_TYPE_SIZE is other than 128 */
- 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 */
- };
- #endif
-
- void
- e24toasc (x, string, ndigs)
- unsigned EMUSHORT x[];
- char *string;
- int ndigs;
- {
- unsigned EMUSHORT w[NI];
-
- e24toe (x, w);
- etoasc (w, string, ndigs);
- }
-
-
- void
- e53toasc (x, string, ndigs)
- unsigned EMUSHORT x[];
- char *string;
- int ndigs;
- {
- unsigned EMUSHORT w[NI];
-
- e53toe (x, w);
- etoasc (w, string, ndigs);
- }
-
-
- void
- e64toasc (x, string, ndigs)
- unsigned EMUSHORT x[];
- char *string;
- int ndigs;
- {
- unsigned EMUSHORT w[NI];
-
- e64toe (x, w);
- etoasc (w, string, ndigs);
- }
-
- void
- e113toasc (x, string, ndigs)
- unsigned EMUSHORT x[];
- char *string;
- int ndigs;
- {
- unsigned EMUSHORT w[NI];
-
- e113toe (x, w);
- etoasc (w, string, ndigs);
- }
-
-
- static char wstring[80]; /* working storage for ASCII output */
-
- void
- etoasc (x, string, ndigs)
- unsigned EMUSHORT x[];
- char *string;
- int ndigs;
- {
- EMUSHORT digit;
- unsigned EMUSHORT y[NI], t[NI], u[NI], w[NI];
- unsigned EMUSHORT *p, *r, *ten;
- unsigned EMUSHORT sign;
- int i, j, k, expon, rndsav;
- char *s, *ss;
- unsigned EMUSHORT m;
-
-
- rndsav = rndprc;
- ss = string;
- s = wstring;
- *ss = '\0';
- *s = '\0';
- #ifdef NANS
- if (eisnan (x))
- {
- sprintf (wstring, " NaN ");
- goto bxit;
- }
- #endif
- rndprc = NBITS; /* set to full precision */
- emov (x, y); /* retain external format */
- if (y[NE - 1] & 0x8000)
- {
- sign = 0xffff;
- y[NE - 1] &= 0x7fff;
- }
- else
- {
- sign = 0;
- }
- expon = 0;
- ten = &etens[NTEN][0];
- emov (eone, t);
- /* Test for zero exponent */
- if (y[NE - 1] == 0)
- {
- for (k = 0; k < NE - 1; k++)
- {
- if (y[k] != 0)
- goto tnzro; /* denormalized number */
- }
- goto isone; /* legal all zeros */
- }
- tnzro:
-
- /* Test for infinity. */
- if (y[NE - 1] == 0x7fff)
- {
- if (sign)
- sprintf (wstring, " -NaN ");
- else
- sprintf (wstring, " NaN ");
- goto bxit;
- }
-
- /* 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");
- goto bxit;
- }
-
- /* Compare to 1.0 */
- i = ecmp (eone, y);
- if (i == 0)
- goto isone;
-
- if (i == -2)
- abort ();
-
- if (i < 0)
- { /* Number is greater than 1 */
- /* Convert significand to an integer and strip trailing decimal zeros. */
- emov (y, u);
- u[NE - 1] = EXONE + NBITS - 1;
-
- p = &etens[NTEN - 4][0];
- m = 16;
- do
- {
- ediv (p, u, t);
- efloor (t, w);
- for (j = 0; j < NE - 1; j++)
- {
- if (t[j] != w[j])
- goto noint;
- }
- emov (t, u);
- expon += (int) m;
- noint:
- p += NE;
- m >>= 1;
- }
- while (m != 0);
-
- /* Rescale from integer significand */
- u[NE - 1] += y[NE - 1] - (unsigned int) (EXONE + NBITS - 1);
- emov (u, y);
- /* Find power of 10 */
- emov (eone, t);
- m = MAXP;
- p = &etens[0][0];
- /* An unordered compare result shouldn't happen here. */
- while (ecmp (ten, u) <= 0)
- {
- if (ecmp (p, u) <= 0)
- {
- ediv (p, u, u);
- emul (p, t, t);
- expon += (int) m;
- }
- m >>= 1;
- if (m == 0)
- break;
- p += NE;
- }
- }
- else
- { /* Number is less than 1.0 */
- /* Pad significand with trailing decimal zeros. */
- if (y[NE - 1] == 0)
- {
- while ((y[NE - 2] & 0x8000) == 0)
- {
- emul (ten, y, y);
- expon -= 1;
- }
- }
- else
- {
- emovi (y, w);
- for (i = 0; i < NDEC + 1; i++)
- {
- if ((w[NI - 1] & 0x7) != 0)
- break;
- /* multiply by 10 */
- emovz (w, u);
- eshdn1 (u);
- eshdn1 (u);
- eaddm (w, u);
- u[1] += 3;
- while (u[2] != 0)
- {
- eshdn1 (u);
- u[1] += 1;
- }
- if (u[NI - 1] != 0)
- break;
- if (eone[NE - 1] <= u[1])
- break;
- emovz (u, w);
- expon -= 1;
- }
- emovo (w, y);
- }
- k = -MAXP;
- p = &emtens[0][0];
- r = &etens[0][0];
- emov (y, w);
- emov (eone, t);
- while (ecmp (eone, w) > 0)
- {
- if (ecmp (p, w) >= 0)
- {
- emul (r, w, w);
- emul (r, t, t);
- expon += k;
- }
- k /= 2;
- if (k == 0)
- break;
- p += NE;
- r += NE;
- }
- ediv (t, eone, t);
- }
- isone:
- /* Find the first (leading) digit. */
- emovi (t, w);
- emovz (w, t);
- emovi (y, w);
- emovz (w, y);
- eiremain (t, y);
- digit = equot[NI - 1];
- while ((digit == 0) && (ecmp (y, ezero) != 0))
- {
- eshup1 (y);
- emovz (y, u);
- eshup1 (u);
- eshup1 (u);
- eaddm (u, y);
- eiremain (t, y);
- digit = equot[NI - 1];
- expon -= 1;
- }
- s = wstring;
- if (sign)
- *s++ = '-';
- else
- *s++ = ' ';
- /* Examine number of digits requested by caller. */
- if (ndigs < 0)
- ndigs = 0;
- if (ndigs > NDEC)
- ndigs = NDEC;
- if (digit == 10)
- {
- *s++ = '1';
- *s++ = '.';
- if (ndigs > 0)
- {
- *s++ = '0';
- ndigs -= 1;
- }
- expon += 1;
- }
- else
- {
- *s++ = (char)digit + '0';
- *s++ = '.';
- }
- /* Generate digits after the decimal point. */
- for (k = 0; k <= ndigs; k++)
- {
- /* multiply current number by 10, without normalizing */
- eshup1 (y);
- emovz (y, u);
- eshup1 (u);
- eshup1 (u);
- eaddm (u, y);
- eiremain (t, y);
- *s++ = (char) equot[NI - 1] + '0';
- }
- digit = equot[NI - 1];
- --s;
- ss = s;
- /* round off the ASCII string */
- if (digit > 4)
- {
- /* Test for critical rounding case in ASCII output. */
- if (digit == 5)
- {
- emovo (y, t);
- if (ecmp (t, ezero) != 0)
- goto roun; /* round to nearest */
- if ((*(s - 1) & 1) == 0)
- goto doexp; /* round to even */
- }
- /* Round up and propagate carry-outs */
- roun:
- --s;
- k = *s & 0x7f;
- /* Carry out to most significant digit? */
- if (k == '.')
- {
- --s;
- k = *s;
- k += 1;
- *s = (char) k;
- /* Most significant digit carries to 10? */
- if (k > '9')
- {
- expon += 1;
- *s = '1';
- }
- goto doexp;
- }
- /* Round up and carry out from less significant digits */
- k += 1;
- *s = (char) k;
- if (k > '9')
- {
- *s = '0';
- goto roun;
- }
- }
- doexp:
- /*
- if (expon >= 0)
- sprintf (ss, "e+%d", expon);
- else
- sprintf (ss, "e%d", expon);
- */
- sprintf (ss, "e%d", expon);
- bxit:
- rndprc = rndsav;
- /* copy out the working string */
- s = string;
- ss = wstring;
- while (*ss == ' ') /* strip possible leading space */
- ++ss;
- while ((*s++ = *ss++) != '\0')
- ;
- }
-
-
-
-
- /*
- ; ASCTOQ
- ; ASCTOQ.MAC LATEST REV: 11 JAN 84
- ; SLM, 3 JAN 78
- ;
- ; 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).
- ;
- ; Usage:
- ; asctoq (string, q);
- */
-
- /* ASCII to single */
- void
- asctoe24 (s, y)
- char *s;
- unsigned EMUSHORT *y;
- {
- asctoeg (s, y, 24);
- }
-
-
- /* ASCII to double */
- void
- asctoe53 (s, y)
- char *s;
- unsigned EMUSHORT *y;
- {
- #if defined(DEC) || defined(IBM)
- asctoeg (s, y, 56);
- #else
- asctoeg (s, y, 53);
- #endif
- }
-
-
- /* ASCII to long double */
- void
- asctoe64 (s, y)
- char *s;
- unsigned EMUSHORT *y;
- {
- asctoeg (s, y, 64);
- }
-
- /* ASCII to 128-bit long double */
- void
- asctoe113 (s, y)
- char *s;
- unsigned EMUSHORT *y;
- {
- asctoeg (s, y, 113);
- }
-
- /* ASCII to super double */
- void
- asctoe (s, y)
- char *s;
- unsigned EMUSHORT *y;
- {
- asctoeg (s, y, NBITS);
- }
-
-
- /* ASCII to e type, with specified rounding precision = oprec. */
- void
- asctoeg (ss, y, oprec)
- char *ss;
- unsigned EMUSHORT *y;
- int oprec;
- {
- unsigned EMUSHORT yy[NI], xt[NI], tt[NI];
- int esign, decflg, sgnflg, nexp, exp, prec, lost;
- int k, trail, c, rndsav;
- EMULONG lexp;
- unsigned EMUSHORT nsign, *p;
- char *sp, *s, *lstr;
-
- /* Copy the input string. */
- lstr = (char *) alloca (strlen (ss) + 1);
- s = ss;
- while (*s == ' ') /* skip leading spaces */
- ++s;
- sp = lstr;
- while ((*sp++ = *s++) != '\0')
- ;
- s = lstr;
-
- rndsav = rndprc;
- rndprc = NBITS; /* Set to full precision */
- lost = 0;
- nsign = 0;
- decflg = 0;
- sgnflg = 0;
- nexp = 0;
- exp = 0;
- prec = 0;
- ecleaz (yy);
- trail = 0;
-
- nxtcom:
- k = *s - '0';
- if ((k >= 0) && (k <= 9))
- {
- /* Ignore leading zeros */
- if ((prec == 0) && (decflg == 0) && (k == 0))
- goto donchr;
- /* Identify and strip trailing zeros after the decimal point. */
- if ((trail == 0) && (decflg != 0))
- {
- sp = s;
- while ((*sp >= '0') && (*sp <= '9'))
- ++sp;
- /* Check for syntax error */
- c = *sp & 0x7f;
- if ((c != 'e') && (c != 'E') && (c != '\0')
- && (c != '\n') && (c != '\r') && (c != ' ')
- && (c != ','))
- goto error;
- --sp;
- while (*sp == '0')
- *sp-- = 'z';
- trail = 1;
- if (*s == 'z')
- goto donchr;
- }
- /* 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.
- */
- if (yy[2] == 0)
- {
- if (decflg)
- nexp += 1; /* count digits after decimal point */
- eshup1 (yy); /* multiply current number by 10 */
- emovz (yy, xt);
- eshup1 (xt);
- eshup1 (xt);
- eaddm (xt, yy);
- ecleaz (xt);
- xt[NI - 2] = (unsigned EMUSHORT) k;
- eaddm (xt, yy);
- }
- else
- {
- /* Mark any lost non-zero digit. */
- lost |= k;
- /* Count lost digits before the decimal point. */
- if (decflg == 0)
- nexp -= 1;
- }
- prec += 1;
- goto donchr;
- }
-
- switch (*s)
- {
- case 'z':
- break;
- case 'E':
- case 'e':
- goto expnt;
- case '.': /* decimal point */
- if (decflg)
- goto error;
- ++decflg;
- break;
- case '-':
- nsign = 0xffff;
- if (sgnflg)
- goto error;
- ++sgnflg;
- break;
- case '+':
- if (sgnflg)
- goto error;
- ++sgnflg;
- break;
- case ',':
- case ' ':
- case '\0':
- case '\n':
- case '\r':
- goto daldone;
- case 'i':
- case 'I':
- goto infinite;
- default:
- error:
- #ifdef NANS
- einan (yy);
- #else
- mtherr ("asctoe", DOMAIN);
- eclear (yy);
- #endif
- goto aexit;
- }
- donchr:
- ++s;
- goto nxtcom;
-
- /* Exponent interpretation */
- expnt:
-
- esign = 1;
- exp = 0;
- ++s;
- /* check for + or - */
- if (*s == '-')
- {
- esign = -1;
- ++s;
- }
- if (*s == '+')
- ++s;
- while ((*s >= '0') && (*s <= '9'))
- {
- exp *= 10;
- exp += *s++ - '0';
- if (exp > -(MINDECEXP))
- {
- if (esign < 0)
- goto zero;
- else
- goto infinite;
- }
- }
- if (esign < 0)
- exp = -exp;
- if (exp > MAXDECEXP)
- {
- infinite:
- ecleaz (yy);
- yy[E] = 0x7fff; /* infinity */
- goto aexit;
- }
- if (exp < MINDECEXP)
- {
- zero:
- ecleaz (yy);
- goto aexit;
- }
-
- daldone:
- nexp = exp - nexp;
- /* Pad trailing zeros to minimize power of 10, per IEEE spec. */
- while ((nexp > 0) && (yy[2] == 0))
- {
- emovz (yy, xt);
- eshup1 (xt);
- eshup1 (xt);
- eaddm (yy, xt);
- eshup1 (xt);
- if (xt[2] != 0)
- break;
- nexp -= 1;
- emovz (xt, yy);
- }
- if ((k = enormlz (yy)) > NBITS)
- {
- ecleaz (yy);
- goto aexit;
- }
- 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.
- */
- lexp = yy[E];
- if (nexp == 0)
- {
- k = 0;
- goto expdon;
- }
- esign = 1;
- if (nexp < 0)
- {
- nexp = -nexp;
- esign = -1;
- if (nexp > 4096)
- { /* Punt. Can't handle this without 2 divides. */
- emovi (etens[0], tt);
- lexp -= tt[E];
- k = edivm (tt, yy);
- lexp += EXONE;
- nexp -= 4096;
- }
- }
- p = &etens[NTEN][0];
- emov (eone, xt);
- exp = 1;
- do
- {
- if (exp & nexp)
- emul (p, xt, xt);
- p -= NE;
- exp = exp + exp;
- }
- while (exp <= MAXP);
-
- emovi (xt, tt);
- if (esign < 0)
- {
- lexp -= tt[E];
- k = edivm (tt, yy);
- lexp += EXONE;
- }
- else
- {
- lexp += tt[E];
- k = emulm (tt, yy);
- lexp -= EXONE - 1;
- }
-
- expdon:
-
- /* Round and convert directly to the destination type */
- if (oprec == 53)
- lexp -= EXONE - 0x3ff;
- #ifdef IBM
- else if (oprec == 24 || oprec == 56)
- lexp -= EXONE - (0x41 << 2);
- #else
- else if (oprec == 24)
- lexp -= EXONE - 0177;
- #endif
- #ifdef DEC
- else if (oprec == 56)
- lexp -= EXONE - 0201;
- #endif
- rndprc = oprec;
- emdnorm (yy, k, 0, lexp, 64);
-
- aexit:
-
- rndprc = rndsav;
- yy[0] = nsign;
- switch (oprec)
- {
- #ifdef DEC
- case 56:
- todec (yy, y); /* see etodec.c */
- break;
- #endif
- #ifdef IBM
- case 56:
- toibm (yy, y, DFmode);
- break;
- #endif
- case 53:
- toe53 (yy, y);
- break;
- case 24:
- toe24 (yy, y);
- break;
- case 64:
- toe64 (yy, y);
- break;
- case 113:
- toe113 (yy, y);
- break;
- case NBITS:
- emovo (yy, y);
- break;
- }
- }
-
-
-
- /* y = largest integer not greater than x
- * (truncated toward minus infinity)
- *
- * unsigned EMUSHORT x[NE], y[NE]
- *
- * efloor (x, y);
- */
- static unsigned EMUSHORT bmask[] =
- {
- 0xffff,
- 0xfffe,
- 0xfffc,
- 0xfff8,
- 0xfff0,
- 0xffe0,
- 0xffc0,
- 0xff80,
- 0xff00,
- 0xfe00,
- 0xfc00,
- 0xf800,
- 0xf000,
- 0xe000,
- 0xc000,
- 0x8000,
- 0x0000,
- };
-
- void
- efloor (x, y)
- unsigned EMUSHORT x[], y[];
- {
- register unsigned EMUSHORT *p;
- int e, expon, i;
- unsigned EMUSHORT f[NE];
-
- emov (x, f); /* leave in external format */
- expon = (int) f[NE - 1];
- e = (expon & 0x7fff) - (EXONE - 1);
- if (e <= 0)
- {
- eclear (y);
- goto isitneg;
- }
- /* number of bits to clear out */
- e = NBITS - e;
- emov (f, y);
- if (e <= 0)
- return;
-
- p = &y[0];
- while (e >= 16)
- {
- *p++ = 0;
- e -= 16;
- }
- /* clear the remaining bits */
- *p &= bmask[e];
- /* truncate negatives toward minus infinity */
- isitneg:
-
- if ((unsigned EMUSHORT) expon & (unsigned EMUSHORT) 0x8000)
- {
- for (i = 0; i < NE - 1; i++)
- {
- if (f[i] != y[i])
- {
- esub (eone, y, y);
- break;
- }
- }
- }
- }
-
-
- /* unsigned EMUSHORT x[], s[];
- * int *exp;
- *
- * efrexp (x, exp, 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.
- */
- void
- efrexp (x, exp, s)
- unsigned EMUSHORT x[];
- int *exp;
- unsigned EMUSHORT s[];
- {
- unsigned EMUSHORT xi[NI];
- EMULONG li;
-
- emovi (x, xi);
- li = (EMULONG) ((EMUSHORT) xi[1]);
-
- if (li == 0)
- {
- li -= enormlz (xi);
- }
- xi[1] = 0x3ffe;
- emovo (xi, s);
- *exp = (int) (li - 0x3ffe);
- }
-
-
-
- /* unsigned EMUSHORT x[], y[];
- * int pwr2;
- *
- * eldexp (x, pwr2, y);
- *
- * Returns y = x * 2**pwr2.
- */
- void
- eldexp (x, pwr2, y)
- unsigned EMUSHORT x[];
- int pwr2;
- unsigned EMUSHORT y[];
- {
- unsigned EMUSHORT xi[NI];
- EMULONG li;
- int i;
-
- emovi (x, xi);
- li = xi[1];
- li += pwr2;
- i = 0;
- emdnorm (xi, i, i, li, 64);
- emovo (xi, y);
- }
-
-
- /* c = remainder after dividing b by a
- * Least significant integer quotient bits left in equot[].
- */
- void
- eremain (a, b, c)
- unsigned EMUSHORT a[], b[], c[];
- {
- unsigned EMUSHORT den[NI], num[NI];
-
- #ifdef NANS
- if (eisinf (b)
- || (ecmp (a, ezero) == 0)
- || eisnan (a)
- || eisnan (b))
- {
- enan (c);
- return;
- }
- #endif
- if (ecmp (a, ezero) == 0)
- {
- mtherr ("eremain", SING);
- eclear (c);
- return;
- }
- emovi (a, den);
- emovi (b, num);
- eiremain (den, num);
- /* Sign of remainder = sign of quotient */
- if (a[0] == b[0])
- num[0] = 0;
- else
- num[0] = 0xffff;
- emovo (num, c);
- }
-
- void
- eiremain (den, num)
- unsigned EMUSHORT den[], num[];
- {
- EMULONG ld, ln;
- unsigned EMUSHORT j;
-
- ld = den[E];
- ld -= enormlz (den);
- ln = num[E];
- ln -= enormlz (num);
- ecleaz (equot);
- while (ln >= ld)
- {
- if (ecmpm (den, num) <= 0)
- {
- esubm (den, num);
- j = 1;
- }
- else
- {
- j = 0;
- }
- eshup1 (equot);
- equot[NI - 1] |= j;
- eshup1 (num);
- ln -= 1;
- }
- emdnorm (num, 0, 0, ln, 0);
- }
-
- /* mtherr.c
- *
- * Library common error handling routine
- *
- *
- *
- * SYNOPSIS:
- *
- * char *fctnam;
- * int code;
- * void mtherr ();
- *
- * mtherr (fctnam, code);
- *
- *
- *
- * DESCRIPTION:
- *
- * 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
- * errors.
- *
- * Since all error conditions pass control to this function,
- * the display may be easily changed, eliminated, or directed
- * to an error logging device.
- *
- * SEE ALSO:
- *
- * mconf.h
- *
- */
-
- /*
- Cephes Math Library Release 2.0: April, 1987
- Copyright 1984, 1987 by Stephen L. Moshier
- Direct inquiries to 30 Frost Street, Cambridge, MA 02140
- */
-
- /* include "mconf.h" */
-
- /* Notice: the order of appearance of the following
- * messages is bound to the error codes defined
- * in mconf.h.
- */
- #define NMSGS 8
- static char *ermsg[NMSGS] =
- {
- "unknown", /* error code 0 */
- "domain", /* error code 1 */
- "singularity", /* et seq. */
- "overflow",
- "underflow",
- "total loss of precision",
- "partial loss of precision",
- "invalid operation"
- };
-
- int merror = 0;
- extern int merror;
-
- void
- mtherr (name, code)
- char *name;
- int code;
- {
- char errstr[80];
-
- /* 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
- * by the code argument.
- */
- if ((code <= 0) || (code >= NMSGS))
- code = 0;
- sprintf (errstr, " %s %s error", name, ermsg[code]);
- if (extra_warnings)
- warning (errstr);
- /* Set global error message word */
- merror = code + 1;
-
- /* Return to calling
- * program
- */
- }
-
- #ifdef DEC
- /* Here is etodec.c .
- *
- */
-
- /*
- ; convert DEC double precision to e type
- ; double d;
- ; EMUSHORT e[NE];
- ; dectoe (&d, e);
- */
- void
- dectoe (d, e)
- unsigned EMUSHORT *d;
- unsigned EMUSHORT *e;
- {
- unsigned EMUSHORT y[NI];
- 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 */
- goto done;
-
-
- 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 */
- *p++ = *d++;
- *p = *d;
-
- eshdn8 (y); /* shift our mantissa down 8 bits */
- done:
- emovo (y, e);
- }
-
-
-
- /*
- ; convert e type to DEC double precision
- ; double d;
- ; EMUSHORT e[NE];
- ; etodec (e, &d);
- */
-
- void
- etodec (x, d)
- unsigned EMUSHORT *x, *d;
- {
- unsigned EMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- emovi (x, xi);
- exp = (EMULONG) xi[E] - (EXONE - 0201); /* adjust exponent for offsets */
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- todec (xi, d);
- }
-
- void
- todec (x, y)
- unsigned EMUSHORT *x, *y;
- {
- unsigned EMUSHORT i;
- unsigned EMUSHORT *p;
-
- p = x;
- *y = 0;
- if (*p++)
- *y = 0100000;
- i = *p++;
- if (i == 0)
- {
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
- return;
- }
- if (i > 0377)
- {
- *y++ |= 077777;
- *y++ = 0xffff;
- *y++ = 0xffff;
- *y++ = 0xffff;
- #ifdef ERANGE
- errno = ERANGE;
- #endif
- return;
- }
- i &= 0377;
- i <<= 7;
- eshup8 (x);
- x[M] &= 0177;
- i |= x[M];
- *y++ |= i;
- *y++ = x[M + 1];
- *y++ = x[M + 2];
- *y++ = x[M + 3];
- }
- #endif /* DEC */
-
- #ifdef IBM
- /* Here is etoibm
- *
- */
-
- /*
- ; convert IBM single/double precision to e type
- ; single/double d;
- ; EMUSHORT e[NE];
- ; enum machine_mode mode; SFmode/DFmode
- ; ibmtoe (&d, e, mode);
- */
- void
- ibmtoe (d, e, mode)
- unsigned EMUSHORT *d;
- unsigned EMUSHORT *e;
- enum machine_mode mode;
- {
- unsigned EMUSHORT y[NI];
- register unsigned EMUSHORT r, *p;
- int rndsav;
-
- ecleaz (y); /* start with a zero */
- p = y; /* point to our number */
- r = *d; /* get IBM exponent word */
- if (*d & (unsigned int) 0x8000)
- *p = 0xffff; /* fill in our sign */
- ++p; /* bump pointer to our exponent word */
- r &= 0x7f00; /* strip the sign bit */
- r >>= 6; /* shift exponent word down 6 bits */
- /* in fact shift by 8 right and 2 left */
- r += EXONE - (0x41 << 2); /* subtract IBM exponent offset */
- /* add our e type exponent offset */
- *p++ = r; /* to form our exponent */
-
- *p++ = *d++ & 0xff; /* now do the high order mantissa */
- /* strip off the IBM exponent and sign bits */
- if (mode != SFmode) /* there are only 2 words in SFmode */
- {
- *p++ = *d++; /* fill in the rest of our mantissa */
- *p++ = *d++;
- }
- *p = *d;
-
- if (y[M] == 0 && y[M+1] == 0 && y[M+2] == 0 && y[M+3] == 0)
- y[0] = y[E] = 0;
- else
- y[E] -= 5 + enormlz (y); /* now normalise the mantissa */
- /* handle change in RADIX */
- emovo (y, e);
- }
-
-
-
- /*
- ; convert e type to IBM single/double precision
- ; single/double d;
- ; EMUSHORT e[NE];
- ; enum machine_mode mode; SFmode/DFmode
- ; etoibm (e, &d, mode);
- */
-
- void
- etoibm (x, d, mode)
- unsigned EMUSHORT *x, *d;
- enum machine_mode mode;
- {
- unsigned EMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- emovi (x, xi);
- exp = (EMULONG) xi[E] - (EXONE - (0x41 << 2)); /* adjust exponent for offsets */
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- toibm (xi, d, mode);
- }
-
- void
- toibm (x, y, mode)
- unsigned EMUSHORT *x, *y;
- enum machine_mode mode;
- {
- unsigned EMUSHORT i;
- unsigned EMUSHORT *p;
- int r;
-
- p = x;
- *y = 0;
- if (*p++)
- *y = 0x8000;
- i = *p++;
- if (i == 0)
- {
- *y++ = 0;
- *y++ = 0;
- if (mode != SFmode)
- {
- *y++ = 0;
- *y++ = 0;
- }
- return;
- }
- r = i & 0x3;
- i >>= 2;
- if (i > 0x7f)
- {
- *y++ |= 0x7fff;
- *y++ = 0xffff;
- if (mode != SFmode)
- {
- *y++ = 0xffff;
- *y++ = 0xffff;
- }
- #ifdef ERANGE
- errno = ERANGE;
- #endif
- return;
- }
- i &= 0x7f;
- *y |= (i << 8);
- eshift (x, r + 5);
- *y++ |= x[M];
- *y++ = x[M + 1];
- if (mode != SFmode)
- {
- *y++ = x[M + 2];
- *y++ = x[M + 3];
- }
- }
- #endif /* IBM */
-
- /* 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
- patterns here. */
- #ifdef TFMODE_NAN
- TFMODE_NAN;
- #else
- #ifdef MIEEE
- unsigned EMUSHORT TFnan[8] =
- {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
- #endif
- #ifdef IBMPC
- unsigned EMUSHORT TFnan[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0xffff};
- #endif
- #endif
-
- #ifdef XFMODE_NAN
- XFMODE_NAN;
- #else
- #ifdef MIEEE
- unsigned EMUSHORT XFnan[6] = {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
- #endif
- #ifdef IBMPC
- unsigned EMUSHORT XFnan[6] = {0, 0, 0, 0xc000, 0xffff, 0};
- #endif
- #endif
-
- #ifdef DFMODE_NAN
- DFMODE_NAN;
- #else
- #ifdef MIEEE
- unsigned EMUSHORT DFnan[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
- #endif
- #ifdef IBMPC
- unsigned EMUSHORT DFnan[4] = {0, 0, 0, 0xfff8};
- #endif
- #endif
-
- #ifdef SFMODE_NAN
- SFMODE_NAN;
- #else
- #ifdef MIEEE
- unsigned EMUSHORT SFnan[2] = {0x7fff, 0xffff};
- #endif
- #ifdef IBMPC
- unsigned EMUSHORT SFnan[2] = {0, 0xffc0};
- #endif
- #endif
-
-
- void
- make_nan (nan, mode)
- unsigned EMUSHORT *nan;
- enum machine_mode mode;
- {
- int i, n;
- unsigned EMUSHORT *p;
-
- n = 0;
- switch (mode)
- {
- /* Possibly the `reserved operand' patterns on a VAX can be
- used like NaN's, but probably not in the same way as IEEE. */
- #if !defined(DEC) && !defined(IBM)
- case TFmode:
- n = 8;
- p = TFnan;
- break;
- case XFmode:
- n = 6;
- p = XFnan;
- break;
- case DFmode:
- n = 4;
- p = DFnan;
- break;
- case SFmode:
- n = 2;
- p = SFnan;
- break;
- #endif
- default:
- abort ();
- }
- for (i=0; i < n; i++)
- *nan++ = *p++;
- }
-
- /* 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. */
-
- REAL_VALUE_TYPE
- ereal_from_float (f)
- unsigned long f;
- {
- REAL_VALUE_TYPE r;
- unsigned EMUSHORT s[2];
- unsigned EMUSHORT e[NE];
-
- /* 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. */
- #if FLOAT_WORDS_BIG_ENDIAN
- s[0] = (unsigned EMUSHORT) (f >> 16);
- s[1] = (unsigned EMUSHORT) f;
- #else
- s[0] = (unsigned EMUSHORT) f;
- s[1] = (unsigned EMUSHORT) (f >> 16);
- #endif
- /* Convert and promote the target float to E-type. */
- e24toe (s, e);
- /* Output E-type to REAL_VALUE_TYPE. */
- PUT_REAL (e, &r);
- return r;
- }
-
-
- /* 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 long 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. */
-
- REAL_VALUE_TYPE
- ereal_from_double (d)
- unsigned long d[];
- {
- REAL_VALUE_TYPE r;
- unsigned EMUSHORT s[4];
- unsigned EMUSHORT e[NE];
-
- /* Convert array of 32 bit pieces to equivalent array of 16 bit pieces.
- This is the inverse of `endian'. */
- #if FLOAT_WORDS_BIG_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];
- #else
- 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);
- #endif
- /* Convert target double to E-type. */
- e53toe (s, e);
- /* Output E-type to REAL_VALUE_TYPE. */
- PUT_REAL (e, &r);
- return r;
- }
-
-
- /* Convert target computer unsigned 64-bit integer to e-type.
- The endian-ness of DImode follows the convention for integers,
- so we use WORDS_BIG_ENDIAN here, not FLOAT_WORDS_BIG_ENDIAN. */
-
- void
- uditoe (di, e)
- unsigned EMUSHORT *di; /* Address of the 64-bit int. */
- unsigned EMUSHORT *e;
- {
- unsigned EMUSHORT yi[NI];
- int k;
-
- ecleaz (yi);
- #if WORDS_BIG_ENDIAN
- for (k = M; k < M + 4; k++)
- yi[k] = *di++;
- #else
- for (k = M + 3; k >= M; k--)
- yi[k] = *di++;
- #endif
- yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
- else
- yi[E] -= (unsigned EMUSHORT) k;/* subtract shift count from exponent */
- emovo (yi, e);
- }
-
- /* Convert target computer signed 64-bit integer to e-type. */
-
- void
- ditoe (di, e)
- unsigned EMUSHORT *di; /* Address of the 64-bit int. */
- unsigned EMUSHORT *e;
- {
- unsigned EMULONG acc;
- unsigned EMUSHORT yi[NI];
- unsigned EMUSHORT carry;
- int k, sign;
-
- ecleaz (yi);
- #if WORDS_BIG_ENDIAN
- for (k = M; k < M + 4; k++)
- yi[k] = *di++;
- #else
- for (k = M + 3; k >= M; k--)
- yi[k] = *di++;
- #endif
- /* Take absolute value */
- sign = 0;
- if (yi[M] & 0x8000)
- {
- sign = 1;
- carry = 0;
- for (k = M + 3; k >= M; k--)
- {
- acc = (unsigned EMULONG) (~yi[k] & 0xffff) + carry;
- yi[k] = acc;
- carry = 0;
- if (acc & 0x10000)
- carry = 1;
- }
- }
- yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
- else
- yi[E] -= (unsigned EMUSHORT) k;/* subtract shift count from exponent */
- emovo (yi, e);
- if (sign)
- eneg (e);
- }
-
-
- /* Convert e-type to unsigned 64-bit int. */
-
- void
- etoudi (x, i)
- unsigned EMUSHORT *x;
- unsigned EMUSHORT *i;
- {
- unsigned EMUSHORT xi[NI];
- int j, k;
-
- emovi (x, xi);
- if (xi[0])
- {
- xi[M] = 0;
- goto noshift;
- }
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0;
- return;
- }
- if (k > 64)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0xffff;
- if (extra_warnings)
- warning ("overflow on truncation to integer");
- return;
- }
- if (k > 16)
- {
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- if (j == 0)
- j = 16;
- eshift (xi, j);
- #if WORDS_BIG_ENDIAN
- *i++ = xi[M];
- #else
- i += 3;
- *i-- = xi[M];
- #endif
- k -= j;
- do
- {
- eshup6 (xi);
- #if WORDS_BIG_ENDIAN
- *i++ = xi[M];
- #else
- *i-- = xi[M];
- #endif
- }
- while ((k -= 16) > 0);
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
-
- noshift:
-
- #if WORDS_BIG_ENDIAN
- i += 3;
- *i-- = xi[M];
- *i-- = 0;
- *i-- = 0;
- *i = 0;
- #else
- *i++ = xi[M];
- *i++ = 0;
- *i++ = 0;
- *i = 0;
- #endif
- }
- }
-
-
- /* Convert e-type to signed 64-bit int. */
-
- void
- etodi (x, i)
- unsigned EMUSHORT *x;
- unsigned EMUSHORT *i;
- {
- unsigned EMULONG acc;
- unsigned EMUSHORT xi[NI];
- unsigned EMUSHORT carry;
- unsigned EMUSHORT *isave;
- int j, k;
-
- emovi (x, xi);
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0;
- return;
- }
- if (k > 64)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0xffff;
- if (extra_warnings)
- warning ("overflow on truncation to integer");
- return;
- }
- isave = i;
- if (k > 16)
- {
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- if (j == 0)
- j = 16;
- eshift (xi, j);
- #if WORDS_BIG_ENDIAN
- *i++ = xi[M];
- #else
- i += 3;
- *i-- = xi[M];
- #endif
- k -= j;
- do
- {
- eshup6 (xi);
- #if WORDS_BIG_ENDIAN
- *i++ = xi[M];
- #else
- *i-- = xi[M];
- #endif
- }
- while ((k -= 16) > 0);
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
-
- #if WORDS_BIG_ENDIAN
- i += 3;
- *i = xi[M];
- *i-- = 0;
- *i-- = 0;
- *i = 0;
- #else
- *i++ = xi[M];
- *i++ = 0;
- *i++ = 0;
- *i = 0;
- #endif
- }
- /* Negate if negative */
- if (xi[0])
- {
- carry = 0;
- #if WORDS_BIG_ENDIAN
- isave += 3;
- #endif
- for (k = 0; k < 4; k++)
- {
- acc = (unsigned EMULONG) (~(*isave) & 0xffff) + carry;
- #if WORDS_BIG_ENDIAN
- *isave-- = acc;
- #else
- *isave++ = acc;
- #endif
- carry = 0;
- if (acc & 0x10000)
- carry = 1;
- }
- }
- }
-
-
- /* Longhand square root routine. */
-
-
- static int esqinited = 0;
- static unsigned short sqrndbit[NI];
-
- void
- esqrt (x, y)
- unsigned EMUSHORT *x, *y;
- {
- unsigned EMUSHORT temp[NI], num[NI], sq[NI], xx[NI];
- EMULONG m, exp;
- int i, j, k, n, nlups;
-
- if (esqinited == 0)
- {
- ecleaz (sqrndbit);
- sqrndbit[NI - 2] = 1;
- esqinited = 1;
- }
- /* Check for arg <= 0 */
- i = ecmp (x, ezero);
- if (i <= 0)
- {
- #ifdef NANS
- if (i == -2)
- {
- enan (y);
- return;
- }
- #endif
- eclear (y);
- if (i < 0)
- mtherr ("esqrt", DOMAIN);
- return;
- }
-
- #ifdef INFINITY
- if (eisinf (x))
- {
- eclear (y);
- einfin (y);
- return;
- }
- #endif
- /* Bring in the arg and renormalize if it is denormal. */
- emovi (x, xx);
- m = (EMULONG) xx[1]; /* local long word exponent */
- if (m == 0)
- m -= enormlz (xx);
-
- /* Divide exponent by 2 */
- m -= 0x3ffe;
- exp = (unsigned short) ((m / 2) + 0x3ffe);
-
- /* Adjust if exponent odd */
- if ((m & 1) != 0)
- {
- if (m > 0)
- exp += 1;
- eshdn1 (xx);
- }
-
- ecleaz (sq);
- ecleaz (num);
- n = 8; /* get 8 bits of result per inner loop */
- nlups = rndprc;
- j = 0;
-
- while (nlups > 0)
- {
- /* bring in next word of arg */
- if (j < NE)
- num[NI - 1] = xx[j + 3];
- /* Do additional bit on last outer loop, for roundoff. */
- if (nlups <= 8)
- n = nlups + 1;
- for (i = 0; i < n; i++)
- {
- /* Next 2 bits of arg */
- eshup1 (num);
- eshup1 (num);
- /* Shift up answer */
- eshup1 (sq);
- /* Make trial divisor */
- for (k = 0; k < NI; k++)
- temp[k] = sq[k];
- eshup1 (temp);
- eaddm (sqrndbit, temp);
- /* Subtract and insert answer bit if it goes in */
- if (ecmpm (temp, num) <= 0)
- {
- esubm (temp, num);
- sq[NI - 2] |= 1;
- }
- }
- nlups -= n;
- j += 1;
- }
-
- /* Adjust for extra, roundoff loop done. */
- exp += (NBITS - 1) - rndprc;
-
- /* Sticky bit = 1 if the remainder is nonzero. */
- k = 0;
- for (i = 3; i < NI; i++)
- k |= (int) num[i];
-
- /* Renormalize and round off. */
- emdnorm (sq, k, 0, exp, 64);
- emovo (sq, y);
- }
-
- #endif /* EMU_NON_COMPILE not defined */
-