v / vlib / math / modulo.v
85 lines · 78 sloc · 1.75 KB · c51d30bf5309653c6b573ec815268e69a78ea8cc
Raw
1module math
2
3// DivResult[T] represents the result of an integer division (both quotient and remainder)
4// See also https://en.wikipedia.org/wiki/Modulo
5pub struct DivResult[T] {
6pub mut:
7 quot T
8 rem T
9}
10
11// divide_truncated returns the truncated version of the result of dividing numer to denom
12@[inline]
13pub fn divide_truncated[T](numer T, denom T) DivResult[T] {
14 return DivResult[T]{
15 quot: numer / denom
16 rem: numer % denom
17 }
18}
19
20// divide_euclid returns the Euclidean version of the result of dividing numer to denom
21@[inline]
22pub fn divide_euclid[T](numer T, denom T) DivResult[T] {
23 mut q := numer / denom
24 mut r := numer % denom
25 if r < 0 {
26 if denom > 0 {
27 q = q - 1
28 r = r + denom
29 } else {
30 q = q + 1
31 r = r - denom
32 }
33 }
34 return DivResult[T]{
35 quot: q
36 rem: r
37 }
38}
39
40// divide_floored returns the floored version of the result of dividing numer to denom
41@[inline]
42pub fn divide_floored[T](numer T, denom T) DivResult[T] {
43 mut q := numer / denom
44 mut r := numer % denom
45 if (r > 0 && denom < 0) || (r < 0 && denom > 0) {
46 q = q - 1
47 r = r + denom
48 }
49 return DivResult[T]{
50 quot: q
51 rem: r
52 }
53}
54
55// modulo_truncated returns the truncated remainder of dividing numer to denom
56@[inline]
57pub fn modulo_truncated[T](numer T, denom T) T {
58 return numer % denom
59}
60
61// modulo_euclid returns the Euclidean remainder of dividing numer to denom
62@[inline]
63pub fn modulo_euclid[T](numer T, denom T) T {
64 mut r := numer % denom
65 return if r < 0 {
66 if denom > 0 {
67 r + denom
68 } else {
69 r - denom
70 }
71 } else {
72 r
73 }
74}
75
76// modulo_floored returns the floored remainder of dividing numer to denom
77@[inline]
78pub fn modulo_floored[T](numer T, denom T) T {
79 r := numer % denom
80 return if (r > 0 && denom < 0) || (r < 0 && denom > 0) {
81 r + denom
82 } else {
83 r
84 }
85}
86