Set Rounding mode for IEEE floating point operations
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
On Mon, Jan 15, 2018 at 12:27 PM, Steffen Märcker <merkste@web.de> 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/
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 <serge.stinckwich@gmail.com>:
On Mon, Jan 15, 2018 at 12:27 PM, Steffen Märcker <merkste@web.de> 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.â
*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 <merkste@web.de>:
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
On Wed, May 23, 2018 at 11:47 AM Steffen Märcker <merkste@web.de> 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 ?â -- 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/
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
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
On Wed, May 23, 2018 at 3:39 PM Steffen Märcker <merkste@web.de> 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/
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
On Thu, May 24, 2018 at 10:31 AM Steffen Märcker <merkste@web.de> 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/
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 < serge.stinckwich@gmail.com> wrote:
On Thu, May 24, 2018 at 10:31 AM Steffen Märcker <merkste@web.de> 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/
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/n... Best, Steffen Am .05.2018, 11:57 Uhr, schrieb Serge Stinckwich <serge.stinckwich@gmail.com>:
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 < serge.stinckwich@gmail.com> wrote:
On Thu, May 24, 2018 at 10:31 AM Steffen Märcker <merkste@web.de> 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/
On Thu, May 24, 2018 at 12:27 PM Steffen Märcker <merkste@web.de> 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/n...
â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/
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 <serge.stinckwich@gmail.com>:
On Thu, May 24, 2018 at 12:27 PM Steffen Märcker <merkste@web.de> 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/n...
âOk.
Can we try to pack everything in a PR for Pharo 7.0 ? âThank you.
On Tue, May 29, 2018 at 4:15 PM Steffen Märcker <merkste@web.de> 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/
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 <serge.stinckwich@gmail.com>:
On Wed, May 23, 2018 at 11:47 AM Steffen Märcker <merkste@web.de> 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 ?â
participants (3)
-
Henrik Sperre Johansen -
Serge Stinckwich -
Steffen Märcker