diff --git a/utils/collection/contains.go b/utils/collection/contains.go index 7613122..dda4939 100644 --- a/utils/collection/contains.go +++ b/utils/collection/contains.go @@ -1,5 +1,61 @@ package collection +// EqualSlice 检查两个切片是否相等,当 handler 返回 true 时,表示 slice1 中的某个元素和 slice2 中的某个元素相匹配 +// - 当两个切片的容量不同时,不会影响最终的比较结果 +func EqualSlice[S ~[]V, V any](slice1 S, slice2 S, handler ComparisonHandler[V]) bool { + if len(slice1) != len(slice2) { + return false + } + for i, v1 := range slice1 { + if !handler(v1, slice2[i]) { + return false + } + } + return true +} + +// EqualComparableSlice 检查两个切片的值是否相同 +// - 当两个切片的容量不同时,不会影响最终的比较结果 +func EqualComparableSlice[S ~[]V, V comparable](slice1 S, slice2 S) bool { + if len(slice1) != len(slice2) { + return false + } + for i, v1 := range slice1 { + if v1 != slice2[i] { + return false + } + } + return true +} + +// EqualMap 检查两个 map 是否相等,当 handler 返回 true 时,表示 map1 中的某个元素和 map2 中的某个元素相匹配 +// - 当两个 map 的容量不同时,不会影响最终的比较结果 +func EqualMap[M ~map[K]V, K comparable, V any](map1 M, map2 M, handler ComparisonHandler[V]) bool { + if len(map1) != len(map2) { + return false + } + for k, v1 := range map1 { + if !handler(v1, map2[k]) { + return false + } + } + return true +} + +// EqualComparableMap 检查两个 map 的值是否相同 +// - 当两个 map 的容量不同时,不会影响最终的比较结果 +func EqualComparableMap[M ~map[K]V, K comparable, V comparable](map1 M, map2 M) bool { + if len(map1) != len(map2) { + return false + } + for k, v1 := range map1 { + if v1 != map2[k] { + return false + } + } + return true +} + // InSlice 检查 v 是否被包含在 slice 中,当 handler 返回 true 时,表示 v 和 slice 中的某个元素相匹配 func InSlice[S ~[]V, V any](slice S, v V, handler ComparisonHandler[V]) bool { if len(slice) == 0 { diff --git a/utils/collection/contains_example_test.go b/utils/collection/contains_example_test.go index 3b96d36..033f0fe 100644 --- a/utils/collection/contains_example_test.go +++ b/utils/collection/contains_example_test.go @@ -5,6 +5,58 @@ import ( "github.com/kercylan98/minotaur/utils/collection" ) +func ExampleEqualSlice() { + s1 := []int{1, 2, 3} + s2 := []int{1} + s3 := []int{1, 2, 3} + fmt.Println(collection.EqualSlice(s1, s2, func(source, target int) bool { + return source == target + })) + fmt.Println(collection.EqualSlice(s1, s3, func(source, target int) bool { + return source == target + })) + // Output: + // false + // true +} + +func ExampleEqualComparableSlice() { + s1 := []int{1, 2, 3} + s2 := []int{1} + s3 := []int{1, 2, 3} + fmt.Println(collection.EqualComparableSlice(s1, s2)) + fmt.Println(collection.EqualComparableSlice(s1, s3)) + // Output: + // false + // true +} + +func ExampleEqualMap() { + m1 := map[string]int{"a": 1, "b": 2} + m2 := map[string]int{"a": 1} + m3 := map[string]int{"a": 1, "b": 2} + fmt.Println(collection.EqualMap(m1, m2, func(source, target int) bool { + return source == target + })) + fmt.Println(collection.EqualMap(m1, m3, func(source, target int) bool { + return source == target + })) + // Output: + // false + // true +} + +func ExampleEqualComparableMap() { + m1 := map[string]int{"a": 1, "b": 2} + m2 := map[string]int{"a": 1} + m3 := map[string]int{"a": 1, "b": 2} + fmt.Println(collection.EqualComparableMap(m1, m2)) + fmt.Println(collection.EqualComparableMap(m1, m3)) + // Output: + // false + // true +} + func ExampleInSlice() { result := collection.InSlice([]int{1, 2, 3}, 2, func(source, target int) bool { return source == target diff --git a/utils/collection/contains_test.go b/utils/collection/contains_test.go index 2c339c3..f9f1b32 100644 --- a/utils/collection/contains_test.go +++ b/utils/collection/contains_test.go @@ -9,6 +9,106 @@ var intComparisonHandler = func(source, target int) bool { return source == target } +func TestEqualSlice(t *testing.T) { + var cases = []struct { + name string + input []int + inputV []int + expected bool + }{ + {"TestEqualSlice_NonEmptySliceEqual", []int{1, 2, 3}, []int{1, 2, 3}, true}, + {"TestEqualSlice_NonEmptySliceNotEqual", []int{1, 2, 3}, []int{1, 2}, false}, + {"TestEqualSlice_EmptySlice", []int{}, []int{}, true}, + {"TestEqualSlice_NilSlice", nil, nil, true}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var actual = collection.EqualSlice(c.input, c.inputV, func(source, target int) bool { + return source == target + }) + if actual != c.expected { + t.Fatalf("%s failed, expected: %v, actual: %v, error: %s", + c.name, c.expected, actual, "not as expected") + } + }) + } +} + +func TestEqualComparableSlice(t *testing.T) { + var cases = []struct { + name string + input []int + inputV []int + expected bool + }{ + {"TestEqualComparableSlice_NonEmptySliceEqual", []int{1, 2, 3}, []int{1, 2, 3}, true}, + {"TestEqualComparableSlice_NonEmptySliceNotEqual", []int{1, 2, 3}, []int{1, 2}, false}, + {"TestEqualComparableSlice_EmptySlice", []int{}, []int{}, true}, + {"TestEqualComparableSlice_NilSlice", nil, nil, true}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var actual = collection.EqualComparableSlice(c.input, c.inputV) + if actual != c.expected { + t.Fatalf("%s failed, expected: %v, actual: %v, error: %s", + c.name, c.expected, actual, "not as expected") + } + }) + } +} + +func TestEqualMap(t *testing.T) { + var cases = []struct { + name string + input map[int]int + inputV map[int]int + expected bool + }{ + {"TestEqualMap_NonEmptyMapEqual", map[int]int{1: 1, 2: 2}, map[int]int{1: 1, 2: 2}, true}, + {"TestEqualMap_NonEmptyMapNotEqual", map[int]int{1: 1, 2: 2}, map[int]int{1: 1}, false}, + {"TestEqualMap_EmptyMap", map[int]int{}, map[int]int{}, true}, + {"TestEqualMap_NilMap", nil, nil, true}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var actual = collection.EqualMap(c.input, c.inputV, func(source, target int) bool { + return source == target + }) + if actual != c.expected { + t.Fatalf("%s failed, expected: %v, actual: %v, error: %s", + c.name, c.expected, actual, "not as expected") + } + }) + } +} + +func TestEqualComparableMap(t *testing.T) { + var cases = []struct { + name string + input map[int]int + inputV map[int]int + expected bool + }{ + {"TestEqualComparableMap_NonEmptyMapEqual", map[int]int{1: 1, 2: 2}, map[int]int{1: 1, 2: 2}, true}, + {"TestEqualComparableMap_NonEmptyMapNotEqual", map[int]int{1: 1, 2: 2}, map[int]int{1: 1}, false}, + {"TestEqualComparableMap_EmptyMap", map[int]int{}, map[int]int{}, true}, + {"TestEqualComparableMap_NilMap", nil, nil, true}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var actual = collection.EqualComparableMap(c.input, c.inputV) + if actual != c.expected { + t.Fatalf("%s failed, expected: %v, actual: %v, error: %s", + c.name, c.expected, actual, "not as expected") + } + }) + } +} + func TestInSlice(t *testing.T) { var cases = []struct { name string diff --git a/utils/collection/loop.go b/utils/collection/loop.go new file mode 100644 index 0000000..9b3700c --- /dev/null +++ b/utils/collection/loop.go @@ -0,0 +1,188 @@ +package collection + +import ( + "github.com/kercylan98/minotaur/utils/generic" + "sort" +) + +// LoopSlice 迭代切片 slice 中的每一个函数,并将索引和值传递给 f 函数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopSlice[S ~[]V, V any](slice S, f func(i int, val V) bool) { + for i, v := range slice { + if !f(i, v) { + break + } + } +} + +// ReverseLoopSlice 逆序迭代切片 slice 中的每一个函数,并将索引和值传递给 f 函数 +// - 迭代过程将在 f 函数返回 false 时中断 +func ReverseLoopSlice[S ~[]V, V any](slice S, f func(i int, val V) bool) { + for i := len(slice) - 1; i >= 0; i-- { + if !f(i, slice[i]) { + break + } + } +} + +// LoopMap 迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - m 的迭代顺序是不确定的,因此每次迭代的顺序可能不同 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMap[M ~map[K]V, K comparable, V any](m M, f func(i int, key K, val V) bool) { + var i int + for k, v := range m { + if !f(i, k, v) { + break + } + i++ + } +} + +// LoopMapByOrderedKeyAsc 按照键的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMapByOrderedKeyAsc[M ~map[K]V, K generic.Ordered, V any](m M, f func(i int, key K, val V) bool) { + var keys []K + for k := range m { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { + return AscBy(keys[i], keys[j]) + }) + for i, k := range keys { + if !f(i, k, m[k]) { + break + } + } +} + +// LoopMapByOrderedKeyDesc 按照键的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMapByOrderedKeyDesc[M ~map[K]V, K generic.Ordered, V any](m M, f func(i int, key K, val V) bool) { + var keys []K + for k := range m { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { + return DescBy(keys[i], keys[j]) + }) + for i, k := range keys { + if !f(i, k, m[k]) { + break + } + } +} + +// LoopMapByOrderedValueAsc 按照值的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMapByOrderedValueAsc[M ~map[K]V, K comparable, V generic.Ordered](m M, f func(i int, key K, val V) bool) { + var keys []K + var values []V + for k, v := range m { + keys = append(keys, k) + values = append(values, v) + } + sort.Slice(values, func(i, j int) bool { + return AscBy(values[i], values[j]) + }) + for i, v := range values { + if !f(i, keys[i], v) { + break + } + } +} + +// LoopMapByOrderedValueDesc 按照值的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMapByOrderedValueDesc[M ~map[K]V, K comparable, V generic.Ordered](m M, f func(i int, key K, val V) bool) { + var keys []K + var values []V + for k, v := range m { + keys = append(keys, k) + values = append(values, v) + } + sort.Slice(values, func(i, j int) bool { + return DescBy(values[i], values[j]) + }) + for i, v := range values { + if !f(i, keys[i], v) { + break + } + } +} + +// LoopMapByKeyGetterAsc 按照键的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMapByKeyGetterAsc[M ~map[K]V, K comparable, V comparable, N generic.Ordered](m M, getter func(k K) N, f func(i int, key K, val V) bool) { + var keys []K + for k := range m { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { + return AscBy(getter(keys[i]), getter(keys[j])) + }) + for i, v := range keys { + if !f(i, keys[i], m[v]) { + break + } + } +} + +// LoopMapByValueGetterAsc 按照值的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMapByValueGetterAsc[M ~map[K]V, K comparable, V any, N generic.Ordered](m M, getter func(v V) N, f func(i int, key K, val V) bool) { + var keys []K + for k := range m { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { + return AscBy(getter(m[keys[i]]), getter(m[keys[j]])) + }) + for i, v := range keys { + if !f(i, keys[i], m[v]) { + break + } + } +} + +// LoopMapByKeyGetterDesc 按照键的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMapByKeyGetterDesc[M ~map[K]V, K comparable, V comparable, N generic.Ordered](m M, getter func(k K) N, f func(i int, key K, val V) bool) { + var keys []K + for k := range m { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { + return DescBy(getter(keys[i]), getter(keys[j])) + }) + for i, v := range keys { + if !f(i, keys[i], m[v]) { + break + } + } +} + +// LoopMapByValueGetterDesc 按照值的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数 +// - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数 +// - 迭代过程将在 f 函数返回 false 时中断 +func LoopMapByValueGetterDesc[M ~map[K]V, K comparable, V any, N generic.Ordered](m M, getter func(v V) N, f func(i int, key K, val V) bool) { + var keys []K + for k := range m { + keys = append(keys, k) + } + sort.Slice(keys, func(i, j int) bool { + return DescBy(getter(m[keys[i]]), getter(m[keys[j]])) + }) + for i, v := range keys { + if !f(i, keys[i], m[v]) { + break + } + } +} diff --git a/utils/collection/loop_example_test.go b/utils/collection/loop_example_test.go new file mode 100644 index 0000000..f725606 --- /dev/null +++ b/utils/collection/loop_example_test.go @@ -0,0 +1,159 @@ +package collection_test + +import ( + "fmt" + "github.com/kercylan98/minotaur/utils/collection" +) + +func ExampleLoopSlice() { + var result []int + collection.LoopSlice([]int{1, 2, 3, 4, 5}, func(i int, val int) bool { + result = append(result, val) + if uint(i) == 1 { + return false + } + return true + }) + fmt.Println(result) + // Output: [1 2] +} + +func ExampleReverseLoopSlice() { + var result []int + collection.ReverseLoopSlice([]int{1, 2, 3, 4, 5}, func(i int, val int) bool { + result = append(result, val) + if uint(i) == 1 { + return false + } + return true + }) + fmt.Println(result) + // Output: [5 4 3 2] +} + +func ExampleLoopMap() { + var result []int + collection.LoopMap(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool { + result = append(result, val) + return true + }) + fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3})) + // Output: + // true +} + +func ExampleLoopMapByOrderedKeyAsc() { + var result []int + collection.LoopMapByOrderedKeyAsc(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool { + result = append(result, val) + return true + }) + fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3})) + // Output: + // true +} + +func ExampleLoopMapByOrderedKeyDesc() { + var result []int + collection.LoopMapByOrderedKeyDesc(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool { + result = append(result, val) + return true + }) + fmt.Println(collection.AllInComparableSlice(result, []int{3, 2, 1})) + // Output: + // true +} + +func ExampleLoopMapByOrderedValueAsc() { + var result []int + collection.LoopMapByOrderedValueAsc(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool { + result = append(result, val) + return true + }) + fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3})) + // Output: + // true +} + +func ExampleLoopMapByOrderedValueDesc() { + var result []int + collection.LoopMapByOrderedValueDesc(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool { + result = append(result, val) + return true + }) + fmt.Println(collection.AllInComparableSlice(result, []int{3, 2, 1})) + // Output: + // true +} + +func ExampleLoopMapByKeyGetterAsc() { + var m = map[string]int{"a": 1, "b": 2, "c": 3} + var result []int + collection.LoopMapByKeyGetterAsc( + m, + func(k string) int { + return m[k] + }, + func(i int, key string, val int) bool { + result = append(result, val) + return true + }, + ) + fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3})) + // Output: + // true +} + +func ExampleLoopMapByKeyGetterDesc() { + var m = map[string]int{"a": 1, "b": 2, "c": 3} + var result []int + collection.LoopMapByKeyGetterDesc( + m, + func(k string) int { + return m[k] + }, + func(i int, key string, val int) bool { + result = append(result, val) + return true + }, + ) + fmt.Println(collection.AllInComparableSlice(result, []int{3, 2, 1})) + // Output: + // true +} + +func ExampleLoopMapByValueGetterAsc() { + var m = map[string]int{"a": 1, "b": 2, "c": 3} + var result []int + collection.LoopMapByValueGetterAsc( + m, + func(v int) int { + return v + }, + func(i int, key string, val int) bool { + result = append(result, val) + return true + }, + ) + fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3})) + // Output: + // true +} + +func ExampleLoopMapByValueGetterDesc() { + var m = map[string]int{"a": 1, "b": 2, "c": 3} + var result []int + collection.LoopMapByValueGetterDesc( + m, + func(v int) int { + return v + }, + func(i int, key string, val int) bool { + result = append(result, val) + return true + }, + ) + fmt.Println(collection.AllInComparableSlice(result, []int{3, 2, 1})) + // Output: + // true +} diff --git a/utils/collection/loop_test.go b/utils/collection/loop_test.go new file mode 100644 index 0000000..8c0c739 --- /dev/null +++ b/utils/collection/loop_test.go @@ -0,0 +1,333 @@ +package collection_test + +import ( + "github.com/kercylan98/minotaur/utils/collection" + "testing" +) + +func TestLoopSlice(t *testing.T) { + var cases = []struct { + name string + in []int + out []int + breakIndex uint + }{ + {"TestLoopSlice_Part", []int{1, 2, 3, 4, 5}, []int{1, 2}, 2}, + {"TestLoopSlice_All", []int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4, 5}, 0}, + {"TestLoopSlice_Empty", []int{}, []int{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []int + collection.LoopSlice(c.in, func(i int, val int) bool { + result = append(result, val) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopSlice(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestReverseLoopSlice(t *testing.T) { + var cases = []struct { + name string + in []int + out []int + breakIndex uint + }{ + {"TestReverseLoopSlice_Part", []int{1, 2, 3, 4, 5}, []int{5, 4}, 2}, + {"TestReverseLoopSlice_All", []int{1, 2, 3, 4, 5}, []int{5, 4, 3, 2, 1}, 0}, + {"TestReverseLoopSlice_Empty", []int{}, []int{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []int + collection.ReverseLoopSlice(c.in, func(i int, val int) bool { + result = append(result, val) + if c.breakIndex != 0 && uint(i) == uint(len(c.in))-c.breakIndex { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("ReverseLoopSlice(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMap(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out map[int]string + breakIndex uint + }{ + {"TestLoopMap_Part", map[int]string{1: "1", 2: "2", 3: "3"}, map[int]string{1: "1", 2: "2"}, 2}, + {"TestLoopMap_All", map[int]string{1: "1", 2: "2", 3: "3"}, map[int]string{1: "1", 2: "2", 3: "3"}, 0}, + {"TestLoopMap_Empty", map[int]string{}, map[int]string{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result = make(map[int]string) + collection.LoopMap(c.in, func(i int, key int, val string) bool { + result[key] = val + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableMap(result, c.out) { + t.Errorf("LoopMap(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMapByOrderedKeyAsc(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out []int + breakIndex uint + }{ + {"TestLoopMapByOrderedKeyAsc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []int{1, 2}, 2}, + {"TestLoopMapByOrderedKeyAsc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []int{1, 2, 3}, 0}, + {"TestLoopMapByOrderedKeyAsc_Empty", map[int]string{}, []int{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []int + collection.LoopMapByOrderedKeyAsc(c.in, func(i int, key int, val string) bool { + result = append(result, key) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopMapByOrderedKeyAsc(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMapByOrderedKeyDesc(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out []int + breakIndex uint + }{ + {"TestLoopMapByOrderedKeyDesc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []int{3, 2}, 2}, + {"TestLoopMapByOrderedKeyDesc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []int{3, 2, 1}, 0}, + {"TestLoopMapByOrderedKeyDesc_Empty", map[int]string{}, []int{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []int + collection.LoopMapByOrderedKeyDesc(c.in, func(i int, key int, val string) bool { + result = append(result, key) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopMapByOrderedKeyDesc(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMapByOrderedValueAsc(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out []string + breakIndex uint + }{ + {"TestLoopMapByOrderedValueAsc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"1", "2"}, 2}, + {"TestLoopMapByOrderedValueAsc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"1", "2", "3"}, 0}, + {"TestLoopMapByOrderedValueAsc_Empty", map[int]string{}, []string{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []string + collection.LoopMapByOrderedValueAsc(c.in, func(i int, key int, val string) bool { + result = append(result, val) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopMapByOrderedValueAsc(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMapByOrderedValueDesc(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out []string + breakIndex uint + }{ + {"TestLoopMapByOrderedValueDesc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"3", "2"}, 2}, + {"TestLoopMapByOrderedValueDesc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"3", "2", "1"}, 0}, + {"TestLoopMapByOrderedValueDesc_Empty", map[int]string{}, []string{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []string + collection.LoopMapByOrderedValueDesc(c.in, func(i int, key int, val string) bool { + result = append(result, val) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopMapByOrderedValueDesc(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMapByKeyGetterAsc(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out []int + breakIndex uint + }{ + {"TestLoopMapByKeyGetterAsc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []int{1, 2}, 2}, + {"TestLoopMapByKeyGetterAsc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []int{1, 2, 3}, 0}, + {"TestLoopMapByKeyGetterAsc_Empty", map[int]string{}, []int{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []int + collection.LoopMapByKeyGetterAsc(c.in, func(key int) int { + return key + }, func(i int, key int, val string) bool { + result = append(result, key) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopMapByKeyGetterAsc(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMapByKeyGetterDesc(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out []int + breakIndex uint + }{ + {"TestLoopMapByKeyGetterDesc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []int{3, 2}, 2}, + {"TestLoopMapByKeyGetterDesc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []int{3, 2, 1}, 0}, + {"TestLoopMapByKeyGetterDesc_Empty", map[int]string{}, []int{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []int + collection.LoopMapByKeyGetterDesc(c.in, func(key int) int { + return key + }, func(i int, key int, val string) bool { + result = append(result, key) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopMapByKeyGetterDesc(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMapByValueGetterAsc(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out []string + breakIndex uint + }{ + {"TestLoopMapByValueGetterAsc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"1", "2"}, 2}, + {"TestLoopMapByValueGetterAsc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"1", "2", "3"}, 0}, + {"TestLoopMapByValueGetterAsc_Empty", map[int]string{}, []string{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []string + collection.LoopMapByValueGetterAsc(c.in, func(val string) string { + return val + }, func(i int, key int, val string) bool { + result = append(result, val) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopMapByValueGetterAsc(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} + +func TestLoopMapByValueGetterDesc(t *testing.T) { + var cases = []struct { + name string + in map[int]string + out []string + breakIndex uint + }{ + {"TestLoopMapByValueGetterDesc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"3", "2"}, 2}, + {"TestLoopMapByValueGetterDesc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"3", "2", "1"}, 0}, + {"TestLoopMapByValueGetterDesc_Empty", map[int]string{}, []string{}, 0}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var result []string + collection.LoopMapByValueGetterDesc(c.in, func(val string) string { + return val + }, func(i int, key int, val string) bool { + result = append(result, val) + if c.breakIndex != 0 && uint(i) == c.breakIndex-1 { + return false + } + return true + }) + if !collection.EqualComparableSlice(result, c.out) { + t.Errorf("LoopMapByValueGetterDesc(%v) got %v, want %v", c.in, result, c.out) + } + }) + } +} diff --git a/utils/huge/int.go b/utils/huge/int.go index b46bf54..44bc742 100644 --- a/utils/huge/int.go +++ b/utils/huge/int.go @@ -85,42 +85,67 @@ func (slf *Int) SetInt(i int) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetInt8 设置当前 Int 对象的值为 i func (slf *Int) SetInt8(i int8) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetInt16 设置当前 Int 对象的值为 i func (slf *Int) SetInt16(i int16) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetInt32 设置当前 Int 对象的值为 i func (slf *Int) SetInt32(i int32) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetInt64 设置当前 Int 对象的值为 i func (slf *Int) SetInt64(i int64) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetUint 设置当前 Int 对象的值为 i func (slf *Int) SetUint(i uint) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetUint8 设置当前 Int 对象的值为 i func (slf *Int) SetUint8(i uint8) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetUint16 设置当前 Int 对象的值为 i func (slf *Int) SetUint16(i uint16) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetUint32 设置当前 Int 对象的值为 i func (slf *Int) SetUint32(i uint32) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetUint64 设置当前 Int 对象的值为 i func (slf *Int) SetUint64(i uint64) *Int { return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) } +// SetFloat32 设置当前 Int 对象的值为 i 向下取整后的值 +func (slf *Int) SetFloat32(i float32) *Int { + return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) +} + +// SetFloat64 设置当前 Int 对象的值为 i 向下取整后的值 +func (slf *Int) SetFloat64(i float64) *Int { + return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) +} + +// SetBool 设置当前 Int 对象的值为 i,当 i 为 true 时,值为 1,当 i 为 false 时,值为 0 +func (slf *Int) SetBool(i bool) *Int { + return (*Int)(slf.ToBigint().Set((*big.Int)(NewInt(i)))) +} + +// IsZero 判断当前 Int 对象的值是否为 0 func (slf *Int) IsZero() bool { if slf == nil || slf.EqualTo(IntZero) { return true @@ -128,6 +153,7 @@ func (slf *Int) IsZero() bool { return false } +// ToBigint 转换为 *big.Int func (slf *Int) ToBigint() *big.Int { if slf == nil { return big.NewInt(0) @@ -140,35 +166,37 @@ func (slf *Int) Cmp(i *Int) int { return slf.ToBigint().Cmp(i.ToBigint()) } -// GreaterThan 大于 +// GreaterThan 检查 slf 是否大于 i func (slf *Int) GreaterThan(i *Int) bool { return slf.Cmp(i) > 0 } -// GreaterThanOrEqualTo 大于或等于 +// GreaterThanOrEqualTo 检查 slf 是否大于或等于 i func (slf *Int) GreaterThanOrEqualTo(i *Int) bool { return slf.Cmp(i) >= 0 } -// LessThan 小于 +// LessThan 检查 slf 是否小于 i func (slf *Int) LessThan(i *Int) bool { return slf.Cmp(i) < 0 } -// LessThanOrEqualTo 小于或等于 +// LessThanOrEqualTo 检查 slf 是否小于或等于 i func (slf *Int) LessThanOrEqualTo(i *Int) bool { return slf.Cmp(i) <= 0 } -// EqualTo 等于 +// EqualTo 检查 slf 是否等于 i func (slf *Int) EqualTo(i *Int) bool { return slf.Cmp(i) == 0 } +// Int64 转换为 int64 类型进行返回 func (slf *Int) Int64() int64 { return slf.ToBigint().Int64() } +// String 转换为 string 类型进行返回 func (slf *Int) String() string { if slf == nil { return "0" @@ -176,6 +204,7 @@ func (slf *Int) String() string { return slf.ToBigint().String() } +// Add 使用 i 对 slf 进行加法运算,slf 的值会变为运算后的值。返回 slf func (slf *Int) Add(i *Int) *Int { x := slf.ToBigint() return (*Int)(x.Add(x, i.ToBigint())) diff --git a/utils/huge/int_example_test.go b/utils/huge/int_example_test.go new file mode 100644 index 0000000..c4ce3f0 --- /dev/null +++ b/utils/huge/int_example_test.go @@ -0,0 +1,42 @@ +package huge_test + +import ( + "fmt" + "github.com/kercylan98/minotaur/utils/huge" +) + +// 该案例展示了 NewInt 对各种基本类型的支持及用法 +func ExampleNewInt() { + fmt.Println(huge.NewInt("12345678900000000")) + fmt.Println(huge.NewInt(1234567890)) + fmt.Println(huge.NewInt(true)) + fmt.Println(huge.NewInt(123.123)) + fmt.Println(huge.NewInt(byte(1))) + // Output: + // 12345678900000000 + // 1234567890 + // 1 + // 123 + // 1 +} + +func ExampleInt_Copy() { + var a = huge.NewInt(1234567890) + var b = a.Copy().SetInt64(9876543210) + fmt.Println(a) + fmt.Println(b) + // Output: + // 1234567890 + // 9876543210 +} + +func ExampleInt_Set() { + var a = huge.NewInt(1234567890) + var b = huge.NewInt(9876543210) + fmt.Println(a) + a.Set(b) + fmt.Println(a) + // Output: + // 1234567890 + // 9876543210 +} diff --git a/utils/huge/int_test.go b/utils/huge/int_test.go index cfdc4d8..851ac30 100644 --- a/utils/huge/int_test.go +++ b/utils/huge/int_test.go @@ -2,6 +2,7 @@ package huge_test import ( "github.com/kercylan98/minotaur/utils/huge" + "math/big" "testing" ) @@ -38,7 +39,7 @@ func TestNewInt(t *testing.T) { got = huge.NewInt(c.in).MulInt64(c.mul) } if s := got.String(); s != c.want { - t.Errorf("want: %s, got: %s", c.want, got.String()) + t.Fatalf("want: %s, got: %s", c.want, got.String()) } else { t.Log(s) } @@ -67,3 +68,458 @@ func TestNewInt(t *testing.T) { } }) } + +func TestInt_Copy(t *testing.T) { + var cases = []struct { + name string + in int64 + want string + }{ + {name: "TestIntCopyNegative", in: -1, want: "-1"}, + {name: "TestIntCopyZero", in: 0, want: "0"}, + {name: "TestIntCopyPositive", in: 1, want: "1"}, + {name: "TestIntCopyMax", in: 9223372036854775807, want: "9223372036854775807"}, + {name: "TestIntCopyMin", in: -9223372036854775808, want: "-9223372036854775808"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in = huge.NewInt(c.in) + var got = in.Copy() + if in.Int64() != c.in { + t.Fatalf("want: %d, got: %d", c.in, in.Int64()) + } + if s := got.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, got.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_Set(t *testing.T) { + var cases = []struct { + name string + in int64 + want string + }{ + {name: "TestIntSetNegative", in: -1, want: "-1"}, + {name: "TestIntSetZero", in: 0, want: "0"}, + {name: "TestIntSetPositive", in: 1, want: "1"}, + {name: "TestIntSetMax", in: 9223372036854775807, want: "9223372036854775807"}, + {name: "TestIntSetMin", in: -9223372036854775808, want: "-9223372036854775808"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.Set(huge.NewInt(c.in)) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetString(t *testing.T) { + var cases = []struct { + name string + in string + want string + }{ + {name: "TestIntSetStringNegative", in: "-1", want: "-1"}, + {name: "TestIntSetStringZero", in: "0", want: "0"}, + {name: "TestIntSetStringPositive", in: "1", want: "1"}, + {name: "TestIntSetStringMax", in: "9223372036854775807", want: "9223372036854775807"}, + {name: "TestIntSetStringMin", in: "-9223372036854775808", want: "-9223372036854775808"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetString(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetInt(t *testing.T) { + var cases = []struct { + name string + in int64 + want string + }{ + {name: "TestIntSetIntNegative", in: -1, want: "-1"}, + {name: "TestIntSetIntZero", in: 0, want: "0"}, + {name: "TestIntSetIntPositive", in: 1, want: "1"}, + {name: "TestIntSetIntMax", in: 9223372036854775807, want: "9223372036854775807"}, + {name: "TestIntSetIntMin", in: -9223372036854775808, want: "-9223372036854775808"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetInt64(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetInt8(t *testing.T) { + var cases = []struct { + name string + in int8 + want string + }{ + {name: "TestIntSetInt8Negative", in: -1, want: "-1"}, + {name: "TestIntSetInt8Zero", in: 0, want: "0"}, + {name: "TestIntSetInt8Positive", in: 1, want: "1"}, + {name: "TestIntSetInt8Max", in: 127, want: "127"}, + {name: "TestIntSetInt8Min", in: -128, want: "-128"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetInt8(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetInt16(t *testing.T) { + var cases = []struct { + name string + in int16 + want string + }{ + {name: "TestIntSetInt16Negative", in: -1, want: "-1"}, + {name: "TestIntSetInt16Zero", in: 0, want: "0"}, + {name: "TestIntSetInt16Positive", in: 1, want: "1"}, + {name: "TestIntSetInt16Max", in: 32767, want: "32767"}, + {name: "TestIntSetInt16Min", in: -32768, want: "-32768"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetInt16(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetInt32(t *testing.T) { + var cases = []struct { + name string + in int32 + want string + }{ + {name: "TestIntSetInt32Negative", in: -1, want: "-1"}, + {name: "TestIntSetInt32Zero", in: 0, want: "0"}, + {name: "TestIntSetInt32Positive", in: 1, want: "1"}, + {name: "TestIntSetInt32Max", in: 2147483647, want: "2147483647"}, + {name: "TestIntSetInt32Min", in: -2147483648, want: "-2147483648"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetInt32(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetInt64(t *testing.T) { + var cases = []struct { + name string + in int64 + want string + }{ + {name: "TestIntSetInt64Negative", in: -1, want: "-1"}, + {name: "TestIntSetInt64Zero", in: 0, want: "0"}, + {name: "TestIntSetInt64Positive", in: 1, want: "1"}, + {name: "TestIntSetInt64Max", in: 9223372036854775807, want: "9223372036854775807"}, + {name: "TestIntSetInt64Min", in: -9223372036854775808, want: "-9223372036854775808"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetInt64(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetUint(t *testing.T) { + var cases = []struct { + name string + in uint64 + want string + }{ + {name: "TestIntSetUintNegative", in: 0, want: "0"}, + {name: "TestIntSetUintZero", in: 0, want: "0"}, + {name: "TestIntSetUintPositive", in: 1, want: "1"}, + {name: "TestIntSetUintMax", in: 18446744073709551615, want: "18446744073709551615"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetUint64(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetUint8(t *testing.T) { + var cases = []struct { + name string + in uint8 + want string + }{ + {name: "TestIntSetUint8Negative", in: 0, want: "0"}, + {name: "TestIntSetUint8Zero", in: 0, want: "0"}, + {name: "TestIntSetUint8Positive", in: 1, want: "1"}, + {name: "TestIntSetUint8Max", in: 255, want: "255"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetUint8(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetUint16(t *testing.T) { + var cases = []struct { + name string + in uint16 + want string + }{ + {name: "TestIntSetUint16Negative", in: 0, want: "0"}, + {name: "TestIntSetUint16Zero", in: 0, want: "0"}, + {name: "TestIntSetUint16Positive", in: 1, want: "1"}, + {name: "TestIntSetUint16Max", in: 65535, want: "65535"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetUint16(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetUint32(t *testing.T) { + var cases = []struct { + name string + in uint32 + want string + }{ + {name: "TestIntSetUint32Negative", in: 0, want: "0"}, + {name: "TestIntSetUint32Zero", in: 0, want: "0"}, + {name: "TestIntSetUint32Positive", in: 1, want: "1"}, + {name: "TestIntSetUint32Max", in: 4294967295, want: "4294967295"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetUint32(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetUint64(t *testing.T) { + var cases = []struct { + name string + in uint64 + want string + }{ + {name: "TestIntSetUint64Negative", in: 0, want: "0"}, + {name: "TestIntSetUint64Zero", in: 0, want: "0"}, + {name: "TestIntSetUint64Positive", in: 1, want: "1"}, + {name: "TestIntSetUint64Max", in: 18446744073709551615, want: "18446744073709551615"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetUint64(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetFloat32(t *testing.T) { + var cases = []struct { + name string + in float32 + want string + }{ + {name: "TestIntSetFloat32Negative", in: -1.1, want: "-1"}, + {name: "TestIntSetFloat32Zero", in: 0, want: "0"}, + {name: "TestIntSetFloat32Positive", in: 1.1, want: "1"}, + {name: "TestIntSetFloat32Max", in: 9223372036854775807, want: "9223372036854775807"}, + {name: "TestIntSetFloat32Min", in: -9223372036854775808, want: "-9223372036854775808"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetFloat32(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetFloat64(t *testing.T) { + var cases = []struct { + name string + in float64 + want string + }{ + {name: "TestIntSetFloat64Negative", in: -1.1, want: "-1"}, + {name: "TestIntSetFloat64Zero", in: 0, want: "0"}, + {name: "TestIntSetFloat64Positive", in: 1.1, want: "1"}, + {name: "TestIntSetFloat64Max", in: 9223372036854775807, want: "9223372036854775807"}, + {name: "TestIntSetFloat64Min", in: -9223372036854775808, want: "-9223372036854775808"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetFloat64(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_SetBool(t *testing.T) { + var cases = []struct { + name string + in bool + want string + }{ + {name: "TestIntSetBoolFalse", in: false, want: "0"}, + {name: "TestIntSetBoolTrue", in: true, want: "1"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + var in *huge.Int + in = in.SetBool(c.in) + if s := in.String(); s != c.want { + t.Fatalf("want: %s, got: %s", c.want, in.String()) + } else { + t.Log(s) + } + }) + } +} + +func TestInt_IsZero(t *testing.T) { + var cases = []struct { + name string + in int64 + want bool + }{ + {name: "TestIntIsZeroNegative", in: -1, want: false}, + {name: "TestIntIsZeroZero", in: 0, want: true}, + {name: "TestIntIsZeroPositive", in: 1, want: false}, + {name: "TestIntIsZeroMax", in: 9223372036854775807, want: false}, + {name: "TestIntIsZeroMin", in: -9223372036854775808, want: false}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + if got := huge.NewInt(c.in).IsZero(); got != c.want { + t.Fatalf("want: %t, got: %t", c.want, got) + } + }) + } +} + +func TestInt_ToBigint(t *testing.T) { + var cases = []struct { + name string + in int64 + want *big.Int + }{ + {name: "TestIntToBigintNegative", in: -1, want: big.NewInt(-1)}, + {name: "TestIntToBigintZero", in: 0, want: big.NewInt(0)}, + {name: "TestIntToBigintPositive", in: 1, want: big.NewInt(1)}, + {name: "TestIntToBigintMax", in: 9223372036854775807, want: big.NewInt(9223372036854775807)}, + {name: "TestIntToBigintMin", in: -9223372036854775808, want: big.NewInt(-9223372036854775808)}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + if got := huge.NewInt(c.in).ToBigint(); got.Cmp(c.want) != 0 { + t.Fatalf("want: %s, got: %s", c.want.String(), got.String()) + } + }) + } +}