diff --git a/Source/FloatHelper.Test.cs b/Source/FloatHelper.Test.cs index d84e752..bae8a02 100644 --- a/Source/FloatHelper.Test.cs +++ b/Source/FloatHelper.Test.cs @@ -59,8 +59,51 @@ namespace Nuclex.Support { ); } + /// Tests the integer reinterpretation functions + [Test] + public void TestIntegerReinterpretation() { + Assert.AreEqual( + 12345.0f, + FloatHelper.ReinterpretAsFloat(FloatHelper.ReinterpretAsInt(12345.0f)), + "Number hasn't changed after mirrored reinterpretation" + ); + } + + /// Tests the long reinterpretation functions + [Test] + public void TestLongReinterpretation() { + Assert.AreEqual( + 12345.67890, + FloatHelper.ReinterpretAsDouble(FloatHelper.ReinterpretAsLong(12345.67890)), + "Number hasn't changed after mirrored reinterpretation" + ); + } + + /// Tests the floating point reinterpretation functions + [Test] + public void TestFloatReinterpretation() { + Assert.AreEqual( + 12345, + FloatHelper.ReinterpretAsInt(FloatHelper.ReinterpretAsFloat(12345)), + "Number hasn't changed after mirrored reinterpretation" + ); + } + + + /// + /// Tests the double prevision floating point reinterpretation functions + /// + [Test] + public void TestDoubleReinterpretation() { + Assert.AreEqual( + 1234567890, + FloatHelper.ReinterpretAsLong(FloatHelper.ReinterpretAsDouble(1234567890)), + "Number hasn't changed after mirrored reinterpretation" + ); + } + } } // namespace Nuclex.Support -#endif // UNITTEST \ No newline at end of file +#endif // UNITTEST diff --git a/Source/FloatHelper.cs b/Source/FloatHelper.cs index 412ac98..e6e568b 100644 --- a/Source/FloatHelper.cs +++ b/Source/FloatHelper.cs @@ -143,6 +143,66 @@ namespace Nuclex.Support { return (Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps); } + /// + /// Reinterprets the memory contents of a floating point value as an integer value + /// + /// + /// Floating point value whose memory contents to reinterpret + /// + /// + /// The memory contents of the floating point value interpreted as an integer + /// + public static int ReinterpretAsInt(float value) { + FloatIntUnion union = new FloatIntUnion(); + union.Float = value; + return union.Int; + } + + /// + /// Reinterprets the memory contents of a double precision floating point + /// value as an integer value + /// + /// + /// Double precision floating point value whose memory contents to reinterpret + /// + /// + /// The memory contents of the double precision floating point value + /// interpreted as an integer + /// + public static long ReinterpretAsLong(double value) { + DoubleLongUnion union = new DoubleLongUnion(); + union.Double = value; + return union.Long; + } + + /// + /// Reinterprets the memory contents of an integer as a floating point value + /// + /// Integer value whose memory contents to reinterpret + /// + /// The memory contents of the integer value interpreted as a floating point value + /// + public static float ReinterpretAsFloat(int value) { + FloatIntUnion union = new FloatIntUnion(); + union.Int = value; + return union.Float; + } + + /// + /// Reinterprets the memory contents of an integer value as a double precision + /// floating point value + /// + /// Integer whose memory contents to reinterpret + /// + /// The memory contents of the integer interpreted as a double precision + /// floating point value + /// + public static double ReinterpretAsDouble(long value) { + DoubleLongUnion union = new DoubleLongUnion(); + union.Long = value; + return union.Double; + } + } } // namespace Nuclex.Support diff --git a/Source/Tracking/Waitable.cs b/Source/Tracking/Waitable.cs index 4dbc1a8..69237f4 100644 --- a/Source/Tracking/Waitable.cs +++ b/Source/Tracking/Waitable.cs @@ -23,7 +23,9 @@ using System.Threading; namespace Nuclex.Support.Tracking { - /// Base class for actions on which that give an indication of their progress + /// + /// Base class for actions on which that give an indication of their progress + /// /// /// /// By encapsulating long-running operations which will ideally be running in @@ -85,11 +87,11 @@ namespace Nuclex.Support.Tracking { // We can *not* optimize this lock away since we absolutely must not create // two doneEvents -- someone might call .WaitOne() on the first one when only // the second one is referenced by this.doneEvent and thus gets set in the end. - if(this.doneEvent == null) { + if (this.doneEvent == null) { - lock(this) { + lock (this) { - if(this.doneEvent == null) + if (this.doneEvent == null) this.doneEvent = new ManualResetEvent(this.ended); } @@ -119,13 +121,13 @@ namespace Nuclex.Support.Tracking { // Make sure the progression is not ended more than once. By guaranteeing that // a progression can only be ended once, we allow users of this class to // skip some safeguards against notifications arriving twice. - lock(this) { + lock (this) { // No double lock here, this is an exception that indicates an implementation // error that will not be triggered under normal circumstances. We don't want // to waste any effort optimizing the speed at which an implementation fault // will be noticed. - if(this.ended) + if (this.ended) throw new InvalidOperationException("The progression has already been ended"); this.ended = true; @@ -135,12 +137,12 @@ namespace Nuclex.Support.Tracking { // Doesn't need a lock. If another thread wins the race and creates the event // after we just saw it being null, it would be created in an already set // state due to the ended flag (see above) being set to true beforehand! - if(this.doneEvent != null) + if (this.doneEvent != null) this.doneEvent.Set(); // Finally, fire the AsyncEnded event EventHandler copy = AsyncEnded; - if(copy != null) + if (copy != null) copy(this, EventArgs.Empty); }