mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 22:58:46 +00:00
big: Add Extended Euclidean algorithm.
This commit is contained in:
@@ -86,13 +86,13 @@ print :: proc(name: string, a: ^Int, base := i8(10), print_name := true, newline
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf :: fmt.printf;
|
// printf :: fmt.printf;
|
||||||
|
|
||||||
demo :: proc() {
|
demo :: proc() {
|
||||||
a, b, c, d, e, f, res := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
|
a, b, c, d, e, f, res := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
|
||||||
defer destroy(a, b, c, d, e, f, res);
|
defer destroy(a, b, c, d, e, f, res);
|
||||||
|
|
||||||
bits := 111;
|
bits := 64;
|
||||||
trials := -1;
|
trials := -1;
|
||||||
|
|
||||||
flags := Primality_Flags{};
|
flags := Primality_Flags{};
|
||||||
|
|||||||
@@ -1280,6 +1280,89 @@ internal_random_prime :: proc(a: ^Int, size_in_bits: int, trials: int, flags :=
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Extended Euclidean algorithm of (a, b) produces `a * u1` + `b * u2` = `u3`.
|
||||||
|
*/
|
||||||
|
internal_int_extended_euclidean :: proc(a, b, U1, U2, U3: ^Int, allocator := context.allocator) -> (err: Error) {
|
||||||
|
context.allocator = allocator;
|
||||||
|
|
||||||
|
u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
|
||||||
|
defer internal_destroy(u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp);
|
||||||
|
internal_init_multi(u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp) or_return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize, (u1, u2, u3) = (1, 0, a).
|
||||||
|
*/
|
||||||
|
internal_set(u1, 1) or_return;
|
||||||
|
internal_set(u3, a) or_return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize, (v1, v2, v3) = (0, 1, b).
|
||||||
|
*/
|
||||||
|
internal_set(v2, 1) or_return;
|
||||||
|
internal_set(v3, b) or_return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Loop while v3 != 0
|
||||||
|
*/
|
||||||
|
for !internal_is_zero(v3) {
|
||||||
|
/*
|
||||||
|
q = u3 / v3
|
||||||
|
*/
|
||||||
|
internal_div(q, u3, v3) or_return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
(t1, t2, t3) = (u1, u2, u3) - (v1, v2, v3)q
|
||||||
|
*/
|
||||||
|
internal_mul(tmp, v1, q) or_return;
|
||||||
|
internal_sub( t1, u1, tmp) or_return;
|
||||||
|
|
||||||
|
internal_mul(tmp, v2, q) or_return;
|
||||||
|
internal_sub( t2, u2, tmp) or_return;
|
||||||
|
|
||||||
|
internal_mul(tmp, v3, q) or_return;
|
||||||
|
internal_sub( t3, u3, tmp) or_return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
(u1, u2, u3) = (v1, v2, v3)
|
||||||
|
*/
|
||||||
|
internal_set(u1, v1) or_return;
|
||||||
|
internal_set(u2, v2) or_return;
|
||||||
|
internal_set(u3, v3) or_return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
(v1, v2, v3) = (t1, t2, t3)
|
||||||
|
*/
|
||||||
|
internal_set(v1, t1) or_return;
|
||||||
|
internal_set(v2, t2) or_return;
|
||||||
|
internal_set(v3, t3) or_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Make sure U3 >= 0.
|
||||||
|
*/
|
||||||
|
if internal_is_negative(u3) {
|
||||||
|
internal_neg(u1, u1) or_return;
|
||||||
|
internal_neg(u2, u2) or_return;
|
||||||
|
internal_neg(u3, u3) or_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copy result out.
|
||||||
|
*/
|
||||||
|
if U1 != nil {
|
||||||
|
internal_swap(u1, U1);
|
||||||
|
}
|
||||||
|
if U2 != nil {
|
||||||
|
internal_swap(u2, U2);
|
||||||
|
}
|
||||||
|
if U3 != nil {
|
||||||
|
internal_swap(u3, U3);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns the number of Rabin-Miller trials needed for a given bit size.
|
Returns the number of Rabin-Miller trials needed for a given bit size.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user