func-math.go: mul() and add() now support fractions

This commit is contained in:
Celestino Amoroso 2024-05-01 21:53:54 +02:00
parent 7c748f0e31
commit 5809de419f

View File

@ -10,16 +10,17 @@ import (
) )
func checkNumberParamExpected(funcName string, paramValue any, paramPos int) (err error) { 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) err = fmt.Errorf("%s(): param nr %d has wrong type %T, number expected", funcName, paramPos+1, paramValue)
} }
return return
} }
func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) { 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 floatSum float64 = 0.0
var intSum int64 = 0 var intSum int64 = 0
var fractSum *fraction
var v any var v any
for v, err = it.Next(); err == nil; v, err = it.Next() { 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 { if err = checkNumberParamExpected(name, v, it.Index()); err != nil {
break break
} }
if array, ok := v.([]any); ok { if array, ok := v.(*ListType); ok {
if v, err = doAdd(ctx, name, NewFlatArrayIterator(array)); err != nil { if v, err = doAdd(ctx, name, NewFlatArrayIterator(*array)); err != nil {
break break
} }
} }
} }
if !sumAsFloat && isFloat(v) { if !sumAsFloat {
sumAsFloat = true if isFloat(v) {
floatSum = float64(intSum) sumAsFloat = true
if sumAsFract {
floatSum = fractSum.toFloat()
} else {
floatSum = float64(intSum)
}
} else if !sumAsFract && isFraction(v) {
fractSum = newFraction(intSum, 1)
sumAsFract = true
}
} }
if sumAsFloat { if sumAsFloat {
floatSum += numAsFloat(v) 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 { } else {
iv, _ := v.(int64) iv, _ := v.(int64)
intSum += iv intSum += iv
@ -58,6 +77,8 @@ func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) {
err = nil err = nil
if sumAsFloat { if sumAsFloat {
result = floatSum result = floatSum
} else if sumAsFract {
result = fractSum
} else { } else {
result = intSum 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) { 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 floatProd float64 = 1.0
var intProd int64 = 1 var intProd int64 = 1
var fractProd *fraction
var v any var v any
for v, err = it.Next(); err == nil; v, err = it.Next() { for v, err = it.Next(); err == nil; v, err = it.Next() {
if err = checkNumberParamExpected(name, v, it.Index()); err != nil { if subIter, ok := v.(Iterator); ok {
break if v, err = doAdd(ctx, name, subIter); err != nil {
}
if array, ok := v.([]any); ok {
if v, err = doMul(ctx, name, NewFlatArrayIterator(array)); err != nil {
break 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) { if !mulAsFloat {
mulAsFloat = true if isFloat(v) {
floatProd = float64(intProd) mulAsFloat = true
if mulAsFract {
floatProd = fractProd.toFloat()
} else {
floatProd = float64(intProd)
}
} else if !mulAsFract && isFraction(v) {
fractProd = newFraction(intProd, 1)
mulAsFract = true
}
} }
if mulAsFloat { if mulAsFloat {
floatProd *= numAsFloat(v) 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 { } else {
iv, _ := v.(int64) iv, _ := v.(int64)
intProd *= iv intProd *= iv
@ -102,6 +153,8 @@ func doMul(ctx ExprContext, name string, it Iterator) (result any, err error) {
err = nil err = nil
if mulAsFloat { if mulAsFloat {
result = floatProd result = floatProd
} else if mulAsFract {
result = fractProd
} else { } else {
result = intProd result = intProd
} }