mirror of
https://github.com/MontFerret/ferret.git
synced 2025-03-03 15:02:32 +02:00
Feature/#7 numeric functions (#116)
* #7 Added ABS * #7 Added ACOS * #7 Added ASIN * #7 Added ATAN * #7 Added ATAN2 * #7 Added AVERAGE * #7 Added CEIL * #7 Added COS * #7 Added DEGREES * #7 Added EXP * #7 Added EXP2 * #7 Added FLOOR * #7 Added LOG * #7 Added LOG2 * #7 Added LOG10 * #7 Added MAX * #7 Added MEDIAN * #7 Added MIN * #7 Added PERCENTILE * #7 Added PI * #7 Added POW * #7 Added RADIANS * #7 Added RAND * #7 Added RANGE * #7 Added ROUND * #7 Added SIN * #7 Added SQRT * #7 Added TAN * #7 Added SUM * #7 Added STDDEV_POPULATION * #7 Added STDDEV_SAMPLE, VARIANCE_POPULATION, VARIANCE_SAMPLE
This commit is contained in:
parent
2417be3f9d
commit
5f94b77a39
@ -4,6 +4,7 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"hash/fnv"
|
||||
"sort"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/pkg/errors"
|
||||
@ -221,3 +222,17 @@ func (t *Array) Clone() core.Cloneable {
|
||||
|
||||
return cloned
|
||||
}
|
||||
|
||||
func (t *Array) Sort() *Array {
|
||||
c := make([]core.Value, len(t.value))
|
||||
copy(c, t.value)
|
||||
|
||||
sort.SliceStable(c, func(i, j int) bool {
|
||||
return c[i].Compare(c[j]) == 0
|
||||
})
|
||||
|
||||
res := new(Array)
|
||||
res.value = c
|
||||
|
||||
return res
|
||||
}
|
||||
|
@ -63,6 +63,14 @@ func ParseFloatP(input interface{}) Float {
|
||||
return res
|
||||
}
|
||||
|
||||
func IsNaN(input Float) Boolean {
|
||||
return NewBoolean(math.IsNaN(float64(input)))
|
||||
}
|
||||
|
||||
func IsInf(input Float, sign Int) Boolean {
|
||||
return NewBoolean(math.IsInf(float64(input), int(sign)))
|
||||
}
|
||||
|
||||
func (t Float) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(float64(t))
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/arrays"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/collections"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/html"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/objects"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/strings"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/types"
|
||||
@ -22,6 +23,7 @@ func NewLib() map[string]core.Function {
|
||||
|
||||
add(types.NewLib())
|
||||
add(strings.NewLib())
|
||||
add(math.NewLib())
|
||||
add(collections.NewLib())
|
||||
add(arrays.NewLib())
|
||||
add(objects.NewLib())
|
||||
|
29
pkg/stdlib/math/abs.go
Normal file
29
pkg/stdlib/math/abs.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the absolute value of a given number.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The absolute value of a given number.
|
||||
*/
|
||||
func Abs(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Abs(toFloat(args[0]))), nil
|
||||
}
|
38
pkg/stdlib/math/abs_test.go
Normal file
38
pkg/stdlib/math/abs_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAbs(t *testing.T) {
|
||||
Convey("Should return absolute value", t, func() {
|
||||
Convey("When value is int", func() {
|
||||
out, err := math.Abs(context.Background(), values.NewInt(-5))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 5)
|
||||
|
||||
out, err = math.Abs(context.Background(), values.NewInt(3))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 3)
|
||||
})
|
||||
|
||||
Convey("When value is float", func() {
|
||||
out, err := math.Abs(context.Background(), values.NewFloat(-5))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 5)
|
||||
|
||||
out, err = math.Abs(context.Background(), values.NewFloat(5.1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 5.1)
|
||||
})
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/acos.go
Normal file
29
pkg/stdlib/math/acos.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the arccosine, in radians, of a given number.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The arccosine, in radians, of a given number.
|
||||
*/
|
||||
func Acos(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Acos(toFloat(args[0]))), nil
|
||||
}
|
24
pkg/stdlib/math/acos_test.go
Normal file
24
pkg/stdlib/math/acos_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAcos(t *testing.T) {
|
||||
Convey("Should return arccosine", t, func() {
|
||||
out, err := math.Acos(context.Background(), values.NewInt(-1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 3.141592653589793)
|
||||
|
||||
out, err = math.Acos(context.Background(), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1.5707963267948966)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/asin.go
Normal file
29
pkg/stdlib/math/asin.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the arcsine, in radians, of a given number.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The arcsine, in radians, of a given number.
|
||||
*/
|
||||
func Asin(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Asin(toFloat(args[0]))), nil
|
||||
}
|
34
pkg/stdlib/math/asin_test.go
Normal file
34
pkg/stdlib/math/asin_test.go
Normal file
@ -0,0 +1,34 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAsin(t *testing.T) {
|
||||
Convey("Should return arcsine value", t, func() {
|
||||
out, err := math.Asin(context.Background(), values.NewInt(1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1.5707963267948966)
|
||||
|
||||
out, err = math.Asin(context.Background(), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 0)
|
||||
|
||||
out, err = math.Asin(context.Background(), values.NewInt(-1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, -1.5707963267948966)
|
||||
|
||||
out, err = math.Asin(context.Background(), values.NewInt(2))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(values.IsNaN(out.(values.Float)), ShouldEqual, true)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/atan.go
Normal file
29
pkg/stdlib/math/atan.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the arctangent, in radians, of a given number.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The arctangent, in radians, of a given number.
|
||||
*/
|
||||
func Atan(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Atan(toFloat(args[0]))), nil
|
||||
}
|
39
pkg/stdlib/math/atan2.go
Normal file
39
pkg/stdlib/math/atan2.go
Normal file
@ -0,0 +1,39 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the arc tangent of y/x, using the signs of the two to determine the quadrant of the return value.
|
||||
* @param number1 (Int|Float) - Input number.
|
||||
* @param number2 (Int|Float) - Input number.
|
||||
* @returns (Float) - The arc tangent of y/x, using the signs of the two to determine the quadrant of the return value.
|
||||
*/
|
||||
func Atan2(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 2, 2)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[1], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arg1 := toFloat(args[0])
|
||||
arg2 := toFloat(args[1])
|
||||
|
||||
return values.NewFloat(math.Atan2(arg1, arg2)), nil
|
||||
}
|
34
pkg/stdlib/math/atan2_test.go
Normal file
34
pkg/stdlib/math/atan2_test.go
Normal file
@ -0,0 +1,34 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAtan2(t *testing.T) {
|
||||
Convey("Should return tangent value", t, func() {
|
||||
out, err := math.Atan2(context.Background(), values.NewInt(0), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 0)
|
||||
|
||||
out, err = math.Atan2(context.Background(), values.NewInt(1), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1.5707963267948966)
|
||||
|
||||
out, err = math.Atan2(context.Background(), values.NewInt(1), values.NewInt(1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, 0.7853981633974483)
|
||||
|
||||
out, err = math.Atan2(context.Background(), values.NewInt(-10), values.NewInt(20))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, -0.4636476090008061)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/atan_test.go
Normal file
29
pkg/stdlib/math/atan_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAtan(t *testing.T) {
|
||||
Convey("Should return arctangent value", t, func() {
|
||||
out, err := math.Atan(context.Background(), values.NewInt(-1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, -0.7853981633974483)
|
||||
|
||||
out, err = math.Atan(context.Background(), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 0)
|
||||
|
||||
out, err = math.Atan(context.Background(), values.NewInt(10))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, 1.4711276743037345)
|
||||
})
|
||||
}
|
55
pkg/stdlib/math/average.go
Normal file
55
pkg/stdlib/math/average.go
Normal file
@ -0,0 +1,55 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the average (arithmetic mean) of the values in array.
|
||||
* @param array (Array) - Array of numbers.
|
||||
* @returns (Float) - The average of the values in array.
|
||||
*/
|
||||
func Average(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
var sum float64
|
||||
|
||||
arr.ForEach(func(value core.Value, idx int) bool {
|
||||
err = core.ValidateType(value, core.FloatType, core.IntType)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
sum += toFloat(value)
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
count := arr.Length()
|
||||
|
||||
return values.Float(sum / float64(count)), nil
|
||||
}
|
47
pkg/stdlib/math/average_test.go
Normal file
47
pkg/stdlib/math/average_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAverage(t *testing.T) {
|
||||
Convey("Should return average value", t, func() {
|
||||
out, err := math.Average(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(5),
|
||||
values.NewInt(2),
|
||||
values.NewInt(9),
|
||||
values.NewInt(2),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 4.5)
|
||||
|
||||
out, err = math.Average(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(-3),
|
||||
values.NewInt(-5),
|
||||
values.NewInt(2),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, -2)
|
||||
|
||||
out, err = math.Average(context.Background(), values.NewArrayWith(
|
||||
values.None,
|
||||
values.NewInt(-5),
|
||||
values.False,
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, values.None)
|
||||
|
||||
out, err = math.Average(context.Background(), values.NewArray(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, values.None)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/ceil.go
Normal file
29
pkg/stdlib/math/ceil.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the least integer value greater than or equal to a given value.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Int) - The least integer value greater than or equal to a given value.
|
||||
*/
|
||||
func Ceil(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewInt(int(math.Ceil(toFloat(args[0])))), nil
|
||||
}
|
29
pkg/stdlib/math/ceil_test.go
Normal file
29
pkg/stdlib/math/ceil_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestCeil(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Ceil(context.Background(), values.NewFloat(2.49))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 3)
|
||||
|
||||
out, err = math.Ceil(context.Background(), values.NewFloat(2.50))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 3)
|
||||
|
||||
out, err = math.Ceil(context.Background(), values.NewFloat(-2.50))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, -2)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/cos.go
Normal file
29
pkg/stdlib/math/cos.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the cosine of a given number.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The cosine of a given number.
|
||||
*/
|
||||
func Cos(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Cos(toFloat(args[0]))), nil
|
||||
}
|
29
pkg/stdlib/math/cos_test.go
Normal file
29
pkg/stdlib/math/cos_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestCos(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Cos(context.Background(), values.NewFloat(1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 0.5403023058681398)
|
||||
|
||||
out, err = math.Cos(context.Background(), values.NewFloat(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1)
|
||||
|
||||
out, err = math.Cos(context.Background(), values.NewFloat(-3.141592653589783))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, -1)
|
||||
})
|
||||
}
|
30
pkg/stdlib/math/degrees.go
Normal file
30
pkg/stdlib/math/degrees.go
Normal file
@ -0,0 +1,30 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the angle converted from radians to degrees.
|
||||
* @param number (Float|Int) - The input number.
|
||||
* @returns (Float) - The angle in degrees.
|
||||
*/
|
||||
func Degrees(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
r := toFloat(args[0])
|
||||
|
||||
return values.NewFloat(r * RadToDeg), nil
|
||||
}
|
24
pkg/stdlib/math/degrees_test.go
Normal file
24
pkg/stdlib/math/degrees_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestDegrees(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Degrees(context.Background(), values.NewFloat(0.7853981633974483))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 45)
|
||||
|
||||
out, err = math.Degrees(context.Background(), values.NewFloat(3.141592653589793))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 180)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/exp.go
Normal file
29
pkg/stdlib/math/exp.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns Euler's constant (2.71828...) raised to the power of value.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - Euler's constant raised to the power of value.
|
||||
*/
|
||||
func Exp(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Exp(toFloat(args[0]))), nil
|
||||
}
|
29
pkg/stdlib/math/exp2.go
Normal file
29
pkg/stdlib/math/exp2.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns 2 raised to the power of value.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - 2 raised to the power of value.
|
||||
*/
|
||||
func Exp2(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Exp2(toFloat(args[0]))), nil
|
||||
}
|
29
pkg/stdlib/math/exp2_test.go
Normal file
29
pkg/stdlib/math/exp2_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestExp2(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Exp2(context.Background(), values.NewFloat(16))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 65536)
|
||||
|
||||
out, err = math.Exp(context.Background(), values.NewFloat(1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Compare(values.NewFloat(2)) == 1, ShouldBeTrue)
|
||||
|
||||
out, err = math.Exp(context.Background(), values.NewFloat(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/exp_test.go
Normal file
29
pkg/stdlib/math/exp_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestExp(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Exp(context.Background(), values.NewFloat(1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2.718281828459045)
|
||||
|
||||
out, err = math.Exp(context.Background(), values.NewFloat(10))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Compare(values.NewFloat(22026.46579480671)) == 1, ShouldBeTrue)
|
||||
|
||||
out, err = math.Exp(context.Background(), values.NewFloat(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/floor.go
Normal file
29
pkg/stdlib/math/floor.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the greatest integer value less than or equal to a given value.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Int) - The greatest integer value less than or equal to a given value.
|
||||
*/
|
||||
func Floor(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewInt(int(math.Floor(toFloat(args[0])))), nil
|
||||
}
|
29
pkg/stdlib/math/floor_test.go
Normal file
29
pkg/stdlib/math/floor_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestFloor(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Floor(context.Background(), values.NewFloat(2.49))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2)
|
||||
|
||||
out, err = math.Floor(context.Background(), values.NewFloat(2.50))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2)
|
||||
|
||||
out, err = math.Floor(context.Background(), values.NewFloat(-2.50))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, -3)
|
||||
})
|
||||
}
|
60
pkg/stdlib/math/lib.go
Normal file
60
pkg/stdlib/math/lib.go
Normal file
@ -0,0 +1,60 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
RadToDeg = 180 / math.Pi
|
||||
DegToRad = math.Pi / 180
|
||||
RadToGrad = 200 / math.Pi
|
||||
GradToDeg = math.Pi / 200
|
||||
)
|
||||
|
||||
func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
"ABS": Abs,
|
||||
"ACOS": Acos,
|
||||
"ASIN": Asin,
|
||||
"ATAN": Atan,
|
||||
"ATAN2": Atan2,
|
||||
"AVERAGE": Average,
|
||||
"CEIL": Ceil,
|
||||
"COS": Cos,
|
||||
"DEGREES": Degrees,
|
||||
"EXP": Exp,
|
||||
"EXP2": Exp2,
|
||||
"FLOOR": Floor,
|
||||
"LOG": Log,
|
||||
"LOG2": Log2,
|
||||
"LOG10": Log10,
|
||||
"MAX": Max,
|
||||
"MEDIAN": Median,
|
||||
"MIN": Min,
|
||||
"PERCENTILE": Percentile,
|
||||
"PI": Pi,
|
||||
"POW": Pow,
|
||||
"RADIANS": Radians,
|
||||
"RAND": Rand,
|
||||
"RANGE": Range,
|
||||
"ROUND": Round,
|
||||
"SIN": Sin,
|
||||
"SQRT": Sqrt,
|
||||
"STDDEV_POPULATION": StandardDeviationPopulation,
|
||||
"STDDEV_SAMPLE": StandardDeviationSample,
|
||||
"SUM": Sum,
|
||||
"TAN": Tan,
|
||||
"VARIANCE_POPULATION": PopulationVariance,
|
||||
"VARIANCE_SAMPLE": SampleVariance,
|
||||
}
|
||||
}
|
||||
|
||||
func toFloat(arg core.Value) float64 {
|
||||
if arg.Type() == core.IntType {
|
||||
return float64(arg.(values.Int))
|
||||
}
|
||||
|
||||
return float64(arg.(values.Float))
|
||||
}
|
29
pkg/stdlib/math/log.go
Normal file
29
pkg/stdlib/math/log.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the natural logarithm of a given value.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The natural logarithm of a given value.
|
||||
*/
|
||||
func Log(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Log(toFloat(args[0]))), nil
|
||||
}
|
29
pkg/stdlib/math/log10.go
Normal file
29
pkg/stdlib/math/log10.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the decimal logarithm of a given value.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The decimal logarithm of a given value.
|
||||
*/
|
||||
func Log10(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Log10(toFloat(args[0]))), nil
|
||||
}
|
29
pkg/stdlib/math/log10_test.go
Normal file
29
pkg/stdlib/math/log10_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestLog10(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Log10(context.Background(), values.NewFloat(10000))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 4)
|
||||
|
||||
out, err = math.Log10(context.Background(), values.NewFloat(10))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1)
|
||||
|
||||
out, err = math.Log10(context.Background(), values.NewFloat(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(values.IsInf(out.(values.Float), -1).Unwrap(), ShouldBeTrue)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/log2.go
Normal file
29
pkg/stdlib/math/log2.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the binary logarithm of a given value.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The binary logarithm of a given value.
|
||||
*/
|
||||
func Log2(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Log2(toFloat(args[0]))), nil
|
||||
}
|
29
pkg/stdlib/math/log2_test.go
Normal file
29
pkg/stdlib/math/log2_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestLog2(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Log2(context.Background(), values.NewFloat(1024))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 10)
|
||||
|
||||
out, err = math.Log2(context.Background(), values.NewFloat(8))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 3)
|
||||
|
||||
out, err = math.Log2(context.Background(), values.NewFloat(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(values.IsInf(out.(values.Float), -1).Unwrap(), ShouldBeTrue)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/log_test.go
Normal file
29
pkg/stdlib/math/log_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestLog(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Log(context.Background(), values.NewFloat(2.718281828459045))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1)
|
||||
|
||||
out, err = math.Log(context.Background(), values.NewFloat(10))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2.302585092994046)
|
||||
|
||||
out, err = math.Log(context.Background(), values.NewFloat(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(values.IsInf(out.(values.Float), -1).Unwrap(), ShouldBeTrue)
|
||||
})
|
||||
}
|
57
pkg/stdlib/math/max.go
Normal file
57
pkg/stdlib/math/max.go
Normal file
@ -0,0 +1,57 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the greatest (arithmetic mean) of the values in array.
|
||||
* @param array (Array) - Array of numbers.
|
||||
* @returns (Float) - The greatest of the values in array.
|
||||
*/
|
||||
func Max(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
var max float64
|
||||
|
||||
arr.ForEach(func(value core.Value, idx int) bool {
|
||||
err = core.ValidateType(value, core.FloatType, core.IntType)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
fv := toFloat(value)
|
||||
|
||||
if fv > max {
|
||||
max = fv
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
return values.NewFloat(max), nil
|
||||
}
|
47
pkg/stdlib/math/max_test.go
Normal file
47
pkg/stdlib/math/max_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestMax(t *testing.T) {
|
||||
Convey("Should return the largest value", t, func() {
|
||||
out, err := math.Max(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(5),
|
||||
values.NewInt(2),
|
||||
values.NewInt(9),
|
||||
values.NewInt(2),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 9)
|
||||
|
||||
out, err = math.Max(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(-3),
|
||||
values.NewInt(-5),
|
||||
values.NewInt(2),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2)
|
||||
|
||||
out, err = math.Max(context.Background(), values.NewArrayWith(
|
||||
values.None,
|
||||
values.NewInt(-5),
|
||||
values.False,
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, values.None)
|
||||
|
||||
out, err = math.Max(context.Background(), values.NewArray(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, values.None)
|
||||
})
|
||||
}
|
34
pkg/stdlib/math/mean.go
Normal file
34
pkg/stdlib/math/mean.go
Normal file
@ -0,0 +1,34 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
func mean(input *values.Array) (values.Float, error) {
|
||||
if input.Length() == 0 {
|
||||
return values.NewFloat(math.NaN()), nil
|
||||
}
|
||||
|
||||
var err error
|
||||
var sum float64
|
||||
|
||||
input.ForEach(func(value core.Value, idx int) bool {
|
||||
err = core.ValidateType(value, core.FloatType, core.IntType)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
sum += toFloat(value)
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return values.NewFloat(sum / float64(input.Length())), nil
|
||||
}
|
53
pkg/stdlib/math/median.go
Normal file
53
pkg/stdlib/math/median.go
Normal file
@ -0,0 +1,53 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the median of the values in array.
|
||||
* @param array (Array) - Array of numbers.
|
||||
* @returns (Float) - The median of the values in array.
|
||||
*/
|
||||
func Median(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
sorted := arr.Sort()
|
||||
|
||||
l := sorted.Length()
|
||||
|
||||
var median core.Value
|
||||
|
||||
if l == 0 {
|
||||
return values.NewFloat(math.NaN()), nil
|
||||
} else if l%2 == 0 {
|
||||
median, err = mean(sorted.Slice(l/2-1, l/2+1))
|
||||
|
||||
if err != nil {
|
||||
return values.None, nil
|
||||
}
|
||||
} else {
|
||||
median = sorted.Get(l / 2)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
return median, nil
|
||||
}
|
52
pkg/stdlib/math/median_test.go
Normal file
52
pkg/stdlib/math/median_test.go
Normal file
@ -0,0 +1,52 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestMedian(t *testing.T) {
|
||||
Convey("Should return median value", t, func() {
|
||||
out, err := math.Median(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
values.NewInt(2),
|
||||
values.NewInt(3),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2)
|
||||
|
||||
out, err = math.Average(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
values.NewInt(2),
|
||||
values.NewInt(3),
|
||||
values.NewInt(4),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2.5)
|
||||
|
||||
out, err = math.Average(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(2),
|
||||
values.NewInt(1),
|
||||
values.NewInt(4),
|
||||
values.NewInt(3),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2.5)
|
||||
|
||||
out, err = math.Average(context.Background(), values.NewArrayWith(
|
||||
values.None,
|
||||
values.NewInt(-5),
|
||||
values.False,
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, values.None)
|
||||
})
|
||||
}
|
57
pkg/stdlib/math/min.go
Normal file
57
pkg/stdlib/math/min.go
Normal file
@ -0,0 +1,57 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the smallest (arithmetic mean) of the values in array.
|
||||
* @param array (Array) - Array of numbers.
|
||||
* @returns (Float) - The smallest of the values in array.
|
||||
*/
|
||||
func Min(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
var min float64
|
||||
|
||||
arr.ForEach(func(value core.Value, idx int) bool {
|
||||
err = core.ValidateType(value, core.FloatType, core.IntType)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
fv := toFloat(value)
|
||||
|
||||
if min > fv || idx == 0 {
|
||||
min = fv
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
return values.NewFloat(min), nil
|
||||
}
|
47
pkg/stdlib/math/min_test.go
Normal file
47
pkg/stdlib/math/min_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestMin(t *testing.T) {
|
||||
Convey("Should return the smallest value", t, func() {
|
||||
out, err := math.Min(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(5),
|
||||
values.NewInt(2),
|
||||
values.NewInt(9),
|
||||
values.NewInt(2),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2)
|
||||
|
||||
out, err = math.Min(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(-3),
|
||||
values.NewInt(-5),
|
||||
values.NewInt(2),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, -5)
|
||||
|
||||
out, err = math.Min(context.Background(), values.NewArrayWith(
|
||||
values.None,
|
||||
values.NewInt(-5),
|
||||
values.False,
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, values.None)
|
||||
|
||||
out, err = math.Min(context.Background(), values.NewArray(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, values.None)
|
||||
})
|
||||
}
|
92
pkg/stdlib/math/percentile.go
Normal file
92
pkg/stdlib/math/percentile.go
Normal file
@ -0,0 +1,92 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/pkg/errors"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the nth percentile of the values in a given array.
|
||||
* @param array (Array) - Array of numbers.
|
||||
* @param numb (Int) - A number which must be between 0 (excluded) and 100 (included).
|
||||
* @param method (String, optional) - "rank" (default) or "interpolation".
|
||||
* @returns (Float) - The nth percentile, or null if the array is empty or only null values are contained in it or the percentile cannot be calculated.
|
||||
*/
|
||||
func Percentile(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 2, 3)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[1], core.IntType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
// TODO: Implement different methods
|
||||
//method := "rank"
|
||||
//
|
||||
//if len(args) > 2 {
|
||||
// err = core.ValidateType(args[2], core.StringType)
|
||||
//
|
||||
// if err != nil {
|
||||
// return values.None, err
|
||||
// }
|
||||
//
|
||||
// if args[2].String() == "interpolation" {
|
||||
// method = "interpolation"
|
||||
// }
|
||||
//}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
percent := values.Float(args[1].(values.Int))
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.NewFloat(math.NaN()), nil
|
||||
}
|
||||
|
||||
if percent <= 0 || percent > 100 {
|
||||
return values.NewFloat(math.NaN()), errors.New("input is outside of range")
|
||||
}
|
||||
|
||||
sorted := arr.Sort()
|
||||
|
||||
// Multiply percent by length of input
|
||||
l := values.Float(sorted.Length())
|
||||
index := (percent / 100) * l
|
||||
even := values.Float(values.Int(index))
|
||||
|
||||
var percentile core.Value
|
||||
|
||||
// Check if the index is a whole number
|
||||
if index == even {
|
||||
|
||||
// Convert float to int
|
||||
i := values.Int(index)
|
||||
|
||||
// Find the value at the index
|
||||
percentile = sorted.Get(i - 1)
|
||||
} else if index > 1 {
|
||||
|
||||
// Convert float to int via truncation
|
||||
i := values.Int(index)
|
||||
|
||||
// Find the average of the index and following values
|
||||
percentile, _ = mean(values.NewArrayWith(sorted.Get(i-1), sorted.Get(i)))
|
||||
} else {
|
||||
return values.NewFloat(math.NaN()), errors.New("input is outside of range")
|
||||
}
|
||||
|
||||
return percentile, nil
|
||||
}
|
28
pkg/stdlib/math/percentile_test.go
Normal file
28
pkg/stdlib/math/percentile_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestPrecentile(t *testing.T) {
|
||||
Convey("Should return nth percentile value", t, func() {
|
||||
out, err := math.Percentile(
|
||||
context.Background(),
|
||||
values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
values.NewInt(2),
|
||||
values.NewInt(3),
|
||||
values.NewInt(4),
|
||||
),
|
||||
values.NewInt(50),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2)
|
||||
})
|
||||
}
|
22
pkg/stdlib/math/pi.go
Normal file
22
pkg/stdlib/math/pi.go
Normal file
@ -0,0 +1,22 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns Pi value.
|
||||
* @returns (Float) - Pi value.
|
||||
*/
|
||||
func Pi(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 0, 0)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Pi), nil
|
||||
}
|
18
pkg/stdlib/math/pi_test.go
Normal file
18
pkg/stdlib/math/pi_test.go
Normal file
@ -0,0 +1,18 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
m "math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPi(t *testing.T) {
|
||||
Convey("Should return Pi value", t, func() {
|
||||
out, err := math.Pi(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, m.Pi)
|
||||
})
|
||||
}
|
36
pkg/stdlib/math/pow.go
Normal file
36
pkg/stdlib/math/pow.go
Normal file
@ -0,0 +1,36 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the base to the exponent value.
|
||||
* @param base (Int|Float) - The base value.
|
||||
* @param exp (Int|Float) - The exponent value.
|
||||
* @returns (Float) - The exponentiated value.
|
||||
*/
|
||||
func Pow(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 2, 2)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[1], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Pow(toFloat(args[0]), toFloat(args[1]))), nil
|
||||
}
|
29
pkg/stdlib/math/pow_test.go
Normal file
29
pkg/stdlib/math/pow_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestPow(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Pow(context.Background(), values.NewInt(2), values.NewInt(4))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 16)
|
||||
|
||||
out, err = math.Pow(context.Background(), values.NewInt(5), values.NewInt(-1))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 0.2)
|
||||
|
||||
out, err = math.Pow(context.Background(), values.NewInt(5), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1)
|
||||
})
|
||||
}
|
30
pkg/stdlib/math/radians.go
Normal file
30
pkg/stdlib/math/radians.go
Normal file
@ -0,0 +1,30 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the angle converted from degrees to radians.
|
||||
* @param number (Float|Int) - The input number.
|
||||
* @returns (Float) - The angle in radians.
|
||||
*/
|
||||
func Radians(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
r := toFloat(args[0])
|
||||
|
||||
return values.NewFloat(r * DegToRad), nil
|
||||
}
|
29
pkg/stdlib/math/radians_test.go
Normal file
29
pkg/stdlib/math/radians_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestRadians(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Radians(context.Background(), values.NewInt(180))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 3.141592653589793)
|
||||
|
||||
out, err = math.Radians(context.Background(), values.NewFloat(90))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1.5707963267948966)
|
||||
|
||||
out, err = math.Radians(context.Background(), values.NewFloat(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 0)
|
||||
})
|
||||
}
|
22
pkg/stdlib/math/rand.go
Normal file
22
pkg/stdlib/math/rand.go
Normal file
@ -0,0 +1,22 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
/*
|
||||
* Return a pseudo-random number between 0 and 1.
|
||||
* @returns (Float) - A number greater than 0 and less than 1.
|
||||
*/
|
||||
func Rand(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 0, 0)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(rand.Float64()), nil
|
||||
}
|
17
pkg/stdlib/math/rand_test.go
Normal file
17
pkg/stdlib/math/rand_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRand(t *testing.T) {
|
||||
Convey("Should return pseudo-random value", t, func() {
|
||||
out, err := math.Rand(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldBeLessThan, 1)
|
||||
})
|
||||
}
|
56
pkg/stdlib/math/range.go
Normal file
56
pkg/stdlib/math/range.go
Normal file
@ -0,0 +1,56 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns an array of numbers in the specified range, optionally with increments other than 1.
|
||||
* @param start (Int|Float) - The value to start the range at (inclusive).
|
||||
* @param end (Int|Float) - The value to end the range with (inclusive).
|
||||
* @param step (Int|Float, optional) - How much to increment in every step, the default is 1.0.
|
||||
*/
|
||||
func Range(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 2, 3)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[1], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
var step float64 = 1
|
||||
|
||||
if len(args) > 2 {
|
||||
err = core.ValidateType(args[2], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
step = toFloat(args[2])
|
||||
}
|
||||
|
||||
start := toFloat(args[0])
|
||||
end := toFloat(args[1])
|
||||
|
||||
arr := values.NewArray(int(end))
|
||||
|
||||
for i := start; i <= end; i += step {
|
||||
arr.Push(values.NewFloat(i))
|
||||
}
|
||||
|
||||
return arr, nil
|
||||
}
|
62
pkg/stdlib/math/range_test.go
Normal file
62
pkg/stdlib/math/range_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestRange(t *testing.T) {
|
||||
Convey("Should return range of numbers", t, func() {
|
||||
out, err := math.Range(context.Background(), values.NewInt(1), values.NewInt(4))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.String(), ShouldEqual, "[1,2,3,4]")
|
||||
|
||||
out, err = math.Range(context.Background(),
|
||||
values.NewInt(1),
|
||||
values.NewInt(4),
|
||||
values.NewInt(2))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.String(), ShouldEqual, "[1,3]")
|
||||
|
||||
out, err = math.Range(context.Background(),
|
||||
values.NewInt(1),
|
||||
values.NewInt(4),
|
||||
values.NewInt(3),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.String(), ShouldEqual, "[1,4]")
|
||||
|
||||
out, err = math.Range(context.Background(),
|
||||
values.NewFloat(1.5),
|
||||
values.NewFloat(2.5),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.String(), ShouldEqual, "[1.5,2.5]")
|
||||
|
||||
out, err = math.Range(context.Background(),
|
||||
values.NewFloat(1.5),
|
||||
values.NewFloat(2.5),
|
||||
values.NewFloat(0.5),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.String(), ShouldEqual, "[1.5,2,2.5]")
|
||||
|
||||
out, err = math.Range(context.Background(),
|
||||
values.NewFloat(-0.75),
|
||||
values.NewFloat(1.1),
|
||||
values.NewFloat(0.5),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.String(), ShouldEqual, "[-0.75,-0.25,0.25,0.75]")
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/round.go
Normal file
29
pkg/stdlib/math/round.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the nearest integer, rounding half away from zero.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Int) - The nearest integer, rounding half away from zero.
|
||||
*/
|
||||
func Round(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewInt(int(math.Round(toFloat(args[0])))), nil
|
||||
}
|
34
pkg/stdlib/math/round_test.go
Normal file
34
pkg/stdlib/math/round_test.go
Normal file
@ -0,0 +1,34 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestRound(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.Round(context.Background(), values.NewFloat(2.49))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 2)
|
||||
|
||||
out, err = math.Round(context.Background(), values.NewFloat(2.50))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 3)
|
||||
|
||||
out, err = math.Ceil(context.Background(), values.NewFloat(-2.50))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, -2)
|
||||
|
||||
out, err = math.Ceil(context.Background(), values.NewFloat(-2.49))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, -2)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/sin.go
Normal file
29
pkg/stdlib/math/sin.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the sine of the radian argument.
|
||||
* @param number (Int|Float) - Input number.
|
||||
* @returns (Float) - The sin, in radians, of a given number.
|
||||
*/
|
||||
func Sin(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Sin(toFloat(args[0]))), nil
|
||||
}
|
36
pkg/stdlib/math/sin_test.go
Normal file
36
pkg/stdlib/math/sin_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestSin(t *testing.T) {
|
||||
Convey("Should return sin value", t, func() {
|
||||
out, err := math.Sin(context.Background(), values.NewFloat(3.141592653589783/2))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1)
|
||||
|
||||
out, err = math.Sin(context.Background(), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 0)
|
||||
|
||||
out, err = math.Sin(context.Background(), values.NewFloat(-3.141592653589783/2))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, -1)
|
||||
|
||||
v, _ := math.Radians(context.Background(), values.NewInt(270))
|
||||
|
||||
out, err = math.Sin(context.Background(), v)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, -1)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/sqrt.go
Normal file
29
pkg/stdlib/math/sqrt.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the square root of a given number.
|
||||
* @param value (Int|Float) - A number.
|
||||
* @returns (Float) - The square root.
|
||||
*/
|
||||
func Sqrt(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Sqrt(toFloat(args[0]))), nil
|
||||
}
|
24
pkg/stdlib/math/sqrt_test.go
Normal file
24
pkg/stdlib/math/sqrt_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestSqrt(t *testing.T) {
|
||||
Convey("Should return square value", t, func() {
|
||||
out, err := math.Sqrt(context.Background(), values.NewFloat(9))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 3)
|
||||
|
||||
out, err = math.Sqrt(context.Background(), values.NewInt(2))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 1.4142135623730951)
|
||||
})
|
||||
}
|
42
pkg/stdlib/math/stddev_population.go
Normal file
42
pkg/stdlib/math/stddev_population.go
Normal file
@ -0,0 +1,42 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the population standard deviation of the values in a given array.
|
||||
* @params (Array) - Array of numbers.
|
||||
* @returns (Float) - The population standard deviation.
|
||||
*/
|
||||
func StandardDeviationPopulation(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.NewFloat(math.NaN()), nil
|
||||
}
|
||||
|
||||
vp, err := variance(arr, values.NewInt(0))
|
||||
|
||||
if err != nil {
|
||||
return values.NewFloat(math.NaN()), err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Pow(float64(vp), 0.5)), nil
|
||||
}
|
28
pkg/stdlib/math/stddev_population_test.go
Normal file
28
pkg/stdlib/math/stddev_population_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestStandardDeviationPopulation(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.StandardDeviationPopulation(
|
||||
context.Background(),
|
||||
values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
values.NewInt(3),
|
||||
values.NewInt(6),
|
||||
values.NewInt(5),
|
||||
values.NewInt(2),
|
||||
),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, 1.8547236990991407)
|
||||
})
|
||||
}
|
42
pkg/stdlib/math/stddev_sample.go
Normal file
42
pkg/stdlib/math/stddev_sample.go
Normal file
@ -0,0 +1,42 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the sample standard deviation of the values in a given array.
|
||||
* @params (Array) - Array of numbers.
|
||||
* @returns (Float) - The sample standard deviation.
|
||||
*/
|
||||
func StandardDeviationSample(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.NewFloat(math.NaN()), nil
|
||||
}
|
||||
|
||||
vp, err := variance(arr, values.NewInt(1))
|
||||
|
||||
if err != nil {
|
||||
return values.NewFloat(math.NaN()), err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Pow(float64(vp), 0.5)), nil
|
||||
}
|
28
pkg/stdlib/math/stddev_sample_test.go
Normal file
28
pkg/stdlib/math/stddev_sample_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestStandardDeviationSample(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.StandardDeviationSample(
|
||||
context.Background(),
|
||||
values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
values.NewInt(3),
|
||||
values.NewInt(6),
|
||||
values.NewInt(5),
|
||||
values.NewInt(2),
|
||||
),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, 2.073644135332772)
|
||||
})
|
||||
}
|
53
pkg/stdlib/math/sum.go
Normal file
53
pkg/stdlib/math/sum.go
Normal file
@ -0,0 +1,53 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the sum of the values in a given array.
|
||||
* @param array (Array) - Array of numbers.
|
||||
* @returns (Float) - The sum of the values.
|
||||
*/
|
||||
func Sum(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
var sum float64
|
||||
|
||||
arr.ForEach(func(value core.Value, idx int) bool {
|
||||
err = core.ValidateType(value, core.FloatType, core.IntType)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
sum += toFloat(value)
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return values.None, nil
|
||||
}
|
||||
|
||||
return values.NewFloat(sum), nil
|
||||
}
|
33
pkg/stdlib/math/sum_test.go
Normal file
33
pkg/stdlib/math/sum_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestSum(t *testing.T) {
|
||||
Convey("Should return sum of values", t, func() {
|
||||
out, err := math.Sum(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(5),
|
||||
values.NewInt(2),
|
||||
values.NewInt(9),
|
||||
values.NewInt(2),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 18)
|
||||
|
||||
out, err = math.Sum(context.Background(), values.NewArrayWith(
|
||||
values.NewInt(-3),
|
||||
values.NewInt(-5),
|
||||
values.NewInt(2),
|
||||
))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, -6)
|
||||
})
|
||||
}
|
29
pkg/stdlib/math/tan.go
Normal file
29
pkg/stdlib/math/tan.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the tangent of a given number.
|
||||
* @param value (Int|Float) - A number.
|
||||
* @returns (Float) - The tangent.
|
||||
*/
|
||||
func Tan(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
return values.NewFloat(math.Tan(toFloat(args[0]))), nil
|
||||
}
|
29
pkg/stdlib/math/tan_test.go
Normal file
29
pkg/stdlib/math/tan_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestTan(t *testing.T) {
|
||||
Convey("Should return tan value", t, func() {
|
||||
out, err := math.Tan(context.Background(), values.NewFloat(10))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, 0.6483608274590867)
|
||||
|
||||
out, err = math.Tan(context.Background(), values.NewInt(5))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, -3.3805150062465854)
|
||||
|
||||
out, err = math.Tan(context.Background(), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out, ShouldEqual, 0)
|
||||
})
|
||||
}
|
39
pkg/stdlib/math/variance.go
Normal file
39
pkg/stdlib/math/variance.go
Normal file
@ -0,0 +1,39 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
func variance(input *values.Array, sample values.Int) (values.Float, error) {
|
||||
if input.Length() == 0 {
|
||||
return values.NewFloat(math.NaN()), nil
|
||||
}
|
||||
|
||||
m, _ := mean(input)
|
||||
|
||||
var err error
|
||||
var variance values.Float
|
||||
|
||||
input.ForEach(func(value core.Value, idx int) bool {
|
||||
err = core.ValidateType(value, core.IntType, core.FloatType)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
n := values.Float(toFloat(value))
|
||||
|
||||
variance += (n - m) * (n - m)
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
// When getting the mean of the squared differences
|
||||
// "sample" will allow us to know if it's a sample
|
||||
// or population and wether to subtract by one or not
|
||||
l := values.Float(input.Length() - (1 * sample))
|
||||
|
||||
return variance / l, nil
|
||||
}
|
36
pkg/stdlib/math/variance_population.go
Normal file
36
pkg/stdlib/math/variance_population.go
Normal file
@ -0,0 +1,36 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the population variance of the values in a given array.
|
||||
* @params (Array) - Array of numbers.
|
||||
* @returns (Float) - The population variance.
|
||||
*/
|
||||
func PopulationVariance(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.NewFloat(math.NaN()), nil
|
||||
}
|
||||
|
||||
return variance(arr, values.NewInt(0))
|
||||
}
|
28
pkg/stdlib/math/variance_population_test.go
Normal file
28
pkg/stdlib/math/variance_population_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestPopulationVariance(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.PopulationVariance(
|
||||
context.Background(),
|
||||
values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
values.NewInt(3),
|
||||
values.NewInt(6),
|
||||
values.NewInt(5),
|
||||
values.NewInt(2),
|
||||
),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, 3.44)
|
||||
})
|
||||
}
|
36
pkg/stdlib/math/variance_sample.go
Normal file
36
pkg/stdlib/math/variance_sample.go
Normal file
@ -0,0 +1,36 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"math"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the sample variance of the values in a given array.
|
||||
* @params (Array) - Array of numbers.
|
||||
* @returns (Float) - The sample variance.
|
||||
*/
|
||||
func SampleVariance(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
var err error
|
||||
err = core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ArrayType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
arr := args[0].(*values.Array)
|
||||
|
||||
if arr.Length() == 0 {
|
||||
return values.NewFloat(math.NaN()), nil
|
||||
}
|
||||
|
||||
return variance(arr, values.NewInt(1))
|
||||
}
|
28
pkg/stdlib/math/variance_sample_test.go
Normal file
28
pkg/stdlib/math/variance_sample_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/math"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestSampleVariance(t *testing.T) {
|
||||
Convey("Should return a value", t, func() {
|
||||
out, err := math.SampleVariance(
|
||||
context.Background(),
|
||||
values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
values.NewInt(3),
|
||||
values.NewInt(6),
|
||||
values.NewInt(5),
|
||||
values.NewInt(2),
|
||||
),
|
||||
)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(out.Unwrap(), ShouldEqual, 4.3)
|
||||
})
|
||||
}
|
26
pkg/stdlib/types/is_nan.go
Normal file
26
pkg/stdlib/types/is_nan.go
Normal file
@ -0,0 +1,26 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Checks whether value is NaN.
|
||||
* @param value (Value) - Input value of arbitrary type.
|
||||
* @returns (Boolean) - Returns true if value is NaN, otherwise false.
|
||||
*/
|
||||
func IsNaN(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 1)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
if args[0].Type() != core.FloatType {
|
||||
return values.False, nil
|
||||
}
|
||||
|
||||
return values.IsNaN(args[0].(values.Float)), nil
|
||||
}
|
@ -24,6 +24,7 @@ func NewLib() map[string]core.Function {
|
||||
"IS_HTML_ELEMENT": IsHTMLElement,
|
||||
"IS_HTML_DOCUMENT": IsHTMLDocument,
|
||||
"IS_BINARY": IsBinary,
|
||||
"IS_NAN": IsNaN,
|
||||
"TYPENAME": TypeName,
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user