Browse Source

run dos2unix on these files

Eric Andersen 24 năm trước cách đây
mục cha
commit
915950ede2
15 tập tin đã thay đổi với 9774 bổ sung9774 xóa
  1. 73 73
      test/crypt/Makefile
  2. 91 91
      test/math/Makefile
  3. 96 96
      test/math/econst.c
  4. 77 77
      test/math/eexp.c
  5. 42 42
      test/math/ehead.h
  6. 92 92
      test/math/elog.c
  7. 3550 3550
      test/math/eparanoi.c
  8. 215 215
      test/math/epow.c
  9. 52 52
      test/math/etanh.c
  10. 181 181
      test/math/etodec.c
  11. 4119 4119
      test/math/ieee.c
  12. 850 850
      test/math/ieetst.c
  13. 132 132
      test/math/ieetst.doc
  14. 108 108
      test/math/mconf.h
  15. 96 96
      test/math/mtherr.c

+ 73 - 73
test/crypt/Makefile

@@ -1,73 +1,73 @@
-# Makefile for uClibc
-#
-# Copyright (C) 2002 Erik Andersen <andersen@uclibc.org>
-#
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Library General Public License as published by the Free
-# Software Foundation; either version 2 of the License, or (at your option) any
-# later version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Library General Public License
-# along with this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-TESTDIR=../
-include $(TESTDIR)/Rules.mak
-
-TARGETS=diff md5c-test
-EXTRA_LIBS=-lcrypt
-
-all: $(TARGETS)
-
-crypt: crypt.c Makefile $(TESTDIR)/Config $(TESTDIR)/Rules.mak $(CC)
-	-@ echo "-------"
-	-@ echo " "
-	-@ echo "Compiling vs uClibc: "
-	-@ echo " "
-	$(CC) $(CFLAGS) -c $< -o $@.o
-	$(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
-	$(STRIPTOOL) -x -R .note -R .comment $@
-	-./$@ < crypt.input > $@.out 2>&1
-	-@ echo " "
-
-crypt_glibc: crypt.c Makefile $(TESTDIR)/Config $(TESTDIR)/Rules.mak $(CC)
-	-@ echo "-------"
-	-@ echo " "
-	-@ echo "Compiling vs uClibc: "
-	-@ echo " "
-	$(HOST_CC) $(GLIBC_CFLAGS) -c $< -o $@.o
-	$(HOST_CC) $(GLIBC_LDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
-	$(STRIPTOOL) -x -R .note -R .comment $@
-	-./$@ < crypt.input > $@.out 2>&1
-	-@ echo " "
-
-diff: crypt_glibc crypt
-	-@ echo "-------"
-	-@ echo " "
-	-@ echo "Diffing output: "
-	-@ echo " "
-	-diff -u crypt_glibc.out crypt.out
-	-@ echo " "
-
-md5c-test: md5c-test.c Makefile $(TESTDIR)/Config $(TESTDIR)/Rules.mak $(CC)
-	-@ echo "-------"
-	-@ echo " "
-	-@ echo "Compiling vs uClibc: "
-	-@ echo " "
-	$(CC) $(CFLAGS) -c $< -o $@.o
-	$(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
-	$(STRIPTOOL) -x -R .note -R .comment $@
-	-./$@
-	-@ echo " "
-
-clean:
-	rm -f *.[oa] *~ core crypt_glibc crypt crypt_glibc.out crypt.out md5c-test
-
-
+# Makefile for uClibc
+#
+# Copyright (C) 2002 Erik Andersen <andersen@uclibc.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+TESTDIR=../
+include $(TESTDIR)/Rules.mak
+
+TARGETS=crypt md5c-test
+EXTRA_LIBS=-lcrypt
+
+all: $(TARGETS)
+
+crypt: crypt.c Makefile $(TESTDIR)/Config $(TESTDIR)/Rules.mak $(CC)
+	-@ echo "-------"
+	-@ echo " "
+	-@ echo "Compiling vs uClibc: "
+	-@ echo " "
+	$(CC) $(CFLAGS) -c $< -o $@.o
+	$(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
+	$(STRIPTOOL) -x -R .note -R .comment $@
+	-./$@ < crypt.input #> $@.out 2>&1
+	-@ echo " "
+
+crypt_glibc: crypt.c Makefile $(TESTDIR)/Config $(TESTDIR)/Rules.mak $(CC)
+	-@ echo "-------"
+	-@ echo " "
+	-@ echo "Compiling vs uClibc: "
+	-@ echo " "
+	$(HOST_CC) $(GLIBC_CFLAGS) -c $< -o $@.o
+	$(HOST_CC) $(GLIBC_LDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
+	$(STRIPTOOL) -x -R .note -R .comment $@
+	-./$@ < crypt.input > $@.out 2>&1
+	-@ echo " "
+
+diff: crypt_glibc crypt
+	-@ echo "-------"
+	-@ echo " "
+	-@ echo "Diffing output: "
+	-@ echo " "
+	-diff -u crypt_glibc.out crypt.out
+	-@ echo " "
+
+md5c-test: md5c-test.c Makefile $(TESTDIR)/Config $(TESTDIR)/Rules.mak $(CC)
+	-@ echo "-------"
+	-@ echo " "
+	-@ echo "Compiling vs uClibc: "
+	-@ echo " "
+	$(CC) $(CFLAGS) -c $< -o $@.o
+	$(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
+	$(STRIPTOOL) -x -R .note -R .comment $@
+	-./$@
+	-@ echo " "
+
+clean:
+	rm -f *.[oa] *~ core crypt_glibc crypt crypt_glibc.out crypt.out md5c-test
+
+

+ 91 - 91
test/math/Makefile

@@ -1,91 +1,91 @@
-# Makefile for uClibc
-#
-# Copyright (C) 2000,2001 Erik Andersen <andersen@uclibc.org>
-#
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Library General Public License as published by the Free
-# Software Foundation; either version 2 of the License, or (at your option) any
-# later version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Library General Public License
-# along with this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-# Unix makefile for ieetst, eparanoi.
-# Set LARGEMEM 1 in qcalc.h for 32-bit memory addresses.
-# Define computer type and/or endianness in mconf.h.
-#
-# Configure eparanoi.c for desired arithmetic test;
-# also define appropriate version of setprec.o, or use a stub that
-# does no FPU setup.  To test native arithmetic, eparanoi uses
-# the system libraries only; compile simply by `cc eparanoi.c -lm'.
-#
-
-TESTDIR=../
-include $(TESTDIR)/Rules.mak
-
-
-#CC = gcc
-#CFLAGS= -O
-INCS= mconf.h ehead.h
-OBJS = ieee.o econst.o eexp.o elog.o epow.o etanh.o etodec.o mtherr.o #setprec.o
-TARGETS=ieetst eparanoi
-
-all: $(TARGETS)
-
-ieetst: ieetst.o $(OBJS) drand.o $(INCS)
-	$(CC) -o ieetst ieetst.o $(OBJS) drand.o -lc -lm
-
-eparanoi: eparanoi.o $(OBJS) $(INCS)
-	$(CC) -o eparanoi  eparanoi.o $(OBJS) -lc -lm
-
-#setprec.o: setprec.387
-#	as -o setprec.o setprec.387
-
-#setprec.o: setprec.688
-#	as -o setprec.o setprec.688
-
-ieee.o: ieee.c $(INCS)
-	$(CC) $(CFLAGS) -c ieee.c
-
-econst.o: econst.c $(INCS)
-	$(CC) $(CFLAGS) -c econst.c
-
-elog.o: elog.c $(INCS)
-	$(CC) $(CFLAGS) -c elog.c
-
-eexp.o: eexp.c $(INCS)
-	$(CC) $(CFLAGS) -c eexp.c
-
-etanh.o: etanh.c $(INCS)
-	$(CC) $(CFLAGS) -c etanh.c
-
-epow.o: epow.c $(INCS)
-	$(CC) $(CFLAGS) -c epow.c
-
-mtherr.o: mtherr.c $(INCS)
-	$(CC) $(CFLAGS) -c mtherr.c
-
-ieetst.o: ieetst.c $(INCS)
-	$(CC) $(CFLAGS) -c ieetst.c
-
-drand.o: drand.c $(INCS)
-	$(CC) $(CFLAGS) -c drand.c
-
-etodec.o: etodec.c $(INCS)
-	$(CC) $(CFLAGS) -c etodec.c
-
-eparanoi.o: eparanoi.c $(INCS)
-	$(CC) $(CFLAGS) -c eparanoi.c
-
-clean:
-	rm -f *.[oa] *~ core $(TARGETS)
-
-
+# Makefile for uClibc
+#
+# Copyright (C) 2000,2001 Erik Andersen <andersen@uclibc.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+# Unix makefile for ieetst, eparanoi.
+# Set LARGEMEM 1 in qcalc.h for 32-bit memory addresses.
+# Define computer type and/or endianness in mconf.h.
+#
+# Configure eparanoi.c for desired arithmetic test;
+# also define appropriate version of setprec.o, or use a stub that
+# does no FPU setup.  To test native arithmetic, eparanoi uses
+# the system libraries only; compile simply by `cc eparanoi.c -lm'.
+#
+
+TESTDIR=../
+include $(TESTDIR)/Rules.mak
+
+
+#CC = gcc
+#CFLAGS= -O
+INCS= mconf.h ehead.h
+OBJS = ieee.o econst.o eexp.o elog.o epow.o etanh.o etodec.o mtherr.o #setprec.o
+TARGETS=ieetst eparanoi
+
+all: $(TARGETS)
+
+ieetst: ieetst.o $(OBJS) drand.o $(INCS)
+	$(CC) -o ieetst ieetst.o $(OBJS) drand.o -lc -lm
+
+eparanoi: eparanoi.o $(OBJS) $(INCS)
+	$(CC) -o eparanoi  eparanoi.o $(OBJS) -lc -lm
+
+#setprec.o: setprec.387
+#	as -o setprec.o setprec.387
+
+#setprec.o: setprec.688
+#	as -o setprec.o setprec.688
+
+ieee.o: ieee.c $(INCS)
+	$(CC) $(CFLAGS) -c ieee.c
+
+econst.o: econst.c $(INCS)
+	$(CC) $(CFLAGS) -c econst.c
+
+elog.o: elog.c $(INCS)
+	$(CC) $(CFLAGS) -c elog.c
+
+eexp.o: eexp.c $(INCS)
+	$(CC) $(CFLAGS) -c eexp.c
+
+etanh.o: etanh.c $(INCS)
+	$(CC) $(CFLAGS) -c etanh.c
+
+epow.o: epow.c $(INCS)
+	$(CC) $(CFLAGS) -c epow.c
+
+mtherr.o: mtherr.c $(INCS)
+	$(CC) $(CFLAGS) -c mtherr.c
+
+ieetst.o: ieetst.c $(INCS)
+	$(CC) $(CFLAGS) -c ieetst.c
+
+drand.o: drand.c $(INCS)
+	$(CC) $(CFLAGS) -c drand.c
+
+etodec.o: etodec.c $(INCS)
+	$(CC) $(CFLAGS) -c etodec.c
+
+eparanoi.o: eparanoi.c $(INCS)
+	$(CC) $(CFLAGS) -c eparanoi.c
+
+clean:
+	rm -f *.[oa] *~ core $(TARGETS)
+
+

+ 96 - 96
test/math/econst.c

@@ -1,96 +1,96 @@
-/*							econst.c	*/
-/*  e type constants used by high precision check routines */
-
-#include "ehead.h"
-
-
-#if NE == 10
-/* 0.0 */
-unsigned short ezero[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
-  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
-
-/* 5.0E-1 */
-unsigned short ehalf[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
-  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3ffe,};
-
-/* 1.0E0 */
-unsigned short eone[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
-  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
-
-/* 2.0E0 */
-unsigned short etwo[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
-  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4000,};
-
-/* 3.2E1 */
-unsigned short e32[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
-  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4004,};
-
-/* 6.93147180559945309417232121458176568075500134360255E-1 */
-unsigned short elog2[NE] =
- {0x40f3, 0xf6af, 0x03f2, 0xb398,
-  0xc9e3, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
-
-/* 1.41421356237309504880168872420969807856967187537695E0 */
-unsigned short esqrt2[NE] =
- {0x1d6f, 0xbe9f, 0x754a, 0x89b3,
-  0x597d, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
-
-/* 3.14159265358979323846264338327950288419716939937511E0 */
-unsigned short epi[NE] =
- {0x2902, 0x1cd1, 0x80dc, 0x628b,
-  0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
-  
-/* 5.7721566490153286060651209008240243104215933593992E-1 */
-unsigned short eeul[NE] = {
-0xd1be,0xc7a4,0076660,0063743,0111704,0x3ffe,};
-
-#else
-
-/* 0.0 */
-unsigned short ezero[NE] = {
-0, 0000000,0000000,0000000,0000000,0000000,};
-/* 5.0E-1 */
-unsigned short ehalf[NE] = {
-0, 0000000,0000000,0000000,0100000,0x3ffe,};
-/* 1.0E0 */
-unsigned short eone[NE] = {
-0, 0000000,0000000,0000000,0100000,0x3fff,};
-/* 2.0E0 */
-unsigned short etwo[NE] = {
-0, 0000000,0000000,0000000,0100000,0040000,};
-/* 3.2E1 */
-unsigned short e32[NE] = {
-0, 0000000,0000000,0000000,0100000,0040004,};
-/* 6.93147180559945309417232121458176568075500134360255E-1 */
-unsigned short elog2[NE] = {
-0xc9e4,0x79ab,0150717,0013767,0130562,0x3ffe,};
-/* 1.41421356237309504880168872420969807856967187537695E0 */
-unsigned short esqrt2[NE] = {
-0x597e,0x6484,0174736,0171463,0132404,0x3fff,};
-/* 2/sqrt(PI) =
- * 1.12837916709551257389615890312154517168810125865800E0 */
-unsigned short eoneopi[NE] = {
-0x71d5,0x688d,0012333,0135202,0110156,0x3fff,};
-/* 3.14159265358979323846264338327950288419716939937511E0 */
-unsigned short epi[NE] = {
-0xc4c6,0xc234,0020550,0155242,0144417,0040000,};
-/* 5.7721566490153286060651209008240243104215933593992E-1 */
-unsigned short eeul[NE] = {
-0xd1be,0xc7a4,0076660,0063743,0111704,0x3ffe,};
-#endif
-extern unsigned short ezero[];
-extern unsigned short ehalf[];
-extern unsigned short eone[];
-extern unsigned short etwo[];
-extern unsigned short e32[];
-extern unsigned short elog2[];
-extern unsigned short esqrt2[];
-extern unsigned short eoneopi[];
-extern unsigned short epi[];
-extern unsigned short eeul[];
-
+/*							econst.c	*/
+/*  e type constants used by high precision check routines */
+
+#include "ehead.h"
+
+
+#if NE == 10
+/* 0.0 */
+unsigned short ezero[NE] =
+ {0x0000, 0x0000, 0x0000, 0x0000,
+  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
+
+/* 5.0E-1 */
+unsigned short ehalf[NE] =
+ {0x0000, 0x0000, 0x0000, 0x0000,
+  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3ffe,};
+
+/* 1.0E0 */
+unsigned short eone[NE] =
+ {0x0000, 0x0000, 0x0000, 0x0000,
+  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
+
+/* 2.0E0 */
+unsigned short etwo[NE] =
+ {0x0000, 0x0000, 0x0000, 0x0000,
+  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4000,};
+
+/* 3.2E1 */
+unsigned short e32[NE] =
+ {0x0000, 0x0000, 0x0000, 0x0000,
+  0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4004,};
+
+/* 6.93147180559945309417232121458176568075500134360255E-1 */
+unsigned short elog2[NE] =
+ {0x40f3, 0xf6af, 0x03f2, 0xb398,
+  0xc9e3, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
+
+/* 1.41421356237309504880168872420969807856967187537695E0 */
+unsigned short esqrt2[NE] =
+ {0x1d6f, 0xbe9f, 0x754a, 0x89b3,
+  0x597d, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
+
+/* 3.14159265358979323846264338327950288419716939937511E0 */
+unsigned short epi[NE] =
+ {0x2902, 0x1cd1, 0x80dc, 0x628b,
+  0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
+  
+/* 5.7721566490153286060651209008240243104215933593992E-1 */
+unsigned short eeul[NE] = {
+0xd1be,0xc7a4,0076660,0063743,0111704,0x3ffe,};
+
+#else
+
+/* 0.0 */
+unsigned short ezero[NE] = {
+0, 0000000,0000000,0000000,0000000,0000000,};
+/* 5.0E-1 */
+unsigned short ehalf[NE] = {
+0, 0000000,0000000,0000000,0100000,0x3ffe,};
+/* 1.0E0 */
+unsigned short eone[NE] = {
+0, 0000000,0000000,0000000,0100000,0x3fff,};
+/* 2.0E0 */
+unsigned short etwo[NE] = {
+0, 0000000,0000000,0000000,0100000,0040000,};
+/* 3.2E1 */
+unsigned short e32[NE] = {
+0, 0000000,0000000,0000000,0100000,0040004,};
+/* 6.93147180559945309417232121458176568075500134360255E-1 */
+unsigned short elog2[NE] = {
+0xc9e4,0x79ab,0150717,0013767,0130562,0x3ffe,};
+/* 1.41421356237309504880168872420969807856967187537695E0 */
+unsigned short esqrt2[NE] = {
+0x597e,0x6484,0174736,0171463,0132404,0x3fff,};
+/* 2/sqrt(PI) =
+ * 1.12837916709551257389615890312154517168810125865800E0 */
+unsigned short eoneopi[NE] = {
+0x71d5,0x688d,0012333,0135202,0110156,0x3fff,};
+/* 3.14159265358979323846264338327950288419716939937511E0 */
+unsigned short epi[NE] = {
+0xc4c6,0xc234,0020550,0155242,0144417,0040000,};
+/* 5.7721566490153286060651209008240243104215933593992E-1 */
+unsigned short eeul[NE] = {
+0xd1be,0xc7a4,0076660,0063743,0111704,0x3ffe,};
+#endif
+extern unsigned short ezero[];
+extern unsigned short ehalf[];
+extern unsigned short eone[];
+extern unsigned short etwo[];
+extern unsigned short e32[];
+extern unsigned short elog2[];
+extern unsigned short esqrt2[];
+extern unsigned short eoneopi[];
+extern unsigned short epi[];
+extern unsigned short eeul[];
+

+ 77 - 77
test/math/eexp.c

@@ -1,77 +1,77 @@
-/*							xexp.c		*/
-/* exponential function check routine */
-/* by Stephen L. Moshier. */
-
-
-#include "ehead.h"
-
-/*
-extern int powinited;
-extern short maxposint[], maxnegint[];
-*/
-
-void eexp( x, y )
-unsigned short *x, *y;
-{
-unsigned short num[NE], den[NE], x2[NE];
-long i;
-unsigned short sign, expchk;
-
-/* range reduction theory: x = i + f, 0<=f<1;
- * e**x = e**i * e**f 
- * e**i = 2**(i/log 2).
- * Let i/log2 = i1 + f1, 0<=f1<1.
- * Then e**i = 2**i1 * 2**f1, so
- * e**x = 2**i1 * e**(log 2 * f1) * e**f.
- */
-/*
-if( powinited == 0 )
-	initpow();
-*/
-if( ecmp(x, ezero) == 0 )
-	{
-	emov( eone, y );
-	return;
-	}
-emov(x, x2);
-expchk = x2[NE-1];
-sign = expchk & 0x8000;
-x2[NE-1] &= 0x7fff;
-
-/* Test for excessively large argument */
-expchk &= 0x7fff;
-if( expchk > (EXONE + 15) )
-	{
-	eclear( y );
-	if( sign == 0 )
-		einfin( y );
-	return;
-	}
-
-eifrac( x2, &i, num );		/* x = i + f		*/
-
-if( i != 0 )
- {
- ltoe( &i, den );		/* floating point i	*/
- ediv( elog2, den, den );	/* i/log 2		*/
- eifrac( den, &i, den );	/* i/log 2  =  i1 + f1	*/
- emul( elog2, den, den );	/* log 2 * f1		*/
- eadd( den, num, x2 );		/* log 2 * f1  + f	*/
- }
-
-/*x2[NE-1] -= 1;*/
-eldexp( x2, -1L, x2 ); /* divide by 2 */
-etanh( x2, x2 );	/* tanh( x/2 )			*/
-eadd( x2, eone, num );	/* 1 + tanh			*/
-eneg( x2 );
-eadd( x2, eone, den );	/* 1 - tanh			*/
-ediv( den, num, y );	/* (1 + tanh)/(1 - tanh)	*/
-
-/*y[NE-1] += i;*/
-if( sign )
-	{
-	ediv( y, eone, y );
-	i = -i;
-	}
-eldexp( y, i, y );	/* multiply by 2**i */
-}
+/*							xexp.c		*/
+/* exponential function check routine */
+/* by Stephen L. Moshier. */
+
+
+#include "ehead.h"
+
+/*
+extern int powinited;
+extern short maxposint[], maxnegint[];
+*/
+
+void eexp( x, y )
+unsigned short *x, *y;
+{
+unsigned short num[NE], den[NE], x2[NE];
+long i;
+unsigned short sign, expchk;
+
+/* range reduction theory: x = i + f, 0<=f<1;
+ * e**x = e**i * e**f 
+ * e**i = 2**(i/log 2).
+ * Let i/log2 = i1 + f1, 0<=f1<1.
+ * Then e**i = 2**i1 * 2**f1, so
+ * e**x = 2**i1 * e**(log 2 * f1) * e**f.
+ */
+/*
+if( powinited == 0 )
+	initpow();
+*/
+if( ecmp(x, ezero) == 0 )
+	{
+	emov( eone, y );
+	return;
+	}
+emov(x, x2);
+expchk = x2[NE-1];
+sign = expchk & 0x8000;
+x2[NE-1] &= 0x7fff;
+
+/* Test for excessively large argument */
+expchk &= 0x7fff;
+if( expchk > (EXONE + 15) )
+	{
+	eclear( y );
+	if( sign == 0 )
+		einfin( y );
+	return;
+	}
+
+eifrac( x2, &i, num );		/* x = i + f		*/
+
+if( i != 0 )
+ {
+ ltoe( &i, den );		/* floating point i	*/
+ ediv( elog2, den, den );	/* i/log 2		*/
+ eifrac( den, &i, den );	/* i/log 2  =  i1 + f1	*/
+ emul( elog2, den, den );	/* log 2 * f1		*/
+ eadd( den, num, x2 );		/* log 2 * f1  + f	*/
+ }
+
+/*x2[NE-1] -= 1;*/
+eldexp( x2, -1L, x2 ); /* divide by 2 */
+etanh( x2, x2 );	/* tanh( x/2 )			*/
+eadd( x2, eone, num );	/* 1 + tanh			*/
+eneg( x2 );
+eadd( x2, eone, den );	/* 1 - tanh			*/
+ediv( den, num, y );	/* (1 + tanh)/(1 - tanh)	*/
+
+/*y[NE-1] += i;*/
+if( sign )
+	{
+	ediv( y, eone, y );
+	i = -i;
+	}
+eldexp( y, i, y );	/* multiply by 2**i */
+}

+ 42 - 42
test/math/ehead.h

@@ -1,42 +1,42 @@
-
-/* Include file for extended precision arithmetic programs.
- */
-
-/* Number of 16 bit words in external x type format */
-#define NE 6
-
-/* Number of 16 bit words in internal format */
-#define NI (NE+3)
-
-/* Array offset to exponent */
-#define E 1
-
-/* Array offset to high guard word */
-#define M 2
-
-/* Number of bits of precision */
-#define NBITS ((NI-4)*16)
-
-/* Maximum number of decimal digits in ASCII conversion
- * = NBITS*log10(2)
- */
-#define NDEC (NBITS*8/27)
-
-/* The exponent of 1.0 */
-#define EXONE (0x3fff)
-
-void eadd(), esub(), emul(), ediv();
-int ecmp(), enormlz(), eshift();
-void eshup1(), eshup8(), eshup6(), eshdn1(), eshdn8(), eshdn6();
-void eabs(), eneg(), emov(), eclear(), einfin(), efloor();
-void eldexp(), efrexp(), eifrac(), ltoe();
-void esqrt(), elog(), eexp(), etanh(), epow();
-void asctoe(), asctoe24(), asctoe53(), asctoe64();
-void etoasc(), e24toasc(), e53toasc(), e64toasc();
-void etoe64(), etoe53(), etoe24(), e64toe(), e53toe(), e24toe();
-void mtherr();
-extern unsigned short ezero[], ehalf[], eone[], etwo[];
-extern unsigned short elog2[], esqrt2[];
-
-
-/* by Stephen L. Moshier. */
+
+/* Include file for extended precision arithmetic programs.
+ */
+
+/* Number of 16 bit words in external x type format */
+#define NE 6
+
+/* Number of 16 bit words in internal format */
+#define NI (NE+3)
+
+/* Array offset to exponent */
+#define E 1
+
+/* Array offset to high guard word */
+#define M 2
+
+/* Number of bits of precision */
+#define NBITS ((NI-4)*16)
+
+/* Maximum number of decimal digits in ASCII conversion
+ * = NBITS*log10(2)
+ */
+#define NDEC (NBITS*8/27)
+
+/* The exponent of 1.0 */
+#define EXONE (0x3fff)
+
+void eadd(), esub(), emul(), ediv();
+int ecmp(), enormlz(), eshift();
+void eshup1(), eshup8(), eshup6(), eshdn1(), eshdn8(), eshdn6();
+void eabs(), eneg(), emov(), eclear(), einfin(), efloor();
+void eldexp(), efrexp(), eifrac(), ltoe();
+void esqrt(), elog(), eexp(), etanh(), epow();
+void asctoe(), asctoe24(), asctoe53(), asctoe64();
+void etoasc(), e24toasc(), e53toasc(), e64toasc();
+void etoe64(), etoe53(), etoe24(), e64toe(), e53toe(), e24toe();
+void mtherr();
+extern unsigned short ezero[], ehalf[], eone[], etwo[];
+extern unsigned short elog2[], esqrt2[];
+
+
+/* by Stephen L. Moshier. */

+ 92 - 92
test/math/elog.c

@@ -1,92 +1,92 @@
-/*						xlog.c	*/
-/* natural logarithm */
-/* by Stephen L. Moshier. */
-
-#include "mconf.h"
-#include "ehead.h"
-
-
-
-void elog( x, y )
-unsigned short *x, *y;
-{
-unsigned short xx[NE], z[NE], a[NE], b[NE], t[NE], qj[NE];
-long ex;
-int fex;
-
-
-if( x[NE-1] & (unsigned short )0x8000 )
-	{
-	eclear(y);
-	mtherr( "elog", DOMAIN );
-	return;
-	}
-if( ecmp( x, ezero ) == 0 )
-	{
-	einfin( y );
-	eneg(y);
-	mtherr( "elog", SING );
-	return;
-	}
-if( ecmp( x, eone ) == 0 )
-	{
-	eclear( y );
-	return;
-	}
-
-/* range reduction: log x = log( 2**ex * m ) = ex * log2 + log m */
-efrexp( x, &fex, xx );
-/*
-emov(x, xx );
-ex = xx[NX-1] & 0x7fff;
-ex -= 0x3ffe;
-xx[NX-1] = 0x3ffe;
-*/
-
-/* Adjust range to 1/sqrt(2), sqrt(2) */
-esqrt2[NE-1] -= 1;
-if( ecmp( xx, esqrt2 ) < 0 )
-	{
-	fex -= 1;
-	emul( xx, etwo, xx );
-	}
-esqrt2[NE-1] += 1;
-
-esub( eone, xx, a );
-if( a[NE-1] == 0 )
-	{
-	eclear( y );
-	goto logdon;
-	}
-eadd( eone, xx, b );
-ediv( b, a, y );	/* store (x-1)/(x+1) in y */
-
-emul( y, y, z );
-
-emov( eone, a );
-emov( eone, b );
-emov( eone, qj );
-do
-	{
-	eadd( etwo, qj, qj );	/* 2 * i + 1		*/
-	emul( z, a, a );
-	ediv( qj, a, t );
-	eadd( t, b, b );
-	}
-while( ((b[NE-1] & 0x7fff) - (t[NE-1] & 0x7fff)) < NBITS );
-
-
-emul( b, y, y );
-emul( y, etwo, y );
-
-logdon:
-
-/* now add log of 2**ex */
-if( fex != 0 )
-	{
-	ex = fex;
-	ltoe( &ex, b );
-	emul( elog2, b, b );
-	eadd( b, y, y );
-	}
-}
+/*						xlog.c	*/
+/* natural logarithm */
+/* by Stephen L. Moshier. */
+
+#include "mconf.h"
+#include "ehead.h"
+
+
+
+void elog( x, y )
+unsigned short *x, *y;
+{
+unsigned short xx[NE], z[NE], a[NE], b[NE], t[NE], qj[NE];
+long ex;
+int fex;
+
+
+if( x[NE-1] & (unsigned short )0x8000 )
+	{
+	eclear(y);
+	mtherr( "elog", DOMAIN );
+	return;
+	}
+if( ecmp( x, ezero ) == 0 )
+	{
+	einfin( y );
+	eneg(y);
+	mtherr( "elog", SING );
+	return;
+	}
+if( ecmp( x, eone ) == 0 )
+	{
+	eclear( y );
+	return;
+	}
+
+/* range reduction: log x = log( 2**ex * m ) = ex * log2 + log m */
+efrexp( x, &fex, xx );
+/*
+emov(x, xx );
+ex = xx[NX-1] & 0x7fff;
+ex -= 0x3ffe;
+xx[NX-1] = 0x3ffe;
+*/
+
+/* Adjust range to 1/sqrt(2), sqrt(2) */
+esqrt2[NE-1] -= 1;
+if( ecmp( xx, esqrt2 ) < 0 )
+	{
+	fex -= 1;
+	emul( xx, etwo, xx );
+	}
+esqrt2[NE-1] += 1;
+
+esub( eone, xx, a );
+if( a[NE-1] == 0 )
+	{
+	eclear( y );
+	goto logdon;
+	}
+eadd( eone, xx, b );
+ediv( b, a, y );	/* store (x-1)/(x+1) in y */
+
+emul( y, y, z );
+
+emov( eone, a );
+emov( eone, b );
+emov( eone, qj );
+do
+	{
+	eadd( etwo, qj, qj );	/* 2 * i + 1		*/
+	emul( z, a, a );
+	ediv( qj, a, t );
+	eadd( t, b, b );
+	}
+while( ((b[NE-1] & 0x7fff) - (t[NE-1] & 0x7fff)) < NBITS );
+
+
+emul( b, y, y );
+emul( y, etwo, y );
+
+logdon:
+
+/* now add log of 2**ex */
+if( fex != 0 )
+	{
+	ex = fex;
+	ltoe( &ex, b );
+	emul( elog2, b, b );
+	eadd( b, y, y );
+	}
+}

+ 3550 - 3550
test/math/eparanoi.c

@@ -1,3550 +1,3550 @@
-/* paranoia.c arithmetic tester
- *
- * This is an implementation of the PARANOIA program.  It substitutes
- * subroutine calls for ALL floating point arithmetic operations.
- * This permits you to substitute your own experimental versions of
- * arithmetic routines.  It also defeats compiler optimizations,
- * so for native arithmetic you can be pretty sure you are testing
- * the arithmetic and not the compiler.
- *
- * This version of PARANOIA omits the display of division by zero.
- * It also omits the test for extra precise subexpressions, since
- * they cannot occur in this context.  Otherwise it includes all the
- * tests of the 27 Jan 86 distribution, plus a few additional tests.
- * Commentary has been reduced to a minimum in order to make the program
- * smaller.
- *
- * The original PARANOIA program, written by W. Kahan, C version
- * by Thos Sumner and David Gay, can be downloaded free from the
- * Internet NETLIB.  An MSDOS disk can be obtained for $15 from:
- *   Richard Karpinski
- *   6521 Raymond Street
- *   Oakland, CA 94609
- *
- * Steve Moshier, 28 Oct 88
- * last rev: 23 May 92
- */
-
-#define DEBUG 0
-
-/* To use the native arithmetic of the computer, define NATIVE
- * to be 1.  To use your own supplied arithmetic routines, NATIVE is 0.
- */
-#define NATIVE 0
-
-/* gcc real.c interface */
-#define L128DOUBLE 0
-
-#include <stdio.h>
-
-
-
-
-/* Data structure of floating point number.  If NATIVE was
- * selected above, you can define LDOUBLE 1 to test 80-bit long double
- * precision or define it 0 to test 64-bit double precision.
-*/
-#define LDOUBLE 0
-#if NATIVE
-
-#define NE 1
-#if LDOUBLE
-#define FSIZE long double
-#define FLOAT(x) FSIZE x[NE]
-static FSIZE eone[NE] = {1.0L};	/* The constant 1.0 */
-#define ZSQRT sqrtl
-#define ZLOG logl
-#define ZFLOOR floorl
-#define ZPOW powl
-long double sqrtl(), logl(), floorl(), powl();
-#define FSETUP einit
-#else /* not LDOUBLE */
-#define FSIZE double
-#define FLOAT(x) FSIZE x[NE]
-static FSIZE eone[NE] = {1.0};	/* The constant 1.0 */
-#define ZSQRT sqrt
-#define ZLOG log
-#define ZFLOOR floor
-#define ZPOW pow
-double sqrt(), log(), floor(), pow();
-/* Coprocessor initialization,
- * defeat underflow trap or what have you.
- * This is required mainly on i386 and 68K processors.
- */
-#define FSETUP dprec
-#endif /* double, not LDOUBLE */
-
-#else /* not NATIVE */
-
-/* Setup for extended double type.
- * Put NE = 10 for real.c operating with TFmode support (16-byte reals)
- * Put NE = 6 for real.c operating with XFmode support (10- or 12-byte reals)
- * The value of NE must agree with that in ehead.h, if ieee.c is used.
- */
-#define NE 6
-#define FSIZE unsigned short
-#define FLOAT(x) unsigned short x[NE]
-extern unsigned short eone[];
-#define FSETUP einit
-
-/* default for FSETUP */
-/*
-einit()
-{}
-*/
-
-error(s)
-char *s;
-{
-printf( "error: %s\n", s );
-}
-
-#endif	/* not NATIVE */
-
-
-
-#if L128DOUBLE
-/* real.c interface */
-
-#undef FSETUP
-#define FSETUP efsetup
-
-FLOAT(enone);
-
-#define ONE enone
-
-/* Use emov to convert from widest type to widest type, ... */
-/*
-#define ENTOE emov
-#define ETOEN emov
-*/
-
-/*                 ... else choose e24toe, e53toe, etc. */
-#define ENTOE e64toe
-#define ETOEN etoe64
-#define NNBITS 64
-
-#define NIBITS ((NE-1)*16)
-extern int rndprc;
-
-efsetup()
-{
-rndprc = NNBITS;
-ETOEN(eone, enone);
-}
-
-add(a,b,c)
-FLOAT(a);
-FLOAT(b);
-FLOAT(c);
-{
-unsigned short aa[10], bb[10], cc[10];
-
-ENTOE(a,aa);
-ENTOE(b,bb);
-eadd(aa,bb,cc);
-ETOEN(cc,c);
-}
-
-sub(a,b,c)
-FLOAT(a);
-FLOAT(b);
-FLOAT(c);
-{
-unsigned short aa[10], bb[10], cc[10];
-
-ENTOE(a,aa);
-ENTOE(b,bb);
-esub(aa,bb,cc);
-ETOEN(cc,c);
-}
-
-mul(a,b,c)
-FLOAT(a);
-FLOAT(b);
-FLOAT(c);
-{
-unsigned short aa[10], bb[10], cc[10];
-
-ENTOE(a,aa);
-ENTOE(b,bb);
-emul(aa,bb,cc);
-ETOEN(cc,c);
-}
-
-div(a,b,c)
-FLOAT(a);
-FLOAT(b);
-FLOAT(c);
-{
-unsigned short aa[10], bb[10], cc[10];
-
-ENTOE(a,aa);
-ENTOE(b,bb);
-ediv(aa,bb,cc);
-ETOEN(cc,c);
-}
-
-int cmp(a,b)
-FLOAT(a);
-FLOAT(b);
-{
-unsigned short aa[10], bb[10];
-int c;
-int ecmp();
-
-ENTOE(a,aa);
-ENTOE(b,bb);
-c = ecmp(aa,bb);
-return(c);
-}
-
-mov(a,b)
-FLOAT(a);
-FLOAT(b);
-{
-int i;
-
-for( i=0; i<NE; i++ )
-	b[i] = a[i];
-}
-
-
-neg(a)
-FLOAT(a);
-{
-unsigned short aa[10];
-
-ENTOE(a,aa);
-eneg(aa);
-ETOEN(aa,a);
-}
-
-clear(a)
-FLOAT(a);
-{
-int i;
-
-for( i=0; i<NE; i++ )
-	a[i] = 0;
-}
-
-FABS(a)
-FLOAT(a);
-{
-unsigned short aa[10];
-
-ENTOE(a,aa);
-eabs(aa);
-ETOEN(aa,a);
-}
-
-FLOOR(a,b)
-FLOAT(a);
-FLOAT(b);
-{
-unsigned short aa[10], bb[10];
-
-ENTOE(a,aa);
-efloor(aa,bb);
-ETOEN(bb,b);
-}
-
-LOG(a,b)
-FLOAT(a);
-FLOAT(b);
-{
-unsigned short aa[10], bb[10];
-int rndsav;
-
-ENTOE(a,aa);
-rndsav = rndprc;
-rndprc = NIBITS;
-elog(aa,bb);
-rndprc = rndsav;
-ETOEN(bb,b);
-}
-
-POW(a,b,c)
-FLOAT(a);
-FLOAT(b);
-FLOAT(c);
-{
-unsigned short aa[10], bb[10], cc[10];
-int rndsav;
-
-ENTOE(a,aa);
-ENTOE(b,bb);
-rndsav = rndprc;
-rndprc = NIBITS;
-epow(aa,bb,cc);
-rndprc = rndsav;
-ETOEN(cc,c);
-}
-
-SQRT(a,b)
-FLOAT(a);
-FLOAT(b);
-{
-unsigned short aa[10], bb[10];
-
-ENTOE(a,aa);
-esqrt(aa,bb);
-ETOEN(bb,b);
-}
-
-FTOL(x,ip,f)
-FLOAT(x);
-long *ip;
-FLOAT(f);
-{
-unsigned short xx[10], ff[10];
-
-ENTOE(x,xx);
-eifrac(xx,ip,ff);
-ETOEN(ff,f);
-}
-
-LTOF(ip,x)
-long *ip;
-FLOAT(x);
-{
-unsigned short xx[10];
-ltoe(ip,xx);
-ETOEN(xx,x);
-}
-
-TOASC(a,b,c)
-FLOAT(a);
-int b;
-char *c;
-{
-unsigned short xx[10];
-
-ENTOE(a,xx);
-etoasc(xx,b,c);
-}
-
-#else /* not L128DOUBLE */
-
-#define ONE eone
-
-/* Note all arguments of operation subroutines are pointers. */
-/* c = b + a */
-#define add(a,b,c) eadd(a,b,c)
-/* c = b - a */
-#define sub(a,b,c) esub(a,b,c)
-/* c = b * a */
-#define mul(a,b,c) emul(a,b,c)
-/* c = b / a */
-#define div(a,b,c) ediv(a,b,c)
-/* 1 if a>b, 0 if a==b, -1 if a<b */
-#define cmp(a,b) ecmp(a,b)
-/* b = a */
-#define mov(a,b) emov(a,b)
-/* a = -a */
-#define neg(a) eneg(a)
-/* a = 0 */
-#define clear(a) eclear(a)
-
-#define FABS(x) eabs(x)
-#define FLOOR(x,y) efloor(x,y)
-#define LOG(x,y) elog(x,y)
-#define POW(x,y,z) epow(x,y,z)
-#define SQRT(x,y) esqrt(x,y)
-
-/* x = &FLOAT input, i = &long integer part, f = &FLOAT fractional part */
-#define FTOL(x,i,f) eifrac(x,i,f)
-
-/* i = &long integer input, x = &FLOAT output */
-#define LTOF(i,x) ltoe(i,x)
-
-/* Convert FLOAT a to decimal ASCII string with b digits */
-#define TOASC(a,b,c) etoasc(a,b,c)
-#endif /* not L128DOUBLE */
-
-
-
-/* The following subroutines are implementations of the above
- * named functions, using the native or default arithmetic.
- */
-#if NATIVE
-eadd(a,b,c)
-FSIZE *a, *b, *c;
-{
-*c = *b + *a;
-}
-
-esub(a,b,c)
-FSIZE *a, *b, *c;
-{
-*c = *b - *a;
-}
-
-emul(a,b,c)
-FSIZE *a, *b, *c;
-{
-*c = (*b) * (*a);
-}
-
-ediv(a,b,c)
-FSIZE *a, *b, *c;
-{
-*c = (*b) / (*a);
-}
-
-
-/* Important note: comparison can be done by subracting
- * or by a compare instruction that may or may not be
- * equivalent to subtracting.
- */
-ecmp(a,b)
-FSIZE *a, *b;
-{
-if( (*a) > (*b) )
-	return( 1 );
-if( (*a) < (*b) )
-	return( -1 );
-if( (*a) != (*b) )
-	goto cmpf;
-if( (*a) == (*b) )
-	return( 0 );
-cmpf:
-printf( "Compare fails\n" );
-return(0);
-}
-
-
-emov( a, b )
-FSIZE *a, *b;
-{
-*b = *a;
-}
-
-eneg( a )
-FSIZE *a;
-{
-*a = -(*a);
-}
-
-eclear(a)
-FSIZE *a;
-{
-*a = 0.0;
-}
-
-eabs(x)
-FSIZE *x;
-{
-if( (*x) < 0.0 )
-	*x = -(*x);
-}
-
-efloor(x,y)
-FSIZE *x, *y;
-{
-
-*y = (FSIZE )ZFLOOR( *x );
-}
-
-elog(x,y)
-FSIZE *x, *y;
-{
-
-*y = (FSIZE )ZLOG( *x );
-}
-
-epow(x,y,z)
-FSIZE *x, *y, *z;
-{
-
-*z = (FSIZE )ZPOW( *x, *y );
-}
-
-esqrt(x,y)
-FSIZE *x, *y;
-{
-
-*y = (FSIZE )ZSQRT( *x );
-}
-
-
-eifrac(x,i,f)
-FSIZE *x;
-long *i;
-FSIZE *f;
-{
-FSIZE y;
-
-y = (FSIZE )ZFLOOR( *x );
-if( y < 0.0 )
-	{
-	*f = y - *x;
-	*i = -y;
-	}
-else
-	{
-	*f = *x - y;
-	*i = y;
-	}
-}
-
-
-ltoe(i,x)
-long *i;
-FSIZE *x;
-{
-*x = *i;
-}
-
-
-etoasc(a,str,n)
-FSIZE *a;
-char *str;
-int n;
-{
-double x;
-
-x = (double )(*a);
-sprintf( str, " %.17e ", x );
-}
-
-/* default for FSETUP */
-einit()
-{}
-
-#endif	/* NATIVE */
-
-
-
-
-FLOAT(Radix);
-FLOAT(BInvrse);
-FLOAT(RadixD2);
-FLOAT(BMinusU2);
-/*Small floating point constants.*/
-FLOAT(Zero);
-FLOAT(Half);
-FLOAT(One);
-FLOAT(Two);
-FLOAT(Three);
-FLOAT(Four);
-FLOAT(Five);
-FLOAT(Six);
-FLOAT(Eight);
-FLOAT(Nine);
-FLOAT(Ten);
-FLOAT(TwentySeven);
-FLOAT(ThirtyTwo);
-FLOAT(TwoForty);
-FLOAT(MinusOne );
-FLOAT(OneAndHalf);
-
-/*Integer constants*/
-int NoTrials = 20; /*Number of tests for commutativity. */
-#define False 0
-#define True 1
-
-/* Definitions for declared types 
-	Guard == (Yes, No);
-	Rounding == (Chopped, Rounded, Other);
-	Message == packed array [1..40] of char;
-	Class == (Flaw, Defect, Serious, Failure);
-	  */
-#define Yes 1
-#define No  0
-#define Chopped 2
-#define Rounded 1
-#define Other   0
-#define Flaw    3
-#define Defect  2
-#define Serious 1
-#define Failure 0
-
-typedef int Guard, Rounding, Class;
-typedef char Message;
-
-/* Declarations of Variables */
-FLOAT(AInvrse);
-FLOAT(A1);
-FLOAT(C);
-FLOAT(CInvrse);
-FLOAT(D);
-FLOAT(FourD);
-FLOAT(E0);
-FLOAT(E1);
-FLOAT(Exp2);
-FLOAT(E3);
-FLOAT(MinSqEr);
-FLOAT(SqEr);
-FLOAT(MaxSqEr);
-FLOAT(E9);
-FLOAT(Third);
-FLOAT(F6);
-FLOAT(F9);
-FLOAT(H);
-FLOAT(HInvrse);
-FLOAT(StickyBit);
-FLOAT(J);
-FLOAT(MyZero);
-FLOAT(Precision);
-FLOAT(Q);
-FLOAT(Q9);
-FLOAT(R);
-FLOAT(Random9);
-FLOAT(T);
-FLOAT(Underflow);
-FLOAT(S);
-FLOAT(OneUlp);
-FLOAT(UfThold);
-FLOAT(U1);
-FLOAT(U2);
-FLOAT(V);
-FLOAT(V0);
-FLOAT(V9);
-FLOAT(W);
-FLOAT(X);
-FLOAT(X1);
-FLOAT(X2);
-FLOAT(X8);
-FLOAT(Random1);
-FLOAT(Y);
-FLOAT(YY1);
-FLOAT(Y2);
-FLOAT(Random2);
-FLOAT(Z);
-FLOAT(PseudoZero);
-FLOAT(Z1);
-FLOAT(Z2);
-FLOAT(Z9);
-static FLOAT(t);
-FLOAT(t2);
-FLOAT(Sqarg);
-int ErrCnt[4];
-int fpecount;
-int Milestone;
-int PageNo;
-int I, M, N, N1, stkflg;
-Guard GMult, GDiv, GAddSub;
-Rounding RMult, RDiv, RAddSub, RSqrt;
-int Break, Done, NotMonot, Monot, Anomaly, IEEE;
-int SqRWrng, UfNGrad;
-int k, k2;
-int Indx;
-char ch[8];
-
-long lngint, lng2; /* intermediate for conversion between int and FLOAT */
-
-/* Computed constants. */
-/*U1  gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
-/*U2  gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
-
-
-show( x )
-short x[];
-{
-int i;
-char s[80];
-
-/* Number of 16-bit groups to display */
-#if NATIVE
-#if LDOUBLE
-#define NPRT (sizeof( long double )/2)
-#else
-#define NPRT (sizeof( double )/2)
-#endif
-#else
-#define NPRT NE
-#endif
-
-TOASC( x, s, 70 );
-printf( "%s\n", s );
-for( i=0; i<NPRT; i++ )
-	printf( "%04x ", x[i] & 0xffff );
-printf( "\n" );
-}
-
-/* define NOSIGNAL */
-#ifndef NOSIGNAL
-#include <signal.h>
-#endif
-#include <setjmp.h>
-jmp_buf ovfl_buf;
-/*typedef int (*Sig_type)();*/
-typedef void (*Sig_type)();
-Sig_type sigsave;
-
-/* Floating point exception receiver */
-void sigfpe()
-{
-fpecount++;
-printf( "\n* * * FLOATING-POINT ERROR * * *\n" );
-/* reinitialize the floating point unit */
-FSETUP();
-fflush(stdout);
-if( sigsave )
-	{
-#ifndef NOSIGNAL
-	signal( SIGFPE, sigsave );
-#endif
-	sigsave = 0;
-	longjmp( ovfl_buf, 1 );
-	}
-abort();
-}
-
-
-main()
-{
-
-/* Do coprocessor or other initializations */
-FSETUP();
-
-printf(
- "This version of paranoia omits test for extra precise subexpressions\n" );
-printf( "and includes a few additional tests.\n" );
-
-clear(Zero);
-printf( "0 = " );
-show( Zero );
-mov( ONE, One);
-printf( "1 = " );
-show( One );
-add( One, One, Two );
-printf( "1+1 = " );
-show( Two );
-add( Two, One, Three );
-add( Three, One, Four );
-add( Four, One, Five );
-add( Five, One, Six );
-add( Four, Four, Eight );
-mul( Three, Three, Nine );
-add( Nine, One, Ten );
-mul( Nine, Three, TwentySeven );
-mul( Four, Eight, ThirtyTwo );
-mul( Four, Five, t );
-mul( t, Three, t );
-mul( t, Four, TwoForty );
-mov( One, MinusOne );
-neg( MinusOne );
-div( Two, One, Half );
-add( One, Half, OneAndHalf );
-ErrCnt[Failure] = 0;
-ErrCnt[Serious] = 0;
-ErrCnt[Defect] = 0;
-ErrCnt[Flaw] = 0;
-PageNo = 1;
-#ifndef NOSIGNAL
-signal( SIGFPE, sigfpe );
-#endif
-printf("Program is now RUNNING tests on small integers:\n");
-
-add( Zero, Zero, t );
-if( cmp( t, Zero ) != 0)
-	{
-	printf( "0+0 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-sub( One, One, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "1-1 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-if( cmp( One, Zero ) <= 0 )
-	{
-	printf( "1 <= 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-add( One, One, t );
-if( cmp( t, Two ) != 0 )
-	{
-	printf( "1+1 != 2\n" );
-	ErrCnt[Failure] += 1;
-	}
-mov( Zero, Z );
-neg( Z );
-FLOOR( Z, t );
-if( cmp(t,Zero) != 0 )
-	{
-	ErrCnt[Serious] += 1;
-	printf( "FLOOR(-0) should equal 0, is = " );
-	show( t );
-	}
-if( cmp(Z, Zero) != 0)
-	{
-	ErrCnt[Failure] += 1;
-	printf("Comparison alleges that -0.0 is Non-zero!\n");
-	}
-else
-	{
-	div( TwoForty, One, U1 ); /* U1 = 0.001 */
-	mov( One, Radix );
-	TstPtUf();
-	}
-add( Two, One, t );
-if( cmp( t, Three ) != 0 )
-	{
-	printf( "2+1 != 3\n" );
-	ErrCnt[Failure] += 1;
-	}
-add( Three, One, t );
-if( cmp( t, Four ) != 0 )
-	{
-	printf( "3+1 != 4\n" );
-	ErrCnt[Failure] += 1;
-	}
-mov( Two, t );
-neg( t );
-mul( Two, t, t );
-add( Four, t, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "4+2*(-2) != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-sub( Three, Four, t );
-sub( One, t, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "4-3-1 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-	sub( One, Zero, t );
-if( cmp( t, MinusOne ) != 0 )
-	{
-	printf( "-1 != 0-1\n" );
-	ErrCnt[Failure] += 1;
-	}
-add( One, MinusOne, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "1+(-1) != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-mov( One, t );
-FABS( t );
-add( MinusOne, t, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "-1+abs(1) != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-mul( MinusOne, MinusOne, t );
-add( MinusOne, t, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "-1+(-1)*(-1) != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-add( Half, MinusOne, t );
-add( Half, t, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "1/2 + (-1) + 1/2 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-Milestone = 10;
-mul( Three, Three, t );
-if( cmp( t, Nine ) != 0 )
-	{
-	printf( "3*3 != 9\n" );
-	ErrCnt[Failure] += 1;
-	}
-mul( Nine, Three, t );
-if( cmp( t, TwentySeven ) != 0 )
-	{
-	printf( "3*9 != 27\n" );
-	ErrCnt[Failure] += 1;
-	}
-add( Four, Four, t );
-if( cmp( t, Eight ) != 0 )
-	{
-	printf( "4+4 != 8\n" );
-	ErrCnt[Failure] += 1;
-	}
-mul( Eight, Four, t );
-if( cmp( t, ThirtyTwo ) != 0 )
-	{
-	printf( "8*4 != 32\n" );
-	ErrCnt[Failure] += 1;
-	}
-sub( TwentySeven, ThirtyTwo, t );
-sub( Four, t, t );
-sub( One, t, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "32-27-4-1 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-add( Four, One, t );
-if( cmp( t, Five ) != 0 )
-	{
-	printf( "4+1 != 5\n" );
-	ErrCnt[Failure] += 1;
-	}
-mul( Four, Five, t );
-mul( Three, t, t );
-mul( Four, t, t );
-if( cmp( t, TwoForty ) != 0 )
-	{
-	printf( "4*5*3*4 != 240\n" );
-	ErrCnt[Failure] += 1;
-	}
-div( Three, TwoForty, t );
-mul( Four, Four, t2 );
-mul( Five, t2, t2 );
-sub( t2, t2, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "240/3 - 4*4*5 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-div( Four, TwoForty, t );
-mul( Five, Three, t2 );
-mul( Four, t2, t2 );
-sub( t2, t, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "240/4 - 5*3*4 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-div( Five, TwoForty, t );
-mul( Four, Three, t2 );
-mul( Four, t2, t2 );
-sub( t2, t, t );
-if( cmp( t, Zero ) != 0 )
-	{
-	printf( "240/5 - 4*3*4 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-if(ErrCnt[Failure] == 0)
-	{
-printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n\n");
-	}
-printf("Searching for Radix and Precision.\n");
-mov( One, W );
-do
-	{
-	add( W, W, W );
-	add( W, One, Y );
-	sub( W, Y, Z );
-	sub( One, Z, Y );
-	mov( Y, t );
-	FABS(t);
-	add( MinusOne, t, t );
-	k = cmp( t, Zero );
-	}
-while( k < 0 );
-/*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/
-mov( Zero, Precision );
-mov( One, Y );
-do
-	{
-	add( W, Y, Radix );
-	add( Y, Y, Y );
-	sub( W, Radix, Radix );
-	k = cmp( Radix, Zero );
-	}
-while( k == 0);
-
-if( cmp(Radix, Two) < 0 )
-	mov( One, Radix );
-printf("Radix = " );
-show( Radix );
-if( cmp(Radix, One) != 0)
-	{
-	mov( One, W );
-	do
-		{
-		add( One, Precision, Precision );
-		mul( W, Radix, W );
-		add( W, One, Y );
-		sub( W, Y, t );
-		k = cmp( t, One );
-		}
-	while( k == 0 );
-	}
-/* now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1 */
-div( W, One, U1 );
-mul( Radix, U1, U2 );
-printf( "Closest relative separation found is U 1 = " );
-show( U1 );
-printf( "Recalculating radix and precision." );
-	
-/*save old values*/
-mov( Radix, E0 );
-mov( U1, E1 );
-mov( U2, E9 );
-mov( Precision, E3 );
-	
-div( Three, Four, X );
-sub( One, X, Third );
-sub( Third, Half, F6 );
-add( F6, F6, X );
-sub( Third, X, X );
-FABS( X );
-if( cmp(X, U2) < 0 )
-	mov( U2, X );
-	
-/*... now X = (unknown no.) ulps of 1+...*/
-do
-	{
-	mov( X, U2 );
-/* Y = Half * U2 + ThirtyTwo * U2 * U2; */
-	mul( ThirtyTwo, U2, t );
-	mul( t, U2, t );
-	mul( Half, U2, Y );
-	add( t, Y, Y );
-	add( One, Y, Y );
-	sub( One, Y, X );
-	k = cmp( U2, X );
-	k2 = cmp( X, Zero );
-	}
-while ( ! ((k <= 0) || (k2 <= 0)));
-	
-/*... now U2 == 1 ulp of 1 + ... */
-div( Three, Two, X );
-sub( Half, X, F6 );
-add( F6, F6, Third );
-sub( Half, Third, X );
-add( F6, X, X );
-FABS( X );
-if( cmp(X, U1) < 0 )
-	mov( U1, X );
-	
-/*... now  X == (unknown no.) ulps of 1 -... */
-do
-	{
-	mov( X, U1 );
- /* Y = Half * U1 + ThirtyTwo * U1 * U1;*/
-	mul( ThirtyTwo, U1, t );
-	mul( U1, t, t );
-	mul( Half, U1, Y );
-	add( t, Y, Y );
-	sub( Y, Half, Y );
-	add( Half, Y, X );
-	sub( X, Half, Y );
-	add( Half, Y, X );
-	k = cmp( U1, X );
-	k2 = cmp( X, Zero );
-	} while ( ! ((k <= 0) || (k2 <= 0)));
-/*... now U1 == 1 ulp of 1 - ... */
-if( cmp( U1, E1 ) == 0 )
-	printf("confirms closest relative separation U1 .\n");
-else
-	{
-	printf("gets better closest relative separation U1 = " );
-	show( U1 );
-	}
-div( U1, One, W );
-sub( U1, Half, F9 );
-add( F9, Half, F9 );
-div( U1, U2, t );
-div( TwoForty, One, t2 );
-add( t2, t, t );
-FLOOR( t, Radix );
-if( cmp(Radix, E0) == 0 )
-	printf("Radix confirmed.\n");
-else
-	{
-	printf("MYSTERY: recalculated Radix = " );
-	show( Radix );
-	mov( E0, Radix );
-	}
-add( Eight, Eight, t );
-if( cmp( Radix, t ) > 0 )
-	{
-	printf( "Radix is too big: roundoff problems\n" );
-	ErrCnt[Defect] += 1;
-	}
-k = 1;
-if( cmp( Radix, Two ) == 0 )
-	k = 0;
-if( cmp( Radix, Ten ) == 0 )
-	k = 0;
-if( cmp( Radix, One ) == 0 )
-	k = 0;
-if( k != 0 )
-	{
-	printf( "Radix is not as good as 2 or 10\n" );
-	ErrCnt[Flaw] += 1;
-	}
-/*=============================================*/
-Milestone = 20;
-/*=============================================*/
-sub( Half, F9, t );
-if( cmp( t, Half ) >= 0 )
-	{
-	printf( "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?\n" );
-	ErrCnt[Failure] += 1;
-	}
-mov( F9, X );
-I = 1;
-sub( Half, X, Y );
-sub( Half, Y, Z );
-if( (cmp( X, One ) == 0) && (cmp( Z, Zero) != 0) )
-	{
-	printf( "Comparison is fuzzy ,X=1 but X-1/2-1/2 != 0\n" );
-	ErrCnt[Failure] += 1;
-	}
-add( One, U2, X );
-I = 0;
-/*=============================================*/
-Milestone = 25;
-/*=============================================*/
-/*... BMinusU2 = nextafter(Radix, 0) */
-
-sub( One, Radix, BMinusU2 );
-sub( U2, BMinusU2, t );
-add( One, t, BMinusU2 );
-/* Purify Integers */
-if( cmp(Radix,One) != 0 )
-	{
-/*X = - TwoForty * LOG(U1) / LOG(Radix);*/
-	LOG( U1, X );
-	LOG( Radix, t );
-	div( t, X, X );
-	mul( TwoForty, X, X );
-	neg( X );	
-
-	add( Half, X, Y );
-	FLOOR( Y, Y );
-	sub( Y, X, t );
-	FABS( t );
-	mul( Four, t, t );
-	if( cmp( t, One ) < 0 )
-		mov( Y, X );
-	div( TwoForty, X, Precision );
-	add( Half, Precision, Y );
-	FLOOR( Y, Y );
-	sub( Y, Precision, t );
-	FABS( t );
-	mul( TwoForty, t, t );
-	if( cmp( t, Half ) < 0 )
-		mov( Y, Precision );
-	}
-FLOOR( Precision, t );
-if( (cmp( Precision, t ) != 0) || (cmp( Radix, One ) == 0) )
-	{
-	printf("Precision cannot be characterized by an Integer number\n");
-	printf("of significant digits but, by itself, this is a minor flaw.\n");
-	}
-if( cmp(Radix, One) == 0 ) 
-	printf("logarithmic encoding has precision characterized solely by U1.\n");
-else
-	{
-	printf("The number of significant digits of the Radix is " );
-	show( Precision );
-	}
-mul( U2, Nine, t );
-mul( Nine, t, t );
-mul( TwoForty, t, t );
-if( cmp( t, One ) >= 0 )
-	{
-	printf( "Precision worse than 5 decimal figures\n" );
-	ErrCnt[Serious] += 1;
-	}
-/*=============================================*/
-Milestone = 30;
-/*=============================================*/
-/* Test for extra-precise subepressions has been deleted. */
-Milestone = 35;
-/*=============================================*/
-if( cmp(Radix,Two) >= 0 )
-	{
-	mul( Radix, Radix, t );
-	div( t, W, X );
-	add( X, One, Y );
-	sub( X, Y, Z );
-	add( Z, U2, T );
-	sub( Z, T, X );
-	if( cmp( X, U2 ) != 0 )
-		{
-		printf( "Subtraction is not normalized X=Y,X+Z != Y+Z!\n" );
-		ErrCnt[Failure] += 1;
-		}
-	if( cmp(X,U2) == 0 )
-	 printf("Subtraction appears to be normalized, as it should be.");
-	}
-
-printf("\nChecking for guard digit in *, /, and -.\n");
-mul( F9, One, Y );
-mul( One, F9, Z );
-sub( Half, F9, X );
-sub( Half, Y, Y );
-sub( X, Y, Y );
-sub( Half, Z, Z );
-sub( X, Z, Z );
-add( One, U2, X );
-mul( X, Radix, T );
-mul( Radix, X, R );
-sub( Radix, T, X );
-mul( Radix, U2, t );
-sub( t, X, X );
-sub( Radix, R, T );
-mul( Radix, U2, t );
-sub( t, T, T );
-sub( One, Radix, t );
-mul( t, X, X );
-sub( One, Radix, t );
-mul( t, T, T );
-
-k = cmp(X,Zero);
-k |= cmp(Y,Zero);
-k |= cmp(Z,Zero);
-k |= cmp(T,Zero);
-if( k == 0 )
-	GMult = Yes;
-else
-	{
-	GMult = No;
-	ErrCnt[Serious] += 1;
-	printf( "* lacks a Guard Digit, so 1*X != X\n" );
-	}
-mul( Radix, U2, Z );
-add( One, Z, X );
-add( X, Z, Y );
-mul( X, X, t );
-sub( t, Y, Y );
-FABS( Y );
-sub( U2, Y, Y );
-sub( U2, One, X );
-sub( U2, X, Z );
-mul( X, X, t );
-sub( t, Z, Z );
-FABS( Z );
-sub( U1, Z, Z );
-if( (cmp(Y,Zero) > 0) || (cmp(Z,Zero) > 0) )
-	{
-	ErrCnt[Failure] += 1;
-	printf( "* gets too many final digits wrong.\n" );
-	}
-sub( U2, One, Y );
-add( One, U2, X );
-div( Y, One, Z );
-sub( X, Z, Y );
-div( Three, One, X );
-div( Nine, Three, Z );
-sub( Z, X, X );
-div( TwentySeven, Nine, T );
-sub( T, Z, Z );
-k = cmp( X, Zero );
-k |= cmp( Y, Zero );
-k |= cmp( Z, Zero );
-if( k )
-	{
-	ErrCnt[Defect] += 1;
-printf( "Division lacks a Guard Digit, so error can exceed 1 ulp\n" );
-printf( "or  1/3  and  3/9  and  9/27 may disagree\n" );
-	}
-div( One, F9, Y );
-sub( Half, F9, X );
-sub( Half, Y, Y );
-sub( X, Y, Y );
-add( One, U2, X );
-div( One, X, T );
-sub( X, T, X );
-k = cmp( X, Zero );
-k |= cmp( Y, Zero );
-k |= cmp( Z, Zero );
-if( k == 0 )
-	GDiv = Yes;
-else
-	{
-	GDiv = No;
-	ErrCnt[Serious] += 1;
-	printf( "Division lacks a Guard Digit, so X/1 != X\n" );
-	}
-add( One, U2, X );
-div( X, One, X );
-sub( Half, X, Y );
-sub( Half, Y, Y );
-if( cmp(Y,Zero) >= 0 )
-	{
-	ErrCnt[Serious] += 1;
-	printf( "Computed value of 1/1.000..1 >= 1\n" );
-	}
-sub( U2, One, X );
-mul( Radix, U2, Y );
-add( One, Y, Y );
-mul( X, Radix, Z );
-mul( Y, Radix, T );
-div( Radix, Z, R );
-div( Radix, T, StickyBit );
-sub( X, R, X );
-sub( Y, StickyBit, Y );
-k = cmp( X, Zero );
-k |= cmp( Y, Zero );
-if( k )
-	{
-	ErrCnt[Failure] += 1;
-	printf( "* and/or / gets too many last digits wrong\n" );
-	}
-sub( U1, One, Y );
-sub( F9, One, X );
-sub( Y, One, Y );
-sub( U2, Radix, T );
-sub( BMinusU2, Radix, Z );
-sub( T, Radix, T );
-k = cmp( X, U1 );
-k |= cmp( Y, U1 );
-k |= cmp( Z, U2 );
-k |= cmp( T, U2 );
-if( k == 0 )
-	GAddSub = Yes;
-else
-	{
-	GAddSub = No;
-	ErrCnt[Serious] += 1;
-	printf( "- lacks Guard Digit, so cancellation is obscured\n" );
-	}
-sub( One, F9, t );
-if( (cmp(F9,One) != 0) && (cmp(t,Zero) >= 0) )
-	{
-	ErrCnt[Serious] += 1;
-	printf("comparison alleges  (1-U1) < 1  although\n");
-	printf("  subtration yields  (1-U1) - 1 = 0 , thereby vitiating\n");
-	printf("  such precautions against division by zero as\n");
-	printf("  ...  if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
-	}
-if (GMult == Yes && GDiv == Yes && GAddSub == Yes)
-	printf(" *, /, and - appear to have guard digits, as they should.\n");
-/*=============================================*/
-Milestone = 40;
-/*=============================================*/
-printf("Checking rounding on multiply, divide and add/subtract.\n");
-RMult = Other;
-RDiv = Other;
-RAddSub = Other;
-div( Two, Radix, RadixD2 );
-mov( Two, A1 );
-Done = False;
-do
-	{
-	mov( Radix, AInvrse );
-	do
-		{
-		mov( AInvrse, X );
-		div( A1, AInvrse, AInvrse );
-		FLOOR( AInvrse, t );
-		k = cmp( t, AInvrse );
-		}
-	while( ! (k != 0 ) );
-	k = cmp( X, One );
-	k2 = cmp( A1, Three );
-	Done = (k == 0) || (k2 > 0);
-	if(! Done)
-		add( Nine, One, A1 );
-	}
-while( ! (Done));
-if( cmp(X, One) == 0 )
-	mov( Radix, A1 );
-div( A1, One, AInvrse );
-mov( A1, X );
-mov( AInvrse, Y );
-Done = False;
-do
-	{
-	mul( X, Y, Z );
-	sub( Half, Z, Z );
-	if( cmp( Z, Half ) != 0 )
-		{
-		ErrCnt[Failure] += 1;
-		printf( "X * (1/X) differs from 1\n" );
-		}
-	k = cmp( X, Radix );
-	Done = (k == 0);
-	mov( Radix, X );
-	div( X, One, Y );
-	}
-while( ! (Done));
-
-add( One, U2, Y2 );
-sub( U2, One, YY1 );
-sub( U2, OneAndHalf, X );
-add( OneAndHalf, U2, Y );
-sub( U2, X, Z );
-mul( Z, Y2, Z );
-mul( Y, YY1, T );
-sub( X, Z, Z );
-sub( X, T, T );
-mul( X, Y2, X );
-add( Y, U2, Y );
-mul( Y, YY1, Y );
-sub( OneAndHalf, X, X );
-sub( OneAndHalf, Y, Y );
-k = cmp( X, Zero );
-k |= cmp( Y, Zero );
-k |= cmp( Z, Zero );
-if( cmp( T, Zero ) > 0 )
-	k = 1;
-if( k == 0 )
-	{
-	add( OneAndHalf, U2, X );
-	mul( X, Y2, X );
-	sub( U2, OneAndHalf, Y );
-	sub( U2, Y, Y );
-	add( OneAndHalf, U2, Z );
-	add( U2, Z, Z );
-	sub( U2, OneAndHalf, T );
-	mul( T, YY1, T );
-	add( Z, U2, t );
-	sub( t, X, X );
-	mul( Y, YY1, StickyBit );
-	mul( Z, Y2, S );
-	sub( Y, T, T );
-	sub( Y, U2, Y );
-	add( StickyBit, Y, Y );
-/* Z = S - (Z + U2 + U2); */
-	add( Z, U2, t );
-	add( t, U2, t );
-	sub( t, S, Z );
-	add( Y2, U2, t );
-	mul( t, YY1, StickyBit );
-	mul( Y2, YY1, YY1 );
-	sub( Y2, StickyBit, StickyBit );
-	sub( Half, YY1, YY1 );
-	k = cmp( X, Zero );
-	k |= cmp( Y, Zero );
-	k |= cmp( Z, Zero );
-	k |= cmp( T, Zero );
-	k |= cmp( StickyBit, Zero );
-	k |= cmp( YY1, Half );
-	if( k == 0 )
-		{
-		RMult = Rounded;
-		printf("Multiplication appears to round correctly.\n");
-		}
-	else
-		{
-		add( X, U2, t );
-		k = cmp( t, Zero );
-		if( cmp( Y, Zero ) >= 0 )
-			k |= 1;
-		add( Z, U2, t );
-		k |= cmp( t, Zero );
-		if( cmp( T, Zero ) >= 0 )
-			k |= 1;
-		add( StickyBit, U2, t );
-		k |= cmp( t, Zero );
-		if( cmp(YY1, Half) >= 0 )
-			k |= 1;
-		if( k == 0 )
-			{
-			printf("Multiplication appears to chop.\n");
-			}
-		else
-			{
-		printf("* is neither chopped nor correctly rounded.\n");
-			}
-		if( (RMult == Rounded) && (GMult == No) )
-			printf("Multiplication has inconsistent result");
-		}
-	}
-else
-	printf("* is neither chopped nor correctly rounded.\n");
-
-/*=============================================*/
-Milestone = 45;
-/*=============================================*/
-add( One, U2, Y2 );
-sub( U2, One, YY1 );
-add( OneAndHalf, U2, Z );
-add( Z, U2, Z );
-div( Y2, Z, X );
-sub( U2, OneAndHalf, T );
-sub( U2, T, T );
-sub( U2, T, Y );
-div( YY1, Y, Y );
-add( Z, U2, Z );
-div( Y2, Z, Z );
-sub( OneAndHalf, X, X );
-sub( T, Y, Y );
-div( YY1, T, T );
-add( OneAndHalf, U2, t );
-sub( t, Z, Z );
-sub( OneAndHalf, U2, t );
-add( t, T, T );
-k = 0;
-if( cmp( X, Zero ) > 0 )
-	k = 1;
-if( cmp( Y, Zero ) > 0 )
-	k = 1;
-if( cmp( Z, Zero ) > 0 )
-	k = 1;
-if( cmp( T, Zero ) > 0 )
-	k = 1;
-if( k == 0 )
-	{
-	div( Y2, OneAndHalf, X );
-	sub( U2, OneAndHalf, Y );
-	add( U2, OneAndHalf, Z );
-	sub( Y, X, X );
-	div( YY1, OneAndHalf, T );
-	div( YY1, Y, Y );
-	add( Z, U2, t );
-	sub( t, T, T );
-	sub( Z, Y, Y );
-	div( Y2, Z, Z );
-	add( Y2, U2, YY1 );
-	div( Y2, YY1, YY1 );
-	sub( OneAndHalf, Z, Z );
-	sub( Y2, YY1, Y2 );
-	sub( U1, F9, YY1 );
-	div( F9, YY1, YY1 );
-	k = cmp( X, Zero );
-	k |= cmp( Y, Zero );
-	k |= cmp( Z, Zero );
-	k |= cmp( T, Zero );
-	k |= cmp( Y2, Zero );
-	sub( Half, YY1, t );
-	sub( Half, F9, t2 );
-	k |= cmp( t, t2 );
-	if( k == 0 )
-		{
-		RDiv = Rounded;
-		printf("Division appears to round correctly.\n");
-		if(GDiv == No)
-			printf("Division test inconsistent\n");
-		}
-	else
-		{
-		k = 0;
-		if( cmp( X, Zero ) >= 0 )
-			k = 1;
-		if( cmp( Y, Zero ) >= 0 )
-			k = 1;
-		if( cmp( Z, Zero ) >= 0 )
-			k = 1;
-		if( cmp( T, Zero ) >= 0 )
-			k = 1;
-		if( cmp( Y, Zero ) >= 0 )
-			k = 1;
-		sub( Half, YY1, t );
-		sub( Half, F9, t2 );
-		if( cmp( t, t2 ) >= 0 )
-			k = 1;
-		if( k == 0 )
-			{
-			RDiv = Chopped;
-			printf("Division appears to chop.\n");
-			}
-		}
-	}
-if(RDiv == Other)
-	printf("/ is neither chopped nor correctly rounded.\n");
-div( Radix, One, BInvrse );
-mul( BInvrse, Radix, t );
-sub( Half, t, t );
-if( cmp( t, Half ) != 0 )
-	{
-	ErrCnt[Failure] += 1;
-	printf( "Radix * ( 1 / Radix ) differs from 1\n" );
-	}
-
-Milestone = 50;
-/*=============================================*/
-add( F9, U1, t );
-sub( Half, t, t );
-k = cmp( t, Half );
-add( BMinusU2, U2, t );
-sub( One, t, t );
-sub( One, Radix, t2 );
-k |= cmp( t, t2 );
-if( k != 0 )
-	{
-	ErrCnt[Failure] += 1;
-	printf( "Incomplete carry-propagation in Addition\n" );
-	}
-mul( U1, U1, X );
-sub( X, One, X );
-sub( U2, One, Y );
-mul( U2, Y, Y );
-add( One, Y, Y );
-sub( Half, F9, Z );
-sub( Half, X, X );
-sub( Z, X, X );
-sub( One, Y, Y );
-if( (cmp(X,Zero) == 0) && (cmp(Y,Zero) == 0) )
-	{
-	RAddSub = Chopped;
-	printf("Add/Subtract appears to be chopped.\n");
-	}
-if(GAddSub == Yes)
-	{
-	add( Half, U2, X );
-	mul( X, U2, X );
-	sub( U2, Half, Y );
-	mul( Y, U2, Y );
-	add( One, X, X );
-	add( One, Y, Y );
-	add( One, U2, t );
-	sub( X, t, X );
-	sub( Y, One, Y );
-	k = cmp(X,Zero);
-	if( k )
-		printf( "1+U2-[u2(1/2+U2)+1] != 0\n" );
-	k2 = cmp(Y,Zero);
-	if( k2 )
-		printf( "1-[U2(1/2-U2)+1] != 0\n" );
-	k |= k2;
-	if( k == 0 )
-		{
-		add( Half, U2, X );
-		mul( X, U1, X );
-		sub( U2, Half, Y );
-		mul( Y, U1, Y );
-		sub( X, One, X );
-		sub( Y, One, Y );
-		sub( X, F9, X );
-		sub( Y, One, Y );
-		k = cmp(X,Zero);
-		if( k )
-			printf( "F9-[1-U1(1/2+U2)] != 0\n" );
-		k2 = cmp(Y,Zero);
-		if( k2 )
-			printf( "1-[1-U1(1/2-U2)] != 0\n" );
-		k |= k2;
-		if( k == 0 )
-			{
-			RAddSub = Rounded;
-		printf("Addition/Subtraction appears to round correctly.\n");
-			if(GAddSub == No)
-				printf( "Add/Subtract test inconsistent\n");
-			}
-		else
-			{
-		 printf("Addition/Subtraction neither rounds nor chops.\n");
-			}
-		}
-	else
-		printf("Addition/Subtraction neither rounds nor chops.\n");
-	}
-else
-	printf("Addition/Subtraction neither rounds nor chops.\n");
-
-mov( One, S );
-add( One, Half, X );
-mul( Half, X, X );
-add( One, X, X );
-add( One, U2, Y );
-mul( Y, Half, Y );
-sub( Y, X, Z );
-sub( X, Y, T );
-add( Z, T, StickyBit );
-if( cmp(StickyBit, Zero) != 0 )
-	{
-	mov( Zero, S );
-	ErrCnt[Flaw] += 1;
-	printf( "(X - Y) + (Y - X) is non zero!\n" );
-	}
-mov( Zero, StickyBit );
-FLOOR( RadixD2, t );
-k2 = cmp( t, RadixD2 );
-k = 1;
-if( (GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
-	&& (RMult == Rounded) && (RDiv == Rounded)
-	&& (RAddSub == Rounded) && (k2 == 0) )
-	{
-	printf("Checking for sticky bit.\n");
-	k = 0;
-	add( Half, U1, X );
-	mul( X, U2, X );
-	mul( Half, U2, Y );
-	add( One, Y, Z );
-	add( One, X, T );
-	sub( One, Z, t );
-	sub( One, T, t2 );
-	if( cmp(t,Zero) > 0 )
-		{
-		k = 1;
-		printf( "[1+(1/2)U2]-1 > 0\n" );
-		}
-	if( cmp(t2,U2) < 0 )
-		{
-		k = 1;
-		printf( "[1+U2(1/2+U1)]-1 < U2\n" );
-		}
-	add( T, Y, Z );
-	sub( X, Z, Y );
-	sub( T, Z, t );
-	sub( T, Y, t2 );
-	if( cmp(t,U2) < 0 )
-		{
-		k = 1;
-		printf( "[[1+U2(1/2+U1)]+(1/2)U2]-[1+U2(1/2+U1)] < U2\n" );
-		}
-	if( cmp(t2,Zero) != 0 )
-		{
-		k = 1;
-		printf( "(1/2)U2-[1+U2(1/2+U1)] != 0\n" );
-		}
-	add( Half, U1, X );
-	mul( X, U1, X );
-	mul( Half, U1, Y );
-	sub( Y, One, Z );
-	sub( X, One, T );
-	sub( One, Z, t );
-	sub( F9, T, t2 );
-	if( cmp(t,Zero) != 0 )
-		{
-		k = 1;
-		printf( "(1-(1/2)U1)-1 != 0\n" );
-		}
-	if( cmp(t2,Zero) != 0 )
-		{
-		k = 1;
-		printf( "[1-U1(1/2+U1)]-F9 != 0\n" );
-		}
-	sub( U1, Half, Z );
-	mul( Z, U1, Z );
-	sub( Z, F9, T );
-	sub( Y, F9, Q );
-	sub( F9, T, t );
-	if( cmp( t, Zero ) != 0 )
-		{
-		k = 1;
-		printf( "[F9-U1(1/2-U1)]-F9 != 0\n" );
-		}
-	sub( U1, F9, t );
-	sub( Q, t, t );
-	if( cmp( t, Zero ) != 0 )
-		{
-		k = 1;
-		printf( "(F9-U1)-(F9-(1/2)U1) != 0\n" );
-		}
-	add( One, U2, Z );
-	mul( Z, OneAndHalf, Z );
-	add( OneAndHalf, U2, T );
-	sub( Z, T, T );
-	add( U2, T, T );
-	div( Radix, Half, X );
-	add( One, X, X );
-	mul( Radix, U2, Y );
-	add( One, Y, Y );
-	mul( X, Y, Z );
-	if( cmp( T, Zero ) != 0 )
-		{
-		k = 1;
-		printf( "(3/2+U2)-3/2(1+U2)+U2 != 0\n" );
-		}
-	mul( Radix, U2, t );
-	add( X, t, t );
-	sub( Z, t, t );
-	if( cmp( t, Zero ) != 0 )
-		{
-		k = 1;
-	printf( "(1+1/2Radix)+Radix*U2-[1+1/(2Radix)][1+Radix*U2] != 0\n" );
-		}
-	if( cmp(Radix, Two) != 0 )
-		{
-		add( Two, U2, X );
-		div( Two, X, Y );
-		sub( One, Y, t );
-		if( cmp( t, Zero) != 0 )
-			k = 1;
-		}
-	}
-if( k == 0 )
-	{
-	printf("Sticky bit apparently used correctly.\n");
-	mov( One, StickyBit );
-	}
-else
-	{
-	printf("Sticky bit used incorrectly or not at all.\n");
-	}
-
-if( GMult == No || GDiv == No || GAddSub == No ||
-		RMult == Other || RDiv == Other || RAddSub == Other)
-	{
-	ErrCnt[Flaw] += 1;
- printf("lack(s) of guard digits or failure(s) to correctly round or chop\n");
-printf( "(noted above) count as one flaw in the final tally below\n" );
-	}
-/*=============================================*/
-Milestone = 60;
-/*=============================================*/
-printf("\n");
-printf("Does Multiplication commute?  ");
-printf("Testing on %d random pairs.\n", NoTrials);
-SQRT( Three, Random9 );
-mov( Third, Random1 );
-I = 1;
-do
-	{
-	Random();
-	mov( Random1, X );
-	Random();
-	mov( Random1, Y );
-	mul( Y, X, Z9 );
-	mul( X, Y, Z );
-	sub( Z9, Z, Z9 );
-	I = I + 1;
-	}
-while ( ! ((I > NoTrials) || (cmp(Z9,Zero) != 0)));
-if(I == NoTrials)
-	{
-	div( Three, Half, t );
-	add( One, t, Random1 );
-	add( U2, U1, t );
-	add( t, One, Random2 );
-	mul( Random1, Random2, Z );
-	mul( Random2, Random1, Y );
-/* Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
- *			Three) * ((U2 + U1) + One);
- */
-	div( Three, Half, t2 );
-	add( One, t2, t2 );
-	add( U2, U1, t );
-	add( t, One, t );
-	mul( t2, t, Z9 );
-	mul( t2, t, t );
-	sub( t, Z9, Z9 );
-	}
-if(! ((I == NoTrials) || (cmp(Z9,Zero) == 0)))
-	{
-	ErrCnt[Defect] += 1;
-	printf( "X * Y == Y * X trial fails.\n");
-	}
-else
-	{
-	printf("     No failures found in %d integer pairs.\n", NoTrials);
-	}
-/*=============================================*/
-Milestone = 70;
-/*=============================================*/
-sqtest();
-Milestone = 90;
-pow1test();
-
-Milestone = 110;
-
-printf("Seeking Underflow thresholds UfThold and E0.\n");
-mov( U1, D );
-FLOOR( Precision, t );
-if( cmp(Precision, t) != 0 )
-	{
-	mov( BInvrse, D );
-	mov( Precision, X );
-	do
-		{
-		mul( D, BInvrse, D );
-		sub( One, X, X );
-		}
-	while( cmp(X, Zero) > 0 );
-	}
-mov( One, Y );
-mov( D, Z );
-/* ... D is power of 1/Radix < 1. */
-sigsave = sigfpe;
-if( setjmp(ovfl_buf) )
-	goto under0;
-do
-	{
-	mov( Y, C );
-	mov( Z, Y );
-	mul( Y, Y, Z );
-	add( Z, Z, t );
-	}
-while( (cmp(Y,Z) > 0) && (cmp(t,Z) > 0) );
-
-under0:
-sigsave = 0;
-
-mov( C, Y );
-mul( Y, D, Z );
-sigsave = sigfpe;
-if( setjmp(ovfl_buf) )
-	goto under1;
-do
-	{
-	mov( Y, C );
-	mov( Z, Y );
-	mul( Y, D, Z );
-	add( Z, Z, t );
-	}
-while( (cmp(Y,Z) > 0) && (cmp(t,Z) > 0) );
-
-under1:
-sigsave = 0;
-
-if( cmp(Radix,Two) < 0 )
-	mov( Two, HInvrse );
-else
-	mov( Radix, HInvrse );
-div( HInvrse, One, H );
-/* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
-div( C, One, CInvrse );
-mov( C, E0 );
-mul( E0, H, Z );
-/* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
-sigsave = sigfpe;
-if( setjmp(ovfl_buf) )
-	goto under2;
-do
-	{
-	mov( E0, Y );
-	mov( Z, E0 );
-	mul( E0, H, Z );
-	add( Z, Z, t );
-	}
-while( (cmp(E0,Z) > 0) && (cmp(t,Z) > 0) );
-
-under2:
-sigsave = 0;
-
-mov( E0, UfThold );
-mov( Zero, E1 );
-mov( Zero, Q );
-mov( U2, E9 );
-add( One, E9, S );
-mul( C, S, D );
-if( cmp(D,C) <= 0 )
-	{
-	mul( Radix, U2, E9 );
-	add( One, E9, S );
-	mul( C, S, D );
-	if( cmp(D, C) <= 0 )
-		{
-		ErrCnt[Failure] += 1;
-		printf( "multiplication gets too many last digits wrong.\n" );
-		mov( E0, Underflow );
-		mov( Zero, YY1 );
-		mov( Z, PseudoZero );
-		}
-	}
-else
-	{
-	mov( D, Underflow );
-	mul( Underflow, H, PseudoZero );
-	mov( Zero, UfThold );
-	do
-		{
-		mov( Underflow, YY1 );
-		mov( PseudoZero, Underflow );
-		add( E1, E1, t );
-		if( cmp(t, E1) <= 0)
-			{
-			mul( Underflow, HInvrse, Y2 );
-			sub( Y2, YY1, E1 );
-			FABS( E1 );
-			mov( YY1, Q );
-			if( (cmp( UfThold, Zero ) == 0)
-				&& (cmp(YY1, Y2) != 0) )
-				mov( YY1, UfThold );
-			}
-		mul( PseudoZero, H, PseudoZero );
-		add( PseudoZero, PseudoZero, t );
-		}
-	while( (cmp(Underflow, PseudoZero) > 0)
-		&& (cmp(t, PseudoZero) > 0) );
-	}
-/* Comment line 4530 .. 4560 */
-if( cmp(PseudoZero, Zero) != 0 )
-	{
-	printf("\n");
-	mov(PseudoZero, Z );
-/* ... Test PseudoZero for "phoney- zero" violates */
-/* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
-		   ... */
-	if( cmp(PseudoZero, Zero) <= 0 )
-		{
-		ErrCnt[Failure] += 1;
-		printf("Positive expressions can underflow to an\n");
-		printf("allegedly negative value\n");
-		printf("PseudoZero that prints out as: " );
-		show( PseudoZero );
-		mov( PseudoZero, X );
-		neg( X );
-		if( cmp(X, Zero) <= 0 )
-			{
-			printf("But -PseudoZero, which should be\n");
-			printf("positive, isn't; it prints out as " );
-			show( X );
-			}
-		}
-	else
-		{
-		ErrCnt[Flaw] += 1;
-		printf( "Underflow can stick at an allegedly positive\n");
-		printf("value PseudoZero that prints out as " );
-		show( PseudoZero );
-		}
-/*	TstPtUf();*/
-	}
-
-/*=============================================*/
-Milestone = 120;
-/*=============================================*/
-mul( CInvrse, Y, t );
-mul( CInvrse, YY1, t2 );
-if( cmp(t,t2) > 0 )
-	{
-	mul( H, S, S );
-	mov( Underflow, E0 );
-	}
-if(! ((cmp(E1,Zero) == 0) || (cmp(E1,E0) == 0)) )
-	{
-	ErrCnt[Defect] += 1;
-	if( cmp(E1,E0) < 0 )
-		{
-		printf("Products underflow at a higher");
-		printf(" threshold than differences.\n");
-		if( cmp(PseudoZero,Zero) == 0 ) 
-			mov( E1, E0 );
-		}
-	else
-		{
-		printf("Difference underflows at a higher");
-		printf(" threshold than products.\n");
-		}
-	}
-printf("Smallest strictly positive number found is E0 = " );
-show( E0 );
-mov( E0, Z );
-TstPtUf();
-mov( E0, Underflow );
-if(N == 1)
-	mov( Y, Underflow );
-I = 4;
-if( cmp(E1,Zero) == 0 )
-	I = 3;
-if( cmp( UfThold,Zero) == 0 )
-	I = I - 2;
-UfNGrad = True;
-switch(I)
-	{
-	case 1:
-	mov( Underflow, UfThold );
-	mul( CInvrse, Q, t );
-	mul( CInvrse, Y, t2 );
-	mul( t2, S, t2 );
-	if( cmp( t, t2 ) != 0 )
-		{
-		mov( Y, UfThold );
-		ErrCnt[Failure] += 1;
-		printf( "Either accuracy deteriorates as numbers\n");
-		printf("approach a threshold = " );
-		show( UfThold );
-		printf(" coming down from " );
-		show( C );
-	printf(" or else multiplication gets too many last digits wrong.\n");
-		}
-	break;
-	
-	case	2:
-	ErrCnt[Failure] += 1;
-	printf( "Underflow confuses Comparison which alleges that\n");
-	printf("Q == Y while denying that |Q - Y| == 0; these values\n");
-	printf("print out as Q = " );
-	show( Q );
-	printf( ", Y = " );
-	show( Y );
-	sub( Y2, Q, t );
-	FABS(t);
-	printf ("|Q - Y| = " );
-	show( t );
-	mov( Q, UfThold );
-	break;
-	
-	case 3:
-	mov( X, X );
-	break;
-	
-	case 4:
-	div( E9, E1, t );
-	sub( t, UfThold, t );
-	FABS(t);
-	if( (cmp(Q,UfThold) == 0) && (cmp(E1,E0) == 0)
-		&& (cmp(t,E1) <= 0) )
-		{
-		UfNGrad = False;
-		printf("Underflow is gradual; it incurs Absolute Error =\n");
-		printf("(roundoff in UfThold) < E0.\n");
-		mul( E0, CInvrse, Y );
-		add( OneAndHalf, U2, t );
-		mul( Y, t, Y );
-		add( One, U2, X );
-		mul( CInvrse, X, X );
-		div( X, Y, t );
-		IEEE = (cmp(t,E0) == 0);
-		if( IEEE == 0 )
-			{
-		printf( "((CInvrse E0) (1.5+U2)) / (CInvrse (1+U2)) != E0\n" );
-			printf( "CInvrse = " );
-			show( CInvrse );
-			printf( "E0 = " );
-			show( E0 );
-			printf( "U2 = " );
-			show( U2 );
-			printf( "X = " );
-			show(X);
-			printf( "Y = " );
-			show(Y);
-			printf( "Y/X = " );
-			show(t);
-			}
-		}
-	}
-if(UfNGrad)
-	{
-	printf("\n");
-	div( UfThold, Underflow, R );
-	SQRT( R, R );
-	if( cmp(R,H) <= 0)
-		{
-		mul( R, UfThold, Z );
-/* X = Z * (One + R * H * (One + H));*/
-		add( One, H, X );
-		mul( H, X, X );
-		mul( R, X, X );
-		add( One, X, X );
-		mul( Z, X, X );
-		}
-	else
-		{
-		mov( UfThold, Z );
-/*X = Z * (One + H * H * (One + H));*/
-		add( One, H, X );
-		mul( H, X, X );
-		mul( H, X, X );
-		add( One, X, X );
-		mul( Z, X, X );
-		}
-	sub( Z, X, t );
-/*	if(! ((cmp(X,Z) == 0) || (cmp(t,Zero) != 0)) )*/
-	if( (cmp(X,Z) != 0) && (cmp(t,Zero) == 0) )
-		{
-/*		ErrCnt[Flaw] += 1;*/
-		ErrCnt[Serious] += 1;
-		printf("X = " );
-		show( X );
-		printf( "\tis not equal to Z = " );
-		show( Z );
-/*		sub( Z, X, Z9 );*/
-		printf("yet X - Z yields " );
-		show( t );
-		printf("which compares equal to " );
-		show( Zero );
-		printf("    Should this NOT signal Underflow, ");
-		printf("this is a SERIOUS DEFECT\nthat causes ");
-		printf("confusion when innocent statements like\n");;
-		printf("    if (X == Z)  ...  else");
-		printf("  ... (f(X) - f(Z)) / (X - Z) ...\n");
-		printf("encounter Division by Zero although actually\n");
-		printf("X / Z = 1 + " );
-		div( Z, X, t );
-		sub( Half, t, t );
-		sub( Half, t, t );
-		show(t);
-		}
-	}
-printf("The Underflow threshold is " );
-show( UfThold );
-printf( "below which calculation may suffer larger Relative error than" );
-printf( " merely roundoff.\n");
-mul( U1, U1, Y2 );
-mul( Y2, Y2, Y );
-mul( Y, U1, Y2 );
-if( cmp( Y2,UfThold) <= 0 )
-	{
-	if( cmp(Y,E0) > 0 )
-		{
-		ErrCnt[Defect] += 1;
-		I = 5;
-		}
-	else
-		{
-		ErrCnt[Serious] += 1;
-		I = 4;
-		}
-	printf("Range is too narrow; U1^%d Underflows.\n", I);
-	}
-Milestone = 130;
-
-/*Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty;*/
-LOG( UfThold, Y );
-LOG( HInvrse, t );
-div( t, Y, Y );
-mul( TwoForty, Y, Y );
-sub( Y, Half, Y );
-FLOOR( Y, Y );
-div( TwoForty, Y, Y );
-neg(Y);
-sub( One, Y, Y2 ); /* ***** changed from Y2 = Y + Y */
-printf("Since underflow occurs below the threshold\n");
-printf("UfThold = " ); 
-show( HInvrse );
-printf( "\tto the power  " );
-show( Y );
-printf( "only underflow should afflict the expression " );
-show( HInvrse );
-printf( "\tto the power  " );
-show( Y2 );
-POW( HInvrse, Y2, V9 );
-printf("Actually calculating yields: " );
-show( V9 );
-add( Radix, Radix, t );
-add( t, E9, t );
-mul( t, UfThold, t );
-if( (cmp(V9,Zero) < 0) || (cmp(V9,t) > 0) )
-	{
-	ErrCnt[Serious] += 1;
-	printf( "this is not between 0 and underflow\n");
-	printf("   threshold = " );
-	show( UfThold );
-	}
-else
-	{
-	add( One, E9, t );
-	mul( UfThold, t, t );
-	if( cmp(V9,t) <= 0 )
-		printf("This computed value is O.K.\n");
-	else
-		{
-		ErrCnt[Defect] += 1;
-		printf( "this is not between 0 and underflow\n");
-		printf("   threshold = " );
-		show( UfThold );
-		}
-	}
-
-Milestone = 140;
-
-pow2test();
-	
-/*=============================================*/
-Milestone = 160;
-/*=============================================*/
-Pause();
-printf("Searching for Overflow threshold:\n");
-printf("This may generate an error.\n");
-sigsave = sigfpe;
-I = 0;
-mov( CInvrse, Y ); /* a large power of 2 */
-neg(Y);
-mul( HInvrse, Y, V9 ); /* HInvrse = 2 */
-if (setjmp(ovfl_buf))
-	goto overflow;
-do
-	{
-	mov( Y, V );
-	mov( V9, Y );
-	mul( HInvrse, Y, V9 );
-	}
-while( cmp(V9,Y) < 0 ); /* V9 = 2 * Y */
-I = 1;
-
-overflow:
-
-show( HInvrse );
-printf( "\ttimes " );
-show( Y );
-printf( "\tequals " );
-show( V9 );
-
-mov( V9, Z );
-printf("Can `Z = -Y' overflow?\n");
-printf("Trying it on Y = " );
-show(Y);
-mov( Y, V9 );
-neg( V9 );
-mov( V9, V0 );
-sub( Y, V, t );
-add( V, V0, t2 );
-if( cmp(t,t2) == 0 )
-	printf("Seems O.K.\n");
-else
-	{
-	printf("finds a Flaw, -(-Y) differs from Y.\n");
-	printf( "V-Y=t:" );
-	show(V);
-	show(Y);
-	show(t);
-	printf( "V+V0=t2:" );
-	show(V);
-	show(V0);
-	show(t2);
-	ErrCnt[Flaw] += 1;
-	}
-if( (cmp(Z, Y) != 0) && (I != 0) )
-	{
-	ErrCnt[Serious] += 1;
-	printf("overflow past " );
-	show( Y );
-	printf( "\tshrinks to " );
-	show( Z );
-	printf( "= Y * " );
-	show( HInvrse );
-	}
-/*Y = V * (HInvrse * U2 - HInvrse);*/
-mul( HInvrse, U2, Y );
-sub( HInvrse, Y, Y );
-mul( V, Y, Y );
-/*Z = Y + ((One - HInvrse) * U2) * V;*/
-sub( HInvrse, One, Z );
-mul( Z, U2, Z );
-mul( Z, V, Z );
-add( Y, Z, Z );
-if( cmp(Z,V0) < 0 )
-	mov( Z, Y );
-if( cmp(Y,V0) < 0)
-	mov( Y, V );
-sub( V, V0, t );
-if( cmp(t,V0) < 0 )
-	mov( V0, V );
-printf("Overflow threshold is V  = " );
-show( V );
-if(I)
-	{
-	printf("Overflow saturates at V0 = " );
-	show( V0 );
-	}
-else
-printf("There is no saturation value because the system traps on overflow.\n");
-
-mul( V, One, V9 );
-printf("No Overflow should be signaled for V * 1 = " );
-show( V9 );
-div( One, V, V9 );
-	printf("                           nor for V / 1 = " );
-	show( V9 );
-	printf("Any overflow signal separating this * from the one\n");
-	printf("above is a DEFECT.\n");
-/*=============================================*/
-Milestone = 170;
-/*=============================================*/
-mov( V, t );
-neg( t );
-k = 0;
-if( cmp(t,V) >= 0 )
-	k = 1;
-mov( V0, t );
-neg( t );
-if( cmp(t,V0) >= 0 )
-	k = 1;
-mov( UfThold, t );
-neg(t);
-if( cmp(t,V) >= 0 )
-	k = 1;
-if( cmp(UfThold,V) >= 0 )
-	k = 1;
-if( k != 0 )
-	{
-	ErrCnt[Failure] += 1;
-	printf( "Comparisons involving +-");
-	show( V );
-	show( V0 );
-	show( UfThold );
-	printf("are confused by Overflow." );
-	}
-/*=============================================*/
-Milestone = 175;
-/*=============================================*/
-printf("\n");
-for(Indx = 1; Indx <= 3; ++Indx) {
-	switch(Indx)
-		{
-		case 1: mov(UfThold, Z); break;
-		case 2: mov( E0, Z); break;
-		case 3: mov(PseudoZero, Z); break;
-		}
-if( cmp(Z, Zero) != 0 )
-	{
-	SQRT( Z, V9 );
-	mul( V9, V9, Y );
-	mul( Radix, E9, t );
-	sub( t, One, t );
-	div( t, Y, t );
-	add( One, Radix, t2 );
-	add( t2, E9, t2 );
-	mul( t2, Z, t2 );
-	if( (cmp(t,Z) < 0) || (cmp(Y,t2) > 0) )
-		{
-		if( cmp(V9,U1) > 0 )
-			ErrCnt[Serious] += 1;
-		else
-			ErrCnt[Defect] += 1;
-		printf("Comparison alleges that what prints as Z = " );
-		show( Z );
-		printf(" is too far from sqrt(Z) ^ 2 = " );
-		show( Y );
-		}
-	}
-}
-
-Milestone = 180;
-
-for(Indx = 1; Indx <= 2; ++Indx)
-	{
-	if(Indx == 1)
-		mov( V, Z );
-	else
-		mov( V0, Z );
-	SQRT( Z, V9 );
-	mul( Radix, E9, X );
-	sub( X, One, X );
-	mul( X, V9, X );
-	mul( V9, X, V9 );
-	mul( Two, Radix, t );
-	mul( t, E9, t );
-	sub( t, One, t );
-	mul( t, Z, t );
-	if( (cmp(V9,t) < 0) || (cmp(V9,Z) > 0) )
-		{
-		mov( V9, Y );
-		if( cmp(X,W) <  0 )
-			ErrCnt[Serious] += 1;
-		else
-			ErrCnt[Defect] += 1;
-		printf("Comparison alleges that Z = " );
-		show( Z );
-		printf(" is too far from sqrt(Z) ^ 2 :" );
-		show( Y );
-		}
-	}
-
-Milestone = 190;
-
-Pause();
-mul( UfThold, V, X ); 
-mul( Radix, Radix, Y );
-mul( X, Y, t );
-if( (cmp(t,One) < 0) || (cmp(X,Y) > 0) )
-	{
-	mul( X, Y, t );
-	div( U1, Y, t2 );
-	if( (cmp(t,U1) < 0) || (cmp(X,t2) > 0) )
-		{
-		ErrCnt[Defect] += 1;
-		printf( "Badly " );
-		}
-	else
-		{
-		ErrCnt[Flaw] += 1;
-		}
-	printf(" unbalanced range; UfThold * V = " );
-	show( X );
-	printf( "\tis too far from 1.\n");
-	}
-Milestone = 200;
-
-for(Indx = 1; Indx <= 5; ++Indx)
-	{
-	mov( F9, X );
-	switch(Indx)
-		{
-		case 2: add( One, U2, X ); break;
-		case 3: mov( V, X ); break;
-		case 4: mov(UfThold,X); break;
-		case 5: mov(Radix,X);
-		}
-	mov( X, Y );
-
-	sigsave = sigfpe;
-	if (setjmp(ovfl_buf))
-		{
-		printf("  X / X  traps when X = " );
-		show( X );
-		}
-	else
-		{
-/*V9 = (Y / X - Half) - Half;*/
-		div( X, Y, t );
-		sub( Half, t, t );
-		sub( Half, t, V9 );
-		if( cmp(V9,Zero) == 0 )
-			continue;
-		mov( U1, t );
-		neg(t);
-		if( (cmp(V9,t) == 0) && (Indx < 5) )
-			{
-			ErrCnt[Flaw] += 1;
-			}
-		else
-			{
-			ErrCnt[Serious] += 1;
-			}
-		printf("  X / X differs from 1 when X = " );
-		show( X );
-		printf("  instead, X / X - 1/2 - 1/2 = " );
-		show( V9 );
-		}
-	}
-
-	Pause();
-	printf("\n");
-	{
-		static char *msg[] = {
-			"FAILUREs  encountered =",
-			"SERIOUS DEFECTs  discovered =",
-			"DEFECTs  discovered =",
-			"FLAWs  discovered =" };
-		int i;
-		for(i = 0; i < 4; i++) if (ErrCnt[i])
-			printf("The number of  %-29s %d.\n",
-				msg[i], ErrCnt[i]);
-		}
-	printf("\n");
-	if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect]
-			+ ErrCnt[Flaw]) > 0) {
-		if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[
-			Defect] == 0) && (ErrCnt[Flaw] > 0)) {
-			printf("The arithmetic diagnosed seems ");
-			printf("satisfactory though flawed.\n");
-			}
-		if ((ErrCnt[Failure] + ErrCnt[Serious] == 0)
-			&& ( ErrCnt[Defect] > 0)) {
-			printf("The arithmetic diagnosed may be acceptable\n");
-			printf("despite inconvenient Defects.\n");
-			}
-		if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) {
-			printf("The arithmetic diagnosed has ");
-			printf("unacceptable serious defects.\n");
-			}
-		if (ErrCnt[Failure] > 0) {
-			printf("Fatal FAILURE may have spoiled this");
-			printf(" program's subsequent diagnoses.\n");
-			}
-		}
-	else {
-		printf("No failures, defects nor flaws have been discovered.\n");
-		if (! ((RMult == Rounded) && (RDiv == Rounded)
-			&& (RAddSub == Rounded) && (RSqrt == Rounded))) 
-			printf("The arithmetic diagnosed seems satisfactory.\n");
-		else {
-			k = 0;
-			if( cmp( Radix, Two ) == 0 )
-				k = 1;
-			if( cmp( Radix, Ten ) == 0 )
-				k = 1;
-			if( (cmp(StickyBit,One) >= 0) && (k == 1) )
-				{
-				printf("Rounding appears to conform to ");
-				printf("the proposed IEEE standard P");
-				k = 0;
-				k |= cmp( Radix, Two );
-				mul( Four, Three, t );
-				mul( t, Two, t );
-				sub( t, Precision, t );
-				sub( TwentySeven, Precision, t2 );
-				sub( TwentySeven, t2, t2 );
-				add( t2, One, t2 );
-				mul( t2, t, t );
-				if( (cmp(Radix,Two) == 0)
-					&& (cmp(t,Zero) == 0) )
-					printf("754");
-				else
-					printf("854");
-				if(IEEE)
-					printf(".\n");
-				else
-					{
-			printf(",\nexcept for possibly Double Rounding");
-			printf(" during Gradual Underflow.\n");
-					}
-				}
-		printf("The arithmetic diagnosed appears to be excellent!\n");
-			}
-		}
-	if (fpecount)
-		printf("\nA total of %d floating point exceptions were registered.\n",
-			fpecount);
-	printf("END OF TEST.\n");
-	}
-
-
-/* Random */
-/*  Random computes
-     X = (Random1 + Random9)^5
-     Random1 = X - FLOOR(X) + 0.000005 * X;
-   and returns the new value of Random1
-*/
-
-
-static int randflg = 0;
-FLOAT(C5em6);
-
-Random()
-{
-
-if( randflg == 0 )
-	{
-	mov( Six, t );
-	neg(t);
-	POW( Ten, t, t );
-	mul( Five, t, C5em6 );
-	randflg = 1;
-	}
-add( Random1, Random9, t );
-mul( t, t, t2 );
-mul( t2, t2, t2 );
-mul( t, t2, t );
-FLOOR(t, t2 );
-sub( t2, t, t2 );
-mul( t, C5em6, t );
-add( t, t2, Random1 );
-/*return(Random1);*/
-}
-
-/* SqXMinX */
-
-SqXMinX( ErrKind )
-int ErrKind;
-{
-mul( X, BInvrse, t2 );
-sub( t2, X, t );
-/*SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp;*/
-mul( X, X, Sqarg );
-SQRT( Sqarg, SqEr );
-sub( t2, SqEr, SqEr );
-sub( t, SqEr, SqEr );
-div( OneUlp, SqEr, SqEr );
-if( cmp(SqEr,Zero) != 0)
-	{
-	Showsq( 0 );
-	add( J, One, J );
-	ErrCnt[ErrKind] += 1;
-	printf("sqrt of " );
-	mul( X, X, t );
-	show( t );
-	printf( "minus " );
-	show( X );
-	printf( "equals " );
-	mul( OneUlp, SqEr, t );
-	show( t );
-	printf("\tinstead of correct value 0 .\n");
-	}
-}
-
-/* NewD */
-
-NewD()
-{
-mul( Z1, Q, X );
-/*X = FLOOR(Half - X / Radix) * Radix + X;*/
-div( Radix, X, t );
-sub( t, Half, t );
-FLOOR( t, t );
-mul( t, Radix, t );
-add( t, X, X );
-/*Q = (Q - X * Z) / Radix + X * X * (D / Radix);*/
-mul( X, Z, t );
-sub( t, Q, t );
-div( Radix, t, t );
-div( Radix, D, t2 );
-mul( X, t2, t2 );
-mul( X, t2, t2 );
-add( t, t2, Q );
-/*Z = Z - Two * X * D;*/
-mul( Two, X, t );
-mul( t, D, t );
-sub( t, Z, Z );
-
-if( cmp(Z,Zero) <= 0)
-	{
-	neg(Z);
-	neg(Z1);
-	}
-mul( Radix, D, D );
-}
-
-/* SR3750 */
-
-SR3750()
-{
-sub( Radix, X, t );
-sub( Radix, Z2, t2 );
-k = 0;
-if( cmp(t,t2) < 0 )
-	k = 1;
-sub( Z2, X, t );
-sub( Z2, W, t2 );
-if( cmp(t,t2) > 0 )
-	k = 1;
-/*if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) {*/
-if( k == 0 )
-	{
-	I = I + 1;
-	mul( X, D, X2 );
-	mov( X2, Sqarg );
-	SQRT( X2, X2 );
-/*Y2 = (X2 - Z2) - (Y - Z2);*/
-	sub( Z2, X2, Y2 );
-	sub( Z2, Y, t );
-	sub( t, Y2, Y2 );
-	sub( Half, Y, X2 );
-	div( X2, X8, X2 );
-	mul( Half, X2, t );
-	mul( t, X2, t );
-	sub( t, X2, X2 );
-/*SqEr = (Y2 + Half) + (Half - X2);*/
-	add( Y2, Half, SqEr );
-	sub( X2, Half, t );
-	add( t, SqEr, SqEr );
-	Showsq( -1 );
-	sub( X2, Y2, SqEr );
-	Showsq( 1 );
-	}
-}
-
-/* IsYeqX */
-
-IsYeqX()
-{
-if( cmp(Y,X) != 0 )
-	{
-	if (N <= 0)
-		{
-		if( (cmp(Z,Zero) == 0) && (cmp(Q,Zero) <= 0) )
-			printf("WARNING:  computing\n");
-		else
-			{
-			ErrCnt[Defect] += 1;
-			printf( "computing\n");
-			}
-		show( Z );
-		printf( "\tto the power " );
-		show( Q );
-		printf("\tyielded " );
-		show( Y );
-		printf("\twhich compared unequal to correct " );
-		show( X );
-		sub( X, Y, t );
-		printf("\t\tthey differ by " );
-		show( t );
-		}
-	N = N + 1; /* ... count discrepancies. */
-	}
-}
-
-/* SR3980 */
-
-SR3980()
-{
-long li;
-
-do
-	{
-/*Q = (FLOAT) I;*/
-	li = I;
-	LTOF( &li, Q );
-	POW( Z, Q, Y );
-	IsYeqX();
-	if(++I > M)
-		break;
-	mul( Z, X, X );
-	}
-while( cmp(X,W) < 0 );
-}
-
-/* PrintIfNPositive */
-
-PrintIfNPositive()
-{
-if(N > 0)
-	printf("Similar discrepancies have occurred %d times.\n", N);
-}
-
-
-/* TstPtUf */
-
-TstPtUf()
-{
-N = 0;
-if( cmp(Z,Zero) != 0)
-	{
-	printf( "Z = " );
-	show(Z);
-	printf("Since comparison denies Z = 0, evaluating ");
-	printf("(Z + Z) / Z should be safe.\n");
-	sigsave = sigfpe;
-	if (setjmp(ovfl_buf))
-		goto very_serious;
-	add( Z, Z, Q9 );
-	div( Z, Q9, Q9 );
-	printf("What the machine gets for (Z + Z) / Z is " );
-	show( Q9 );
-	sub( Two, Q9, t );
-	FABS(t);
-	mul( Radix, U2, t2 );
-	if( cmp(t,t2) < 0 )
-		{
-		printf("This is O.K., provided Over/Underflow");
-		printf(" has NOT just been signaled.\n");
-		}
-	else
-		{
-		if( (cmp(Q9,One) < 0) || (cmp(Q9,Two) > 0) )
-			{
-very_serious:
-			N = 1;
-			ErrCnt [Serious] = ErrCnt [Serious] + 1;
-			printf("This is a VERY SERIOUS DEFECT!\n");
-			}
-		else
-			{
-			N = 1;
-			ErrCnt[Defect] += 1;
-			printf("This is a DEFECT!\n");
-			}
-		}
-	mul( Z, One, V9 );
-	mov( V9, Random1 );
-	mul( One, Z, V9 );
-	mov( V9, Random2 );
-	div( One, Z, V9 );
-	if( (cmp(Z,Random1) == 0) && (cmp(Z,Random2) == 0)
-		&& (cmp(Z,V9) == 0) )
-		{
-		if (N > 0)
-			Pause();
-		}
-	else
-		{
-		N = 1;
-		ErrCnt[Defect] += 1;
-		printf( "What prints as Z = ");
-		show( Z );
-		printf( "\tcompares different from " );
-		if( cmp(Z,Random1) != 0)
-			{
-			printf("Z * 1 = " );
-			show( Random1 );
-			}
-		if( (cmp(Z,Random2) != 0)
-			|| (cmp(Random2,Random1) != 0) )
-			{
-			printf("1 * Z == " );
-			show( Random2 );
-			}
-		if( cmp(Z,V9) != 0 )
-			{
-			printf("Z / 1 = " );
-			show( V9 );
-			}
-		if( cmp(Random2,Random1) != 0 )
-			{
-			ErrCnt[Defect] += 1;
-			printf( "Multiplication does not commute!\n");
-			printf("\tComparison alleges that 1 * Z = " );
-			show(Random2);
-			printf("\tdiffers from Z * 1 = " );
-			show(Random1);
-			}
-		Pause();
-		}
-	}
-}
-
-Pause()
-{
-}
-
-Sign( x, y )
-FSIZE *x, *y;
-{
-
-if( cmp( x, Zero ) < 0 )
-	{
-	mov( One, y );
-	neg( y );
-	}
-else
-	{
-	mov( One, y );
-	}
-}
-
-sqtest()
-{
-printf("\nRunning test of square root(x).\n");
-
-RSqrt = Other;
-k = 0;
-SQRT( Zero, t );
-k |= cmp( Zero, t );
-mov( Zero, t );
-neg(t);
-SQRT( t, t2 );
-k |= cmp( t, t2 );
-SQRT( One, t );
-k |= cmp( One, t );
-if( k != 0 )
- 	{
-	ErrCnt[Failure] += 1;
-	printf( "Square root of 0.0, -0.0 or 1.0 wrong\n");
-	}
-mov( Zero, MinSqEr );
-mov( Zero, MaxSqEr );
-mov( Zero, J );
-mov( Radix, X );
-mov( U2, OneUlp );
-SqXMinX( Serious );
-mov( BInvrse, X );
-mul( BInvrse, U1, OneUlp );
-SqXMinX( Serious );
-mov( U1, X );
-mul( U1, U1, OneUlp );
-SqXMinX( Serious );
-if( cmp(J,Zero) != 0)
-	Pause();
-printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
-mov( Zero, J );
-mov( Two, X );
-mov( Radix, Y );
-if( cmp(Radix,One) != 0 )
-	{
-	lngint = NoTrials;
-	LTOF( &lngint, t );
-	FTOL( t, &lng2, X );
-	if( lngint != lng2 )
-		{
-		printf( "Integer conversion error\n" );
-		exit(1);
-		}
-	do
-		{
-		mov( Y, X );
-		mul( Radix, Y, Y );
-		sub( X, Y, t2 );
-		}
-	while( ! (cmp(t2,t) >= 0) );
-	}
-mul( X, U2, OneUlp );
-I = 1;
-while(I < 10)
-	{
-	add( X, One, X );
-	SqXMinX( Defect );
-	if( cmp(J,Zero) > 0 )
-		break;
-	I = I + 1;
-	}
-printf("Test for sqrt monotonicity.\n");
-I = - 1;
-mov( BMinusU2, X );
-mov( Radix, Y );
-mul( Radix, U2, Z );
-add( Radix, Z, Z );
-NotMonot = False;
-Monot = False;
-while( ! (NotMonot || Monot))
-	{
-	I = I + 1;
-	SQRT(X, X);
-	SQRT(Y,Q);
-	SQRT(Z,Z);
-	if( (cmp(X,Q) > 0) || (cmp(Q,Z) > 0) )
-		NotMonot = True;
-	else
-		{
-		add( Q, Half, Q );
-		FLOOR( Q, Q );
-		mul( Q, Q, t );
-		if( (I > 0) || (cmp(Radix,t) == 0) )
-			Monot = True;
-		else if (I > 0)
-			{
-			if(I > 1)
-				Monot = True;
-			else
-				{
-				mul( Y, BInvrse, Y );
-				sub( U1, Y, X );
-				add( Y, U1, Z );
-				}
-			}
-		else
-			{
-			mov( Q, Y );
-			sub( U2, Y, X );
-			add( Y, U2, Z );
-			}
-		}
-	}
-if( Monot )
-	printf("sqrt has passed a test for Monotonicity.\n");
-else
-	{
-	ErrCnt[Defect] += 1;
-	printf("sqrt(X) is non-monotonic for X near " );
-	show(Y);
-	}
-/*=============================================*/
-Milestone = 80;
-/*=============================================*/
-add( MinSqEr, Half, MinSqEr );
-sub( Half, MaxSqEr, MaxSqEr);
-/*Y = (SQRT(One + U2) - One) / U2;*/
-add( One, U2, Sqarg );
-SQRT( Sqarg, Y );
-sub( One, Y, Y );
-div( U2, Y, Y );
-/*SqEr = (Y - One) + U2 / Eight;*/
-sub( One, Y, t );
-div( Eight, U2, SqEr );
-add( t, SqEr, SqEr );
-Showsq( 1 );
-div( Eight, U2, SqEr );
-add( Y, SqEr, SqEr );
-Showsq( -1 );
-/*Y = ((SQRT(F9) - U2) - (One - U2)) / U1;*/
-mov( F9, Sqarg );
-SQRT( Sqarg, Y );
-sub( U2, Y, Y );
-sub( U2, One, t );
-sub( t, Y, Y );
-div( U1, Y, Y );
-div( Eight, U1, SqEr );
-add( Y, SqEr, SqEr );
-Showsq( 1 );
-/*SqEr = (Y + One) + U1 / Eight;*/
-div( Eight, U1, t );
-add( Y, One, SqEr );
-add( SqEr, t, SqEr );
-Showsq( -1 );
-mov( U2, OneUlp );
-mov( OneUlp, X );
-for( Indx = 1; Indx <= 3; ++Indx)
-	{
-/*Y = SQRT((X + U1 + X) + F9);*/
-	add( X, U1, Y );
-	add( Y, X, Y );
-	add( Y, F9, Y );
-	mov( Y, Sqarg );
-	SQRT( Sqarg, Y );
-/*Y = ((Y - U2) - ((One - U2) + X)) / OneUlp;*/
-	sub( U2, One, t );
-	add( t, X, t );
-	sub( U2, Y, Y );
-	sub( t, Y, Y );
-	div( OneUlp, Y, Y );
-/*Z = ((U1 - X) + F9) * Half * X * X / OneUlp;*/
-	sub( X, U1, t );
-	add( t, F9, t );
-	mul( t, Half, t );
-	mul( t, X, t );
-	mul( t, X, t );
-	div( OneUlp, t, Z );
-	add( Y, Half, SqEr );
-	add( SqEr, Z, SqEr );
-	Showsq( -1 );
-	sub( Half, Y, SqEr );
-	add( SqEr, Z, SqEr );
-	Showsq( 1 );
-	if(((Indx == 1) || (Indx == 3))) 
-		{
-/*X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp)));*/
-		mov( OneUlp, Sqarg );
-		SQRT( Sqarg, t );
-		mul( Nine, t, t );
-		div( t, Eight, t );
-		FLOOR( t, t );
-		Sign( X, t2 );
-		mul( t2, t, t );
-		mul( OneUlp, t, X );
-		}
-	else
-		{
-		mov( U1, OneUlp );
-		mov( OneUlp, X );
-		neg( X );
-		}
-	}
-/*=============================================*/
-Milestone = 85;
-/*=============================================*/
-SqRWrng = False;
-Anomaly = False;
-if( cmp(Radix,One) != 0 )
-	{
-	printf("Testing whether sqrt is rounded or chopped.\n");
-/*D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision)));*/
-	FLOOR( Precision, t2 );
-	add( One, Precision, t );
-	sub( t2, t, t );
-	POW( Radix, t, D );
-	add( Half, D, D );
-	FLOOR( D, D );
-/* ... == Radix^(1 + fract) if (Precision == Integer + fract. */
-	div( Radix, D, X );
-	div( A1, D, Y );
-	FLOOR( X, t );
-	FLOOR( Y, t2 );
-	if( (cmp(X,t) != 0) || (cmp(Y,t2) != 0) )
-		{
-		Anomaly = True;
-		printf( "Anomaly 1\n" );
-		}
-	else
-		{
-		mov( Zero, X );
-		mov( X, Z2 );
-		mov( One, Y );
-		mov( Y, Y2 );
-		sub( One, Radix, Z1 );
-		mul( Four, D, FourD );
-		do
-			{
-			if( cmp(Y2,Z2) >0 )
-				{
-				mov( Radix, Q );
-				mov( Y, YY1 );
-				do
-					{
-/*X1 = FABS(Q + FLOOR(Half - Q / YY1) * YY1);*/
-					div( YY1, Q, t );
-					sub( t, Half, t );
-					FLOOR( t, t );
-					mul( t, YY1, t );
-					add( Q, t, X1 );
-					FABS( X1 );
-					mov( YY1, Q );
-					mov( X1, YY1 );
-					}
-				while( ! (cmp(X1,Zero) <= 0) );
-				if( cmp(Q,One) <= 0 )
-					{
-					mov( Y2, Z2 );
-					mov( Y, Z );
-					}
-				}
-			add( Y, Two, Y );
-			add( X, Eight, X );
-			add( Y2, X, Y2 );
-			if( cmp(Y2,FourD) >= 0 )
-				sub( FourD, Y2, Y2 );
-			}
-		while( ! (cmp(Y,D) >= 0) );
-		sub( Z2, FourD, X8 );
-		mul( Z, Z, Q );
-		add( X8, Q, Q );
-		div( FourD, Q, Q );
-		div( Eight, X8, X8 );
-		FLOOR( Q, t );
-		if( cmp(Q,t) != 0 )
-			{
-			Anomaly = True;
-			printf( "Anomaly 2\n" );
-			}
-		else
-			{
-			Break = False;
-			do
-				{
-				mul( Z1, Z, X );
-/*X = X - FLOOR(X / Radix) * Radix;*/
-				div( Radix, X, t );
-				FLOOR( t, t );
-				mul( t, Radix, t );
-				sub( t, X, X );
-				if( cmp(X,One) == 0 ) 
-					Break = True;
-				else
-					sub( One, Z1, Z1 );
-				}
-			while( ! (Break || (cmp(Z1,Zero) <= 0)) );
-			if( (cmp(Z1,Zero) <= 0) && (! Break))
-				{
-				printf( "Anomaly 3\n" );
-				Anomaly = True;
-				}
-			else
-				{
-				if( cmp(Z1,RadixD2) > 0)
-					sub( Radix, Z1, Z1 );
-				do
-					{
-					NewD();
-					mul( U2, D, t );
-					}
-				while( ! (cmp(t,F9) >= 0) );
-				mul( D, Radix, t );
-				sub( D, t, t );
-				sub( D, W, t2 );
-				if (cmp(t,t2) != 0 )
-					{
-					printf( "Anomaly 4\n" );
-					Anomaly = True;
-					}
-				else
-					{
-					mov( D, Z2 );
-					I = 0;
-					add( One, Z, t );
-					mul( t, Half, t );
-					add( D, t, Y );
-					add( D, Z, X );
-					add( X, Q, X );
-					SR3750();
-					sub( Z, One, t );
-					mul( t, Half, t );
-					add( D, t, Y );
-					add( Y, D, Y );
-					sub( Z, D, X );
-					add( X, D, X );
-					add( X, Q, t );
-					add( t, X, X );
-					SR3750();
-					NewD();
-					sub( Z2, D, t );
-					sub( Z2, W, t2 );
-					if(cmp(t,t2) != 0 )
-						{
-						printf( "Anomaly 5\n" );
-						Anomaly = True;
-						}
-					else
-						{
-/*Y = (D - Z2) + (Z2 + (One - Z) * Half);*/
-						sub( Z, One, t );
-						mul( t, Half, t );
-						add( Z2, t, t );
-						sub( Z2, D, Y );
-						add( Y, t, Y );
-/*X = (D - Z2) + (Z2 - Z + Q);*/
-						sub( Z, Z2, t );
-						add( t, Q, t );
-						sub( Z2, D, X );
-						add( X, t, X );
-						SR3750();
-						add( One, Z, Y );
-						mul( Y, Half, Y );
-						mov( Q, X );
-						SR3750();
-						if(I == 0)
-							{
-							printf( "Anomaly 6\n" );
-							Anomaly = True;
-							}
-						}
-					}
-				}
-			}
-		}
-	if ((I == 0) || Anomaly)
-		{
-		ErrCnt[Failure] += 1;
-		printf( "Anomalous arithmetic with Integer < \n");
-		printf("Radix^Precision = " );
-		show( W );
-		printf(" fails test whether sqrt rounds or chops.\n");
-		SqRWrng = True;
-		}
-	}
-if(! Anomaly)
-	{
-	if(! ((cmp(MinSqEr,Zero) < 0) || (cmp(MaxSqEr,Zero) > 0))) {
-	RSqrt = Rounded;
-	printf("Square root appears to be correctly rounded.\n");
-	}
-	else
-		{
-		k = 0;
-		add( MaxSqEr, U2, t );
-		sub( Half, U2, t2 );
-		if( cmp(t,t2) > 0 )
-			k = 1;
-		if( cmp( MinSqEr, Half ) > 0 )
-			k = 1;
-		add( MinSqEr, Radix, t );
-		if( cmp( t, Half ) < 0 )
-			k = 1;
-		if( k == 1 )
-			SqRWrng = True;
-		else
-			{
-			RSqrt = Chopped;
-			printf("Square root appears to be chopped.\n");
-			}
-		}
-	}
-if( SqRWrng )
-	{
-	printf("Square root is neither chopped nor correctly rounded.\n");
-	printf("Observed errors run from " );
-	sub( Half, MinSqEr, t );
-	show( t );
-	printf("\tto " );
-	add( Half, MaxSqEr, t );
-	show( t );
-	printf( "ulps.\n" );
-	sub( MinSqEr, MaxSqEr, t );
-	mul( Radix, Radix, t2 );
-	if( cmp( t, t2 ) >= 0 )
-		{
-		ErrCnt[Serious] += 1;
-		printf( "sqrt gets too many last digits wrong\n");
-		}
-	}
-}
-
-Showsq( arg )
-int arg;
-{
-
-k = 0;
-if( arg <= 0 )
-	{
-	if( cmp(SqEr,MinSqEr) < 0 )
-		{
-		k = 1;
-		mov( SqEr, MinSqEr );
-		}
-	}
-if( arg >= 0 )
-	{
-	if( cmp(SqEr,MaxSqEr) > 0 )
-		{
-		k = 2;
-		mov( SqEr, MaxSqEr );
-		}
-	}
-#if DEBUG
-if( k != 0 )
-	{
-	printf( "Square root of " );
-	show( arg );
-	printf( "\tis in error by " );
-	show( SqEr );
-	}
-#endif
-}
-
-
-pow1test()
-{
-
-/*=============================================*/
-Milestone = 90;
-/*=============================================*/
-Pause();
-printf("Testing powers Z^i for small Integers Z and i.\n");
-N = 0;
-/* ... test powers of zero. */
-I = 0;
-mov( Zero, Z );
-neg(Z);
-M = 3;
-Break = False;
-do
-	{
-	mov( One, X );
-	SR3980();
-	if(I <= 10)
-		{
-		I = 1023;
-		SR3980();
-		}
-	if( cmp(Z,MinusOne) == 0 )
-		Break = True;
-	else
-		{
-		mov( MinusOne, Z );
-		PrintIfNPositive();
-		N = 0;
-/* .. if(-1)^N is invalid, replace MinusOne by One. */
-		I = - 4;
-		}
-	}
-while( ! Break );
-PrintIfNPositive();
-N1 = N;
-N = 0;
-mov( A1, Z );
-/*M = FLOOR(Two * LOG(W) / LOG(A1));*/
-LOG( W, t );
-mul( Two, t, t );
-FLOOR( t, t );
-LOG( A1, t2 );
-div( t2, t, t );
-FTOL( t, &lngint, t2 );
-M = lngint;
-Break = False;
-do
-	{
-	mov( Z, X );
-	I = 1;
-	SR3980();
-	if( cmp(Z,AInvrse) == 0 )
-		Break = True;
-	else
-		 mov( AInvrse, Z );
-	}
-while( ! (Break) );
-/*=============================================*/
-Milestone = 100;
-/*=============================================*/
-/*  Powers of Radix have been tested, */
-/*         next try a few primes     */
-
-M = NoTrials;
-
-mov( Three, Z );
-do
-	{
-	mov( Z, X );
-	I = 1;
-	SR3980();
-	do
-		{
-		add( Z, Two, Z );
-		div( Three, Z, t );
-		FLOOR( t, t );
-		mul( Three, t, t );
-		}
-	while( cmp(t,Z) == 0 );
-	mul( Eight, Three, t );
-	}
-while( cmp(Z,t) < 0 );
-
-if(N > 0)
-	{
-	printf("Errors like this may invalidate financial calculations\n");
-	printf("\tinvolving interest rates.\n");
-	}
-PrintIfNPositive();
-N += N1;
-if(N == 0)
-	printf("... no discrepancies found.\n");
-if(N > 0)
-	Pause();
-else printf("\n");
-}
-
-
-
-pow2test()
-{
-printf("\n");
-/* ...calculate Exp2 == exp(2) == 7.38905 60989 30650 22723 04275-... */
-mov( Zero, X );
-mov( Two, t2 ); /*I = 2;*/
-
-mul( Two, Three, Y );
-mov( Zero, Q );
-N = 0;
-do
-	{
-	mov( X, Z );
-	add( t2, One, t2 ); /*I = I + 1;*/
-	add( t2, t2, t );
-	div( t, Y, Y ); /*Y = Y / (I + I);*/
-	add( Y, Q, R );
-	add( Z, R, X );
-	sub( X, Z, Q );
-	add( Q, R, Q );
-	}
-while( cmp(X,Z) > 0 );
-
-/*Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo);*/
-div( Eight, One, t );
-add( OneAndHalf, t, Z );
-mul( OneAndHalf, ThirtyTwo, t );
-div( t, X, t );
-add( Z, t, Z );
-mul( Z, Z, X );
-mul( X, X, Exp2 );
-mov( F9, X );
-sub( U1, X, Y );
-printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = " );
-show( Exp2 );
-printf( "\tas X -> 1.\n" );
-for(I = 1;;)
-	{
-	sub( BInvrse, X, Z );
-/*Z = (X + One) / (Z - (One - BInvrse));*/
-	add( X, One, t2 );
-	sub( BInvrse, One, t );
-	sub( t, Z, t );
-	div( t, t2, Z );
-	POW( X, Z, Sqarg );
-	sub( Exp2, Sqarg, Q );
-	mov( Q, t );
-	FABS( t );
-	mul( TwoForty, U2, t2 );
-	if( cmp( t, t2 ) > 0 )
-		{
-		N = 1;
-		sub( BInvrse, X, V9 );
-		sub( BInvrse, One, t );
-		sub( t, V9, V9 );
-		ErrCnt[Defect] += 1;
-		printf( "Calculated " );
-		show( Sqarg );
-		printf(" for \t(1 + " );
-		show( V9 );
-		printf( "\tto the power " );
-		show( Z );
-		printf("\tdiffers from correct value by " );
-		show( Q );
-		printf("\tThis much error may spoil financial\n");
-		printf("\tcalculations involving tiny interest rates.\n");
-		break;
-		}
-	else
-		{
-		sub( X, Y, Z );
-		mul( Z, Two, Z );
-		add( Z, Y, Z );
-		mov( Y, X );
-		mov( Z, Y );
-		sub( F9, X, Z );
-		mul( Z, Z, Z );
-		add( Z, One, Z );
-		if( (cmp(Z,One) > 0) && (I < NoTrials) )
-			I++;
-		else
-			{
-			if( cmp(X,One) > 0 )
-				{
-				if(N == 0)
-					printf("Accuracy seems adequate.\n");
-				break;
-				}
-			else
-				{
-				add( One, U2, X );
-				add( U2, U2, Y );
-				add( X, Y, Y );
-				I = 1;
-				}
-			}
-		}
-	}
-/*=============================================*/
-Milestone = 150;
-/*=============================================*/
-printf("Testing powers Z^Q at four nearly extreme values.\n");
-N = 0;
-mov( A1, Z );
-/*Q = FLOOR(Half - LOG(C) / LOG(A1));*/
-LOG( C, t );
-LOG( A1, t2 );
-div( t2, t, t );
-sub( t, Half, t );
-FLOOR( t, Q );
-Break = False;
-do
-	{
-	mov( CInvrse, X );
-	POW( Z, Q, Y );
-	IsYeqX();
-	neg(Q);
-	mov( C, X );
-	POW( Z, Q, Y );
-	IsYeqX();
-	if( cmp(Z,One) < 0 )
-		Break = True;
-	else
-		mov( AInvrse, Z );
-	}
-while( ! (Break));
-PrintIfNPositive();
-if(N == 0)
-	printf(" ... no discrepancies found.\n");
-printf("\n");
-}
+/* paranoia.c arithmetic tester
+ *
+ * This is an implementation of the PARANOIA program.  It substitutes
+ * subroutine calls for ALL floating point arithmetic operations.
+ * This permits you to substitute your own experimental versions of
+ * arithmetic routines.  It also defeats compiler optimizations,
+ * so for native arithmetic you can be pretty sure you are testing
+ * the arithmetic and not the compiler.
+ *
+ * This version of PARANOIA omits the display of division by zero.
+ * It also omits the test for extra precise subexpressions, since
+ * they cannot occur in this context.  Otherwise it includes all the
+ * tests of the 27 Jan 86 distribution, plus a few additional tests.
+ * Commentary has been reduced to a minimum in order to make the program
+ * smaller.
+ *
+ * The original PARANOIA program, written by W. Kahan, C version
+ * by Thos Sumner and David Gay, can be downloaded free from the
+ * Internet NETLIB.  An MSDOS disk can be obtained for $15 from:
+ *   Richard Karpinski
+ *   6521 Raymond Street
+ *   Oakland, CA 94609
+ *
+ * Steve Moshier, 28 Oct 88
+ * last rev: 23 May 92
+ */
+
+#define DEBUG 0
+
+/* To use the native arithmetic of the computer, define NATIVE
+ * to be 1.  To use your own supplied arithmetic routines, NATIVE is 0.
+ */
+#define NATIVE 0
+
+/* gcc real.c interface */
+#define L128DOUBLE 0
+
+#include <stdio.h>
+
+
+
+
+/* Data structure of floating point number.  If NATIVE was
+ * selected above, you can define LDOUBLE 1 to test 80-bit long double
+ * precision or define it 0 to test 64-bit double precision.
+*/
+#define LDOUBLE 0
+#if NATIVE
+
+#define NE 1
+#if LDOUBLE
+#define FSIZE long double
+#define FLOAT(x) FSIZE x[NE]
+static FSIZE eone[NE] = {1.0L};	/* The constant 1.0 */
+#define ZSQRT sqrtl
+#define ZLOG logl
+#define ZFLOOR floorl
+#define ZPOW powl
+long double sqrtl(), logl(), floorl(), powl();
+#define FSETUP einit
+#else /* not LDOUBLE */
+#define FSIZE double
+#define FLOAT(x) FSIZE x[NE]
+static FSIZE eone[NE] = {1.0};	/* The constant 1.0 */
+#define ZSQRT sqrt
+#define ZLOG log
+#define ZFLOOR floor
+#define ZPOW pow
+double sqrt(), log(), floor(), pow();
+/* Coprocessor initialization,
+ * defeat underflow trap or what have you.
+ * This is required mainly on i386 and 68K processors.
+ */
+#define FSETUP dprec
+#endif /* double, not LDOUBLE */
+
+#else /* not NATIVE */
+
+/* Setup for extended double type.
+ * Put NE = 10 for real.c operating with TFmode support (16-byte reals)
+ * Put NE = 6 for real.c operating with XFmode support (10- or 12-byte reals)
+ * The value of NE must agree with that in ehead.h, if ieee.c is used.
+ */
+#define NE 6
+#define FSIZE unsigned short
+#define FLOAT(x) unsigned short x[NE]
+extern unsigned short eone[];
+#define FSETUP einit
+
+/* default for FSETUP */
+/*
+einit()
+{}
+*/
+
+error(s)
+char *s;
+{
+printf( "error: %s\n", s );
+}
+
+#endif	/* not NATIVE */
+
+
+
+#if L128DOUBLE
+/* real.c interface */
+
+#undef FSETUP
+#define FSETUP efsetup
+
+FLOAT(enone);
+
+#define ONE enone
+
+/* Use emov to convert from widest type to widest type, ... */
+/*
+#define ENTOE emov
+#define ETOEN emov
+*/
+
+/*                 ... else choose e24toe, e53toe, etc. */
+#define ENTOE e64toe
+#define ETOEN etoe64
+#define NNBITS 64
+
+#define NIBITS ((NE-1)*16)
+extern int rndprc;
+
+efsetup()
+{
+rndprc = NNBITS;
+ETOEN(eone, enone);
+}
+
+add(a,b,c)
+FLOAT(a);
+FLOAT(b);
+FLOAT(c);
+{
+unsigned short aa[10], bb[10], cc[10];
+
+ENTOE(a,aa);
+ENTOE(b,bb);
+eadd(aa,bb,cc);
+ETOEN(cc,c);
+}
+
+sub(a,b,c)
+FLOAT(a);
+FLOAT(b);
+FLOAT(c);
+{
+unsigned short aa[10], bb[10], cc[10];
+
+ENTOE(a,aa);
+ENTOE(b,bb);
+esub(aa,bb,cc);
+ETOEN(cc,c);
+}
+
+mul(a,b,c)
+FLOAT(a);
+FLOAT(b);
+FLOAT(c);
+{
+unsigned short aa[10], bb[10], cc[10];
+
+ENTOE(a,aa);
+ENTOE(b,bb);
+emul(aa,bb,cc);
+ETOEN(cc,c);
+}
+
+div(a,b,c)
+FLOAT(a);
+FLOAT(b);
+FLOAT(c);
+{
+unsigned short aa[10], bb[10], cc[10];
+
+ENTOE(a,aa);
+ENTOE(b,bb);
+ediv(aa,bb,cc);
+ETOEN(cc,c);
+}
+
+int cmp(a,b)
+FLOAT(a);
+FLOAT(b);
+{
+unsigned short aa[10], bb[10];
+int c;
+int ecmp();
+
+ENTOE(a,aa);
+ENTOE(b,bb);
+c = ecmp(aa,bb);
+return(c);
+}
+
+mov(a,b)
+FLOAT(a);
+FLOAT(b);
+{
+int i;
+
+for( i=0; i<NE; i++ )
+	b[i] = a[i];
+}
+
+
+neg(a)
+FLOAT(a);
+{
+unsigned short aa[10];
+
+ENTOE(a,aa);
+eneg(aa);
+ETOEN(aa,a);
+}
+
+clear(a)
+FLOAT(a);
+{
+int i;
+
+for( i=0; i<NE; i++ )
+	a[i] = 0;
+}
+
+FABS(a)
+FLOAT(a);
+{
+unsigned short aa[10];
+
+ENTOE(a,aa);
+eabs(aa);
+ETOEN(aa,a);
+}
+
+FLOOR(a,b)
+FLOAT(a);
+FLOAT(b);
+{
+unsigned short aa[10], bb[10];
+
+ENTOE(a,aa);
+efloor(aa,bb);
+ETOEN(bb,b);
+}
+
+LOG(a,b)
+FLOAT(a);
+FLOAT(b);
+{
+unsigned short aa[10], bb[10];
+int rndsav;
+
+ENTOE(a,aa);
+rndsav = rndprc;
+rndprc = NIBITS;
+elog(aa,bb);
+rndprc = rndsav;
+ETOEN(bb,b);
+}
+
+POW(a,b,c)
+FLOAT(a);
+FLOAT(b);
+FLOAT(c);
+{
+unsigned short aa[10], bb[10], cc[10];
+int rndsav;
+
+ENTOE(a,aa);
+ENTOE(b,bb);
+rndsav = rndprc;
+rndprc = NIBITS;
+epow(aa,bb,cc);
+rndprc = rndsav;
+ETOEN(cc,c);
+}
+
+SQRT(a,b)
+FLOAT(a);
+FLOAT(b);
+{
+unsigned short aa[10], bb[10];
+
+ENTOE(a,aa);
+esqrt(aa,bb);
+ETOEN(bb,b);
+}
+
+FTOL(x,ip,f)
+FLOAT(x);
+long *ip;
+FLOAT(f);
+{
+unsigned short xx[10], ff[10];
+
+ENTOE(x,xx);
+eifrac(xx,ip,ff);
+ETOEN(ff,f);
+}
+
+LTOF(ip,x)
+long *ip;
+FLOAT(x);
+{
+unsigned short xx[10];
+ltoe(ip,xx);
+ETOEN(xx,x);
+}
+
+TOASC(a,b,c)
+FLOAT(a);
+int b;
+char *c;
+{
+unsigned short xx[10];
+
+ENTOE(a,xx);
+etoasc(xx,b,c);
+}
+
+#else /* not L128DOUBLE */
+
+#define ONE eone
+
+/* Note all arguments of operation subroutines are pointers. */
+/* c = b + a */
+#define add(a,b,c) eadd(a,b,c)
+/* c = b - a */
+#define sub(a,b,c) esub(a,b,c)
+/* c = b * a */
+#define mul(a,b,c) emul(a,b,c)
+/* c = b / a */
+#define div(a,b,c) ediv(a,b,c)
+/* 1 if a>b, 0 if a==b, -1 if a<b */
+#define cmp(a,b) ecmp(a,b)
+/* b = a */
+#define mov(a,b) emov(a,b)
+/* a = -a */
+#define neg(a) eneg(a)
+/* a = 0 */
+#define clear(a) eclear(a)
+
+#define FABS(x) eabs(x)
+#define FLOOR(x,y) efloor(x,y)
+#define LOG(x,y) elog(x,y)
+#define POW(x,y,z) epow(x,y,z)
+#define SQRT(x,y) esqrt(x,y)
+
+/* x = &FLOAT input, i = &long integer part, f = &FLOAT fractional part */
+#define FTOL(x,i,f) eifrac(x,i,f)
+
+/* i = &long integer input, x = &FLOAT output */
+#define LTOF(i,x) ltoe(i,x)
+
+/* Convert FLOAT a to decimal ASCII string with b digits */
+#define TOASC(a,b,c) etoasc(a,b,c)
+#endif /* not L128DOUBLE */
+
+
+
+/* The following subroutines are implementations of the above
+ * named functions, using the native or default arithmetic.
+ */
+#if NATIVE
+eadd(a,b,c)
+FSIZE *a, *b, *c;
+{
+*c = *b + *a;
+}
+
+esub(a,b,c)
+FSIZE *a, *b, *c;
+{
+*c = *b - *a;
+}
+
+emul(a,b,c)
+FSIZE *a, *b, *c;
+{
+*c = (*b) * (*a);
+}
+
+ediv(a,b,c)
+FSIZE *a, *b, *c;
+{
+*c = (*b) / (*a);
+}
+
+
+/* Important note: comparison can be done by subracting
+ * or by a compare instruction that may or may not be
+ * equivalent to subtracting.
+ */
+ecmp(a,b)
+FSIZE *a, *b;
+{
+if( (*a) > (*b) )
+	return( 1 );
+if( (*a) < (*b) )
+	return( -1 );
+if( (*a) != (*b) )
+	goto cmpf;
+if( (*a) == (*b) )
+	return( 0 );
+cmpf:
+printf( "Compare fails\n" );
+return(0);
+}
+
+
+emov( a, b )
+FSIZE *a, *b;
+{
+*b = *a;
+}
+
+eneg( a )
+FSIZE *a;
+{
+*a = -(*a);
+}
+
+eclear(a)
+FSIZE *a;
+{
+*a = 0.0;
+}
+
+eabs(x)
+FSIZE *x;
+{
+if( (*x) < 0.0 )
+	*x = -(*x);
+}
+
+efloor(x,y)
+FSIZE *x, *y;
+{
+
+*y = (FSIZE )ZFLOOR( *x );
+}
+
+elog(x,y)
+FSIZE *x, *y;
+{
+
+*y = (FSIZE )ZLOG( *x );
+}
+
+epow(x,y,z)
+FSIZE *x, *y, *z;
+{
+
+*z = (FSIZE )ZPOW( *x, *y );
+}
+
+esqrt(x,y)
+FSIZE *x, *y;
+{
+
+*y = (FSIZE )ZSQRT( *x );
+}
+
+
+eifrac(x,i,f)
+FSIZE *x;
+long *i;
+FSIZE *f;
+{
+FSIZE y;
+
+y = (FSIZE )ZFLOOR( *x );
+if( y < 0.0 )
+	{
+	*f = y - *x;
+	*i = -y;
+	}
+else
+	{
+	*f = *x - y;
+	*i = y;
+	}
+}
+
+
+ltoe(i,x)
+long *i;
+FSIZE *x;
+{
+*x = *i;
+}
+
+
+etoasc(a,str,n)
+FSIZE *a;
+char *str;
+int n;
+{
+double x;
+
+x = (double )(*a);
+sprintf( str, " %.17e ", x );
+}
+
+/* default for FSETUP */
+einit()
+{}
+
+#endif	/* NATIVE */
+
+
+
+
+FLOAT(Radix);
+FLOAT(BInvrse);
+FLOAT(RadixD2);
+FLOAT(BMinusU2);
+/*Small floating point constants.*/
+FLOAT(Zero);
+FLOAT(Half);
+FLOAT(One);
+FLOAT(Two);
+FLOAT(Three);
+FLOAT(Four);
+FLOAT(Five);
+FLOAT(Six);
+FLOAT(Eight);
+FLOAT(Nine);
+FLOAT(Ten);
+FLOAT(TwentySeven);
+FLOAT(ThirtyTwo);
+FLOAT(TwoForty);
+FLOAT(MinusOne );
+FLOAT(OneAndHalf);
+
+/*Integer constants*/
+int NoTrials = 20; /*Number of tests for commutativity. */
+#define False 0
+#define True 1
+
+/* Definitions for declared types 
+	Guard == (Yes, No);
+	Rounding == (Chopped, Rounded, Other);
+	Message == packed array [1..40] of char;
+	Class == (Flaw, Defect, Serious, Failure);
+	  */
+#define Yes 1
+#define No  0
+#define Chopped 2
+#define Rounded 1
+#define Other   0
+#define Flaw    3
+#define Defect  2
+#define Serious 1
+#define Failure 0
+
+typedef int Guard, Rounding, Class;
+typedef char Message;
+
+/* Declarations of Variables */
+FLOAT(AInvrse);
+FLOAT(A1);
+FLOAT(C);
+FLOAT(CInvrse);
+FLOAT(D);
+FLOAT(FourD);
+FLOAT(E0);
+FLOAT(E1);
+FLOAT(Exp2);
+FLOAT(E3);
+FLOAT(MinSqEr);
+FLOAT(SqEr);
+FLOAT(MaxSqEr);
+FLOAT(E9);
+FLOAT(Third);
+FLOAT(F6);
+FLOAT(F9);
+FLOAT(H);
+FLOAT(HInvrse);
+FLOAT(StickyBit);
+FLOAT(J);
+FLOAT(MyZero);
+FLOAT(Precision);
+FLOAT(Q);
+FLOAT(Q9);
+FLOAT(R);
+FLOAT(Random9);
+FLOAT(T);
+FLOAT(Underflow);
+FLOAT(S);
+FLOAT(OneUlp);
+FLOAT(UfThold);
+FLOAT(U1);
+FLOAT(U2);
+FLOAT(V);
+FLOAT(V0);
+FLOAT(V9);
+FLOAT(W);
+FLOAT(X);
+FLOAT(X1);
+FLOAT(X2);
+FLOAT(X8);
+FLOAT(Random1);
+FLOAT(Y);
+FLOAT(YY1);
+FLOAT(Y2);
+FLOAT(Random2);
+FLOAT(Z);
+FLOAT(PseudoZero);
+FLOAT(Z1);
+FLOAT(Z2);
+FLOAT(Z9);
+static FLOAT(t);
+FLOAT(t2);
+FLOAT(Sqarg);
+int ErrCnt[4];
+int fpecount;
+int Milestone;
+int PageNo;
+int I, M, N, N1, stkflg;
+Guard GMult, GDiv, GAddSub;
+Rounding RMult, RDiv, RAddSub, RSqrt;
+int Break, Done, NotMonot, Monot, Anomaly, IEEE;
+int SqRWrng, UfNGrad;
+int k, k2;
+int Indx;
+char ch[8];
+
+long lngint, lng2; /* intermediate for conversion between int and FLOAT */
+
+/* Computed constants. */
+/*U1  gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
+/*U2  gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
+
+
+show( x )
+short x[];
+{
+int i;
+char s[80];
+
+/* Number of 16-bit groups to display */
+#if NATIVE
+#if LDOUBLE
+#define NPRT (sizeof( long double )/2)
+#else
+#define NPRT (sizeof( double )/2)
+#endif
+#else
+#define NPRT NE
+#endif
+
+TOASC( x, s, 70 );
+printf( "%s\n", s );
+for( i=0; i<NPRT; i++ )
+	printf( "%04x ", x[i] & 0xffff );
+printf( "\n" );
+}
+
+/* define NOSIGNAL */
+#ifndef NOSIGNAL
+#include <signal.h>
+#endif
+#include <setjmp.h>
+jmp_buf ovfl_buf;
+/*typedef int (*Sig_type)();*/
+typedef void (*Sig_type)();
+Sig_type sigsave;
+
+/* Floating point exception receiver */
+void sigfpe()
+{
+fpecount++;
+printf( "\n* * * FLOATING-POINT ERROR * * *\n" );
+/* reinitialize the floating point unit */
+FSETUP();
+fflush(stdout);
+if( sigsave )
+	{
+#ifndef NOSIGNAL
+	signal( SIGFPE, sigsave );
+#endif
+	sigsave = 0;
+	longjmp( ovfl_buf, 1 );
+	}
+abort();
+}
+
+
+main()
+{
+
+/* Do coprocessor or other initializations */
+FSETUP();
+
+printf(
+ "This version of paranoia omits test for extra precise subexpressions\n" );
+printf( "and includes a few additional tests.\n" );
+
+clear(Zero);
+printf( "0 = " );
+show( Zero );
+mov( ONE, One);
+printf( "1 = " );
+show( One );
+add( One, One, Two );
+printf( "1+1 = " );
+show( Two );
+add( Two, One, Three );
+add( Three, One, Four );
+add( Four, One, Five );
+add( Five, One, Six );
+add( Four, Four, Eight );
+mul( Three, Three, Nine );
+add( Nine, One, Ten );
+mul( Nine, Three, TwentySeven );
+mul( Four, Eight, ThirtyTwo );
+mul( Four, Five, t );
+mul( t, Three, t );
+mul( t, Four, TwoForty );
+mov( One, MinusOne );
+neg( MinusOne );
+div( Two, One, Half );
+add( One, Half, OneAndHalf );
+ErrCnt[Failure] = 0;
+ErrCnt[Serious] = 0;
+ErrCnt[Defect] = 0;
+ErrCnt[Flaw] = 0;
+PageNo = 1;
+#ifndef NOSIGNAL
+signal( SIGFPE, sigfpe );
+#endif
+printf("Program is now RUNNING tests on small integers:\n");
+
+add( Zero, Zero, t );
+if( cmp( t, Zero ) != 0)
+	{
+	printf( "0+0 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+sub( One, One, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "1-1 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+if( cmp( One, Zero ) <= 0 )
+	{
+	printf( "1 <= 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+add( One, One, t );
+if( cmp( t, Two ) != 0 )
+	{
+	printf( "1+1 != 2\n" );
+	ErrCnt[Failure] += 1;
+	}
+mov( Zero, Z );
+neg( Z );
+FLOOR( Z, t );
+if( cmp(t,Zero) != 0 )
+	{
+	ErrCnt[Serious] += 1;
+	printf( "FLOOR(-0) should equal 0, is = " );
+	show( t );
+	}
+if( cmp(Z, Zero) != 0)
+	{
+	ErrCnt[Failure] += 1;
+	printf("Comparison alleges that -0.0 is Non-zero!\n");
+	}
+else
+	{
+	div( TwoForty, One, U1 ); /* U1 = 0.001 */
+	mov( One, Radix );
+	TstPtUf();
+	}
+add( Two, One, t );
+if( cmp( t, Three ) != 0 )
+	{
+	printf( "2+1 != 3\n" );
+	ErrCnt[Failure] += 1;
+	}
+add( Three, One, t );
+if( cmp( t, Four ) != 0 )
+	{
+	printf( "3+1 != 4\n" );
+	ErrCnt[Failure] += 1;
+	}
+mov( Two, t );
+neg( t );
+mul( Two, t, t );
+add( Four, t, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "4+2*(-2) != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+sub( Three, Four, t );
+sub( One, t, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "4-3-1 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+	sub( One, Zero, t );
+if( cmp( t, MinusOne ) != 0 )
+	{
+	printf( "-1 != 0-1\n" );
+	ErrCnt[Failure] += 1;
+	}
+add( One, MinusOne, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "1+(-1) != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+mov( One, t );
+FABS( t );
+add( MinusOne, t, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "-1+abs(1) != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+mul( MinusOne, MinusOne, t );
+add( MinusOne, t, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "-1+(-1)*(-1) != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+add( Half, MinusOne, t );
+add( Half, t, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "1/2 + (-1) + 1/2 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+Milestone = 10;
+mul( Three, Three, t );
+if( cmp( t, Nine ) != 0 )
+	{
+	printf( "3*3 != 9\n" );
+	ErrCnt[Failure] += 1;
+	}
+mul( Nine, Three, t );
+if( cmp( t, TwentySeven ) != 0 )
+	{
+	printf( "3*9 != 27\n" );
+	ErrCnt[Failure] += 1;
+	}
+add( Four, Four, t );
+if( cmp( t, Eight ) != 0 )
+	{
+	printf( "4+4 != 8\n" );
+	ErrCnt[Failure] += 1;
+	}
+mul( Eight, Four, t );
+if( cmp( t, ThirtyTwo ) != 0 )
+	{
+	printf( "8*4 != 32\n" );
+	ErrCnt[Failure] += 1;
+	}
+sub( TwentySeven, ThirtyTwo, t );
+sub( Four, t, t );
+sub( One, t, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "32-27-4-1 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+add( Four, One, t );
+if( cmp( t, Five ) != 0 )
+	{
+	printf( "4+1 != 5\n" );
+	ErrCnt[Failure] += 1;
+	}
+mul( Four, Five, t );
+mul( Three, t, t );
+mul( Four, t, t );
+if( cmp( t, TwoForty ) != 0 )
+	{
+	printf( "4*5*3*4 != 240\n" );
+	ErrCnt[Failure] += 1;
+	}
+div( Three, TwoForty, t );
+mul( Four, Four, t2 );
+mul( Five, t2, t2 );
+sub( t2, t2, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "240/3 - 4*4*5 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+div( Four, TwoForty, t );
+mul( Five, Three, t2 );
+mul( Four, t2, t2 );
+sub( t2, t, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "240/4 - 5*3*4 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+div( Five, TwoForty, t );
+mul( Four, Three, t2 );
+mul( Four, t2, t2 );
+sub( t2, t, t );
+if( cmp( t, Zero ) != 0 )
+	{
+	printf( "240/5 - 4*3*4 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+if(ErrCnt[Failure] == 0)
+	{
+printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n\n");
+	}
+printf("Searching for Radix and Precision.\n");
+mov( One, W );
+do
+	{
+	add( W, W, W );
+	add( W, One, Y );
+	sub( W, Y, Z );
+	sub( One, Z, Y );
+	mov( Y, t );
+	FABS(t);
+	add( MinusOne, t, t );
+	k = cmp( t, Zero );
+	}
+while( k < 0 );
+/*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/
+mov( Zero, Precision );
+mov( One, Y );
+do
+	{
+	add( W, Y, Radix );
+	add( Y, Y, Y );
+	sub( W, Radix, Radix );
+	k = cmp( Radix, Zero );
+	}
+while( k == 0);
+
+if( cmp(Radix, Two) < 0 )
+	mov( One, Radix );
+printf("Radix = " );
+show( Radix );
+if( cmp(Radix, One) != 0)
+	{
+	mov( One, W );
+	do
+		{
+		add( One, Precision, Precision );
+		mul( W, Radix, W );
+		add( W, One, Y );
+		sub( W, Y, t );
+		k = cmp( t, One );
+		}
+	while( k == 0 );
+	}
+/* now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1 */
+div( W, One, U1 );
+mul( Radix, U1, U2 );
+printf( "Closest relative separation found is U 1 = " );
+show( U1 );
+printf( "Recalculating radix and precision." );
+	
+/*save old values*/
+mov( Radix, E0 );
+mov( U1, E1 );
+mov( U2, E9 );
+mov( Precision, E3 );
+	
+div( Three, Four, X );
+sub( One, X, Third );
+sub( Third, Half, F6 );
+add( F6, F6, X );
+sub( Third, X, X );
+FABS( X );
+if( cmp(X, U2) < 0 )
+	mov( U2, X );
+	
+/*... now X = (unknown no.) ulps of 1+...*/
+do
+	{
+	mov( X, U2 );
+/* Y = Half * U2 + ThirtyTwo * U2 * U2; */
+	mul( ThirtyTwo, U2, t );
+	mul( t, U2, t );
+	mul( Half, U2, Y );
+	add( t, Y, Y );
+	add( One, Y, Y );
+	sub( One, Y, X );
+	k = cmp( U2, X );
+	k2 = cmp( X, Zero );
+	}
+while ( ! ((k <= 0) || (k2 <= 0)));
+	
+/*... now U2 == 1 ulp of 1 + ... */
+div( Three, Two, X );
+sub( Half, X, F6 );
+add( F6, F6, Third );
+sub( Half, Third, X );
+add( F6, X, X );
+FABS( X );
+if( cmp(X, U1) < 0 )
+	mov( U1, X );
+	
+/*... now  X == (unknown no.) ulps of 1 -... */
+do
+	{
+	mov( X, U1 );
+ /* Y = Half * U1 + ThirtyTwo * U1 * U1;*/
+	mul( ThirtyTwo, U1, t );
+	mul( U1, t, t );
+	mul( Half, U1, Y );
+	add( t, Y, Y );
+	sub( Y, Half, Y );
+	add( Half, Y, X );
+	sub( X, Half, Y );
+	add( Half, Y, X );
+	k = cmp( U1, X );
+	k2 = cmp( X, Zero );
+	} while ( ! ((k <= 0) || (k2 <= 0)));
+/*... now U1 == 1 ulp of 1 - ... */
+if( cmp( U1, E1 ) == 0 )
+	printf("confirms closest relative separation U1 .\n");
+else
+	{
+	printf("gets better closest relative separation U1 = " );
+	show( U1 );
+	}
+div( U1, One, W );
+sub( U1, Half, F9 );
+add( F9, Half, F9 );
+div( U1, U2, t );
+div( TwoForty, One, t2 );
+add( t2, t, t );
+FLOOR( t, Radix );
+if( cmp(Radix, E0) == 0 )
+	printf("Radix confirmed.\n");
+else
+	{
+	printf("MYSTERY: recalculated Radix = " );
+	show( Radix );
+	mov( E0, Radix );
+	}
+add( Eight, Eight, t );
+if( cmp( Radix, t ) > 0 )
+	{
+	printf( "Radix is too big: roundoff problems\n" );
+	ErrCnt[Defect] += 1;
+	}
+k = 1;
+if( cmp( Radix, Two ) == 0 )
+	k = 0;
+if( cmp( Radix, Ten ) == 0 )
+	k = 0;
+if( cmp( Radix, One ) == 0 )
+	k = 0;
+if( k != 0 )
+	{
+	printf( "Radix is not as good as 2 or 10\n" );
+	ErrCnt[Flaw] += 1;
+	}
+/*=============================================*/
+Milestone = 20;
+/*=============================================*/
+sub( Half, F9, t );
+if( cmp( t, Half ) >= 0 )
+	{
+	printf( "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?\n" );
+	ErrCnt[Failure] += 1;
+	}
+mov( F9, X );
+I = 1;
+sub( Half, X, Y );
+sub( Half, Y, Z );
+if( (cmp( X, One ) == 0) && (cmp( Z, Zero) != 0) )
+	{
+	printf( "Comparison is fuzzy ,X=1 but X-1/2-1/2 != 0\n" );
+	ErrCnt[Failure] += 1;
+	}
+add( One, U2, X );
+I = 0;
+/*=============================================*/
+Milestone = 25;
+/*=============================================*/
+/*... BMinusU2 = nextafter(Radix, 0) */
+
+sub( One, Radix, BMinusU2 );
+sub( U2, BMinusU2, t );
+add( One, t, BMinusU2 );
+/* Purify Integers */
+if( cmp(Radix,One) != 0 )
+	{
+/*X = - TwoForty * LOG(U1) / LOG(Radix);*/
+	LOG( U1, X );
+	LOG( Radix, t );
+	div( t, X, X );
+	mul( TwoForty, X, X );
+	neg( X );	
+
+	add( Half, X, Y );
+	FLOOR( Y, Y );
+	sub( Y, X, t );
+	FABS( t );
+	mul( Four, t, t );
+	if( cmp( t, One ) < 0 )
+		mov( Y, X );
+	div( TwoForty, X, Precision );
+	add( Half, Precision, Y );
+	FLOOR( Y, Y );
+	sub( Y, Precision, t );
+	FABS( t );
+	mul( TwoForty, t, t );
+	if( cmp( t, Half ) < 0 )
+		mov( Y, Precision );
+	}
+FLOOR( Precision, t );
+if( (cmp( Precision, t ) != 0) || (cmp( Radix, One ) == 0) )
+	{
+	printf("Precision cannot be characterized by an Integer number\n");
+	printf("of significant digits but, by itself, this is a minor flaw.\n");
+	}
+if( cmp(Radix, One) == 0 ) 
+	printf("logarithmic encoding has precision characterized solely by U1.\n");
+else
+	{
+	printf("The number of significant digits of the Radix is " );
+	show( Precision );
+	}
+mul( U2, Nine, t );
+mul( Nine, t, t );
+mul( TwoForty, t, t );
+if( cmp( t, One ) >= 0 )
+	{
+	printf( "Precision worse than 5 decimal figures\n" );
+	ErrCnt[Serious] += 1;
+	}
+/*=============================================*/
+Milestone = 30;
+/*=============================================*/
+/* Test for extra-precise subepressions has been deleted. */
+Milestone = 35;
+/*=============================================*/
+if( cmp(Radix,Two) >= 0 )
+	{
+	mul( Radix, Radix, t );
+	div( t, W, X );
+	add( X, One, Y );
+	sub( X, Y, Z );
+	add( Z, U2, T );
+	sub( Z, T, X );
+	if( cmp( X, U2 ) != 0 )
+		{
+		printf( "Subtraction is not normalized X=Y,X+Z != Y+Z!\n" );
+		ErrCnt[Failure] += 1;
+		}
+	if( cmp(X,U2) == 0 )
+	 printf("Subtraction appears to be normalized, as it should be.");
+	}
+
+printf("\nChecking for guard digit in *, /, and -.\n");
+mul( F9, One, Y );
+mul( One, F9, Z );
+sub( Half, F9, X );
+sub( Half, Y, Y );
+sub( X, Y, Y );
+sub( Half, Z, Z );
+sub( X, Z, Z );
+add( One, U2, X );
+mul( X, Radix, T );
+mul( Radix, X, R );
+sub( Radix, T, X );
+mul( Radix, U2, t );
+sub( t, X, X );
+sub( Radix, R, T );
+mul( Radix, U2, t );
+sub( t, T, T );
+sub( One, Radix, t );
+mul( t, X, X );
+sub( One, Radix, t );
+mul( t, T, T );
+
+k = cmp(X,Zero);
+k |= cmp(Y,Zero);
+k |= cmp(Z,Zero);
+k |= cmp(T,Zero);
+if( k == 0 )
+	GMult = Yes;
+else
+	{
+	GMult = No;
+	ErrCnt[Serious] += 1;
+	printf( "* lacks a Guard Digit, so 1*X != X\n" );
+	}
+mul( Radix, U2, Z );
+add( One, Z, X );
+add( X, Z, Y );
+mul( X, X, t );
+sub( t, Y, Y );
+FABS( Y );
+sub( U2, Y, Y );
+sub( U2, One, X );
+sub( U2, X, Z );
+mul( X, X, t );
+sub( t, Z, Z );
+FABS( Z );
+sub( U1, Z, Z );
+if( (cmp(Y,Zero) > 0) || (cmp(Z,Zero) > 0) )
+	{
+	ErrCnt[Failure] += 1;
+	printf( "* gets too many final digits wrong.\n" );
+	}
+sub( U2, One, Y );
+add( One, U2, X );
+div( Y, One, Z );
+sub( X, Z, Y );
+div( Three, One, X );
+div( Nine, Three, Z );
+sub( Z, X, X );
+div( TwentySeven, Nine, T );
+sub( T, Z, Z );
+k = cmp( X, Zero );
+k |= cmp( Y, Zero );
+k |= cmp( Z, Zero );
+if( k )
+	{
+	ErrCnt[Defect] += 1;
+printf( "Division lacks a Guard Digit, so error can exceed 1 ulp\n" );
+printf( "or  1/3  and  3/9  and  9/27 may disagree\n" );
+	}
+div( One, F9, Y );
+sub( Half, F9, X );
+sub( Half, Y, Y );
+sub( X, Y, Y );
+add( One, U2, X );
+div( One, X, T );
+sub( X, T, X );
+k = cmp( X, Zero );
+k |= cmp( Y, Zero );
+k |= cmp( Z, Zero );
+if( k == 0 )
+	GDiv = Yes;
+else
+	{
+	GDiv = No;
+	ErrCnt[Serious] += 1;
+	printf( "Division lacks a Guard Digit, so X/1 != X\n" );
+	}
+add( One, U2, X );
+div( X, One, X );
+sub( Half, X, Y );
+sub( Half, Y, Y );
+if( cmp(Y,Zero) >= 0 )
+	{
+	ErrCnt[Serious] += 1;
+	printf( "Computed value of 1/1.000..1 >= 1\n" );
+	}
+sub( U2, One, X );
+mul( Radix, U2, Y );
+add( One, Y, Y );
+mul( X, Radix, Z );
+mul( Y, Radix, T );
+div( Radix, Z, R );
+div( Radix, T, StickyBit );
+sub( X, R, X );
+sub( Y, StickyBit, Y );
+k = cmp( X, Zero );
+k |= cmp( Y, Zero );
+if( k )
+	{
+	ErrCnt[Failure] += 1;
+	printf( "* and/or / gets too many last digits wrong\n" );
+	}
+sub( U1, One, Y );
+sub( F9, One, X );
+sub( Y, One, Y );
+sub( U2, Radix, T );
+sub( BMinusU2, Radix, Z );
+sub( T, Radix, T );
+k = cmp( X, U1 );
+k |= cmp( Y, U1 );
+k |= cmp( Z, U2 );
+k |= cmp( T, U2 );
+if( k == 0 )
+	GAddSub = Yes;
+else
+	{
+	GAddSub = No;
+	ErrCnt[Serious] += 1;
+	printf( "- lacks Guard Digit, so cancellation is obscured\n" );
+	}
+sub( One, F9, t );
+if( (cmp(F9,One) != 0) && (cmp(t,Zero) >= 0) )
+	{
+	ErrCnt[Serious] += 1;
+	printf("comparison alleges  (1-U1) < 1  although\n");
+	printf("  subtration yields  (1-U1) - 1 = 0 , thereby vitiating\n");
+	printf("  such precautions against division by zero as\n");
+	printf("  ...  if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
+	}
+if (GMult == Yes && GDiv == Yes && GAddSub == Yes)
+	printf(" *, /, and - appear to have guard digits, as they should.\n");
+/*=============================================*/
+Milestone = 40;
+/*=============================================*/
+printf("Checking rounding on multiply, divide and add/subtract.\n");
+RMult = Other;
+RDiv = Other;
+RAddSub = Other;
+div( Two, Radix, RadixD2 );
+mov( Two, A1 );
+Done = False;
+do
+	{
+	mov( Radix, AInvrse );
+	do
+		{
+		mov( AInvrse, X );
+		div( A1, AInvrse, AInvrse );
+		FLOOR( AInvrse, t );
+		k = cmp( t, AInvrse );
+		}
+	while( ! (k != 0 ) );
+	k = cmp( X, One );
+	k2 = cmp( A1, Three );
+	Done = (k == 0) || (k2 > 0);
+	if(! Done)
+		add( Nine, One, A1 );
+	}
+while( ! (Done));
+if( cmp(X, One) == 0 )
+	mov( Radix, A1 );
+div( A1, One, AInvrse );
+mov( A1, X );
+mov( AInvrse, Y );
+Done = False;
+do
+	{
+	mul( X, Y, Z );
+	sub( Half, Z, Z );
+	if( cmp( Z, Half ) != 0 )
+		{
+		ErrCnt[Failure] += 1;
+		printf( "X * (1/X) differs from 1\n" );
+		}
+	k = cmp( X, Radix );
+	Done = (k == 0);
+	mov( Radix, X );
+	div( X, One, Y );
+	}
+while( ! (Done));
+
+add( One, U2, Y2 );
+sub( U2, One, YY1 );
+sub( U2, OneAndHalf, X );
+add( OneAndHalf, U2, Y );
+sub( U2, X, Z );
+mul( Z, Y2, Z );
+mul( Y, YY1, T );
+sub( X, Z, Z );
+sub( X, T, T );
+mul( X, Y2, X );
+add( Y, U2, Y );
+mul( Y, YY1, Y );
+sub( OneAndHalf, X, X );
+sub( OneAndHalf, Y, Y );
+k = cmp( X, Zero );
+k |= cmp( Y, Zero );
+k |= cmp( Z, Zero );
+if( cmp( T, Zero ) > 0 )
+	k = 1;
+if( k == 0 )
+	{
+	add( OneAndHalf, U2, X );
+	mul( X, Y2, X );
+	sub( U2, OneAndHalf, Y );
+	sub( U2, Y, Y );
+	add( OneAndHalf, U2, Z );
+	add( U2, Z, Z );
+	sub( U2, OneAndHalf, T );
+	mul( T, YY1, T );
+	add( Z, U2, t );
+	sub( t, X, X );
+	mul( Y, YY1, StickyBit );
+	mul( Z, Y2, S );
+	sub( Y, T, T );
+	sub( Y, U2, Y );
+	add( StickyBit, Y, Y );
+/* Z = S - (Z + U2 + U2); */
+	add( Z, U2, t );
+	add( t, U2, t );
+	sub( t, S, Z );
+	add( Y2, U2, t );
+	mul( t, YY1, StickyBit );
+	mul( Y2, YY1, YY1 );
+	sub( Y2, StickyBit, StickyBit );
+	sub( Half, YY1, YY1 );
+	k = cmp( X, Zero );
+	k |= cmp( Y, Zero );
+	k |= cmp( Z, Zero );
+	k |= cmp( T, Zero );
+	k |= cmp( StickyBit, Zero );
+	k |= cmp( YY1, Half );
+	if( k == 0 )
+		{
+		RMult = Rounded;
+		printf("Multiplication appears to round correctly.\n");
+		}
+	else
+		{
+		add( X, U2, t );
+		k = cmp( t, Zero );
+		if( cmp( Y, Zero ) >= 0 )
+			k |= 1;
+		add( Z, U2, t );
+		k |= cmp( t, Zero );
+		if( cmp( T, Zero ) >= 0 )
+			k |= 1;
+		add( StickyBit, U2, t );
+		k |= cmp( t, Zero );
+		if( cmp(YY1, Half) >= 0 )
+			k |= 1;
+		if( k == 0 )
+			{
+			printf("Multiplication appears to chop.\n");
+			}
+		else
+			{
+		printf("* is neither chopped nor correctly rounded.\n");
+			}
+		if( (RMult == Rounded) && (GMult == No) )
+			printf("Multiplication has inconsistent result");
+		}
+	}
+else
+	printf("* is neither chopped nor correctly rounded.\n");
+
+/*=============================================*/
+Milestone = 45;
+/*=============================================*/
+add( One, U2, Y2 );
+sub( U2, One, YY1 );
+add( OneAndHalf, U2, Z );
+add( Z, U2, Z );
+div( Y2, Z, X );
+sub( U2, OneAndHalf, T );
+sub( U2, T, T );
+sub( U2, T, Y );
+div( YY1, Y, Y );
+add( Z, U2, Z );
+div( Y2, Z, Z );
+sub( OneAndHalf, X, X );
+sub( T, Y, Y );
+div( YY1, T, T );
+add( OneAndHalf, U2, t );
+sub( t, Z, Z );
+sub( OneAndHalf, U2, t );
+add( t, T, T );
+k = 0;
+if( cmp( X, Zero ) > 0 )
+	k = 1;
+if( cmp( Y, Zero ) > 0 )
+	k = 1;
+if( cmp( Z, Zero ) > 0 )
+	k = 1;
+if( cmp( T, Zero ) > 0 )
+	k = 1;
+if( k == 0 )
+	{
+	div( Y2, OneAndHalf, X );
+	sub( U2, OneAndHalf, Y );
+	add( U2, OneAndHalf, Z );
+	sub( Y, X, X );
+	div( YY1, OneAndHalf, T );
+	div( YY1, Y, Y );
+	add( Z, U2, t );
+	sub( t, T, T );
+	sub( Z, Y, Y );
+	div( Y2, Z, Z );
+	add( Y2, U2, YY1 );
+	div( Y2, YY1, YY1 );
+	sub( OneAndHalf, Z, Z );
+	sub( Y2, YY1, Y2 );
+	sub( U1, F9, YY1 );
+	div( F9, YY1, YY1 );
+	k = cmp( X, Zero );
+	k |= cmp( Y, Zero );
+	k |= cmp( Z, Zero );
+	k |= cmp( T, Zero );
+	k |= cmp( Y2, Zero );
+	sub( Half, YY1, t );
+	sub( Half, F9, t2 );
+	k |= cmp( t, t2 );
+	if( k == 0 )
+		{
+		RDiv = Rounded;
+		printf("Division appears to round correctly.\n");
+		if(GDiv == No)
+			printf("Division test inconsistent\n");
+		}
+	else
+		{
+		k = 0;
+		if( cmp( X, Zero ) >= 0 )
+			k = 1;
+		if( cmp( Y, Zero ) >= 0 )
+			k = 1;
+		if( cmp( Z, Zero ) >= 0 )
+			k = 1;
+		if( cmp( T, Zero ) >= 0 )
+			k = 1;
+		if( cmp( Y, Zero ) >= 0 )
+			k = 1;
+		sub( Half, YY1, t );
+		sub( Half, F9, t2 );
+		if( cmp( t, t2 ) >= 0 )
+			k = 1;
+		if( k == 0 )
+			{
+			RDiv = Chopped;
+			printf("Division appears to chop.\n");
+			}
+		}
+	}
+if(RDiv == Other)
+	printf("/ is neither chopped nor correctly rounded.\n");
+div( Radix, One, BInvrse );
+mul( BInvrse, Radix, t );
+sub( Half, t, t );
+if( cmp( t, Half ) != 0 )
+	{
+	ErrCnt[Failure] += 1;
+	printf( "Radix * ( 1 / Radix ) differs from 1\n" );
+	}
+
+Milestone = 50;
+/*=============================================*/
+add( F9, U1, t );
+sub( Half, t, t );
+k = cmp( t, Half );
+add( BMinusU2, U2, t );
+sub( One, t, t );
+sub( One, Radix, t2 );
+k |= cmp( t, t2 );
+if( k != 0 )
+	{
+	ErrCnt[Failure] += 1;
+	printf( "Incomplete carry-propagation in Addition\n" );
+	}
+mul( U1, U1, X );
+sub( X, One, X );
+sub( U2, One, Y );
+mul( U2, Y, Y );
+add( One, Y, Y );
+sub( Half, F9, Z );
+sub( Half, X, X );
+sub( Z, X, X );
+sub( One, Y, Y );
+if( (cmp(X,Zero) == 0) && (cmp(Y,Zero) == 0) )
+	{
+	RAddSub = Chopped;
+	printf("Add/Subtract appears to be chopped.\n");
+	}
+if(GAddSub == Yes)
+	{
+	add( Half, U2, X );
+	mul( X, U2, X );
+	sub( U2, Half, Y );
+	mul( Y, U2, Y );
+	add( One, X, X );
+	add( One, Y, Y );
+	add( One, U2, t );
+	sub( X, t, X );
+	sub( Y, One, Y );
+	k = cmp(X,Zero);
+	if( k )
+		printf( "1+U2-[u2(1/2+U2)+1] != 0\n" );
+	k2 = cmp(Y,Zero);
+	if( k2 )
+		printf( "1-[U2(1/2-U2)+1] != 0\n" );
+	k |= k2;
+	if( k == 0 )
+		{
+		add( Half, U2, X );
+		mul( X, U1, X );
+		sub( U2, Half, Y );
+		mul( Y, U1, Y );
+		sub( X, One, X );
+		sub( Y, One, Y );
+		sub( X, F9, X );
+		sub( Y, One, Y );
+		k = cmp(X,Zero);
+		if( k )
+			printf( "F9-[1-U1(1/2+U2)] != 0\n" );
+		k2 = cmp(Y,Zero);
+		if( k2 )
+			printf( "1-[1-U1(1/2-U2)] != 0\n" );
+		k |= k2;
+		if( k == 0 )
+			{
+			RAddSub = Rounded;
+		printf("Addition/Subtraction appears to round correctly.\n");
+			if(GAddSub == No)
+				printf( "Add/Subtract test inconsistent\n");
+			}
+		else
+			{
+		 printf("Addition/Subtraction neither rounds nor chops.\n");
+			}
+		}
+	else
+		printf("Addition/Subtraction neither rounds nor chops.\n");
+	}
+else
+	printf("Addition/Subtraction neither rounds nor chops.\n");
+
+mov( One, S );
+add( One, Half, X );
+mul( Half, X, X );
+add( One, X, X );
+add( One, U2, Y );
+mul( Y, Half, Y );
+sub( Y, X, Z );
+sub( X, Y, T );
+add( Z, T, StickyBit );
+if( cmp(StickyBit, Zero) != 0 )
+	{
+	mov( Zero, S );
+	ErrCnt[Flaw] += 1;
+	printf( "(X - Y) + (Y - X) is non zero!\n" );
+	}
+mov( Zero, StickyBit );
+FLOOR( RadixD2, t );
+k2 = cmp( t, RadixD2 );
+k = 1;
+if( (GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
+	&& (RMult == Rounded) && (RDiv == Rounded)
+	&& (RAddSub == Rounded) && (k2 == 0) )
+	{
+	printf("Checking for sticky bit.\n");
+	k = 0;
+	add( Half, U1, X );
+	mul( X, U2, X );
+	mul( Half, U2, Y );
+	add( One, Y, Z );
+	add( One, X, T );
+	sub( One, Z, t );
+	sub( One, T, t2 );
+	if( cmp(t,Zero) > 0 )
+		{
+		k = 1;
+		printf( "[1+(1/2)U2]-1 > 0\n" );
+		}
+	if( cmp(t2,U2) < 0 )
+		{
+		k = 1;
+		printf( "[1+U2(1/2+U1)]-1 < U2\n" );
+		}
+	add( T, Y, Z );
+	sub( X, Z, Y );
+	sub( T, Z, t );
+	sub( T, Y, t2 );
+	if( cmp(t,U2) < 0 )
+		{
+		k = 1;
+		printf( "[[1+U2(1/2+U1)]+(1/2)U2]-[1+U2(1/2+U1)] < U2\n" );
+		}
+	if( cmp(t2,Zero) != 0 )
+		{
+		k = 1;
+		printf( "(1/2)U2-[1+U2(1/2+U1)] != 0\n" );
+		}
+	add( Half, U1, X );
+	mul( X, U1, X );
+	mul( Half, U1, Y );
+	sub( Y, One, Z );
+	sub( X, One, T );
+	sub( One, Z, t );
+	sub( F9, T, t2 );
+	if( cmp(t,Zero) != 0 )
+		{
+		k = 1;
+		printf( "(1-(1/2)U1)-1 != 0\n" );
+		}
+	if( cmp(t2,Zero) != 0 )
+		{
+		k = 1;
+		printf( "[1-U1(1/2+U1)]-F9 != 0\n" );
+		}
+	sub( U1, Half, Z );
+	mul( Z, U1, Z );
+	sub( Z, F9, T );
+	sub( Y, F9, Q );
+	sub( F9, T, t );
+	if( cmp( t, Zero ) != 0 )
+		{
+		k = 1;
+		printf( "[F9-U1(1/2-U1)]-F9 != 0\n" );
+		}
+	sub( U1, F9, t );
+	sub( Q, t, t );
+	if( cmp( t, Zero ) != 0 )
+		{
+		k = 1;
+		printf( "(F9-U1)-(F9-(1/2)U1) != 0\n" );
+		}
+	add( One, U2, Z );
+	mul( Z, OneAndHalf, Z );
+	add( OneAndHalf, U2, T );
+	sub( Z, T, T );
+	add( U2, T, T );
+	div( Radix, Half, X );
+	add( One, X, X );
+	mul( Radix, U2, Y );
+	add( One, Y, Y );
+	mul( X, Y, Z );
+	if( cmp( T, Zero ) != 0 )
+		{
+		k = 1;
+		printf( "(3/2+U2)-3/2(1+U2)+U2 != 0\n" );
+		}
+	mul( Radix, U2, t );
+	add( X, t, t );
+	sub( Z, t, t );
+	if( cmp( t, Zero ) != 0 )
+		{
+		k = 1;
+	printf( "(1+1/2Radix)+Radix*U2-[1+1/(2Radix)][1+Radix*U2] != 0\n" );
+		}
+	if( cmp(Radix, Two) != 0 )
+		{
+		add( Two, U2, X );
+		div( Two, X, Y );
+		sub( One, Y, t );
+		if( cmp( t, Zero) != 0 )
+			k = 1;
+		}
+	}
+if( k == 0 )
+	{
+	printf("Sticky bit apparently used correctly.\n");
+	mov( One, StickyBit );
+	}
+else
+	{
+	printf("Sticky bit used incorrectly or not at all.\n");
+	}
+
+if( GMult == No || GDiv == No || GAddSub == No ||
+		RMult == Other || RDiv == Other || RAddSub == Other)
+	{
+	ErrCnt[Flaw] += 1;
+ printf("lack(s) of guard digits or failure(s) to correctly round or chop\n");
+printf( "(noted above) count as one flaw in the final tally below\n" );
+	}
+/*=============================================*/
+Milestone = 60;
+/*=============================================*/
+printf("\n");
+printf("Does Multiplication commute?  ");
+printf("Testing on %d random pairs.\n", NoTrials);
+SQRT( Three, Random9 );
+mov( Third, Random1 );
+I = 1;
+do
+	{
+	Random();
+	mov( Random1, X );
+	Random();
+	mov( Random1, Y );
+	mul( Y, X, Z9 );
+	mul( X, Y, Z );
+	sub( Z9, Z, Z9 );
+	I = I + 1;
+	}
+while ( ! ((I > NoTrials) || (cmp(Z9,Zero) != 0)));
+if(I == NoTrials)
+	{
+	div( Three, Half, t );
+	add( One, t, Random1 );
+	add( U2, U1, t );
+	add( t, One, Random2 );
+	mul( Random1, Random2, Z );
+	mul( Random2, Random1, Y );
+/* Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
+ *			Three) * ((U2 + U1) + One);
+ */
+	div( Three, Half, t2 );
+	add( One, t2, t2 );
+	add( U2, U1, t );
+	add( t, One, t );
+	mul( t2, t, Z9 );
+	mul( t2, t, t );
+	sub( t, Z9, Z9 );
+	}
+if(! ((I == NoTrials) || (cmp(Z9,Zero) == 0)))
+	{
+	ErrCnt[Defect] += 1;
+	printf( "X * Y == Y * X trial fails.\n");
+	}
+else
+	{
+	printf("     No failures found in %d integer pairs.\n", NoTrials);
+	}
+/*=============================================*/
+Milestone = 70;
+/*=============================================*/
+sqtest();
+Milestone = 90;
+pow1test();
+
+Milestone = 110;
+
+printf("Seeking Underflow thresholds UfThold and E0.\n");
+mov( U1, D );
+FLOOR( Precision, t );
+if( cmp(Precision, t) != 0 )
+	{
+	mov( BInvrse, D );
+	mov( Precision, X );
+	do
+		{
+		mul( D, BInvrse, D );
+		sub( One, X, X );
+		}
+	while( cmp(X, Zero) > 0 );
+	}
+mov( One, Y );
+mov( D, Z );
+/* ... D is power of 1/Radix < 1. */
+sigsave = sigfpe;
+if( setjmp(ovfl_buf) )
+	goto under0;
+do
+	{
+	mov( Y, C );
+	mov( Z, Y );
+	mul( Y, Y, Z );
+	add( Z, Z, t );
+	}
+while( (cmp(Y,Z) > 0) && (cmp(t,Z) > 0) );
+
+under0:
+sigsave = 0;
+
+mov( C, Y );
+mul( Y, D, Z );
+sigsave = sigfpe;
+if( setjmp(ovfl_buf) )
+	goto under1;
+do
+	{
+	mov( Y, C );
+	mov( Z, Y );
+	mul( Y, D, Z );
+	add( Z, Z, t );
+	}
+while( (cmp(Y,Z) > 0) && (cmp(t,Z) > 0) );
+
+under1:
+sigsave = 0;
+
+if( cmp(Radix,Two) < 0 )
+	mov( Two, HInvrse );
+else
+	mov( Radix, HInvrse );
+div( HInvrse, One, H );
+/* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
+div( C, One, CInvrse );
+mov( C, E0 );
+mul( E0, H, Z );
+/* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
+sigsave = sigfpe;
+if( setjmp(ovfl_buf) )
+	goto under2;
+do
+	{
+	mov( E0, Y );
+	mov( Z, E0 );
+	mul( E0, H, Z );
+	add( Z, Z, t );
+	}
+while( (cmp(E0,Z) > 0) && (cmp(t,Z) > 0) );
+
+under2:
+sigsave = 0;
+
+mov( E0, UfThold );
+mov( Zero, E1 );
+mov( Zero, Q );
+mov( U2, E9 );
+add( One, E9, S );
+mul( C, S, D );
+if( cmp(D,C) <= 0 )
+	{
+	mul( Radix, U2, E9 );
+	add( One, E9, S );
+	mul( C, S, D );
+	if( cmp(D, C) <= 0 )
+		{
+		ErrCnt[Failure] += 1;
+		printf( "multiplication gets too many last digits wrong.\n" );
+		mov( E0, Underflow );
+		mov( Zero, YY1 );
+		mov( Z, PseudoZero );
+		}
+	}
+else
+	{
+	mov( D, Underflow );
+	mul( Underflow, H, PseudoZero );
+	mov( Zero, UfThold );
+	do
+		{
+		mov( Underflow, YY1 );
+		mov( PseudoZero, Underflow );
+		add( E1, E1, t );
+		if( cmp(t, E1) <= 0)
+			{
+			mul( Underflow, HInvrse, Y2 );
+			sub( Y2, YY1, E1 );
+			FABS( E1 );
+			mov( YY1, Q );
+			if( (cmp( UfThold, Zero ) == 0)
+				&& (cmp(YY1, Y2) != 0) )
+				mov( YY1, UfThold );
+			}
+		mul( PseudoZero, H, PseudoZero );
+		add( PseudoZero, PseudoZero, t );
+		}
+	while( (cmp(Underflow, PseudoZero) > 0)
+		&& (cmp(t, PseudoZero) > 0) );
+	}
+/* Comment line 4530 .. 4560 */
+if( cmp(PseudoZero, Zero) != 0 )
+	{
+	printf("\n");
+	mov(PseudoZero, Z );
+/* ... Test PseudoZero for "phoney- zero" violates */
+/* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
+		   ... */
+	if( cmp(PseudoZero, Zero) <= 0 )
+		{
+		ErrCnt[Failure] += 1;
+		printf("Positive expressions can underflow to an\n");
+		printf("allegedly negative value\n");
+		printf("PseudoZero that prints out as: " );
+		show( PseudoZero );
+		mov( PseudoZero, X );
+		neg( X );
+		if( cmp(X, Zero) <= 0 )
+			{
+			printf("But -PseudoZero, which should be\n");
+			printf("positive, isn't; it prints out as " );
+			show( X );
+			}
+		}
+	else
+		{
+		ErrCnt[Flaw] += 1;
+		printf( "Underflow can stick at an allegedly positive\n");
+		printf("value PseudoZero that prints out as " );
+		show( PseudoZero );
+		}
+/*	TstPtUf();*/
+	}
+
+/*=============================================*/
+Milestone = 120;
+/*=============================================*/
+mul( CInvrse, Y, t );
+mul( CInvrse, YY1, t2 );
+if( cmp(t,t2) > 0 )
+	{
+	mul( H, S, S );
+	mov( Underflow, E0 );
+	}
+if(! ((cmp(E1,Zero) == 0) || (cmp(E1,E0) == 0)) )
+	{
+	ErrCnt[Defect] += 1;
+	if( cmp(E1,E0) < 0 )
+		{
+		printf("Products underflow at a higher");
+		printf(" threshold than differences.\n");
+		if( cmp(PseudoZero,Zero) == 0 ) 
+			mov( E1, E0 );
+		}
+	else
+		{
+		printf("Difference underflows at a higher");
+		printf(" threshold than products.\n");
+		}
+	}
+printf("Smallest strictly positive number found is E0 = " );
+show( E0 );
+mov( E0, Z );
+TstPtUf();
+mov( E0, Underflow );
+if(N == 1)
+	mov( Y, Underflow );
+I = 4;
+if( cmp(E1,Zero) == 0 )
+	I = 3;
+if( cmp( UfThold,Zero) == 0 )
+	I = I - 2;
+UfNGrad = True;
+switch(I)
+	{
+	case 1:
+	mov( Underflow, UfThold );
+	mul( CInvrse, Q, t );
+	mul( CInvrse, Y, t2 );
+	mul( t2, S, t2 );
+	if( cmp( t, t2 ) != 0 )
+		{
+		mov( Y, UfThold );
+		ErrCnt[Failure] += 1;
+		printf( "Either accuracy deteriorates as numbers\n");
+		printf("approach a threshold = " );
+		show( UfThold );
+		printf(" coming down from " );
+		show( C );
+	printf(" or else multiplication gets too many last digits wrong.\n");
+		}
+	break;
+	
+	case	2:
+	ErrCnt[Failure] += 1;
+	printf( "Underflow confuses Comparison which alleges that\n");
+	printf("Q == Y while denying that |Q - Y| == 0; these values\n");
+	printf("print out as Q = " );
+	show( Q );
+	printf( ", Y = " );
+	show( Y );
+	sub( Y2, Q, t );
+	FABS(t);
+	printf ("|Q - Y| = " );
+	show( t );
+	mov( Q, UfThold );
+	break;
+	
+	case 3:
+	mov( X, X );
+	break;
+	
+	case 4:
+	div( E9, E1, t );
+	sub( t, UfThold, t );
+	FABS(t);
+	if( (cmp(Q,UfThold) == 0) && (cmp(E1,E0) == 0)
+		&& (cmp(t,E1) <= 0) )
+		{
+		UfNGrad = False;
+		printf("Underflow is gradual; it incurs Absolute Error =\n");
+		printf("(roundoff in UfThold) < E0.\n");
+		mul( E0, CInvrse, Y );
+		add( OneAndHalf, U2, t );
+		mul( Y, t, Y );
+		add( One, U2, X );
+		mul( CInvrse, X, X );
+		div( X, Y, t );
+		IEEE = (cmp(t,E0) == 0);
+		if( IEEE == 0 )
+			{
+		printf( "((CInvrse E0) (1.5+U2)) / (CInvrse (1+U2)) != E0\n" );
+			printf( "CInvrse = " );
+			show( CInvrse );
+			printf( "E0 = " );
+			show( E0 );
+			printf( "U2 = " );
+			show( U2 );
+			printf( "X = " );
+			show(X);
+			printf( "Y = " );
+			show(Y);
+			printf( "Y/X = " );
+			show(t);
+			}
+		}
+	}
+if(UfNGrad)
+	{
+	printf("\n");
+	div( UfThold, Underflow, R );
+	SQRT( R, R );
+	if( cmp(R,H) <= 0)
+		{
+		mul( R, UfThold, Z );
+/* X = Z * (One + R * H * (One + H));*/
+		add( One, H, X );
+		mul( H, X, X );
+		mul( R, X, X );
+		add( One, X, X );
+		mul( Z, X, X );
+		}
+	else
+		{
+		mov( UfThold, Z );
+/*X = Z * (One + H * H * (One + H));*/
+		add( One, H, X );
+		mul( H, X, X );
+		mul( H, X, X );
+		add( One, X, X );
+		mul( Z, X, X );
+		}
+	sub( Z, X, t );
+/*	if(! ((cmp(X,Z) == 0) || (cmp(t,Zero) != 0)) )*/
+	if( (cmp(X,Z) != 0) && (cmp(t,Zero) == 0) )
+		{
+/*		ErrCnt[Flaw] += 1;*/
+		ErrCnt[Serious] += 1;
+		printf("X = " );
+		show( X );
+		printf( "\tis not equal to Z = " );
+		show( Z );
+/*		sub( Z, X, Z9 );*/
+		printf("yet X - Z yields " );
+		show( t );
+		printf("which compares equal to " );
+		show( Zero );
+		printf("    Should this NOT signal Underflow, ");
+		printf("this is a SERIOUS DEFECT\nthat causes ");
+		printf("confusion when innocent statements like\n");;
+		printf("    if (X == Z)  ...  else");
+		printf("  ... (f(X) - f(Z)) / (X - Z) ...\n");
+		printf("encounter Division by Zero although actually\n");
+		printf("X / Z = 1 + " );
+		div( Z, X, t );
+		sub( Half, t, t );
+		sub( Half, t, t );
+		show(t);
+		}
+	}
+printf("The Underflow threshold is " );
+show( UfThold );
+printf( "below which calculation may suffer larger Relative error than" );
+printf( " merely roundoff.\n");
+mul( U1, U1, Y2 );
+mul( Y2, Y2, Y );
+mul( Y, U1, Y2 );
+if( cmp( Y2,UfThold) <= 0 )
+	{
+	if( cmp(Y,E0) > 0 )
+		{
+		ErrCnt[Defect] += 1;
+		I = 5;
+		}
+	else
+		{
+		ErrCnt[Serious] += 1;
+		I = 4;
+		}
+	printf("Range is too narrow; U1^%d Underflows.\n", I);
+	}
+Milestone = 130;
+
+/*Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty;*/
+LOG( UfThold, Y );
+LOG( HInvrse, t );
+div( t, Y, Y );
+mul( TwoForty, Y, Y );
+sub( Y, Half, Y );
+FLOOR( Y, Y );
+div( TwoForty, Y, Y );
+neg(Y);
+sub( One, Y, Y2 ); /* ***** changed from Y2 = Y + Y */
+printf("Since underflow occurs below the threshold\n");
+printf("UfThold = " ); 
+show( HInvrse );
+printf( "\tto the power  " );
+show( Y );
+printf( "only underflow should afflict the expression " );
+show( HInvrse );
+printf( "\tto the power  " );
+show( Y2 );
+POW( HInvrse, Y2, V9 );
+printf("Actually calculating yields: " );
+show( V9 );
+add( Radix, Radix, t );
+add( t, E9, t );
+mul( t, UfThold, t );
+if( (cmp(V9,Zero) < 0) || (cmp(V9,t) > 0) )
+	{
+	ErrCnt[Serious] += 1;
+	printf( "this is not between 0 and underflow\n");
+	printf("   threshold = " );
+	show( UfThold );
+	}
+else
+	{
+	add( One, E9, t );
+	mul( UfThold, t, t );
+	if( cmp(V9,t) <= 0 )
+		printf("This computed value is O.K.\n");
+	else
+		{
+		ErrCnt[Defect] += 1;
+		printf( "this is not between 0 and underflow\n");
+		printf("   threshold = " );
+		show( UfThold );
+		}
+	}
+
+Milestone = 140;
+
+pow2test();
+	
+/*=============================================*/
+Milestone = 160;
+/*=============================================*/
+Pause();
+printf("Searching for Overflow threshold:\n");
+printf("This may generate an error.\n");
+sigsave = sigfpe;
+I = 0;
+mov( CInvrse, Y ); /* a large power of 2 */
+neg(Y);
+mul( HInvrse, Y, V9 ); /* HInvrse = 2 */
+if (setjmp(ovfl_buf))
+	goto overflow;
+do
+	{
+	mov( Y, V );
+	mov( V9, Y );
+	mul( HInvrse, Y, V9 );
+	}
+while( cmp(V9,Y) < 0 ); /* V9 = 2 * Y */
+I = 1;
+
+overflow:
+
+show( HInvrse );
+printf( "\ttimes " );
+show( Y );
+printf( "\tequals " );
+show( V9 );
+
+mov( V9, Z );
+printf("Can `Z = -Y' overflow?\n");
+printf("Trying it on Y = " );
+show(Y);
+mov( Y, V9 );
+neg( V9 );
+mov( V9, V0 );
+sub( Y, V, t );
+add( V, V0, t2 );
+if( cmp(t,t2) == 0 )
+	printf("Seems O.K.\n");
+else
+	{
+	printf("finds a Flaw, -(-Y) differs from Y.\n");
+	printf( "V-Y=t:" );
+	show(V);
+	show(Y);
+	show(t);
+	printf( "V+V0=t2:" );
+	show(V);
+	show(V0);
+	show(t2);
+	ErrCnt[Flaw] += 1;
+	}
+if( (cmp(Z, Y) != 0) && (I != 0) )
+	{
+	ErrCnt[Serious] += 1;
+	printf("overflow past " );
+	show( Y );
+	printf( "\tshrinks to " );
+	show( Z );
+	printf( "= Y * " );
+	show( HInvrse );
+	}
+/*Y = V * (HInvrse * U2 - HInvrse);*/
+mul( HInvrse, U2, Y );
+sub( HInvrse, Y, Y );
+mul( V, Y, Y );
+/*Z = Y + ((One - HInvrse) * U2) * V;*/
+sub( HInvrse, One, Z );
+mul( Z, U2, Z );
+mul( Z, V, Z );
+add( Y, Z, Z );
+if( cmp(Z,V0) < 0 )
+	mov( Z, Y );
+if( cmp(Y,V0) < 0)
+	mov( Y, V );
+sub( V, V0, t );
+if( cmp(t,V0) < 0 )
+	mov( V0, V );
+printf("Overflow threshold is V  = " );
+show( V );
+if(I)
+	{
+	printf("Overflow saturates at V0 = " );
+	show( V0 );
+	}
+else
+printf("There is no saturation value because the system traps on overflow.\n");
+
+mul( V, One, V9 );
+printf("No Overflow should be signaled for V * 1 = " );
+show( V9 );
+div( One, V, V9 );
+	printf("                           nor for V / 1 = " );
+	show( V9 );
+	printf("Any overflow signal separating this * from the one\n");
+	printf("above is a DEFECT.\n");
+/*=============================================*/
+Milestone = 170;
+/*=============================================*/
+mov( V, t );
+neg( t );
+k = 0;
+if( cmp(t,V) >= 0 )
+	k = 1;
+mov( V0, t );
+neg( t );
+if( cmp(t,V0) >= 0 )
+	k = 1;
+mov( UfThold, t );
+neg(t);
+if( cmp(t,V) >= 0 )
+	k = 1;
+if( cmp(UfThold,V) >= 0 )
+	k = 1;
+if( k != 0 )
+	{
+	ErrCnt[Failure] += 1;
+	printf( "Comparisons involving +-");
+	show( V );
+	show( V0 );
+	show( UfThold );
+	printf("are confused by Overflow." );
+	}
+/*=============================================*/
+Milestone = 175;
+/*=============================================*/
+printf("\n");
+for(Indx = 1; Indx <= 3; ++Indx) {
+	switch(Indx)
+		{
+		case 1: mov(UfThold, Z); break;
+		case 2: mov( E0, Z); break;
+		case 3: mov(PseudoZero, Z); break;
+		}
+if( cmp(Z, Zero) != 0 )
+	{
+	SQRT( Z, V9 );
+	mul( V9, V9, Y );
+	mul( Radix, E9, t );
+	sub( t, One, t );
+	div( t, Y, t );
+	add( One, Radix, t2 );
+	add( t2, E9, t2 );
+	mul( t2, Z, t2 );
+	if( (cmp(t,Z) < 0) || (cmp(Y,t2) > 0) )
+		{
+		if( cmp(V9,U1) > 0 )
+			ErrCnt[Serious] += 1;
+		else
+			ErrCnt[Defect] += 1;
+		printf("Comparison alleges that what prints as Z = " );
+		show( Z );
+		printf(" is too far from sqrt(Z) ^ 2 = " );
+		show( Y );
+		}
+	}
+}
+
+Milestone = 180;
+
+for(Indx = 1; Indx <= 2; ++Indx)
+	{
+	if(Indx == 1)
+		mov( V, Z );
+	else
+		mov( V0, Z );
+	SQRT( Z, V9 );
+	mul( Radix, E9, X );
+	sub( X, One, X );
+	mul( X, V9, X );
+	mul( V9, X, V9 );
+	mul( Two, Radix, t );
+	mul( t, E9, t );
+	sub( t, One, t );
+	mul( t, Z, t );
+	if( (cmp(V9,t) < 0) || (cmp(V9,Z) > 0) )
+		{
+		mov( V9, Y );
+		if( cmp(X,W) <  0 )
+			ErrCnt[Serious] += 1;
+		else
+			ErrCnt[Defect] += 1;
+		printf("Comparison alleges that Z = " );
+		show( Z );
+		printf(" is too far from sqrt(Z) ^ 2 :" );
+		show( Y );
+		}
+	}
+
+Milestone = 190;
+
+Pause();
+mul( UfThold, V, X ); 
+mul( Radix, Radix, Y );
+mul( X, Y, t );
+if( (cmp(t,One) < 0) || (cmp(X,Y) > 0) )
+	{
+	mul( X, Y, t );
+	div( U1, Y, t2 );
+	if( (cmp(t,U1) < 0) || (cmp(X,t2) > 0) )
+		{
+		ErrCnt[Defect] += 1;
+		printf( "Badly " );
+		}
+	else
+		{
+		ErrCnt[Flaw] += 1;
+		}
+	printf(" unbalanced range; UfThold * V = " );
+	show( X );
+	printf( "\tis too far from 1.\n");
+	}
+Milestone = 200;
+
+for(Indx = 1; Indx <= 5; ++Indx)
+	{
+	mov( F9, X );
+	switch(Indx)
+		{
+		case 2: add( One, U2, X ); break;
+		case 3: mov( V, X ); break;
+		case 4: mov(UfThold,X); break;
+		case 5: mov(Radix,X);
+		}
+	mov( X, Y );
+
+	sigsave = sigfpe;
+	if (setjmp(ovfl_buf))
+		{
+		printf("  X / X  traps when X = " );
+		show( X );
+		}
+	else
+		{
+/*V9 = (Y / X - Half) - Half;*/
+		div( X, Y, t );
+		sub( Half, t, t );
+		sub( Half, t, V9 );
+		if( cmp(V9,Zero) == 0 )
+			continue;
+		mov( U1, t );
+		neg(t);
+		if( (cmp(V9,t) == 0) && (Indx < 5) )
+			{
+			ErrCnt[Flaw] += 1;
+			}
+		else
+			{
+			ErrCnt[Serious] += 1;
+			}
+		printf("  X / X differs from 1 when X = " );
+		show( X );
+		printf("  instead, X / X - 1/2 - 1/2 = " );
+		show( V9 );
+		}
+	}
+
+	Pause();
+	printf("\n");
+	{
+		static char *msg[] = {
+			"FAILUREs  encountered =",
+			"SERIOUS DEFECTs  discovered =",
+			"DEFECTs  discovered =",
+			"FLAWs  discovered =" };
+		int i;
+		for(i = 0; i < 4; i++) if (ErrCnt[i])
+			printf("The number of  %-29s %d.\n",
+				msg[i], ErrCnt[i]);
+		}
+	printf("\n");
+	if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect]
+			+ ErrCnt[Flaw]) > 0) {
+		if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[
+			Defect] == 0) && (ErrCnt[Flaw] > 0)) {
+			printf("The arithmetic diagnosed seems ");
+			printf("satisfactory though flawed.\n");
+			}
+		if ((ErrCnt[Failure] + ErrCnt[Serious] == 0)
+			&& ( ErrCnt[Defect] > 0)) {
+			printf("The arithmetic diagnosed may be acceptable\n");
+			printf("despite inconvenient Defects.\n");
+			}
+		if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) {
+			printf("The arithmetic diagnosed has ");
+			printf("unacceptable serious defects.\n");
+			}
+		if (ErrCnt[Failure] > 0) {
+			printf("Fatal FAILURE may have spoiled this");
+			printf(" program's subsequent diagnoses.\n");
+			}
+		}
+	else {
+		printf("No failures, defects nor flaws have been discovered.\n");
+		if (! ((RMult == Rounded) && (RDiv == Rounded)
+			&& (RAddSub == Rounded) && (RSqrt == Rounded))) 
+			printf("The arithmetic diagnosed seems satisfactory.\n");
+		else {
+			k = 0;
+			if( cmp( Radix, Two ) == 0 )
+				k = 1;
+			if( cmp( Radix, Ten ) == 0 )
+				k = 1;
+			if( (cmp(StickyBit,One) >= 0) && (k == 1) )
+				{
+				printf("Rounding appears to conform to ");
+				printf("the proposed IEEE standard P");
+				k = 0;
+				k |= cmp( Radix, Two );
+				mul( Four, Three, t );
+				mul( t, Two, t );
+				sub( t, Precision, t );
+				sub( TwentySeven, Precision, t2 );
+				sub( TwentySeven, t2, t2 );
+				add( t2, One, t2 );
+				mul( t2, t, t );
+				if( (cmp(Radix,Two) == 0)
+					&& (cmp(t,Zero) == 0) )
+					printf("754");
+				else
+					printf("854");
+				if(IEEE)
+					printf(".\n");
+				else
+					{
+			printf(",\nexcept for possibly Double Rounding");
+			printf(" during Gradual Underflow.\n");
+					}
+				}
+		printf("The arithmetic diagnosed appears to be excellent!\n");
+			}
+		}
+	if (fpecount)
+		printf("\nA total of %d floating point exceptions were registered.\n",
+			fpecount);
+	printf("END OF TEST.\n");
+	}
+
+
+/* Random */
+/*  Random computes
+     X = (Random1 + Random9)^5
+     Random1 = X - FLOOR(X) + 0.000005 * X;
+   and returns the new value of Random1
+*/
+
+
+static int randflg = 0;
+FLOAT(C5em6);
+
+Random()
+{
+
+if( randflg == 0 )
+	{
+	mov( Six, t );
+	neg(t);
+	POW( Ten, t, t );
+	mul( Five, t, C5em6 );
+	randflg = 1;
+	}
+add( Random1, Random9, t );
+mul( t, t, t2 );
+mul( t2, t2, t2 );
+mul( t, t2, t );
+FLOOR(t, t2 );
+sub( t2, t, t2 );
+mul( t, C5em6, t );
+add( t, t2, Random1 );
+/*return(Random1);*/
+}
+
+/* SqXMinX */
+
+SqXMinX( ErrKind )
+int ErrKind;
+{
+mul( X, BInvrse, t2 );
+sub( t2, X, t );
+/*SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp;*/
+mul( X, X, Sqarg );
+SQRT( Sqarg, SqEr );
+sub( t2, SqEr, SqEr );
+sub( t, SqEr, SqEr );
+div( OneUlp, SqEr, SqEr );
+if( cmp(SqEr,Zero) != 0)
+	{
+	Showsq( 0 );
+	add( J, One, J );
+	ErrCnt[ErrKind] += 1;
+	printf("sqrt of " );
+	mul( X, X, t );
+	show( t );
+	printf( "minus " );
+	show( X );
+	printf( "equals " );
+	mul( OneUlp, SqEr, t );
+	show( t );
+	printf("\tinstead of correct value 0 .\n");
+	}
+}
+
+/* NewD */
+
+NewD()
+{
+mul( Z1, Q, X );
+/*X = FLOOR(Half - X / Radix) * Radix + X;*/
+div( Radix, X, t );
+sub( t, Half, t );
+FLOOR( t, t );
+mul( t, Radix, t );
+add( t, X, X );
+/*Q = (Q - X * Z) / Radix + X * X * (D / Radix);*/
+mul( X, Z, t );
+sub( t, Q, t );
+div( Radix, t, t );
+div( Radix, D, t2 );
+mul( X, t2, t2 );
+mul( X, t2, t2 );
+add( t, t2, Q );
+/*Z = Z - Two * X * D;*/
+mul( Two, X, t );
+mul( t, D, t );
+sub( t, Z, Z );
+
+if( cmp(Z,Zero) <= 0)
+	{
+	neg(Z);
+	neg(Z1);
+	}
+mul( Radix, D, D );
+}
+
+/* SR3750 */
+
+SR3750()
+{
+sub( Radix, X, t );
+sub( Radix, Z2, t2 );
+k = 0;
+if( cmp(t,t2) < 0 )
+	k = 1;
+sub( Z2, X, t );
+sub( Z2, W, t2 );
+if( cmp(t,t2) > 0 )
+	k = 1;
+/*if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) {*/
+if( k == 0 )
+	{
+	I = I + 1;
+	mul( X, D, X2 );
+	mov( X2, Sqarg );
+	SQRT( X2, X2 );
+/*Y2 = (X2 - Z2) - (Y - Z2);*/
+	sub( Z2, X2, Y2 );
+	sub( Z2, Y, t );
+	sub( t, Y2, Y2 );
+	sub( Half, Y, X2 );
+	div( X2, X8, X2 );
+	mul( Half, X2, t );
+	mul( t, X2, t );
+	sub( t, X2, X2 );
+/*SqEr = (Y2 + Half) + (Half - X2);*/
+	add( Y2, Half, SqEr );
+	sub( X2, Half, t );
+	add( t, SqEr, SqEr );
+	Showsq( -1 );
+	sub( X2, Y2, SqEr );
+	Showsq( 1 );
+	}
+}
+
+/* IsYeqX */
+
+IsYeqX()
+{
+if( cmp(Y,X) != 0 )
+	{
+	if (N <= 0)
+		{
+		if( (cmp(Z,Zero) == 0) && (cmp(Q,Zero) <= 0) )
+			printf("WARNING:  computing\n");
+		else
+			{
+			ErrCnt[Defect] += 1;
+			printf( "computing\n");
+			}
+		show( Z );
+		printf( "\tto the power " );
+		show( Q );
+		printf("\tyielded " );
+		show( Y );
+		printf("\twhich compared unequal to correct " );
+		show( X );
+		sub( X, Y, t );
+		printf("\t\tthey differ by " );
+		show( t );
+		}
+	N = N + 1; /* ... count discrepancies. */
+	}
+}
+
+/* SR3980 */
+
+SR3980()
+{
+long li;
+
+do
+	{
+/*Q = (FLOAT) I;*/
+	li = I;
+	LTOF( &li, Q );
+	POW( Z, Q, Y );
+	IsYeqX();
+	if(++I > M)
+		break;
+	mul( Z, X, X );
+	}
+while( cmp(X,W) < 0 );
+}
+
+/* PrintIfNPositive */
+
+PrintIfNPositive()
+{
+if(N > 0)
+	printf("Similar discrepancies have occurred %d times.\n", N);
+}
+
+
+/* TstPtUf */
+
+TstPtUf()
+{
+N = 0;
+if( cmp(Z,Zero) != 0)
+	{
+	printf( "Z = " );
+	show(Z);
+	printf("Since comparison denies Z = 0, evaluating ");
+	printf("(Z + Z) / Z should be safe.\n");
+	sigsave = sigfpe;
+	if (setjmp(ovfl_buf))
+		goto very_serious;
+	add( Z, Z, Q9 );
+	div( Z, Q9, Q9 );
+	printf("What the machine gets for (Z + Z) / Z is " );
+	show( Q9 );
+	sub( Two, Q9, t );
+	FABS(t);
+	mul( Radix, U2, t2 );
+	if( cmp(t,t2) < 0 )
+		{
+		printf("This is O.K., provided Over/Underflow");
+		printf(" has NOT just been signaled.\n");
+		}
+	else
+		{
+		if( (cmp(Q9,One) < 0) || (cmp(Q9,Two) > 0) )
+			{
+very_serious:
+			N = 1;
+			ErrCnt [Serious] = ErrCnt [Serious] + 1;
+			printf("This is a VERY SERIOUS DEFECT!\n");
+			}
+		else
+			{
+			N = 1;
+			ErrCnt[Defect] += 1;
+			printf("This is a DEFECT!\n");
+			}
+		}
+	mul( Z, One, V9 );
+	mov( V9, Random1 );
+	mul( One, Z, V9 );
+	mov( V9, Random2 );
+	div( One, Z, V9 );
+	if( (cmp(Z,Random1) == 0) && (cmp(Z,Random2) == 0)
+		&& (cmp(Z,V9) == 0) )
+		{
+		if (N > 0)
+			Pause();
+		}
+	else
+		{
+		N = 1;
+		ErrCnt[Defect] += 1;
+		printf( "What prints as Z = ");
+		show( Z );
+		printf( "\tcompares different from " );
+		if( cmp(Z,Random1) != 0)
+			{
+			printf("Z * 1 = " );
+			show( Random1 );
+			}
+		if( (cmp(Z,Random2) != 0)
+			|| (cmp(Random2,Random1) != 0) )
+			{
+			printf("1 * Z == " );
+			show( Random2 );
+			}
+		if( cmp(Z,V9) != 0 )
+			{
+			printf("Z / 1 = " );
+			show( V9 );
+			}
+		if( cmp(Random2,Random1) != 0 )
+			{
+			ErrCnt[Defect] += 1;
+			printf( "Multiplication does not commute!\n");
+			printf("\tComparison alleges that 1 * Z = " );
+			show(Random2);
+			printf("\tdiffers from Z * 1 = " );
+			show(Random1);
+			}
+		Pause();
+		}
+	}
+}
+
+Pause()
+{
+}
+
+Sign( x, y )
+FSIZE *x, *y;
+{
+
+if( cmp( x, Zero ) < 0 )
+	{
+	mov( One, y );
+	neg( y );
+	}
+else
+	{
+	mov( One, y );
+	}
+}
+
+sqtest()
+{
+printf("\nRunning test of square root(x).\n");
+
+RSqrt = Other;
+k = 0;
+SQRT( Zero, t );
+k |= cmp( Zero, t );
+mov( Zero, t );
+neg(t);
+SQRT( t, t2 );
+k |= cmp( t, t2 );
+SQRT( One, t );
+k |= cmp( One, t );
+if( k != 0 )
+ 	{
+	ErrCnt[Failure] += 1;
+	printf( "Square root of 0.0, -0.0 or 1.0 wrong\n");
+	}
+mov( Zero, MinSqEr );
+mov( Zero, MaxSqEr );
+mov( Zero, J );
+mov( Radix, X );
+mov( U2, OneUlp );
+SqXMinX( Serious );
+mov( BInvrse, X );
+mul( BInvrse, U1, OneUlp );
+SqXMinX( Serious );
+mov( U1, X );
+mul( U1, U1, OneUlp );
+SqXMinX( Serious );
+if( cmp(J,Zero) != 0)
+	Pause();
+printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
+mov( Zero, J );
+mov( Two, X );
+mov( Radix, Y );
+if( cmp(Radix,One) != 0 )
+	{
+	lngint = NoTrials;
+	LTOF( &lngint, t );
+	FTOL( t, &lng2, X );
+	if( lngint != lng2 )
+		{
+		printf( "Integer conversion error\n" );
+		exit(1);
+		}
+	do
+		{
+		mov( Y, X );
+		mul( Radix, Y, Y );
+		sub( X, Y, t2 );
+		}
+	while( ! (cmp(t2,t) >= 0) );
+	}
+mul( X, U2, OneUlp );
+I = 1;
+while(I < 10)
+	{
+	add( X, One, X );
+	SqXMinX( Defect );
+	if( cmp(J,Zero) > 0 )
+		break;
+	I = I + 1;
+	}
+printf("Test for sqrt monotonicity.\n");
+I = - 1;
+mov( BMinusU2, X );
+mov( Radix, Y );
+mul( Radix, U2, Z );
+add( Radix, Z, Z );
+NotMonot = False;
+Monot = False;
+while( ! (NotMonot || Monot))
+	{
+	I = I + 1;
+	SQRT(X, X);
+	SQRT(Y,Q);
+	SQRT(Z,Z);
+	if( (cmp(X,Q) > 0) || (cmp(Q,Z) > 0) )
+		NotMonot = True;
+	else
+		{
+		add( Q, Half, Q );
+		FLOOR( Q, Q );
+		mul( Q, Q, t );
+		if( (I > 0) || (cmp(Radix,t) == 0) )
+			Monot = True;
+		else if (I > 0)
+			{
+			if(I > 1)
+				Monot = True;
+			else
+				{
+				mul( Y, BInvrse, Y );
+				sub( U1, Y, X );
+				add( Y, U1, Z );
+				}
+			}
+		else
+			{
+			mov( Q, Y );
+			sub( U2, Y, X );
+			add( Y, U2, Z );
+			}
+		}
+	}
+if( Monot )
+	printf("sqrt has passed a test for Monotonicity.\n");
+else
+	{
+	ErrCnt[Defect] += 1;
+	printf("sqrt(X) is non-monotonic for X near " );
+	show(Y);
+	}
+/*=============================================*/
+Milestone = 80;
+/*=============================================*/
+add( MinSqEr, Half, MinSqEr );
+sub( Half, MaxSqEr, MaxSqEr);
+/*Y = (SQRT(One + U2) - One) / U2;*/
+add( One, U2, Sqarg );
+SQRT( Sqarg, Y );
+sub( One, Y, Y );
+div( U2, Y, Y );
+/*SqEr = (Y - One) + U2 / Eight;*/
+sub( One, Y, t );
+div( Eight, U2, SqEr );
+add( t, SqEr, SqEr );
+Showsq( 1 );
+div( Eight, U2, SqEr );
+add( Y, SqEr, SqEr );
+Showsq( -1 );
+/*Y = ((SQRT(F9) - U2) - (One - U2)) / U1;*/
+mov( F9, Sqarg );
+SQRT( Sqarg, Y );
+sub( U2, Y, Y );
+sub( U2, One, t );
+sub( t, Y, Y );
+div( U1, Y, Y );
+div( Eight, U1, SqEr );
+add( Y, SqEr, SqEr );
+Showsq( 1 );
+/*SqEr = (Y + One) + U1 / Eight;*/
+div( Eight, U1, t );
+add( Y, One, SqEr );
+add( SqEr, t, SqEr );
+Showsq( -1 );
+mov( U2, OneUlp );
+mov( OneUlp, X );
+for( Indx = 1; Indx <= 3; ++Indx)
+	{
+/*Y = SQRT((X + U1 + X) + F9);*/
+	add( X, U1, Y );
+	add( Y, X, Y );
+	add( Y, F9, Y );
+	mov( Y, Sqarg );
+	SQRT( Sqarg, Y );
+/*Y = ((Y - U2) - ((One - U2) + X)) / OneUlp;*/
+	sub( U2, One, t );
+	add( t, X, t );
+	sub( U2, Y, Y );
+	sub( t, Y, Y );
+	div( OneUlp, Y, Y );
+/*Z = ((U1 - X) + F9) * Half * X * X / OneUlp;*/
+	sub( X, U1, t );
+	add( t, F9, t );
+	mul( t, Half, t );
+	mul( t, X, t );
+	mul( t, X, t );
+	div( OneUlp, t, Z );
+	add( Y, Half, SqEr );
+	add( SqEr, Z, SqEr );
+	Showsq( -1 );
+	sub( Half, Y, SqEr );
+	add( SqEr, Z, SqEr );
+	Showsq( 1 );
+	if(((Indx == 1) || (Indx == 3))) 
+		{
+/*X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp)));*/
+		mov( OneUlp, Sqarg );
+		SQRT( Sqarg, t );
+		mul( Nine, t, t );
+		div( t, Eight, t );
+		FLOOR( t, t );
+		Sign( X, t2 );
+		mul( t2, t, t );
+		mul( OneUlp, t, X );
+		}
+	else
+		{
+		mov( U1, OneUlp );
+		mov( OneUlp, X );
+		neg( X );
+		}
+	}
+/*=============================================*/
+Milestone = 85;
+/*=============================================*/
+SqRWrng = False;
+Anomaly = False;
+if( cmp(Radix,One) != 0 )
+	{
+	printf("Testing whether sqrt is rounded or chopped.\n");
+/*D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision)));*/
+	FLOOR( Precision, t2 );
+	add( One, Precision, t );
+	sub( t2, t, t );
+	POW( Radix, t, D );
+	add( Half, D, D );
+	FLOOR( D, D );
+/* ... == Radix^(1 + fract) if (Precision == Integer + fract. */
+	div( Radix, D, X );
+	div( A1, D, Y );
+	FLOOR( X, t );
+	FLOOR( Y, t2 );
+	if( (cmp(X,t) != 0) || (cmp(Y,t2) != 0) )
+		{
+		Anomaly = True;
+		printf( "Anomaly 1\n" );
+		}
+	else
+		{
+		mov( Zero, X );
+		mov( X, Z2 );
+		mov( One, Y );
+		mov( Y, Y2 );
+		sub( One, Radix, Z1 );
+		mul( Four, D, FourD );
+		do
+			{
+			if( cmp(Y2,Z2) >0 )
+				{
+				mov( Radix, Q );
+				mov( Y, YY1 );
+				do
+					{
+/*X1 = FABS(Q + FLOOR(Half - Q / YY1) * YY1);*/
+					div( YY1, Q, t );
+					sub( t, Half, t );
+					FLOOR( t, t );
+					mul( t, YY1, t );
+					add( Q, t, X1 );
+					FABS( X1 );
+					mov( YY1, Q );
+					mov( X1, YY1 );
+					}
+				while( ! (cmp(X1,Zero) <= 0) );
+				if( cmp(Q,One) <= 0 )
+					{
+					mov( Y2, Z2 );
+					mov( Y, Z );
+					}
+				}
+			add( Y, Two, Y );
+			add( X, Eight, X );
+			add( Y2, X, Y2 );
+			if( cmp(Y2,FourD) >= 0 )
+				sub( FourD, Y2, Y2 );
+			}
+		while( ! (cmp(Y,D) >= 0) );
+		sub( Z2, FourD, X8 );
+		mul( Z, Z, Q );
+		add( X8, Q, Q );
+		div( FourD, Q, Q );
+		div( Eight, X8, X8 );
+		FLOOR( Q, t );
+		if( cmp(Q,t) != 0 )
+			{
+			Anomaly = True;
+			printf( "Anomaly 2\n" );
+			}
+		else
+			{
+			Break = False;
+			do
+				{
+				mul( Z1, Z, X );
+/*X = X - FLOOR(X / Radix) * Radix;*/
+				div( Radix, X, t );
+				FLOOR( t, t );
+				mul( t, Radix, t );
+				sub( t, X, X );
+				if( cmp(X,One) == 0 ) 
+					Break = True;
+				else
+					sub( One, Z1, Z1 );
+				}
+			while( ! (Break || (cmp(Z1,Zero) <= 0)) );
+			if( (cmp(Z1,Zero) <= 0) && (! Break))
+				{
+				printf( "Anomaly 3\n" );
+				Anomaly = True;
+				}
+			else
+				{
+				if( cmp(Z1,RadixD2) > 0)
+					sub( Radix, Z1, Z1 );
+				do
+					{
+					NewD();
+					mul( U2, D, t );
+					}
+				while( ! (cmp(t,F9) >= 0) );
+				mul( D, Radix, t );
+				sub( D, t, t );
+				sub( D, W, t2 );
+				if (cmp(t,t2) != 0 )
+					{
+					printf( "Anomaly 4\n" );
+					Anomaly = True;
+					}
+				else
+					{
+					mov( D, Z2 );
+					I = 0;
+					add( One, Z, t );
+					mul( t, Half, t );
+					add( D, t, Y );
+					add( D, Z, X );
+					add( X, Q, X );
+					SR3750();
+					sub( Z, One, t );
+					mul( t, Half, t );
+					add( D, t, Y );
+					add( Y, D, Y );
+					sub( Z, D, X );
+					add( X, D, X );
+					add( X, Q, t );
+					add( t, X, X );
+					SR3750();
+					NewD();
+					sub( Z2, D, t );
+					sub( Z2, W, t2 );
+					if(cmp(t,t2) != 0 )
+						{
+						printf( "Anomaly 5\n" );
+						Anomaly = True;
+						}
+					else
+						{
+/*Y = (D - Z2) + (Z2 + (One - Z) * Half);*/
+						sub( Z, One, t );
+						mul( t, Half, t );
+						add( Z2, t, t );
+						sub( Z2, D, Y );
+						add( Y, t, Y );
+/*X = (D - Z2) + (Z2 - Z + Q);*/
+						sub( Z, Z2, t );
+						add( t, Q, t );
+						sub( Z2, D, X );
+						add( X, t, X );
+						SR3750();
+						add( One, Z, Y );
+						mul( Y, Half, Y );
+						mov( Q, X );
+						SR3750();
+						if(I == 0)
+							{
+							printf( "Anomaly 6\n" );
+							Anomaly = True;
+							}
+						}
+					}
+				}
+			}
+		}
+	if ((I == 0) || Anomaly)
+		{
+		ErrCnt[Failure] += 1;
+		printf( "Anomalous arithmetic with Integer < \n");
+		printf("Radix^Precision = " );
+		show( W );
+		printf(" fails test whether sqrt rounds or chops.\n");
+		SqRWrng = True;
+		}
+	}
+if(! Anomaly)
+	{
+	if(! ((cmp(MinSqEr,Zero) < 0) || (cmp(MaxSqEr,Zero) > 0))) {
+	RSqrt = Rounded;
+	printf("Square root appears to be correctly rounded.\n");
+	}
+	else
+		{
+		k = 0;
+		add( MaxSqEr, U2, t );
+		sub( Half, U2, t2 );
+		if( cmp(t,t2) > 0 )
+			k = 1;
+		if( cmp( MinSqEr, Half ) > 0 )
+			k = 1;
+		add( MinSqEr, Radix, t );
+		if( cmp( t, Half ) < 0 )
+			k = 1;
+		if( k == 1 )
+			SqRWrng = True;
+		else
+			{
+			RSqrt = Chopped;
+			printf("Square root appears to be chopped.\n");
+			}
+		}
+	}
+if( SqRWrng )
+	{
+	printf("Square root is neither chopped nor correctly rounded.\n");
+	printf("Observed errors run from " );
+	sub( Half, MinSqEr, t );
+	show( t );
+	printf("\tto " );
+	add( Half, MaxSqEr, t );
+	show( t );
+	printf( "ulps.\n" );
+	sub( MinSqEr, MaxSqEr, t );
+	mul( Radix, Radix, t2 );
+	if( cmp( t, t2 ) >= 0 )
+		{
+		ErrCnt[Serious] += 1;
+		printf( "sqrt gets too many last digits wrong\n");
+		}
+	}
+}
+
+Showsq( arg )
+int arg;
+{
+
+k = 0;
+if( arg <= 0 )
+	{
+	if( cmp(SqEr,MinSqEr) < 0 )
+		{
+		k = 1;
+		mov( SqEr, MinSqEr );
+		}
+	}
+if( arg >= 0 )
+	{
+	if( cmp(SqEr,MaxSqEr) > 0 )
+		{
+		k = 2;
+		mov( SqEr, MaxSqEr );
+		}
+	}
+#if DEBUG
+if( k != 0 )
+	{
+	printf( "Square root of " );
+	show( arg );
+	printf( "\tis in error by " );
+	show( SqEr );
+	}
+#endif
+}
+
+
+pow1test()
+{
+
+/*=============================================*/
+Milestone = 90;
+/*=============================================*/
+Pause();
+printf("Testing powers Z^i for small Integers Z and i.\n");
+N = 0;
+/* ... test powers of zero. */
+I = 0;
+mov( Zero, Z );
+neg(Z);
+M = 3;
+Break = False;
+do
+	{
+	mov( One, X );
+	SR3980();
+	if(I <= 10)
+		{
+		I = 1023;
+		SR3980();
+		}
+	if( cmp(Z,MinusOne) == 0 )
+		Break = True;
+	else
+		{
+		mov( MinusOne, Z );
+		PrintIfNPositive();
+		N = 0;
+/* .. if(-1)^N is invalid, replace MinusOne by One. */
+		I = - 4;
+		}
+	}
+while( ! Break );
+PrintIfNPositive();
+N1 = N;
+N = 0;
+mov( A1, Z );
+/*M = FLOOR(Two * LOG(W) / LOG(A1));*/
+LOG( W, t );
+mul( Two, t, t );
+FLOOR( t, t );
+LOG( A1, t2 );
+div( t2, t, t );
+FTOL( t, &lngint, t2 );
+M = lngint;
+Break = False;
+do
+	{
+	mov( Z, X );
+	I = 1;
+	SR3980();
+	if( cmp(Z,AInvrse) == 0 )
+		Break = True;
+	else
+		 mov( AInvrse, Z );
+	}
+while( ! (Break) );
+/*=============================================*/
+Milestone = 100;
+/*=============================================*/
+/*  Powers of Radix have been tested, */
+/*         next try a few primes     */
+
+M = NoTrials;
+
+mov( Three, Z );
+do
+	{
+	mov( Z, X );
+	I = 1;
+	SR3980();
+	do
+		{
+		add( Z, Two, Z );
+		div( Three, Z, t );
+		FLOOR( t, t );
+		mul( Three, t, t );
+		}
+	while( cmp(t,Z) == 0 );
+	mul( Eight, Three, t );
+	}
+while( cmp(Z,t) < 0 );
+
+if(N > 0)
+	{
+	printf("Errors like this may invalidate financial calculations\n");
+	printf("\tinvolving interest rates.\n");
+	}
+PrintIfNPositive();
+N += N1;
+if(N == 0)
+	printf("... no discrepancies found.\n");
+if(N > 0)
+	Pause();
+else printf("\n");
+}
+
+
+
+pow2test()
+{
+printf("\n");
+/* ...calculate Exp2 == exp(2) == 7.38905 60989 30650 22723 04275-... */
+mov( Zero, X );
+mov( Two, t2 ); /*I = 2;*/
+
+mul( Two, Three, Y );
+mov( Zero, Q );
+N = 0;
+do
+	{
+	mov( X, Z );
+	add( t2, One, t2 ); /*I = I + 1;*/
+	add( t2, t2, t );
+	div( t, Y, Y ); /*Y = Y / (I + I);*/
+	add( Y, Q, R );
+	add( Z, R, X );
+	sub( X, Z, Q );
+	add( Q, R, Q );
+	}
+while( cmp(X,Z) > 0 );
+
+/*Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo);*/
+div( Eight, One, t );
+add( OneAndHalf, t, Z );
+mul( OneAndHalf, ThirtyTwo, t );
+div( t, X, t );
+add( Z, t, Z );
+mul( Z, Z, X );
+mul( X, X, Exp2 );
+mov( F9, X );
+sub( U1, X, Y );
+printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = " );
+show( Exp2 );
+printf( "\tas X -> 1.\n" );
+for(I = 1;;)
+	{
+	sub( BInvrse, X, Z );
+/*Z = (X + One) / (Z - (One - BInvrse));*/
+	add( X, One, t2 );
+	sub( BInvrse, One, t );
+	sub( t, Z, t );
+	div( t, t2, Z );
+	POW( X, Z, Sqarg );
+	sub( Exp2, Sqarg, Q );
+	mov( Q, t );
+	FABS( t );
+	mul( TwoForty, U2, t2 );
+	if( cmp( t, t2 ) > 0 )
+		{
+		N = 1;
+		sub( BInvrse, X, V9 );
+		sub( BInvrse, One, t );
+		sub( t, V9, V9 );
+		ErrCnt[Defect] += 1;
+		printf( "Calculated " );
+		show( Sqarg );
+		printf(" for \t(1 + " );
+		show( V9 );
+		printf( "\tto the power " );
+		show( Z );
+		printf("\tdiffers from correct value by " );
+		show( Q );
+		printf("\tThis much error may spoil financial\n");
+		printf("\tcalculations involving tiny interest rates.\n");
+		break;
+		}
+	else
+		{
+		sub( X, Y, Z );
+		mul( Z, Two, Z );
+		add( Z, Y, Z );
+		mov( Y, X );
+		mov( Z, Y );
+		sub( F9, X, Z );
+		mul( Z, Z, Z );
+		add( Z, One, Z );
+		if( (cmp(Z,One) > 0) && (I < NoTrials) )
+			I++;
+		else
+			{
+			if( cmp(X,One) > 0 )
+				{
+				if(N == 0)
+					printf("Accuracy seems adequate.\n");
+				break;
+				}
+			else
+				{
+				add( One, U2, X );
+				add( U2, U2, Y );
+				add( X, Y, Y );
+				I = 1;
+				}
+			}
+		}
+	}
+/*=============================================*/
+Milestone = 150;
+/*=============================================*/
+printf("Testing powers Z^Q at four nearly extreme values.\n");
+N = 0;
+mov( A1, Z );
+/*Q = FLOOR(Half - LOG(C) / LOG(A1));*/
+LOG( C, t );
+LOG( A1, t2 );
+div( t2, t, t );
+sub( t, Half, t );
+FLOOR( t, Q );
+Break = False;
+do
+	{
+	mov( CInvrse, X );
+	POW( Z, Q, Y );
+	IsYeqX();
+	neg(Q);
+	mov( C, X );
+	POW( Z, Q, Y );
+	IsYeqX();
+	if( cmp(Z,One) < 0 )
+		Break = True;
+	else
+		mov( AInvrse, Z );
+	}
+while( ! (Break));
+PrintIfNPositive();
+if(N == 0)
+	printf(" ... no discrepancies found.\n");
+printf("\n");
+}

+ 215 - 215
test/math/epow.c

@@ -1,215 +1,215 @@
-/*						epow.c	*/
-/*  power function: z = x**y */
-/*  by Stephen L. Moshier. */
-
-
-#include "ehead.h"
-#define MAXPOS ((long) (((unsigned long) ~(0L)) >> 1))
-#define MAXNEG (-MAXPOS)
-/* #define MAXNEG (-MAXPOS - 1L) */
-
-extern int rndprc;
-void epowi();
-static void epowr();
-
-
-/* Run-time determination of largest integers */
-
-int powinited = 0;
-unsigned short maxposint[NE], maxnegint[NE];
-
-void initpow()
-{
-long li;
-
-li = MAXPOS;
-ltoe( &li, maxposint );
-li = MAXNEG;
-ltoe( &li, maxnegint );
-powinited = 1;
-}
-
-
-
-
-void epow( x, y, z )
-unsigned short *x, *y, *z;
-{
-unsigned short w[NE];
-int rndsav;
-long li;
-
-if( powinited == 0 )
-	initpow();
-
-/* Check for integer power. */
-
-efloor( y, w );
-if( (ecmp(y,w) == 0)
-   && (ecmp(maxposint,w) >= 0)
-   && (ecmp(w,maxnegint) >= 0) )
-	{
-	eifrac( y, &li, w );
-	epowi( x, y, z );
-	return;
-	}
-epowr( x, y, z );
-}
-
-
-
-
-/* y is integer valued. */
-
-void epowi( x, y, z )
-unsigned short x[], y[], z[];
-{
-unsigned short w[NE];
-long li, lx;
-unsigned long lu;
-int rndsav;
-unsigned short signx;
-/* unsigned short signy; */
-
-if( powinited == 0 )
-	initpow();
-
-rndsav = rndprc;
-
-if( (ecmp(y,maxposint) > 0) || (ecmp(maxnegint,y) > 0) )
-	{
-	epowr( x, y, z );
-	return;
-	}
-
-eifrac( y, &li, w );
-if( li < 0 )
-	lx = -li;
-else
-	lx = li;
-
-/*
-if( (x[NE-1] & (unsigned short )0x7fff) == 0 )
-*/
-
-if( ecmp( x, ezero) == 0 )
-	{
-	if( li == 0 )
-		{
-		emov( eone, z );
-		return;
-		}
-	else if( li < 0 )
-		{
-		einfin( z );
-		return;
-		}
-	else
-		{
-		eclear( z );
-		return;
-		}
-	}
-
-if( li == 0L )
-	{
-	emov( eone, z );
-	return;
-	}
-
-emov( x, w );
-signx = w[NE-1] & (unsigned short )0x8000;
-w[NE-1] &= (unsigned short )0x7fff;
-
-/* Overflow detection */
-/*
-lx = li * (w[NE-1] - 0x3fff);
-if( lx > 16385L )
-	{
-	einfin( z );
-	mtherr( "epowi", OVERFLOW );
-	goto done;
-	}
-if( lx < -16450L )
-	{
-	eclear( z );
-	return;
-	}
-*/
-rndprc = NBITS;
-
-if( li < 0 )
-	{
-	lu = (unsigned int )( -li );
-/*	signy = 0xffff;*/
-	ediv( w, eone, w );
-	}
-else
-	{
-	lu = (unsigned int )li;
-/*	signy = 0;*/
-	}
-
-/* First bit of the power */
-if( lu & 1 )
-	{
-	emov( w, z );
-	}	
-else
-	{
-	emov( eone, z );
-	signx = 0;
-	}
-
-
-lu >>= 1;
-while( lu != 0L )
-	{
-	emul( w, w, w );	/* arg to the 2-to-the-kth power */
-	if( lu & 1L )	/* if that bit is set, then include in product */
-		emul( w, z, z );
-	lu >>= 1;
-	}
-
-
-done:
-
-if( signx )
-	eneg( z ); /* odd power of negative number */
-
-/*
-if( signy )
-  	{
-  	if( ecmp( z, ezero ) != 0 )
- 		{
-		ediv( z, eone, z );
-		}
-	else
-		{
-		einfin( z );
-		printf( "epowi OVERFLOW\n" );
-		}
-	}
-*/
-rndprc = rndsav;
-emul( eone, z, z );
-}
-
-
-
-/* z = exp( y * log(x) ) */
-
-static void epowr( x, y, z )
-unsigned short *x, *y, *z;
-{
-unsigned short w[NE];
-int rndsav;
-
-rndsav = rndprc;
-rndprc = NBITS;
-elog( x, w );
-emul( y, w, w );
-eexp( w, z );
-rndprc = rndsav;
-emul( eone, z, z );
-}
+/*						epow.c	*/
+/*  power function: z = x**y */
+/*  by Stephen L. Moshier. */
+
+
+#include "ehead.h"
+#define MAXPOS ((long) (((unsigned long) ~(0L)) >> 1))
+#define MAXNEG (-MAXPOS)
+/* #define MAXNEG (-MAXPOS - 1L) */
+
+extern int rndprc;
+void epowi();
+static void epowr();
+
+
+/* Run-time determination of largest integers */
+
+int powinited = 0;
+unsigned short maxposint[NE], maxnegint[NE];
+
+void initpow()
+{
+long li;
+
+li = MAXPOS;
+ltoe( &li, maxposint );
+li = MAXNEG;
+ltoe( &li, maxnegint );
+powinited = 1;
+}
+
+
+
+
+void epow( x, y, z )
+unsigned short *x, *y, *z;
+{
+unsigned short w[NE];
+int rndsav;
+long li;
+
+if( powinited == 0 )
+	initpow();
+
+/* Check for integer power. */
+
+efloor( y, w );
+if( (ecmp(y,w) == 0)
+   && (ecmp(maxposint,w) >= 0)
+   && (ecmp(w,maxnegint) >= 0) )
+	{
+	eifrac( y, &li, w );
+	epowi( x, y, z );
+	return;
+	}
+epowr( x, y, z );
+}
+
+
+
+
+/* y is integer valued. */
+
+void epowi( x, y, z )
+unsigned short x[], y[], z[];
+{
+unsigned short w[NE];
+long li, lx;
+unsigned long lu;
+int rndsav;
+unsigned short signx;
+/* unsigned short signy; */
+
+if( powinited == 0 )
+	initpow();
+
+rndsav = rndprc;
+
+if( (ecmp(y,maxposint) > 0) || (ecmp(maxnegint,y) > 0) )
+	{
+	epowr( x, y, z );
+	return;
+	}
+
+eifrac( y, &li, w );
+if( li < 0 )
+	lx = -li;
+else
+	lx = li;
+
+/*
+if( (x[NE-1] & (unsigned short )0x7fff) == 0 )
+*/
+
+if( ecmp( x, ezero) == 0 )
+	{
+	if( li == 0 )
+		{
+		emov( eone, z );
+		return;
+		}
+	else if( li < 0 )
+		{
+		einfin( z );
+		return;
+		}
+	else
+		{
+		eclear( z );
+		return;
+		}
+	}
+
+if( li == 0L )
+	{
+	emov( eone, z );
+	return;
+	}
+
+emov( x, w );
+signx = w[NE-1] & (unsigned short )0x8000;
+w[NE-1] &= (unsigned short )0x7fff;
+
+/* Overflow detection */
+/*
+lx = li * (w[NE-1] - 0x3fff);
+if( lx > 16385L )
+	{
+	einfin( z );
+	mtherr( "epowi", OVERFLOW );
+	goto done;
+	}
+if( lx < -16450L )
+	{
+	eclear( z );
+	return;
+	}
+*/
+rndprc = NBITS;
+
+if( li < 0 )
+	{
+	lu = (unsigned int )( -li );
+/*	signy = 0xffff;*/
+	ediv( w, eone, w );
+	}
+else
+	{
+	lu = (unsigned int )li;
+/*	signy = 0;*/
+	}
+
+/* First bit of the power */
+if( lu & 1 )
+	{
+	emov( w, z );
+	}	
+else
+	{
+	emov( eone, z );
+	signx = 0;
+	}
+
+
+lu >>= 1;
+while( lu != 0L )
+	{
+	emul( w, w, w );	/* arg to the 2-to-the-kth power */
+	if( lu & 1L )	/* if that bit is set, then include in product */
+		emul( w, z, z );
+	lu >>= 1;
+	}
+
+
+done:
+
+if( signx )
+	eneg( z ); /* odd power of negative number */
+
+/*
+if( signy )
+  	{
+  	if( ecmp( z, ezero ) != 0 )
+ 		{
+		ediv( z, eone, z );
+		}
+	else
+		{
+		einfin( z );
+		printf( "epowi OVERFLOW\n" );
+		}
+	}
+*/
+rndprc = rndsav;
+emul( eone, z, z );
+}
+
+
+
+/* z = exp( y * log(x) ) */
+
+static void epowr( x, y, z )
+unsigned short *x, *y, *z;
+{
+unsigned short w[NE];
+int rndsav;
+
+rndsav = rndprc;
+rndprc = NBITS;
+elog( x, w );
+emul( y, w, w );
+eexp( w, z );
+rndprc = rndsav;
+emul( eone, z, z );
+}

+ 52 - 52
test/math/etanh.c

@@ -1,52 +1,52 @@
-/*							xtanh.c		*/
-/* hyperbolic tangent check routine */
-/* this subroutine is used by the exponential function routine */
-/* by Stephen L. Moshier. */
-
-
-
-#include "ehead.h"
-
-
-void etanh( x, y )
-unsigned short *x, *y;
-{
-unsigned short e[NE], r[NE], j[NE], xx[NE], m2[NE];
-short i, n;
-long lj;
-
-emov( x, r );
-r[NE-1] &= (unsigned short )0x7fff;
-if( ecmp(r, eone) >= 0 )
-	{
-/* tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
- * Note eexp() calls xtanh, but with an argument less than (1 + log 2)/2.
- */
-	eexp( r, e );
-	ediv( e, eone, r );
-	esub( r, e, xx );
-	eadd( r, e, j );
-	ediv( j, xx, y );
-	return;
-	}
-
-emov( etwo, m2 );
-eneg( m2 );
-
-n = NBITS/8;	/* Number of terms to do in the continued fraction */
-lj = 2 * n + 1;
-ltoe( &lj, j );
-
-emov( j, e );
-emul( x, x, xx );
-
-/* continued fraction */
-for( i=0; i<n; i++)
-	{
-	ediv( e, xx, r );
-	eadd( m2, j, j );
-	eadd( r, j, e );
-	}
-
-ediv( e, x, y );
-}
+/*							xtanh.c		*/
+/* hyperbolic tangent check routine */
+/* this subroutine is used by the exponential function routine */
+/* by Stephen L. Moshier. */
+
+
+
+#include "ehead.h"
+
+
+void etanh( x, y )
+unsigned short *x, *y;
+{
+unsigned short e[NE], r[NE], j[NE], xx[NE], m2[NE];
+short i, n;
+long lj;
+
+emov( x, r );
+r[NE-1] &= (unsigned short )0x7fff;
+if( ecmp(r, eone) >= 0 )
+	{
+/* tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
+ * Note eexp() calls xtanh, but with an argument less than (1 + log 2)/2.
+ */
+	eexp( r, e );
+	ediv( e, eone, r );
+	esub( r, e, xx );
+	eadd( r, e, j );
+	ediv( j, xx, y );
+	return;
+	}
+
+emov( etwo, m2 );
+eneg( m2 );
+
+n = NBITS/8;	/* Number of terms to do in the continued fraction */
+lj = 2 * n + 1;
+ltoe( &lj, j );
+
+emov( j, e );
+emul( x, x, xx );
+
+/* continued fraction */
+for( i=0; i<n; i++)
+	{
+	ediv( e, xx, r );
+	eadd( m2, j, j );
+	eadd( r, j, e );
+	}
+
+ediv( e, x, y );
+}

+ 181 - 181
test/math/etodec.c

@@ -1,181 +1,181 @@
-#include "ehead.h"
-void emovi(), emovo(), ecleaz(), eshdn8(), emdnorm();
-void todec();
-/*
-;	convert DEC double precision to e type
-;	double d;
-;	short e[NE];
-;	dectoe( &d, e );
-*/
-void dectoe( d, e )
-unsigned short *d;
-unsigned short *e;
-{
-unsigned short y[NI];
-register unsigned short r, *p;
-
-ecleaz(y);		/* start with a zero */
-p = y;			/* point to our number */
-r = *d;			/* get DEC exponent word */
-if( *d & (unsigned int )0x8000 )
-	*p = 0xffff;	/* fill in our sign */
-++p;			/* bump pointer to our exponent word */
-r &= 0x7fff;		/* strip the sign bit */
-if( r == 0 )		/* answer = 0 if high order DEC word = 0 */
-	goto done;
-
-
-r >>= 7;	/* shift exponent word down 7 bits */
-r += EXONE - 0201;	/* subtract DEC exponent offset */
-			/* add our e type exponent offset */
-*p++ = r;	/* to form our exponent */
-
-r = *d++;	/* now do the high order mantissa */
-r &= 0177;	/* strip off the DEC exponent and sign bits */
-r |= 0200;	/* the DEC understood high order mantissa bit */
-*p++ = r;	/* put result in our high guard word */
-
-*p++ = *d++;	/* fill in the rest of our mantissa */
-*p++ = *d++;
-*p = *d;
-
-eshdn8(y);	/* shift our mantissa down 8 bits */
-done:
-emovo( y, e );
-}
-
-
-
-/*
-;	convert e type to DEC double precision
-;	double d;
-;	short e[NE];
-;	etodec( e, &d );
-*/
-#if 0
-static unsigned short decbit[NI] = {0,0,0,0,0,0,0200,0};
-void etodec( x, d )
-unsigned short *x, *d;
-{
-unsigned short xi[NI];
-register unsigned short r;
-int i, j;
-
-emovi( x, xi );
-*d = 0;
-if( xi[0] != 0 )
-	*d = 0100000;
-r = xi[E];
-if( r < (EXONE - 128) )
-	goto zout;
-i = xi[M+4];
-if( (i & 0200) != 0 )
-	{
-	if( (i & 0377) == 0200 )
-		{
-		if( (i & 0400) != 0 )
-			{
-		/* check all less significant bits */
-			for( j=M+5; j<NI; j++ )
-				{
-				if( xi[j] != 0 )
-					goto yesrnd;
-				}
-			}
-		goto nornd;
-		}
-yesrnd:
-	eaddm( decbit, xi );
-	r -= enormlz(xi);
-	}
-
-nornd:
-
-r -= EXONE;
-r += 0201;
-if( r < 0 )
-	{
-zout:
-	*d++ = 0;
-	*d++ = 0;
-	*d++ = 0;
-	*d++ = 0;
-	return;
-	}
-if( r >= 0377 )
-	{
-	*d++ = 077777;
-	*d++ = -1;
-	*d++ = -1;
-	*d++ = -1;
-	return;
-	}
-r &= 0377;
-r <<= 7;
-eshup8( xi );
-xi[M] &= 0177;
-r |= xi[M];
-*d++ |= r;
-*d++ = xi[M+1];
-*d++ = xi[M+2];
-*d++ = xi[M+3];
-}
-#else
-
-extern int rndprc;
-
-void etodec( x, d )
-unsigned short *x, *d;
-{
-unsigned short xi[NI];
-long exp;
-int rndsav;
-
-emovi( x, xi );
-exp = (long )xi[E] - (EXONE - 0201); /* adjust exponent for offsets */
-/* round off to nearest or even */
-rndsav = rndprc;
-rndprc = 56;
-emdnorm( xi, 0, 0, exp, 64 );
-rndprc = rndsav;
-todec( xi, d );
-}
-
-void todec( x, y )
-unsigned short *x, *y;
-{
-unsigned short i;
-unsigned short *p;
-
-p = x;
-*y = 0;
-if( *p++ )
-	*y = 0100000;
-i = *p++;
-if( i == 0 )
-	{
-	*y++ = 0;
-	*y++ = 0;
-	*y++ = 0;
-	*y++ = 0;
-	return;
-	}
-if( i > 0377 )
-	{
-	*y++ |= 077777;
-	*y++ = 0xffff;
-	*y++ = 0xffff;
-	*y++ = 0xffff;
-	return;
-	}
-i &= 0377;
-i <<= 7;
-eshup8( x );
-x[M] &= 0177;
-i |= x[M];
-*y++ |= i;
-*y++ = x[M+1];
-*y++ = x[M+2];
-*y++ = x[M+3];
-}
-#endif
+#include "ehead.h"
+void emovi(), emovo(), ecleaz(), eshdn8(), emdnorm();
+void todec();
+/*
+;	convert DEC double precision to e type
+;	double d;
+;	short e[NE];
+;	dectoe( &d, e );
+*/
+void dectoe( d, e )
+unsigned short *d;
+unsigned short *e;
+{
+unsigned short y[NI];
+register unsigned short r, *p;
+
+ecleaz(y);		/* start with a zero */
+p = y;			/* point to our number */
+r = *d;			/* get DEC exponent word */
+if( *d & (unsigned int )0x8000 )
+	*p = 0xffff;	/* fill in our sign */
+++p;			/* bump pointer to our exponent word */
+r &= 0x7fff;		/* strip the sign bit */
+if( r == 0 )		/* answer = 0 if high order DEC word = 0 */
+	goto done;
+
+
+r >>= 7;	/* shift exponent word down 7 bits */
+r += EXONE - 0201;	/* subtract DEC exponent offset */
+			/* add our e type exponent offset */
+*p++ = r;	/* to form our exponent */
+
+r = *d++;	/* now do the high order mantissa */
+r &= 0177;	/* strip off the DEC exponent and sign bits */
+r |= 0200;	/* the DEC understood high order mantissa bit */
+*p++ = r;	/* put result in our high guard word */
+
+*p++ = *d++;	/* fill in the rest of our mantissa */
+*p++ = *d++;
+*p = *d;
+
+eshdn8(y);	/* shift our mantissa down 8 bits */
+done:
+emovo( y, e );
+}
+
+
+
+/*
+;	convert e type to DEC double precision
+;	double d;
+;	short e[NE];
+;	etodec( e, &d );
+*/
+#if 0
+static unsigned short decbit[NI] = {0,0,0,0,0,0,0200,0};
+void etodec( x, d )
+unsigned short *x, *d;
+{
+unsigned short xi[NI];
+register unsigned short r;
+int i, j;
+
+emovi( x, xi );
+*d = 0;
+if( xi[0] != 0 )
+	*d = 0100000;
+r = xi[E];
+if( r < (EXONE - 128) )
+	goto zout;
+i = xi[M+4];
+if( (i & 0200) != 0 )
+	{
+	if( (i & 0377) == 0200 )
+		{
+		if( (i & 0400) != 0 )
+			{
+		/* check all less significant bits */
+			for( j=M+5; j<NI; j++ )
+				{
+				if( xi[j] != 0 )
+					goto yesrnd;
+				}
+			}
+		goto nornd;
+		}
+yesrnd:
+	eaddm( decbit, xi );
+	r -= enormlz(xi);
+	}
+
+nornd:
+
+r -= EXONE;
+r += 0201;
+if( r < 0 )
+	{
+zout:
+	*d++ = 0;
+	*d++ = 0;
+	*d++ = 0;
+	*d++ = 0;
+	return;
+	}
+if( r >= 0377 )
+	{
+	*d++ = 077777;
+	*d++ = -1;
+	*d++ = -1;
+	*d++ = -1;
+	return;
+	}
+r &= 0377;
+r <<= 7;
+eshup8( xi );
+xi[M] &= 0177;
+r |= xi[M];
+*d++ |= r;
+*d++ = xi[M+1];
+*d++ = xi[M+2];
+*d++ = xi[M+3];
+}
+#else
+
+extern int rndprc;
+
+void etodec( x, d )
+unsigned short *x, *d;
+{
+unsigned short xi[NI];
+long exp;
+int rndsav;
+
+emovi( x, xi );
+exp = (long )xi[E] - (EXONE - 0201); /* adjust exponent for offsets */
+/* round off to nearest or even */
+rndsav = rndprc;
+rndprc = 56;
+emdnorm( xi, 0, 0, exp, 64 );
+rndprc = rndsav;
+todec( xi, d );
+}
+
+void todec( x, y )
+unsigned short *x, *y;
+{
+unsigned short i;
+unsigned short *p;
+
+p = x;
+*y = 0;
+if( *p++ )
+	*y = 0100000;
+i = *p++;
+if( i == 0 )
+	{
+	*y++ = 0;
+	*y++ = 0;
+	*y++ = 0;
+	*y++ = 0;
+	return;
+	}
+if( i > 0377 )
+	{
+	*y++ |= 077777;
+	*y++ = 0xffff;
+	*y++ = 0xffff;
+	*y++ = 0xffff;
+	return;
+	}
+i &= 0377;
+i <<= 7;
+eshup8( x );
+x[M] &= 0177;
+i |= x[M];
+*y++ |= i;
+*y++ = x[M+1];
+*y++ = x[M+2];
+*y++ = x[M+3];
+}
+#endif

+ 4119 - 4119
test/math/ieee.c

@@ -1,4119 +1,4119 @@
-/*							ieee.c
- *
- *    Extended precision IEEE binary floating point arithmetic routines
- *
- * Numbers are stored in C language as arrays of 16-bit unsigned
- * short integers.  The arguments of the routines are pointers to
- * the arrays.
- *
- *
- * External e type data structure, simulates Intel 8087 chip
- * temporary real format but possibly with a larger significand:
- *
- *	NE-1 significand words	(least significant word first,
- *				 most significant bit is normally set)
- *	exponent		(value = EXONE for 1.0,
- *				top bit is the sign)
- *
- *
- * Internal data structure of a number (a "word" is 16 bits):
- *
- * ei[0]	sign word	(0 for positive, 0xffff for negative)
- * ei[1]	biased exponent	(value = EXONE for the number 1.0)
- * ei[2]	high guard word	(always zero after normalization)
- * ei[3]
- * to ei[NI-2]	significand	(NI-4 significand words,
- *				 most significant word first,
- *				 most significant bit is set)
- * ei[NI-1]	low guard word	(0x8000 bit is rounding place)
- *
- *
- *
- *		Routines for external format numbers
- *
- *	asctoe( string, e )	ASCII string to extended double e type
- *	asctoe64( string, &d )	ASCII string to long double
- *	asctoe53( string, &d )	ASCII string to double
- *	asctoe24( string, &f )	ASCII string to single
- *	asctoeg( string, e, prec ) ASCII string to specified precision
- *	e24toe( &f, e )		IEEE single precision to e type
- *	e53toe( &d, e )		IEEE double precision to e type
- *	e64toe( &d, e )		IEEE long double precision to e type
- *	eabs(e)			absolute value
- *	eadd( a, b, c )		c = b + a
- *	eclear(e)		e = 0
- *	ecmp (a, b)		Returns 1 if a > b, 0 if a == b,
- *				-1 if a < b, -2 if either a or b is a NaN.
- *	ediv( a, b, c )		c = b / a
- *	efloor( a, b )		truncate to integer, toward -infinity
- *	efrexp( a, exp, s )	extract exponent and significand
- *	eifrac( e, &l, frac )   e to long integer and e type fraction
- *	euifrac( e, &l, frac )  e to unsigned long integer and e type fraction
- *	einfin( e )		set e to infinity, leaving its sign alone
- *	eldexp( a, n, b )	multiply by 2**n
- *	emov( a, b )		b = a
- *	emul( a, b, c )		c = b * a
- *	eneg(e)			e = -e
- *	eround( a, b )		b = nearest integer value to a
- *	esub( a, b, c )		c = b - a
- *	e24toasc( &f, str, n )	single to ASCII string, n digits after decimal
- *	e53toasc( &d, str, n )	double to ASCII string, n digits after decimal
- *	e64toasc( &d, str, n )	long double to ASCII string
- *	etoasc( e, str, n )	e to ASCII string, n digits after decimal
- *	etoe24( e, &f )		convert e type to IEEE single precision
- *	etoe53( e, &d )		convert e type to IEEE double precision
- *	etoe64( e, &d )		convert e type to IEEE long double precision
- *	ltoe( &l, e )		long (32 bit) integer to e type
- *	ultoe( &l, e )		unsigned long (32 bit) integer to e type
- *      eisneg( e )             1 if sign bit of e != 0, else 0
- *      eisinf( e )             1 if e has maximum exponent (non-IEEE)
- *				or is infinite (IEEE)
- *      eisnan( e )             1 if e is a NaN
- *	esqrt( a, b )		b = square root of a
- *
- *
- *		Routines for internal format numbers
- *
- *	eaddm( ai, bi )		add significands, bi = bi + ai
- *	ecleaz(ei)		ei = 0
- *	ecleazs(ei)		set ei = 0 but leave its sign alone
- *	ecmpm( ai, bi )		compare significands, return 1, 0, or -1
- *	edivm( ai, bi )		divide  significands, bi = bi / ai
- *	emdnorm(ai,l,s,exp)	normalize and round off
- *	emovi( a, ai )		convert external a to internal ai
- *	emovo( ai, a )		convert internal ai to external a
- *	emovz( ai, bi )		bi = ai, low guard word of bi = 0
- *	emulm( ai, bi )		multiply significands, bi = bi * ai
- *	enormlz(ei)		left-justify the significand
- *	eshdn1( ai )		shift significand and guards down 1 bit
- *	eshdn8( ai )		shift down 8 bits
- *	eshdn6( ai )		shift down 16 bits
- *	eshift( ai, n )		shift ai n bits up (or down if n < 0)
- *	eshup1( ai )		shift significand and guards up 1 bit
- *	eshup8( ai )		shift up 8 bits
- *	eshup6( ai )		shift up 16 bits
- *	esubm( ai, bi )		subtract significands, bi = bi - ai
- *
- *
- * The result is always normalized and rounded to NI-4 word precision
- * after each arithmetic operation.
- *
- * Exception flags are NOT fully supported.
- *
- * Define INFINITY in mconf.h for support of infinity; otherwise a
- * saturation arithmetic is implemented.
- *
- * Define NANS for support of Not-a-Number items; otherwise the
- * arithmetic will never produce a NaN output, and might be confused
- * by a NaN input.
- * If NaN's are supported, the output of ecmp(a,b) is -2 if
- * either a or b is a NaN. This means asking if(ecmp(a,b) < 0)
- * may not be legitimate. Use if(ecmp(a,b) == -1) for less-than
- * if in doubt.
- * Signaling NaN's are NOT supported; they are treated the same
- * as quiet NaN's.
- *
- * Denormals are always supported here where appropriate (e.g., not
- * for conversion to DEC numbers).
- */
-
-/*
- * Revision history:
- *
- *  5 Jan 84	PDP-11 assembly language version
- *  2 Mar 86	fixed bug in asctoq()
- *  6 Dec 86	C language version
- * 30 Aug 88	100 digit version, improved rounding
- * 15 May 92    80-bit long double support
- *
- * Author:  S. L. Moshier.
- */
-
-#include <stdio.h>
-/* #include "\usr\include\stdio.h" */
-#include "ehead.h"
-#include "mconf.h"
-
-/* Change UNK into something else. */
-#ifdef UNK
-#undef UNK
-#define IBMPC 1
-#endif
-
-/* NaN's require infinity support. */
-#ifdef NANS
-#ifndef INFINITY
-#define INFINITY
-#endif
-#endif
-
-/* This handles 64-bit long ints. */
-#define LONGBITS (8 * sizeof(long))
-
-/* Control register for rounding precision.
- * This can be set to 80 (if NE=6), 64, 56, 53, or 24 bits.
- */
-int rndprc = NBITS;
-extern int rndprc;
-
-void eaddm(), esubm(), emdnorm(), asctoeg(), enan();
-static void toe24(), toe53(), toe64(), toe113();
-void eremain(), einit(), eiremain();
-int ecmpm(), edivm(), emulm(), eisneg(), eisinf();
-void emovi(), emovo(), emovz(), ecleaz(), eadd1();
-void etodec(), todec(), dectoe();
-int eisnan(), eiisnan();
-
-
-
-void einit()
-{
-}
-
-/*
-; Clear out entire external format number.
-;
-; unsigned short x[];
-; eclear( x );
-*/
-
-void eclear( x )
-register unsigned short *x;
-{
-register int i;
-
-for( i=0; i<NE; i++ )
-	*x++ = 0;
-}
-
-
-
-/* Move external format number from a to b.
- *
- * emov( a, b );
- */
-
-void emov( a, b )
-register unsigned short *a, *b;
-{
-register int i;
-
-for( i=0; i<NE; i++ )
-	*b++ = *a++;
-}
-
-
-/*
-;	Absolute value of external format number
-;
-;	short x[NE];
-;	eabs( x );
-*/
-
-void eabs(x)
-unsigned short x[];	/* x is the memory address of a short */
-{
-
-x[NE-1] &= 0x7fff; /* sign is top bit of last word of external format */
-}
-
-
-
-
-/*
-;	Negate external format number
-;
-;	unsigned short x[NE];
-;	eneg( x );
-*/
-
-void eneg(x)
-unsigned short x[];
-{
-
-#ifdef NANS
-if( eisnan(x) )
-	return;
-#endif
-x[NE-1] ^= 0x8000; /* Toggle the sign bit */
-}
-
-
-
-/* Return 1 if external format number is negative,
- * else return zero.
- */
-int eisneg(x)
-unsigned short x[];
-{
-
-#ifdef NANS
-if( eisnan(x) )
-	return( 0 );
-#endif
-if( x[NE-1] & 0x8000 )
-	return( 1 );
-else
-	return( 0 );
-}
-
-
-/* Return 1 if external format number has maximum possible exponent,
- * else return zero.
- */
-int eisinf(x)
-unsigned short x[];
-{
-
-if( (x[NE-1] & 0x7fff) == 0x7fff )
-	{
-#ifdef NANS
-	if( eisnan(x) )
-		return( 0 );
-#endif
-	return( 1 );
-	}
-else
-	return( 0 );
-}
-
-/* Check if e-type number is not a number.
- */
-int eisnan(x)
-unsigned short x[];
-{
-
-#ifdef NANS
-int i;
-/* NaN has maximum exponent */
-if( (x[NE-1] & 0x7fff) != 0x7fff )
-	return (0);
-/* ... and non-zero significand field. */
-for( i=0; i<NE-1; i++ )
-	{
-	if( *x++ != 0 )
-		return (1);
-	}
-#endif
-return (0);
-}
-
-/*
-; Fill entire number, including exponent and significand, with
-; largest possible number.  These programs implement a saturation
-; value that is an ordinary, legal number.  A special value
-; "infinity" may also be implemented; this would require tests
-; for that value and implementation of special rules for arithmetic
-; operations involving inifinity.
-*/
-
-void einfin(x)
-register unsigned short *x;
-{
-register int i;
-
-#ifdef INFINITY
-for( i=0; i<NE-1; i++ )
-	*x++ = 0;
-*x |= 32767;
-#else
-for( i=0; i<NE-1; i++ )
-	*x++ = 0xffff;
-*x |= 32766;
-if( rndprc < NBITS )
-	{
-	if (rndprc == 113)
-		{
-		*(x - 9) = 0;
-		*(x - 8) = 0;
-		}
-	if( rndprc == 64 )
-		{
-		*(x-5) = 0;
-		}
-	if( rndprc == 53 )
-		{
-		*(x-4) = 0xf800;
-		}
-	else
-		{
-		*(x-4) = 0;
-		*(x-3) = 0;
-		*(x-2) = 0xff00;
-		}
-	}
-#endif
-}
-
-
-
-/* Move in external format number,
- * converting it to internal format.
- */
-void emovi( a, b )
-unsigned short *a, *b;
-{
-register unsigned short *p, *q;
-int i;
-
-q = b;
-p = a + (NE-1);	/* point to last word of external number */
-/* get the sign bit */
-if( *p & 0x8000 )
-	*q++ = 0xffff;
-else
-	*q++ = 0;
-/* get the exponent */
-*q = *p--;
-*q++ &= 0x7fff;	/* delete the sign bit */
-#ifdef INFINITY
-if( (*(q-1) & 0x7fff) == 0x7fff )
-	{
-#ifdef NANS
-	if( eisnan(a) )
-		{
-		*q++ = 0;
-		for( i=3; i<NI; i++ )
-			*q++ = *p--;
-		return;
-		}
-#endif
-	for( i=2; i<NI; i++ )
-		*q++ = 0;
-	return;
-	}
-#endif
-/* clear high guard word */
-*q++ = 0;
-/* move in the significand */
-for( i=0; i<NE-1; i++ )
-	*q++ = *p--;
-/* clear low guard word */
-*q = 0;
-}
-
-
-/* Move internal format number out,
- * converting it to external format.
- */
-void emovo( a, b )
-unsigned short *a, *b;
-{
-register unsigned short *p, *q;
-unsigned short i;
-
-p = a;
-q = b + (NE-1); /* point to output exponent */
-/* combine sign and exponent */
-i = *p++;
-if( i )
-	*q-- = *p++ | 0x8000;
-else
-	*q-- = *p++;
-#ifdef INFINITY
-if( *(p-1) == 0x7fff )
-	{
-#ifdef NANS
-	if( eiisnan(a) )
-		{
-		enan( b, NBITS );
-		return;
-		}
-#endif
-	einfin(b);
-	return;
-	}
-#endif
-/* skip over guard word */
-++p;
-/* move the significand */
-for( i=0; i<NE-1; i++ )
-	*q-- = *p++;
-}
-
-
-
-
-/* Clear out internal format number.
- */
-
-void ecleaz( xi )
-register unsigned short *xi;
-{
-register int i;
-
-for( i=0; i<NI; i++ )
-	*xi++ = 0;
-}
-
-/* same, but don't touch the sign. */
-
-void ecleazs( xi )
-register unsigned short *xi;
-{
-register int i;
-
-++xi;
-for(i=0; i<NI-1; i++)
-	*xi++ = 0;
-}
-
-
-
-
-/* Move internal format number from a to b.
- */
-void emovz( a, b )
-register unsigned short *a, *b;
-{
-register int i;
-
-for( i=0; i<NI-1; i++ )
-	*b++ = *a++;
-/* clear low guard word */
-*b = 0;
-}
-
-/* Return nonzero if internal format number is a NaN.
- */
-
-int eiisnan (x)
-unsigned short x[];
-{
-int i;
-
-if( (x[E] & 0x7fff) == 0x7fff )
-	{
-	for( i=M+1; i<NI; i++ )
-		{
-		if( x[i] != 0 )
-			return(1);
-		}
-	}
-return(0);
-}
-
-#ifdef INFINITY
-/* Return nonzero if internal format number is infinite. */
-
-static int 
-eiisinf (x)
-     unsigned short x[];
-{
-
-#ifdef NANS
-  if (eiisnan (x))
-    return (0);
-#endif
-  if ((x[E] & 0x7fff) == 0x7fff)
-    return (1);
-  return (0);
-}
-#endif
-
-/*
-;	Compare significands of numbers in internal format.
-;	Guard words are included in the comparison.
-;
-;	unsigned short a[NI], b[NI];
-;	cmpm( a, b );
-;
-;	for the significands:
-;	returns	+1 if a > b
-;		 0 if a == b
-;		-1 if a < b
-*/
-int ecmpm( a, b )
-register unsigned short *a, *b;
-{
-int i;
-
-a += M; /* skip up to significand area */
-b += M;
-for( i=M; i<NI; i++ )
-	{
-	if( *a++ != *b++ )
-		goto difrnt;
-	}
-return(0);
-
-difrnt:
-if( *(--a) > *(--b) )
-	return(1);
-else
-	return(-1);
-}
-
-
-/*
-;	Shift significand down by 1 bit
-*/
-
-void eshdn1(x)
-register unsigned short *x;
-{
-register unsigned short bits;
-int i;
-
-x += M;	/* point to significand area */
-
-bits = 0;
-for( i=M; i<NI; i++ )
-	{
-	if( *x & 1 )
-		bits |= 1;
-	*x >>= 1;
-	if( bits & 2 )
-		*x |= 0x8000;
-	bits <<= 1;
-	++x;
-	}	
-}
-
-
-
-/*
-;	Shift significand up by 1 bit
-*/
-
-void eshup1(x)
-register unsigned short *x;
-{
-register unsigned short bits;
-int i;
-
-x += NI-1;
-bits = 0;
-
-for( i=M; i<NI; i++ )
-	{
-	if( *x & 0x8000 )
-		bits |= 1;
-	*x <<= 1;
-	if( bits & 2 )
-		*x |= 1;
-	bits <<= 1;
-	--x;
-	}
-}
-
-
-
-/*
-;	Shift significand down by 8 bits
-*/
-
-void eshdn8(x)
-register unsigned short *x;
-{
-register unsigned short newbyt, oldbyt;
-int i;
-
-x += M;
-oldbyt = 0;
-for( i=M; i<NI; i++ )
-	{
-	newbyt = *x << 8;
-	*x >>= 8;
-	*x |= oldbyt;
-	oldbyt = newbyt;
-	++x;
-	}
-}
-
-/*
-;	Shift significand up by 8 bits
-*/
-
-void eshup8(x)
-register unsigned short *x;
-{
-int i;
-register unsigned short newbyt, oldbyt;
-
-x += NI-1;
-oldbyt = 0;
-
-for( i=M; i<NI; i++ )
-	{
-	newbyt = *x >> 8;
-	*x <<= 8;
-	*x |= oldbyt;
-	oldbyt = newbyt;
-	--x;
-	}
-}
-
-/*
-;	Shift significand up by 16 bits
-*/
-
-void eshup6(x)
-register unsigned short *x;
-{
-int i;
-register unsigned short *p;
-
-p = x + M;
-x += M + 1;
-
-for( i=M; i<NI-1; i++ )
-	*p++ = *x++;
-
-*p = 0;
-}
-
-/*
-;	Shift significand down by 16 bits
-*/
-
-void eshdn6(x)
-register unsigned short *x;
-{
-int i;
-register unsigned short *p;
-
-x += NI-1;
-p = x + 1;
-
-for( i=M; i<NI-1; i++ )
-	*(--p) = *(--x);
-
-*(--p) = 0;
-}
-
-/*
-;	Add significands
-;	x + y replaces y
-*/
-
-void eaddm( x, y )
-unsigned short *x, *y;
-{
-register unsigned long a;
-int i;
-unsigned int carry;
-
-x += NI-1;
-y += NI-1;
-carry = 0;
-for( i=M; i<NI; i++ )
-	{
-	a = (unsigned long )(*x) + (unsigned long )(*y) + carry;
-	if( a & 0x10000 )
-		carry = 1;
-	else
-		carry = 0;
-	*y = (unsigned short )a;
-	--x;
-	--y;
-	}
-}
-
-/*
-;	Subtract significands
-;	y - x replaces y
-*/
-
-void esubm( x, y )
-unsigned short *x, *y;
-{
-unsigned long a;
-int i;
-unsigned int carry;
-
-x += NI-1;
-y += NI-1;
-carry = 0;
-for( i=M; i<NI; i++ )
-	{
-	a = (unsigned long )(*y) - (unsigned long )(*x) - carry;
-	if( a & 0x10000 )
-		carry = 1;
-	else
-		carry = 0;
-	*y = (unsigned short )a;
-	--x;
-	--y;
-	}
-}
-
-
-/* Divide significands */
-
-static unsigned short equot[NI] = {0}; /* was static */
-
-#if 0
-int edivm( den, num )
-unsigned short den[], num[];
-{
-int i;
-register unsigned short *p, *q;
-unsigned short j;
-
-p = &equot[0];
-*p++ = num[0];
-*p++ = num[1];
-
-for( i=M; i<NI; i++ )
-	{
-	*p++ = 0;
-	}
-
-/* Use faster compare and subtraction if denominator
- * has only 15 bits of significance.
- */
-p = &den[M+2];
-if( *p++ == 0 )
-	{
-	for( i=M+3; i<NI; i++ )
-		{
-		if( *p++ != 0 )
-			goto fulldiv;
-		}
-	if( (den[M+1] & 1) != 0 )
-		goto fulldiv;
-	eshdn1(num);
-	eshdn1(den);
-
-	p = &den[M+1];
-	q = &num[M+1];
-
-	for( i=0; i<NBITS+2; i++ )
-		{
-		if( *p <= *q )
-			{
-			*q -= *p;
-			j = 1;
-			}
-		else
-			{
-			j = 0;
-			}
-		eshup1(equot);
-		equot[NI-2] |= j;
-		eshup1(num);
-		}
-	goto divdon;
-	}
-
-/* The number of quotient bits to calculate is
- * NBITS + 1 scaling guard bit + 1 roundoff bit.
- */
-fulldiv:
-
-p = &equot[NI-2];
-for( i=0; i<NBITS+2; i++ )
-	{
-	if( ecmpm(den,num) <= 0 )
-		{
-		esubm(den, num);
-		j = 1;	/* quotient bit = 1 */
-		}
-	else
-		j = 0;
-	eshup1(equot);
-	*p |= j;
-	eshup1(num);
-	}
-
-divdon:
-
-eshdn1( equot );
-eshdn1( equot );
-
-/* test for nonzero remainder after roundoff bit */
-p = &num[M];
-j = 0;
-for( i=M; i<NI; i++ )
-	{
-	j |= *p++;
-	}
-if( j )
-	j = 1;
-
-
-for( i=0; i<NI; i++ )
-	num[i] = equot[i];
-return( (int )j );
-}
-
-/* Multiply significands */
-int emulm( a, b )
-unsigned short a[], b[];
-{
-unsigned short *p, *q;
-int i, j, k;
-
-equot[0] = b[0];
-equot[1] = b[1];
-for( i=M; i<NI; i++ )
-	equot[i] = 0;
-
-p = &a[NI-2];
-k = NBITS;
-while( *p == 0 ) /* significand is not supposed to be all zero */
-	{
-	eshdn6(a);
-	k -= 16;
-	}
-if( (*p & 0xff) == 0 )
-	{
-	eshdn8(a);
-	k -= 8;
-	}
-
-q = &equot[NI-1];
-j = 0;
-for( i=0; i<k; i++ )
-	{
-	if( *p & 1 )
-		eaddm(b, equot);
-/* remember if there were any nonzero bits shifted out */
-	if( *q & 1 )
-		j |= 1;
-	eshdn1(a);
-	eshdn1(equot);
-	}
-
-for( i=0; i<NI; i++ )
-	b[i] = equot[i];
-
-/* return flag for lost nonzero bits */
-return(j);
-}
-
-#else
-
-/* Multiply significand of e-type number b
-by 16-bit quantity a, e-type result to c. */
-
-void m16m( a, b, c )
-unsigned short a;
-unsigned short b[], c[];
-{
-register unsigned short *pp;
-register unsigned long carry;
-unsigned short *ps;
-unsigned short p[NI];
-unsigned long aa, m;
-int i;
-
-aa = a;
-pp = &p[NI-2];
-*pp++ = 0;
-*pp = 0;
-ps = &b[NI-1];
-
-for( i=M+1; i<NI; i++ )
-	{
-	if( *ps == 0 )
-		{
-		--ps;
-		--pp;
-		*(pp-1) = 0;
-		}
-	else
-		{
-		m = (unsigned long) aa * *ps--;
-		carry = (m & 0xffff) + *pp;
-		*pp-- = (unsigned short )carry;
-		carry = (carry >> 16) + (m >> 16) + *pp;
-		*pp = (unsigned short )carry;
-		*(pp-1) = carry >> 16;
-		}
-	}
-for( i=M; i<NI; i++ )
-	c[i] = p[i];
-}
-
-
-/* Divide significands. Neither the numerator nor the denominator
-is permitted to have its high guard word nonzero.  */
-
-
-int edivm( den, num )
-unsigned short den[], num[];
-{
-int i;
-register unsigned short *p;
-unsigned long tnum;
-unsigned short j, tdenm, tquot;
-unsigned short tprod[NI+1];
-
-p = &equot[0];
-*p++ = num[0];
-*p++ = num[1];
-
-for( i=M; i<NI; i++ )
-	{
-	*p++ = 0;
-	}
-eshdn1( num );
-tdenm = den[M+1];
-for( i=M; i<NI; i++ )
-	{
-	/* Find trial quotient digit (the radix is 65536). */
-	tnum = (((unsigned long) num[M]) << 16) + num[M+1];
-
-	/* Do not execute the divide instruction if it will overflow. */
-        if( (tdenm * 0xffffL) < tnum )
-		tquot = 0xffff;
-	else
-		tquot = tnum / tdenm;
-
-		/* Prove that the divide worked. */
-/*
-	tcheck = (unsigned long )tquot * tdenm;
-	if( tnum - tcheck > tdenm )
-		tquot = 0xffff;
-*/
-	/* Multiply denominator by trial quotient digit. */
-	m16m( tquot, den, tprod );
-	/* The quotient digit may have been overestimated. */
-	if( ecmpm( tprod, num ) > 0 )
-		{
-		tquot -= 1;
-		esubm( den, tprod );
-		if( ecmpm( tprod, num ) > 0 )
-			{
-			tquot -= 1;
-			esubm( den, tprod );
-			}
-		}
-/*
-	if( ecmpm( tprod, num ) > 0 )
-		{
-		eshow( "tprod", tprod );
-		eshow( "num  ", num );
-		printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
-			 tnum, den[M+1], tquot );
-		}
-*/
-	esubm( tprod, num );
-/*
-	if( ecmpm( num, den ) >= 0 )
-		{
-		eshow( "num  ", num );
-		eshow( "den  ", den );
-		printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
-			 tnum, den[M+1], tquot );
-		}
-*/
-	equot[i] = tquot;
-	eshup6(num);
-	}
-/* test for nonzero remainder after roundoff bit */
-p = &num[M];
-j = 0;
-for( i=M; i<NI; i++ )
-	{
-	j |= *p++;
-	}
-if( j )
-	j = 1;
-
-for( i=0; i<NI; i++ )
-	num[i] = equot[i];
-
-return( (int )j );
-}
-
-
-
-/* Multiply significands */
-int emulm( a, b )
-unsigned short a[], b[];
-{
-unsigned short *p, *q;
-unsigned short pprod[NI];
-unsigned short j;
-int i;
-
-equot[0] = b[0];
-equot[1] = b[1];
-for( i=M; i<NI; i++ )
-	equot[i] = 0;
-
-j = 0;
-p = &a[NI-1];
-q = &equot[NI-1];
-for( i=M+1; i<NI; i++ )
-	{
-	if( *p == 0 )
-		{
-		--p;
-		}
-	else
-		{
-		m16m( *p--, b, pprod );
-		eaddm(pprod, equot);
-		}
-	j |= *q;
-	eshdn6(equot);
-	}
-
-for( i=0; i<NI; i++ )
-	b[i] = equot[i];
-
-/* return flag for lost nonzero bits */
-return( (int)j );
-}
-
-
-/*
-eshow(str, x)
-char *str;
-unsigned short *x;
-{
-int i;
-
-printf( "%s ", str );
-for( i=0; i<NI; i++ )
-	printf( "%04x ", *x++ );
-printf( "\n" );
-}
-*/
-#endif
-
-
-
-/*
- * Normalize and round off.
- *
- * The internal format number to be rounded is "s".
- * Input "lost" indicates whether the number is exact.
- * This is the so-called sticky bit.
- *
- * Input "subflg" indicates whether the number was obtained
- * by a subtraction operation.  In that case if lost is nonzero
- * then the number is slightly smaller than indicated.
- *
- * Input "exp" is the biased exponent, which may be negative.
- * the exponent field of "s" is ignored but is replaced by
- * "exp" as adjusted by normalization and rounding.
- *
- * Input "rcntrl" is the rounding control.
- */
-
-static int rlast = -1;
-static int rw = 0;
-static unsigned short rmsk = 0;
-static unsigned short rmbit = 0;
-static unsigned short rebit = 0;
-static int re = 0;
-static unsigned short rbit[NI] = {0,0,0,0,0,0,0,0};
-
-void emdnorm( s, lost, subflg, exp, rcntrl )
-unsigned short s[];
-int lost;
-int subflg;
-long exp;
-int rcntrl;
-{
-int i, j;
-unsigned short r;
-
-/* Normalize */
-j = enormlz( s );
-
-/* a blank significand could mean either zero or infinity. */
-#ifndef INFINITY
-if( j > NBITS )
-	{
-	ecleazs( s );
-	return;
-	}
-#endif
-exp -= j;
-#ifndef INFINITY
-if( exp >= 32767L )
-	goto overf;
-#else
-if( (j > NBITS) && (exp < 32767L) )
-	{
-	ecleazs( s );
-	return;
-	}
-#endif
-if( exp < 0L )
-	{
-	if( exp > (long )(-NBITS-1) )
-		{
-		j = (int )exp;
-		i = eshift( s, j );
-		if( i )
-			lost = 1;
-		}
-	else
-		{
-		ecleazs( s );
-		return;
-		}
-	}
-/* Round off, unless told not to by rcntrl. */
-if( rcntrl == 0 )
-	goto mdfin;
-/* Set up rounding parameters if the control register changed. */
-if( rndprc != rlast )
-	{
-	ecleaz( rbit );
-	switch( rndprc )
-		{
-		default:
-		case NBITS:
-			rw = NI-1; /* low guard word */
-			rmsk = 0xffff;
-			rmbit = 0x8000;
-			rebit = 1;
-			re = rw - 1;
-			break;
-		case 113:
-			rw = 10;
-			rmsk = 0x7fff;
-			rmbit = 0x4000;
-			rebit = 0x8000;
-			re = rw;
-			break;
-		case 64:
-			rw = 7;
-			rmsk = 0xffff;
-			rmbit = 0x8000;
-			rebit = 1;
-			re = rw-1;
-			break;
-/* For DEC arithmetic */
-		case 56:
-			rw = 6;
-			rmsk = 0xff;
-			rmbit = 0x80;
-			rebit = 0x100;
-			re = rw;
-			break;
-		case 53:
-			rw = 6;
-			rmsk = 0x7ff;
-			rmbit = 0x0400;
-			rebit = 0x800;
-			re = rw;
-			break;
-		case 24:
-			rw = 4;
-			rmsk = 0xff;
-			rmbit = 0x80;
-			rebit = 0x100;
-			re = rw;
-			break;
-		}
-	rbit[re] = rebit;
-	rlast = rndprc;
-	}
-
-/* Shift down 1 temporarily if the data structure has an implied
- * most significant bit and the number is denormal.
- * For rndprc = 64 or NBITS, there is no implied bit.
- * But Intel long double denormals lose one bit of significance even so.
- */
-#if IBMPC
-if( (exp <= 0) && (rndprc != NBITS) )
-#else
-if( (exp <= 0) && (rndprc != 64) && (rndprc != NBITS) )
-#endif
-	{
-	lost |= s[NI-1] & 1;
-	eshdn1(s);
-	}
-/* Clear out all bits below the rounding bit,
- * remembering in r if any were nonzero.
- */
-r = s[rw] & rmsk;
-if( rndprc < NBITS )
-	{
-	i = rw + 1;
-	while( i < NI )
-		{
-		if( s[i] )
-			r |= 1;
-		s[i] = 0;
-		++i;
-		}
-	}
-s[rw] &= ~rmsk;
-if( (r & rmbit) != 0 )
-	{
-	if( r == rmbit )
-		{
-		if( lost == 0 )
-			{ /* round to even */
-			if( (s[re] & rebit) == 0 )
-				goto mddone;
-			}
-		else
-			{
-			if( subflg != 0 )
-				goto mddone;
-			}
-		}
-	eaddm( rbit, s );
-	}
-mddone:
-#if IBMPC
-if( (exp <= 0) && (rndprc != NBITS) )
-#else
-if( (exp <= 0) && (rndprc != 64) && (rndprc != NBITS) )
-#endif
-	{
-	eshup1(s);
-	}
-if( s[2] != 0 )
-	{ /* overflow on roundoff */
-	eshdn1(s);
-	exp += 1;
-	}
-mdfin:
-s[NI-1] = 0;
-if( exp >= 32767L )
-	{
-#ifndef INFINITY
-overf:
-#endif
-#ifdef INFINITY
-	s[1] = 32767;
-	for( i=2; i<NI-1; i++ )
-		s[i] = 0;
-#else
-	s[1] = 32766;
-	s[2] = 0;
-	for( i=M+1; i<NI-1; i++ )
-		s[i] = 0xffff;
-	s[NI-1] = 0;
-	if( (rndprc < 64) || (rndprc == 113) )
-		{
-		s[rw] &= ~rmsk;
-		if( rndprc == 24 )
-			{
-			s[5] = 0;
-			s[6] = 0;
-			}
-		}
-#endif
-	return;
-	}
-if( exp < 0 )
-	s[1] = 0;
-else
-	s[1] = (unsigned short )exp;
-}
-
-
-
-/*
-;	Subtract external format numbers.
-;
-;	unsigned short a[NE], b[NE], c[NE];
-;	esub( a, b, c );	 c = b - a
-*/
-
-static int subflg = 0;
-
-void esub( a, b, c )
-unsigned short *a, *b, *c;
-{
-
-#ifdef NANS
-if( eisnan(a) )
-	{
-	emov (a, c);
-	return;
-	}
-if( eisnan(b) )
-	{
-	emov(b,c);
-	return;
-	}
-/* Infinity minus infinity is a NaN.
- * Test for subtracting infinities of the same sign.
- */
-if( eisinf(a) && eisinf(b) && ((eisneg (a) ^ eisneg (b)) == 0))
-	{
-	mtherr( "esub", DOMAIN );
-	enan( c, NBITS );
-	return;
-	}
-#endif
-subflg = 1;
-eadd1( a, b, c );
-}
-
-
-/*
-;	Add.
-;
-;	unsigned short a[NE], b[NE], c[NE];
-;	eadd( a, b, c );	 c = b + a
-*/
-void eadd( a, b, c )
-unsigned short *a, *b, *c;
-{
-
-#ifdef NANS
-/* NaN plus anything is a NaN. */
-if( eisnan(a) )
-	{
-	emov(a,c);
-	return;
-	}
-if( eisnan(b) )
-	{
-	emov(b,c);
-	return;
-	}
-/* Infinity minus infinity is a NaN.
- * Test for adding infinities of opposite signs.
- */
-if( eisinf(a) && eisinf(b)
-	&& ((eisneg(a) ^ eisneg(b)) != 0) )
-	{
-	mtherr( "eadd", DOMAIN );
-	enan( c, NBITS );
-	return;
-	}
-#endif
-subflg = 0;
-eadd1( a, b, c );
-}
-
-void eadd1( a, b, c )
-unsigned short *a, *b, *c;
-{
-unsigned short ai[NI], bi[NI], ci[NI];
-int i, lost, j, k;
-long lt, lta, ltb;
-
-#ifdef INFINITY
-if( eisinf(a) )
-	{
-	emov(a,c);
-	if( subflg )
-		eneg(c);
-	return;
-	}
-if( eisinf(b) )
-	{
-	emov(b,c);
-	return;
-	}
-#endif
-emovi( a, ai );
-emovi( b, bi );
-if( subflg )
-	ai[0] = ~ai[0];
-
-/* compare exponents */
-lta = ai[E];
-ltb = bi[E];
-lt = lta - ltb;
-if( lt > 0L )
-	{	/* put the larger number in bi */
-	emovz( bi, ci );
-	emovz( ai, bi );
-	emovz( ci, ai );
-	ltb = bi[E];
-	lt = -lt;
-	}
-lost = 0;
-if( lt != 0L )
-	{
-	if( lt < (long )(-NBITS-1) )
-		goto done;	/* answer same as larger addend */
-	k = (int )lt;
-	lost = eshift( ai, k ); /* shift the smaller number down */
-	}
-else
-	{
-/* exponents were the same, so must compare significands */
-	i = ecmpm( ai, bi );
-	if( i == 0 )
-		{ /* the numbers are identical in magnitude */
-		/* if different signs, result is zero */
-		if( ai[0] != bi[0] )
-			{
-			eclear(c);
-			return;
-			}
-		/* if same sign, result is double */
-		/* double denomalized tiny number */
-		if( (bi[E] == 0) && ((bi[3] & 0x8000) == 0) )
-			{
-			eshup1( bi );
-			goto done;
-			}
-		/* add 1 to exponent unless both are zero! */
-		for( j=1; j<NI-1; j++ )
-			{
-			if( bi[j] != 0 )
-				{
-/* This could overflow, but let emovo take care of that. */
-				ltb += 1;
-				break;
-				}
-			}
-		bi[E] = (unsigned short )ltb;
-		goto done;
-		}
-	if( i > 0 )
-		{	/* put the larger number in bi */
-		emovz( bi, ci );
-		emovz( ai, bi );
-		emovz( ci, ai );
-		}
-	}
-if( ai[0] == bi[0] )
-	{
-	eaddm( ai, bi );
-	subflg = 0;
-	}
-else
-	{
-	esubm( ai, bi );
-	subflg = 1;
-	}
-emdnorm( bi, lost, subflg, ltb, 64 );
-
-done:
-emovo( bi, c );
-}
-
-
-
-/*
-;	Divide.
-;
-;	unsigned short a[NE], b[NE], c[NE];
-;	ediv( a, b, c );	c = b / a
-*/
-void ediv( a, b, c )
-unsigned short *a, *b, *c;
-{
-unsigned short ai[NI], bi[NI];
-int i;
-long lt, lta, ltb;
-
-#ifdef NANS
-/* Return any NaN input. */
-if( eisnan(a) )
-	{
-	emov(a,c);
-	return;
-	}
-if( eisnan(b) )
-	{
-	emov(b,c);
-	return;
-	}
-/* Zero over zero, or infinity over infinity, is a NaN. */
-if( ((ecmp(a,ezero) == 0) && (ecmp(b,ezero) == 0))
-	|| (eisinf (a) && eisinf (b)) )
-	{
-	mtherr( "ediv", DOMAIN );
-	enan( c, NBITS );
-	return;
-	}
-#endif
-/* Infinity over anything else is infinity. */
-#ifdef INFINITY
-if( eisinf(b) )
-	{
-	if( eisneg(a) ^ eisneg(b) )
-		*(c+(NE-1)) = 0x8000;
-	else
-		*(c+(NE-1)) = 0;
-	einfin(c);
-	return;
-	}
-if( eisinf(a) )
-	{
-	eclear(c);
-	return;
-	}
-#endif
-emovi( a, ai );
-emovi( b, bi );
-lta = ai[E];
-ltb = bi[E];
-if( bi[E] == 0 )
-	{ /* See if numerator is zero. */
-	for( i=1; i<NI-1; i++ )
-		{
-		if( bi[i] != 0 )
-			{
-			ltb -= enormlz( bi );
-			goto dnzro1;
-			}
-		}
-	eclear(c);
-	return;
-	}
-dnzro1:
-
-if( ai[E] == 0 )
-	{	/* possible divide by zero */
-	for( i=1; i<NI-1; i++ )
-		{
-		if( ai[i] != 0 )
-			{
-			lta -= enormlz( ai );
-			goto dnzro2;
-			}
-		}
-	if( ai[0] == bi[0] )
-		*(c+(NE-1)) = 0;
-	else
-		*(c+(NE-1)) = 0x8000;
-	einfin(c);
-	mtherr( "ediv", SING );
-	return;
-	}
-dnzro2:
-
-i = edivm( ai, bi );
-/* calculate exponent */
-lt = ltb - lta + EXONE;
-emdnorm( bi, i, 0, lt, 64 );
-/* set the sign */
-if( ai[0] == bi[0] )
-	bi[0] = 0;
-else
-	bi[0] = 0Xffff;
-emovo( bi, c );
-}
-
-
-
-/*
-;	Multiply.
-;
-;	unsigned short a[NE], b[NE], c[NE];
-;	emul( a, b, c );	c = b * a
-*/
-void emul( a, b, c )
-unsigned short *a, *b, *c;
-{
-unsigned short ai[NI], bi[NI];
-int i, j;
-long lt, lta, ltb;
-
-#ifdef NANS
-/* NaN times anything is the same NaN. */
-if( eisnan(a) )
-	{
-	emov(a,c);
-	return;
-	}
-if( eisnan(b) )
-	{
-	emov(b,c);
-	return;
-	}
-/* Zero times infinity is a NaN. */
-if( (eisinf(a) && (ecmp(b,ezero) == 0))
-	|| (eisinf(b) && (ecmp(a,ezero) == 0)) )
-	{
-	mtherr( "emul", DOMAIN );
-	enan( c, NBITS );
-	return;
-	}
-#endif
-/* Infinity times anything else is infinity. */
-#ifdef INFINITY
-if( eisinf(a) || eisinf(b) )
-	{
-	if( eisneg(a) ^ eisneg(b) )
-		*(c+(NE-1)) = 0x8000;
-	else
-		*(c+(NE-1)) = 0;
-	einfin(c);
-	return;
-	}
-#endif
-emovi( a, ai );
-emovi( b, bi );
-lta = ai[E];
-ltb = bi[E];
-if( ai[E] == 0 )
-	{
-	for( i=1; i<NI-1; i++ )
-		{
-		if( ai[i] != 0 )
-			{
-			lta -= enormlz( ai );
-			goto mnzer1;
-			}
-		}
-	eclear(c);
-	return;
-	}
-mnzer1:
-
-if( bi[E] == 0 )
-	{
-	for( i=1; i<NI-1; i++ )
-		{
-		if( bi[i] != 0 )
-			{
-			ltb -= enormlz( bi );
-			goto mnzer2;
-			}
-		}
-	eclear(c);
-	return;
-	}
-mnzer2:
-
-/* Multiply significands */
-j = emulm( ai, bi );
-/* calculate exponent */
-lt = lta + ltb - (EXONE - 1);
-emdnorm( bi, j, 0, lt, 64 );
-/* calculate sign of product */
-if( ai[0] == bi[0] )
-	bi[0] = 0;
-else
-	bi[0] = 0xffff;
-emovo( bi, c );
-}
-
-
-
-
-/*
-; Convert IEEE double precision to e type
-;	double d;
-;	unsigned short x[N+2];
-;	e53toe( &d, x );
-*/
-void e53toe( pe, y )
-unsigned short *pe, *y;
-{
-#ifdef DEC
-
-dectoe( pe, y ); /* see etodec.c */
-
-#else
-
-register unsigned short r;
-register unsigned short *p, *e;
-unsigned short yy[NI];
-int denorm, k;
-
-e = pe;
-denorm = 0;	/* flag if denormalized number */
-ecleaz(yy);
-#ifdef IBMPC
-e += 3;
-#endif
-r = *e;
-yy[0] = 0;
-if( r & 0x8000 )
-	yy[0] = 0xffff;
-yy[M] = (r & 0x0f) | 0x10;
-r &= ~0x800f;	/* strip sign and 4 significand bits */
-#ifdef INFINITY
-if( r == 0x7ff0 )
-	{
-#ifdef NANS
-#ifdef IBMPC
-	if( ((pe[3] & 0xf) != 0) || (pe[2] != 0)
-		|| (pe[1] != 0) || (pe[0] != 0) )
-		{
-		enan( y, NBITS );
-		return;
-		}
-#else
-	if( ((pe[0] & 0xf) != 0) || (pe[1] != 0)
-		 || (pe[2] != 0) || (pe[3] != 0) )
-		{
-		enan( y, NBITS );
-		return;
-		}
-#endif
-#endif  /* NANS */
-	eclear( y );
-	einfin( y );
-	if( yy[0] )
-		eneg(y);
-	return;
-	}
-#endif
-r >>= 4;
-/* If zero exponent, then the significand is denormalized.
- * So, take back the understood high significand bit. */ 
-if( r == 0 )
-	{
-	denorm = 1;
-	yy[M] &= ~0x10;
-	}
-r += EXONE - 01777;
-yy[E] = r;
-p = &yy[M+1];
-#ifdef IBMPC
-*p++ = *(--e);
-*p++ = *(--e);
-*p++ = *(--e);
-#endif
-#ifdef MIEEE
-++e;
-*p++ = *e++;
-*p++ = *e++;
-*p++ = *e++;
-#endif
-(void )eshift( yy, -5 );
-if( denorm )
-	{ /* if zero exponent, then normalize the significand */
-	if( (k = enormlz(yy)) > NBITS )
-		ecleazs(yy);
-	else
-		yy[E] -= (unsigned short )(k-1);
-	}
-emovo( yy, y );
-#endif /* not DEC */
-}
-
-void e64toe( pe, y )
-unsigned short *pe, *y;
-{
-unsigned short yy[NI];
-unsigned short *p, *q, *e;
-int i;
-
-e = pe;
-p = yy;
-for( i=0; i<NE-5; i++ )
-	*p++ = 0;
-#ifdef IBMPC
-for( i=0; i<5; i++ )
-	*p++ = *e++;
-#endif
-#ifdef DEC
-for( i=0; i<5; i++ )
-	*p++ = *e++;
-#endif
-#ifdef MIEEE
-p = &yy[0] + (NE-1);
-*p-- = *e++;
-++e;
-for( i=0; i<4; i++ )
-	*p-- = *e++;
-#endif
-
-#ifdef IBMPC
-/* For Intel long double, shift denormal significand up 1
-   -- but only if the top significand bit is zero.  */
-if((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
-  {
-    unsigned short temp[NI+1];
-    emovi(yy, temp);
-    eshup1(temp);
-    emovo(temp,y);
-    return;
-  }
-#endif
-#ifdef INFINITY
-/* Point to the exponent field.  */
-p = &yy[NE-1];
-if( *p == 0x7fff )
-	{
-#ifdef NANS
-#ifdef IBMPC
-	for( i=0; i<4; i++ )
-		{
-		if((i != 3 && pe[i] != 0)
-		   /* Check for Intel long double infinity pattern.  */
-		   || (i == 3 && pe[i] != 0x8000))
-			{
-			enan( y, NBITS );
-			return;
-			}
-		}
-#else
-	for( i=1; i<=4; i++ )
-		{
-		if( pe[i] != 0 )
-			{
-			enan( y, NBITS );
-			return;
-			}
-		}
-#endif
-#endif /* NANS */
-	eclear( y );
-	einfin( y );
-	if( *p & 0x8000 )
-		eneg(y);
-	return;
-	}
-#endif
-p = yy;
-q = y;
-for( i=0; i<NE; i++ )
-	*q++ = *p++;
-}
-
-void e113toe(pe,y)
-unsigned short *pe, *y;
-{
-register unsigned short r;
-unsigned short *e, *p;
-unsigned short yy[NI];
-int denorm, i;
-
-e = pe;
-denorm = 0;
-ecleaz(yy);
-#ifdef IBMPC
-e += 7;
-#endif
-r = *e;
-yy[0] = 0;
-if( r & 0x8000 )
-	yy[0] = 0xffff;
-r &= 0x7fff;
-#ifdef INFINITY
-if( r == 0x7fff )
-	{
-#ifdef NANS
-#ifdef IBMPC
-	for( i=0; i<7; i++ )
-		{
-		if( pe[i] != 0 )
-			{
-			enan( y, NBITS );
-			return;
-			}
-		}
-#else
-	for( i=1; i<8; i++ )
-		{
-		if( pe[i] != 0 )
-			{
-			enan( y, NBITS );
-			return;
-			}
-		}
-#endif
-#endif /* NANS */
-	eclear( y );
-	einfin( y );
-	if( *e & 0x8000 )
-		eneg(y);
-	return;
-	}
-#endif  /* INFINITY */
-yy[E] = r;
-p = &yy[M + 1];
-#ifdef IBMPC
-for( i=0; i<7; i++ )
-	*p++ = *(--e);
-#endif
-#ifdef MIEEE
-++e;
-for( i=0; i<7; i++ )
-	*p++ = *e++;
-#endif
-/* If denormal, remove the implied bit; else shift down 1. */
-if( r == 0 )
-	{
-	yy[M] = 0;
-	}
-else
-	{
-	yy[M] = 1;
-	eshift( yy, -1 );
-	}
-emovo(yy,y);
-}
-
-
-/*
-; Convert IEEE single precision to e type
-;	float d;
-;	unsigned short x[N+2];
-;	dtox( &d, x );
-*/
-void e24toe( pe, y )
-unsigned short *pe, *y;
-{
-register unsigned short r;
-register unsigned short *p, *e;
-unsigned short yy[NI];
-int denorm, k;
-
-e = pe;
-denorm = 0;	/* flag if denormalized number */
-ecleaz(yy);
-#ifdef IBMPC
-e += 1;
-#endif
-#ifdef DEC
-e += 1;
-#endif
-r = *e;
-yy[0] = 0;
-if( r & 0x8000 )
-	yy[0] = 0xffff;
-yy[M] = (r & 0x7f) | 0200;
-r &= ~0x807f;	/* strip sign and 7 significand bits */
-#ifdef INFINITY
-if( r == 0x7f80 )
-	{
-#ifdef NANS
-#ifdef MIEEE
-	if( ((pe[0] & 0x7f) != 0) || (pe[1] != 0) )
-		{
-		enan( y, NBITS );
-		return;
-		}
-#else
-	if( ((pe[1] & 0x7f) != 0) || (pe[0] != 0) )
-		{
-		enan( y, NBITS );
-		return;
-		}
-#endif
-#endif  /* NANS */
-	eclear( y );
-	einfin( y );
-	if( yy[0] )
-		eneg(y);
-	return;
-	}
-#endif
-r >>= 7;
-/* If zero exponent, then the significand is denormalized.
- * So, take back the understood high significand bit. */ 
-if( r == 0 )
-	{
-	denorm = 1;
-	yy[M] &= ~0200;
-	}
-r += EXONE - 0177;
-yy[E] = r;
-p = &yy[M+1];
-#ifdef IBMPC
-*p++ = *(--e);
-#endif
-#ifdef DEC
-*p++ = *(--e);
-#endif
-#ifdef MIEEE
-++e;
-*p++ = *e++;
-#endif
-(void )eshift( yy, -8 );
-if( denorm )
-	{ /* if zero exponent, then normalize the significand */
-	if( (k = enormlz(yy)) > NBITS )
-		ecleazs(yy);
-	else
-		yy[E] -= (unsigned short )(k-1);
-	}
-emovo( yy, y );
-}
-
-void etoe113(x,e)
-unsigned short *x, *e;
-{
-unsigned short xi[NI];
-long exp;
-int rndsav;
-
-#ifdef NANS
-if( eisnan(x) )
-	{
-	enan( e, 113 );
-	return;
-	}
-#endif
-emovi( x, xi );
-exp = (long )xi[E];
-#ifdef INFINITY
-if( eisinf(x) )
-	goto nonorm;
-#endif
-/* round off to nearest or even */
-rndsav = rndprc;
-rndprc = 113;
-emdnorm( xi, 0, 0, exp, 64 );
-rndprc = rndsav;
-nonorm:
-toe113 (xi, e);
-}
-
-/* move out internal format to ieee long double */
-static void toe113(a,b)
-unsigned short *a, *b;
-{
-register unsigned short *p, *q;
-unsigned short i;
-
-#ifdef NANS
-if( eiisnan(a) )
-	{
-	enan( b, 113 );
-	return;
-	}
-#endif
-p = a;
-#ifdef MIEEE
-q = b;
-#else
-q = b + 7;			/* point to output exponent */
-#endif
-
-/* If not denormal, delete the implied bit. */
-if( a[E] != 0 )
-	{
-	eshup1 (a);
-	}
-/* combine sign and exponent */
-i = *p++;
-#ifdef MIEEE
-if( i )
-	*q++ = *p++ | 0x8000;
-else
-	*q++ = *p++;
-#else
-if( i )
-	*q-- = *p++ | 0x8000;
-else
-	*q-- = *p++;
-#endif
-/* skip over guard word */
-++p;
-/* move the significand */
-#ifdef MIEEE
-for (i = 0; i < 7; i++)
-	*q++ = *p++;
-#else
-for (i = 0; i < 7; i++)
-	*q-- = *p++;
-#endif
-}
-
-
-void etoe64( x, e )
-unsigned short *x, *e;
-{
-unsigned short xi[NI];
-long exp;
-int rndsav;
-
-#ifdef NANS
-if( eisnan(x) )
-	{
-	enan( e, 64 );
-	return;
-	}
-#endif
-emovi( x, xi );
-exp = (long )xi[E]; /* adjust exponent for offset */
-#ifdef INFINITY
-if( eisinf(x) )
-	goto nonorm;
-#endif
-/* round off to nearest or even */
-rndsav = rndprc;
-rndprc = 64;
-emdnorm( xi, 0, 0, exp, 64 );
-rndprc = rndsav;
-nonorm:
-toe64( xi, e );
-}
-
-/* move out internal format to ieee long double */
-static void toe64( a, b )
-unsigned short *a, *b;
-{
-register unsigned short *p, *q;
-unsigned short i;
-
-#ifdef NANS
-if( eiisnan(a) )
-	{
-	enan( b, 64 );
-	return;
-	}
-#endif
-#ifdef IBMPC
-/* Shift Intel denormal significand down 1.  */
-if( a[E] == 0 )
-  eshdn1(a);
-#endif
-p = a;
-#ifdef MIEEE
-q = b;
-#else
-q = b + 4; /* point to output exponent */
-#if 1
-/* NOTE: if data type is 96 bits wide, clear the last word here. */
-*(q+1)= 0;
-#endif
-#endif
-
-/* combine sign and exponent */
-i = *p++;
-#ifdef MIEEE
-if( i )
-	*q++ = *p++ | 0x8000;
-else
-	*q++ = *p++;
-*q++ = 0;
-#else
-if( i )
-	*q-- = *p++ | 0x8000;
-else
-	*q-- = *p++;
-#endif
-/* skip over guard word */
-++p;
-/* move the significand */
-#ifdef MIEEE
-for( i=0; i<4; i++ )
-	*q++ = *p++;
-#else
-#ifdef INFINITY
-if (eiisinf (a))
-        {
-	/* Intel long double infinity.  */
-	*q-- = 0x8000;
-	*q-- = 0;
-	*q-- = 0;
-	*q = 0;
-	return;
-	}
-#endif
-for( i=0; i<4; i++ )
-	*q-- = *p++;
-#endif
-}
-
-
-/*
-; e type to IEEE double precision
-;	double d;
-;	unsigned short x[NE];
-;	etoe53( x, &d );
-*/
-
-#ifdef DEC
-
-void etoe53( x, e )
-unsigned short *x, *e;
-{
-etodec( x, e ); /* see etodec.c */
-}
-
-static void toe53( x, y )
-unsigned short *x, *y;
-{
-todec( x, y );
-}
-
-#else
-
-void etoe53( x, e )
-unsigned short *x, *e;
-{
-unsigned short xi[NI];
-long exp;
-int rndsav;
-
-#ifdef NANS
-if( eisnan(x) )
-	{
-	enan( e, 53 );
-	return;
-	}
-#endif
-emovi( x, xi );
-exp = (long )xi[E] - (EXONE - 0x3ff); /* adjust exponent for offsets */
-#ifdef INFINITY
-if( eisinf(x) )
-	goto nonorm;
-#endif
-/* round off to nearest or even */
-rndsav = rndprc;
-rndprc = 53;
-emdnorm( xi, 0, 0, exp, 64 );
-rndprc = rndsav;
-nonorm:
-toe53( xi, e );
-}
-
-
-static void toe53( x, y )
-unsigned short *x, *y;
-{
-unsigned short i;
-unsigned short *p;
-
-
-#ifdef NANS
-if( eiisnan(x) )
-	{
-	enan( y, 53 );
-	return;
-	}
-#endif
-p = &x[0];
-#ifdef IBMPC
-y += 3;
-#endif
-*y = 0;	/* output high order */
-if( *p++ )
-	*y = 0x8000;	/* output sign bit */
-
-i = *p++;
-if( i >= (unsigned int )2047 )
-	{	/* Saturate at largest number less than infinity. */
-#ifdef INFINITY
-	*y |= 0x7ff0;
-#ifdef IBMPC
-	*(--y) = 0;
-	*(--y) = 0;
-	*(--y) = 0;
-#endif
-#ifdef MIEEE
-	++y;
-	*y++ = 0;
-	*y++ = 0;
-	*y++ = 0;
-#endif
-#else
-	*y |= (unsigned short )0x7fef;
-#ifdef IBMPC
-	*(--y) = 0xffff;
-	*(--y) = 0xffff;
-	*(--y) = 0xffff;
-#endif
-#ifdef MIEEE
-	++y;
-	*y++ = 0xffff;
-	*y++ = 0xffff;
-	*y++ = 0xffff;
-#endif
-#endif
-	return;
-	}
-if( i == 0 )
-	{
-	(void )eshift( x, 4 );
-	}
-else
-	{
-	i <<= 4;
-	(void )eshift( x, 5 );
-	}
-i |= *p++ & (unsigned short )0x0f;	/* *p = xi[M] */
-*y |= (unsigned short )i; /* high order output already has sign bit set */
-#ifdef IBMPC
-*(--y) = *p++;
-*(--y) = *p++;
-*(--y) = *p;
-#endif
-#ifdef MIEEE
-++y;
-*y++ = *p++;
-*y++ = *p++;
-*y++ = *p++;
-#endif
-}
-
-#endif /* not DEC */
-
-
-
-/*
-; e type to IEEE single precision
-;	float d;
-;	unsigned short x[N+2];
-;	xtod( x, &d );
-*/
-void etoe24( x, e )
-unsigned short *x, *e;
-{
-long exp;
-unsigned short xi[NI];
-int rndsav;
-
-#ifdef NANS
-if( eisnan(x) )
-	{
-	enan( e, 24 );
-	return;
-	}
-#endif
-emovi( x, xi );
-exp = (long )xi[E] - (EXONE - 0177); /* adjust exponent for offsets */
-#ifdef INFINITY
-if( eisinf(x) )
-	goto nonorm;
-#endif
-/* round off to nearest or even */
-rndsav = rndprc;
-rndprc = 24;
-emdnorm( xi, 0, 0, exp, 64 );
-rndprc = rndsav;
-nonorm:
-toe24( xi, e );
-}
-
-static void toe24( x, y )
-unsigned short *x, *y;
-{
-unsigned short i;
-unsigned short *p;
-
-#ifdef NANS
-if( eiisnan(x) )
-	{
-	enan( y, 24 );
-	return;
-	}
-#endif
-p = &x[0];
-#ifdef IBMPC
-y += 1;
-#endif
-#ifdef DEC
-y += 1;
-#endif
-*y = 0;	/* output high order */
-if( *p++ )
-	*y = 0x8000;	/* output sign bit */
-
-i = *p++;
-if( i >= 255 )
-	{	/* Saturate at largest number less than infinity. */
-#ifdef INFINITY
-	*y |= (unsigned short )0x7f80;
-#ifdef IBMPC
-	*(--y) = 0;
-#endif
-#ifdef DEC
-	*(--y) = 0;
-#endif
-#ifdef MIEEE
-	++y;
-	*y = 0;
-#endif
-#else
-	*y |= (unsigned short )0x7f7f;
-#ifdef IBMPC
-	*(--y) = 0xffff;
-#endif
-#ifdef DEC
-	*(--y) = 0xffff;
-#endif
-#ifdef MIEEE
-	++y;
-	*y = 0xffff;
-#endif
-#endif
-	return;
-	}
-if( i == 0 )
-	{
-	(void )eshift( x, 7 );
-	}
-else
-	{
-	i <<= 7;
-	(void )eshift( x, 8 );
-	}
-i |= *p++ & (unsigned short )0x7f;	/* *p = xi[M] */
-*y |= i;	/* high order output already has sign bit set */
-#ifdef IBMPC
-*(--y) = *p;
-#endif
-#ifdef DEC
-*(--y) = *p;
-#endif
-#ifdef MIEEE
-++y;
-*y = *p;
-#endif
-}
-
-
-/* Compare two e type numbers.
- *
- * unsigned short a[NE], b[NE];
- * ecmp( a, b );
- *
- *  returns +1 if a > b
- *           0 if a == b
- *          -1 if a < b
- *          -2 if either a or b is a NaN.
- */
-int ecmp( a, b )
-unsigned short *a, *b;
-{
-unsigned short ai[NI], bi[NI];
-register unsigned short *p, *q;
-register int i;
-int msign;
-
-#ifdef NANS
-if (eisnan (a)  || eisnan (b))
-	return( -2 );
-#endif
-emovi( a, ai );
-p = ai;
-emovi( b, bi );
-q = bi;
-
-if( *p != *q )
-	{ /* the signs are different */
-/* -0 equals + 0 */
-	for( i=1; i<NI-1; i++ )
-		{
-		if( ai[i] != 0 )
-			goto nzro;
-		if( bi[i] != 0 )
-			goto nzro;
-		}
-	return(0);
-nzro:
-	if( *p == 0 )
-		return( 1 );
-	else
-		return( -1 );
-	}
-/* both are the same sign */
-if( *p == 0 )
-	msign = 1;
-else
-	msign = -1;
-i = NI-1;
-do
-	{
-	if( *p++ != *q++ )
-		{
-		goto diff;
-		}
-	}
-while( --i > 0 );
-
-return(0);	/* equality */
-
-
-
-diff:
-
-if( *(--p) > *(--q) )
-	return( msign );		/* p is bigger */
-else
-	return( -msign );	/* p is littler */
-}
-
-
-
-
-/* Find nearest integer to x = floor( x + 0.5 )
- *
- * unsigned short x[NE], y[NE]
- * eround( x, y );
- */
-void eround( x, y )
-unsigned short *x, *y;
-{
-
-eadd( ehalf, x, y );
-efloor( y, y );
-}
-
-
-
-
-/*
-; convert long (32-bit) integer to e type
-;
-;	long l;
-;	unsigned short x[NE];
-;	ltoe( &l, x );
-; note &l is the memory address of l
-*/
-void ltoe( lp, y )
-long *lp;	/* lp is the memory address of a long integer */
-unsigned short *y;	/* y is the address of a short */
-{
-unsigned short yi[NI];
-unsigned long ll;
-int k;
-
-ecleaz( yi );
-if( *lp < 0 )
-	{
-	ll =  (unsigned long )( -(*lp) ); /* make it positive */
-	yi[0] = 0xffff; /* put correct sign in the e type number */
-	}
-else
-	{
-	ll = (unsigned long )( *lp );
-	}
-/* move the long integer to yi significand area */
-if( sizeof(long) == 8 )
-	{
-	yi[M] = (unsigned short) (ll >> (LONGBITS - 16));
-	yi[M + 1] = (unsigned short) (ll >> (LONGBITS - 32));
-	yi[M + 2] = (unsigned short) (ll >> 16);
-	yi[M + 3] = (unsigned short) ll;
-	yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
-	}
-else
-	{
-	yi[M] = (unsigned short )(ll >> 16); 
-	yi[M+1] = (unsigned short )ll;
-	yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
-	}
-if( (k = enormlz( yi )) > NBITS ) /* normalize the significand */
-	ecleaz( yi );	/* it was zero */
-else
-	yi[E] -= (unsigned short )k; /* subtract shift count from exponent */
-emovo( yi, y );	/* output the answer */
-}
-
-/*
-; convert unsigned long (32-bit) integer to e type
-;
-;	unsigned long l;
-;	unsigned short x[NE];
-;	ltox( &l, x );
-; note &l is the memory address of l
-*/
-void ultoe( lp, y )
-unsigned long *lp; /* lp is the memory address of a long integer */
-unsigned short *y;	/* y is the address of a short */
-{
-unsigned short yi[NI];
-unsigned long ll;
-int k;
-
-ecleaz( yi );
-ll = *lp;
-
-/* move the long integer to ayi significand area */
-if( sizeof(long) == 8 )
-	{
-	yi[M] = (unsigned short) (ll >> (LONGBITS - 16));
-	yi[M + 1] = (unsigned short) (ll >> (LONGBITS - 32));
-	yi[M + 2] = (unsigned short) (ll >> 16);
-	yi[M + 3] = (unsigned short) ll;
-	yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
-	}
-else
-	{
-	yi[M] = (unsigned short )(ll >> 16); 
-	yi[M+1] = (unsigned short )ll;
-	yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
-	}
-if( (k = enormlz( yi )) > NBITS ) /* normalize the significand */
-	ecleaz( yi );	/* it was zero */
-else
-	yi[E] -= (unsigned short )k; /* subtract shift count from exponent */
-emovo( yi, y );	/* output the answer */
-}
-
-
-/*
-;	Find long integer and fractional parts
-
-;	long i;
-;	unsigned short x[NE], frac[NE];
-;	xifrac( x, &i, frac );
- 
-  The integer output has the sign of the input.  The fraction is
-  the positive fractional part of abs(x).
-*/
-void eifrac( x, i, frac )
-unsigned short *x;
-long *i;
-unsigned short *frac;
-{
-unsigned short xi[NI];
-int j, k;
-unsigned long ll;
-
-emovi( x, xi );
-k = (int )xi[E] - (EXONE - 1);
-if( k <= 0 )
-	{
-/* if exponent <= 0, integer = 0 and real output is fraction */
-	*i = 0L;
-	emovo( xi, frac );
-	return;
-	}
-if( k > (8 * sizeof(long) - 1) )
-	{
-/*
-;	long integer overflow: output large integer
-;	and correct fraction
-*/
-	j = 8 * sizeof(long) - 1;
-	if( xi[0] )
-		*i = (long) ((unsigned long) 1) << j;
-	else
-		*i = (long) (((unsigned long) (~(0L))) >> 1);
-	(void )eshift( xi, k );
-	}
-if( k > 16 )
-	{
-/*
-  Shift more than 16 bits: shift up k-16 mod 16
-  then shift by 16's.
-*/
-	j = k - ((k >> 4) << 4);
-	eshift (xi, j);
-	ll = xi[M];
-	k -= j;
-	do
-		{
-		eshup6 (xi);
-		ll = (ll << 16) | xi[M];
-		}
-	while ((k -= 16) > 0);
-	*i = ll;
-	if (xi[0])
-		*i = -(*i);
-	}
-else
-	{
-/* shift not more than 16 bits */
-	eshift( xi, k );
-	*i = (long )xi[M] & 0xffff;
-	if( xi[0] )
-		*i = -(*i);
-	}
-xi[0] = 0;
-xi[E] = EXONE - 1;
-xi[M] = 0;
-if( (k = enormlz( xi )) > NBITS )
-	ecleaz( xi );
-else
-	xi[E] -= (unsigned short )k;
-
-emovo( xi, frac );
-}
-
-
-/*
-;	Find unsigned long integer and fractional parts
-
-;	unsigned long i;
-;	unsigned short x[NE], frac[NE];
-;	xifrac( x, &i, frac );
-
-  A negative e type input yields integer output = 0
-  but correct fraction.
-*/
-void euifrac( x, i, frac )
-unsigned short *x;
-unsigned long *i;
-unsigned short *frac;
-{
-unsigned short xi[NI];
-int j, k;
-unsigned long ll;
-
-emovi( x, xi );
-k = (int )xi[E] - (EXONE - 1);
-if( k <= 0 )
-	{
-/* if exponent <= 0, integer = 0 and argument is fraction */
-	*i = 0L;
-	emovo( xi, frac );
-	return;
-	}
-if( k > (8 * sizeof(long)) )
-	{
-/*
-;	long integer overflow: output large integer
-;	and correct fraction
-*/
-	*i = ~(0L);
-	(void )eshift( xi, k );
-	}
-else if( k > 16 )
-	{
-/*
-  Shift more than 16 bits: shift up k-16 mod 16
-  then shift up by 16's.
-*/
-	j = k - ((k >> 4) << 4);
-	eshift (xi, j);
-	ll = xi[M];
-	k -= j;
-	do
-		{
-		eshup6 (xi);
-		ll = (ll << 16) | xi[M];
-		}
-	while ((k -= 16) > 0);
-	*i = ll;
-	}
-else
-	{
-/* shift not more than 16 bits */
-	eshift( xi, k );
-	*i = (long )xi[M] & 0xffff;
-	}
-
-if( xi[0] )  /* A negative value yields unsigned integer 0. */
-	*i = 0L;
-
-xi[0] = 0;
-xi[E] = EXONE - 1;
-xi[M] = 0;
-if( (k = enormlz( xi )) > NBITS )
-	ecleaz( xi );
-else
-	xi[E] -= (unsigned short )k;
-
-emovo( xi, frac );
-}
-
-
-
-/*
-;	Shift significand
-;
-;	Shifts significand area up or down by the number of bits
-;	given by the variable sc.
-*/
-int eshift( x, sc )
-unsigned short *x;
-int sc;
-{
-unsigned short lost;
-unsigned short *p;
-
-if( sc == 0 )
-	return( 0 );
-
-lost = 0;
-p = x + NI-1;
-
-if( sc < 0 )
-	{
-	sc = -sc;
-	while( sc >= 16 )
-		{
-		lost |= *p;	/* remember lost bits */
-		eshdn6(x);
-		sc -= 16;
-		}
-
-	while( sc >= 8 )
-		{
-		lost |= *p & 0xff;
-		eshdn8(x);
-		sc -= 8;
-		}
-
-	while( sc > 0 )
-		{
-		lost |= *p & 1;
-		eshdn1(x);
-		sc -= 1;
-		}
-	}
-else
-	{
-	while( sc >= 16 )
-		{
-		eshup6(x);
-		sc -= 16;
-		}
-
-	while( sc >= 8 )
-		{
-		eshup8(x);
-		sc -= 8;
-		}
-
-	while( sc > 0 )
-		{
-		eshup1(x);
-		sc -= 1;
-		}
-	}
-if( lost )
-	lost = 1;
-return( (int )lost );
-}
-
-
-
-/*
-;	normalize
-;
-; Shift normalizes the significand area pointed to by argument
-; shift count (up = positive) is returned.
-*/
-int enormlz(x)
-unsigned short x[];
-{
-register unsigned short *p;
-int sc;
-
-sc = 0;
-p = &x[M];
-if( *p != 0 )
-	goto normdn;
-++p;
-if( *p & 0x8000 )
-	return( 0 );	/* already normalized */
-while( *p == 0 )
-	{
-	eshup6(x);
-	sc += 16;
-/* With guard word, there are NBITS+16 bits available.
- * return true if all are zero.
- */
-	if( sc > NBITS )
-		return( sc );
-	}
-/* see if high byte is zero */
-while( (*p & 0xff00) == 0 )
-	{
-	eshup8(x);
-	sc += 8;
-	}
-/* now shift 1 bit at a time */
-while( (*p  & 0x8000) == 0)
-	{
-	eshup1(x);
-	sc += 1;
-	if( sc > (NBITS+16) )
-		{
-		mtherr( "enormlz", UNDERFLOW );
-		return( sc );
-		}
-	}
-return( sc );
-
-/* Normalize by shifting down out of the high guard word
-   of the significand */
-normdn:
-
-if( *p & 0xff00 )
-	{
-	eshdn8(x);
-	sc -= 8;
-	}
-while( *p != 0 )
-	{
-	eshdn1(x);
-	sc -= 1;
-
-	if( sc < -NBITS )
-		{
-		mtherr( "enormlz", OVERFLOW );
-		return( sc );
-		}
-	}
-return( sc );
-}
-
-
-
-
-/* Convert e type number to decimal format ASCII string.
- * The constants are for 64 bit precision.
- */
-
-#define NTEN 12
-#define MAXP 4096
-
-#if NE == 10
-static unsigned short etens[NTEN + 1][NE] =
-{
-  {0x6576, 0x4a92, 0x804a, 0x153f,
-   0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,},	/* 10**4096 */
-  {0x6a32, 0xce52, 0x329a, 0x28ce,
-   0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,},	/* 10**2048 */
-  {0x526c, 0x50ce, 0xf18b, 0x3d28,
-   0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
-  {0x9c66, 0x58f8, 0xbc50, 0x5c54,
-   0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
-  {0x851e, 0xeab7, 0x98fe, 0x901b,
-   0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
-  {0x0235, 0x0137, 0x36b1, 0x336c,
-   0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
-  {0x50f8, 0x25fb, 0xc76b, 0x6b71,
-   0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
-  {0x0000, 0x0000, 0x0000, 0x0000,
-   0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
-  {0x0000, 0x0000, 0x0000, 0x0000,
-   0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
-  {0x0000, 0x0000, 0x0000, 0x0000,
-   0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
-  {0x0000, 0x0000, 0x0000, 0x0000,
-   0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
-  {0x0000, 0x0000, 0x0000, 0x0000,
-   0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
-  {0x0000, 0x0000, 0x0000, 0x0000,
-   0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,},	/* 10**1 */
-};
-
-static unsigned short emtens[NTEN + 1][NE] =
-{
-  {0x2030, 0xcffc, 0xa1c3, 0x8123,
-   0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,},	/* 10**-4096 */
-  {0x8264, 0xd2cb, 0xf2ea, 0x12d4,
-   0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,},	/* 10**-2048 */
-  {0xf53f, 0xf698, 0x6bd3, 0x0158,
-   0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
-  {0xe731, 0x04d4, 0xe3f2, 0xd332,
-   0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
-  {0xa23e, 0x5308, 0xfefb, 0x1155,
-   0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
-  {0xe26d, 0xdbde, 0xd05d, 0xb3f6,
-   0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
-  {0x2a20, 0x6224, 0x47b3, 0x98d7,
-   0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
-  {0x0b5b, 0x4af2, 0xa581, 0x18ed,
-   0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
-  {0xbf71, 0xa9b3, 0x7989, 0xbe68,
-   0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
-  {0x3d4d, 0x7c3d, 0x36ba, 0x0d2b,
-   0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
-  {0xc155, 0xa4a8, 0x404e, 0x6113,
-   0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
-  {0xd70a, 0x70a3, 0x0a3d, 0xa3d7,
-   0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
-  {0xcccd, 0xcccc, 0xcccc, 0xcccc,
-   0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,},	/* 10**-1 */
-};
-#else
-static unsigned short etens[NTEN+1][NE] = {
-{0xc94c,0x979a,0x8a20,0x5202,0xc460,0x7525,},/* 10**4096 */
-{0xa74d,0x5de4,0xc53d,0x3b5d,0x9e8b,0x5a92,},/* 10**2048 */
-{0x650d,0x0c17,0x8175,0x7586,0xc976,0x4d48,},
-{0xcc65,0x91c6,0xa60e,0xa0ae,0xe319,0x46a3,},
-{0xddbc,0xde8d,0x9df9,0xebfb,0xaa7e,0x4351,},
-{0xc66f,0x8cdf,0x80e9,0x47c9,0x93ba,0x41a8,},
-{0x3cbf,0xa6d5,0xffcf,0x1f49,0xc278,0x40d3,},
-{0xf020,0xb59d,0x2b70,0xada8,0x9dc5,0x4069,},
-{0x0000,0x0000,0x0400,0xc9bf,0x8e1b,0x4034,},
-{0x0000,0x0000,0x0000,0x2000,0xbebc,0x4019,},
-{0x0000,0x0000,0x0000,0x0000,0x9c40,0x400c,},
-{0x0000,0x0000,0x0000,0x0000,0xc800,0x4005,},
-{0x0000,0x0000,0x0000,0x0000,0xa000,0x4002,}, /* 10**1 */
-};
-
-static unsigned short emtens[NTEN+1][NE] = {
-{0x2de4,0x9fde,0xd2ce,0x04c8,0xa6dd,0x0ad8,}, /* 10**-4096 */
-{0x4925,0x2de4,0x3436,0x534f,0xceae,0x256b,}, /* 10**-2048 */
-{0x87a6,0xc0bd,0xda57,0x82a5,0xa2a6,0x32b5,},
-{0x7133,0xd21c,0xdb23,0xee32,0x9049,0x395a,},
-{0xfa91,0x1939,0x637a,0x4325,0xc031,0x3cac,},
-{0xac7d,0xe4a0,0x64bc,0x467c,0xddd0,0x3e55,},
-{0x3f24,0xe9a5,0xa539,0xea27,0xa87f,0x3f2a,},
-{0x67de,0x94ba,0x4539,0x1ead,0xcfb1,0x3f94,},
-{0x4c2f,0xe15b,0xc44d,0x94be,0xe695,0x3fc9,},
-{0xfdc2,0xcefc,0x8461,0x7711,0xabcc,0x3fe4,},
-{0xd3c3,0x652b,0xe219,0x1758,0xd1b7,0x3ff1,},
-{0x3d71,0xd70a,0x70a3,0x0a3d,0xa3d7,0x3ff8,},
-{0xcccd,0xcccc,0xcccc,0xcccc,0xcccc,0x3ffb,}, /* 10**-1 */
-};
-#endif
-
-void e24toasc( x, string, ndigs )
-unsigned short x[];
-char *string;
-int ndigs;
-{
-unsigned short w[NI];
-
-e24toe( x, w );
-etoasc( w, string, ndigs );
-}
-
-
-void e53toasc( x, string, ndigs )
-unsigned short x[];
-char *string;
-int ndigs;
-{
-unsigned short w[NI];
-
-e53toe( x, w );
-etoasc( w, string, ndigs );
-}
-
-
-void e64toasc( x, string, ndigs )
-unsigned short x[];
-char *string;
-int ndigs;
-{
-unsigned short w[NI];
-
-e64toe( x, w );
-etoasc( w, string, ndigs );
-}
-
-void e113toasc (x, string, ndigs)
-unsigned short x[];
-char *string;
-int ndigs;
-{
-unsigned short w[NI];
-
-e113toe (x, w);
-etoasc (w, string, ndigs);
-}
-
-
-void etoasc( x, string, ndigs )
-unsigned short x[];
-char *string;
-int ndigs;
-{
-long digit;
-unsigned short y[NI], t[NI], u[NI], w[NI];
-unsigned short *p, *r, *ten;
-unsigned short sign;
-int i, j, k, expon, rndsav;
-char *s, *ss;
-unsigned short m;
-
-rndsav = rndprc;
-#ifdef NANS
-if( eisnan(x) )
-	{
-	sprintf( string, " NaN " );
-	goto bxit;
-	}
-#endif
-rndprc = NBITS;		/* set to full precision */
-emov( x, y ); /* retain external format */
-if( y[NE-1] & 0x8000 )
-	{
-	sign = 0xffff;
-	y[NE-1] &= 0x7fff;
-	}
-else
-	{
-	sign = 0;
-	}
-expon = 0;
-ten = &etens[NTEN][0];
-emov( eone, t );
-/* Test for zero exponent */
-if( y[NE-1] == 0 )
-	{
-	for( k=0; k<NE-1; k++ )
-		{
-		if( y[k] != 0 )
-			goto tnzro; /* denormalized number */
-		}
-	goto isone; /* legal all zeros */
-	}
-tnzro:
-
-/* Test for infinity.
- */
-if( y[NE-1] == 0x7fff )
-	{
-	if( sign )
-		sprintf( string, " -Infinity " );
-	else
-		sprintf( string, " Infinity " );
-	goto bxit;
-	}
-
-/* Test for exponent nonzero but significand denormalized.
- * This is an error condition.
- */
-if( (y[NE-1] != 0) && ((y[NE-2] & 0x8000) == 0) )
-	{
-	mtherr( "etoasc", DOMAIN );
-	sprintf( string, "NaN" );
-	goto bxit;
-	}
-
-/* Compare to 1.0 */
-i = ecmp( eone, y );
-if( i == 0 )
-	goto isone;
-
-if( i < 0 )
-	{ /* Number is greater than 1 */
-/* Convert significand to an integer and strip trailing decimal zeros. */
-	emov( y, u );
-	u[NE-1] = EXONE + NBITS - 1;
-
-	p = &etens[NTEN-4][0];
-	m = 16;
-do
-	{
-	ediv( p, u, t );
-	efloor( t, w );
-	for( j=0; j<NE-1; j++ )
-		{
-		if( t[j] != w[j] )
-			goto noint;
-		}
-	emov( t, u );
-	expon += (int )m;
-noint:
-	p += NE;
-	m >>= 1;
-	}
-while( m != 0 );
-
-/* Rescale from integer significand */
-	u[NE-1] += y[NE-1] - (unsigned int )(EXONE + NBITS - 1);
-	emov( u, y );
-/* Find power of 10 */
-	emov( eone, t );
-	m = MAXP;
-	p = &etens[0][0];
-	while( ecmp( ten, u ) <= 0 )
-		{
-		if( ecmp( p, u ) <= 0 )
-			{
-			ediv( p, u, u );
-			emul( p, t, t );
-			expon += (int )m;
-			}
-		m >>= 1;
-		if( m == 0 )
-			break;
-		p += NE;
-		}
-	}
-else
-	{ /* Number is less than 1.0 */
-/* Pad significand with trailing decimal zeros. */
-	if( y[NE-1] == 0 )
-		{
-		while( (y[NE-2] & 0x8000) == 0 )
-			{
-			emul( ten, y, y );
-			expon -= 1;
-			}
-		}
-	else
-		{
-		emovi( y, w );
-		for( i=0; i<NDEC+1; i++ )
-			{
-			if( (w[NI-1] & 0x7) != 0 )
-				break;
-/* multiply by 10 */
-			emovz( w, u );
-			eshdn1( u );
-			eshdn1( u );
-			eaddm( w, u );
-			u[1] += 3;
-			while( u[2] != 0 )
-				{
-				eshdn1(u);
-				u[1] += 1;
-				}
-			if( u[NI-1] != 0 )
-				break;
-			if( eone[NE-1] <= u[1] )
-				break;
-			emovz( u, w );
-			expon -= 1;
-			}
-		emovo( w, y );
-		}
-	k = -MAXP;
-	p = &emtens[0][0];
-	r = &etens[0][0];
-	emov( y, w );
-	emov( eone, t );
-	while( ecmp( eone, w ) > 0 )
-		{
-		if( ecmp( p, w ) >= 0 )
-			{
-			emul( r, w, w );
-			emul( r, t, t );
-			expon += k;
-			}
-		k /= 2;
-		if( k == 0 )
-			break;
-		p += NE;
-		r += NE;
-		}
-	ediv( t, eone, t );
-	}
-isone:
-/* Find the first (leading) digit. */
-emovi( t, w );
-emovz( w, t );
-emovi( y, w );
-emovz( w, y );
-eiremain( t, y );
-digit = equot[NI-1];
-while( (digit == 0) && (ecmp(y,ezero) != 0) )
-	{
-	eshup1( y );
-	emovz( y, u );
-	eshup1( u );
-	eshup1( u );
-	eaddm( u, y );
-	eiremain( t, y );
-	digit = equot[NI-1];
-	expon -= 1;
-	}
-s = string;
-if( sign )
-	*s++ = '-';
-else
-	*s++ = ' ';
-/* Examine number of digits requested by caller. */
-if( ndigs < 0 )
-	ndigs = 0;
-if( ndigs > NDEC )
-	ndigs = NDEC;
-if( digit == 10 )
-	{
-	*s++ = '1';
-	*s++ = '.';
-	if( ndigs > 0 )
-		{
-		*s++ = '0';
-		ndigs -= 1;
-		}
-	expon += 1;
-	}
-else
-	{
-	*s++ = (char )digit + '0';
-	*s++ = '.';
-	}
-/* Generate digits after the decimal point. */
-for( k=0; k<=ndigs; k++ )
-	{
-/* multiply current number by 10, without normalizing */
-	eshup1( y );
-	emovz( y, u );
-	eshup1( u );
-	eshup1( u );
-	eaddm( u, y );
-	eiremain( t, y );
-	*s++ = (char )equot[NI-1] + '0';
-	}
-digit = equot[NI-1];
---s;
-ss = s;
-/* round off the ASCII string */
-if( digit > 4 )
-	{
-/* Test for critical rounding case in ASCII output. */
-	if( digit == 5 )
-		{
-		emovo( y, t );
-		if( ecmp(t,ezero) != 0 )
-			goto roun;	/* round to nearest */
-		if( (*(s-1) & 1) == 0 )
-			goto doexp;	/* round to even */
-		}
-/* Round up and propagate carry-outs */
-roun:
-	--s;
-	k = *s & 0x7f;
-/* Carry out to most significant digit? */
-	if( k == '.' )
-		{
-		--s;
-		k = *s;
-		k += 1;
-		*s = (char )k;
-/* Most significant digit carries to 10? */
-		if( k > '9' )
-			{
-			expon += 1;
-			*s = '1';
-			}
-		goto doexp;
-		}
-/* Round up and carry out from less significant digits */
-	k += 1;
-	*s = (char )k;
-	if( k > '9' )
-		{
-		*s = '0';
-		goto roun;
-		}
-	}
-doexp:
-/*
-if( expon >= 0 )
-	sprintf( ss, "e+%d", expon );
-else
-	sprintf( ss, "e%d", expon );
-*/
-	sprintf( ss, "E%d", expon );
-bxit:
-rndprc = rndsav;
-}
-
-
-
-
-/*
-;								ASCTOQ
-;		ASCTOQ.MAC		LATEST REV: 11 JAN 84
-;					SLM, 3 JAN 78
-;
-;	Convert ASCII string to quadruple precision floating point
-;
-;		Numeric input is free field decimal number
-;		with max of 15 digits with or without 
-;		decimal point entered as ASCII from teletype.
-;	Entering E after the number followed by a second
-;	number causes the second number to be interpreted
-;	as a power of 10 to be multiplied by the first number
-;	(i.e., "scientific" notation).
-;
-;	Usage:
-;		asctoq( string, q );
-*/
-
-/* ASCII to single */
-void asctoe24( s, y )
-char *s;
-unsigned short *y;
-{
-asctoeg( s, y, 24 );
-}
-
-
-/* ASCII to double */
-void asctoe53( s, y )
-char *s;
-unsigned short *y;
-{
-#ifdef DEC
-asctoeg( s, y, 56 );
-#else
-asctoeg( s, y, 53 );
-#endif
-}
-
-
-/* ASCII to long double */
-void asctoe64( s, y )
-char *s;
-unsigned short *y;
-{
-asctoeg( s, y, 64 );
-}
-
-/* ASCII to 128-bit long double */
-void asctoe113 (s, y)
-char *s;
-unsigned short *y;
-{
-asctoeg( s, y, 113 );
-}
-
-/* ASCII to super double */
-void asctoe( s, y )
-char *s;
-unsigned short *y;
-{
-asctoeg( s, y, NBITS );
-}
-
-/* Space to make a copy of the input string: */
-static char lstr[82] = {0};
-
-void asctoeg( ss, y, oprec )
-char *ss;
-unsigned short *y;
-int oprec;
-{
-unsigned short yy[NI], xt[NI], tt[NI];
-int esign, decflg, sgnflg, nexp, exp, prec, lost;
-int k, trail, c, rndsav;
-long lexp;
-unsigned short nsign, *p;
-char *sp, *s;
-
-/* Copy the input string. */
-s = ss;
-while( *s == ' ' ) /* skip leading spaces */
-	++s;
-sp = lstr;
-for( k=0; k<79; k++ )
-	{
-	if( (*sp++ = *s++) == '\0' )
-		break;
-	}
-*sp = '\0';
-s = lstr;
-
-rndsav = rndprc;
-rndprc = NBITS; /* Set to full precision */
-lost = 0;
-nsign = 0;
-decflg = 0;
-sgnflg = 0;
-nexp = 0;
-exp = 0;
-prec = 0;
-ecleaz( yy );
-trail = 0;
-
-nxtcom:
-k = *s - '0';
-if( (k >= 0) && (k <= 9) )
-	{
-/* Ignore leading zeros */
-	if( (prec == 0) && (decflg == 0) && (k == 0) )
-		goto donchr;
-/* Identify and strip trailing zeros after the decimal point. */
-	if( (trail == 0) && (decflg != 0) )
-		{
-		sp = s;
-		while( (*sp >= '0') && (*sp <= '9') )
-			++sp;
-/* Check for syntax error */
-		c = *sp & 0x7f;
-		if( (c != 'e') && (c != 'E') && (c != '\0')
-			&& (c != '\n') && (c != '\r') && (c != ' ')
-			&& (c != ',') )
-			goto error;
-		--sp;
-		while( *sp == '0' )
-			*sp-- = 'z';
-		trail = 1;
-		if( *s == 'z' )
-			goto donchr;
-		}
-/* If enough digits were given to more than fill up the yy register,
- * continuing until overflow into the high guard word yy[2]
- * guarantees that there will be a roundoff bit at the top
- * of the low guard word after normalization.
- */
-	if( yy[2] == 0 )
-		{
-		if( decflg )
-			nexp += 1; /* count digits after decimal point */
-		eshup1( yy );	/* multiply current number by 10 */
-		emovz( yy, xt );
-		eshup1( xt );
-		eshup1( xt );
-		eaddm( xt, yy );
-		ecleaz( xt );
-		xt[NI-2] = (unsigned short )k;
-		eaddm( xt, yy );
-		}
-	else
-		{
-		/* Mark any lost non-zero digit.  */
-		lost |= k;
-		/* Count lost digits before the decimal point.  */
-		if (decflg == 0)
-		        nexp -= 1;
-		}
-	prec += 1;
-	goto donchr;
-	}
-
-switch( *s )
-	{
-	case 'z':
-		break;
-	case 'E':
-	case 'e':
-		goto expnt;
-	case '.':	/* decimal point */
-		if( decflg )
-			goto error;
-		++decflg;
-		break;
-	case '-':
-		nsign = 0xffff;
-		if( sgnflg )
-			goto error;
-		++sgnflg;
-		break;
-	case '+':
-		if( sgnflg )
-			goto error;
-		++sgnflg;
-		break;
-	case ',':
-	case ' ':
-	case '\0':
-	case '\n':
-	case '\r':
-		goto daldone;
-	case 'i':
-	case 'I':
-		goto infinite;
-	default:
-	error:
-#ifdef NANS
-		enan( yy, NI*16 );
-#else
-		mtherr( "asctoe", DOMAIN );
-		ecleaz(yy);
-#endif
-		goto aexit;
-	}
-donchr:
-++s;
-goto nxtcom;
-
-/* Exponent interpretation */
-expnt:
-
-esign = 1;
-exp = 0;
-++s;
-/* check for + or - */
-if( *s == '-' )
-	{
-	esign = -1;
-	++s;
-	}
-if( *s == '+' )
-	++s;
-while( (*s >= '0') && (*s <= '9') )
-	{
-	exp *= 10;
-	exp += *s++ - '0';
-	if (exp > 4977)
-		{
-		if (esign < 0)
-			goto zero;
-		else
-			goto infinite;
-		}
-	}
-if( esign < 0 )
-	exp = -exp;
-if( exp > 4932 )
-	{
-infinite:
-	ecleaz(yy);
-	yy[E] = 0x7fff;  /* infinity */
-	goto aexit;
-	}
-if( exp < -4977 )
-	{
-zero:
-	ecleaz(yy);
-	goto aexit;
-	}
-
-daldone:
-nexp = exp - nexp;
-/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
-while( (nexp > 0) && (yy[2] == 0) )
-	{
-	emovz( yy, xt );
-	eshup1( xt );
-	eshup1( xt );
-	eaddm( yy, xt );
-	eshup1( xt );
-	if( xt[2] != 0 )
-		break;
-	nexp -= 1;
-	emovz( xt, yy );
-	}
-if( (k = enormlz(yy)) > NBITS )
-	{
-	ecleaz(yy);
-	goto aexit;
-	}
-lexp = (EXONE - 1 + NBITS) - k;
-emdnorm( yy, lost, 0, lexp, 64 );
-/* convert to external format */
-
-
-/* Multiply by 10**nexp.  If precision is 64 bits,
- * the maximum relative error incurred in forming 10**n
- * for 0 <= n <= 324 is 8.2e-20, at 10**180.
- * For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947.
- * For 0 >= n >= -999, it is -1.55e-19 at 10**-435.
- */
-lexp = yy[E];
-if( nexp == 0 )
-	{
-	k = 0;
-	goto expdon;
-	}
-esign = 1;
-if( nexp < 0 )
-	{
-	nexp = -nexp;
-	esign = -1;
-	if( nexp > 4096 )
-		{ /* Punt.  Can't handle this without 2 divides. */
-		emovi( etens[0], tt );
-		lexp -= tt[E];
-		k = edivm( tt, yy );
-		lexp += EXONE;
-		nexp -= 4096;
-		}
-	}
-p = &etens[NTEN][0];
-emov( eone, xt );
-exp = 1;
-do
-	{
-	if( exp & nexp )
-		emul( p, xt, xt );
-	p -= NE;
-	exp = exp + exp;
-	}
-while( exp <= MAXP );
-
-emovi( xt, tt );
-if( esign < 0 )
-	{
-	lexp -= tt[E];
-	k = edivm( tt, yy );
-	lexp += EXONE;
-	}
-else
-	{
-	lexp += tt[E];
-	k = emulm( tt, yy );
-	lexp -= EXONE - 1;
-	}
-
-expdon:
-
-/* Round and convert directly to the destination type */
-if( oprec == 53 )
-	lexp -= EXONE - 0x3ff;
-else if( oprec == 24 )
-	lexp -= EXONE - 0177;
-#ifdef DEC
-else if( oprec == 56 )
-	lexp -= EXONE - 0201;
-#endif
-rndprc = oprec;
-emdnorm( yy, k, 0, lexp, 64 );
-
-aexit:
-
-rndprc = rndsav;
-yy[0] = nsign;
-switch( oprec )
-	{
-#ifdef DEC
-	case 56:
-		todec( yy, y ); /* see etodec.c */
-		break;
-#endif
-	case 53:
-		toe53( yy, y );
-		break;
-	case 24:
-		toe24( yy, y );
-		break;
-	case 64:
-		toe64( yy, y );
-		break;
-	case 113:
-		toe113( yy, y );
-		break;
-	case NBITS:
-		emovo( yy, y );
-		break;
-	}
-}
-
-
- 
-/* y = largest integer not greater than x
- * (truncated toward minus infinity)
- *
- * unsigned short x[NE], y[NE]
- *
- * efloor( x, y );
- */
-static unsigned short bmask[] = {
-0xffff,
-0xfffe,
-0xfffc,
-0xfff8,
-0xfff0,
-0xffe0,
-0xffc0,
-0xff80,
-0xff00,
-0xfe00,
-0xfc00,
-0xf800,
-0xf000,
-0xe000,
-0xc000,
-0x8000,
-0x0000,
-};
-
-void efloor( x, y )
-unsigned short x[], y[];
-{
-register unsigned short *p;
-int e, expon, i;
-unsigned short f[NE];
-
-emov( x, f ); /* leave in external format */
-expon = (int )f[NE-1];
-e = (expon & 0x7fff) - (EXONE - 1);
-if( e <= 0 )
-	{
-	eclear(y);
-	goto isitneg;
-	}
-/* number of bits to clear out */
-e = NBITS - e;
-emov( f, y );
-if( e <= 0 )
-	return;
-
-p = &y[0];
-while( e >= 16 )
-	{
-	*p++ = 0;
-	e -= 16;
-	}
-/* clear the remaining bits */
-*p &= bmask[e];
-/* truncate negatives toward minus infinity */
-isitneg:
-
-if( (unsigned short )expon & (unsigned short )0x8000 )
-	{
-	for( i=0; i<NE-1; i++ )
-		{
-		if( f[i] != y[i] )
-			{
-			esub( eone, y, y );
-			break;
-			}
-		}
-	}
-}
-
-
-/* unsigned short x[], s[];
- * long *exp;
- *
- * efrexp( x, exp, s );
- *
- * Returns s and exp such that  s * 2**exp = x and .5 <= s < 1.
- * For example, 1.1 = 0.55 * 2**1
- * Handles denormalized numbers properly using long integer exp.
- */
-void efrexp( x, exp, s )
-unsigned short x[];
-long *exp;
-unsigned short s[];
-{
-unsigned short xi[NI];
-long li;
-
-emovi( x, xi );
-li = (long )((short )xi[1]);
-
-if( li == 0 )
-	{
-	li -= enormlz( xi );
-	}
-xi[1] = 0x3ffe;
-emovo( xi, s );
-*exp = li - 0x3ffe;
-}
-
-
-
-/* unsigned short x[], y[];
- * long pwr2;
- *
- * eldexp( x, pwr2, y );
- *
- * Returns y = x * 2**pwr2.
- */
-void eldexp( x, pwr2, y )
-unsigned short x[];
-long pwr2;
-unsigned short y[];
-{
-unsigned short xi[NI];
-long li;
-int i;
-
-emovi( x, xi );
-li = xi[1];
-li += pwr2;
-i = 0;
-emdnorm( xi, i, i, li, 64 );
-emovo( xi, y );
-}
-
-
-/* c = remainder after dividing b by a
- * Least significant integer quotient bits left in equot[].
- */
-void eremain( a, b, c )
-unsigned short a[], b[], c[];
-{
-unsigned short den[NI], num[NI];
-
-#ifdef NANS
-if( eisinf(b) || (ecmp(a,ezero) == 0) || eisnan(a) || eisnan(b))
-	{
-	enan( c, NBITS );
-	return;
-	}
-#endif
-if( ecmp(a,ezero) == 0 )
-	{
-	mtherr( "eremain", SING );
-	eclear( c );
-	return;
-	}
-emovi( a, den );
-emovi( b, num );
-eiremain( den, num );
-/* Sign of remainder = sign of quotient */
-if( a[0] == b[0] )
-	num[0] = 0;
-else
-	num[0] = 0xffff;
-emovo( num, c );
-}
-
-
-void eiremain( den, num )
-unsigned short den[], num[];
-{
-long ld, ln;
-unsigned short j;
-
-ld = den[E];
-ld -= enormlz( den );
-ln = num[E];
-ln -= enormlz( num );
-ecleaz( equot );
-while( ln >= ld )
-	{
-	if( ecmpm(den,num) <= 0 )
-		{
-		esubm(den, num);
-		j = 1;
-		}
-	else
-		{
-		j = 0;
-		}
-	eshup1(equot);
-	equot[NI-1] |= j;
-	eshup1(num);
-	ln -= 1;
-	}
-emdnorm( num, 0, 0, ln, 0 );
-}
-
-/* NaN bit patterns
- */
-#ifdef MIEEE
-unsigned short nan113[8] = {
-  0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
-unsigned short nan64[6] = {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
-unsigned short nan53[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
-unsigned short nan24[2] = {0x7fff, 0xffff};
-#endif
-
-#ifdef IBMPC
-unsigned short nan113[8] = {0, 0, 0, 0, 0, 0, 0xc000, 0xffff};
-unsigned short nan64[6] = {0, 0, 0, 0xc000, 0xffff, 0};
-unsigned short nan53[4] = {0, 0, 0, 0xfff8};
-unsigned short nan24[2] = {0, 0xffc0};
-#endif
-
-
-void enan (nan, size)
-unsigned short *nan;
-int size;
-{
-int i, n;
-unsigned short *p;
-
-switch( size )
-	{
-#ifndef DEC
-	case 113:
-	n = 8;
-	p = nan113;
-	break;
-
-	case 64:
-	n = 6;
-	p = nan64;
-	break;
-
-	case 53:
-	n = 4;
-	p = nan53;
-	break;
-
-	case 24:
-	n = 2;
-	p = nan24;
-	break;
-
-	case NBITS:
-	for( i=0; i<NE-2; i++ )
-		*nan++ = 0;
-	*nan++ = 0xc000;
-	*nan++ = 0x7fff;
-	return;
-
-	case NI*16:
-	*nan++ = 0;
-	*nan++ = 0x7fff;
-	*nan++ = 0;
-	*nan++ = 0xc000;
-	for( i=4; i<NI; i++ )
-		*nan++ = 0;
-	return;
-#endif
-	default:
-	mtherr( "enan", DOMAIN );
-	return;
-	}
-for (i=0; i < n; i++)
-	*nan++ = *p++;
-}
-
-
-
-/* Longhand square root. */
-
-static int esqinited = 0;
-static unsigned short sqrndbit[NI];
-
-void esqrt( x, y )
-short *x, *y;
-{
-unsigned short temp[NI], num[NI], sq[NI], xx[NI];
-int i, j, k, n, nlups;
-long m, exp;
-
-if( esqinited == 0 )
-	{
-	ecleaz( sqrndbit );
-	sqrndbit[NI-2] = 1;
-	esqinited = 1;
-	}
-/* Check for arg <= 0 */
-i = ecmp( x, ezero );
-if( i <= 0 )
-	{
-#ifdef NANS
-	if (i == -2)
-		{
-		enan (y, NBITS);
-		return;
-		}
-#endif
-	eclear(y);
-	if( i < 0 )
-		mtherr( "esqrt", DOMAIN );
-	return;
-	}
-
-#ifdef INFINITY
-if( eisinf(x) )
-	{
-	eclear(y);
-	einfin(y);
-	return;
-	}
-#endif
-/* Bring in the arg and renormalize if it is denormal. */
-emovi( x, xx );
-m = (long )xx[1]; /* local long word exponent */
-if( m == 0 )
-	m -= enormlz( xx );
-
-/* Divide exponent by 2 */
-m -= 0x3ffe;
-exp = (unsigned short )( (m / 2) + 0x3ffe );
-
-/* Adjust if exponent odd */
-if( (m & 1) != 0 )
-	{
-	if( m > 0 )
-		exp += 1;
-	eshdn1( xx );
-	}
-
-ecleaz( sq );
-ecleaz( num );
-n = 8; /* get 8 bits of result per inner loop */
-nlups = rndprc;
-j = 0;
-
-while( nlups > 0 )
-	{
-/* bring in next word of arg */
-	if( j < NE )
-		num[NI-1] = xx[j+3];
-/* Do additional bit on last outer loop, for roundoff. */
-	if( nlups <= 8 )
-		n = nlups + 1;
-	for( i=0; i<n; i++ )
-		{
-/* Next 2 bits of arg */
-		eshup1( num );
-		eshup1( num );
-/* Shift up answer */
-		eshup1( sq );
-/* Make trial divisor */
-		for( k=0; k<NI; k++ )
-			temp[k] = sq[k];
-		eshup1( temp );
-		eaddm( sqrndbit, temp );
-/* Subtract and insert answer bit if it goes in */
-		if( ecmpm( temp, num ) <= 0 )
-			{
-			esubm( temp, num );
-			sq[NI-2] |= 1;
-			}
-		}
-	nlups -= n;
-	j += 1;
-	}
-
-/* Adjust for extra, roundoff loop done. */
-exp += (NBITS - 1) - rndprc;
-
-/* Sticky bit = 1 if the remainder is nonzero. */
-k = 0;
-for( i=3; i<NI; i++ )
-	k |= (int )num[i];
-
-/* Renormalize and round off. */
-emdnorm( sq, k, 0, exp, 64 );
-emovo( sq, y );
-}
+/*							ieee.c
+ *
+ *    Extended precision IEEE binary floating point arithmetic routines
+ *
+ * Numbers are stored in C language as arrays of 16-bit unsigned
+ * short integers.  The arguments of the routines are pointers to
+ * the arrays.
+ *
+ *
+ * External e type data structure, simulates Intel 8087 chip
+ * temporary real format but possibly with a larger significand:
+ *
+ *	NE-1 significand words	(least significant word first,
+ *				 most significant bit is normally set)
+ *	exponent		(value = EXONE for 1.0,
+ *				top bit is the sign)
+ *
+ *
+ * Internal data structure of a number (a "word" is 16 bits):
+ *
+ * ei[0]	sign word	(0 for positive, 0xffff for negative)
+ * ei[1]	biased exponent	(value = EXONE for the number 1.0)
+ * ei[2]	high guard word	(always zero after normalization)
+ * ei[3]
+ * to ei[NI-2]	significand	(NI-4 significand words,
+ *				 most significant word first,
+ *				 most significant bit is set)
+ * ei[NI-1]	low guard word	(0x8000 bit is rounding place)
+ *
+ *
+ *
+ *		Routines for external format numbers
+ *
+ *	asctoe( string, e )	ASCII string to extended double e type
+ *	asctoe64( string, &d )	ASCII string to long double
+ *	asctoe53( string, &d )	ASCII string to double
+ *	asctoe24( string, &f )	ASCII string to single
+ *	asctoeg( string, e, prec ) ASCII string to specified precision
+ *	e24toe( &f, e )		IEEE single precision to e type
+ *	e53toe( &d, e )		IEEE double precision to e type
+ *	e64toe( &d, e )		IEEE long double precision to e type
+ *	eabs(e)			absolute value
+ *	eadd( a, b, c )		c = b + a
+ *	eclear(e)		e = 0
+ *	ecmp (a, b)		Returns 1 if a > b, 0 if a == b,
+ *				-1 if a < b, -2 if either a or b is a NaN.
+ *	ediv( a, b, c )		c = b / a
+ *	efloor( a, b )		truncate to integer, toward -infinity
+ *	efrexp( a, exp, s )	extract exponent and significand
+ *	eifrac( e, &l, frac )   e to long integer and e type fraction
+ *	euifrac( e, &l, frac )  e to unsigned long integer and e type fraction
+ *	einfin( e )		set e to infinity, leaving its sign alone
+ *	eldexp( a, n, b )	multiply by 2**n
+ *	emov( a, b )		b = a
+ *	emul( a, b, c )		c = b * a
+ *	eneg(e)			e = -e
+ *	eround( a, b )		b = nearest integer value to a
+ *	esub( a, b, c )		c = b - a
+ *	e24toasc( &f, str, n )	single to ASCII string, n digits after decimal
+ *	e53toasc( &d, str, n )	double to ASCII string, n digits after decimal
+ *	e64toasc( &d, str, n )	long double to ASCII string
+ *	etoasc( e, str, n )	e to ASCII string, n digits after decimal
+ *	etoe24( e, &f )		convert e type to IEEE single precision
+ *	etoe53( e, &d )		convert e type to IEEE double precision
+ *	etoe64( e, &d )		convert e type to IEEE long double precision
+ *	ltoe( &l, e )		long (32 bit) integer to e type
+ *	ultoe( &l, e )		unsigned long (32 bit) integer to e type
+ *      eisneg( e )             1 if sign bit of e != 0, else 0
+ *      eisinf( e )             1 if e has maximum exponent (non-IEEE)
+ *				or is infinite (IEEE)
+ *      eisnan( e )             1 if e is a NaN
+ *	esqrt( a, b )		b = square root of a
+ *
+ *
+ *		Routines for internal format numbers
+ *
+ *	eaddm( ai, bi )		add significands, bi = bi + ai
+ *	ecleaz(ei)		ei = 0
+ *	ecleazs(ei)		set ei = 0 but leave its sign alone
+ *	ecmpm( ai, bi )		compare significands, return 1, 0, or -1
+ *	edivm( ai, bi )		divide  significands, bi = bi / ai
+ *	emdnorm(ai,l,s,exp)	normalize and round off
+ *	emovi( a, ai )		convert external a to internal ai
+ *	emovo( ai, a )		convert internal ai to external a
+ *	emovz( ai, bi )		bi = ai, low guard word of bi = 0
+ *	emulm( ai, bi )		multiply significands, bi = bi * ai
+ *	enormlz(ei)		left-justify the significand
+ *	eshdn1( ai )		shift significand and guards down 1 bit
+ *	eshdn8( ai )		shift down 8 bits
+ *	eshdn6( ai )		shift down 16 bits
+ *	eshift( ai, n )		shift ai n bits up (or down if n < 0)
+ *	eshup1( ai )		shift significand and guards up 1 bit
+ *	eshup8( ai )		shift up 8 bits
+ *	eshup6( ai )		shift up 16 bits
+ *	esubm( ai, bi )		subtract significands, bi = bi - ai
+ *
+ *
+ * The result is always normalized and rounded to NI-4 word precision
+ * after each arithmetic operation.
+ *
+ * Exception flags are NOT fully supported.
+ *
+ * Define INFINITY in mconf.h for support of infinity; otherwise a
+ * saturation arithmetic is implemented.
+ *
+ * Define NANS for support of Not-a-Number items; otherwise the
+ * arithmetic will never produce a NaN output, and might be confused
+ * by a NaN input.
+ * If NaN's are supported, the output of ecmp(a,b) is -2 if
+ * either a or b is a NaN. This means asking if(ecmp(a,b) < 0)
+ * may not be legitimate. Use if(ecmp(a,b) == -1) for less-than
+ * if in doubt.
+ * Signaling NaN's are NOT supported; they are treated the same
+ * as quiet NaN's.
+ *
+ * Denormals are always supported here where appropriate (e.g., not
+ * for conversion to DEC numbers).
+ */
+
+/*
+ * Revision history:
+ *
+ *  5 Jan 84	PDP-11 assembly language version
+ *  2 Mar 86	fixed bug in asctoq()
+ *  6 Dec 86	C language version
+ * 30 Aug 88	100 digit version, improved rounding
+ * 15 May 92    80-bit long double support
+ *
+ * Author:  S. L. Moshier.
+ */
+
+#include <stdio.h>
+/* #include "\usr\include\stdio.h" */
+#include "ehead.h"
+#include "mconf.h"
+
+/* Change UNK into something else. */
+#ifdef UNK
+#undef UNK
+#define IBMPC 1
+#endif
+
+/* NaN's require infinity support. */
+#ifdef NANS
+#ifndef INFINITY
+#define INFINITY
+#endif
+#endif
+
+/* This handles 64-bit long ints. */
+#define LONGBITS (8 * sizeof(long))
+
+/* Control register for rounding precision.
+ * This can be set to 80 (if NE=6), 64, 56, 53, or 24 bits.
+ */
+int rndprc = NBITS;
+extern int rndprc;
+
+void eaddm(), esubm(), emdnorm(), asctoeg(), enan();
+static void toe24(), toe53(), toe64(), toe113();
+void eremain(), einit(), eiremain();
+int ecmpm(), edivm(), emulm(), eisneg(), eisinf();
+void emovi(), emovo(), emovz(), ecleaz(), eadd1();
+void etodec(), todec(), dectoe();
+int eisnan(), eiisnan();
+
+
+
+void einit()
+{
+}
+
+/*
+; Clear out entire external format number.
+;
+; unsigned short x[];
+; eclear( x );
+*/
+
+void eclear( x )
+register unsigned short *x;
+{
+register int i;
+
+for( i=0; i<NE; i++ )
+	*x++ = 0;
+}
+
+
+
+/* Move external format number from a to b.
+ *
+ * emov( a, b );
+ */
+
+void emov( a, b )
+register unsigned short *a, *b;
+{
+register int i;
+
+for( i=0; i<NE; i++ )
+	*b++ = *a++;
+}
+
+
+/*
+;	Absolute value of external format number
+;
+;	short x[NE];
+;	eabs( x );
+*/
+
+void eabs(x)
+unsigned short x[];	/* x is the memory address of a short */
+{
+
+x[NE-1] &= 0x7fff; /* sign is top bit of last word of external format */
+}
+
+
+
+
+/*
+;	Negate external format number
+;
+;	unsigned short x[NE];
+;	eneg( x );
+*/
+
+void eneg(x)
+unsigned short x[];
+{
+
+#ifdef NANS
+if( eisnan(x) )
+	return;
+#endif
+x[NE-1] ^= 0x8000; /* Toggle the sign bit */
+}
+
+
+
+/* Return 1 if external format number is negative,
+ * else return zero.
+ */
+int eisneg(x)
+unsigned short x[];
+{
+
+#ifdef NANS
+if( eisnan(x) )
+	return( 0 );
+#endif
+if( x[NE-1] & 0x8000 )
+	return( 1 );
+else
+	return( 0 );
+}
+
+
+/* Return 1 if external format number has maximum possible exponent,
+ * else return zero.
+ */
+int eisinf(x)
+unsigned short x[];
+{
+
+if( (x[NE-1] & 0x7fff) == 0x7fff )
+	{
+#ifdef NANS
+	if( eisnan(x) )
+		return( 0 );
+#endif
+	return( 1 );
+	}
+else
+	return( 0 );
+}
+
+/* Check if e-type number is not a number.
+ */
+int eisnan(x)
+unsigned short x[];
+{
+
+#ifdef NANS
+int i;
+/* NaN has maximum exponent */
+if( (x[NE-1] & 0x7fff) != 0x7fff )
+	return (0);
+/* ... and non-zero significand field. */
+for( i=0; i<NE-1; i++ )
+	{
+	if( *x++ != 0 )
+		return (1);
+	}
+#endif
+return (0);
+}
+
+/*
+; Fill entire number, including exponent and significand, with
+; largest possible number.  These programs implement a saturation
+; value that is an ordinary, legal number.  A special value
+; "infinity" may also be implemented; this would require tests
+; for that value and implementation of special rules for arithmetic
+; operations involving inifinity.
+*/
+
+void einfin(x)
+register unsigned short *x;
+{
+register int i;
+
+#ifdef INFINITY
+for( i=0; i<NE-1; i++ )
+	*x++ = 0;
+*x |= 32767;
+#else
+for( i=0; i<NE-1; i++ )
+	*x++ = 0xffff;
+*x |= 32766;
+if( rndprc < NBITS )
+	{
+	if (rndprc == 113)
+		{
+		*(x - 9) = 0;
+		*(x - 8) = 0;
+		}
+	if( rndprc == 64 )
+		{
+		*(x-5) = 0;
+		}
+	if( rndprc == 53 )
+		{
+		*(x-4) = 0xf800;
+		}
+	else
+		{
+		*(x-4) = 0;
+		*(x-3) = 0;
+		*(x-2) = 0xff00;
+		}
+	}
+#endif
+}
+
+
+
+/* Move in external format number,
+ * converting it to internal format.
+ */
+void emovi( a, b )
+unsigned short *a, *b;
+{
+register unsigned short *p, *q;
+int i;
+
+q = b;
+p = a + (NE-1);	/* point to last word of external number */
+/* get the sign bit */
+if( *p & 0x8000 )
+	*q++ = 0xffff;
+else
+	*q++ = 0;
+/* get the exponent */
+*q = *p--;
+*q++ &= 0x7fff;	/* delete the sign bit */
+#ifdef INFINITY
+if( (*(q-1) & 0x7fff) == 0x7fff )
+	{
+#ifdef NANS
+	if( eisnan(a) )
+		{
+		*q++ = 0;
+		for( i=3; i<NI; i++ )
+			*q++ = *p--;
+		return;
+		}
+#endif
+	for( i=2; i<NI; i++ )
+		*q++ = 0;
+	return;
+	}
+#endif
+/* clear high guard word */
+*q++ = 0;
+/* move in the significand */
+for( i=0; i<NE-1; i++ )
+	*q++ = *p--;
+/* clear low guard word */
+*q = 0;
+}
+
+
+/* Move internal format number out,
+ * converting it to external format.
+ */
+void emovo( a, b )
+unsigned short *a, *b;
+{
+register unsigned short *p, *q;
+unsigned short i;
+
+p = a;
+q = b + (NE-1); /* point to output exponent */
+/* combine sign and exponent */
+i = *p++;
+if( i )
+	*q-- = *p++ | 0x8000;
+else
+	*q-- = *p++;
+#ifdef INFINITY
+if( *(p-1) == 0x7fff )
+	{
+#ifdef NANS
+	if( eiisnan(a) )
+		{
+		enan( b, NBITS );
+		return;
+		}
+#endif
+	einfin(b);
+	return;
+	}
+#endif
+/* skip over guard word */
+++p;
+/* move the significand */
+for( i=0; i<NE-1; i++ )
+	*q-- = *p++;
+}
+
+
+
+
+/* Clear out internal format number.
+ */
+
+void ecleaz( xi )
+register unsigned short *xi;
+{
+register int i;
+
+for( i=0; i<NI; i++ )
+	*xi++ = 0;
+}
+
+/* same, but don't touch the sign. */
+
+void ecleazs( xi )
+register unsigned short *xi;
+{
+register int i;
+
+++xi;
+for(i=0; i<NI-1; i++)
+	*xi++ = 0;
+}
+
+
+
+
+/* Move internal format number from a to b.
+ */
+void emovz( a, b )
+register unsigned short *a, *b;
+{
+register int i;
+
+for( i=0; i<NI-1; i++ )
+	*b++ = *a++;
+/* clear low guard word */
+*b = 0;
+}
+
+/* Return nonzero if internal format number is a NaN.
+ */
+
+int eiisnan (x)
+unsigned short x[];
+{
+int i;
+
+if( (x[E] & 0x7fff) == 0x7fff )
+	{
+	for( i=M+1; i<NI; i++ )
+		{
+		if( x[i] != 0 )
+			return(1);
+		}
+	}
+return(0);
+}
+
+#ifdef INFINITY
+/* Return nonzero if internal format number is infinite. */
+
+static int 
+eiisinf (x)
+     unsigned short x[];
+{
+
+#ifdef NANS
+  if (eiisnan (x))
+    return (0);
+#endif
+  if ((x[E] & 0x7fff) == 0x7fff)
+    return (1);
+  return (0);
+}
+#endif
+
+/*
+;	Compare significands of numbers in internal format.
+;	Guard words are included in the comparison.
+;
+;	unsigned short a[NI], b[NI];
+;	cmpm( a, b );
+;
+;	for the significands:
+;	returns	+1 if a > b
+;		 0 if a == b
+;		-1 if a < b
+*/
+int ecmpm( a, b )
+register unsigned short *a, *b;
+{
+int i;
+
+a += M; /* skip up to significand area */
+b += M;
+for( i=M; i<NI; i++ )
+	{
+	if( *a++ != *b++ )
+		goto difrnt;
+	}
+return(0);
+
+difrnt:
+if( *(--a) > *(--b) )
+	return(1);
+else
+	return(-1);
+}
+
+
+/*
+;	Shift significand down by 1 bit
+*/
+
+void eshdn1(x)
+register unsigned short *x;
+{
+register unsigned short bits;
+int i;
+
+x += M;	/* point to significand area */
+
+bits = 0;
+for( i=M; i<NI; i++ )
+	{
+	if( *x & 1 )
+		bits |= 1;
+	*x >>= 1;
+	if( bits & 2 )
+		*x |= 0x8000;
+	bits <<= 1;
+	++x;
+	}	
+}
+
+
+
+/*
+;	Shift significand up by 1 bit
+*/
+
+void eshup1(x)
+register unsigned short *x;
+{
+register unsigned short bits;
+int i;
+
+x += NI-1;
+bits = 0;
+
+for( i=M; i<NI; i++ )
+	{
+	if( *x & 0x8000 )
+		bits |= 1;
+	*x <<= 1;
+	if( bits & 2 )
+		*x |= 1;
+	bits <<= 1;
+	--x;
+	}
+}
+
+
+
+/*
+;	Shift significand down by 8 bits
+*/
+
+void eshdn8(x)
+register unsigned short *x;
+{
+register unsigned short newbyt, oldbyt;
+int i;
+
+x += M;
+oldbyt = 0;
+for( i=M; i<NI; i++ )
+	{
+	newbyt = *x << 8;
+	*x >>= 8;
+	*x |= oldbyt;
+	oldbyt = newbyt;
+	++x;
+	}
+}
+
+/*
+;	Shift significand up by 8 bits
+*/
+
+void eshup8(x)
+register unsigned short *x;
+{
+int i;
+register unsigned short newbyt, oldbyt;
+
+x += NI-1;
+oldbyt = 0;
+
+for( i=M; i<NI; i++ )
+	{
+	newbyt = *x >> 8;
+	*x <<= 8;
+	*x |= oldbyt;
+	oldbyt = newbyt;
+	--x;
+	}
+}
+
+/*
+;	Shift significand up by 16 bits
+*/
+
+void eshup6(x)
+register unsigned short *x;
+{
+int i;
+register unsigned short *p;
+
+p = x + M;
+x += M + 1;
+
+for( i=M; i<NI-1; i++ )
+	*p++ = *x++;
+
+*p = 0;
+}
+
+/*
+;	Shift significand down by 16 bits
+*/
+
+void eshdn6(x)
+register unsigned short *x;
+{
+int i;
+register unsigned short *p;
+
+x += NI-1;
+p = x + 1;
+
+for( i=M; i<NI-1; i++ )
+	*(--p) = *(--x);
+
+*(--p) = 0;
+}
+
+/*
+;	Add significands
+;	x + y replaces y
+*/
+
+void eaddm( x, y )
+unsigned short *x, *y;
+{
+register unsigned long a;
+int i;
+unsigned int carry;
+
+x += NI-1;
+y += NI-1;
+carry = 0;
+for( i=M; i<NI; i++ )
+	{
+	a = (unsigned long )(*x) + (unsigned long )(*y) + carry;
+	if( a & 0x10000 )
+		carry = 1;
+	else
+		carry = 0;
+	*y = (unsigned short )a;
+	--x;
+	--y;
+	}
+}
+
+/*
+;	Subtract significands
+;	y - x replaces y
+*/
+
+void esubm( x, y )
+unsigned short *x, *y;
+{
+unsigned long a;
+int i;
+unsigned int carry;
+
+x += NI-1;
+y += NI-1;
+carry = 0;
+for( i=M; i<NI; i++ )
+	{
+	a = (unsigned long )(*y) - (unsigned long )(*x) - carry;
+	if( a & 0x10000 )
+		carry = 1;
+	else
+		carry = 0;
+	*y = (unsigned short )a;
+	--x;
+	--y;
+	}
+}
+
+
+/* Divide significands */
+
+static unsigned short equot[NI] = {0}; /* was static */
+
+#if 0
+int edivm( den, num )
+unsigned short den[], num[];
+{
+int i;
+register unsigned short *p, *q;
+unsigned short j;
+
+p = &equot[0];
+*p++ = num[0];
+*p++ = num[1];
+
+for( i=M; i<NI; i++ )
+	{
+	*p++ = 0;
+	}
+
+/* Use faster compare and subtraction if denominator
+ * has only 15 bits of significance.
+ */
+p = &den[M+2];
+if( *p++ == 0 )
+	{
+	for( i=M+3; i<NI; i++ )
+		{
+		if( *p++ != 0 )
+			goto fulldiv;
+		}
+	if( (den[M+1] & 1) != 0 )
+		goto fulldiv;
+	eshdn1(num);
+	eshdn1(den);
+
+	p = &den[M+1];
+	q = &num[M+1];
+
+	for( i=0; i<NBITS+2; i++ )
+		{
+		if( *p <= *q )
+			{
+			*q -= *p;
+			j = 1;
+			}
+		else
+			{
+			j = 0;
+			}
+		eshup1(equot);
+		equot[NI-2] |= j;
+		eshup1(num);
+		}
+	goto divdon;
+	}
+
+/* The number of quotient bits to calculate is
+ * NBITS + 1 scaling guard bit + 1 roundoff bit.
+ */
+fulldiv:
+
+p = &equot[NI-2];
+for( i=0; i<NBITS+2; i++ )
+	{
+	if( ecmpm(den,num) <= 0 )
+		{
+		esubm(den, num);
+		j = 1;	/* quotient bit = 1 */
+		}
+	else
+		j = 0;
+	eshup1(equot);
+	*p |= j;
+	eshup1(num);
+	}
+
+divdon:
+
+eshdn1( equot );
+eshdn1( equot );
+
+/* test for nonzero remainder after roundoff bit */
+p = &num[M];
+j = 0;
+for( i=M; i<NI; i++ )
+	{
+	j |= *p++;
+	}
+if( j )
+	j = 1;
+
+
+for( i=0; i<NI; i++ )
+	num[i] = equot[i];
+return( (int )j );
+}
+
+/* Multiply significands */
+int emulm( a, b )
+unsigned short a[], b[];
+{
+unsigned short *p, *q;
+int i, j, k;
+
+equot[0] = b[0];
+equot[1] = b[1];
+for( i=M; i<NI; i++ )
+	equot[i] = 0;
+
+p = &a[NI-2];
+k = NBITS;
+while( *p == 0 ) /* significand is not supposed to be all zero */
+	{
+	eshdn6(a);
+	k -= 16;
+	}
+if( (*p & 0xff) == 0 )
+	{
+	eshdn8(a);
+	k -= 8;
+	}
+
+q = &equot[NI-1];
+j = 0;
+for( i=0; i<k; i++ )
+	{
+	if( *p & 1 )
+		eaddm(b, equot);
+/* remember if there were any nonzero bits shifted out */
+	if( *q & 1 )
+		j |= 1;
+	eshdn1(a);
+	eshdn1(equot);
+	}
+
+for( i=0; i<NI; i++ )
+	b[i] = equot[i];
+
+/* return flag for lost nonzero bits */
+return(j);
+}
+
+#else
+
+/* Multiply significand of e-type number b
+by 16-bit quantity a, e-type result to c. */
+
+void m16m( a, b, c )
+unsigned short a;
+unsigned short b[], c[];
+{
+register unsigned short *pp;
+register unsigned long carry;
+unsigned short *ps;
+unsigned short p[NI];
+unsigned long aa, m;
+int i;
+
+aa = a;
+pp = &p[NI-2];
+*pp++ = 0;
+*pp = 0;
+ps = &b[NI-1];
+
+for( i=M+1; i<NI; i++ )
+	{
+	if( *ps == 0 )
+		{
+		--ps;
+		--pp;
+		*(pp-1) = 0;
+		}
+	else
+		{
+		m = (unsigned long) aa * *ps--;
+		carry = (m & 0xffff) + *pp;
+		*pp-- = (unsigned short )carry;
+		carry = (carry >> 16) + (m >> 16) + *pp;
+		*pp = (unsigned short )carry;
+		*(pp-1) = carry >> 16;
+		}
+	}
+for( i=M; i<NI; i++ )
+	c[i] = p[i];
+}
+
+
+/* Divide significands. Neither the numerator nor the denominator
+is permitted to have its high guard word nonzero.  */
+
+
+int edivm( den, num )
+unsigned short den[], num[];
+{
+int i;
+register unsigned short *p;
+unsigned long tnum;
+unsigned short j, tdenm, tquot;
+unsigned short tprod[NI+1];
+
+p = &equot[0];
+*p++ = num[0];
+*p++ = num[1];
+
+for( i=M; i<NI; i++ )
+	{
+	*p++ = 0;
+	}
+eshdn1( num );
+tdenm = den[M+1];
+for( i=M; i<NI; i++ )
+	{
+	/* Find trial quotient digit (the radix is 65536). */
+	tnum = (((unsigned long) num[M]) << 16) + num[M+1];
+
+	/* Do not execute the divide instruction if it will overflow. */
+        if( (tdenm * 0xffffL) < tnum )
+		tquot = 0xffff;
+	else
+		tquot = tnum / tdenm;
+
+		/* Prove that the divide worked. */
+/*
+	tcheck = (unsigned long )tquot * tdenm;
+	if( tnum - tcheck > tdenm )
+		tquot = 0xffff;
+*/
+	/* Multiply denominator by trial quotient digit. */
+	m16m( tquot, den, tprod );
+	/* The quotient digit may have been overestimated. */
+	if( ecmpm( tprod, num ) > 0 )
+		{
+		tquot -= 1;
+		esubm( den, tprod );
+		if( ecmpm( tprod, num ) > 0 )
+			{
+			tquot -= 1;
+			esubm( den, tprod );
+			}
+		}
+/*
+	if( ecmpm( tprod, num ) > 0 )
+		{
+		eshow( "tprod", tprod );
+		eshow( "num  ", num );
+		printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
+			 tnum, den[M+1], tquot );
+		}
+*/
+	esubm( tprod, num );
+/*
+	if( ecmpm( num, den ) >= 0 )
+		{
+		eshow( "num  ", num );
+		eshow( "den  ", den );
+		printf( "tnum = %08lx, tden = %04x, tquot = %04x\n",
+			 tnum, den[M+1], tquot );
+		}
+*/
+	equot[i] = tquot;
+	eshup6(num);
+	}
+/* test for nonzero remainder after roundoff bit */
+p = &num[M];
+j = 0;
+for( i=M; i<NI; i++ )
+	{
+	j |= *p++;
+	}
+if( j )
+	j = 1;
+
+for( i=0; i<NI; i++ )
+	num[i] = equot[i];
+
+return( (int )j );
+}
+
+
+
+/* Multiply significands */
+int emulm( a, b )
+unsigned short a[], b[];
+{
+unsigned short *p, *q;
+unsigned short pprod[NI];
+unsigned short j;
+int i;
+
+equot[0] = b[0];
+equot[1] = b[1];
+for( i=M; i<NI; i++ )
+	equot[i] = 0;
+
+j = 0;
+p = &a[NI-1];
+q = &equot[NI-1];
+for( i=M+1; i<NI; i++ )
+	{
+	if( *p == 0 )
+		{
+		--p;
+		}
+	else
+		{
+		m16m( *p--, b, pprod );
+		eaddm(pprod, equot);
+		}
+	j |= *q;
+	eshdn6(equot);
+	}
+
+for( i=0; i<NI; i++ )
+	b[i] = equot[i];
+
+/* return flag for lost nonzero bits */
+return( (int)j );
+}
+
+
+/*
+eshow(str, x)
+char *str;
+unsigned short *x;
+{
+int i;
+
+printf( "%s ", str );
+for( i=0; i<NI; i++ )
+	printf( "%04x ", *x++ );
+printf( "\n" );
+}
+*/
+#endif
+
+
+
+/*
+ * Normalize and round off.
+ *
+ * The internal format number to be rounded is "s".
+ * Input "lost" indicates whether the number is exact.
+ * This is the so-called sticky bit.
+ *
+ * Input "subflg" indicates whether the number was obtained
+ * by a subtraction operation.  In that case if lost is nonzero
+ * then the number is slightly smaller than indicated.
+ *
+ * Input "exp" is the biased exponent, which may be negative.
+ * the exponent field of "s" is ignored but is replaced by
+ * "exp" as adjusted by normalization and rounding.
+ *
+ * Input "rcntrl" is the rounding control.
+ */
+
+static int rlast = -1;
+static int rw = 0;
+static unsigned short rmsk = 0;
+static unsigned short rmbit = 0;
+static unsigned short rebit = 0;
+static int re = 0;
+static unsigned short rbit[NI] = {0,0,0,0,0,0,0,0};
+
+void emdnorm( s, lost, subflg, exp, rcntrl )
+unsigned short s[];
+int lost;
+int subflg;
+long exp;
+int rcntrl;
+{
+int i, j;
+unsigned short r;
+
+/* Normalize */
+j = enormlz( s );
+
+/* a blank significand could mean either zero or infinity. */
+#ifndef INFINITY
+if( j > NBITS )
+	{
+	ecleazs( s );
+	return;
+	}
+#endif
+exp -= j;
+#ifndef INFINITY
+if( exp >= 32767L )
+	goto overf;
+#else
+if( (j > NBITS) && (exp < 32767L) )
+	{
+	ecleazs( s );
+	return;
+	}
+#endif
+if( exp < 0L )
+	{
+	if( exp > (long )(-NBITS-1) )
+		{
+		j = (int )exp;
+		i = eshift( s, j );
+		if( i )
+			lost = 1;
+		}
+	else
+		{
+		ecleazs( s );
+		return;
+		}
+	}
+/* Round off, unless told not to by rcntrl. */
+if( rcntrl == 0 )
+	goto mdfin;
+/* Set up rounding parameters if the control register changed. */
+if( rndprc != rlast )
+	{
+	ecleaz( rbit );
+	switch( rndprc )
+		{
+		default:
+		case NBITS:
+			rw = NI-1; /* low guard word */
+			rmsk = 0xffff;
+			rmbit = 0x8000;
+			rebit = 1;
+			re = rw - 1;
+			break;
+		case 113:
+			rw = 10;
+			rmsk = 0x7fff;
+			rmbit = 0x4000;
+			rebit = 0x8000;
+			re = rw;
+			break;
+		case 64:
+			rw = 7;
+			rmsk = 0xffff;
+			rmbit = 0x8000;
+			rebit = 1;
+			re = rw-1;
+			break;
+/* For DEC arithmetic */
+		case 56:
+			rw = 6;
+			rmsk = 0xff;
+			rmbit = 0x80;
+			rebit = 0x100;
+			re = rw;
+			break;
+		case 53:
+			rw = 6;
+			rmsk = 0x7ff;
+			rmbit = 0x0400;
+			rebit = 0x800;
+			re = rw;
+			break;
+		case 24:
+			rw = 4;
+			rmsk = 0xff;
+			rmbit = 0x80;
+			rebit = 0x100;
+			re = rw;
+			break;
+		}
+	rbit[re] = rebit;
+	rlast = rndprc;
+	}
+
+/* Shift down 1 temporarily if the data structure has an implied
+ * most significant bit and the number is denormal.
+ * For rndprc = 64 or NBITS, there is no implied bit.
+ * But Intel long double denormals lose one bit of significance even so.
+ */
+#if IBMPC
+if( (exp <= 0) && (rndprc != NBITS) )
+#else
+if( (exp <= 0) && (rndprc != 64) && (rndprc != NBITS) )
+#endif
+	{
+	lost |= s[NI-1] & 1;
+	eshdn1(s);
+	}
+/* Clear out all bits below the rounding bit,
+ * remembering in r if any were nonzero.
+ */
+r = s[rw] & rmsk;
+if( rndprc < NBITS )
+	{
+	i = rw + 1;
+	while( i < NI )
+		{
+		if( s[i] )
+			r |= 1;
+		s[i] = 0;
+		++i;
+		}
+	}
+s[rw] &= ~rmsk;
+if( (r & rmbit) != 0 )
+	{
+	if( r == rmbit )
+		{
+		if( lost == 0 )
+			{ /* round to even */
+			if( (s[re] & rebit) == 0 )
+				goto mddone;
+			}
+		else
+			{
+			if( subflg != 0 )
+				goto mddone;
+			}
+		}
+	eaddm( rbit, s );
+	}
+mddone:
+#if IBMPC
+if( (exp <= 0) && (rndprc != NBITS) )
+#else
+if( (exp <= 0) && (rndprc != 64) && (rndprc != NBITS) )
+#endif
+	{
+	eshup1(s);
+	}
+if( s[2] != 0 )
+	{ /* overflow on roundoff */
+	eshdn1(s);
+	exp += 1;
+	}
+mdfin:
+s[NI-1] = 0;
+if( exp >= 32767L )
+	{
+#ifndef INFINITY
+overf:
+#endif
+#ifdef INFINITY
+	s[1] = 32767;
+	for( i=2; i<NI-1; i++ )
+		s[i] = 0;
+#else
+	s[1] = 32766;
+	s[2] = 0;
+	for( i=M+1; i<NI-1; i++ )
+		s[i] = 0xffff;
+	s[NI-1] = 0;
+	if( (rndprc < 64) || (rndprc == 113) )
+		{
+		s[rw] &= ~rmsk;
+		if( rndprc == 24 )
+			{
+			s[5] = 0;
+			s[6] = 0;
+			}
+		}
+#endif
+	return;
+	}
+if( exp < 0 )
+	s[1] = 0;
+else
+	s[1] = (unsigned short )exp;
+}
+
+
+
+/*
+;	Subtract external format numbers.
+;
+;	unsigned short a[NE], b[NE], c[NE];
+;	esub( a, b, c );	 c = b - a
+*/
+
+static int subflg = 0;
+
+void esub( a, b, c )
+unsigned short *a, *b, *c;
+{
+
+#ifdef NANS
+if( eisnan(a) )
+	{
+	emov (a, c);
+	return;
+	}
+if( eisnan(b) )
+	{
+	emov(b,c);
+	return;
+	}
+/* Infinity minus infinity is a NaN.
+ * Test for subtracting infinities of the same sign.
+ */
+if( eisinf(a) && eisinf(b) && ((eisneg (a) ^ eisneg (b)) == 0))
+	{
+	mtherr( "esub", DOMAIN );
+	enan( c, NBITS );
+	return;
+	}
+#endif
+subflg = 1;
+eadd1( a, b, c );
+}
+
+
+/*
+;	Add.
+;
+;	unsigned short a[NE], b[NE], c[NE];
+;	eadd( a, b, c );	 c = b + a
+*/
+void eadd( a, b, c )
+unsigned short *a, *b, *c;
+{
+
+#ifdef NANS
+/* NaN plus anything is a NaN. */
+if( eisnan(a) )
+	{
+	emov(a,c);
+	return;
+	}
+if( eisnan(b) )
+	{
+	emov(b,c);
+	return;
+	}
+/* Infinity minus infinity is a NaN.
+ * Test for adding infinities of opposite signs.
+ */
+if( eisinf(a) && eisinf(b)
+	&& ((eisneg(a) ^ eisneg(b)) != 0) )
+	{
+	mtherr( "eadd", DOMAIN );
+	enan( c, NBITS );
+	return;
+	}
+#endif
+subflg = 0;
+eadd1( a, b, c );
+}
+
+void eadd1( a, b, c )
+unsigned short *a, *b, *c;
+{
+unsigned short ai[NI], bi[NI], ci[NI];
+int i, lost, j, k;
+long lt, lta, ltb;
+
+#ifdef INFINITY
+if( eisinf(a) )
+	{
+	emov(a,c);
+	if( subflg )
+		eneg(c);
+	return;
+	}
+if( eisinf(b) )
+	{
+	emov(b,c);
+	return;
+	}
+#endif
+emovi( a, ai );
+emovi( b, bi );
+if( subflg )
+	ai[0] = ~ai[0];
+
+/* compare exponents */
+lta = ai[E];
+ltb = bi[E];
+lt = lta - ltb;
+if( lt > 0L )
+	{	/* put the larger number in bi */
+	emovz( bi, ci );
+	emovz( ai, bi );
+	emovz( ci, ai );
+	ltb = bi[E];
+	lt = -lt;
+	}
+lost = 0;
+if( lt != 0L )
+	{
+	if( lt < (long )(-NBITS-1) )
+		goto done;	/* answer same as larger addend */
+	k = (int )lt;
+	lost = eshift( ai, k ); /* shift the smaller number down */
+	}
+else
+	{
+/* exponents were the same, so must compare significands */
+	i = ecmpm( ai, bi );
+	if( i == 0 )
+		{ /* the numbers are identical in magnitude */
+		/* if different signs, result is zero */
+		if( ai[0] != bi[0] )
+			{
+			eclear(c);
+			return;
+			}
+		/* if same sign, result is double */
+		/* double denomalized tiny number */
+		if( (bi[E] == 0) && ((bi[3] & 0x8000) == 0) )
+			{
+			eshup1( bi );
+			goto done;
+			}
+		/* add 1 to exponent unless both are zero! */
+		for( j=1; j<NI-1; j++ )
+			{
+			if( bi[j] != 0 )
+				{
+/* This could overflow, but let emovo take care of that. */
+				ltb += 1;
+				break;
+				}
+			}
+		bi[E] = (unsigned short )ltb;
+		goto done;
+		}
+	if( i > 0 )
+		{	/* put the larger number in bi */
+		emovz( bi, ci );
+		emovz( ai, bi );
+		emovz( ci, ai );
+		}
+	}
+if( ai[0] == bi[0] )
+	{
+	eaddm( ai, bi );
+	subflg = 0;
+	}
+else
+	{
+	esubm( ai, bi );
+	subflg = 1;
+	}
+emdnorm( bi, lost, subflg, ltb, 64 );
+
+done:
+emovo( bi, c );
+}
+
+
+
+/*
+;	Divide.
+;
+;	unsigned short a[NE], b[NE], c[NE];
+;	ediv( a, b, c );	c = b / a
+*/
+void ediv( a, b, c )
+unsigned short *a, *b, *c;
+{
+unsigned short ai[NI], bi[NI];
+int i;
+long lt, lta, ltb;
+
+#ifdef NANS
+/* Return any NaN input. */
+if( eisnan(a) )
+	{
+	emov(a,c);
+	return;
+	}
+if( eisnan(b) )
+	{
+	emov(b,c);
+	return;
+	}
+/* Zero over zero, or infinity over infinity, is a NaN. */
+if( ((ecmp(a,ezero) == 0) && (ecmp(b,ezero) == 0))
+	|| (eisinf (a) && eisinf (b)) )
+	{
+	mtherr( "ediv", DOMAIN );
+	enan( c, NBITS );
+	return;
+	}
+#endif
+/* Infinity over anything else is infinity. */
+#ifdef INFINITY
+if( eisinf(b) )
+	{
+	if( eisneg(a) ^ eisneg(b) )
+		*(c+(NE-1)) = 0x8000;
+	else
+		*(c+(NE-1)) = 0;
+	einfin(c);
+	return;
+	}
+if( eisinf(a) )
+	{
+	eclear(c);
+	return;
+	}
+#endif
+emovi( a, ai );
+emovi( b, bi );
+lta = ai[E];
+ltb = bi[E];
+if( bi[E] == 0 )
+	{ /* See if numerator is zero. */
+	for( i=1; i<NI-1; i++ )
+		{
+		if( bi[i] != 0 )
+			{
+			ltb -= enormlz( bi );
+			goto dnzro1;
+			}
+		}
+	eclear(c);
+	return;
+	}
+dnzro1:
+
+if( ai[E] == 0 )
+	{	/* possible divide by zero */
+	for( i=1; i<NI-1; i++ )
+		{
+		if( ai[i] != 0 )
+			{
+			lta -= enormlz( ai );
+			goto dnzro2;
+			}
+		}
+	if( ai[0] == bi[0] )
+		*(c+(NE-1)) = 0;
+	else
+		*(c+(NE-1)) = 0x8000;
+	einfin(c);
+	mtherr( "ediv", SING );
+	return;
+	}
+dnzro2:
+
+i = edivm( ai, bi );
+/* calculate exponent */
+lt = ltb - lta + EXONE;
+emdnorm( bi, i, 0, lt, 64 );
+/* set the sign */
+if( ai[0] == bi[0] )
+	bi[0] = 0;
+else
+	bi[0] = 0Xffff;
+emovo( bi, c );
+}
+
+
+
+/*
+;	Multiply.
+;
+;	unsigned short a[NE], b[NE], c[NE];
+;	emul( a, b, c );	c = b * a
+*/
+void emul( a, b, c )
+unsigned short *a, *b, *c;
+{
+unsigned short ai[NI], bi[NI];
+int i, j;
+long lt, lta, ltb;
+
+#ifdef NANS
+/* NaN times anything is the same NaN. */
+if( eisnan(a) )
+	{
+	emov(a,c);
+	return;
+	}
+if( eisnan(b) )
+	{
+	emov(b,c);
+	return;
+	}
+/* Zero times infinity is a NaN. */
+if( (eisinf(a) && (ecmp(b,ezero) == 0))
+	|| (eisinf(b) && (ecmp(a,ezero) == 0)) )
+	{
+	mtherr( "emul", DOMAIN );
+	enan( c, NBITS );
+	return;
+	}
+#endif
+/* Infinity times anything else is infinity. */
+#ifdef INFINITY
+if( eisinf(a) || eisinf(b) )
+	{
+	if( eisneg(a) ^ eisneg(b) )
+		*(c+(NE-1)) = 0x8000;
+	else
+		*(c+(NE-1)) = 0;
+	einfin(c);
+	return;
+	}
+#endif
+emovi( a, ai );
+emovi( b, bi );
+lta = ai[E];
+ltb = bi[E];
+if( ai[E] == 0 )
+	{
+	for( i=1; i<NI-1; i++ )
+		{
+		if( ai[i] != 0 )
+			{
+			lta -= enormlz( ai );
+			goto mnzer1;
+			}
+		}
+	eclear(c);
+	return;
+	}
+mnzer1:
+
+if( bi[E] == 0 )
+	{
+	for( i=1; i<NI-1; i++ )
+		{
+		if( bi[i] != 0 )
+			{
+			ltb -= enormlz( bi );
+			goto mnzer2;
+			}
+		}
+	eclear(c);
+	return;
+	}
+mnzer2:
+
+/* Multiply significands */
+j = emulm( ai, bi );
+/* calculate exponent */
+lt = lta + ltb - (EXONE - 1);
+emdnorm( bi, j, 0, lt, 64 );
+/* calculate sign of product */
+if( ai[0] == bi[0] )
+	bi[0] = 0;
+else
+	bi[0] = 0xffff;
+emovo( bi, c );
+}
+
+
+
+
+/*
+; Convert IEEE double precision to e type
+;	double d;
+;	unsigned short x[N+2];
+;	e53toe( &d, x );
+*/
+void e53toe( pe, y )
+unsigned short *pe, *y;
+{
+#ifdef DEC
+
+dectoe( pe, y ); /* see etodec.c */
+
+#else
+
+register unsigned short r;
+register unsigned short *p, *e;
+unsigned short yy[NI];
+int denorm, k;
+
+e = pe;
+denorm = 0;	/* flag if denormalized number */
+ecleaz(yy);
+#ifdef IBMPC
+e += 3;
+#endif
+r = *e;
+yy[0] = 0;
+if( r & 0x8000 )
+	yy[0] = 0xffff;
+yy[M] = (r & 0x0f) | 0x10;
+r &= ~0x800f;	/* strip sign and 4 significand bits */
+#ifdef INFINITY
+if( r == 0x7ff0 )
+	{
+#ifdef NANS
+#ifdef IBMPC
+	if( ((pe[3] & 0xf) != 0) || (pe[2] != 0)
+		|| (pe[1] != 0) || (pe[0] != 0) )
+		{
+		enan( y, NBITS );
+		return;
+		}
+#else
+	if( ((pe[0] & 0xf) != 0) || (pe[1] != 0)
+		 || (pe[2] != 0) || (pe[3] != 0) )
+		{
+		enan( y, NBITS );
+		return;
+		}
+#endif
+#endif  /* NANS */
+	eclear( y );
+	einfin( y );
+	if( yy[0] )
+		eneg(y);
+	return;
+	}
+#endif
+r >>= 4;
+/* If zero exponent, then the significand is denormalized.
+ * So, take back the understood high significand bit. */ 
+if( r == 0 )
+	{
+	denorm = 1;
+	yy[M] &= ~0x10;
+	}
+r += EXONE - 01777;
+yy[E] = r;
+p = &yy[M+1];
+#ifdef IBMPC
+*p++ = *(--e);
+*p++ = *(--e);
+*p++ = *(--e);
+#endif
+#ifdef MIEEE
+++e;
+*p++ = *e++;
+*p++ = *e++;
+*p++ = *e++;
+#endif
+(void )eshift( yy, -5 );
+if( denorm )
+	{ /* if zero exponent, then normalize the significand */
+	if( (k = enormlz(yy)) > NBITS )
+		ecleazs(yy);
+	else
+		yy[E] -= (unsigned short )(k-1);
+	}
+emovo( yy, y );
+#endif /* not DEC */
+}
+
+void e64toe( pe, y )
+unsigned short *pe, *y;
+{
+unsigned short yy[NI];
+unsigned short *p, *q, *e;
+int i;
+
+e = pe;
+p = yy;
+for( i=0; i<NE-5; i++ )
+	*p++ = 0;
+#ifdef IBMPC
+for( i=0; i<5; i++ )
+	*p++ = *e++;
+#endif
+#ifdef DEC
+for( i=0; i<5; i++ )
+	*p++ = *e++;
+#endif
+#ifdef MIEEE
+p = &yy[0] + (NE-1);
+*p-- = *e++;
+++e;
+for( i=0; i<4; i++ )
+	*p-- = *e++;
+#endif
+
+#ifdef IBMPC
+/* For Intel long double, shift denormal significand up 1
+   -- but only if the top significand bit is zero.  */
+if((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
+  {
+    unsigned short temp[NI+1];
+    emovi(yy, temp);
+    eshup1(temp);
+    emovo(temp,y);
+    return;
+  }
+#endif
+#ifdef INFINITY
+/* Point to the exponent field.  */
+p = &yy[NE-1];
+if( *p == 0x7fff )
+	{
+#ifdef NANS
+#ifdef IBMPC
+	for( i=0; i<4; i++ )
+		{
+		if((i != 3 && pe[i] != 0)
+		   /* Check for Intel long double infinity pattern.  */
+		   || (i == 3 && pe[i] != 0x8000))
+			{
+			enan( y, NBITS );
+			return;
+			}
+		}
+#else
+	for( i=1; i<=4; i++ )
+		{
+		if( pe[i] != 0 )
+			{
+			enan( y, NBITS );
+			return;
+			}
+		}
+#endif
+#endif /* NANS */
+	eclear( y );
+	einfin( y );
+	if( *p & 0x8000 )
+		eneg(y);
+	return;
+	}
+#endif
+p = yy;
+q = y;
+for( i=0; i<NE; i++ )
+	*q++ = *p++;
+}
+
+void e113toe(pe,y)
+unsigned short *pe, *y;
+{
+register unsigned short r;
+unsigned short *e, *p;
+unsigned short yy[NI];
+int denorm, i;
+
+e = pe;
+denorm = 0;
+ecleaz(yy);
+#ifdef IBMPC
+e += 7;
+#endif
+r = *e;
+yy[0] = 0;
+if( r & 0x8000 )
+	yy[0] = 0xffff;
+r &= 0x7fff;
+#ifdef INFINITY
+if( r == 0x7fff )
+	{
+#ifdef NANS
+#ifdef IBMPC
+	for( i=0; i<7; i++ )
+		{
+		if( pe[i] != 0 )
+			{
+			enan( y, NBITS );
+			return;
+			}
+		}
+#else
+	for( i=1; i<8; i++ )
+		{
+		if( pe[i] != 0 )
+			{
+			enan( y, NBITS );
+			return;
+			}
+		}
+#endif
+#endif /* NANS */
+	eclear( y );
+	einfin( y );
+	if( *e & 0x8000 )
+		eneg(y);
+	return;
+	}
+#endif  /* INFINITY */
+yy[E] = r;
+p = &yy[M + 1];
+#ifdef IBMPC
+for( i=0; i<7; i++ )
+	*p++ = *(--e);
+#endif
+#ifdef MIEEE
+++e;
+for( i=0; i<7; i++ )
+	*p++ = *e++;
+#endif
+/* If denormal, remove the implied bit; else shift down 1. */
+if( r == 0 )
+	{
+	yy[M] = 0;
+	}
+else
+	{
+	yy[M] = 1;
+	eshift( yy, -1 );
+	}
+emovo(yy,y);
+}
+
+
+/*
+; Convert IEEE single precision to e type
+;	float d;
+;	unsigned short x[N+2];
+;	dtox( &d, x );
+*/
+void e24toe( pe, y )
+unsigned short *pe, *y;
+{
+register unsigned short r;
+register unsigned short *p, *e;
+unsigned short yy[NI];
+int denorm, k;
+
+e = pe;
+denorm = 0;	/* flag if denormalized number */
+ecleaz(yy);
+#ifdef IBMPC
+e += 1;
+#endif
+#ifdef DEC
+e += 1;
+#endif
+r = *e;
+yy[0] = 0;
+if( r & 0x8000 )
+	yy[0] = 0xffff;
+yy[M] = (r & 0x7f) | 0200;
+r &= ~0x807f;	/* strip sign and 7 significand bits */
+#ifdef INFINITY
+if( r == 0x7f80 )
+	{
+#ifdef NANS
+#ifdef MIEEE
+	if( ((pe[0] & 0x7f) != 0) || (pe[1] != 0) )
+		{
+		enan( y, NBITS );
+		return;
+		}
+#else
+	if( ((pe[1] & 0x7f) != 0) || (pe[0] != 0) )
+		{
+		enan( y, NBITS );
+		return;
+		}
+#endif
+#endif  /* NANS */
+	eclear( y );
+	einfin( y );
+	if( yy[0] )
+		eneg(y);
+	return;
+	}
+#endif
+r >>= 7;
+/* If zero exponent, then the significand is denormalized.
+ * So, take back the understood high significand bit. */ 
+if( r == 0 )
+	{
+	denorm = 1;
+	yy[M] &= ~0200;
+	}
+r += EXONE - 0177;
+yy[E] = r;
+p = &yy[M+1];
+#ifdef IBMPC
+*p++ = *(--e);
+#endif
+#ifdef DEC
+*p++ = *(--e);
+#endif
+#ifdef MIEEE
+++e;
+*p++ = *e++;
+#endif
+(void )eshift( yy, -8 );
+if( denorm )
+	{ /* if zero exponent, then normalize the significand */
+	if( (k = enormlz(yy)) > NBITS )
+		ecleazs(yy);
+	else
+		yy[E] -= (unsigned short )(k-1);
+	}
+emovo( yy, y );
+}
+
+void etoe113(x,e)
+unsigned short *x, *e;
+{
+unsigned short xi[NI];
+long exp;
+int rndsav;
+
+#ifdef NANS
+if( eisnan(x) )
+	{
+	enan( e, 113 );
+	return;
+	}
+#endif
+emovi( x, xi );
+exp = (long )xi[E];
+#ifdef INFINITY
+if( eisinf(x) )
+	goto nonorm;
+#endif
+/* round off to nearest or even */
+rndsav = rndprc;
+rndprc = 113;
+emdnorm( xi, 0, 0, exp, 64 );
+rndprc = rndsav;
+nonorm:
+toe113 (xi, e);
+}
+
+/* move out internal format to ieee long double */
+static void toe113(a,b)
+unsigned short *a, *b;
+{
+register unsigned short *p, *q;
+unsigned short i;
+
+#ifdef NANS
+if( eiisnan(a) )
+	{
+	enan( b, 113 );
+	return;
+	}
+#endif
+p = a;
+#ifdef MIEEE
+q = b;
+#else
+q = b + 7;			/* point to output exponent */
+#endif
+
+/* If not denormal, delete the implied bit. */
+if( a[E] != 0 )
+	{
+	eshup1 (a);
+	}
+/* combine sign and exponent */
+i = *p++;
+#ifdef MIEEE
+if( i )
+	*q++ = *p++ | 0x8000;
+else
+	*q++ = *p++;
+#else
+if( i )
+	*q-- = *p++ | 0x8000;
+else
+	*q-- = *p++;
+#endif
+/* skip over guard word */
+++p;
+/* move the significand */
+#ifdef MIEEE
+for (i = 0; i < 7; i++)
+	*q++ = *p++;
+#else
+for (i = 0; i < 7; i++)
+	*q-- = *p++;
+#endif
+}
+
+
+void etoe64( x, e )
+unsigned short *x, *e;
+{
+unsigned short xi[NI];
+long exp;
+int rndsav;
+
+#ifdef NANS
+if( eisnan(x) )
+	{
+	enan( e, 64 );
+	return;
+	}
+#endif
+emovi( x, xi );
+exp = (long )xi[E]; /* adjust exponent for offset */
+#ifdef INFINITY
+if( eisinf(x) )
+	goto nonorm;
+#endif
+/* round off to nearest or even */
+rndsav = rndprc;
+rndprc = 64;
+emdnorm( xi, 0, 0, exp, 64 );
+rndprc = rndsav;
+nonorm:
+toe64( xi, e );
+}
+
+/* move out internal format to ieee long double */
+static void toe64( a, b )
+unsigned short *a, *b;
+{
+register unsigned short *p, *q;
+unsigned short i;
+
+#ifdef NANS
+if( eiisnan(a) )
+	{
+	enan( b, 64 );
+	return;
+	}
+#endif
+#ifdef IBMPC
+/* Shift Intel denormal significand down 1.  */
+if( a[E] == 0 )
+  eshdn1(a);
+#endif
+p = a;
+#ifdef MIEEE
+q = b;
+#else
+q = b + 4; /* point to output exponent */
+#if 1
+/* NOTE: if data type is 96 bits wide, clear the last word here. */
+*(q+1)= 0;
+#endif
+#endif
+
+/* combine sign and exponent */
+i = *p++;
+#ifdef MIEEE
+if( i )
+	*q++ = *p++ | 0x8000;
+else
+	*q++ = *p++;
+*q++ = 0;
+#else
+if( i )
+	*q-- = *p++ | 0x8000;
+else
+	*q-- = *p++;
+#endif
+/* skip over guard word */
+++p;
+/* move the significand */
+#ifdef MIEEE
+for( i=0; i<4; i++ )
+	*q++ = *p++;
+#else
+#ifdef INFINITY
+if (eiisinf (a))
+        {
+	/* Intel long double infinity.  */
+	*q-- = 0x8000;
+	*q-- = 0;
+	*q-- = 0;
+	*q = 0;
+	return;
+	}
+#endif
+for( i=0; i<4; i++ )
+	*q-- = *p++;
+#endif
+}
+
+
+/*
+; e type to IEEE double precision
+;	double d;
+;	unsigned short x[NE];
+;	etoe53( x, &d );
+*/
+
+#ifdef DEC
+
+void etoe53( x, e )
+unsigned short *x, *e;
+{
+etodec( x, e ); /* see etodec.c */
+}
+
+static void toe53( x, y )
+unsigned short *x, *y;
+{
+todec( x, y );
+}
+
+#else
+
+void etoe53( x, e )
+unsigned short *x, *e;
+{
+unsigned short xi[NI];
+long exp;
+int rndsav;
+
+#ifdef NANS
+if( eisnan(x) )
+	{
+	enan( e, 53 );
+	return;
+	}
+#endif
+emovi( x, xi );
+exp = (long )xi[E] - (EXONE - 0x3ff); /* adjust exponent for offsets */
+#ifdef INFINITY
+if( eisinf(x) )
+	goto nonorm;
+#endif
+/* round off to nearest or even */
+rndsav = rndprc;
+rndprc = 53;
+emdnorm( xi, 0, 0, exp, 64 );
+rndprc = rndsav;
+nonorm:
+toe53( xi, e );
+}
+
+
+static void toe53( x, y )
+unsigned short *x, *y;
+{
+unsigned short i;
+unsigned short *p;
+
+
+#ifdef NANS
+if( eiisnan(x) )
+	{
+	enan( y, 53 );
+	return;
+	}
+#endif
+p = &x[0];
+#ifdef IBMPC
+y += 3;
+#endif
+*y = 0;	/* output high order */
+if( *p++ )
+	*y = 0x8000;	/* output sign bit */
+
+i = *p++;
+if( i >= (unsigned int )2047 )
+	{	/* Saturate at largest number less than infinity. */
+#ifdef INFINITY
+	*y |= 0x7ff0;
+#ifdef IBMPC
+	*(--y) = 0;
+	*(--y) = 0;
+	*(--y) = 0;
+#endif
+#ifdef MIEEE
+	++y;
+	*y++ = 0;
+	*y++ = 0;
+	*y++ = 0;
+#endif
+#else
+	*y |= (unsigned short )0x7fef;
+#ifdef IBMPC
+	*(--y) = 0xffff;
+	*(--y) = 0xffff;
+	*(--y) = 0xffff;
+#endif
+#ifdef MIEEE
+	++y;
+	*y++ = 0xffff;
+	*y++ = 0xffff;
+	*y++ = 0xffff;
+#endif
+#endif
+	return;
+	}
+if( i == 0 )
+	{
+	(void )eshift( x, 4 );
+	}
+else
+	{
+	i <<= 4;
+	(void )eshift( x, 5 );
+	}
+i |= *p++ & (unsigned short )0x0f;	/* *p = xi[M] */
+*y |= (unsigned short )i; /* high order output already has sign bit set */
+#ifdef IBMPC
+*(--y) = *p++;
+*(--y) = *p++;
+*(--y) = *p;
+#endif
+#ifdef MIEEE
+++y;
+*y++ = *p++;
+*y++ = *p++;
+*y++ = *p++;
+#endif
+}
+
+#endif /* not DEC */
+
+
+
+/*
+; e type to IEEE single precision
+;	float d;
+;	unsigned short x[N+2];
+;	xtod( x, &d );
+*/
+void etoe24( x, e )
+unsigned short *x, *e;
+{
+long exp;
+unsigned short xi[NI];
+int rndsav;
+
+#ifdef NANS
+if( eisnan(x) )
+	{
+	enan( e, 24 );
+	return;
+	}
+#endif
+emovi( x, xi );
+exp = (long )xi[E] - (EXONE - 0177); /* adjust exponent for offsets */
+#ifdef INFINITY
+if( eisinf(x) )
+	goto nonorm;
+#endif
+/* round off to nearest or even */
+rndsav = rndprc;
+rndprc = 24;
+emdnorm( xi, 0, 0, exp, 64 );
+rndprc = rndsav;
+nonorm:
+toe24( xi, e );
+}
+
+static void toe24( x, y )
+unsigned short *x, *y;
+{
+unsigned short i;
+unsigned short *p;
+
+#ifdef NANS
+if( eiisnan(x) )
+	{
+	enan( y, 24 );
+	return;
+	}
+#endif
+p = &x[0];
+#ifdef IBMPC
+y += 1;
+#endif
+#ifdef DEC
+y += 1;
+#endif
+*y = 0;	/* output high order */
+if( *p++ )
+	*y = 0x8000;	/* output sign bit */
+
+i = *p++;
+if( i >= 255 )
+	{	/* Saturate at largest number less than infinity. */
+#ifdef INFINITY
+	*y |= (unsigned short )0x7f80;
+#ifdef IBMPC
+	*(--y) = 0;
+#endif
+#ifdef DEC
+	*(--y) = 0;
+#endif
+#ifdef MIEEE
+	++y;
+	*y = 0;
+#endif
+#else
+	*y |= (unsigned short )0x7f7f;
+#ifdef IBMPC
+	*(--y) = 0xffff;
+#endif
+#ifdef DEC
+	*(--y) = 0xffff;
+#endif
+#ifdef MIEEE
+	++y;
+	*y = 0xffff;
+#endif
+#endif
+	return;
+	}
+if( i == 0 )
+	{
+	(void )eshift( x, 7 );
+	}
+else
+	{
+	i <<= 7;
+	(void )eshift( x, 8 );
+	}
+i |= *p++ & (unsigned short )0x7f;	/* *p = xi[M] */
+*y |= i;	/* high order output already has sign bit set */
+#ifdef IBMPC
+*(--y) = *p;
+#endif
+#ifdef DEC
+*(--y) = *p;
+#endif
+#ifdef MIEEE
+++y;
+*y = *p;
+#endif
+}
+
+
+/* Compare two e type numbers.
+ *
+ * unsigned short a[NE], b[NE];
+ * ecmp( a, b );
+ *
+ *  returns +1 if a > b
+ *           0 if a == b
+ *          -1 if a < b
+ *          -2 if either a or b is a NaN.
+ */
+int ecmp( a, b )
+unsigned short *a, *b;
+{
+unsigned short ai[NI], bi[NI];
+register unsigned short *p, *q;
+register int i;
+int msign;
+
+#ifdef NANS
+if (eisnan (a)  || eisnan (b))
+	return( -2 );
+#endif
+emovi( a, ai );
+p = ai;
+emovi( b, bi );
+q = bi;
+
+if( *p != *q )
+	{ /* the signs are different */
+/* -0 equals + 0 */
+	for( i=1; i<NI-1; i++ )
+		{
+		if( ai[i] != 0 )
+			goto nzro;
+		if( bi[i] != 0 )
+			goto nzro;
+		}
+	return(0);
+nzro:
+	if( *p == 0 )
+		return( 1 );
+	else
+		return( -1 );
+	}
+/* both are the same sign */
+if( *p == 0 )
+	msign = 1;
+else
+	msign = -1;
+i = NI-1;
+do
+	{
+	if( *p++ != *q++ )
+		{
+		goto diff;
+		}
+	}
+while( --i > 0 );
+
+return(0);	/* equality */
+
+
+
+diff:
+
+if( *(--p) > *(--q) )
+	return( msign );		/* p is bigger */
+else
+	return( -msign );	/* p is littler */
+}
+
+
+
+
+/* Find nearest integer to x = floor( x + 0.5 )
+ *
+ * unsigned short x[NE], y[NE]
+ * eround( x, y );
+ */
+void eround( x, y )
+unsigned short *x, *y;
+{
+
+eadd( ehalf, x, y );
+efloor( y, y );
+}
+
+
+
+
+/*
+; convert long (32-bit) integer to e type
+;
+;	long l;
+;	unsigned short x[NE];
+;	ltoe( &l, x );
+; note &l is the memory address of l
+*/
+void ltoe( lp, y )
+long *lp;	/* lp is the memory address of a long integer */
+unsigned short *y;	/* y is the address of a short */
+{
+unsigned short yi[NI];
+unsigned long ll;
+int k;
+
+ecleaz( yi );
+if( *lp < 0 )
+	{
+	ll =  (unsigned long )( -(*lp) ); /* make it positive */
+	yi[0] = 0xffff; /* put correct sign in the e type number */
+	}
+else
+	{
+	ll = (unsigned long )( *lp );
+	}
+/* move the long integer to yi significand area */
+if( sizeof(long) == 8 )
+	{
+	yi[M] = (unsigned short) (ll >> (LONGBITS - 16));
+	yi[M + 1] = (unsigned short) (ll >> (LONGBITS - 32));
+	yi[M + 2] = (unsigned short) (ll >> 16);
+	yi[M + 3] = (unsigned short) ll;
+	yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
+	}
+else
+	{
+	yi[M] = (unsigned short )(ll >> 16); 
+	yi[M+1] = (unsigned short )ll;
+	yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
+	}
+if( (k = enormlz( yi )) > NBITS ) /* normalize the significand */
+	ecleaz( yi );	/* it was zero */
+else
+	yi[E] -= (unsigned short )k; /* subtract shift count from exponent */
+emovo( yi, y );	/* output the answer */
+}
+
+/*
+; convert unsigned long (32-bit) integer to e type
+;
+;	unsigned long l;
+;	unsigned short x[NE];
+;	ltox( &l, x );
+; note &l is the memory address of l
+*/
+void ultoe( lp, y )
+unsigned long *lp; /* lp is the memory address of a long integer */
+unsigned short *y;	/* y is the address of a short */
+{
+unsigned short yi[NI];
+unsigned long ll;
+int k;
+
+ecleaz( yi );
+ll = *lp;
+
+/* move the long integer to ayi significand area */
+if( sizeof(long) == 8 )
+	{
+	yi[M] = (unsigned short) (ll >> (LONGBITS - 16));
+	yi[M + 1] = (unsigned short) (ll >> (LONGBITS - 32));
+	yi[M + 2] = (unsigned short) (ll >> 16);
+	yi[M + 3] = (unsigned short) ll;
+	yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
+	}
+else
+	{
+	yi[M] = (unsigned short )(ll >> 16); 
+	yi[M+1] = (unsigned short )ll;
+	yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
+	}
+if( (k = enormlz( yi )) > NBITS ) /* normalize the significand */
+	ecleaz( yi );	/* it was zero */
+else
+	yi[E] -= (unsigned short )k; /* subtract shift count from exponent */
+emovo( yi, y );	/* output the answer */
+}
+
+
+/*
+;	Find long integer and fractional parts
+
+;	long i;
+;	unsigned short x[NE], frac[NE];
+;	xifrac( x, &i, frac );
+ 
+  The integer output has the sign of the input.  The fraction is
+  the positive fractional part of abs(x).
+*/
+void eifrac( x, i, frac )
+unsigned short *x;
+long *i;
+unsigned short *frac;
+{
+unsigned short xi[NI];
+int j, k;
+unsigned long ll;
+
+emovi( x, xi );
+k = (int )xi[E] - (EXONE - 1);
+if( k <= 0 )
+	{
+/* if exponent <= 0, integer = 0 and real output is fraction */
+	*i = 0L;
+	emovo( xi, frac );
+	return;
+	}
+if( k > (8 * sizeof(long) - 1) )
+	{
+/*
+;	long integer overflow: output large integer
+;	and correct fraction
+*/
+	j = 8 * sizeof(long) - 1;
+	if( xi[0] )
+		*i = (long) ((unsigned long) 1) << j;
+	else
+		*i = (long) (((unsigned long) (~(0L))) >> 1);
+	(void )eshift( xi, k );
+	}
+if( k > 16 )
+	{
+/*
+  Shift more than 16 bits: shift up k-16 mod 16
+  then shift by 16's.
+*/
+	j = k - ((k >> 4) << 4);
+	eshift (xi, j);
+	ll = xi[M];
+	k -= j;
+	do
+		{
+		eshup6 (xi);
+		ll = (ll << 16) | xi[M];
+		}
+	while ((k -= 16) > 0);
+	*i = ll;
+	if (xi[0])
+		*i = -(*i);
+	}
+else
+	{
+/* shift not more than 16 bits */
+	eshift( xi, k );
+	*i = (long )xi[M] & 0xffff;
+	if( xi[0] )
+		*i = -(*i);
+	}
+xi[0] = 0;
+xi[E] = EXONE - 1;
+xi[M] = 0;
+if( (k = enormlz( xi )) > NBITS )
+	ecleaz( xi );
+else
+	xi[E] -= (unsigned short )k;
+
+emovo( xi, frac );
+}
+
+
+/*
+;	Find unsigned long integer and fractional parts
+
+;	unsigned long i;
+;	unsigned short x[NE], frac[NE];
+;	xifrac( x, &i, frac );
+
+  A negative e type input yields integer output = 0
+  but correct fraction.
+*/
+void euifrac( x, i, frac )
+unsigned short *x;
+unsigned long *i;
+unsigned short *frac;
+{
+unsigned short xi[NI];
+int j, k;
+unsigned long ll;
+
+emovi( x, xi );
+k = (int )xi[E] - (EXONE - 1);
+if( k <= 0 )
+	{
+/* if exponent <= 0, integer = 0 and argument is fraction */
+	*i = 0L;
+	emovo( xi, frac );
+	return;
+	}
+if( k > (8 * sizeof(long)) )
+	{
+/*
+;	long integer overflow: output large integer
+;	and correct fraction
+*/
+	*i = ~(0L);
+	(void )eshift( xi, k );
+	}
+else if( k > 16 )
+	{
+/*
+  Shift more than 16 bits: shift up k-16 mod 16
+  then shift up by 16's.
+*/
+	j = k - ((k >> 4) << 4);
+	eshift (xi, j);
+	ll = xi[M];
+	k -= j;
+	do
+		{
+		eshup6 (xi);
+		ll = (ll << 16) | xi[M];
+		}
+	while ((k -= 16) > 0);
+	*i = ll;
+	}
+else
+	{
+/* shift not more than 16 bits */
+	eshift( xi, k );
+	*i = (long )xi[M] & 0xffff;
+	}
+
+if( xi[0] )  /* A negative value yields unsigned integer 0. */
+	*i = 0L;
+
+xi[0] = 0;
+xi[E] = EXONE - 1;
+xi[M] = 0;
+if( (k = enormlz( xi )) > NBITS )
+	ecleaz( xi );
+else
+	xi[E] -= (unsigned short )k;
+
+emovo( xi, frac );
+}
+
+
+
+/*
+;	Shift significand
+;
+;	Shifts significand area up or down by the number of bits
+;	given by the variable sc.
+*/
+int eshift( x, sc )
+unsigned short *x;
+int sc;
+{
+unsigned short lost;
+unsigned short *p;
+
+if( sc == 0 )
+	return( 0 );
+
+lost = 0;
+p = x + NI-1;
+
+if( sc < 0 )
+	{
+	sc = -sc;
+	while( sc >= 16 )
+		{
+		lost |= *p;	/* remember lost bits */
+		eshdn6(x);
+		sc -= 16;
+		}
+
+	while( sc >= 8 )
+		{
+		lost |= *p & 0xff;
+		eshdn8(x);
+		sc -= 8;
+		}
+
+	while( sc > 0 )
+		{
+		lost |= *p & 1;
+		eshdn1(x);
+		sc -= 1;
+		}
+	}
+else
+	{
+	while( sc >= 16 )
+		{
+		eshup6(x);
+		sc -= 16;
+		}
+
+	while( sc >= 8 )
+		{
+		eshup8(x);
+		sc -= 8;
+		}
+
+	while( sc > 0 )
+		{
+		eshup1(x);
+		sc -= 1;
+		}
+	}
+if( lost )
+	lost = 1;
+return( (int )lost );
+}
+
+
+
+/*
+;	normalize
+;
+; Shift normalizes the significand area pointed to by argument
+; shift count (up = positive) is returned.
+*/
+int enormlz(x)
+unsigned short x[];
+{
+register unsigned short *p;
+int sc;
+
+sc = 0;
+p = &x[M];
+if( *p != 0 )
+	goto normdn;
+++p;
+if( *p & 0x8000 )
+	return( 0 );	/* already normalized */
+while( *p == 0 )
+	{
+	eshup6(x);
+	sc += 16;
+/* With guard word, there are NBITS+16 bits available.
+ * return true if all are zero.
+ */
+	if( sc > NBITS )
+		return( sc );
+	}
+/* see if high byte is zero */
+while( (*p & 0xff00) == 0 )
+	{
+	eshup8(x);
+	sc += 8;
+	}
+/* now shift 1 bit at a time */
+while( (*p  & 0x8000) == 0)
+	{
+	eshup1(x);
+	sc += 1;
+	if( sc > (NBITS+16) )
+		{
+		mtherr( "enormlz", UNDERFLOW );
+		return( sc );
+		}
+	}
+return( sc );
+
+/* Normalize by shifting down out of the high guard word
+   of the significand */
+normdn:
+
+if( *p & 0xff00 )
+	{
+	eshdn8(x);
+	sc -= 8;
+	}
+while( *p != 0 )
+	{
+	eshdn1(x);
+	sc -= 1;
+
+	if( sc < -NBITS )
+		{
+		mtherr( "enormlz", OVERFLOW );
+		return( sc );
+		}
+	}
+return( sc );
+}
+
+
+
+
+/* Convert e type number to decimal format ASCII string.
+ * The constants are for 64 bit precision.
+ */
+
+#define NTEN 12
+#define MAXP 4096
+
+#if NE == 10
+static unsigned short etens[NTEN + 1][NE] =
+{
+  {0x6576, 0x4a92, 0x804a, 0x153f,
+   0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,},	/* 10**4096 */
+  {0x6a32, 0xce52, 0x329a, 0x28ce,
+   0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,},	/* 10**2048 */
+  {0x526c, 0x50ce, 0xf18b, 0x3d28,
+   0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
+  {0x9c66, 0x58f8, 0xbc50, 0x5c54,
+   0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
+  {0x851e, 0xeab7, 0x98fe, 0x901b,
+   0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
+  {0x0235, 0x0137, 0x36b1, 0x336c,
+   0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
+  {0x50f8, 0x25fb, 0xc76b, 0x6b71,
+   0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
+  {0x0000, 0x0000, 0x0000, 0x0000,
+   0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
+  {0x0000, 0x0000, 0x0000, 0x0000,
+   0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
+  {0x0000, 0x0000, 0x0000, 0x0000,
+   0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
+  {0x0000, 0x0000, 0x0000, 0x0000,
+   0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
+  {0x0000, 0x0000, 0x0000, 0x0000,
+   0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
+  {0x0000, 0x0000, 0x0000, 0x0000,
+   0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,},	/* 10**1 */
+};
+
+static unsigned short emtens[NTEN + 1][NE] =
+{
+  {0x2030, 0xcffc, 0xa1c3, 0x8123,
+   0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,},	/* 10**-4096 */
+  {0x8264, 0xd2cb, 0xf2ea, 0x12d4,
+   0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,},	/* 10**-2048 */
+  {0xf53f, 0xf698, 0x6bd3, 0x0158,
+   0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
+  {0xe731, 0x04d4, 0xe3f2, 0xd332,
+   0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
+  {0xa23e, 0x5308, 0xfefb, 0x1155,
+   0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
+  {0xe26d, 0xdbde, 0xd05d, 0xb3f6,
+   0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
+  {0x2a20, 0x6224, 0x47b3, 0x98d7,
+   0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
+  {0x0b5b, 0x4af2, 0xa581, 0x18ed,
+   0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
+  {0xbf71, 0xa9b3, 0x7989, 0xbe68,
+   0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
+  {0x3d4d, 0x7c3d, 0x36ba, 0x0d2b,
+   0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
+  {0xc155, 0xa4a8, 0x404e, 0x6113,
+   0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
+  {0xd70a, 0x70a3, 0x0a3d, 0xa3d7,
+   0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
+  {0xcccd, 0xcccc, 0xcccc, 0xcccc,
+   0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,},	/* 10**-1 */
+};
+#else
+static unsigned short etens[NTEN+1][NE] = {
+{0xc94c,0x979a,0x8a20,0x5202,0xc460,0x7525,},/* 10**4096 */
+{0xa74d,0x5de4,0xc53d,0x3b5d,0x9e8b,0x5a92,},/* 10**2048 */
+{0x650d,0x0c17,0x8175,0x7586,0xc976,0x4d48,},
+{0xcc65,0x91c6,0xa60e,0xa0ae,0xe319,0x46a3,},
+{0xddbc,0xde8d,0x9df9,0xebfb,0xaa7e,0x4351,},
+{0xc66f,0x8cdf,0x80e9,0x47c9,0x93ba,0x41a8,},
+{0x3cbf,0xa6d5,0xffcf,0x1f49,0xc278,0x40d3,},
+{0xf020,0xb59d,0x2b70,0xada8,0x9dc5,0x4069,},
+{0x0000,0x0000,0x0400,0xc9bf,0x8e1b,0x4034,},
+{0x0000,0x0000,0x0000,0x2000,0xbebc,0x4019,},
+{0x0000,0x0000,0x0000,0x0000,0x9c40,0x400c,},
+{0x0000,0x0000,0x0000,0x0000,0xc800,0x4005,},
+{0x0000,0x0000,0x0000,0x0000,0xa000,0x4002,}, /* 10**1 */
+};
+
+static unsigned short emtens[NTEN+1][NE] = {
+{0x2de4,0x9fde,0xd2ce,0x04c8,0xa6dd,0x0ad8,}, /* 10**-4096 */
+{0x4925,0x2de4,0x3436,0x534f,0xceae,0x256b,}, /* 10**-2048 */
+{0x87a6,0xc0bd,0xda57,0x82a5,0xa2a6,0x32b5,},
+{0x7133,0xd21c,0xdb23,0xee32,0x9049,0x395a,},
+{0xfa91,0x1939,0x637a,0x4325,0xc031,0x3cac,},
+{0xac7d,0xe4a0,0x64bc,0x467c,0xddd0,0x3e55,},
+{0x3f24,0xe9a5,0xa539,0xea27,0xa87f,0x3f2a,},
+{0x67de,0x94ba,0x4539,0x1ead,0xcfb1,0x3f94,},
+{0x4c2f,0xe15b,0xc44d,0x94be,0xe695,0x3fc9,},
+{0xfdc2,0xcefc,0x8461,0x7711,0xabcc,0x3fe4,},
+{0xd3c3,0x652b,0xe219,0x1758,0xd1b7,0x3ff1,},
+{0x3d71,0xd70a,0x70a3,0x0a3d,0xa3d7,0x3ff8,},
+{0xcccd,0xcccc,0xcccc,0xcccc,0xcccc,0x3ffb,}, /* 10**-1 */
+};
+#endif
+
+void e24toasc( x, string, ndigs )
+unsigned short x[];
+char *string;
+int ndigs;
+{
+unsigned short w[NI];
+
+e24toe( x, w );
+etoasc( w, string, ndigs );
+}
+
+
+void e53toasc( x, string, ndigs )
+unsigned short x[];
+char *string;
+int ndigs;
+{
+unsigned short w[NI];
+
+e53toe( x, w );
+etoasc( w, string, ndigs );
+}
+
+
+void e64toasc( x, string, ndigs )
+unsigned short x[];
+char *string;
+int ndigs;
+{
+unsigned short w[NI];
+
+e64toe( x, w );
+etoasc( w, string, ndigs );
+}
+
+void e113toasc (x, string, ndigs)
+unsigned short x[];
+char *string;
+int ndigs;
+{
+unsigned short w[NI];
+
+e113toe (x, w);
+etoasc (w, string, ndigs);
+}
+
+
+void etoasc( x, string, ndigs )
+unsigned short x[];
+char *string;
+int ndigs;
+{
+long digit;
+unsigned short y[NI], t[NI], u[NI], w[NI];
+unsigned short *p, *r, *ten;
+unsigned short sign;
+int i, j, k, expon, rndsav;
+char *s, *ss;
+unsigned short m;
+
+rndsav = rndprc;
+#ifdef NANS
+if( eisnan(x) )
+	{
+	sprintf( string, " NaN " );
+	goto bxit;
+	}
+#endif
+rndprc = NBITS;		/* set to full precision */
+emov( x, y ); /* retain external format */
+if( y[NE-1] & 0x8000 )
+	{
+	sign = 0xffff;
+	y[NE-1] &= 0x7fff;
+	}
+else
+	{
+	sign = 0;
+	}
+expon = 0;
+ten = &etens[NTEN][0];
+emov( eone, t );
+/* Test for zero exponent */
+if( y[NE-1] == 0 )
+	{
+	for( k=0; k<NE-1; k++ )
+		{
+		if( y[k] != 0 )
+			goto tnzro; /* denormalized number */
+		}
+	goto isone; /* legal all zeros */
+	}
+tnzro:
+
+/* Test for infinity.
+ */
+if( y[NE-1] == 0x7fff )
+	{
+	if( sign )
+		sprintf( string, " -Infinity " );
+	else
+		sprintf( string, " Infinity " );
+	goto bxit;
+	}
+
+/* Test for exponent nonzero but significand denormalized.
+ * This is an error condition.
+ */
+if( (y[NE-1] != 0) && ((y[NE-2] & 0x8000) == 0) )
+	{
+	mtherr( "etoasc", DOMAIN );
+	sprintf( string, "NaN" );
+	goto bxit;
+	}
+
+/* Compare to 1.0 */
+i = ecmp( eone, y );
+if( i == 0 )
+	goto isone;
+
+if( i < 0 )
+	{ /* Number is greater than 1 */
+/* Convert significand to an integer and strip trailing decimal zeros. */
+	emov( y, u );
+	u[NE-1] = EXONE + NBITS - 1;
+
+	p = &etens[NTEN-4][0];
+	m = 16;
+do
+	{
+	ediv( p, u, t );
+	efloor( t, w );
+	for( j=0; j<NE-1; j++ )
+		{
+		if( t[j] != w[j] )
+			goto noint;
+		}
+	emov( t, u );
+	expon += (int )m;
+noint:
+	p += NE;
+	m >>= 1;
+	}
+while( m != 0 );
+
+/* Rescale from integer significand */
+	u[NE-1] += y[NE-1] - (unsigned int )(EXONE + NBITS - 1);
+	emov( u, y );
+/* Find power of 10 */
+	emov( eone, t );
+	m = MAXP;
+	p = &etens[0][0];
+	while( ecmp( ten, u ) <= 0 )
+		{
+		if( ecmp( p, u ) <= 0 )
+			{
+			ediv( p, u, u );
+			emul( p, t, t );
+			expon += (int )m;
+			}
+		m >>= 1;
+		if( m == 0 )
+			break;
+		p += NE;
+		}
+	}
+else
+	{ /* Number is less than 1.0 */
+/* Pad significand with trailing decimal zeros. */
+	if( y[NE-1] == 0 )
+		{
+		while( (y[NE-2] & 0x8000) == 0 )
+			{
+			emul( ten, y, y );
+			expon -= 1;
+			}
+		}
+	else
+		{
+		emovi( y, w );
+		for( i=0; i<NDEC+1; i++ )
+			{
+			if( (w[NI-1] & 0x7) != 0 )
+				break;
+/* multiply by 10 */
+			emovz( w, u );
+			eshdn1( u );
+			eshdn1( u );
+			eaddm( w, u );
+			u[1] += 3;
+			while( u[2] != 0 )
+				{
+				eshdn1(u);
+				u[1] += 1;
+				}
+			if( u[NI-1] != 0 )
+				break;
+			if( eone[NE-1] <= u[1] )
+				break;
+			emovz( u, w );
+			expon -= 1;
+			}
+		emovo( w, y );
+		}
+	k = -MAXP;
+	p = &emtens[0][0];
+	r = &etens[0][0];
+	emov( y, w );
+	emov( eone, t );
+	while( ecmp( eone, w ) > 0 )
+		{
+		if( ecmp( p, w ) >= 0 )
+			{
+			emul( r, w, w );
+			emul( r, t, t );
+			expon += k;
+			}
+		k /= 2;
+		if( k == 0 )
+			break;
+		p += NE;
+		r += NE;
+		}
+	ediv( t, eone, t );
+	}
+isone:
+/* Find the first (leading) digit. */
+emovi( t, w );
+emovz( w, t );
+emovi( y, w );
+emovz( w, y );
+eiremain( t, y );
+digit = equot[NI-1];
+while( (digit == 0) && (ecmp(y,ezero) != 0) )
+	{
+	eshup1( y );
+	emovz( y, u );
+	eshup1( u );
+	eshup1( u );
+	eaddm( u, y );
+	eiremain( t, y );
+	digit = equot[NI-1];
+	expon -= 1;
+	}
+s = string;
+if( sign )
+	*s++ = '-';
+else
+	*s++ = ' ';
+/* Examine number of digits requested by caller. */
+if( ndigs < 0 )
+	ndigs = 0;
+if( ndigs > NDEC )
+	ndigs = NDEC;
+if( digit == 10 )
+	{
+	*s++ = '1';
+	*s++ = '.';
+	if( ndigs > 0 )
+		{
+		*s++ = '0';
+		ndigs -= 1;
+		}
+	expon += 1;
+	}
+else
+	{
+	*s++ = (char )digit + '0';
+	*s++ = '.';
+	}
+/* Generate digits after the decimal point. */
+for( k=0; k<=ndigs; k++ )
+	{
+/* multiply current number by 10, without normalizing */
+	eshup1( y );
+	emovz( y, u );
+	eshup1( u );
+	eshup1( u );
+	eaddm( u, y );
+	eiremain( t, y );
+	*s++ = (char )equot[NI-1] + '0';
+	}
+digit = equot[NI-1];
+--s;
+ss = s;
+/* round off the ASCII string */
+if( digit > 4 )
+	{
+/* Test for critical rounding case in ASCII output. */
+	if( digit == 5 )
+		{
+		emovo( y, t );
+		if( ecmp(t,ezero) != 0 )
+			goto roun;	/* round to nearest */
+		if( (*(s-1) & 1) == 0 )
+			goto doexp;	/* round to even */
+		}
+/* Round up and propagate carry-outs */
+roun:
+	--s;
+	k = *s & 0x7f;
+/* Carry out to most significant digit? */
+	if( k == '.' )
+		{
+		--s;
+		k = *s;
+		k += 1;
+		*s = (char )k;
+/* Most significant digit carries to 10? */
+		if( k > '9' )
+			{
+			expon += 1;
+			*s = '1';
+			}
+		goto doexp;
+		}
+/* Round up and carry out from less significant digits */
+	k += 1;
+	*s = (char )k;
+	if( k > '9' )
+		{
+		*s = '0';
+		goto roun;
+		}
+	}
+doexp:
+/*
+if( expon >= 0 )
+	sprintf( ss, "e+%d", expon );
+else
+	sprintf( ss, "e%d", expon );
+*/
+	sprintf( ss, "E%d", expon );
+bxit:
+rndprc = rndsav;
+}
+
+
+
+
+/*
+;								ASCTOQ
+;		ASCTOQ.MAC		LATEST REV: 11 JAN 84
+;					SLM, 3 JAN 78
+;
+;	Convert ASCII string to quadruple precision floating point
+;
+;		Numeric input is free field decimal number
+;		with max of 15 digits with or without 
+;		decimal point entered as ASCII from teletype.
+;	Entering E after the number followed by a second
+;	number causes the second number to be interpreted
+;	as a power of 10 to be multiplied by the first number
+;	(i.e., "scientific" notation).
+;
+;	Usage:
+;		asctoq( string, q );
+*/
+
+/* ASCII to single */
+void asctoe24( s, y )
+char *s;
+unsigned short *y;
+{
+asctoeg( s, y, 24 );
+}
+
+
+/* ASCII to double */
+void asctoe53( s, y )
+char *s;
+unsigned short *y;
+{
+#ifdef DEC
+asctoeg( s, y, 56 );
+#else
+asctoeg( s, y, 53 );
+#endif
+}
+
+
+/* ASCII to long double */
+void asctoe64( s, y )
+char *s;
+unsigned short *y;
+{
+asctoeg( s, y, 64 );
+}
+
+/* ASCII to 128-bit long double */
+void asctoe113 (s, y)
+char *s;
+unsigned short *y;
+{
+asctoeg( s, y, 113 );
+}
+
+/* ASCII to super double */
+void asctoe( s, y )
+char *s;
+unsigned short *y;
+{
+asctoeg( s, y, NBITS );
+}
+
+/* Space to make a copy of the input string: */
+static char lstr[82] = {0};
+
+void asctoeg( ss, y, oprec )
+char *ss;
+unsigned short *y;
+int oprec;
+{
+unsigned short yy[NI], xt[NI], tt[NI];
+int esign, decflg, sgnflg, nexp, exp, prec, lost;
+int k, trail, c, rndsav;
+long lexp;
+unsigned short nsign, *p;
+char *sp, *s;
+
+/* Copy the input string. */
+s = ss;
+while( *s == ' ' ) /* skip leading spaces */
+	++s;
+sp = lstr;
+for( k=0; k<79; k++ )
+	{
+	if( (*sp++ = *s++) == '\0' )
+		break;
+	}
+*sp = '\0';
+s = lstr;
+
+rndsav = rndprc;
+rndprc = NBITS; /* Set to full precision */
+lost = 0;
+nsign = 0;
+decflg = 0;
+sgnflg = 0;
+nexp = 0;
+exp = 0;
+prec = 0;
+ecleaz( yy );
+trail = 0;
+
+nxtcom:
+k = *s - '0';
+if( (k >= 0) && (k <= 9) )
+	{
+/* Ignore leading zeros */
+	if( (prec == 0) && (decflg == 0) && (k == 0) )
+		goto donchr;
+/* Identify and strip trailing zeros after the decimal point. */
+	if( (trail == 0) && (decflg != 0) )
+		{
+		sp = s;
+		while( (*sp >= '0') && (*sp <= '9') )
+			++sp;
+/* Check for syntax error */
+		c = *sp & 0x7f;
+		if( (c != 'e') && (c != 'E') && (c != '\0')
+			&& (c != '\n') && (c != '\r') && (c != ' ')
+			&& (c != ',') )
+			goto error;
+		--sp;
+		while( *sp == '0' )
+			*sp-- = 'z';
+		trail = 1;
+		if( *s == 'z' )
+			goto donchr;
+		}
+/* If enough digits were given to more than fill up the yy register,
+ * continuing until overflow into the high guard word yy[2]
+ * guarantees that there will be a roundoff bit at the top
+ * of the low guard word after normalization.
+ */
+	if( yy[2] == 0 )
+		{
+		if( decflg )
+			nexp += 1; /* count digits after decimal point */
+		eshup1( yy );	/* multiply current number by 10 */
+		emovz( yy, xt );
+		eshup1( xt );
+		eshup1( xt );
+		eaddm( xt, yy );
+		ecleaz( xt );
+		xt[NI-2] = (unsigned short )k;
+		eaddm( xt, yy );
+		}
+	else
+		{
+		/* Mark any lost non-zero digit.  */
+		lost |= k;
+		/* Count lost digits before the decimal point.  */
+		if (decflg == 0)
+		        nexp -= 1;
+		}
+	prec += 1;
+	goto donchr;
+	}
+
+switch( *s )
+	{
+	case 'z':
+		break;
+	case 'E':
+	case 'e':
+		goto expnt;
+	case '.':	/* decimal point */
+		if( decflg )
+			goto error;
+		++decflg;
+		break;
+	case '-':
+		nsign = 0xffff;
+		if( sgnflg )
+			goto error;
+		++sgnflg;
+		break;
+	case '+':
+		if( sgnflg )
+			goto error;
+		++sgnflg;
+		break;
+	case ',':
+	case ' ':
+	case '\0':
+	case '\n':
+	case '\r':
+		goto daldone;
+	case 'i':
+	case 'I':
+		goto infinite;
+	default:
+	error:
+#ifdef NANS
+		enan( yy, NI*16 );
+#else
+		mtherr( "asctoe", DOMAIN );
+		ecleaz(yy);
+#endif
+		goto aexit;
+	}
+donchr:
+++s;
+goto nxtcom;
+
+/* Exponent interpretation */
+expnt:
+
+esign = 1;
+exp = 0;
+++s;
+/* check for + or - */
+if( *s == '-' )
+	{
+	esign = -1;
+	++s;
+	}
+if( *s == '+' )
+	++s;
+while( (*s >= '0') && (*s <= '9') )
+	{
+	exp *= 10;
+	exp += *s++ - '0';
+	if (exp > 4977)
+		{
+		if (esign < 0)
+			goto zero;
+		else
+			goto infinite;
+		}
+	}
+if( esign < 0 )
+	exp = -exp;
+if( exp > 4932 )
+	{
+infinite:
+	ecleaz(yy);
+	yy[E] = 0x7fff;  /* infinity */
+	goto aexit;
+	}
+if( exp < -4977 )
+	{
+zero:
+	ecleaz(yy);
+	goto aexit;
+	}
+
+daldone:
+nexp = exp - nexp;
+/* Pad trailing zeros to minimize power of 10, per IEEE spec. */
+while( (nexp > 0) && (yy[2] == 0) )
+	{
+	emovz( yy, xt );
+	eshup1( xt );
+	eshup1( xt );
+	eaddm( yy, xt );
+	eshup1( xt );
+	if( xt[2] != 0 )
+		break;
+	nexp -= 1;
+	emovz( xt, yy );
+	}
+if( (k = enormlz(yy)) > NBITS )
+	{
+	ecleaz(yy);
+	goto aexit;
+	}
+lexp = (EXONE - 1 + NBITS) - k;
+emdnorm( yy, lost, 0, lexp, 64 );
+/* convert to external format */
+
+
+/* Multiply by 10**nexp.  If precision is 64 bits,
+ * the maximum relative error incurred in forming 10**n
+ * for 0 <= n <= 324 is 8.2e-20, at 10**180.
+ * For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947.
+ * For 0 >= n >= -999, it is -1.55e-19 at 10**-435.
+ */
+lexp = yy[E];
+if( nexp == 0 )
+	{
+	k = 0;
+	goto expdon;
+	}
+esign = 1;
+if( nexp < 0 )
+	{
+	nexp = -nexp;
+	esign = -1;
+	if( nexp > 4096 )
+		{ /* Punt.  Can't handle this without 2 divides. */
+		emovi( etens[0], tt );
+		lexp -= tt[E];
+		k = edivm( tt, yy );
+		lexp += EXONE;
+		nexp -= 4096;
+		}
+	}
+p = &etens[NTEN][0];
+emov( eone, xt );
+exp = 1;
+do
+	{
+	if( exp & nexp )
+		emul( p, xt, xt );
+	p -= NE;
+	exp = exp + exp;
+	}
+while( exp <= MAXP );
+
+emovi( xt, tt );
+if( esign < 0 )
+	{
+	lexp -= tt[E];
+	k = edivm( tt, yy );
+	lexp += EXONE;
+	}
+else
+	{
+	lexp += tt[E];
+	k = emulm( tt, yy );
+	lexp -= EXONE - 1;
+	}
+
+expdon:
+
+/* Round and convert directly to the destination type */
+if( oprec == 53 )
+	lexp -= EXONE - 0x3ff;
+else if( oprec == 24 )
+	lexp -= EXONE - 0177;
+#ifdef DEC
+else if( oprec == 56 )
+	lexp -= EXONE - 0201;
+#endif
+rndprc = oprec;
+emdnorm( yy, k, 0, lexp, 64 );
+
+aexit:
+
+rndprc = rndsav;
+yy[0] = nsign;
+switch( oprec )
+	{
+#ifdef DEC
+	case 56:
+		todec( yy, y ); /* see etodec.c */
+		break;
+#endif
+	case 53:
+		toe53( yy, y );
+		break;
+	case 24:
+		toe24( yy, y );
+		break;
+	case 64:
+		toe64( yy, y );
+		break;
+	case 113:
+		toe113( yy, y );
+		break;
+	case NBITS:
+		emovo( yy, y );
+		break;
+	}
+}
+
+
+ 
+/* y = largest integer not greater than x
+ * (truncated toward minus infinity)
+ *
+ * unsigned short x[NE], y[NE]
+ *
+ * efloor( x, y );
+ */
+static unsigned short bmask[] = {
+0xffff,
+0xfffe,
+0xfffc,
+0xfff8,
+0xfff0,
+0xffe0,
+0xffc0,
+0xff80,
+0xff00,
+0xfe00,
+0xfc00,
+0xf800,
+0xf000,
+0xe000,
+0xc000,
+0x8000,
+0x0000,
+};
+
+void efloor( x, y )
+unsigned short x[], y[];
+{
+register unsigned short *p;
+int e, expon, i;
+unsigned short f[NE];
+
+emov( x, f ); /* leave in external format */
+expon = (int )f[NE-1];
+e = (expon & 0x7fff) - (EXONE - 1);
+if( e <= 0 )
+	{
+	eclear(y);
+	goto isitneg;
+	}
+/* number of bits to clear out */
+e = NBITS - e;
+emov( f, y );
+if( e <= 0 )
+	return;
+
+p = &y[0];
+while( e >= 16 )
+	{
+	*p++ = 0;
+	e -= 16;
+	}
+/* clear the remaining bits */
+*p &= bmask[e];
+/* truncate negatives toward minus infinity */
+isitneg:
+
+if( (unsigned short )expon & (unsigned short )0x8000 )
+	{
+	for( i=0; i<NE-1; i++ )
+		{
+		if( f[i] != y[i] )
+			{
+			esub( eone, y, y );
+			break;
+			}
+		}
+	}
+}
+
+
+/* unsigned short x[], s[];
+ * long *exp;
+ *
+ * efrexp( x, exp, s );
+ *
+ * Returns s and exp such that  s * 2**exp = x and .5 <= s < 1.
+ * For example, 1.1 = 0.55 * 2**1
+ * Handles denormalized numbers properly using long integer exp.
+ */
+void efrexp( x, exp, s )
+unsigned short x[];
+long *exp;
+unsigned short s[];
+{
+unsigned short xi[NI];
+long li;
+
+emovi( x, xi );
+li = (long )((short )xi[1]);
+
+if( li == 0 )
+	{
+	li -= enormlz( xi );
+	}
+xi[1] = 0x3ffe;
+emovo( xi, s );
+*exp = li - 0x3ffe;
+}
+
+
+
+/* unsigned short x[], y[];
+ * long pwr2;
+ *
+ * eldexp( x, pwr2, y );
+ *
+ * Returns y = x * 2**pwr2.
+ */
+void eldexp( x, pwr2, y )
+unsigned short x[];
+long pwr2;
+unsigned short y[];
+{
+unsigned short xi[NI];
+long li;
+int i;
+
+emovi( x, xi );
+li = xi[1];
+li += pwr2;
+i = 0;
+emdnorm( xi, i, i, li, 64 );
+emovo( xi, y );
+}
+
+
+/* c = remainder after dividing b by a
+ * Least significant integer quotient bits left in equot[].
+ */
+void eremain( a, b, c )
+unsigned short a[], b[], c[];
+{
+unsigned short den[NI], num[NI];
+
+#ifdef NANS
+if( eisinf(b) || (ecmp(a,ezero) == 0) || eisnan(a) || eisnan(b))
+	{
+	enan( c, NBITS );
+	return;
+	}
+#endif
+if( ecmp(a,ezero) == 0 )
+	{
+	mtherr( "eremain", SING );
+	eclear( c );
+	return;
+	}
+emovi( a, den );
+emovi( b, num );
+eiremain( den, num );
+/* Sign of remainder = sign of quotient */
+if( a[0] == b[0] )
+	num[0] = 0;
+else
+	num[0] = 0xffff;
+emovo( num, c );
+}
+
+
+void eiremain( den, num )
+unsigned short den[], num[];
+{
+long ld, ln;
+unsigned short j;
+
+ld = den[E];
+ld -= enormlz( den );
+ln = num[E];
+ln -= enormlz( num );
+ecleaz( equot );
+while( ln >= ld )
+	{
+	if( ecmpm(den,num) <= 0 )
+		{
+		esubm(den, num);
+		j = 1;
+		}
+	else
+		{
+		j = 0;
+		}
+	eshup1(equot);
+	equot[NI-1] |= j;
+	eshup1(num);
+	ln -= 1;
+	}
+emdnorm( num, 0, 0, ln, 0 );
+}
+
+/* NaN bit patterns
+ */
+#ifdef MIEEE
+unsigned short nan113[8] = {
+  0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
+unsigned short nan64[6] = {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
+unsigned short nan53[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
+unsigned short nan24[2] = {0x7fff, 0xffff};
+#endif
+
+#ifdef IBMPC
+unsigned short nan113[8] = {0, 0, 0, 0, 0, 0, 0xc000, 0xffff};
+unsigned short nan64[6] = {0, 0, 0, 0xc000, 0xffff, 0};
+unsigned short nan53[4] = {0, 0, 0, 0xfff8};
+unsigned short nan24[2] = {0, 0xffc0};
+#endif
+
+
+void enan (nan, size)
+unsigned short *nan;
+int size;
+{
+int i, n;
+unsigned short *p;
+
+switch( size )
+	{
+#ifndef DEC
+	case 113:
+	n = 8;
+	p = nan113;
+	break;
+
+	case 64:
+	n = 6;
+	p = nan64;
+	break;
+
+	case 53:
+	n = 4;
+	p = nan53;
+	break;
+
+	case 24:
+	n = 2;
+	p = nan24;
+	break;
+
+	case NBITS:
+	for( i=0; i<NE-2; i++ )
+		*nan++ = 0;
+	*nan++ = 0xc000;
+	*nan++ = 0x7fff;
+	return;
+
+	case NI*16:
+	*nan++ = 0;
+	*nan++ = 0x7fff;
+	*nan++ = 0;
+	*nan++ = 0xc000;
+	for( i=4; i<NI; i++ )
+		*nan++ = 0;
+	return;
+#endif
+	default:
+	mtherr( "enan", DOMAIN );
+	return;
+	}
+for (i=0; i < n; i++)
+	*nan++ = *p++;
+}
+
+
+
+/* Longhand square root. */
+
+static int esqinited = 0;
+static unsigned short sqrndbit[NI];
+
+void esqrt( x, y )
+short *x, *y;
+{
+unsigned short temp[NI], num[NI], sq[NI], xx[NI];
+int i, j, k, n, nlups;
+long m, exp;
+
+if( esqinited == 0 )
+	{
+	ecleaz( sqrndbit );
+	sqrndbit[NI-2] = 1;
+	esqinited = 1;
+	}
+/* Check for arg <= 0 */
+i = ecmp( x, ezero );
+if( i <= 0 )
+	{
+#ifdef NANS
+	if (i == -2)
+		{
+		enan (y, NBITS);
+		return;
+		}
+#endif
+	eclear(y);
+	if( i < 0 )
+		mtherr( "esqrt", DOMAIN );
+	return;
+	}
+
+#ifdef INFINITY
+if( eisinf(x) )
+	{
+	eclear(y);
+	einfin(y);
+	return;
+	}
+#endif
+/* Bring in the arg and renormalize if it is denormal. */
+emovi( x, xx );
+m = (long )xx[1]; /* local long word exponent */
+if( m == 0 )
+	m -= enormlz( xx );
+
+/* Divide exponent by 2 */
+m -= 0x3ffe;
+exp = (unsigned short )( (m / 2) + 0x3ffe );
+
+/* Adjust if exponent odd */
+if( (m & 1) != 0 )
+	{
+	if( m > 0 )
+		exp += 1;
+	eshdn1( xx );
+	}
+
+ecleaz( sq );
+ecleaz( num );
+n = 8; /* get 8 bits of result per inner loop */
+nlups = rndprc;
+j = 0;
+
+while( nlups > 0 )
+	{
+/* bring in next word of arg */
+	if( j < NE )
+		num[NI-1] = xx[j+3];
+/* Do additional bit on last outer loop, for roundoff. */
+	if( nlups <= 8 )
+		n = nlups + 1;
+	for( i=0; i<n; i++ )
+		{
+/* Next 2 bits of arg */
+		eshup1( num );
+		eshup1( num );
+/* Shift up answer */
+		eshup1( sq );
+/* Make trial divisor */
+		for( k=0; k<NI; k++ )
+			temp[k] = sq[k];
+		eshup1( temp );
+		eaddm( sqrndbit, temp );
+/* Subtract and insert answer bit if it goes in */
+		if( ecmpm( temp, num ) <= 0 )
+			{
+			esubm( temp, num );
+			sq[NI-2] |= 1;
+			}
+		}
+	nlups -= n;
+	j += 1;
+	}
+
+/* Adjust for extra, roundoff loop done. */
+exp += (NBITS - 1) - rndprc;
+
+/* Sticky bit = 1 if the remainder is nonzero. */
+k = 0;
+for( i=3; i<NI; i++ )
+	k |= (int )num[i];
+
+/* Renormalize and round off. */
+emdnorm( sq, k, 0, exp, 64 );
+emovo( sq, y );
+}

+ 850 - 850
test/math/ieetst.c

@@ -1,850 +1,850 @@
-/* Floating point to ASCII input and output string test program.
- *
- * Numbers in the native machine data structure are converted
- * to e type, then to and from decimal ASCII strings.  Native
- * printf() and scanf() functions are also used to produce
- * and read strings.  The resulting e type binary values
- * are compared, with diagnostic printouts of any discrepancies.
- *
- * Steve Moshier, 16 Dec 88
- * last revision: 16 May 92
- */
-
-#include "ehead.h"
-#include "mconf.h"
-
-/* Include tests of 80-bit long double precision: */
-#define LDOUBLE 0
-/* Abort subtest after getting this many errors: */
-#define MAXERR 5
-/* Number of random arguments to try (set as large as you have
- * patience for): */
-#define NRAND 100
-/* Perform internal consistency test: */
-#define CHKINTERNAL 0
-
-static unsigned short fullp[NE], rounded[NE];
-float prec24, sprec24, ssprec24;
-double prec53, sprec53, ssprec53;
-#if LDOUBLE
-long double prec64, sprec64, ssprec64;
-#endif
-
-static unsigned short rprint[NE], rscan[NE];
-static unsigned short q1[NE], q2[NE], q5[NE];
-static unsigned short e1[NE], e2[NE], e3[NE];
-static double d1, d2;
-static int errprint = 0;
-static int errscan = 0;
-static int identerr = 0;
-static int errtot = 0;
-static int count = 0;
-static char str0[80], str1[80], str2[80], str3[80];
-static unsigned short eten[NE], maxm[NE];
-
-int m, n, k2, mprec, SPREC;
-
-char *Ten = "10.0";
-char tformat[10];
-char *format24 = "%.8e";
-#ifdef DEC
-char *format53 = "%.17e";
-#else
-char *format53 = "%.16e";
-#endif
-char *fformat24 = "%e";
-char *fformat53 = "%le";
-char *pct = "%";
-char *quo = "\042";
-#if LDOUBLE
-char *format64 = "%.20Le";
-char *fformat64 = "%Le";
-#endif
-char *format;
-char *fformat;
-char *toomany = "Too many errors; aborting this test.\n";
-
-static int mnrflag;
-static int etrflag;
-void chkit(), printerr(), mnrand(), etrand(), shownoncrit();
-void chkid(), pvec();
-
-main()
-{
-int i, iprec;
-
-printf( "Steve Moshier's printf/scanf tester, version 0.2.\n\n" );
-#ifdef DEC
- /* DEC PDP-11/VAX single precision not yet implemented */
-for( iprec = 1; iprec<2; iprec++ )
-#else
-for( iprec = 0; iprec<3; iprec++ )
-#endif
-	{
-	errscan = 0;
-	identerr = 0;
-	errprint = 0;
-	eclear( rprint );
-	eclear( rscan );
-
-switch( iprec )
-	{
-	case 0:
-		SPREC = 8; /* # digits after the decimal point */
-		mprec = 24; /* # bits in the significand */
-		m = 9; /* max # decimal digits for correct rounding */
-		n = 13; /* max power of ten for correct rounding */
-		k2 = -125; /* underflow beyond 2^-k2 */
-		format = format24; /* printf format string */
-		fformat = fformat24; /* scanf format string */
-		mnrflag = 1; /* sets interval for random numbers */
-		etrflag = 1;
-		printf( "Testing FLOAT precision.\n" );
-		break;
-
-	case 1:
-#ifdef DEC
-		SPREC = 17;
-		mprec = 56;
-		m = 17;
-		n = 27;
-		k2 = -125;
-		format = format53;
-		fformat = fformat53;
-		mnrflag = 2;
-		etrflag = 1;
-		printf( "Testing DEC DOUBLE precision.\n" );
-		break;
-#else
-		SPREC = 16;
-		mprec = 53;
-		m = 17;
-		n = 27;
-		k2 = -1021;
-		format = format53;
-		fformat = fformat53;
-		mnrflag = 2;
-		etrflag = 2;
-		printf( "Testing DOUBLE precision.\n" );
-		break;
-#endif
-	case 2:
-#if LDOUBLE
-		SPREC = 20;
-		mprec = 64;
-		m = 20;
-		n = 34;
-		k2 = -16382;
-		format = format64;
-		fformat = fformat64;
-		mnrflag = 3;
-		etrflag = 3;
-		printf( "Testing LONG DOUBLE precision.\n" );
-		break;
-#else
-		goto nodenorm;
-#endif
-	}
-
-	asctoe( Ten, eten );
-/* 10^m - 1 */
-	d2 = m;
-	e53toe( &d2, e1 );
-	epow( eten, e1, maxm );
-	esub( eone, maxm, maxm );
-
-/* test 1 */
-	printf( "1. Checking 10^n - 1 for n = %d to %d.\n", -m, m );
-	emov( eone, q5 );
-	for( count=0; count<=m; count++ )
-		{
-		esub( eone, q5, fullp );
-		chkit( 1 );
-		ediv( q5, eone, q2 );
-		esub( eone, q2, fullp );
-		chkit( 1 );
-		emul( eten, q5, q5 );
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto end1;
-			}
-		}
-end1:
-	printerr();
-
-
-/* test 2 */
-	printf( "2. Checking powers of 10 from 10^-%d to 10^%d.\n", n, n );
-	emov( eone, q5 );
-	for( count=0; count<=n; count++ )
-		{
-		emov( q5, fullp );
-		chkit( 2 );
-		ediv( q5, eone, fullp );
-		chkit( 2 );
-		emul( eten, q5, q5 );
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto end2;
-			}
-		}
-end2:
-	printerr();
-
-/* test 3 */
-	printf( "3. Checking (10^%d-1)*10^n from n = -%d to %d.\n", m, n, n );
-	emov( eone, q5 );
-	for( count= -n; count<=n; count++ )
-		{
-		emul( maxm, q5, fullp );
-		chkit( 3 );
-		emov( q5, fullp );
-		ediv( fullp, eone, fullp );
-		emul( maxm, fullp, fullp );
-		chkit( 3 );
-		emul( eten, q5, q5 );
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto end3;
-			}
-		}
-end3:
-	printerr();
-
-
-
-/* test 4 */
-	printf( "4. Checking powers of 2 from 2^-24 to 2^+56.\n" );
-	d1 = -24.0;
-	e53toe( &d1, q1 );
-	epow( etwo, q1, q5 );
-
-	for( count = -24; count <= 56; count++ )
-		{
-		emov( q5, fullp );
-		chkit( 4 );
-		emul( etwo, q5, q5 );
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto end4;
-			}
-		}
-end4:
-	printerr();
-
-
-/* test 5 */
-	printf( "5. Checking 2^n - 1 for n = 0 to %d.\n", mprec );
-	emov( eone, q5 );
-	for( count=0; count<=mprec; count++ )
-		{
-		esub( eone, q5, fullp );
-		chkit( 5 );
-		emul( etwo, q5, q5 );
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto end5;
-			}
-		}
-end5:
-	printerr();
-
-/* test 6 */
-	printf( "6. Checking 2^n + 1 for n = 0 to %d.\n", mprec );
-	emov( eone, q5 );
-	for( count=0; count<=mprec; count++ )
-		{
-		eadd( eone, q5, fullp );
-		chkit( 6 );
-		emul( etwo, q5, q5 );
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto end6;
-			}
-		}
-end6:
-	printerr();
-
-/* test 7 */
-	printf(
-	 "7. Checking %d values M * 10^N with random integer M and N,\n",
-	 NRAND );
-	printf("  1 <= M <= 10^%d - 1  and  -%d <= N <= +%d.\n", m, n, n );
-	for( i=0; i<NRAND; i++ )
-		{
-		mnrand( fullp );
-		chkit( 7 );
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto end7;
-			}
-		}
-end7:
-	printerr();
-
-/* test 8 */
-	printf("8. Checking critical rounding cases.\n" );
-	for( i=0; i<20; i++ )
-		{
-		mnrand( fullp );
-		eabs( fullp );
-		if( ecmp( fullp, eone ) < 0 )
-			ediv( fullp, eone, fullp );
-		efloor( fullp, fullp );
-		eadd( ehalf, fullp, fullp );
-		chkit( 8 );
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto end8;
-			}
-		}
-end8:
-	printerr();
-
-
-
-/* test 9 */
-	printf("9. Testing on %d random non-denormal values.\n", NRAND );
-	for( i=0; i<NRAND; i++ )
-		{
-		etrand( fullp );
-		chkit( 9 );
-		}
-	printerr();
-	shownoncrit();
-
-/* test 10 */
-	printf(
-	"Do you want to check denormal numbers in this precision ? (y/n) " );
-	gets( str0 );
-	if( str0[0] != 'y' )
-		goto nodenorm;
-
-	printf( "10. Checking denormal numbers.\n" );
-
-/* Form 2^-starting power */
-	d1 = k2;
-	e53toe( &d1, q1 );
-	epow( etwo, q1, e1 );
-
-/* Find 2^-mprec less than starting power */
-	d1 = -mprec + 4;
-	e53toe( &d1, q1 );
-	epow( etwo, q1, e3 );
-	emul( e1, e3, e3 );
-	emov( e3, e2 );
-	ediv( etwo, e2, e2 );
-
-	while( ecmp(e1,e2) != 0 )
-		{
-		eadd( e1, e2, fullp );
-		switch( mprec )
-			{
-#if LDOUBLE
-			case 64:
-			etoe64( e1, &sprec64 );
-			e64toe( &sprec64, q1 );
-			etoe64( fullp, &prec64 );
-			e64toe( &prec64, q2 );
-			break;
-#endif
-#ifdef DEC
-			case 56:
-#endif
-			case 53:
-			etoe53( e1, &sprec53 );
-			e53toe( &sprec53, q1 );
-			etoe53( fullp, &prec53 );
-			e53toe( &prec53, q2 );
-			break;
-
-			case 24:
-			etoe24( e1, &sprec24 );
-			e24toe( &sprec24, q1 );
-			etoe24( fullp, &prec24 );
-			e24toe( &prec24, q2 );
-			break;
-			}
-		if( ecmp( q2, ezero ) == 0 )
-			goto maxden;
-		chkit(10);
-		if( ecmp(q1,q2) == 0 )
-			{
-			ediv( etwo, e1, e1 );
-			emov( e3, e2 );
-			}
-		if( errtot >= MAXERR )
-			{
-			printf( "%s", toomany );
-			goto maxden;
-			}
-		ediv( etwo, e2, e2 );
-		}
-maxden:
-	printerr();
-nodenorm:
-	printf( "\n" );
-	} /* loop on precision */
-printf( "End of test.\n" );
-}
-
-#if CHKINTERNAL
-long double xprec64;
-double xprec53;
-float xprec24;
-
-/* Check binary -> printf -> scanf -> binary identity
- * of internal routines
- */
-void chkinternal( ref, tst, string )
-unsigned short ref[], tst[];
-char *string;
-{
-
-if( ecmp(ref,tst) != 0 )
-	{
-	printf( "internal identity compare error!\n" );
-	chkid( ref, tst, string );
-	}
-}
-#endif
-
-
-/* Check binary -> printf -> scanf -> binary identity
- */
-void chkid( print, scan, string )
-unsigned short print[], scan[];
-char *string;
-{
-/* Test printf-scanf identity */
-if( ecmp( print, scan ) != 0 )
-	{
-	pvec( print, NE );
-	printf( " ->printf-> %s ->scanf->\n", string );
-	pvec( scan, NE );
-	printf( " is not an identity.\n" );
-	++identerr;
-	}
-}
-
-
-/* Check scanf result
- */
-void chkscan( ref, tst, string )
-unsigned short ref[], tst[];
-char *string;
-{
-/* Test scanf()  */
-if( ecmp( ref, tst ) != 0 )
-	{
-	printf( "scanf(%s) -> ", string );
-	pvec( tst, NE );
-	printf( "\n should be    " );
-	pvec( ref, NE );
-	printf( ".\n" );
-	++errscan;
-	++errtot;
-	}
-}
-
-
-/* Test printf() result
- */
-void chkprint( ref, tst, string ) 
-unsigned short ref[], tst[];
-char *string;
-{
-if( ecmp(ref, tst) != 0 )
-	{
-	printf( "printf( ");
-	pvec( ref, NE );
-	printf( ") -> %s\n", string );
-	printf( "      = " );
-	pvec( tst, NE );
-	printf( ".\n" );
-	++errprint;
-	++errtot;
-	}
-}
-
-
-/* Print array of n 16-bit shorts
- */
-void pvec( x, n )
-unsigned short x[];
-int n;
-{
-int i;
-
-for( i=0; i<n; i++ )
-	{
-	printf( "%04x ", x[i] );
-	}
-}
-
-/* Measure worst case printf rounding error
- */
-void cmpprint( ref, tst )
-unsigned short ref[], tst[];
-{
-unsigned short e[NE];
-
-if( ecmp( ref, ezero ) != 0 )
-	{
-	esub( ref, tst, e );
-	ediv( ref, e, e );
-	eabs( e );
-	if( ecmp( e, rprint ) > 0 )
-		emov( e, rprint );
-	}
-}
-
-/* Measure worst case scanf rounding error
- */
-void cmpscan( ref, tst )
-unsigned short ref[], tst[];
-{
-unsigned short er[NE];
-
-if( ecmp( ref, ezero ) != 0 )
-	{
-	esub( ref, tst, er );
-	ediv( ref, er, er );
-	eabs( er );
-	if( ecmp( er, rscan ) > 0 )
-		emov( er, rscan );
-	if( ecmp( er, ehalf ) > 0 )
-		{
-		etoasc( tst, str1, 21 );
-		printf( "Bad error: scanf(%s) = %s !\n", str0, str1 );
-		}
-	}
-}
-
-/* Check rounded-down decimal string output of printf
- */
-void cmptrunc( ref, tst )
-unsigned short ref[], tst[];
-{
-if( ecmp( ref, tst ) != 0 )
-	{
-	printf( "printf(%s%s%s, %s) -> %s\n", quo, tformat, quo, str1, str2 );
-	printf( "should be      %s .\n", str3 );
-	errprint += 1;
-	}
-}
-
-
-void shownoncrit()
-{
-
-etoasc( rprint, str0, 3 );
-printf( "Maximum relative printf error found = %s .\n", str0 );
-etoasc( rscan, str0, 3 );
-printf( "Maximum relative scanf error found = %s .\n", str0 );
-}
-
-
-
-/* Produce arguments and call comparison subroutines.
- */
-void chkit( testno )
-int testno;
-{
-unsigned short t[NE], u[NE], v[NE];
-int j;
-
-switch( mprec )
-	{
-#if LDOUBLE
-	case 64:
-		etoe64( fullp, &prec64 );
-		e64toe( &prec64, rounded );
-#if CHKINTERNAL
-		e64toasc( &prec64, str1, SPREC );
-		asctoe64( str1, &xprec64 );
-		e64toe( &xprec64, t );
-		chkinternal( rounded, t, str1 );
-#endif
-/* check printf and scanf */
-		sprintf( str2, format, prec64 );
-		sscanf( str2, fformat, &sprec64 );
-		e64toe( &sprec64, u );
-		chkid( rounded, u, str2 );
-		asctoe64( str2, &ssprec64 );
-		e64toe( &ssprec64, v );
-		chkscan( v, u, str2 );
-		chkprint( rounded, v, str2 );
-		if( testno < 8 )
-			break;
-/* rounding error measurement */
-		etoasc( fullp, str0, 24 );
-		etoe64( fullp, &ssprec64 );
-		e64toe( &ssprec64, u );
-		sprintf( str2, format, ssprec64 );
-		asctoe( str2, t );
-		cmpprint( u, t );
-		sscanf( str0, fformat, &sprec64 );
-		e64toe( &sprec64, t );
-		cmpscan( fullp, t );
-		if( testno < 8 )
-			break;
-/* strings rounded to less than maximum precision */
-		e64toasc( &ssprec64, str1, 24 );
-		for( j=SPREC-1; j>0; j-- )		
-			{
-			e64toasc( &ssprec64, str3, j );
-			asctoe( str3, v );
-			sprintf( tformat, "%s.%dLe", pct, j );
-			sprintf( str2, tformat, ssprec64 );
-			asctoe( str2, t );
-			cmptrunc( v, t );
-			}
-		break;
-#endif
-#ifdef DEC
-	case 56:
-#endif
-	case 53:
-		etoe53( fullp, &prec53 );
-		e53toe( &prec53, rounded );
-#if CHKINTERNAL
-		e53toasc( &prec53, str1, SPREC );
-		asctoe53( str1, &xprec53 );
-		e53toe( &xprec53, t );
-		chkinternal( rounded, t, str1 );
-#endif
-		sprintf( str2, format, prec53 );
-		sscanf( str2, fformat, &sprec53 );
-		e53toe( &sprec53, u );
-		chkid( rounded, u, str2 );
-		asctoe53( str2, &ssprec53 );
-		e53toe( &ssprec53, v );
-		chkscan( v, u, str2 );
-		chkprint( rounded, v, str2 );
-		if( testno < 8 )
-			break;
-/* rounding error measurement */
-		etoasc( fullp, str0, 24 );
-		etoe53( fullp, &ssprec53 );
-		e53toe( &ssprec53, u );
-		sprintf( str2, format, ssprec53 );
-		asctoe( str2, t );
-		cmpprint( u, t );
-		sscanf( str0, fformat, &sprec53 );
-		e53toe( &sprec53, t );
-		cmpscan( fullp, t );
-		if( testno < 8 )
-			break;
-		e53toasc( &ssprec53, str1, 24 );
-		for( j=SPREC-1; j>0; j-- )		
-			{
-			e53toasc( &ssprec53, str3, j );
-			asctoe( str3, v );
-			sprintf( tformat, "%s.%de", pct, j );
-			sprintf( str2, tformat, ssprec53 );
-			asctoe( str2, t );
-			cmptrunc( v, t );
-			}
-		break;
-
-	case 24:
-		etoe24( fullp, &prec24 );
-		e24toe( &prec24, rounded );
-#if CHKINTERNAL
-		e24toasc( &prec24, str1, SPREC );
-		asctoe24( str1, &xprec24 );
-		e24toe( &xprec24, t );
-		chkinternal( rounded, t, str1 );
-#endif
-		sprintf( str2, format, prec24 );
-		sscanf( str2, fformat, &sprec24 );
-		e24toe( &sprec24, u );
-		chkid( rounded, u, str2 );
-		asctoe24( str2, &ssprec24 );
-		e24toe( &ssprec24, v );
-		chkscan( v, u, str2 );
-		chkprint( rounded, v, str2 );
-		if( testno < 8 )
-			break;
-/* rounding error measurement */
-		etoasc( fullp, str0, 24 );
-		etoe24( fullp, &ssprec24 );
-		e24toe( &ssprec24, u );
-		sprintf( str2, format, ssprec24 );
-		asctoe( str2, t );
-		cmpprint( u, t );
-		sscanf( str0, fformat, &sprec24 );
-		e24toe( &sprec24, t );
-		cmpscan( fullp, t );
-/*
-		if( testno < 8 )
-			break;
-*/
-		e24toasc( &ssprec24, str1, 24 );
-		for( j=SPREC-1; j>0; j-- )		
-			{
-			e24toasc( &ssprec24, str3, j );
-			asctoe( str3, v );
-			sprintf( tformat, "%s.%de", pct, j );
-			sprintf( str2, tformat, ssprec24 );
-			asctoe( str2, t );
-			cmptrunc( v, t );
-			}
-		break;
-	}
-}
-
-
-void printerr()
-{
-if( (errscan == 0) && (identerr == 0) && (errprint == 0) )
-	printf( "No errors found.\n" );
-else
-	{
-	printf( "%d binary -> decimal errors found.\n", errprint );
-	printf( "%d decimal -> binary errors found.\n", errscan );
-	}
-errscan = 0;	/* reset for next test */
-identerr = 0;
-errprint = 0;
-errtot = 0;
-}
-
-
-/* Random number generator
- * in the range M * 10^N, where 1 <= M <= 10^17 - 1
- * and -27 <= N <= +27.  Test values of M are logarithmically distributed
- * random integers; test values of N are uniformly distributed random integers.
- */
-
-static char *fwidth = "1.036163291797320557783096e1"; /* log(sqrt(10^9-1)) */
-static char *dwidth = "1.957197329044938830915E1"; /* log(sqrt(10^17-1)) */
-static char *ldwidth = "2.302585092994045684017491e1"; /* log(sqrt(10^20-1)) */
-
-static char *a13 = "13.0";
-static char *a27 = "27.0";
-static char *a34 = "34.0";
-static char *a10m13 = "1.0e-13";
-static unsigned short LOW[ NE ], WIDTH[NE], e27[NE], e10m13[NE];
-
-
-void mnrand( erand )
-unsigned short erand[];
-{
-unsigned short ea[NE], em[NE], en[NE], ex[NE];
-double x, a;
-
-if( mnrflag )
-	{
-	if( mnrflag == 3 )
-		{
-		asctoe( ldwidth, WIDTH );
-		asctoe( a34, e27 );
-		}
-	if( mnrflag == 2 )
-		{
-		asctoe( dwidth, WIDTH );
-		asctoe( a27, e27 );
-		}
-	if( mnrflag == 1 )
-		{
-		asctoe( fwidth, WIDTH );
-		asctoe( a13, e27 );
-		}
-	asctoe( a10m13, e10m13 );
-	mnrflag = 0;
-	}
-drand( &x );
-e53toe( &x, ex ); /* x = WIDTH *  ( x - 1.0 )  +  LOW; */
-esub( eone, ex, ex );
-emul( WIDTH, ex, ex );
-eexp( ex, ex );   /* x = exp(x); */
-
-drand( &a );
-e53toe( &a, ea );
-emul( ea, ex, ea );  /* a = 1.0e-13 * x * a; */
-emul( e10m13, ea, ea );
-eabs( ea );
-eadd( ea, ex, ex );	/* add fuzz */
-emul( ex, ex, ex );	/* square it, to get range to 10^17 - 1 */
-efloor( ex, em ); /* this is M */
-
-/* Random power of 10 */
-drand( &a );
-e53toe( &a, ex );
-esub( eone, ex, ex ); /* y3 = 54.0 *  ( y3 - 1.0 ) + 0.5; */
-emul( e27, ex, ex );
-eadd( ex, ex, ex );
-eadd( ehalf, ex, ex );
-efloor( ex, ex ); /* y3 = floor( y3 ) - 27.0; */
-esub( e27, ex, en ); /* this is N */
-epow( eten, en, ex );
-emul( ex, em, erand );
-}
-
-/* -ln 2^16382 */
-char *ldemin = "-1.1355137111933024058873097E4";
-char *ldewid =  "2.2710274223866048117746193E4";
-/* -ln 2^1022 */
-char *demin  = "-7.0839641853226410622441123E2";
-char *dewid  =  "1.4167928370645282124488225E3";
-/* -ln 2^125 */
-char *femin  = "-8.6643397569993163677154015E1";
-char *fewid  =  "1.7328679513998632735430803E2";
-
-void etrand( erand )
-unsigned short erand[];
-{
-unsigned short ea[NE], ex[NE];
-double x, a;
-
-if( etrflag )
-	{
-	if( etrflag == 3 )
-		{
-		asctoe( ldemin, LOW );
-		asctoe( ldewid, WIDTH );
-		asctoe( a34, e27 );
-		}
-	if( etrflag == 2 )
-		{
-		asctoe( demin, LOW );
-		asctoe( dewid, WIDTH );
-		asctoe( a27, e27 );
-		}
-	if( etrflag == 1 )
-		{
-		asctoe( femin, LOW );
-		asctoe( fewid, WIDTH );
-		asctoe( a13, e27 );
-		}
-	asctoe( a10m13, e10m13 );
-	etrflag = 0;
-	}
-drand( &x );
-e53toe( &x, ex ); /* x = WIDTH *  ( x - 1.0 )  +  LOW; */
-esub( eone, ex, ex );
-emul( WIDTH, ex, ex );
-eadd( LOW, ex, ex );
-eexp( ex, ex );   /* x = exp(x); */
-
-/* add fuzz
- */
-drand( &a );
-e53toe( &a, ea );
-emul( ea, ex, ea );  /* a = 1.0e-13 * x * a; */
-emul( e10m13, ea, ea );
-if( ecmp( ex, ezero ) > 0 )
-	eneg( ea );
-eadd( ea, ex, erand );
-}
-
+/* Floating point to ASCII input and output string test program.
+ *
+ * Numbers in the native machine data structure are converted
+ * to e type, then to and from decimal ASCII strings.  Native
+ * printf() and scanf() functions are also used to produce
+ * and read strings.  The resulting e type binary values
+ * are compared, with diagnostic printouts of any discrepancies.
+ *
+ * Steve Moshier, 16 Dec 88
+ * last revision: 16 May 92
+ */
+
+#include "ehead.h"
+#include "mconf.h"
+
+/* Include tests of 80-bit long double precision: */
+#define LDOUBLE 0
+/* Abort subtest after getting this many errors: */
+#define MAXERR 5
+/* Number of random arguments to try (set as large as you have
+ * patience for): */
+#define NRAND 100
+/* Perform internal consistency test: */
+#define CHKINTERNAL 0
+
+static unsigned short fullp[NE], rounded[NE];
+float prec24, sprec24, ssprec24;
+double prec53, sprec53, ssprec53;
+#if LDOUBLE
+long double prec64, sprec64, ssprec64;
+#endif
+
+static unsigned short rprint[NE], rscan[NE];
+static unsigned short q1[NE], q2[NE], q5[NE];
+static unsigned short e1[NE], e2[NE], e3[NE];
+static double d1, d2;
+static int errprint = 0;
+static int errscan = 0;
+static int identerr = 0;
+static int errtot = 0;
+static int count = 0;
+static char str0[80], str1[80], str2[80], str3[80];
+static unsigned short eten[NE], maxm[NE];
+
+int m, n, k2, mprec, SPREC;
+
+char *Ten = "10.0";
+char tformat[10];
+char *format24 = "%.8e";
+#ifdef DEC
+char *format53 = "%.17e";
+#else
+char *format53 = "%.16e";
+#endif
+char *fformat24 = "%e";
+char *fformat53 = "%le";
+char *pct = "%";
+char *quo = "\042";
+#if LDOUBLE
+char *format64 = "%.20Le";
+char *fformat64 = "%Le";
+#endif
+char *format;
+char *fformat;
+char *toomany = "Too many errors; aborting this test.\n";
+
+static int mnrflag;
+static int etrflag;
+void chkit(), printerr(), mnrand(), etrand(), shownoncrit();
+void chkid(), pvec();
+
+main()
+{
+int i, iprec;
+
+printf( "Steve Moshier's printf/scanf tester, version 0.2.\n\n" );
+#ifdef DEC
+ /* DEC PDP-11/VAX single precision not yet implemented */
+for( iprec = 1; iprec<2; iprec++ )
+#else
+for( iprec = 0; iprec<3; iprec++ )
+#endif
+	{
+	errscan = 0;
+	identerr = 0;
+	errprint = 0;
+	eclear( rprint );
+	eclear( rscan );
+
+switch( iprec )
+	{
+	case 0:
+		SPREC = 8; /* # digits after the decimal point */
+		mprec = 24; /* # bits in the significand */
+		m = 9; /* max # decimal digits for correct rounding */
+		n = 13; /* max power of ten for correct rounding */
+		k2 = -125; /* underflow beyond 2^-k2 */
+		format = format24; /* printf format string */
+		fformat = fformat24; /* scanf format string */
+		mnrflag = 1; /* sets interval for random numbers */
+		etrflag = 1;
+		printf( "Testing FLOAT precision.\n" );
+		break;
+
+	case 1:
+#ifdef DEC
+		SPREC = 17;
+		mprec = 56;
+		m = 17;
+		n = 27;
+		k2 = -125;
+		format = format53;
+		fformat = fformat53;
+		mnrflag = 2;
+		etrflag = 1;
+		printf( "Testing DEC DOUBLE precision.\n" );
+		break;
+#else
+		SPREC = 16;
+		mprec = 53;
+		m = 17;
+		n = 27;
+		k2 = -1021;
+		format = format53;
+		fformat = fformat53;
+		mnrflag = 2;
+		etrflag = 2;
+		printf( "Testing DOUBLE precision.\n" );
+		break;
+#endif
+	case 2:
+#if LDOUBLE
+		SPREC = 20;
+		mprec = 64;
+		m = 20;
+		n = 34;
+		k2 = -16382;
+		format = format64;
+		fformat = fformat64;
+		mnrflag = 3;
+		etrflag = 3;
+		printf( "Testing LONG DOUBLE precision.\n" );
+		break;
+#else
+		goto nodenorm;
+#endif
+	}
+
+	asctoe( Ten, eten );
+/* 10^m - 1 */
+	d2 = m;
+	e53toe( &d2, e1 );
+	epow( eten, e1, maxm );
+	esub( eone, maxm, maxm );
+
+/* test 1 */
+	printf( "1. Checking 10^n - 1 for n = %d to %d.\n", -m, m );
+	emov( eone, q5 );
+	for( count=0; count<=m; count++ )
+		{
+		esub( eone, q5, fullp );
+		chkit( 1 );
+		ediv( q5, eone, q2 );
+		esub( eone, q2, fullp );
+		chkit( 1 );
+		emul( eten, q5, q5 );
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto end1;
+			}
+		}
+end1:
+	printerr();
+
+
+/* test 2 */
+	printf( "2. Checking powers of 10 from 10^-%d to 10^%d.\n", n, n );
+	emov( eone, q5 );
+	for( count=0; count<=n; count++ )
+		{
+		emov( q5, fullp );
+		chkit( 2 );
+		ediv( q5, eone, fullp );
+		chkit( 2 );
+		emul( eten, q5, q5 );
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto end2;
+			}
+		}
+end2:
+	printerr();
+
+/* test 3 */
+	printf( "3. Checking (10^%d-1)*10^n from n = -%d to %d.\n", m, n, n );
+	emov( eone, q5 );
+	for( count= -n; count<=n; count++ )
+		{
+		emul( maxm, q5, fullp );
+		chkit( 3 );
+		emov( q5, fullp );
+		ediv( fullp, eone, fullp );
+		emul( maxm, fullp, fullp );
+		chkit( 3 );
+		emul( eten, q5, q5 );
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto end3;
+			}
+		}
+end3:
+	printerr();
+
+
+
+/* test 4 */
+	printf( "4. Checking powers of 2 from 2^-24 to 2^+56.\n" );
+	d1 = -24.0;
+	e53toe( &d1, q1 );
+	epow( etwo, q1, q5 );
+
+	for( count = -24; count <= 56; count++ )
+		{
+		emov( q5, fullp );
+		chkit( 4 );
+		emul( etwo, q5, q5 );
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto end4;
+			}
+		}
+end4:
+	printerr();
+
+
+/* test 5 */
+	printf( "5. Checking 2^n - 1 for n = 0 to %d.\n", mprec );
+	emov( eone, q5 );
+	for( count=0; count<=mprec; count++ )
+		{
+		esub( eone, q5, fullp );
+		chkit( 5 );
+		emul( etwo, q5, q5 );
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto end5;
+			}
+		}
+end5:
+	printerr();
+
+/* test 6 */
+	printf( "6. Checking 2^n + 1 for n = 0 to %d.\n", mprec );
+	emov( eone, q5 );
+	for( count=0; count<=mprec; count++ )
+		{
+		eadd( eone, q5, fullp );
+		chkit( 6 );
+		emul( etwo, q5, q5 );
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto end6;
+			}
+		}
+end6:
+	printerr();
+
+/* test 7 */
+	printf(
+	 "7. Checking %d values M * 10^N with random integer M and N,\n",
+	 NRAND );
+	printf("  1 <= M <= 10^%d - 1  and  -%d <= N <= +%d.\n", m, n, n );
+	for( i=0; i<NRAND; i++ )
+		{
+		mnrand( fullp );
+		chkit( 7 );
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto end7;
+			}
+		}
+end7:
+	printerr();
+
+/* test 8 */
+	printf("8. Checking critical rounding cases.\n" );
+	for( i=0; i<20; i++ )
+		{
+		mnrand( fullp );
+		eabs( fullp );
+		if( ecmp( fullp, eone ) < 0 )
+			ediv( fullp, eone, fullp );
+		efloor( fullp, fullp );
+		eadd( ehalf, fullp, fullp );
+		chkit( 8 );
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto end8;
+			}
+		}
+end8:
+	printerr();
+
+
+
+/* test 9 */
+	printf("9. Testing on %d random non-denormal values.\n", NRAND );
+	for( i=0; i<NRAND; i++ )
+		{
+		etrand( fullp );
+		chkit( 9 );
+		}
+	printerr();
+	shownoncrit();
+
+/* test 10 */
+	printf(
+	"Do you want to check denormal numbers in this precision ? (y/n) " );
+	gets( str0 );
+	if( str0[0] != 'y' )
+		goto nodenorm;
+
+	printf( "10. Checking denormal numbers.\n" );
+
+/* Form 2^-starting power */
+	d1 = k2;
+	e53toe( &d1, q1 );
+	epow( etwo, q1, e1 );
+
+/* Find 2^-mprec less than starting power */
+	d1 = -mprec + 4;
+	e53toe( &d1, q1 );
+	epow( etwo, q1, e3 );
+	emul( e1, e3, e3 );
+	emov( e3, e2 );
+	ediv( etwo, e2, e2 );
+
+	while( ecmp(e1,e2) != 0 )
+		{
+		eadd( e1, e2, fullp );
+		switch( mprec )
+			{
+#if LDOUBLE
+			case 64:
+			etoe64( e1, &sprec64 );
+			e64toe( &sprec64, q1 );
+			etoe64( fullp, &prec64 );
+			e64toe( &prec64, q2 );
+			break;
+#endif
+#ifdef DEC
+			case 56:
+#endif
+			case 53:
+			etoe53( e1, &sprec53 );
+			e53toe( &sprec53, q1 );
+			etoe53( fullp, &prec53 );
+			e53toe( &prec53, q2 );
+			break;
+
+			case 24:
+			etoe24( e1, &sprec24 );
+			e24toe( &sprec24, q1 );
+			etoe24( fullp, &prec24 );
+			e24toe( &prec24, q2 );
+			break;
+			}
+		if( ecmp( q2, ezero ) == 0 )
+			goto maxden;
+		chkit(10);
+		if( ecmp(q1,q2) == 0 )
+			{
+			ediv( etwo, e1, e1 );
+			emov( e3, e2 );
+			}
+		if( errtot >= MAXERR )
+			{
+			printf( "%s", toomany );
+			goto maxden;
+			}
+		ediv( etwo, e2, e2 );
+		}
+maxden:
+	printerr();
+nodenorm:
+	printf( "\n" );
+	} /* loop on precision */
+printf( "End of test.\n" );
+}
+
+#if CHKINTERNAL
+long double xprec64;
+double xprec53;
+float xprec24;
+
+/* Check binary -> printf -> scanf -> binary identity
+ * of internal routines
+ */
+void chkinternal( ref, tst, string )
+unsigned short ref[], tst[];
+char *string;
+{
+
+if( ecmp(ref,tst) != 0 )
+	{
+	printf( "internal identity compare error!\n" );
+	chkid( ref, tst, string );
+	}
+}
+#endif
+
+
+/* Check binary -> printf -> scanf -> binary identity
+ */
+void chkid( print, scan, string )
+unsigned short print[], scan[];
+char *string;
+{
+/* Test printf-scanf identity */
+if( ecmp( print, scan ) != 0 )
+	{
+	pvec( print, NE );
+	printf( " ->printf-> %s ->scanf->\n", string );
+	pvec( scan, NE );
+	printf( " is not an identity.\n" );
+	++identerr;
+	}
+}
+
+
+/* Check scanf result
+ */
+void chkscan( ref, tst, string )
+unsigned short ref[], tst[];
+char *string;
+{
+/* Test scanf()  */
+if( ecmp( ref, tst ) != 0 )
+	{
+	printf( "scanf(%s) -> ", string );
+	pvec( tst, NE );
+	printf( "\n should be    " );
+	pvec( ref, NE );
+	printf( ".\n" );
+	++errscan;
+	++errtot;
+	}
+}
+
+
+/* Test printf() result
+ */
+void chkprint( ref, tst, string ) 
+unsigned short ref[], tst[];
+char *string;
+{
+if( ecmp(ref, tst) != 0 )
+	{
+	printf( "printf( ");
+	pvec( ref, NE );
+	printf( ") -> %s\n", string );
+	printf( "      = " );
+	pvec( tst, NE );
+	printf( ".\n" );
+	++errprint;
+	++errtot;
+	}
+}
+
+
+/* Print array of n 16-bit shorts
+ */
+void pvec( x, n )
+unsigned short x[];
+int n;
+{
+int i;
+
+for( i=0; i<n; i++ )
+	{
+	printf( "%04x ", x[i] );
+	}
+}
+
+/* Measure worst case printf rounding error
+ */
+void cmpprint( ref, tst )
+unsigned short ref[], tst[];
+{
+unsigned short e[NE];
+
+if( ecmp( ref, ezero ) != 0 )
+	{
+	esub( ref, tst, e );
+	ediv( ref, e, e );
+	eabs( e );
+	if( ecmp( e, rprint ) > 0 )
+		emov( e, rprint );
+	}
+}
+
+/* Measure worst case scanf rounding error
+ */
+void cmpscan( ref, tst )
+unsigned short ref[], tst[];
+{
+unsigned short er[NE];
+
+if( ecmp( ref, ezero ) != 0 )
+	{
+	esub( ref, tst, er );
+	ediv( ref, er, er );
+	eabs( er );
+	if( ecmp( er, rscan ) > 0 )
+		emov( er, rscan );
+	if( ecmp( er, ehalf ) > 0 )
+		{
+		etoasc( tst, str1, 21 );
+		printf( "Bad error: scanf(%s) = %s !\n", str0, str1 );
+		}
+	}
+}
+
+/* Check rounded-down decimal string output of printf
+ */
+void cmptrunc( ref, tst )
+unsigned short ref[], tst[];
+{
+if( ecmp( ref, tst ) != 0 )
+	{
+	printf( "printf(%s%s%s, %s) -> %s\n", quo, tformat, quo, str1, str2 );
+	printf( "should be      %s .\n", str3 );
+	errprint += 1;
+	}
+}
+
+
+void shownoncrit()
+{
+
+etoasc( rprint, str0, 3 );
+printf( "Maximum relative printf error found = %s .\n", str0 );
+etoasc( rscan, str0, 3 );
+printf( "Maximum relative scanf error found = %s .\n", str0 );
+}
+
+
+
+/* Produce arguments and call comparison subroutines.
+ */
+void chkit( testno )
+int testno;
+{
+unsigned short t[NE], u[NE], v[NE];
+int j;
+
+switch( mprec )
+	{
+#if LDOUBLE
+	case 64:
+		etoe64( fullp, &prec64 );
+		e64toe( &prec64, rounded );
+#if CHKINTERNAL
+		e64toasc( &prec64, str1, SPREC );
+		asctoe64( str1, &xprec64 );
+		e64toe( &xprec64, t );
+		chkinternal( rounded, t, str1 );
+#endif
+/* check printf and scanf */
+		sprintf( str2, format, prec64 );
+		sscanf( str2, fformat, &sprec64 );
+		e64toe( &sprec64, u );
+		chkid( rounded, u, str2 );
+		asctoe64( str2, &ssprec64 );
+		e64toe( &ssprec64, v );
+		chkscan( v, u, str2 );
+		chkprint( rounded, v, str2 );
+		if( testno < 8 )
+			break;
+/* rounding error measurement */
+		etoasc( fullp, str0, 24 );
+		etoe64( fullp, &ssprec64 );
+		e64toe( &ssprec64, u );
+		sprintf( str2, format, ssprec64 );
+		asctoe( str2, t );
+		cmpprint( u, t );
+		sscanf( str0, fformat, &sprec64 );
+		e64toe( &sprec64, t );
+		cmpscan( fullp, t );
+		if( testno < 8 )
+			break;
+/* strings rounded to less than maximum precision */
+		e64toasc( &ssprec64, str1, 24 );
+		for( j=SPREC-1; j>0; j-- )		
+			{
+			e64toasc( &ssprec64, str3, j );
+			asctoe( str3, v );
+			sprintf( tformat, "%s.%dLe", pct, j );
+			sprintf( str2, tformat, ssprec64 );
+			asctoe( str2, t );
+			cmptrunc( v, t );
+			}
+		break;
+#endif
+#ifdef DEC
+	case 56:
+#endif
+	case 53:
+		etoe53( fullp, &prec53 );
+		e53toe( &prec53, rounded );
+#if CHKINTERNAL
+		e53toasc( &prec53, str1, SPREC );
+		asctoe53( str1, &xprec53 );
+		e53toe( &xprec53, t );
+		chkinternal( rounded, t, str1 );
+#endif
+		sprintf( str2, format, prec53 );
+		sscanf( str2, fformat, &sprec53 );
+		e53toe( &sprec53, u );
+		chkid( rounded, u, str2 );
+		asctoe53( str2, &ssprec53 );
+		e53toe( &ssprec53, v );
+		chkscan( v, u, str2 );
+		chkprint( rounded, v, str2 );
+		if( testno < 8 )
+			break;
+/* rounding error measurement */
+		etoasc( fullp, str0, 24 );
+		etoe53( fullp, &ssprec53 );
+		e53toe( &ssprec53, u );
+		sprintf( str2, format, ssprec53 );
+		asctoe( str2, t );
+		cmpprint( u, t );
+		sscanf( str0, fformat, &sprec53 );
+		e53toe( &sprec53, t );
+		cmpscan( fullp, t );
+		if( testno < 8 )
+			break;
+		e53toasc( &ssprec53, str1, 24 );
+		for( j=SPREC-1; j>0; j-- )		
+			{
+			e53toasc( &ssprec53, str3, j );
+			asctoe( str3, v );
+			sprintf( tformat, "%s.%de", pct, j );
+			sprintf( str2, tformat, ssprec53 );
+			asctoe( str2, t );
+			cmptrunc( v, t );
+			}
+		break;
+
+	case 24:
+		etoe24( fullp, &prec24 );
+		e24toe( &prec24, rounded );
+#if CHKINTERNAL
+		e24toasc( &prec24, str1, SPREC );
+		asctoe24( str1, &xprec24 );
+		e24toe( &xprec24, t );
+		chkinternal( rounded, t, str1 );
+#endif
+		sprintf( str2, format, prec24 );
+		sscanf( str2, fformat, &sprec24 );
+		e24toe( &sprec24, u );
+		chkid( rounded, u, str2 );
+		asctoe24( str2, &ssprec24 );
+		e24toe( &ssprec24, v );
+		chkscan( v, u, str2 );
+		chkprint( rounded, v, str2 );
+		if( testno < 8 )
+			break;
+/* rounding error measurement */
+		etoasc( fullp, str0, 24 );
+		etoe24( fullp, &ssprec24 );
+		e24toe( &ssprec24, u );
+		sprintf( str2, format, ssprec24 );
+		asctoe( str2, t );
+		cmpprint( u, t );
+		sscanf( str0, fformat, &sprec24 );
+		e24toe( &sprec24, t );
+		cmpscan( fullp, t );
+/*
+		if( testno < 8 )
+			break;
+*/
+		e24toasc( &ssprec24, str1, 24 );
+		for( j=SPREC-1; j>0; j-- )		
+			{
+			e24toasc( &ssprec24, str3, j );
+			asctoe( str3, v );
+			sprintf( tformat, "%s.%de", pct, j );
+			sprintf( str2, tformat, ssprec24 );
+			asctoe( str2, t );
+			cmptrunc( v, t );
+			}
+		break;
+	}
+}
+
+
+void printerr()
+{
+if( (errscan == 0) && (identerr == 0) && (errprint == 0) )
+	printf( "No errors found.\n" );
+else
+	{
+	printf( "%d binary -> decimal errors found.\n", errprint );
+	printf( "%d decimal -> binary errors found.\n", errscan );
+	}
+errscan = 0;	/* reset for next test */
+identerr = 0;
+errprint = 0;
+errtot = 0;
+}
+
+
+/* Random number generator
+ * in the range M * 10^N, where 1 <= M <= 10^17 - 1
+ * and -27 <= N <= +27.  Test values of M are logarithmically distributed
+ * random integers; test values of N are uniformly distributed random integers.
+ */
+
+static char *fwidth = "1.036163291797320557783096e1"; /* log(sqrt(10^9-1)) */
+static char *dwidth = "1.957197329044938830915E1"; /* log(sqrt(10^17-1)) */
+static char *ldwidth = "2.302585092994045684017491e1"; /* log(sqrt(10^20-1)) */
+
+static char *a13 = "13.0";
+static char *a27 = "27.0";
+static char *a34 = "34.0";
+static char *a10m13 = "1.0e-13";
+static unsigned short LOW[ NE ], WIDTH[NE], e27[NE], e10m13[NE];
+
+
+void mnrand( erand )
+unsigned short erand[];
+{
+unsigned short ea[NE], em[NE], en[NE], ex[NE];
+double x, a;
+
+if( mnrflag )
+	{
+	if( mnrflag == 3 )
+		{
+		asctoe( ldwidth, WIDTH );
+		asctoe( a34, e27 );
+		}
+	if( mnrflag == 2 )
+		{
+		asctoe( dwidth, WIDTH );
+		asctoe( a27, e27 );
+		}
+	if( mnrflag == 1 )
+		{
+		asctoe( fwidth, WIDTH );
+		asctoe( a13, e27 );
+		}
+	asctoe( a10m13, e10m13 );
+	mnrflag = 0;
+	}
+drand( &x );
+e53toe( &x, ex ); /* x = WIDTH *  ( x - 1.0 )  +  LOW; */
+esub( eone, ex, ex );
+emul( WIDTH, ex, ex );
+eexp( ex, ex );   /* x = exp(x); */
+
+drand( &a );
+e53toe( &a, ea );
+emul( ea, ex, ea );  /* a = 1.0e-13 * x * a; */
+emul( e10m13, ea, ea );
+eabs( ea );
+eadd( ea, ex, ex );	/* add fuzz */
+emul( ex, ex, ex );	/* square it, to get range to 10^17 - 1 */
+efloor( ex, em ); /* this is M */
+
+/* Random power of 10 */
+drand( &a );
+e53toe( &a, ex );
+esub( eone, ex, ex ); /* y3 = 54.0 *  ( y3 - 1.0 ) + 0.5; */
+emul( e27, ex, ex );
+eadd( ex, ex, ex );
+eadd( ehalf, ex, ex );
+efloor( ex, ex ); /* y3 = floor( y3 ) - 27.0; */
+esub( e27, ex, en ); /* this is N */
+epow( eten, en, ex );
+emul( ex, em, erand );
+}
+
+/* -ln 2^16382 */
+char *ldemin = "-1.1355137111933024058873097E4";
+char *ldewid =  "2.2710274223866048117746193E4";
+/* -ln 2^1022 */
+char *demin  = "-7.0839641853226410622441123E2";
+char *dewid  =  "1.4167928370645282124488225E3";
+/* -ln 2^125 */
+char *femin  = "-8.6643397569993163677154015E1";
+char *fewid  =  "1.7328679513998632735430803E2";
+
+void etrand( erand )
+unsigned short erand[];
+{
+unsigned short ea[NE], ex[NE];
+double x, a;
+
+if( etrflag )
+	{
+	if( etrflag == 3 )
+		{
+		asctoe( ldemin, LOW );
+		asctoe( ldewid, WIDTH );
+		asctoe( a34, e27 );
+		}
+	if( etrflag == 2 )
+		{
+		asctoe( demin, LOW );
+		asctoe( dewid, WIDTH );
+		asctoe( a27, e27 );
+		}
+	if( etrflag == 1 )
+		{
+		asctoe( femin, LOW );
+		asctoe( fewid, WIDTH );
+		asctoe( a13, e27 );
+		}
+	asctoe( a10m13, e10m13 );
+	etrflag = 0;
+	}
+drand( &x );
+e53toe( &x, ex ); /* x = WIDTH *  ( x - 1.0 )  +  LOW; */
+esub( eone, ex, ex );
+emul( WIDTH, ex, ex );
+eadd( LOW, ex, ex );
+eexp( ex, ex );   /* x = exp(x); */
+
+/* add fuzz
+ */
+drand( &a );
+e53toe( &a, ea );
+emul( ea, ex, ea );  /* a = 1.0e-13 * x * a; */
+emul( e10m13, ea, ea );
+if( ecmp( ex, ezero ) > 0 )
+	eneg( ea );
+eadd( ea, ex, erand );
+}
+

+ 132 - 132
test/math/ieetst.doc

@@ -1,132 +1,132 @@
-
-                  ieetst, version 0.2
-
-   This software tests the numerical accuracy of floating point
-binary <-> decimal string conversion, as done by your C language
-library functions printf() and scanf(), for compliance with the
-IEEE arithmetic standards ANSI/IEEE Std 754-1985 and ANSI/IEEE
-Std 854-1987.  The test covers 32-bit float, 64-bit double, and
-80-bit long double precision conversions to and from decimal
-ASCII strings.
-
-   The test program checks for proper implementation of the
-following specifications of the standards:
-
-   (1) correctly rounded conversions of numbers of the form M *
-   10^N, where M and N are integers such that, in double precision,
-   for example, |M| < 10^17, |N| <= 27.
-
-   (2) binary -> decimal -> binary conversions to be an identity
-   if a sufficiently large number of decimal digits is requested.
-
-   (3) correctly rounded decimal outputs of less than the maximum
-   number of digits
-
-   (4) The maximum observed conversion error of numbers outside the
-   domain covered by (1) is reported by the test program; it is
-   not supposed to exceed 0.97 ulp.
-
-There are 10 separate tests.  Tests 1 through 6 use values near
-2^n and 10^n.  Test 7 addresses item (1) above.  Test 8 checks
-the rounding of exact half-integer numbers. Test 9 is for item
-(4) above.  Test 10 checks denormal numbers.  Tests 8 through 10
-address item (3) using printf formats that produce outputs of 1,
-2, 3, ... digits after the decimal point.  All tests check, when
-appropriate, that the binary output of scanf is the same as the
-binary input to printf, item (2).
-
-Example error messages:
-
-   0000 0000 0000 1000 8000 3f80 ->printf-> 5.87748296e-39 ->scanf->
-   0000 0000 0000 0000 8000 3f6e  is not an identity.
-
-   scanf(-9.9999900000000003e-01) -> 0000 4800 085f ef39 ffff bffe 
-   should be 0000 5000 085f ef39 ffff bffe .
-
-   printf("%.14e",  6.13592315154256467968352E-3) -> 6.13592315154257e-03
-   should be       6.13592315154256E-3 .
-
-Binary values are displayed as four-digit hex groups in the
-little-endian format of the internal reference arithmetic. The
-least significant 16-bit word is first, the exponent is last.
-
-   The design of the test program requires knowing the binary
-data structure of the floating point format under test.  For
-configuration, check the .h files carefully. All the programs
-need to be told via mconf.h if the numeric format is
-little-endian (IBMPC) or big-endian (MIEEE).  If your system
-supports an 80-bit long double precision data type, define
-LDOUBLE 1 in ieetst.c; otherwise define LDOUBLE 0.  A provision
-for DEC PDP-11/VAX numbers is implemented (double precision
-only).  Conversions for other data structures can be added by
-analogy to the ifdefs for DEC.
-
-   Most of the tests rely on comparison with the results of a
-portable reference arithmetic, contained in the file ieee.c. 
-This is configured for an 80-bit significand, to have enough
-precision to satisfy the conversion requirements of IEEE 854 for
-the extended double format of IEEE 754.  The reference arithmetic
-includes binary <--> ASCII conversion routines and single <-->
-double <--> extended double conversions.  A strictly rounded
-square root function is given in esqrt.c.  Additional functions
-are provided by elog.c, eexp.c, etanh.c, epow.c, all of which
-call on ieee.c for their arithmetic.  Some of the ANSI C
-functions are supplied in ieee.c; for example, efloor(),
-efrexp(), eldexp(). The functions and the reference arithmetic
-are described further in the book _Methods and Programs for
-Mathematical Functions_ (Prentice-Hall or Simon & Schuster
-International, 1989), by S. L. Moshier.
-
-   As an aid in diagnosis, a calculator program, ecalc.c, is
-supplied.  It uses ieee.c for its arithmetic. Documentation for
-the calculator's user interface is in the file calc100.doc
-(calc100 is a fuller featured 100-digit version of ecalc).  The
-calculator needs to be told by qcalc.h if addresses are 32 bits
-long (define LARGEMEM 1) or 16 bits long (define LARGEMEM 0).
-
-   Because the source code of ieee.c is included here, a version
-of W. Kahan's PARANOIA is also provided; this has been heavily
-modified by substituting subroutine calls to ieee.c in place of
-all arithmetic operators.  It is important that you use PARANOIA
-to check the arithmetic after any modifications you may make to
-ieee.c.
-
-   Several systems have been tested with the initial version of
-ieetst.  Sun 4 (SPARC) passes; DEC VMS C has only a small flaw;
-Microsoft flunks; ATT SysVR2 (Motorola) flunks even worse.
-
-
-   Files:
-
-calc100.doc     calculator documentaton
-descrip.mms     part of VAX VMS makefile
-drand.c         random number generator
-ecalc.c         calculator
-ecalc.opt       part of VAX VMS makefile
-econst.c        constants for reference arithmetic
-eexp.c          reference exponential function
-ehead.h         declarations for reference arithmetic routines
-elog.c          reference logarithm
-eparanoi.c      floating point arithmetic tester
-eparanoi.opt    part of VAX VMS makefile
-epow.c          reference exponentiation
-esqrt.c         reference square root
-etanh.c         reference hyperbolic tangent
-etodec.c        conversions to and from DEC double precision format
-ieee.c          the reference arithmetic
-ieetst.c        printf/scanf tester
-ieetst.doc      this file
-ieetst.mak      Microsoft make file
-ieetst.opt      part of VAX VMS makefile
-makefile        Unix make file
-mconf.h         definitions for arithmetic format
-mtherr.c        common error reporter
-qcalc.h         definitions for calculator
-
-
-This software may be copied freely.
-
--- Steve Moshier
-
-v0.1   July, 1992
-v0.2   January, 1993
+
+                  ieetst, version 0.2
+
+   This software tests the numerical accuracy of floating point
+binary <-> decimal string conversion, as done by your C language
+library functions printf() and scanf(), for compliance with the
+IEEE arithmetic standards ANSI/IEEE Std 754-1985 and ANSI/IEEE
+Std 854-1987.  The test covers 32-bit float, 64-bit double, and
+80-bit long double precision conversions to and from decimal
+ASCII strings.
+
+   The test program checks for proper implementation of the
+following specifications of the standards:
+
+   (1) correctly rounded conversions of numbers of the form M *
+   10^N, where M and N are integers such that, in double precision,
+   for example, |M| < 10^17, |N| <= 27.
+
+   (2) binary -> decimal -> binary conversions to be an identity
+   if a sufficiently large number of decimal digits is requested.
+
+   (3) correctly rounded decimal outputs of less than the maximum
+   number of digits
+
+   (4) The maximum observed conversion error of numbers outside the
+   domain covered by (1) is reported by the test program; it is
+   not supposed to exceed 0.97 ulp.
+
+There are 10 separate tests.  Tests 1 through 6 use values near
+2^n and 10^n.  Test 7 addresses item (1) above.  Test 8 checks
+the rounding of exact half-integer numbers. Test 9 is for item
+(4) above.  Test 10 checks denormal numbers.  Tests 8 through 10
+address item (3) using printf formats that produce outputs of 1,
+2, 3, ... digits after the decimal point.  All tests check, when
+appropriate, that the binary output of scanf is the same as the
+binary input to printf, item (2).
+
+Example error messages:
+
+   0000 0000 0000 1000 8000 3f80 ->printf-> 5.87748296e-39 ->scanf->
+   0000 0000 0000 0000 8000 3f6e  is not an identity.
+
+   scanf(-9.9999900000000003e-01) -> 0000 4800 085f ef39 ffff bffe 
+   should be 0000 5000 085f ef39 ffff bffe .
+
+   printf("%.14e",  6.13592315154256467968352E-3) -> 6.13592315154257e-03
+   should be       6.13592315154256E-3 .
+
+Binary values are displayed as four-digit hex groups in the
+little-endian format of the internal reference arithmetic. The
+least significant 16-bit word is first, the exponent is last.
+
+   The design of the test program requires knowing the binary
+data structure of the floating point format under test.  For
+configuration, check the .h files carefully. All the programs
+need to be told via mconf.h if the numeric format is
+little-endian (IBMPC) or big-endian (MIEEE).  If your system
+supports an 80-bit long double precision data type, define
+LDOUBLE 1 in ieetst.c; otherwise define LDOUBLE 0.  A provision
+for DEC PDP-11/VAX numbers is implemented (double precision
+only).  Conversions for other data structures can be added by
+analogy to the ifdefs for DEC.
+
+   Most of the tests rely on comparison with the results of a
+portable reference arithmetic, contained in the file ieee.c. 
+This is configured for an 80-bit significand, to have enough
+precision to satisfy the conversion requirements of IEEE 854 for
+the extended double format of IEEE 754.  The reference arithmetic
+includes binary <--> ASCII conversion routines and single <-->
+double <--> extended double conversions.  A strictly rounded
+square root function is given in esqrt.c.  Additional functions
+are provided by elog.c, eexp.c, etanh.c, epow.c, all of which
+call on ieee.c for their arithmetic.  Some of the ANSI C
+functions are supplied in ieee.c; for example, efloor(),
+efrexp(), eldexp(). The functions and the reference arithmetic
+are described further in the book _Methods and Programs for
+Mathematical Functions_ (Prentice-Hall or Simon & Schuster
+International, 1989), by S. L. Moshier.
+
+   As an aid in diagnosis, a calculator program, ecalc.c, is
+supplied.  It uses ieee.c for its arithmetic. Documentation for
+the calculator's user interface is in the file calc100.doc
+(calc100 is a fuller featured 100-digit version of ecalc).  The
+calculator needs to be told by qcalc.h if addresses are 32 bits
+long (define LARGEMEM 1) or 16 bits long (define LARGEMEM 0).
+
+   Because the source code of ieee.c is included here, a version
+of W. Kahan's PARANOIA is also provided; this has been heavily
+modified by substituting subroutine calls to ieee.c in place of
+all arithmetic operators.  It is important that you use PARANOIA
+to check the arithmetic after any modifications you may make to
+ieee.c.
+
+   Several systems have been tested with the initial version of
+ieetst.  Sun 4 (SPARC) passes; DEC VMS C has only a small flaw;
+Microsoft flunks; ATT SysVR2 (Motorola) flunks even worse.
+
+
+   Files:
+
+calc100.doc     calculator documentaton
+descrip.mms     part of VAX VMS makefile
+drand.c         random number generator
+ecalc.c         calculator
+ecalc.opt       part of VAX VMS makefile
+econst.c        constants for reference arithmetic
+eexp.c          reference exponential function
+ehead.h         declarations for reference arithmetic routines
+elog.c          reference logarithm
+eparanoi.c      floating point arithmetic tester
+eparanoi.opt    part of VAX VMS makefile
+epow.c          reference exponentiation
+esqrt.c         reference square root
+etanh.c         reference hyperbolic tangent
+etodec.c        conversions to and from DEC double precision format
+ieee.c          the reference arithmetic
+ieetst.c        printf/scanf tester
+ieetst.doc      this file
+ieetst.mak      Microsoft make file
+ieetst.opt      part of VAX VMS makefile
+makefile        Unix make file
+mconf.h         definitions for arithmetic format
+mtherr.c        common error reporter
+qcalc.h         definitions for calculator
+
+
+This software may be copied freely.
+
+-- Steve Moshier
+
+v0.1   July, 1992
+v0.2   January, 1993

+ 108 - 108
test/math/mconf.h

@@ -1,108 +1,108 @@
-/*							mconf.h
- *
- *	Common include file for math routines
- *
- *
- *
- * SYNOPSIS:
- *
- * #include "mconf.h"
- *
- *
- *
- * DESCRIPTION:
- *
- * This file contains definitions for error codes that are
- * passed to the common error handling routine mtherr()
- * (which see).
- *
- * The file also includes a conditional assembly definition
- * for the type of computer arithmetic (IEEE, DEC, Motorola
- * IEEE, or UNKnown).
- *
- * For Digital Equipment PDP-11 and VAX computers, certain
- * IBM systems, and others that use numbers with a 56-bit
- * significand, the symbol DEC should be defined.  In this
- * mode, most floating point constants are given as arrays
- * of octal integers to eliminate decimal to binary conversion
- * errors that might be introduced by the compiler.
- *
- * For computers, such as IBM PC, that follow the IEEE 
- * Standard for Binary Floating Point Arithmetic (ANSI/IEEE
- * Std 754-1985), the symbol IBMPC should be defined.  These
- * numbers have 53-bit significands.  In this mode, constants
- * are provided as arrays of hexadecimal 16 bit integers.
- *
- * To accommodate other types of computer arithmetic, all
- * constants are also provided in a normal decimal radix
- * which one can hope are correctly converted to a suitable
- * format by the available C language compiler.  To invoke
- * this mode, the symbol UNK is defined.
- *
- * An important difference among these modes is a predefined
- * set of machine arithmetic constants for each.  The numbers
- * MACHEP (the machine roundoff error), MAXNUM (largest number
- * represented), and several other parameters are preset by
- * the configuration symbol.  Check the file const.c to
- * ensure that these values are correct for your computer.
- *
- */
-
-/*
-Cephes Math Library Release 2.0:  April, 1987
-by Stephen L. Moshier
-Direct inquiries to 30 Frost Street, Cambridge, MA 02140
-*/
-
-
-/* Constant definitions for math error conditions
- */
-
-#define DOMAIN		1	/* argument domain error */
-#define SING		2	/* argument singularity */
-#define OVERFLOW	3	/* overflow range error */
-#define UNDERFLOW	4	/* underflow range error */
-#define TLOSS		5	/* total loss of precision */
-#define PLOSS		6	/* partial loss of precision */
-
-#define EDOM		33
-#define ERANGE		34
-
-/*
-typedef struct
-	{
-	double r;
-	double i;
-	}cmplx;
-*/
-
-/* Type of computer arithmetic */
-
-/* PDP-11, Pro350, VAX:
- */
-/*define DEC 1*/
-
-/* Intel IEEE, low order words come first:
- */
-#define IBMPC 1
-
-/* Motorola IEEE, high order words come first
- * (Sun workstation):
- */
-/*define MIEEE 1*/
-
-/* UNKnown arithmetic, invokes coefficients given in
- * normal decimal format.  Beware of range boundary
- * problems (MACHEP, MAXLOG, etc. in const.c) and
- * roundoff problems in pow.c:
- */
- /*define UNK 1*/
-
-/* Define to ask for infinity support, else undefine. */
-#define INFINITY
-
-/* Define to ask for Not-a-Number support, else undefine. */
-#define NANS
-
-/* Define to support denormal numbers, else undefine. */
-#define DENORMAL
+/*							mconf.h
+ *
+ *	Common include file for math routines
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * #include "mconf.h"
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * This file contains definitions for error codes that are
+ * passed to the common error handling routine mtherr()
+ * (which see).
+ *
+ * The file also includes a conditional assembly definition
+ * for the type of computer arithmetic (IEEE, DEC, Motorola
+ * IEEE, or UNKnown).
+ *
+ * For Digital Equipment PDP-11 and VAX computers, certain
+ * IBM systems, and others that use numbers with a 56-bit
+ * significand, the symbol DEC should be defined.  In this
+ * mode, most floating point constants are given as arrays
+ * of octal integers to eliminate decimal to binary conversion
+ * errors that might be introduced by the compiler.
+ *
+ * For computers, such as IBM PC, that follow the IEEE 
+ * Standard for Binary Floating Point Arithmetic (ANSI/IEEE
+ * Std 754-1985), the symbol IBMPC should be defined.  These
+ * numbers have 53-bit significands.  In this mode, constants
+ * are provided as arrays of hexadecimal 16 bit integers.
+ *
+ * To accommodate other types of computer arithmetic, all
+ * constants are also provided in a normal decimal radix
+ * which one can hope are correctly converted to a suitable
+ * format by the available C language compiler.  To invoke
+ * this mode, the symbol UNK is defined.
+ *
+ * An important difference among these modes is a predefined
+ * set of machine arithmetic constants for each.  The numbers
+ * MACHEP (the machine roundoff error), MAXNUM (largest number
+ * represented), and several other parameters are preset by
+ * the configuration symbol.  Check the file const.c to
+ * ensure that these values are correct for your computer.
+ *
+ */
+
+/*
+Cephes Math Library Release 2.0:  April, 1987
+by Stephen L. Moshier
+Direct inquiries to 30 Frost Street, Cambridge, MA 02140
+*/
+
+
+/* Constant definitions for math error conditions
+ */
+
+#define DOMAIN		1	/* argument domain error */
+#define SING		2	/* argument singularity */
+#define OVERFLOW	3	/* overflow range error */
+#define UNDERFLOW	4	/* underflow range error */
+#define TLOSS		5	/* total loss of precision */
+#define PLOSS		6	/* partial loss of precision */
+
+#define EDOM		33
+#define ERANGE		34
+
+/*
+typedef struct
+	{
+	double r;
+	double i;
+	}cmplx;
+*/
+
+/* Type of computer arithmetic */
+
+/* PDP-11, Pro350, VAX:
+ */
+/*define DEC 1*/
+
+/* Intel IEEE, low order words come first:
+ */
+#define IBMPC 1
+
+/* Motorola IEEE, high order words come first
+ * (Sun workstation):
+ */
+/*define MIEEE 1*/
+
+/* UNKnown arithmetic, invokes coefficients given in
+ * normal decimal format.  Beware of range boundary
+ * problems (MACHEP, MAXLOG, etc. in const.c) and
+ * roundoff problems in pow.c:
+ */
+ /*define UNK 1*/
+
+/* Define to ask for infinity support, else undefine. */
+#define INFINITY
+
+/* Define to ask for Not-a-Number support, else undefine. */
+#define NANS
+
+/* Define to support denormal numbers, else undefine. */
+#define DENORMAL

+ 96 - 96
test/math/mtherr.c

@@ -1,96 +1,96 @@
-/*							mtherr.c
- *
- *	Library common error handling routine
- *
- *
- *
- * SYNOPSIS:
- *
- * char *fctnam;
- * int code;
- * void mtherr();
- *
- * mtherr( fctnam, code );
- *
- *
- *
- * DESCRIPTION:
- *
- * This routine may be called to report one of the following
- * error conditions (in the include file mconf.h).
- *  
- *   Mnemonic        Value          Significance
- *
- *    DOMAIN            1       argument domain error
- *    SING              2       function singularity
- *    OVERFLOW          3       overflow range error
- *    UNDERFLOW         4       underflow range error
- *    TLOSS             5       total loss of precision
- *    PLOSS             6       partial loss of precision
- *    EDOM             33       Unix domain error code
- *    ERANGE           34       Unix range error code
- *
- * The default version of the file prints the function name,
- * passed to it by the pointer fctnam, followed by the
- * error condition.  The display is directed to the standard
- * output device.  The routine then returns to the calling
- * program.  Users may wish to modify the program to abort by
- * calling exit() under severe error conditions such as domain
- * errors.
- *
- * Since all error conditions pass control to this function,
- * the display may be easily changed, eliminated, or directed
- * to an error logging device.
- *
- * SEE ALSO:
- *
- * mconf.h
- *
- */
-
-/*
-Cephes Math Library Release 2.0:  April, 1987
-by Stephen L. Moshier
-Direct inquiries to 30 Frost Street, Cambridge, MA 02140
-*/
-
-#include "mconf.h"
-
-/* Notice: the order of appearance of the following
- * messages is bound to the error codes defined
- * in mconf.h.
- */
-static char *ermsg[7] = {
-"unknown",      /* error code 0 */
-"domain",       /* error code 1 */
-"singularity",  /* et seq.      */
-"overflow",
-"underflow",
-"total loss of precision",
-"partial loss of precision"
-};
-
-
-
-void mtherr( name, code )
-char *name;
-int code;
-{
-
-/* Display string passed by calling program,
- * which is supposed to be the name of the
- * function in which the error occurred:
- */
-printf( "\n%s ", name );
-
-/* Display error message defined
- * by the code argument.
- */
-if( (code <= 0) || (code >= 6) )
-	code = 0;
-printf( "%s error\n", ermsg[code] );
-
-/* Return to calling
- * program
- */
-}
+/*							mtherr.c
+ *
+ *	Library common error handling routine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * char *fctnam;
+ * int code;
+ * void mtherr();
+ *
+ * mtherr( fctnam, code );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * This routine may be called to report one of the following
+ * error conditions (in the include file mconf.h).
+ *  
+ *   Mnemonic        Value          Significance
+ *
+ *    DOMAIN            1       argument domain error
+ *    SING              2       function singularity
+ *    OVERFLOW          3       overflow range error
+ *    UNDERFLOW         4       underflow range error
+ *    TLOSS             5       total loss of precision
+ *    PLOSS             6       partial loss of precision
+ *    EDOM             33       Unix domain error code
+ *    ERANGE           34       Unix range error code
+ *
+ * The default version of the file prints the function name,
+ * passed to it by the pointer fctnam, followed by the
+ * error condition.  The display is directed to the standard
+ * output device.  The routine then returns to the calling
+ * program.  Users may wish to modify the program to abort by
+ * calling exit() under severe error conditions such as domain
+ * errors.
+ *
+ * Since all error conditions pass control to this function,
+ * the display may be easily changed, eliminated, or directed
+ * to an error logging device.
+ *
+ * SEE ALSO:
+ *
+ * mconf.h
+ *
+ */
+
+/*
+Cephes Math Library Release 2.0:  April, 1987
+by Stephen L. Moshier
+Direct inquiries to 30 Frost Street, Cambridge, MA 02140
+*/
+
+#include "mconf.h"
+
+/* Notice: the order of appearance of the following
+ * messages is bound to the error codes defined
+ * in mconf.h.
+ */
+static char *ermsg[7] = {
+"unknown",      /* error code 0 */
+"domain",       /* error code 1 */
+"singularity",  /* et seq.      */
+"overflow",
+"underflow",
+"total loss of precision",
+"partial loss of precision"
+};
+
+
+
+void mtherr( name, code )
+char *name;
+int code;
+{
+
+/* Display string passed by calling program,
+ * which is supposed to be the name of the
+ * function in which the error occurred:
+ */
+printf( "\n%s ", name );
+
+/* Display error message defined
+ * by the code argument.
+ */
+if( (code <= 0) || (code >= 6) )
+	code = 0;
+printf( "%s error\n", ermsg[code] );
+
+/* Return to calling
+ * program
+ */
+}