Skip to content

Commit

Permalink
Add modulo support for expressions (#115)
Browse files Browse the repository at this point in the history
Add modulo, log, pow, and sqrt expression functions
  • Loading branch information
zix99 authored Dec 22, 2024
1 parent c559360 commit 0901569
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 5 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ jobs:
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
- if: ${{ !startsWith(github.ref, 'refs/tags/') }}
run: echo "flags=--snapshot" >> $GITHUB_ENV
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6.1.0
with:
version: v2.5.0
args: release
args: release --clean ${{ env.flags }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUBTOKEN }}
10 changes: 8 additions & 2 deletions docs/usage/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ Create exponentially (base-10) increase buckets.

### Arithmetic

#### Sumi, Subi, Multi, Divi
#### Sumi, Subi, Multi, Divi, Modi

Syntax: `{sumi ...}`, `{subi ...}`, `{multi ...}`, `{divi ...}`
Syntax: `{sumi ...}`, `{subi ...}`, `{multi ...}`, `{divi ...}`, `{modi ...}`

Evaluates integers using operator from left to right. Requires at least 2 arguments.

Expand Down Expand Up @@ -146,6 +146,12 @@ Returns the floor, ceil, or rounded format of a floating-point number.

Eg: `{floor 123.765}` will result in `123`

#### log, pow, sqrt

Syntax: `{log10 val}`, `{log2 val}`, `{ln val}`, `{pow val exp}`, `{sqrt val}`

Returns the log (10, 2, or natural), power, or sqrt of a floating-point number.

#### Clamp

Syntax: `{clamp intVal "min" "max"}`
Expand Down
6 changes: 6 additions & 0 deletions pkg/expressions/stdlib/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var StandardFunctions = map[string]KeyBuilderFunction{
"subi": arithmaticHelperi(func(a, b int) int { return a - b }),
"multi": arithmaticHelperi(func(a, b int) int { return a * b }),
"divi": arithmaticHelperi(func(a, b int) int { return a / b }),
"modi": arithmaticHelperi(func(a, b int) int { return a % b }),
"maxi": arithmaticHelperi(func(a, b int) int {
if a > b {
return a
Expand All @@ -39,6 +40,11 @@ var StandardFunctions = map[string]KeyBuilderFunction{
"divf": arithmaticHelperf(func(a, b float64) float64 { return a / b }),
"ceil": unaryArithmaticHelperfi(func(f float64) int64 { return int64(math.Ceil(f)) }),
"floor": unaryArithmaticHelperfi(func(f float64) int64 { return int64(math.Floor(f)) }),
"log10": unaryArithmaticHelperf(math.Log10),
"log2": unaryArithmaticHelperf(math.Log2),
"ln": unaryArithmaticHelperf(math.Log),
"pow": arithmaticHelperf(math.Pow),
"sqrt": unaryArithmaticHelperf(math.Sqrt),
"round": kfRound,

// Comparisons
Expand Down
18 changes: 18 additions & 0 deletions pkg/expressions/stdlib/funcsArithmatic.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,24 @@ func arithmaticHelperf(equation func(float64, float64) float64) KeyBuilderFuncti
})
}

// Helper that takes in a float, operates on it
func unaryArithmaticHelperf(op func(float64) float64) KeyBuilderFunction {
return func(args []KeyBuilderStage) (KeyBuilderStage, error) {
if len(args) != 1 {
return stageErrArgCount(args, 1)
}

return func(context KeyBuilderContext) string {
val, err := strconv.ParseFloat(args[0](context), 64)
if err != nil {
return ErrorNum
}

return strconv.FormatFloat(op(val), 'f', -1, 64)
}, nil
}
}

// Helper that takes in a float, operates on it, and spits out an int
func unaryArithmaticHelperfi(op func(float64) int64) KeyBuilderFunction {
return func(args []KeyBuilderStage) (KeyBuilderStage, error) {
Expand Down
14 changes: 12 additions & 2 deletions pkg/expressions/stdlib/funcsArithmatic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
)

func TestArithmatic(t *testing.T) {
kb, _ := NewStdKeyBuilder().Compile("{sumi {1} {4}} {multi {1} 2} {divi {1} 2} {subi {1} 10}")
kb, _ := NewStdKeyBuilder().Compile("{sumi {1} {4}} {multi {1} 2} {divi {1} 2} {subi {1} 10} {modi {1} 7}")
key := kb.BuildKey(mockContext("ab", "100", "1000000", "5000000.123456", "22"))
assert.Equal(t, "122 200 50 90", key)
assert.Equal(t, "122 200 50 90 2", key)
}

func TestArithmaticError(t *testing.T) {
Expand Down Expand Up @@ -45,3 +45,13 @@ func TestFloorCeilRound(t *testing.T) {
testExpressionErr(t, mockContext("123.123"), "{round {0} {0}}", "<CONST>", ErrConst)
testExpressionErr(t, mockContext("123.123"), "{round {0} b}", "<CONST>", ErrConst)
}

func TestLogPow(t *testing.T) {
testExpression(t, mockContext("100"), "{log10 {0}}", "2")
testExpression(t, mockContext("64"), "{log2 {0}}", "6")
testExpression(t, mockContext("64"), "{round {ln {0}} 4}", "4.1589")
testExpression(t, mockContext("3"), "{pow {0} 3}", "27")
testExpression(t, mockContext("81"), "{sqrt {0}}", "9")

testExpressionErr(t, mockContext(), "{sqrt 1 2}", "<ARGN>", ErrArgCount)
}

0 comments on commit 0901569

Please sign in to comment.