mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
big: Correct pow bugs from the original.
This commit is contained in:
@@ -60,6 +60,9 @@ Error :: enum byte {
|
|||||||
Buffer_Overflow = 6,
|
Buffer_Overflow = 6,
|
||||||
Integer_Overflow = 7,
|
Integer_Overflow = 7,
|
||||||
|
|
||||||
|
Division_by_Zero = 8,
|
||||||
|
Math_Domain_Error = 9,
|
||||||
|
|
||||||
Unimplemented = 127,
|
Unimplemented = 127,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -57,15 +57,14 @@ 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, -1024);
|
for base in -3..=3 {
|
||||||
err = set(b, -1024);
|
for power in -3..=3 {
|
||||||
|
err = pow(a, base, power);
|
||||||
|
fmt.printf("err: %v | pow(%v, %v) = ", err, base, power); print("", a, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
print("a", a, 10);
|
|
||||||
print("b", b, 10);
|
|
||||||
|
|
||||||
fmt.println("--- mul ---");
|
|
||||||
mul(c, a, a);
|
|
||||||
print("c", c, 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
|
|||||||
+76
-26
@@ -51,43 +51,93 @@ log :: proc { int_log, int_log_digit, };
|
|||||||
Calculate c = a**b using a square-multiply algorithm.
|
Calculate c = a**b using a square-multiply algorithm.
|
||||||
*/
|
*/
|
||||||
int_pow :: proc(dest, base: ^Int, power: int) -> (err: Error) {
|
int_pow :: proc(dest, base: ^Int, power: int) -> (err: Error) {
|
||||||
if err = clear_if_uninitialized(dest); err != .None { return err; }
|
power := power;
|
||||||
if err = clear_if_uninitialized(base); err != .None { return err; }
|
if err = clear_if_uninitialized(base); err != .None { return err; }
|
||||||
|
if err = clear_if_uninitialized(dest); err != .None { return err; }
|
||||||
|
/*
|
||||||
|
Early outs.
|
||||||
|
*/
|
||||||
|
if z, _ := is_zero(base); z {
|
||||||
|
/*
|
||||||
|
A zero base is a special case.
|
||||||
|
*/
|
||||||
|
if power < 0 {
|
||||||
|
if err = zero(dest); err != .None { return err; }
|
||||||
|
return .Math_Domain_Error;
|
||||||
|
}
|
||||||
|
if power == 0 { return one(dest); }
|
||||||
|
if power > 0 { return zero(dest); }
|
||||||
|
|
||||||
// if ((err = mp_init_copy(&g, a)) != MP_OKAY) {
|
}
|
||||||
// return err;
|
if power < 0 {
|
||||||
// }
|
/*
|
||||||
|
Fraction, so we'll return zero.
|
||||||
|
*/
|
||||||
|
return zero(dest);
|
||||||
|
}
|
||||||
|
switch(power) {
|
||||||
|
case 0:
|
||||||
|
/*
|
||||||
|
Any base to the power zero is one.
|
||||||
|
*/
|
||||||
|
return one(dest);
|
||||||
|
case 1:
|
||||||
|
/*
|
||||||
|
Any base to the power one is itself.
|
||||||
|
*/
|
||||||
|
return copy(dest, base);
|
||||||
|
case 2:
|
||||||
|
return sqr(dest, base);
|
||||||
|
}
|
||||||
|
|
||||||
// /* set initial result */
|
g := &Int{};
|
||||||
// mp_set(c, 1uL);
|
if err = copy(g, base); err != .None { return err; }
|
||||||
|
|
||||||
// while (b > 0) {
|
/*
|
||||||
// /* if the bit is set multiply */
|
Set initial result.
|
||||||
// if ((b & 1) != 0) {
|
*/
|
||||||
// if ((err = mp_mul(c, &g, c)) != MP_OKAY) {
|
if err = set(dest, 1); err != .None { return err; }
|
||||||
// goto LBL_ERR;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /* square */
|
loop: for power > 0 {
|
||||||
// if (b > 1) {
|
/*
|
||||||
// if ((err = mp_sqr(&g, &g)) != MP_OKAY) {
|
If the bit is set, multiply.
|
||||||
// goto LBL_ERR;
|
*/
|
||||||
// }
|
if power & 1 != 0 {
|
||||||
// }
|
if err = mul(dest, g, dest); err != .None {
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Square.
|
||||||
|
*/
|
||||||
|
if power > 1 {
|
||||||
|
if err = sqr(g, g); err != .None {
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// /* shift to next bit */
|
/* shift to next bit */
|
||||||
// b >>= 1;
|
power >>= 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// LBL_ERR:
|
destroy(g);
|
||||||
// mp_clear(&g);
|
|
||||||
// return err;
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate c = a**b.
|
||||||
|
*/
|
||||||
|
int_pow_int :: proc(dest: ^Int, base, power: int) -> (err: Error) {
|
||||||
|
base_t := &Int{};
|
||||||
|
defer destroy(base_t);
|
||||||
|
|
||||||
pow :: proc { int_pow, };
|
if err = set(base_t, base); err != .None { return err; }
|
||||||
|
|
||||||
|
return int_pow(dest, base_t, power);
|
||||||
|
}
|
||||||
|
|
||||||
|
pow :: proc { int_pow, int_pow_int, };
|
||||||
|
exp :: pow;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns the log2 of an `Int`, provided `base` is a power of two.
|
Returns the log2 of an `Int`, provided `base` is a power of two.
|
||||||
|
|||||||
Reference in New Issue
Block a user