// tests/suite/test_math.el — comprehensive tests for runtime/math.el
//
// Covers every public function in math.el: integer utilities, float math,
// conversions, and rounding.  Import after runtime modules and test.el.

// ── el_abs ────────────────────────────────────────────────────────────────────

fn test_el_abs_basic(_: String) -> String {
    assert_int_eq(el_abs(5), 5, "positive stays positive")
    assert_int_eq(el_abs(-5), 5, "negative becomes positive")
    assert_int_eq(el_abs(0), 0, "zero stays zero")
    assert_int_eq(el_abs(-1), 1, "negative one becomes one")
    assert_int_eq(el_abs(1000000), 1000000, "large positive unchanged")
    assert_int_eq(el_abs(-1000000), 1000000, "large negative becomes positive")
    return ""
}

// ── el_max ────────────────────────────────────────────────────────────────────

fn test_el_max_basic(_: String) -> String {
    assert_int_eq(el_max(3, 5), 5, "5 is larger than 3")
    assert_int_eq(el_max(5, 3), 5, "5 is larger than 3 (reversed args)")
    assert_int_eq(el_max(4, 4), 4, "equal values returns the value")
    assert_int_eq(el_max(-1, -5), -1, "larger of two negatives")
    assert_int_eq(el_max(0, -1), 0, "zero is larger than negative")
    assert_int_eq(el_max(-1, 0), 0, "zero is larger than negative (reversed)")
    return ""
}

fn test_el_max_edge(_: String) -> String {
    assert_int_eq(el_max(0, 0), 0, "max of zeros is zero")
    assert_int_eq(el_max(1000000, 999999), 1000000, "large values")
    assert_int_eq(el_max(-1000000, 1000000), 1000000, "mixed sign large values")
    assert_int_eq(el_max(1, 2), 2, "sequential integers")
    return ""
}

// ── el_min ────────────────────────────────────────────────────────────────────

fn test_el_min_basic(_: String) -> String {
    assert_int_eq(el_min(3, 5), 3, "3 is smaller than 5")
    assert_int_eq(el_min(5, 3), 3, "3 is smaller than 5 (reversed args)")
    assert_int_eq(el_min(4, 4), 4, "equal values returns the value")
    assert_int_eq(el_min(-1, -5), -5, "smaller of two negatives")
    assert_int_eq(el_min(0, -1), -1, "negative is smaller than zero")
    assert_int_eq(el_min(-1, 0), -1, "negative is smaller than zero (reversed)")
    return ""
}

fn test_el_min_edge(_: String) -> String {
    assert_int_eq(el_min(0, 0), 0, "min of zeros is zero")
    assert_int_eq(el_min(1000000, 999999), 999999, "large values")
    assert_int_eq(el_min(-1000000, 1000000), -1000000, "mixed sign large values")
    assert_int_eq(el_min(1, 2), 1, "sequential integers")
    return ""
}

// ── math_sqrt ─────────────────────────────────────────────────────────────────

fn test_math_sqrt_basic(_: String) -> String {
    let r: Float = math_sqrt(4.0)
    assert_true(r > 1.99, "sqrt(4) > 1.99")
    assert_true(r < 2.01, "sqrt(4) < 2.01")

    let r9: Float = math_sqrt(9.0)
    assert_true(r9 > 2.99, "sqrt(9) > 2.99")
    assert_true(r9 < 3.01, "sqrt(9) < 3.01")

    let r1: Float = math_sqrt(1.0)
    assert_true(r1 > 0.99, "sqrt(1) is close to 1")
    assert_true(r1 < 1.01, "sqrt(1) is close to 1")

    let r0: Float = math_sqrt(0.0)
    assert_true(r0 >= 0.0, "sqrt(0) is non-negative")
    assert_true(r0 < 0.001, "sqrt(0) is close to 0")
    return ""
}

fn test_math_sqrt_larger(_: String) -> String {
    let r25: Float = math_sqrt(25.0)
    assert_true(r25 > 4.99, "sqrt(25) > 4.99")
    assert_true(r25 < 5.01, "sqrt(25) < 5.01")

    let r100: Float = math_sqrt(100.0)
    assert_true(r100 > 9.99, "sqrt(100) > 9.99")
    assert_true(r100 < 10.01, "sqrt(100) < 10.01")

    let r2: Float = math_sqrt(2.0)
    assert_true(r2 > 1.41, "sqrt(2) > 1.41")
    assert_true(r2 < 1.43, "sqrt(2) < 1.43")
    return ""
}

// ── math_log / math_ln ───────────────────────────────────────────────────────

fn test_math_log_basic(_: String) -> String {
    let log10: Float = math_log(10.0)
    assert_true(log10 > 0.99, "log(10) > 0.99")
    assert_true(log10 < 1.01, "log(10) < 1.01")

    let log1: Float = math_log(1.0)
    assert_true(log1 > -0.001, "log(1) is close to 0")
    assert_true(log1 < 0.001, "log(1) is close to 0")

    let log100: Float = math_log(100.0)
    assert_true(log100 > 1.99, "log(100) > 1.99")
    assert_true(log100 < 2.01, "log(100) < 2.01")
    return ""
}

fn test_math_ln_basic(_: String) -> String {
    let lne: Float = math_ln(2.718281828)
    assert_true(lne > 0.99, "ln(e) is close to 1")
    assert_true(lne < 1.01, "ln(e) is close to 1")

    let ln1: Float = math_ln(1.0)
    assert_true(ln1 > -0.001, "ln(1) is close to 0")
    assert_true(ln1 < 0.001, "ln(1) is close to 0")

    let ln10: Float = math_ln(10.0)
    assert_true(ln10 > 2.30, "ln(10) > 2.30")
    assert_true(ln10 < 2.31, "ln(10) < 2.31")
    return ""
}

// ── math_sin / math_cos / math_pi ────────────────────────────────────────────

fn test_math_pi_basic(_: String) -> String {
    let pi: Float = math_pi()
    assert_true(pi > 3.14, "pi > 3.14")
    assert_true(pi < 3.15, "pi < 3.15")
    assert_true(pi > 0.0, "pi is positive")
    assert_true(pi == math_pi(), "pi is constant across calls")
    return ""
}

fn test_math_sin_basic(_: String) -> String {
    let sin0: Float = math_sin(0.0)
    assert_true(sin0 > -0.001, "sin(0) is close to 0")
    assert_true(sin0 < 0.001, "sin(0) is close to 0")

    let pi: Float = math_pi()
    let sin_half_pi: Float = math_sin(pi / 2.0)
    assert_true(sin_half_pi > 0.99, "sin(pi/2) is close to 1")
    assert_true(sin_half_pi < 1.01, "sin(pi/2) is close to 1")
    return ""
}

fn test_math_cos_basic(_: String) -> String {
    let cos0: Float = math_cos(0.0)
    assert_true(cos0 > 0.99, "cos(0) is close to 1")
    assert_true(cos0 < 1.01, "cos(0) is close to 1")

    let pi: Float = math_pi()
    let cos_pi: Float = math_cos(pi)
    assert_true(cos_pi < -0.99, "cos(pi) is close to -1")
    assert_true(cos_pi > -1.01, "cos(pi) is close to -1")
    return ""
}

// ── int_to_float / float_to_int ──────────────────────────────────────────────
//
// NOTE: int_to_float, float_to_int, format_float, and decimal_round use seed
// primitives (__int_to_float, __float_to_int, __format_float) that are not yet
// implemented in el_seed.c on the runtime/integrate branch. These tests are
// omitted until those seed primitives are available. The float arithmetic and
// comparison tests below exercise the float type via language builtins instead.

// ── Integer arithmetic (language built-ins) ───────────────────────────────────

fn test_int_arithmetic_basic(_: String) -> String {
    assert_int_eq(2 + 3, 5, "addition")
    assert_int_eq(10 - 4, 6, "subtraction")
    assert_int_eq(3 * 4, 12, "multiplication")
    assert_int_eq(10 / 3, 3, "integer division truncates")
    assert_int_eq(10 % 3, 1, "modulo")
    assert_int_eq(0 - 5, -5, "negation via subtraction")
    return ""
}

fn test_int_arithmetic_edge(_: String) -> String {
    assert_int_eq(0 + 0, 0, "zero plus zero")
    assert_int_eq(0 * 100, 0, "zero times anything")
    assert_int_eq(1 * 1, 1, "one times one")
    assert_int_eq(100 / 100, 1, "divide by self")
    assert_int_eq(7 % 7, 0, "self modulo is zero")
    assert_int_eq(-5 + 5, 0, "additive inverse")
    return ""
}

fn test_int_arithmetic_negative(_: String) -> String {
    assert_int_eq(-3 + -2, -5, "negative addition")
    assert_int_eq(-3 * 4, -12, "negative times positive")
    assert_int_eq(-10 / 3, -3, "negative division truncates toward zero")
    assert_int_eq(0 - 1000, -1000, "large negative")
    assert_int_eq(-1 * -1, 1, "negative times negative is positive")
    return ""
}

// ── Float arithmetic (language built-ins) ────────────────────────────────────

fn test_float_arithmetic_basic(_: String) -> String {
    let a: Float = 1.5 + 2.5
    assert_true(a > 3.99, "1.5 + 2.5 = 4.0")
    assert_true(a < 4.01, "1.5 + 2.5 = 4.0")

    let b: Float = 5.0 - 2.5
    assert_true(b > 2.49, "5.0 - 2.5 = 2.5")
    assert_true(b < 2.51, "5.0 - 2.5 = 2.5")

    let c: Float = 2.0 * 3.0
    assert_true(c > 5.99, "2.0 * 3.0 = 6.0")
    assert_true(c < 6.01, "2.0 * 3.0 = 6.0")

    let d: Float = 9.0 / 3.0
    assert_true(d > 2.99, "9.0 / 3.0 = 3.0")
    assert_true(d < 3.01, "9.0 / 3.0 = 3.0")
    return ""
}

fn test_float_comparison_basic(_: String) -> String {
    assert_true(1.0 < 2.0, "1.0 < 2.0")
    assert_true(2.0 > 1.0, "2.0 > 1.0")
    assert_false(1.0 > 2.0, "1.0 not > 2.0")
    assert_false(2.0 < 1.0, "2.0 not < 1.0")
    assert_true(1.5 >= 1.5, "1.5 >= 1.5")
    assert_true(1.5 <= 1.5, "1.5 <= 1.5")
    return ""
}
