diff --git a/pkg/test/assembly_bench_test.go b/pkg/test/assembly_bench_test.go index 9703d9f61..cff95f0d2 100644 --- a/pkg/test/assembly_bench_test.go +++ b/pkg/test/assembly_bench_test.go @@ -38,6 +38,10 @@ func Test_AsmBench_Shf(t *testing.T) { util.CheckWithFields(t, false, "asm/bench/shf", util.ASM_MAX_PADDING, field.BLS12_377, field.KOALABEAR_16) } +func Test_AsmBench_Mod(t *testing.T) { + util.CheckWithFields(t, false, "asm/bench/mod", util.ASM_MAX_PADDING, field.BLS12_377, field.KOALABEAR_16) +} + func Test_AsmBench_Stp(t *testing.T) { util.CheckWithFields(t, false, "asm/bench/stp", util.ASM_MAX_PADDING, field.BLS12_377, field.KOALABEAR_16) } diff --git a/testdata/asm/bench/mod.accepts b/testdata/asm/bench/mod.accepts new file mode 100644 index 000000000..7784fce55 --- /dev/null +++ b/testdata/asm/bench/mod.accepts @@ -0,0 +1,150 @@ +{"mod": {"ARG_1":[0],"ARG_2":[0],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[0],"INST":[5],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[0],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[0],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1000000000000000000000000000],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1000000000000000000000000000],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[100000000000000000000000],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1000000],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[10000],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[100089000],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[10027337093055173198],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[100500000],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[100600000],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1063722548954841694],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1074787952766011976],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[10],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[10],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[115792089237316195423570985008687907853269984665640564039457584007913129639935],"INST":[5],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[120],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1223011452902],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1251942489728280893],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1461501637330902918203684832716283019655932542976],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[14889399780889809609408117],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[14982633751816419],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[15],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[16777216],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[16],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[18446744073709551616],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[192],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[1],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[200000000],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[228127113569201868],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[24],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[256],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[256],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[281474976710656],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[2],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[2],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[309485009821345068724781056],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[3281043104505],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[340282366920938463463374607431768211456],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[3],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[40320],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[410127816544206508],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[4294967296],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[455843288657269650],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[45],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[4722366482869645213696],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[47917192688627071376575381163212800],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[4],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[501387261813357055],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[50207077772073100170],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[5040],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[50],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[51069121924991624173],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[576529869730161187],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[63718288891407589],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[6],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[720],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[725984524129222612],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[7592553942],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[79228162514264337593543950336],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[796496997120250491389740],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[8191],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[849304507514456856026894],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[86400361979650954],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[8],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[8],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[9070771949],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[9104278865539931101],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[0],"ARG_2":[997668518092716560],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[99],"ARG_2":[32],"INST":[4],"RES":[3]}} +{"mod": {"ARG_1":[9],"ARG_2":[32],"INST":[4],"RES":[0]}} +{"mod": {"ARG_1":[775580],"ARG_2":[4],"INST":[5],"RES":[193895]}} +{"mod": {"ARG_1":[775724],"ARG_2":[4],"INST":[5],"RES":[193931]}} +{"mod": {"ARG_1":[775796],"ARG_2":[4],"INST":[5],"RES":[193949]}} +{"mod": {"ARG_1":[8143506],"ARG_2":[42],"INST":[5],"RES":[193893]}} +{"mod": {"ARG_1":[8388607],"ARG_2":[1],"INST":[5],"RES":[8388607]}} +{"mod": {"ARG_1":[8388607],"ARG_2":[50],"INST":[5],"RES":[167772]}} +{"mod": {"ARG_1":[8388607],"ARG_2":[60],"INST":[5],"RES":[139810]}} +{"mod": {"ARG_1":[9565736],"ARG_2":[256],"INST":[6],"RES":[40]}} +{"mod": {"ARG_1":[9600],"ARG_2":[160],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[960],"ARG_2":[160],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[960],"ARG_2":[192],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[9647952],"ARG_2":[256],"INST":[6],"RES":[80]}} +{"mod": {"ARG_1":[9657512],"ARG_2":[256],"INST":[6],"RES":[168]}} +{"mod": {"ARG_1":[96],"ARG_2":[8],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[9760],"ARG_2":[160],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[9792],"ARG_2":[288],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[9920],"ARG_2":[160],"INST":[6],"RES":[0]}} +{"mod": {"ARG_1":[318715],"ARG_2":[256],"INST":[7],"RES":[251]}} +{"mod": {"ARG_1":[318815],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[318815],"ARG_2":[256],"INST":[7],"RES":[95]}} +{"mod": {"ARG_1":[318915],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[318915],"ARG_2":[256],"INST":[7],"RES":[195]}} +{"mod": {"ARG_1":[319015],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319015],"ARG_2":[256],"INST":[7],"RES":[39]}} +{"mod": {"ARG_1":[319115],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319115],"ARG_2":[256],"INST":[7],"RES":[139]}} +{"mod": {"ARG_1":[319215],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319215],"ARG_2":[256],"INST":[7],"RES":[239]}} +{"mod": {"ARG_1":[319315],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319315],"ARG_2":[256],"INST":[7],"RES":[83]}} +{"mod": {"ARG_1":[319415],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319415],"ARG_2":[256],"INST":[7],"RES":[183]}} +{"mod": {"ARG_1":[319515],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319515],"ARG_2":[256],"INST":[7],"RES":[27]}} +{"mod": {"ARG_1":[319615],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319615],"ARG_2":[256],"INST":[7],"RES":[127]}} +{"mod": {"ARG_1":[31964],"ARG_2":[256],"INST":[7],"RES":[220]}} +{"mod": {"ARG_1":[31965],"ARG_2":[256],"INST":[7],"RES":[221]}} +{"mod": {"ARG_1":[31966],"ARG_2":[256],"INST":[7],"RES":[222]}} +{"mod": {"ARG_1":[319715],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319715],"ARG_2":[256],"INST":[7],"RES":[227]}} +{"mod": {"ARG_1":[31972],"ARG_2":[256],"INST":[7],"RES":[228]}} +{"mod": {"ARG_1":[319767],"ARG_2":[256],"INST":[7],"RES":[23]}} +{"mod": {"ARG_1":[319769],"ARG_2":[256],"INST":[7],"RES":[25]}} +{"mod": {"ARG_1":[319771],"ARG_2":[256],"INST":[7],"RES":[27]}} +{"mod": {"ARG_1":[319780],"ARG_2":[256],"INST":[7],"RES":[36]}} +{"mod": {"ARG_1":[319815],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319815],"ARG_2":[256],"INST":[7],"RES":[71]}} +{"mod": {"ARG_1":[319816],"ARG_2":[256],"INST":[7],"RES":[72]}} +{"mod": {"ARG_1":[319850],"ARG_2":[50],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319859],"ARG_2":[256],"INST":[7],"RES":[115]}} +{"mod": {"ARG_1":[319915],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[319915],"ARG_2":[256],"INST":[7],"RES":[171]}} +{"mod": {"ARG_1":[3231],"ARG_2":[256],"INST":[7],"RES":[159]}} +{"mod": {"ARG_1":[3232],"ARG_2":[256],"INST":[7],"RES":[160]}} +{"mod": {"ARG_1":[3867],"ARG_2":[256],"INST":[7],"RES":[27]}} +{"mod": {"ARG_1":[3876],"ARG_2":[256],"INST":[7],"RES":[36]}} +{"mod": {"ARG_1":[38778],"ARG_2":[256],"INST":[7],"RES":[122]}} +{"mod": {"ARG_1":[38779],"ARG_2":[256],"INST":[7],"RES":[123]}} +{"mod": {"ARG_1":[3877],"ARG_2":[256],"INST":[7],"RES":[37]}} +{"mod": {"ARG_1":[38781],"ARG_2":[256],"INST":[7],"RES":[125]}} +{"mod": {"ARG_1":[3878],"ARG_2":[256],"INST":[7],"RES":[38]}} +{"mod": {"ARG_1":[3879],"ARG_2":[256],"INST":[7],"RES":[39]}} +{"mod": {"ARG_1":[3880],"ARG_2":[256],"INST":[7],"RES":[40]}} +{"mod": {"ARG_1":[3],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[3],"ARG_2":[256],"INST":[7],"RES":[3]}} +{"mod": {"ARG_1":[3],"ARG_2":[2],"INST":[7],"RES":[1]}} +{"mod": {"ARG_1":[3],"ARG_2":[3],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[3],"ARG_2":[4],"INST":[7],"RES":[3]}} +{"mod": {"ARG_1":[4],"ARG_2":[1],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[4],"ARG_2":[2],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[4],"ARG_2":[3],"INST":[7],"RES":[1]}} +{"mod": {"ARG_1":[4],"ARG_2":[4],"INST":[7],"RES":[0]}} +{"mod": {"ARG_1":[581],"ARG_2":[256],"INST":[7],"RES":[69]}} +{"mod": {"ARG_1":[582],"ARG_2":[256],"INST":[7],"RES":[70]}} +{"mod": {"ARG_1":[6396],"ARG_2":[256],"INST":[7],"RES":[252]}} +{"mod": {"ARG_1":[6397],"ARG_2":[256],"INST":[7],"RES":[253]}} diff --git a/testdata/asm/bench/mod.all.bz2 b/testdata/asm/bench/mod.all.bz2 new file mode 100644 index 000000000..be70172d1 Binary files /dev/null and b/testdata/asm/bench/mod.all.bz2 differ diff --git a/testdata/asm/bench/mod.zkasm b/testdata/asm/bench/mod.zkasm new file mode 100644 index 000000000..478d14d05 --- /dev/null +++ b/testdata/asm/bench/mod.zkasm @@ -0,0 +1,104 @@ +include "evm.zkasm" +include "../util/bit_xoan.zkasm" + +fn mod(INST=0x4 u8, ARG_1 u256, ARG_2=1 u256) -> (RES u256) { + var tmp u256 + ;; + if INST==EVM_INST_DIV goto div + if INST==EVM_INST_MOD goto mod + if INST==EVM_INST_SDIV goto sdiv + if INST==EVM_INST_SMOD goto smod + fail +div: + RES, tmp = divide(ARG_1, ARG_2) + return +mod: + tmp, RES = divide(ARG_1, ARG_2) + return +sdiv: + RES, tmp = signed_divide(ARG_1, ARG_2) + return +smod: + RES, tmp = signed_divide(ARG_1, ARG_2) + return +} + +fn signed_divide(num u256, den=1 u256) -> (quot u256, rem u256) { + var num_s, den_s u1 + var abs_num, abs_den u256 + var abs_quot, abs_rem u256 + ;; + abs_num, num_s = abs(num) + abs_den, den_s = abs(num) + ;; unsigned division + abs_quot,abs_rem = divide(abs_num,abs_den) + ;; decide if output positive or negative + if num_s != den_s goto negative + ;; positive result + quot = abs_quot + rem = abs_rem + return + ;; +negative: + ;; negative result + quot = negate(abs_quot) + rem = negate(abs_rem) + return +} + +;; Compute the absolute value of a u256 word assuming twos complement +;; notation. +fn abs(val u256) -> (abs_val u256, signed u1) { + var tmp u255 + ;; + signed, tmp = val + ;; check if val < 0 + if signed != 0 goto negative + ;; positive case + abs_val = val + return + ;; negative case +negative: + abs_val = negate(val) + return +} + +;; Determine the two's complement negation of a given value. This is +;; done following the standard recipe of inverting all bits and then +;; adding one. +fn negate(val u256) -> (neg_val u256) { + var inv_val u256 + var c u1 + ;; invert then add one + inv_val = bit_xoan_u256(BIT_NOT,val,0) + ;; + c,neg_val = inv_val + 1 + return +} + +;; TEMPORARY HACK. This cannot be used as it is seriously expensive. +;; For now, it is being used as temporary scafolding in order to write +;; the remainder of this module. +fn divide(num u256, den=1 u256) -> (quot u256, rem u256) { + var b, c u1 + var tmp1, tmp2 u256 + ;; handle division by 0 + if den == 0 goto exit_0 + ;; check num < den + b,tmp1 = num - den + if b != 0 goto base_case + ;; + tmp2, rem = divide(tmp1, den) + ;; assert c == 0 + c,quot = tmp2 + 1 + ;; + return +base_case: + quot = 0 + rem = num + return +exit_0: + quot = 0 + rem = 0 + return +}