File: randx.go

package info (click to toggle)
golang-github-icza-gox 0.0~git20210726.cd40a3f-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 332 kB
  • sloc: makefile: 2
file content (61 lines) | stat: -rw-r--r-- 1,528 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package randx

import "math/rand"

var randFloat64 = rand.Float64 // Mockable rand.Float64 function

// RandomWeight chooses an index randomly using the listed (non-negative)
// probabilities as weights. Weights must add up to 1.
//
// The default Rand of math/rand package is used for random data.
//
// Implementation guarantees to return an integer in the range of [0..len(weights)).
// If weights don't add up to 1, -1 may be returned.
func RandomWeight(weights ...float64) int {
	r := randFloat64()

	sum := 0.0
	for i, w := range weights {
		sum += w
		if r < sum {
			return i
		}
	}

	// We can only end up here if sum of weights is less than 1.
	return -1
}

var randIntn = rand.Intn // Mockable rand.Intn function

// RandomIntWeight chooses an index randomly using the listed non-negative
// relative weights.
//
// The default Rand of math/rand package is used for random data.
//
// Implementation guarantees to return an integer in the range of [0..len(weights)).
// If no weight is provided or they add up to 0, -1 is returned.
// Behavior for negative weights is undefined.
func RandomIntWeight(weights ...int) int {
	sum := 0
	for _, w := range weights {
		sum += w
	}

	// Return early if sum is not positive, Intn() would panic.
	if sum <= 0 {
		return -1
	}

	r, s := randIntn(sum), 0
	for i, w := range weights {
		s += w
		if r < s {
			return i
		}
	}

	// We could only end up here if weights add up to a non-positive number,
	// but that is checked earlier (and returned early).
	panic("unreachable")
}