Browse Source

added Math specification (part 1)

Simon Krajewski 12 years ago
parent
commit
e3b52ec513
2 changed files with 383 additions and 9 deletions
  1. 176 9
      std/Math.hx
  2. 207 0
      tests/unit/unitstd/Math.unit.hx

+ 176 - 9
std/Math.hx

@@ -26,27 +26,177 @@
 extern class Math
 extern class Math
 {
 {
 	static var PI(default,null) : Float;
 	static var PI(default,null) : Float;
-	static var NaN(default,null) : Float;
-	static var NEGATIVE_INFINITY(default,null) : Float;
+	
+	/**
+		A special Float constant which denotes negative infinity.
+		
+		For example, this is the result of -1.0 / 0.0.
+		
+		Operations with NEGATIVE_INFINITY as an operand may result in
+		NEGATIVE_INFINITY, POSITIVE_INFINITY or NaN. For detailed information,
+		see ...
+		
+		If this constant is converted to an Int, e.g. through Std.int(), the
+		result is unspecified.
+	**/
+	static var NEGATIVE_INFINITY(default, null) : Float;
+	/**
+		A special Float constant which denotes negative infinity.
+		
+		For example, this is the result of 1.0 / 0.0.
+		
+		Operations with POSITIVE_INFINITY as an operand may result in
+		NEGATIVE_INFINITY, POSITIVE_INFINITY or NaN. For detailed information,
+		see ...
+	
+		If this constant is converted to an Int, e.g. through Std.int(), the
+		result is unspecified.		
+	**/	
 	static var POSITIVE_INFINITY(default,null) : Float;
 	static var POSITIVE_INFINITY(default,null) : Float;
 
 
+	/**
+		A special Float constant which denotes an invalid number.
+		
+		NaN stands for "Not a Number". It occurs when a mathematically incorrect
+		operation is executed, such as taking the square root of a negative
+		number: Math.sqrt(-1).
+		
+		All further operations with NaN as an operand will result in NaN.
+		
+		If this constant is converted to an Int, e.g. through Std.int(), the
+		result is unspecified.		
+	**/
+	static var NaN(default, null) : Float;
+
+	/**
+		Returns the absolute value of [v].
+		
+		If [v] is positive or 0, the result is unchanged. Otherwise the result
+		is -[v].
+		
+		If [v] is NEGATIVE_INFINITY or POSITIVE_INFINITY, the result is
+		POSITIVE_INFINITY.
+		
+		If [v] is NaN, the result is NaN.
+	**/
 	static function abs(v:Float):Float;
 	static function abs(v:Float):Float;
-	static function min(a:Float,b:Float):Float;
-	static function max(a:Float,b:Float):Float;
+	
+	/**
+		Returns the smaller of values [a] and [b].
+		
+		If [a] or [b] are NaN, the result is NaN.
+		
+		If [a] or [b] are NEGATIVE_INFINITY, the result is NEGATIVE_INFINITY.
+		
+		If [a] and [b] are POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+	**/
+	static function min(a:Float, b:Float):Float;
+	
+	/**
+		Returns the greater of values [a] and [b].
+		
+		If [a] or [b] are NaN, the result is NaN.
+		
+		If [a] or [b] are POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+		
+		If [a] and [b] are NEGATIVE_INFINITY, the result is NEGATIVE_INFINITY.
+	**/	
+	static function max(a:Float, b:Float):Float;
+	
+	/**
+		Returns the trigonometric sine of [v].
+		
+		The unit of [v] is radians.
+		
+		If [v] is NaN or infinite, the result is NaN.
+	**/
 	static function sin(v:Float):Float;
 	static function sin(v:Float):Float;
+	
+	/**
+		Returns the trigonometric cosine of [v].
+		
+		The unit of [v] is radians.
+		
+		If [v] is NaN or infinite, the result is NaN.
+	**/	
 	static function cos(v:Float):Float;
 	static function cos(v:Float):Float;
-	static function atan2(y:Float,x:Float):Float;
+	
+	// TODO
 	static function tan(v:Float):Float;
 	static function tan(v:Float):Float;
+	static function asin(v:Float):Float;
+	static function acos(v:Float):Float;
+	static function atan(v:Float):Float;
+	static function atan2(y:Float, x:Float):Float;
+	
+	/**
+		Returns Euler's number, raised to the power of [v].
+		
+		exp(1.0) is approximately 2.718281828459.
+		
+		If [v] is POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+		
+		If [v] is NEGATIVE_INFINITY, the result is 0.0.
+		
+		If [v] is NaN, the result is NaN.
+	**/
 	static function exp(v:Float):Float;
 	static function exp(v:Float):Float;
+	
+	/**
+		Returns the natural logarithm of [v].
+		
+		If [v] is negative (including NEGATIVE_INFINITY) or NaN, the result is
+		NaN.
+		
+		If [v] is POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+		
+		If [v] is 0.0, the result is NEGATIVE_INFINITY.
+		
+		This is the inverse operation of exp, i.e. log(exp(v)) == v always
+		holds.
+	**/
 	static function log(v:Float):Float;
 	static function log(v:Float):Float;
+	
+	// TODO
+	// http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Math.html#pow(double, double) <-- wtf?
+	static function pow(v:Float, exp:Float):Float;
+	
+	/**
+		Returns the square root of [v].
+		
+		If [v] is negative (including NEGATIVE_INFINITY) or NaN, the result is
+		NaN.
+		
+		If [v] is POSITIVE_INFINITY, the result is POSITIVE_INFINITY.
+		
+		If [v] is 0.0, the result is 0.0.
+	**/
 	static function sqrt(v:Float):Float;
 	static function sqrt(v:Float):Float;
+	
+	/**
+		Rounds [v] to the nearest Int value.
+		
+		TODO: need spec
+	**/
 	static function round(v:Float):Int;
 	static function round(v:Float):Int;
+	
+	/**
+		Returns the largest Int value that is not greater than [v].
+		
+		TODO: need spec
+	**/
 	static function floor(v:Float):Int;
 	static function floor(v:Float):Int;
+	
+	/**
+		Returns the smallest Int value that is not less than [v].
+		
+		TODO: need spec
+	**/	
 	static function ceil(v:Float):Int;
 	static function ceil(v:Float):Int;
-	static function atan(v:Float):Float;
-	static function asin(v:Float):Float;
-	static function acos(v:Float):Float;
-	static function pow(v:Float,exp:Float):Float;
+	
+	/**
+		Returns a pseudo-random number which is greater than or equal to 0.0,
+		and less than 1.0.
+	**/
 	static function random() : Float;
 	static function random() : Float;
 	
 	
 	#if ((flash9 && !as3) || cpp)
 	#if ((flash9 && !as3) || cpp)
@@ -72,7 +222,24 @@ extern class Math
 	#end
 	#end
 	
 	
 
 
+	/**
+		Tells if [f] is a finite number.
+		
+		If [f] is POSITIVE_INFINITY, NEGATIVE_INFINITY or NaN, the result is
+		false.
+		
+		Otherwise the result is true.
+	**/
 	static function isFinite( f : Float ) : Bool;
 	static function isFinite( f : Float ) : Bool;
+	
+	/**
+		Tells if [f] is not a valid number.
+		
+		If [f] is NaN, the result is true.
+		
+		Otherwise the result is false. In particular, both POSITIVE_INFINITY and
+		NEGATIVE_INFINITY are not considered invalid numbers.
+	**/
 	static function isNaN( f : Float ) : Bool;
 	static function isNaN( f : Float ) : Bool;
 
 
 	private static function __init__() : Void untyped {
 	private static function __init__() : Void untyped {

+ 207 - 0
tests/unit/unitstd/Math.unit.hx

@@ -0,0 +1,207 @@
+// constants
+var zero = 0.0;
+var one = 1.0;
+//1.0 / zero == Math.POSITIVE_INFINITY;
+//-1.0 / zero == Math.NEGATIVE_INFINITY;
+(Math.NaN == Math.NaN) == false;
+Math.isNaN(Math.NaN) == true;
+Math.isNaN(Math.sqrt( -1)) == true;
+Math.NEGATIVE_INFINITY == Math.NEGATIVE_INFINITY;
+Math.POSITIVE_INFINITY == Math.POSITIVE_INFINITY;
+// +
+Math.POSITIVE_INFINITY + Math.POSITIVE_INFINITY == Math.POSITIVE_INFINITY;
+Math.NEGATIVE_INFINITY + Math.NEGATIVE_INFINITY == Math.NEGATIVE_INFINITY;
+Math.POSITIVE_INFINITY + one == Math.POSITIVE_INFINITY;
+Math.NEGATIVE_INFINITY + one == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.POSITIVE_INFINITY + Math.NEGATIVE_INFINITY) == true;
+Math.isNaN(Math.POSITIVE_INFINITY + Math.NaN) == true;
+Math.isNaN(Math.NEGATIVE_INFINITY + Math.NaN) == true;
+// -
+one - Math.POSITIVE_INFINITY == Math.NEGATIVE_INFINITY;
+one - Math.NEGATIVE_INFINITY == Math.POSITIVE_INFINITY;
+-Math.POSITIVE_INFINITY == Math.NEGATIVE_INFINITY;
+-Math.NEGATIVE_INFINITY == Math.POSITIVE_INFINITY;
+Math.POSITIVE_INFINITY - one == Math.POSITIVE_INFINITY;
+Math.NEGATIVE_INFINITY - one == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.POSITIVE_INFINITY - Math.POSITIVE_INFINITY ) == true;
+Math.isNaN(Math.NEGATIVE_INFINITY - Math.NEGATIVE_INFINITY) == true;
+Math.POSITIVE_INFINITY - Math.NEGATIVE_INFINITY == Math.POSITIVE_INFINITY;
+Math.NEGATIVE_INFINITY - Math.POSITIVE_INFINITY == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.POSITIVE_INFINITY - Math.NaN) == true;
+Math.isNaN(Math.NEGATIVE_INFINITY - Math.NaN) == true;
+Math.isNaN(Math.NaN - Math.POSITIVE_INFINITY) == true;
+Math.isNaN(Math.NaN - Math.NEGATIVE_INFINITY) == true;
+// *
+Math.POSITIVE_INFINITY * one == Math.POSITIVE_INFINITY;
+Math.NEGATIVE_INFINITY * one == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.POSITIVE_INFINITY * zero) == true;
+Math.isNaN(Math.NEGATIVE_INFINITY * zero) == true;
+Math.POSITIVE_INFINITY * Math.POSITIVE_INFINITY == Math.POSITIVE_INFINITY;
+Math.NEGATIVE_INFINITY * Math.NEGATIVE_INFINITY  == Math.POSITIVE_INFINITY;
+Math.POSITIVE_INFINITY * Math.NEGATIVE_INFINITY == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.POSITIVE_INFINITY * Math.NaN) == true;
+Math.isNaN(Math.NEGATIVE_INFINITY * Math.NaN) == true;
+// /
+Math.POSITIVE_INFINITY / one == Math.POSITIVE_INFINITY;
+Math.NEGATIVE_INFINITY / one == Math.NEGATIVE_INFINITY;
+//Math.POSITIVE_INFINITY / zero == Math.POSITIVE_INFINITY;
+//Math.NEGATIVE_INFINITY / zero == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.POSITIVE_INFINITY / Math.POSITIVE_INFINITY);
+Math.isNaN(Math.POSITIVE_INFINITY / Math.NEGATIVE_INFINITY);
+Math.isNaN(Math.NEGATIVE_INFINITY / Math.POSITIVE_INFINITY);
+Math.isNaN(Math.NEGATIVE_INFINITY / Math.NEGATIVE_INFINITY);
+Math.isNaN(Math.NaN / Math.POSITIVE_INFINITY);
+Math.isNaN(Math.POSITIVE_INFINITY / Math.NaN);
+Math.isNaN(Math.NaN / Math.POSITIVE_INFINITY);
+Math.isNaN(Math.NEGATIVE_INFINITY / Math.NaN);
+
+// abs
+Math.abs(-1.223) == 1.223;
+Math.abs(1.223) == 1.223;
+Math.abs(0) == 0;
+Math.isNaN(Math.abs(Math.NaN)) == true;
+Math.abs(Math.NEGATIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.abs(Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+
+// min
+Math.min(0.0, 1.0) == 0.0;
+Math.min(0.0, -1.0) == -1.0;
+Math.min(0.0, 0.0) == 0.0;
+Math.min(1.0, 1.0) == 1.0;
+Math.min(Math.NEGATIVE_INFINITY, Math.NEGATIVE_INFINITY) == Math.NEGATIVE_INFINITY;
+Math.min(Math.NEGATIVE_INFINITY, Math.POSITIVE_INFINITY) == Math.NEGATIVE_INFINITY;
+Math.min(Math.POSITIVE_INFINITY, Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.min(Math.POSITIVE_INFINITY, zero) == zero;
+Math.min(Math.NEGATIVE_INFINITY, zero) == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.min(Math.NEGATIVE_INFINITY, Math.NaN)) == true;
+Math.isNaN(Math.min(Math.POSITIVE_INFINITY, Math.NaN)) == true;
+Math.isNaN(Math.min(Math.NaN, Math.NaN)) == true;
+Math.isNaN(Math.min(one, Math.NaN)) == true;
+Math.isNaN(Math.min(zero, Math.NaN)) == true;
+Math.isNaN(Math.min(Math.NaN, Math.NEGATIVE_INFINITY)) == true;
+Math.isNaN(Math.min(Math.NaN,Math.POSITIVE_INFINITY)) == true;
+Math.isNaN(Math.min(Math.NaN, one)) == true;
+Math.isNaN(Math.min(Math.NaN, zero)) == true;
+
+// max
+Math.max(0.0, 1.0) == 1.0;
+Math.max(0.0, -1.0) == 0.0;
+Math.max(0.0, 0.0) == 0.0;
+Math.max(1.0, 1.0) == 1.0;
+Math.max(Math.NEGATIVE_INFINITY, Math.NEGATIVE_INFINITY) == Math.NEGATIVE_INFINITY;
+Math.max(Math.NEGATIVE_INFINITY, Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.max(Math.POSITIVE_INFINITY, Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.max(Math.POSITIVE_INFINITY, zero) == Math.POSITIVE_INFINITY;
+Math.max(Math.NEGATIVE_INFINITY, zero) == 0;
+Math.isNaN(Math.max(Math.NEGATIVE_INFINITY, Math.NaN)) == true;
+Math.isNaN(Math.max(Math.POSITIVE_INFINITY, Math.NaN)) == true;
+Math.isNaN(Math.max(Math.NaN, Math.NaN)) == true;
+Math.isNaN(Math.max(one, Math.NaN)) == true;
+Math.isNaN(Math.max(zero, Math.NaN)) == true;
+Math.isNaN(Math.max(Math.NaN, Math.NEGATIVE_INFINITY)) == true;
+Math.isNaN(Math.max(Math.NaN,Math.POSITIVE_INFINITY)) == true;
+Math.isNaN(Math.max(Math.NaN, one)) == true;
+Math.isNaN(Math.max(Math.NaN, zero)) == true;
+
+// sin
+Math.sin(0.0) == 0.0;
+Math.sin(Math.PI / 2) == 1.0;
+Math.sin(Math.PI) == 0.0;
+Math.sin(Math.PI * 3 / 2) == -1.0;
+Math.isNaN(Math.sin(Math.POSITIVE_INFINITY)) == true;
+Math.isNaN(Math.sin(Math.NEGATIVE_INFINITY)) == true;
+Math.isNaN(Math.sin(Math.NaN)) == true;
+
+// cos
+Math.cos(0.0) == 1.0;
+Math.cos(Math.PI / 2) == 0.0;
+Math.cos(Math.PI) == -1.0;
+Math.cos(Math.PI * 3 / 2) == 0.0;
+Math.isNaN(Math.cos(Math.POSITIVE_INFINITY)) == true;
+Math.isNaN(Math.cos(Math.NEGATIVE_INFINITY)) == true;
+Math.isNaN(Math.cos(Math.NaN)) == true;
+
+// exp
+Math.exp(0.0) == 1.0;
+Math.exp(1.0) == 2.7182818284590452353602874713527;
+Math.exp(Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.exp(Math.NEGATIVE_INFINITY) == 0.0;
+Math.isNaN(Math.exp(Math.NaN)) == true;
+
+// log
+Math.log(0.0) == Math.NEGATIVE_INFINITY;
+Math.log(2.7182818284590452353602874713527) == 1.0;
+Math.isNaN(Math.log( -1.0)) == true;
+Math.isNaN(Math.log(Math.NaN)) == true;
+Math.isNaN(Math.log(Math.NEGATIVE_INFINITY)) == true;
+Math.log(Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+
+// exp + log
+var floats = [1.33, 39232.911, 12.0, -112.999992, 99999.99999, 0.0, Math.NEGATIVE_INFINITY, Math.POSITIVE_INFINITY];
+for (f in floats) {
+	Math.log(Math.exp(f)) == f;
+}
+
+// sqrt
+Math.sqrt(4.0) == 2;
+Math.sqrt(0.0) == 0.0;
+Math.sqrt(Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.isNaN(Math.sqrt(Math.NEGATIVE_INFINITY)) == true;
+Math.isNaN(Math.sqrt(Math.NaN)) == true;
+Math.isNaN(Math.sqrt( -1.0)) == true;
+
+// round
+Math.round(0.0) == 0;
+Math.round(0.1) == 0;
+Math.round(0.4999) == 0;
+Math.round(0.5) == 1;
+Math.round(1.0) == 1;
+Math.round(1.499) == 1;
+Math.round(-0.1) == 0;
+Math.round(-0.4999) == 0;
+Math.round(-0.5) == 0;
+Math.round(-0.50001) == -1;
+Math.round(-1.0) == -1;
+Math.round(-1.499) == -1;
+Math.round(-1.5) == -1;
+Math.round( -1.50001) == -2;
+Math.round(Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.round(Math.NEGATIVE_INFINITY) == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.round(Math.NaN)) == true;
+
+// floor
+Math.floor(0.0) == 0;
+Math.floor(0.9999) == 0;
+Math.floor(1.0) == 1;
+Math.floor( -0.0001) == -1;
+Math.floor( -1.0) == -1;
+Math.floor( -1.0001) == -2;
+Math.floor(Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.floor(Math.NEGATIVE_INFINITY) == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.floor(Math.NaN)) == true;
+
+// ceil
+Math.ceil(0.0) == 0;
+Math.ceil(-0.9999) == 0;
+Math.ceil(-1.0) == -1;
+Math.ceil( 0.0001) == 1;
+Math.ceil( 1.0) == 1;
+Math.ceil( 1.0001) == 2;
+Math.ceil(Math.POSITIVE_INFINITY) == Math.POSITIVE_INFINITY;
+Math.ceil(Math.NEGATIVE_INFINITY) == Math.NEGATIVE_INFINITY;
+Math.isNaN(Math.ceil(Math.NaN)) == true;
+
+// random
+// not much to test here...
+
+// isFinite
+Math.isFinite(Math.POSITIVE_INFINITY) == false;
+Math.isFinite(Math.NEGATIVE_INFINITY) == false;
+Math.isFinite(Math.NaN) == false;
+Math.isFinite(0.0) == true;
+
+// isNaN
+Math.isNaN(Math.POSITIVE_INFINITY) == false;
+Math.isNaN(Math.NEGATIVE_INFINITY) == false;
+Math.isNaN(Math.NaN) == true;
+Math.isNaN(0.0) == false;