Skip to content

Commit

Permalink
ivy: update to math/rand/v2
Browse files Browse the repository at this point in the history
Because math/big is not updated to v2, we must do a bit more of the lifting
ourselves, but the word-stuffing interface to big.Int makes it pretty easy.

One minor annoyance, probably not worth fixing, is that the Seed for PCG
is two words, but the UI we have only allows one.

Fixes #174
  • Loading branch information
robpike committed Jan 2, 2025
1 parent 16f847d commit eb57228
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 50 deletions.
16 changes: 8 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"fmt"
"io"
"math/big"
"math/rand"
"math/rand/v2"
"os"
"path/filepath"
"strconv"
Expand Down Expand Up @@ -40,10 +40,10 @@ type Config struct {
formatFloat bool // Whether format is floating-point.
origin int
bigOrigin *big.Int
seed int64
seed uint64
debug [len(DebugFlags)]int
traceLevel int
source rand.Source
source *rand.PCG
random *rand.Rand
randLock sync.Mutex
maxBits uint // Maximum length of an integer; 0 means no limit.
Expand All @@ -66,9 +66,9 @@ func (c *Config) init() {
c.output = os.Stdout
c.errOutput = os.Stderr
c.origin = 1
c.seed = time.Now().UnixNano()
c.seed = uint64(time.Now().UnixNano())
c.bigOrigin = big.NewInt(1)
c.source = rand.NewSource(c.seed)
c.source = rand.NewPCG(c.seed, c.seed) // Need two words. Oh well.
c.random = rand.New(c.source)
c.maxBits = 1e6
c.maxDigits = 1e4
Expand Down Expand Up @@ -222,19 +222,19 @@ func (c *Config) Random() *rand.Rand {
}

// RandomSeed returns the seed used to initialize the random number generator.
func (c *Config) RandomSeed() int64 {
func (c *Config) RandomSeed() uint64 {
c.LockRandom()
seed := c.seed
c.UnlockRandom()
return seed
}

// SetRandomSeed sets the seed for the random number generator.
func (c *Config) SetRandomSeed(seed int64) {
func (c *Config) SetRandomSeed(seed uint64) {
c.init()
c.LockRandom()
c.seed = seed
c.source.Seed(seed)
c.source.Seed(seed, seed) // All we can do for now.
c.UnlockRandom()
}

Expand Down
42 changes: 21 additions & 21 deletions demo/demo.out
Original file line number Diff line number Diff line change
Expand Up @@ -205,32 +205,32 @@ world
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
6
53
2 3 1 4 4 1 4 1 1 1 4 1 3 4 4 4 2 5 3 5
2 5 5 3 5 4 5 6 3 5 5 4 2 5 4 2 2 5 3 3
2
2 3 5
23
68
3 3 3 1 5 3 5 6 3 2 2 1 5 3 4 5 1 1 2 2
5 5 2 4 6 4 6 2 1 4 5 2 2 6 5 6 3 3 6 3
5
5 6 2
21 22 23 24 25
16 17 18 19 20
11 12 13 14 15
6 7 8 9 10
1 2 3 4 5
1 13 16 17 4 9 19 20 6 12 15 2 3 5 7 10 11 14 18 8
2 2 2 2 3 3 3 3 4 4 4 5 5 5 5 5 5 5 5 6
6 5 5 5 5 5 5 5 5 4 4 4 3 3 3 3 2 2 2 2
9 3 8 12 13 17 18 20 4 6 10 1 2 11 15 5 7 14 16 19
1 2 2 2 2 3 3 3 4 4 4 5 5 5 5 6 6 6 6 6
6 6 6 6 6 5 5 5 5 4 4 4 3 3 3 2 2 2 2 1
dehllloorw
wroolllhed
1 5 1 3 6 5 6 4 6 5
1 2 5 1 5 1 5 4 4 2
1 0 0 1 0 1 0 0 0 0
0 1 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0
0 0 1 0 1 0 1 0 0 0
3 3 5 3 3 3 2 4 6 2
3 4 1 1 2 1 1 6 2 6
0 0 1 1 0 1 1 0 0 0
0 0 0 0 1 0 0 0 1 0
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
3 2 0 2 3 0
10009 10060 10101 10006 9947 9877
0 0 0 0 0 0 0 1 0 1
4 2 1 1 0 2
10003 10005 9943 10003 9936 10110
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
18446744073709551616
2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 1073741824 2147483648 4294967296 8589934592 17179869184 34359738368 68719476736 137438953472 274877906944 549755813888 1099511627776 2199023255552 4398046511104 8796093022208 17592186044416 35184372088832 70368744177664 140737488355328 281474976710656 562949953421312 1125899906842624 2251799813685248 4503599627370496 9007199254740992 18014398509481984 36028797018963968 72057594037927936 144115188075855872 288230376151711744 576460752303423488 1152921504606846976 2305843009213693952 4611686018427387904 9223372036854775808 18446744073709551616
Expand Down Expand Up @@ -299,7 +299,7 @@ obase 10
1000000
20790751712732071385260775389205038176518395689256962640553572190852257598673381784322742265316923818079968268215969189602199756251999333965132909951960289976500893760055198463215219092698883914498589405550491920067455174599775586168862012029023648238127.07022046010735612342287230013067007929306351019435926435028561499747440517352604713511825702766039147857499953727037090383883084362025734950710726648468500009346666636430630292715823581701770581944408657475021305573686463728114465493959674058665751620534257457985005236196057918114857289948561454225538704595167673182840177586048550697493300879332131946404945958668733624356589082017084900781744552767939649882284675393555693897791351239406170600871901402146316763999367014729002406016871658214237371538566964220527856919345434240455587742731759660673744448451839668041045815121881991267912200316539315387310602396711510323411102824513044338894430799360841703725372940892716130795137220663022833926894670773439711904995174455909277266084634431285
50.5
999 995 994
980 979 978
wroo
1 1 1
3
Expand All @@ -313,7 +313,7 @@ wroo
7
105
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
6 4 7 3 1
9 5 1 10 6
(A♠) (A♡) (A♣) (A♢)
(2♠) (2♡) (2♣) (2♢)
(3♠) (3♡) (3♣) (3♢)
Expand All @@ -327,5 +327,5 @@ wroo
(J♠) (J♡) (J♣) (J♢)
(Q♠) (Q♡) (Q♣) (Q♢)
(K♠) (K♡) (K♣) (K♢)
(J♠) (6♡) (4♢) (5♢) (4♡) (7♢) (8♡) (2) (4♣) (Q♣) (9♡) (3♣) (Q♠) (2♣) (J♡) (J♣) (A♠) (K♡) (3♢) (0♣) (6) (8♠) (A♢) (A♣) (0) (9♢) (8♣) (K) (2♠) (3♡) (Q♡) (J♢) (9♠) (3♠) (K♢) (9♣) (Q♢) (7♡) (0♢) (5♠) (4♠) (0♠) (7♠) (7♣) (5♡) (6♣) (6♠) (5♣) (8♢) (A♡) (K♣) (2♡)
(A♢) (3♣) (2♢) (3♡) (0♡) (4♢) (8♡) (2) (J♢) (K♣) (J♠) (J♡) (5♠) (J♣) (5♢) (8♣) (A♠) (5♣) (K♠) (6♣) (6) (2♠) (0♢) (Q♡) (0) (4♡) (K♡) (K) (Q♢) (9♡) (4♠) (8♠) (7♢) (0♣) (7♣) (5♡) (9♢) (6♡) (9♠) (8♢) (A♡) (9♣) (A♣) (Q♠) (7♠) (3♠) (Q♣) (4♣) (6♢) (2♣) (3♢) (7♡)
22
2 changes: 1 addition & 1 deletion parse/special.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ Switch:
p.Println(conf.RandomSeed())
break Switch
}
conf.SetRandomSeed(p.nextDecimalNumber64())
conf.SetRandomSeed(uint64(p.nextDecimalNumber64()))
case "timezone":
if p.peek().Type == scan.EOF {
_, offset := time.Now().In(conf.Location()).Zone()
Expand Down
2 changes: 1 addition & 1 deletion testdata/binary_int.ivy
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@

)seed 0
5?10
9 3 4 1 6
5 6 9 2 1

2 , 5
2 5
Expand Down
2 changes: 1 addition & 1 deletion testdata/reduce.ivy
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,4 @@ floor F/%3 4 5 6 rho iota 100
)seed 0
throws = ? 10000 rho 6
+/(iota 6) o.== throws
1584 1704 1669 1699 1700 1644
1660 1684 1656 1642 1671 1687
6 changes: 3 additions & 3 deletions testdata/unary_bigfloat.ivy
Original file line number Diff line number Diff line change
Expand Up @@ -204,20 +204,20 @@ first sqrt 2
# Random numbers
)seed 0
rand 3
1.96599645204
1.32199404393

# High precision, not float64s.
)seed 0
1e1000 * rand 1e-1000
0.655332150681
0.44066468131

# Test stats. For a uniform distribution, ideally: mean = .5, 𝛔 = 1/√12 = 0.2887
)seed 0
x = rand 10000 rho 1
mean = (+/ x) / 10000
sigma = sqrt 1/10000 * +/(x - mean) ** 2
mean sigma
0.500853881349 0.288396812059
0.499676724781 0.289259555152

# There is a (possible?) but in big.Float.Copy that made this not work.
# BigFloat.inverse would change the value of floatOne. This is a simple
Expand Down
2 changes: 1 addition & 1 deletion testdata/unary_bigint.ivy
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

)seed 0
?1e10
8354553846
2226562147

1e10
10000000000
Expand Down
2 changes: 1 addition & 1 deletion testdata/unary_int.ivy
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

)seed 0
?10
6
3

23
23
Expand Down
4 changes: 2 additions & 2 deletions testdata/unary_matrix.ivy
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ rho rho 1

)seed 0
?2 3 rho iota 6
1 1 2
3 3 4
1 2 2
4 2 1

+ 2 3 rho 23 45 56
23 45 56
Expand Down
2 changes: 1 addition & 1 deletion testdata/unary_vector.ivy
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ x = 4

)seed 0
?10 10 10
6 3 8
3 7 4

+ 23 45 56
23 45 56
Expand Down
28 changes: 18 additions & 10 deletions value/unary.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,19 @@ func bigFloatWrap(op func(*big.Float, *big.Float) *big.Float) func(Context, *big
// bigIntRand sets a to a random number in [origin, origin+b].
func bigIntRand(c Context, a, b *big.Int) *big.Int {
config := c.Config()
bWords := b.Bits()
words := make([]big.Word, len(bWords))
config.LockRandom()
a.Rand(config.Random(), b)
// Words are in little-endian order.
for i := range words {
if i < len(words)-1 || words[i] == (1<<bits.UintSize)-1 { // Word is a uint.
words[i] = big.Word(c.Config().Random().Uint64())
} else {
words[i] = big.Word(c.Config().Random().Uint64N(uint64(bWords[i])))
}
}
config.UnlockRandom()
return a.Add(a, config.BigOrigin())
return a.SetBits(words).Add(a, config.BigOrigin())
}

func self(c Context, v Value) Value {
Expand Down Expand Up @@ -149,13 +158,12 @@ func bigFloatRand(c Context, f *big.Float) Value {
maxBits[i] = big.Word(^uint(0))
}
max := big.NewInt(0).SetBits(maxBits)
max.Add(max, bigIntOne.Int) // big.Int.Rand is [0,n)
// Now pick a random integer from [0 to max)
config.LockRandom()
rand := big.NewInt(0).Rand(config.Random(), max)
config.UnlockRandom()
max.Add(max, bigIntOne.Int) // We want range [0,n) but we have n-1.
// Now grab a random integer from [0, max)
randInt := big.NewInt(0)
bigIntRand(c, randInt, max)
// Make it a float and normalize it.
x := big.NewFloat(0).SetInt(rand)
x := big.NewFloat(0).SetInt(randInt)
x.Quo(x, big.NewFloat(0).SetInt(max))
// Finally, scale it up to [0, f).
x.Mul(x, f)
Expand All @@ -174,9 +182,9 @@ func init() {
Errorf("illegal roll value %v", v)
}
c.Config().LockRandom()
res := Int(c.Config().Origin()) + Int(c.Config().Random().Int63n(i))
res := Int(c.Config().Random().Int64N(int64(i)))
c.Config().UnlockRandom()
return res
return Int(c.Config().Origin()) + res
},
bigIntType: func(c Context, v Value) Value {
if v.(BigInt).Sign() <= 0 {
Expand Down

0 comments on commit eb57228

Please sign in to comment.