[Oberon] real to longint

Patrik Reali reali at acm.org
Thu Aug 14 00:20:40 CEST 2003


The language report defines ENTIER (x) as "the largest integer not greater
than x".

On IA32 (aka Intel) machines, the default behaviour of the FPU is "round to
nearest". For ENTIER, the FPU mode must be changed to "round to -infinity".
Because of the peculiar (also said brain dead) design of the IA32 FPU,
changing the rounding mode is quite complicated and expensive and requires
as many as 4-5 instructions.

It is somewhat strange, that the Oberon language provides only this function
(pascal also had TRUNC).

Jacques' routine is obviously faster but implements a slightly different
semantic (round to nearest). You may think that this is a tiny detail, but
changing this in the language breaks quite some code using reals (in
particular in the GUI and the printing support) [yes, we tried that!].

-Patrik

----- Original Message -----
From: "Jacques Eloff" <eloff at cs.sun.ac.za>
To: <oberon at inf.ethz.ch>
Sent: Thursday, August 14, 2003 2:56 AM
Subject: Re: [Oberon] real to longint


> Hi
>
> ENTIER works fine, but changes the rounding of the FPU. I'm talking
strictly
> Intel now (Patrik, please correct me if I'm wrong). From what I can
gather,
> when ENTIER is used, the compiler first pushes the FPU control word onto
the
> stack, changes it to 400H (Which selects 'round to negative infinity'),
does
> the FISTP (floating point integer store with pop) and then restores the
> floating point control word. Try displaying 3.6.
> Texts.WriteRealFix gives 3.599999.....
> ENTIER(3.6) = 3
> The routine below gives 4 since it uses the default rounding.
> I suspect the 3 is because Oberon always rounds and ENTIER explicitly
selects
> this option
>
> Shortest way I can think is the following:
>
> PROCEDURE -Real2Longint(r: REAL): LONGINT;
> CODE {SYSTEM.i386}
>   FLD DWORD [ESP]      ; Load r into ST(0)
>   FISTP DWORD [ESP]   ; Store ST(0) in [ESP] and pop ST(0)
>   POP EAX                     ; EAX = [ESP]
> END Real2Longint;
>
> Since its an inline routine, there's 0 overhead, except for the real which
is
> pushed on to the CPU stack. It reuses the stack space allocated to r by
> storing the LONGINT in its place and popping it back as the function
result.
>
> Regards
>
>
> --
> Jacques Eloff
> Department of Computer Science
> University of Stellenbosch
> http://www.cs.sun.ac.za/~eloff
>
> --
> Oberon at inf.ethz.ch mailing list for ETH Oberon and related systems
> http://www.lists.inf.ethz.ch/mailman/listinfo/oberon
>
>




More information about the Oberon mailing list