[Oberon] On a code generated for Math.Mod.txt

Joerg joerg.straube at iaeth.ch
Fri Jul 15 09:08:59 CEST 2016


Hi Srinivas

While investigating your problem I found two flaws in the current compiler :-(

Lets start with the basics
The rounding effect you found in the C compiler has the Oberon compiler as well. At least in the emulator, did not check on the real  FPGA implementation yet.

Compile this code, and look at the assembly
- - - - - - 
  MODULE RealTest
  VAR r1, r2: REAL
  BEGIN
    r1 := 0.99999993;
    r2 := 0.99999994;
  END RealTest.
- - - - - - 
You will find that r1 is smaller than 1.0 and r2 is equal to 1.0.

So the rounding effect is there, but it is numerically incorrect, as the rounding effect should occur between
  0.99999998 and 0.99999999
This is the first flaw: The code in ORS.Number is not fine-tuned to numerical rounding errors when dealing with REALs.

I wanted to prove my statement that it is possible to improve the compiler code by doing this:
  MODULE RealTest
  VAR r1, r2: REAL
  BEGIN
    r1 := 0.9999999 + 8.E-8;
    r2 := 0.9999999 + 9.E-8;
  END RealTest.

By compiling this, I found that the compiler does not evaluate constant expressions when dealing with REAL constants
(Unnecessary FADDs are generated)

Hence I added the const evaluation to ORG.RealOp to

	PROCEDURE RealOp*(op: INTEGER; VAR x, y: Item);	(* x := x op y *)
	BEGIN
		IF (x.mode = ORB.Const) & (y.mode = ORB.Const) THEN
			IF op = ORS.plus THEN x.a := S.VAL(LONGINT, S.VAL(REAL, x.a) + S.VAL(REAL, y.a))
			ELSIF op = ORS.minus THEN x.a := S.VAL(LONGINT, S.VAL(REAL, x.a) - S.VAL(REAL, y.a))
			ELSIF op = ORS.times THEN x.a := S.VAL(LONGINT, S.VAL(REAL, x.a) * S.VAL(REAL, y.a))
			ELSIF op = ORS.rdiv THEN
				IF S.VAL(SET, y.a) - {31} = {}  THEN (* catching IEEE754 +0 and -0 *)
					ORS.Mark(„divisor 0.0“) 
				ELSE
					x.a := S.VAL(LONGINT, S.VAL(REAL, x.a) / S.VAL(REAL, y.a))
				END
			END
		ELSE
			load(x); load(y);
			IF op = ORS.plus THEN Put0(Fad, RH-2, x.r, y.r)
			ELSIF op = ORS.minus THEN Put0(Fsb, RH-2, x.r, y.r)
			ELSIF op = ORS.times THEN Put0(Fml, RH-2, x.r, y.r)
			ELSIF op = ORS.rdiv THEN Put0(Fdv, RH-2, x.r, y.r)
			END ;
			DEC(RH); x.r := RH-1
		END
	END RealOp;

After compiling ORG.Mod, unloading the old compiler and re-compiling my test module with the improved compiler, you see that r1 is smaller than 1.0 and r2 is 1.0 —> the rounding effect is indeed between  0.99999998 and 0.99999999.
 
Jörg

> Am 14.07.2016 um 09:25 schrieb Srinivas Nayak <sinu.nayak2001 at gmail.com>:
> 
> Thanks Jorg.
> You are correct.
> 
> I see in C, on x86,
> 
> #include <stdio.h>
> int main()
> {
> 	union {float f; int i;}u;
> 
> 	u.f = 9.999999e-1;
> 	printf("%e  =  ", u.f);
> 	printf("%#x\n", u.i);
> 
> 	u.f = 9.9999999e-1;
> 	printf("%e  =  ", u.f);
> 	printf("%#x\n", u.i);
> 
> 	return 0;
> }
> 
> produces
> 
> # ./a.out
> 9.999999e-01  =  0x3f7ffffe
> 1.000000e+00  =  0x3f800000
> #
> 
> But I think, Oberon doesn't convert 9.9999999e-1 to 1.000000e+00.
> When both use 32bit and use IEEE 754 format, what is causing this?
> Is it language trick? I don't think so, since Oberon compiler doesn't do anything special for this.
> Is it processor dependent thing? Don't know anything about this.
> 
> Hope you will shed some more light on this deepening darkness.
> 
> 
> 
> With thanks and best regards,
> 
> Yours sincerely,
> Srinivas Nayak
> 
> Home: http://www.mathmeth.com/sn/
> Blog: http://srinivas-nayak.blogspot.in/
> 
> On 07/14/2016 03:26 AM, Jörg Straube wrote:
>> Srinivas
>> 
>>    MOV' R1 #aa    (upper 16 bit)
>>    IOR R1 #bb       (lower 16 bit)
>> is the code to fill the register R1 with the 32 bit constant #aabb
>> 
>> You find all the details of the RISC5 instruction set in this paper:
>> https://www.inf.ethz.ch/personal/wirth/FPGA-relatedWork/RISC-Arch.pdf
>> 
>> Jörg
>> 
>> 
>> 
>> Gruss, Jörg
>>> Am 13.07.2016 um 21:18 schrieb Srinivas Nayak <sinu.nayak2001 at gmail.com>:
>>> 
>>> In math.Mod.txt we see
>>> 
>>> q0 =  9.9999999E-1;
>>> IF ODD(n) THEN f := (((((q6*yy + q5)*yy + q4)*yy + q3)*yy + q2)*yy + q1)*yy + q0
>>> 
>>> ELSE
>>> 
>>> For the last addition of q0, I see the code generated is:
>>> 
>>> 61003F7F  MOV'  R1  R0  16255
>>> 
>>> 4116FFFE  IOR  R1  R1     -2
>>> 
>>> How it is different from
>>> 
>>> 61003F80  MOV'  R1  R0  16256
>>> 
>>> 
>>> 
>>> 
>>> With thanks and best regards,
>>> 
>>> Yours sincerely,
>>> Srinivas Nayak
>>> 
>>> Home: http://www.mathmeth.com/sn/
>>> Blog: http://srinivas-nayak.blogspot.in/
>>> --
>>> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
>>> https://lists.inf.ethz.ch/mailman/listinfo/oberon
>> 
>> --
>> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
>> https://lists.inf.ethz.ch/mailman/listinfo/oberon
>> 
> --
> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
> https://lists.inf.ethz.ch/mailman/listinfo/oberon



More information about the Oberon mailing list