[Mono-list] MS doc discrepencies

Jon Guymon gnarg@slackworks.com
Wed, 27 Feb 2002 11:49:28 -0800


This is a multi-part message in MIME format.

------=_NextPart_000_0000_01C1BF84.CFDF22E0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 8bit

The class I'm testing is System.Math.

Here are the question areas:
operation				docs				result
Log(0)				PositiveInfinity		NegativeInfinity
Log(0, y)				PositiveInfinity		NegativeInfinity
Log10(0)				PositiveInfinity		NegativeInfinity
Pow(x, NegativeInfinity)	0				NaN
Pow(x, PositiveInfinity)	PositiveInfinity		NaN

that's it I think

I am admittedly /not/ a math buff, but I think I did everything correctly.
In any event I have attached the code for checking and cross-posting and
stuff.  The trouble spots are commented.

Oh, by the way, where can I get my hands on IEEE specs for these operations?

thanks,
jon

-----Original Message-----
From: Ben Houston [mailto:ben@exocortex.org]
Sent: Tuesday, February 26, 2002 8:40 PM
To: 'Jon Guymon'
Subject: RE: [Mono-list] MS doc discrepencies


Hi Jon,

Just out of curiosity what behavior differs between the docs and the
actual classes?   I'm a bit of a math buff and am currently writing a
DSP library in C# thus I'm interested. :-)

And if it helps I would suggest going with the behavior that is most
adherent to numerical methods standards (i.e IEEE, etc...).

Take care,
-ben houston
http://www.exocortex.org/~ben
 


> -----Original Message-----
> From: mono-list-admin@ximian.com [mailto:mono-list-admin@ximian.com]
On
> Behalf Of Jon Guymon
> Sent: Wednesday, February 27, 2002 1:26 AM
> To: mono-list@ximian.com
> Subject: [Mono-list] MS doc discrepencies
>
> Hello,
>
> I've been working on MonoTests.System.MathTest, running it with the
> Microsoft runtime, and testing the Microsoft classes.  What I found is
> that
> in a couple of cases the Microsoft System.Math class does not behave
as
> the
> documentation describes it.
>
> This makes me wonder which I should treat as law.  Should I write the
> tests
> to they follow the docs to the letter, or should I write them so they
all
> pass when run against the Microsoft classes?
>
> It seems to me that the docs should be trusted over the
implementation,
> but
> I want to check before I submit something.
>
> It's also possible I'm doing something wrong.  I'll send my code to
> whoever
> wants to proof it, but I don't want to clutter the mailing list just
yet
> ^_^.
>
> Also, assuming this all gets worked out, should I simply post the code
to
> this list?
>
> Thanks
> Jon
>
>
>
> _______________________________________________
> Mono-list maillist  -  Mono-list@ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list

------=_NextPart_000_0000_01C1BF84.CFDF22E0
Content-Type: application/octet-stream;
	name="MathTest.cs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="MathTest.cs"

// MathTest.cs
//
// Jon Guymon (guymon@slackworks.com)
//
// (C) 2002 Jon Guymon
//=20

using System;
using NUnit.Framework;

namespace MonoTests.System=20
{

public class MathTest : TestCase {
=09
	public MathTest() : base ("System.Math testsuite") {}
	public MathTest(string name) : base(name) {}

	protected override void SetUp() {}
	protected override void TearDown() {}

	public static ITest Suite {
		get {=20
			return new TestSuite(typeof(MathTest));=20
		}
	}

	static double x =3D 0.1234;
	static double y =3D 12.345;

	public void TestDecimalAbs() {
		decimal a =3D -9.0M;

		Assert(9.0M =3D=3D Math.Abs(a));
	}


	public void TestDoubleAbs() {
		double a =3D -9.0D;

		Assert(9.0D =3D=3D Math.Abs(a));
	}

	public void TestFloatAbs() {
		float a =3D -9.0F;

		Assert(9.0F =3D=3D Math.Abs(a));
	}

	public void TestLongAbs() {
		long a =3D -9L;
		long b =3D Int64.MinValue;

		Assert(9L =3D=3D Math.Abs(a));
		try {
			Math.Abs(b);
			Fail("Should raise System.OverflowException");
		} catch(Exception e) {
			Assert(typeof(OverflowException) =3D=3D e.GetType());
		}
	}

	public void TestIntAbs() {
		int a =3D -9;
		int b =3D Int32.MinValue;

		Assert(9 =3D=3D Math.Abs(a));
		try {
			Math.Abs(b);
			Fail("Should raise System.OverflowException");
		} catch(Exception e) {
			Assert(typeof(OverflowException) =3D=3D e.GetType());
		}
	}

	public void TestSbyteAbs() {
		sbyte a =3D -9;
		sbyte b =3D SByte.MinValue;

		Assert(9 =3D=3D Math.Abs(a));
		try {
			Math.Abs(b);
			Fail("Should raise System.OverflowException");
		} catch(Exception e) {
			Assert(typeof(OverflowException) =3D=3D e.GetType());
		}
	}

	public void TestShortAbs() {
		short a =3D -9;
		short b =3D Int16.MinValue;

		Assert(9 =3D=3D Math.Abs(a));
		try {
			Math.Abs(b);
			Fail("Should raise System.OverflowException");
		} catch(Exception e) {
			Assert(typeof(OverflowException) =3D=3D e.GetType());
		}
	}

	public void TestAcos() {
		double a =3D Math.Acos(x);
		double b =3D 1.4470809809523457;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.Acos(-1.01D)));
		Assert(double.IsNaN(Math.Acos(1.01D)));
	}

	public void TestAsin() {
		double a =3D Math.Asin(x);
		double b =3D 0.12371534584255098;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.Asin(-1.01D)));
		Assert(double.IsNaN(Math.Asin(1.01D)));
	}

	public void TestAtan() {
		double a =3D Math.Atan(x);
		double b =3D 0.12277930094473837;
		double c =3D 1.5707963267948966;
		double d =3D -1.5707963267948966;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert("should return NaN",=20
		       double.IsNaN(Math.Atan(double.NaN)));
		Assert(Math.Atan(double.PositiveInfinity).ToString("G99")+" !=3D =
"+c.ToString("G99"),=20
		       Math.Abs((double)Math.Atan(double.PositiveInfinity) - c) <=3D =
double.Epsilon);
		Assert(Math.Atan(double.NegativeInfinity).ToString("G99")+" !=3D =
"+d.ToString("G99"),
		       Math.Abs((double)Math.Atan(double.NegativeInfinity) - d) <=3D =
double.Epsilon);
	}

	public void TestAtan2() {
		double a =3D Math.Atan2(x, y);
		double b =3D 0.0099956168687207747;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.Acos(-2D)));
		Assert(double.IsNaN(Math.Acos(2D)));
	}

	public void TestCos() {
		double a =3D Math.Cos(x);
		double b =3D 0.99239587670489104;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
	}

	public void TestCosh() {
		double a =3D Math.Cosh(x);
		double b =3D 1.0076234465130722;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(Math.Cosh(double.NegativeInfinity) =3D=3D =
double.PositiveInfinity);
		Assert(Math.Cosh(double.PositiveInfinity) =3D=3D =
double.PositiveInfinity);
		Assert(double.IsNaN(Math.Cosh(double.NaN)));
	}

	public void TestSin() {
		double a =3D Math.Sin(x);
		double b =3D 0.12308705821137626;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
	}

	public void TestSinh() {
		double a =3D Math.Sinh(x);
		double b =3D 0.12371341868561381;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
	}

	public void TestTan() {
		double a =3D Math.Tan(x);
		double b =3D 0.12403019913793806;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
	}

	public void TestTanh() {
		double a =3D Math.Tanh(x);
		double b =3D 0.12277743150353424;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
	}

	public void TestSqrt() {
		double a =3D Math.Sqrt(x);
		double b =3D 0.35128336140500593;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
	}

	public void TestExp() {
		double a =3D Math.Exp(x);
		double b =3D 1.1313368651986859;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.Exp(double.NaN)));
		Assert(Math.Exp(double.NegativeInfinity) =3D=3D 0);
		Assert(Math.Exp(double.PositiveInfinity) =3D=3D =
double.PositiveInfinity);
	}

	public void TestCeiling() {
		double a =3D Math.Ceiling(1.5);
		double b =3D 2;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(Math.Ceiling(double.NegativeInfinity) =3D=3D =
double.NegativeInfinity);
		Assert(Math.Ceiling(double.PositiveInfinity) =3D=3D =
double.PositiveInfinity);
		Assert(double.IsNaN(Math.Ceiling(double.NaN)));
	}

	public void TestFloor() {
		double a =3D Math.Floor(1.5);
		double b =3D 1;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(Math.Floor(double.NegativeInfinity) =3D=3D =
double.NegativeInfinity);
		Assert(Math.Floor(double.PositiveInfinity) =3D=3D =
double.PositiveInfinity);
		Assert(double.IsNaN(Math.Floor(double.NaN)));
	}

	public void TestIEEERemainder() {
		double a =3D Math.IEEERemainder(y, x);
		double b =3D 0.0050000000000007816;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.IEEERemainder(y, 0)));
	}

	public void TestLog() {
		double a =3D Math.Log(y);
		double b =3D 2.513251122797143;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.Log(-1)));
		Assert(double.IsNaN(Math.Log(double.NaN)));

		// MS docs say this should be PositiveInfinity
		Assert(Math.Log(0) =3D=3D double.NegativeInfinity);
		Assert(Math.Log(double.PositiveInfinity) =3D=3D =
double.PositiveInfinity);
	}

	public void TestLog2() {
		double a =3D Math.Log(x, y);
		double b =3D -0.83251695325303621;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.Log(-1, y)));
		Assert(double.IsNaN(Math.Log(double.NaN, y)));
		Assert(double.IsNaN(Math.Log(x, double.NaN)));
		Assert(double.IsNaN(Math.Log(double.NegativeInfinity, y)));
		Assert(double.IsNaN(Math.Log(x, double.NegativeInfinity)));
		Assert(double.IsNaN(Math.Log(double.PositiveInfinity, =
double.PositiveInfinity)));

		// MS docs say this should be PositiveInfinity
		Assert(Math.Log(0, y) =3D=3D double.NegativeInfinity);
		Assert(Math.Log(double.PositiveInfinity, y) =3D=3D =
double.PositiveInfinity);
		Assert(Math.Log(x, double.PositiveInfinity) =3D=3D 0);
	}

 	public void TestLog10() {
		double a =3D Math.Log10(x);
		double b =3D -0.90868484030277719;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.Log10(-1)));
		Assert(double.IsNaN(Math.Log10(double.NaN)));

		// MS docs say this should be PositiveInfinity
		Assert(Math.Log10(0) =3D=3D double.NegativeInfinity);
		Assert(Math.Log10(double.PositiveInfinity) =3D=3D =
double.PositiveInfinity);

	}=09

 	public void TestPow() {
		double a =3D Math.Pow(y, x);
		double b =3D 1.363609446060212;

		Assert(a.ToString("G99") + " !=3D " + b.ToString("G99"),=20
		       (Math.Abs(a - b) <=3D double.Epsilon));
		Assert(double.IsNaN(Math.Pow(y, double.NaN)));
		Assert(double.IsNaN(Math.Pow(double.NaN, x)));
		Assert(Math.Pow(double.NegativeInfinity, 1) =3D=3D =
double.NegativeInfinity);
		Assert(Math.Pow(double.NegativeInfinity, 2) =3D=3D =
double.PositiveInfinity);

		// MS docs say this should be 0
		Assert(double.IsNaN(Math.Pow(1, double.NegativeInfinity)));
		Assert(Math.Pow(double.PositiveInfinity, double.NegativeInfinity) =
=3D=3D 0);
		Assert(Math.Pow(double.PositiveInfinity, 1) =3D=3D =
double.PositiveInfinity);

		// MS docs say this should be PositiveInfinity
		Assert(double.IsNaN(Math.Pow(1, double.PositiveInfinity)));
	}=09

	public void TestByteMax() {
		byte a =3D 1;
		byte b =3D 2;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestDecimalMax() {
		decimal a =3D 1.5M;
		decimal b =3D 2.5M;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestDoubleMax() {
		double a =3D 1.5D;
		double b =3D 2.5D;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestFloatMax() {
		float a =3D 1.5F;
		float b =3D 2.5F;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestIntMax() {
		int a =3D 1;
		int b =3D 2;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestLongMax() {
		long a =3D 1L;
		long b =3D 2L;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestSbyteMax() {
		sbyte a =3D 1;
		sbyte b =3D 2;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestShortMax() {
		short a =3D 1;
		short b =3D 2;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestUintMax() {
		uint a =3D 1U;
		uint b =3D 2U;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestUlongMax() {
		ulong a =3D 1UL;
		ulong b =3D 2UL;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestUshortMax() {
		ushort a =3D 1;
		ushort b =3D 2;

		Assert(b =3D=3D Math.Max(a, b));
		Assert(b =3D=3D Math.Max(b, a));
	}

	public void TestByteMin() {
		byte a =3D 1;
		byte b =3D 2;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestDecimalMin() {
		decimal a =3D 1.5M;
		decimal b =3D 2.5M;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestDoubleMin() {
		double a =3D 1.5D;
		double b =3D 2.5D;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestFloatMin() {
		float a =3D 1.5F;
		float b =3D 2.5F;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestIntMin() {
		int a =3D 1;
		int b =3D 2;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestLongMin() {
		long a =3D 1L;
		long b =3D 2L;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestSbyteMin() {
		sbyte a =3D 1;
		sbyte b =3D 2;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestShortMin() {
		short a =3D 1;
		short b =3D 2;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestUintMin() {
		uint a =3D 1U;
		uint b =3D 2U;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestUlongMin() {
		ulong a =3D 1UL;
		ulong b =3D 2UL;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestUshortMin() {
		ushort a =3D 1;
		ushort b =3D 2;

		Assert(a =3D=3D Math.Min(a, b));
		Assert(a =3D=3D Math.Min(b, a));
	}

	public void TestDecimalRound() {
		decimal a =3D 1.5M;
		decimal b =3D 2.5M;

		Assert(Math.Round(a) + " !=3D 2", Math.Round(a) =3D=3D 2);
		Assert(Math.Round(b) + " !=3D 2", Math.Round(b) =3D=3D 2);
	}

	public void TestDecimalRound2() {
		decimal a =3D 3.45M;
		decimal b =3D 3.46M;

		Assert(Math.Round(a, 1) =3D=3D 3.4M);
		Assert(Math.Round(b, 1) =3D=3D 3.5M);
	}

	public void TestDoubleRound() {
		double a =3D 1.5D;
		double b =3D 2.5D;

		Assert(Math.Round(a) + " !=3D 2", Math.Round(a) =3D=3D 2);
		Assert(Math.Round(b) + " !=3D 2", Math.Round(b) =3D=3D 2);
	}

	public void TestDoubleRound2() {
		double a =3D 3.45D;
		double b =3D 3.46D;

		Assert(Math.Round(a, 1) =3D=3D 3.4D);
		Assert(Math.Round(b, 1) =3D=3D 3.5D);
	}
=09
	public void TestDecimalSign() {
		decimal a =3D -5M;
		decimal b =3D 5M;

		Assert(Math.Sign(a) =3D=3D -1);
		Assert(Math.Sign(b) =3D=3D 1);
		Assert(Math.Sign(0M) =3D=3D 0);
	}

	public void TestDoubleSign() {
		double a =3D -5D;
		double b =3D 5D;

		Assert(Math.Sign(a) =3D=3D -1);
		Assert(Math.Sign(b) =3D=3D 1);
		Assert(Math.Sign(0D) =3D=3D 0);
	}

	public void TestFloatSign() {
		float a =3D -5F;
		float b =3D 5F;

		Assert(Math.Sign(a) =3D=3D -1);
		Assert(Math.Sign(b) =3D=3D 1);
		Assert(Math.Sign(0F) =3D=3D 0);
	}

	public void TestIntSign() {
		int a =3D -5;
		int b =3D 5;

		Assert(Math.Sign(a) =3D=3D -1);
		Assert(Math.Sign(b) =3D=3D 1);
	}

	public void TestLongSign() {
		long a =3D -5L;
		long b =3D 5L;

		Assert(Math.Sign(a) =3D=3D -1);
		Assert(Math.Sign(b) =3D=3D 1);
		Assert(Math.Sign(0L) =3D=3D 0);
	}

	public void TestSbyteSign() {
		sbyte a =3D -5;
		sbyte b =3D 5;

		Assert(Math.Sign(a) =3D=3D -1);
		Assert(Math.Sign(b) =3D=3D 1);
		Assert(Math.Sign(0) =3D=3D 0);
	}

	public void TestShortSign() {
		short a =3D -5;
		short b =3D 5;

		Assert(Math.Sign(a) =3D=3D -1);
		Assert(Math.Sign(b) =3D=3D 1);
		Assert(Math.Sign(0) =3D=3D 0);
	}

}

}

------=_NextPart_000_0000_01C1BF84.CFDF22E0--