github.com/richardwilkes/toolbox@v1.121.0/eval/float_function.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package eval 11 12 import ( 13 "strings" 14 15 "github.com/richardwilkes/toolbox/xmath" 16 "golang.org/x/exp/constraints" 17 ) 18 19 // FloatFunctions returns standard functions that work with constraints.Float. 20 func FloatFunctions[T constraints.Float]() map[string]Function { 21 return map[string]Function{ 22 "abs": floatAbs[T], 23 "cbrt": floatCubeRoot[T], 24 "ceil": floatCeiling[T], 25 "exp": floatBaseEExponential[T], 26 "exp2": floatBase2Exponential[T], 27 "floor": floatFloor[T], 28 "if": floatIf[T], 29 "log": floatNaturalLog[T], 30 "log1p": floatNaturalLogSum1[T], 31 "log10": floatDecimalLog[T], 32 "max": floatMaximum[T], 33 "min": floatMinimum[T], 34 "round": floatRound[T], 35 "sqrt": floatSquareRoot[T], 36 } 37 } 38 39 func floatAbs[T constraints.Float](e *Evaluator, arguments string) (any, error) { 40 return floatSingleNumberFunc(e, arguments, xmath.Abs[T]) 41 } 42 43 func floatBase2Exponential[T constraints.Float](e *Evaluator, arguments string) (any, error) { 44 return floatSingleNumberFunc(e, arguments, xmath.Exp2[T]) 45 } 46 47 func floatBaseEExponential[T constraints.Float](e *Evaluator, arguments string) (any, error) { 48 return floatSingleNumberFunc(e, arguments, xmath.Exp[T]) 49 } 50 51 func floatCeiling[T constraints.Float](e *Evaluator, arguments string) (any, error) { 52 return floatSingleNumberFunc(e, arguments, xmath.Ceil[T]) 53 } 54 55 func floatCubeRoot[T constraints.Float](e *Evaluator, arguments string) (any, error) { 56 return floatSingleNumberFunc(e, arguments, xmath.Cbrt[T]) 57 } 58 59 func floatDecimalLog[T constraints.Float](e *Evaluator, arguments string) (any, error) { 60 return floatSingleNumberFunc(e, arguments, xmath.Log10[T]) 61 } 62 63 func floatFloor[T constraints.Float](e *Evaluator, arguments string) (any, error) { 64 return floatSingleNumberFunc(e, arguments, xmath.Floor[T]) 65 } 66 67 func floatIf[T constraints.Float](e *Evaluator, arguments string) (any, error) { 68 var arg string 69 arg, arguments = NextArg(arguments) 70 evaluated, err := e.EvaluateNew(arg) 71 if err != nil { 72 return nil, err 73 } 74 var value T 75 if value, err = floatFrom[T](evaluated); err != nil { 76 if s, ok := evaluated.(string); ok { 77 if s != "" && !strings.EqualFold(s, "false") { 78 value = 1 79 } 80 } else { 81 return nil, err 82 } 83 } 84 if value == 0 { 85 _, arguments = NextArg(arguments) 86 } 87 arg, _ = NextArg(arguments) 88 return e.EvaluateNew(arg) 89 } 90 91 func floatMaximum[T constraints.Float](e *Evaluator, arguments string) (any, error) { 92 maxValue := xmath.MinValue[T]() 93 for arguments != "" { 94 var arg string 95 arg, arguments = NextArg(arguments) 96 value, err := evalToFloat[T](e, arg) 97 if err != nil { 98 return nil, err 99 } 100 maxValue = max(value, maxValue) 101 } 102 return maxValue, nil 103 } 104 105 func floatMinimum[T constraints.Float](e *Evaluator, arguments string) (any, error) { 106 minValue := xmath.MaxValue[T]() 107 for arguments != "" { 108 var arg string 109 arg, arguments = NextArg(arguments) 110 value, err := evalToFloat[T](e, arg) 111 if err != nil { 112 return nil, err 113 } 114 minValue = min(value, minValue) 115 } 116 return minValue, nil 117 } 118 119 func floatNaturalLog[T constraints.Float](e *Evaluator, arguments string) (any, error) { 120 return floatSingleNumberFunc(e, arguments, xmath.Log[T]) 121 } 122 123 func floatNaturalLogSum1[T constraints.Float](e *Evaluator, arguments string) (any, error) { 124 value, err := evalToFloat[T](e, arguments) 125 if err != nil { 126 return nil, err 127 } 128 return xmath.Log(value + 1), nil 129 } 130 131 func floatRound[T constraints.Float](e *Evaluator, arguments string) (any, error) { 132 return floatSingleNumberFunc(e, arguments, xmath.Round[T]) 133 } 134 135 func floatSquareRoot[T constraints.Float](e *Evaluator, arguments string) (any, error) { 136 return floatSingleNumberFunc(e, arguments, xmath.Sqrt[T]) 137 } 138 139 func evalToFloat[T constraints.Float](e *Evaluator, arg string) (T, error) { 140 evaluated, err := e.EvaluateNew(arg) 141 if err != nil { 142 return 0, err 143 } 144 return floatFrom[T](evaluated) 145 } 146 147 func floatSingleNumberFunc[T constraints.Float](e *Evaluator, arguments string, f func(T) T) (any, error) { 148 value, err := evalToFloat[T](e, arguments) 149 if err != nil { 150 return nil, err 151 } 152 return f(value), nil 153 }