OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc1/] [newlib/] [libc/] [stdlib/] [ldtoa.c] - Diff between revs 207 and 345

Only display areas with differences | Details | Blame | View Log

Rev 207 Rev 345
 /* Extended precision arithmetic functions for long double I/O.
 /* Extended precision arithmetic functions for long double I/O.
  * This program has been placed in the public domain.
  * This program has been placed in the public domain.
  */
  */
 
 
#include <_ansi.h>
#include <_ansi.h>
#include <reent.h>
#include <reent.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#include "mprec.h"
#include "mprec.h"
 
 
/* These are the externally visible entries. */
/* These are the externally visible entries. */
/* linux name:  long double _IO_strtold (char *, char **); */
/* linux name:  long double _IO_strtold (char *, char **); */
long double _strtold (char *, char **);
long double _strtold (char *, char **);
char * _ldtoa_r (struct _reent *, long double, int, int, int *, int *, char **);
char * _ldtoa_r (struct _reent *, long double, int, int, int *, int *, char **);
int    _ldcheck (long double *);
int    _ldcheck (long double *);
#if 0
#if 0
void _IO_ldtostr(long double *, char *, int, int, char);
void _IO_ldtostr(long double *, char *, int, int, char);
#endif
#endif
 
 
 /* Number of 16 bit words in external x type format */
 /* Number of 16 bit words in external x type format */
 #define NE 10
 #define NE 10
 
 
 /* Number of 16 bit words in internal format */
 /* Number of 16 bit words in internal format */
 #define NI (NE+3)
 #define NI (NE+3)
 
 
 /* Array offset to exponent */
 /* Array offset to exponent */
 #define E 1
 #define E 1
 
 
 /* Array offset to high guard word */
 /* Array offset to high guard word */
 #define M 2
 #define M 2
 
 
 /* Number of bits of precision */
 /* Number of bits of precision */
 #define NBITS ((NI-4)*16)
 #define NBITS ((NI-4)*16)
 
 
 /* Maximum number of decimal digits in ASCII conversion
 /* Maximum number of decimal digits in ASCII conversion
  * = NBITS*log10(2)
  * = NBITS*log10(2)
  */
  */
 #define NDEC (NBITS*8/27)
 #define NDEC (NBITS*8/27)
 
 
 /* The exponent of 1.0 */
 /* The exponent of 1.0 */
 #define EXONE (0x3fff)
 #define EXONE (0x3fff)
 
 
 /* Maximum exponent digits - base 10 */
 /* Maximum exponent digits - base 10 */
 #define MAX_EXP_DIGITS 5
 #define MAX_EXP_DIGITS 5
 
 
/* Control structure for long double conversion including rounding precision values.
/* Control structure for long double conversion including rounding precision values.
 * rndprc can be set to 80 (if NE=6), 64, 56, 53, or 24 bits.
 * rndprc can be set to 80 (if NE=6), 64, 56, 53, or 24 bits.
 */
 */
typedef struct
typedef struct
{
{
  int rlast;
  int rlast;
  int rndprc;
  int rndprc;
  int rw;
  int rw;
  int re;
  int re;
  int outexpon;
  int outexpon;
  unsigned short rmsk;
  unsigned short rmsk;
  unsigned short rmbit;
  unsigned short rmbit;
  unsigned short rebit;
  unsigned short rebit;
  unsigned short rbit[NI];
  unsigned short rbit[NI];
  unsigned short equot[NI];
  unsigned short equot[NI];
} LDPARMS;
} LDPARMS;
 
 
static void esub(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static void esub(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static void emul(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static void emul(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static void ediv(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static void ediv(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp);
static int ecmp(short unsigned int *a, short unsigned int *b);
static int ecmp(short unsigned int *a, short unsigned int *b);
static int enormlz(short unsigned int *x);
static int enormlz(short unsigned int *x);
static int eshift(short unsigned int *x, int sc);
static int eshift(short unsigned int *x, int sc);
static void eshup1(register short unsigned int *x);
static void eshup1(register short unsigned int *x);
static void eshup8(register short unsigned int *x);
static void eshup8(register short unsigned int *x);
static void eshup6(register short unsigned int *x);
static void eshup6(register short unsigned int *x);
static void eshdn1(register short unsigned int *x);
static void eshdn1(register short unsigned int *x);
static void eshdn8(register short unsigned int *x);
static void eshdn8(register short unsigned int *x);
static void eshdn6(register short unsigned int *x);
static void eshdn6(register short unsigned int *x);
static void eneg(short unsigned int *x);
static void eneg(short unsigned int *x);
static void emov(register short unsigned int *a, register short unsigned int *b);
static void emov(register short unsigned int *a, register short unsigned int *b);
static void eclear(register short unsigned int *x);
static void eclear(register short unsigned int *x);
static void einfin(register short unsigned int *x, register LDPARMS *ldp);
static void einfin(register short unsigned int *x, register LDPARMS *ldp);
static void efloor(short unsigned int *x, short unsigned int *y, LDPARMS *ldp);
static void efloor(short unsigned int *x, short unsigned int *y, LDPARMS *ldp);
static void etoasc(short unsigned int *x, char *string, int ndigs, int outformat, LDPARMS *ldp);
static void etoasc(short unsigned int *x, char *string, int ndigs, int outformat, LDPARMS *ldp);
 
 
union uconv
union uconv
{
{
  unsigned short pe;
  unsigned short pe;
  long double d;
  long double d;
};
};
 
 
#if LDBL_MANT_DIG == 24
#if LDBL_MANT_DIG == 24
static void e24toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
static void e24toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
#elif LDBL_MANT_DIG == 53
#elif LDBL_MANT_DIG == 53
static void e53toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
static void e53toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
#elif LDBL_MANT_DIG == 64
#elif LDBL_MANT_DIG == 64
static void e64toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
static void e64toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
#else
#else
static void e113toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
static void e113toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp);
#endif
#endif
 
 
/*                                                      econst.c        */
/*                                                      econst.c        */
/*  e type constants used by high precision check routines */
/*  e type constants used by high precision check routines */
 
 
#if NE == 10
#if NE == 10
/* 0.0 */
/* 0.0 */
static unsigned short ezero[NE] =
static unsigned short ezero[NE] =
 {0x0000, 0x0000, 0x0000, 0x0000,
 {0x0000, 0x0000, 0x0000, 0x0000,
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
 
 
/* 1.0E0 */
/* 1.0E0 */
static unsigned short eone[NE] =
static unsigned short eone[NE] =
 {0x0000, 0x0000, 0x0000, 0x0000,
 {0x0000, 0x0000, 0x0000, 0x0000,
  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
 
 
#else
#else
 
 
/* 0.0 */
/* 0.0 */
static unsigned short ezero[NE] = {
static unsigned short ezero[NE] = {
0, 0000000,0000000,0000000,0000000,0000000,};
0, 0000000,0000000,0000000,0000000,0000000,};
/* 1.0E0 */
/* 1.0E0 */
static unsigned short eone[NE] = {
static unsigned short eone[NE] = {
0, 0000000,0000000,0000000,0100000,0x3fff,};
0, 0000000,0000000,0000000,0100000,0x3fff,};
 
 
#endif
#endif
 
 
/* Debugging routine for displaying errors */
/* Debugging routine for displaying errors */
#ifdef DEBUG
#ifdef DEBUG
/* Notice: the order of appearance of the following
/* Notice: the order of appearance of the following
 * messages is bound to the error codes defined
 * messages is bound to the error codes defined
 * in mconf.h.
 * in mconf.h.
 */
 */
static char *ermsg[7] = {
static char *ermsg[7] = {
"unknown",      /* error code 0 */
"unknown",      /* error code 0 */
"domain",       /* error code 1 */
"domain",       /* error code 1 */
"singularity",  /* et seq.      */
"singularity",  /* et seq.      */
"overflow",
"overflow",
"underflow",
"underflow",
"total loss of precision",
"total loss of precision",
"partial loss of precision"
"partial loss of precision"
};
};
#define mtherr(name, code) printf( "\n%s %s error\n", name, ermsg[code] );
#define mtherr(name, code) printf( "\n%s %s error\n", name, ermsg[code] );
#else
#else
#define mtherr(name, code)
#define mtherr(name, code)
#endif
#endif
 
 
/*                                                      ieee.c
/*                                                      ieee.c
 *
 *
 *    Extended precision IEEE binary floating point arithmetic routines
 *    Extended precision IEEE binary floating point arithmetic routines
 *
 *
 * Numbers are stored in C language as arrays of 16-bit unsigned
 * Numbers are stored in C language as arrays of 16-bit unsigned
 * short integers.  The arguments of the routines are pointers to
 * short integers.  The arguments of the routines are pointers to
 * the arrays.
 * the arrays.
 *
 *
 *
 *
 * External e type data structure, simulates Intel 8087 chip
 * External e type data structure, simulates Intel 8087 chip
 * temporary real format but possibly with a larger significand:
 * temporary real format but possibly with a larger significand:
 *
 *
 *      NE-1 significand words  (least significant word first,
 *      NE-1 significand words  (least significant word first,
 *                               most significant bit is normally set)
 *                               most significant bit is normally set)
 *      exponent                (value = EXONE for 1.0,
 *      exponent                (value = EXONE for 1.0,
 *                              top bit is the sign)
 *                              top bit is the sign)
 *
 *
 *
 *
 * Internal data structure of a number (a "word" is 16 bits):
 * Internal data structure of a number (a "word" is 16 bits):
 *
 *
 * ei[0]        sign word       (0 for positive, 0xffff for negative)
 * ei[0]        sign word       (0 for positive, 0xffff for negative)
 * ei[1]        biased exponent (value = EXONE for the number 1.0)
 * ei[1]        biased exponent (value = EXONE for the number 1.0)
 * ei[2]        high guard word (always zero after normalization)
 * ei[2]        high guard word (always zero after normalization)
 * ei[3]
 * ei[3]
 * to ei[NI-2]  significand     (NI-4 significand words,
 * to ei[NI-2]  significand     (NI-4 significand words,
 *                               most significant word first,
 *                               most significant word first,
 *                               most significant bit is set)
 *                               most significant bit is set)
 * ei[NI-1]     low guard word  (0x8000 bit is rounding place)
 * ei[NI-1]     low guard word  (0x8000 bit is rounding place)
 *
 *
 *
 *
 *
 *
 *              Routines for external format numbers
 *              Routines for external format numbers
 *
 *
 *      asctoe( string, e )     ASCII string to extended double e type
 *      asctoe( string, e )     ASCII string to extended double e type
 *      asctoe64( string, &d )  ASCII string to long double
 *      asctoe64( string, &d )  ASCII string to long double
 *      asctoe53( string, &d )  ASCII string to double
 *      asctoe53( string, &d )  ASCII string to double
 *      asctoe24( string, &f )  ASCII string to single
 *      asctoe24( string, &f )  ASCII string to single
 *      asctoeg( string, e, prec, ldp ) ASCII string to specified precision
 *      asctoeg( string, e, prec, ldp ) ASCII string to specified precision
 *      e24toe( &f, e, ldp )    IEEE single precision to e type
 *      e24toe( &f, e, ldp )    IEEE single precision to e type
 *      e53toe( &d, e, ldp )    IEEE double precision to e type
 *      e53toe( &d, e, ldp )    IEEE double precision to e type
 *      e64toe( &d, e, ldp )    IEEE long double precision to e type
 *      e64toe( &d, e, ldp )    IEEE long double precision to e type
 *      e113toe( &d, e, ldp )   IEEE long double precision to e type
 *      e113toe( &d, e, ldp )   IEEE long double precision to e type
 *      eabs(e)                 absolute value
 *      eabs(e)                 absolute value
 *      eadd( a, b, c )         c = b + a
 *      eadd( a, b, c )         c = b + a
 *      eclear(e)               e = 0
 *      eclear(e)               e = 0
 *      ecmp (a, b)             Returns 1 if a > b, 0 if a == b,
 *      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.
 *                              -1 if a < b, -2 if either a or b is a NaN.
 *      ediv( a, b, c, ldp )    c = b / a
 *      ediv( a, b, c, ldp )    c = b / a
 *      efloor( a, b, ldp )     truncate to integer, toward -infinity
 *      efloor( a, b, ldp )     truncate to integer, toward -infinity
 *      efrexp( a, exp, s )     extract exponent and significand
 *      efrexp( a, exp, s )     extract exponent and significand
 *      eifrac( e, &l, frac )   e to long integer and e type fraction
 *      eifrac( e, &l, frac )   e to long integer and e type fraction
 *      euifrac( e, &l, frac )  e to unsigned long integer and e type fraction
 *      euifrac( e, &l, frac )  e to unsigned long integer and e type fraction
 *      einfin( e, ldp )        set e to infinity, leaving its sign alone
 *      einfin( e, ldp )        set e to infinity, leaving its sign alone
 *      eldexp( a, n, b )       multiply by 2**n
 *      eldexp( a, n, b )       multiply by 2**n
 *      emov( a, b )            b = a
 *      emov( a, b )            b = a
 *      emul( a, b, c, ldp )    c = b * a
 *      emul( a, b, c, ldp )    c = b * a
 *      eneg(e)                 e = -e
 *      eneg(e)                 e = -e
 *      eround( a, b )          b = nearest integer value to a
 *      eround( a, b )          b = nearest integer value to a
 *      esub( a, b, c, ldp )    c = b - a
 *      esub( a, b, c, ldp )    c = b - a
 *      e24toasc( &f, str, n )  single to ASCII string, n digits after decimal
 *      e24toasc( &f, str, n )  single to ASCII string, n digits after decimal
 *      e53toasc( &d, str, n )  double to ASCII string, n digits after decimal
 *      e53toasc( &d, str, n )  double to ASCII string, n digits after decimal
 *      e64toasc( &d, str, n )  long double to ASCII string
 *      e64toasc( &d, str, n )  long double to ASCII string
 *      etoasc(e,str,n,fmt,ldp)e to ASCII string, n digits after decimal
 *      etoasc(e,str,n,fmt,ldp)e to ASCII string, n digits after decimal
 *      etoe24( e, &f )         convert e type to IEEE single precision
 *      etoe24( e, &f )         convert e type to IEEE single precision
 *      etoe53( e, &d )         convert e type to IEEE double precision
 *      etoe53( e, &d )         convert e type to IEEE double precision
 *      etoe64( e, &d )         convert e type to IEEE long double precision
 *      etoe64( e, &d )         convert e type to IEEE long double precision
 *      ltoe( &l, e )           long (32 bit) integer to e type
 *      ltoe( &l, e )           long (32 bit) integer to e type
 *      ultoe( &l, e )          unsigned long (32 bit) integer to e type
 *      ultoe( &l, e )          unsigned long (32 bit) integer to e type
 *      eisneg( e )             1 if sign bit of e != 0, else 0
 *      eisneg( e )             1 if sign bit of e != 0, else 0
 *      eisinf( e )             1 if e has maximum exponent (non-IEEE)
 *      eisinf( e )             1 if e has maximum exponent (non-IEEE)
 *                              or is infinite (IEEE)
 *                              or is infinite (IEEE)
 *      eisnan( e )             1 if e is a NaN
 *      eisnan( e )             1 if e is a NaN
 *      esqrt( a, b )           b = square root of a
 *      esqrt( a, b )           b = square root of a
 *
 *
 *
 *
 *              Routines for internal format numbers
 *              Routines for internal format numbers
 *
 *
 *      eaddm( ai, bi )         add significands, bi = bi + ai
 *      eaddm( ai, bi )         add significands, bi = bi + ai
 *      ecleaz(ei)              ei = 0
 *      ecleaz(ei)              ei = 0
 *      ecleazs(ei)             set ei = 0 but leave its sign alone
 *      ecleazs(ei)             set ei = 0 but leave its sign alone
 *      ecmpm( ai, bi )         compare significands, return 1, 0, or -1
 *      ecmpm( ai, bi )         compare significands, return 1, 0, or -1
 *      edivm( ai, bi, ldp )    divide  significands, bi = bi / ai
 *      edivm( ai, bi, ldp )    divide  significands, bi = bi / ai
 *      emdnorm(ai,l,s,exp,ldp) normalize and round off
 *      emdnorm(ai,l,s,exp,ldp) normalize and round off
 *      emovi( a, ai )          convert external a to internal ai
 *      emovi( a, ai )          convert external a to internal ai
 *      emovo( ai, a, ldp )     convert internal ai to external a
 *      emovo( ai, a, ldp )     convert internal ai to external a
 *      emovz( ai, bi )         bi = ai, low guard word of bi = 0
 *      emovz( ai, bi )         bi = ai, low guard word of bi = 0
 *      emulm( ai, bi, ldp )    multiply significands, bi = bi * ai
 *      emulm( ai, bi, ldp )    multiply significands, bi = bi * ai
 *      enormlz(ei)             left-justify the significand
 *      enormlz(ei)             left-justify the significand
 *      eshdn1( ai )            shift significand and guards down 1 bit
 *      eshdn1( ai )            shift significand and guards down 1 bit
 *      eshdn8( ai )            shift down 8 bits
 *      eshdn8( ai )            shift down 8 bits
 *      eshdn6( ai )            shift down 16 bits
 *      eshdn6( ai )            shift down 16 bits
 *      eshift( ai, n )         shift ai n bits up (or down if n < 0)
 *      eshift( ai, n )         shift ai n bits up (or down if n < 0)
 *      eshup1( ai )            shift significand and guards up 1 bit
 *      eshup1( ai )            shift significand and guards up 1 bit
 *      eshup8( ai )            shift up 8 bits
 *      eshup8( ai )            shift up 8 bits
 *      eshup6( ai )            shift up 16 bits
 *      eshup6( ai )            shift up 16 bits
 *      esubm( ai, bi )         subtract significands, bi = bi - ai
 *      esubm( ai, bi )         subtract significands, bi = bi - ai
 *
 *
 *
 *
 * The result is always normalized and rounded to NI-4 word precision
 * The result is always normalized and rounded to NI-4 word precision
 * after each arithmetic operation.
 * after each arithmetic operation.
 *
 *
 * Exception flags are NOT fully supported.
 * Exception flags are NOT fully supported.
 *
 *
 * Define USE_INFINITY in mconf.h for support of infinity; otherwise a
 * Define USE_INFINITY in mconf.h for support of infinity; otherwise a
 * saturation arithmetic is implemented.
 * saturation arithmetic is implemented.
 *
 *
 * Define NANS for support of Not-a-Number items; otherwise the
 * Define NANS for support of Not-a-Number items; otherwise the
 * arithmetic will never produce a NaN output, and might be confused
 * arithmetic will never produce a NaN output, and might be confused
 * by a NaN input.
 * by a NaN input.
 * If NaN's are supported, the output of ecmp(a,b) is -2 if
 * 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)
 * 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
 * may not be legitimate. Use if(ecmp(a,b) == -1) for less-than
 * if in doubt.
 * if in doubt.
 * Signaling NaN's are NOT supported; they are treated the same
 * Signaling NaN's are NOT supported; they are treated the same
 * as quiet NaN's.
 * as quiet NaN's.
 *
 *
 * Denormals are always supported here where appropriate (e.g., not
 * Denormals are always supported here where appropriate (e.g., not
 * for conversion to DEC numbers).
 * for conversion to DEC numbers).
 */
 */
 
 
/*
/*
 * Revision history:
 * Revision history:
 *
 *
 *  5 Jan 84    PDP-11 assembly language version
 *  5 Jan 84    PDP-11 assembly language version
 *  6 Dec 86    C language version
 *  6 Dec 86    C language version
 * 30 Aug 88    100 digit version, improved rounding
 * 30 Aug 88    100 digit version, improved rounding
 * 15 May 92    80-bit long double support
 * 15 May 92    80-bit long double support
 * 22 Nov 00    Revised to fit into newlib by Jeff Johnston <jjohnstn@redhat.com>
 * 22 Nov 00    Revised to fit into newlib by Jeff Johnston <jjohnstn@redhat.com>
 *
 *
 * Author:  S. L. Moshier.
 * Author:  S. L. Moshier.
 *
 *
 * Copyright (c) 1984,2000 S.L. Moshier
 * Copyright (c) 1984,2000 S.L. Moshier
 *
 *
 * Permission to use, copy, modify, and distribute this software for any
 * Permission to use, copy, modify, and distribute this software for any
 * purpose without fee is hereby granted, provided that this entire notice
 * purpose without fee is hereby granted, provided that this entire notice
 * is included in all copies of any software which is or includes a copy
 * is included in all copies of any software which is or includes a copy
 * or modification of this software and in all copies of the supporting
 * or modification of this software and in all copies of the supporting
 * documentation for such software.
 * documentation for such software.
 *
 *
 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTY.  IN PARTICULAR,  THE AUTHOR MAKES NO REPRESENTATION
 * WARRANTY.  IN PARTICULAR,  THE AUTHOR MAKES NO REPRESENTATION
 * OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
 * OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS
 * SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
 * SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
 *
 *
 */
 */
 
 
#include <stdio.h>
#include <stdio.h>
/* #include "\usr\include\stdio.h" */
/* #include "\usr\include\stdio.h" */
/*#include "ehead.h"*/
/*#include "ehead.h"*/
/*#include "mconf.h"*/
/*#include "mconf.h"*/
/*                                                      mconf.h
/*                                                      mconf.h
 *
 *
 *      Common include file for math routines
 *      Common include file for math routines
 *
 *
 *
 *
 *
 *
 * SYNOPSIS:
 * SYNOPSIS:
 *
 *
 * #include "mconf.h"
 * #include "mconf.h"
 *
 *
 *
 *
 *
 *
 * DESCRIPTION:
 * DESCRIPTION:
 *
 *
 * This file contains definitions for error codes that are
 * This file contains definitions for error codes that are
 * passed to the common error handling routine mtherr()
 * passed to the common error handling routine mtherr()
 * (which see).
 * (which see).
 *
 *
 * The file also includes a conditional assembly definition
 * The file also includes a conditional assembly definition
 * for the type of computer arithmetic (IEEE, DEC, Motorola
 * for the type of computer arithmetic (IEEE, DEC, Motorola
 * IEEE, or UNKnown).
 * IEEE, or UNKnown).
 *
 *
 * For Digital Equipment PDP-11 and VAX computers, certain
 * For Digital Equipment PDP-11 and VAX computers, certain
 * IBM systems, and others that use numbers with a 56-bit
 * IBM systems, and others that use numbers with a 56-bit
 * significand, the symbol DEC should be defined.  In this
 * significand, the symbol DEC should be defined.  In this
 * mode, most floating point constants are given as arrays
 * mode, most floating point constants are given as arrays
 * of octal integers to eliminate decimal to binary conversion
 * of octal integers to eliminate decimal to binary conversion
 * errors that might be introduced by the compiler.
 * errors that might be introduced by the compiler.
 *
 *
 * For computers, such as IBM PC, that follow the IEEE
 * For computers, such as IBM PC, that follow the IEEE
 * Standard for Binary Floating Point Arithmetic (ANSI/IEEE
 * Standard for Binary Floating Point Arithmetic (ANSI/IEEE
 * Std 754-1985), the symbol IBMPC should be defined.  These
 * Std 754-1985), the symbol IBMPC should be defined.  These
 * numbers have 53-bit significands.  In this mode, constants
 * numbers have 53-bit significands.  In this mode, constants
 * are provided as arrays of hexadecimal 16 bit integers.
 * are provided as arrays of hexadecimal 16 bit integers.
 *
 *
 * To accommodate other types of computer arithmetic, all
 * To accommodate other types of computer arithmetic, all
 * constants are also provided in a normal decimal radix
 * constants are also provided in a normal decimal radix
 * which one can hope are correctly converted to a suitable
 * which one can hope are correctly converted to a suitable
 * format by the available C language compiler.  To invoke
 * format by the available C language compiler.  To invoke
 * this mode, the symbol UNK is defined.
 * this mode, the symbol UNK is defined.
 *
 *
 * An important difference among these modes is a predefined
 * An important difference among these modes is a predefined
 * set of machine arithmetic constants for each.  The numbers
 * set of machine arithmetic constants for each.  The numbers
 * MACHEP (the machine roundoff error), MAXNUM (largest number
 * MACHEP (the machine roundoff error), MAXNUM (largest number
 * represented), and several other parameters are preset by
 * represented), and several other parameters are preset by
 * the configuration symbol.  Check the file const.c to
 * the configuration symbol.  Check the file const.c to
 * ensure that these values are correct for your computer.
 * ensure that these values are correct for your computer.
 *
 *
 * For ANSI C compatibility, define ANSIC equal to 1.  Currently
 * For ANSI C compatibility, define ANSIC equal to 1.  Currently
 * this affects only the atan2() function and others that use it.
 * this affects only the atan2() function and others that use it.
 */
 */
 
 
/* Constant definitions for math error conditions
/* Constant definitions for math error conditions
 */
 */
 
 
#define DOMAIN          1       /* argument domain error */
#define DOMAIN          1       /* argument domain error */
#define SING            2       /* argument singularity */
#define SING            2       /* argument singularity */
#define OVERFLOW        3       /* overflow range error */
#define OVERFLOW        3       /* overflow range error */
#define UNDERFLOW       4       /* underflow range error */
#define UNDERFLOW       4       /* underflow range error */
#define TLOSS           5       /* total loss of precision */
#define TLOSS           5       /* total loss of precision */
#define PLOSS           6       /* partial loss of precision */
#define PLOSS           6       /* partial loss of precision */
 
 
#define EDOM            33
#define EDOM            33
#define ERANGE          34
#define ERANGE          34
 
 
typedef struct
typedef struct
        {
        {
        double r;
        double r;
        double i;
        double i;
        }cmplx;
        }cmplx;
 
 
/* Type of computer arithmetic */
/* Type of computer arithmetic */
 
 
#ifndef DEC
#ifndef DEC
#ifdef __IEEE_LITTLE_ENDIAN
#ifdef __IEEE_LITTLE_ENDIAN
#define IBMPC 1
#define IBMPC 1
#else  /* !__IEEE_LITTLE_ENDIAN */
#else  /* !__IEEE_LITTLE_ENDIAN */
#define MIEEE 1
#define MIEEE 1
#endif /* !__IEEE_LITTLE_ENDIAN */
#endif /* !__IEEE_LITTLE_ENDIAN */
#endif /* !DEC */
#endif /* !DEC */
 
 
/* Define 1 for ANSI C atan2() function
/* Define 1 for ANSI C atan2() function
 * See atan.c and clog.c.
 * See atan.c and clog.c.
 */
 */
#define ANSIC 1
#define ANSIC 1
 
 
/*define VOLATILE volatile*/
/*define VOLATILE volatile*/
#define VOLATILE 
#define VOLATILE 
 
 
#define NANS
#define NANS
#define USE_INFINITY
#define USE_INFINITY
 
 
/* NaN's require infinity support. */
/* NaN's require infinity support. */
#ifdef NANS
#ifdef NANS
#ifndef INFINITY
#ifndef INFINITY
#define USE_INFINITY
#define USE_INFINITY
#endif
#endif
#endif
#endif
 
 
/* This handles 64-bit long ints. */
/* This handles 64-bit long ints. */
#define LONGBITS (8 * sizeof(long))
#define LONGBITS (8 * sizeof(long))
 
 
 
 
static void eaddm(short unsigned int *x, short unsigned int *y);
static void eaddm(short unsigned int *x, short unsigned int *y);
static void esubm(short unsigned int *x, short unsigned int *y);
static void esubm(short unsigned int *x, short unsigned int *y);
static void emdnorm(short unsigned int *s, int lost, int subflg, long int exp, int rcntrl, LDPARMS *ldp);
static void emdnorm(short unsigned int *s, int lost, int subflg, long int exp, int rcntrl, LDPARMS *ldp);
static int  asctoeg(char *ss, short unsigned int *y, int oprec, LDPARMS *ldp);
static int  asctoeg(char *ss, short unsigned int *y, int oprec, LDPARMS *ldp);
static void enan(short unsigned int *nan, int size);
static void enan(short unsigned int *nan, int size);
#if LDBL_MANT_DIG == 24
#if LDBL_MANT_DIG == 24
static void toe24(short unsigned int *x, short unsigned int *y);
static void toe24(short unsigned int *x, short unsigned int *y);
#elif LDBL_MANT_DIG == 53
#elif LDBL_MANT_DIG == 53
static void toe53(short unsigned int *x, short unsigned int *y);
static void toe53(short unsigned int *x, short unsigned int *y);
#elif LDBL_MANT_DIG == 64
#elif LDBL_MANT_DIG == 64
static void toe64(short unsigned int *a, short unsigned int *b);
static void toe64(short unsigned int *a, short unsigned int *b);
#else
#else
static void toe113(short unsigned int *a, short unsigned int *b);
static void toe113(short unsigned int *a, short unsigned int *b);
#endif
#endif
static void eiremain(short unsigned int *den, short unsigned int *num, LDPARMS *ldp);
static void eiremain(short unsigned int *den, short unsigned int *num, LDPARMS *ldp);
static int ecmpm(register short unsigned int *a, register short unsigned int *b);
static int ecmpm(register short unsigned int *a, register short unsigned int *b);
static int edivm(short unsigned int *den, short unsigned int *num, LDPARMS *ldp);
static int edivm(short unsigned int *den, short unsigned int *num, LDPARMS *ldp);
static int emulm(short unsigned int *a, short unsigned int *b, LDPARMS *ldp);
static int emulm(short unsigned int *a, short unsigned int *b, LDPARMS *ldp);
static int eisneg(short unsigned int *x);
static int eisneg(short unsigned int *x);
static int eisinf(short unsigned int *x);
static int eisinf(short unsigned int *x);
static void emovi(short unsigned int *a, short unsigned int *b);
static void emovi(short unsigned int *a, short unsigned int *b);
static void emovo(short unsigned int *a, short unsigned int *b, LDPARMS *ldp);
static void emovo(short unsigned int *a, short unsigned int *b, LDPARMS *ldp);
static void emovz(register short unsigned int *a, register short unsigned int *b);
static void emovz(register short unsigned int *a, register short unsigned int *b);
static void ecleaz(register short unsigned int *xi);
static void ecleaz(register short unsigned int *xi);
static void eadd1(short unsigned int *a, short unsigned int *b, short unsigned int *c, int subflg, LDPARMS *ldp);
static void eadd1(short unsigned int *a, short unsigned int *b, short unsigned int *c, int subflg, LDPARMS *ldp);
static int eisnan(short unsigned int *x);
static int eisnan(short unsigned int *x);
static int eiisnan(short unsigned int *x);
static int eiisnan(short unsigned int *x);
 
 
#ifdef DEC
#ifdef DEC
static void etodec(), todec(), dectoe();
static void etodec(), todec(), dectoe();
#endif
#endif
 
 
/*
/*
; Clear out entire external format number.
; Clear out entire external format number.
;
;
; unsigned short x[];
; unsigned short x[];
; eclear( x );
; eclear( x );
*/
*/
 
 
static void eclear(register short unsigned int *x)
static void eclear(register short unsigned int *x)
{
{
register int i;
register int i;
 
 
for( i=0; i<NE; i++ )
for( i=0; i<NE; i++ )
        *x++ = 0;
        *x++ = 0;
}
}
 
 
 
 
 
 
/* Move external format number from a to b.
/* Move external format number from a to b.
 *
 *
 * emov( a, b );
 * emov( a, b );
 */
 */
 
 
static void emov(register short unsigned int *a, register short unsigned int *b)
static void emov(register short unsigned int *a, register short unsigned int *b)
{
{
register int i;
register int i;
 
 
for( i=0; i<NE; i++ )
for( i=0; i<NE; i++ )
        *b++ = *a++;
        *b++ = *a++;
}
}
 
 
 
 
/*
/*
;       Negate external format number
;       Negate external format number
;
;
;       unsigned short x[NE];
;       unsigned short x[NE];
;       eneg( x );
;       eneg( x );
*/
*/
 
 
static void eneg(short unsigned int *x)
static void eneg(short unsigned int *x)
{
{
 
 
#ifdef NANS
#ifdef NANS
if( eisnan(x) )
if( eisnan(x) )
        return;
        return;
#endif
#endif
x[NE-1] ^= 0x8000; /* Toggle the sign bit */
x[NE-1] ^= 0x8000; /* Toggle the sign bit */
}
}
 
 
 
 
 
 
/* Return 1 if external format number is negative,
/* Return 1 if external format number is negative,
 * else return zero.
 * else return zero.
 */
 */
static int eisneg(short unsigned int *x)
static int eisneg(short unsigned int *x)
{
{
 
 
#ifdef NANS
#ifdef NANS
if( eisnan(x) )
if( eisnan(x) )
        return( 0 );
        return( 0 );
#endif
#endif
if( x[NE-1] & 0x8000 )
if( x[NE-1] & 0x8000 )
        return( 1 );
        return( 1 );
else
else
        return( 0 );
        return( 0 );
}
}
 
 
 
 
/* Return 1 if external format number has maximum possible exponent,
/* Return 1 if external format number has maximum possible exponent,
 * else return zero.
 * else return zero.
 */
 */
static int eisinf(short unsigned int *x)
static int eisinf(short unsigned int *x)
{
{
 
 
if( (x[NE-1] & 0x7fff) == 0x7fff )
if( (x[NE-1] & 0x7fff) == 0x7fff )
        {
        {
#ifdef NANS
#ifdef NANS
        if( eisnan(x) )
        if( eisnan(x) )
                return( 0 );
                return( 0 );
#endif
#endif
        return( 1 );
        return( 1 );
        }
        }
else
else
        return( 0 );
        return( 0 );
}
}
 
 
/* Check if e-type number is not a number.
/* Check if e-type number is not a number.
 */
 */
static int eisnan(short unsigned int *x)
static int eisnan(short unsigned int *x)
{
{
 
 
#ifdef NANS
#ifdef NANS
int i;
int i;
/* NaN has maximum exponent */
/* NaN has maximum exponent */
if( (x[NE-1] & 0x7fff) != 0x7fff )
if( (x[NE-1] & 0x7fff) != 0x7fff )
        return (0);
        return (0);
/* ... and non-zero significand field. */
/* ... and non-zero significand field. */
for( i=0; i<NE-1; i++ )
for( i=0; i<NE-1; i++ )
        {
        {
        if( *x++ != 0 )
        if( *x++ != 0 )
                return (1);
                return (1);
        }
        }
#endif
#endif
return (0);
return (0);
}
}
 
 
/*
/*
; Fill entire number, including exponent and significand, with
; Fill entire number, including exponent and significand, with
; largest possible number.  These programs implement a saturation
; largest possible number.  These programs implement a saturation
; value that is an ordinary, legal number.  A special value
; value that is an ordinary, legal number.  A special value
; "infinity" may also be implemented; this would require tests
; "infinity" may also be implemented; this would require tests
; for that value and implementation of special rules for arithmetic
; for that value and implementation of special rules for arithmetic
; operations involving inifinity.
; operations involving inifinity.
*/
*/
 
 
static void einfin(register short unsigned int *x, register LDPARMS *ldp)
static void einfin(register short unsigned int *x, register LDPARMS *ldp)
{
{
register int i;
register int i;
 
 
#ifdef USE_INFINITY
#ifdef USE_INFINITY
for( i=0; i<NE-1; i++ )
for( i=0; i<NE-1; i++ )
        *x++ = 0;
        *x++ = 0;
*x |= 32767;
*x |= 32767;
ldp = ldp;
ldp = ldp;
#else
#else
for( i=0; i<NE-1; i++ )
for( i=0; i<NE-1; i++ )
        *x++ = 0xffff;
        *x++ = 0xffff;
*x |= 32766;
*x |= 32766;
if( ldp->rndprc < NBITS )
if( ldp->rndprc < NBITS )
        {
        {
        if (ldp->rndprc == 113)
        if (ldp->rndprc == 113)
                {
                {
                *(x - 9) = 0;
                *(x - 9) = 0;
                *(x - 8) = 0;
                *(x - 8) = 0;
                }
                }
        if( ldp->rndprc == 64 )
        if( ldp->rndprc == 64 )
                {
                {
                *(x-5) = 0;
                *(x-5) = 0;
                }
                }
        if( ldp->rndprc == 53 )
        if( ldp->rndprc == 53 )
                {
                {
                *(x-4) = 0xf800;
                *(x-4) = 0xf800;
                }
                }
        else
        else
                {
                {
                *(x-4) = 0;
                *(x-4) = 0;
                *(x-3) = 0;
                *(x-3) = 0;
                *(x-2) = 0xff00;
                *(x-2) = 0xff00;
                }
                }
        }
        }
#endif
#endif
}
}
 
 
/* Move in external format number,
/* Move in external format number,
 * converting it to internal format.
 * converting it to internal format.
 */
 */
static void emovi(short unsigned int *a, short unsigned int *b)
static void emovi(short unsigned int *a, short unsigned int *b)
{
{
register unsigned short *p, *q;
register unsigned short *p, *q;
int i;
int i;
 
 
q = b;
q = b;
p = a + (NE-1); /* point to last word of external number */
p = a + (NE-1); /* point to last word of external number */
/* get the sign bit */
/* get the sign bit */
if( *p & 0x8000 )
if( *p & 0x8000 )
        *q++ = 0xffff;
        *q++ = 0xffff;
else
else
        *q++ = 0;
        *q++ = 0;
/* get the exponent */
/* get the exponent */
*q = *p--;
*q = *p--;
*q++ &= 0x7fff; /* delete the sign bit */
*q++ &= 0x7fff; /* delete the sign bit */
#ifdef USE_INFINITY
#ifdef USE_INFINITY
if( (*(q-1) & 0x7fff) == 0x7fff )
if( (*(q-1) & 0x7fff) == 0x7fff )
        {
        {
#ifdef NANS
#ifdef NANS
        if( eisnan(a) )
        if( eisnan(a) )
                {
                {
                *q++ = 0;
                *q++ = 0;
                for( i=3; i<NI; i++ )
                for( i=3; i<NI; i++ )
                        *q++ = *p--;
                        *q++ = *p--;
                return;
                return;
                }
                }
#endif
#endif
        for( i=2; i<NI; i++ )
        for( i=2; i<NI; i++ )
                *q++ = 0;
                *q++ = 0;
        return;
        return;
        }
        }
#endif
#endif
/* clear high guard word */
/* clear high guard word */
*q++ = 0;
*q++ = 0;
/* move in the significand */
/* move in the significand */
for( i=0; i<NE-1; i++ )
for( i=0; i<NE-1; i++ )
        *q++ = *p--;
        *q++ = *p--;
/* clear low guard word */
/* clear low guard word */
*q = 0;
*q = 0;
}
}
 
 
 
 
/* Move internal format number out,
/* Move internal format number out,
 * converting it to external format.
 * converting it to external format.
 */
 */
static void emovo(short unsigned int *a, short unsigned int *b, LDPARMS *ldp)
static void emovo(short unsigned int *a, short unsigned int *b, LDPARMS *ldp)
{
{
register unsigned short *p, *q;
register unsigned short *p, *q;
unsigned short i;
unsigned short i;
 
 
p = a;
p = a;
q = b + (NE-1); /* point to output exponent */
q = b + (NE-1); /* point to output exponent */
/* combine sign and exponent */
/* combine sign and exponent */
i = *p++;
i = *p++;
if( i )
if( i )
        *q-- = *p++ | 0x8000;
        *q-- = *p++ | 0x8000;
else
else
        *q-- = *p++;
        *q-- = *p++;
#ifdef USE_INFINITY
#ifdef USE_INFINITY
if( *(p-1) == 0x7fff )
if( *(p-1) == 0x7fff )
        {
        {
#ifdef NANS
#ifdef NANS
        if( eiisnan(a) )
        if( eiisnan(a) )
                {
                {
                enan( b, NBITS );
                enan( b, NBITS );
                return;
                return;
                }
                }
#endif
#endif
        einfin(b, ldp);
        einfin(b, ldp);
        return;
        return;
        }
        }
#endif
#endif
/* skip over guard word */
/* skip over guard word */
++p;
++p;
/* move the significand */
/* move the significand */
for( i=0; i<NE-1; i++ )
for( i=0; i<NE-1; i++ )
        *q-- = *p++;
        *q-- = *p++;
}
}
 
 
 
 
/* Clear out internal format number.
/* Clear out internal format number.
 */
 */
 
 
static void ecleaz(register short unsigned int *xi)
static void ecleaz(register short unsigned int *xi)
{
{
register int i;
register int i;
 
 
for( i=0; i<NI; i++ )
for( i=0; i<NI; i++ )
        *xi++ = 0;
        *xi++ = 0;
}
}
 
 
/* same, but don't touch the sign. */
/* same, but don't touch the sign. */
 
 
static void ecleazs(register short unsigned int *xi)
static void ecleazs(register short unsigned int *xi)
{
{
register int i;
register int i;
 
 
++xi;
++xi;
for(i=0; i<NI-1; i++)
for(i=0; i<NI-1; i++)
        *xi++ = 0;
        *xi++ = 0;
}
}
 
 
 
 
 
 
 
 
/* Move internal format number from a to b.
/* Move internal format number from a to b.
 */
 */
static void emovz(register short unsigned int *a, register short unsigned int *b)
static void emovz(register short unsigned int *a, register short unsigned int *b)
{
{
register int i;
register int i;
 
 
for( i=0; i<NI-1; i++ )
for( i=0; i<NI-1; i++ )
        *b++ = *a++;
        *b++ = *a++;
/* clear low guard word */
/* clear low guard word */
*b = 0;
*b = 0;
}
}
 
 
/* Return nonzero if internal format number is a NaN.
/* Return nonzero if internal format number is a NaN.
 */
 */
 
 
static int eiisnan (short unsigned int *x)
static int eiisnan (short unsigned int *x)
{
{
int i;
int i;
 
 
if( (x[E] & 0x7fff) == 0x7fff )
if( (x[E] & 0x7fff) == 0x7fff )
        {
        {
        for( i=M+1; i<NI; i++ )
        for( i=M+1; i<NI; i++ )
                {
                {
                if( x[i] != 0 )
                if( x[i] != 0 )
                        return(1);
                        return(1);
                }
                }
        }
        }
return(0);
return(0);
}
}
 
 
#if LDBL_MANT_DIG == 64
#if LDBL_MANT_DIG == 64
 
 
/* Return nonzero if internal format number is infinite. */
/* Return nonzero if internal format number is infinite. */
static int
static int
eiisinf (unsigned short x[])
eiisinf (unsigned short x[])
{
{
 
 
#ifdef NANS
#ifdef NANS
  if (eiisnan (x))
  if (eiisnan (x))
    return (0);
    return (0);
#endif
#endif
  if ((x[E] & 0x7fff) == 0x7fff)
  if ((x[E] & 0x7fff) == 0x7fff)
    return (1);
    return (1);
  return (0);
  return (0);
}
}
#endif /* LDBL_MANT_DIG == 64 */
#endif /* LDBL_MANT_DIG == 64 */
 
 
/*
/*
;       Compare significands of numbers in internal format.
;       Compare significands of numbers in internal format.
;       Guard words are included in the comparison.
;       Guard words are included in the comparison.
;
;
;       unsigned short a[NI], b[NI];
;       unsigned short a[NI], b[NI];
;       cmpm( a, b );
;       cmpm( a, b );
;
;
;       for the significands:
;       for the significands:
;       returns +1 if a > b
;       returns +1 if a > b
;                0 if a == b
;                0 if a == b
;               -1 if a < b
;               -1 if a < b
*/
*/
static int ecmpm(register short unsigned int *a, register short unsigned int *b)
static int ecmpm(register short unsigned int *a, register short unsigned int *b)
{
{
int i;
int i;
 
 
a += M; /* skip up to significand area */
a += M; /* skip up to significand area */
b += M;
b += M;
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        if( *a++ != *b++ )
        if( *a++ != *b++ )
                goto difrnt;
                goto difrnt;
        }
        }
return(0);
return(0);
 
 
difrnt:
difrnt:
if( *(--a) > *(--b) )
if( *(--a) > *(--b) )
        return(1);
        return(1);
else
else
        return(-1);
        return(-1);
}
}
 
 
 
 
/*
/*
;       Shift significand down by 1 bit
;       Shift significand down by 1 bit
*/
*/
 
 
static void eshdn1(register short unsigned int *x)
static void eshdn1(register short unsigned int *x)
{
{
register unsigned short bits;
register unsigned short bits;
int i;
int i;
 
 
x += M; /* point to significand area */
x += M; /* point to significand area */
 
 
bits = 0;
bits = 0;
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        if( *x & 1 )
        if( *x & 1 )
                bits |= 1;
                bits |= 1;
        *x >>= 1;
        *x >>= 1;
        if( bits & 2 )
        if( bits & 2 )
                *x |= 0x8000;
                *x |= 0x8000;
        bits <<= 1;
        bits <<= 1;
        ++x;
        ++x;
        }
        }
}
}
 
 
 
 
 
 
/*
/*
;       Shift significand up by 1 bit
;       Shift significand up by 1 bit
*/
*/
 
 
static void eshup1(register short unsigned int *x)
static void eshup1(register short unsigned int *x)
{
{
register unsigned short bits;
register unsigned short bits;
int i;
int i;
 
 
x += NI-1;
x += NI-1;
bits = 0;
bits = 0;
 
 
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        if( *x & 0x8000 )
        if( *x & 0x8000 )
                bits |= 1;
                bits |= 1;
        *x <<= 1;
        *x <<= 1;
        if( bits & 2 )
        if( bits & 2 )
                *x |= 1;
                *x |= 1;
        bits <<= 1;
        bits <<= 1;
        --x;
        --x;
        }
        }
}
}
 
 
 
 
 
 
/*
/*
;       Shift significand down by 8 bits
;       Shift significand down by 8 bits
*/
*/
 
 
static void eshdn8(register short unsigned int *x)
static void eshdn8(register short unsigned int *x)
{
{
register unsigned short newbyt, oldbyt;
register unsigned short newbyt, oldbyt;
int i;
int i;
 
 
x += M;
x += M;
oldbyt = 0;
oldbyt = 0;
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        newbyt = *x << 8;
        newbyt = *x << 8;
        *x >>= 8;
        *x >>= 8;
        *x |= oldbyt;
        *x |= oldbyt;
        oldbyt = newbyt;
        oldbyt = newbyt;
        ++x;
        ++x;
        }
        }
}
}
 
 
/*
/*
;       Shift significand up by 8 bits
;       Shift significand up by 8 bits
*/
*/
 
 
static void eshup8(register short unsigned int *x)
static void eshup8(register short unsigned int *x)
{
{
int i;
int i;
register unsigned short newbyt, oldbyt;
register unsigned short newbyt, oldbyt;
 
 
x += NI-1;
x += NI-1;
oldbyt = 0;
oldbyt = 0;
 
 
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        newbyt = *x >> 8;
        newbyt = *x >> 8;
        *x <<= 8;
        *x <<= 8;
        *x |= oldbyt;
        *x |= oldbyt;
        oldbyt = newbyt;
        oldbyt = newbyt;
        --x;
        --x;
        }
        }
}
}
 
 
/*
/*
;       Shift significand up by 16 bits
;       Shift significand up by 16 bits
*/
*/
 
 
static void eshup6(register short unsigned int *x)
static void eshup6(register short unsigned int *x)
{
{
int i;
int i;
register unsigned short *p;
register unsigned short *p;
 
 
p = x + M;
p = x + M;
x += M + 1;
x += M + 1;
 
 
for( i=M; i<NI-1; i++ )
for( i=M; i<NI-1; i++ )
        *p++ = *x++;
        *p++ = *x++;
 
 
*p = 0;
*p = 0;
}
}
 
 
/*
/*
;       Shift significand down by 16 bits
;       Shift significand down by 16 bits
*/
*/
 
 
static void eshdn6(register short unsigned int *x)
static void eshdn6(register short unsigned int *x)
{
{
int i;
int i;
register unsigned short *p;
register unsigned short *p;
 
 
x += NI-1;
x += NI-1;
p = x + 1;
p = x + 1;
 
 
for( i=M; i<NI-1; i++ )
for( i=M; i<NI-1; i++ )
        *(--p) = *(--x);
        *(--p) = *(--x);
 
 
*(--p) = 0;
*(--p) = 0;
}
}


/*
/*
;       Add significands
;       Add significands
;       x + y replaces y
;       x + y replaces y
*/
*/
 
 
static void eaddm(short unsigned int *x, short unsigned int *y)
static void eaddm(short unsigned int *x, short unsigned int *y)
{
{
register unsigned long a;
register unsigned long a;
int i;
int i;
unsigned int carry;
unsigned int carry;
 
 
x += NI-1;
x += NI-1;
y += NI-1;
y += NI-1;
carry = 0;
carry = 0;
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        a = (unsigned long )(*x) + (unsigned long )(*y) + carry;
        a = (unsigned long )(*x) + (unsigned long )(*y) + carry;
        if( a & 0x10000 )
        if( a & 0x10000 )
                carry = 1;
                carry = 1;
        else
        else
                carry = 0;
                carry = 0;
        *y = (unsigned short )a;
        *y = (unsigned short )a;
        --x;
        --x;
        --y;
        --y;
        }
        }
}
}
 
 
/*
/*
;       Subtract significands
;       Subtract significands
;       y - x replaces y
;       y - x replaces y
*/
*/
 
 
static void esubm(short unsigned int *x, short unsigned int *y)
static void esubm(short unsigned int *x, short unsigned int *y)
{
{
unsigned long a;
unsigned long a;
int i;
int i;
unsigned int carry;
unsigned int carry;
 
 
x += NI-1;
x += NI-1;
y += NI-1;
y += NI-1;
carry = 0;
carry = 0;
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        a = (unsigned long )(*y) - (unsigned long )(*x) - carry;
        a = (unsigned long )(*y) - (unsigned long )(*x) - carry;
        if( a & 0x10000 )
        if( a & 0x10000 )
                carry = 1;
                carry = 1;
        else
        else
                carry = 0;
                carry = 0;
        *y = (unsigned short )a;
        *y = (unsigned short )a;
        --x;
        --x;
        --y;
        --y;
        }
        }
}
}
 
 
 
 
/* Divide significands */
/* Divide significands */
 
 
 
 
/* Multiply significand of e-type number b
/* Multiply significand of e-type number b
by 16-bit quantity a, e-type result to c. */
by 16-bit quantity a, e-type result to c. */
 
 
static void m16m(short unsigned int a, short unsigned int *b, short unsigned int *c)
static void m16m(short unsigned int a, short unsigned int *b, short unsigned int *c)
{
{
register unsigned short *pp;
register unsigned short *pp;
register unsigned long carry;
register unsigned long carry;
unsigned short *ps;
unsigned short *ps;
unsigned short p[NI];
unsigned short p[NI];
unsigned long aa, m;
unsigned long aa, m;
int i;
int i;
 
 
aa = a;
aa = a;
pp = &p[NI-2];
pp = &p[NI-2];
*pp++ = 0;
*pp++ = 0;
*pp = 0;
*pp = 0;
ps = &b[NI-1];
ps = &b[NI-1];
 
 
for( i=M+1; i<NI; i++ )
for( i=M+1; i<NI; i++ )
        {
        {
        if( *ps == 0 )
        if( *ps == 0 )
                {
                {
                --ps;
                --ps;
                --pp;
                --pp;
                *(pp-1) = 0;
                *(pp-1) = 0;
                }
                }
        else
        else
                {
                {
                m = (unsigned long) aa * *ps--;
                m = (unsigned long) aa * *ps--;
                carry = (m & 0xffff) + *pp;
                carry = (m & 0xffff) + *pp;
                *pp-- = (unsigned short )carry;
                *pp-- = (unsigned short )carry;
                carry = (carry >> 16) + (m >> 16) + *pp;
                carry = (carry >> 16) + (m >> 16) + *pp;
                *pp = (unsigned short )carry;
                *pp = (unsigned short )carry;
                *(pp-1) = carry >> 16;
                *(pp-1) = carry >> 16;
                }
                }
        }
        }
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        c[i] = p[i];
        c[i] = p[i];
}
}
 
 
 
 
/* Divide significands. Neither the numerator nor the denominator
/* Divide significands. Neither the numerator nor the denominator
is permitted to have its high guard word nonzero.  */
is permitted to have its high guard word nonzero.  */
 
 
 
 
static int edivm(short unsigned int *den, short unsigned int *num, LDPARMS *ldp)
static int edivm(short unsigned int *den, short unsigned int *num, LDPARMS *ldp)
{
{
int i;
int i;
register unsigned short *p;
register unsigned short *p;
unsigned long tnum;
unsigned long tnum;
unsigned short j, tdenm, tquot;
unsigned short j, tdenm, tquot;
unsigned short tprod[NI+1];
unsigned short tprod[NI+1];
unsigned short *equot = ldp->equot;
unsigned short *equot = ldp->equot;
 
 
p = &equot[0];
p = &equot[0];
*p++ = num[0];
*p++ = num[0];
*p++ = num[1];
*p++ = num[1];
 
 
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        *p++ = 0;
        *p++ = 0;
        }
        }
eshdn1( num );
eshdn1( num );
tdenm = den[M+1];
tdenm = den[M+1];
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        /* Find trial quotient digit (the radix is 65536). */
        /* Find trial quotient digit (the radix is 65536). */
        tnum = (((unsigned long) num[M]) << 16) + num[M+1];
        tnum = (((unsigned long) num[M]) << 16) + num[M+1];
 
 
        /* Do not execute the divide instruction if it will overflow. */
        /* Do not execute the divide instruction if it will overflow. */
        if( (tdenm * 0xffffUL) < tnum )
        if( (tdenm * 0xffffUL) < tnum )
                tquot = 0xffff;
                tquot = 0xffff;
        else
        else
                tquot = tnum / tdenm;
                tquot = tnum / tdenm;
 
 
                /* Prove that the divide worked. */
                /* Prove that the divide worked. */
/*
/*
        tcheck = (unsigned long )tquot * tdenm;
        tcheck = (unsigned long )tquot * tdenm;
        if( tnum - tcheck > tdenm )
        if( tnum - tcheck > tdenm )
                tquot = 0xffff;
                tquot = 0xffff;
*/
*/
        /* Multiply denominator by trial quotient digit. */
        /* Multiply denominator by trial quotient digit. */
        m16m( tquot, den, tprod );
        m16m( tquot, den, tprod );
        /* The quotient digit may have been overestimated. */
        /* The quotient digit may have been overestimated. */
        if( ecmpm( tprod, num ) > 0 )
        if( ecmpm( tprod, num ) > 0 )
                {
                {
                tquot -= 1;
                tquot -= 1;
                esubm( den, tprod );
                esubm( den, tprod );
                if( ecmpm( tprod, num ) > 0 )
                if( ecmpm( tprod, num ) > 0 )
                        {
                        {
                        tquot -= 1;
                        tquot -= 1;
                        esubm( den, tprod );
                        esubm( den, tprod );
                        }
                        }
                }
                }
/*
/*
        if( ecmpm( tprod, num ) > 0 )
        if( ecmpm( tprod, num ) > 0 )
                {
                {
                eshow( "tprod", tprod );
                eshow( "tprod", tprod );
                eshow( "num  ", num );
                eshow( "num  ", num );
                printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
                printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
                         tnum, den[M+1], tquot );
                         tnum, den[M+1], tquot );
                }
                }
*/
*/
        esubm( tprod, num );
        esubm( tprod, num );
/*
/*
        if( ecmpm( num, den ) >= 0 )
        if( ecmpm( num, den ) >= 0 )
                {
                {
                eshow( "num  ", num );
                eshow( "num  ", num );
                eshow( "den  ", den );
                eshow( "den  ", den );
                printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
                printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
                         tnum, den[M+1], tquot );
                         tnum, den[M+1], tquot );
                }
                }
*/
*/
        equot[i] = tquot;
        equot[i] = tquot;
        eshup6(num);
        eshup6(num);
        }
        }
/* test for nonzero remainder after roundoff bit */
/* test for nonzero remainder after roundoff bit */
p = &num[M];
p = &num[M];
j = 0;
j = 0;
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        {
        {
        j |= *p++;
        j |= *p++;
        }
        }
if( j )
if( j )
        j = 1;
        j = 1;
 
 
for( i=0; i<NI; i++ )
for( i=0; i<NI; i++ )
        num[i] = equot[i];
        num[i] = equot[i];
 
 
return( (int )j );
return( (int )j );
}
}
 
 
 
 
 
 
/* Multiply significands */
/* Multiply significands */
static int emulm(short unsigned int *a, short unsigned int *b, LDPARMS *ldp)
static int emulm(short unsigned int *a, short unsigned int *b, LDPARMS *ldp)
{
{
unsigned short *p, *q;
unsigned short *p, *q;
unsigned short pprod[NI];
unsigned short pprod[NI];
unsigned short j;
unsigned short j;
int i;
int i;
unsigned short *equot = ldp->equot;
unsigned short *equot = ldp->equot;
 
 
equot[0] = b[0];
equot[0] = b[0];
equot[1] = b[1];
equot[1] = b[1];
for( i=M; i<NI; i++ )
for( i=M; i<NI; i++ )
        equot[i] = 0;
        equot[i] = 0;
 
 
j = 0;
j = 0;
p = &a[NI-1];
p = &a[NI-1];
q = &equot[NI-1];
q = &equot[NI-1];
for( i=M+1; i<NI; i++ )
for( i=M+1; i<NI; i++ )
        {
        {
        if( *p == 0 )
        if( *p == 0 )
                {
                {
                --p;
                --p;
                }
                }
        else
        else
                {
                {
                m16m( *p--, b, pprod );
                m16m( *p--, b, pprod );
                eaddm(pprod, equot);
                eaddm(pprod, equot);
                }
                }
        j |= *q;
        j |= *q;
        eshdn6(equot);
        eshdn6(equot);
        }
        }
 
 
for( i=0; i<NI; i++ )
for( i=0; i<NI; i++ )
        b[i] = equot[i];
        b[i] = equot[i];
 
 
/* return flag for lost nonzero bits */
/* return flag for lost nonzero bits */
return( (int)j );
return( (int)j );
}
}
 
 
 
 
/*
/*
static void eshow(str, x)
static void eshow(str, x)
char *str;
char *str;
unsigned short *x;
unsigned short *x;
{
{
int i;
int i;
 
 
printf( "%s ", str );
printf( "%s ", str );
for( i=0; i<NI; i++ )
for( i=0; i<NI; i++ )
        printf( "%04x ", *x++ );
        printf( "%04x ", *x++ );
printf( "\n" );
printf( "\n" );
}
}
*/
*/
 
 
 
 
/*
/*
 * Normalize and round off.
 * Normalize and round off.
 *
 *
 * The internal format number to be rounded is "s".
 * The internal format number to be rounded is "s".
 * Input "lost" indicates whether the number is exact.
 * Input "lost" indicates whether the number is exact.
 * This is the so-called sticky bit.
 * This is the so-called sticky bit.
 *
 *
 * Input "subflg" indicates whether the number was obtained
 * Input "subflg" indicates whether the number was obtained
 * by a subtraction operation.  In that case if lost is nonzero
 * by a subtraction operation.  In that case if lost is nonzero
 * then the number is slightly smaller than indicated.
 * then the number is slightly smaller than indicated.
 *
 *
 * Input "exp" is the biased exponent, which may be negative.
 * Input "exp" is the biased exponent, which may be negative.
 * the exponent field of "s" is ignored but is replaced by
 * the exponent field of "s" is ignored but is replaced by
 * "exp" as adjusted by normalization and rounding.
 * "exp" as adjusted by normalization and rounding.
 *
 *
 * Input "rcntrl" is the rounding control.
 * Input "rcntrl" is the rounding control.
 */
 */
 
 
 
 
static void emdnorm(short unsigned int *s, int lost, int subflg, long int exp, int rcntrl, LDPARMS *ldp)
static void emdnorm(short unsigned int *s, int lost, int subflg, long int exp, int rcntrl, LDPARMS *ldp)
{
{
int i, j;
int i, j;
unsigned short r;
unsigned short r;
 
 
/* Normalize */
/* Normalize */
j = enormlz( s );
j = enormlz( s );
 
 
/* a blank significand could mean either zero or infinity. */
/* a blank significand could mean either zero or infinity. */
#ifndef USE_INFINITY
#ifndef USE_INFINITY
if( j > NBITS )
if( j > NBITS )
        {
        {
        ecleazs( s );
        ecleazs( s );
        return;
        return;
        }
        }
#endif
#endif
exp -= j;
exp -= j;
#ifndef USE_INFINITY
#ifndef USE_INFINITY
if( exp >= 32767L )
if( exp >= 32767L )
        goto overf;
        goto overf;
#else
#else
if( (j > NBITS) && (exp < 32767L) )
if( (j > NBITS) && (exp < 32767L) )
        {
        {
        ecleazs( s );
        ecleazs( s );
        return;
        return;
        }
        }
#endif
#endif
if( exp < 0L )
if( exp < 0L )
        {
        {
        if( exp > (long )(-NBITS-1) )
        if( exp > (long )(-NBITS-1) )
                {
                {
                j = (int )exp;
                j = (int )exp;
                i = eshift( s, j );
                i = eshift( s, j );
                if( i )
                if( i )
                        lost = 1;
                        lost = 1;
                }
                }
        else
        else
                {
                {
                ecleazs( s );
                ecleazs( s );
                return;
                return;
                }
                }
        }
        }
/* Round off, unless told not to by rcntrl. */
/* Round off, unless told not to by rcntrl. */
if( rcntrl == 0 )
if( rcntrl == 0 )
        goto mdfin;
        goto mdfin;
/* Set up rounding parameters if the control register changed. */
/* Set up rounding parameters if the control register changed. */
if( ldp->rndprc != ldp->rlast )
if( ldp->rndprc != ldp->rlast )
        {
        {
        ecleaz( ldp->rbit );
        ecleaz( ldp->rbit );
        switch( ldp->rndprc )
        switch( ldp->rndprc )
                {
                {
                default:
                default:
                case NBITS:
                case NBITS:
                        ldp->rw = NI-1; /* low guard word */
                        ldp->rw = NI-1; /* low guard word */
                        ldp->rmsk = 0xffff;
                        ldp->rmsk = 0xffff;
                        ldp->rmbit = 0x8000;
                        ldp->rmbit = 0x8000;
                        ldp->rebit = 1;
                        ldp->rebit = 1;
                        ldp->re = ldp->rw - 1;
                        ldp->re = ldp->rw - 1;
                        break;
                        break;
                case 113:
                case 113:
                        ldp->rw = 10;
                        ldp->rw = 10;
                        ldp->rmsk = 0x7fff;
                        ldp->rmsk = 0x7fff;
                        ldp->rmbit = 0x4000;
                        ldp->rmbit = 0x4000;
                        ldp->rebit = 0x8000;
                        ldp->rebit = 0x8000;
                        ldp->re = ldp->rw;
                        ldp->re = ldp->rw;
                        break;
                        break;
                case 64:
                case 64:
                        ldp->rw = 7;
                        ldp->rw = 7;
                        ldp->rmsk = 0xffff;
                        ldp->rmsk = 0xffff;
                        ldp->rmbit = 0x8000;
                        ldp->rmbit = 0x8000;
                        ldp->rebit = 1;
                        ldp->rebit = 1;
                        ldp->re = ldp->rw-1;
                        ldp->re = ldp->rw-1;
                        break;
                        break;
/* For DEC arithmetic */
/* For DEC arithmetic */
                case 56:
                case 56:
                        ldp->rw = 6;
                        ldp->rw = 6;
                        ldp->rmsk = 0xff;
                        ldp->rmsk = 0xff;
                        ldp->rmbit = 0x80;
                        ldp->rmbit = 0x80;
                        ldp->rebit = 0x100;
                        ldp->rebit = 0x100;
                        ldp->re = ldp->rw;
                        ldp->re = ldp->rw;
                        break;
                        break;
                case 53:
                case 53:
                        ldp->rw = 6;
                        ldp->rw = 6;
                        ldp->rmsk = 0x7ff;
                        ldp->rmsk = 0x7ff;
                        ldp->rmbit = 0x0400;
                        ldp->rmbit = 0x0400;
                        ldp->rebit = 0x800;
                        ldp->rebit = 0x800;
                        ldp->re = ldp->rw;
                        ldp->re = ldp->rw;
                        break;
                        break;
                case 24:
                case 24:
                        ldp->rw = 4;
                        ldp->rw = 4;
                        ldp->rmsk = 0xff;
                        ldp->rmsk = 0xff;
                        ldp->rmbit = 0x80;
                        ldp->rmbit = 0x80;
                        ldp->rebit = 0x100;
                        ldp->rebit = 0x100;
                        ldp->re = ldp->rw;
                        ldp->re = ldp->rw;
                        break;
                        break;
                }
                }
        ldp->rbit[ldp->re] = ldp->rebit;
        ldp->rbit[ldp->re] = ldp->rebit;
        ldp->rlast = ldp->rndprc;
        ldp->rlast = ldp->rndprc;
        }
        }
 
 
/* Shift down 1 temporarily if the data structure has an implied
/* Shift down 1 temporarily if the data structure has an implied
 * most significant bit and the number is denormal.
 * most significant bit and the number is denormal.
 * For rndprc = 64 or NBITS, there is no implied bit.
 * For rndprc = 64 or NBITS, there is no implied bit.
 * But Intel long double denormals lose one bit of significance even so.
 * But Intel long double denormals lose one bit of significance even so.
 */
 */
#if IBMPC
#if IBMPC
if( (exp <= 0) && (ldp->rndprc != NBITS) )
if( (exp <= 0) && (ldp->rndprc != NBITS) )
#else
#else
if( (exp <= 0) && (ldp->rndprc != 64) && (ldp->rndprc != NBITS) )
if( (exp <= 0) && (ldp->rndprc != 64) && (ldp->rndprc != NBITS) )
#endif
#endif
        {
        {
        lost |= s[NI-1] & 1;
        lost |= s[NI-1] & 1;
        eshdn1(s);
        eshdn1(s);
        }
        }
/* Clear out all bits below the rounding bit,
/* Clear out all bits below the rounding bit,
 * remembering in r if any were nonzero.
 * remembering in r if any were nonzero.
 */
 */
r = s[ldp->rw] & ldp->rmsk;
r = s[ldp->rw] & ldp->rmsk;
if( ldp->rndprc < NBITS )
if( ldp->rndprc < NBITS )
        {
        {
        i = ldp->rw + 1;
        i = ldp->rw + 1;
        while( i < NI )
        while( i < NI )
                {
                {
                if( s[i] )
                if( s[i] )
                        r |= 1;
                        r |= 1;
                s[i] = 0;
                s[i] = 0;
                ++i;
                ++i;
                }
                }
        }
        }
s[ldp->rw] &= ~ldp->rmsk;
s[ldp->rw] &= ~ldp->rmsk;
if( (r & ldp->rmbit) != 0 )
if( (r & ldp->rmbit) != 0 )
        {
        {
        if( r == ldp->rmbit )
        if( r == ldp->rmbit )
                {
                {
                if( lost == 0 )
                if( lost == 0 )
                        { /* round to even */
                        { /* round to even */
                        if( (s[ldp->re] & ldp->rebit) == 0 )
                        if( (s[ldp->re] & ldp->rebit) == 0 )
                                goto mddone;
                                goto mddone;
                        }
                        }
                else
                else
                        {
                        {
                        if( subflg != 0 )
                        if( subflg != 0 )
                                goto mddone;
                                goto mddone;
                        }
                        }
                }
                }
        eaddm( ldp->rbit, s );
        eaddm( ldp->rbit, s );
        }
        }
mddone:
mddone:
#if IBMPC
#if IBMPC
if( (exp <= 0) && (ldp->rndprc != NBITS) )
if( (exp <= 0) && (ldp->rndprc != NBITS) )
#else
#else
if( (exp <= 0) && (ldp->rndprc != 64) && (ldp->rndprc != NBITS) )
if( (exp <= 0) && (ldp->rndprc != 64) && (ldp->rndprc != NBITS) )
#endif
#endif
        {
        {
        eshup1(s);
        eshup1(s);
        }
        }
if( s[2] != 0 )
if( s[2] != 0 )
        { /* overflow on roundoff */
        { /* overflow on roundoff */
        eshdn1(s);
        eshdn1(s);
        exp += 1;
        exp += 1;
        }
        }
mdfin:
mdfin:
s[NI-1] = 0;
s[NI-1] = 0;
if( exp >= 32767L )
if( exp >= 32767L )
        {
        {
#ifndef USE_INFINITY
#ifndef USE_INFINITY
overf:
overf:
#endif
#endif
#ifdef USE_INFINITY
#ifdef USE_INFINITY
        s[1] = 32767;
        s[1] = 32767;
        for( i=2; i<NI-1; i++ )
        for( i=2; i<NI-1; i++ )
                s[i] = 0;
                s[i] = 0;
#else
#else
        s[1] = 32766;
        s[1] = 32766;
        s[2] = 0;
        s[2] = 0;
        for( i=M+1; i<NI-1; i++ )
        for( i=M+1; i<NI-1; i++ )
                s[i] = 0xffff;
                s[i] = 0xffff;
        s[NI-1] = 0;
        s[NI-1] = 0;
        if( (ldp->rndprc < 64) || (ldp->rndprc == 113) )
        if( (ldp->rndprc < 64) || (ldp->rndprc == 113) )
                {
                {
                s[ldp->rw] &= ~ldp->rmsk;
                s[ldp->rw] &= ~ldp->rmsk;
                if( ldp->rndprc == 24 )
                if( ldp->rndprc == 24 )
                        {
                        {
                        s[5] = 0;
                        s[5] = 0;
                        s[6] = 0;
                        s[6] = 0;
                        }
                        }
                }
                }
#endif
#endif
        return;
        return;
        }
        }
if( exp < 0 )
if( exp < 0 )
        s[1] = 0;
        s[1] = 0;
else
else
        s[1] = (unsigned short )exp;
        s[1] = (unsigned short )exp;
}
}
 
 
 
 
 
 
/*
/*
;       Subtract external format numbers.
;       Subtract external format numbers.
;
;
;       unsigned short a[NE], b[NE], c[NE];
;       unsigned short a[NE], b[NE], c[NE];
;       LDPARMS *ldp;
;       LDPARMS *ldp;
;       esub( a, b, c, ldp );    c = b - a
;       esub( a, b, c, ldp );    c = b - a
*/
*/
 
 
static void esub(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
static void esub(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
{
{
 
 
#ifdef NANS
#ifdef NANS
if( eisnan(a) )
if( eisnan(a) )
        {
        {
        emov (a, c);
        emov (a, c);
        return;
        return;
        }
        }
if( eisnan(b) )
if( eisnan(b) )
        {
        {
        emov(b,c);
        emov(b,c);
        return;
        return;
        }
        }
/* Infinity minus infinity is a NaN.
/* Infinity minus infinity is a NaN.
 * Test for subtracting infinities of the same sign.
 * Test for subtracting infinities of the same sign.
 */
 */
if( eisinf(a) && eisinf(b) && ((eisneg (a) ^ eisneg (b)) == 0))
if( eisinf(a) && eisinf(b) && ((eisneg (a) ^ eisneg (b)) == 0))
        {
        {
        mtherr( "esub", DOMAIN );
        mtherr( "esub", DOMAIN );
        enan( c, NBITS );
        enan( c, NBITS );
        return;
        return;
        }
        }
#endif
#endif
eadd1( a, b, c, 1, ldp );
eadd1( a, b, c, 1, ldp );
}
}
 
 
 
 
 
 
static void eadd1(short unsigned int *a, short unsigned int *b, short unsigned int *c, int subflg, LDPARMS *ldp)
static void eadd1(short unsigned int *a, short unsigned int *b, short unsigned int *c, int subflg, LDPARMS *ldp)
{
{
unsigned short ai[NI], bi[NI], ci[NI];
unsigned short ai[NI], bi[NI], ci[NI];
int i, lost, j, k;
int i, lost, j, k;
long lt, lta, ltb;
long lt, lta, ltb;
 
 
#ifdef USE_INFINITY
#ifdef USE_INFINITY
if( eisinf(a) )
if( eisinf(a) )
        {
        {
        emov(a,c);
        emov(a,c);
        if( subflg )
        if( subflg )
                eneg(c);
                eneg(c);
        return;
        return;
        }
        }
if( eisinf(b) )
if( eisinf(b) )
        {
        {
        emov(b,c);
        emov(b,c);
        return;
        return;
        }
        }
#endif
#endif
emovi( a, ai );
emovi( a, ai );
emovi( b, bi );
emovi( b, bi );
if( subflg )
if( subflg )
        ai[0] = ~ai[0];
        ai[0] = ~ai[0];
 
 
/* compare exponents */
/* compare exponents */
lta = ai[E];
lta = ai[E];
ltb = bi[E];
ltb = bi[E];
lt = lta - ltb;
lt = lta - ltb;
if( lt > 0L )
if( lt > 0L )
        {       /* put the larger number in bi */
        {       /* put the larger number in bi */
        emovz( bi, ci );
        emovz( bi, ci );
        emovz( ai, bi );
        emovz( ai, bi );
        emovz( ci, ai );
        emovz( ci, ai );
        ltb = bi[E];
        ltb = bi[E];
        lt = -lt;
        lt = -lt;
        }
        }
lost = 0;
lost = 0;
if( lt != 0L )
if( lt != 0L )
        {
        {
        if( lt < (long )(-NBITS-1) )
        if( lt < (long )(-NBITS-1) )
                goto done;      /* answer same as larger addend */
                goto done;      /* answer same as larger addend */
        k = (int )lt;
        k = (int )lt;
        lost = eshift( ai, k ); /* shift the smaller number down */
        lost = eshift( ai, k ); /* shift the smaller number down */
        }
        }
else
else
        {
        {
/* exponents were the same, so must compare significands */
/* exponents were the same, so must compare significands */
        i = ecmpm( ai, bi );
        i = ecmpm( ai, bi );
        if( i == 0 )
        if( i == 0 )
                { /* the numbers are identical in magnitude */
                { /* the numbers are identical in magnitude */
                /* if different signs, result is zero */
                /* if different signs, result is zero */
                if( ai[0] != bi[0] )
                if( ai[0] != bi[0] )
                        {
                        {
                        eclear(c);
                        eclear(c);
                        return;
                        return;
                        }
                        }
                /* if same sign, result is double */
                /* if same sign, result is double */
                /* double denomalized tiny number */
                /* double denomalized tiny number */
                if( (bi[E] == 0) && ((bi[3] & 0x8000) == 0) )
                if( (bi[E] == 0) && ((bi[3] & 0x8000) == 0) )
                        {
                        {
                        eshup1( bi );
                        eshup1( bi );
                        goto done;
                        goto done;
                        }
                        }
                /* add 1 to exponent unless both are zero! */
                /* add 1 to exponent unless both are zero! */
                for( j=1; j<NI-1; j++ )
                for( j=1; j<NI-1; j++ )
                        {
                        {
                        if( bi[j] != 0 )
                        if( bi[j] != 0 )
                                {
                                {
/* This could overflow, but let emovo take care of that. */
/* This could overflow, but let emovo take care of that. */
                                ltb += 1;
                                ltb += 1;
                                break;
                                break;
                                }
                                }
                        }
                        }
                bi[E] = (unsigned short )ltb;
                bi[E] = (unsigned short )ltb;
                goto done;
                goto done;
                }
                }
        if( i > 0 )
        if( i > 0 )
                {       /* put the larger number in bi */
                {       /* put the larger number in bi */
                emovz( bi, ci );
                emovz( bi, ci );
                emovz( ai, bi );
                emovz( ai, bi );
                emovz( ci, ai );
                emovz( ci, ai );
                }
                }
        }
        }
if( ai[0] == bi[0] )
if( ai[0] == bi[0] )
        {
        {
        eaddm( ai, bi );
        eaddm( ai, bi );
        subflg = 0;
        subflg = 0;
        }
        }
else
else
        {
        {
        esubm( ai, bi );
        esubm( ai, bi );
        subflg = 1;
        subflg = 1;
        }
        }
emdnorm( bi, lost, subflg, ltb, 64, ldp );
emdnorm( bi, lost, subflg, ltb, 64, ldp );
 
 
done:
done:
emovo( bi, c, ldp );
emovo( bi, c, ldp );
}
}
 
 
 
 
 
 
/*
/*
;       Divide.
;       Divide.
;
;
;       unsigned short a[NE], b[NE], c[NE];
;       unsigned short a[NE], b[NE], c[NE];
;       LDPARMS *ldp;
;       LDPARMS *ldp;
;       ediv( a, b, c, ldp );   c = b / a
;       ediv( a, b, c, ldp );   c = b / a
*/
*/
static void ediv(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
static void ediv(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
{
{
unsigned short ai[NI], bi[NI];
unsigned short ai[NI], bi[NI];
int i;
int i;
long lt, lta, ltb;
long lt, lta, ltb;
 
 
#ifdef NANS
#ifdef NANS
/* Return any NaN input. */
/* Return any NaN input. */
if( eisnan(a) )
if( eisnan(a) )
        {
        {
        emov(a,c);
        emov(a,c);
        return;
        return;
        }
        }
if( eisnan(b) )
if( eisnan(b) )
        {
        {
        emov(b,c);
        emov(b,c);
        return;
        return;
        }
        }
/* Zero over zero, or infinity over infinity, is a NaN. */
/* Zero over zero, or infinity over infinity, is a NaN. */
if( ((ecmp(a,ezero) == 0) && (ecmp(b,ezero) == 0))
if( ((ecmp(a,ezero) == 0) && (ecmp(b,ezero) == 0))
        || (eisinf (a) && eisinf (b)) )
        || (eisinf (a) && eisinf (b)) )
        {
        {
        mtherr( "ediv", DOMAIN );
        mtherr( "ediv", DOMAIN );
        enan( c, NBITS );
        enan( c, NBITS );
        return;
        return;
        }
        }
#endif
#endif
/* Infinity over anything else is infinity. */
/* Infinity over anything else is infinity. */
#ifdef USE_INFINITY
#ifdef USE_INFINITY
if( eisinf(b) )
if( eisinf(b) )
        {
        {
        if( eisneg(a) ^ eisneg(b) )
        if( eisneg(a) ^ eisneg(b) )
                *(c+(NE-1)) = 0x8000;
                *(c+(NE-1)) = 0x8000;
        else
        else
                *(c+(NE-1)) = 0;
                *(c+(NE-1)) = 0;
        einfin(c, ldp);
        einfin(c, ldp);
        return;
        return;
        }
        }
if( eisinf(a) )
if( eisinf(a) )
        {
        {
        eclear(c);
        eclear(c);
        return;
        return;
        }
        }
#endif
#endif
emovi( a, ai );
emovi( a, ai );
emovi( b, bi );
emovi( b, bi );
lta = ai[E];
lta = ai[E];
ltb = bi[E];
ltb = bi[E];
if( bi[E] == 0 )
if( bi[E] == 0 )
        { /* See if numerator is zero. */
        { /* See if numerator is zero. */
        for( i=1; i<NI-1; i++ )
        for( i=1; i<NI-1; i++ )
                {
                {
                if( bi[i] != 0 )
                if( bi[i] != 0 )
                        {
                        {
                        ltb -= enormlz( bi );
                        ltb -= enormlz( bi );
                        goto dnzro1;
                        goto dnzro1;
                        }
                        }
                }
                }
        eclear(c);
        eclear(c);
        return;
        return;
        }
        }
dnzro1:
dnzro1:
 
 
if( ai[E] == 0 )
if( ai[E] == 0 )
        {       /* possible divide by zero */
        {       /* possible divide by zero */
        for( i=1; i<NI-1; i++ )
        for( i=1; i<NI-1; i++ )
                {
                {
                if( ai[i] != 0 )
                if( ai[i] != 0 )
                        {
                        {
                        lta -= enormlz( ai );
                        lta -= enormlz( ai );
                        goto dnzro2;
                        goto dnzro2;
                        }
                        }
                }
                }
        if( ai[0] == bi[0] )
        if( ai[0] == bi[0] )
                *(c+(NE-1)) = 0;
                *(c+(NE-1)) = 0;
        else
        else
                *(c+(NE-1)) = 0x8000;
                *(c+(NE-1)) = 0x8000;
        einfin(c, ldp);
        einfin(c, ldp);
        mtherr( "ediv", SING );
        mtherr( "ediv", SING );
        return;
        return;
        }
        }
dnzro2:
dnzro2:
 
 
i = edivm( ai, bi, ldp );
i = edivm( ai, bi, ldp );
/* calculate exponent */
/* calculate exponent */
lt = ltb - lta + EXONE;
lt = ltb - lta + EXONE;
emdnorm( bi, i, 0, lt, 64, ldp );
emdnorm( bi, i, 0, lt, 64, ldp );
/* set the sign */
/* set the sign */
if( ai[0] == bi[0] )
if( ai[0] == bi[0] )
        bi[0] = 0;
        bi[0] = 0;
else
else
        bi[0] = 0Xffff;
        bi[0] = 0Xffff;
emovo( bi, c, ldp );
emovo( bi, c, ldp );
}
}
 
 
 
 
 
 
/*
/*
;       Multiply.
;       Multiply.
;
;
;       unsigned short a[NE], b[NE], c[NE];
;       unsigned short a[NE], b[NE], c[NE];
;       LDPARMS *ldp
;       LDPARMS *ldp
;       emul( a, b, c, ldp );   c = b * a
;       emul( a, b, c, ldp );   c = b * a
*/
*/
static void emul(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
static void emul(short unsigned int *a, short unsigned int *b, short unsigned int *c, LDPARMS *ldp)
{
{
unsigned short ai[NI], bi[NI];
unsigned short ai[NI], bi[NI];
int i, j;
int i, j;
long lt, lta, ltb;
long lt, lta, ltb;
 
 
#ifdef NANS
#ifdef NANS
/* NaN times anything is the same NaN. */
/* NaN times anything is the same NaN. */
if( eisnan(a) )
if( eisnan(a) )
        {
        {
        emov(a,c);
        emov(a,c);
        return;
        return;
        }
        }
if( eisnan(b) )
if( eisnan(b) )
        {
        {
        emov(b,c);
        emov(b,c);
        return;
        return;
        }
        }
/* Zero times infinity is a NaN. */
/* Zero times infinity is a NaN. */
if( (eisinf(a) && (ecmp(b,ezero) == 0))
if( (eisinf(a) && (ecmp(b,ezero) == 0))
        || (eisinf(b) && (ecmp(a,ezero) == 0)) )
        || (eisinf(b) && (ecmp(a,ezero) == 0)) )
        {
        {
        mtherr( "emul", DOMAIN );
        mtherr( "emul", DOMAIN );
        enan( c, NBITS );
        enan( c, NBITS );
        return;
        return;
        }
        }
#endif
#endif
/* Infinity times anything else is infinity. */
/* Infinity times anything else is infinity. */
#ifdef USE_INFINITY
#ifdef USE_INFINITY
if( eisinf(a) || eisinf(b) )
if( eisinf(a) || eisinf(b) )
        {
        {
        if( eisneg(a) ^ eisneg(b) )
        if( eisneg(a) ^ eisneg(b) )
                *(c+(NE-1)) = 0x8000;
                *(c+(NE-1)) = 0x8000;
        else
        else
                *(c+(NE-1)) = 0;
                *(c+(NE-1)) = 0;
        einfin(c, ldp);
        einfin(c, ldp);
        return;
        return;
        }
        }
#endif
#endif
emovi( a, ai );
emovi( a, ai );
emovi( b, bi );
emovi( b, bi );
lta = ai[E];
lta = ai[E];
ltb = bi[E];
ltb = bi[E];
if( ai[E] == 0 )
if( ai[E] == 0 )
        {
        {
        for( i=1; i<NI-1; i++ )
        for( i=1; i<NI-1; i++ )
                {
                {
                if( ai[i] != 0 )
                if( ai[i] != 0 )
                        {
                        {
                        lta -= enormlz( ai );
                        lta -= enormlz( ai );
                        goto mnzer1;
                        goto mnzer1;
                        }
                        }
                }
                }
        eclear(c);
        eclear(c);
        return;
        return;
        }
        }
mnzer1:
mnzer1:
 
 
if( bi[E] == 0 )
if( bi[E] == 0 )
        {
        {
        for( i=1; i<NI-1; i++ )
        for( i=1; i<NI-1; i++ )
                {
                {
                if( bi[i] != 0 )
                if( bi[i] != 0 )
                        {
                        {
                        ltb -= enormlz( bi );
                        ltb -= enormlz( bi );
                        goto mnzer2;
                        goto mnzer2;
                        }
                        }
                }
                }
        eclear(c);
        eclear(c);
        return;
        return;
        }
        }
mnzer2:
mnzer2:
 
 
/* Multiply significands */
/* Multiply significands */
j = emulm( ai, bi, ldp );
j = emulm( ai, bi, ldp );
/* calculate exponent */
/* calculate exponent */
lt = lta + ltb - (EXONE - 1);
lt = lta + ltb - (EXONE - 1);
emdnorm( bi, j, 0, lt, 64, ldp );
emdnorm( bi, j, 0, lt, 64, ldp );
/* calculate sign of product */
/* calculate sign of product */
if( ai[0] == bi[0] )
if( ai[0] == bi[0] )
        bi[0] = 0;
        bi[0] = 0;
else
else
        bi[0] = 0xffff;
        bi[0] = 0xffff;
emovo( bi, c, ldp );
emovo( bi, c, ldp );
}
}
 
 
 
 
 
 
#if LDBL_MANT_DIG > 64
#if LDBL_MANT_DIG > 64
static void e113toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
static void e113toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
{
{
register unsigned short r;
register unsigned short r;
unsigned short *e, *p;
unsigned short *e, *p;
unsigned short yy[NI];
unsigned short yy[NI];
int denorm, i;
int denorm, i;
 
 
e = pe;
e = pe;
denorm = 0;
denorm = 0;
ecleaz(yy);
ecleaz(yy);
#ifdef IBMPC
#ifdef IBMPC
e += 7;
e += 7;
#endif
#endif
r = *e;
r = *e;
yy[0] = 0;
yy[0] = 0;
if( r & 0x8000 )
if( r & 0x8000 )
        yy[0] = 0xffff;
        yy[0] = 0xffff;
r &= 0x7fff;
r &= 0x7fff;
#ifdef USE_INFINITY
#ifdef USE_INFINITY
if( r == 0x7fff )
if( r == 0x7fff )
        {
        {
#ifdef NANS
#ifdef NANS
#ifdef IBMPC
#ifdef IBMPC
        for( i=0; i<7; i++ )
        for( i=0; i<7; i++ )
                {
                {
                if( pe[i] != 0 )
                if( pe[i] != 0 )
                        {
                        {
                        enan( y, NBITS );
                        enan( y, NBITS );
                        return;
                        return;
                        }
                        }
                }
                }
#else  /* !IBMPC */
#else  /* !IBMPC */
        for( i=1; i<8; i++ )
        for( i=1; i<8; i++ )
                {
                {
                if( pe[i] != 0 )
                if( pe[i] != 0 )
                        {
                        {
                        enan( y, NBITS );
                        enan( y, NBITS );
                        return;
                        return;
                        }
                        }
                }
                }
#endif /* !IBMPC */
#endif /* !IBMPC */
#endif /* NANS */
#endif /* NANS */
        eclear( y );
        eclear( y );
        einfin( y, ldp );
        einfin( y, ldp );
        if( *e & 0x8000 )
        if( *e & 0x8000 )
                eneg(y);
                eneg(y);
        return;
        return;
        }
        }
#endif  /* INFINITY */
#endif  /* INFINITY */
yy[E] = r;
yy[E] = r;
p = &yy[M + 1];
p = &yy[M + 1];
#ifdef IBMPC
#ifdef IBMPC
for( i=0; i<7; i++ )
for( i=0; i<7; i++ )
        *p++ = *(--e);
        *p++ = *(--e);
#else  /* IBMPC */
#else  /* IBMPC */
++e;
++e;
for( i=0; i<7; i++ )
for( i=0; i<7; i++ )
        *p++ = *e++;
        *p++ = *e++;
#endif /* IBMPC */ 
#endif /* IBMPC */ 
/* If denormal, remove the implied bit; else shift down 1. */
/* If denormal, remove the implied bit; else shift down 1. */
if( r == 0 )
if( r == 0 )
        {
        {
        yy[M] = 0;
        yy[M] = 0;
        }
        }
else
else
        {
        {
        yy[M] = 1;
        yy[M] = 1;
        eshift( yy, -1 );
        eshift( yy, -1 );
        }
        }
emovo(yy,y,ldp);
emovo(yy,y,ldp);
}
}
 
 
/* move out internal format to ieee long double */
/* move out internal format to ieee long double */
static void toe113(short unsigned int *a, short unsigned int *b)
static void toe113(short unsigned int *a, short unsigned int *b)
{
{
register unsigned short *p, *q;
register unsigned short *p, *q;
unsigned short i;
unsigned short i;
 
 
#ifdef NANS
#ifdef NANS
if( eiisnan(a) )
if( eiisnan(a) )
        {
        {
        enan( b, 113 );
        enan( b, 113 );
        return;
        return;
        }
        }
#endif
#endif
p = a;
p = a;
#ifdef MIEEE
#ifdef MIEEE
q = b;
q = b;
#else
#else
q = b + 7;                      /* point to output exponent */
q = b + 7;                      /* point to output exponent */
#endif
#endif
 
 
/* If not denormal, delete the implied bit. */
/* If not denormal, delete the implied bit. */
if( a[E] != 0 )
if( a[E] != 0 )
        {
        {
        eshup1 (a);
        eshup1 (a);
        }
        }
/* combine sign and exponent */
/* combine sign and exponent */
i = *p++;
i = *p++;
#ifdef MIEEE
#ifdef MIEEE
if( i )
if( i )
        *q++ = *p++ | 0x8000;
        *q++ = *p++ | 0x8000;
else
else
        *q++ = *p++;
        *q++ = *p++;
#else
#else
if( i )
if( i )
        *q-- = *p++ | 0x8000;
        *q-- = *p++ | 0x8000;
else
else
        *q-- = *p++;
        *q-- = *p++;
#endif
#endif
/* skip over guard word */
/* skip over guard word */
++p;
++p;
/* move the significand */
/* move the significand */
#ifdef MIEEE
#ifdef MIEEE
for (i = 0; i < 7; i++)
for (i = 0; i < 7; i++)
        *q++ = *p++;
        *q++ = *p++;
#else
#else
for (i = 0; i < 7; i++)
for (i = 0; i < 7; i++)
        *q-- = *p++;
        *q-- = *p++;
#endif
#endif
}
}
#endif /* LDBL_MANT_DIG > 64 */
#endif /* LDBL_MANT_DIG > 64 */
 
 
 
 
#if LDBL_MANT_DIG == 64
#if LDBL_MANT_DIG == 64
static void e64toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
static void e64toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
{
{
unsigned short yy[NI];
unsigned short yy[NI];
unsigned short *p, *q, *e;
unsigned short *p, *q, *e;
int i;
int i;
 
 
e = pe;
e = pe;
p = yy;
p = yy;
 
 
for( i=0; i<NE-5; i++ )
for( i=0; i<NE-5; i++ )
        *p++ = 0;
        *p++ = 0;
#ifdef IBMPC
#ifdef IBMPC
for( i=0; i<5; i++ )
for( i=0; i<5; i++ )
        *p++ = *e++;
        *p++ = *e++;
#endif
#endif
#ifdef DEC
#ifdef DEC
for( i=0; i<5; i++ )
for( i=0; i<5; i++ )
        *p++ = *e++;
        *p++ = *e++;
#endif
#endif
#ifdef MIEEE
#ifdef MIEEE
p = &yy[0] + (NE-1);
p = &yy[0] + (NE-1);
*p-- = *e++;
*p-- = *e++;
++e;  /* MIEEE skips over 2nd short */
++e;  /* MIEEE skips over 2nd short */
for( i=0; i<4; i++ )
for( i=0; i<4; i++ )
        *p-- = *e++;
        *p-- = *e++;
#endif
#endif
 
 
#ifdef IBMPC
#ifdef IBMPC
/* For Intel long double, shift denormal significand up 1
/* For Intel long double, shift denormal significand up 1
   -- but only if the top significand bit is zero.  */
   -- but only if the top significand bit is zero.  */
if((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
if((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
  {
  {
    unsigned short temp[NI+1];
    unsigned short temp[NI+1];
    emovi(yy, temp);
    emovi(yy, temp);
    eshup1(temp);
    eshup1(temp);
    emovo(temp,y,ldp);
    emovo(temp,y,ldp);
    return;
    return;
  }
  }
#endif
#endif
#ifdef USE_INFINITY
#ifdef USE_INFINITY
/* Point to the exponent field.  */
/* Point to the exponent field.  */
p = &yy[NE-1];
p = &yy[NE-1];
if( (*p & 0x7fff) == 0x7fff )
if( (*p & 0x7fff) == 0x7fff )
        {
        {
#ifdef NANS
#ifdef NANS
#ifdef IBMPC
#ifdef IBMPC
        for( i=0; i<4; i++ )
        for( i=0; i<4; i++ )
                {
                {
                if((i != 3 && pe[i] != 0)
                if((i != 3 && pe[i] != 0)
                   /* Check for Intel long double infinity pattern.  */
                   /* Check for Intel long double infinity pattern.  */
                   || (i == 3 && pe[i] != 0x8000))
                   || (i == 3 && pe[i] != 0x8000))
                        {
                        {
                        enan( y, NBITS );
                        enan( y, NBITS );
                        return;
                        return;
                        }
                        }
                }
                }
#endif
#endif
#ifdef MIEEE
#ifdef MIEEE
        for( i=2; i<=5; i++ )
        for( i=2; i<=5; i++ )
                {
                {
                if( pe[i] != 0 )
                if( pe[i] != 0 )
                        {
                        {
                        enan( y, NBITS );
                        enan( y, NBITS );
                        return;
                        return;
                        }
                        }
                }
                }
#endif
#endif
#endif /* NANS */
#endif /* NANS */
        eclear( y );
        eclear( y );
        einfin( y, ldp );
        einfin( y, ldp );
        if( *p & 0x8000 )
        if( *p & 0x8000 )
                eneg(y);
                eneg(y);
        return;
        return;
        }
        }
#endif /* USE_INFINITY */
#endif /* USE_INFINITY */
p = yy;
p = yy;
q = y;
q = y;
for( i=0; i<NE; i++ )
for( i=0; i<NE; i++ )
        *q++ = *p++;
        *q++ = *p++;
}
}
 
 
/* move out internal format to ieee long double */
/* move out internal format to ieee long double */
static void toe64(short unsigned int *a, short unsigned int *b)
static void toe64(short unsigned int *a, short unsigned int *b)
{
{
register unsigned short *p, *q;
register unsigned short *p, *q;
unsigned short i;
unsigned short i;
 
 
#ifdef NANS
#ifdef NANS
if( eiisnan(a) )
if( eiisnan(a) )
        {
        {
        enan( b, 64 );
        enan( b, 64 );
        return;
        return;
        }
        }
#endif
#endif
#ifdef IBMPC
#ifdef IBMPC
/* Shift Intel denormal significand down 1.  */
/* Shift Intel denormal significand down 1.  */
if( a[E] == 0 )
if( a[E] == 0 )
  eshdn1(a);
  eshdn1(a);
#endif
#endif
p = a;
p = a;
#ifdef MIEEE
#ifdef MIEEE
q = b;
q = b;
#else
#else
q = b + 4; /* point to output exponent */
q = b + 4; /* point to output exponent */
/* NOTE: Intel data type is 96 bits wide, clear the last word here. */
/* NOTE: Intel data type is 96 bits wide, clear the last word here. */
*(q+1)= 0;
*(q+1)= 0;
#endif
#endif
 
 
/* combine sign and exponent */
/* combine sign and exponent */
i = *p++;
i = *p++;
#ifdef MIEEE
#ifdef MIEEE
if( i )
if( i )
        *q++ = *p++ | 0x8000;
        *q++ = *p++ | 0x8000;
else
else
        *q++ = *p++;
        *q++ = *p++;
*q++ = 0; /* leave 2nd short blank */
*q++ = 0; /* leave 2nd short blank */
#else
#else
if( i )
if( i )
        *q-- = *p++ | 0x8000;
        *q-- = *p++ | 0x8000;
else
else
        *q-- = *p++;
        *q-- = *p++;
#endif
#endif
/* skip over guard word */
/* skip over guard word */
++p;
++p;
/* move the significand */
/* move the significand */
#ifdef MIEEE
#ifdef MIEEE
for( i=0; i<4; i++ )
for( i=0; i<4; i++ )
        *q++ = *p++;
        *q++ = *p++;
#else
#else
#ifdef USE_INFINITY
#ifdef USE_INFINITY
#ifdef IBMPC
#ifdef IBMPC
if (eiisinf (a))
if (eiisinf (a))
        {
        {
        /* Intel long double infinity.  */
        /* Intel long double infinity.  */
        *q-- = 0x8000;
        *q-- = 0x8000;
        *q-- = 0;
        *q-- = 0;
        *q-- = 0;
        *q-- = 0;
        *q = 0;
        *q = 0;
        return;
        return;
        }
        }
#endif /* IBMPC */
#endif /* IBMPC */
#endif /* USE_INFINITY */
#endif /* USE_INFINITY */
for( i=0; i<4; i++ )
for( i=0; i<4; i++ )
        *q-- = *p++;
        *q-- = *p++;
#endif
#endif
}
}
 
 
#endif /* LDBL_MANT_DIG == 64 */
#endif /* LDBL_MANT_DIG == 64 */
 
 
#if LDBL_MANT_DIG == 53
#if LDBL_MANT_DIG == 53
/*
/*
; Convert IEEE double precision to e type
; Convert IEEE double precision to e type
;       double d;
;       double d;
;       unsigned short x[N+2];
;       unsigned short x[N+2];
;       e53toe( &d, x );
;       e53toe( &d, x );
*/
*/
static void e53toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
static void e53toe(short unsigned int *pe, short unsigned int *y, LDPARMS *ldp)
{
{
#ifdef DEC
#ifdef DEC
 
 
dectoe( pe, y ); /* see etodec.c */
dectoe( pe, y ); /* see etodec.c */
 
 
#else
#else
 
 
register unsigned short r;
register unsigned short r;
register unsigned short *p, *e;
register unsigned short *p, *e;
unsigned short yy[NI];
unsigned short yy[NI];
int denorm, k;
int denorm, k;
 
 
e = pe;
e = pe;
denorm = 0;      /* flag if denormalized number */
denorm = 0;      /* flag if denormalized number */
ecleaz(yy);
ecleaz(yy);
#ifdef IBMPC
#ifdef IBMPC
e += 3;
e += 3;
#endif
#endif
#ifdef DEC
#ifdef DEC
e += 3;
e += 3;
#endif 
#endif 
r = *e;
r = *e;
yy[0] = 0;
yy[0] = 0;
if( r & 0x8000 )
if( r & 0x8000 )
        yy[0] = 0xffff;
        yy[0] = 0xffff;
yy[M] = (r & 0x0f) | 0x10;
yy[M] = (r & 0x0f) | 0x10;
r &= ~0x800f;   /* strip sign and 4 significand bits */
r &= ~0x800f;   /* strip sign and 4 significand bits */
#ifdef USE_INFINITY
#ifdef USE_INFINITY
if( r == 0x7ff0 )
if( r == 0x7ff0 )
        {
        {
#ifdef NANS
#ifdef NANS
#ifdef IBMPC
#ifdef IBMPC
        if( ((pe[3] & 0xf) != 0) || (pe[2] != 0)
        if( ((pe[3] & 0xf) != 0) || (pe[2] != 0)
                || (pe[1] != 0) || (pe[0] != 0) )
                || (pe[1] != 0) || (pe[0] != 0) )
                {
                {
                enan( y, NBITS );
                enan( y, NBITS );
                return;
                return;
                }
                }
#else  /* !IBMPC */
#else  /* !IBMPC */
        if( ((pe[0] & 0xf) != 0) || (pe[1] != 0)
        if( ((pe[0] & 0xf) != 0) || (pe[1] != 0)
                 || (pe[2] != 0) || (pe[3] != 0) )
                 || (pe[2] != 0) || (pe[3] != 0) )
                {
                {
                enan( y, NBITS );
                enan( y, NBITS );
                return;
                return;
                }
                }
#endif /* !IBMPC */
#endif /* !IBMPC */
#endif  /* NANS */
#endif  /* NANS */
        eclear( y );
        eclear( y );
        einfin( y, ldp );
        einfin( y, ldp );
        if( yy[0] )
        if( yy[0] )
                eneg(y);
                eneg(y);
        return;
        return;
        }
        }
#endif
#endif
r >>= 4;
r >>= 4;
/* If zero exponent, then the significand is denormalized.
/* If zero exponent, then the significand is denormalized.
 * So, take back the understood high significand bit. */
 * So, take back the understood high significand bit. */
if( r == 0 )
if( r == 0 )
        {
        {
        denorm = 1;
        denorm = 1;
        yy[M] &= ~0x10;
        yy[M] &= ~0x10;
        }
        }
r += EXONE - 01777;
r += EXONE - 01777;
yy[E] = r;
yy[E] = r;
p = &yy[M+1];
p = &yy[M+1];
#ifdef IBMPC
#ifdef IBMPC
*p++ = *(--e);
*p++ = *(--e);
*p++ = *(--e);
*p++ = *(--e);
*p++ = *(--e);
*p++ = *(--e);
#else  /* !IBMPC */
#else  /* !IBMPC */
++e;
++e;
*p++ = *e++;
*p++ = *e++;
*p++ = *e++;
*p++ = *e++;
*p++ = *e++;
*p++ = *e++;
#endif /* !IBMPC */
#endif /* !IBMPC */
(void )eshift( yy, -5 );
(void )eshift( yy, -5 );
if( denorm )
if( denorm )
        { /* if zero exponent, then normalize the significand */
        { /* if zero exponent, then normalize the significand */
        if( (k = enormlz(yy)) > NBITS )
        if( (k = enormlz(yy)) > NBITS )
                ecleazs(yy);
                ecleazs(yy);
        else
        else
                yy[E] -= (unsigned short )(k-1);
                yy[E] -= (unsigned short )(k-1);
        }
        }
emovo( yy, y, ldp );
emovo( yy, y, ldp );
#endif /* !DEC */
#endif /* !DEC */
}
}
 
 
/*
/*
; e type to IEEE double precision
; e type to IEEE double precision
;       double d;
;       double d;
;       unsigned short x[NE];
;       unsigned short x[NE];
;       etoe53( x, &d );
;       etoe53( x, &d );
*/
*/
 
 
#ifdef DEC
#ifdef DEC
 
 
static void etoe53( x, e )
static void etoe53( x, e )
unsigned short *x, *e;
unsigned short *x, *e;
{
{
etodec( x, e ); /* see etodec.c */
etodec( x, e ); /* see etodec.c */
}
}
 
 
static void toe53( x, y )
static void toe53( x, y )
unsigned short *x, *y;
unsigned short *x, *y;
{
{
todec( x, y );
todec( x, y );
}
}
 
 
#else
#else
 
 
static void toe53(short unsigned int *x, short unsigned int *y)
static void toe53(short unsigned int *x, short unsigned int *y)
{
{
unsigned short i;
unsigned short i;
unsigned short *p;
unsigned short *p;
 
 
 
 
#ifdef NANS
#ifdef NANS
if( eiisnan(x) )
if( eiisnan(x) )
        {
        {
        enan( y, 53 );
        enan( y, 53 );
        return;
        return;
        }
        }
#endif
#endif
p = &x[0];
p = &x[0];
#ifdef IBMPC
#ifdef IBMPC
y += 3;
y += 3;
#endif
#endif
#ifdef DEC
#ifdef DEC
y += 3;
y += 3;
#endif
#endif
*y = 0;  /* output high order */
*y = 0;  /* output high order */
if( *p++ )
if( *p++ )
        *y = 0x8000;    /* output sign bit */
        *y = 0x8000;    /* output sign bit */
 
 
i = *p++;
i = *p++;
if( i >= (unsigned int )2047 )
if( i >= (unsigned int )2047 )
        {       /* Saturate at largest number less than infinity. */
        {       /* Saturate at largest number less than infinity. */
#ifdef USE_INFINITY
#ifdef USE_INFINITY
        *y |= 0x7ff0;
        *y |= 0x7ff0;
#ifdef IBMPC
#ifdef IBMPC
        *(--y) = 0;
        *(--y) = 0;
        *(--y) = 0;
        *(--y) = 0;
        *(--y) = 0;
        *(--y) = 0;
#else /* !IBMPC */
#else /* !IBMPC */
        ++y;
        ++y;
        *y++ = 0;
        *y++ = 0;
        *y++ = 0;
        *y++ = 0;
        *y++ = 0;
        *y++ = 0;
#endif /* IBMPC */
#endif /* IBMPC */
#else /* !USE_INFINITY */
#else /* !USE_INFINITY */
        *y |= (unsigned short )0x7fef;
        *y |= (unsigned short )0x7fef;
#ifdef IBMPC
#ifdef IBMPC
        *(--y) = 0xffff;
        *(--y) = 0xffff;
        *(--y) = 0xffff;
        *(--y) = 0xffff;
        *(--y) = 0xffff;
        *(--y) = 0xffff;
#else /* !IBMPC */
#else /* !IBMPC */
        ++y;
        ++y;
        *y++ = 0xffff;
        *y++ = 0xffff;
        *y++ = 0xffff;
        *y++ = 0xffff;
        *y++ = 0xffff;
        *y++ = 0xffff;
#endif
#endif
#endif /* !USE_INFINITY */
#endif /* !USE_INFINITY */
        return;
        return;
        }
        }
if( i == 0 )
if( i == 0 )
        {
        {
        (void )eshift( x, 4 );
        (void )eshift( x, 4 );
        }
        }
else
else
        {
        {
        i <<= 4;
        i <<= 4;
        (void )eshift( x, 5 );
        (void )eshift( x, 5 );
        }
        }
i |= *p++ & (unsigned short )0x0f;      /* *p = xi[M] */
i |= *p++ & (unsigned short )0x0f;      /* *p = xi[M] */
*y |= (unsigned short )i; /* high order output already has sign bit set */
*y |= (unsigned short )i; /* high order output already has sign bit set */
#ifdef IBMPC
#ifdef IBMPC
*(--y) = *p++;
*(--y) = *p++;
*(--y) = *p++;
*(--y) = *p++;
*(--y) = *p;
*(--y) = *p;
#else /* !IBMPC */
#else /* !IBMPC */
++y;
++y;
*y++ = *p++;
*y++ = *p++;
*y++ = *p++;
*y++ = *p++;
*y++ = *p++;
*y++ = *p++;
#endif /* !IBMPC */
#endif /* !IBMPC */
}
}
 
 
#endif /* not DEC */
#endif /* not DEC */
#endif /* LDBL_MANT_DIG == 53 */
#endif /* LDBL_MANT_DIG == 53 */
 
 
#if LDBL_MANT_DIG == 24
#if LDBL_MANT_DIG == 24
/*
/*
; Convert IEEE single precision to e type
; Convert IEEE single precision to e type
;       float d;
;       float d;
;       unsigned short x[N+2];
;       unsigned short x[N+2];
;       dtox( &d, x );
;       dtox( &d, x );
*/
*/
void e24toe( short unsigned int *pe, short unsigned int *y, LDPARMS *ldp )
void e24toe( short unsigned int *pe, short unsigned int *y, LDPARMS *ldp )
{
{
register unsigned short r;
register unsigned short r;
register unsigned short *p, *e;
register unsigned short *p, *e;
unsigned short yy[NI];
unsigned short yy[NI];
int denorm, k;
int denorm, k;
 
 
e = pe;
e = pe;
denorm = 0;      /* flag if denormalized number */
denorm = 0;      /* flag if denormalized number */
ecleaz(yy);
ecleaz(yy);
#ifdef IBMPC
#ifdef IBMPC
e += 1;
e += 1;
#endif
#endif
#ifdef DEC
#ifdef DEC
e += 1;
e += 1;
#endif
#endif
r = *e;
r = *e;
yy[0] = 0;
yy[0] = 0;
if( r & 0x8000 )
if( r & 0x8000 )
        yy[0] = 0xffff;
        yy[0] = 0xffff;
yy[M] = (r & 0x7f) | 0200;
yy[M] = (r & 0x7f) | 0200;
r &= ~0x807f;   /* strip sign and 7 significand bits */
r &= ~0x807f;   /* strip sign and 7 significand bits */
#ifdef USE_INFINITY
#ifdef USE_INFINITY
if( r == 0x7f80 )
if( r == 0x7f80 )
        {
        {
#ifdef NANS
#ifdef NANS
#ifdef MIEEE
#ifdef MIEEE
        if( ((pe[0] & 0x7f) != 0) || (pe[1] != 0) )
        if( ((pe[0] & 0x7f) != 0) || (pe[1] != 0) )
                {
                {
                enan( y, NBITS );
                enan( y, NBITS );
                return;
                return;
                }
                }
#else  /* !MIEEE */
#else  /* !MIEEE */
        if( ((pe[1] & 0x7f) != 0) || (pe[0] != 0) )
        if( ((pe[1] & 0x7f) != 0) || (pe[0] != 0) )
                {
                {
                enan( y, NBITS );
                enan( y, NBITS );
                return;
                return;
                }
                }
#endif /* !MIEEE */
#endif /* !MIEEE */
#endif  /* NANS */
#endif  /* NANS */
        eclear( y );
        eclear( y );
        einfin( y, ldp );
        einfin( y, ldp );
        if( yy[0] )
        if( yy[0] )
                eneg(y);
                eneg(y);
        return;
        return;
        }
        }
#endif
#endif
r >>= 7;
r >>= 7;
/* If zero exponent, then the significand is denormalized.
/* If zero exponent, then the significand is denormalized.
 * So, take back the understood high significand bit. */
 * So, take back the understood high significand bit. */
if( r == 0 )
if( r == 0 )
        {
        {
        denorm = 1;
        denorm = 1;
        yy[M] &= ~0200;
        yy[M] &= ~0200;
        }
        }
r += EXONE - 0177;
r += EXONE - 0177;
yy[E] = r;
yy[E] = r;
p = &yy[M+1];
p = &yy[M+1];
#ifdef IBMPC
#ifdef IBMPC
*p++ = *(--e);
*p++ = *(--e);
#endif
#endif
#ifdef DEC
#ifdef DEC
*p++ = *(--e);
*p++ = *(--e);
#endif
#endif
#ifdef MIEEE
#ifdef MIEEE
++e;
++e;
*p++ = *e++;
*p++ = *e++;
#endif
#endif
(void )eshift( yy, -8 );
(void )eshift( yy, -8 );
if( denorm )
if( denorm )
        { /* if zero exponent, then normalize the significand */
        { /* if zero exponent, then normalize the significand */
        if( (k = enormlz(yy)) > NBITS )
        if( (k = enormlz(yy)) > NBITS )
                ecleazs(yy);
                ecleazs(yy);
        else
        else
                yy[E] -= (unsigned short )(k-1);
                yy[E] -= (unsigned short )(k-1);
        }
        }
emovo( yy, y, ldp );
emovo( yy, y, ldp );
}
}
 
 
static void toe24(short unsigned int *x, short unsigned int *y)
static void toe24(short unsigned int *x, short unsigned int *y)
{
{
unsigned short i;
unsigned short i;
unsigned short *p;
unsigned short *p;
 
 
#ifdef NANS
#ifdef NANS
if( eiisnan(x) )
if( eiisnan(x) )
        {
        {
        enan( y, 24 );
        enan( y, 24 );
        return;
        return;
        }
        }
#endif
#endif
p = &x[0];
p = &x[0];
#ifdef IBMPC
#ifdef IBMPC
y += 1;
y += 1;
#endif
#endif
#ifdef DEC
#ifdef DEC
y += 1;
y += 1;
#endif
#endif
*y = 0;  /* output high order */
*y = 0;  /* output high order */
if( *p++ )
if( *p++ )
        *y = 0x8000;    /* output sign bit */
        *y = 0x8000;    /* output sign bit */
 
 
i = *p++;
i = *p++;
if( i >= 255 )
if( i >= 255 )
        {       /* Saturate at largest number less than infinity. */
        {       /* Saturate at largest number less than infinity. */
#ifdef USE_INFINITY
#ifdef USE_INFINITY
        *y |= (unsigned short )0x7f80;
        *y |= (unsigned short )0x7f80;
#ifdef IBMPC
#ifdef IBMPC
        *(--y) = 0;
        *(--y) = 0;
#endif
#endif
#ifdef DEC
#ifdef DEC
        *(--y) = 0;
        *(--y) = 0;
#endif
#endif
#ifdef MIEEE
#ifdef MIEEE
        ++y;
        ++y;
        *y = 0;
        *y = 0;
#endif
#endif
#else /* !USE_INFINITY */
#else /* !USE_INFINITY */
        *y |= (unsigned short )0x7f7f;
        *y |= (unsigned short )0x7f7f;
#ifdef IBMPC
#ifdef IBMPC
        *(--y) = 0xffff;
        *(--y) = 0xffff;
#endif
#endif
#ifdef DEC
#ifdef DEC
        *(--y) = 0xffff;
        *(--y) = 0xffff;
#endif
#endif
#ifdef MIEEE
#ifdef MIEEE
        ++y;
        ++y;
        *y = 0xffff;
        *y = 0xffff;
#endif
#endif
#endif /* !USE_INFINITY */
#endif /* !USE_INFINITY */
        return;
        return;
        }
        }
if( i == 0 )
if( i == 0 )
        {
        {
        (void )eshift( x, 7 );
        (void )eshift( x, 7 );
        }
        }
else
else
        {
        {
        i <<= 7;
        i <<= 7;
        (void )eshift( x, 8 );
        (void )eshift( x, 8 );
        }
        }
i |= *p++ & (unsigned short )0x7f;      /* *p = xi[M] */
i |= *p++ & (unsigned short )0x7f;      /* *p = xi[M] */
*y |= i;        /* high order output already has sign bit set */
*y |= i;        /* high order output already has sign bit set */
#ifdef IBMPC
#ifdef IBMPC
*(--y) = *p;
*(--y) = *p;
#endif
#endif
#ifdef DEC
#ifdef DEC
*(--y) = *p;
*(--y) = *p;
#endif
#endif
#ifdef MIEEE
#ifdef MIEEE
++y;
++y;
*y = *p;
*y = *p;
#endif
#endif
}
}
#endif /* LDBL_MANT_DIG == 24 */
#endif /* LDBL_MANT_DIG == 24 */
 
 
/* Compare two e type numbers.
/* Compare two e type numbers.
 *
 *
 * unsigned short a[NE], b[NE];
 * unsigned short a[NE], b[NE];
 * ecmp( a, b );
 * ecmp( a, b );
 *
 *
 *  returns +1 if a > b
 *  returns +1 if a > b
 *           0 if a == b
 *           0 if a == b
 *          -1 if a < b
 *          -1 if a < b
 *          -2 if either a or b is a NaN.
 *          -2 if either a or b is a NaN.
 */
 */
static int ecmp(short unsigned int *a, short unsigned int *b)
static int ecmp(short unsigned int *a, short unsigned int *b)
{
{
unsigned short ai[NI], bi[NI];
unsigned short ai[NI], bi[NI];
register unsigned short *p, *q;
register unsigned short *p, *q;
register int i;
register int i;
int msign;
int msign;
 
 
#ifdef NANS
#ifdef NANS
if (eisnan (a)  || eisnan (b))
if (eisnan (a)  || eisnan (b))
        return( -2 );
        return( -2 );
#endif
#endif
emovi( a, ai );
emovi( a, ai );
p = ai;
p = ai;
emovi( b, bi );
emovi( b, bi );
q = bi;
q = bi;
 
 
if( *p != *q )
if( *p != *q )
        { /* the signs are different */
        { /* the signs are different */
/* -0 equals + 0 */
/* -0 equals + 0 */
        for( i=1; i<NI-1; i++ )
        for( i=1; i<NI-1; i++ )
                {
                {
                if( ai[i] != 0 )
                if( ai[i] != 0 )
                        goto nzro;
                        goto nzro;
                if( bi[i] != 0 )
                if( bi[i] != 0 )
                        goto nzro;
                        goto nzro;
                }
                }
        return(0);
        return(0);
nzro:
nzro:
        if( *p == 0 )
        if( *p == 0 )
                return( 1 );
                return( 1 );
        else
        else
                return( -1 );
                return( -1 );
        }
        }
/* both are the same sign */
/* both are the same sign */
if( *p == 0 )
if( *p == 0 )
        msign = 1;
        msign = 1;
else
else
        msign = -1;
        msign = -1;
i = NI-1;
i = NI-1;
do
do
        {
        {
        if( *p++ != *q++ )
        if( *p++ != *q++ )
                {
                {
                goto diff;
                goto diff;
                }
                }
        }
        }
while( --i > 0 );
while( --i > 0 );
 
 
return(0);       /* equality */
return(0);       /* equality */
 
 
 
 
 
 
diff:
diff:
 
 
if( *(--p) > *(--q) )
if( *(--p) > *(--q) )
        return( msign );                /* p is bigger */
        return( msign );                /* p is bigger */
else
else
        return( -msign );       /* p is littler */
        return( -msign );       /* p is littler */
}
}
 
 
 
 
/*
/*
;       Shift significand
;       Shift significand
;
;
;       Shifts significand area up or down by the number of bits
;       Shifts significand area up or down by the number of bits
;       given by the variable sc.
;       given by the variable sc.
*/
*/
static int eshift(short unsigned int *x, int sc)
static int eshift(short unsigned int *x, int sc)
{
{
unsigned short lost;
unsigned short lost;
unsigned short *p;
unsigned short *p;
 
 
if( sc == 0 )
if( sc == 0 )
        return( 0 );
        return( 0 );
 
 
lost = 0;
lost = 0;
p = x + NI-1;
p = x + NI-1;
 
 
if( sc < 0 )
if( sc < 0 )
        {
        {
        sc = -sc;
        sc = -sc;
        while( sc >= 16 )
        while( sc >= 16 )
                {
                {
                lost |= *p;     /* remember lost bits */
                lost |= *p;     /* remember lost bits */
                eshdn6(x);
                eshdn6(x);
                sc -= 16;
                sc -= 16;
                }
                }
 
 
        while( sc >= 8 )
        while( sc >= 8 )
                {
                {
                lost |= *p & 0xff;
                lost |= *p & 0xff;
                eshdn8(x);
                eshdn8(x);
                sc -= 8;
                sc -= 8;
                }
                }
 
 
        while( sc > 0 )
        while( sc > 0 )
                {
                {
                lost |= *p & 1;
                lost |= *p & 1;
                eshdn1(x);
                eshdn1(x);
                sc -= 1;
                sc -= 1;
                }
                }
        }
        }
else
else
        {
        {
        while( sc >= 16 )
        while( sc >= 16 )
                {
                {
                eshup6(x);
                eshup6(x);
                sc -= 16;
                sc -= 16;
                }
                }
 
 
        while( sc >= 8 )
        while( sc >= 8 )
                {
                {
                eshup8(x);
                eshup8(x);
                sc -= 8;
                sc -= 8;
                }
                }
 
 
        while( sc > 0 )
        while( sc > 0 )
                {
                {
                eshup1(x);
                eshup1(x);
                sc -= 1;
                sc -= 1;
                }
                }
        }
        }
if( lost )
if( lost )
        lost = 1;
        lost = 1;
return( (int )lost );
return( (int )lost );
}
}
 
 
 
 
 
 
/*
/*
;       normalize
;       normalize
;
;
; Shift normalizes the significand area pointed to by argument
; Shift normalizes the significand area pointed to by argument
; shift count (up = positive) is returned.
; shift count (up = positive) is returned.
*/
*/
static int enormlz(short unsigned int *x)
static int enormlz(short unsigned int *x)
{
{
register unsigned short *p;
register unsigned short *p;
int sc;
int sc;
 
 
sc = 0;
sc = 0;
p = &x[M];
p = &x[M];
if( *p != 0 )
if( *p != 0 )
        goto normdn;
        goto normdn;
++p;
++p;
if( *p & 0x8000 )
if( *p & 0x8000 )
        return( 0 );     /* already normalized */
        return( 0 );     /* already normalized */
while( *p == 0 )
while( *p == 0 )
        {
        {
        eshup6(x);
        eshup6(x);
        sc += 16;
        sc += 16;
/* With guard word, there are NBITS+16 bits available.
/* With guard word, there are NBITS+16 bits available.
 * return true if all are zero.
 * return true if all are zero.
 */
 */
        if( sc > NBITS )
        if( sc > NBITS )
                return( sc );
                return( sc );
        }
        }
/* see if high byte is zero */
/* see if high byte is zero */
while( (*p & 0xff00) == 0 )
while( (*p & 0xff00) == 0 )
        {
        {
        eshup8(x);
        eshup8(x);
        sc += 8;
        sc += 8;
        }
        }
/* now shift 1 bit at a time */
/* now shift 1 bit at a time */
while( (*p  & 0x8000) == 0)
while( (*p  & 0x8000) == 0)
        {
        {
        eshup1(x);
        eshup1(x);
        sc += 1;
        sc += 1;
        if( sc > (NBITS+16) )
        if( sc > (NBITS+16) )
                {
                {
                mtherr( "enormlz", UNDERFLOW );
                mtherr( "enormlz", UNDERFLOW );
                return( sc );
                return( sc );
                }
                }
        }
        }
return( sc );
return( sc );
 
 
/* Normalize by shifting down out of the high guard word
/* Normalize by shifting down out of the high guard word
   of the significand */
   of the significand */
normdn:
normdn:
 
 
if( *p & 0xff00 )
if( *p & 0xff00 )
        {
        {
        eshdn8(x);
        eshdn8(x);
        sc -= 8;
        sc -= 8;
        }
        }
while( *p != 0 )
while( *p != 0 )
        {
        {
        eshdn1(x);
        eshdn1(x);
        sc -= 1;
        sc -= 1;
 
 
        if( sc < -NBITS )
        if( sc < -NBITS )
                {
                {
                mtherr( "enormlz", OVERFLOW );
                mtherr( "enormlz", OVERFLOW );
                return( sc );
                return( sc );
                }
                }
        }
        }
return( sc );
return( sc );
}
}
 
 
 
 
 
 
 
 
/* Convert e type number to decimal format ASCII string.
/* Convert e type number to decimal format ASCII string.
 * The constants are for 64 bit precision.
 * The constants are for 64 bit precision.
 */
 */
 
 
#define NTEN 12
#define NTEN 12
#define MAXP 4096
#define MAXP 4096
 
 
#if NE == 10
#if NE == 10
static unsigned short etens[NTEN + 1][NE] =
static unsigned short etens[NTEN + 1][NE] =
{
{
  {0x6576, 0x4a92, 0x804a, 0x153f,
  {0x6576, 0x4a92, 0x804a, 0x153f,
   0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,},    /* 10**4096 */
   0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,},    /* 10**4096 */
  {0x6a32, 0xce52, 0x329a, 0x28ce,
  {0x6a32, 0xce52, 0x329a, 0x28ce,
   0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,},    /* 10**2048 */
   0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,},    /* 10**2048 */
  {0x526c, 0x50ce, 0xf18b, 0x3d28,
  {0x526c, 0x50ce, 0xf18b, 0x3d28,
   0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
   0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
  {0x9c66, 0x58f8, 0xbc50, 0x5c54,
  {0x9c66, 0x58f8, 0xbc50, 0x5c54,
   0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
   0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
  {0x851e, 0xeab7, 0x98fe, 0x901b,
  {0x851e, 0xeab7, 0x98fe, 0x901b,
   0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
   0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
  {0x0235, 0x0137, 0x36b1, 0x336c,
  {0x0235, 0x0137, 0x36b1, 0x336c,
   0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
   0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
  {0x50f8, 0x25fb, 0xc76b, 0x6b71,
  {0x50f8, 0x25fb, 0xc76b, 0x6b71,
   0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
   0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
  {0x0000, 0x0000, 0x0000, 0x0000,
  {0x0000, 0x0000, 0x0000, 0x0000,
   0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
   0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
  {0x0000, 0x0000, 0x0000, 0x0000,
  {0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
   0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
  {0x0000, 0x0000, 0x0000, 0x0000,
  {0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
   0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
  {0x0000, 0x0000, 0x0000, 0x0000,
  {0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
   0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
  {0x0000, 0x0000, 0x0000, 0x0000,
  {0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
   0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
  {0x0000, 0x0000, 0x0000, 0x0000,
  {0x0000, 0x0000, 0x0000, 0x0000,
   0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,},    /* 10**1 */
   0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,},    /* 10**1 */
};
};
 
 
static unsigned short emtens[NTEN + 1][NE] =
static unsigned short emtens[NTEN + 1][NE] =
{
{
  {0x2030, 0xcffc, 0xa1c3, 0x8123,
  {0x2030, 0xcffc, 0xa1c3, 0x8123,
   0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,},    /* 10**-4096 */
   0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,},    /* 10**-4096 */
  {0x8264, 0xd2cb, 0xf2ea, 0x12d4,
  {0x8264, 0xd2cb, 0xf2ea, 0x12d4,
   0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,},    /* 10**-2048 */
   0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,},    /* 10**-2048 */
  {0xf53f, 0xf698, 0x6bd3, 0x0158,
  {0xf53f, 0xf698, 0x6bd3, 0x0158,
   0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
   0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
  {0xe731, 0x04d4, 0xe3f2, 0xd332,
  {0xe731, 0x04d4, 0xe3f2, 0xd332,
   0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
   0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
  {0xa23e, 0x5308, 0xfefb, 0x1155,
  {0xa23e, 0x5308, 0xfefb, 0x1155,
   0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
   0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
  {0xe26d, 0xdbde, 0xd05d, 0xb3f6,
  {0xe26d, 0xdbde, 0xd05d, 0xb3f6,
   0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
   0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
  {0x2a20, 0x6224, 0x47b3, 0x98d7,
  {0x2a20, 0x6224, 0x47b3, 0x98d7,
   0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
   0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
  {0x0b5b, 0x4af2, 0xa581, 0x18ed,
  {0x0b5b, 0x4af2, 0xa581, 0x18ed,
   0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
   0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
  {0xbf71, 0xa9b3, 0x7989, 0xbe68,
  {0xbf71, 0xa9b3, 0x7989, 0xbe68,
   0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
   0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
  {0x3d4d, 0x7c3d, 0x36ba, 0x0d2b,
  {0x3d4d, 0x7c3d, 0x36ba, 0x0d2b,
   0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
   0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
  {0xc155, 0xa4a8, 0x404e, 0x6113,
  {0xc155, 0xa4a8, 0x404e, 0x6113,
   0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
   0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
  {0xd70a, 0x70a3, 0x0a3d, 0xa3d7,
  {0xd70a, 0x70a3, 0x0a3d, 0xa3d7,
   0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
   0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
  {0xcccd, 0xcccc, 0xcccc, 0xcccc,
  {0xcccd, 0xcccc, 0xcccc, 0xcccc,
   0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,},    /* 10**-1 */
   0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,},    /* 10**-1 */
};
};
#else
#else
static unsigned short etens[NTEN+1][NE] = {
static unsigned short etens[NTEN+1][NE] = {
{0xc94c,0x979a,0x8a20,0x5202,0xc460,0x7525,},/* 10**4096 */
{0xc94c,0x979a,0x8a20,0x5202,0xc460,0x7525,},/* 10**4096 */
{0xa74d,0x5de4,0xc53d,0x3b5d,0x9e8b,0x5a92,},/* 10**2048 */
{0xa74d,0x5de4,0xc53d,0x3b5d,0x9e8b,0x5a92,},/* 10**2048 */
{0x650d,0x0c17,0x8175,0x7586,0xc976,0x4d48,},
{0x650d,0x0c17,0x8175,0x7586,0xc976,0x4d48,},
{0xcc65,0x91c6,0xa60e,0xa0ae,0xe319,0x46a3,},
{0xcc65,0x91c6,0xa60e,0xa0ae,0xe319,0x46a3,},
{0xddbc,0xde8d,0x9df9,0xebfb,0xaa7e,0x4351,},
{0xddbc,0xde8d,0x9df9,0xebfb,0xaa7e,0x4351,},
{0xc66f,0x8cdf,0x80e9,0x47c9,0x93ba,0x41a8,},
{0xc66f,0x8cdf,0x80e9,0x47c9,0x93ba,0x41a8,},
{0x3cbf,0xa6d5,0xffcf,0x1f49,0xc278,0x40d3,},
{0x3cbf,0xa6d5,0xffcf,0x1f49,0xc278,0x40d3,},
{0xf020,0xb59d,0x2b70,0xada8,0x9dc5,0x4069,},
{0xf020,0xb59d,0x2b70,0xada8,0x9dc5,0x4069,},
{0x0000,0x0000,0x0400,0xc9bf,0x8e1b,0x4034,},
{0x0000,0x0000,0x0400,0xc9bf,0x8e1b,0x4034,},
{0x0000,0x0000,0x0000,0x2000,0xbebc,0x4019,},
{0x0000,0x0000,0x0000,0x2000,0xbebc,0x4019,},
{0x0000,0x0000,0x0000,0x0000,0x9c40,0x400c,},
{0x0000,0x0000,0x0000,0x0000,0x9c40,0x400c,},
{0x0000,0x0000,0x0000,0x0000,0xc800,0x4005,},
{0x0000,0x0000,0x0000,0x0000,0xc800,0x4005,},
{0x0000,0x0000,0x0000,0x0000,0xa000,0x4002,}, /* 10**1 */
{0x0000,0x0000,0x0000,0x0000,0xa000,0x4002,}, /* 10**1 */
};
};
 
 
static unsigned short emtens[NTEN+1][NE] = {
static unsigned short emtens[NTEN+1][NE] = {
{0x2de4,0x9fde,0xd2ce,0x04c8,0xa6dd,0x0ad8,}, /* 10**-4096 */
{0x2de4,0x9fde,0xd2ce,0x04c8,0xa6dd,0x0ad8,}, /* 10**-4096 */
{0x4925,0x2de4,0x3436,0x534f,0xceae,0x256b,}, /* 10**-2048 */
{0x4925,0x2de4,0x3436,0x534f,0xceae,0x256b,}, /* 10**-2048 */
{0x87a6,0xc0bd,0xda57,0x82a5,0xa2a6,0x32b5,},
{0x87a6,0xc0bd,0xda57,0x82a5,0xa2a6,0x32b5,},
{0x7133,0xd21c,0xdb23,0xee32,0x9049,0x395a,},
{0x7133,0xd21c,0xdb23,0xee32,0x9049,0x395a,},
{0xfa91,0x1939,0x637a,0x4325,0xc031,0x3cac,},
{0xfa91,0x1939,0x637a,0x4325,0xc031,0x3cac,},
{0xac7d,0xe4a0,0x64bc,0x467c,0xddd0,0x3e55,},
{0xac7d,0xe4a0,0x64bc,0x467c,0xddd0,0x3e55,},
{0x3f24,0xe9a5,0xa539,0xea27,0xa87f,0x3f2a,},
{0x3f24,0xe9a5,0xa539,0xea27,0xa87f,0x3f2a,},
{0x67de,0x94ba,0x4539,0x1ead,0xcfb1,0x3f94,},
{0x67de,0x94ba,0x4539,0x1ead,0xcfb1,0x3f94,},
{0x4c2f,0xe15b,0xc44d,0x94be,0xe695,0x3fc9,},
{0x4c2f,0xe15b,0xc44d,0x94be,0xe695,0x3fc9,},
{0xfdc2,0xcefc,0x8461,0x7711,0xabcc,0x3fe4,},
{0xfdc2,0xcefc,0x8461,0x7711,0xabcc,0x3fe4,},
{0xd3c3,0x652b,0xe219,0x1758,0xd1b7,0x3ff1,},
{0xd3c3,0x652b,0xe219,0x1758,0xd1b7,0x3ff1,},
{0x3d71,0xd70a,0x70a3,0x0a3d,0xa3d7,0x3ff8,},
{0x3d71,0xd70a,0x70a3,0x0a3d,0xa3d7,0x3ff8,},
{0xcccd,0xcccc,0xcccc,0xcccc,0xcccc,0x3ffb,}, /* 10**-1 */
{0xcccd,0xcccc,0xcccc,0xcccc,0xcccc,0x3ffb,}, /* 10**-1 */
};
};
#endif
#endif
 
 
 
 
 
 
/* ASCII string outputs for unix */
/* ASCII string outputs for unix */
 
 
 
 
#if 0
#if 0
void _IO_ldtostr(x, string, ndigs, flags, fmt)
void _IO_ldtostr(x, string, ndigs, flags, fmt)
long double *x;
long double *x;
char *string;
char *string;
int ndigs;
int ndigs;
int flags;
int flags;
char fmt;
char fmt;
{
{
unsigned short w[NI];
unsigned short w[NI];
char *t, *u;
char *t, *u;
LDPARMS rnd;
LDPARMS rnd;
LDPARMS *ldp = &rnd;
LDPARMS *ldp = &rnd;
 
 
rnd.rlast = -1;
rnd.rlast = -1;
rnd.rndprc = NBITS;
rnd.rndprc = NBITS;
 
 
if (sizeof(long double) == 16)
if (sizeof(long double) == 16)
  e113toe( (unsigned short *)x, w, ldp );
  e113toe( (unsigned short *)x, w, ldp );
else
else
  e64toe( (unsigned short *)x, w, ldp );
  e64toe( (unsigned short *)x, w, ldp );
 
 
etoasc( w, string, ndigs, -1, ldp );
etoasc( w, string, ndigs, -1, ldp );
if( ndigs == 0 && flags == 0 )
if( ndigs == 0 && flags == 0 )
        {
        {
        /* Delete the decimal point unless alternate format.  */
        /* Delete the decimal point unless alternate format.  */
        t = string;
        t = string;
        while( *t != '.' )
        while( *t != '.' )
                ++t;
                ++t;
        u = t +  1;
        u = t +  1;
        while( *t != '\0' )
        while( *t != '\0' )
                *t++ = *u++;
                *t++ = *u++;
        }
        }
if (*string == ' ')
if (*string == ' ')
        {
        {
        t = string;
        t = string;
        u = t + 1;
        u = t + 1;
        while( *t != '\0' )
        while( *t != '\0' )
                *t++ = *u++;
                *t++ = *u++;
        }
        }
if (fmt == 'E')
if (fmt == 'E')
        {
        {
        t = string;
        t = string;
        while( *t != 'e' )
        while( *t != 'e' )
                ++t;
                ++t;
        *t = 'E';
        *t = 'E';
        }
        }
}
}
 
 
#endif
#endif
 
 
/* This routine will not return more than NDEC+1 digits. */
/* This routine will not return more than NDEC+1 digits. */
 
 
char *
char *
_ldtoa_r (struct _reent *ptr, long double d, int mode, int ndigits, int *decpt,
_ldtoa_r (struct _reent *ptr, long double d, int mode, int ndigits, int *decpt,
          int *sign, char **rve)
          int *sign, char **rve)
{
{
unsigned short e[NI];
unsigned short e[NI];
char *s, *p;
char *s, *p;
int i, j, k;
int i, j, k;
int orig_ndigits;
int orig_ndigits;
LDPARMS rnd;
LDPARMS rnd;
LDPARMS *ldp = &rnd;
LDPARMS *ldp = &rnd;
char *outstr;
char *outstr;
char outbuf[NDEC + MAX_EXP_DIGITS + 10];
char outbuf[NDEC + MAX_EXP_DIGITS + 10];
union uconv du;
union uconv du;
du.d = d;
du.d = d;
 
 
orig_ndigits = ndigits;
orig_ndigits = ndigits;
rnd.rlast = -1;
rnd.rlast = -1;
rnd.rndprc = NBITS;
rnd.rndprc = NBITS;
 
 
  _REENT_CHECK_MP(ptr);
  _REENT_CHECK_MP(ptr);
 
 
/* reentrancy addition to use mprec storage pool */
/* reentrancy addition to use mprec storage pool */
if (_REENT_MP_RESULT(ptr))
if (_REENT_MP_RESULT(ptr))
  {
  {
    _REENT_MP_RESULT(ptr)->_k = _REENT_MP_RESULT_K(ptr);
    _REENT_MP_RESULT(ptr)->_k = _REENT_MP_RESULT_K(ptr);
    _REENT_MP_RESULT(ptr)->_maxwds = 1 << _REENT_MP_RESULT_K(ptr);
    _REENT_MP_RESULT(ptr)->_maxwds = 1 << _REENT_MP_RESULT_K(ptr);
    Bfree (ptr, _REENT_MP_RESULT(ptr));
    Bfree (ptr, _REENT_MP_RESULT(ptr));
    _REENT_MP_RESULT(ptr) = 0;
    _REENT_MP_RESULT(ptr) = 0;
  }
  }
 
 
#if LDBL_MANT_DIG == 24
#if LDBL_MANT_DIG == 24
e24toe( &du.pe, e, ldp );
e24toe( &du.pe, e, ldp );
#elif LDBL_MANT_DIG == 53
#elif LDBL_MANT_DIG == 53
e53toe( &du.pe, e, ldp );
e53toe( &du.pe, e, ldp );
#elif LDBL_MANT_DIG == 64
#elif LDBL_MANT_DIG == 64
e64toe( &du.pe, e, ldp );
e64toe( &du.pe, e, ldp );
#else
#else
e113toe( &du.pe, e, ldp );
e113toe( &du.pe, e, ldp );
#endif
#endif
 
 
if( eisneg(e) )
if( eisneg(e) )
        *sign = 1;
        *sign = 1;
else
else
        *sign = 0;
        *sign = 0;
/* Mode 3 is "f" format.  */
/* Mode 3 is "f" format.  */
if( mode != 3 )
if( mode != 3 )
        ndigits -= 1;
        ndigits -= 1;
/* Mode 0 is for %.999 format, which is supposed to give a
/* Mode 0 is for %.999 format, which is supposed to give a
   minimum length string that will convert back to the same binary value.
   minimum length string that will convert back to the same binary value.
   For now, just ask for 20 digits which is enough but sometimes too many.  */
   For now, just ask for 20 digits which is enough but sometimes too many.  */
if( mode == 0 )
if( mode == 0 )
        ndigits = 20;
        ndigits = 20;
 
 
/* This sanity limit must agree with the corresponding one in etoasc, to
/* This sanity limit must agree with the corresponding one in etoasc, to
   keep straight the returned value of outexpon.  */
   keep straight the returned value of outexpon.  */
if( ndigits > NDEC )
if( ndigits > NDEC )
        ndigits = NDEC;
        ndigits = NDEC;
 
 
etoasc( e, outbuf, ndigits, mode, ldp );
etoasc( e, outbuf, ndigits, mode, ldp );
s =  outbuf;
s =  outbuf;
if( eisinf(e) || eisnan(e) )
if( eisinf(e) || eisnan(e) )
        {
        {
        *decpt = 9999;
        *decpt = 9999;
        goto stripspaces;
        goto stripspaces;
        }
        }
*decpt = ldp->outexpon + 1;
*decpt = ldp->outexpon + 1;
 
 
/* Transform the string returned by etoasc into what the caller wants.  */
/* Transform the string returned by etoasc into what the caller wants.  */
 
 
/* Look for decimal point and delete it from the string. */
/* Look for decimal point and delete it from the string. */
s = outbuf;
s = outbuf;
while( *s != '\0' )
while( *s != '\0' )
        {
        {
        if( *s == '.' )
        if( *s == '.' )
               goto yesdecpt;
               goto yesdecpt;
        ++s;
        ++s;
        }
        }
goto nodecpt;
goto nodecpt;
 
 
yesdecpt:
yesdecpt:
 
 
/* Delete the decimal point.  */
/* Delete the decimal point.  */
while( *s != '\0' )
while( *s != '\0' )
        {
        {
        *s = *(s+1);
        *s = *(s+1);
        ++s;
        ++s;
        }
        }
 
 
nodecpt:
nodecpt:
 
 
/* Back up over the exponent field. */
/* Back up over the exponent field. */
while( *s != 'E' && s > outbuf)
while( *s != 'E' && s > outbuf)
        --s;
        --s;
*s = '\0';
*s = '\0';
 
 
stripspaces:
stripspaces:
 
 
/* Strip leading spaces and sign. */
/* Strip leading spaces and sign. */
p = outbuf;
p = outbuf;
while( *p == ' ' || *p == '-')
while( *p == ' ' || *p == '-')
        ++p;
        ++p;
 
 
/* Find new end of string.  */
/* Find new end of string.  */
s = outbuf;
s = outbuf;
while( (*s++ = *p++) != '\0' )
while( (*s++ = *p++) != '\0' )
        ;
        ;
--s;
--s;
 
 
/* Strip trailing zeros.  */
/* Strip trailing zeros.  */
if( mode == 2 )
if( mode == 2 )
        k = 1;
        k = 1;
else if( ndigits > ldp->outexpon )
else if( ndigits > ldp->outexpon )
        k = ndigits;
        k = ndigits;
else
else
        k = ldp->outexpon;
        k = ldp->outexpon;
 
 
while( *(s-1) == '0' && ((s - outbuf) > k))
while( *(s-1) == '0' && ((s - outbuf) > k))
        *(--s) = '\0';
        *(--s) = '\0';
 
 
/* In f format, flush small off-scale values to zero.
/* In f format, flush small off-scale values to zero.
   Rounding has been taken care of by etoasc. */
   Rounding has been taken care of by etoasc. */
if( mode == 3 && ((ndigits + ldp->outexpon) < 0))
if( mode == 3 && ((ndigits + ldp->outexpon) < 0))
        {
        {
        s = outbuf;
        s = outbuf;
        *s = '\0';
        *s = '\0';
        *decpt = 0;
        *decpt = 0;
        }
        }
 
 
/* reentrancy addition to use mprec storage pool */
/* reentrancy addition to use mprec storage pool */
/* we want to have enough space to hold the formatted result */
/* we want to have enough space to hold the formatted result */
 
 
if (mode == 3) /* f format, account for sign + dec digits + decpt + frac */
if (mode == 3) /* f format, account for sign + dec digits + decpt + frac */
  i = *decpt + orig_ndigits + 3;
  i = *decpt + orig_ndigits + 3;
else /* account for sign + max precision digs + E + exp sign + exponent */
else /* account for sign + max precision digs + E + exp sign + exponent */
  i = orig_ndigits + MAX_EXP_DIGITS + 4;
  i = orig_ndigits + MAX_EXP_DIGITS + 4;
 
 
j = sizeof (__ULong);
j = sizeof (__ULong);
for (_REENT_MP_RESULT_K(ptr) = 0; sizeof (_Bigint) - sizeof (__ULong) + j <= i; j <<= 1)
for (_REENT_MP_RESULT_K(ptr) = 0; sizeof (_Bigint) - sizeof (__ULong) + j <= i; j <<= 1)
  _REENT_MP_RESULT_K(ptr)++;
  _REENT_MP_RESULT_K(ptr)++;
_REENT_MP_RESULT(ptr) = Balloc (ptr, _REENT_MP_RESULT_K(ptr));
_REENT_MP_RESULT(ptr) = Balloc (ptr, _REENT_MP_RESULT_K(ptr));
 
 
/* Copy from internal temporary buffer to permanent buffer.  */
/* Copy from internal temporary buffer to permanent buffer.  */
outstr = (char *)_REENT_MP_RESULT(ptr);
outstr = (char *)_REENT_MP_RESULT(ptr);
strcpy (outstr, outbuf);
strcpy (outstr, outbuf);
 
 
if( rve )
if( rve )
        *rve = outstr + (s - outbuf);
        *rve = outstr + (s - outbuf);
 
 
return outstr;
return outstr;
}
}
 
 
/* Routine used to tell if long double is NaN or Infinity or regular number.
/* Routine used to tell if long double is NaN or Infinity or regular number.
   Returns:  0 = regular number
   Returns:  0 = regular number
             1 = Nan
             1 = Nan
             2 = Infinity
             2 = Infinity
*/
*/
int
int
_ldcheck (long double *d)
_ldcheck (long double *d)
{
{
unsigned short e[NI];
unsigned short e[NI];
LDPARMS rnd;
LDPARMS rnd;
LDPARMS *ldp = &rnd;
LDPARMS *ldp = &rnd;
 
 
union uconv du;
union uconv du;
 
 
rnd.rlast = -1;
rnd.rlast = -1;
rnd.rndprc = NBITS;
rnd.rndprc = NBITS;
du.d = *d;
du.d = *d;
#if LDBL_MANT_DIG == 24
#if LDBL_MANT_DIG == 24
e24toe( &du.pe, e, ldp );
e24toe( &du.pe, e, ldp );
#elif LDBL_MANT_DIG == 53
#elif LDBL_MANT_DIG == 53
e53toe( &du.pe, e, ldp );
e53toe( &du.pe, e, ldp );
#elif LDBL_MANT_DIG == 64
#elif LDBL_MANT_DIG == 64
e64toe( &du.pe, e, ldp );
e64toe( &du.pe, e, ldp );
#else
#else
e113toe( &du.pe, e, ldp );
e113toe( &du.pe, e, ldp );
#endif
#endif
 
 
if( (e[NE-1] & 0x7fff) == 0x7fff )
if( (e[NE-1] & 0x7fff) == 0x7fff )
        {
        {
#ifdef NANS
#ifdef NANS
        if( eisnan(e) )
        if( eisnan(e) )
                return( 1 );
                return( 1 );
#endif
#endif
        return( 2 );
        return( 2 );
        }
        }
else
else
        return( 0 );
        return( 0 );
} /* _ldcheck */
} /* _ldcheck */
 
 
static void etoasc(short unsigned int *x, char *string, int ndigits, int outformat, LDPARMS *ldp)
static void etoasc(short unsigned int *x, char *string, int ndigits, int outformat, LDPARMS *ldp)
{
{
long digit;
long digit;
unsigned short y[NI], t[NI], u[NI], w[NI];
unsigned short y[NI], t[NI], u[NI], w[NI];
unsigned short *p, *r, *ten;
unsigned short *p, *r, *ten;
unsigned short sign;
unsigned short sign;
int i, j, k, expon, rndsav, ndigs;
int i, j, k, expon, rndsav, ndigs;
char *s, *ss;
char *s, *ss;
unsigned short m;
unsigned short m;
unsigned short *equot = ldp->equot;
unsigned short *equot = ldp->equot;
 
 
ndigs = ndigits;
ndigs = ndigits;
rndsav = ldp->rndprc;
rndsav = ldp->rndprc;
#ifdef NANS
#ifdef NANS
if( eisnan(x) )
if( eisnan(x) )
        {
        {
        sprintf( string, " NaN " );
        sprintf( string, " NaN " );
        expon = 9999;
        expon = 9999;
        goto bxit;
        goto bxit;
        }
        }
#endif
#endif
ldp->rndprc = NBITS;            /* set to full precision */
ldp->rndprc = NBITS;            /* set to full precision */
emov( x, y ); /* retain external format */
emov( x, y ); /* retain external format */
if( y[NE-1] & 0x8000 )
if( y[NE-1] & 0x8000 )
        {
        {
        sign = 0xffff;
        sign = 0xffff;
        y[NE-1] &= 0x7fff;
        y[NE-1] &= 0x7fff;
        }
        }
else
else
        {
        {
        sign = 0;
        sign = 0;
        }
        }
expon = 0;
expon = 0;
ten = &etens[NTEN][0];
ten = &etens[NTEN][0];
emov( eone, t );
emov( eone, t );
/* Test for zero exponent */
/* Test for zero exponent */
if( y[NE-1] == 0 )
if( y[NE-1] == 0 )
        {
        {
        for( k=0; k<NE-1; k++ )
        for( k=0; k<NE-1; k++ )
                {
                {
                if( y[k] != 0 )
                if( y[k] != 0 )
                        goto tnzro; /* denormalized number */
                        goto tnzro; /* denormalized number */
                }
                }
        goto isone; /* legal all zeros */
        goto isone; /* legal all zeros */
        }
        }
tnzro:
tnzro:
 
 
/* Test for infinity.
/* Test for infinity.
 */
 */
if( y[NE-1] == 0x7fff )
if( y[NE-1] == 0x7fff )
        {
        {
        if( sign )
        if( sign )
                sprintf( string, " -Infinity " );
                sprintf( string, " -Infinity " );
        else
        else
                sprintf( string, " Infinity " );
                sprintf( string, " Infinity " );
        expon = 9999;
        expon = 9999;
        goto bxit;
        goto bxit;
        }
        }
 
 
/* Test for exponent nonzero but significand denormalized.
/* Test for exponent nonzero but significand denormalized.
 * This is an error condition.
 * This is an error condition.
 */
 */
if( (y[NE-1] != 0) && ((y[NE-2] & 0x8000) == 0) )
if( (y[NE-1] != 0) && ((y[NE-2] & 0x8000) == 0) )
        {
        {
        mtherr( "etoasc", DOMAIN );
        mtherr( "etoasc", DOMAIN );
        sprintf( string, "NaN" );
        sprintf( string, "NaN" );
        expon = 9999;
        expon = 9999;
        goto bxit;
        goto bxit;
        }
        }
 
 
/* Compare to 1.0 */
/* Compare to 1.0 */
i = ecmp( eone, y );
i = ecmp( eone, y );
if( i == 0 )
if( i == 0 )
        goto isone;
        goto isone;
 
 
if( i < 0 )
if( i < 0 )
        { /* Number is greater than 1 */
        { /* Number is greater than 1 */
/* Convert significand to an integer and strip trailing decimal zeros. */
/* Convert significand to an integer and strip trailing decimal zeros. */
        emov( y, u );
        emov( y, u );
        u[NE-1] = EXONE + NBITS - 1;
        u[NE-1] = EXONE + NBITS - 1;
 
 
        p = &etens[NTEN-4][0];
        p = &etens[NTEN-4][0];
        m = 16;
        m = 16;
do
do
        {
        {
        ediv( p, u, t, ldp );
        ediv( p, u, t, ldp );
        efloor( t, w, ldp );
        efloor( t, w, ldp );
        for( j=0; j<NE-1; j++ )
        for( j=0; j<NE-1; j++ )
                {
                {
                if( t[j] != w[j] )
                if( t[j] != w[j] )
                        goto noint;
                        goto noint;
                }
                }
        emov( t, u );
        emov( t, u );
        expon += (int )m;
        expon += (int )m;
noint:
noint:
        p += NE;
        p += NE;
        m >>= 1;
        m >>= 1;
        }
        }
while( m != 0 );
while( m != 0 );
 
 
/* Rescale from integer significand */
/* Rescale from integer significand */
        u[NE-1] += y[NE-1] - (unsigned int )(EXONE + NBITS - 1);
        u[NE-1] += y[NE-1] - (unsigned int )(EXONE + NBITS - 1);
        emov( u, y );
        emov( u, y );
/* Find power of 10 */
/* Find power of 10 */
        emov( eone, t );
        emov( eone, t );
        m = MAXP;
        m = MAXP;
        p = &etens[0][0];
        p = &etens[0][0];
        while( ecmp( ten, u ) <= 0 )
        while( ecmp( ten, u ) <= 0 )
                {
                {
                if( ecmp( p, u ) <= 0 )
                if( ecmp( p, u ) <= 0 )
                        {
                        {
                        ediv( p, u, u, ldp );
                        ediv( p, u, u, ldp );
                        emul( p, t, t, ldp );
                        emul( p, t, t, ldp );
                        expon += (int )m;
                        expon += (int )m;
                        }
                        }
                m >>= 1;
                m >>= 1;
                if( m == 0 )
                if( m == 0 )
                        break;
                        break;
                p += NE;
                p += NE;
                }
                }
        }
        }
else
else
        { /* Number is less than 1.0 */
        { /* Number is less than 1.0 */
/* Pad significand with trailing decimal zeros. */
/* Pad significand with trailing decimal zeros. */
        if( y[NE-1] == 0 )
        if( y[NE-1] == 0 )
                {
                {
                while( (y[NE-2] & 0x8000) == 0 )
                while( (y[NE-2] & 0x8000) == 0 )
                        {
                        {
                        emul( ten, y, y, ldp );
                        emul( ten, y, y, ldp );
                        expon -= 1;
                        expon -= 1;
                        }
                        }
                }
                }
        else
        else
                {
                {
                emovi( y, w );
                emovi( y, w );
                for( i=0; i<NDEC+1; i++ )
                for( i=0; i<NDEC+1; i++ )
                        {
                        {
                        if( (w[NI-1] & 0x7) != 0 )
                        if( (w[NI-1] & 0x7) != 0 )
                                break;
                                break;
/* multiply by 10 */
/* multiply by 10 */
                        emovz( w, u );
                        emovz( w, u );
                        eshdn1( u );
                        eshdn1( u );
                        eshdn1( u );
                        eshdn1( u );
                        eaddm( w, u );
                        eaddm( w, u );
                        u[1] += 3;
                        u[1] += 3;
                        while( u[2] != 0 )
                        while( u[2] != 0 )
                                {
                                {
                                eshdn1(u);
                                eshdn1(u);
                                u[1] += 1;
                                u[1] += 1;
                                }
                                }
                        if( u[NI-1] != 0 )
                        if( u[NI-1] != 0 )
                                break;
                                break;
                        if( eone[NE-1] <= u[1] )
                        if( eone[NE-1] <= u[1] )
                                break;
                                break;
                        emovz( u, w );
                        emovz( u, w );
                        expon -= 1;
                        expon -= 1;
                        }
                        }
                emovo( w, y, ldp );
                emovo( w, y, ldp );
                }
                }
        k = -MAXP;
        k = -MAXP;
        p = &emtens[0][0];
        p = &emtens[0][0];
        r = &etens[0][0];
        r = &etens[0][0];
        emov( y, w );
        emov( y, w );
        emov( eone, t );
        emov( eone, t );
        while( ecmp( eone, w ) > 0 )
        while( ecmp( eone, w ) > 0 )
                {
                {
                if( ecmp( p, w ) >= 0 )
                if( ecmp( p, w ) >= 0 )
                        {
                        {
                        emul( r, w, w, ldp );
                        emul( r, w, w, ldp );
                        emul( r, t, t, ldp );
                        emul( r, t, t, ldp );
                        expon += k;
                        expon += k;
                        }
                        }
                k /= 2;
                k /= 2;
                if( k == 0 )
                if( k == 0 )
                        break;
                        break;
                p += NE;
                p += NE;
                r += NE;
                r += NE;
                }
                }
        ediv( t, eone, t, ldp );
        ediv( t, eone, t, ldp );
        }
        }
isone:
isone:
/* Find the first (leading) digit. */
/* Find the first (leading) digit. */
emovi( t, w );
emovi( t, w );
emovz( w, t );
emovz( w, t );
emovi( y, w );
emovi( y, w );
emovz( w, y );
emovz( w, y );
eiremain( t, y, ldp );
eiremain( t, y, ldp );
digit = equot[NI-1];
digit = equot[NI-1];
while( (digit == 0) && (ecmp(y,ezero) != 0) )
while( (digit == 0) && (ecmp(y,ezero) != 0) )
        {
        {
        eshup1( y );
        eshup1( y );
        emovz( y, u );
        emovz( y, u );
        eshup1( u );
        eshup1( u );
        eshup1( u );
        eshup1( u );
        eaddm( u, y );
        eaddm( u, y );
        eiremain( t, y, ldp );
        eiremain( t, y, ldp );
        digit = equot[NI-1];
        digit = equot[NI-1];
        expon -= 1;
        expon -= 1;
        }
        }
s = string;
s = string;
if( sign )
if( sign )
        *s++ = '-';
        *s++ = '-';
else
else
        *s++ = ' ';
        *s++ = ' ';
/* Examine number of digits requested by caller. */
/* Examine number of digits requested by caller. */
if( outformat == 3 )
if( outformat == 3 )
        ndigs += expon;
        ndigs += expon;
/*
/*
else if( ndigs < 0 )
else if( ndigs < 0 )
        ndigs = 0;
        ndigs = 0;
*/
*/
if( ndigs > NDEC )
if( ndigs > NDEC )
        ndigs = NDEC;
        ndigs = NDEC;
if( digit == 10 )
if( digit == 10 )
        {
        {
        *s++ = '1';
        *s++ = '1';
        *s++ = '.';
        *s++ = '.';
        if( ndigs > 0 )
        if( ndigs > 0 )
                {
                {
                *s++ = '0';
                *s++ = '0';
                ndigs -= 1;
                ndigs -= 1;
                }
                }
        expon += 1;
        expon += 1;
        if( ndigs < 0 )
        if( ndigs < 0 )
                {
                {
                ss = s;
                ss = s;
                goto doexp;
                goto doexp;
                }
                }
        }
        }
else
else
        {
        {
        *s++ = (char )digit + '0';
        *s++ = (char )digit + '0';
        *s++ = '.';
        *s++ = '.';
        }
        }
/* Generate digits after the decimal point. */
/* Generate digits after the decimal point. */
for( k=0; k<=ndigs; k++ )
for( k=0; k<=ndigs; k++ )
        {
        {
/* multiply current number by 10, without normalizing */
/* multiply current number by 10, without normalizing */
        eshup1( y );
        eshup1( y );
        emovz( y, u );
        emovz( y, u );
        eshup1( u );
        eshup1( u );
        eshup1( u );
        eshup1( u );
        eaddm( u, y );
        eaddm( u, y );
        eiremain( t, y, ldp );
        eiremain( t, y, ldp );
        *s++ = (char )equot[NI-1] + '0';
        *s++ = (char )equot[NI-1] + '0';
        }
        }
digit = equot[NI-1];
digit = equot[NI-1];
--s;
--s;
ss = s;
ss = s;
/* round off the ASCII string */
/* round off the ASCII string */
if( digit > 4 )
if( digit > 4 )
        {
        {
/* Test for critical rounding case in ASCII output. */
/* Test for critical rounding case in ASCII output. */
        if( digit == 5 )
        if( digit == 5 )
                {
                {
                emovo( y, t, ldp );
                emovo( y, t, ldp );
                if( ecmp(t,ezero) != 0 )
                if( ecmp(t,ezero) != 0 )
                        goto roun;      /* round to nearest */
                        goto roun;      /* round to nearest */
                if( ndigs < 0 || (*(s-1-(*(s-1)=='.')) & 1) == 0 )
                if( ndigs < 0 || (*(s-1-(*(s-1)=='.')) & 1) == 0 )
                        goto doexp;     /* round to even */
                        goto doexp;     /* round to even */
                }
                }
/* Round up and propagate carry-outs */
/* Round up and propagate carry-outs */
roun:
roun:
        --s;
        --s;
        k = *s & 0x7f;
        k = *s & 0x7f;
/* Carry out to most significant digit? */
/* Carry out to most significant digit? */
        if( ndigs < 0 )
        if( ndigs < 0 )
                {
                {
                /* This will print like "1E-6". */
                /* This will print like "1E-6". */
                *s = '1';
                *s = '1';
                expon += 1;
                expon += 1;
                goto doexp;
                goto doexp;
                }
                }
        else if( k == '.' )
        else if( k == '.' )
                {
                {
                --s;
                --s;
                k = *s;
                k = *s;
                k += 1;
                k += 1;
                *s = (char )k;
                *s = (char )k;
/* Most significant digit carries to 10? */
/* Most significant digit carries to 10? */
                if( k > '9' )
                if( k > '9' )
                        {
                        {
                        expon += 1;
                        expon += 1;
                        *s = '1';
                        *s = '1';
                        }
                        }
                goto doexp;
                goto doexp;
                }
                }
/* Round up and carry out from less significant digits */
/* Round up and carry out from less significant digits */
        k += 1;
        k += 1;
        *s = (char )k;
        *s = (char )k;
        if( k > '9' )
        if( k > '9' )
                {
                {
                *s = '0';
                *s = '0';
                goto roun;
                goto roun;
                }
                }
        }
        }
doexp:
doexp:
#ifdef __GO32__
#ifdef __GO32__
if( expon >= 0 )
if( expon >= 0 )
        sprintf( ss, "e+%02d", expon );
        sprintf( ss, "e+%02d", expon );
else
else
        sprintf( ss, "e-%02d", -expon );
        sprintf( ss, "e-%02d", -expon );
#else
#else
        sprintf( ss, "E%d", expon );
        sprintf( ss, "E%d", expon );
#endif
#endif
bxit:
bxit:
ldp->rndprc = rndsav;
ldp->rndprc = rndsav;
ldp->outexpon =  expon;
ldp->outexpon =  expon;
}
}
 
 
 
 
 
 
 
 
/*
/*
;                                                               ASCTOQ
;                                                               ASCTOQ
;               ASCTOQ.MAC              LATEST REV: 11 JAN 84
;               ASCTOQ.MAC              LATEST REV: 11 JAN 84
;                                       SLM, 3 JAN 78
;                                       SLM, 3 JAN 78
;
;
;       Convert ASCII string to quadruple precision floating point
;       Convert ASCII string to quadruple precision floating point
;
;
;               Numeric input is free field decimal number
;               Numeric input is free field decimal number
;               with max of 15 digits with or without
;               with max of 15 digits with or without
;               decimal point entered as ASCII from teletype.
;               decimal point entered as ASCII from teletype.
;       Entering E after the number followed by a second
;       Entering E after the number followed by a second
;       number causes the second number to be interpreted
;       number causes the second number to be interpreted
;       as a power of 10 to be multiplied by the first number
;       as a power of 10 to be multiplied by the first number
;       (i.e., "scientific" notation).
;       (i.e., "scientific" notation).
;
;
;       Usage:
;       Usage:
;               asctoq( string, q );
;               asctoq( string, q );
*/
*/
 
 
long double _strtold (char *s, char **se)
long double _strtold (char *s, char **se)
{
{
  union uconv x;
  union uconv x;
  LDPARMS rnd;
  LDPARMS rnd;
  LDPARMS *ldp = &rnd;
  LDPARMS *ldp = &rnd;
  int lenldstr;
  int lenldstr;
 
 
  rnd.rlast = -1;
  rnd.rlast = -1;
  rnd.rndprc = NBITS;
  rnd.rndprc = NBITS;
 
 
  lenldstr = asctoeg( s, &x.pe, LDBL_MANT_DIG, ldp );
  lenldstr = asctoeg( s, &x.pe, LDBL_MANT_DIG, ldp );
  if (se)
  if (se)
    *se = s + lenldstr;
    *se = s + lenldstr;
  return x.d;
  return x.d;
}
}
 
 
#define REASONABLE_LEN 200
#define REASONABLE_LEN 200
 
 
static int
static int
asctoeg(char *ss, short unsigned int *y, int oprec, LDPARMS *ldp)
asctoeg(char *ss, short unsigned int *y, int oprec, LDPARMS *ldp)
{
{
unsigned short yy[NI], xt[NI], tt[NI];
unsigned short yy[NI], xt[NI], tt[NI];
int esign, decflg, sgnflg, nexp, exp, prec, lost;
int esign, decflg, sgnflg, nexp, exp, prec, lost;
int k, trail, c, rndsav;
int k, trail, c, rndsav;
long lexp;
long lexp;
unsigned short nsign, *p;
unsigned short nsign, *p;
char *sp, *s, *lstr;
char *sp, *s, *lstr;
int lenldstr;
int lenldstr;
int mflag = 0;
int mflag = 0;
char tmpstr[REASONABLE_LEN];
char tmpstr[REASONABLE_LEN];
 
 
/* Copy the input string. */
/* Copy the input string. */
c = strlen (ss) + 2;
c = strlen (ss) + 2;
if (c <= REASONABLE_LEN)
if (c <= REASONABLE_LEN)
  lstr = tmpstr;
  lstr = tmpstr;
else
else
  {
  {
    lstr = (char *) calloc (c, 1);
    lstr = (char *) calloc (c, 1);
    mflag = 1;
    mflag = 1;
  }
  }
s = ss;
s = ss;
lenldstr = 0;
lenldstr = 0;
while( *s == ' ' ) /* skip leading spaces */
while( *s == ' ' ) /* skip leading spaces */
  {
  {
    ++s;
    ++s;
    ++lenldstr;
    ++lenldstr;
  }
  }
sp = lstr;
sp = lstr;
for( k=0; k<c; k++ )
for( k=0; k<c; k++ )
        {
        {
        if( (*sp++ = *s++) == '\0' )
        if( (*sp++ = *s++) == '\0' )
                break;
                break;
        }
        }
*sp = '\0';
*sp = '\0';
s = lstr;
s = lstr;
 
 
rndsav = ldp->rndprc;
rndsav = ldp->rndprc;
ldp->rndprc = NBITS; /* Set to full precision */
ldp->rndprc = NBITS; /* Set to full precision */
lost = 0;
lost = 0;
nsign = 0;
nsign = 0;
decflg = 0;
decflg = 0;
sgnflg = 0;
sgnflg = 0;
nexp = 0;
nexp = 0;
exp = 0;
exp = 0;
prec = 0;
prec = 0;
ecleaz( yy );
ecleaz( yy );
trail = 0;
trail = 0;
 
 
nxtcom:
nxtcom:
k = *s - '0';
k = *s - '0';
if( (k >= 0) && (k <= 9) )
if( (k >= 0) && (k <= 9) )
        {
        {
/* Ignore leading zeros */
/* Ignore leading zeros */
        if( (prec == 0) && (decflg == 0) && (k == 0) )
        if( (prec == 0) && (decflg == 0) && (k == 0) )
                goto donchr;
                goto donchr;
/* Identify and strip trailing zeros after the decimal point. */
/* Identify and strip trailing zeros after the decimal point. */
        if( (trail == 0) && (decflg != 0) )
        if( (trail == 0) && (decflg != 0) )
                {
                {
                sp = s;
                sp = s;
                while( (*sp >= '0') && (*sp <= '9') )
                while( (*sp >= '0') && (*sp <= '9') )
                        ++sp;
                        ++sp;
/* Check for syntax error */
/* Check for syntax error */
                c = *sp & 0x7f;
                c = *sp & 0x7f;
                if( (c != 'e') && (c != 'E') && (c != '\0')
                if( (c != 'e') && (c != 'E') && (c != '\0')
                        && (c != '\n') && (c != '\r') && (c != ' ')
                        && (c != '\n') && (c != '\r') && (c != ' ')
                        && (c != ',') )
                        && (c != ',') )
                        goto error;
                        goto error;
                --sp;
                --sp;
                while( *sp == '0' )
                while( *sp == '0' )
                        *sp-- = 'z';
                        *sp-- = 'z';
                trail = 1;
                trail = 1;
                if( *s == 'z' )
                if( *s == 'z' )
                        goto donchr;
                        goto donchr;
                }
                }
/* If enough digits were given to more than fill up the yy register,
/* If enough digits were given to more than fill up the yy register,
 * continuing until overflow into the high guard word yy[2]
 * continuing until overflow into the high guard word yy[2]
 * guarantees that there will be a roundoff bit at the top
 * guarantees that there will be a roundoff bit at the top
 * of the low guard word after normalization.
 * of the low guard word after normalization.
 */
 */
        if( yy[2] == 0 )
        if( yy[2] == 0 )
                {
                {
                if( decflg )
                if( decflg )
                        nexp += 1; /* count digits after decimal point */
                        nexp += 1; /* count digits after decimal point */
                eshup1( yy );   /* multiply current number by 10 */
                eshup1( yy );   /* multiply current number by 10 */
                emovz( yy, xt );
                emovz( yy, xt );
                eshup1( xt );
                eshup1( xt );
                eshup1( xt );
                eshup1( xt );
                eaddm( xt, yy );
                eaddm( xt, yy );
                ecleaz( xt );
                ecleaz( xt );
                xt[NI-2] = (unsigned short )k;
                xt[NI-2] = (unsigned short )k;
                eaddm( xt, yy );
                eaddm( xt, yy );
                }
                }
        else
        else
                {
                {
                /* Mark any lost non-zero digit.  */
                /* Mark any lost non-zero digit.  */
                lost |= k;
                lost |= k;
                /* Count lost digits before the decimal point.  */
                /* Count lost digits before the decimal point.  */
                if (decflg == 0)
                if (decflg == 0)
                        nexp -= 1;
                        nexp -= 1;
                }
                }
        prec += 1;
        prec += 1;
        goto donchr;
        goto donchr;
        }
        }
 
 
switch( *s )
switch( *s )
        {
        {
        case 'z':
        case 'z':
                break;
                break;
        case 'E':
        case 'E':
        case 'e':
        case 'e':
                goto expnt;
                goto expnt;
        case '.':       /* decimal point */
        case '.':       /* decimal point */
                if( decflg )
                if( decflg )
                        goto error;
                        goto error;
                ++decflg;
                ++decflg;
                break;
                break;
        case '-':
        case '-':
                nsign = 0xffff;
                nsign = 0xffff;
                if( sgnflg )
                if( sgnflg )
                        goto error;
                        goto error;
                ++sgnflg;
                ++sgnflg;
                break;
                break;
        case '+':
        case '+':
                if( sgnflg )
                if( sgnflg )
                        goto error;
                        goto error;
                ++sgnflg;
                ++sgnflg;
                break;
                break;
        case ',':
        case ',':
        case ' ':
        case ' ':
        case '\0':
        case '\0':
        case '\n':
        case '\n':
        case '\r':
        case '\r':
                goto daldone;
                goto daldone;
        case 'i':
        case 'i':
        case 'I':
        case 'I':
                goto infinite;
                goto infinite;
        default:
        default:
        error:
        error:
#ifdef NANS
#ifdef NANS
                enan( yy, NI*16 );
                enan( yy, NI*16 );
#else
#else
                mtherr( "asctoe", DOMAIN );
                mtherr( "asctoe", DOMAIN );
                ecleaz(yy);
                ecleaz(yy);
#endif
#endif
                goto aexit;
                goto aexit;
        }
        }
donchr:
donchr:
++s;
++s;
goto nxtcom;
goto nxtcom;
 
 
/* Exponent interpretation */
/* Exponent interpretation */
expnt:
expnt:
 
 
esign = 1;
esign = 1;
exp = 0;
exp = 0;
++s;
++s;
/* check for + or - */
/* check for + or - */
if( *s == '-' )
if( *s == '-' )
        {
        {
        esign = -1;
        esign = -1;
        ++s;
        ++s;
        }
        }
if( *s == '+' )
if( *s == '+' )
        ++s;
        ++s;
while( (*s >= '0') && (*s <= '9') )
while( (*s >= '0') && (*s <= '9') )
        {
        {
        exp *= 10;
        exp *= 10;
        exp += *s++ - '0';
        exp += *s++ - '0';
        if (exp > 4977)
        if (exp > 4977)
                {
                {
                if (esign < 0)
                if (esign < 0)
                        goto zero;
                        goto zero;
                else
                else
                        goto infinite;
                        goto infinite;
                }
                }
        }
        }
if( esign < 0 )
if( esign < 0 )
        exp = -exp;
        exp = -exp;
if( exp > 4932 )
if( exp > 4932 )
        {
        {
infinite:
infinite:
        ecleaz(yy);
        ecleaz(yy);
        yy[E] = 0x7fff;  /* infinity */
        yy[E] = 0x7fff;  /* infinity */
        goto aexit;
        goto aexit;
        }
        }
if( exp < -4977 )
if( exp < -4977 )
        {
        {
zero:
zero:
        ecleaz(yy);
        ecleaz(yy);
        goto aexit;
        goto aexit;
        }
        }
 
 
daldone:
daldone:
nexp = exp - nexp;
nexp = exp - nexp;
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
while( (nexp > 0) && (yy[2] == 0) )
while( (nexp > 0) && (yy[2] == 0) )
        {
        {
        emovz( yy, xt );
        emovz( yy, xt );
        eshup1( xt );
        eshup1( xt );
        eshup1( xt );
        eshup1( xt );
        eaddm( yy, xt );
        eaddm( yy, xt );
        eshup1( xt );
        eshup1( xt );
        if( xt[2] != 0 )
        if( xt[2] != 0 )
                break;
                break;
        nexp -= 1;
        nexp -= 1;
        emovz( xt, yy );
        emovz( xt, yy );
        }
        }
if( (k = enormlz(yy)) > NBITS )
if( (k = enormlz(yy)) > NBITS )
        {
        {
        ecleaz(yy);
        ecleaz(yy);
        goto aexit;
        goto aexit;
        }
        }
lexp = (EXONE - 1 + NBITS) - k;
lexp = (EXONE - 1 + NBITS) - k;
emdnorm( yy, lost, 0, lexp, 64, ldp );
emdnorm( yy, lost, 0, lexp, 64, ldp );
/* convert to external format */
/* convert to external format */
 
 
 
 
/* Multiply by 10**nexp.  If precision is 64 bits,
/* Multiply by 10**nexp.  If precision is 64 bits,
 * the maximum relative error incurred in forming 10**n
 * the maximum relative error incurred in forming 10**n
 * for 0 <= n <= 324 is 8.2e-20, at 10**180.
 * 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, the peak relative error is 1.4e-19 at 10**947.
 * For 0 >= n >= -999, it is -1.55e-19 at 10**-435.
 * For 0 >= n >= -999, it is -1.55e-19 at 10**-435.
 */
 */
lexp = yy[E];
lexp = yy[E];
if( nexp == 0 )
if( nexp == 0 )
        {
        {
        k = 0;
        k = 0;
        goto expdon;
        goto expdon;
        }
        }
esign = 1;
esign = 1;
if( nexp < 0 )
if( nexp < 0 )
        {
        {
        nexp = -nexp;
        nexp = -nexp;
        esign = -1;
        esign = -1;
        if( nexp > 4096 )
        if( nexp > 4096 )
                { /* Punt.  Can't handle this without 2 divides. */
                { /* Punt.  Can't handle this without 2 divides. */
                emovi( etens[0], tt );
                emovi( etens[0], tt );
                lexp -= tt[E];
                lexp -= tt[E];
                k = edivm( tt, yy, ldp );
                k = edivm( tt, yy, ldp );
                lexp += EXONE;
                lexp += EXONE;
                nexp -= 4096;
                nexp -= 4096;
                }
                }
        }
        }
p = &etens[NTEN][0];
p = &etens[NTEN][0];
emov( eone, xt );
emov( eone, xt );
exp = 1;
exp = 1;
do
do
        {
        {
        if( exp & nexp )
        if( exp & nexp )
                emul( p, xt, xt, ldp );
                emul( p, xt, xt, ldp );
        p -= NE;
        p -= NE;
        exp = exp + exp;
        exp = exp + exp;
        }
        }
while( exp <= MAXP );
while( exp <= MAXP );
 
 
emovi( xt, tt );
emovi( xt, tt );
if( esign < 0 )
if( esign < 0 )
        {
        {
        lexp -= tt[E];
        lexp -= tt[E];
        k = edivm( tt, yy, ldp );
        k = edivm( tt, yy, ldp );
        lexp += EXONE;
        lexp += EXONE;
        }
        }
else
else
        {
        {
        lexp += tt[E];
        lexp += tt[E];
        k = emulm( tt, yy, ldp );
        k = emulm( tt, yy, ldp );
        lexp -= EXONE - 1;
        lexp -= EXONE - 1;
        }
        }
 
 
expdon:
expdon:
 
 
/* Round and convert directly to the destination type */
/* Round and convert directly to the destination type */
if( oprec == 53 )
if( oprec == 53 )
        lexp -= EXONE - 0x3ff;
        lexp -= EXONE - 0x3ff;
else if( oprec == 24 )
else if( oprec == 24 )
        lexp -= EXONE - 0177;
        lexp -= EXONE - 0177;
#ifdef DEC
#ifdef DEC
else if( oprec == 56 )
else if( oprec == 56 )
        lexp -= EXONE - 0201;
        lexp -= EXONE - 0201;
#endif
#endif
ldp->rndprc = oprec;
ldp->rndprc = oprec;
emdnorm( yy, k, 0, lexp, 64, ldp );
emdnorm( yy, k, 0, lexp, 64, ldp );
 
 
aexit:
aexit:
 
 
ldp->rndprc = rndsav;
ldp->rndprc = rndsav;
yy[0] = nsign;
yy[0] = nsign;
switch( oprec )
switch( oprec )
        {
        {
#ifdef DEC
#ifdef DEC
        case 56:
        case 56:
                todec( yy, y ); /* see etodec.c */
                todec( yy, y ); /* see etodec.c */
                break;
                break;
#endif
#endif
#if LDBL_MANT_DIG == 53
#if LDBL_MANT_DIG == 53
        case 53:
        case 53:
                toe53( yy, y );
                toe53( yy, y );
                break;
                break;
#elif LDBL_MANT_DIG == 24
#elif LDBL_MANT_DIG == 24
        case 24:
        case 24:
                toe24( yy, y );
                toe24( yy, y );
                break;
                break;
#elif LDBL_MANT_DIG == 64
#elif LDBL_MANT_DIG == 64
        case 64:
        case 64:
                toe64( yy, y );
                toe64( yy, y );
                break;
                break;
#elif LDBL_MANT_DIG == 113
#elif LDBL_MANT_DIG == 113
        case 113:
        case 113:
                toe113( yy, y );
                toe113( yy, y );
                break;
                break;
#else
#else
        case NBITS:
        case NBITS:
                emovo( yy, y, ldp );
                emovo( yy, y, ldp );
                break;
                break;
#endif
#endif
        }
        }
lenldstr += s - lstr;
lenldstr += s - lstr;
if (mflag)
if (mflag)
  free (lstr);
  free (lstr);
return lenldstr;
return lenldstr;
}
}
 
 
 
 
 
 
/* y = largest integer not greater than x
/* y = largest integer not greater than x
 * (truncated toward minus infinity)
 * (truncated toward minus infinity)
 *
 *
 * unsigned short x[NE], y[NE]
 * unsigned short x[NE], y[NE]
 * LDPARMS *ldp
 * LDPARMS *ldp
 *
 *
 * efloor( x, y, ldp );
 * efloor( x, y, ldp );
 */
 */
static unsigned short bmask[] = {
static unsigned short bmask[] = {
0xffff,
0xffff,
0xfffe,
0xfffe,
0xfffc,
0xfffc,
0xfff8,
0xfff8,
0xfff0,
0xfff0,
0xffe0,
0xffe0,
0xffc0,
0xffc0,
0xff80,
0xff80,
0xff00,
0xff00,
0xfe00,
0xfe00,
0xfc00,
0xfc00,
0xf800,
0xf800,
0xf000,
0xf000,
0xe000,
0xe000,
0xc000,
0xc000,
0x8000,
0x8000,
0x0000,
0x0000,
};
};
 
 
static void efloor(short unsigned int *x, short unsigned int *y, LDPARMS *ldp)
static void efloor(short unsigned int *x, short unsigned int *y, LDPARMS *ldp)
{
{
register unsigned short *p;
register unsigned short *p;
int e, expon, i;
int e, expon, i;
unsigned short f[NE];
unsigned short f[NE];
 
 
emov( x, f ); /* leave in external format */
emov( x, f ); /* leave in external format */
expon = (int )f[NE-1];
expon = (int )f[NE-1];
e = (expon & 0x7fff) - (EXONE - 1);
e = (expon & 0x7fff) - (EXONE - 1);
if( e <= 0 )
if( e <= 0 )
        {
        {
        eclear(y);
        eclear(y);
        goto isitneg;
        goto isitneg;
        }
        }
/* number of bits to clear out */
/* number of bits to clear out */
e = NBITS - e;
e = NBITS - e;
emov( f, y );
emov( f, y );
if( e <= 0 )
if( e <= 0 )
        return;
        return;
 
 
p = &y[0];
p = &y[0];
while( e >= 16 )
while( e >= 16 )
        {
        {
        *p++ = 0;
        *p++ = 0;
        e -= 16;
        e -= 16;
        }
        }
/* clear the remaining bits */
/* clear the remaining bits */
*p &= bmask[e];
*p &= bmask[e];
/* truncate negatives toward minus infinity */
/* truncate negatives toward minus infinity */
isitneg:
isitneg:
 
 
if( (unsigned short )expon & (unsigned short )0x8000 )
if( (unsigned short )expon & (unsigned short )0x8000 )
        {
        {
        for( i=0; i<NE-1; i++ )
        for( i=0; i<NE-1; i++ )
                {
                {
                if( f[i] != y[i] )
                if( f[i] != y[i] )
                        {
                        {
                        esub( eone, y, y, ldp );
                        esub( eone, y, y, ldp );
                        break;
                        break;
                        }
                        }
                }
                }
        }
        }
}
}
 
 
 
 
 
 
static void eiremain(short unsigned int *den, short unsigned int *num, LDPARMS *ldp)
static void eiremain(short unsigned int *den, short unsigned int *num, LDPARMS *ldp)
{
{
long ld, ln;
long ld, ln;
unsigned short j;
unsigned short j;
 unsigned short *equot = ldp->equot;
 unsigned short *equot = ldp->equot;
 
 
ld = den[E];
ld = den[E];
ld -= enormlz( den );
ld -= enormlz( den );
ln = num[E];
ln = num[E];
ln -= enormlz( num );
ln -= enormlz( num );
ecleaz( equot );
ecleaz( equot );
while( ln >= ld )
while( ln >= ld )
        {
        {
        if( ecmpm(den,num) <= 0 )
        if( ecmpm(den,num) <= 0 )
                {
                {
                esubm(den, num);
                esubm(den, num);
                j = 1;
                j = 1;
                }
                }
        else
        else
                {
                {
                j = 0;
                j = 0;
                }
                }
        eshup1(equot);
        eshup1(equot);
        equot[NI-1] |= j;
        equot[NI-1] |= j;
        eshup1(num);
        eshup1(num);
        ln -= 1;
        ln -= 1;
        }
        }
emdnorm( num, 0, 0, ln, 0, ldp );
emdnorm( num, 0, 0, ln, 0, ldp );
}
}
 
 
/* NaN bit patterns
/* NaN bit patterns
 */
 */
#ifdef MIEEE
#ifdef MIEEE
static unsigned short nan113[8] = {
static unsigned short nan113[8] = {
  0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
  0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
static unsigned short nan64[6] = {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
static unsigned short nan64[6] = {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
static unsigned short nan53[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
static unsigned short nan53[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
static unsigned short nan24[2] = {0x7fff, 0xffff};
static unsigned short nan24[2] = {0x7fff, 0xffff};
#else /* !MIEEE */
#else /* !MIEEE */
static unsigned short nan113[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0x7fff};
static unsigned short nan113[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0x7fff};
static unsigned short nan64[6] = {0, 0, 0, 0, 0xc000, 0x7fff};
static unsigned short nan64[6] = {0, 0, 0, 0, 0xc000, 0x7fff};
static unsigned short nan53[4] = {0, 0, 0, 0x7ff8};
static unsigned short nan53[4] = {0, 0, 0, 0x7ff8};
static unsigned short nan24[2] = {0, 0x7fc0};
static unsigned short nan24[2] = {0, 0x7fc0};
#endif /* !MIEEE */
#endif /* !MIEEE */
 
 
 
 
static void enan (short unsigned int *nan, int size)
static void enan (short unsigned int *nan, int size)
{
{
int i, n;
int i, n;
unsigned short *p;
unsigned short *p;
 
 
switch( size )
switch( size )
        {
        {
#ifndef DEC
#ifndef DEC
        case 113:
        case 113:
        n = 8;
        n = 8;
        p = nan113;
        p = nan113;
        break;
        break;
 
 
        case 64:
        case 64:
        n = 6;
        n = 6;
        p = nan64;
        p = nan64;
        break;
        break;
 
 
        case 53:
        case 53:
        n = 4;
        n = 4;
        p = nan53;
        p = nan53;
        break;
        break;
 
 
        case 24:
        case 24:
        n = 2;
        n = 2;
        p = nan24;
        p = nan24;
        break;
        break;
 
 
        case NBITS:
        case NBITS:
        for( i=0; i<NE-2; i++ )
        for( i=0; i<NE-2; i++ )
                *nan++ = 0;
                *nan++ = 0;
        *nan++ = 0xc000;
        *nan++ = 0xc000;
        *nan++ = 0x7fff;
        *nan++ = 0x7fff;
        return;
        return;
 
 
        case NI*16:
        case NI*16:
        *nan++ = 0;
        *nan++ = 0;
        *nan++ = 0x7fff;
        *nan++ = 0x7fff;
        *nan++ = 0;
        *nan++ = 0;
        *nan++ = 0xc000;
        *nan++ = 0xc000;
        for( i=4; i<NI; i++ )
        for( i=4; i<NI; i++ )
                *nan++ = 0;
                *nan++ = 0;
        return;
        return;
#endif
#endif
        default:
        default:
        mtherr( "enan", DOMAIN );
        mtherr( "enan", DOMAIN );
        return;
        return;
        }
        }
for (i=0; i < n; i++)
for (i=0; i < n; i++)
        *nan++ = *p++;
        *nan++ = *p++;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.