big: Add mod_power_of_two.

This commit is contained in:
Jeroen van Rijn
2021-08-11 20:59:51 +02:00
parent 78c0877994
commit d4d863c4db
2 changed files with 55 additions and 12 deletions
+43
View File
@@ -463,6 +463,49 @@ int_double :: proc(dest, src: ^Int) -> (err: Error) {
double :: proc { int_double, }; double :: proc { int_double, };
shl1 :: double; shl1 :: double;
/*
dest = src % (2^power);
*/
int_mod_power_of_two :: proc(dest, src: ^Int, power: int) -> (err: Error) {
dest := dest; src := src;
if err = clear_if_uninitialized(dest); err != .None {
return err;
}
if err = clear_if_uninitialized(src); err != .None {
return err;
}
if power < 0 { return .Invalid_Argument; }
if power == 0 { return zero(dest); }
/*
If the modulus is larger than the value, return the value.
*/
err = copy(dest, src);
if power >= (src.used * _DIGIT_BITS) || err != .None {
return;
}
/*
Zero digits above the last digit of the modulus.
*/
zero_count := (power / _DIGIT_BITS) + 0 if (power % _DIGIT_BITS == 0) else 1;
/*
Zero remainder.
*/
if zero_count > 0 {
mem.zero_slice(dest.digit[zero_count:]);
}
/*
Clear the digit that is not completely outside/inside the modulus.
*/
dest.digit[power / _DIGIT_BITS] &= DIGIT(1 << DIGIT(power % _DIGIT_BITS)) - DIGIT(1);
return clamp(dest);
}
mod_power_of_two :: proc { int_mod_power_of_two, };
/* /*
========================== ==========================
Low-level routines Low-level routines
+4 -4
View File
@@ -57,16 +57,16 @@ demo :: proc() {
a, b, c := &Int{}, &Int{}, &Int{}; a, b, c := &Int{}, &Int{}, &Int{};
defer destroy(a, b, c); defer destroy(a, b, c);
err = set(a, 0); err = set(a, -512);
a.used = 2;
a.digit[1] = 1;
err = set(b, 1); err = set(b, 1);
err = set(c, -4); err = set(c, -4);
err = mod_power_of_two(a, a, 10);
fmt.printf("%v (%v)\n", int_get_float(a)); fmt.printf("%v (%v)\n", int_get_float(a));
print("a", a, 16); print("a", a, 10);
print("b", b, 10); print("b", b, 10);
print("c", c, 10); print("c", c, 10);