(module math (export abs_i32 neg_i32 rem_i32 bit_and_i32 bit_or_i32 bit_xor_i32 is_even_i32 is_odd_i32 min_i32 max_i32 clamp_i32 square_i32 cube_i32 is_zero_i32 is_positive_i32 is_negative_i32 in_range_i32 abs_i64 neg_i64 rem_i64 bit_and_i64 bit_or_i64 bit_xor_i64 is_even_i64 is_odd_i64 min_i64 max_i64 clamp_i64 square_i64 cube_i64 is_zero_i64 is_positive_i64 is_negative_i64 in_range_i64 abs_f64 neg_f64 min_f64 max_f64 clamp_f64 square_f64 cube_f64 is_zero_f64 is_positive_f64 is_negative_f64 in_range_f64))

(fn abs_i32 ((value i32)) -> i32
  (if (< value 0)
    (- 0 value)
    value))

(fn neg_i32 ((value i32)) -> i32
  (- 0 value))

(fn rem_i32 ((left i32) (right i32)) -> i32
  (% left right))

(fn bit_and_i32 ((left i32) (right i32)) -> i32
  (bit_and left right))

(fn bit_or_i32 ((left i32) (right i32)) -> i32
  (bit_or left right))

(fn bit_xor_i32 ((left i32) (right i32)) -> i32
  (bit_xor left right))

(fn is_even_i32 ((value i32)) -> bool
  (= (rem_i32 value 2) 0))

(fn is_odd_i32 ((value i32)) -> bool
  (if (= (rem_i32 value 2) 0)
    false
    true))

(fn min_i32 ((left i32) (right i32)) -> i32
  (if (< left right)
    left
    right))

(fn max_i32 ((left i32) (right i32)) -> i32
  (if (> left right)
    left
    right))

(fn clamp_i32 ((value i32) (low i32) (high i32)) -> i32
  (max_i32 low (min_i32 value high)))

(fn square_i32 ((value i32)) -> i32
  (* value value))

(fn cube_i32 ((value i32)) -> i32
  (* (square_i32 value) value))

(fn is_zero_i32 ((value i32)) -> bool
  (= value 0))

(fn is_positive_i32 ((value i32)) -> bool
  (> value 0))

(fn is_negative_i32 ((value i32)) -> bool
  (< value 0))

(fn in_range_i32 ((value i32) (low i32) (high i32)) -> bool
  (if (>= value low)
    (<= value high)
    false))

(fn abs_i64 ((value i64)) -> i64
  (if (< value 0i64)
    (- 0i64 value)
    value))

(fn neg_i64 ((value i64)) -> i64
  (- 0i64 value))

(fn rem_i64 ((left i64) (right i64)) -> i64
  (% left right))

(fn bit_and_i64 ((left i64) (right i64)) -> i64
  (bit_and left right))

(fn bit_or_i64 ((left i64) (right i64)) -> i64
  (bit_or left right))

(fn bit_xor_i64 ((left i64) (right i64)) -> i64
  (bit_xor left right))

(fn is_even_i64 ((value i64)) -> bool
  (= (rem_i64 value 2i64) 0i64))

(fn is_odd_i64 ((value i64)) -> bool
  (if (= (rem_i64 value 2i64) 0i64)
    false
    true))

(fn min_i64 ((left i64) (right i64)) -> i64
  (if (< left right)
    left
    right))

(fn max_i64 ((left i64) (right i64)) -> i64
  (if (> left right)
    left
    right))

(fn clamp_i64 ((value i64) (low i64) (high i64)) -> i64
  (max_i64 low (min_i64 value high)))

(fn square_i64 ((value i64)) -> i64
  (* value value))

(fn cube_i64 ((value i64)) -> i64
  (* (square_i64 value) value))

(fn is_zero_i64 ((value i64)) -> bool
  (= value 0i64))

(fn is_positive_i64 ((value i64)) -> bool
  (> value 0i64))

(fn is_negative_i64 ((value i64)) -> bool
  (< value 0i64))

(fn in_range_i64 ((value i64) (low i64) (high i64)) -> bool
  (if (>= value low)
    (<= value high)
    false))

(fn abs_f64 ((value f64)) -> f64
  (if (< value 0.0)
    (- 0.0 value)
    value))

(fn neg_f64 ((value f64)) -> f64
  (- 0.0 value))

(fn min_f64 ((left f64) (right f64)) -> f64
  (if (< left right)
    left
    right))

(fn max_f64 ((left f64) (right f64)) -> f64
  (if (> left right)
    left
    right))

(fn clamp_f64 ((value f64) (low f64) (high f64)) -> f64
  (max_f64 low (min_f64 value high)))

(fn square_f64 ((value f64)) -> f64
  (* value value))

(fn cube_f64 ((value f64)) -> f64
  (* (square_f64 value) value))

(fn is_zero_f64 ((value f64)) -> bool
  (= value 0.0))

(fn is_positive_f64 ((value f64)) -> bool
  (> value 0.0))

(fn is_negative_f64 ((value f64)) -> bool
  (< value 0.0))

(fn in_range_f64 ((value f64) (low f64) (high f64)) -> bool
  (if (>= value low)
    (<= value high)
    false))

(fn i32_helpers_ok () -> bool
  (if (= (abs_i32 -7) 7)
    (if (= (neg_i32 7) -7)
      (if (= (min_i32 4 9) 4)
        (if (= (max_i32 4 9) 9)
          (if (= (clamp_i32 15 0 10) 10)
            (if (= (square_i32 6) 36)
              (if (= (cube_i32 3) 27)
                (if (is_zero_i32 0)
                  (if (is_positive_i32 5)
                    (if (is_negative_i32 -5)
                      (if (= (rem_i32 -17 5) -2)
                        (if (is_even_i32 42)
                          (if (is_odd_i32 -41)
                            (if (= (bit_and_i32 6 3) 2)
                              (if (= (bit_or_i32 4 2) 6)
                                (if (= (bit_xor_i32 7 3) 4)
                                  (in_range_i32 5 0 10)
                                  false)
                                false)
                              false)
                            false)
                          false)
                        false)
                      false)
                    false)
                  false)
                false)
              false)
            false)
          false)
        false)
      false)
    false))

(fn i64_helpers_ok () -> bool
  (if (= (abs_i64 -9i64) 9i64)
    (if (= (neg_i64 7i64) -7i64)
      (if (= (min_i64 4i64 9i64) 4i64)
        (if (= (max_i64 4i64 9i64) 9i64)
          (if (= (clamp_i64 -5i64 0i64 10i64) 0i64)
            (if (= (square_i64 12i64) 144i64)
              (if (= (cube_i64 3i64) 27i64)
                (if (is_zero_i64 0i64)
                  (if (is_positive_i64 5i64)
                    (if (is_negative_i64 -5i64)
                      (if (= (rem_i64 -17i64 5i64) -2i64)
                        (if (is_even_i64 42i64)
                          (if (is_odd_i64 -41i64)
                            (if (= (bit_and_i64 6i64 3i64) 2i64)
                              (if (= (bit_or_i64 4i64 2i64) 6i64)
                                (if (= (bit_xor_i64 7i64 3i64) 4i64)
                                  (in_range_i64 5i64 0i64 10i64)
                                  false)
                                false)
                              false)
                            false)
                          false)
                        false)
                      false)
                    false)
                  false)
                false)
              false)
            false)
          false)
        false)
      false)
    false))

(fn f64_helpers_ok () -> bool
  (if (= (abs_f64 -2.5) 2.5)
    (if (= (neg_f64 7.5) -7.5)
      (if (= (min_f64 4.5 9.0) 4.5)
        (if (= (max_f64 4.5 9.0) 9.0)
          (if (= (clamp_f64 12.5 0.0 10.0) 10.0)
            (if (= (square_f64 1.5) 2.25)
              (if (= (cube_f64 2.0) 8.0)
                (if (is_zero_f64 0.0)
                  (if (is_positive_f64 5.0)
                    (if (is_negative_f64 -5.0)
                      (in_range_f64 5.0 0.0 10.0)
                      false)
                    false)
                  false)
                false)
              false)
            false)
          false)
        false)
      false)
    false))

(test "local math i32 helpers"
  (i32_helpers_ok))

(test "local math i64 helpers"
  (i64_helpers_ok))

(test "local math f64 helpers"
  (f64_helpers_ok))
