Skip to content
This repository has been archived by the owner on Jan 9, 2025. It is now read-only.

Commit

Permalink
feat: fast_exp
Browse files Browse the repository at this point in the history
  • Loading branch information
Eikix committed Nov 14, 2023
1 parent b3b353b commit 20ea59b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 15 deletions.
7 changes: 4 additions & 3 deletions src/kakarot/instructions/stop_and_math_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ from kakarot.model import model
from kakarot.execution_context import ExecutionContext
from kakarot.stack import Stack
from kakarot.errors import Errors
from utils.uint256 import uint256_exp
from utils.uint256 import uint256_fast_exp

// @title Stop and Math operations opcodes.
// @notice Math operations gathers Arithmetic and Comparison operations
Expand Down Expand Up @@ -241,10 +241,11 @@ namespace StopAndMathOperations {
EXP:
let range_check_ptr = [ap - 2];
let popped = cast([ap - 1], Uint256*);
tempvar bitwise_ptr = cast([fp - 4], BitwiseBuiltin*);

let result = uint256_exp(popped[0], popped[1]);
let result = uint256_fast_exp(popped[0], popped[1]);

tempvar bitwise_ptr = cast([fp - 4], BitwiseBuiltin*);
tempvar bitwise_ptr = bitwise_ptr;
tempvar range_check_ptr = range_check_ptr;
tempvar result = Uint256(result.low, result.high);
jmp end;
Expand Down
62 changes: 50 additions & 12 deletions src/utils/uint256.cairo
Original file line number Diff line number Diff line change
@@ -1,21 +1,59 @@
from starkware.cairo.common.uint256 import Uint256, uint256_eq, uint256_le, uint256_sub, uint256_mul
from starkware.cairo.common.uint256 import Uint256, uint256_eq, uint256_le, uint256_sub, uint256_mul, uint256_unsigned_div_rem, uint256_and
from starkware.cairo.common.bool import FALSE
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin

// @notice Internal exponentiation of two 256-bit integers.
// @dev The result is modulo 2^256.
// @param a The base.
// @param b The exponent.
// @param value - The base.
// @param exponent - The exponent.
// @return The result of the exponentiation.
func uint256_exp{range_check_ptr}(a: Uint256, b: Uint256) -> Uint256 {
let one_uint = Uint256(1, 0);
let zero_uint = Uint256(0, 0);
func uint256_exp{range_check_ptr}(value: Uint256, exponent: Uint256) -> Uint256 {
let one = Uint256(1, 0);
let zero = Uint256(0, 0);

let (is_b_zero) = uint256_eq(b, zero_uint);
if (is_b_zero != FALSE) {
return one_uint;
let (exponent_is_zero) = uint256_eq(exponent, zero);
if (exponent_is_zero != FALSE) {
return one;
}
let (b_minus_one) = uint256_sub(b, one_uint);
let pow = uint256_exp(a, b_minus_one);
let (res, _) = uint256_mul(a, pow);
let (exponent_minus_one) = uint256_sub(exponent, one);
let pow = uint256_exp(value, exponent_minus_one);
let (res, _) = uint256_mul(value, pow);
return res;
}

// @notice Internal fast exponentiation of two 256-bit integers.
// @dev The result is modulo 2^256.
// @param value - The base.
// @param exponent - The exponent.
// @return The result of the exponentiation.
func uint256_fast_exp{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(value: Uint256, exponent: Uint256) -> Uint256 {
alloc_locals;

let one = Uint256(1, 0);
let zero = Uint256(0, 0);

let (exponent_is_zero) = uint256_eq(exponent, zero);
if (exponent_is_zero != FALSE) {
return one;
}

let (exponent_is_one) = uint256_eq(exponent, one);
if (exponent_is_one != FALSE) {
return value;
}

let (exponent_is_odd) = uint256_and(exponent, one);
if (exponent_is_odd.low != FALSE) {
let (exponent_minus_one) = uint256_sub(exponent, one);
let (half_exponent, _) = uint256_unsigned_div_rem(exponent_minus_one, Uint256(2, 0));
let pow = uint256_fast_exp(value, half_exponent);
let (res, _) = uint256_mul(pow, pow);
let (res, _) = uint256_mul(res, value);
return res;
} else {
let (half_exponent, _) = uint256_unsigned_div_rem(exponent, Uint256(2, 0));
let pow = uint256_fast_exp(value, half_exponent);
let (res, _) = uint256_mul(pow, pow);
return res;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ class TestMathOperations:
(Opcodes.MULMOD, [3, 2, 2], (3 * 2) % 2),
(Opcodes.EXP, [3, 2], (3**2)),
(Opcodes.EXP, [3, 1], (3**1)),
(Opcodes.EXP, [3, 0], (3**0)),
(
Opcodes.EXP,
[0xff, 0x11],
(0xff**0x11),
),
(Opcodes.SIGNEXTEND, [3, 2, 1], 2),
(Opcodes.LT, [2, 1], 0),
(Opcodes.LT, [1, 2], 1),
Expand Down

0 comments on commit 20ea59b

Please sign in to comment.