porting functions
This commit is contained in:
parent
4ad3676934
commit
602b59cdc4
|
@ -27,7 +27,129 @@ var CeilFunc = function.New(&function.Spec{
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// FloorFunc contructs a function that returns the closest whole number lesser
|
||||||
|
// than or equal to the given value.
|
||||||
|
var FloorFunc = function.New(&function.Spec{
|
||||||
|
Params: []function.Parameter{
|
||||||
|
{
|
||||||
|
Name: "num",
|
||||||
|
Type: cty.Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: function.StaticReturnType(cty.Number),
|
||||||
|
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
|
||||||
|
var val float64
|
||||||
|
if err := gocty.FromCtyValue(args[0], &val); err != nil {
|
||||||
|
return cty.UnknownVal(cty.String), err
|
||||||
|
}
|
||||||
|
return cty.NumberIntVal(int64(math.Floor(val))), nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// LogFunc contructs a function that returns the logarithm of a given number in a given base.
|
||||||
|
var LogFunc = function.New(&function.Spec{
|
||||||
|
Params: []function.Parameter{
|
||||||
|
{
|
||||||
|
Name: "num",
|
||||||
|
Type: cty.Number,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "base",
|
||||||
|
Type: cty.Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: function.StaticReturnType(cty.Number),
|
||||||
|
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
|
||||||
|
var num float64
|
||||||
|
if err := gocty.FromCtyValue(args[0], &num); err != nil {
|
||||||
|
return cty.UnknownVal(cty.String), err
|
||||||
|
}
|
||||||
|
|
||||||
|
var base float64
|
||||||
|
if err := gocty.FromCtyValue(args[1], &base); err != nil {
|
||||||
|
return cty.UnknownVal(cty.String), err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cty.NumberFloatVal(math.Log(num) / math.Log(base)), nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// PowFunc contructs a function that returns the logarithm of a given number in a given base.
|
||||||
|
var PowFunc = function.New(&function.Spec{
|
||||||
|
Params: []function.Parameter{
|
||||||
|
{
|
||||||
|
Name: "num",
|
||||||
|
Type: cty.Number,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "power",
|
||||||
|
Type: cty.Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: function.StaticReturnType(cty.Number),
|
||||||
|
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
|
||||||
|
var num float64
|
||||||
|
if err := gocty.FromCtyValue(args[0], &num); err != nil {
|
||||||
|
return cty.UnknownVal(cty.String), err
|
||||||
|
}
|
||||||
|
|
||||||
|
var power float64
|
||||||
|
if err := gocty.FromCtyValue(args[1], &power); err != nil {
|
||||||
|
return cty.UnknownVal(cty.String), err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cty.NumberFloatVal(math.Pow(num, power)), nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// SignumFunc contructs a function that returns the closest whole number greater
|
||||||
|
// than or equal to the given value.
|
||||||
|
var SignumFunc = function.New(&function.Spec{
|
||||||
|
Params: []function.Parameter{
|
||||||
|
{
|
||||||
|
Name: "num",
|
||||||
|
Type: cty.Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: function.StaticReturnType(cty.Number),
|
||||||
|
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
|
||||||
|
var num int
|
||||||
|
if err := gocty.FromCtyValue(args[0], &num); err != nil {
|
||||||
|
return cty.UnknownVal(cty.String), err
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case num < 0:
|
||||||
|
return cty.NumberIntVal(-1), nil
|
||||||
|
case num > 0:
|
||||||
|
return cty.NumberIntVal(+1), nil
|
||||||
|
default:
|
||||||
|
return cty.NumberIntVal(0), nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
// Ceil returns the closest whole number greater than or equal to the given value.
|
// Ceil returns the closest whole number greater than or equal to the given value.
|
||||||
func Ceil(num cty.Value) (cty.Value, error) {
|
func Ceil(num cty.Value) (cty.Value, error) {
|
||||||
return CeilFunc.Call([]cty.Value{num})
|
return CeilFunc.Call([]cty.Value{num})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Floor returns the closest whole number lesser than or equal to the given value.
|
||||||
|
func Floor(num cty.Value) (cty.Value, error) {
|
||||||
|
return FloorFunc.Call([]cty.Value{num})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log returns returns the logarithm of a given number in a given base.
|
||||||
|
func Log(num, base cty.Value) (cty.Value, error) {
|
||||||
|
return LogFunc.Call([]cty.Value{num, base})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pow returns the logarithm of a given number in a given base.
|
||||||
|
func Pow(num, power cty.Value) (cty.Value, error) {
|
||||||
|
return PowFunc.Call([]cty.Value{num, power})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signum determines the sign of a number, returning a number between -1 and
|
||||||
|
// 1 to represent the sign.
|
||||||
|
func Signum(num cty.Value) (cty.Value, error) {
|
||||||
|
return SignumFunc.Call([]cty.Value{num})
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestCeil(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(fmt.Sprintf("Ceil(%#v)", test.Num), func(t *testing.T) {
|
t.Run(fmt.Sprintf("ceil(%#v)", test.Num), func(t *testing.T) {
|
||||||
got, err := Ceil(test.Num)
|
got, err := Ceil(test.Num)
|
||||||
|
|
||||||
if test.Err {
|
if test.Err {
|
||||||
|
@ -44,3 +44,216 @@ func TestCeil(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFloor(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Num cty.Value
|
||||||
|
Want cty.Value
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(-1.8),
|
||||||
|
cty.NumberFloatVal(-2),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(1.2),
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(fmt.Sprintf("floor(%#v)", test.Num), func(t *testing.T) {
|
||||||
|
got, err := Floor(test.Num)
|
||||||
|
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !got.RawEquals(test.Want) {
|
||||||
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLog(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Num cty.Value
|
||||||
|
Base cty.Value
|
||||||
|
Want cty.Value
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
cty.NumberFloatVal(10),
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(10),
|
||||||
|
cty.NumberFloatVal(10),
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
cty.NumberFloatVal(10),
|
||||||
|
cty.NegativeInfinity,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(10),
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
cty.NumberFloatVal(-0),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(fmt.Sprintf("log(%#v, %#v)", test.Num, test.Base), func(t *testing.T) {
|
||||||
|
got, err := Log(test.Num, test.Base)
|
||||||
|
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !got.RawEquals(test.Want) {
|
||||||
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPow(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Num cty.Value
|
||||||
|
Power cty.Value
|
||||||
|
Want cty.Value
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(2),
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(2),
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
cty.NumberFloatVal(2),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(3),
|
||||||
|
cty.NumberFloatVal(2),
|
||||||
|
cty.NumberFloatVal(9),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(-3),
|
||||||
|
cty.NumberFloatVal(2),
|
||||||
|
cty.NumberFloatVal(9),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(2),
|
||||||
|
cty.NumberFloatVal(-2),
|
||||||
|
cty.NumberFloatVal(0.25),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
cty.NumberFloatVal(2),
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(fmt.Sprintf("pow(%#v, %#v)", test.Num, test.Power), func(t *testing.T) {
|
||||||
|
got, err := Pow(test.Num, test.Power)
|
||||||
|
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !got.RawEquals(test.Want) {
|
||||||
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignum(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Num cty.Value
|
||||||
|
Want cty.Value
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
cty.NumberFloatVal(0),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(12),
|
||||||
|
cty.NumberFloatVal(1),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.NumberFloatVal(-29),
|
||||||
|
cty.NumberFloatVal(-1),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(fmt.Sprintf("signum(%#v)", test.Num), func(t *testing.T) {
|
||||||
|
got, err := Signum(test.Num)
|
||||||
|
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !got.RawEquals(test.Want) {
|
||||||
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package funcs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -110,6 +111,21 @@ var SplitFunc = function.New(&function.Spec{
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ChompFunc constructions a function that removes newline characters at the end of a string.
|
||||||
|
var ChompFunc = function.New(&function.Spec{
|
||||||
|
Params: []function.Parameter{
|
||||||
|
{
|
||||||
|
Name: "str",
|
||||||
|
Type: cty.String,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: function.StaticReturnType(cty.String),
|
||||||
|
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
|
||||||
|
newlines := regexp.MustCompile(`(?:\r\n?|\n)*\z`)
|
||||||
|
return cty.StringVal(newlines.ReplaceAllString(args[0].AsString(), "")), nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
// Join concatenates together the string elements of one or more lists with a
|
// Join concatenates together the string elements of one or more lists with a
|
||||||
// given separator.
|
// given separator.
|
||||||
func Join(sep cty.Value, lists ...cty.Value) (cty.Value, error) {
|
func Join(sep cty.Value, lists ...cty.Value) (cty.Value, error) {
|
||||||
|
@ -130,3 +146,8 @@ func Sort(list cty.Value) (cty.Value, error) {
|
||||||
func Split(sep, str cty.Value) (cty.Value, error) {
|
func Split(sep, str cty.Value) (cty.Value, error) {
|
||||||
return SplitFunc.Call([]cty.Value{sep, str})
|
return SplitFunc.Call([]cty.Value{sep, str})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Chomp removes newline characters at the end of a string.
|
||||||
|
func Chomp(str cty.Value) (cty.Value, error) {
|
||||||
|
return ChompFunc.Call([]cty.Value{str})
|
||||||
|
}
|
||||||
|
|
|
@ -244,3 +244,66 @@ func TestSplit(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestChomp(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
String cty.Value
|
||||||
|
Want cty.Value
|
||||||
|
Err bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
cty.StringVal("hello world"),
|
||||||
|
cty.StringVal("hello world"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.StringVal("goodbye\ncruel\nworld"),
|
||||||
|
cty.StringVal("goodbye\ncruel\nworld"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.StringVal("goodbye\r\nwindows\r\nworld"),
|
||||||
|
cty.StringVal("goodbye\r\nwindows\r\nworld"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.StringVal("goodbye\ncruel\nworld\n"),
|
||||||
|
cty.StringVal("goodbye\ncruel\nworld"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.StringVal("goodbye\ncruel\nworld\n\n\n\n"),
|
||||||
|
cty.StringVal("goodbye\ncruel\nworld"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.StringVal("goodbye\r\nwindows\r\nworld\r\n"),
|
||||||
|
cty.StringVal("goodbye\r\nwindows\r\nworld"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cty.StringVal("goodbye\r\nwindows\r\nworld\r\n\r\n\r\n\r\n"),
|
||||||
|
cty.StringVal("goodbye\r\nwindows\r\nworld"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(fmt.Sprintf("chomp(%#v)", test.String), func(t *testing.T) {
|
||||||
|
got, err := Chomp(test.String)
|
||||||
|
|
||||||
|
if test.Err {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("succeeded; want error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !got.RawEquals(test.Want) {
|
||||||
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func (s *Scope) Functions() map[string]function.Function {
|
||||||
"base64sha512": funcs.Base64Sha512Func,
|
"base64sha512": funcs.Base64Sha512Func,
|
||||||
"bcrypt": funcs.BcryptFunc,
|
"bcrypt": funcs.BcryptFunc,
|
||||||
"ceil": funcs.CeilFunc,
|
"ceil": funcs.CeilFunc,
|
||||||
"chomp": unimplFunc, // TODO
|
"chomp": funcs.ChompFunc,
|
||||||
"cidrhost": unimplFunc, // TODO
|
"cidrhost": unimplFunc, // TODO
|
||||||
"cidrnetmask": unimplFunc, // TODO
|
"cidrnetmask": unimplFunc, // TODO
|
||||||
"cidrsubnet": unimplFunc, // TODO
|
"cidrsubnet": unimplFunc, // TODO
|
||||||
|
@ -56,7 +56,7 @@ func (s *Scope) Functions() map[string]function.Function {
|
||||||
"filebase64": funcs.MakeFileFunc(s.BaseDir, true),
|
"filebase64": funcs.MakeFileFunc(s.BaseDir, true),
|
||||||
"matchkeys": unimplFunc, // TODO
|
"matchkeys": unimplFunc, // TODO
|
||||||
"flatten": unimplFunc, // TODO
|
"flatten": unimplFunc, // TODO
|
||||||
"floor": unimplFunc, // TODO
|
"floor": funcs.FloorFunc,
|
||||||
"format": stdlib.FormatFunc,
|
"format": stdlib.FormatFunc,
|
||||||
"formatlist": stdlib.FormatListFunc,
|
"formatlist": stdlib.FormatListFunc,
|
||||||
"indent": unimplFunc, // TODO
|
"indent": unimplFunc, // TODO
|
||||||
|
@ -67,7 +67,7 @@ func (s *Scope) Functions() map[string]function.Function {
|
||||||
"keys": unimplFunc, // TODO
|
"keys": unimplFunc, // TODO
|
||||||
"length": funcs.LengthFunc,
|
"length": funcs.LengthFunc,
|
||||||
"list": unimplFunc, // TODO
|
"list": unimplFunc, // TODO
|
||||||
"log": unimplFunc, // TODO
|
"log": funcs.LogFunc,
|
||||||
"lookup": unimplFunc, // TODO
|
"lookup": unimplFunc, // TODO
|
||||||
"lower": stdlib.LowerFunc,
|
"lower": stdlib.LowerFunc,
|
||||||
"map": unimplFunc, // TODO
|
"map": unimplFunc, // TODO
|
||||||
|
@ -76,7 +76,7 @@ func (s *Scope) Functions() map[string]function.Function {
|
||||||
"merge": unimplFunc, // TODO
|
"merge": unimplFunc, // TODO
|
||||||
"min": stdlib.MinFunc,
|
"min": stdlib.MinFunc,
|
||||||
"pathexpand": funcs.PathExpandFunc,
|
"pathexpand": funcs.PathExpandFunc,
|
||||||
"pow": unimplFunc, // TODO
|
"pow": funcs.PowFunc,
|
||||||
"replace": unimplFunc, // TODO
|
"replace": unimplFunc, // TODO
|
||||||
"rsadecrypt": funcs.RsaDecryptFunc,
|
"rsadecrypt": funcs.RsaDecryptFunc,
|
||||||
"sha1": funcs.Sha1Func,
|
"sha1": funcs.Sha1Func,
|
||||||
|
|
|
@ -3,13 +3,12 @@ layout: "functions"
|
||||||
page_title: "log function"
|
page_title: "log function"
|
||||||
sidebar_current: "docs-funcs-numeric-log"
|
sidebar_current: "docs-funcs-numeric-log"
|
||||||
description: |-
|
description: |-
|
||||||
The log function returns the closest whole number less than or equal to
|
The log function returns the logarithm of a given number in a given base.
|
||||||
the given value.
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# `log` Function
|
# `log` Function
|
||||||
|
|
||||||
`log` returns the the logarithm of a given number in a given base.
|
`log` returns the logarithm of a given number in a given base.
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
log(number, base)
|
log(number, base)
|
||||||
|
|
Loading…
Reference in New Issue