Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.0] New Numeric methods #1017

Merged
merged 51 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
4004cc9
i486-toBytes: tests added to SigmaTyperTest
aslesarenko May 14, 2024
b55d336
i486-toBytes: ExactNumeric.toBytes implemented
aslesarenko May 14, 2024
9d83125
Merge branch 'develop' into i486-toBytes
aslesarenko May 14, 2024
e865264
Merge remote-tracking branch 'origin/v6.0.0-fix-tests' into i486-toBytes
aslesarenko May 14, 2024
d4ff7b5
Merge remote-tracking branch 'refs/remotes/origin/v6.0.0-refactor-ir-…
aslesarenko May 16, 2024
727be9b
Merge remote-tracking branch 'refs/remotes/origin/i994-fix-subst-cons…
aslesarenko May 23, 2024
3ccf11e
i486-toBytes: fixes after merge
aslesarenko May 23, 2024
e5a32c8
i486-toBytes: Versioned.scala added
aslesarenko May 25, 2024
bba2230
i486-toBytes: ensure VersionContext.current in tests
aslesarenko May 25, 2024
dc361a1
i486-toBytes: ErgoTreeSpecification versioned and updated
aslesarenko May 25, 2024
70786a0
i486-toBytes: clarified description of demotion of SNumericType
aslesarenko May 25, 2024
c76ac1a
i486-toBytes: GraphBuilding to handle numeric methods
aslesarenko May 25, 2024
2427db3
i486-toBytes: added userDefinedInvoke handler to SMethod
aslesarenko May 25, 2024
02e2d06
i486-toBytes: toBigEndianBytes implemented
aslesarenko May 25, 2024
dd7bdc6
removing serialize
kushti Jun 7, 2024
4b27c86
merging w. 6.0-newfeature
kushti Jun 7, 2024
e1bfb1c
remove serialize from GraphBuilding and ErgoTreeSpecification
kushti Jun 7, 2024
312167b
merging w. 6.0.0
kushti Jun 10, 2024
a731962
simplifying the code
kushti Jul 5, 2024
cb7e262
initial toBits failing tests
kushti Jul 6, 2024
f577fd3
passing test (compilation fixed)
kushti Jul 8, 2024
cadf53d
tests for Byte and BigInt
kushti Jul 8, 2024
81ed008
Merge branch 'i486-toBytes' of github.com:ScorexFoundation/sigmastate…
kushti Jul 8, 2024
ee59083
Byte.toBits test passing
kushti Jul 8, 2024
3fde5fa
toBits tests for Long and BigInt(failing)
kushti Jul 8, 2024
9ea7597
BigInt.toBits test passing
kushti Jul 8, 2024
be77315
bitwise inversion
kushti Jul 9, 2024
a575d38
bitwiseInverse tests for Long and Byte
kushti Jul 9, 2024
7ff3542
bitwise or impl
kushti Jul 10, 2024
868fbb1
bitwiseAnd
kushti Jul 10, 2024
f21436d
bitwiseXor
kushti Jul 10, 2024
ced229f
shiftLeft
kushti Jul 11, 2024
9519ef6
shiftRight
kushti Jul 16, 2024
3037f1a
merging w 6.0.0, fixing ErgoTreeSpec
kushti Aug 27, 2024
016262b
removing unused SNumericTypeMethods.getMethods
kushti Aug 27, 2024
baef87f
more efficient toBits impl
kushti Sep 2, 2024
c7918ad
merging v6.0.0
kushti Sep 2, 2024
5a983b3
merging w. 6.0.0
kushti Sep 3, 2024
2e8d8f4
optimizing imports, polishing
kushti Sep 3, 2024
0c674fe
Merge branch 'v6.0.0' of github.com:ScorexFoundation/sigmastate-inter…
kushti Sep 4, 2024
ed5b8f5
fixing SigmaTyperTest
kushti Sep 4, 2024
b2de9cf
scaladoc
kushti Sep 6, 2024
eccc9ca
6.0 methods for Byte in LSV6
kushti Sep 10, 2024
f566b7b
6.0 methods for Short in LSV6
kushti Sep 10, 2024
8cf4264
6.0 methods for Int in LSV6
kushti Sep 10, 2024
fa2c2df
Long tests in LSV6, shift check in shiftRight
kushti Sep 11, 2024
48db432
shiftLeft/shiftRight shift limit
kushti Sep 11, 2024
a2f3030
bigint - LSV6 tests
kushti Sep 11, 2024
297265f
arg descs, 2.11 comp fix, BOS tests fixed
kushti Sep 12, 2024
55d03cd
addressing review comments
kushti Sep 16, 2024
5f0c5c5
scaladoc improvements, Ints.toBits
kushti Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions core/shared/src/main/scala/sigma/SigmaDsl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import java.math.BigInteger
import sigma.data._

/**
* All `modQ` operations assume that Q is a global constant (an order of the only one cryptographically strong group
* which is used for all cryptographic operations).
* So it is globally and implicitly used in all methods.
* Functions defined for 256-bit signed integers
* */
trait BigInt {
/** Convert this BigInt value to Byte.
Expand Down Expand Up @@ -154,6 +152,23 @@ trait BigInt {
*/
def or(that: BigInt): BigInt
def |(that: BigInt): BigInt = or(that)

/**
* @return a big integer whose value is `this xor that`
*/
def xor(that: BigInt): BigInt

/**
* @return a 256-bit signed integer whose value is (this << n). The shift distance, n, may be negative,
* in which case this method performs a right shift. (Computes floor(this * 2n).)
*/
def shiftLeft(n: Int): BigInt

/**
* @return a 256-bit signed integer whose value is (this >> n). Sign extension is performed. The shift distance, n,
* may be negative, in which case this method performs a left shift. (Computes floor(this / 2n).)
*/
def shiftRight(n: Int): BigInt
}

/** Base class for points on elliptic curves. */
Expand Down
55 changes: 38 additions & 17 deletions core/shared/src/main/scala/sigma/ast/SType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -113,27 +113,48 @@ object SType {
* typeId this map contains a companion object which can be used to access the list of
* corresponding methods.
*
* NOTE: in the current implementation only monomorphic methods are supported (without
* type parameters)
* @note starting from v6.0 methods with type parameters are also supported.
*
* NOTE2: in v3.x SNumericType.typeId is silently shadowed by SGlobal.typeId as part of
* `toMap` operation. As a result, the methods collected into SByte.methods cannot be
* @note on versioning:
* In v3.x-5.x SNumericType.typeId is silently shadowed by SGlobal.typeId as part of
* `toMap` operation. As a result, SNumericTypeMethods container cannot be resolved by
* typeId = 106, because SNumericType was being silently removed when `_types` map is
* constructed. See `property("SNumericType.typeId resolves to SGlobal")`.
* In addition, the methods associated with the concrete numeric types cannot be
* resolved (using SMethod.fromIds()) for all numeric types (SByte, SShort, SInt,
* SLong, SBigInt). See the corresponding regression `property("MethodCall on numerics")`.
* SLong) because these types are not registered in the `_types` map.
* See the corresponding property("MethodCall on numerics")`.
* However, this "shadowing" is not a problem since all casting methods are implemented
* via Downcast, Upcast opcodes and the remaining `toBytes`, `toBits` methods are not
* implemented at all.
* In order to allow MethodCalls on numeric types in future versions the SNumericType.typeId
* should be changed and SGlobal.typeId should be preserved. The regression tests in
* `property("MethodCall Codes")` should pass.
* via lowering to Downcast, Upcast opcodes and the remaining `toBytes`, `toBits`
* methods are not implemented at all.
*
* Starting from v6.0 the SNumericType.typeId is demoted as a receiver object of
* method calls and:
* 1) numeric type SByte, SShort, SInt, SLong are promoted as receivers and added to
* the _types map.
* 2) all methods from SNumericTypeMethods are copied to all the concrete numeric types
* (SByte, SShort, SInt, SLong, SBigInt) and the generic tNum type parameter is
* specialized accordingly.
*
* This difference in behaviour is tested by `property("MethodCall on numerics")`.
*
* The regression tests in `property("MethodCall Codes")` should pass.
*/
// TODO v6.0: should contain all numeric types (including also SNumericType)
// to support method calls like 10.toByte which encoded as MethodCall with typeId = 4, methodId = 1
// see https://github.com/ScorexFoundation/sigmastate-interpreter/issues/667
lazy val types: Map[Byte, STypeCompanion] = Seq(
SBoolean, SNumericType, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader,
private val v5Types = Seq(
SBoolean, SString, STuple, SGroupElement, SSigmaProp, SContext, SGlobal, SHeader, SPreHeader,
SAvlTree, SBox, SOption, SCollection, SBigInt
).map { t => (t.typeId, t) }.toMap
)
private val v6Types = v5Types ++ Seq(SByte, SShort, SInt, SLong)

private val v5TypesMap = v5Types.map { t => (t.typeId, t) }.toMap

private val v6TypesMap = v6Types.map { t => (t.typeId, t) }.toMap

def types: Map[Byte, STypeCompanion] = if (VersionContext.current.isV6SoftForkActivated) {
v6TypesMap
} else {
v5TypesMap
}

/** Checks that the type of the value corresponds to the descriptor `tpe`.
* If the value has complex structure only root type constructor is checked.
Expand Down Expand Up @@ -452,7 +473,7 @@ case object SLong extends SPrimType with SEmbeddable with SNumericType with SMon
}
}

/** Type of 256 bit integet values. Implemented using [[java.math.BigInteger]]. */
/** Type of 256 bit integer values. Implemented using [[java.math.BigInteger]]. */
case object SBigInt extends SPrimType with SEmbeddable with SNumericType with SMonoType {
override type WrappedType = BigInt
override val typeCode: TypeCode = 6: Byte
Expand Down
6 changes: 6 additions & 0 deletions core/shared/src/main/scala/sigma/ast/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ package object ast {

def asNumType: SNumericType = tpe.asInstanceOf[SNumericType]

/** Cast this type to numeric type or else throws the given error. */
def asNumTypeOrElse(error: => Exception): SNumericType = tpe match {
case nt: SNumericType => nt
case _ => throw error
}

def asFunc: SFunc = tpe.asInstanceOf[SFunc]

def asProduct: SProduct = tpe.asInstanceOf[SProduct]
Expand Down
6 changes: 6 additions & 0 deletions core/shared/src/main/scala/sigma/data/CBigInt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,10 @@ case class CBigInt(override val wrappedValue: BigInteger) extends BigInt with Wr
override def and(that: BigInt): BigInt = CBigInt(wrappedValue.and(that.asInstanceOf[CBigInt].wrappedValue))

override def or(that: BigInt): BigInt = CBigInt(wrappedValue.or(that.asInstanceOf[CBigInt].wrappedValue))

override def xor(that: BigInt): BigInt = CBigInt(wrappedValue.xor(that.asInstanceOf[CBigInt].wrappedValue))

override def shiftLeft(n: Int): BigInt = CBigInt(wrappedValue.shiftLeft(n).to256BitValueExact)

override def shiftRight(n: Int): BigInt = CBigInt(wrappedValue.shiftRight(n).to256BitValueExact)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import debox.cfor
import sigma.VersionContext
import sigma.ast.SCollectionType.{CollectionTypeCode, NestedCollectionTypeCode}
import sigma.ast._
import sigma.serialization.{CoreByteReader, CoreByteWriter, InvalidTypePrefix}
import sigma.util.safeNewArray
import sigma.validation.ValidationRules.{CheckPrimitiveTypeCode, CheckTypeCode}

Expand Down Expand Up @@ -215,7 +214,6 @@ class TypeSerializer {
STypeParam(ident.asInstanceOf[STypeVar])
}
SFunc(tDom, tRange, tpeParams)
// todo: serialize tParams
case _ =>
// todo: 6.0: replace 1008 check with identical behavior but other opcode, to activate
// ReplacedRule(1008 -> new opcode) during 6.0 activation
Expand Down
184 changes: 160 additions & 24 deletions data/shared/src/main/scala/sigma/ast/methods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import sigma.ast.SCollection.{SBooleanArray, SBoxArray, SByteArray, SByteArray2,
import sigma.ast.SMethod.{MethodCallIrBuilder, MethodCostFunc, javaMethodOf}
import sigma.ast.SType.TypeCode
import sigma.ast.syntax.{SValue, ValueOps}
import sigma.data.ExactIntegral.{ByteIsExactIntegral, IntIsExactIntegral, LongIsExactIntegral, ShortIsExactIntegral}
import sigma.data.NumericOps.BigIntIsExactIntegral
import sigma.data.OverloadHack.Overloaded1
import sigma.data.{DataValueComparer, KeyValueColl, Nullable, RType, SigmaConstants}
import sigma.eval.{CostDetails, ErgoTreeEvaluator, TracedCost}
Expand Down Expand Up @@ -156,14 +158,34 @@ trait MonoTypeMethods extends MethodsContainer {

trait SNumericTypeMethods extends MonoTypeMethods {
import SNumericTypeMethods.tNum

private val subst = Map(tNum -> this.ownerType)

val v5Methods = {
SNumericTypeMethods.v5Methods.map { m =>
m.copy(stype = applySubst(m.stype, subst).asFunc)
}
}

val v6Methods = {
SNumericTypeMethods.v6Methods.map { m =>
m.copy(
objType = this, // associate the method with the concrete numeric type
stype = applySubst(m.stype, subst).asFunc
)}
}

protected override def getMethods(): Seq[SMethod] = {
super.getMethods() ++ SNumericTypeMethods.methods.map {
m => m.copy(stype = applySubst(m.stype, Map(tNum -> this.ownerType)).asFunc)
if (VersionContext.current.isV6SoftForkActivated) {
super.getMethods() ++ v6Methods
} else {
super.getMethods() ++ v5Methods
}
}
}

object SNumericTypeMethods extends MethodsContainer {

/** Type for which this container defines methods. */
override def ownerType: STypeCompanion = SNumericType

Expand Down Expand Up @@ -216,6 +238,15 @@ object SNumericTypeMethods extends MethodsContainer {
val ToBytesMethod: SMethod = SMethod(
this, "toBytes", SFunc(tNum, SByteArray), 6, ToBytes_CostKind)
.withIRInfo(MethodCallIrBuilder)
.withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) =>
m.objType match {
case SByteMethods => ByteIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Byte])
case SShortMethods => ShortIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Short])
case SIntMethods => IntIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Int])
case SLongMethods => LongIsExactIntegral.toBigEndianBytes(obj.asInstanceOf[Long])
case SBigIntMethods => obj.asInstanceOf[BigInt].toBytes
}
})
.withInfo(PropertyCall,
""" Returns a big-endian representation of this numeric value in a collection of bytes.
| For example, the \lst{Int} value \lst{0x12131415} would yield the
Expand All @@ -229,12 +260,124 @@ object SNumericTypeMethods extends MethodsContainer {
val ToBitsMethod: SMethod = SMethod(
this, "toBits", SFunc(tNum, SBooleanArray), 7, ToBits_CostKind)
.withIRInfo(MethodCallIrBuilder)
.withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) =>
m.objType match {
case SByteMethods => ByteIsExactIntegral.toBits(obj.asInstanceOf[Byte])
case SShortMethods => ShortIsExactIntegral.toBits(obj.asInstanceOf[Short])
case SIntMethods => IntIsExactIntegral.toBits(obj.asInstanceOf[Int])
case SLongMethods => LongIsExactIntegral.toBits(obj.asInstanceOf[Long])
case SBigIntMethods => BigIntIsExactIntegral.toBits(obj.asInstanceOf[BigInt])
}
})
.withInfo(PropertyCall,
""" Returns a big-endian representation of this numeric in a collection of Booleans.
| Each boolean corresponds to one bit.
""".stripMargin)

protected override def getMethods(): Seq[SMethod] = Array(
/** Cost of inverting bits of a number. */
val BitwiseInverse_CostKind = FixedCost(JitCost(5))

val BitwiseInverseMethod: SMethod = SMethod(
this, "bitwiseInverse", SFunc(tNum, tNum), 8, BitwiseInverse_CostKind)
.withIRInfo(MethodCallIrBuilder)
.withUserDefinedInvoke({ (m: SMethod, obj: Any, _: Array[Any]) =>
m.objType match {
case SByteMethods => ByteIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Byte])
case SShortMethods => ShortIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Short])
case SIntMethods => IntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Int])
case SLongMethods => LongIsExactIntegral.bitwiseInverse(obj.asInstanceOf[Long])
case SBigIntMethods => BigIntIsExactIntegral.bitwiseInverse(obj.asInstanceOf[BigInt])
}
})
.withInfo(PropertyCall, desc = "Returns bitwise inverse of this numeric. ")

val BitwiseOrMethod: SMethod = SMethod(
this, "bitwiseOr", SFunc(Array(tNum, tNum), tNum), 9, BitwiseInverse_CostKind)
.withIRInfo(MethodCallIrBuilder)
.withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) =>
m.objType match {
case SByteMethods => ByteIsExactIntegral.bitwiseOr(obj.asInstanceOf[Byte], other.head.asInstanceOf[Byte])
case SShortMethods => ShortIsExactIntegral.bitwiseOr(obj.asInstanceOf[Short], other.head.asInstanceOf[Short])
case SIntMethods => IntIsExactIntegral.bitwiseOr(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
case SLongMethods => LongIsExactIntegral.bitwiseOr(obj.asInstanceOf[Long], other.head.asInstanceOf[Long])
case SBigIntMethods => BigIntIsExactIntegral.bitwiseOr(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt])
}
})
.withInfo(MethodCall,
""" Returns bitwise or of this numeric and provided one. """.stripMargin,
ArgInfo("that", "A numeric value to calculate or with."))

val BitwiseAndMethod: SMethod = SMethod(
this, "bitwiseAnd", SFunc(Array(tNum, tNum), tNum), 10, BitwiseInverse_CostKind)
.withIRInfo(MethodCallIrBuilder)
.withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) =>
m.objType match {
case SByteMethods => ByteIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Byte], other.head.asInstanceOf[Byte])
case SShortMethods => ShortIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Short], other.head.asInstanceOf[Short])
case SIntMethods => IntIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
case SLongMethods => LongIsExactIntegral.bitwiseAnd(obj.asInstanceOf[Long], other.head.asInstanceOf[Long])
case SBigIntMethods => BigIntIsExactIntegral.bitwiseAnd(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt])
}
})
.withInfo(MethodCall,
""" Returns bitwise and of this numeric and provided one. """.stripMargin,
ArgInfo("that", "A numeric value to calculate and with."))

val BitwiseXorMethod: SMethod = SMethod(
this, "bitwiseXor", SFunc(Array(tNum, tNum), tNum), 11, BitwiseInverse_CostKind)
.withIRInfo(MethodCallIrBuilder)
.withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) =>
m.objType match {
case SByteMethods => ByteIsExactIntegral.bitwiseXor(obj.asInstanceOf[Byte], other.head.asInstanceOf[Byte])
case SShortMethods => ShortIsExactIntegral.bitwiseXor(obj.asInstanceOf[Short], other.head.asInstanceOf[Short])
case SIntMethods => IntIsExactIntegral.bitwiseXor(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
case SLongMethods => LongIsExactIntegral.bitwiseXor(obj.asInstanceOf[Long], other.head.asInstanceOf[Long])
case SBigIntMethods => BigIntIsExactIntegral.bitwiseXor(obj.asInstanceOf[BigInt], other.head.asInstanceOf[BigInt])
}
})
.withInfo(MethodCall,
""" Returns bitwise xor of this numeric and provided one. """.stripMargin,
ArgInfo("that", "A numeric value to calculate xor with."))

val ShiftLeftMethod: SMethod = SMethod(
this, "shiftLeft", SFunc(Array(tNum, SInt), tNum), 12, BitwiseInverse_CostKind)
.withIRInfo(MethodCallIrBuilder)
.withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) =>
m.objType match {
case SByteMethods => ByteIsExactIntegral.shiftLeft(obj.asInstanceOf[Byte], other.head.asInstanceOf[Int])
case SShortMethods => ShortIsExactIntegral.shiftLeft(obj.asInstanceOf[Short], other.head.asInstanceOf[Int])
case SIntMethods => IntIsExactIntegral.shiftLeft(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
case SLongMethods => LongIsExactIntegral.shiftLeft(obj.asInstanceOf[Long], other.head.asInstanceOf[Int])
case SBigIntMethods => BigIntIsExactIntegral.shiftLeft(obj.asInstanceOf[BigInt], other.head.asInstanceOf[Int])
}
})
.withInfo(MethodCall,
""" Returns a big-endian representation of this numeric in a collection of Booleans.
| Each boolean corresponds to one bit.
""".stripMargin,
ArgInfo("bits", "Number of bit to shift to the left. Note, that bits value must be non-negative and less than " +
"the size of the number in bits (e.g. 64 for Long, 256 for BigInt)"))

val ShiftRightMethod: SMethod = SMethod(
this, "shiftRight", SFunc(Array(tNum, SInt), tNum), 13, BitwiseInverse_CostKind)
.withIRInfo(MethodCallIrBuilder)
.withUserDefinedInvoke({ (m: SMethod, obj: Any, other: Array[Any]) =>
m.objType match {
case SByteMethods => ByteIsExactIntegral.shiftRight(obj.asInstanceOf[Byte], other.head.asInstanceOf[Int])
case SShortMethods => ShortIsExactIntegral.shiftRight(obj.asInstanceOf[Short], other.head.asInstanceOf[Int])
case SIntMethods => IntIsExactIntegral.shiftRight(obj.asInstanceOf[Int], other.head.asInstanceOf[Int])
case SLongMethods => LongIsExactIntegral.shiftRight(obj.asInstanceOf[Long], other.head.asInstanceOf[Int])
case SBigIntMethods => BigIntIsExactIntegral.shiftRight(obj.asInstanceOf[BigInt], other.head.asInstanceOf[Int])
}
})
.withInfo(MethodCall,
""" Returns a big-endian representation of this numeric in a collection of Booleans.
| Each boolean corresponds to one bit.
""".stripMargin,
ArgInfo("bits", "Number of bit to shift to the right. Note, that bits value must be non-negative and less than " +
"the size of the number in bits (e.g. 64 for Long, 256 for BigInt)"))

lazy val v5Methods = Array(
ToByteMethod, // see Downcast
ToShortMethod, // see Downcast
ToIntMethod, // see Downcast
Expand All @@ -244,7 +387,21 @@ object SNumericTypeMethods extends MethodsContainer {
ToBitsMethod
)

lazy val v6Methods = v5Methods ++ Array(
BitwiseInverseMethod,
BitwiseOrMethod,
BitwiseAndMethod,
BitwiseXorMethod,
ShiftLeftMethod,
ShiftRightMethod
)

protected override def getMethods(): Seq[SMethod] = {
throw new Exception("SNumericTypeMethods.getMethods shouldn't ever be called")
}

/** Collection of names of numeric casting methods (like `toByte`, `toInt`, etc). */
// todo: add unsigned big int
val castMethods: Array[String] =
Array(ToByteMethod, ToShortMethod, ToIntMethod, ToLongMethod, ToBigIntMethod)
.map(_.name)
Expand Down Expand Up @@ -309,21 +466,6 @@ case object SBigIntMethods extends SNumericTypeMethods {
/** Type for which this container defines methods. */
override def ownerType: SMonoType = SBigInt

/** The following `modQ` methods are not fully implemented in v4.x and this descriptors.
* This descritors are remain here in the code and are waiting for full implementation
* is upcoming soft-forks at which point the cost parameters should be calculated and
* changed.
*/
val ModQMethod = SMethod(this, "modQ", SFunc(this.ownerType, SBigInt), 1, FixedCost(JitCost(1)))
.withInfo(ModQ, "Returns this \\lst{mod} Q, i.e. remainder of division by Q, where Q is an order of the cryprographic group.")
val PlusModQMethod = SMethod(this, "plusModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 2, FixedCost(JitCost(1)))
.withInfo(ModQArithOp.PlusModQ, "Adds this number with \\lst{other} by module Q.", ArgInfo("other", "Number to add to this."))
val MinusModQMethod = SMethod(this, "minusModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 3, FixedCost(JitCost(1)))
.withInfo(ModQArithOp.MinusModQ, "Subtracts \\lst{other} number from this by module Q.", ArgInfo("other", "Number to subtract from this."))
val MultModQMethod = SMethod(this, "multModQ", SFunc(IndexedSeq(this.ownerType, SBigInt), SBigInt), 4, FixedCost(JitCost(1)))
.withIRInfo(MethodCallIrBuilder)
.withInfo(MethodCall, "Multiply this number with \\lst{other} by module Q.", ArgInfo("other", "Number to multiply with this."))

protected override def getMethods(): Seq[SMethod] = {
if (VersionContext.current.isV6SoftForkActivated) {
super.getMethods()
Expand All @@ -337,12 +479,6 @@ case object SBigIntMethods extends SNumericTypeMethods {
}
}

/**
*
*/
def nbits_eval(mc: MethodCall, bi: sigma.BigInt)(implicit E: ErgoTreeEvaluator): Long = {
???
}

}

Expand Down
Loading
Loading