Skip to content

Update for math/rand/v2 package #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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