// 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 ()// Architecture and/or implementation specific integer limits and bit widths.const (MaxInt = 1<<(IntBits-1) - 1MinInt = -MaxInt - 1MaxUint = 1<<IntBits - 1IntBits = 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#Implementationsfunc (, byte) byte {for != 0 { , = , % }return}// GCDUint16 returns the greatest common divisor of a and b.func (, uint16) uint16 {for != 0 { , = , % }return}// GCDUint32 returns the greatest common divisor of a and b.func (, uint32) uint32 {for != 0 { , = , % }return}// GCDUint64 returns the greatest common divisor of a and b.func (, uint64) uint64 {for != 0 { , = , % }return}// ISqrt returns floor(sqrt(n)). Typical run time is few hundreds of ns.func ( uint32) ( uint32) {if == 0 {return }if >= math.MaxUint16*math.MaxUint16 {returnmath.MaxUint16 }var , uint32for = ; ; , = , { = ( + /) / 2if == || == {break } }return}// SqrtUint64 returns floor(sqrt(n)). Typical run time is about 0.5 µs.func ( uint64) ( uint64) {if == 0 {return }if >= math.MaxUint32*math.MaxUint32 {returnmath.MaxUint32 }var , uint64for = ; ; , = , { = ( + /) / 2if == || == {break } }return}// SqrtBig returns floor(sqrt(n)). It panics on n < 0.func ( *big.Int) ( *big.Int) {switch .Sign() {case -1:panic(-1)case0:returnbig.NewInt(0) }var , big.Int = big.NewInt(0) .SetBit(, .BitLen()/2+1, 1)for { .Rsh(.Add(, .Div(, )), 1)if .Cmp() == 0 || .Cmp(&) == 0 {break } .Set() .Set(&) }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 ( byte) int {returnlog2[]}// 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 ( uint16) int {if := >> 8; != 0 {returnlog2[] + 8 }returnlog2[]}// 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 ( uint32) int {if := >> 24; != 0 {returnlog2[] + 24 }if := >> 16; != 0 {returnlog2[] + 16 }if := >> 8; != 0 {returnlog2[] + 8 }returnlog2[]}// 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 ( uint64) int {if := >> 56; != 0 {returnlog2[] + 56 }if := >> 48; != 0 {returnlog2[] + 48 }if := >> 40; != 0 {returnlog2[] + 40 }if := >> 32; != 0 {returnlog2[] + 32 }if := >> 24; != 0 {returnlog2[] + 24 }if := >> 16; != 0 {returnlog2[] + 16 }if := >> 8; != 0 {returnlog2[] + 8 }returnlog2[]}// 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_methodfunc (, , byte) byte {if == 0 && == 0 {panic(0) }if == 1 {return0 } := uint16(1)for , := uint16(), uint16(); > 0; , = *%, >>1 {if &1 == 1 { = * % } }returnbyte()}// ModPowUint16 computes (b^e)%m. It panics for m == 0 || b == e == 0.func (, , uint16) uint16 {if == 0 && == 0 {panic(0) }if == 1 {return0 } := uint32(1)for , := uint32(), uint32(); > 0; , = *%, >>1 {if &1 == 1 { = * % } }returnuint16()}// ModPowUint32 computes (b^e)%m. It panics for m == 0 || b == e == 0.func (, , uint32) uint32 {if == 0 && == 0 {panic(0) }if == 1 {return0 } := uint64(1)for , := uint64(), uint64(); > 0; , = *%, >>1 {if &1 == 1 { = * % } }returnuint32()}// ModPowUint64 computes (b^e)%m. It panics for m == 0 || b == e == 0.func (, , uint64) ( uint64) {if == 0 && == 0 {panic(0) }if == 1 {return0 }returnmodPowBigInt(big.NewInt(0).SetUint64(), big.NewInt(0).SetUint64(), big.NewInt(0).SetUint64()).Uint64()}func (, , *big.Int) ( *big.Int) { = big.NewInt(1)for , := 0, .BitLen(); < ; ++ {if .Bit() != 0 { .Mod(.Mul(, ), ) } .Mod(.Mul(, ), ) }return}// ModPowBigInt computes (b^e)%m. Returns nil for e < 0. It panics for m == 0 || b == e == 0.func (, , *big.Int) ( *big.Int) {if .Sign() == 0 && .Sign() == 0 {panic(0) }if .Cmp(_1) == 0 {returnbig.NewInt(0) }if .Sign() < 0 {return }returnmodPowBigInt(big.NewInt(0).Set(), big.NewInt(0).Set(), )}varuint64ToBigIntDeltabig.Intfunc () {uint64ToBigIntDelta.SetBit(&uint64ToBigIntDelta, 63, 1)}varuintptrBitsintfunc () { := uint64(math.MaxUint64)uintptrBits = BitLenUintptr(uintptr())}// UintptrBits returns the bit width of an uintptr at the executing machine.func () int {returnuintptrBits}// AddUint128_64 returns the uint128 sum of uint64 a and b.func (, uint64) ( uint64, uint64) { = + if < { = 1 }return , }// MulUint128_64 returns the uint128 bit product of uint64 a and b.func (, uint64) (, 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 = 32const = 1<< - 1 , , , := >>, >>, &, & = * := * := * , := AddUint128_64(, <<) , := AddUint128_64(, <<) _, = AddUint128_64(*, >>+>>++)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 (, *big.Int) ( uint32, *big.Int) {switch {case .Cmp(_2) < 0 || .Sign() < 0:returncase .Sign() == 0 || .Cmp(_1) == 0:return0, big.NewInt(1)case .Cmp(_2) == 0: = big.NewInt(0) = uint32(.BitLen() - 1) .SetBit(, int(), 1)if .Cmp() < 0 { .Mul(, _2) ++ }return } := .BitLen() := .BitLen() = big.NewInt(1)var , big.Intfor {switch .Cmp() {case -1: := uint32(( - .BitLen()) / )if == 0 { = 1 } += switch {case1: .Mul(, )default: .Set(_1) .Set() := for {if &1 != 0 { .Mul(&, &) }if >>= 1; == 0 {break } .Mul(&, &) } .Mul(, &) }case0, 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 ( uint32, *big.Int) ( uint32, *big.Int) {switch {case < 2 || .Sign() < 0:returncase .Sign() == 0 || .Cmp(_1) == 0:return0, big.NewInt(1)case == 2: = big.NewInt(0) = uint32(.BitLen() - 1) .SetBit(, int(), 1)if .Cmp() < 0 { .Mul(, _2) ++ }return }varbig.Int .SetInt64(int64())returnPowerizeBigInt(&, )}/*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' andk == 1.Wrt pseudocode shown athttp://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 afixed/non-random 'a'. Otherwise it's the same algorithm.See also: http://mathworld.wolfram.com/Rabin-MillerStrongPseudoprimeTest.html*/func (, uint32) bool { , := -1, 0for ; &1 == 0; , = >>1, +1 { } := uint64(ModPowUint32(, , ))if == 1 || uint32() == -1 {returntrue }for ; > 1; -- {if = * % uint64(); == 1 {returnfalse }ifuint32() == -1 {returntrue } }returnfalse}// 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 ( uint64, uint32) bool { , := -1, 0for ; &1 == 0; , = >>1, +1 { } := ModPowUint64(uint64(), , )if == 1 || == -1 {returntrue } , := big.NewInt(0).SetUint64(), big.NewInt(0).SetUint64()for ; > 1; -- {if = .Mod(.Mul(, ), ).Uint64(); == 1 {returnfalse }if == -1 {returntrue } }returnfalse}// 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 ( *big.Int, uint32) bool {varbig.Int .Set() .Sub(&, _1) // d <- n-1 := 0for ; .Bit() == 0; ++ { } := big.NewInt(0).Set(&) .Rsh(&, uint()) := ModPowBigInt(big.NewInt(int64()), &, )if .Cmp(_1) == 0 || .Cmp() == 0 {returntrue }for ; > 1; -- {if = .Mod(.Mul(, ), ); .Cmp(_1) == 0 {returnfalse }if .Cmp() == 0 {returntrue } }returnfalse}// 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 (, *big.Int) bool {varbig.Int .Set() .Sub(&, _1) // d <- n-1 := 0for ; .Bit() == 0; ++ { } := big.NewInt(0).Set(&) .Rsh(&, uint()) := ModPowBigInt(, &, )if .Cmp(_1) == 0 || .Cmp() == 0 {returntrue }for ; > 1; -- {if = .Mod(.Mul(, ), ); .Cmp(_1) == 0 {returnfalse }if .Cmp() == 0 {returntrue } }returnfalse}// Max returns the larger of a and b.func (, int) int {if > {return }return}// Min returns the smaller of a and b.func (, int) int {if < {return }return}// MaxPtr returns a pointer to the larger of a and b, or nil.func (, *int) *int {if == nil {return }if == nil {return }if * > * {return }return}// MinPtr returns a pointer to the smaller of a and b, or nil.func (, *int) *int {if == nil {return }if == nil {return }if * < * {return }return}// MaxVal returns the largest argument passed.func ( int, ...int) int { := for , := range {if > { = } }return}// MinVal returns the smallest argument passed.func ( int, ...int) int { := for , := range {if < { = } }return}// Clamp returns a value restricted between lo and hi.func (, , int) int {returnMin(Max(, ), )}// UMax returns the larger of a and b.func (, uint) uint {if > {return }return}// UMin returns the smaller of a and b.func (, uint) uint {if < {return }return}// UMaxPtr returns a pointer to the larger of a and b, or nil.func (, *uint) *uint {if == nil {return }if == nil {return }if * > * {return }return}// UMinPtr returns a pointer to the smaller of a and b, or nil.func (, *uint) *uint {if == nil {return }if == nil {return }if * < * {return }return}// UMaxVal returns the largest argument passed.func ( uint, ...uint) uint { := for , := range {if > { = } }return}// UMinVal returns the smallest argument passed.func ( uint, ...uint) uint { := for , := range {if < { = } }return}// UClamp returns a value restricted between lo and hi.func (, , uint) uint {returnUMin(UMax(, ), )}// MaxByte returns the larger of a and b.func (, byte) byte {if > {return }return}// MinByte returns the smaller of a and b.func (, byte) byte {if < {return }return}// MaxBytePtr returns a pointer to the larger of a and b, or nil.func (, *byte) *byte {if == nil {return }if == nil {return }if * > * {return }return}// MinBytePtr returns a pointer to the smaller of a and b, or nil.func (, *byte) *byte {if == nil {return }if == nil {return }if * < * {return }return}// MaxByteVal returns the largest argument passed.func ( byte, ...byte) byte { := for , := range {if > { = } }return}// MinByteVal returns the smallest argument passed.func ( byte, ...byte) byte { := for , := range {if < { = } }return}// ClampByte returns a value restricted between lo and hi.func (, , byte) byte {returnMinByte(MaxByte(, ), )}// MaxInt8 returns the larger of a and b.func (, int8) int8 {if > {return }return}// MinInt8 returns the smaller of a and b.func (, int8) int8 {if < {return }return}// MaxInt8Ptr returns a pointer to the larger of a and b, or nil.func (, *int8) *int8 {if == nil {return }if == nil {return }if * > * {return }return}// MinInt8Ptr returns a pointer to the smaller of a and b, or nil.func (, *int8) *int8 {if == nil {return }if == nil {return }if * < * {return }return}// MaxInt8Val returns the largest argument passed.func ( int8, ...int8) int8 { := for , := range {if > { = } }return}// MinInt8Val returns the smallest argument passed.func ( int8, ...int8) int8 { := for , := range {if < { = } }return}// ClampInt8 returns a value restricted between lo and hi.func (, , int8) int8 {returnMinInt8(MaxInt8(, ), )}// MaxUint16 returns the larger of a and b.func (, uint16) uint16 {if > {return }return}// MinUint16 returns the smaller of a and b.func (, uint16) uint16 {if < {return }return}// MaxUint16Ptr returns a pointer to the larger of a and b, or nil.func (, *uint16) *uint16 {if == nil {return }if == nil {return }if * > * {return }return}// MinUint16Ptr returns a pointer to the smaller of a and b, or nil.func (, *uint16) *uint16 {if == nil {return }if == nil {return }if * < * {return }return}// MaxUint16Val returns the largest argument passed.func ( uint16, ...uint16) uint16 { := for , := range {if > { = } }return}// MinUint16Val returns the smallest argument passed.func ( uint16, ...uint16) uint16 { := for , := range {if < { = } }return}// ClampUint16 returns a value restricted between lo and hi.func (, , uint16) uint16 {returnMinUint16(MaxUint16(, ), )}// MaxInt16 returns the larger of a and b.func (, int16) int16 {if > {return }return}// MinInt16 returns the smaller of a and b.func (, int16) int16 {if < {return }return}// MaxInt16Ptr returns a pointer to the larger of a and b, or nil.func (, *int16) *int16 {if == nil {return }if == nil {return }if * > * {return }return}// MinInt16Ptr returns a pointer to the smaller of a and b, or nil.func (, *int16) *int16 {if == nil {return }if == nil {return }if * < * {return }return}// MaxInt16Val returns the largest argument passed.func ( int16, ...int16) int16 { := for , := range {if > { = } }return}// MinInt16Val returns the smallest argument passed.func ( int16, ...int16) int16 { := for , := range {if < { = } }return}// ClampInt16 returns a value restricted between lo and hi.func (, , int16) int16 {returnMinInt16(MaxInt16(, ), )}// MaxUint32 returns the larger of a and b.func (, uint32) uint32 {if > {return }return}// MinUint32 returns the smaller of a and b.func (, uint32) uint32 {if < {return }return}// MaxUint32Ptr returns a pointer to the larger of a and b, or nil.func (, *uint32) *uint32 {if == nil {return }if == nil {return }if * > * {return }return}// MinUint32Ptr returns a pointer to the smaller of a and b, or nil.func (, *uint32) *uint32 {if == nil {return }if == nil {return }if * < * {return }return}// MaxUint32Val returns the largest argument passed.func ( uint32, ...uint32) uint32 { := for , := range {if > { = } }return}// MinUint32Val returns the smallest argument passed.func ( uint32, ...uint32) uint32 { := for , := range {if < { = } }return}// ClampUint32 returns a value restricted between lo and hi.func (, , uint32) uint32 {returnMinUint32(MaxUint32(, ), )}// MaxInt32 returns the larger of a and b.func (, int32) int32 {if > {return }return}// MinInt32 returns the smaller of a and b.func (, int32) int32 {if < {return }return}// MaxInt32Ptr returns a pointer to the larger of a and b, or nil.func (, *int32) *int32 {if == nil {return }if == nil {return }if * > * {return }return}// MinInt32Ptr returns a pointer to the smaller of a and b, or nil.func (, *int32) *int32 {if == nil {return }if == nil {return }if * < * {return }return}// MaxInt32Val returns the largest argument passed.func ( int32, ...int32) int32 { := for , := range {if > { = } }return}// MinInt32Val returns the smallest argument passed.func ( int32, ...int32) int32 { := for , := range {if < { = } }return}// ClampInt32 returns a value restricted between lo and hi.func (, , int32) int32 {returnMinInt32(MaxInt32(, ), )}// MaxUint64 returns the larger of a and b.func (, uint64) uint64 {if > {return }return}// MinUint64 returns the smaller of a and b.func (, uint64) uint64 {if < {return }return}// MaxUint64Ptr returns a pointer to the larger of a and b, or nil.func (, *uint64) *uint64 {if == nil {return }if == nil {return }if * > * {return }return}// MinUint64Ptr returns a pointer to the smaller of a and b, or nil.func (, *uint64) *uint64 {if == nil {return }if == nil {return }if * < * {return }return}// MaxUint64Val returns the largest argument passed.func ( uint64, ...uint64) uint64 { := for , := range {if > { = } }return}// MinUint64Val returns the smallest argument passed.func ( uint64, ...uint64) uint64 { := for , := range {if < { = } }return}// ClampUint64 returns a value restricted between lo and hi.func (, , uint64) uint64 {returnMinUint64(MaxUint64(, ), )}// MaxInt64 returns the larger of a and b.func (, int64) int64 {if > {return }return}// MinInt64 returns the smaller of a and b.func (, int64) int64 {if < {return }return}// MaxInt64Ptr returns a pointer to the larger of a and b, or nil.func (, *int64) *int64 {if == nil {return }if == nil {return }if * > * {return }return}// MinInt64Ptr returns a pointer to the smaller of a and b, or nil.func (, *int64) *int64 {if == nil {return }if == nil {return }if * < * {return }return}// MaxInt64Val returns the largest argument passed.func ( int64, ...int64) int64 { := for , := range {if > { = } }return}// MinInt64Val returns the smallest argument passed.func ( int64, ...int64) int64 { := for , := range {if < { = } }return}// ClampInt64 returns a value restricted between lo and hi.func (, , int64) int64 {returnMinInt64(MaxInt64(, ), )}// 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 ( *big.Int, int) []int {varbig.Int .Set()if < 2 {panic("invalid base") } := 1switch .Sign() {case -1: .Neg(&) = -1case0:return []int{0} } := big.NewInt(int64())var []int := big.NewInt(0)for .Sign() != 0 { .QuoRem(&, , ) = append(, *int(.Int64())) }return}// CheckAddInt64 returns the a+b and an indicator that the result is greater// than math.MaxInt64.func (, int64) ( int64, bool) {return + , > 0 && > math.MaxInt64- || < 0 && < math.MinInt64-}// CheckSubInt64 returns a-b and an indicator that the result is less than than// math.MinInt64.func (, int64) ( int64, bool) {return - , > 0 && -math.MaxInt64 > || < 0 && -math.MinInt64 < }// AddOverflowInt8 returns a + b and an indication whether the addition// overflowed the int8 range.func (, int8) ( int8, bool) { = + if > 0 && > 0 {return , uint8() > math.MaxInt8 }if < 0 && < 0 {return , uint8() <= math.MaxInt8 }return , false}// AddOverflowInt16 returns a + b and an indication whether the addition// overflowed the int16 range.func (, int16) ( int16, bool) { = + if > 0 && > 0 {return , uint16() > math.MaxInt16 }if < 0 && < 0 {return , uint16() <= math.MaxInt16 }return , false}// AddOverflowInt32 returns a + b and an indication whether the addition// overflowed the int32 range.func (, int32) ( int32, bool) { = + if > 0 && > 0 {return , uint32() > math.MaxInt32 }if < 0 && < 0 {return , uint32() <= math.MaxInt32 }return , false}// AddOverflowInt64 returns a + b and an indication whether the addition// overflowed the int64 range.func (, int64) ( int64, bool) { = + if > 0 && > 0 {return , uint64() > math.MaxInt64 }if < 0 && < 0 {return , uint64() <= math.MaxInt64 }return , false}// SubOverflowInt8 returns a - b and an indication whether the subtraction// overflowed the int8 range.func (, int8) ( int8, bool) { = - if >= 0 && < 0 {return , uint8() >= math.MaxInt8+1 }if < 0 && > 0 {return , uint8() <= math.MaxInt8 }return , false}// SubOverflowInt16 returns a - b and an indication whether the subtraction// overflowed the int16 range.func (, int16) ( int16, bool) { = - if >= 0 && < 0 {return , uint16() >= math.MaxInt16+1 }if < 0 && > 0 {return , uint16() <= math.MaxInt16 }return , false}// SubOverflowInt32 returns a - b and an indication whether the subtraction// overflowed the int32 range.func (, int32) ( int32, bool) { = - if >= 0 && < 0 {return , uint32() >= math.MaxInt32+1 }if < 0 && > 0 {return , uint32() <= math.MaxInt32 }return , false}// SubOverflowInt64 returns a - b and an indication whether the subtraction// overflowed the int64 range.func (, int64) ( int64, bool) { = - if >= 0 && < 0 {return , uint64() >= math.MaxInt64+1 }if < 0 && > 0 {return , uint64() <= math.MaxInt64 }return , false}// MulOverflowInt8 returns a * b and an indication whether the product// overflowed the int8 range.func (, int8) ( int8, bool) {if == 0 || == 0 {return0, false } := int16() * int16()returnint8(), < math.MinInt8 || > math.MaxInt8}// MulOverflowInt16 returns a * b and an indication whether the product// overflowed the int16 range.func (, int16) ( int16, bool) {if == 0 || == 0 {return0, false } := int32() * int32()returnint16(), < math.MinInt16 || > math.MaxInt16}// MulOverflowInt32 returns a * b and an indication whether the product// overflowed the int32 range.func (, int32) ( int32, bool) {if == 0 || == 0 {return0, false } := int64() * int64()returnint32(), < math.MinInt32 || > math.MaxInt32}// MulOverflowInt64 returns a * b and an indication whether the product// overflowed the int64 range.func (, int64) ( int64, bool) {// https://groups.google.com/g/golang-nuts/c/h5oSN5t3Au4/m/KaNQREhZh0QJconst = 1<<63 - 1const = -( + 1) = * if == 0 || == 0 || == 1 || == 1 {return , false }if == || == {return , true }return , / != }
The pages are generated with Goldsv0.3.6. (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.