import "../../runtime/eltest.el"
// test_math.el - native test suite for runtime/math.el
//
// Covers: integer math (abs, max, min), float math (sqrt, log, sin, cos, pi),
// float conversions, format_float, and decimal_round.

test "el-abs" {
    let pos: Int = el_abs(5)
    assert pos == 5, "abs of positive"
    let neg: Int = el_abs(-5)
    assert neg == 5, "abs of negative"
    let zero: Int = el_abs(0)
    assert zero == 0, "abs of zero"
    let large: Int = el_abs(-1000000)
    assert large == 1000000, "abs of large negative"
}

test "el-max" {
    let m: Int = el_max(3, 7)
    assert m == 7, "max of 3 and 7"
    let m2: Int = el_max(7, 3)
    assert m2 == 7, "max is commutative"
    let same: Int = el_max(5, 5)
    assert same == 5, "max of equal values"
    let neg: Int = el_max(-3, -7)
    assert neg == -3, "max of two negatives"
}

test "el-min" {
    let m: Int = el_min(3, 7)
    assert m == 3, "min of 3 and 7"
    let m2: Int = el_min(7, 3)
    assert m2 == 3, "min is commutative"
    let same: Int = el_min(5, 5)
    assert same == 5, "min of equal values"
    let neg: Int = el_min(-3, -7)
    assert neg == -7, "min of two negatives"
}

test "math-pi" {
    let pi: Float = math_pi()
    // pi ~ 3.14159265358979
    // Check it's between 3.141 and 3.142
    let too_low: Float = pi - 3.141
    let too_high: Float = 3.142 - pi
    assert too_low > 0.0, "pi > 3.141"
    assert too_high > 0.0, "pi < 3.142"
}

test "math-sqrt" {
    let r4: Float = math_sqrt(4.0)
    let diff4: Float = r4 - 2.0
    assert diff4 == 0.0, "sqrt(4) == 2.0"
    let r9: Float = math_sqrt(9.0)
    let diff9: Float = r9 - 3.0
    assert diff9 == 0.0, "sqrt(9) == 3.0"
    let r1: Float = math_sqrt(1.0)
    let diff1: Float = r1 - 1.0
    assert diff1 == 0.0, "sqrt(1) == 1.0"
    let r0: Float = math_sqrt(0.0)
    assert r0 == 0.0, "sqrt(0) == 0.0"
}

test "math-sin-cos" {
    // sin(0) == 0, cos(0) == 1
    let s0: Float = math_sin(0.0)
    assert s0 == 0.0, "sin(0) == 0.0"
    let c0: Float = math_cos(0.0)
    assert c0 == 1.0, "cos(0) == 1.0"
    // sin(pi/2) ~ 1.0, cos(pi/2) ~ 0.0
    let half_pi: Float = math_pi() / 2.0
    let s_half: Float = math_sin(half_pi)
    // Check within 0.000001 of 1.0
    let diff_s: Float = s_half - 1.0
    assert diff_s > -0.000001, "sin(pi/2) close to 1.0 low"
    assert diff_s < 0.000001, "sin(pi/2) close to 1.0 high"
}

test "int-to-float-and-back" {
    let f: Float = int_to_float(42)
    let back: Int = float_to_int(f)
    assert back == 42, "42 round-trips int->float->int"
    let neg: Float = int_to_float(-7)
    let neg_back: Int = float_to_int(neg)
    assert neg_back == -7, "-7 round-trips"
    let zero: Float = int_to_float(0)
    let zero_back: Int = float_to_int(zero)
    assert zero_back == 0, "0 round-trips"
}

test "float-to-int-truncates" {
    let t1: Int = float_to_int(3.9)
    assert t1 == 3, "3.9 truncates to 3"
    let t2: Int = float_to_int(3.1)
    assert t2 == 3, "3.1 truncates to 3"
    let t3: Int = float_to_int(-3.7)
    assert t3 == -3, "-3.7 truncates toward zero to -3"
}

test "str-to-float-and-back" {
    let f: Float = str_to_float("3.14")
    // Check it's between 3.13 and 3.15
    let lo: Float = f - 3.13
    let hi: Float = 3.15 - f
    assert lo > 0.0, "3.14 parsed > 3.13"
    assert hi > 0.0, "3.14 parsed < 3.15"
    let zero: Float = str_to_float("0.0")
    assert zero == 0.0, "parse 0.0"
}

test "format-float" {
    let s0: String = format_float(3.14159, 2)
    assert s0 == "3.14", "format to 2 decimals"
    let s1: String = format_float(1.0, 0)
    assert s1 == "1", "format to 0 decimals"
    let s2: String = format_float(0.0, 3)
    assert s2 == "0.000", "format zero to 3 decimals"
    let s3: String = format_float(-2.5, 1)
    assert s3 == "-2.5", "format negative to 1 decimal"
}

test "decimal-round" {
    let r0: Float = decimal_round(2.5, 0)
    assert r0 == 3.0, "round 2.5 to 0 places"
    let r1: Float = decimal_round(2.45, 1)
    assert r1 == 2.5, "round 2.45 to 1 place"
    let neg: Float = decimal_round(-2.5, 0)
    assert neg == -3.0, "round -2.5 to 0 places (half-away-from-zero)"
    let exact: Float = decimal_round(1.0, 2)
    assert exact == 1.0, "rounding exact value unchanged"
}

test "math-log" {
    // log10(100) == 2
    let l100: Float = math_log(100.0)
    let diff: Float = l100 - 2.0
    assert diff > -0.000001, "log10(100) close to 2 low"
    assert diff < 0.000001, "log10(100) close to 2 high"
    // log10(1) == 0
    let l1: Float = math_log(1.0)
    assert l1 == 0.0, "log10(1) == 0"
}

test "math-ln" {
    // ln(1) == 0
    let l1: Float = math_ln(1.0)
    assert l1 == 0.0, "ln(1) == 0"
    // ln(e) ~ 1.0  — e ~ 2.71828
    let e: Float = 2.718281828
    let le: Float = math_ln(e)
    let diff: Float = le - 1.0
    assert diff > -0.000001, "ln(e) close to 1 low"
    assert diff < 0.000001, "ln(e) close to 1 high"
}
