Skip to content

Commit

Permalink
✨ feat: mathutil - add new func: IntOrDefault, UnitOrDefault, FloatOr…
Browse files Browse the repository at this point in the history
…Default ... and more for convert with default

- support for issues #111
  • Loading branch information
inhere committed Jul 20, 2023
1 parent 9c10a51 commit e906c90
Show file tree
Hide file tree
Showing 12 changed files with 602 additions and 272 deletions.
82 changes: 81 additions & 1 deletion mathutil/README.md
Expand Up @@ -10,11 +10,91 @@ go get github.com/gookit/goutil/mathutil

## Go docs

- [Go docs](https://pkg.go.dev/github.com/gookit/goutil/mathutil)
- [Go Docs](https://pkg.go.dev/github.com/gookit/goutil)

## Usage


## Functions

```go

func CompFloat[T comdef.Float](first, second T, op string) (ok bool)
func CompInt[T comdef.Xint](first, second T, op string) (ok bool)
func CompInt64(first, second int64, op string) bool
func CompValue[T comdef.XintOrFloat](first, second T, op string) (ok bool)
func Compare(first, second any, op string) (ok bool)
func DataSize(size uint64) string
func ElapsedTime(startTime time.Time) string
func Float(in any) (float64, error)
func FloatOr(in any, defVal float64) float64
func FloatOrDefault(in any, defVal float64) float64
func FloatOrErr(in any) (float64, error)
func FloatOrPanic(in any) float64
func GreaterOr[T comdef.XintOrFloat](val, min, defVal T) T
func GteOr[T comdef.XintOrFloat](val, min, defVal T) T
func HowLongAgo(sec int64) string
func InRange[T comdef.IntOrFloat](val, min, max T) bool
func InUintRange[T comdef.Uint](val, min, max T) bool
func Int(in any) (int, error)
func Int64(in any) (int64, error)
func Int64OrErr(in any) (int64, error)
func IntOr(in any, defVal int) int
func IntOrDefault(in any, defVal int) int
func IntOrErr(in any) (iVal int, err error)
func IntOrPanic(in any) int
func IsNumeric(c byte) bool
func LessOr[T comdef.XintOrFloat](val, max, devVal T) T
func LteOr[T comdef.XintOrFloat](val, max, devVal T) T
func Max[T comdef.XintOrFloat](x, y T) T
func MaxFloat(x, y float64) float64
func MaxI64(x, y int64) int64
func MaxInt(x, y int) int
func Min[T comdef.XintOrFloat](x, y T) T
func MustFloat(in any) float64
func MustInt(in any) int
func MustInt64(in any) int64
func MustString(val any) string
func MustUint(in any) uint64
func OrElse[T comdef.XintOrFloat](val, defVal T) T
func OutRange[T comdef.IntOrFloat](val, min, max T) bool
func Percent(val, total int) float64
func QuietFloat(in any) float64
func QuietInt(in any) int
func QuietInt64(in any) int64
func QuietString(val any) string
func QuietUint(in any) uint64
func RandInt(min, max int) int
func RandIntWithSeed(min, max int, seed int64) int
func RandomInt(min, max int) int
func RandomIntWithSeed(min, max int, seed int64) int
func SafeFloat(in any) float64
func SafeInt(in any) int
func SafeInt64(in any) int64
func SafeUint(in any) uint64
func StrInt(s string) int
func StrIntOr(s string, defVal int) int
func String(val any) string
func StringOrErr(val any) (string, error)
func StringOrPanic(val any) string
func SwapMax[T comdef.XintOrFloat](x, y T) (T, T)
func SwapMaxI64(x, y int64) (int64, int64)
func SwapMaxInt(x, y int) (int, int)
func SwapMin[T comdef.XintOrFloat](x, y T) (T, T)
func ToFloat(in any) (f64 float64, err error)
func ToFloatWithFunc(in any, usrFn func(any) (float64, error)) (f64 float64, err error)
func ToInt(in any) (iVal int, err error)
func ToInt64(in any) (i64 int64, err error)
func ToString(val any) (string, error)
func ToUint(in any) (u64 uint64, err error)
func ToUintWithFunc(in any, usrFn func(any) (uint64, error)) (u64 uint64, err error)
func TryToString(val any, defaultAsErr bool) (str string, err error)
func Uint(in any) (uint64, error)
func UintOrErr(in any) (uint64, error)
func ZeroOr[T comdef.XintOrFloat](val, defVal T) T

```

## Testings

```shell
Expand Down
82 changes: 39 additions & 43 deletions mathutil/check.go
Expand Up @@ -2,78 +2,74 @@ package mathutil

import "github.com/gookit/goutil/comdef"

// Compare any intX,floatX value by given op. returns `srcVal op(=,!=,<,<=,>,>=) dstVal`
// IsNumeric returns true if the given character is a numeric, otherwise false.
func IsNumeric(c byte) bool {
return c >= '0' && c <= '9'
}

// Compare any intX,floatX value by given op. returns `first op(=,!=,<,<=,>,>=) second`
//
// Usage:
//
// mathutil.Compare(2, 3, ">") // false
// mathutil.Compare(2, 1.3, ">") // true
// mathutil.Compare(2.2, 1.3, ">") // true
// mathutil.Compare(2.1, 2, ">") // true
func Compare(srcVal, dstVal any, op string) (ok bool) {
if srcVal == nil || dstVal == nil {
func Compare(first, second any, op string) bool {
if first == nil || second == nil {
return false
}

// float
if srcFlt, ok := srcVal.(float64); ok {
if dstFlt, err := ToFloat(dstVal); err == nil {
return CompFloat(srcFlt, dstFlt, op)
switch fVal := first.(type) {
case float64:
if sVal, err := ToFloat(second); err == nil {
return CompFloat(fVal, sVal, op)
}
return false
}

if srcFlt, ok := srcVal.(float32); ok {
if dstFlt, err := ToFloat(dstVal); err == nil {
return CompFloat(float64(srcFlt), dstFlt, op)
case float32:
if sVal, err := ToFloat(second); err == nil {
return CompFloat(float64(fVal), sVal, op)
}
default: // as int64
if int1, err := ToInt64(first); err == nil {
if int2, err := ToInt64(second); err == nil {
return CompInt64(int1, int2, op)
}
}
return false
}

// as int64
srcInt, err := ToInt64(srcVal)
if err != nil {
return false
}

dstInt, err := ToInt64(dstVal)
if err != nil {
return false
}

return CompInt64(srcInt, dstInt, op)
return false
}

// CompInt compare int,uint value. returns `srcVal op(=,!=,<,<=,>,>=) dstVal`
func CompInt[T comdef.Xint](srcVal, dstVal T, op string) (ok bool) {
return CompValue(srcVal, dstVal, op)
// CompInt compare all intX,uintX type value. returns `first op(=,!=,<,<=,>,>=) second`
func CompInt[T comdef.Xint](first, second T, op string) (ok bool) {
return CompValue(first, second, op)
}

// CompInt64 compare int64 value. returns `srcVal op(=,!=,<,<=,>,>=) dstVal`
func CompInt64(srcVal, dstVal int64, op string) bool {
return CompValue(srcVal, dstVal, op)
// CompInt64 compare int64 value. returns `first op(=,!=,<,<=,>,>=) second`
func CompInt64(first, second int64, op string) bool {
return CompValue(first, second, op)
}

// CompFloat compare float64,float32 value. returns `srcVal op(=,!=,<,<=,>,>=) dstVal`
func CompFloat[T comdef.Float](srcVal, dstVal T, op string) (ok bool) {
return CompValue(srcVal, dstVal, op)
// CompFloat compare float64,float32 value. returns `first op(=,!=,<,<=,>,>=) second`
func CompFloat[T comdef.Float](first, second T, op string) (ok bool) {
return CompValue(first, second, op)
}

// CompValue compare intX,uintX,floatX value. returns `srcVal op(=,!=,<,<=,>,>=) dstVal`
func CompValue[T comdef.XintOrFloat](srcVal, dstVal T, op string) (ok bool) {
// CompValue compare intX,uintX,floatX value. returns `first op(=,!=,<,<=,>,>=) second`
func CompValue[T comdef.XintOrFloat](first, second T, op string) (ok bool) {
switch op {
case "<", "lt":
ok = srcVal < dstVal
ok = first < second
case "<=", "lte":
ok = srcVal <= dstVal
ok = first <= second
case ">", "gt":
ok = srcVal > dstVal
ok = first > second
case ">=", "gte":
ok = srcVal >= dstVal
ok = first >= second
case "=", "eq":
ok = srcVal == dstVal
ok = first == second
case "!=", "ne", "neq":
ok = srcVal != dstVal
ok = first != second
}
return
}
Expand Down
20 changes: 19 additions & 1 deletion mathutil/check_test.go
Expand Up @@ -8,6 +8,11 @@ import (
"github.com/gookit/goutil/testutil/assert"
)

func TestIsNumeric(t *testing.T) {
assert.True(t, mathutil.IsNumeric('3'))
assert.False(t, mathutil.IsNumeric('a'))
}

func TestCompare(t *testing.T) {
tests := []struct {
x, y any
Expand Down Expand Up @@ -42,7 +47,20 @@ func TestCompare(t *testing.T) {
assert.False(t, mathutil.Compare("abc", 3, comdef.OpGt))
assert.False(t, mathutil.Compare(2, "def", comdef.OpGt))

assert.True(t, mathutil.CompInt64(2, 3, comdef.OpLt))
// float64
assert.False(t, mathutil.Compare(2.4, "def", comdef.OpGt))

// float32
assert.True(t, mathutil.Compare(float32(2.3), float32(2.1), comdef.OpGt))
assert.False(t, mathutil.Compare(float32(2.3), float32(2.1), "<"))
assert.False(t, mathutil.Compare(float32(2.3), "invalid", "<"))

assert.True(t, mathutil.CompInt(2, 3, comdef.OpLt))

// int64
assert.True(t, mathutil.CompInt64(int64(2), 3, comdef.OpLt))
assert.True(t, mathutil.CompInt64(int64(22), 3, comdef.OpGt))
assert.False(t, mathutil.CompInt64(int64(2), 3, comdef.OpGt))
}

func TestInRange(t *testing.T) {
Expand Down
76 changes: 76 additions & 0 deletions mathutil/compare.go
@@ -0,0 +1,76 @@
package mathutil

import (
"math"

"github.com/gookit/goutil/comdef"
)

// Min compare two value and return max value
func Min[T comdef.XintOrFloat](x, y T) T {
if x < y {
return x
}
return y
}

// Max compare two value and return max value
func Max[T comdef.XintOrFloat](x, y T) T {
if x > y {
return x
}
return y
}

// SwapMin compare and always return [min, max] value
func SwapMin[T comdef.XintOrFloat](x, y T) (T, T) {
if x < y {
return x, y
}
return y, x
}

// SwapMax compare and always return [max, min] value
func SwapMax[T comdef.XintOrFloat](x, y T) (T, T) {
if x > y {
return x, y
}
return y, x
}

// MaxInt compare and return max value
func MaxInt(x, y int) int {
if x > y {
return x
}
return y
}

// SwapMaxInt compare and return max, min value
func SwapMaxInt(x, y int) (int, int) {
if x > y {
return x, y
}
return y, x
}

// MaxI64 compare and return max value
func MaxI64(x, y int64) int64 {
if x > y {
return x
}
return y
}

// SwapMaxI64 compare and return max, min value
func SwapMaxI64(x, y int64) (int64, int64) {
if x > y {
return x, y
}
return y, x
}

// MaxFloat compare and return max value
func MaxFloat(x, y float64) float64 {
return math.Max(x, y)
}
63 changes: 63 additions & 0 deletions mathutil/compare_test.go
@@ -0,0 +1,63 @@
package mathutil_test

import (
"testing"

"github.com/gookit/goutil/mathutil"
"github.com/gookit/goutil/testutil/assert"
)

func TestMaxFloat(t *testing.T) {
assert.Eq(t, float64(3), mathutil.MaxFloat(2, 3))
assert.Eq(t, 3.3, mathutil.MaxFloat(2.1, 3.3))

assert.Eq(t, 3.3, mathutil.Max(2.1, 3.3))
assert.Eq(t, 3.3, mathutil.Max(3.3, 2.1))

assert.Eq(t, 2.1, mathutil.Min(2.1, 3.3))
assert.Eq(t, 2.1, mathutil.Min(3.3, 2.1))
}

func TestMaxI64(t *testing.T) {
assert.Eq(t, 3, mathutil.MaxInt(2, 3))
assert.Eq(t, 3, mathutil.MaxInt(3, 2))

assert.Eq(t, int64(3), mathutil.MaxI64(2, 3))
assert.Eq(t, int64(3), mathutil.MaxI64(3, 2))

assert.Eq(t, 3, mathutil.Max[int](3, 2))
assert.Eq(t, int64(3), mathutil.Max[int64](3, 2))
assert.Eq(t, int64(3), mathutil.Max(int64(3), int64(2)))
}

func TestSwapMaxInt(t *testing.T) {
x, y := mathutil.SwapMax(2, 34)
assert.Eq(t, 34, x)
assert.Eq(t, 2, y)

x, y = mathutil.SwapMax(34, 2)
assert.Eq(t, 34, x)
assert.Eq(t, 2, y)

x, y = mathutil.SwapMin(2, 34)
assert.Eq(t, 2, x)
assert.Eq(t, 34, y)

x, y = mathutil.SwapMin(34, 2)
assert.Eq(t, 2, x)
assert.Eq(t, 34, y)

x, y = mathutil.SwapMaxInt(2, 34)
assert.Eq(t, 34, x)
assert.Eq(t, 2, y)
x, y = mathutil.SwapMaxInt(34, 2)
assert.Eq(t, 34, x)
assert.Eq(t, 2, y)

x64, y64 := mathutil.SwapMaxI64(2, 34)
assert.Eq(t, int64(34), x64)
assert.Eq(t, int64(2), y64)
x64, y64 = mathutil.SwapMaxI64(34, 2)
assert.Eq(t, int64(34), x64)
assert.Eq(t, int64(2), y64)
}

0 comments on commit e906c90

Please sign in to comment.