From 5809de419f19cc98824f480e0b43f21be63739e8 Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Wed, 1 May 2024 21:53:54 +0200 Subject: [PATCH] func-math.go: mul() and add() now support fractions --- func-math.go | 87 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 17 deletions(-) diff --git a/func-math.go b/func-math.go index a08c06c..60976f8 100644 --- a/func-math.go +++ b/func-math.go @@ -10,16 +10,17 @@ import ( ) func checkNumberParamExpected(funcName string, paramValue any, paramPos int) (err error) { - if !(isNumber(paramValue) || isList(paramValue) || isIterator(paramValue)) { + if !(isNumber(paramValue) || isList(paramValue) || isFraction(paramValue)) { err = fmt.Errorf("%s(): param nr %d has wrong type %T, number expected", funcName, paramPos+1, paramValue) } return } func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) { - var sumAsFloat = false + var sumAsFloat, sumAsFract bool var floatSum float64 = 0.0 var intSum int64 = 0 + var fractSum *fraction var v any for v, err = it.Next(); err == nil; v, err = it.Next() { @@ -36,19 +37,37 @@ func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) { 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 { + if array, ok := v.(*ListType); ok { + if v, err = doAdd(ctx, name, NewFlatArrayIterator(*array)); err != nil { break } } } - if !sumAsFloat && isFloat(v) { - sumAsFloat = true - floatSum = float64(intSum) + if !sumAsFloat { + if isFloat(v) { + sumAsFloat = true + if sumAsFract { + floatSum = fractSum.toFloat() + } else { + floatSum = float64(intSum) + } + } else if !sumAsFract && isFraction(v) { + fractSum = newFraction(intSum, 1) + sumAsFract = true + } } + if sumAsFloat { floatSum += numAsFloat(v) + } else if sumAsFract { + var item *fraction + var ok bool + if item, ok = v.(*fraction); !ok { + iv, _ := v.(int64) + item = newFraction(iv, 1) + } + fractSum = sumFract(fractSum, item) } else { iv, _ := v.(int64) intSum += iv @@ -58,6 +77,8 @@ func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) { err = nil if sumAsFloat { result = floatSum + } else if sumAsFract { + result = fractSum } else { result = intSum } @@ -71,28 +92,58 @@ func addFunc(ctx ExprContext, name string, args []any) (result any, err error) { } func doMul(ctx ExprContext, name string, it Iterator) (result any, err error) { - var mulAsFloat = false + var mulAsFloat, mulAsFract bool var floatProd float64 = 1.0 var intProd int64 = 1 + var fractProd *fraction 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 = doMul(ctx, name, NewFlatArrayIterator(array)); err != nil { + if subIter, ok := v.(Iterator); ok { + if v, err = doAdd(ctx, name, subIter); err != nil { break } + if subIter.HasOperation(cleanName) { + if _, err = subIter.CallOperation(cleanName, nil); err != nil { + return + } + } + } else { + if err = checkNumberParamExpected(name, v, it.Index()); err != nil { + break + } + + if array, ok := v.(*ListType); ok { + if v, err = doMul(ctx, name, NewFlatArrayIterator(*array)); err != nil { + break + } + } } - if !mulAsFloat && isFloat(v) { - mulAsFloat = true - floatProd = float64(intProd) + if !mulAsFloat { + if isFloat(v) { + mulAsFloat = true + if mulAsFract { + floatProd = fractProd.toFloat() + } else { + floatProd = float64(intProd) + } + } else if !mulAsFract && isFraction(v) { + fractProd = newFraction(intProd, 1) + mulAsFract = true + } } + if mulAsFloat { floatProd *= numAsFloat(v) + } else if mulAsFract { + var item *fraction + var ok bool + if item, ok = v.(*fraction); !ok { + iv, _ := v.(int64) + item = newFraction(iv, 1) + } + fractProd = mulFract(fractProd, item) } else { iv, _ := v.(int64) intProd *= iv @@ -102,6 +153,8 @@ func doMul(ctx ExprContext, name string, it Iterator) (result any, err error) { err = nil if mulAsFloat { result = floatProd + } else if mulAsFract { + result = fractProd } else { result = intProd }