diff options
| author | 2025-03-09 17:47:56 +0100 | |
|---|---|---|
| committer | 2025-03-10 01:59:49 +0100 | |
| commit | 3ac1ee16f377d31a0fb80c8dae28b6239ac4229e (patch) | |
| tree | f61faa581feaaeaba2542b9f2b8234a590684413 /vendor/modernc.org/mathutil/rnd.go | |
| parent | [chore] update URLs to forked source (diff) | |
| download | gotosocial-3ac1ee16f377d31a0fb80c8dae28b6239ac4229e.tar.xz | |
[chore] remove vendor
Diffstat (limited to 'vendor/modernc.org/mathutil/rnd.go')
| -rw-r--r-- | vendor/modernc.org/mathutil/rnd.go | 383 |
1 files changed, 0 insertions, 383 deletions
diff --git a/vendor/modernc.org/mathutil/rnd.go b/vendor/modernc.org/mathutil/rnd.go deleted file mode 100644 index 08454cd81..000000000 --- a/vendor/modernc.org/mathutil/rnd.go +++ /dev/null @@ -1,383 +0,0 @@ -// 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 // import "modernc.org/mathutil" - -import ( - "fmt" - "math" - "math/big" -) - -// FC32 is a full cycle PRNG covering the 32 bit signed integer range. -// In contrast to full cycle generators shown at e.g. http://en.wikipedia.org/wiki/Full_cycle, -// this code doesn't produce values at constant delta (mod cycle length). -// The 32 bit limit is per this implementation, the algorithm used has no intrinsic limit on the cycle size. -// Properties include: -// - Adjustable limits on creation (hi, lo). -// - Positionable/randomly accessible (Pos, Seek). -// - Repeatable (deterministic). -// - Can run forward or backward (Next, Prev). -// - For a billion numbers cycle the Next/Prev PRN can be produced in cca 100-150ns. -// That's like 5-10 times slower compared to PRNs generated using the (non FC) rand package. -type FC32 struct { - cycle int64 // On average: 3 * delta / 2, (HQ: 2 * delta) - delta int64 // hi - lo - factors [][]int64 // This trades some space for hopefully a bit of speed (multiple adding vs multiplying). - lo int - mods []int // pos % set - pos int64 // Within cycle. - primes []int64 // Ordered. ∏ primes == cycle. - set []int64 // Reordered primes (magnitude order bases) according to seed. -} - -// NewFC32 returns a newly created FC32 adjusted for the closed interval [lo, hi] or an Error if any. -// If hq == true then trade some generation time for improved (pseudo)randomness. -func NewFC32(lo, hi int, hq bool) (r *FC32, err error) { - if lo > hi { - return nil, fmt.Errorf("invalid range %d > %d", lo, hi) - } - - if uint64(hi)-uint64(lo) > math.MaxUint32 { - return nil, fmt.Errorf("range out of int32 limits %d, %d", lo, hi) - } - - delta := int64(hi) - int64(lo) - // Find the primorial covering whole delta - n, set, p := int64(1), []int64{}, uint32(2) - if hq { - p++ - } - for { - set = append(set, int64(p)) - n *= int64(p) - if n > delta { - break - } - p, _ = NextPrime(p) - } - - // Adjust the set so n ∊ [delta, 2 * delta] (HQ: [delta, 3 * delta]) - // while keeping the cardinality of the set (correlates with the statistic "randomness quality") - // at max, i.e. discard atmost one member. - i := -1 // no candidate prime - if n > 2*(delta+1) { - for j, p := range set { - q := n / p - if q < delta+1 { - break - } - - i = j // mark the highest candidate prime set index - } - } - if i >= 0 { // shrink the inner cycle - n = n / set[i] - set = delete(set, i) - } - r = &FC32{ - cycle: n, - delta: delta, - factors: make([][]int64, len(set)), - lo: lo, - mods: make([]int, len(set)), - primes: set, - } - r.Seed(1) // the default seed should be always non zero - return -} - -// Cycle reports the length of the inner FCPRNG cycle. -// Cycle is atmost the double (HQ: triple) of the generator period (hi - lo + 1). -func (r *FC32) Cycle() int64 { - return r.cycle -} - -// Next returns the first PRN after Pos. -func (r *FC32) Next() int { - return r.step(1) -} - -// Pos reports the current position within the inner cycle. -func (r *FC32) Pos() int64 { - return r.pos -} - -// Prev return the first PRN before Pos. -func (r *FC32) Prev() int { - return r.step(-1) -} - -// Seed uses the provided seed value to initialize the generator to a deterministic state. -// A zero seed produces a "canonical" generator with worse randomness than for most non zero seeds. -// Still, the FC property holds for any seed value. -func (r *FC32) Seed(seed int64) { - u := uint64(seed) - r.set = mix(r.primes, &u) - n := int64(1) - for i, p := range r.set { - k := make([]int64, p) - v := int64(0) - for j := range k { - k[j] = v - v += n - } - n *= p - r.factors[i] = mix(k, &u) - } -} - -// Seek sets Pos to |pos| % Cycle. -func (r *FC32) Seek(pos int64) { //vet:ignore - if pos < 0 { - pos = -pos - } - pos %= r.cycle - r.pos = pos - for i, p := range r.set { - r.mods[i] = int(pos % p) - } -} - -func (r *FC32) step(dir int) int { - for { // avg loops per step: 3/2 (HQ: 2) - y := int64(0) - pos := r.pos - pos += int64(dir) - switch { - case pos < 0: - pos = r.cycle - 1 - case pos >= r.cycle: - pos = 0 - } - r.pos = pos - for i, mod := range r.mods { - mod += dir - p := int(r.set[i]) - switch { - case mod < 0: - mod = p - 1 - case mod >= p: - mod = 0 - } - r.mods[i] = mod - y += r.factors[i][mod] - } - if y <= r.delta { - return int(y) + r.lo - } - } -} - -func delete(set []int64, i int) (y []int64) { - for j, v := range set { - if j != i { - y = append(y, v) - } - } - return -} - -func mix(set []int64, seed *uint64) (y []int64) { - for len(set) != 0 { - *seed = rol(*seed) - i := int(*seed % uint64(len(set))) - y = append(y, set[i]) - set = delete(set, i) - } - return -} - -func rol(u uint64) (y uint64) { - y = u << 1 - if int64(u) < 0 { - y |= 1 - } - return -} - -// FCBig is a full cycle PRNG covering ranges outside of the int32 limits. -// For more info see the FC32 docs. -// Next/Prev PRN on a 1e15 cycle can be produced in about 2 µsec. -type FCBig struct { - cycle *big.Int // On average: 3 * delta / 2, (HQ: 2 * delta) - delta *big.Int // hi - lo - factors [][]*big.Int // This trades some space for hopefully a bit of speed (multiple adding vs multiplying). - lo *big.Int - mods []int // pos % set - pos *big.Int // Within cycle. - primes []int64 // Ordered. ∏ primes == cycle. - set []int64 // Reordered primes (magnitude order bases) according to seed. -} - -// NewFCBig returns a newly created FCBig adjusted for the closed interval [lo, hi] or an Error if any. -// If hq == true then trade some generation time for improved (pseudo)randomness. -func NewFCBig(lo, hi *big.Int, hq bool) (r *FCBig, err error) { - if lo.Cmp(hi) > 0 { - return nil, fmt.Errorf("invalid range %d > %d", lo, hi) - } - - delta := big.NewInt(0) - delta.Add(delta, hi).Sub(delta, lo) - - // Find the primorial covering whole delta - n, set, pp, p := big.NewInt(1), []int64{}, big.NewInt(0), uint32(2) - if hq { - p++ - } - for { - set = append(set, int64(p)) - pp.SetInt64(int64(p)) - n.Mul(n, pp) - if n.Cmp(delta) > 0 { - break - } - p, _ = NextPrime(p) - } - - // Adjust the set so n ∊ [delta, 2 * delta] (HQ: [delta, 3 * delta]) - // while keeping the cardinality of the set (correlates with the statistic "randomness quality") - // at max, i.e. discard atmost one member. - dd1 := big.NewInt(1) - dd1.Add(dd1, delta) - dd2 := big.NewInt(0) - dd2.Lsh(dd1, 1) - i := -1 // no candidate prime - if n.Cmp(dd2) > 0 { - q := big.NewInt(0) - for j, p := range set { - pp.SetInt64(p) - q.Set(n) - q.Div(q, pp) - if q.Cmp(dd1) < 0 { - break - } - - i = j // mark the highest candidate prime set index - } - } - if i >= 0 { // shrink the inner cycle - pp.SetInt64(set[i]) - n.Div(n, pp) - set = delete(set, i) - } - r = &FCBig{ - cycle: n, - delta: delta, - factors: make([][]*big.Int, len(set)), - lo: lo, - mods: make([]int, len(set)), - pos: big.NewInt(0), - primes: set, - } - r.Seed(1) // the default seed should be always non zero - return -} - -// Cycle reports the length of the inner FCPRNG cycle. -// Cycle is atmost the double (HQ: triple) of the generator period (hi - lo + 1). -func (r *FCBig) Cycle() *big.Int { - return r.cycle -} - -// Next returns the first PRN after Pos. -func (r *FCBig) Next() *big.Int { - return r.step(1) -} - -// Pos reports the current position within the inner cycle. -func (r *FCBig) Pos() *big.Int { - return r.pos -} - -// Prev return the first PRN before Pos. -func (r *FCBig) Prev() *big.Int { - return r.step(-1) -} - -// Seed uses the provided seed value to initialize the generator to a deterministic state. -// A zero seed produces a "canonical" generator with worse randomness than for most non zero seeds. -// Still, the FC property holds for any seed value. -func (r *FCBig) Seed(seed int64) { - u := uint64(seed) - r.set = mix(r.primes, &u) - n := big.NewInt(1) - v := big.NewInt(0) - pp := big.NewInt(0) - for i, p := range r.set { - k := make([]*big.Int, p) - v.SetInt64(0) - for j := range k { - k[j] = big.NewInt(0) - k[j].Set(v) - v.Add(v, n) - } - pp.SetInt64(p) - n.Mul(n, pp) - r.factors[i] = mixBig(k, &u) - } -} - -// Seek sets Pos to |pos| % Cycle. -func (r *FCBig) Seek(pos *big.Int) { - r.pos.Set(pos) - r.pos.Abs(r.pos) - r.pos.Mod(r.pos, r.cycle) - mod := big.NewInt(0) - pp := big.NewInt(0) - for i, p := range r.set { - pp.SetInt64(p) - r.mods[i] = int(mod.Mod(r.pos, pp).Int64()) - } -} - -func (r *FCBig) step(dir int) (y *big.Int) { - y = big.NewInt(0) - d := big.NewInt(int64(dir)) - for { // avg loops per step: 3/2 (HQ: 2) - r.pos.Add(r.pos, d) - switch { - case r.pos.Sign() < 0: - r.pos.Add(r.pos, r.cycle) - case r.pos.Cmp(r.cycle) >= 0: - r.pos.SetInt64(0) - } - for i, mod := range r.mods { - mod += dir - p := int(r.set[i]) - switch { - case mod < 0: - mod = p - 1 - case mod >= p: - mod = 0 - } - r.mods[i] = mod - y.Add(y, r.factors[i][mod]) - } - if y.Cmp(r.delta) <= 0 { - y.Add(y, r.lo) - return - } - y.SetInt64(0) - } -} - -func deleteBig(set []*big.Int, i int) (y []*big.Int) { - for j, v := range set { - if j != i { - y = append(y, v) - } - } - return -} - -func mixBig(set []*big.Int, seed *uint64) (y []*big.Int) { - for len(set) != 0 { - *seed = rol(*seed) - i := int(*seed % uint64(len(set))) - y = append(y, set[i]) - set = deleteBig(set, i) - } - return -} |
