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