decred.org/dcrdex@v1.0.5/server/matcher/mt19937/mt19937_test.go (about)

     1  // This code is available on the terms of the project LICENSE.md file,
     2  // also available online at https://blueoakcouncil.org/license/1.0.0.
     3  
     4  package mt19937
     5  
     6  import (
     7  	"bufio"
     8  	"encoding/binary"
     9  	"math/rand"
    10  	"os"
    11  	"strconv"
    12  	"testing"
    13  )
    14  
    15  // Ensure mt19937.Source satisfies rand.Source and rand.Source64.
    16  var _ rand.Source = (*Source)(nil)
    17  var _ rand.Source64 = (*Source)(nil)
    18  
    19  func BenchmarkSource_Uint64(b *testing.B) {
    20  	s := NewSource()
    21  	for i := 0; i < b.N; i++ {
    22  		s.Uint64()
    23  	}
    24  }
    25  
    26  func BenchmarkSource_Int63(b *testing.B) {
    27  	s := NewSource()
    28  	for i := 0; i < b.N; i++ {
    29  		s.Int63()
    30  	}
    31  }
    32  
    33  func BenchmarkSource_Seed(b *testing.B) {
    34  	s := NewSource()
    35  	for i := 0; i < b.N; i++ {
    36  		s.Seed(12341324)
    37  	}
    38  }
    39  
    40  func TestSource_Uint64_default(t *testing.T) {
    41  	file, err := os.Open("refuint64.dat")
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	defer file.Close()
    46  
    47  	scanner := bufio.NewScanner(file)
    48  	scanner.Split(bufio.ScanWords)
    49  
    50  	var refUint64 []uint64
    51  	for scanner.Scan() {
    52  		val, err := strconv.ParseUint(scanner.Text(), 10, 64)
    53  		if err != nil {
    54  			t.Fatal(err)
    55  		}
    56  		refUint64 = append(refUint64, val)
    57  	}
    58  
    59  	// Default seed, automatically seeded on first generate.
    60  	s := NewSource()
    61  	for i, want := range refUint64 {
    62  		got := s.Uint64()
    63  		if got != want {
    64  			t.Errorf("incorrect value #%d: got %d want %d", i, got, want)
    65  		}
    66  	}
    67  
    68  	s = NewSource()
    69  	got63 := s.Int63()
    70  	want63 := int64(7257142393139058515)
    71  	if got63 != want63 {
    72  		t.Errorf("incorrect value: got %d want %d", got63, want63)
    73  	}
    74  
    75  	// Int63 and Uint64 both affect the state and advance the sequence.
    76  	got64 := s.Uint64()
    77  	want64 := uint64(4620546740167642908)
    78  	if got64 != want64 {
    79  		t.Errorf("incorrect value: got %d want %d", got64, want64)
    80  	}
    81  
    82  	// Check the 10000th value as per
    83  	// https://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine
    84  	for i := 3; i < 10000; i++ {
    85  		_ = s.Uint64()
    86  	}
    87  	tenThou := s.Uint64()
    88  	wantTenThou := uint64(9981545732273789042)
    89  	if tenThou != wantTenThou {
    90  		t.Errorf("10000th value should be %d, got %d", wantTenThou, tenThou)
    91  	}
    92  }
    93  
    94  func TestSource_Uint64_SliceSeed(t *testing.T) {
    95  	// The authors gold standard for the array initialization tests uses the
    96  	// following seedValues to generate the sequence at
    97  	// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt19937-64.out.txt
    98  	seedVals := []uint64{0x12345, 0x23456, 0x34567, 0x45678}
    99  	file, err := os.Open("refuint64_sliceseed.dat")
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	defer file.Close()
   104  
   105  	scanner := bufio.NewScanner(file)
   106  	scanner.Split(bufio.ScanWords)
   107  
   108  	var refUint64 []uint64
   109  	for scanner.Scan() {
   110  		val, err := strconv.ParseUint(scanner.Text(), 10, 64)
   111  		if err != nil {
   112  			t.Fatal(err)
   113  		}
   114  		refUint64 = append(refUint64, val)
   115  	}
   116  
   117  	s := NewSource()
   118  	s.SeedVals(seedVals)
   119  	for i, want := range refUint64 {
   120  		got := s.Uint64()
   121  		if got != want {
   122  			t.Errorf("incorrect value #%d: got %d want %d", i, got, want)
   123  		}
   124  	}
   125  }
   126  
   127  func TestSource_Uint64_BytesSeed(t *testing.T) {
   128  	file, err := os.Open("refuint64_sliceseed.dat")
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	defer file.Close()
   133  
   134  	scanner := bufio.NewScanner(file)
   135  	scanner.Split(bufio.ScanWords)
   136  
   137  	var refUint64 []uint64
   138  	for scanner.Scan() {
   139  		val, err := strconv.ParseUint(scanner.Text(), 10, 64)
   140  		if err != nil {
   141  			t.Fatal(err)
   142  		}
   143  		refUint64 = append(refUint64, val)
   144  	}
   145  
   146  	vals := []uint64{0x12345, 0x23456, 0x34567, 0x45678}
   147  	numBytes := len(vals) * 8
   148  	bytes := make([]byte, numBytes)
   149  	for i, v := range vals {
   150  		ib := i * 8
   151  		binary.BigEndian.PutUint64(bytes[ib:ib+8], v)
   152  	}
   153  
   154  	s := NewSource()
   155  	s.SeedBytes(bytes)
   156  	for i, want := range refUint64 {
   157  		got := s.Uint64()
   158  		if got != want {
   159  			t.Errorf("incorrect value #%d: got %d want %d", i, got, want)
   160  		}
   161  	}
   162  
   163  	s = NewSource()
   164  	s.SeedBytes(bytes[:numBytes-2])
   165  	got, want := s.Uint64(), uint64(7862454683178703257)
   166  	if got != want {
   167  		t.Errorf("incorrect value: got %d want %d", got, want)
   168  	}
   169  }