Feature/mathandreduce (#41608)

* Added new math functions: round, ceil, floor 
* Added a new reduce function: last.
This commit is contained in:
Marius Bezuidenhout
2022-01-21 20:15:50 +02:00
committed by GitHub
parent 5d0bc9e933
commit 9fc0aee02b
6 changed files with 98 additions and 1 deletions

View File

@@ -53,6 +53,21 @@ var builtins = map[string]parse.Func{
VariantReturn: true,
F: isNumber,
},
"round": {
Args: []parse.ReturnType{parse.TypeVariantSet},
VariantReturn: true,
F: round,
},
"ceil": {
Args: []parse.ReturnType{parse.TypeVariantSet},
VariantReturn: true,
F: ceil,
},
"floor": {
Args: []parse.ReturnType{parse.TypeVariantSet},
VariantReturn: true,
F: floor,
},
}
// abs returns the absolute value for each result in NumberSet, SeriesSet, or Scalar
@@ -253,3 +268,42 @@ func perNullableFloat(e *State, val Value, floatF func(x *float64) *float64) (Va
return newVal, nil
}
// round returns the rounded value for each result in NumberSet, SeriesSet, or Scalar
func round(e *State, varSet Results) (Results, error) {
newRes := Results{}
for _, res := range varSet.Values {
newVal, err := perFloat(e, res, math.Round)
if err != nil {
return newRes, err
}
newRes.Values = append(newRes.Values, newVal)
}
return newRes, nil
}
// ceil returns the rounded up value for each result in NumberSet, SeriesSet, or Scalar
func ceil(e *State, varSet Results) (Results, error) {
newRes := Results{}
for _, res := range varSet.Values {
newVal, err := perFloat(e, res, math.Ceil)
if err != nil {
return newRes, err
}
newRes.Values = append(newRes.Values, newVal)
}
return newRes, nil
}
// floor returns the rounded down value for each result in NumberSet, SeriesSet, or Scalar
func floor(e *State, varSet Results) (Results, error) {
newRes := Results{}
for _, res := range varSet.Values {
newVal, err := perFloat(e, res, math.Floor)
if err != nil {
return newRes, err
}
newRes.Values = append(newRes.Values, newVal)
}
return newRes, nil
}

View File

@@ -69,6 +69,17 @@ func Count(fv *Float64Field) *float64 {
return &f
}
func Last(fv *Float64Field) *float64 {
var f float64
if fv.Len() == 0 {
f = math.NaN()
return &f
}
v := fv.GetValue(fv.Len() - 1)
f = *v
return &f
}
// Reduce turns the Series into a Number based on the given reduction function
func (s Series) Reduce(refID, rFunc string) (Number, error) {
var l data.Labels
@@ -90,6 +101,8 @@ func (s Series) Reduce(refID, rFunc string) (Number, error) {
f = Max(&floatField)
case "count":
f = Count(&floatField)
case "last":
f = Last(&floatField)
default:
return number, fmt.Errorf("reduction %v not implemented", rFunc)
}

View File

@@ -214,6 +214,19 @@ func TestSeriesReduce(t *testing.T) {
},
},
},
{
name: "last empty series",
red: "last",
varToReduce: "A",
vars: seriesEmpty,
errIs: require.NoError,
resultsIs: require.Equal,
results: Results{
[]Value{
makeNumber("", nil, NaN),
},
},
},
}
for _, tt := range tests {