mirror of
https://github.com/vlang/v.git
synced 2025-09-07 22:30:57 -04:00
math: add divide_truncated/2, divide_euclid/2, divide_floored/2 and modulo_truncated/2, modulo_euclid/2, modulo_floored/2 (#21759)
This commit is contained in:
parent
895bd71fa0
commit
3799d7f635
65
vlib/math/modulo.v
Normal file
65
vlib/math/modulo.v
Normal file
@ -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
|
||||||
|
}
|
70
vlib/math/modulo_test.v
Normal file
70
vlib/math/modulo_test.v
Normal file
@ -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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user