refactor power

This commit is contained in:
Dmitry Vagner 2023-01-24 16:35:49 +07:00
parent 60cbdde879
commit 5deb164865
6 changed files with 276 additions and 306 deletions

View File

@ -110,34 +110,34 @@ pub fn gen_fp12_sparse() -> Fp12 {
sparse_embed(gen_fp(), gen_fp2(), gen_fp2())
}
/// The output T of the miller loop is not an invariant,
/// but one gets an invariant by raising T to the power
/// The output y of the miller loop is not an invariant,
/// but one gets an invariant by raising y to the power
/// (p^12 - 1)/N = (p^6 - 1)(p^2 + 1)(p^4 - p^2 + 1)/N
/// where N is the cyclic group order of the curve.
/// To achieve this, we first exponentiate T by p^6 - 1 via
/// T = T_6 / T
/// To achieve this, we first exponentiate y by p^6 - 1 via
/// y = y_6 / y
/// and then exponentiate the result by p^2 + 1 via
/// T = T_2 * T
/// y = y_2 * y
/// We then note that (p^4 - p^2 + 1)/N can be rewritten as
/// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0
/// where 0 < a0, a1, a2 < p. Then the final power is given by
/// T = T_3 * (T^a2)_2 * (T^-a1)_1 * (T^-a0)
/// y = y_3 * (y^a2)_2 * (y^-a1)_1 * (y^-a0)
pub fn invariance_inducing_power(f: Fp12) -> Fp12 {
let mut t = f.frob(6) / f;
t = t.frob(2) * t;
let (t_a2, t_a1, t_a0) = get_powers(t);
t.frob(3) * t_a2.frob(2) * t_a1.frob(1) * t_a0
let mut y = f.frob(6) / f;
y = y.frob(2) * y;
let (y_a2, y_a1, y_a0) = get_custom_powers(y);
y.frob(3) * y_a2.frob(2) * y_a1.frob(1) * y_a0
}
/// Given an f: Fp12, this function computes
/// T^a2, T^(-a1), T^(-a0)
/// y^a2, y^(-a1), y^(-a0)
/// by first computing
/// T^a4, T^a2, T^a0
/// y^a4, y^a2, y^a0
/// where a1 is given by
/// a1 = a4 + 2a2 - a0
/// thus what remains is inverting T^a0 and returning
/// T^a2, T^a4 * T^a2 * T^a2 * T^(-a0), T^(-a0)
fn get_powers(f: Fp12) -> (Fp12, Fp12, Fp12) {
/// thus what remains is inverting y^a0 and returning
/// y^a2, y^a4 * y^a2 * y^a2 * y^(-a0), y^(-a0)
fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) {
const EXPS4: [(usize, usize, usize); 64] = [
(1, 1, 0),
(1, 1, 1),

View File

@ -27,13 +27,13 @@ pub(crate) fn combined_kernel() -> Kernel {
include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/curve_add.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/curve_mul.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/final_power.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/miller_loop.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/tate_pairing.asm"),
include_str!("asm/curve/bn254/field_arithmetic/inverse.asm"),
include_str!("asm/curve/bn254/field_arithmetic/fp6_mul.asm"),
include_str!("asm/curve/bn254/field_arithmetic/fp12_mul.asm"),
include_str!("asm/curve/bn254/field_arithmetic/frobenius.asm"),
include_str!("asm/curve/bn254/field_arithmetic/power.asm"),
include_str!("asm/curve/bn254/field_arithmetic/util.asm"),
include_str!("asm/curve/common.asm"),
include_str!("asm/curve/secp256k1/curve_mul.asm"),

View File

@ -0,0 +1,229 @@
/// def final_exp(y):
/// y0, y4, y2 = 1, 1, 1
/// power_loop_4()
/// power_loop_2()
/// power_loop_0()
/// custom_powers()
/// final_power()
///
/// def custom_powers()
/// y0 = y0^{-1}
/// y1 = y4 * y2^2 * y0
/// return y2, y1, y0
///
/// def final_power()
/// y = y.frob(3)
/// y2 = y2.frob(2)
/// y1 = y1.frob(1)
/// return y * y2 * y4 * y0
global final_exp:
// stack: val, retdest
%stack () -> (1, 1, 1)
// stack: 1, 1, 1, val, retdest
%mstore_kernel_general(200)
%mstore_kernel_general(224)
%mstore_kernel_general(212)
// stack: val, retdest {200: y0, 212: y2, 224: y4}
stack () -> 64, 62, 65
// stack: 64, 62, 65, val, retdest {200: y0, 212: y2, 224: y4}
%jump(power_loop_4)
custom_powers:
// stack: val, retdest {200: y0, 212: y2, 224: y4}
%stack () -> (200, 236, make_y1_1)
// stack: 200, 236, make_y1_1, val, retdest {200: y0, 212: y2, 224: y4}
%jump(inv_fp12)
make_y1_1:
// stack: val, retdest {236: y0^-1, 212: y2, 224: y4}
%stack () -> (212, 224, 224, make_y1_2)
// stack: 212, 224, 224, make_y1_2, val, retdest {236: y0^-1, 212: y2, 224: y4}
%jump(mul_fp12)
make_y1_2:
// stack: val, retdest {236: y0^-1, 212: y2, 224: y4 * y2}
%stack () -> (212, 224, 224, make_y1_3)
// stack: 212, 224, 224, make_y1_3, val, retdest {236: y0^-1, 212: y2, 224: y4 * y2}
%jump(mul_fp12)
make_y1_3:
// stack: val, retdest {236: y0^-1, 212: y2, 224: y4 * y2^2}
%stack () -> (236, 224, 224, final_power)
// stack: 236, 224, 224, final_power, val, retdest {236: y0^-1, 212: y2, 224: y4 * y2^2}
%jump(mul_fp12)
final_power:
// stack: val, retdest {val: y , 212: y^a2 , 224: y^a1 , 236: y^a0}
%frob_fp12_3
// stack: val, retdest {val: y_3, 212: y^a2 , 224: y^a1 , 236: y^a0}
%stack () -> (212, 212)
%frob_fp12_2_
POP
// stack: val, retdest {val: y_3, 212: (y^a2)_2, 224: y^a1 , 236: y^a0}
PUSH 224
%frob_fp12_1
POP
// stack: val, retdest {val: y_3, 212: (y^a2)_2, 224: (y^a1)_1, 236: y^a0}
%stack (val) -> (212, val, val, penult_mul, val)
// stack: 212, val, val, penult_mul, val, retdest {val: y_3, 212: (y^a2)_2, 224: (y^a1)_1, 236: y^a0}
%jump(mul_fp12)
penult_mul:
// stack: val, retdest {val: y_3 * (y^a2)_2, 224: (y^a1)_1, 236: y^a0}
%stack (val) -> (224, val, val, final_mul, val)
// stack: 224, val, val, final_mul, val, retdest {val: y_3 * (y^a2)_2, 224: (y^a1)_1, 236: y^a0}
%jump(mul_fp12)
final_mul:
// stack: val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 236: y^a0}
%stack (val) -> (236, val, val)
// stack: 236, val, val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 236: y^a0}
%jump(mul_fp12)
/// def power_loop_4():
/// for i in range(64):
/// abc = load(i, power_data_4)
/// if a:
/// y4 *= acc
/// if b:
/// y2 *= acc
/// if c:
/// y0 *= acc
/// acc = square_fp12(acc)
/// y4 *= acc
///
/// def power_loop_2():
/// for i in range(62):
/// ab = load(i, power_data_2)
/// if a:
/// y2 *= acc
/// if b:
/// y0 *= acc
/// acc = square_fp12(acc)
/// y2 *= acc
///
/// def power_loop_0():
/// for i in range(65):
/// a = load(i, power_data_0)
/// if a:
/// y0 *= acc
/// acc = square_fp12(acc)
/// y0 *= acc
power_loop_4:
// stack: i , j, k, val {200: y0, 212: y2, 224: y4}
DUP1 ISZERO
// stack: break?, i , j, k, val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_4_end)
// stack: i , j, k, val {200: y0, 212: y2, 224: y4}
%sub_const(1)
// stack: i-1, j, k, val {200: y0, 212: y2, 224: y4}
DUP1 %mload_kernel_code(power_data_4)
// stack: abc, i-1, j, k, val {200: y0, 212: y2, 224: y4}
DUP1 %lt_const(100)
// stack: skip?, abc, i-1, j, k, val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_4_b)
// stack: abc, i-1, j, k, val {200: y0, 212: y2, 224: y4}
%sub_const(100)
// stack: bc, i-1, j, k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_4_b PUSH 224 DUP1 DUP8
// stack: val, 224, 224, power_loop_4_b, bc, i-1, j, k, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_4_b:
// stack: bc, i, j, k, val {200: y0, 212: y2, 224: y4}
DUP1 %lt_const(10)
// stack: skip?, bc, i, j, k, val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_4_c)
// stack: bc, i, j, k, val {200: y0, 212: y2, 224: y4}
%sub_const(10)
// stack: c, i, j, k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_4_c PUSH 212 DUP1 DUP8
// stack: val, 212, 212, power_loop_4_c, c, i, j, k, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_4_c:
// stack: c, i, j, k, val {200: y0, 212: y2, 224: y4}
ISZERO
// stack: skip?, i, j, k, val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_4_sq)
// stack: i, j, k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_4_sq PUSH 200 DUP1 DUP7
// stack: val, 200, 200, power_loop_4_sq, i, j, k, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_4_sq:
// stack: i, j, k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_4 DUP5 DUP1
// stack: val, val, power_loop_4, i, j, k, val {200: y0, 212: y2, 224: y4}
%jump(square_fp12)
power_loop_4_end:
// stack: 0, j, k, val {200: y0, 212: y2, 224: y4}
POP
// stack: j, k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_2 PUSH 224 DUP1 DUP6
// stack: val, 224, 224, power_loop_2, j, k, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_2:
// stack: j , k, val {200: y0, 212: y2, 224: y4}
DUP1 ISZERO
// stack: break?, j , k, val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_2_end)
// stack: j , k, val {200: y0, 212: y2, 224: y4}
%sub_const(1)
// stack: j-1, k, val {200: y0, 212: y2, 224: y4}
DUP1 %mload_kernel_code(power_data_2)
// stack: ab, j-1, k, val {200: y0, 212: y2, 224: y4}
DUP1 %lt_const(10)
// stack: skip?, ab, j-1, k, val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_2_b)
// stack: ab, j-1, k, val {200: y0, 212: y2, 224: y4}
%sub_const(10)
// stack: b, j-1, k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_2_b PUSH 212 DUP1 DUP7
// stack: val, 212, 212, power_loop_2_b, b, j-1, k, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_2_b:
// stack: b, j, k, val {200: y0, 212: y2, 224: y4}
ISZERO
// stack: skip?, j, k, val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_2_sq)
// stack: j, k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_2_sq PUSH 200 DUP1 DUP6
// stack: val, 200, 200, power_loop_2_sq, j, k, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_2_sq:
// stack: j, k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_2 DUP4 DUP1
// stack: val, val, power_loop_2, j, k, val {200: y0, 212: y2, 224: y4}
%jump(square_fp12)
power_loop_2_end:
// stack: 0, k, val {200: y0, 212: y2, 224: y4}
POP
// stack: k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_0 PUSH 212 DUP1 DUP5
// stack: val, 212, 212, power_loop_0, k, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_0:
// stack: k , val {200: y0, 212: y2, 224: y4}
DUP1 ISZERO
// stack: break?, k , val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_0_end)
// stack: k , val {200: y0, 212: y2, 224: y4}
%sub_const(1)
// stack: k-1, val {200: y0, 212: y2, 224: y4}
DUP1 %mload_kernel_code(power_data_0)
// stack: a, k-1, val {200: y0, 212: y2, 224: y4}
ISZERO
// stack: skip?, k-1, val {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_0_sq)
// stack: k-1, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_0_sq PUSH 200 DUP1 DUP5
// stack: val, 200, 200, power_loop_0_sq, k-1, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_0_sq:
// stack: k, val {200: y0, 212: y2, 224: y4}
PUSH power_loop_0 DUP3 DUP1
// stack: val, val, power_loop_0, k, val {200: y0, 212: y2, 224: y4}
%jump(square_fp12)
power_loop_0_end:
// stack: 0, val {200: y0, 212: y2, 224: y4}
%stack (i, val) -> (200, val, 200, custom_powers, val)
// stack: 200, val, 200, custom_powers, val {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)

View File

@ -25,7 +25,7 @@
/// 0xnm -= 1
/// mul_tangent()
global miller_init:
global miller:
// stack: ptr, out, retdest
PUSH 1
// stack: 1, ptr, out, retdest

View File

@ -1,74 +1,38 @@
/// def tate(P: Curve, Q: TwistedCurve) -> Fp12:
/// out = miller_loop(P, Q)
/// out = out.frob(6) / out
/// out = out.frob(2) * out
/// return final_power(out)
/// return make_invariant(P, Q)
global tate:
// stack: ptr, out, retdest
DUP2
// stack: out, ptr, out, retdest
PUSH post_miller
// stack: post_miller, out, ptr, out, retdest
SWAP2
// stack: ptr, out, post_miller, out, retdest
%jump(miller_init)
global post_miller:
// stack: out, retdest
PUSH tate_mul_1
// stack: tate_mul_1, out, retdest
PUSH 100
// stack: 100, tate_mul_1, out, retdest
DUP3
// stack: out, 100, tate_mul_1, out, retdest
// stack: inp, out, retdest
%stack (inp, out) -> (inp, out, make_invariant, out)
// stack: inp, out, make_invariant, out, retdest
%jump(miller)
/// def make_invariant(y: Fp12):
/// y = first_exp(y)
/// y = second_exp(y)
/// return final_exponentiation(y)
global make_invariant:
/// def first_exp(t):
/// return t.frob(6) / t
// stack: out, retdest {out: y}
%stack (out) -> (out, 100, first_exp, out)
// stack: out, 100, first_exp, out, retdest {out: y}
%jump(inv_fp12)
tate_mul_1:
// stack: out, retdest {100: inv}
global first_exp:
// stack: out, retdest {out: y , 100: y^-1}
%frob_fp12_6
// stack: out, retdest {100: inv}
PUSH tate_mul_2
// stack: tate_mul_2, out, retdest {100: inv}
DUP2
// stack: out, tate_mul_2, out, retdest {100: inv}
PUSH 100
// stack: 100, out, tate_mul_2, out, retdest {100: inv}
DUP2
// stack: out, 100, out, tate_mul_2, out, retdest {100: inv}
// stack: out, retdest {out: y_6, 100: y^-1}
%stack (out) -> (out, 100, out, second_exp, out)
// stack: out, 100, out, second_exp, out, retdest {out: y_6, 100: y^-1}
%jump(mul_fp12)
tate_mul_2:
// stack: out, retdest {100: inv}
PUSH tate_power
// stack: tate_power, out, retdest {100: inv}
DUP2
// stack: out, tate_power, out, retdest {100: inv}
PUSH 100
// stack: 100, out, tate_power, out, retdest {100: inv}
DUP2
// stack: out, 100, out, tate_power, out, retdest {100: inv}
/// def second_exp(t):
/// return t.frob(2) * t
global second_exp:
// stack: out, retdest {out: y}
%stack (out) -> (out, 100, out, final_exp, out)
// stack: out, 100, out, final_exp, out, retdest {out: y}
%frob_fp12_2_
// stack: 100, out, tate_power, out, retdest {100: acc}
DUP2
// stack: out, 100, out, tate_power, out, retdest {100: acc}
%jump(mul_fp12)
tate_power:
// stack: out, retdest {100: acc}
PUSH tate_return
// stack: tate_return, out, retdest {100: acc}
PUSH 100
// stack: 100, tate_return, out, retdest {100: acc}
PUSH 300
// stack: 300, 100, tate_return, out, retdest {100: acc}
DUP4
// stack: out, 300, 100, tate_return, out, retdest {100: acc}
%move_fp12
// stack: 300, 100, tate_return, out, retdest {100: acc, 300: out}
%jump(power)
tate_return:
// stack: out, retdest {100: pow}
PUSH 100
// stack: 100, out, retdest {100: pow}
DUP2
// stack: out, 100, out, retdest {100: pow}
%frob_fp12_3
// stack: out, 100, out, retdest {100: pow}
// stack: 100, out, final_exp, out, retdest {out: y, 100: y_2}
%jump(mul_fp12)

View File

@ -1,223 +0,0 @@
/// def invariance_inducing_power(acc):
/// power_init()
/// power_loop_4()
/// power_loop_2()
/// power_loop_0()
/// power_return()
///
/// def power_init()
/// y0, y4, y2 = 1, 1, 1
///
/// def power_return()
/// y0 = y0^{-1}
/// y4 *= y0 * (y2**2)
/// y4 = frob_fp12_1(y4)
/// y2 = frob_fp12_2_(y2)
/// return y2 * y4 * y0
global power:
// stack: ptr, out, retdest
PUSH 1 DUP1 DUP1
// stack: 1, 1, 1, ptr, out, retdest
%mstore_kernel_general(200) %mstore_kernel_general(224) %mstore_kernel_general(212)
// stack: ptr, out, retdest {200: y0, 212: y2, 224: y4}
PUSH 65 PUSH 62 PUSH 64
// stack: 64, 62, 65, ptr, out, retdest {200: y0, 212: y2, 224: y4}
%jump(power_loop_4)
power_return:
// stack: out, retdest {200: y0, 212: y2, 224: y4}
PUSH power_return_1 PUSH 236 PUSH 200
// stack: 200, 236, power_return_1, out, retdest {200: y0, 212: y2, 224: y4}
%jump(inv_fp12)
power_return_1:
// stack: out, retdest {236: y0, 212: y2, 224: y4}
PUSH power_return_2 PUSH 224 DUP1 PUSH 212
// stack: 212, 224, 224, power_return_2, out, retdest {236: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_return_2:
// stack: out, retdest {236: y0, 212: y2, 224: y4}
PUSH power_return_3 PUSH 224 DUP1 PUSH 212
// stack: 212, 224, 224, power_return_3, out, retdest {236: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_return_3:
// stack: out, retdest {236: y0, 212: y2, 224: y4}
PUSH power_return_4 PUSH 224 DUP1 PUSH 236
// stack: 236, 224, 224, power_return_4, out, retdest {236: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_return_4:
// stack: out, retdest {236: y0, 212: y2, 224: y4}
PUSH 224
// stack: 224, out, retdest {236: y0, 212: y2, 224: y4}
%frob_fp12_1
// stack: 224, out, retdest {236: y0, 212: y2, 224: y4}
POP
// stack: out, retdest {236: y0, 212: y2, 224: y4}
PUSH 212 DUP1
// stack: 212, 212, out, retdest {236: y0, 212: y2, 224: y4}
%frob_fp12_2_
// stack: 212, out, retdest {236: y0, 212: y2, 224: y4}
POP
// stack: out, retdest {236: y0, 212: y2, 224: y4}
PUSH power_return_5 DUP2 PUSH 236 PUSH 224
// stack: 224, 236, out, power_return_5, out, retdest {236: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_return_5:
// stack: out, retdest {236: y0, 212: y2, 224: y4}
PUSH 212 DUP2
// stack: out, 212, out, retdest {236: y0, 212: y2, 224: y4}
%jump(mul_fp12)
/// def power_loop_4():
/// for i in range(64):
/// abc = load(i, power_data_4)
/// if a:
/// y4 *= acc
/// if b:
/// y2 *= acc
/// if c:
/// y0 *= acc
/// acc = square_fp12(acc)
/// y4 *= acc
///
/// def power_loop_2():
/// for i in range(62):
/// ab = load(i, power_data_2)
/// if a:
/// y2 *= acc
/// if b:
/// y0 *= acc
/// acc = square_fp12(acc)
/// y2 *= acc
///
/// def power_loop_0():
/// for i in range(65):
/// a = load(i, power_data_0)
/// if a:
/// y0 *= acc
/// acc = square_fp12(acc)
/// y0 *= acc
power_loop_4:
// stack: i , j, k, ptr {200: y0, 212: y2, 224: y4}
DUP1 ISZERO
// stack: break?, i , j, k, ptr {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_4_end)
// stack: i , j, k, ptr {200: y0, 212: y2, 224: y4}
%sub_const(1)
// stack: i-1, j, k, ptr {200: y0, 212: y2, 224: y4}
DUP1 %mload_kernel_code(power_data_4)
// stack: abc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4}
DUP1 %lt_const(100)
// stack: skip?, abc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_4_b)
// stack: abc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4}
%sub_const(100)
// stack: bc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_4_b PUSH 224 DUP1 DUP8
// stack: ptr, 224, 224, power_loop_4_b, bc, i-1, j, k, ptr {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_4_b:
// stack: bc, i, j, k, ptr {200: y0, 212: y2, 224: y4}
DUP1 %lt_const(10)
// stack: skip?, bc, i, j, k, ptr {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_4_c)
// stack: bc, i, j, k, ptr {200: y0, 212: y2, 224: y4}
%sub_const(10)
// stack: c, i, j, k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_4_c PUSH 212 DUP1 DUP8
// stack: ptr, 212, 212, power_loop_4_c, c, i, j, k, ptr {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_4_c:
// stack: c, i, j, k, ptr {200: y0, 212: y2, 224: y4}
ISZERO
// stack: skip?, i, j, k, ptr {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_4_sq)
// stack: i, j, k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_4_sq PUSH 200 DUP1 DUP7
// stack: ptr, 200, 200, power_loop_4_sq, i, j, k, ptr {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_4_sq:
// stack: i, j, k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_4 DUP5 DUP1
// stack: ptr, ptr, power_loop_4, i, j, k, ptr {200: y0, 212: y2, 224: y4}
%jump(square_fp12)
power_loop_4_end:
// stack: 0, j, k, ptr {200: y0, 212: y2, 224: y4}
POP
// stack: j, k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_2 PUSH 224 DUP1 DUP6
// stack: ptr, 224, 224, power_loop_2, j, k, ptr {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_2:
// stack: j , k, ptr {200: y0, 212: y2, 224: y4}
DUP1 ISZERO
// stack: break?, j , k, ptr {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_2_end)
// stack: j , k, ptr {200: y0, 212: y2, 224: y4}
%sub_const(1)
// stack: j-1, k, ptr {200: y0, 212: y2, 224: y4}
DUP1 %mload_kernel_code(power_data_2)
// stack: ab, j-1, k, ptr {200: y0, 212: y2, 224: y4}
DUP1 %lt_const(10)
// stack: skip?, ab, j-1, k, ptr {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_2_b)
// stack: ab, j-1, k, ptr {200: y0, 212: y2, 224: y4}
%sub_const(10)
// stack: b, j-1, k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_2_b PUSH 212 DUP1 DUP7
// stack: ptr, 212, 212, power_loop_2_b, b, j-1, k, ptr {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_2_b:
// stack: b, j, k, ptr {200: y0, 212: y2, 224: y4}
ISZERO
// stack: skip?, j, k, ptr {200: y0, 212: y2, 224: y4}
%jumpi(power_loop_2_sq)
// stack: j, k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_2_sq PUSH 200 DUP1 DUP6
// stack: ptr, 200, 200, power_loop_2_sq, j, k, ptr {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_2_sq:
// stack: j, k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_2 DUP4 DUP1
// stack: ptr, ptr, power_loop_2, j, k, ptr {200: y0, 212: y2, 224: y4}
%jump(square_fp12)
power_loop_2_end:
// stack: 0, k, ptr {200: y0, 212: y2, 224: y4}
POP
// stack: k, ptr {200: y0, 212: y2, 224: y4}
PUSH power_loop_0 PUSH 212 DUP1 DUP5
// stack: ptr, 212, 212, power_loop_0, k, ptr {200: y0, 212: y2, 224: y4}
%jump(mul_fp12)
power_loop_0:
// stack: k , ptr
DUP1 ISZERO
// stack: break?, k , ptr
%jumpi(power_loop_0_end)
// stack: k , ptr
%sub_const(1)
// stack: k-1, ptr
DUP1 %mload_kernel_code(power_data_0)
// stack: a, k-1, ptr
ISZERO
// stack: skip?, k-1, ptr
%jumpi(power_loop_0_sq)
// stack: k-1, ptr
PUSH power_loop_0_sq PUSH 200 DUP1 DUP5
// stack: ptr, 200, 200, power_loop_0_sq, k-1, ptr
%jump(mul_fp12)
power_loop_0_sq:
// stack: k, ptr
PUSH power_loop_0 DUP3 DUP1
// stack: ptr, ptr, power_loop_0, k, ptr
%jump(square_fp12)
power_loop_0_end:
// stack: 0, ptr
POP
// stack: ptr
PUSH 200 PUSH power_return SWAP2 DUP2
// stack: 200, ptr, 200, power_return
%jump(mul_fp12)