OpenVMS Source-Code Demos

BASIC_DECIMAL_MOD_BUG

1000	!=============================================================================
	! title  : BASIC_DECIMAL_MOD_PROBLEM.BAS
	!	   (was: diffie_hellman_demo_100.bas)
	! author : Neil Rieck
	! history:
	! 101 NSR 120910 1. derived from BASIC_DECIMAL_MOD_PROBLEM.BAS
	!		 2. testing with: Alpha BASIC V1.7-000 (original compiler)
	! 102 NSR 120914 1. testing with: Alpha BASIC V1.7-001 (test compiler)
	!=============================================================================
	! Sample Output (production compiler - Alpha BASIC V1.7-000):
	!
	!	====================
	!	pow1:  31
	!	tmp0:  2147483648           <-- 2^31
	!	tmp1:  2147483649           <-- tmp0 + 1
	!	div1:  1073741824           <-- tmp1 / 2
	!	mod1:  1                    <-- tmp1 % 2
	!	====================
	!	pow1:  32                   fails at 32
	!	tmp0:  4294967296
	!	tmp1:  4294967297
	!	div1:  2147483648
	!	-e-error: 51 at stage 4
	!	%NONAME-E-NOMSG, Message number 00000002
	!=============================================================================
	! Sample Output (experimental compiler - Alpha BASIC V1.7-001):
	!
	!	====================
	!	pow1: 53                    works at 53 (no compile-time warning)
	!	tmp0: 9007199254740992 
	!	tmp1: 9007199254740993 
	!	div1: 4503599627370496 
	!	mod1: 1 
	!	====================
	!	pow1: 54                    appears to work at 54 (with compile-time warnings)
	!	tmp0: 18014398509481984 
	!	tmp1: 18014398509481985 
	!	div1: 9007199254740992 
	!	mod1: 1 
	!	...
	!	====================
	!	pow1:  63                   this test appears to work at 63
	!	tmp0:  9223372036854775808  <-- 2^63
	!	tmp1:  9223372036854775809  <-- tmp0 + 1 ("this test" appears to work)
	!	div1:  4611686018427387904  <-- tmp1 / 2 ("this test" appears to work)
	!	mod1:  1                    <-- tmp1 % 2 ("this test" appears to work)
	!	====================
	!	pow1:  64                   this test fails
	!	tmp0:  18446744073709551616 <-- 2^64
	!	tmp1:  1                    Oops (GFLOAT loss of precision)
	!	div1:  0                    Oops (GFLOAT loss of precision)
	!	mod1:  1                    Oops (GFLOAT loss of precision)
	!	====================
	!	note: this version of BASIC code was never meant to operate this high
	!=============================================================================
	option	type = explicit			,	!			&
		size = integer	quad		,	!			&
		size = real	xfloat		, 	!			&
		size = decimal	(31,0)			!
	declare long	rc%			,	! return code		&
			stage%			,	! stage register	&
			error%				! error register
!----------------------------------------------------------------------------------------------
!	notes:
!	1) 2^102 = 5070602400912917605986812821504 requires 31 decimal digits.
!	2) GFLOAT (which is used behind the scenes) only guarantees 15 digits of precision
!	3) BASIC would need to switch to XFLOAT to guarantee 33 digits of precision
!	4) testing with Alpha BASIC V1.7-001 (test compiler)
!
!	   declaration   max size compile warnings notes
!	   ------------- -------- ---------------- --------------------------------------------
!	   decimal(16,0) 2^53     n
!	   decimal(17,0) 2^56     y       safer to use quad
!	   decimal(18,0) 2^59     y       safer to use quad
!	   decimal(19,0) 2^62     y       safer to use quad
!	   decimal(31,0) 2^102    y       safer to use quad
!----------------------------------------------------------------------------------------------
	declare decimal(31,0)	tmp0		,	!			&
				tmp1		,	!			&
				div1		,	!			&
				mod1		,	!			&
				pow1
2000	main:						!
	on error goto trap				! old school trapping
	print "Basic version (decimal)"			!
	when error in					! new school trapping
	    for pow1 = 30 to 102			!
		print "===================="		!
		print "pow1: "; pow1	 		!
		!
		stage% = 1				!
		tmp0 = 2 ^ pow1				! raise 2 to the power of pow1
		print "tmp0: "; tmp0			!
		!
		stage% = 2				!
		tmp1 = tmp0 + 1				! add one to test modulus
		print "tmp1: "; tmp1			!
		!
		stage% = 3				!
		div1 = tmp1 / 2				! lets' try divide
		print "div1: "; div1			!
		!
		stage% = 4				!
		mod1 = mod(tmp1, 2)			! let's try modulus
		print "mod1: "; mod1			!
		!
	     next pow1					!
	     error% = 0					! cool
	use						!
	     error% = err				! oops
	end when					!
	!
	select error%					!
	    case 0					!
		goto fini				!
	    case else					!
		print "-e-error: "+str$(error%)+" at stage "+ str$(stage%)
		goto fini_error				!
	end select					!
	!
30000	trap:						!
	print "error: ";str$(err)			!
	print "line : ";str$(erl)			!
	print "text : ";ert$(err)			!
	resume fini_error				!
	!
	fini_error:					!
	rc% = 2						! VMS-E-
	goto fini_common				!
	!
32000	fini:						!
	rc% = 1						! VMS-S-
	!
	fini_common:					!
	end program rc%					!