xref: /openbsd-src/regress/lib/libc/cephes/ieetst.c (revision 36cd4f112ba9185542870bf6e070ac18e11a471b)
1*36cd4f11Sbluhm /*	$OpenBSD: ieetst.c,v 1.3 2017/07/27 15:08:37 bluhm Exp $	*/
2b7275c88Smartynas 
3b7275c88Smartynas /*
4b7275c88Smartynas  * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
5b7275c88Smartynas  *
6b7275c88Smartynas  * Permission to use, copy, modify, and distribute this software for any
7b7275c88Smartynas  * purpose with or without fee is hereby granted, provided that the above
8b7275c88Smartynas  * copyright notice and this permission notice appear in all copies.
9b7275c88Smartynas  *
10b7275c88Smartynas  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11b7275c88Smartynas  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12b7275c88Smartynas  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13b7275c88Smartynas  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14b7275c88Smartynas  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15b7275c88Smartynas  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16b7275c88Smartynas  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17b7275c88Smartynas  */
18b7275c88Smartynas 
19b7275c88Smartynas /* Floating point to ASCII input and output string test program.
20b7275c88Smartynas  *
21b7275c88Smartynas  * Numbers in the native machine data structure are converted
22b7275c88Smartynas  * to e type, then to and from decimal ASCII strings.  Native
23b7275c88Smartynas  * printf() and scanf() functions are also used to produce
24b7275c88Smartynas  * and read strings.  The resulting e type binary values
25b7275c88Smartynas  * are compared, with diagnostic printouts of any discrepancies.
26b7275c88Smartynas  *
27b7275c88Smartynas  * Steve Moshier, 16 Dec 88
28b7275c88Smartynas  * last revision: 16 May 92
29b7275c88Smartynas  */
30b7275c88Smartynas 
31e5597882Smartynas #include <float.h>
32b7275c88Smartynas #include <stdio.h>
33b7275c88Smartynas 
34b7275c88Smartynas #include "mconf.h"
35b7275c88Smartynas #include "ehead.h"
36b7275c88Smartynas 
37b7275c88Smartynas /* Include tests of 80-bit long double precision: */
38e5597882Smartynas #if	LDBL_MANT_DIG == 64
39e5597882Smartynas #define LDOUBLE 1
40e5597882Smartynas #else	/* LDBL_MANT_DIG == 64 */
41b7275c88Smartynas #define LDOUBLE 0
42e5597882Smartynas #endif	/* LDBL_MANT_DIG == 64 */
43b7275c88Smartynas /* Abort subtest after getting this many errors: */
44b7275c88Smartynas #define MAXERR 5
45b7275c88Smartynas /* Number of random arguments to try (set as large as you have
46b7275c88Smartynas  * patience for): */
47b7275c88Smartynas #define NRAND 100
48b7275c88Smartynas /* Perform internal consistency test: */
49b7275c88Smartynas #define CHKINTERNAL 0
50b7275c88Smartynas 
51b7275c88Smartynas static unsigned short fullp[NE], rounded[NE];
52b7275c88Smartynas float prec24, sprec24, ssprec24;
53b7275c88Smartynas double prec53, sprec53, ssprec53;
54b7275c88Smartynas #if LDOUBLE
55b7275c88Smartynas long double prec64, sprec64, ssprec64;
56b7275c88Smartynas #endif
57b7275c88Smartynas 
58b7275c88Smartynas static unsigned short rprint[NE], rscan[NE];
59b7275c88Smartynas static unsigned short q1[NE], q2[NE], q5[NE];
60b7275c88Smartynas static unsigned short e1[NE], e2[NE], e3[NE];
61b7275c88Smartynas static double d1, d2;
62b7275c88Smartynas static int errprint = 0;
63b7275c88Smartynas static int errscan = 0;
64b7275c88Smartynas static int identerr = 0;
65b7275c88Smartynas static int errtot = 0;
66b7275c88Smartynas static int count = 0;
67b7275c88Smartynas static char str0[80], str1[80], str2[80], str3[80];
68b7275c88Smartynas static unsigned short eten[NE], maxm[NE];
69b7275c88Smartynas 
70b7275c88Smartynas int m, n, k2, mprec, SPREC;
71b7275c88Smartynas 
72b7275c88Smartynas char *Ten = "10.0";
73b7275c88Smartynas char tformat[10];
74b7275c88Smartynas char *format24 = "%.8e";
75b7275c88Smartynas #ifdef DEC
76b7275c88Smartynas char *format53 = "%.17e";
77b7275c88Smartynas #else
78b7275c88Smartynas char *format53 = "%.16e";
79b7275c88Smartynas #endif
80b7275c88Smartynas char *fformat24 = "%e";
81b7275c88Smartynas char *fformat53 = "%le";
82b7275c88Smartynas char *pct = "%";
83b7275c88Smartynas char *quo = "\042";
84b7275c88Smartynas #if LDOUBLE
85b7275c88Smartynas char *format64 = "%.20Le";
86b7275c88Smartynas char *fformat64 = "%Le";
87b7275c88Smartynas #endif
88b7275c88Smartynas char *format;
89b7275c88Smartynas char *fformat;
90b7275c88Smartynas char *toomany = "Too many errors; aborting this test.\n";
91b7275c88Smartynas 
92b7275c88Smartynas static int mnrflag;
93b7275c88Smartynas static int etrflag;
94b7275c88Smartynas void chkit(), printerr(), mnrand(), etrand(), shownoncrit();
95b7275c88Smartynas void chkid(), pvec();
96b7275c88Smartynas 
97*36cd4f11Sbluhm int
main()98b7275c88Smartynas main()
99b7275c88Smartynas {
100b7275c88Smartynas int i, iprec, retval = 0;
101b7275c88Smartynas 
102b7275c88Smartynas printf( "Steve Moshier's printf/scanf tester, version 0.2.\n\n" );
103b7275c88Smartynas #ifdef DEC
104b7275c88Smartynas  /* DEC PDP-11/VAX single precision not yet implemented */
105b7275c88Smartynas for( iprec = 1; iprec<2; iprec++ )
106b7275c88Smartynas #else
107b7275c88Smartynas for( iprec = 0; iprec<3; iprec++ )
108b7275c88Smartynas /*for( iprec = 2; iprec<3; iprec++ )*/
109b7275c88Smartynas #endif
110b7275c88Smartynas 	{
111b7275c88Smartynas 	errscan = 0;
112b7275c88Smartynas 	identerr = 0;
113b7275c88Smartynas 	errprint = 0;
114b7275c88Smartynas 	eclear( rprint );
115b7275c88Smartynas 	eclear( rscan );
116b7275c88Smartynas 
117b7275c88Smartynas switch( iprec )
118b7275c88Smartynas 	{
119b7275c88Smartynas 	case 0:
120b7275c88Smartynas 		SPREC = 8; /* # digits after the decimal point */
121b7275c88Smartynas 		mprec = 24; /* # bits in the significand */
122b7275c88Smartynas 		m = 9; /* max # decimal digits for correct rounding */
123b7275c88Smartynas 		n = 13; /* max power of ten for correct rounding */
124b7275c88Smartynas 		k2 = -125; /* underflow beyond 2^-k2 */
125b7275c88Smartynas 		format = format24; /* printf format string */
126b7275c88Smartynas 		fformat = fformat24; /* scanf format string */
127b7275c88Smartynas 		mnrflag = 1; /* sets interval for random numbers */
128b7275c88Smartynas 		etrflag = 1;
129b7275c88Smartynas 		printf( "Testing FLOAT precision.\n" );
130b7275c88Smartynas 		break;
131b7275c88Smartynas 
132b7275c88Smartynas 	case 1:
133b7275c88Smartynas #ifdef DEC
134b7275c88Smartynas 		SPREC = 17;
135b7275c88Smartynas 		mprec = 56;
136b7275c88Smartynas 		m = 17;
137b7275c88Smartynas 		n = 27;
138b7275c88Smartynas 		k2 = -125;
139b7275c88Smartynas 		format = format53;
140b7275c88Smartynas 		fformat = fformat53;
141b7275c88Smartynas 		mnrflag = 2;
142b7275c88Smartynas 		etrflag = 1;
143b7275c88Smartynas 		printf( "Testing DEC DOUBLE precision.\n" );
144b7275c88Smartynas 		break;
145b7275c88Smartynas #else
146b7275c88Smartynas 		SPREC = 16;
147b7275c88Smartynas 		mprec = 53;
148b7275c88Smartynas 		m = 17;
149b7275c88Smartynas 		n = 27;
150b7275c88Smartynas 		k2 = -1021;
151b7275c88Smartynas 		format = format53;
152b7275c88Smartynas 		fformat = fformat53;
153b7275c88Smartynas 		mnrflag = 2;
154b7275c88Smartynas 		etrflag = 2;
155b7275c88Smartynas 		printf( "Testing DOUBLE precision.\n" );
156b7275c88Smartynas 		break;
157b7275c88Smartynas #endif
158b7275c88Smartynas 	case 2:
159b7275c88Smartynas #if LDOUBLE
160b7275c88Smartynas 		SPREC = 20;
161b7275c88Smartynas 		mprec = 64;
162b7275c88Smartynas 		m = 20;
163b7275c88Smartynas 		n = 34;
164b7275c88Smartynas 		k2 = -16382;
165b7275c88Smartynas 		format = format64;
166b7275c88Smartynas 		fformat = fformat64;
167b7275c88Smartynas 		mnrflag = 3;
168b7275c88Smartynas 		etrflag = 3;
169b7275c88Smartynas 		printf( "Testing LONG DOUBLE precision.\n" );
170b7275c88Smartynas 		break;
171b7275c88Smartynas #else
172b7275c88Smartynas 		goto nodenorm;
173b7275c88Smartynas #endif
174b7275c88Smartynas 	}
175b7275c88Smartynas 
176b7275c88Smartynas 	asctoe( Ten, eten );
177b7275c88Smartynas /* 10^m - 1 */
178b7275c88Smartynas 	d2 = m;
179b7275c88Smartynas 	e53toe( &d2, e1 );
180b7275c88Smartynas 	epow( eten, e1, maxm );
181b7275c88Smartynas 	esub( eone, maxm, maxm );
182b7275c88Smartynas 
183b7275c88Smartynas /* test 1 */
184b7275c88Smartynas 	printf( "1. Checking 10^n - 1 for n = %d to %d.\n", -m, m );
185b7275c88Smartynas 	emov( eone, q5 );
186b7275c88Smartynas 	for( count=0; count<=m; count++ )
187b7275c88Smartynas 		{
188b7275c88Smartynas 		esub( eone, q5, fullp );
189b7275c88Smartynas 		chkit( 1 );
190b7275c88Smartynas 		ediv( q5, eone, q2 );
191b7275c88Smartynas 		esub( eone, q2, fullp );
192b7275c88Smartynas 		chkit( 1 );
193b7275c88Smartynas 		emul( eten, q5, q5 );
194b7275c88Smartynas 		if( errtot >= MAXERR )
195b7275c88Smartynas 			{
196b7275c88Smartynas 			printf( "%s", toomany );
197b7275c88Smartynas 			goto end1;
198b7275c88Smartynas 			}
199b7275c88Smartynas 		}
200b7275c88Smartynas end1:
201b7275c88Smartynas 	printerr();
202b7275c88Smartynas 
203b7275c88Smartynas 
204b7275c88Smartynas /* test 2 */
205b7275c88Smartynas 	printf( "2. Checking powers of 10 from 10^-%d to 10^%d.\n", n, n );
206b7275c88Smartynas 	emov( eone, q5 );
207b7275c88Smartynas 	for( count=0; count<=n; count++ )
208b7275c88Smartynas 		{
209b7275c88Smartynas 		emov( q5, fullp );
210b7275c88Smartynas 		chkit( 2 );
211b7275c88Smartynas 		ediv( q5, eone, fullp );
212b7275c88Smartynas 		chkit( 2 );
213b7275c88Smartynas 		emul( eten, q5, q5 );
214b7275c88Smartynas 		if( errtot >= MAXERR )
215b7275c88Smartynas 			{
216b7275c88Smartynas 			printf( "%s", toomany );
217b7275c88Smartynas 			goto end2;
218b7275c88Smartynas 			}
219b7275c88Smartynas 		}
220b7275c88Smartynas end2:
221b7275c88Smartynas 	printerr();
222b7275c88Smartynas 
223b7275c88Smartynas /* test 3 */
224b7275c88Smartynas 	printf( "3. Checking (10^%d-1)*10^n from n = -%d to %d.\n", m, n, n );
225b7275c88Smartynas 	emov( eone, q5 );
226b7275c88Smartynas 	for( count= -n; count<=n; count++ )
227b7275c88Smartynas 		{
228b7275c88Smartynas 		emul( maxm, q5, fullp );
229b7275c88Smartynas 		chkit( 3 );
230b7275c88Smartynas 		emov( q5, fullp );
231b7275c88Smartynas 		ediv( fullp, eone, fullp );
232b7275c88Smartynas 		emul( maxm, fullp, fullp );
233b7275c88Smartynas 		chkit( 3 );
234b7275c88Smartynas 		emul( eten, q5, q5 );
235b7275c88Smartynas 		if( errtot >= MAXERR )
236b7275c88Smartynas 			{
237b7275c88Smartynas 			printf( "%s", toomany );
238b7275c88Smartynas 			goto end3;
239b7275c88Smartynas 			}
240b7275c88Smartynas 		}
241b7275c88Smartynas end3:
242b7275c88Smartynas 	printerr();
243b7275c88Smartynas 
244b7275c88Smartynas 
245b7275c88Smartynas 
246b7275c88Smartynas /* test 4 */
247b7275c88Smartynas 	printf( "4. Checking powers of 2 from 2^-24 to 2^+56.\n" );
248b7275c88Smartynas 	d1 = -24.0;
249b7275c88Smartynas 	e53toe( &d1, q1 );
250b7275c88Smartynas 	epow( etwo, q1, q5 );
251b7275c88Smartynas 
252b7275c88Smartynas 	for( count = -24; count <= 56; count++ )
253b7275c88Smartynas 		{
254b7275c88Smartynas 		emov( q5, fullp );
255b7275c88Smartynas 		chkit( 4 );
256b7275c88Smartynas 		emul( etwo, q5, q5 );
257b7275c88Smartynas 		if( errtot >= MAXERR )
258b7275c88Smartynas 			{
259b7275c88Smartynas 			printf( "%s", toomany );
260b7275c88Smartynas 			goto end4;
261b7275c88Smartynas 			}
262b7275c88Smartynas 		}
263b7275c88Smartynas end4:
264b7275c88Smartynas 	printerr();
265b7275c88Smartynas 
266b7275c88Smartynas 
267b7275c88Smartynas /* test 5 */
268b7275c88Smartynas 	printf( "5. Checking 2^n - 1 for n = 0 to %d.\n", mprec );
269b7275c88Smartynas 	emov( eone, q5 );
270b7275c88Smartynas 	for( count=0; count<=mprec; count++ )
271b7275c88Smartynas 		{
272b7275c88Smartynas 		esub( eone, q5, fullp );
273b7275c88Smartynas 		chkit( 5 );
274b7275c88Smartynas 		emul( etwo, q5, q5 );
275b7275c88Smartynas 		if( errtot >= MAXERR )
276b7275c88Smartynas 			{
277b7275c88Smartynas 			printf( "%s", toomany );
278b7275c88Smartynas 			goto end5;
279b7275c88Smartynas 			}
280b7275c88Smartynas 		}
281b7275c88Smartynas end5:
282b7275c88Smartynas 	printerr();
283b7275c88Smartynas 
284b7275c88Smartynas /* test 6 */
285b7275c88Smartynas 	printf( "6. Checking 2^n + 1 for n = 0 to %d.\n", mprec );
286b7275c88Smartynas 	emov( eone, q5 );
287b7275c88Smartynas 	for( count=0; count<=mprec; count++ )
288b7275c88Smartynas 		{
289b7275c88Smartynas 		eadd( eone, q5, fullp );
290b7275c88Smartynas 		chkit( 6 );
291b7275c88Smartynas 		emul( etwo, q5, q5 );
292b7275c88Smartynas 		if( errtot >= MAXERR )
293b7275c88Smartynas 			{
294b7275c88Smartynas 			printf( "%s", toomany );
295b7275c88Smartynas 			goto end6;
296b7275c88Smartynas 			}
297b7275c88Smartynas 		}
298b7275c88Smartynas end6:
299b7275c88Smartynas 	printerr();
300b7275c88Smartynas 
301b7275c88Smartynas /* test 7 */
302b7275c88Smartynas 	printf(
303b7275c88Smartynas 	 "7. Checking %d values M * 10^N with random integer M and N,\n",
304b7275c88Smartynas 	 NRAND );
305b7275c88Smartynas 	printf("  1 <= M <= 10^%d - 1  and  -%d <= N <= +%d.\n", m, n, n );
306b7275c88Smartynas 	for( i=0; i<NRAND; i++ )
307b7275c88Smartynas 		{
308b7275c88Smartynas 		mnrand( fullp );
309b7275c88Smartynas 		chkit( 7 );
310b7275c88Smartynas 		if( errtot >= MAXERR )
311b7275c88Smartynas 			{
312b7275c88Smartynas 			printf( "%s", toomany );
313b7275c88Smartynas 			goto end7;
314b7275c88Smartynas 			}
315b7275c88Smartynas 		}
316b7275c88Smartynas end7:
317b7275c88Smartynas 	printerr();
318b7275c88Smartynas 
319b7275c88Smartynas /* test 8 */
320b7275c88Smartynas 	printf("8. Checking critical rounding cases.\n" );
321b7275c88Smartynas 	for( i=0; i<20; i++ )
322b7275c88Smartynas 		{
323b7275c88Smartynas 		mnrand( fullp );
324b7275c88Smartynas 		eabs( fullp );
325b7275c88Smartynas 		if( ecmp( fullp, eone ) < 0 )
326b7275c88Smartynas 			ediv( fullp, eone, fullp );
327b7275c88Smartynas 		efloor( fullp, fullp );
328b7275c88Smartynas 		eadd( ehalf, fullp, fullp );
329b7275c88Smartynas 		chkit( 8 );
330b7275c88Smartynas 		if( errtot >= MAXERR )
331b7275c88Smartynas 			{
332b7275c88Smartynas 			printf( "%s", toomany );
333b7275c88Smartynas 			goto end8;
334b7275c88Smartynas 			}
335b7275c88Smartynas 		}
336b7275c88Smartynas end8:
337b7275c88Smartynas 	printerr();
338b7275c88Smartynas 
339b7275c88Smartynas 
340b7275c88Smartynas 
341b7275c88Smartynas /* test 9 */
342b7275c88Smartynas 	printf("9. Testing on %d random non-denormal values.\n", NRAND );
343b7275c88Smartynas 	for( i=0; i<NRAND; i++ )
344b7275c88Smartynas 		{
345b7275c88Smartynas 		etrand( fullp );
346b7275c88Smartynas 		chkit( 9 );
347b7275c88Smartynas 		}
348b7275c88Smartynas 	printerr();
349b7275c88Smartynas 	shownoncrit();
350b7275c88Smartynas 
351b7275c88Smartynas /* test 10 */
352b7275c88Smartynas #if 0
353b7275c88Smartynas 	printf(
354b7275c88Smartynas 	"Do you want to check denormal numbers in this precision ? (y/n) " );
355b7275c88Smartynas 	gets( str0 );
356b7275c88Smartynas 	if( str0[0] != 'y' )
357b7275c88Smartynas 		goto nodenorm;
358b7275c88Smartynas #endif
359b7275c88Smartynas 
360b7275c88Smartynas 	printf( "10. Checking denormal numbers.\n" );
361b7275c88Smartynas 
362b7275c88Smartynas /* Form 2^-starting power */
363b7275c88Smartynas 	d1 = k2;
364b7275c88Smartynas 	e53toe( &d1, q1 );
365b7275c88Smartynas 	epow( etwo, q1, e1 );
366b7275c88Smartynas 
367b7275c88Smartynas /* Find 2^-mprec less than starting power */
368b7275c88Smartynas 	d1 = -mprec + 4;
369b7275c88Smartynas 	e53toe( &d1, q1 );
370b7275c88Smartynas 	epow( etwo, q1, e3 );
371b7275c88Smartynas 	emul( e1, e3, e3 );
372b7275c88Smartynas 	emov( e3, e2 );
373b7275c88Smartynas 	ediv( etwo, e2, e2 );
374b7275c88Smartynas 
375b7275c88Smartynas 	while( ecmp(e1,e2) != 0 )
376b7275c88Smartynas 		{
377b7275c88Smartynas 		eadd( e1, e2, fullp );
378b7275c88Smartynas 		switch( mprec )
379b7275c88Smartynas 			{
380b7275c88Smartynas #if LDOUBLE
381b7275c88Smartynas 			case 64:
382b7275c88Smartynas 			etoe64( e1, &sprec64 );
383b7275c88Smartynas 			e64toe( &sprec64, q1 );
384b7275c88Smartynas 			etoe64( fullp, &prec64 );
385b7275c88Smartynas 			e64toe( &prec64, q2 );
386b7275c88Smartynas 			break;
387b7275c88Smartynas #endif
388b7275c88Smartynas #ifdef DEC
389b7275c88Smartynas 			case 56:
390b7275c88Smartynas #endif
391b7275c88Smartynas 			case 53:
392b7275c88Smartynas 			etoe53( e1, &sprec53 );
393b7275c88Smartynas 			e53toe( &sprec53, q1 );
394b7275c88Smartynas 			etoe53( fullp, &prec53 );
395b7275c88Smartynas 			e53toe( &prec53, q2 );
396b7275c88Smartynas 			break;
397b7275c88Smartynas 
398b7275c88Smartynas 			case 24:
399b7275c88Smartynas 			etoe24( e1, &sprec24 );
400b7275c88Smartynas 			e24toe( &sprec24, q1 );
401b7275c88Smartynas 			etoe24( fullp, &prec24 );
402b7275c88Smartynas 			e24toe( &prec24, q2 );
403b7275c88Smartynas 			break;
404b7275c88Smartynas 			}
405b7275c88Smartynas 		if( ecmp( q2, ezero ) == 0 )
406b7275c88Smartynas 			goto maxden;
407b7275c88Smartynas 		chkit(10);
408b7275c88Smartynas 		if( ecmp(q1,q2) == 0 )
409b7275c88Smartynas 			{
410b7275c88Smartynas 			ediv( etwo, e1, e1 );
411b7275c88Smartynas 			emov( e3, e2 );
412b7275c88Smartynas 			}
413b7275c88Smartynas 		if( errtot >= MAXERR )
414b7275c88Smartynas 			{
415b7275c88Smartynas 			printf( "%s", toomany );
416b7275c88Smartynas 			goto maxden;
417b7275c88Smartynas 			}
418b7275c88Smartynas 		ediv( etwo, e2, e2 );
419b7275c88Smartynas 		}
420b7275c88Smartynas maxden:
421b7275c88Smartynas 	printerr();
422b7275c88Smartynas nodenorm:
423b7275c88Smartynas 	printf( "\n" );
424b7275c88Smartynas 	retval |= errscan | identerr | errprint;
425b7275c88Smartynas 	} /* loop on precision */
426b7275c88Smartynas printf( "End of test.\n" );
427b7275c88Smartynas return (retval);
428b7275c88Smartynas }
429b7275c88Smartynas 
430b7275c88Smartynas #if CHKINTERNAL
431b7275c88Smartynas long double xprec64;
432b7275c88Smartynas double xprec53;
433b7275c88Smartynas float xprec24;
434b7275c88Smartynas 
435b7275c88Smartynas /* Check binary -> printf -> scanf -> binary identity
436b7275c88Smartynas  * of internal routines
437b7275c88Smartynas  */
chkinternal(ref,tst,string)438b7275c88Smartynas void chkinternal( ref, tst, string )
439b7275c88Smartynas unsigned short ref[], tst[];
440b7275c88Smartynas char *string;
441b7275c88Smartynas {
442b7275c88Smartynas 
443b7275c88Smartynas if( ecmp(ref,tst) != 0 )
444b7275c88Smartynas 	{
445b7275c88Smartynas 	printf( "internal identity compare error!\n" );
446b7275c88Smartynas 	chkid( ref, tst, string );
447b7275c88Smartynas 	}
448b7275c88Smartynas }
449b7275c88Smartynas #endif
450b7275c88Smartynas 
451b7275c88Smartynas 
452b7275c88Smartynas /* Check binary -> printf -> scanf -> binary identity
453b7275c88Smartynas  */
chkid(print,scan,string)454b7275c88Smartynas void chkid( print, scan, string )
455b7275c88Smartynas unsigned short print[], scan[];
456b7275c88Smartynas char *string;
457b7275c88Smartynas {
458b7275c88Smartynas /* Test printf-scanf identity */
459b7275c88Smartynas if( ecmp( print, scan ) != 0 )
460b7275c88Smartynas 	{
461b7275c88Smartynas 	pvec( print, NE );
462b7275c88Smartynas 	printf( " ->printf-> %s ->scanf->\n", string );
463b7275c88Smartynas 	pvec( scan, NE );
464b7275c88Smartynas 	printf( " is not an identity.\n" );
465b7275c88Smartynas 	++identerr;
466b7275c88Smartynas 	}
467b7275c88Smartynas }
468b7275c88Smartynas 
469b7275c88Smartynas 
470b7275c88Smartynas /* Check scanf result
471b7275c88Smartynas  */
chkscan(ref,tst,string)472b7275c88Smartynas void chkscan( ref, tst, string )
473b7275c88Smartynas unsigned short ref[], tst[];
474b7275c88Smartynas char *string;
475b7275c88Smartynas {
476b7275c88Smartynas /* Test scanf()  */
477b7275c88Smartynas if( ecmp( ref, tst ) != 0 )
478b7275c88Smartynas 	{
479b7275c88Smartynas 	printf( "scanf(%s) -> ", string );
480b7275c88Smartynas 	pvec( tst, NE );
481b7275c88Smartynas 	printf( "\n should be    " );
482b7275c88Smartynas 	pvec( ref, NE );
483b7275c88Smartynas 	printf( ".\n" );
484b7275c88Smartynas 	++errscan;
485b7275c88Smartynas 	++errtot;
486b7275c88Smartynas 	}
487b7275c88Smartynas }
488b7275c88Smartynas 
489b7275c88Smartynas 
490b7275c88Smartynas /* Test printf() result
491b7275c88Smartynas  */
chkprint(ref,tst,string)492b7275c88Smartynas void chkprint( ref, tst, string )
493b7275c88Smartynas unsigned short ref[], tst[];
494b7275c88Smartynas char *string;
495b7275c88Smartynas {
496b7275c88Smartynas if( ecmp(ref, tst) != 0 )
497b7275c88Smartynas 	{
498b7275c88Smartynas 	printf( "printf( ");
499b7275c88Smartynas 	pvec( ref, NE );
500b7275c88Smartynas 	printf( ") -> %s\n", string );
501b7275c88Smartynas 	printf( "      = " );
502b7275c88Smartynas 	pvec( tst, NE );
503b7275c88Smartynas 	printf( ".\n" );
504b7275c88Smartynas 	++errprint;
505b7275c88Smartynas 	++errtot;
506b7275c88Smartynas 	}
507b7275c88Smartynas }
508b7275c88Smartynas 
509b7275c88Smartynas 
510b7275c88Smartynas /* Print array of n 16-bit shorts
511b7275c88Smartynas  */
pvec(x,n)512b7275c88Smartynas void pvec( x, n )
513b7275c88Smartynas unsigned short x[];
514b7275c88Smartynas int n;
515b7275c88Smartynas {
516b7275c88Smartynas int i;
517b7275c88Smartynas 
518b7275c88Smartynas for( i=0; i<n; i++ )
519b7275c88Smartynas 	{
520b7275c88Smartynas 	printf( "%04x ", x[i] );
521b7275c88Smartynas 	}
522b7275c88Smartynas }
523b7275c88Smartynas 
524b7275c88Smartynas /* Measure worst case printf rounding error
525b7275c88Smartynas  */
cmpprint(ref,tst)526b7275c88Smartynas void cmpprint( ref, tst )
527b7275c88Smartynas unsigned short ref[], tst[];
528b7275c88Smartynas {
529b7275c88Smartynas unsigned short e[NE];
530b7275c88Smartynas 
531b7275c88Smartynas if( ecmp( ref, ezero ) != 0 )
532b7275c88Smartynas 	{
533b7275c88Smartynas 	esub( ref, tst, e );
534b7275c88Smartynas 	ediv( ref, e, e );
535b7275c88Smartynas 	eabs( e );
536b7275c88Smartynas 	if( ecmp( e, rprint ) > 0 )
537b7275c88Smartynas 		emov( e, rprint );
538b7275c88Smartynas 	}
539b7275c88Smartynas }
540b7275c88Smartynas 
541b7275c88Smartynas /* Measure worst case scanf rounding error
542b7275c88Smartynas  */
cmpscan(ref,tst)543b7275c88Smartynas void cmpscan( ref, tst )
544b7275c88Smartynas unsigned short ref[], tst[];
545b7275c88Smartynas {
546b7275c88Smartynas unsigned short er[NE];
547b7275c88Smartynas 
548b7275c88Smartynas if( ecmp( ref, ezero ) != 0 )
549b7275c88Smartynas 	{
550b7275c88Smartynas 	esub( ref, tst, er );
551b7275c88Smartynas 	ediv( ref, er, er );
552b7275c88Smartynas 	eabs( er );
553b7275c88Smartynas 	if( ecmp( er, rscan ) > 0 )
554b7275c88Smartynas 		emov( er, rscan );
555b7275c88Smartynas 	if( ecmp( er, ehalf ) > 0 )
556b7275c88Smartynas 		{
557b7275c88Smartynas 		etoasc( tst, str1, 21 );
558b7275c88Smartynas 		printf( "Bad error: scanf(%s) = %s !\n", str0, str1 );
559b7275c88Smartynas 		}
560b7275c88Smartynas 	}
561b7275c88Smartynas }
562b7275c88Smartynas 
563b7275c88Smartynas /* Check rounded-down decimal string output of printf
564b7275c88Smartynas  */
cmptrunc(ref,tst)565b7275c88Smartynas void cmptrunc( ref, tst )
566b7275c88Smartynas unsigned short ref[], tst[];
567b7275c88Smartynas {
568b7275c88Smartynas if( ecmp( ref, tst ) != 0 )
569b7275c88Smartynas 	{
570b7275c88Smartynas 	printf( "printf(%s%s%s, %s) -> %s\n", quo, tformat, quo, str1, str2 );
571b7275c88Smartynas 	printf( "should be      %s .\n", str3 );
572b7275c88Smartynas 	errprint += 1;
573b7275c88Smartynas 	}
574b7275c88Smartynas }
575b7275c88Smartynas 
576b7275c88Smartynas 
shownoncrit()577b7275c88Smartynas void shownoncrit()
578b7275c88Smartynas {
579b7275c88Smartynas 
580b7275c88Smartynas etoasc( rprint, str0, 3 );
581b7275c88Smartynas printf( "Maximum relative printf error found = %s .\n", str0 );
582b7275c88Smartynas etoasc( rscan, str0, 3 );
583b7275c88Smartynas printf( "Maximum relative scanf error found = %s .\n", str0 );
584b7275c88Smartynas }
585b7275c88Smartynas 
586b7275c88Smartynas 
587b7275c88Smartynas 
588b7275c88Smartynas /* Produce arguments and call comparison subroutines.
589b7275c88Smartynas  */
chkit(testno)590b7275c88Smartynas void chkit( testno )
591b7275c88Smartynas int testno;
592b7275c88Smartynas {
593b7275c88Smartynas unsigned short t[NE], u[NE], v[NE];
594b7275c88Smartynas int j;
595b7275c88Smartynas 
596b7275c88Smartynas switch( mprec )
597b7275c88Smartynas 	{
598b7275c88Smartynas #if LDOUBLE
599b7275c88Smartynas 	case 64:
600b7275c88Smartynas 		etoe64( fullp, &prec64 );
601b7275c88Smartynas 		e64toe( &prec64, rounded );
602b7275c88Smartynas #if CHKINTERNAL
603b7275c88Smartynas 		e64toasc( &prec64, str1, SPREC );
604b7275c88Smartynas 		asctoe64( str1, &xprec64 );
605b7275c88Smartynas 		e64toe( &xprec64, t );
606b7275c88Smartynas 		chkinternal( rounded, t, str1 );
607b7275c88Smartynas #endif
608b7275c88Smartynas /* check printf and scanf */
609b7275c88Smartynas 		sprintf( str2, format, prec64 );
610b7275c88Smartynas 		sscanf( str2, fformat, &sprec64 );
611b7275c88Smartynas 		e64toe( &sprec64, u );
612b7275c88Smartynas 		chkid( rounded, u, str2 );
613b7275c88Smartynas 		asctoe64( str2, &ssprec64 );
614b7275c88Smartynas 		e64toe( &ssprec64, v );
615b7275c88Smartynas 		chkscan( v, u, str2 );
616b7275c88Smartynas 		chkprint( rounded, v, str2 );
617b7275c88Smartynas 		if( testno < 8 )
618b7275c88Smartynas 			break;
619b7275c88Smartynas /* rounding error measurement */
620b7275c88Smartynas 		etoasc( fullp, str0, 24 );
621b7275c88Smartynas 		etoe64( fullp, &ssprec64 );
622b7275c88Smartynas 		e64toe( &ssprec64, u );
623b7275c88Smartynas 		sprintf( str2, format, ssprec64 );
624b7275c88Smartynas 		asctoe( str2, t );
625b7275c88Smartynas 		cmpprint( u, t );
626b7275c88Smartynas 		sscanf( str0, fformat, &sprec64 );
627b7275c88Smartynas 		e64toe( &sprec64, t );
628b7275c88Smartynas 		cmpscan( fullp, t );
629b7275c88Smartynas 		if( testno < 8 )
630b7275c88Smartynas 			break;
631b7275c88Smartynas /* strings rounded to less than maximum precision */
632b7275c88Smartynas 		e64toasc( &ssprec64, str1, 24 );
633b7275c88Smartynas 		for( j=SPREC-1; j>0; j-- )
634b7275c88Smartynas 			{
635b7275c88Smartynas 			e64toasc( &ssprec64, str3, j );
636b7275c88Smartynas 			asctoe( str3, v );
637b7275c88Smartynas 			sprintf( tformat, "%s.%dLe", pct, j );
638b7275c88Smartynas 			sprintf( str2, tformat, ssprec64 );
639b7275c88Smartynas 			asctoe( str2, t );
640b7275c88Smartynas 			cmptrunc( v, t );
641b7275c88Smartynas 			}
642b7275c88Smartynas 		break;
643b7275c88Smartynas #endif
644b7275c88Smartynas #ifdef DEC
645b7275c88Smartynas 	case 56:
646b7275c88Smartynas #endif
647b7275c88Smartynas 	case 53:
648b7275c88Smartynas 		etoe53( fullp, &prec53 );
649b7275c88Smartynas 		e53toe( &prec53, rounded );
650b7275c88Smartynas #if CHKINTERNAL
651b7275c88Smartynas 		e53toasc( &prec53, str1, SPREC );
652b7275c88Smartynas 		asctoe53( str1, &xprec53 );
653b7275c88Smartynas 		e53toe( &xprec53, t );
654b7275c88Smartynas 		chkinternal( rounded, t, str1 );
655b7275c88Smartynas #endif
656b7275c88Smartynas 		sprintf( str2, format, prec53 );
657b7275c88Smartynas 		sscanf( str2, fformat, &sprec53 );
658b7275c88Smartynas 		e53toe( &sprec53, u );
659b7275c88Smartynas 		chkid( rounded, u, str2 );
660b7275c88Smartynas 		asctoe53( str2, &ssprec53 );
661b7275c88Smartynas 		e53toe( &ssprec53, v );
662b7275c88Smartynas 		chkscan( v, u, str2 );
663b7275c88Smartynas 		chkprint( rounded, v, str2 );
664b7275c88Smartynas 		if( testno < 8 )
665b7275c88Smartynas 			break;
666b7275c88Smartynas /* rounding error measurement */
667b7275c88Smartynas 		etoasc( fullp, str0, 24 );
668b7275c88Smartynas 		etoe53( fullp, &ssprec53 );
669b7275c88Smartynas 		e53toe( &ssprec53, u );
670b7275c88Smartynas 		sprintf( str2, format, ssprec53 );
671b7275c88Smartynas 		asctoe( str2, t );
672b7275c88Smartynas 		cmpprint( u, t );
673b7275c88Smartynas 		sscanf( str0, fformat, &sprec53 );
674b7275c88Smartynas 		e53toe( &sprec53, t );
675b7275c88Smartynas 		cmpscan( fullp, t );
676b7275c88Smartynas 		if( testno < 8 )
677b7275c88Smartynas 			break;
678b7275c88Smartynas 		e53toasc( &ssprec53, str1, 24 );
679b7275c88Smartynas 		for( j=SPREC-1; j>0; j-- )
680b7275c88Smartynas 			{
681b7275c88Smartynas 			e53toasc( &ssprec53, str3, j );
682b7275c88Smartynas 			asctoe( str3, v );
683b7275c88Smartynas 			sprintf( tformat, "%s.%de", pct, j );
684b7275c88Smartynas 			sprintf( str2, tformat, ssprec53 );
685b7275c88Smartynas 			asctoe( str2, t );
686b7275c88Smartynas 			cmptrunc( v, t );
687b7275c88Smartynas 			}
688b7275c88Smartynas 		break;
689b7275c88Smartynas 
690b7275c88Smartynas 	case 24:
691b7275c88Smartynas 		etoe24( fullp, &prec24 );
692b7275c88Smartynas 		e24toe( &prec24, rounded );
693b7275c88Smartynas #if CHKINTERNAL
694b7275c88Smartynas 		e24toasc( &prec24, str1, SPREC );
695b7275c88Smartynas 		asctoe24( str1, &xprec24 );
696b7275c88Smartynas 		e24toe( &xprec24, t );
697b7275c88Smartynas 		chkinternal( rounded, t, str1 );
698b7275c88Smartynas #endif
699b7275c88Smartynas 		sprintf( str2, format, prec24 );
700b7275c88Smartynas 		sscanf( str2, fformat, &sprec24 );
701b7275c88Smartynas 		e24toe( &sprec24, u );
702b7275c88Smartynas 		chkid( rounded, u, str2 );
703b7275c88Smartynas 		asctoe24( str2, &ssprec24 );
704b7275c88Smartynas 		e24toe( &ssprec24, v );
705b7275c88Smartynas 		chkscan( v, u, str2 );
706b7275c88Smartynas 		chkprint( rounded, v, str2 );
707b7275c88Smartynas 		if( testno < 8 )
708b7275c88Smartynas 			break;
709b7275c88Smartynas /* rounding error measurement */
710b7275c88Smartynas 		etoasc( fullp, str0, 24 );
711b7275c88Smartynas 		etoe24( fullp, &ssprec24 );
712b7275c88Smartynas 		e24toe( &ssprec24, u );
713b7275c88Smartynas 		sprintf( str2, format, ssprec24 );
714b7275c88Smartynas 		asctoe( str2, t );
715b7275c88Smartynas 		cmpprint( u, t );
716b7275c88Smartynas 		sscanf( str0, fformat, &sprec24 );
717b7275c88Smartynas 		e24toe( &sprec24, t );
718b7275c88Smartynas 		cmpscan( fullp, t );
719b7275c88Smartynas /*
720b7275c88Smartynas 		if( testno < 8 )
721b7275c88Smartynas 			break;
722b7275c88Smartynas */
723b7275c88Smartynas 		e24toasc( &ssprec24, str1, 24 );
724b7275c88Smartynas 		for( j=SPREC-1; j>0; j-- )
725b7275c88Smartynas 			{
726b7275c88Smartynas 			e24toasc( &ssprec24, str3, j );
727b7275c88Smartynas 			asctoe( str3, v );
728b7275c88Smartynas 			sprintf( tformat, "%s.%de", pct, j );
729b7275c88Smartynas 			sprintf( str2, tformat, ssprec24 );
730b7275c88Smartynas 			asctoe( str2, t );
731b7275c88Smartynas 			cmptrunc( v, t );
732b7275c88Smartynas 			}
733b7275c88Smartynas 		break;
734b7275c88Smartynas 	}
735b7275c88Smartynas }
736b7275c88Smartynas 
737b7275c88Smartynas 
printerr()738b7275c88Smartynas void printerr()
739b7275c88Smartynas {
740b7275c88Smartynas if( (errscan == 0) && (identerr == 0) && (errprint == 0) )
741b7275c88Smartynas 	printf( "No errors found.\n" );
742b7275c88Smartynas else
743b7275c88Smartynas 	{
744b7275c88Smartynas 	printf( "%d binary -> decimal errors found.\n", errprint );
745b7275c88Smartynas 	printf( "%d decimal -> binary errors found.\n", errscan );
746b7275c88Smartynas 	}
747b7275c88Smartynas errscan = 0;	/* reset for next test */
748b7275c88Smartynas identerr = 0;
749b7275c88Smartynas errprint = 0;
750b7275c88Smartynas errtot = 0;
751b7275c88Smartynas }
752b7275c88Smartynas 
753b7275c88Smartynas 
754b7275c88Smartynas /* Random number generator
755b7275c88Smartynas  * in the range M * 10^N, where 1 <= M <= 10^17 - 1
756b7275c88Smartynas  * and -27 <= N <= +27.  Test values of M are logarithmically distributed
757b7275c88Smartynas  * random integers; test values of N are uniformly distributed random integers.
758b7275c88Smartynas  */
759b7275c88Smartynas 
760b7275c88Smartynas static char *fwidth = "1.036163291797320557783096e1"; /* log(sqrt(10^9-1)) */
761b7275c88Smartynas static char *dwidth = "1.957197329044938830915E1"; /* log(sqrt(10^17-1)) */
762b7275c88Smartynas static char *ldwidth = "2.302585092994045684017491e1"; /* log(sqrt(10^20-1)) */
763b7275c88Smartynas 
764b7275c88Smartynas static char *a13 = "13.0";
765b7275c88Smartynas static char *a27 = "27.0";
766b7275c88Smartynas static char *a34 = "34.0";
767b7275c88Smartynas static char *a10m13 = "1.0e-13";
768b7275c88Smartynas static unsigned short LOW[ NE ], WIDTH[NE], e27[NE], e10m13[NE];
769b7275c88Smartynas 
770b7275c88Smartynas 
mnrand(erand)771b7275c88Smartynas void mnrand( erand )
772b7275c88Smartynas unsigned short erand[];
773b7275c88Smartynas {
774b7275c88Smartynas unsigned short ea[NE], em[NE], en[NE], ex[NE];
775b7275c88Smartynas double x, a;
776b7275c88Smartynas 
777b7275c88Smartynas if( mnrflag )
778b7275c88Smartynas 	{
779b7275c88Smartynas 	if( mnrflag == 3 )
780b7275c88Smartynas 		{
781b7275c88Smartynas 		asctoe( ldwidth, WIDTH );
782b7275c88Smartynas 		asctoe( a34, e27 );
783b7275c88Smartynas 		}
784b7275c88Smartynas 	if( mnrflag == 2 )
785b7275c88Smartynas 		{
786b7275c88Smartynas 		asctoe( dwidth, WIDTH );
787b7275c88Smartynas 		asctoe( a27, e27 );
788b7275c88Smartynas 		}
789b7275c88Smartynas 	if( mnrflag == 1 )
790b7275c88Smartynas 		{
791b7275c88Smartynas 		asctoe( fwidth, WIDTH );
792b7275c88Smartynas 		asctoe( a13, e27 );
793b7275c88Smartynas 		}
794b7275c88Smartynas 	asctoe( a10m13, e10m13 );
795b7275c88Smartynas 	mnrflag = 0;
796b7275c88Smartynas 	}
797b7275c88Smartynas drand( &x );
798b7275c88Smartynas e53toe( &x, ex ); /* x = WIDTH *  ( x - 1.0 )  +  LOW; */
799b7275c88Smartynas esub( eone, ex, ex );
800b7275c88Smartynas emul( WIDTH, ex, ex );
801b7275c88Smartynas eexp( ex, ex );   /* x = exp(x); */
802b7275c88Smartynas 
803b7275c88Smartynas drand( &a );
804b7275c88Smartynas e53toe( &a, ea );
805b7275c88Smartynas emul( ea, ex, ea );  /* a = 1.0e-13 * x * a; */
806b7275c88Smartynas emul( e10m13, ea, ea );
807b7275c88Smartynas eabs( ea );
808b7275c88Smartynas eadd( ea, ex, ex );	/* add fuzz */
809b7275c88Smartynas emul( ex, ex, ex );	/* square it, to get range to 10^17 - 1 */
810b7275c88Smartynas efloor( ex, em ); /* this is M */
811b7275c88Smartynas 
812b7275c88Smartynas /* Random power of 10 */
813b7275c88Smartynas drand( &a );
814b7275c88Smartynas e53toe( &a, ex );
815b7275c88Smartynas esub( eone, ex, ex ); /* y3 = 54.0 *  ( y3 - 1.0 ) + 0.5; */
816b7275c88Smartynas emul( e27, ex, ex );
817b7275c88Smartynas eadd( ex, ex, ex );
818b7275c88Smartynas eadd( ehalf, ex, ex );
819b7275c88Smartynas efloor( ex, ex ); /* y3 = floor( y3 ) - 27.0; */
820b7275c88Smartynas esub( e27, ex, en ); /* this is N */
821b7275c88Smartynas epow( eten, en, ex );
822b7275c88Smartynas emul( ex, em, erand );
823b7275c88Smartynas }
824b7275c88Smartynas 
825b7275c88Smartynas /* -ln 2^16382 */
826b7275c88Smartynas char *ldemin = "-1.1355137111933024058873097E4";
827b7275c88Smartynas char *ldewid =  "2.2710274223866048117746193E4";
828b7275c88Smartynas /* -ln 2^1022 */
829b7275c88Smartynas char *demin  = "-7.0839641853226410622441123E2";
830b7275c88Smartynas char *dewid  =  "1.4167928370645282124488225E3";
831b7275c88Smartynas /* -ln 2^125 */
832b7275c88Smartynas char *femin  = "-8.6643397569993163677154015E1";
833b7275c88Smartynas char *fewid  =  "1.7328679513998632735430803E2";
834b7275c88Smartynas 
etrand(erand)835b7275c88Smartynas void etrand( erand )
836b7275c88Smartynas unsigned short erand[];
837b7275c88Smartynas {
838b7275c88Smartynas unsigned short ea[NE], ex[NE];
839b7275c88Smartynas double x, a;
840b7275c88Smartynas 
841b7275c88Smartynas if( etrflag )
842b7275c88Smartynas 	{
843b7275c88Smartynas 	if( etrflag == 3 )
844b7275c88Smartynas 		{
845b7275c88Smartynas 		asctoe( ldemin, LOW );
846b7275c88Smartynas 		asctoe( ldewid, WIDTH );
847b7275c88Smartynas 		asctoe( a34, e27 );
848b7275c88Smartynas 		}
849b7275c88Smartynas 	if( etrflag == 2 )
850b7275c88Smartynas 		{
851b7275c88Smartynas 		asctoe( demin, LOW );
852b7275c88Smartynas 		asctoe( dewid, WIDTH );
853b7275c88Smartynas 		asctoe( a27, e27 );
854b7275c88Smartynas 		}
855b7275c88Smartynas 	if( etrflag == 1 )
856b7275c88Smartynas 		{
857b7275c88Smartynas 		asctoe( femin, LOW );
858b7275c88Smartynas 		asctoe( fewid, WIDTH );
859b7275c88Smartynas 		asctoe( a13, e27 );
860b7275c88Smartynas 		}
861b7275c88Smartynas 	asctoe( a10m13, e10m13 );
862b7275c88Smartynas 	etrflag = 0;
863b7275c88Smartynas 	}
864b7275c88Smartynas drand( &x );
865b7275c88Smartynas e53toe( &x, ex ); /* x = WIDTH *  ( x - 1.0 )  +  LOW; */
866b7275c88Smartynas esub( eone, ex, ex );
867b7275c88Smartynas emul( WIDTH, ex, ex );
868b7275c88Smartynas eadd( LOW, ex, ex );
869b7275c88Smartynas eexp( ex, ex );   /* x = exp(x); */
870b7275c88Smartynas 
871b7275c88Smartynas /* add fuzz
872b7275c88Smartynas  */
873b7275c88Smartynas drand( &a );
874b7275c88Smartynas e53toe( &a, ea );
875b7275c88Smartynas emul( ea, ex, ea );  /* a = 1.0e-13 * x * a; */
876b7275c88Smartynas emul( e10m13, ea, ea );
877b7275c88Smartynas if( ecmp( ex, ezero ) > 0 )
878b7275c88Smartynas 	eneg( ea );
879b7275c88Smartynas eadd( ea, ex, erand );
880b7275c88Smartynas }
881b7275c88Smartynas 
882