From bd59d9647c4fc2d422b2d8d5be3b54b2aa905d36 Mon Sep 17 00:00:00 2001 From: andig Date: Mon, 2 Dec 2024 05:21:46 +0100 Subject: [PATCH] Calc: add abs (#17530) --- provider/calc.go | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/provider/calc.go b/provider/calc.go index 3d8d3c613..fe1fb2844 100644 --- a/provider/calc.go +++ b/provider/calc.go @@ -4,13 +4,14 @@ import ( "context" "errors" "fmt" + "math" "github.com/evcc-io/evcc/util" ) type calcProvider struct { add, mul, div []func() (float64, error) - sign func() (float64, error) + abs, sign func() (float64, error) } func init() { @@ -23,6 +24,7 @@ func NewCalcFromConfig(ctx context.Context, other map[string]interface{}) (Provi Add []Config Mul []Config Div []Config + Abs *Config Sign *Config } @@ -30,13 +32,18 @@ func NewCalcFromConfig(ctx context.Context, other map[string]interface{}) (Provi return nil, err } - o := &calcProvider{} - if i := min(len(cc.Add), 1) + min(len(cc.Mul), 1) + min(len(cc.Div), 1); i > 1 || - (len(cc.Add) > 0 && cc.Sign != nil) || - (len(cc.Mul) > 0 && cc.Sign != nil) || - (len(cc.Div) > 0 && cc.Sign != nil) { - return nil, errors.New("can only have either add, mul, div or sign") + cnt := min(len(cc.Add), 1) + min(len(cc.Mul), 1) + min(len(cc.Div), 1) + if cc.Abs != nil { + cnt++ } + if cc.Sign != nil { + cnt++ + } + if cnt != 1 { + return nil, errors.New("can only have either add, mul, div, abs or sign") + } + + o := &calcProvider{} for idx, cc := range cc.Add { f, err := NewFloatGetterFromConfig(ctx, cc) @@ -62,6 +69,14 @@ func NewCalcFromConfig(ctx context.Context, other map[string]interface{}) (Provi o.div = append(o.div, f) } + if cc.Abs != nil { + f, err := NewFloatGetterFromConfig(ctx, *cc.Abs) + if err != nil { + return nil, fmt.Errorf("abs: %w", err) + } + o.abs = f + } + if cc.Sign != nil { f, err := NewFloatGetterFromConfig(ctx, *cc.Sign) if err != nil { @@ -139,12 +154,19 @@ func (o *calcProvider) floatGetter() (float64, error) { } } + case o.abs != nil: + v, err := o.abs() + if err != nil { + return 0, fmt.Errorf("abs: %w", err) + } + res = math.Abs(v) + default: v, err := o.sign() if err != nil { return 0, fmt.Errorf("sign: %w", err) } - res = map[bool]float64{false: -1, true: 1}[v >= 0] + res = math.Copysign(1, v) } return res, nil