Bug 11320 – std.math.fmod, round, trunc are not yet pure

Status
NEW
Severity
enhancement
Priority
P4
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-10-21T17:43:25Z
Last change time
2024-12-01T16:19:02Z
Keywords
rejects-valid
Assigned to
No Owner
Creator
bearophile_hugs
Moved to GitHub: phobos#10008 →

Comments

Comment #0 by bearophile_hugs — 2013-10-21T17:43:25Z
void main() pure { import std.math: fmod, round, trunc; auto r1 = fmod(5.1, 1.5); auto r2 = round(5.1); auto r3 = trunc(5.1); } dmd 2.064beta2 gives: test.d(3): Error: pure function 'D main' cannot call impure function 'std.math.fmod' test.d(4): Error: pure function 'D main' cannot call impure function 'std.math.round' test.d(5): Error: pure function 'D main' cannot call impure function 'std.math.trunc'
Comment #1 by clumsycodemonkey — 2017-01-24T02:02:21Z
I can confirm this is still an issue in 2.071.2.
Comment #2 by s.naarmann — 2018-10-14T14:55:49Z
This issue is still in 2.082.0. Are there technical problems (floating representation etc.) that require impurity? Otherwise, I'll make a PR that adds the pure keyword.
Comment #3 by s.naarmann — 2018-10-26T10:24:15Z
I see no problems to making fmod() pure. But with round(), here's the Phobos code: auto round(real x) @trusted nothrow @nogc { version (CRuntime_Microsoft) { auto old = FloatingPointControl.getControlState(); FloatingPointControl.setControlState( (old & (-1 - FloatingPointControl.roundingMask)) | FloatingPointControl.roundToZero ); x = rint((x >= 0) ? x + 0.5 : x - 0.5); FloatingPointControl.setControlState(old); return x; } else return core.stdc.math.roundl(x); } Can the CRuntime_Microsoft version ever be pure? It backs up global state of the CPU's floating point processing, then restores it: static void setControlState(ControlState newState) @trusted { version (InlineAsm_X86_Any) { asm nothrow @nogc { fclex; fldcw newState; } // Also update MXCSR, SSE's control register. // ... asm nothrow @nogc { ldmxcsr mxcsr; } // ... How should this be handled w.r.t. purity? I haven't looked at all into how such CPU state behaves with multithreaded code. For now, I'd have to leave round() as impure across all platforms.
Comment #4 by s.naarmann — 2018-10-26T11:48:04Z
D language spec, Pure Functions: https://dlang.org/spec/function.html#pure-functions In Point 8, it says: As a concession to practicality, a pure function can also: * read and write the floating point exception flags * read and write the floating point mode flags, as long as those flags are restored to their initial state upon function entry That's exactly what happens in round(), but through indirection. The compiler will not know that setControlState will be called a second time, and the compiler will not know that setControlState enjoys the special concession of the spec (it looks like any other impure function to the compiler).
Comment #5 by s.naarmann — 2018-11-12T15:33:09Z
Sorry, I lack the time these weeks. I've unassigned myself. Here are my ideas: - Refactor setControlState into a string mixin (seems best w.r.t. spec?) - Refactor setControlState into standalone pure function (weird because it's impure) - Cast round() to pure inside Phobos even though we call setCountrolState (feels like a bad idea)
Comment #6 by robert.schadek — 2024-12-01T16:19:02Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/phobos/issues/10008 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB