gotosocial/vendor/modernc.org/mathutil/mathutil.go
kim ed46224573
Add SQLite support, fix un-thread-safe DB caches, small performance f… (#172)
* Add SQLite support, fix un-thread-safe DB caches, small performance fixes

Signed-off-by: kim (grufwub) <grufwub@gmail.com>

* add SQLite licenses to README

Signed-off-by: kim (grufwub) <grufwub@gmail.com>

* appease the linter, and fix my dumbass-ery

Signed-off-by: kim (grufwub) <grufwub@gmail.com>

* make requested changes

Signed-off-by: kim (grufwub) <grufwub@gmail.com>

* add back comment

Signed-off-by: kim (grufwub) <grufwub@gmail.com>
2021-08-29 16:41:41 +02:00

1605 lines
30 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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
}