github.com/coveo/gotemplate@v2.7.7+incompatible/template/math_base.go (about) 1 package template 2 3 import ( 4 "fmt" 5 "math" 6 "reflect" 7 "strconv" 8 "strings" 9 10 "github.com/coveo/gotemplate/utils" 11 ) 12 13 func add(a interface{}, args ...interface{}) (r interface{}, err error) { 14 if a == nil { 15 return 16 } 17 defer func() { err = trapError(err, recover()) }() 18 arguments := convertArgs(a, args...) 19 args = arguments.AsArray() 20 21 values, err := toListOfFloats(arguments) 22 if err != nil { 23 if len(args) == 2 { 24 // If the first argument is an array of float, we process it with the generic processor function 25 if af, err := toListOfFloats(convertArgs(args[0])); err == nil { 26 if _, err := strconv.ParseFloat(fmt.Sprint(args[1]), 64); err == nil { 27 return processFloat2(af, args[1], func(a, b float64) float64 { 28 return a + b 29 }) 30 } 31 } 32 } 33 34 switch reflect.TypeOf(args[0]).Kind() { 35 case reflect.String: 36 break 37 case reflect.Array, reflect.Slice: 38 switch reflect.TypeOf(args[1]).Kind() { 39 case reflect.Array, reflect.Slice: 40 return utils.MergeLists(convertArgs(args[0]), convertArgs(args[1])), nil 41 default: 42 return convertArgs(args[0]).Append(args[1]), nil 43 } 44 } 45 46 // If it is not possible to convert all arguments into numeric values 47 // we simply return the concatenation of their string representation 48 // This allow support of "Foo" + "Bar" or "Foo" + 1 49 return fmt.Sprint(args...), nil 50 } 51 52 var result float64 53 for _, value := range mustAsFloats(values) { 54 result += value 55 } 56 return simplify(result), nil 57 } 58 59 func multiply(a interface{}, args ...interface{}) (r interface{}, err error) { 60 if a == nil && len(args) < 2 { 61 return 62 } 63 defer func() { err = trapError(err, recover()) }() 64 arguments := convertArgs(a, args...) 65 args = arguments.AsArray() 66 67 values, err := toListOfFloats(arguments) 68 if err != nil { 69 if len(args) == 2 { 70 // If the first argument is an array of float, we process it with the generic processor function 71 if af, err := toListOfFloats(convertArgs(args[0])); err == nil { 72 if _, err := strconv.ParseFloat(fmt.Sprintf("%v", args[1]), 64); err == nil { 73 return processFloat2(af, args[1], func(a, b float64) float64 { 74 return a * b 75 }) 76 } 77 if af2, err := toListOfFloats(convertArgs(args[1])); err == nil { 78 af2 := mustAsFloats(af2) 79 // If the second argument is also an array of float, we then multiply the two arrays 80 result := make([]interface{}, len(af2)) 81 for i := range af2 { 82 result[i], err = multiply(af, af2[i]) 83 } 84 return result, nil 85 } 86 } 87 88 switch a := args[0].(type) { 89 case string: 90 return strings.Repeat(a, toInt(args[1])), nil 91 default: 92 result := make([]interface{}, toInt(args[1])) 93 for i := range result { 94 result[i] = args[0] 95 } 96 return result, nil 97 } 98 } 99 } 100 101 { 102 // Values is an array of floats 103 values := mustAsFloats(values) 104 if len(values) == 0 { 105 return 0, nil 106 } 107 var result float64 = 1 108 for _, value := range values { 109 result *= value 110 } 111 return simplify(result), nil 112 } 113 } 114 115 func subtract(a, b interface{}) (r interface{}, err error) { 116 defer func() { err = trapError(err, recover()) }() 117 return processFloat2(a, b, func(a, b float64) float64 { return a - b }) 118 } 119 120 func divide(a, b interface{}) (r interface{}, err error) { 121 defer func() { err = trapError(err, recover()) }() 122 return processFloat2(a, b, func(a, b float64) float64 { 123 if b == 0 { 124 panic(fmt.Errorf("Division by 0")) 125 } 126 return a / b 127 }) 128 } 129 130 func modulo(a, b interface{}) (r interface{}, err error) { 131 defer func() { err = trapError(err, recover()) }() 132 return processFloat2(a, b, math.Mod) 133 } 134 135 func modf(a interface{}) (r interface{}, err error) { 136 defer func() { err = trapError(err, recover()) }() 137 return process(a, math.Modf) 138 } 139 140 func power(a, b interface{}) (r interface{}, err error) { 141 defer func() { err = trapError(err, recover()) }() 142 return processFloat2(a, b, math.Pow) 143 } 144 145 func power10(a interface{}) (r interface{}, err error) { 146 defer func() { err = trapError(err, recover()) }() 147 return processFloat(a, func(a float64) float64 { 148 return math.Pow10(int(a)) 149 }) 150 }