diff --git a/benchmark/src/test/scala/com/wavesplatform/lang/v1/BigIntOpsBenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/lang/v1/BigIntOpsBenchmark.scala new file mode 100644 index 00000000000..0ae875124dc --- /dev/null +++ b/benchmark/src/test/scala/com/wavesplatform/lang/v1/BigIntOpsBenchmark.scala @@ -0,0 +1,437 @@ +package com.wavesplatform.lang.v1 + +import com.wavesplatform.common.state.ByteStr +import com.wavesplatform.common.utils.EitherExt2 +import com.wavesplatform.lang.Common +import com.wavesplatform.lang.directives.DirectiveSet +import com.wavesplatform.lang.directives.values.{Account, Expression, StdLibVersion} +import com.wavesplatform.lang.utils.lazyContexts +import com.wavesplatform.lang.v1.FunctionHeader.Native +import com.wavesplatform.lang.v1.compiler.Terms.{ARR, CONST_BIGINT, CONST_BYTESTR, CONST_LONG, CONST_STRING, FUNCTION_CALL} +import com.wavesplatform.lang.v1.evaluator.FunctionIds.{ + BIGINT_TO_BYTES, + BYTES_TO_BIGINT, + BYTES_TO_BIGINT_LIM, + DIV_BIGINT, + FRACTION_BIGINT, + FRACTION_BIGINT_ROUNDS, + GE_BIGINT, + GT_BIGINT, + MAX_LIST_BIGINT, + MEDIAN_LISTBIGINT, + MIN_LIST_BIGINT, + MOD_BIGINT, + MUL_BIGINT, + STRING_TO_BIGINT, + STRING_TO_BIGINTOPT, + SUB_BIGINT, + SUM_BIGINT, + UMINUS_BIGINT +} +import com.wavesplatform.lang.v1.evaluator.ctx.impl.{PureContext, Rounding} +import org.openjdk.jmh.annotations.* +import org.openjdk.jmh.infra.Blackhole + +import java.util.concurrent.TimeUnit + +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@BenchmarkMode(Array(Mode.AverageTime)) +@Threads(1) +@Fork(1) +@Warmup(iterations = 10, time = 1) +@Measurement(iterations = 10, time = 1) +class BigIntOpsBenchmark { + @Benchmark + def sum1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.sumExpr1)) + + @Benchmark + def sum2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.sumExpr2)) + + @Benchmark + def sum3(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.sumExpr3)) + + @Benchmark + def sum4(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.sumExpr4)) + + @Benchmark + def sub1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.subExpr1)) + + @Benchmark + def sub2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.subExpr2)) + + @Benchmark + def sub3(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.subExpr3)) + + @Benchmark + def sub4(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.subExpr4)) + + @Benchmark + def mul1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.mulExpr1)) + + @Benchmark + def mul2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.mulExpr2)) + + @Benchmark + def mul3(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.mulExpr3)) + + @Benchmark + def div1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.divExpr1)) + + @Benchmark + def div2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.divExpr2)) + + @Benchmark + def div3(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.divExpr3)) + + @Benchmark + def mod1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.modExpr1)) + + @Benchmark + def mod2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.modExpr2)) + + @Benchmark + def mod3(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.modExpr3)) + + @Benchmark + def mod4(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.modExpr4)) + + @Benchmark + def fraction1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.fractionExpr1)) + + @Benchmark + def fraction2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.fractionExpr2)) + + @Benchmark + def fraction3(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.fractionExpr3)) + + @Benchmark + def fraction1Round(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.fractionRoundExpr1)) + + @Benchmark + def fraction2Round(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.fractionRoundExpr2)) + + @Benchmark + def fraction3Round(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.fractionRoundExpr3)) + + @Benchmark + def uminus1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.uminusExpr1)) + + @Benchmark + def uminus2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.uminusExpr2)) + + @Benchmark + def ge1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.geExpr1)) + + @Benchmark + def ge2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.geExpr2)) + + @Benchmark + def ge3(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.geExpr3)) + + @Benchmark + def gt1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.gtExpr1)) + + @Benchmark + def gt2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.gtExpr2)) + + @Benchmark + def gt3(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.gtExpr3)) + + @Benchmark + def listMin1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.listMinExpr1)) + + @Benchmark + def listMin2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.listMinExpr2)) + + @Benchmark + def listMax1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.listMaxExpr1)) + + @Benchmark + def listMax2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.listMaxExpr2)) + + @Benchmark + def medianList(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.medianListExpr)) + + @Benchmark + def bigIntToBytes1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.bigIntToBytes1)) + + @Benchmark + def bigIntToBytes2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.bigIntToBytes2)) + + @Benchmark + def bytesToBigInt1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.bytesToBigIntExpr1)) + + @Benchmark + def bytesToBigInt2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.bytesToBigIntExpr2)) + + @Benchmark + def bytesToBigIntLim1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.bytesToBigIntLimExpr1)) + + @Benchmark + def bytesToBigIntLim2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.bytesToBigIntLimExpr2)) + + @Benchmark + def stringToBigInt1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.stringToBigIntExpr1)) + + @Benchmark + def stringToBigInt2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.stringToBigIntExpr2)) + + @Benchmark + def stringToBigIntOpt1(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.stringToBigIntOptExpr1)) + + @Benchmark + def stringToBigIntOpt2(bh: Blackhole, s: BigIntOpsSt): Unit = bh.consume(eval(s.ctx, s.stringToBigIntOptExpr2)) +} + +@State(Scope.Benchmark) +class BigIntOpsSt { + val ds = DirectiveSet(StdLibVersion.VersionDic.all.max, Account, Expression).fold(null, identity) + val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment()) + + val max = CONST_BIGINT(PureContext.BigIntMax) + val prevMax = CONST_BIGINT(PureContext.BigIntMax - 1) + val halfMax = CONST_BIGINT(PureContext.BigIntMax / 2) + val halfMin = CONST_BIGINT(PureContext.BigIntMin / 2) + val min = CONST_BIGINT(PureContext.BigIntMin) + val maxSqrt = CONST_BIGINT(BigInt("57896044618658097711785492504343953926634992332820282019728792003956564819968")) + val three = CONST_BIGINT(3) + val two = CONST_BIGINT(2) + val list = ARR((PureContext.BigIntMin to PureContext.BigIntMin + PureContext.MaxListLengthV4 - 1).map(CONST_BIGINT), limited = true).explicitGet() + val listReversed = ARR(list.xs.reverse, limited = true).explicitGet() + val maxBytes = PureContext.BigIntMax.toByteArray + + val sumExpr1 = FUNCTION_CALL( + Native(SUM_BIGINT), + List(halfMax, halfMax) + ) + + val sumExpr2 = FUNCTION_CALL( + Native(SUM_BIGINT), + List(halfMin, halfMin) + ) + + val sumExpr3 = FUNCTION_CALL( + Native(SUM_BIGINT), + List(halfMin, halfMax) + ) + + val sumExpr4 = FUNCTION_CALL( + Native(SUM_BIGINT), + List(halfMax, three) + ) + + val subExpr1 = FUNCTION_CALL( + Native(SUB_BIGINT), + List(halfMax, halfMin) + ) + + val subExpr2 = FUNCTION_CALL( + Native(SUB_BIGINT), + List(halfMin, halfMin) + ) + + val subExpr3 = FUNCTION_CALL( + Native(SUB_BIGINT), + List(halfMax, halfMax) + ) + + val subExpr4 = FUNCTION_CALL( + Native(SUB_BIGINT), + List(halfMax, three) + ) + + val mulExpr1 = FUNCTION_CALL( + Native(MUL_BIGINT), + List(maxSqrt, three) + ) + + val mulExpr2 = FUNCTION_CALL( + Native(MUL_BIGINT), + List(maxSqrt, maxSqrt) + ) + + val mulExpr3 = FUNCTION_CALL( + Native(MUL_BIGINT), + List(halfMin, two) + ) + + val divExpr1 = FUNCTION_CALL( + Native(DIV_BIGINT), + List(max, three) + ) + + val divExpr2 = FUNCTION_CALL( + Native(DIV_BIGINT), + List(max, max) + ) + + val divExpr3 = FUNCTION_CALL( + Native(DIV_BIGINT), + List(min, three) + ) + + val modExpr1 = FUNCTION_CALL( + Native(MOD_BIGINT), + List(max, three) + ) + + val modExpr2 = FUNCTION_CALL( + Native(MOD_BIGINT), + List(max, max) + ) + + val modExpr3 = FUNCTION_CALL( + Native(MOD_BIGINT), + List(min, three) + ) + + val modExpr4 = FUNCTION_CALL( + Native(MOD_BIGINT), + List(prevMax, max) + ) + + val fractionExpr1 = FUNCTION_CALL( + Native(FRACTION_BIGINT), + List(halfMax, three, three) + ) + + val fractionExpr2 = FUNCTION_CALL( + Native(FRACTION_BIGINT), + List(max, min, min) + ) + + val fractionExpr3 = FUNCTION_CALL( + Native(FRACTION_BIGINT), + List(maxSqrt, maxSqrt, three) + ) + + val fractionRoundExpr1 = FUNCTION_CALL( + Native(FRACTION_BIGINT_ROUNDS), + List(halfMax, three, three, Rounding.HalfEven.value) + ) + + val fractionRoundExpr2 = FUNCTION_CALL( + Native(FRACTION_BIGINT_ROUNDS), + List(max, min, min, Rounding.HalfEven.value) + ) + + val fractionRoundExpr3 = FUNCTION_CALL( + Native(FRACTION_BIGINT_ROUNDS), + List(maxSqrt, maxSqrt, maxSqrt, Rounding.HalfEven.value) + ) + + val uminusExpr1 = FUNCTION_CALL( + Native(UMINUS_BIGINT), + List(halfMax) + ) + + val uminusExpr2 = FUNCTION_CALL( + Native(UMINUS_BIGINT), + List(halfMin) + ) + + val geExpr1 = FUNCTION_CALL( + Native(GE_BIGINT), + List(max, min) + ) + + val geExpr2 = FUNCTION_CALL( + Native(GE_BIGINT), + List(min, max) + ) + + val geExpr3 = FUNCTION_CALL( + Native(GE_BIGINT), + List(max, max) + ) + + val gtExpr1 = FUNCTION_CALL( + Native(GT_BIGINT), + List(max, min) + ) + + val gtExpr2 = FUNCTION_CALL( + Native(GT_BIGINT), + List(min, max) + ) + + val gtExpr3 = FUNCTION_CALL( + Native(GT_BIGINT), + List(max, max) + ) + + val listMinExpr1 = FUNCTION_CALL( + Native(MIN_LIST_BIGINT), + List(list) + ) + + val listMinExpr2 = FUNCTION_CALL( + Native(MIN_LIST_BIGINT), + List(listReversed) + ) + + val listMaxExpr1 = FUNCTION_CALL( + Native(MAX_LIST_BIGINT), + List(list) + ) + + val listMaxExpr2 = FUNCTION_CALL( + Native(MAX_LIST_BIGINT), + List(listReversed) + ) + + val medianListExpr = FUNCTION_CALL( + Native(MEDIAN_LISTBIGINT), + List(list) + ) + + val bigIntToBytes1 = FUNCTION_CALL( + Native(BIGINT_TO_BYTES), + List(max) + ) + + val bigIntToBytes2 = FUNCTION_CALL( + Native(BIGINT_TO_BYTES), + List(min) + ) + + val bytesToBigIntExpr1 = FUNCTION_CALL( + Native(BYTES_TO_BIGINT), + List(CONST_BYTESTR(ByteStr(PureContext.BigIntMax.toByteArray)).explicitGet()) + ) + + val bytesToBigIntExpr2 = FUNCTION_CALL( + Native(BYTES_TO_BIGINT), + List(CONST_BYTESTR(ByteStr(PureContext.BigIntMin.toByteArray)).explicitGet()) + ) + + val bytesToBigIntLimExpr1 = FUNCTION_CALL( + Native(BYTES_TO_BIGINT_LIM), + List(CONST_BYTESTR(ByteStr(maxBytes ++ Array.fill(100)(1.toByte))).explicitGet(), CONST_LONG(0), CONST_LONG(maxBytes.length)) + ) + + val bytesToBigIntLimExpr2 = FUNCTION_CALL( + Native(BYTES_TO_BIGINT_LIM), + List(CONST_BYTESTR(ByteStr(Array.fill(100)(1.toByte) ++ maxBytes)).explicitGet(), CONST_LONG(100), CONST_LONG(maxBytes.length)) + ) + + val stringToBigIntExpr1 = FUNCTION_CALL( + Native(STRING_TO_BIGINT), + List(CONST_STRING(PureContext.BigIntMax.toString()).explicitGet()) + ) + + val stringToBigIntExpr2 = FUNCTION_CALL( + Native(STRING_TO_BIGINT), + List(CONST_STRING(PureContext.BigIntMin.toString()).explicitGet()) + ) + + val stringToBigIntOptExpr1 = FUNCTION_CALL( + Native(STRING_TO_BIGINTOPT), + List(CONST_STRING(PureContext.BigIntMax.toString()).explicitGet()) + ) + + val stringToBigIntOptExpr2 = FUNCTION_CALL( + Native(STRING_TO_BIGINTOPT), + List(CONST_STRING(PureContext.BigIntMin.toString()).explicitGet()) + ) +} diff --git a/benchmark/src/test/scala/com/wavesplatform/lang/v1/FractionBigIntBenchmark.scala b/benchmark/src/test/scala/com/wavesplatform/lang/v1/FractionBigIntBenchmark.scala deleted file mode 100644 index 3e54f7e4fe6..00000000000 --- a/benchmark/src/test/scala/com/wavesplatform/lang/v1/FractionBigIntBenchmark.scala +++ /dev/null @@ -1,82 +0,0 @@ -package com.wavesplatform.lang.v1 - -import java.util.concurrent.TimeUnit - -import com.wavesplatform.lang.Common -import com.wavesplatform.lang.directives.DirectiveSet -import com.wavesplatform.lang.directives.values.{Account, Expression, V5} -import com.wavesplatform.lang.utils.lazyContexts -import com.wavesplatform.lang.v1.FunctionHeader.Native -import com.wavesplatform.lang.v1.compiler.Terms.{CONST_BIGINT, FUNCTION_CALL} -import com.wavesplatform.lang.v1.evaluator.FunctionIds.{FRACTION_BIGINT, FRACTION_BIGINT_ROUNDS} -import com.wavesplatform.lang.v1.evaluator.ctx.impl.{PureContext, Rounding} -import org.openjdk.jmh.annotations.* -import org.openjdk.jmh.infra.Blackhole - -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@BenchmarkMode(Array(Mode.AverageTime)) -@Threads(1) -@Fork(1) -@Warmup(iterations = 10, time = 1) -@Measurement(iterations = 10, time = 1) -class FractionBigIntBenchmark { - @Benchmark - def fraction1(bh: Blackhole, s: FractionBigIntSt): Unit = bh.consume(eval(s.ctx, s.expr1, V5)) - - @Benchmark - def fraction2(bh: Blackhole, s: FractionBigIntSt): Unit = bh.consume(eval(s.ctx, s.expr2, V5)) - - @Benchmark - def fraction3(bh: Blackhole, s: FractionBigIntSt): Unit = bh.consume(eval(s.ctx, s.expr3, V5)) - - @Benchmark - def fraction1Round(bh: Blackhole, s: FractionBigIntSt): Unit = bh.consume(eval(s.ctx, s.expr1Round, V5)) - - @Benchmark - def fraction2Round(bh: Blackhole, s: FractionBigIntSt): Unit = bh.consume(eval(s.ctx, s.expr2Round, V5)) - - @Benchmark - def fraction3Round(bh: Blackhole, s: FractionBigIntSt): Unit = bh.consume(eval(s.ctx, s.expr3Round, V5)) -} - -@State(Scope.Benchmark) -class FractionBigIntSt { - val ds = DirectiveSet(V5, Account, Expression).fold(null, identity) - val ctx = lazyContexts((ds, true, true)).value().evaluationContext(Common.emptyBlockchainEnvironment()) - - val max = CONST_BIGINT(PureContext.BigIntMax) - val halfMax = CONST_BIGINT(PureContext.BigIntMax / 2) - val min = CONST_BIGINT(PureContext.BigIntMin) - val maxSqrt = CONST_BIGINT(BigInt("57896044618658097711785492504343953926634992332820282019728792003956564819968")) - val three = CONST_BIGINT(3) - - val expr1 = FUNCTION_CALL( - Native(FRACTION_BIGINT), - List(halfMax, three, three) - ) - - val expr2 = FUNCTION_CALL( - Native(FRACTION_BIGINT), - List(max, min, min) - ) - - val expr3 = FUNCTION_CALL( - Native(FRACTION_BIGINT), - List(maxSqrt, maxSqrt, three) - ) - - val expr1Round = FUNCTION_CALL( - Native(FRACTION_BIGINT_ROUNDS), - List(halfMax, three, three, Rounding.HalfEven.value) - ) - - val expr2Round = FUNCTION_CALL( - Native(FRACTION_BIGINT_ROUNDS), - List(max, min, min, Rounding.HalfEven.value) - ) - - val expr3Round = FUNCTION_CALL( - Native(FRACTION_BIGINT_ROUNDS), - List(maxSqrt, maxSqrt, maxSqrt, Rounding.HalfEven.value) - ) -} diff --git a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala index 6d33727b6e5..262e9b5ea0a 100644 --- a/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala +++ b/lang/shared/src/main/scala/com/wavesplatform/lang/v1/evaluator/ctx/impl/PureContext.scala @@ -142,7 +142,7 @@ object PureContext { } lazy val stringToBigInt: BaseFunction[NoContext] = - NativeFunction("parseBigIntValue", 65, STRING_TO_BIGINT, BIGINT, ("n", STRING)) { + NativeFunction("parseBigIntValue", Map(V5 -> 65L, V6 -> 65L, V7 -> 65L, V8 -> 1L), STRING_TO_BIGINT, BIGINT, ("n", STRING)) { case CONST_STRING(n) :: Nil => Either .cond(n.length <= 155, BigInt(n), s"String too long for 512-bits big integers (${n.length} when max is 155)") @@ -153,7 +153,7 @@ object PureContext { } lazy val stringToBigIntOpt: BaseFunction[NoContext] = - NativeFunction("parseBigInt", 65, STRING_TO_BIGINTOPT, UNION(BIGINT, UNIT), ("n", STRING)) { + NativeFunction("parseBigInt", Map(V5 -> 65L, V6 -> 65L, V7 -> 65L, V8 -> 1L), STRING_TO_BIGINTOPT, UNION(BIGINT, UNIT), ("n", STRING)) { case CONST_STRING(n) :: Nil => Right((if (n.length <= 155) { try { @@ -173,13 +173,21 @@ object PureContext { } lazy val bigIntToBytes: BaseFunction[NoContext] = - NativeFunction("toBytes", 65, BIGINT_TO_BYTES, BYTESTR, ("n", BIGINT)) { + NativeFunction("toBytes", Map(V5 -> 65L, V6 -> 65L, V7 -> 65L, V8 -> 1L), BIGINT_TO_BYTES, BYTESTR, ("n", BIGINT)) { case CONST_BIGINT(n) :: Nil => CONST_BYTESTR(ByteStr(n.toByteArray)) case xs => notImplemented[Id, EVALUATED]("toBytes(n: BigInt)", xs) } lazy val bytesToBigIntLim: BaseFunction[NoContext] = - NativeFunction("toBigInt", 65, BYTES_TO_BIGINT_LIM, BIGINT, ("n", BYTESTR), ("off", LONG), ("size", LONG)) { + NativeFunction( + "toBigInt", + Map(V5 -> 65L, V6 -> 65L, V7 -> 65L, V8 -> 1L), + BYTES_TO_BIGINT_LIM, + BIGINT, + ("n", BYTESTR), + ("off", LONG), + ("size", LONG) + ) { case CONST_BYTESTR(ByteStr(n)) :: CONST_LONG(off) :: CONST_LONG(s) :: Nil => Either.cond( off >= 0 && off <= n.length && s <= 64 && s > 0, @@ -190,7 +198,7 @@ object PureContext { } lazy val bytesToBigInt: BaseFunction[NoContext] = - NativeFunction("toBigInt", 65, BYTES_TO_BIGINT, BIGINT, ("n", BYTESTR)) { + NativeFunction("toBigInt", Map(V5 -> 65L, V6 -> 65L, V7 -> 65L, V8 -> 1L), BYTES_TO_BIGINT, BIGINT, ("n", BYTESTR)) { case CONST_BYTESTR(ByteStr(n)) :: Nil => Either.cond(n.length <= 64, CONST_BIGINT(BigInt(n)), s"Too big ByteVector for BigInt (${n.length} > 64 bytes)") case xs => notImplemented[Id, EVALUATED]("toBigInt(n: ByteStr)", xs) @@ -220,14 +228,19 @@ object PureContext { } } - lazy val sumToBigInt: BaseFunction[NoContext] = bigIntArithmeticOp(SUM_OP, SUM_BIGINT, Map[StdLibVersion, Long](V5 -> 8L)) { _ + _ } - lazy val subToBigInt: BaseFunction[NoContext] = bigIntArithmeticOp(SUB_OP, SUB_BIGINT, Map[StdLibVersion, Long](V5 -> 8L)) { _ - _ } - lazy val mulToBigInt: BaseFunction[NoContext] = bigIntArithmeticOp(MUL_OP, MUL_BIGINT, Map[StdLibVersion, Long](V5 -> 64L)) { _ * _ } - lazy val divToBigInt: BaseFunction[NoContext] = bigIntArithmeticOp(DIV_OP, DIV_BIGINT, Map[StdLibVersion, Long](V5 -> 64L)) { _ / _ } - lazy val modToBigInt: BaseFunction[NoContext] = bigIntArithmeticOp(MOD_OP, MOD_BIGINT, Map[StdLibVersion, Long](V5 -> 64L)) { _ % _ } + lazy val sumToBigInt: BaseFunction[NoContext] = + bigIntArithmeticOp(SUM_OP, SUM_BIGINT, Map[StdLibVersion, Long](V5 -> 8L, V6 -> 8L, V7 -> 8L, V8 -> 1L)) { _ + _ } + lazy val subToBigInt: BaseFunction[NoContext] = + bigIntArithmeticOp(SUB_OP, SUB_BIGINT, Map[StdLibVersion, Long](V5 -> 8L, V6 -> 8L, V7 -> 8L, V8 -> 1L)) { _ - _ } + lazy val mulToBigInt: BaseFunction[NoContext] = + bigIntArithmeticOp(MUL_OP, MUL_BIGINT, Map[StdLibVersion, Long](V5 -> 64L, V6 -> 64L, V7 -> 64L, V8 -> 1L)) { _ * _ } + lazy val divToBigInt: BaseFunction[NoContext] = + bigIntArithmeticOp(DIV_OP, DIV_BIGINT, Map[StdLibVersion, Long](V5 -> 64L, V6 -> 64L, V7 -> 64L, V8 -> 1L)) { _ / _ } + lazy val modToBigInt: BaseFunction[NoContext] = + bigIntArithmeticOp(MOD_OP, MOD_BIGINT, Map[StdLibVersion, Long](V5 -> 64L, V6 -> 64L, V7 -> 64L, V8 -> 1L)) { _ % _ } lazy val negativeBigInt: BaseFunction[NoContext] = - NativeFunction("-", 8, UMINUS_BIGINT, BIGINT, ("n", BIGINT)) { + NativeFunction("-", Map(V5 -> 8L, V6 -> 8L, V7 -> 8L, V8 -> 1L), UMINUS_BIGINT, BIGINT, ("n", BIGINT)) { case CONST_BIGINT(n) :: Nil => Either.cond(n != BigIntMin, CONST_BIGINT(-n), s"Positive BigInt overflow") case xs => notImplemented[Id, EVALUATED]("-(n: BigInt)", xs) } @@ -1340,10 +1353,10 @@ object PureContext { case xs => notImplemented[Id, EVALUATED](s"${opsToFunctions(op)}(a: ${t.toString}, b: ${t.toString})", xs) } - def bigIntConditionOp(op: BinaryOperation, func: Short, complexity: Int = 8)( + def bigIntConditionOp(op: BinaryOperation, func: Short)( body: (BigInt, BigInt) => Boolean ): BaseFunction[NoContext] = - NativeFunction(opsToFunctions(op), complexity, func, BOOLEAN, ("a", BIGINT), ("b", BIGINT)) { + NativeFunction(opsToFunctions(op), Map(V5 -> 8L, V6 -> 8L, V7 -> 8L, V8 -> 1L), func, BOOLEAN, ("a", BIGINT), ("b", BIGINT)) { case CONST_BIGINT(a) :: CONST_BIGINT(b) :: Nil => Try(body(a, b)).toEither.bimap(_.getMessage, CONST_BOOLEAN) case xs => notImplemented[Id, EVALUATED](s"${opsToFunctions(op)}(a: BIGINT, b: BIGINT)", xs) } @@ -1396,7 +1409,7 @@ object PureContext { } lazy val listBigIntMax: BaseFunction[NoContext] = - NativeFunction("max", 192, MAX_LIST_BIGINT, BIGINT, ("list", PARAMETERIZEDLIST(BIGINT))) { + NativeFunction("max", Map(V5 -> 192L, V6 -> 192L, V7 -> 192L, V8 -> 6L), MAX_LIST_BIGINT, BIGINT, ("list", PARAMETERIZEDLIST(BIGINT))) { case ARR(list) :: Nil => Either.cond( list.nonEmpty, @@ -1408,7 +1421,7 @@ object PureContext { } lazy val listBigIntMin: BaseFunction[NoContext] = - NativeFunction("min", 192, MIN_LIST_BIGINT, BIGINT, ("list", PARAMETERIZEDLIST(BIGINT))) { + NativeFunction("min", Map(V5 -> 192L, V6 -> 192L, V7 -> 192L, V8 -> 6L), MIN_LIST_BIGINT, BIGINT, ("list", PARAMETERIZEDLIST(BIGINT))) { case ARR(list) :: Nil => Either.cond( list.nonEmpty, @@ -1729,7 +1742,13 @@ object PureContext { } val getBigIntListMedian: BaseFunction[NoContext] = - NativeFunction("median", 20 * 8, MEDIAN_LISTBIGINT, BIGINT, ("arr", PARAMETERIZEDLIST(BIGINT))) { + NativeFunction( + "median", + Map(V5 -> 20 * 8L, V6 -> 20 * 8L, V7 -> 20 * 8L, V8 -> 35L), + MEDIAN_LISTBIGINT, + BIGINT, + ("arr", PARAMETERIZEDLIST(BIGINT)) + ) { case xs @ ARR(arr) :: Nil => if (arr.headOption.forall(_.isInstanceOf[CONST_BIGINT])) { if (arr.nonEmpty)