Discussion:
OBNC 0.16.1 Issue with SYSTEM.VAL
(too old to reply)
Guy T.
2020-03-01 03:54:57 UTC
Permalink
Hello all,

I'm using OBNC on MacOS configured with INTEGER and REAL of length 4.

Here is a program that is puzzling me. I would expect both REAL values to be the same after calling SYSTEM.VAL twice, but it's not the case:

MODULE toto;
IMPORT Out, SYSTEM;
VAR
i: REAL;
j: INTEGER;
k: REAL;
BEGIN
i := 123.456;
j := SYSTEM.VAL(INTEGER, i);
k := SYSTEM.VAL(REAL, j);

IF i = k THEN
Out.String("OK")
ELSE
Out.String("NOT OK!"); Out.Ln;
Out.Real(i,0); Out.String(" vs "); Out.Real(k,0)
END;

Out.Ln; Out.String("INTEGER Size: "); Out.Int(SYSTEM.SIZE(INTEGER), 0);
Out.Ln; Out.String("REAL Size: "); Out.Int(SYSTEM.SIZE(REAL), 0);
Out.Ln;
END toto.

The result I get is the following:

$ obnc toto.Mod
$ ./toto
NOT OK!
1.234560E+02 vs 1.230000E+02
INTEGER Size: 4
REAL Size: 4


Any help would be appreciated.

Cheers!

Guy T.
c***@gmail.com
2020-03-01 09:01:10 UTC
Permalink
Post by Guy T.
$ obnc toto.Mod
$ ./toto
NOT OK!
1.234560E+02 vs 1.230000E+02
INTEGER Size: 4
REAL Size: 4
I just ran your test program using the Astrobe for Cortex-M4 and Astrobe for RISC5 Oberon compilers and it was successful. It may be due to a deficiency / limitation / bug in OBNC.
miasap
2020-03-01 10:00:44 UTC
Permalink
Post by Guy T.
I would expect both REAL values to be the same after calling
I can confirm that OBNC is incorrect in this case. The function call
SYSTEM.VAL(T, n) is translated into the C code `(T) n' which performs
value conversion instead of keeping the bit pattern of the value. I will
soon release an update. Thanks for reporting the issue.

Regards,
Karl
Guy T.
2020-03-01 11:20:24 UTC
Permalink
Post by miasap
Post by Guy T.
I would expect both REAL values to be the same after calling
I can confirm that OBNC is incorrect in this case. The function call
SYSTEM.VAL(T, n) is translated into the C code `(T) n' which performs
value conversion instead of keeping the bit pattern of the value. I will
soon release an update. Thanks for reporting the issue.
Regards,
Karl
Thank you very much for your help! In the interim, here is the hand made module in C I'm using to resolve the issue:

#include ".obnc/Reals.h"
#include <obnc/OBNC.h>

#define OBERON_SOURCE_FILENAME "Reals.Mod"

union {
OBNC_REAL f;
OBNC_INTEGER i;
} w;
void Reals__RealToInt_(OBNC_REAL r_, OBNC_INTEGER *i_) {
w.f = r_; *i_ = w.i;
}
void Reals__IntToReal_(OBNC_INTEGER i_, OBNC_REAL *r_) {
w.i = i_; *r_ = w.f;
}
void Reals__Init(void) {
}

Cheers!

Guy T.
n***@gmail.com
2020-03-05 11:25:16 UTC
Permalink
Post by Guy T.
Hello all,
I'm using OBNC on MacOS configured with INTEGER and REAL of length 4.
MODULE toto;
IMPORT Out, SYSTEM;
VAR
i: REAL;
j: INTEGER;
k: REAL;
BEGIN
i := 123.456;
j := SYSTEM.VAL(INTEGER, i);
k := SYSTEM.VAL(REAL, j);
IF i = k THEN
Out.String("OK")
ELSE
Out.String("NOT OK!"); Out.Ln;
Out.Real(i,0); Out.String(" vs "); Out.Real(k,0)
END;
Out.Ln; Out.String("INTEGER Size: "); Out.Int(SYSTEM.SIZE(INTEGER), 0);
Out.Ln; Out.String("REAL Size: "); Out.Int(SYSTEM.SIZE(REAL), 0);
Out.Ln;
END toto.
$ obnc toto.Mod
$ ./toto
NOT OK!
1.234560E+02 vs 1.230000E+02
INTEGER Size: 4
REAL Size: 4
Any help would be appreciated.
Cheers!
Guy T.
I dont have a Oberon compiler at the moment. Thus I am unable to
test this for myself. But I am curious to know so please help:

When I first read the post I thought it was obvious.

It all comes down to 3 lines:

i := 123.456;
j := SYSTEM.VAL(INTEGER, i);
k := SYSTEM.VAL(REAL, j);

j=123
k=1.23e02

Then you are comparing i & k and naturally they are not equal
i=1.23456e02 k=1.23e02 as your output shows.

You are comparing real numbers and I cannot see anywhere where
you have restricted the precision of the comparison.

What am I missing ?
Guy T.
2020-03-05 11:56:59 UTC
Permalink
Post by n***@gmail.com
Post by Guy T.
Hello all,
I'm using OBNC on MacOS configured with INTEGER and REAL of length 4.
MODULE toto;
IMPORT Out, SYSTEM;
VAR
i: REAL;
j: INTEGER;
k: REAL;
BEGIN
i := 123.456;
j := SYSTEM.VAL(INTEGER, i);
k := SYSTEM.VAL(REAL, j);
IF i = k THEN
Out.String("OK")
ELSE
Out.String("NOT OK!"); Out.Ln;
Out.Real(i,0); Out.String(" vs "); Out.Real(k,0)
END;
Out.Ln; Out.String("INTEGER Size: "); Out.Int(SYSTEM.SIZE(INTEGER), 0);
Out.Ln; Out.String("REAL Size: "); Out.Int(SYSTEM.SIZE(REAL), 0);
Out.Ln;
END toto.
$ obnc toto.Mod
$ ./toto
NOT OK!
1.234560E+02 vs 1.230000E+02
INTEGER Size: 4
REAL Size: 4
Any help would be appreciated.
Cheers!
Guy T.
I dont have a Oberon compiler at the moment. Thus I am unable to
When I first read the post I thought it was obvious.
i := 123.456;
j := SYSTEM.VAL(INTEGER, i);
k := SYSTEM.VAL(REAL, j);
j=123
k=1.23e02
Then you are comparing i & k and naturally they are not equal
i=1.23456e02 k=1.23e02 as your output shows.
You are comparing real numbers and I cannot see anywhere where
you have restricted the precision of the comparison.
What am I missing ?
SYSTEM.VAL is a mean to change the type associated to a variable without changing the memory content. In the example the variable i is seen as REAL -> INTEGER -> REAL, but the internal representation of the content, bits by bits, is not changed.

In C, a way to get the same result would be to use an union structure like this: union { float real; int integer; } val; and use statements like this: val.real = i; j = val.integer; to exchange the meaning of the content between floating point and integer types.

As there is no modification to the content, the equality of values when comparing two real variables is preserved, as we are comparing the same data, bits per bits.

Hope this is clear enough.

Cheers!

Guy T.
n***@gmail.com
2020-03-05 14:02:46 UTC
Permalink
Post by Guy T.
Post by n***@gmail.com
Post by Guy T.
Hello all,
I'm using OBNC on MacOS configured with INTEGER and REAL of length 4.
MODULE toto;
IMPORT Out, SYSTEM;
VAR
i: REAL;
j: INTEGER;
k: REAL;
BEGIN
i := 123.456;
j := SYSTEM.VAL(INTEGER, i);
k := SYSTEM.VAL(REAL, j);
IF i = k THEN
Out.String("OK")
ELSE
Out.String("NOT OK!"); Out.Ln;
Out.Real(i,0); Out.String(" vs "); Out.Real(k,0)
END;
Out.Ln; Out.String("INTEGER Size: "); Out.Int(SYSTEM.SIZE(INTEGER), 0);
Out.Ln; Out.String("REAL Size: "); Out.Int(SYSTEM.SIZE(REAL), 0);
Out.Ln;
END toto.
$ obnc toto.Mod
$ ./toto
NOT OK!
1.234560E+02 vs 1.230000E+02
INTEGER Size: 4
REAL Size: 4
Any help would be appreciated.
Cheers!
Guy T.
I dont have a Oberon compiler at the moment. Thus I am unable to
When I first read the post I thought it was obvious.
i := 123.456;
j := SYSTEM.VAL(INTEGER, i);
k := SYSTEM.VAL(REAL, j);
j=123
k=1.23e02
Then you are comparing i & k and naturally they are not equal
i=1.23456e02 k=1.23e02 as your output shows.
You are comparing real numbers and I cannot see anywhere where
you have restricted the precision of the comparison.
What am I missing ?
SYSTEM.VAL is a mean to change the type associated to a variable without changing the memory content. In the example the variable i is seen as REAL -> INTEGER -> REAL, but the internal representation of the content, bits by bits, is not changed.
In C, a way to get the same result would be to use an union structure like this: union { float real; int integer; } val; and use statements like this: val.real = i; j = val.integer; to exchange the meaning of the content between floating point and integer types.
As there is no modification to the content, the equality of values when comparing two real variables is preserved, as we are comparing the same data, bits per bits.
Hope this is clear enough.
Cheers!
Guy T.
Thank you for the explanation. I can see now where I was going wrong.
Loading...