[comp.lang.c] Incorrect subtraction in C program

jwp@uwmacc.UUCP (Jeffrey W Percival) (06/02/87)

I have a problem I have distilled down into a short C program.
The problem is that when I subtract a tiny number from 1,
I get 1 (the right answer) on a VAX 780 running 4.3BSD, but
I get 0 (the wrong answer) on a MicroVAX running 4.3BSD.  Here's
the program:
---------------------------------------------------
#include <stdio.h>
#include <math.h>

main()
{
    double a, b, c, d, e;

    a = 1.000000;
    b = 0.000001;
    c = 0.193113;

    d = (b * c);
    e = a - d;

    fprintf(stdout, "a=%f, b=%f, c=%f, d=%f, e=%f\n", a, b, c, d, e);

    exit(0);
}
----------------------------------------------------------
and here's the MicroVAX output followed by the VAX 780 output:
-------------------------------------------------------
a=1.000000, b=0.000001, c=0.193113, d=0.000000, e=0.000000
a=1.000000, b=0.000001, c=0.193113, d=0.000000, e=1.000000

So, the MicroVAX says that (a-d) is 0, not 1.
What's the deal here?
-- 
	Jeff Percival (jwp@salvax1)

chris@mimsy.UUCP (06/02/87)

In article <1573@uwmacc.UUCP> jwp@uwmacc.UUCP (Jeffrey W Percival) writes:
>The problem is that when I subtract a tiny number from 1,
>I get 1 (the right answer) on a VAX 780 running 4.3BSD, but
>I get 0 (the wrong answer) on a MicroVAX running 4.3BSD.  Here's
>the program:

[the important line:]
>    fprintf(stdout, "a=%f, b=%f, c=%f, d=%f, e=%f\n", a, b, c, d, e);

There is a bug in the emulation code in /sys/vax/emulate.s.  Try

	main(){printf("%.0f\n", 0.9);exit(0);}

I have not seen a fix on comp.bugs.4bsd.ucb-fixes.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

drw@cullvax.UUCP (Dale Worley) (06/04/87)

jwp@uwmacc.UUCP (Jeffrey W Percival) writes:
> I have a problem I have distilled down into a short C program.
> The problem is that when I subtract a tiny number from 1,
> I get 1 (the right answer) on a VAX 780 running 4.3BSD, but
> I get 0 (the wrong answer) on a MicroVAX running 4.3BSD.  Here's
> the program:

This may have to do with the fact that the code in BSD that simulates
the VAX instructions that the uVAX hardware doesn't have has problems
with it.  If you have VMS on a uVAX also, use the debuggers to see if
the floating subtract instructions produce different results on the
two OS's from the same arguments.  (There's someone out in netland who
knows more about this.)

Dale
-- 
Dale Worley		Cullinet Software
UUCP: ...!seismo!harvard!mit-eddie!cullvax!drw
ARPA: cullvax!drw@eddie.mit.edu
Un*x (a generic name for a class of OS's) != Unix (AT&T's brand of such)

ed@mtxinu.UUCP (06/04/87)

>>The problem is that when I subtract a tiny number from 1,
>
>There is a bug in the emulation code in /sys/vax/emulate.s.  Try
>
>	main(){printf("%.0f\n", 0.9);exit(0);}
>
>I have not seen a fix on comp.bugs.4bsd.ucb-fixes.

I posted fixes for that problem to this group some months ago.  mt Xinu
customers - including educational institutions - with maintenance
contracts also received a Maintenance Release with the correct code in
the past several weeks.  I don't have the diffs handy right now;
if anyone needs them and can't get them either from an archive or
from our product release, send me *mail* and I'll dig them out again.

-- 
Ed Gould                    mt Xinu, 2560 Ninth St., Berkeley, CA  94710  USA
{ucbvax,decvax}!mtxinu!ed   +1 415 644 0146

"A man of quality is not threatened by a woman of equality."

rick@seismo.CSS.GOV (Rick Adams) (06/05/87)

From ed@mtxinu.UUCP Tue Jan 27 15:57:30 1987
Path: beno!seismo!rutgers!sri-spam!mordor!lll-lcc!unisoft!mtxinu!ed
From: ed@mtxinu.UUCP (Ed Gould)
Newsgroups: comp.bugs.4bsd
Subject: MicroVAX emulation code bug fixes
Message-ID: <289@mtxinu.UUCP>
Date: 27 Jan 87 20:57:30 GMT
Reply-To: ed@mtxinu.UUCP (Ed Gould)
Distribution: comp
Organization: mt Xinu, Berkeley, CA
Lines: 246
Index: 	sys/vax/emulate.s 4.3BSD
Status: RO

Description:
	The MicroVAX emulation code for unimplemented instructions has
	a few bugs that show themselves at the limits of "printf"s.
	Also, there are numerous places where separate increment and
	test instructions can be combined into one "sob" instruction.
Repeat-By:
	On a uVAX-II running 4.3:
		printf("%.0f\n", 0.9);
	produces
		0
	And, in some cases, "df" will produce a capacity of 00% when
	it should be 100%.  Other mysterious things can happen to code
	written by those strange folk who program in assembly.
Fix:
	A diff of emulate.s follows:
58,61c56,57
< 	toarg(r8,1)		# save r8 in arg1 spot
< 	argl(4,r8)		# (4) source address == r8
< 	toarg(r1,4)		# save r1 in arg4 spot
< 	tstl	arg3		# (3) source length == "arg3"
---
> 	argl(4,r3)		# (4) source address == r3
> 	arguw(3,r2)		# (3) source length == r2
64c60
< 	xorb2	(r8)+,r0
---
> 	xorb2	(r3)+,r0
71,72c67
< 	decl	arg3
< 	jneq	Lcrc_loop
---
> 	sobgtr	r2,Lcrc_loop
76,77c71
< 	argl(1,r8)
< 	argl(4,r1)
---
> 	clrl	r1
97,99c91,92
< 	decl	r4
< 	jeql	Lmovtc_out
< 	jbr	Lmovtc_loop
---
> 	sobgtr	r4,Lmovtc_loop
> 	jbr	Lmovtc_out
102,103c95
< 	decl	r4
< 	jneq	Lmovtc_2loop
---
> 	sobgtr	r4,Lmovtc_2loop
131,132c123
< 	decl	r4
< 	jneq	Lmovtuc_loop
---
> 	sobgtr	r4,Lmovtuc_loop
163,164c154
< 	decl	r2
< 	jneq	Lmatchc_loop
---
> 	sobgtr	r2,Lmatchc_loop
168a159
> 	movl	r1,r3
180d170
< 	argl(3,r3)		# (3) table address == r3
181a172
> 	argl(3,r3)		# (3) table address == r3
190,191c181
< 	decl	r0
< 	jneq	Lspanc_loop
---
> 	sobgtr	r0,Lspanc_loop
202d191
< 	argl(3,r3)		# (3) table address == r3
203a193
> 	argl(3,r3)		# (3) table address == r3
212,213c202
< 	decl	r0
< 	jneq	Lscanc_loop
---
> 	sobgtr	r0,Lscanc_loop
226c215
< 	incl	r0
---
> 	jeql	Lskpc_out	# forget zero length strings
228,233c217,220
< 	decl	r0
< 	jeql	Lskpc_out
< 	cmpb	(r1)+,r11
< 	jeql	Lskpc_loop
< 	decl	r1
< 	tstl	r0
---
> 	cmpb	(r1),r11
> 	jneq	Lskpc_out
> 	incl	r1
> 	sobgtr	r0,Lskpc_loop
234a222
> 	tstl	r0		# be sure of condition codes
245c233
< 	incl	r0
---
> 	jeql	Lskpc_out	# forget zero length strings
247c235
< 	decl	r0
---
> 	cmpb	(r1),r11
249,252c237,238
< 	cmpb	(r1)+,r11
< 	jneq	Llocc_loop
< 	decl	r1
< 	tstl	r0
---
> 	incl	r1
> 	sobgtr  r0,Llocc_loop
253a240
> 	tstl	r0		# be sure of condition codes
270,271c257
< 	decl	r0
< 	jneq	Lcmpc3_loop
---
> 	sobgtr	r0,Lcmpc3_loop
295,296c281
< 	decl	r0
< 	jneq	Lcmpc5_loop
---
> 	sobgtr	r0,Lcmpc5_loop
304,305c289
< 	decl	r2
< 	jneq	Lcmpc5_str2loop
---
> 	sobgtr	r2,Lcmpc5_str2loop
311,312c295
< 	decl	r0
< 	jneq	Lcmpc5_str1loop
---
> 	sobgtr	r0,Lcmpc5_str1loop
514,515c497
< 	decl	r11		# while (--source length)
< 	jneq	Laddp4_same_loop
---
> 	sobgtr	r11,Laddp4_same_loop	# while (--source length)
583,584c565
< 	decl	r11		# loop for length of source
< 	jneq	Lmovp_copy
---
> 	sobgtr	r11,Lmovp_copy	# loop for length of source
797,798c778
< 	decl	r11
< 	jneq	L200
---
> 	sobgtr	r11,L200
830,831c810
< 	decl	r1
< 	jneq	Le_fill_loop
---
> 	sobgtr	r1,Le_fill_loop
856,857c835
< 	decl	r1
< 	jneq	L214
---
> 	sobgtr	r1,L214
885,886c863
< 	decl	r1
< 	jneq	L221
---
> 	sobgtr	r1,L221
901a879
> 			# arg2 holds "even or odd" destination length
918,919c896,901
< L245:				# r3<0> counts digits going into destination
< 	bisl2	$1,r3		#	and is flip-flop for which nibble to
---
> L245:
> 	clrl	arg2		# arg2 is 1 if dstlen is even, 0 if odd
> 	blbs	r3,L246
> 	incl	arg2
> 	bisl2	$1,r3		# r3<0> counts digits going into destination
> L246:				#	and is flip-flop for which nibble to
946,948c928,929
< 	decl	r3		# move to next nibble in destination, but
< 	jneq	L258		#	don't go beyond the end.
< 	incl	r3
---
> 	sobgtr	r3,L258		# move to next nibble in destination, but
> 	incl	r3		#	don't go beyond the end.
959c940
< 	jeql	Lashp_sethigh
---
> 	jeql	Lashp_round
981,984c962,966
< 	jgeq	Lashp_noovfl	# if we've moved passed destination limits
< 	clrl	r3		#	test the result for possible overflow
< 	tstl	arg5		#	ignore zero nibbles
< 	jeql	L265		#	if the nibble was non-zero, overflow
---
> 	cmpl	r3,arg2		# if we've moved passed destination limits
> 	jgeq	Lashp_noovfl	#	test the result for possible overflow
> 	movl	arg2,r3		#	ignore zero nibbles
> 	tstl	arg5		#	if the nibble was non-zero, overflow
> 	jeql	L265
991,992c973
< 	decl	r6
< 	insv	arg5,$0,$4,(r6)
---
> 	movb	arg5,-(r6)
994,995c975
< 	decl	r10		# loop for length of source
< 	jneq	Lashp_shloop
---
> 	sobgtr	r10,Lashp_shloop	# loop for length of source
997,1000c977,985
< Lashp_sethigh:
< 	jlbc	r3,L266		# if we haven't set the high nibble,
< 	insv	r2,$4,$4,(r6)	# carry the round into the high nibble
< 	clrl	r2
---
> Lashp_round:
> 	tstl	r2		# take care of round out of high nibble
> 	jeql	Lashp_zeroround
> 	decl	r3
> 	cmpl	r3,arg2		# if we've moved passed destination limits
> 	jlss	Lashp_overfl	#	then overflow
> 	jlbs	r3,L266
> 	insv	arg5,$4,$4,(r6)	# put the round into destination (high or low)
> 	jbr	Lashp_zeroround
1001a987,989
> 	movb	arg5,-(r6)
> 
> Lashp_zeroround:
1008,1009c996
< 	cvtlb	r2,-(r6)	# fill up MSNs of destination with carry or zero
< 	clrl	r2
---
> 	clrb	-(r6)		# fill up MSNs of destination with zeros
1013,1014d999
< 	tstl	r2		# if carry beyond destination, overflow
< 	jneq	Lashp_overfl
1102,1103c1087
< 	decl	r11
< 	jneq	Lcvtpl_loop
---
> 	sobgtr	r11,Lcvtpl_loop
-- 
Ed Gould                    mt Xinu, 2560 Ninth St., Berkeley, CA  94710  USA
{ucbvax,decvax}!mtxinu!ed   +1 415 644 0146

"A man of quality is not threatened by a woman of equality."