github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/lang/funcs/number.go (about) 1 package funcs 2 3 import ( 4 "math" 5 "math/big" 6 7 "github.com/zclconf/go-cty/cty" 8 "github.com/zclconf/go-cty/cty/function" 9 "github.com/zclconf/go-cty/cty/gocty" 10 ) 11 12 // CeilFunc contructs a function that returns the closest whole number greater 13 // than or equal to the given value. 14 var CeilFunc = function.New(&function.Spec{ 15 Params: []function.Parameter{ 16 { 17 Name: "num", 18 Type: cty.Number, 19 }, 20 }, 21 Type: function.StaticReturnType(cty.Number), 22 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { 23 var val float64 24 if err := gocty.FromCtyValue(args[0], &val); err != nil { 25 return cty.UnknownVal(cty.String), err 26 } 27 return cty.NumberIntVal(int64(math.Ceil(val))), nil 28 }, 29 }) 30 31 // FloorFunc contructs a function that returns the closest whole number lesser 32 // than or equal to the given value. 33 var FloorFunc = function.New(&function.Spec{ 34 Params: []function.Parameter{ 35 { 36 Name: "num", 37 Type: cty.Number, 38 }, 39 }, 40 Type: function.StaticReturnType(cty.Number), 41 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { 42 var val float64 43 if err := gocty.FromCtyValue(args[0], &val); err != nil { 44 return cty.UnknownVal(cty.String), err 45 } 46 return cty.NumberIntVal(int64(math.Floor(val))), nil 47 }, 48 }) 49 50 // LogFunc contructs a function that returns the logarithm of a given number in a given base. 51 var LogFunc = function.New(&function.Spec{ 52 Params: []function.Parameter{ 53 { 54 Name: "num", 55 Type: cty.Number, 56 }, 57 { 58 Name: "base", 59 Type: cty.Number, 60 }, 61 }, 62 Type: function.StaticReturnType(cty.Number), 63 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { 64 var num float64 65 if err := gocty.FromCtyValue(args[0], &num); err != nil { 66 return cty.UnknownVal(cty.String), err 67 } 68 69 var base float64 70 if err := gocty.FromCtyValue(args[1], &base); err != nil { 71 return cty.UnknownVal(cty.String), err 72 } 73 74 return cty.NumberFloatVal(math.Log(num) / math.Log(base)), nil 75 }, 76 }) 77 78 // PowFunc contructs a function that returns the logarithm of a given number in a given base. 79 var PowFunc = function.New(&function.Spec{ 80 Params: []function.Parameter{ 81 { 82 Name: "num", 83 Type: cty.Number, 84 }, 85 { 86 Name: "power", 87 Type: cty.Number, 88 }, 89 }, 90 Type: function.StaticReturnType(cty.Number), 91 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { 92 var num float64 93 if err := gocty.FromCtyValue(args[0], &num); err != nil { 94 return cty.UnknownVal(cty.String), err 95 } 96 97 var power float64 98 if err := gocty.FromCtyValue(args[1], &power); err != nil { 99 return cty.UnknownVal(cty.String), err 100 } 101 102 return cty.NumberFloatVal(math.Pow(num, power)), nil 103 }, 104 }) 105 106 // SignumFunc contructs a function that returns the closest whole number greater 107 // than or equal to the given value. 108 var SignumFunc = function.New(&function.Spec{ 109 Params: []function.Parameter{ 110 { 111 Name: "num", 112 Type: cty.Number, 113 }, 114 }, 115 Type: function.StaticReturnType(cty.Number), 116 Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { 117 var num int 118 if err := gocty.FromCtyValue(args[0], &num); err != nil { 119 return cty.UnknownVal(cty.String), err 120 } 121 switch { 122 case num < 0: 123 return cty.NumberIntVal(-1), nil 124 case num > 0: 125 return cty.NumberIntVal(+1), nil 126 default: 127 return cty.NumberIntVal(0), nil 128 } 129 }, 130 }) 131 132 // ParseIntFunc contructs a function that parses a string argument and returns an integer of the specified base. 133 var ParseIntFunc = function.New(&function.Spec{ 134 Params: []function.Parameter{ 135 { 136 Name: "number", 137 Type: cty.DynamicPseudoType, 138 }, 139 { 140 Name: "base", 141 Type: cty.Number, 142 }, 143 }, 144 145 Type: func(args []cty.Value) (cty.Type, error) { 146 if !args[0].Type().Equals(cty.String) { 147 return cty.Number, function.NewArgErrorf(0, "first argument must be a string, not %s", args[0].Type().FriendlyName()) 148 } 149 return cty.Number, nil 150 }, 151 152 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { 153 var numstr string 154 var base int 155 var err error 156 157 if err = gocty.FromCtyValue(args[0], &numstr); err != nil { 158 return cty.UnknownVal(cty.String), function.NewArgError(0, err) 159 } 160 161 if err = gocty.FromCtyValue(args[1], &base); err != nil { 162 return cty.UnknownVal(cty.Number), function.NewArgError(1, err) 163 } 164 165 if base < 2 || base > 62 { 166 return cty.UnknownVal(cty.Number), function.NewArgErrorf( 167 1, 168 "base must be a whole number between 2 and 62 inclusive", 169 ) 170 } 171 172 num, ok := (&big.Int{}).SetString(numstr, base) 173 if !ok { 174 return cty.UnknownVal(cty.Number), function.NewArgErrorf( 175 0, 176 "cannot parse %q as a base %d integer", 177 numstr, 178 base, 179 ) 180 } 181 182 parsedNum := cty.NumberVal((&big.Float{}).SetInt(num)) 183 184 return parsedNum, nil 185 }, 186 }) 187 188 // Ceil returns the closest whole number greater than or equal to the given value. 189 func Ceil(num cty.Value) (cty.Value, error) { 190 return CeilFunc.Call([]cty.Value{num}) 191 } 192 193 // Floor returns the closest whole number lesser than or equal to the given value. 194 func Floor(num cty.Value) (cty.Value, error) { 195 return FloorFunc.Call([]cty.Value{num}) 196 } 197 198 // Log returns returns the logarithm of a given number in a given base. 199 func Log(num, base cty.Value) (cty.Value, error) { 200 return LogFunc.Call([]cty.Value{num, base}) 201 } 202 203 // Pow returns the logarithm of a given number in a given base. 204 func Pow(num, power cty.Value) (cty.Value, error) { 205 return PowFunc.Call([]cty.Value{num, power}) 206 } 207 208 // Signum determines the sign of a number, returning a number between -1 and 209 // 1 to represent the sign. 210 func Signum(num cty.Value) (cty.Value, error) { 211 return SignumFunc.Call([]cty.Value{num}) 212 } 213 214 // ParseInt parses a string argument and returns an integer of the specified base. 215 func ParseInt(num cty.Value, base cty.Value) (cty.Value, error) { 216 return ParseIntFunc.Call([]cty.Value{num, base}) 217 }