Set Rounding mode for IEEE floating point operations

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

Set Rounding mode for IEEE floating point operations

Steffen Märcker
Hi,

is there any way to set the rounding mode for IEEE floating point
operations? Maybe something like

> Double roundToMinusInfWhile: [... code goes here ...]Double  
> roundToZeroWhile: [... more code here ...]

If not, is it possible to add this behavior, e.g., via a custom primitive?

Best, Steffen

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

SergeStinckwich


On Mon, Jan 15, 2018 at 12:27 PM, Steffen Märcker <[hidden email]> wrote:
Hi,

is there any way to set the rounding mode for IEEE floating point
operations? Maybe something like

Double roundToMinusInfWhile: [... code goes here ...]Double roundToZeroWhile: [... more code here ...]

If not, is it possible to add this behavior, e.g., via a custom primitive?


​This might interesting to have something like that for PolyMath, but I'm a little worried of subtle consequences
that might appear in UI if you use points for examples.​

--
Serge Stinckwich
UMI UMMISCO 209 (IRD/UPMC/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/
Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

Steffen Märcker
Yes, I was considering this in the context of some approximation  
algorithms. Maybe one of the VM experts here could comment on the  
possibility to implement that?


Am .01.2018, 10:00 Uhr, schrieb Serge Stinckwich  
<[hidden email]>:

> On Mon, Jan 15, 2018 at 12:27 PM, Steffen Märcker <[hidden email]> wrote:
>
>> Hi,
>>
>> is there any way to set the rounding mode for IEEE floating point
>> operations? Maybe something like
>>
>> Double roundToMinusInfWhile: [... code goes here ...]Double
>>> roundToZeroWhile: [... more code here ...]
>>>
>>
>> If not, is it possible to add this behavior, e.g., via a custom  
>> primitive?
>>
>>
> ​This might interesting to have something like that for PolyMath, but  
> I'm a
> little worried of subtle consequences
> that might appear in UI if you use points for examples.​

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

Steffen Märcker
In reply to this post by Steffen Märcker
*bump*

I guess there no way to do this now. But maybe a VM guy can give me how  
difficult it might be to extend the VM accordingly.

Best, Steffen

Am .01.2018, 12:27 Uhr, schrieb Steffen Märcker <[hidden email]>:

> Hi,
>
> is there any way to set the rounding mode for IEEE floating point
> operations? Maybe something like
>
>> Double roundToMinusInfWhile: [... code goes here ...]Double  
>> roundToZeroWhile: [... more code here ...]
>
> If not, is it possible to add this behavior, e.g., via a custom  
> primitive?
>
> Best, Steffen

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

SergeStinckwich


On Wed, May 23, 2018 at 11:47 AM Steffen Märcker <[hidden email]> wrote:
*bump*

I guess there no way to do this now. But maybe a VM guy can give me how 
difficult it might be to extend the VM accordingly.


​Yes you should followup this question to the VM mailing-list.
so we don't forget about it ?​

​Do you have specific needs behind this ?​

--
Serge Stinckwich
UMI UMMISCO 209 (SU/IRD/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/
Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

Henrik Sperre Johansen
fesetround()/fegetround() are part of C99, and amazingly, also present in the
Windows CRT, it might be possible to try to do this with FFI only?

IIRC the numerical model is supposed to act identical across platforms;
whether it would actually affect anything depends on how the VM achieves
that; I assume it's done by explicitly setting fp state to be identical
(including rounding mode), rather than using some library which avoids
x87/sse ops entirely, but I haven't actually looked.

For the same reason, I hope you intend roundByMethodXWhile: to be a
mandatory API, forgetting to set the mode back when done (or, never getting
there due to errors, etc) is an area best left unexplored ;)

Cheers,
Henry




--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

Steffen Märcker
In reply to this post by SergeStinckwich
I'll cross-post there later. Thanks for the suggestion!

The application I have in mind is approximation algorithms for systems of  
linear equations or linear programs. Approximation algorithms, such as the  
power method, typically run until convergence of the solution vector is  
reached. However, determining convergence is usually done by computing the  
difference (epsilon) between the last two solutions and comparing it to  
some threshold. This may work in some cases but not in general, as the  
intermediate epsilon does not tell the distance to the actual solution.  
Interval iteration tackles this problem by approaching the solution from  
above and below. The difference between the upper and lower solution  
bounds determines the quality of the solution. However, if we use  
imprecise arithmetic (floats, doubles) it is important to round down/up in  
computing the lower/upper bounds.

Best, Steffen



Am .05.2018, 12:50 Uhr, schrieb Serge Stinckwich  
<[hidden email]>:

> On Wed, May 23, 2018 at 11:47 AM Steffen Märcker <[hidden email]> wrote:
>
>> *bump*
>>
>> I guess there no way to do this now. But maybe a VM guy can give me how
>> difficult it might be to extend the VM accordingly.
>>
>>
> ​Yes you should followup this question to the VM mailing-list.
> Can you open an issue here:  
> https://github.com/PolyMathOrg/PolyMath/issues
> so we don't forget about it ?​
>
> ​Do you have specific needs behind this ?​

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

Steffen Märcker
In reply to this post by Henrik Sperre Johansen
Hi Henry,

> [...] it might be possible to try to do this with FFI only?

If I understand you correctly, I could use FFI to call an external lib to  
perform the actual computation according to the rounding mode, right? In  
this case I'd be worry about the performance impact of many FFI calls.

> For the same reason, I hope you intend roundByMethodXWhile: to be a
> mandatory API, forgetting to set the mode back when done (or, never  
> getting
> there due to errors, etc) is an area best left unexplored ;)

I used roundByMethodXWhile: aBlock just to convey the idea that an API  
could work "local" and ensures resetting the rounding mode afterwards. =)

Best, Steffen

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

SergeStinckwich


On Wed, May 23, 2018 at 3:39 PM Steffen Märcker <[hidden email]> wrote:
Hi Henry,

> [...] it might be possible to try to do this with FFI only?

If I understand you correctly, I could use FFI to call an external lib to 
perform the actual computation according to the rounding mode, right? In 
this case I'd be worry about the performance impact of many FFI calls.

> For the same reason, I hope you intend roundByMethodXWhile: to be a
> mandatory API, forgetting to set the mode back when done (or, never 
> getting
> there due to errors, etc) is an area best left unexplored ;)

I used roundByMethodXWhile: aBlock just to convey the idea that an API 
could work "local" and ensures resetting the rounding mode afterwards. =)


​This quite easy to implement :

LibC>>fegetround
    ^ self ffiCall: #(int fegetround(void))​

​LibC>>​
fesetround: round
    ^ self ffiCall: #(void fesetround(int round))
 
​but apparently nothing happens when you do :

LibC uniqueInstance fesetround: 1024.
LibC uniqueInstance fegetround.

always return 0.​

--
Serge Stinckwich
UMI UMMISCO 209 (SU/IRD/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/
Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

Steffen Märcker
I actually made progress: It works like a charm! Basically, I implemented  
the same code as you. Testing is straightforward (using the constant  
values from libc):

   current := LibC fegetround.
   LibC fesetround: FE_DOWNWARDS.
   v1 := 1.0/10.0.
   LibC feesetround: FE_UPWARDS.
   v2 := 1.0/10.0.
   LibC feesetround: current.
   v1 < v2. "true"

> ​but apparently nothing happens when you do :
>   LibC uniqueInstance fesetround: 1024.
>   LibC uniqueInstance fegetround.
> always return 0.​

This is expected, since the fesetround function returns 0 only if the set  
operation was successful.

Thanks again for your support!

Best,
Steffen

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

SergeStinckwich


On Thu, May 24, 2018 at 10:31 AM Steffen Märcker <[hidden email]> wrote:
I actually made progress: It works like a charm! Basically, I implemented 
the same code as you. Testing is straightforward (using the constant 
values from libc):

   current := LibC fegetround.
   LibC fesetround: FE_DOWNWARDS.
   v1 := 1.0/10.0.
   LibC feesetround: FE_UPWARDS.
   v2 := 1.0/10.0.
   LibC feesetround: current.
   v1 < v2. "true"

> ​but apparently nothing happens when you do :
>   LibC uniqueInstance fesetround: 1024.
>   LibC uniqueInstance fegetround.
> always return 0.​

This is expected, since the fesetround function returns 0 only if the set 
operation was successful.


​I was talking about fgetround function.
​ Can you check the value returns by your fegetround function ?​

Constants values are not dependent of the platform ?​

​Can you commit yr code to Pharo 7.0 or if there is no interest for this to PolyMath ?​
​Thank you.​
--
Serge Stinckwich
UMI UMMISCO 209 (SU/IRD/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/
Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

SergeStinckwich
What is really strange is when I print the following lines, I obtain 2048:

current := LibC uniqueInstance fegetround.
LibC uniqueInstance fesetround: 2048.
LibC uniqueInstance fegetround.

and 0 when I remove the first line :
LibC uniqueInstance fesetround: 2048.
LibC uniqueInstance fegetround.



On Thu, May 24, 2018 at 10:37 AM Serge Stinckwich <[hidden email]> wrote:


On Thu, May 24, 2018 at 10:31 AM Steffen Märcker <[hidden email]> wrote:
I actually made progress: It works like a charm! Basically, I implemented 
the same code as you. Testing is straightforward (using the constant 
values from libc):

   current := LibC fegetround.
   LibC fesetround: FE_DOWNWARDS.
   v1 := 1.0/10.0.
   LibC feesetround: FE_UPWARDS.
   v2 := 1.0/10.0.
   LibC feesetround: current.
   v1 < v2. "true"

> ​but apparently nothing happens when you do :
>   LibC uniqueInstance fesetround: 1024.
>   LibC uniqueInstance fegetround.
> always return 0.​

This is expected, since the fesetround function returns 0 only if the set 
operation was successful.


​I was talking about fgetround function.
​ Can you check the value returns by your fegetround function ?​

Constants values are not dependent of the platform ?​

​Can you commit yr code to Pharo 7.0 or if there is no interest for this to PolyMath ?​
​Thank you.​
--
Serge Stinckwich
UMI UMMISCO 209 (SU/IRD/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/


--
Serge Stinckwich
UMI UMMISCO 209 (SU/IRD/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/
Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

Steffen Märcker
Hi,

now I've observed the same issue. It might be related to context  
switching, since introducing a delay has a similar effect. Consider:

   | FE_TONEAREST FE_DOWNWARD FE_UPWARD FE_TOWARDZERO |
   FE_TONEAREST  := 16r0000.
   FE_DOWNWARD   := 16r0400.
   FE_UPWARD     := 16r0800.
   FE_TOWARDZERO := 16r0C00.
   "For some reasons we have to call fegetround once."
   "c := LibC new fegetround."
   LibC new fesetround: FE_DOWNWARD.
   (Delay forSeconds: 1) wait.
   v1 := 1.0/10.0.
   LibC new fesetround: FE_UPWARD.
   v2 := 1.0/10.0.
   LibC new fesetround: FE_TONEAREST.
   v1 < v2.

If the delay is inserted, the script evaluates to false. Using the same  
LibC-instance or creating a new one does not seem to change anything here.  
Interestingly, a similar approach in VisualWorks does not show this issue  
yet.

Actually, I expect the FE_* macros to be platform/implementation  
dependent, as suggested here:
http://www.enseignement.polytechnique.fr/informatique/INF478/docs/Cpp/en/c/numeric/fenv/FE_round.html

Best, Steffen




Am .05.2018, 11:57 Uhr, schrieb Serge Stinckwich  
<[hidden email]>:

> What is really strange is when I print the following lines, I obtain  
> 2048:
>
> current := LibC uniqueInstance fegetround.
> LibC uniqueInstance fesetround: 2048.
> LibC uniqueInstance fegetround.
>
> and 0 when I remove the first line :
> LibC uniqueInstance fesetround: 2048.
> LibC uniqueInstance fegetround.
>
>
>
> On Thu, May 24, 2018 at 10:37 AM Serge Stinckwich <
> [hidden email]> wrote:
>
>>
>>
>> On Thu, May 24, 2018 at 10:31 AM Steffen Märcker <[hidden email]> wrote:
>>
>>> I actually made progress: It works like a charm! Basically, I
>>> implemented
>>> the same code as you. Testing is straightforward (using the constant
>>> values from libc):
>>>
>>>    current := LibC fegetround.
>>>    LibC fesetround: FE_DOWNWARDS.
>>>    v1 := 1.0/10.0.
>>>    LibC feesetround: FE_UPWARDS.
>>>    v2 := 1.0/10.0.
>>>    LibC feesetround: current.
>>>    v1 < v2. "true"
>>>
>>> > ​but apparently nothing happens when you do :
>>> >   LibC uniqueInstance fesetround: 1024.
>>> >   LibC uniqueInstance fegetround.
>>> > always return 0.​
>>>
>>> This is expected, since the fesetround function returns 0 only if the
>>> set
>>> operation was successful.
>>>
>>>
>> ​I was talking about fgetround function.
>> ​ Can you check the value returns by your fegetround function ?​
>>
>> Constants values are not dependent of the platform ?​
>>
>> ​Can you commit yr code to Pharo 7.0 or if there is no interest for this
>> to PolyMath ?​
>> ​Thank you.​
>> --
>> Serge Stinckwich
>> UMI UMMISCO 209 (SU/IRD/UY1)
>> "Programs must be written for people to read, and only incidentally for
>> machines to execute."http://www.doesnotunderstand.org/
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

SergeStinckwich


On Thu, May 24, 2018 at 12:27 PM Steffen Märcker <[hidden email]> wrote:
Hi,

now I've observed the same issue. It might be related to context 
switching, since introducing a delay has a similar effect. Consider:

   | FE_TONEAREST FE_DOWNWARD FE_UPWARD FE_TOWARDZERO |
   FE_TONEAREST  := 16r0000.
   FE_DOWNWARD   := 16r0400.
   FE_UPWARD     := 16r0800.
   FE_TOWARDZERO := 16r0C00.
   "For some reasons we have to call fegetround once."
   "c := LibC new fegetround."
   LibC new fesetround: FE_DOWNWARD.
   (Delay forSeconds: 1) wait.
   v1 := 1.0/10.0.
   LibC new fesetround: FE_UPWARD.
   v2 := 1.0/10.0.
   LibC new fesetround: FE_TONEAREST.
   v1 < v2.

If the delay is inserted, the script evaluates to false. Using the same 
LibC-instance or creating a new one does not seem to change anything here. 
Interestingly, a similar approach in VisualWorks does not show this issue 
yet.


​Ok, so maybe we need to use put evaluation in a block and use valueNoContextSwitch ?
​Maybe use an API like the one you propose before :
Double roundToMinusInfWhile: [ ... ]

 
Actually, I expect the FE_* macros to be platform/implementation 
dependent, as suggested here:
http://www.enseignement.polytechnique.fr/informatique/INF478/docs/Cpp/en/c/numeric/fenv/FE_round.html


​Ok.

Can we try to pack everything in a PR for Pharo 7.0 ?
​Thank you.

--
Serge Stinckwich
UMI UMMISCO 209 (SU/IRD/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/
Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

Steffen Märcker
Dear Serge,

on the VM mailing list, Levente pointed out, that this could also be  
related to some lib the VM uses (e.g., Freetype) that might change the  
rounding mode. I'll dig into it and give your idea a try and come back  
with the results.

I think it would be nice to have in Pharo 7. But before I want to make  
sure it a) works as expected and b) does not cause some nasty side effects.

Bye, Steffen


Am .05.2018, 12:26 Uhr, schrieb Serge Stinckwich  
<[hidden email]>:

> On Thu, May 24, 2018 at 12:27 PM Steffen Märcker <[hidden email]> wrote:
>
>> Hi,
>>
>> now I've observed the same issue. It might be related to context
>> switching, since introducing a delay has a similar effect. Consider:
>>
>>    | FE_TONEAREST FE_DOWNWARD FE_UPWARD FE_TOWARDZERO |
>>    FE_TONEAREST  := 16r0000.
>>    FE_DOWNWARD   := 16r0400.
>>    FE_UPWARD     := 16r0800.
>>    FE_TOWARDZERO := 16r0C00.
>>    "For some reasons we have to call fegetround once."
>>    "c := LibC new fegetround."
>>    LibC new fesetround: FE_DOWNWARD.
>>    (Delay forSeconds: 1) wait.
>>    v1 := 1.0/10.0.
>>    LibC new fesetround: FE_UPWARD.
>>    v2 := 1.0/10.0.
>>    LibC new fesetround: FE_TONEAREST.
>>    v1 < v2.
>>
>> If the delay is inserted, the script evaluates to false. Using the same
>> LibC-instance or creating a new one does not seem to change anything
>> here.
>> Interestingly, a similar approach in VisualWorks does not show this  
>> issue
>> yet.
>>
>>
> ​Ok, so maybe we need to use put evaluation in a block and use
> valueNoContextSwitch ?
> ​Maybe use an API like the one you propose before :
> Double roundToMinusInfWhile: [ ... ]
>
>
>
>> Actually, I expect the FE_* macros to be platform/implementation
>> dependent, as suggested here:
>>
>> http://www.enseignement.polytechnique.fr/informatique/INF478/docs/Cpp/en/c/numeric/fenv/FE_round.html
>>
>>
> ​Ok.
>
> Can we try to pack everything in a PR for Pharo 7.0 ?
> ​Thank you.

Reply | Threaded
Open this post in threaded view
|

Re: Set Rounding mode for IEEE floating point operations

SergeStinckwich


On Tue, May 29, 2018 at 4:15 PM Steffen Märcker <[hidden email]> wrote:
Dear Serge,

on the VM mailing list, Levente pointed out, that this could also be 
related to some lib the VM uses (e.g., Freetype) that might change the 
rounding mode. I'll dig into it and give your idea a try and come back 
with the results.
 
I think it would be nice to have in Pharo 7. But before I want to make 
sure it a) works as expected and b) does not cause some nasty side effects.


​Yes in order to avoid any side effect, we can use what you propose before.
An API like :
Double roundToMinusInfWhile: [... code goes here ...]​

​so we don't expose the rest of the system to these modifications.

See you.​
--
Serge Stinckwich
UMI UMMISCO 209 (SU/IRD/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/