2024-04-13 06:00:22 +02:00
|
|
|
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
|
|
// All rights reserved.
|
|
|
|
|
2024-03-30 07:01:00 +01:00
|
|
|
// funcs-math.go
|
|
|
|
package expr
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
|
|
|
func checkNumberParamExpected(funcName string, paramValue any, paramPos int) (err error) {
|
|
|
|
if !(isNumber(paramValue) || isList(paramValue)) {
|
|
|
|
err = fmt.Errorf("%s(): param nr %d has wrong type %T, number expected", funcName, paramPos+1, paramValue)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-08 23:17:56 +02:00
|
|
|
func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) {
|
2024-03-30 07:01:00 +01:00
|
|
|
var sumAsFloat = false
|
|
|
|
var floatSum float64 = 0.0
|
|
|
|
var intSum int64 = 0
|
|
|
|
var v any
|
|
|
|
|
|
|
|
for v, err = it.Next(); err == nil; v, err = it.Next() {
|
2024-04-26 04:47:59 +02:00
|
|
|
if subIter, ok := v.(Iterator); ok {
|
|
|
|
if v, err = doAdd(ctx, name, subIter); err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err = checkNumberParamExpected(name, v, it.Index()); err != nil {
|
2024-03-30 07:01:00 +01:00
|
|
|
break
|
|
|
|
}
|
2024-04-26 04:47:59 +02:00
|
|
|
if array, ok := v.([]any); ok {
|
|
|
|
if v, err = doAdd(ctx, name, NewFlatArrayIterator(array)); err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2024-03-30 07:01:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if !sumAsFloat && isFloat(v) {
|
|
|
|
sumAsFloat = true
|
|
|
|
floatSum = float64(intSum)
|
|
|
|
}
|
|
|
|
if sumAsFloat {
|
|
|
|
floatSum += numAsFloat(v)
|
|
|
|
} else {
|
|
|
|
iv, _ := v.(int64)
|
|
|
|
intSum += iv
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err == nil || err == io.EOF {
|
|
|
|
err = nil
|
|
|
|
if sumAsFloat {
|
|
|
|
result = floatSum
|
|
|
|
} else {
|
|
|
|
result = intSum
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-08 23:17:56 +02:00
|
|
|
func addFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
2024-03-30 07:01:00 +01:00
|
|
|
result, err = doAdd(ctx, name, NewFlatArrayIterator(args))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-08 23:17:56 +02:00
|
|
|
func doMul(ctx ExprContext, name string, it Iterator) (result any, err error) {
|
2024-03-30 07:01:00 +01:00
|
|
|
var mulAsFloat = false
|
|
|
|
var floatProd float64 = 1.0
|
|
|
|
var intProd int64 = 1
|
|
|
|
var v any
|
|
|
|
|
|
|
|
for v, err = it.Next(); err == nil; v, err = it.Next() {
|
|
|
|
if err = checkNumberParamExpected(name, v, it.Index()); err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if array, ok := v.([]any); ok {
|
|
|
|
if v, err = doAdd(ctx, name, NewFlatArrayIterator(array)); err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !mulAsFloat && isFloat(v) {
|
|
|
|
mulAsFloat = true
|
|
|
|
floatProd = float64(intProd)
|
|
|
|
}
|
|
|
|
if mulAsFloat {
|
|
|
|
floatProd *= numAsFloat(v)
|
|
|
|
} else {
|
|
|
|
iv, _ := v.(int64)
|
|
|
|
intProd *= iv
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err == nil || err == io.EOF {
|
|
|
|
err = nil
|
|
|
|
if mulAsFloat {
|
|
|
|
result = floatProd
|
|
|
|
} else {
|
|
|
|
result = intProd
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-08 23:17:56 +02:00
|
|
|
func mulFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
2024-03-30 07:01:00 +01:00
|
|
|
result, err = doMul(ctx, name, NewFlatArrayIterator(args))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-04-13 04:18:14 +02:00
|
|
|
func ImportMathFuncs(ctx ExprContext) {
|
2024-04-02 04:36:03 +02:00
|
|
|
ctx.RegisterFunc("add", &simpleFunctor{f: addFunc}, 0, -1)
|
|
|
|
ctx.RegisterFunc("mul", &simpleFunctor{f: mulFunc}, 0, -1)
|
2024-03-30 07:01:00 +01:00
|
|
|
}
|
2024-04-19 00:18:23 +02:00
|
|
|
|
|
|
|
func init() {
|
2024-04-28 05:41:13 +02:00
|
|
|
registerImport("math.arith", ImportMathFuncs, "Function add() and mul()")
|
2024-04-19 00:18:23 +02:00
|
|
|
}
|