Skip to content

Commit

Permalink
added Copier and Jumper interfaces; made all prngs implement Copier
Browse files Browse the repository at this point in the history
  • Loading branch information
zephyrtronium committed Jun 9, 2019
1 parent 464b785 commit d6ce698
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 0 deletions.
6 changes: 6 additions & 0 deletions lfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ func (lfg *LFG) Restore(from io.Reader) (n int, err error) {
return n, nil
}

// Copy creates a copy of the generator.
func (lfg *LFG) Copy() Copier {
l := *lfg
return &l
}

// lfgs0 is the initial seed state. This is the state of the algorithm after
// 2**34 iterations initialized with 0, 1, ... 606.
var lfgS0 = [lfgK]uint64{
Expand Down
13 changes: 13 additions & 0 deletions lfg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ func TestLFGSave(t *testing.T) {
}
}

func TestLFGCopy(t *testing.T) {
lfg := CryptoSeeded(NewLFG(), lfgK).(*LFG)
x, y := make([]byte, 8000), make([]byte, 8000)
for i := 0; i < 2*lfgK; i++ {
cp := lfg.Copy()
lfg.Read(x)
cp.Read(y)
if !bytes.Equal(x, y) {
t.Fail()
}
}
}

func BenchmarkLFG(b *testing.B) {
lfg := CryptoSeeded(NewLFG(), lfgK).(*LFG)
f := func(p []byte) func(b *testing.B) {
Expand Down
6 changes: 6 additions & 0 deletions mt64-19937.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,9 @@ func (mt *MT64) Restore(from io.Reader) (n int, err error) {
mt.i = int(p[len(p)-2])<<8 | int(p[len(p)-1])
return n, nil
}

// Copy creates a copy of the generator.
func (mt *MT64) Copy() Copier {
m := *mt
return &m
}
13 changes: 13 additions & 0 deletions mt64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ func TestMT64Save(t *testing.T) {
}
}

func TestMT64Copy(t *testing.T) {
mt := CryptoSeeded(NewMT64(), mt64N).(*MT64)
x, y := make([]byte, 8000), make([]byte, 8000)
for i := 0; i < 2*mt64N; i++ {
cp := mt.Copy()
mt.Read(x)
cp.Read(y)
if !bytes.Equal(x, y) {
t.Fail()
}
}
}

func BenchmarkMT64(b *testing.B) {
mt := CryptoSeeded(NewMT64(), mt64N).(*MT64)
f := func(p []byte) func(b *testing.B) {
Expand Down
19 changes: 19 additions & 0 deletions source.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,22 @@ type Saver interface {
// number of bytes read and any error that occurred.
Restore(from io.Reader) (n int, err error)
}

// A Copier is a PRNG that can produce a copy of itself that will generate the
// same sequence of values. This interface is only necessary when using PRNGs
// through interfaces; PRNG values can be copied directly by dereferencing.
type Copier interface {
Seeder
// Copy creates a copy of the PRNG.
Copy() Copier
}

// A Jumper is a PRNG that can efficiently "jump" to a new state, such that the
// output sequences of the pre- and post-jump states will not overlap for a
// long time. This facilitates parallel scaling by ensuring that many separate
// random processes each have unique contributions to a single problem.
type Jumper interface {
Seeder
// Jump advances the state of the PRNG by 2**(64+n) iterations.
Jump(n uint)
}
12 changes: 12 additions & 0 deletions xoroshiro.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ func (xoro *Xoroshiro) Int63() int64 {
return int64(xoro.Uint64() >> 1)
}

// Copy creates a copy of the generator.
func (xoro *Xoroshiro) Copy() Copier {
x := *xoro
return &x
}

// Rexoroshiro is deprecated. Use Xoshiro instead.
//
// Rexoroshiro is the same as Xoroshiro but yields values that are bytewise
Expand Down Expand Up @@ -202,3 +208,9 @@ func (rexo *Rexoroshiro) Int63() int64 {
// instead of shifting.
return int64(rexo.Uint64() & 0x7fffffffffffffff)
}

// Copy creates a copy of the generator.
func (rexo *Rexoroshiro) Copy() Copier {
r := *rexo
return &r
}
13 changes: 13 additions & 0 deletions xoroshiro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ func TestXoroSave(t *testing.T) {
}
}

func TestXoroCopy(t *testing.T) {
xoro := CryptoSeeded(NewXoroshiro(), 16).(*Xoroshiro)
x, y := make([]byte, 8000), make([]byte, 8000)
for i := 0; i < 1024; i++ {
cp := xoro.Copy()
xoro.Read(x)
cp.Read(y)
if !bytes.Equal(x, y) {
t.Fail()
}
}
}

func BenchmarkXoroshiro(b *testing.B) {
xoro := CryptoSeeded(NewXoroshiro(), 16).(*Xoroshiro)
f := func(p []byte) func(b *testing.B) {
Expand Down
6 changes: 6 additions & 0 deletions xoshiro.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,9 @@ func (xoshi *Xoshiro) Restore(from io.Reader) (n int, err error) {
func (xoshi *Xoshiro) Seed(x int64) {
SeedInt64(xoshi, x)
}

// Copy creates a copy of the generator.
func (xoshi *Xoshiro) Copy() Copier {
x := *xoshi
return &x
}
13 changes: 13 additions & 0 deletions xoshiro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ func TestXoshiSave(t *testing.T) {
}
}

func TestXoshiCopy(t *testing.T) {
xoshi := CryptoSeeded(NewXoshiro(), 32).(*Xoshiro)
x, y := make([]byte, 8000), make([]byte, 8000)
for i := 0; i < 1024; i++ {
cp := xoshi.Copy()
xoshi.Read(x)
cp.Read(y)
if !bytes.Equal(x, y) {
t.Fail()
}
}
}

func BenchmarkXoshiro(b *testing.B) {
xoshi := CryptoSeeded(NewXoshiro(), 32).(*Xoshiro)
f := func(p []byte) func(b *testing.B) {
Expand Down

0 comments on commit d6ce698

Please sign in to comment.