mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
big: Add gcd_lcm fast path in wrapper.
This commit is contained in:
+35
-23
@@ -1271,26 +1271,45 @@ _int_div_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT) -> (remain
|
|||||||
*/
|
*/
|
||||||
int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int) -> (err: Error) {
|
int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int) -> (err: Error) {
|
||||||
if err = clear_if_uninitialized(res_gcd, res_lcm, a, b); err != .None { return err; }
|
if err = clear_if_uninitialized(res_gcd, res_lcm, a, b); err != .None { return err; }
|
||||||
|
|
||||||
|
az, _ := is_zero(a); bz, _ := is_zero(b);
|
||||||
|
if az && bz {
|
||||||
|
if res_gcd != nil {
|
||||||
|
if err = zero(res_gcd); err != .None { return err; }
|
||||||
|
}
|
||||||
|
if res_lcm != nil {
|
||||||
|
if err = zero(res_lcm); err != .None { return err; }
|
||||||
|
}
|
||||||
|
return .None;
|
||||||
|
}
|
||||||
|
else if az {
|
||||||
|
if res_gcd != nil {
|
||||||
|
if err = abs(res_gcd, b); err != .None { return err; }
|
||||||
|
}
|
||||||
|
if res_lcm != nil {
|
||||||
|
if err = zero(res_lcm); err != .None { return err; }
|
||||||
|
}
|
||||||
|
return .None;
|
||||||
|
}
|
||||||
|
else if bz {
|
||||||
|
if res_gcd != nil {
|
||||||
|
if err = abs(res_gcd, a); err != .None { return err; }
|
||||||
|
}
|
||||||
|
if res_lcm != nil {
|
||||||
|
if err = zero(res_lcm); err != .None { return err; }
|
||||||
|
}
|
||||||
|
return .None;
|
||||||
|
}
|
||||||
|
|
||||||
return #force_inline _int_gcd_lcm(res_gcd, res_lcm, a, b);
|
return #force_inline _int_gcd_lcm(res_gcd, res_lcm, a, b);
|
||||||
}
|
}
|
||||||
gcd_lcm :: proc { int_gcd_lcm, };
|
gcd_lcm :: proc { int_gcd_lcm, };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Greatest Common Divisor using the binary method.
|
Greatest Common Divisor.
|
||||||
*/
|
*/
|
||||||
int_gcd :: proc(res, a, b: ^Int) -> (err: Error) {
|
int_gcd :: proc(res, a, b: ^Int) -> (err: Error) {
|
||||||
if err = clear_if_uninitialized(res, a, b); err != .None { return err; }
|
return #force_inline int_gcd_lcm(res, nil, a, b);
|
||||||
|
|
||||||
/*
|
|
||||||
If both `a` and `b` are zero, return zero.
|
|
||||||
If either `a` or `b`, return the other one.
|
|
||||||
*/
|
|
||||||
az, _ := is_zero(a); bz, _ := is_zero(b);
|
|
||||||
if az && bz { return zero(res); }
|
|
||||||
else if az { return abs(res, b); }
|
|
||||||
else if bz { return abs(res, a); }
|
|
||||||
|
|
||||||
return #force_inline _int_gcd_lcm(res, nil, a, b);
|
|
||||||
}
|
}
|
||||||
gcd :: proc { int_gcd, };
|
gcd :: proc { int_gcd, };
|
||||||
|
|
||||||
@@ -1298,20 +1317,13 @@ gcd :: proc { int_gcd, };
|
|||||||
Least Common Multiple.
|
Least Common Multiple.
|
||||||
*/
|
*/
|
||||||
int_lcm :: proc(res, a, b: ^Int) -> (err: Error) {
|
int_lcm :: proc(res, a, b: ^Int) -> (err: Error) {
|
||||||
if err = clear_if_uninitialized(res, a, b); err != .None { return err; }
|
return #force_inline int_gcd_lcm(nil, res, a, b);
|
||||||
|
|
||||||
/*
|
|
||||||
If both `a` and `b` are zero, return zero.
|
|
||||||
*/
|
|
||||||
az, _ := is_zero(a); bz, _ := is_zero(b);
|
|
||||||
if az || bz { return zero(res); }
|
|
||||||
|
|
||||||
return #force_inline _int_gcd_lcm(nil, res, a, b);
|
|
||||||
}
|
}
|
||||||
lcm :: proc { int_lcm, };
|
lcm :: proc { int_lcm, };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Internal function computing both GCD and (if target isn't `nil`) also LCM.
|
Internal function computing both GCD using the binary method,
|
||||||
|
and, if target isn't `nil`, also LCM.
|
||||||
Expects the arguments to have been initialized.
|
Expects the arguments to have been initialized.
|
||||||
*/
|
*/
|
||||||
_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int) -> (err: Error) {
|
_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int) -> (err: Error) {
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
@echo off
|
@echo off
|
||||||
:odin run . -vet
|
odin run . -vet
|
||||||
:odin build . -build-mode:shared -show-timings -o:minimal -use-separate-modules
|
:odin build . -build-mode:shared -show-timings -o:minimal -use-separate-modules
|
||||||
:odin build . -build-mode:shared -show-timings -o:size -use-separate-modules -no-bounds-check
|
:odin build . -build-mode:shared -show-timings -o:size -use-separate-modules -no-bounds-check
|
||||||
:odin build . -build-mode:shared -show-timings -o:size -use-separate-modules
|
:odin build . -build-mode:shared -show-timings -o:size -use-separate-modules
|
||||||
:odin build . -build-mode:shared -show-timings -o:speed -use-separate-modules -no-bounds-check
|
:odin build . -build-mode:shared -show-timings -o:speed -use-separate-modules -no-bounds-check
|
||||||
:odin build . -build-mode:shared -show-timings -o:speed -use-separate-modules
|
:odin build . -build-mode:shared -show-timings -o:speed -use-separate-modules
|
||||||
|
|
||||||
python test.py
|
:python test.py
|
||||||
:del big.*
|
|
||||||
@@ -115,7 +115,7 @@ demo :: proc() {
|
|||||||
defer destroy(a, b, c, d, e, f);
|
defer destroy(a, b, c, d, e, f);
|
||||||
|
|
||||||
set(a, 125);
|
set(a, 125);
|
||||||
set(b, 0);
|
set(b, 75);
|
||||||
|
|
||||||
err = gcd_lcm(c, d, a, b);
|
err = gcd_lcm(c, d, a, b);
|
||||||
fmt.printf("gcd_lcm(");
|
fmt.printf("gcd_lcm(");
|
||||||
@@ -138,8 +138,6 @@ demo :: proc() {
|
|||||||
print(", b =", b, 10, false, true, false);
|
print(", b =", b, 10, false, true, false);
|
||||||
print(") =", c, 10, false, true, false);
|
print(") =", c, 10, false, true, false);
|
||||||
fmt.printf(" (err = %v)\n", err);
|
fmt.printf(" (err = %v)\n", err);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
|
|||||||
@@ -324,8 +324,8 @@ PyRes :: struct {
|
|||||||
ai, bi, dest := &Int{}, &Int{}, &Int{};
|
ai, bi, dest := &Int{}, &Int{}, &Int{};
|
||||||
defer destroy(ai, bi, dest);
|
defer destroy(ai, bi, dest);
|
||||||
|
|
||||||
if err = atoi(ai, string(a), 16); err != .None { return PyRes{res=":gcd:atoi(a):", err=err}; }
|
if err = atoi(ai, string(a), 16); err != .None { return PyRes{res=":lcm:atoi(a):", err=err}; }
|
||||||
if err = atoi(bi, string(b), 16); err != .None { return PyRes{res=":gcd:atoi(b):", err=err}; }
|
if err = atoi(bi, string(b), 16); err != .None { return PyRes{res=":lcm:atoi(b):", err=err}; }
|
||||||
if err = lcm(dest, ai, bi); err != .None { return PyRes{res=":lcm:lcm(a, b):", err=err}; }
|
if err = lcm(dest, ai, bi); err != .None { return PyRes{res=":lcm:lcm(a, b):", err=err}; }
|
||||||
|
|
||||||
r: cstring;
|
r: cstring;
|
||||||
|
|||||||
Reference in New Issue
Block a user