-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
math: add divide_truncated/2, divide_euclid/2, divide_floored/2 and m…
…odulo_truncated/2, modulo_euclid/2, modulo_floored/2 (#21759)
- Loading branch information
Showing
2 changed files
with
135 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |