diff --git a/runtime/vam/expr/function/function.go b/runtime/vam/expr/function/function.go index 0ca7eb3feb..df5d53c7e7 100644 --- a/runtime/vam/expr/function/function.go +++ b/runtime/vam/expr/function/function.go @@ -24,6 +24,8 @@ func New(zctx *super.Context, name string, narg int) (expr.Function, field.Path, argmin = 2 argmax = 2 f = &Bucket{zctx: zctx, name: name} + case "ceil": + f = &Ceil{zctx} case "coalesce": argmax = -1 f = &Coalesce{} diff --git a/runtime/vam/expr/function/math.go b/runtime/vam/expr/function/math.go index d6b37fae62..a33b3d94ff 100644 --- a/runtime/vam/expr/function/math.go +++ b/runtime/vam/expr/function/math.go @@ -60,3 +60,39 @@ func (a *Abs) abs(vec vector.Any) vector.Any { panic(vec) } } + +// https://github.com/brimdata/super/blob/main/docs/language/functions.md#ceil +type Ceil struct { + zctx *super.Context +} + +func (c *Ceil) Call(args ...vector.Any) vector.Any { + vec := vector.Under(args[0]) + switch id := vec.Type().ID(); { + case super.IsFloat(id): + return c.ceil(vec) + case super.IsNumber(id): + return vec + } + return vector.NewWrappedError(c.zctx, "ceil: not a number", vec) +} + +func (c *Ceil) ceil(vec vector.Any) vector.Any { + switch vec := vec.(type) { + case *vector.Const: + val := super.NewFloat(vec.Type(), math.Ceil(vec.Value().Float())) + return vector.NewConst(val, vec.Len(), vec.Nulls) + case *vector.View: + return vector.NewView(c.ceil(vec.Any), vec.Index) + case *vector.Dict: + return vector.NewDict(c.ceil(vec.Any), vec.Index, vec.Counts, vec.Nulls) + case *vector.Float: + var floats []float64 + for _, v := range vec.Values { + floats = append(floats, math.Ceil(v)) + } + return vector.NewFloat(vec.Type(), floats, vec.Nulls) + default: + panic(vec) + } +} diff --git a/runtime/ztests/expr/function/ceil.yaml b/runtime/ztests/expr/function/ceil.yaml new file mode 100644 index 0000000000..cb7e8f80da --- /dev/null +++ b/runtime/ztests/expr/function/ceil.yaml @@ -0,0 +1,17 @@ +zed: ceil(this) + +vector: true + +input: | + 1.5 + -1.5 + 1(uint8) + 1.5(float32) + "foo" + +output: | + 2. + -1. + 1(uint8) + 2.(float32) + error({message:"ceil: not a number",on:"foo"})