From 9bf70d5b063de0fe0cdd938b8694d7b5928e62a5 Mon Sep 17 00:00:00 2001 From: Denis Shelomovskij Date: Thu, 14 Mar 2013 16:40:11 +0400 Subject: [PATCH 1/3] [whitespace] Fix spaces in `std.math.FloatingPointControl` example and unittest. --- std/math.d | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/std/math.d b/std/math.d index 2b124b93d..b7aefced8 100644 --- a/std/math.d +++ b/std/math.d @@ -2778,23 +2778,23 @@ void resetIeeeFlags() { IeeeFlags.resetIeeeFlags(); } Example: - ---- - { +---- +{ // Enable hardware exceptions for division by zero, overflow to infinity, // invalid operations, and uninitialized floating-point variables. FloatingPointControl fpctrl; fpctrl.enableExceptions(FloatingPointControl.severeExceptions); - double y = x*3.0; // will generate a hardware exception, if x is uninitialized. + double y = x * 3.0; // will generate a hardware exception, if x is uninitialized. // fpctrl.rounding = FloatingPointControl.roundUp; // The hardware exceptions will be disabled when leaving this scope. // The original rounding mode will also be restored. - } +} - ---- +---- */ struct FloatingPointControl @@ -2963,20 +2963,20 @@ private: unittest { - { + { FloatingPointControl ctrl; ctrl.enableExceptions(FloatingPointControl.divByZeroException - | FloatingPointControl.overflowException); + | FloatingPointControl.overflowException); assert(ctrl.enabledExceptions == - (FloatingPointControl.divByZeroException - | FloatingPointControl.overflowException)); + (FloatingPointControl.divByZeroException + | FloatingPointControl.overflowException)); ctrl.rounding = FloatingPointControl.roundUp; assert(FloatingPointControl.rounding == FloatingPointControl.roundUp); } assert(FloatingPointControl.rounding - == FloatingPointControl.roundToNearest); - assert(FloatingPointControl.enabledExceptions ==0); + == FloatingPointControl.roundToNearest); + assert(FloatingPointControl.enabledExceptions == 0); } From 99e3440e2f97ffbe2af639018e5ecdcc3c7b5984 Mon Sep 17 00:00:00 2001 From: Denis Shelomovskij Date: Thu, 14 Mar 2013 16:47:42 +0400 Subject: [PATCH 2/3] Fix `std.math.FloatingPointControl` two issues. 1. Do not call `setControlState` in destructor if not initialized (previously results in enabling all exceptions). 2. Call `initialize` on setting rounding mode (previously not called). --- std/math.d | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/std/math.d b/std/math.d index b7aefced8..1930db198 100644 --- a/std/math.d +++ b/std/math.d @@ -2852,8 +2852,8 @@ public: //// Change the floating-point hardware rounding mode @property void rounding(RoundingMode newMode) { - ushort old = getControlState(); - setControlState((old & ~ROUNDING_MASK) | (newMode & ROUNDING_MASK)); + initialize(); + setControlState((getControlState() & ~ROUNDING_MASK) | (newMode & ROUNDING_MASK)); } /// Return the exceptions which are currently enabled (unmasked) @@ -2872,7 +2872,8 @@ public: ~this() { clearExceptions(); - setControlState(savedState); + if (initialized) + setControlState(savedState); } private: @@ -2963,6 +2964,25 @@ private: unittest { + void ensureDefaults() + { + assert(FloatingPointControl.rounding + == FloatingPointControl.roundToNearest); + assert(FloatingPointControl.enabledExceptions == 0); + } + + { + FloatingPointControl ctrl; + } + ensureDefaults(); + + { + FloatingPointControl ctrl; + ctrl.rounding = FloatingPointControl.roundDown; + assert(FloatingPointControl.rounding == FloatingPointControl.roundDown); + } + ensureDefaults(); + { FloatingPointControl ctrl; ctrl.enableExceptions(FloatingPointControl.divByZeroException @@ -2974,9 +2994,7 @@ unittest ctrl.rounding = FloatingPointControl.roundUp; assert(FloatingPointControl.rounding == FloatingPointControl.roundUp); } - assert(FloatingPointControl.rounding - == FloatingPointControl.roundToNearest); - assert(FloatingPointControl.enabledExceptions == 0); + ensureDefaults(); } From 6fb40fb8acdd225443e8dbbbb92ebfdd5705f7e7 Mon Sep 17 00:00:00 2001 From: Denis Shelomovskij Date: Thu, 14 Mar 2013 17:24:44 +0400 Subject: [PATCH 3/3] [docs] Improve `std.math.FloatingPointControl` example. --- std/math.d | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/std/math.d b/std/math.d index 1930db198..091529685 100644 --- a/std/math.d +++ b/std/math.d @@ -2780,20 +2780,33 @@ void resetIeeeFlags() { IeeeFlags.resetIeeeFlags(); } Example: ---- { + FloatingPointControl fpctrl; + // Enable hardware exceptions for division by zero, overflow to infinity, // invalid operations, and uninitialized floating-point variables. - - FloatingPointControl fpctrl; fpctrl.enableExceptions(FloatingPointControl.severeExceptions); - double y = x * 3.0; // will generate a hardware exception, if x is uninitialized. - // - fpctrl.rounding = FloatingPointControl.roundUp; + // This will generate a hardware exception, if x is a + // default-initialized floating point variable: + real x; // Add `= 0` or even `= real.nan` to not throw the exception. + real y = x * 3.0; - // The hardware exceptions will be disabled when leaving this scope. + // The exception is only thrown for default-uninitialized NaN-s. + // NaN-s with other payload are valid: + real z = y * real.nan; // ok + + // Changing the rounding mode: + fpctrl.rounding = FloatingPointControl.roundUp; + assert(rint(1.1) == 2); + + // The set hardware exceptions will be disabled when leaving this scope. // The original rounding mode will also be restored. } +// Ensure previous values are returned: +assert(!FloatingPointControl.enabledExceptions); +assert(FloatingPointControl.rounding == FloatingPointControl.roundToNearest); +assert(rint(1.1) == 1); ---- */