Skip to content

Commit

Permalink
Merge pull request #4 from goark/v2-develop
Browse files Browse the repository at this point in the history
Update for math/rand/v2 package
  • Loading branch information
spiegel-im-spiegel committed Mar 9, 2024
2 parents 2a5b852 + 4925a60 commit a1765aa
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 241 deletions.
78 changes: 45 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# [goark/mt][mt] -- [Mersenne Twister]; Pseudo Random Number Generator, Implemented by [Golang]
# [goark/mt][github.com/goark/mt/v2] -- [Mersenne Twister]; Pseudo Random Number Generator, Implemented by [Golang][Go]

[![check vulns](https://github.com/goark/mt/workflows/vulns/badge.svg)](https://github.com/goark/mt/actions)
[![lint status](https://github.com/goark/mt/workflows/lint/badge.svg)](https://github.com/goark/mt/actions)
Expand All @@ -7,36 +7,47 @@

This package is "[Mersenne Twister]" algorithm, implemented by pure [Go].

- Compatible with [math/rand] standard package.
- Concurrency-safe (if it uses [mt].PRNG type)
- required Go 1.22 or later
- Compatible with [math/rand/v2] standard package.
- Concurrency-safe (if it uses [mt][github.com/goark/mt/v2].PRNG type)

**Migrated repository to [github.com/goark/mt][mt]**
**Migrated repository to [github.com/goark/mt][github.com/goark/mt/v2]**

## Usage

### Usage with [math/rand] Standard Package (not concurrency-safe)
### Import

```go
import "github.com/goark/mt/v2"
```

### Usage with [math/rand/v2] Standard Package (not concurrency-safe)

```go
package main

import (
"fmt"
"math/rand"
"math/rand/v2"

"github.com/goark/mt/mt19937"
"github.com/goark/mt/v2/mt19937"
)

fmt.Println(rand.New(mt19937.New(19650218)).Uint64())
//Output:
//13735441942630277712
func main() {
fmt.Println(rand.New(mt19937.New(19650218)).Uint64())
//Output:
//13735441942630277712
}
```

### Usage of [mt].PRNG type (concurrency-safe version)
### Usage of [mt][github.com/goark/mt/v2].PRNG type (concurrency-safe version)

```go
import (
"fmt"

"github.com/goark/mt"
"github.com/goark/mt/mt19937"
"github.com/goark/mt/v2"
"github.com/goark/mt/v2/mt19937"
)

fmt.Println(mt.New(mt19937.New(19650218)).Uint64())
Expand All @@ -47,30 +58,31 @@ fmt.Println(mt.New(mt19937.New(19650218)).Uint64())
#### Use [io].Reader interface

```go
package main

import (
"encoding/binary"
"fmt"
"math/rand/v2"
"sync"

"github.com/goark/mt"
"github.com/goark/mt/mt19937"
"github.com/goark/mt/v2"
"github.com/goark/mt/v2/mt19937"
)

func main() {
prng := mt.New(mt19937.New(19650218))
wg := sync.WaitGroup{}
prng := mt.New(mt19937.New(rand.Int64()))
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
r := prng.NewReader()
buf := [8]byte{}
for i := 0; i < 10000; i++ {
buf := [8]byte{}
_, err := r.Read(buf[:])
ct, err := r.Read(buf[:])
if err != nil {
return
}
fmt.Println(binary.LittleEndian.Uint64(buf[:ct]))
}
}()
}
Expand All @@ -84,15 +96,16 @@ func main() {
$ go test -bench Random -benchmem ./benchmark
goos: linux
goarch: amd64
pkg: github.com/goark/mt/benchmark
BenchmarkRandomALFG-4 1000000000 0.0466 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917-4 1000000000 0.0649 ns/op 0 B/op 0 allocs/op
BenchmarkRandomALFGRand-4 1000000000 0.0720 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917Rand-4 1000000000 0.0862 ns/op 0 B/op 0 allocs/op
BenchmarkRandomALFGLocked-4 1000000000 0.172 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917Locked-4 1000000000 0.192 ns/op 0 B/op 0 allocs/op
pkg: github.com/goark/mt/v2/benchmark
cpu: AMD Ryzen 5 PRO 4650G with Radeon Graphics
BenchmarkRandomPCG-12 785103775 2.031 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917-12 338082381 3.551 ns/op 0 B/op 0 allocs/op
BenchmarkRandomPCGRand-12 359948874 3.288 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917Rand-12 325159622 3.687 ns/op 0 B/op 0 allocs/op
BenchmarkRandomChaCha8Locked-12 186311572 6.443 ns/op 0 B/op 0 allocs/op
BenchmarkRandomMT19917Locked-12 128465040 9.346 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/goark/mt/benchmark 6.895s
ok github.com/goark/mt/v2/benchmark 10.408s
```

## License
Expand All @@ -102,9 +115,8 @@ This package is licensed under MIT license.
- [Commercial Use of Mersenne Twister](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/elicense.html)
- [Mersenne Twisterの商業利用について](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/license.html)

[mt]: https://github.com/goark/mt "goark/mt: Mersenne Twister; Pseudo Random Number Generator, Implemented by Golang"
[Go]: https://golang.org/ "The Go Programming Language"
[Golang]: https://golang.org/ "The Go Programming Language"
[math/rand]: https://golang.org/pkg/math/rand/ "rand - The Go Programming Language"
[io]: https://golang.org/pkg/io/ "io - The Go Programming Language"
[github.com/goark/mt/v2]: https://github.com/goark/mt "goark/mt: Mersenne Twister; Pseudo Random Number Generator, Implemented by Golang"
[Go]: https://go.dev/ "The Go Programming Language"
[math/rand/v2]: https://pkg.go.dev/math/rand/v2 "rand package - math/rand/v2 - Go Packages"
[io]: https://pkg.go.dev/io "io package - io - Go Packages"
[Mersenne Twister]: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html "Mersenne Twister: A random number generator (since 1997/10)"
2 changes: 1 addition & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ tasks:
- '**/*.go'

prepare:
- go mod tidy -v -go=1.21
- go mod tidy -v -go=1.22

clean:
desc: Initialize module and build cache, and remake go.sum file.
Expand Down
51 changes: 25 additions & 26 deletions benchmark/benchmark_test.go
Original file line number Diff line number Diff line change
@@ -1,66 +1,65 @@
package benchmark

import (
"math/rand"
"math/rand/v2"
"testing"
"time"

"github.com/goark/mt"
"github.com/goark/mt/mt19937"
"github.com/goark/mt/v2"
"github.com/goark/mt/v2/mt19937"
)

const count = 10000000
var seed1, seed2, seed3 = rand.Uint64(), rand.Uint64(), rand.Int64()

func BenchmarkRandomALFG(b *testing.B) {
rnd := rand.NewSource(time.Now().UnixNano()).(rand.Source64)
func BenchmarkRandomPCG(b *testing.B) {
rnd := rand.NewPCG(seed1, seed2)
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
for i := 0; i < b.N; i++ {
_ = rnd.Uint64()
}
}

func BenchmarkRandomMT19917(b *testing.B) {
rnd := mt19937.New(time.Now().UnixNano())
rnd := mt19937.New(seed3)
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
for i := 0; i < b.N; i++ {
_ = rnd.Uint64()
}
}

func BenchmarkRandomALFGRand(b *testing.B) {
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
func BenchmarkRandomPCGRand(b *testing.B) {
rnd := rand.New(rand.NewPCG(seed1, seed2))
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
for i := 0; i < b.N; i++ {
_ = rnd.Uint64()
}
}

func BenchmarkRandomMT19917Rand(b *testing.B) {
rnd := rand.New(mt19937.New(time.Now().UnixNano()))
rnd := rand.New(mt19937.New(seed3))
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
for i := 0; i < b.N; i++ {
_ = rnd.Uint64()
}
}

func BenchmarkRandomALFGLocked(b *testing.B) {
func BenchmarkRandomChaCha8Locked(b *testing.B) {
b.ResetTimer()
for i := 0; i < count; i++ {
rand.Uint64()
for i := 0; i < b.N; i++ {
_ = rand.Uint64()
}
}

func BenchmarkRandomMT19917Locked(b *testing.B) {
rnd := mt.New(mt19937.New(time.Now().UnixNano()))
rnd := mt.New(mt19937.New(seed3))
b.ResetTimer()
for i := 0; i < count; i++ {
rnd.Uint64()
for i := 0; i < b.N; i++ {
_ = rnd.Uint64()
}
}

/* MIT License
*
* Copyright 2019 Spiegel
* Copyright 2019-2024 Spiegel
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/goark/mt
module github.com/goark/mt/v2

go 1.21
go 1.22

toolchain go1.22.1
6 changes: 3 additions & 3 deletions mt19937/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package mt19937_test

import (
"fmt"
"math/rand"
"math/rand/v2"

"github.com/goark/mt/mt19937"
"github.com/goark/mt/v2/mt19937"
)

func ExampleNew() {
Expand All @@ -15,7 +15,7 @@ func ExampleNew() {

/* MIT License
*
* Copyright 2019,2020 Spiegel
* Copyright 2019-2024 Spiegel
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down
26 changes: 13 additions & 13 deletions mt19937/mt19937.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
package mt19937

import (
"github.com/goark/mt"
"github.com/goark/mt/v2"
)

const (
nn = 312
mm = nn / 2
)

//Source is a source of random numbers.
// Source is a source of random numbers.
type Source struct {
mt [nn]uint64 //The array for the state vector
mti int //mti==nn+1 means mt[nn] is not initialized
}

var _ mt.Source = (*Source)(nil) //Source is compatible with mt.Source interface

//New returns a new pseudo-random source seeded with the given value.
// New returns a new pseudo-random source seeded with the given value.
func New(seed int64) *Source {
rng := &Source{mt: [nn]uint64{}, mti: nn + 1}
rng.Seed(seed)
return rng
}

//NewWithArray returns a new pseudo-random source seeded with the given values.
// NewWithArray returns a new pseudo-random source seeded with the given values.
func NewWithArray(seeds []uint64) *Source {
rng := &Source{mt: [nn]uint64{}, mti: nn + 1}
rng.SeedArray(seeds)
return rng
}

//Seed initializes Source with a seed
// Seed initializes Source with a seed
func (s *Source) Seed(seed int64) {
if s == nil {
return
Expand All @@ -42,7 +42,7 @@ func (s *Source) Seed(seed int64) {
}
}

//SeedArray initializes Source with seeds array
// SeedArray initializes Source with seeds array
func (s *Source) SeedArray(seeds []uint64) {
if s == nil {
return
Expand Down Expand Up @@ -89,7 +89,7 @@ var (
matrixA = [2]uint64{0, 0xB5026F5AA96619E9}
)

//Uint64 generates a random number on [0, 2^64-1]-interval
// Uint64 generates a random number on [0, 2^64-1]-interval
func (s *Source) Uint64() uint64 {
if s == nil {
return 0
Expand Down Expand Up @@ -120,12 +120,12 @@ func (s *Source) Uint64() uint64 {
return x
}

//Int63 generates a random number on [0, 2^63-1]-interval
func (s *Source) Int63() int64 {
return (int64)(s.Uint64() >> 1)
}
// // Int63 generates a random number on [0, 2^63-1]-interval
// func (s *Source) Int63() int64 {
// return (int64)(s.Uint64() >> 1)
// }

//Real generates a random number
// Real generates a random number
// on [0,1)-real-interval if mode==1,
// on (0,1)-real-interval if mode==2,
// on [0,1]-real-interval others
Expand All @@ -145,7 +145,7 @@ func (s *Source) Real(mode int) float64 {

/* MIT License
*
* Copyright 2019 Spiegel, fork from 64bit Mersenne Twister code "mt19937-64.c".
* Copyright 2019-2024 Spiegel, fork from 64bit Mersenne Twister code "mt19937-64.c".
* (http://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/mt64.html)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
14 changes: 7 additions & 7 deletions mt19937/mt19937_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,29 +444,29 @@ func TestMT(t *testing.T) {

func TestEmpty(t *testing.T) {
rnd := &Source{mt: [nn]uint64{}, mti: nn + 1}
r := rnd.Int63()
res := New(5489).Int63()
r := rnd.Uint64()
res := New(5489).Uint64()
if r != res {
t.Errorf("<empty>.Int63() = \"%v\", want \"%v\".", r, res)
}
rnd.SeedArray(nil)
r2 := rnd.Int63()
res2 := New(19650218).Int63()
r2 := rnd.Uint64()
res2 := New(19650218).Uint64()
if r2 != res2 {
t.Errorf("<empty>.Int63() = \"%v\", want \"%v\".", r2, res2)
}
}

func TestNil(t *testing.T) {
r := (*Source)(nil).Int63()
r := (*Source)(nil).Uint64()
if r != 0 {
t.Errorf("<nil>.Int63() = \"%v\", want \"%v\".", r, 0)
t.Errorf("<nil>.Uint64() = \"%v\", want \"%v\".", r, 0)
}
}

/* MIT License
*
* Copyright 2019,2020 Spiegel
* Copyright 2019-2024 Spiegel
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading

0 comments on commit a1765aa

Please sign in to comment.