{"files_list":{"files_list":[{"path":"project.pax","content":"---\r\nPAX Project Configuration\r\n*---\r\n\/\r\n    name        :: \"mathlib\",\r\n    version     :: \"4.4.0\",\r\n    author      :: \"xcx-official\",\r\n    description :: \"Standard math library for XCX \u2014 constants, arithmetic, trigonometry, statistics, geometry, combinatorics, unit conversion, and bit operations\",\r\n    main        :: \"src\/math.xcx\",\r\n    tags  :: [\"math\", \"stdlib\", \"statistics\", \"geometry\", \"trigonometry\", \"xcx\"],\r\n    files :: [\"src\/math.xcx\"],\r\n    deps  :: []\r\n\/"},{"path":"README.md","content":"# mathlib\r\n\r\nStandard math library for [XCX](https:\/\/xcxlang.com). Provides constants, arithmetic, trigonometry, statistics, geometry, combinatorics, unit conversion, and bit operations \u2014 all implemented in pure XCX with no external dependencies.\r\n\r\n## Installation\r\n\r\n```sh\r\nxcx pax add mathlib@latest\r\n```\r\n\r\n## Usage\r\n\r\n```xcx\r\ninclude \"mathlib\/math.xcx\" as math;\r\n\r\nf: area = math.circle_area(5.0);\r\nf: root = math.sqrt_f(144.0);\r\nf: angle = math.sin_f(math.PI \/ 4.0);\r\n```\r\n\r\n## Contents\r\n\r\n| Module | Functions |\r\n|---|---|\r\n| Constants | `PI`, `E`, `TAU`, `PHI`, `SQRT2`, `LN2`, `INF`, `EPSILON`, `INT_MAX`, `INT_MIN` |\r\n| Integer math | `abs_i`, `min_i`, `max_i`, `clamp_i`, `sign_i`, `wrap_i`, `same_sign` |\r\n| Float math | `abs_f`, `min_f`, `max_f`, `clamp_f`, `floor_f`, `ceil_f`, `round_f`, `round_to`, `lerp`, `lerp_clamped`, `smoothstep`, `remap`, `nearly_equal` |\r\n| Powers & roots | `pow_i`, `pow_f`, `sqrt_f`, `cbrt_f`, `nroot_f`, `hypot`, `hypot3` |\r\n| Logarithms & exp | `exp_f`, `ln_f`, `log2_f`, `log10_f`, `log_base` |\r\n| Trigonometry | `sin_f`, `cos_f`, `tan_f`, `asin_f`, `acos_f`, `atan_f`, `atan2_f`, `deg_to_rad`, `rad_to_deg` |\r\n| Number theory | `gcd`, `lcm`, `is_prime`, `factorial`, `fibonacci` |\r\n| Statistics | `sum`, `mean`, `variance`, `std_dev`, `median`, `min_arr`, `max_arr`, `range_arr`, `weighted_mean`, `dot_product`, `norm_vec`, `correlation` |\r\n| Unit conversion | length, weight, temperature, volume, speed, data |\r\n| Geometry | `circle_area`, `rect_area`, `triangle_area`, `triangle_area_heron`, `sphere_volume`, `dist2d`, `dist3d` |\r\n| Combinatorics | `combinations`, `permutations`, `factorial`, `catalan`, `derangements`, `surjections` |\r\n| Bit operations | `is_pow2`, `popcount` |\r\n"},{"path":"src\/math.xcx","content":"\r\n--- ================================================================\r\n---                      _   _     _ _ _\r\n---                     | | | |   | (_) |\r\n---  _ __ ___ __ _| |_| |__ | |_| |__\r\n--- | '_ ` _ \\ \/ _` | __| '_ \\| | | '_ \\\r\n--- | | | | | | (_| | |_| | | | | | |_) |\r\n--- |_| |_| |_|\\__,_|\\__|_| |_|_|_|_.__\/\r\n---  +---------------------------------------------------+\r\n---  |  XCX Standard Math Library  v4.4.0               |\r\n---  |  Usage: include \"math.xcx\" as math;               |\r\n---  +---------------------------------------------------+\r\n---  |  [1]  Constants            [7]  Number Theory     |\r\n---  |  [2]  Basic - Integer      [8]  Statistics        |\r\n---  |  [3]  Basic - Float        [9]  Unit Converters   |\r\n---  |  [4]  Powers & Roots       [10] Geometry          |\r\n---  |  [5]  Logarithms & Exp     [11] Combinatorics     |\r\n---  |  [6]  Trigonometry         [12] Bit Operations    |\r\n---  +---------------------------------------------------+\r\n--- ================================================================\r\n\r\n--- [1] Constants\r\n--- ================================================================\r\n\r\nconst f: PI      = 3.14159265358979;\r\nconst f: E       = 2.71828182845905;\r\nconst f: TAU     = 6.28318530717959;\r\nconst f: PHI     = 1.61803398874989;\r\nconst f: SQRT2   = 1.41421356237310;\r\nconst f: SQRT3   = 1.73205080756888;\r\nconst f: LN2     = 0.69314718055995;\r\nconst f: LN10    = 2.30258509299405;\r\nconst f: LOG2E   = 1.44269504088896;\r\nconst f: INF     = 999999999999999.0;\r\nconst f: EPSILON = 0.000000001;\r\nconst i: INT_MAX = 2147483647;\r\nconst i: INT_MIN = -2147483648;\r\n\r\n--- [2] Basic - Integer\r\n--- ================================================================\r\n\r\nfunc abs_i(i: x -> i) {\r\n    if (x < 0) then; return -x; end;\r\n    return x;\r\n};\r\n\r\nfunc min_i(i: a, i: b -> i) {\r\n    if (a < b) then; return a; end;\r\n    return b;\r\n};\r\n\r\nfunc max_i(i: a, i: b -> i) {\r\n    if (a > b) then; return a; end;\r\n    return b;\r\n};\r\n\r\nfunc clamp_i(i: val, i: lo, i: hi -> i) {\r\n    if (val < lo) then; return lo; end;\r\n    if (val > hi) then; return hi; end;\r\n    return val;\r\n};\r\n\r\nfunc sign_i(i: x -> i) {\r\n    if (x > 0) then; return 1; end;\r\n    if (x < 0) then; return -1; end;\r\n    return 0;\r\n};\r\n\r\n--- Returns true if a and b have the same sign (both positive or both negative).\r\nfunc same_sign(i: a, i: b -> b) {\r\n    return sign_i(a) == sign_i(b);\r\n};\r\n\r\n--- Returns a wrapped into the range [0, m).\r\nfunc wrap_i(i: a, i: m -> i) {\r\n    if (m <= 0) then;\r\n        halt.error >! \"wrap_i: modulus must be positive\";\r\n        return 0;\r\n    end;\r\n    i: r = a % m;\r\n    if (r < 0) then; return r + m; end;\r\n    return r;\r\n};\r\n\r\n--- [3] Basic - Float\r\n--- ================================================================\r\n\r\nfunc abs_f(f: x -> f) {\r\n    if (x < 0.0) then; return -x; end;\r\n    return x;\r\n};\r\n\r\nfunc min_f(f: a, f: b -> f) {\r\n    if (a < b) then; return a; end;\r\n    return b;\r\n};\r\n\r\nfunc max_f(f: a, f: b -> f) {\r\n    if (a > b) then; return a; end;\r\n    return b;\r\n};\r\n\r\nfunc clamp_f(f: val, f: lo, f: hi -> f) {\r\n    if (val < lo) then; return lo; end;\r\n    if (val > hi) then; return hi; end;\r\n    return val;\r\n};\r\n\r\nfunc sign_f(f: x -> i) {\r\n    if (x > 0.0) then; return 1; end;\r\n    if (x < 0.0) then; return -1; end;\r\n    return 0;\r\n};\r\n\r\nfunc floor_f(f: x -> i) {\r\n    i: n = i(x);\r\n    if (x < 0.0 AND f(n) != x) then; return n - 1; end;\r\n    return n;\r\n};\r\n\r\nfunc ceil_f(f: x -> i) {\r\n    i: n = i(x);\r\n    if (x > 0.0 AND f(n) != x) then; return n + 1; end;\r\n    return n;\r\n};\r\n\r\nfunc round_f(f: x -> i) {\r\n    return floor_f(x + 0.5);\r\n};\r\n\r\n--- Rounds x to d decimal places.\r\nfunc round_to(f: x, i: d -> f) {\r\n    f: factor = pow_f(10.0, d);\r\n    return f(round_f(x * factor)) \/ factor;\r\n};\r\n\r\nfunc frac(f: x -> f) {\r\n    return x - f(i(x));\r\n};\r\n\r\nfunc lerp(f: a, f: b, f: t -> f) {\r\n    return a + (b - a) * t;\r\n};\r\n\r\nfunc lerp_clamped(f: a, f: b, f: t -> f) {\r\n    f: tc = clamp_f(t, 0.0, 1.0);\r\n    return a + (b - a) * tc;\r\n};\r\n\r\nfunc nearly_equal(f: a, f: b, f: epsilon -> b) {\r\n    return abs_f(a - b) < epsilon;\r\n};\r\n\r\n--- Smooth Hermite interpolation (smoothstep).\r\nfunc smoothstep(f: edge0, f: edge1, f: x -> f) {\r\n    f: t = clamp_f((x - edge0) \/ (edge1 - edge0), 0.0, 1.0);\r\n    return t * t * (3.0 - 2.0 * t);\r\n};\r\n\r\n--- Maps x from range [a, b] to range [c, d].\r\nfunc remap(f: x, f: a, f: b, f: c, f: d -> f) {\r\n    if (abs_f(b - a) < EPSILON) then;\r\n        halt.error >! \"remap: source range has zero length\";\r\n        return c;\r\n    end;\r\n    return c + (x - a) \/ (b - a) * (d - c);\r\n};\r\n\r\n--- [4] Powers & Roots\r\n--- ================================================================\r\n\r\nfunc pow_i(i: base, i: exp -> i) {\r\n    if (exp < 0) then;\r\n        halt.error >! \"pow_i: negative exponent\";\r\n        return 0;\r\n    end;\r\n    if (exp == 0) then; return 1; end;\r\n    i: result = 1;\r\n    i: e = exp;\r\n    i: b = base;\r\n    while (e > 0) do;\r\n        if (e % 2 == 1) then; result = result * b; end;\r\n        b = b * b;\r\n        e = e \/ 2;\r\n    end;\r\n    return result;\r\n};\r\n\r\nfunc pow_f(f: base, i: exp -> f) {\r\n    if (exp == 0) then; return 1.0; end;\r\n    b: neg = (exp < 0);\r\n    i: e = abs_i(exp);\r\n    f: result = 1.0;\r\n    f: b = base;\r\n    while (e > 0) do;\r\n        if (e % 2 == 1) then; result = result * b; end;\r\n        b = b * b;\r\n        e = e \/ 2;\r\n    end;\r\n    if (neg) then;\r\n        if (result == 0.0) then;\r\n            halt.error >! \"pow_f: division by zero\";\r\n            return 0.0;\r\n        end;\r\n        return 1.0 \/ result;\r\n    end;\r\n    return result;\r\n};\r\n\r\nfunc sqrt_f(f: x -> f) {\r\n    if (x < 0.0) then;\r\n        halt.error >! \"sqrt_f: negative argument\";\r\n        return -1.0;\r\n    end;\r\n    if (x == 0.0) then; return 0.0; end;\r\n    f: guess = x \/ 2.0;\r\n    i: iter = 0;\r\n    while (iter < 50) do;\r\n        f: next = (guess + x \/ guess) \/ 2.0;\r\n        if (abs_f(next - guess) < EPSILON) then; return next; end;\r\n        guess = next;\r\n        iter = iter + 1;\r\n    end;\r\n    return guess;\r\n};\r\n\r\nfunc cbrt_f(f: x -> f) {\r\n    if (x == 0.0) then; return 0.0; end;\r\n    f: s = 1.0;\r\n    if (x < 0.0) then; s = -1.0; end;\r\n    f: ax = abs_f(x);\r\n    f: g = ax \/ 3.0;\r\n    i: iter = 0;\r\n    while (iter < 50) do;\r\n        f: g3 = g * g * g;\r\n        f: next = g - (g3 - ax) \/ (3.0 * g * g);\r\n        if (abs_f(next - g) < EPSILON) then; return s * next; end;\r\n        g = next;\r\n        iter = iter + 1;\r\n    end;\r\n    return s * g;\r\n};\r\n\r\n--- Returns the n-th root of x.\r\nfunc nroot_f(f: x, i: n -> f) {\r\n    if (n == 0) then;\r\n        halt.error >! \"nroot_f: n cannot be zero\";\r\n        return 0.0;\r\n    end;\r\n    if (n == 2) then; return sqrt_f(x); end;\r\n    if (n == 3) then; return cbrt_f(x); end;\r\n    if (x < 0.0 AND n % 2 == 0) then;\r\n        halt.error >! \"nroot_f: even root of negative number\";\r\n        return 0.0;\r\n    end;\r\n    f: s = 1.0;\r\n    if (x < 0.0) then; s = -1.0; end;\r\n    f: ax = abs_f(x);\r\n    f: g = ax \/ f(n);\r\n    i: iter = 0;\r\n    while (iter < 60) do;\r\n        f: gn = pow_f(g, n - 1);\r\n        f: next = (f(n - 1) * g + ax \/ gn) \/ f(n);\r\n        if (abs_f(next - g) < EPSILON) then; return s * next; end;\r\n        g = next;\r\n        iter = iter + 1;\r\n    end;\r\n    return s * g;\r\n};\r\n\r\nfunc hypot(f: a, f: b -> f) {\r\n    return sqrt_f(a * a + b * b);\r\n};\r\n\r\n--- 3D hypotenuse.\r\nfunc hypot3(f: a, f: b, f: c -> f) {\r\n    return sqrt_f(a * a + b * b + c * c);\r\n};\r\n\r\n--- [5] Logarithms & Exp\r\n--- ================================================================\r\n\r\nfunc exp_f(f: x -> f) {\r\n    f: result = 1.0;\r\n    f: term   = 1.0;\r\n    i: n      = 1;\r\n    while (n < 100) do;\r\n        term = term * x \/ f(n);\r\n        result = result + term;\r\n        if (abs_f(term) < 0.0000000000001) then; return result; end;\r\n        n = n + 1;\r\n    end;\r\n    return result;\r\n};\r\n\r\nfunc ln_f(f: x -> f) {\r\n    if (x <= 0.0) then;\r\n        halt.error >! \"ln_f: non-positive argument\";\r\n        return 0.0;\r\n    end;\r\n    i: k = 0;\r\n    f: v = x;\r\n    while (v >= E) do; v = v \/ E; k = k + 1; end;\r\n    while (v < 1.0) do; v = v * E; k = k - 1; end;\r\n    f: t      = v - 1.0;\r\n    f: result = 0.0;\r\n    f: term   = t;\r\n    i: n      = 1;\r\n    while (n < 200) do;\r\n        if (n % 2 == 1) then;\r\n            result = result + term \/ f(n);\r\n        else;\r\n            result = result - term \/ f(n);\r\n        end;\r\n        term = term * t;\r\n        if (abs_f(term) < 0.0000000000001) then; return f(k) + result; end;\r\n        n = n + 1;\r\n    end;\r\n    return f(k) + result;\r\n};\r\n\r\nfunc log2_f(f: x -> f) {\r\n    return ln_f(x) \/ LN2;\r\n};\r\n\r\nfunc log10_f(f: x -> f) {\r\n    return ln_f(x) \/ LN10;\r\n};\r\n\r\nfunc log_base(f: x, f: base -> f) {\r\n    if (base <= 0.0 OR base == 1.0) then;\r\n        halt.error >! \"log_base: invalid base\";\r\n        return 0.0;\r\n    end;\r\n    return ln_f(x) \/ ln_f(base);\r\n};\r\n\r\n--- [6] Trigonometry\r\n--- ================================================================\r\n\r\nfunc deg_to_rad(f: deg -> f) {\r\n    return deg * PI \/ 180.0;\r\n};\r\n\r\nfunc rad_to_deg(f: rad -> f) {\r\n    return rad * 180.0 \/ PI;\r\n};\r\n\r\nfunc sin_f(f: x -> f) {\r\n    f: v = x;\r\n    while (v > PI)  do; v = v - TAU; end;\r\n    while (v < -PI) do; v = v + TAU; end;\r\n    f: result = v;\r\n    f: term   = v;\r\n    i: n      = 1;\r\n    while (n < 20) do;\r\n        term = -term * v * v \/ f(2 * n) \/ f(2 * n + 1);\r\n        result = result + term;\r\n        n = n + 1;\r\n    end;\r\n    return result;\r\n};\r\n\r\nfunc cos_f(f: x -> f) {\r\n    return sin_f(x + PI \/ 2.0);\r\n};\r\n\r\nfunc tan_f(f: x -> f) {\r\n    f: c = cos_f(x);\r\n    if (abs_f(c) < EPSILON) then;\r\n        halt.error >! \"tan_f: undefined (cos = 0)\";\r\n        return 0.0;\r\n    end;\r\n    return sin_f(x) \/ c;\r\n};\r\n\r\nfunc atan_f(f: x -> f) {\r\n    if (x > 1.0)  then; return PI \/ 2.0  - atan_f(1.0 \/ x); end;\r\n    if (x < -1.0) then; return -PI \/ 2.0 - atan_f(1.0 \/ x); end;\r\n    f: x2     = x * x;\r\n    f: result = x;\r\n    f: term   = x;\r\n    i: n      = 1;\r\n    while (n < 50) do;\r\n        term = -term * x2;\r\n        result = result + term \/ f(2 * n + 1);\r\n        n = n + 1;\r\n    end;\r\n    return result;\r\n};\r\n\r\nfunc atan2_f(f: y, f: x -> f) {\r\n    if (x > 0.0)               then; return atan_f(y \/ x);      end;\r\n    if (x < 0.0 AND y >= 0.0)  then; return atan_f(y \/ x) + PI; end;\r\n    if (x < 0.0 AND y < 0.0)   then; return atan_f(y \/ x) - PI; end;\r\n    if (x == 0.0 AND y > 0.0)  then; return PI \/ 2.0;           end;\r\n    if (x == 0.0 AND y < 0.0)  then; return -PI \/ 2.0;          end;\r\n    halt.error >! \"atan2_f: both arguments are zero\";\r\n    return 0.0;\r\n};\r\n\r\nfunc asin_f(f: x -> f) {\r\n    if (x < -1.0 OR x > 1.0) then;\r\n        halt.error >! \"asin_f: argument out of [-1, 1]\";\r\n        return 0.0;\r\n    end;\r\n    return atan_f(x \/ sqrt_f(1.0 - x * x));\r\n};\r\n\r\nfunc acos_f(f: x -> f) {\r\n    if (x < -1.0 OR x > 1.0) then;\r\n        halt.error >! \"acos_f: argument out of [-1, 1]\";\r\n        return 0.0;\r\n    end;\r\n    return PI \/ 2.0 - asin_f(x);\r\n};\r\n\r\nfunc sinh_f(f: x -> f) {\r\n    return (exp_f(x) - exp_f(-x)) \/ 2.0;\r\n};\r\n\r\nfunc cosh_f(f: x -> f) {\r\n    return (exp_f(x) + exp_f(-x)) \/ 2.0;\r\n};\r\n\r\nfunc tanh_f(f: x -> f) {\r\n    f: e2 = exp_f(2.0 * x);\r\n    return (e2 - 1.0) \/ (e2 + 1.0);\r\n};\r\n\r\n--- [7] Number Theory\r\n--- ================================================================\r\n\r\nfunc gcd(i: a, i: b -> i) {\r\n    i: x = abs_i(a);\r\n    i: y = abs_i(b);\r\n    while (y != 0) do;\r\n        i: t = y;\r\n        y = x % y;\r\n        x = t;\r\n    end;\r\n    return x;\r\n};\r\n\r\nfunc lcm(i: a, i: b -> i) {\r\n    if (a == 0 OR b == 0) then; return 0; end;\r\n    return abs_i(a \/ gcd(a, b) * b);\r\n};\r\n\r\nfunc is_prime(i: n -> b) {\r\n    if (n < 2)      then; return false; end;\r\n    if (n == 2)     then; return true;  end;\r\n    if (n % 2 == 0) then; return false; end;\r\n    i: k = 3;\r\n    while (k * k <= n) do;\r\n        if (n % k == 0) then; return false; end;\r\n        k = k + 2;\r\n    end;\r\n    return true;\r\n};\r\n\r\nfunc factorial(i: n -> i) {\r\n    if (n < 0) then;\r\n        halt.error >! \"factorial: negative argument\";\r\n        return -1;\r\n    end;\r\n    if (n == 0 OR n == 1) then; return 1; end;\r\n    i: result = 1;\r\n    i: k = 2;\r\n    while (k <= n) do;\r\n        result = result * k;\r\n        k = k + 1;\r\n    end;\r\n    return result;\r\n};\r\n\r\nfunc fibonacci(i: n -> i) {\r\n    if (n < 0) then;\r\n        halt.error >! \"fibonacci: negative argument\";\r\n        return -1;\r\n    end;\r\n    if (n == 0) then; return 0; end;\r\n    if (n == 1) then; return 1; end;\r\n    i: a = 0;\r\n    i: b = 1;\r\n    i: k = 2;\r\n    while (k <= n) do;\r\n        i: tmp = a + b;\r\n        a = b;\r\n        b = tmp;\r\n        k = k + 1;\r\n    end;\r\n    return b;\r\n};\r\n\r\n--- Returns the next prime number after n.\r\nfunc next_prime(i: n -> i) {\r\n    i: c = n + 1;\r\n    while (NOT is_prime(c)) do;\r\n        c = c + 1;\r\n    end;\r\n    return c;\r\n};\r\n\r\n--- Returns Euler's totient \u03c6(n).\r\nfunc totient(i: n -> i) {\r\n    if (n <= 0) then;\r\n        halt.error >! \"totient: argument must be positive\";\r\n        return 0;\r\n    end;\r\n    i: result = n;\r\n    i: p = 2;\r\n    i: v = n;\r\n    while (p * p <= v) do;\r\n        if (v % p == 0) then;\r\n            while (v % p == 0) do; v = v \/ p; end;\r\n            result = result - result \/ p;\r\n        end;\r\n        p = p + 1;\r\n    end;\r\n    if (v > 1) then; result = result - result \/ v; end;\r\n    return result;\r\n};\r\n\r\nfunc combinations(i: n, i: k -> i) {\r\n    if (k < 0 OR k > n) then; return 0; end;\r\n    if (k == 0 OR k == n) then; return 1; end;\r\n    i: kk = k;\r\n    if (n - k < k) then; kk = n - k; end;\r\n    i: result = 1;\r\n    i: j = 0;\r\n    while (j < kk) do;\r\n        result = result * (n - j) \/ (j + 1);\r\n        j = j + 1;\r\n    end;\r\n    return result;\r\n};\r\n\r\nfunc permutations(i: n, i: k -> i) {\r\n    if (k < 0 OR k > n) then; return 0; end;\r\n    i: result = 1;\r\n    i: j = 0;\r\n    while (j < k) do;\r\n        result = result * (n - j);\r\n        j = j + 1;\r\n    end;\r\n    return result;\r\n};\r\n\r\nfunc is_even(i: n -> b) { return n % 2 == 0; };\r\nfunc is_odd(i: n -> b)  { return n % 2 != 0; };\r\n\r\nfunc is_divisible(i: n, i: d -> b) {\r\n    if (d == 0) then;\r\n        halt.error >! \"is_divisible: zero divisor\";\r\n        return false;\r\n    end;\r\n    return n % d == 0;\r\n};\r\n\r\nfunc digits_sum(i: n -> i) {\r\n    i: v = abs_i(n);\r\n    i: s = 0;\r\n    while (v > 0) do;\r\n        s = s + v % 10;\r\n        v = v \/ 10;\r\n    end;\r\n    return s;\r\n};\r\n\r\nfunc count_digits(i: n -> i) {\r\n    if (n == 0) then; return 1; end;\r\n    i: v = abs_i(n);\r\n    i: c = 0;\r\n    while (v > 0) do; v = v \/ 10; c = c + 1; end;\r\n    return c;\r\n};\r\n\r\nfunc reverse_int(i: n -> i) {\r\n    b: neg = (n < 0);\r\n    i: v = abs_i(n);\r\n    i: r = 0;\r\n    while (v > 0) do;\r\n        r = r * 10 + v % 10;\r\n        v = v \/ 10;\r\n    end;\r\n    if (neg) then; return -r; end;\r\n    return r;\r\n};\r\n\r\nfunc is_palindrome_int(i: n -> b) {\r\n    if (n < 0) then; return false; end;\r\n    return n == reverse_int(n);\r\n};\r\n\r\n--- [8] Statistics\r\n--- ================================================================\r\n\r\nfunc sum_arr(array:f: arr -> f) {\r\n    f: s = 0.0;\r\n    i: k = 0;\r\n    i: sz = arr.size();\r\n    while (k < sz) do;\r\n        f: val = arr.get(k);\r\n        s = s + val;\r\n        k = k + 1;\r\n    end;\r\n    return s;\r\n};\r\n\r\nfunc sum_arr_i(array:i: arr -> i) {\r\n    i: s = 0;\r\n    i: k = 0;\r\n    while (k < arr.size()) do;\r\n        s = s + arr.get(k);\r\n        k = k + 1;\r\n    end;\r\n    return s;\r\n};\r\n\r\nfunc mean(array:f: arr -> f) {\r\n    i: n = arr.size();\r\n    if (n == 0) then;\r\n        halt.error >! \"mean: empty array\";\r\n        return 0.0;\r\n    end;\r\n    return sum_arr(arr) \/ f(n);\r\n};\r\n\r\nfunc variance(array:f: arr -> f) {\r\n    i: n = arr.size();\r\n    if (n < 2) then;\r\n        halt.error >! \"variance: need at least 2 elements\";\r\n        return 0.0;\r\n    end;\r\n    f: m   = mean(arr);\r\n    f: acc = 0.0;\r\n    i: k   = 0;\r\n    while (k < n) do;\r\n        f: diff = arr.get(k) - m;\r\n        acc = acc + diff * diff;\r\n        k = k + 1;\r\n    end;\r\n    return acc \/ f(n);\r\n};\r\n\r\n--- Sample variance (Bessel's correction, divides by n-1).\r\nfunc variance_sample(array:f: arr -> f) {\r\n    i: n = arr.size();\r\n    if (n < 2) then;\r\n        halt.error >! \"variance_sample: need at least 2 elements\";\r\n        return 0.0;\r\n    end;\r\n    f: m   = mean(arr);\r\n    f: acc = 0.0;\r\n    i: k   = 0;\r\n    while (k < n) do;\r\n        f: diff = arr.get(k) - m;\r\n        acc = acc + diff * diff;\r\n        k = k + 1;\r\n    end;\r\n    return acc \/ f(n - 1);\r\n};\r\n\r\nfunc std_dev(array:f: arr -> f) {\r\n    return sqrt_f(variance(arr));\r\n};\r\n\r\n--- Sample standard deviation.\r\nfunc std_dev_sample(array:f: arr -> f) {\r\n    return sqrt_f(variance_sample(arr));\r\n};\r\n\r\nfunc min_arr(array:f: arr -> f) {\r\n    i: n = arr.size();\r\n    if (n == 0) then;\r\n        halt.error >! \"min_arr: empty array\";\r\n        return 0.0;\r\n    end;\r\n    f: m = arr.get(0);\r\n    i: k = 1;\r\n    while (k < n) do;\r\n        f: v = arr.get(k);\r\n        if (v < m) then; m = v; end;\r\n        k = k + 1;\r\n    end;\r\n    return m;\r\n};\r\n\r\nfunc max_arr(array:f: arr -> f) {\r\n    i: n = arr.size();\r\n    if (n == 0) then;\r\n        halt.error >! \"max_arr: empty array\";\r\n        return 0.0;\r\n    end;\r\n    f: m = arr.get(0);\r\n    i: k = 1;\r\n    while (k < n) do;\r\n        f: v = arr.get(k);\r\n        if (v > m) then; m = v; end;\r\n        k = k + 1;\r\n    end;\r\n    return m;\r\n};\r\n\r\nfunc range_arr(array:f: arr -> f) {\r\n    return max_arr(arr) - min_arr(arr);\r\n};\r\n\r\nfunc median(array:f: arr -> f) {\r\n    i: n = arr.size();\r\n    if (n == 0) then;\r\n        halt.error >! \"median: empty array\";\r\n        return 0.0;\r\n    end;\r\n    arr.sort();\r\n    if (n % 2 == 1) then; return arr.get(n \/ 2); end;\r\n    return (arr.get(n \/ 2 - 1) + arr.get(n \/ 2)) \/ 2.0;\r\n};\r\n\r\n--- Returns the weighted mean: sum(w_i * x_i) \/ sum(w_i).\r\nfunc weighted_mean(array:f: vals, array:f: weights -> f) {\r\n    if (vals.size() != weights.size()) then;\r\n        halt.error >! \"weighted_mean: arrays must be same length\";\r\n        return 0.0;\r\n    end;\r\n    i: n = vals.size();\r\n    if (n == 0) then;\r\n        halt.error >! \"weighted_mean: empty arrays\";\r\n        return 0.0;\r\n    end;\r\n    f: wsum = 0.0;\r\n    f: vsum = 0.0;\r\n    i: k = 0;\r\n    while (k < n) do;\r\n        f: w = weights.get(k);\r\n        wsum = wsum + w;\r\n        vsum = vsum + vals.get(k) * w;\r\n        k = k + 1;\r\n    end;\r\n    if (abs_f(wsum) < EPSILON) then;\r\n        halt.error >! \"weighted_mean: sum of weights is zero\";\r\n        return 0.0;\r\n    end;\r\n    return vsum \/ wsum;\r\n};\r\n\r\nfunc dot_product(array:f: a, array:f: b -> f) {\r\n    if (a.size() != b.size()) then;\r\n        halt.error >! \"dot_product: arrays must be equal length\";\r\n        return 0.0;\r\n    end;\r\n    f: s = 0.0;\r\n    i: k = 0;\r\n    while (k < a.size()) do;\r\n        s = s + a.get(k) * b.get(k);\r\n        k = k + 1;\r\n    end;\r\n    return s;\r\n};\r\n\r\nfunc norm_vec(array:f: v -> f) {\r\n    return sqrt_f(dot_product(v, v));\r\n};\r\n\r\n--- Returns Pearson correlation coefficient between two arrays.\r\nfunc correlation(array:f: x, array:f: y -> f) {\r\n    i: n = x.size();\r\n    if (n != y.size() OR n < 2) then;\r\n        halt.error >! \"correlation: arrays must be equal length >= 2\";\r\n        return 0.0;\r\n    end;\r\n    f: mx = mean(x);\r\n    f: my = mean(y);\r\n    f: num = 0.0;\r\n    f: dxa = 0.0;\r\n    f: dya = 0.0;\r\n    i: k = 0;\r\n    while (k < n) do;\r\n        f: dx = x.get(k) - mx;\r\n        f: dy = y.get(k) - my;\r\n        num = num + dx * dy;\r\n        dxa = dxa + dx * dx;\r\n        dya = dya + dy * dy;\r\n        k = k + 1;\r\n    end;\r\n    f: denom = sqrt_f(dxa * dya);\r\n    if (abs_f(denom) < EPSILON) then;\r\n        halt.error >! \"correlation: zero variance in input\";\r\n        return 0.0;\r\n    end;\r\n    return num \/ denom;\r\n};\r\n\r\n--- [9] Unit Converters\r\n--- ================================================================\r\n\r\nfunc km_to_miles(f: km  -> f) { return km  * 0.621371; };\r\nfunc miles_to_km(f: mi  -> f) { return mi  * 1.609344; };\r\nfunc m_to_ft(f: m       -> f) { return m   * 3.280840; };\r\nfunc ft_to_m(f: ft      -> f) { return ft  * 0.304800; };\r\nfunc cm_to_in(f: cm     -> f) { return cm  * 0.393701; };\r\nfunc in_to_cm(f: inches -> f) { return inches * 2.54;  };\r\n\r\nfunc kg_to_lbs(f: kg    -> f) { return kg  * 2.204623; };\r\nfunc lbs_to_kg(f: lbs   -> f) { return lbs * 0.453592; };\r\nfunc g_to_oz(f: g       -> f) { return g   * 0.035274; };\r\nfunc oz_to_g(f: oz      -> f) { return oz  * 28.34952; };\r\n\r\nfunc celsius_to_f(f: c       -> f) { return c * 9.0 \/ 5.0 + 32.0;      };\r\nfunc fahrenheit_to_c(f: fahr -> f) { return (fahr - 32.0) * 5.0 \/ 9.0; };\r\nfunc celsius_to_k(f: c       -> f) { return c + 273.15;                 };\r\nfunc kelvin_to_c(f: k        -> f) { return k - 273.15;                 };\r\n\r\nfunc liters_to_gal(f: l -> f) { return l * 0.264172; };\r\nfunc gal_to_liters(f: g -> f) { return g * 3.785412; };\r\nfunc ml_to_fl_oz(f: ml  -> f) { return ml  * 0.033814; };\r\nfunc fl_oz_to_ml(f: foz -> f) { return foz * 29.5735; };\r\n\r\n--- Speed\r\nfunc mps_to_kph(f: mps  -> f) { return mps  * 3.6;       };\r\nfunc kph_to_mps(f: kph  -> f) { return kph  \/ 3.6;       };\r\nfunc kph_to_mph(f: kph  -> f) { return kph  * 0.621371;  };\r\nfunc mph_to_kph(f: mph  -> f) { return mph  * 1.609344;  };\r\n\r\n--- Data\r\nfunc bytes_to_kb(f: b -> f) { return b  \/ 1024.0;       };\r\nfunc kb_to_mb(f: kb     -> f) { return kb \/ 1024.0;      };\r\nfunc mb_to_gb(f: mb     -> f) { return mb \/ 1024.0;      };\r\n\r\n--- [10] Geometry\r\n--- ================================================================\r\n\r\n--- Circle area.\r\nfunc circle_area(f: r -> f) {\r\n    return PI * r * r;\r\n};\r\n\r\n--- Circle circumference.\r\nfunc circle_circumference(f: r -> f) {\r\n    return TAU * r;\r\n};\r\n\r\n--- Rectangle area.\r\nfunc rect_area(f: w, f: h -> f) {\r\n    return w * h;\r\n};\r\n\r\n--- Rectangle perimeter.\r\nfunc rect_perimeter(f: w, f: h -> f) {\r\n    return 2.0 * (w + h);\r\n};\r\n\r\n--- Triangle area from base and height.\r\nfunc triangle_area(f: base, f: height -> f) {\r\n    return 0.5 * base * height;\r\n};\r\n\r\n--- Triangle area from three sides (Heron's formula).\r\nfunc triangle_area_heron(f: a, f: b, f: c -> f) {\r\n    f: s = (a + b + c) \/ 2.0;\r\n    f: v = s * (s - a) * (s - b) * (s - c);\r\n    if (v < 0.0) then;\r\n        halt.error >! \"triangle_area_heron: invalid triangle sides\";\r\n        return 0.0;\r\n    end;\r\n    return sqrt_f(v);\r\n};\r\n\r\n--- Sphere volume.\r\nfunc sphere_volume(f: r -> f) {\r\n    return (4.0 \/ 3.0) * PI * r * r * r;\r\n};\r\n\r\n--- Sphere surface area.\r\nfunc sphere_surface(f: r -> f) {\r\n    return 4.0 * PI * r * r;\r\n};\r\n\r\n--- Cylinder volume.\r\nfunc cylinder_volume(f: r, f: h -> f) {\r\n    return PI * r * r * h;\r\n};\r\n\r\n--- Euclidean distance between two 2D points.\r\nfunc dist2d(f: x1, f: y1, f: x2, f: y2 -> f) {\r\n    return hypot(x2 - x1, y2 - y1);\r\n};\r\n\r\n--- Euclidean distance between two 3D points.\r\nfunc dist3d(f: x1, f: y1, f: z1, f: x2, f: y2, f: z2 -> f) {\r\n    return hypot3(x2 - x1, y2 - y1, z2 - z1);\r\n};\r\n\r\n--- [11] Combinatorics\r\n--- ================================================================\r\n\r\n--- Returns the number of derangements D(n): permutations with no fixed points.\r\nfunc derangements(i: n -> i) {\r\n    if (n == 0) then; return 1; end;\r\n    if (n == 1) then; return 0; end;\r\n    i: a = 1;\r\n    i: b = 0;\r\n    i: k = 2;\r\n    while (k <= n) do;\r\n        i: c = (k - 1) * (a + b);\r\n        a = b;\r\n        b = c;\r\n        k = k + 1;\r\n    end;\r\n    return b;\r\n};\r\n\r\n--- Returns Catalan number C(n).\r\nfunc catalan(i: n -> i) {\r\n    return combinations(2 * n, n) \/ (n + 1);\r\n};\r\n\r\n--- Returns the number of surjections from n elements to k elements.\r\nfunc surjections(i: n, i: k -> i) {\r\n    if (k > n) then; return 0; end;\r\n    i: result = 0;\r\n    i: j = 0;\r\n    while (j <= k) do;\r\n        i: term = combinations(k, j) * pow_i(k - j, n);\r\n        if (j % 2 == 0) then;\r\n            result = result + term;\r\n        else;\r\n            result = result - term;\r\n        end;\r\n        j = j + 1;\r\n    end;\r\n    return result;\r\n};\r\n\r\n--- [12] Bit Operations\r\n--- ================================================================\r\n\r\n--- Returns true if n is a power of two.\r\nfunc is_pow2(i: n -> b) {\r\n    if (n <= 0) then; return false; end;\r\n    return n % 2 == 0 AND (n \/ 2) % 2 == 0 OR n == 1 OR n == 2 OR n == 4 OR n == 8 OR n == 16 OR n == 32 OR n == 64 OR n == 128 OR n == 256 OR n == 512 OR n == 1024 OR n == 2048 OR n == 4096 OR n == 8192 OR n == 16384 OR n == 32768 OR n == 65536;\r\n};\r\n\r\n--- Returns the number of set bits (1s) in n (Brian Kernighan algorithm).\r\nfunc popcount(i: n -> i) {\r\n    i: v = abs_i(n);\r\n    i: c = 0;\r\n    while (v > 0) do;\r\n        v = v - (v - (v \/ 2) * 2) * 0;\r\n        i: bit = v % 2;\r\n        c = c + bit;\r\n        v = v \/ 2;\r\n    end;\r\n    return c;\r\n};\r\n\r\n--- ================================================================\r\n---   END OF math.xcx  v2.0.0\r\n--- ================================================================\r\n"}]}}