package Maths
import NoWurst
import public Angle
import Real
import Integer
import Wurstunit

/** Euler's constant */
public constant real EULER	  =  2.718281828
/** PI constant */
public constant real PI			=  3.141592654
/** PI * 2 constant */
public constant real PI2 		=  6.28318
/** PI / 2 constant */
public constant real PIHALF		=  1.570796326
/**
 * Returns the length of the hypotenuse of a right-angle triangle with the
 * given side lengths. Does not overflow or underflow as fast as
 * SquareRoot(x^2 + y^2) does.
 */
public function hypot(real dx, real dy) returns real
	real x = dx.abs()
	let y = dy.abs()
	real t = 0
	if x > y
		t = y / x
	else if x < y
		t = x / y
		x = y
	return x * SquareRoot(1 + t * t)

/** Returns the angle of a height-slope */
public function getSlopeAngle(real z1, real z2, real dist) returns angle
	return angle(Atan2(z2 - z1, dist))

public function int.moduloInt(int divisor) returns int
	return this - (this div divisor) * divisor

/** Returns the largest value in the set provided as arguments.
	Example: max(6, 4, -12)  // Returns 6. */
public function max(vararg int numbers) returns int
	var maxNumber = INT_MIN
	for number in numbers
		maxNumber = number > maxNumber ? number : maxNumber
	return maxNumber

/** Returns the largest value in the set provided as arguments.
	Example: max(6.5, 4.5, -12.5)  // Returns 6.5. */
public function max(vararg real numbers) returns real
	var maxNumber = REAL_MIN
	for number in numbers
		maxNumber = number > maxNumber ? number : maxNumber
	return maxNumber

/** Returns the smallest value in the set provided as arguments.
	Example: min(6, 4, -12)  // Returns -12. */
public function min(vararg int numbers) returns int
	var minNumber = INT_MAX
	for number in numbers
		minNumber = number < minNumber ? number : minNumber
	return minNumber

/** Returns the smallest value in the set provided as arguments.
	Example: min(6.5, 4.5, -12.5)  // Returns -12,5. */
public function min(vararg real numbers) returns real
	var minNumber = REAL_MAX
	for number in numbers
		minNumber = number < minNumber ? number : minNumber
	return minNumber

@test function minmax()
	let three = 3
	max(three,4,21,43,51,30).assertEquals(51)
	max(3.,4.,5.).assertEquals(5)
	max(-4,three).assertEquals(3)
	min(three,4,0,-2,-1).assertEquals(-2)
	min(3.,4.,-20.,-3.).assertEquals(-20.)

@test function test_hypot()
	test_hypot_help(5,6)
	test_hypot_help(5000000.,6)
	test_hypot_help(3.,123456789.)
	test_hypot_help(543532403425324.,123456789.)
	test_hypot_help(0.0000001,0.0000000000023)
	test_hypot_help(0,0)


function test_hypot_help(real x, real y)
	hypot(x,y).assertEquals(SquareRoot(x * x + y * y), 0.0001)