diff --git a/function/math/README.md b/function/math/README.md new file mode 100644 index 0000000..3eda6ff --- /dev/null +++ b/function/math/README.md @@ -0,0 +1,119 @@ + + +# Math Functions +This function package exposes common math functions. + +## ceil() +Ceil returns the least integer value greater than or equal to input + +### Input Args + +| Arg | Type | Description | +|:------------|:-------|:-----------------| +| inputNumber | number | The input number | + +### Output + +| Arg | Type | Description | +|:----------|:-------|:-----------------------------------| +| returnVal | number | The ceil value of the input number | + + +## floor() +Floor returns the greatest integer value less than or equal to input + +### Input Args + +| Arg | Type | Description | +|:------------|:-------|:-----------------| +| inputNumber | number | The input number | + +### Output + +| Arg | Type | Description | +|:----------|:-------|:------------------------------------| +| returnVal | number | The floor value of the input number | + + +## isNaN() +IsNaN reports whether input is an IEEE 754 "not-a-number" value + +### Input Args + +| Arg | Type | Description | +|:------|:-------|:------------------| +| input | any | The input to test | + +### Output + +| Arg | Type | Description | +|:----------|:--------|:--------------------------------------------| +| returnVal | boolean | Is true if input is IEEE 754 "not-a-number" | + + +## mod() +Mod returns the floating-point remainder of x/y. The magnitude of the result is less than y and its sign agrees with that of x + +### Input Args + +| Arg | Type | Description | +|:----|:-------|:----------------------------| +| x | number | The dividend or first input | +| y | number | The divisor or second input | + +### Output + +| Arg | Type | Description | +|:----------|:-------|:--------------------------------------------------| +| returnVal | number | The remainder of the Euclidean division of x by y | + + +## round() +Round returns the nearest integer, rounding half away from zero + +### Input Args + +| Arg | Type | Description | +|:------------|:-------|:-----------------| +| inputNumber | number | The input number | + +### Output + +| Arg | Type | Description | +|:----------|:-------|:--------------------------------------------------| +| returnVal | number | The nearest integer, rounding half away from zero | + + +## roundToEven() +RoundToEven returns the nearest integer, rounding ties to even + +### Input Args + +| Arg | Type | Description | +|:------------|:-------|:-----------------| +| inputNumber | number | The input number | + +### Output + +| Arg | Type | Description | +|:----------|:-------|:-------------------------------------------| +| returnVal | number | The nearest integer, rounding ties to even | + + +## trunc() +Trunc returns the integer value of input + +### Input Args + +| Arg | Type | Description | +|:----|:-------|:----------------------------| +| inputNumber | number | The input number | + +### Output + +| Arg | Type | Description | +|:----------|:-------|:-----------------------------------------| +| returnVal | number | The truncated integer value of the input | \ No newline at end of file diff --git a/function/math/ceil.go b/function/math/ceil.go new file mode 100644 index 0000000..a3f7f65 --- /dev/null +++ b/function/math/ceil.go @@ -0,0 +1,36 @@ +package math + +import ( + "fmt" + "math" + + "github.com/project-flogo/core/data" + "github.com/project-flogo/core/data/coerce" + "github.com/project-flogo/core/data/expression/function" +) + +func init() { + _ = function.Register(&fnCeil{}) +} + +type fnCeil struct { +} + +// Name returns the name of the function +func (fnCeil) Name() string { + return "ceil" +} + +// Sig returns the function signature +func (fnCeil) Sig() (paramTypes []data.Type, isVariadic bool) { + return []data.Type{data.TypeFloat64}, false +} + +// Eval executes the function +func (fnCeil) Eval(params ...interface{}) (interface{}, error) { + obj, err := coerce.ToFloat64(params[0]) + if err != nil { + return nil, fmt.Errorf("Unable to coerce [%+v] to float64: %s", params[0], err.Error()) + } + return math.Ceil(obj), nil +} diff --git a/function/math/ceil_test.go b/function/math/ceil_test.go new file mode 100644 index 0000000..fd2b1df --- /dev/null +++ b/function/math/ceil_test.go @@ -0,0 +1,15 @@ +package math + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFnCeil(t *testing.T) { + input := 1.49 + f := &fnCeil{} + v, err := f.Eval(input) + assert.Nil(t, err) + assert.Equal(t, 2.0, v) +} diff --git a/function/math/descriptor.json b/function/math/descriptor.json new file mode 100644 index 0000000..f1140c0 --- /dev/null +++ b/function/math/descriptor.json @@ -0,0 +1,112 @@ +{ + "name": "math", + "type": "flogo:function", + "version": "0.1.0", + "title": "Math Functions", + "description": "Common Math Functions", + "homepage": "https://github.com/prject-flogo/contrib/tree/master/function/math", + "functions": [ + { + "name": "ceil", + "description": "Ceil returns the least integer value greater than or equal to input", + "example": "math.ceil(1.49) => 2.0", + "args": [ + { + "name": "inputNumber", + "type": "number" + } + ], + "return": { + "type": "number" + } + }, + { + "name": "floor", + "description": "Floor returns the greatest integer value less than or equal to input", + "example": "math.ceil(1.51) => 1.0", + "args": [ + { + "name": "inputNumber", + "type": "number" + } + ], + "return": { + "type": "number" + } + }, + { + "name": "isNaN", + "description": "IsNaN reports whether input is an IEEE 754 \"not-a-number\" value", + "example": "math.isNaN(1.0) => false", + "args": [ + { + "name": "input", + "type": "any" + } + ], + "return": { + "type": "boolean" + } + }, + { + "name": "mod", + "description": "Mod returns the floating-point remainder of x/y. The magnitude of the result is less than y and its sign agrees with that of x", + "example": "math.mod(7, 4) => 3.0", + "args": [ + { + "name": "x", + "type": "number" + }, + { + "name": "y", + "type": "number" + } + ], + "return": { + "type": "number" + } + }, + { + "name": "round", + "description": "Round returns the nearest integer, rounding half away from zero", + "example": "math.round(1.50) => 2.0", + "args": [ + { + "name": "inputNumber", + "type": "number" + } + ], + "return": { + "type": "number" + } + }, + { + "name": "roundToEven", + "description": "RoundToEven returns the nearest integer, rounding ties to even", + "example": "math.round(12.5) => 12.0", + "args": [ + { + "name": "inputNumber", + "type": "number" + } + ], + "return": { + "type": "number" + } + }, + { + "name": "trunc", + "description": "Trunc returns the integer value of input", + "example": "math.round(3.142) => 3.0", + "args": [ + { + "name": "inputNumber", + "type": "number" + } + ], + "return": { + "type": "number" + } + } + ] +} diff --git a/function/math/floor.go b/function/math/floor.go new file mode 100644 index 0000000..501366e --- /dev/null +++ b/function/math/floor.go @@ -0,0 +1,36 @@ +package math + +import ( + "fmt" + "math" + + "github.com/project-flogo/core/data" + "github.com/project-flogo/core/data/coerce" + "github.com/project-flogo/core/data/expression/function" +) + +func init() { + _ = function.Register(&fnFloor{}) +} + +type fnFloor struct { +} + +// Name returns the name of the function +func (fnFloor) Name() string { + return "floor" +} + +// Sig returns the function signature +func (fnFloor) Sig() (paramTypes []data.Type, isVariadic bool) { + return []data.Type{data.TypeFloat64}, false +} + +// Eval executes the function +func (fnFloor) Eval(params ...interface{}) (interface{}, error) { + obj, err := coerce.ToFloat64(params[0]) + if err != nil { + return nil, fmt.Errorf("Unable to coerce [%+v] to float64: %s", params[0], err.Error()) + } + return math.Floor(obj), nil +} diff --git a/function/math/floor_test.go b/function/math/floor_test.go new file mode 100644 index 0000000..1241840 --- /dev/null +++ b/function/math/floor_test.go @@ -0,0 +1,15 @@ +package math + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFnFloor(t *testing.T) { + input := 1.51 + f := &fnFloor{} + v, err := f.Eval(input) + assert.Nil(t, err) + assert.Equal(t, 1.0, v) +} diff --git a/function/math/go.mod b/function/math/go.mod new file mode 100644 index 0000000..0a14364 --- /dev/null +++ b/function/math/go.mod @@ -0,0 +1,8 @@ +module github.com/project-flogo/contrib/function/math + +go 1.16 + +require ( + github.com/project-flogo/core v1.5.0 + github.com/stretchr/testify v1.7.0 +) diff --git a/function/math/go.sum b/function/math/go.sum new file mode 100644 index 0000000..58e1bcb --- /dev/null +++ b/function/math/go.sum @@ -0,0 +1,66 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195 h1:c4mLfegoDw6OhSJXTd2jUEQgZUQuJWtocudb97Qn9EM= +github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/project-flogo/core v1.5.0 h1:g8KuSBMSWJTCvSy6jkc/+/8lo80r7qXBO34yezqvkeU= +github.com/project-flogo/core v1.5.0/go.mod h1:fapTXUhLxDeAHyb6eMkuwnYswO8FpZJAMat055QVdJE= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/function/math/isnan.go b/function/math/isnan.go new file mode 100644 index 0000000..c887ea3 --- /dev/null +++ b/function/math/isnan.go @@ -0,0 +1,67 @@ +package math + +import ( + "encoding/json" + "fmt" + "math" + + "github.com/project-flogo/core/data" + "github.com/project-flogo/core/data/expression/function" +) + +func init() { + _ = function.Register(&fnIsNaN{}) +} + +type fnIsNaN struct { +} + +// Name returns the name of the function +func (fnIsNaN) Name() string { + return "isNaN" +} + +// Sig returns the function signature +func (fnIsNaN) Sig() (paramTypes []data.Type, isVariadic bool) { + return []data.Type{data.TypeFloat64}, false +} + +// Eval executes the function +func (fnIsNaN) Eval(params ...interface{}) (interface{}, error) { + input, err := coerceToFloat64(params[0]) + if err != nil { + return true, err + } + return math.IsNaN(input), nil +} + +func coerceToFloat64(input interface{}) (float64, error) { + switch t := input.(type) { + case float32: + return float64(t), nil + case float64: + return t, nil + case int: + return float64(t), nil + case int8: + return float64(t), nil + case int32: + return float64(t), nil + case int64: + return float64(t), nil + case uint: + return float64(t), nil + case uint8: + return float64(t), nil + case uint16: + return float64(t), nil + case uint32: + return float64(t), nil + case uint64: + return float64(t), nil + case json.Number: + return t.Float64() + default: + return 0.0, fmt.Errorf("Unable to coerce %#v to float64", input) + } +} diff --git a/function/math/isnan_test.go b/function/math/isnan_test.go new file mode 100644 index 0000000..7ea9ad3 --- /dev/null +++ b/function/math/isnan_test.go @@ -0,0 +1,15 @@ +package math + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFnIsNaN(t *testing.T) { + input := 1.0 + f := &fnIsNaN{} + v, err := f.Eval(input) + assert.Nil(t, err) + assert.Equal(t, false, v) +} diff --git a/function/math/mod.go b/function/math/mod.go new file mode 100644 index 0000000..658e56c --- /dev/null +++ b/function/math/mod.go @@ -0,0 +1,40 @@ +package math + +import ( + "fmt" + "math" + + "github.com/project-flogo/core/data" + "github.com/project-flogo/core/data/coerce" + "github.com/project-flogo/core/data/expression/function" +) + +func init() { + _ = function.Register(&fnMod{}) +} + +type fnMod struct { +} + +// Name returns the name of the function +func (fnMod) Name() string { + return "mod" +} + +// Sig returns the function signature +func (fnMod) Sig() (paramTypes []data.Type, isVariadic bool) { + return []data.Type{data.TypeFloat64, data.TypeFloat64}, false +} + +// Eval executes the function +func (fnMod) Eval(params ...interface{}) (interface{}, error) { + x, err := coerce.ToFloat64(params[0]) + if err != nil { + return nil, fmt.Errorf("Unable to coerce [%+v] to float64: %s", params[0], err.Error()) + } + y, err := coerce.ToFloat64(params[1]) + if err != nil { + return nil, fmt.Errorf("Unable to coerce [%+v] to float64: %s", params[0], err.Error()) + } + return math.Mod(x, y), nil +} diff --git a/function/math/mod_test.go b/function/math/mod_test.go new file mode 100644 index 0000000..ba003fe --- /dev/null +++ b/function/math/mod_test.go @@ -0,0 +1,16 @@ +package math + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFnMod(t *testing.T) { + input1 := 7.0 + input2 := 4.0 + f := &fnMod{} + v, err := f.Eval(input1, input2) + assert.Nil(t, err) + assert.Equal(t, 3.0, v) +} diff --git a/function/math/round.go b/function/math/round.go new file mode 100644 index 0000000..f87764e --- /dev/null +++ b/function/math/round.go @@ -0,0 +1,36 @@ +package math + +import ( + "fmt" + "math" + + "github.com/project-flogo/core/data" + "github.com/project-flogo/core/data/coerce" + "github.com/project-flogo/core/data/expression/function" +) + +func init() { + _ = function.Register(&fnRound{}) +} + +type fnRound struct { +} + +// Name returns the name of the function +func (fnRound) Name() string { + return "round" +} + +// Sig returns the function signature +func (fnRound) Sig() (paramTypes []data.Type, isVariadic bool) { + return []data.Type{data.TypeFloat64}, false +} + +// Eval executes the function +func (fnRound) Eval(params ...interface{}) (interface{}, error) { + obj, err := coerce.ToFloat64(params[0]) + if err != nil { + return nil, fmt.Errorf("Unable to coerce [%+v] to float64: %s", params[0], err.Error()) + } + return math.Round(obj), nil +} diff --git a/function/math/round_test.go b/function/math/round_test.go new file mode 100644 index 0000000..527b579 --- /dev/null +++ b/function/math/round_test.go @@ -0,0 +1,23 @@ +package math + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFnRoundDown(t *testing.T) { + input := 1.49 + f := &fnRound{} + v, err := f.Eval(input) + assert.Nil(t, err) + assert.Equal(t, 1.0, v) +} + +func TestFnRoundUp(t *testing.T) { + input := 1.50 + f := &fnRound{} + v, err := f.Eval(input) + assert.Nil(t, err) + assert.Equal(t, 2.0, v) +} diff --git a/function/math/roundtoeven.go b/function/math/roundtoeven.go new file mode 100644 index 0000000..89d2dfa --- /dev/null +++ b/function/math/roundtoeven.go @@ -0,0 +1,36 @@ +package math + +import ( + "fmt" + "math" + + "github.com/project-flogo/core/data" + "github.com/project-flogo/core/data/coerce" + "github.com/project-flogo/core/data/expression/function" +) + +func init() { + _ = function.Register(&fnRoundToEven{}) +} + +type fnRoundToEven struct { +} + +// Name returns the name of the function +func (fnRoundToEven) Name() string { + return "roundToEven" +} + +// Sig returns the function signature +func (fnRoundToEven) Sig() (paramTypes []data.Type, isVariadic bool) { + return []data.Type{data.TypeFloat64}, false +} + +// Eval executes the function +func (fnRoundToEven) Eval(params ...interface{}) (interface{}, error) { + obj, err := coerce.ToFloat64(params[0]) + if err != nil { + return nil, fmt.Errorf("Unable to coerce [%+v] to float64: %s", params[0], err.Error()) + } + return math.RoundToEven(obj), nil +} diff --git a/function/math/roundtoeven_test.go b/function/math/roundtoeven_test.go new file mode 100644 index 0000000..ca72a2d --- /dev/null +++ b/function/math/roundtoeven_test.go @@ -0,0 +1,15 @@ +package math + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFnRoundToEven(t *testing.T) { + input := 12.50 + f := &fnRoundToEven{} + v, err := f.Eval(input) + assert.Nil(t, err) + assert.Equal(t, 12.0, v) +} diff --git a/function/math/trunc.go b/function/math/trunc.go new file mode 100644 index 0000000..4842db6 --- /dev/null +++ b/function/math/trunc.go @@ -0,0 +1,36 @@ +package math + +import ( + "fmt" + "math" + + "github.com/project-flogo/core/data" + "github.com/project-flogo/core/data/coerce" + "github.com/project-flogo/core/data/expression/function" +) + +func init() { + _ = function.Register(&fnTrunc{}) +} + +type fnTrunc struct { +} + +// Name returns the name of the function +func (fnTrunc) Name() string { + return "trunc" +} + +// Sig returns the function signature +func (fnTrunc) Sig() (paramTypes []data.Type, isVariadic bool) { + return []data.Type{data.TypeFloat64}, false +} + +// Eval executes the function +func (fnTrunc) Eval(params ...interface{}) (interface{}, error) { + obj, err := coerce.ToFloat64(params[0]) + if err != nil { + return nil, fmt.Errorf("Unable to coerce [%+v] to float64: %s", params[0], err.Error()) + } + return math.Trunc(obj), nil +} diff --git a/function/math/trunc_test.go b/function/math/trunc_test.go new file mode 100644 index 0000000..dcc8ffc --- /dev/null +++ b/function/math/trunc_test.go @@ -0,0 +1,15 @@ +package math + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFnTrunc(t *testing.T) { + input := 3.142 + f := &fnTrunc{} + v, err := f.Eval(input) + assert.Nil(t, err) + assert.Equal(t, 3.0, v) +}