From 0b54870bfe4c50bd04f987483c7c74fd0aa2e241 Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Tue, 2 Mar 2021 14:56:32 +0300 Subject: [PATCH] compiler: add missing math routines Add interops for ABS, SIGN, MIN, MAX, WITHIN opcodes --- pkg/compiler/syscall_test.go | 60 +++++++++++++++++++++++++++++ pkg/interop/math/math.go | 29 ++++++++++++++ pkg/interop/neogointernal/opcode.go | 5 +++ 3 files changed, 94 insertions(+) diff --git a/pkg/compiler/syscall_test.go b/pkg/compiler/syscall_test.go index 5ce03d9e2..9630c1f8c 100644 --- a/pkg/compiler/syscall_test.go +++ b/pkg/compiler/syscall_test.go @@ -133,4 +133,64 @@ func TestOpcode(t *testing.T) { }` eval(t, src, big.NewInt(3)) }) + t.Run("SIGN", func(t *testing.T) { + src := `package foo + import "github.com/nspcc-dev/neo-go/pkg/interop/math" + func Main() []int { + signs := make([]int, 3) + signs[0] = math.Sign(-123) + signs[1] = math.Sign(0) + signs[2] = math.Sign(42) + return signs + }` + eval(t, src, []stackitem.Item{ + stackitem.Make(-1), + stackitem.Make(0), + stackitem.Make(1), + }) + }) + t.Run("ABS", func(t *testing.T) { + src := `package foo + import "github.com/nspcc-dev/neo-go/pkg/interop/math" + func Main() int { + return math.Abs(-3) + }` + eval(t, src, big.NewInt(3)) + }) + t.Run("MAX", func(t *testing.T) { + src := `package foo + import "github.com/nspcc-dev/neo-go/pkg/interop/math" + func Main() int { + return math.Max(1, 2) + math.Max(8, 3) + }` + eval(t, src, big.NewInt(10)) + }) + t.Run("MIN", func(t *testing.T) { + src := `package foo + import "github.com/nspcc-dev/neo-go/pkg/interop/math" + func Main() int { + return math.Min(1, 2) + math.Min(8, 3) + }` + eval(t, src, big.NewInt(4)) + }) + t.Run("WITHIN", func(t *testing.T) { + src := `package foo + import "github.com/nspcc-dev/neo-go/pkg/interop/math" + func Main() []bool { + r := make([]bool, 5) + r[0] = math.Within(2, 3, 5) + r[1] = math.Within(3, 3, 5) + r[2] = math.Within(4, 3, 5) + r[3] = math.Within(5, 3, 5) + r[4] = math.Within(6, 3, 5) + return r + }` + eval(t, src, []stackitem.Item{ + stackitem.Make(false), + stackitem.Make(true), + stackitem.Make(true), + stackitem.Make(false), + stackitem.Make(false), + }) + }) } diff --git a/pkg/interop/math/math.go b/pkg/interop/math/math.go index 86cbd020d..6097bae1c 100644 --- a/pkg/interop/math/math.go +++ b/pkg/interop/math/math.go @@ -12,3 +12,32 @@ func Pow(a, b int) int { func Sqrt(x int) int { return neogointernal.Opcode1("SQRT", x).(int) } + +// Sign returns: +// +// -1 if x < 0 +// 0 if x == 0 +// +1 if x > 0 +func Sign(a int) int { + return neogointernal.Opcode1("SIGN", a).(int) +} + +// Abs returns absolute value of a. +func Abs(a int) int { + return neogointernal.Opcode1("ABS", a).(int) +} + +// Max returns maximum of a, b. +func Max(a, b int) int { + return neogointernal.Opcode2("MAX", a, b).(int) +} + +// Min returns minimum of a, b. +func Min(a, b int) int { + return neogointernal.Opcode2("MIN", a, b).(int) +} + +// Within returns true if a <= x < b. +func Within(x, a, b int) bool { + return neogointernal.Opcode3("WITHIN", x, a, b).(bool) +} diff --git a/pkg/interop/neogointernal/opcode.go b/pkg/interop/neogointernal/opcode.go index 3a7cb00a4..2e18b936b 100644 --- a/pkg/interop/neogointernal/opcode.go +++ b/pkg/interop/neogointernal/opcode.go @@ -9,3 +9,8 @@ func Opcode1(op string, arg interface{}) interface{} { func Opcode2(op string, arg1, arg2 interface{}) interface{} { return nil } + +// Opcode3 emits opcode with 3 arguments. +func Opcode3(op string, arg1, arg2, arg3 interface{}) interface{} { + return nil +}