diff --git a/vlib/math/modulo.v b/vlib/math/modulo.v new file mode 100644 index 0000000000..9cb9b1a7f5 --- /dev/null +++ b/vlib/math/modulo.v @@ -0,0 +1,65 @@ +module math + +// DivResult[T] represents the result of an integer division (both quotient and remainder) +// See also https://en.wikipedia.org/wiki/Modulo +pub struct DivResult[T] { +pub mut: + quot T + rem T +} + +// divide_truncated returns the truncated version of the result of dividing numer to denom +pub fn divide_truncated[T](numer T, denom T) DivResult[T] { + return DivResult[T]{ + quot: numer / denom + rem: numer % denom + } +} + +// divide_euclid returns the Euclidean version of the result of dividing numer to denom +pub fn divide_euclid[T](numer T, denom T) DivResult[T] { + mut q := numer / denom + mut r := numer % denom + if r < 0 { + if denom > 0 { + q = q - 1 + r = r + denom + } else { + q = q + 1 + r = r - denom + } + } + return DivResult[T]{ + quot: q + rem: r + } +} + +// divide_floored returns the floored version of the result of dividing numer to denom +pub fn divide_floored[T](numer T, denom T) DivResult[T] { + mut q := numer / denom + mut r := numer % denom + if (r > 0 && denom < 0) || (r < 0 && denom > 0) { + q = q - 1 + r = r + denom + } + return DivResult[T]{ + quot: q + rem: r + } +} + +// modulo_truncated returns the truncated remainder of dividing numer to denom +pub fn modulo_truncated[T](numer T, denom T) T { + return numer % denom +} + +// modulo_euclid returns the Euclidean remainder of dividing numer to denom +pub fn modulo_euclid[T](numer T, denom T) T { + return divide_euclid(numer, denom).rem +} + +// modulo_floored returns the floored remainder of dividing numer to denom +pub fn modulo_floored[T](numer T, denom T) T { + return divide_floored(numer, denom).rem +} diff --git a/vlib/math/modulo_test.v b/vlib/math/modulo_test.v new file mode 100644 index 0000000000..3ebfab7795 --- /dev/null +++ b/vlib/math/modulo_test.v @@ -0,0 +1,70 @@ +import math + +fn test_modulo() { + assert math.modulo_euclid(5, 1) == 0 + assert math.modulo_floored(5, 1) == 0 + assert math.modulo_truncated(5, 1) == 0 + assert math.modulo_euclid(5, 2) == 1 + assert math.modulo_floored(5, 2) == 1 + assert math.modulo_truncated(5, 2) == 1 + assert math.modulo_euclid(5, 3) == 2 + assert math.modulo_floored(5, 3) == 2 + assert math.modulo_truncated(5, 3) == 2 + assert math.modulo_euclid(5, 4) == 1 + assert math.modulo_floored(5, 4) == 1 + assert math.modulo_truncated(5, 4) == 1 + assert math.modulo_euclid(5, 5) == 0 + assert math.modulo_floored(5, 5) == 0 + assert math.modulo_truncated(5, 5) == 0 + assert math.modulo_euclid(-5, 1) == 0 + assert math.modulo_floored(-5, 1) == 0 + assert math.modulo_truncated(-5, 1) == 0 + assert math.modulo_euclid(-5, 2) == 1 + assert math.modulo_floored(-5, 2) == 1 + assert math.modulo_truncated(-5, 2) == -1 + assert math.modulo_euclid(-5, 3) == 1 + assert math.modulo_floored(-5, 3) == 1 + assert math.modulo_truncated(-5, 3) == -2 + assert math.modulo_euclid(-5, 4) == 3 + assert math.modulo_floored(-5, 4) == 3 + assert math.modulo_truncated(-5, 4) == -1 + assert math.modulo_euclid(-5, 5) == 0 + assert math.modulo_floored(-5, 5) == 0 + assert math.modulo_truncated(-5, 5) == 0 + assert math.modulo_euclid(1, 5) == 1 + assert math.modulo_floored(1, 5) == 1 + assert math.modulo_truncated(1, 5) == 1 + assert math.modulo_euclid(2, 5) == 2 + assert math.modulo_floored(2, 5) == 2 + assert math.modulo_truncated(2, 5) == 2 + assert math.modulo_euclid(3, 5) == 3 + assert math.modulo_floored(3, 5) == 3 + assert math.modulo_truncated(3, 5) == 3 + assert math.modulo_euclid(4, 5) == 4 + assert math.modulo_floored(4, 5) == 4 + assert math.modulo_truncated(4, 5) == 4 + assert math.modulo_euclid(-1, 5) == 4 + assert math.modulo_floored(-1, 5) == 4 + assert math.modulo_truncated(-1, 5) == -1 + assert math.modulo_euclid(-2, 5) == 3 + assert math.modulo_floored(-2, 5) == 3 + assert math.modulo_truncated(-2, 5) == -2 + assert math.modulo_euclid(-3, 5) == 2 + assert math.modulo_floored(-3, 5) == 2 + assert math.modulo_truncated(-3, 5) == -3 + assert math.modulo_euclid(-4, 5) == 1 + assert math.modulo_floored(-4, 5) == 1 + assert math.modulo_truncated(-4, 5) == -4 + assert math.modulo_euclid(-1, -5) == 4 + assert math.modulo_floored(-1, -5) == -1 + assert math.modulo_truncated(-1, -5) == -1 + assert math.modulo_euclid(-2, -5) == 3 + assert math.modulo_floored(-2, -5) == -2 + assert math.modulo_truncated(-2, -5) == -2 + assert math.modulo_euclid(-3, -5) == 2 + assert math.modulo_floored(-3, -5) == -3 + assert math.modulo_truncated(-3, -5) == -3 + assert math.modulo_euclid(-4, -5) == 1 + assert math.modulo_floored(-4, -5) == -4 + assert math.modulo_truncated(-4, -5) == -4 +}