[Oberon] On a code generated for Math.Mod.txt
Srinivas Nayak
sinu.nayak2001 at gmail.com
Fri Jul 15 10:37:29 CEST 2016
Thanks Jorg,
Nice step taken.
I think we are going to keep only INTEGER and deprecate LONGINT...right?
Or?
And, will not SYSTEM.VAL() cause any rounding error using it several times
from LONGINT to REAL and REAL to LONGINT ?
I am not sure on these. Just a thought.
You can better judge here.
With thanks and best regards,
Yours sincerely,
Srinivas Nayak
Home: http://www.mathmeth.com/sn/
Blog: http://srinivas-nayak.blogspot.in/
On 07/15/2016 12:38 PM, Joerg wrote:
> 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
>
> --
> 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