summaryrefslogtreecommitdiffstats
path: root/vendor/modernc.org/mathutil/mathutil.go
diff options
context:
space:
mode:
authorWim <wim@42.be>2022-01-31 00:27:37 +0100
committerWim <wim@42.be>2022-03-20 14:57:48 +0100
commite3cafeaf9292f67459ff1d186f68283bfaedf2ae (patch)
treeb69c39620aa91dba695b3b935c6651c0fb37ce75 /vendor/modernc.org/mathutil/mathutil.go
parente7b193788a56ee7cdb02a87a9db0ad6724ef66d5 (diff)
downloadmatterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.tar.gz
matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.tar.bz2
matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.zip
Add dependencies/vendor (whatsapp)
Diffstat (limited to 'vendor/modernc.org/mathutil/mathutil.go')
-rw-r--r--vendor/modernc.org/mathutil/mathutil.go1604
1 files changed, 1604 insertions, 0 deletions
diff --git a/vendor/modernc.org/mathutil/mathutil.go b/vendor/modernc.org/mathutil/mathutil.go
new file mode 100644
index 00000000..6db66409
--- /dev/null
+++ b/vendor/modernc.org/mathutil/mathutil.go
@@ -0,0 +1,1604 @@
+// Copyright (c) 2014 The mathutil Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package mathutil provides utilities supplementing the standard 'math' and
+// 'math/rand' packages.
+//
+// Release history and compatibility issues
+//
+// 2020-12-20 v1.2.1 fixes MulOverflowInt64.
+//
+// 2020-12-19 Added {Add,Sub,Mul}OverflowInt{8,16,32,64}
+//
+// 2018-10-21 Added BinaryLog
+//
+// 2018-04-25: New functions for determining Max/Min of nullable values. Ex:
+// func MaxPtr(a, b *int) *int {
+// func MinPtr(a, b *int) *int {
+// func MaxBytePtr(a, b *byte) *byte {
+// func MinBytePtr(a, b *byte) *byte {
+// ...
+//
+// 2017-10-14: New variadic functions for Max/Min. Ex:
+// func MaxVal(val int, vals ...int) int {
+// func MinVal(val int, vals ...int) int {
+// func MaxByteVal(val byte, vals ...byte) byte {
+// func MinByteVal(val byte, vals ...byte) byte {
+// ...
+//
+// 2016-10-10: New functions QuadPolyDiscriminant and QuadPolyFactors.
+//
+// 2013-12-13: The following functions have been REMOVED
+//
+// func Uint64ToBigInt(n uint64) *big.Int
+// func Uint64FromBigInt(n *big.Int) (uint64, bool)
+//
+// 2013-05-13: The following functions are now DEPRECATED
+//
+// func Uint64ToBigInt(n uint64) *big.Int
+// func Uint64FromBigInt(n *big.Int) (uint64, bool)
+//
+// These functions will be REMOVED with Go release 1.1+1.
+//
+// 2013-01-21: The following functions have been REMOVED
+//
+// func MaxInt() int
+// func MinInt() int
+// func MaxUint() uint
+// func UintPtrBits() int
+//
+// They are now replaced by untyped constants
+//
+// MaxInt
+// MinInt
+// MaxUint
+// UintPtrBits
+//
+// Additionally one more untyped constant was added
+//
+// IntBits
+//
+// This change breaks any existing code depending on the above removed
+// functions. They should have not been published in the first place, that was
+// unfortunate. Instead, defining such architecture and/or implementation
+// specific integer limits and bit widths as untyped constants improves
+// performance and allows for static dead code elimination if it depends on
+// these values. Thanks to minux for pointing it out in the mail list
+// (https://groups.google.com/d/msg/golang-nuts/tlPpLW6aJw8/NT3mpToH-a4J).
+//
+// 2012-12-12: The following functions will be DEPRECATED with Go release
+// 1.0.3+1 and REMOVED with Go release 1.0.3+2, b/c of
+// http://code.google.com/p/go/source/detail?r=954a79ee3ea8
+//
+// func Uint64ToBigInt(n uint64) *big.Int
+// func Uint64FromBigInt(n *big.Int) (uint64, bool)
+package mathutil // import "modernc.org/mathutil"
+
+import (
+ "math"
+ "math/big"
+)
+
+// Architecture and/or implementation specific integer limits and bit widths.
+const (
+ MaxInt = 1<<(IntBits-1) - 1
+ MinInt = -MaxInt - 1
+ MaxUint = 1<<IntBits - 1
+ IntBits = 1 << (^uint(0)>>32&1 + ^uint(0)>>16&1 + ^uint(0)>>8&1 + 3)
+ UintPtrBits = 1 << (^uintptr(0)>>32&1 + ^uintptr(0)>>16&1 + ^uintptr(0)>>8&1 + 3)
+)
+
+var (
+ _1 = big.NewInt(1)
+ _2 = big.NewInt(2)
+)
+
+// GCDByte returns the greatest common divisor of a and b. Based on:
+// http://en.wikipedia.org/wiki/Euclidean_algorithm#Implementations
+func GCDByte(a, b byte) byte {
+ for b != 0 {
+ a, b = b, a%b
+ }
+ return a
+}
+
+// GCDUint16 returns the greatest common divisor of a and b.
+func GCDUint16(a, b uint16) uint16 {
+ for b != 0 {
+ a, b = b, a%b
+ }
+ return a
+}
+
+// GCDUint32 returns the greatest common divisor of a and b.
+func GCDUint32(a, b uint32) uint32 {
+ for b != 0 {
+ a, b = b, a%b
+ }
+ return a
+}
+
+// GCDUint64 returns the greatest common divisor of a and b.
+func GCDUint64(a, b uint64) uint64 {
+ for b != 0 {
+ a, b = b, a%b
+ }
+ return a
+}
+
+// ISqrt returns floor(sqrt(n)). Typical run time is few hundreds of ns.
+func ISqrt(n uint32) (x uint32) {
+ if n == 0 {
+ return
+ }
+
+ if n >= math.MaxUint16*math.MaxUint16 {
+ return math.MaxUint16
+ }
+
+ var px, nx uint32
+ for x = n; ; px, x = x, nx {
+ nx = (x + n/x) / 2
+ if nx == x || nx == px {
+ break
+ }
+ }
+ return
+}
+
+// SqrtUint64 returns floor(sqrt(n)). Typical run time is about 0.5 µs.
+func SqrtUint64(n uint64) (x uint64) {
+ if n == 0 {
+ return
+ }
+
+ if n >= math.MaxUint32*math.MaxUint32 {
+ return math.MaxUint32
+ }
+
+ var px, nx uint64
+ for x = n; ; px, x = x, nx {
+ nx = (x + n/x) / 2
+ if nx == x || nx == px {
+ break
+ }
+ }
+ return
+}
+
+// SqrtBig returns floor(sqrt(n)). It panics on n < 0.
+func SqrtBig(n *big.Int) (x *big.Int) {
+ switch n.Sign() {
+ case -1:
+ panic(-1)
+ case 0:
+ return big.NewInt(0)
+ }
+
+ var px, nx big.Int
+ x = big.NewInt(0)
+ x.SetBit(x, n.BitLen()/2+1, 1)
+ for {
+ nx.Rsh(nx.Add(x, nx.Div(n, x)), 1)
+ if nx.Cmp(x) == 0 || nx.Cmp(&px) == 0 {
+ break
+ }
+ px.Set(x)
+ x.Set(&nx)
+ }
+ return
+}
+
+// Log2Byte returns log base 2 of n. It's the same as index of the highest
+// bit set in n. For n == 0 -1 is returned.
+func Log2Byte(n byte) int {
+ return log2[n]
+}
+
+// Log2Uint16 returns log base 2 of n. It's the same as index of the highest
+// bit set in n. For n == 0 -1 is returned.
+func Log2Uint16(n uint16) int {
+ if b := n >> 8; b != 0 {
+ return log2[b] + 8
+ }
+
+ return log2[n]
+}
+
+// Log2Uint32 returns log base 2 of n. It's the same as index of the highest
+// bit set in n. For n == 0 -1 is returned.
+func Log2Uint32(n uint32) int {
+ if b := n >> 24; b != 0 {
+ return log2[b] + 24
+ }
+
+ if b := n >> 16; b != 0 {
+ return log2[b] + 16
+ }
+
+ if b := n >> 8; b != 0 {
+ return log2[b] + 8
+ }
+
+ return log2[n]
+}
+
+// Log2Uint64 returns log base 2 of n. It's the same as index of the highest
+// bit set in n. For n == 0 -1 is returned.
+func Log2Uint64(n uint64) int {
+ if b := n >> 56; b != 0 {
+ return log2[b] + 56
+ }
+
+ if b := n >> 48; b != 0 {
+ return log2[b] + 48
+ }
+
+ if b := n >> 40; b != 0 {
+ return log2[b] + 40
+ }
+
+ if b := n >> 32; b != 0 {
+ return log2[b] + 32
+ }
+
+ if b := n >> 24; b != 0 {
+ return log2[b] + 24
+ }
+
+ if b := n >> 16; b != 0 {
+ return log2[b] + 16
+ }
+
+ if b := n >> 8; b != 0 {
+ return log2[b] + 8
+ }
+
+ return log2[n]
+}
+
+// ModPowByte computes (b^e)%m. It panics for m == 0 || b == e == 0.
+//
+// See also: http://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method
+func ModPowByte(b, e, m byte) byte {
+ if b == 0 && e == 0 {
+ panic(0)
+ }
+
+ if m == 1 {
+ return 0
+ }
+
+ r := uint16(1)
+ for b, m := uint16(b), uint16(m); e > 0; b, e = b*b%m, e>>1 {
+ if e&1 == 1 {
+ r = r * b % m
+ }
+ }
+ return byte(r)
+}
+
+// ModPowUint16 computes (b^e)%m. It panics for m == 0 || b == e == 0.
+func ModPowUint16(b, e, m uint16) uint16 {
+ if b == 0 && e == 0 {
+ panic(0)
+ }
+
+ if m == 1 {
+ return 0
+ }
+
+ r := uint32(1)
+ for b, m := uint32(b), uint32(m); e > 0; b, e = b*b%m, e>>1 {
+ if e&1 == 1 {
+ r = r * b % m
+ }
+ }
+ return uint16(r)
+}
+
+// ModPowUint32 computes (b^e)%m. It panics for m == 0 || b == e == 0.
+func ModPowUint32(b, e, m uint32) uint32 {
+ if b == 0 && e == 0 {
+ panic(0)
+ }
+
+ if m == 1 {
+ return 0
+ }
+
+ r := uint64(1)
+ for b, m := uint64(b), uint64(m); e > 0; b, e = b*b%m, e>>1 {
+ if e&1 == 1 {
+ r = r * b % m
+ }
+ }
+ return uint32(r)
+}
+
+// ModPowUint64 computes (b^e)%m. It panics for m == 0 || b == e == 0.
+func ModPowUint64(b, e, m uint64) (r uint64) {
+ if b == 0 && e == 0 {
+ panic(0)
+ }
+
+ if m == 1 {
+ return 0
+ }
+
+ return modPowBigInt(big.NewInt(0).SetUint64(b), big.NewInt(0).SetUint64(e), big.NewInt(0).SetUint64(m)).Uint64()
+}
+
+func modPowBigInt(b, e, m *big.Int) (r *big.Int) {
+ r = big.NewInt(1)
+ for i, n := 0, e.BitLen(); i < n; i++ {
+ if e.Bit(i) != 0 {
+ r.Mod(r.Mul(r, b), m)
+ }
+ b.Mod(b.Mul(b, b), m)
+ }
+ return
+}
+
+// ModPowBigInt computes (b^e)%m. Returns nil for e < 0. It panics for m == 0 || b == e == 0.
+func ModPowBigInt(b, e, m *big.Int) (r *big.Int) {
+ if b.Sign() == 0 && e.Sign() == 0 {
+ panic(0)
+ }
+
+ if m.Cmp(_1) == 0 {
+ return big.NewInt(0)
+ }
+
+ if e.Sign() < 0 {
+ return
+ }
+
+ return modPowBigInt(big.NewInt(0).Set(b), big.NewInt(0).Set(e), m)
+}
+
+var uint64ToBigIntDelta big.Int
+
+func init() {
+ uint64ToBigIntDelta.SetBit(&uint64ToBigIntDelta, 63, 1)
+}
+
+var uintptrBits int
+
+func init() {
+ x := uint64(math.MaxUint64)
+ uintptrBits = BitLenUintptr(uintptr(x))
+}
+
+// UintptrBits returns the bit width of an uintptr at the executing machine.
+func UintptrBits() int {
+ return uintptrBits
+}
+
+// AddUint128_64 returns the uint128 sum of uint64 a and b.
+func AddUint128_64(a, b uint64) (hi uint64, lo uint64) {
+ lo = a + b
+ if lo < a {
+ hi = 1
+ }
+ return hi, lo
+}
+
+// MulUint128_64 returns the uint128 bit product of uint64 a and b.
+func MulUint128_64(a, b uint64) (hi, lo uint64) {
+ /*
+ 2^(2 W) ahi bhi + 2^W alo bhi + 2^W ahi blo + alo blo
+
+ FEDCBA98 76543210 FEDCBA98 76543210
+ ---- alo*blo ----
+ ---- alo*bhi ----
+ ---- ahi*blo ----
+ ---- ahi*bhi ----
+ */
+ const w = 32
+ const m = 1<<w - 1
+ ahi, bhi, alo, blo := a>>w, b>>w, a&m, b&m
+ lo = alo * blo
+ mid1 := alo * bhi
+ mid2 := ahi * blo
+ c1, lo := AddUint128_64(lo, mid1<<w)
+ c2, lo := AddUint128_64(lo, mid2<<w)
+ _, hi = AddUint128_64(ahi*bhi, mid1>>w+mid2>>w+c1+c2)
+ return
+}
+
+// PowerizeBigInt returns (e, p) such that e is the smallest number for which p
+// == b^e is greater or equal n. For n < 0 or b < 2 (0, nil) is returned.
+//
+// NOTE: Run time for large values of n (above about 2^1e6 ~= 1e300000) can be
+// significant and/or unacceptabe. For any smaller values of n the function
+// typically performs in sub second time. For "small" values of n (cca bellow
+// 2^1e3 ~= 1e300) the same can be easily below 10 µs.
+//
+// A special (and trivial) case of b == 2 is handled separately and performs
+// much faster.
+func PowerizeBigInt(b, n *big.Int) (e uint32, p *big.Int) {
+ switch {
+ case b.Cmp(_2) < 0 || n.Sign() < 0:
+ return
+ case n.Sign() == 0 || n.Cmp(_1) == 0:
+ return 0, big.NewInt(1)
+ case b.Cmp(_2) == 0:
+ p = big.NewInt(0)
+ e = uint32(n.BitLen() - 1)
+ p.SetBit(p, int(e), 1)
+ if p.Cmp(n) < 0 {
+ p.Mul(p, _2)
+ e++
+ }
+ return
+ }
+
+ bw := b.BitLen()
+ nw := n.BitLen()
+ p = big.NewInt(1)
+ var bb, r big.Int
+ for {
+ switch p.Cmp(n) {
+ case -1:
+ x := uint32((nw - p.BitLen()) / bw)
+ if x == 0 {
+ x = 1
+ }
+ e += x
+ switch x {
+ case 1:
+ p.Mul(p, b)
+ default:
+ r.Set(_1)
+ bb.Set(b)
+ e := x
+ for {
+ if e&1 != 0 {
+ r.Mul(&r, &bb)
+ }
+ if e >>= 1; e == 0 {
+ break
+ }
+
+ bb.Mul(&bb, &bb)
+ }
+ p.Mul(p, &r)
+ }
+ case 0, 1:
+ return
+ }
+ }
+}
+
+// PowerizeUint32BigInt returns (e, p) such that e is the smallest number for
+// which p == b^e is greater or equal n. For n < 0 or b < 2 (0, nil) is
+// returned.
+//
+// More info: see PowerizeBigInt.
+func PowerizeUint32BigInt(b uint32, n *big.Int) (e uint32, p *big.Int) {
+ switch {
+ case b < 2 || n.Sign() < 0:
+ return
+ case n.Sign() == 0 || n.Cmp(_1) == 0:
+ return 0, big.NewInt(1)
+ case b == 2:
+ p = big.NewInt(0)
+ e = uint32(n.BitLen() - 1)
+ p.SetBit(p, int(e), 1)
+ if p.Cmp(n) < 0 {
+ p.Mul(p, _2)
+ e++
+ }
+ return
+ }
+
+ var bb big.Int
+ bb.SetInt64(int64(b))
+ return PowerizeBigInt(&bb, n)
+}
+
+/*
+ProbablyPrimeUint32 returns true if n is prime or n is a pseudoprime to base a.
+It implements the Miller-Rabin primality test for one specific value of 'a' and
+k == 1.
+
+Wrt pseudocode shown at
+http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
+
+ Input: n > 3, an odd integer to be tested for primality;
+ Input: k, a parameter that determines the accuracy of the test
+ Output: composite if n is composite, otherwise probably prime
+ write n − 1 as 2^s·d with d odd by factoring powers of 2 from n − 1
+ LOOP: repeat k times:
+ pick a random integer a in the range [2, n − 2]
+ x ← a^d mod n
+ if x = 1 or x = n − 1 then do next LOOP
+ for r = 1 .. s − 1
+ x ← x^2 mod n
+ if x = 1 then return composite
+ if x = n − 1 then do next LOOP
+ return composite
+ return probably prime
+
+... this function behaves like passing 1 for 'k' and additionally a
+fixed/non-random 'a'. Otherwise it's the same algorithm.
+
+See also: http://mathworld.wolfram.com/Rabin-MillerStrongPseudoprimeTest.html
+*/
+func ProbablyPrimeUint32(n, a uint32) bool {
+ d, s := n-1, 0
+ for ; d&1 == 0; d, s = d>>1, s+1 {
+ }
+ x := uint64(ModPowUint32(a, d, n))
+ if x == 1 || uint32(x) == n-1 {
+ return true
+ }
+
+ for ; s > 1; s-- {
+ if x = x * x % uint64(n); x == 1 {
+ return false
+ }
+
+ if uint32(x) == n-1 {
+ return true
+ }
+ }
+ return false
+}
+
+// ProbablyPrimeUint64_32 returns true if n is prime or n is a pseudoprime to
+// base a. It implements the Miller-Rabin primality test for one specific value
+// of 'a' and k == 1. See also ProbablyPrimeUint32.
+func ProbablyPrimeUint64_32(n uint64, a uint32) bool {
+ d, s := n-1, 0
+ for ; d&1 == 0; d, s = d>>1, s+1 {
+ }
+ x := ModPowUint64(uint64(a), d, n)
+ if x == 1 || x == n-1 {
+ return true
+ }
+
+ bx, bn := big.NewInt(0).SetUint64(x), big.NewInt(0).SetUint64(n)
+ for ; s > 1; s-- {
+ if x = bx.Mod(bx.Mul(bx, bx), bn).Uint64(); x == 1 {
+ return false
+ }
+
+ if x == n-1 {
+ return true
+ }
+ }
+ return false
+}
+
+// ProbablyPrimeBigInt_32 returns true if n is prime or n is a pseudoprime to
+// base a. It implements the Miller-Rabin primality test for one specific value
+// of 'a' and k == 1. See also ProbablyPrimeUint32.
+func ProbablyPrimeBigInt_32(n *big.Int, a uint32) bool {
+ var d big.Int
+ d.Set(n)
+ d.Sub(&d, _1) // d <- n-1
+ s := 0
+ for ; d.Bit(s) == 0; s++ {
+ }
+ nMinus1 := big.NewInt(0).Set(&d)
+ d.Rsh(&d, uint(s))
+
+ x := ModPowBigInt(big.NewInt(int64(a)), &d, n)
+ if x.Cmp(_1) == 0 || x.Cmp(nMinus1) == 0 {
+ return true
+ }
+
+ for ; s > 1; s-- {
+ if x = x.Mod(x.Mul(x, x), n); x.Cmp(_1) == 0 {
+ return false
+ }
+
+ if x.Cmp(nMinus1) == 0 {
+ return true
+ }
+ }
+ return false
+}
+
+// ProbablyPrimeBigInt returns true if n is prime or n is a pseudoprime to base
+// a. It implements the Miller-Rabin primality test for one specific value of
+// 'a' and k == 1. See also ProbablyPrimeUint32.
+func ProbablyPrimeBigInt(n, a *big.Int) bool {
+ var d big.Int
+ d.Set(n)
+ d.Sub(&d, _1) // d <- n-1
+ s := 0
+ for ; d.Bit(s) == 0; s++ {
+ }
+ nMinus1 := big.NewInt(0).Set(&d)
+ d.Rsh(&d, uint(s))
+
+ x := ModPowBigInt(a, &d, n)
+ if x.Cmp(_1) == 0 || x.Cmp(nMinus1) == 0 {
+ return true
+ }
+
+ for ; s > 1; s-- {
+ if x = x.Mod(x.Mul(x, x), n); x.Cmp(_1) == 0 {
+ return false
+ }
+
+ if x.Cmp(nMinus1) == 0 {
+ return true
+ }
+ }
+ return false
+}
+
+// Max returns the larger of a and b.
+func Max(a, b int) int {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// Min returns the smaller of a and b.
+func Min(a, b int) int {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxPtr returns a pointer to the larger of a and b, or nil.
+func MaxPtr(a, b *int) *int {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinPtr returns a pointer to the smaller of a and b, or nil.
+func MinPtr(a, b *int) *int {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxVal returns the largest argument passed.
+func MaxVal(val int, vals ...int) int {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinVal returns the smallest argument passed.
+func MinVal(val int, vals ...int) int {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// Clamp returns a value restricted between lo and hi.
+func Clamp(v, lo, hi int) int {
+ return Min(Max(v, lo), hi)
+}
+
+// UMax returns the larger of a and b.
+func UMax(a, b uint) uint {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// UMin returns the smaller of a and b.
+func UMin(a, b uint) uint {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// UMaxPtr returns a pointer to the larger of a and b, or nil.
+func UMaxPtr(a, b *uint) *uint {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// UMinPtr returns a pointer to the smaller of a and b, or nil.
+func UMinPtr(a, b *uint) *uint {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// UMaxVal returns the largest argument passed.
+func UMaxVal(val uint, vals ...uint) uint {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// UMinVal returns the smallest argument passed.
+func UMinVal(val uint, vals ...uint) uint {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// UClamp returns a value restricted between lo and hi.
+func UClamp(v, lo, hi uint) uint {
+ return UMin(UMax(v, lo), hi)
+}
+
+// MaxByte returns the larger of a and b.
+func MaxByte(a, b byte) byte {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// MinByte returns the smaller of a and b.
+func MinByte(a, b byte) byte {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxBytePtr returns a pointer to the larger of a and b, or nil.
+func MaxBytePtr(a, b *byte) *byte {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinBytePtr returns a pointer to the smaller of a and b, or nil.
+func MinBytePtr(a, b *byte) *byte {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxByteVal returns the largest argument passed.
+func MaxByteVal(val byte, vals ...byte) byte {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinByteVal returns the smallest argument passed.
+func MinByteVal(val byte, vals ...byte) byte {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// ClampByte returns a value restricted between lo and hi.
+func ClampByte(v, lo, hi byte) byte {
+ return MinByte(MaxByte(v, lo), hi)
+}
+
+// MaxInt8 returns the larger of a and b.
+func MaxInt8(a, b int8) int8 {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// MinInt8 returns the smaller of a and b.
+func MinInt8(a, b int8) int8 {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxInt8Ptr returns a pointer to the larger of a and b, or nil.
+func MaxInt8Ptr(a, b *int8) *int8 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinInt8Ptr returns a pointer to the smaller of a and b, or nil.
+func MinInt8Ptr(a, b *int8) *int8 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxInt8Val returns the largest argument passed.
+func MaxInt8Val(val int8, vals ...int8) int8 {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinInt8Val returns the smallest argument passed.
+func MinInt8Val(val int8, vals ...int8) int8 {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// ClampInt8 returns a value restricted between lo and hi.
+func ClampInt8(v, lo, hi int8) int8 {
+ return MinInt8(MaxInt8(v, lo), hi)
+}
+
+// MaxUint16 returns the larger of a and b.
+func MaxUint16(a, b uint16) uint16 {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// MinUint16 returns the smaller of a and b.
+func MinUint16(a, b uint16) uint16 {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxUint16Ptr returns a pointer to the larger of a and b, or nil.
+func MaxUint16Ptr(a, b *uint16) *uint16 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinUint16Ptr returns a pointer to the smaller of a and b, or nil.
+func MinUint16Ptr(a, b *uint16) *uint16 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxUint16Val returns the largest argument passed.
+func MaxUint16Val(val uint16, vals ...uint16) uint16 {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinUint16Val returns the smallest argument passed.
+func MinUint16Val(val uint16, vals ...uint16) uint16 {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// ClampUint16 returns a value restricted between lo and hi.
+func ClampUint16(v, lo, hi uint16) uint16 {
+ return MinUint16(MaxUint16(v, lo), hi)
+}
+
+// MaxInt16 returns the larger of a and b.
+func MaxInt16(a, b int16) int16 {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// MinInt16 returns the smaller of a and b.
+func MinInt16(a, b int16) int16 {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxInt16Ptr returns a pointer to the larger of a and b, or nil.
+func MaxInt16Ptr(a, b *int16) *int16 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinInt16Ptr returns a pointer to the smaller of a and b, or nil.
+func MinInt16Ptr(a, b *int16) *int16 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxInt16Val returns the largest argument passed.
+func MaxInt16Val(val int16, vals ...int16) int16 {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinInt16Val returns the smallest argument passed.
+func MinInt16Val(val int16, vals ...int16) int16 {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// ClampInt16 returns a value restricted between lo and hi.
+func ClampInt16(v, lo, hi int16) int16 {
+ return MinInt16(MaxInt16(v, lo), hi)
+}
+
+// MaxUint32 returns the larger of a and b.
+func MaxUint32(a, b uint32) uint32 {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// MinUint32 returns the smaller of a and b.
+func MinUint32(a, b uint32) uint32 {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxUint32Ptr returns a pointer to the larger of a and b, or nil.
+func MaxUint32Ptr(a, b *uint32) *uint32 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinUint32Ptr returns a pointer to the smaller of a and b, or nil.
+func MinUint32Ptr(a, b *uint32) *uint32 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxUint32Val returns the largest argument passed.
+func MaxUint32Val(val uint32, vals ...uint32) uint32 {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinUint32Val returns the smallest argument passed.
+func MinUint32Val(val uint32, vals ...uint32) uint32 {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// ClampUint32 returns a value restricted between lo and hi.
+func ClampUint32(v, lo, hi uint32) uint32 {
+ return MinUint32(MaxUint32(v, lo), hi)
+}
+
+// MaxInt32 returns the larger of a and b.
+func MaxInt32(a, b int32) int32 {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// MinInt32 returns the smaller of a and b.
+func MinInt32(a, b int32) int32 {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxInt32Ptr returns a pointer to the larger of a and b, or nil.
+func MaxInt32Ptr(a, b *int32) *int32 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinInt32Ptr returns a pointer to the smaller of a and b, or nil.
+func MinInt32Ptr(a, b *int32) *int32 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxInt32Val returns the largest argument passed.
+func MaxInt32Val(val int32, vals ...int32) int32 {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinInt32Val returns the smallest argument passed.
+func MinInt32Val(val int32, vals ...int32) int32 {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// ClampInt32 returns a value restricted between lo and hi.
+func ClampInt32(v, lo, hi int32) int32 {
+ return MinInt32(MaxInt32(v, lo), hi)
+}
+
+// MaxUint64 returns the larger of a and b.
+func MaxUint64(a, b uint64) uint64 {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// MinUint64 returns the smaller of a and b.
+func MinUint64(a, b uint64) uint64 {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxUint64Ptr returns a pointer to the larger of a and b, or nil.
+func MaxUint64Ptr(a, b *uint64) *uint64 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinUint64Ptr returns a pointer to the smaller of a and b, or nil.
+func MinUint64Ptr(a, b *uint64) *uint64 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxUint64Val returns the largest argument passed.
+func MaxUint64Val(val uint64, vals ...uint64) uint64 {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinUint64Val returns the smallest argument passed.
+func MinUint64Val(val uint64, vals ...uint64) uint64 {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// ClampUint64 returns a value restricted between lo and hi.
+func ClampUint64(v, lo, hi uint64) uint64 {
+ return MinUint64(MaxUint64(v, lo), hi)
+}
+
+// MaxInt64 returns the larger of a and b.
+func MaxInt64(a, b int64) int64 {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// MinInt64 returns the smaller of a and b.
+func MinInt64(a, b int64) int64 {
+ if a < b {
+ return a
+ }
+
+ return b
+}
+
+// MaxInt64Ptr returns a pointer to the larger of a and b, or nil.
+func MaxInt64Ptr(a, b *int64) *int64 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a > *b {
+ return a
+ }
+
+ return b
+}
+
+// MinInt64Ptr returns a pointer to the smaller of a and b, or nil.
+func MinInt64Ptr(a, b *int64) *int64 {
+ if a == nil {
+ return b
+ }
+ if b == nil {
+ return a
+ }
+ if *a < *b {
+ return a
+ }
+
+ return b
+}
+
+// MaxInt64Val returns the largest argument passed.
+func MaxInt64Val(val int64, vals ...int64) int64 {
+ res := val
+ for _, v := range vals {
+ if v > res {
+ res = v
+ }
+ }
+ return res
+}
+
+// MinInt64Val returns the smallest argument passed.
+func MinInt64Val(val int64, vals ...int64) int64 {
+ res := val
+ for _, v := range vals {
+ if v < res {
+ res = v
+ }
+ }
+ return res
+}
+
+// ClampInt64 returns a value restricted between lo and hi.
+func ClampInt64(v, lo, hi int64) int64 {
+ return MinInt64(MaxInt64(v, lo), hi)
+}
+
+// ToBase produces n in base b. For example
+//
+// ToBase(2047, 22) -> [1, 5, 4]
+//
+// 1 * 22^0 1
+// 5 * 22^1 110
+// 4 * 22^2 1936
+// ----
+// 2047
+//
+// ToBase panics for bases < 2.
+func ToBase(n *big.Int, b int) []int {
+ var nn big.Int
+ nn.Set(n)
+ if b < 2 {
+ panic("invalid base")
+ }
+
+ k := 1
+ switch nn.Sign() {
+ case -1:
+ nn.Neg(&nn)
+ k = -1
+ case 0:
+ return []int{0}
+ }
+
+ bb := big.NewInt(int64(b))
+ var r []int
+ rem := big.NewInt(0)
+ for nn.Sign() != 0 {
+ nn.QuoRem(&nn, bb, rem)
+ r = append(r, k*int(rem.Int64()))
+ }
+ return r
+}
+
+// CheckAddInt64 returns the a+b and an indicator that the result is greater
+// than math.MaxInt64.
+func CheckAddInt64(a, b int64) (sum int64, gt bool) {
+ return a + b, a > 0 && b > math.MaxInt64-a || a < 0 && b < math.MinInt64-a
+}
+
+// CheckSubInt64 returns a-b and an indicator that the result is less than than
+// math.MinInt64.
+func CheckSubInt64(a, b int64) (sum int64, lt bool) {
+ return a - b, a > 0 && a-math.MaxInt64 > b || a < 0 && a-math.MinInt64 < b
+}
+
+// AddOverflowInt8 returns a + b and an indication whether the addition
+// overflowed the int8 range.
+func AddOverflowInt8(a, b int8) (r int8, ovf bool) {
+ r = a + b
+ if a > 0 && b > 0 {
+ return r, uint8(r) > math.MaxInt8
+ }
+
+ if a < 0 && b < 0 {
+ return r, uint8(r) <= math.MaxInt8
+ }
+
+ return r, false
+}
+
+// AddOverflowInt16 returns a + b and an indication whether the addition
+// overflowed the int16 range.
+func AddOverflowInt16(a, b int16) (r int16, ovf bool) {
+ r = a + b
+ if a > 0 && b > 0 {
+ return r, uint16(r) > math.MaxInt16
+ }
+
+ if a < 0 && b < 0 {
+ return r, uint16(r) <= math.MaxInt16
+ }
+
+ return r, false
+}
+
+// AddOverflowInt32 returns a + b and an indication whether the addition
+// overflowed the int32 range.
+func AddOverflowInt32(a, b int32) (r int32, ovf bool) {
+ r = a + b
+ if a > 0 && b > 0 {
+ return r, uint32(r) > math.MaxInt32
+ }
+
+ if a < 0 && b < 0 {
+ return r, uint32(r) <= math.MaxInt32
+ }
+
+ return r, false
+}
+
+// AddOverflowInt64 returns a + b and an indication whether the addition
+// overflowed the int64 range.
+func AddOverflowInt64(a, b int64) (r int64, ovf bool) {
+ r = a + b
+ if a > 0 && b > 0 {
+ return r, uint64(r) > math.MaxInt64
+ }
+
+ if a < 0 && b < 0 {
+ return r, uint64(r) <= math.MaxInt64
+ }
+
+ return r, false
+}
+
+// SubOverflowInt8 returns a - b and an indication whether the subtraction
+// overflowed the int8 range.
+func SubOverflowInt8(a, b int8) (r int8, ovf bool) {
+ r = a - b
+ if a >= 0 && b < 0 {
+ return r, uint8(r) >= math.MaxInt8+1
+ }
+
+ if a < 0 && b > 0 {
+ return r, uint8(r) <= math.MaxInt8
+ }
+
+ return r, false
+}
+
+// SubOverflowInt16 returns a - b and an indication whether the subtraction
+// overflowed the int16 range.
+func SubOverflowInt16(a, b int16) (r int16, ovf bool) {
+ r = a - b
+ if a >= 0 && b < 0 {
+ return r, uint16(r) >= math.MaxInt16+1
+ }
+
+ if a < 0 && b > 0 {
+ return r, uint16(r) <= math.MaxInt16
+ }
+
+ return r, false
+}
+
+// SubOverflowInt32 returns a - b and an indication whether the subtraction
+// overflowed the int32 range.
+func SubOverflowInt32(a, b int32) (r int32, ovf bool) {
+ r = a - b
+ if a >= 0 && b < 0 {
+ return r, uint32(r) >= math.MaxInt32+1
+ }
+
+ if a < 0 && b > 0 {
+ return r, uint32(r) <= math.MaxInt32
+ }
+
+ return r, false
+}
+
+// SubOverflowInt64 returns a - b and an indication whether the subtraction
+// overflowed the int64 range.
+func SubOverflowInt64(a, b int64) (r int64, ovf bool) {
+ r = a - b
+ if a >= 0 && b < 0 {
+ return r, uint64(r) >= math.MaxInt64+1
+ }
+
+ if a < 0 && b > 0 {
+ return r, uint64(r) <= math.MaxInt64
+ }
+
+ return r, false
+}
+
+// MulOverflowInt8 returns a * b and an indication whether the product
+// overflowed the int8 range.
+func MulOverflowInt8(a, b int8) (r int8, ovf bool) {
+ if a == 0 || b == 0 {
+ return 0, false
+ }
+
+ z := int16(a) * int16(b)
+ return int8(z), z < math.MinInt8 || z > math.MaxInt8
+}
+
+// MulOverflowInt16 returns a * b and an indication whether the product
+// overflowed the int16 range.
+func MulOverflowInt16(a, b int16) (r int16, ovf bool) {
+ if a == 0 || b == 0 {
+ return 0, false
+ }
+
+ z := int32(a) * int32(b)
+ return int16(z), z < math.MinInt16 || z > math.MaxInt16
+}
+
+// MulOverflowInt32 returns a * b and an indication whether the product
+// overflowed the int32 range.
+func MulOverflowInt32(a, b int32) (r int32, ovf bool) {
+ if a == 0 || b == 0 {
+ return 0, false
+ }
+
+ z := int64(a) * int64(b)
+ return int32(z), z < math.MinInt32 || z > math.MaxInt32
+}
+
+// MulOverflowInt64 returns a * b and an indication whether the product
+// overflowed the int64 range.
+func MulOverflowInt64(a, b int64) (r int64, ovf bool) {
+ // https://groups.google.com/g/golang-nuts/c/h5oSN5t3Au4/m/KaNQREhZh0QJ
+ const mostPositive = 1<<63 - 1
+ const mostNegative = -(mostPositive + 1)
+ r = a * b
+ if a == 0 || b == 0 || a == 1 || b == 1 {
+ return r, false
+ }
+
+ if a == mostNegative || b == mostNegative {
+ return r, true
+ }
+
+ return r, r/b != a
+}