aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2021-07-26 15:07:58 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2021-08-11 20:59:51 +0200
commit9646d1f2b842dd22893b3a70eb9c8aef9b1ffa75 (patch)
tree613b7eb5c6c88ceea0359f109ada9a2087f311bf
parent5f7aeb30450cb9ca794ffe45949f77ed67836ecf (diff)
big: Add `submod`, `mulmod`, `sqrmod`.
-rw-r--r--core/math/big/basic.odin38
-rw-r--r--core/math/big/example.odin4
2 files changed, 37 insertions, 5 deletions
diff --git a/core/math/big/basic.odin b/core/math/big/basic.odin
index fe443db87..52992e15f 100644
--- a/core/math/big/basic.odin
+++ b/core/math/big/basic.odin
@@ -656,7 +656,7 @@ sqr :: proc(dest, src: ^Int) -> (err: Error) {
divmod.
Both the quotient and remainder are optional and may be passed a nil.
*/
-int_div :: proc(quotient, remainder, numerator, denominator: ^Int) -> (err: Error) {
+int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int) -> (err: Error) {
/*
Early out if neither of the results is wanted.
*/
@@ -692,7 +692,12 @@ int_div :: proc(quotient, remainder, numerator, denominator: ^Int) -> (err: Erro
return err;
}
-div :: proc{ int_div, };
+divmod :: proc{ int_divmod, };
+
+int_div :: proc(quotient, numerator, denominator: ^Int) -> (err: Error) {
+ return int_divmod(quotient, nil, numerator, denominator);
+}
+div :: proc { int_div, };
/*
remainder = numerator % denominator.
@@ -700,7 +705,7 @@ div :: proc{ int_div, };
denominator < remainder <= 0 if denominator < 0
*/
int_mod :: proc(remainder, numerator, denominator: ^Int) -> (err: Error) {
- if err = div(nil, remainder, numerator, denominator); err != .None { return err; }
+ if err = divmod(nil, remainder, numerator, denominator); err != .None { return err; }
z: bool;
if z, err = is_zero(remainder); z || denominator.sign == remainder.sign { return .None; }
@@ -718,6 +723,33 @@ int_addmod :: proc(remainder, number, addend, modulus: ^Int) -> (err: Error) {
addmod :: proc { int_addmod, };
/*
+ remainder = (number - decrease) % modulus.
+*/
+int_submod :: proc(remainder, number, decrease, modulus: ^Int) -> (err: Error) {
+ if err = add(remainder, number, decrease); err != .None { return err; }
+ return mod(remainder, remainder, modulus);
+}
+submod :: proc { int_submod, };
+
+/*
+ remainder = (number * multiplicand) % modulus.
+*/
+int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int) -> (err: Error) {
+ if err = mul(remainder, number, multiplicand); err != .None { return err; }
+ return mod(remainder, remainder, modulus);
+}
+mulmod :: proc { int_mulmod, };
+
+/*
+ remainder = (number * number) % modulus.
+*/
+int_sqrmod :: proc(remainder, number, modulus: ^Int) -> (err: Error) {
+ if err = sqr(remainder, number); err != .None { return err; }
+ return mod(remainder, remainder, modulus);
+}
+sqrmod :: proc { int_sqrmod, };
+
+/*
==========================
Low-level routines
==========================
diff --git a/core/math/big/example.odin b/core/math/big/example.odin
index 5a7976a88..ceb047f74 100644
--- a/core/math/big/example.odin
+++ b/core/math/big/example.odin
@@ -69,10 +69,10 @@ demo :: proc() {
err = set (numerator, 3);
err = set (denominator, 2);
- err = set (quotient, 3);
+ err = set (quotient, 5);
err = zero(remainder);
- err = addmod(remainder, numerator, denominator, quotient);
+ err = mulmod(remainder, numerator, denominator, quotient);
if err != .None {
fmt.printf("Error: %v\n", err);
} else {