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 }