github.com/xaionaro-go/rand@v0.0.0-20191005105903-aba1befc54a5/mathrand/read_autogenerated.go (about) 1 package mathrand 2 3 import ( 4 "unsafe" 5 ) 6 7 // This file was automatically generated by github.com/xaionaro-go/rand/internal/autogen 8 9 // ReadUint64AddRotateMultiply is an analog of math/rand.Read. This random 10 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 11 // 12 // Applied PRNG method: 13 // Uint64AddRotateMultiply is a fast analog of `math/rand.Uint64`. 14 // 15 // The reliability on statistical tests of this method is unknown. This is 16 // improved LCG method, so see also Uint64MultiplyAdd. 17 func (prng *PRNG) ReadUint64AddRotateMultiply(b []byte) (l int, err error) { 18 l = len(b) 19 s := (uintptr)((unsafe.Pointer)(&b[0])) 20 p := s 21 e := s + uintptr(l) 22 { 23 state64Temp0 := prng.state64[0] 24 for f := e - 8; p <= f; p += 8 { 25 state64Temp0 += primeNumber64bit1 26 state64Temp0 = rotateLeft64(state64Temp0, 32) 27 state64Temp0 *= primeNumber64bit0 28 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 29 } 30 prng.state64[0] = state64Temp0 31 } 32 33 if e-p == 0 { 34 return 35 } 36 rest := prng.Uint64AddRotateMultiply() 37 if e-p >= 4 { 38 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 39 rest >>= 32 40 p += 4 41 } 42 if e-p >= 2 { 43 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 44 rest >>= 16 45 p += 2 46 } 47 if e-p >= 1 { 48 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 49 } 50 return 51 } 52 53 // XORReadUint64AddRotateMultiply XORs argument "b" with a pseudo-random value. 54 // The result is the same (but faster) as: 55 // 56 // x := make([]byte, len(b)) 57 // mathrand.ReadUint64AddRotateMultiply(x) 58 // for i := range b { 59 // b[i] ^= x[i] 60 // } 61 func (prng *PRNG) XORReadUint64AddRotateMultiply(b []byte) (l int, err error) { 62 l = len(b) 63 s := (uintptr)((unsafe.Pointer)(&b[0])) 64 p := s 65 e := s + uintptr(l) 66 { 67 state64Temp0 := prng.state64[0] 68 for f := e - 8; p <= f; p += 8 { 69 state64Temp0 += primeNumber64bit1 70 state64Temp0 = rotateLeft64(state64Temp0, 32) 71 state64Temp0 *= primeNumber64bit0 72 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 73 } 74 prng.state64[0] = state64Temp0 75 } 76 77 if e-p == 0 { 78 return 79 } 80 rest := prng.Uint64AddRotateMultiply() 81 if e-p >= 4 { 82 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 83 rest >>= 32 84 p += 4 85 } 86 if e-p >= 2 { 87 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 88 rest >>= 16 89 p += 2 90 } 91 if e-p >= 1 { 92 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 93 } 94 return 95 } 96 97 // ReadUint64AddRotateMultiplyWithReseed is an analog of math/rand.Read. This random 98 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 99 // 100 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 101 // a pointer `& 0xff < 8`. Sometimes it allows to improve randomness of random numbers with a 102 // small performance impact. 103 // This method makes sense only if len(b) is large enough (>= 256 bytes). 104 // Otherwise it could affect strongly performance or it will not improve the randomness. 105 // 106 // Applied PRNG method: 107 // Uint64AddRotateMultiply is a fast analog of `math/rand.Uint64`. 108 // 109 // The reliability on statistical tests of this method is unknown. This is 110 // improved LCG method, so see also Uint64MultiplyAdd. 111 func (prng *PRNG) ReadUint64AddRotateMultiplyWithReseed(b []byte) (l int, err error) { 112 l = len(b) 113 s := (uintptr)((unsafe.Pointer)(&b[0])) 114 p := s 115 e := s + uintptr(l) 116 { 117 state64Temp0 := prng.state64[0] 118 for f := e - 8; p <= f; p += 8 { 119 state64Temp0 += primeNumber64bit1 120 state64Temp0 = rotateLeft64(state64Temp0, 32) 121 state64Temp0 *= primeNumber64bit0 122 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 123 if p&0xff < 8 { 124 continue 125 } 126 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 127 } 128 prng.state64[0] = state64Temp0 129 } 130 131 if e-p == 0 { 132 return 133 } 134 rest := prng.Uint64AddRotateMultiply() 135 if e-p >= 4 { 136 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 137 rest >>= 32 138 p += 4 139 } 140 if e-p >= 2 { 141 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 142 rest >>= 16 143 p += 2 144 } 145 if e-p >= 1 { 146 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 147 } 148 return 149 } 150 151 // XORReadUint64AddRotateMultiplyWithReseed XORs argument "b" with a pseudo-random value. 152 // The result is the same (but faster) as: 153 // 154 // x := make([]byte, len(b)) 155 // mathrand.ReadUint64AddRotateMultiplyWithReseed(x) 156 // for i := range b { 157 // b[i] ^= x[i] 158 // } 159 func (prng *PRNG) XORReadUint64AddRotateMultiplyWithReseed(b []byte) (l int, err error) { 160 l = len(b) 161 s := (uintptr)((unsafe.Pointer)(&b[0])) 162 p := s 163 e := s + uintptr(l) 164 { 165 state64Temp0 := prng.state64[0] 166 for f := e - 8; p <= f; p += 8 { 167 state64Temp0 += primeNumber64bit1 168 state64Temp0 = rotateLeft64(state64Temp0, 32) 169 state64Temp0 *= primeNumber64bit0 170 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 171 if p&0xff < 8 { 172 continue 173 } 174 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 175 } 176 prng.state64[0] = state64Temp0 177 } 178 179 if e-p == 0 { 180 return 181 } 182 rest := prng.Uint64AddRotateMultiply() 183 if e-p >= 4 { 184 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 185 rest >>= 32 186 p += 4 187 } 188 if e-p >= 2 { 189 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 190 rest >>= 16 191 p += 2 192 } 193 if e-p >= 1 { 194 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 195 } 196 return 197 } 198 199 // ReadUint64AddNRotateMultiply is an analog of math/rand.Read. This random 200 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 201 // 202 // Applied PRNG method: 203 // Uint64AddNRotateMultiply is a fast analog of `math/rand.Uint64`. 204 // 205 // The reliability on statistical tests of this method is unknown. This is 206 // improved LCG method, so see also Uint64MultiplyAdd. 207 func (prng *PRNG) ReadUint64AddNRotateMultiply(b []byte) (l int, err error) { 208 l = len(b) 209 s := (uintptr)((unsafe.Pointer)(&b[0])) 210 p := s 211 e := s + uintptr(l) 212 { 213 state64Temp0 := prng.state64[0] 214 for f := e - 8; p <= f; p += 8 { 215 state64Temp0 += primeNumber64bit1 216 r := 28 + int(state64Temp0&0x7) 217 state64Temp0 = rotateLeft64(state64Temp0, r) 218 state64Temp0 *= primeNumber64bit0 219 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 220 } 221 prng.state64[0] = state64Temp0 222 } 223 224 if e-p == 0 { 225 return 226 } 227 rest := prng.Uint64AddNRotateMultiply() 228 if e-p >= 4 { 229 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 230 rest >>= 32 231 p += 4 232 } 233 if e-p >= 2 { 234 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 235 rest >>= 16 236 p += 2 237 } 238 if e-p >= 1 { 239 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 240 } 241 return 242 } 243 244 // XORReadUint64AddNRotateMultiply XORs argument "b" with a pseudo-random value. 245 // The result is the same (but faster) as: 246 // 247 // x := make([]byte, len(b)) 248 // mathrand.ReadUint64AddNRotateMultiply(x) 249 // for i := range b { 250 // b[i] ^= x[i] 251 // } 252 func (prng *PRNG) XORReadUint64AddNRotateMultiply(b []byte) (l int, err error) { 253 l = len(b) 254 s := (uintptr)((unsafe.Pointer)(&b[0])) 255 p := s 256 e := s + uintptr(l) 257 { 258 state64Temp0 := prng.state64[0] 259 for f := e - 8; p <= f; p += 8 { 260 state64Temp0 += primeNumber64bit1 261 r := 28 + int(state64Temp0&0x7) 262 state64Temp0 = rotateLeft64(state64Temp0, r) 263 state64Temp0 *= primeNumber64bit0 264 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 265 } 266 prng.state64[0] = state64Temp0 267 } 268 269 if e-p == 0 { 270 return 271 } 272 rest := prng.Uint64AddNRotateMultiply() 273 if e-p >= 4 { 274 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 275 rest >>= 32 276 p += 4 277 } 278 if e-p >= 2 { 279 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 280 rest >>= 16 281 p += 2 282 } 283 if e-p >= 1 { 284 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 285 } 286 return 287 } 288 289 // ReadUint64AddNRotateMultiplyWithReseed is an analog of math/rand.Read. This random 290 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 291 // 292 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 293 // a pointer `& 0xff < 8`. Sometimes it allows to improve randomness of random numbers with a 294 // small performance impact. 295 // This method makes sense only if len(b) is large enough (>= 256 bytes). 296 // Otherwise it could affect strongly performance or it will not improve the randomness. 297 // 298 // Applied PRNG method: 299 // Uint64AddNRotateMultiply is a fast analog of `math/rand.Uint64`. 300 // 301 // The reliability on statistical tests of this method is unknown. This is 302 // improved LCG method, so see also Uint64MultiplyAdd. 303 func (prng *PRNG) ReadUint64AddNRotateMultiplyWithReseed(b []byte) (l int, err error) { 304 l = len(b) 305 s := (uintptr)((unsafe.Pointer)(&b[0])) 306 p := s 307 e := s + uintptr(l) 308 { 309 state64Temp0 := prng.state64[0] 310 for f := e - 8; p <= f; p += 8 { 311 state64Temp0 += primeNumber64bit1 312 r := 28 + int(state64Temp0&0x7) 313 state64Temp0 = rotateLeft64(state64Temp0, r) 314 state64Temp0 *= primeNumber64bit0 315 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 316 if p&0xff < 8 { 317 continue 318 } 319 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 320 } 321 prng.state64[0] = state64Temp0 322 } 323 324 if e-p == 0 { 325 return 326 } 327 rest := prng.Uint64AddNRotateMultiply() 328 if e-p >= 4 { 329 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 330 rest >>= 32 331 p += 4 332 } 333 if e-p >= 2 { 334 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 335 rest >>= 16 336 p += 2 337 } 338 if e-p >= 1 { 339 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 340 } 341 return 342 } 343 344 // XORReadUint64AddNRotateMultiplyWithReseed XORs argument "b" with a pseudo-random value. 345 // The result is the same (but faster) as: 346 // 347 // x := make([]byte, len(b)) 348 // mathrand.ReadUint64AddNRotateMultiplyWithReseed(x) 349 // for i := range b { 350 // b[i] ^= x[i] 351 // } 352 func (prng *PRNG) XORReadUint64AddNRotateMultiplyWithReseed(b []byte) (l int, err error) { 353 l = len(b) 354 s := (uintptr)((unsafe.Pointer)(&b[0])) 355 p := s 356 e := s + uintptr(l) 357 { 358 state64Temp0 := prng.state64[0] 359 for f := e - 8; p <= f; p += 8 { 360 state64Temp0 += primeNumber64bit1 361 r := 28 + int(state64Temp0&0x7) 362 state64Temp0 = rotateLeft64(state64Temp0, r) 363 state64Temp0 *= primeNumber64bit0 364 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 365 if p&0xff < 8 { 366 continue 367 } 368 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 369 } 370 prng.state64[0] = state64Temp0 371 } 372 373 if e-p == 0 { 374 return 375 } 376 rest := prng.Uint64AddNRotateMultiply() 377 if e-p >= 4 { 378 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 379 rest >>= 32 380 p += 4 381 } 382 if e-p >= 2 { 383 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 384 rest >>= 16 385 p += 2 386 } 387 if e-p >= 1 { 388 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 389 } 390 return 391 } 392 393 // ReadUint64MultiplyAdd is an analog of math/rand.Read. This random 394 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 395 // 396 // Applied PRNG method: 397 // Uint64MultiplyAdd is a fast (but week) analog of `math/rand.Uint64`. 398 // 399 // See also: https://en.wikipedia.org/wiki/Linear_congruential_generator 400 func (prng *PRNG) ReadUint64MultiplyAdd(b []byte) (l int, err error) { 401 l = len(b) 402 s := (uintptr)((unsafe.Pointer)(&b[0])) 403 p := s 404 e := s + uintptr(l) 405 { 406 state64Temp0 := prng.state64[0] 407 for f := e - 8; p <= f; p += 8 { 408 state64Temp0 *= primeNumber64bit0 409 state64Temp0 += primeNumber64bit1 410 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 411 } 412 prng.state64[0] = state64Temp0 413 } 414 415 if e-p == 0 { 416 return 417 } 418 rest := prng.Uint64MultiplyAdd() 419 if e-p >= 4 { 420 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 421 rest >>= 32 422 p += 4 423 } 424 if e-p >= 2 { 425 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 426 rest >>= 16 427 p += 2 428 } 429 if e-p >= 1 { 430 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 431 } 432 return 433 } 434 435 // XORReadUint64MultiplyAdd XORs argument "b" with a pseudo-random value. 436 // The result is the same (but faster) as: 437 // 438 // x := make([]byte, len(b)) 439 // mathrand.ReadUint64MultiplyAdd(x) 440 // for i := range b { 441 // b[i] ^= x[i] 442 // } 443 func (prng *PRNG) XORReadUint64MultiplyAdd(b []byte) (l int, err error) { 444 l = len(b) 445 s := (uintptr)((unsafe.Pointer)(&b[0])) 446 p := s 447 e := s + uintptr(l) 448 { 449 state64Temp0 := prng.state64[0] 450 for f := e - 8; p <= f; p += 8 { 451 state64Temp0 *= primeNumber64bit0 452 state64Temp0 += primeNumber64bit1 453 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 454 } 455 prng.state64[0] = state64Temp0 456 } 457 458 if e-p == 0 { 459 return 460 } 461 rest := prng.Uint64MultiplyAdd() 462 if e-p >= 4 { 463 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 464 rest >>= 32 465 p += 4 466 } 467 if e-p >= 2 { 468 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 469 rest >>= 16 470 p += 2 471 } 472 if e-p >= 1 { 473 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 474 } 475 return 476 } 477 478 // ReadUint64MultiplyAddWithReseed is an analog of math/rand.Read. This random 479 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 480 // 481 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 482 // a pointer `& 0xff < 8`. Sometimes it allows to improve randomness of random numbers with a 483 // small performance impact. 484 // This method makes sense only if len(b) is large enough (>= 256 bytes). 485 // Otherwise it could affect strongly performance or it will not improve the randomness. 486 // 487 // Applied PRNG method: 488 // Uint64MultiplyAdd is a fast (but week) analog of `math/rand.Uint64`. 489 // 490 // See also: https://en.wikipedia.org/wiki/Linear_congruential_generator 491 func (prng *PRNG) ReadUint64MultiplyAddWithReseed(b []byte) (l int, err error) { 492 l = len(b) 493 s := (uintptr)((unsafe.Pointer)(&b[0])) 494 p := s 495 e := s + uintptr(l) 496 { 497 state64Temp0 := prng.state64[0] 498 for f := e - 8; p <= f; p += 8 { 499 state64Temp0 *= primeNumber64bit0 500 state64Temp0 += primeNumber64bit1 501 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 502 if p&0xff < 8 { 503 continue 504 } 505 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 506 } 507 prng.state64[0] = state64Temp0 508 } 509 510 if e-p == 0 { 511 return 512 } 513 rest := prng.Uint64MultiplyAdd() 514 if e-p >= 4 { 515 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 516 rest >>= 32 517 p += 4 518 } 519 if e-p >= 2 { 520 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 521 rest >>= 16 522 p += 2 523 } 524 if e-p >= 1 { 525 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 526 } 527 return 528 } 529 530 // XORReadUint64MultiplyAddWithReseed XORs argument "b" with a pseudo-random value. 531 // The result is the same (but faster) as: 532 // 533 // x := make([]byte, len(b)) 534 // mathrand.ReadUint64MultiplyAddWithReseed(x) 535 // for i := range b { 536 // b[i] ^= x[i] 537 // } 538 func (prng *PRNG) XORReadUint64MultiplyAddWithReseed(b []byte) (l int, err error) { 539 l = len(b) 540 s := (uintptr)((unsafe.Pointer)(&b[0])) 541 p := s 542 e := s + uintptr(l) 543 { 544 state64Temp0 := prng.state64[0] 545 for f := e - 8; p <= f; p += 8 { 546 state64Temp0 *= primeNumber64bit0 547 state64Temp0 += primeNumber64bit1 548 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 549 if p&0xff < 8 { 550 continue 551 } 552 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 553 } 554 prng.state64[0] = state64Temp0 555 } 556 557 if e-p == 0 { 558 return 559 } 560 rest := prng.Uint64MultiplyAdd() 561 if e-p >= 4 { 562 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 563 rest >>= 32 564 p += 4 565 } 566 if e-p >= 2 { 567 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 568 rest >>= 16 569 p += 2 570 } 571 if e-p >= 1 { 572 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 573 } 574 return 575 } 576 577 // ReadUint64AddRotate is an analog of math/rand.Read. This random 578 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 579 // 580 // Applied PRNG method: 581 // Uint64AddRotate is a very fast (but weak) analog of `math/rand.Uint64`. 582 func (prng *PRNG) ReadUint64AddRotate(b []byte) (l int, err error) { 583 l = len(b) 584 s := (uintptr)((unsafe.Pointer)(&b[0])) 585 p := s 586 e := s + uintptr(l) 587 { 588 state64Temp0 := prng.state64[0] 589 for f := e - 8; p <= f; p += 8 { 590 state64Temp0 += primeNumber64bit1 591 state64Temp0 = rotateLeft64(state64Temp0, 32) 592 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 593 } 594 prng.state64[0] = state64Temp0 595 } 596 597 if e-p == 0 { 598 return 599 } 600 rest := prng.Uint64AddRotate() 601 if e-p >= 4 { 602 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 603 rest >>= 32 604 p += 4 605 } 606 if e-p >= 2 { 607 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 608 rest >>= 16 609 p += 2 610 } 611 if e-p >= 1 { 612 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 613 } 614 return 615 } 616 617 // XORReadUint64AddRotate XORs argument "b" with a pseudo-random value. 618 // The result is the same (but faster) as: 619 // 620 // x := make([]byte, len(b)) 621 // mathrand.ReadUint64AddRotate(x) 622 // for i := range b { 623 // b[i] ^= x[i] 624 // } 625 func (prng *PRNG) XORReadUint64AddRotate(b []byte) (l int, err error) { 626 l = len(b) 627 s := (uintptr)((unsafe.Pointer)(&b[0])) 628 p := s 629 e := s + uintptr(l) 630 { 631 state64Temp0 := prng.state64[0] 632 for f := e - 8; p <= f; p += 8 { 633 state64Temp0 += primeNumber64bit1 634 state64Temp0 = rotateLeft64(state64Temp0, 32) 635 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 636 } 637 prng.state64[0] = state64Temp0 638 } 639 640 if e-p == 0 { 641 return 642 } 643 rest := prng.Uint64AddRotate() 644 if e-p >= 4 { 645 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 646 rest >>= 32 647 p += 4 648 } 649 if e-p >= 2 { 650 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 651 rest >>= 16 652 p += 2 653 } 654 if e-p >= 1 { 655 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 656 } 657 return 658 } 659 660 // ReadUint64AddRotateWithReseed is an analog of math/rand.Read. This random 661 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 662 // 663 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 664 // a pointer `& 0xff < 8`. Sometimes it allows to improve randomness of random numbers with a 665 // small performance impact. 666 // This method makes sense only if len(b) is large enough (>= 256 bytes). 667 // Otherwise it could affect strongly performance or it will not improve the randomness. 668 // 669 // Applied PRNG method: 670 // Uint64AddRotate is a very fast (but weak) analog of `math/rand.Uint64`. 671 func (prng *PRNG) ReadUint64AddRotateWithReseed(b []byte) (l int, err error) { 672 l = len(b) 673 s := (uintptr)((unsafe.Pointer)(&b[0])) 674 p := s 675 e := s + uintptr(l) 676 { 677 state64Temp0 := prng.state64[0] 678 for f := e - 8; p <= f; p += 8 { 679 state64Temp0 += primeNumber64bit1 680 state64Temp0 = rotateLeft64(state64Temp0, 32) 681 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 682 if p&0xff < 8 { 683 continue 684 } 685 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 686 } 687 prng.state64[0] = state64Temp0 688 } 689 690 if e-p == 0 { 691 return 692 } 693 rest := prng.Uint64AddRotate() 694 if e-p >= 4 { 695 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 696 rest >>= 32 697 p += 4 698 } 699 if e-p >= 2 { 700 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 701 rest >>= 16 702 p += 2 703 } 704 if e-p >= 1 { 705 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 706 } 707 return 708 } 709 710 // XORReadUint64AddRotateWithReseed XORs argument "b" with a pseudo-random value. 711 // The result is the same (but faster) as: 712 // 713 // x := make([]byte, len(b)) 714 // mathrand.ReadUint64AddRotateWithReseed(x) 715 // for i := range b { 716 // b[i] ^= x[i] 717 // } 718 func (prng *PRNG) XORReadUint64AddRotateWithReseed(b []byte) (l int, err error) { 719 l = len(b) 720 s := (uintptr)((unsafe.Pointer)(&b[0])) 721 p := s 722 e := s + uintptr(l) 723 { 724 state64Temp0 := prng.state64[0] 725 for f := e - 8; p <= f; p += 8 { 726 state64Temp0 += primeNumber64bit1 727 state64Temp0 = rotateLeft64(state64Temp0, 32) 728 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 729 if p&0xff < 8 { 730 continue 731 } 732 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 733 } 734 prng.state64[0] = state64Temp0 735 } 736 737 if e-p == 0 { 738 return 739 } 740 rest := prng.Uint64AddRotate() 741 if e-p >= 4 { 742 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 743 rest >>= 32 744 p += 4 745 } 746 if e-p >= 2 { 747 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 748 rest >>= 16 749 p += 2 750 } 751 if e-p >= 1 { 752 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 753 } 754 return 755 } 756 757 // ReadUint64AddIfShiftXOR is an analog of math/rand.Read. This random 758 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 759 // 760 // Applied PRNG method: 761 // Uint64AddIfShiftXOR is a very fast (but weak) analog of `math/rand.Uint32`. 762 func (prng *PRNG) ReadUint64AddIfShiftXOR(b []byte) (l int, err error) { 763 l = len(b) 764 s := (uintptr)((unsafe.Pointer)(&b[0])) 765 p := s 766 e := s + uintptr(l) 767 { 768 state64Temp0 := prng.state64[0] 769 for f := e - 8; p <= f; p += 8 { 770 state64Temp0 += primeNumber64bit1 771 if state64Temp0&0x02 == 0 { 772 state64Temp0 ^= state64Temp0 >> 32 773 } 774 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 775 } 776 prng.state64[0] = state64Temp0 777 } 778 779 if e-p == 0 { 780 return 781 } 782 rest := prng.Uint64AddIfShiftXOR() 783 if e-p >= 4 { 784 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 785 rest >>= 32 786 p += 4 787 } 788 if e-p >= 2 { 789 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 790 rest >>= 16 791 p += 2 792 } 793 if e-p >= 1 { 794 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 795 } 796 return 797 } 798 799 // XORReadUint64AddIfShiftXOR XORs argument "b" with a pseudo-random value. 800 // The result is the same (but faster) as: 801 // 802 // x := make([]byte, len(b)) 803 // mathrand.ReadUint64AddIfShiftXOR(x) 804 // for i := range b { 805 // b[i] ^= x[i] 806 // } 807 func (prng *PRNG) XORReadUint64AddIfShiftXOR(b []byte) (l int, err error) { 808 l = len(b) 809 s := (uintptr)((unsafe.Pointer)(&b[0])) 810 p := s 811 e := s + uintptr(l) 812 { 813 state64Temp0 := prng.state64[0] 814 for f := e - 8; p <= f; p += 8 { 815 state64Temp0 += primeNumber64bit1 816 if state64Temp0&0x02 == 0 { 817 state64Temp0 ^= state64Temp0 >> 32 818 } 819 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 820 } 821 prng.state64[0] = state64Temp0 822 } 823 824 if e-p == 0 { 825 return 826 } 827 rest := prng.Uint64AddIfShiftXOR() 828 if e-p >= 4 { 829 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 830 rest >>= 32 831 p += 4 832 } 833 if e-p >= 2 { 834 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 835 rest >>= 16 836 p += 2 837 } 838 if e-p >= 1 { 839 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 840 } 841 return 842 } 843 844 // ReadUint64AddIfShiftXORWithReseed is an analog of math/rand.Read. This random 845 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 846 // 847 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 848 // a pointer `& 0xff < 8`. Sometimes it allows to improve randomness of random numbers with a 849 // small performance impact. 850 // This method makes sense only if len(b) is large enough (>= 256 bytes). 851 // Otherwise it could affect strongly performance or it will not improve the randomness. 852 // 853 // Applied PRNG method: 854 // Uint64AddIfShiftXOR is a very fast (but weak) analog of `math/rand.Uint32`. 855 func (prng *PRNG) ReadUint64AddIfShiftXORWithReseed(b []byte) (l int, err error) { 856 l = len(b) 857 s := (uintptr)((unsafe.Pointer)(&b[0])) 858 p := s 859 e := s + uintptr(l) 860 { 861 state64Temp0 := prng.state64[0] 862 for f := e - 8; p <= f; p += 8 { 863 state64Temp0 += primeNumber64bit1 864 if state64Temp0&0x02 == 0 { 865 state64Temp0 ^= state64Temp0 >> 32 866 } 867 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 868 if p&0xff < 8 { 869 continue 870 } 871 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 872 } 873 prng.state64[0] = state64Temp0 874 } 875 876 if e-p == 0 { 877 return 878 } 879 rest := prng.Uint64AddIfShiftXOR() 880 if e-p >= 4 { 881 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 882 rest >>= 32 883 p += 4 884 } 885 if e-p >= 2 { 886 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 887 rest >>= 16 888 p += 2 889 } 890 if e-p >= 1 { 891 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 892 } 893 return 894 } 895 896 // XORReadUint64AddIfShiftXORWithReseed XORs argument "b" with a pseudo-random value. 897 // The result is the same (but faster) as: 898 // 899 // x := make([]byte, len(b)) 900 // mathrand.ReadUint64AddIfShiftXORWithReseed(x) 901 // for i := range b { 902 // b[i] ^= x[i] 903 // } 904 func (prng *PRNG) XORReadUint64AddIfShiftXORWithReseed(b []byte) (l int, err error) { 905 l = len(b) 906 s := (uintptr)((unsafe.Pointer)(&b[0])) 907 p := s 908 e := s + uintptr(l) 909 { 910 state64Temp0 := prng.state64[0] 911 for f := e - 8; p <= f; p += 8 { 912 state64Temp0 += primeNumber64bit1 913 if state64Temp0&0x02 == 0 { 914 state64Temp0 ^= state64Temp0 >> 32 915 } 916 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 917 if p&0xff < 8 { 918 continue 919 } 920 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 921 } 922 prng.state64[0] = state64Temp0 923 } 924 925 if e-p == 0 { 926 return 927 } 928 rest := prng.Uint64AddIfShiftXOR() 929 if e-p >= 4 { 930 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 931 rest >>= 32 932 p += 4 933 } 934 if e-p >= 2 { 935 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 936 rest >>= 16 937 p += 2 938 } 939 if e-p >= 1 { 940 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 941 } 942 return 943 } 944 945 // ReadUint64Xorshift is an analog of math/rand.Read. This random 946 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 947 // 948 // Applied PRNG method: 949 // Uint64Xorshift is a very fast (but weak) analog of `math/rand.Uint64`. 950 // 951 // See also: https://en.wikipedia.org/wiki/Xorshift 952 func (prng *PRNG) ReadUint64Xorshift(b []byte) (l int, err error) { 953 l = len(b) 954 s := (uintptr)((unsafe.Pointer)(&b[0])) 955 p := s 956 e := s + uintptr(l) 957 { 958 state64Temp0 := prng.state64[0] 959 for f := e - 8; p <= f; p += 8 { 960 state64Temp0 ^= state64Temp0 << 13 961 state64Temp0 ^= state64Temp0 >> 7 962 state64Temp0 ^= state64Temp0 << 17 963 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 964 } 965 prng.state64[0] = state64Temp0 966 } 967 968 if e-p == 0 { 969 return 970 } 971 rest := prng.Uint64Xorshift() 972 if e-p >= 4 { 973 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 974 rest >>= 32 975 p += 4 976 } 977 if e-p >= 2 { 978 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 979 rest >>= 16 980 p += 2 981 } 982 if e-p >= 1 { 983 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 984 } 985 return 986 } 987 988 // XORReadUint64Xorshift XORs argument "b" with a pseudo-random value. 989 // The result is the same (but faster) as: 990 // 991 // x := make([]byte, len(b)) 992 // mathrand.ReadUint64Xorshift(x) 993 // for i := range b { 994 // b[i] ^= x[i] 995 // } 996 func (prng *PRNG) XORReadUint64Xorshift(b []byte) (l int, err error) { 997 l = len(b) 998 s := (uintptr)((unsafe.Pointer)(&b[0])) 999 p := s 1000 e := s + uintptr(l) 1001 { 1002 state64Temp0 := prng.state64[0] 1003 for f := e - 8; p <= f; p += 8 { 1004 state64Temp0 ^= state64Temp0 << 13 1005 state64Temp0 ^= state64Temp0 >> 7 1006 state64Temp0 ^= state64Temp0 << 17 1007 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 1008 } 1009 prng.state64[0] = state64Temp0 1010 } 1011 1012 if e-p == 0 { 1013 return 1014 } 1015 rest := prng.Uint64Xorshift() 1016 if e-p >= 4 { 1017 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 1018 rest >>= 32 1019 p += 4 1020 } 1021 if e-p >= 2 { 1022 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1023 rest >>= 16 1024 p += 2 1025 } 1026 if e-p >= 1 { 1027 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1028 } 1029 return 1030 } 1031 1032 // ReadUint64XorshiftWithReseed is an analog of math/rand.Read. This random 1033 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1034 // 1035 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 1036 // a pointer `& 0xff < 8`. Sometimes it allows to improve randomness of random numbers with a 1037 // small performance impact. 1038 // This method makes sense only if len(b) is large enough (>= 256 bytes). 1039 // Otherwise it could affect strongly performance or it will not improve the randomness. 1040 // 1041 // Applied PRNG method: 1042 // Uint64Xorshift is a very fast (but weak) analog of `math/rand.Uint64`. 1043 // 1044 // See also: https://en.wikipedia.org/wiki/Xorshift 1045 func (prng *PRNG) ReadUint64XorshiftWithReseed(b []byte) (l int, err error) { 1046 l = len(b) 1047 s := (uintptr)((unsafe.Pointer)(&b[0])) 1048 p := s 1049 e := s + uintptr(l) 1050 { 1051 state64Temp0 := prng.state64[0] 1052 for f := e - 8; p <= f; p += 8 { 1053 state64Temp0 ^= state64Temp0 << 13 1054 state64Temp0 ^= state64Temp0 >> 7 1055 state64Temp0 ^= state64Temp0 << 17 1056 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 1057 if p&0xff < 8 { 1058 continue 1059 } 1060 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 1061 } 1062 prng.state64[0] = state64Temp0 1063 } 1064 1065 if e-p == 0 { 1066 return 1067 } 1068 rest := prng.Uint64Xorshift() 1069 if e-p >= 4 { 1070 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 1071 rest >>= 32 1072 p += 4 1073 } 1074 if e-p >= 2 { 1075 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1076 rest >>= 16 1077 p += 2 1078 } 1079 if e-p >= 1 { 1080 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1081 } 1082 return 1083 } 1084 1085 // XORReadUint64XorshiftWithReseed XORs argument "b" with a pseudo-random value. 1086 // The result is the same (but faster) as: 1087 // 1088 // x := make([]byte, len(b)) 1089 // mathrand.ReadUint64XorshiftWithReseed(x) 1090 // for i := range b { 1091 // b[i] ^= x[i] 1092 // } 1093 func (prng *PRNG) XORReadUint64XorshiftWithReseed(b []byte) (l int, err error) { 1094 l = len(b) 1095 s := (uintptr)((unsafe.Pointer)(&b[0])) 1096 p := s 1097 e := s + uintptr(l) 1098 { 1099 state64Temp0 := prng.state64[0] 1100 for f := e - 8; p <= f; p += 8 { 1101 state64Temp0 ^= state64Temp0 << 13 1102 state64Temp0 ^= state64Temp0 >> 7 1103 state64Temp0 ^= state64Temp0 << 17 1104 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 1105 if p&0xff < 8 { 1106 continue 1107 } 1108 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 1109 } 1110 prng.state64[0] = state64Temp0 1111 } 1112 1113 if e-p == 0 { 1114 return 1115 } 1116 rest := prng.Uint64Xorshift() 1117 if e-p >= 4 { 1118 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 1119 rest >>= 32 1120 p += 4 1121 } 1122 if e-p >= 2 { 1123 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1124 rest >>= 16 1125 p += 2 1126 } 1127 if e-p >= 1 { 1128 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1129 } 1130 return 1131 } 1132 1133 // ReadUint64Xoshiro256 is an analog of math/rand.Read. This random 1134 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1135 // 1136 // Applied PRNG method: 1137 // See also: https://en.wikipedia.org/wiki/Xorshift#xoshiro_and_xoroshiro 1138 func (prng *PRNG) ReadUint64Xoshiro256(b []byte) (l int, err error) { 1139 l = len(b) 1140 s := (uintptr)((unsafe.Pointer)(&b[0])) 1141 p := s 1142 e := s + uintptr(l) 1143 { 1144 var result uint64 1145 state64Temp1 := prng.state64[1] 1146 state64Temp2 := prng.state64[2] 1147 state64Temp0 := prng.state64[0] 1148 state64Temp3 := prng.state64[3] 1149 for f := e - 8; p <= f; p += 8 { 1150 result = rotateLeft64(state64Temp1*5, 7) * 9 1151 t := state64Temp1 << 17 1152 state64Temp2 ^= state64Temp0 1153 state64Temp3 ^= state64Temp1 1154 state64Temp1 ^= state64Temp2 1155 state64Temp0 ^= state64Temp3 1156 state64Temp2 ^= t 1157 state64Temp3 ^= rotateLeft64(state64Temp3, 45) 1158 *(*uint64)((unsafe.Pointer)(p)) = result 1159 } 1160 prng.state64[1] = state64Temp1 1161 prng.state64[2] = state64Temp2 1162 prng.state64[0] = state64Temp0 1163 prng.state64[3] = state64Temp3 1164 } 1165 1166 if e-p == 0 { 1167 return 1168 } 1169 rest := prng.Uint64Xoshiro256() 1170 if e-p >= 4 { 1171 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 1172 rest >>= 32 1173 p += 4 1174 } 1175 if e-p >= 2 { 1176 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1177 rest >>= 16 1178 p += 2 1179 } 1180 if e-p >= 1 { 1181 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1182 } 1183 return 1184 } 1185 1186 // XORReadUint64Xoshiro256 XORs argument "b" with a pseudo-random value. 1187 // The result is the same (but faster) as: 1188 // 1189 // x := make([]byte, len(b)) 1190 // mathrand.ReadUint64Xoshiro256(x) 1191 // for i := range b { 1192 // b[i] ^= x[i] 1193 // } 1194 func (prng *PRNG) XORReadUint64Xoshiro256(b []byte) (l int, err error) { 1195 l = len(b) 1196 s := (uintptr)((unsafe.Pointer)(&b[0])) 1197 p := s 1198 e := s + uintptr(l) 1199 { 1200 var result uint64 1201 state64Temp1 := prng.state64[1] 1202 state64Temp2 := prng.state64[2] 1203 state64Temp0 := prng.state64[0] 1204 state64Temp3 := prng.state64[3] 1205 for f := e - 8; p <= f; p += 8 { 1206 result = rotateLeft64(state64Temp1*5, 7) * 9 1207 t := state64Temp1 << 17 1208 state64Temp2 ^= state64Temp0 1209 state64Temp3 ^= state64Temp1 1210 state64Temp1 ^= state64Temp2 1211 state64Temp0 ^= state64Temp3 1212 state64Temp2 ^= t 1213 state64Temp3 ^= rotateLeft64(state64Temp3, 45) 1214 *(*uint64)((unsafe.Pointer)(p)) ^= result 1215 } 1216 prng.state64[1] = state64Temp1 1217 prng.state64[2] = state64Temp2 1218 prng.state64[0] = state64Temp0 1219 prng.state64[3] = state64Temp3 1220 } 1221 1222 if e-p == 0 { 1223 return 1224 } 1225 rest := prng.Uint64Xoshiro256() 1226 if e-p >= 4 { 1227 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 1228 rest >>= 32 1229 p += 4 1230 } 1231 if e-p >= 2 { 1232 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1233 rest >>= 16 1234 p += 2 1235 } 1236 if e-p >= 1 { 1237 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1238 } 1239 return 1240 } 1241 1242 // ReadUint64Xoshiro256WithReseed is an analog of math/rand.Read. This random 1243 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1244 // 1245 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 1246 // a pointer `& 0xff < 8`. Sometimes it allows to improve randomness of random numbers with a 1247 // small performance impact. 1248 // This method makes sense only if len(b) is large enough (>= 256 bytes). 1249 // Otherwise it could affect strongly performance or it will not improve the randomness. 1250 // 1251 // Applied PRNG method: 1252 // See also: https://en.wikipedia.org/wiki/Xorshift#xoshiro_and_xoroshiro 1253 func (prng *PRNG) ReadUint64Xoshiro256WithReseed(b []byte) (l int, err error) { 1254 l = len(b) 1255 s := (uintptr)((unsafe.Pointer)(&b[0])) 1256 p := s 1257 e := s + uintptr(l) 1258 { 1259 var result uint64 1260 state64Temp1 := prng.state64[1] 1261 state64Temp2 := prng.state64[2] 1262 state64Temp0 := prng.state64[0] 1263 state64Temp3 := prng.state64[3] 1264 for f := e - 8; p <= f; p += 8 { 1265 result = rotateLeft64(state64Temp1*5, 7) * 9 1266 t := state64Temp1 << 17 1267 state64Temp2 ^= state64Temp0 1268 state64Temp3 ^= state64Temp1 1269 state64Temp1 ^= state64Temp2 1270 state64Temp0 ^= state64Temp3 1271 state64Temp2 ^= t 1272 state64Temp3 ^= rotateLeft64(state64Temp3, 45) 1273 *(*uint64)((unsafe.Pointer)(p)) = result 1274 if p&0xff < 8 { 1275 continue 1276 } 1277 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 1278 } 1279 prng.state64[1] = state64Temp1 1280 prng.state64[2] = state64Temp2 1281 prng.state64[0] = state64Temp0 1282 prng.state64[3] = state64Temp3 1283 } 1284 1285 if e-p == 0 { 1286 return 1287 } 1288 rest := prng.Uint64Xoshiro256() 1289 if e-p >= 4 { 1290 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 1291 rest >>= 32 1292 p += 4 1293 } 1294 if e-p >= 2 { 1295 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1296 rest >>= 16 1297 p += 2 1298 } 1299 if e-p >= 1 { 1300 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1301 } 1302 return 1303 } 1304 1305 // XORReadUint64Xoshiro256WithReseed XORs argument "b" with a pseudo-random value. 1306 // The result is the same (but faster) as: 1307 // 1308 // x := make([]byte, len(b)) 1309 // mathrand.ReadUint64Xoshiro256WithReseed(x) 1310 // for i := range b { 1311 // b[i] ^= x[i] 1312 // } 1313 func (prng *PRNG) XORReadUint64Xoshiro256WithReseed(b []byte) (l int, err error) { 1314 l = len(b) 1315 s := (uintptr)((unsafe.Pointer)(&b[0])) 1316 p := s 1317 e := s + uintptr(l) 1318 { 1319 var result uint64 1320 state64Temp1 := prng.state64[1] 1321 state64Temp2 := prng.state64[2] 1322 state64Temp0 := prng.state64[0] 1323 state64Temp3 := prng.state64[3] 1324 for f := e - 8; p <= f; p += 8 { 1325 result = rotateLeft64(state64Temp1*5, 7) * 9 1326 t := state64Temp1 << 17 1327 state64Temp2 ^= state64Temp0 1328 state64Temp3 ^= state64Temp1 1329 state64Temp1 ^= state64Temp2 1330 state64Temp0 ^= state64Temp3 1331 state64Temp2 ^= t 1332 state64Temp3 ^= rotateLeft64(state64Temp3, 45) 1333 *(*uint64)((unsafe.Pointer)(p)) ^= result 1334 if p&0xff < 8 { 1335 continue 1336 } 1337 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 1338 } 1339 prng.state64[1] = state64Temp1 1340 prng.state64[2] = state64Temp2 1341 prng.state64[0] = state64Temp0 1342 prng.state64[3] = state64Temp3 1343 } 1344 1345 if e-p == 0 { 1346 return 1347 } 1348 rest := prng.Uint64Xoshiro256() 1349 if e-p >= 4 { 1350 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 1351 rest >>= 32 1352 p += 4 1353 } 1354 if e-p >= 2 { 1355 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1356 rest >>= 16 1357 p += 2 1358 } 1359 if e-p >= 1 { 1360 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1361 } 1362 return 1363 } 1364 1365 // ReadUint64MSWS is an analog of math/rand.Read. This random 1366 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1367 // 1368 // Applied PRNG method: 1369 // See also: https://en.wikipedia.org/wiki/Middle-square_method 1370 func (prng *PRNG) ReadUint64MSWS(b []byte) (l int, err error) { 1371 l = len(b) 1372 s := (uintptr)((unsafe.Pointer)(&b[0])) 1373 p := s 1374 e := s + uintptr(l) 1375 { 1376 state64Temp0 := prng.state64[0] 1377 state64Temp1 := prng.state64[1] 1378 for f := e - 8; p <= f; p += 8 { 1379 state64Temp0 *= state64Temp0 1380 state64Temp1 += mswsSeed 1381 state64Temp0 += state64Temp1 1382 state64Temp0 = rotateLeft64(state64Temp0, 32) 1383 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 1384 } 1385 prng.state64[0] = state64Temp0 1386 prng.state64[1] = state64Temp1 1387 } 1388 1389 if e-p == 0 { 1390 return 1391 } 1392 rest := prng.Uint64MSWS() 1393 if e-p >= 4 { 1394 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 1395 rest >>= 32 1396 p += 4 1397 } 1398 if e-p >= 2 { 1399 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1400 rest >>= 16 1401 p += 2 1402 } 1403 if e-p >= 1 { 1404 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1405 } 1406 return 1407 } 1408 1409 // XORReadUint64MSWS XORs argument "b" with a pseudo-random value. 1410 // The result is the same (but faster) as: 1411 // 1412 // x := make([]byte, len(b)) 1413 // mathrand.ReadUint64MSWS(x) 1414 // for i := range b { 1415 // b[i] ^= x[i] 1416 // } 1417 func (prng *PRNG) XORReadUint64MSWS(b []byte) (l int, err error) { 1418 l = len(b) 1419 s := (uintptr)((unsafe.Pointer)(&b[0])) 1420 p := s 1421 e := s + uintptr(l) 1422 { 1423 state64Temp0 := prng.state64[0] 1424 state64Temp1 := prng.state64[1] 1425 for f := e - 8; p <= f; p += 8 { 1426 state64Temp0 *= state64Temp0 1427 state64Temp1 += mswsSeed 1428 state64Temp0 += state64Temp1 1429 state64Temp0 = rotateLeft64(state64Temp0, 32) 1430 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 1431 } 1432 prng.state64[0] = state64Temp0 1433 prng.state64[1] = state64Temp1 1434 } 1435 1436 if e-p == 0 { 1437 return 1438 } 1439 rest := prng.Uint64MSWS() 1440 if e-p >= 4 { 1441 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 1442 rest >>= 32 1443 p += 4 1444 } 1445 if e-p >= 2 { 1446 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1447 rest >>= 16 1448 p += 2 1449 } 1450 if e-p >= 1 { 1451 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1452 } 1453 return 1454 } 1455 1456 // ReadUint64MSWSWithReseed is an analog of math/rand.Read. This random 1457 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1458 // 1459 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 1460 // a pointer `& 0xff < 8`. Sometimes it allows to improve randomness of random numbers with a 1461 // small performance impact. 1462 // This method makes sense only if len(b) is large enough (>= 256 bytes). 1463 // Otherwise it could affect strongly performance or it will not improve the randomness. 1464 // 1465 // Applied PRNG method: 1466 // See also: https://en.wikipedia.org/wiki/Middle-square_method 1467 func (prng *PRNG) ReadUint64MSWSWithReseed(b []byte) (l int, err error) { 1468 l = len(b) 1469 s := (uintptr)((unsafe.Pointer)(&b[0])) 1470 p := s 1471 e := s + uintptr(l) 1472 { 1473 state64Temp0 := prng.state64[0] 1474 state64Temp1 := prng.state64[1] 1475 for f := e - 8; p <= f; p += 8 { 1476 state64Temp0 *= state64Temp0 1477 state64Temp1 += mswsSeed 1478 state64Temp0 += state64Temp1 1479 state64Temp0 = rotateLeft64(state64Temp0, 32) 1480 *(*uint64)((unsafe.Pointer)(p)) = state64Temp0 1481 if p&0xff < 8 { 1482 continue 1483 } 1484 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 1485 } 1486 prng.state64[0] = state64Temp0 1487 prng.state64[1] = state64Temp1 1488 } 1489 1490 if e-p == 0 { 1491 return 1492 } 1493 rest := prng.Uint64MSWS() 1494 if e-p >= 4 { 1495 *(*uint32)((unsafe.Pointer)(p)) = uint32(rest) 1496 rest >>= 32 1497 p += 4 1498 } 1499 if e-p >= 2 { 1500 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1501 rest >>= 16 1502 p += 2 1503 } 1504 if e-p >= 1 { 1505 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1506 } 1507 return 1508 } 1509 1510 // XORReadUint64MSWSWithReseed XORs argument "b" with a pseudo-random value. 1511 // The result is the same (but faster) as: 1512 // 1513 // x := make([]byte, len(b)) 1514 // mathrand.ReadUint64MSWSWithReseed(x) 1515 // for i := range b { 1516 // b[i] ^= x[i] 1517 // } 1518 func (prng *PRNG) XORReadUint64MSWSWithReseed(b []byte) (l int, err error) { 1519 l = len(b) 1520 s := (uintptr)((unsafe.Pointer)(&b[0])) 1521 p := s 1522 e := s + uintptr(l) 1523 { 1524 state64Temp0 := prng.state64[0] 1525 state64Temp1 := prng.state64[1] 1526 for f := e - 8; p <= f; p += 8 { 1527 state64Temp0 *= state64Temp0 1528 state64Temp1 += mswsSeed 1529 state64Temp0 += state64Temp1 1530 state64Temp0 = rotateLeft64(state64Temp0, 32) 1531 *(*uint64)((unsafe.Pointer)(p)) ^= state64Temp0 1532 if p&0xff < 8 { 1533 continue 1534 } 1535 state64Temp0 = xorShift64(state64Temp0 ^ primeNumber64bit0) 1536 } 1537 prng.state64[0] = state64Temp0 1538 prng.state64[1] = state64Temp1 1539 } 1540 1541 if e-p == 0 { 1542 return 1543 } 1544 rest := prng.Uint64MSWS() 1545 if e-p >= 4 { 1546 *(*uint32)((unsafe.Pointer)(p)) ^= uint32(rest) 1547 rest >>= 32 1548 p += 4 1549 } 1550 if e-p >= 2 { 1551 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1552 rest >>= 16 1553 p += 2 1554 } 1555 if e-p >= 1 { 1556 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1557 } 1558 return 1559 } 1560 1561 // ReadUint32AddRotateMultiply is an analog of math/rand.Read. This random 1562 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1563 // 1564 // Applied PRNG method: 1565 // Uint32AddRotateMultiply is a fast analog of `math/rand.Uint32`. 1566 // 1567 // The reliability on statistical tests of this method is unknown. This is 1568 // improved LCG method, so see also Uint32MultiplyAdd. 1569 func (prng *PRNG) ReadUint32AddRotateMultiply(b []byte) (l int, err error) { 1570 l = len(b) 1571 s := (uintptr)((unsafe.Pointer)(&b[0])) 1572 p := s 1573 e := s + uintptr(l) 1574 { 1575 state32Temp0 := prng.state32[0] 1576 for f := e - 4; p <= f; p += 4 { 1577 state32Temp0 += primeNumber32bit1 1578 state32Temp0 = rotateLeft32(state32Temp0, 32) 1579 state32Temp0 *= primeNumber32bit0 1580 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 1581 } 1582 prng.state32[0] = state32Temp0 1583 } 1584 1585 if e-p == 0 { 1586 return 1587 } 1588 rest := prng.Uint32AddRotateMultiply() 1589 if e-p >= 2 { 1590 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1591 rest >>= 16 1592 p += 2 1593 } 1594 if e-p >= 1 { 1595 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1596 } 1597 return 1598 } 1599 1600 // XORReadUint32AddRotateMultiply XORs argument "b" with a pseudo-random value. 1601 // The result is the same (but faster) as: 1602 // 1603 // x := make([]byte, len(b)) 1604 // mathrand.ReadUint32AddRotateMultiply(x) 1605 // for i := range b { 1606 // b[i] ^= x[i] 1607 // } 1608 func (prng *PRNG) XORReadUint32AddRotateMultiply(b []byte) (l int, err error) { 1609 l = len(b) 1610 s := (uintptr)((unsafe.Pointer)(&b[0])) 1611 p := s 1612 e := s + uintptr(l) 1613 { 1614 state32Temp0 := prng.state32[0] 1615 for f := e - 4; p <= f; p += 4 { 1616 state32Temp0 += primeNumber32bit1 1617 state32Temp0 = rotateLeft32(state32Temp0, 32) 1618 state32Temp0 *= primeNumber32bit0 1619 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 1620 } 1621 prng.state32[0] = state32Temp0 1622 } 1623 1624 if e-p == 0 { 1625 return 1626 } 1627 rest := prng.Uint32AddRotateMultiply() 1628 if e-p >= 2 { 1629 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1630 rest >>= 16 1631 p += 2 1632 } 1633 if e-p >= 1 { 1634 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1635 } 1636 return 1637 } 1638 1639 // ReadUint32AddRotateMultiplyWithReseed is an analog of math/rand.Read. This random 1640 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1641 // 1642 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 1643 // a pointer `& 0xff < 4`. Sometimes it allows to improve randomness of random numbers with a 1644 // small performance impact. 1645 // This method makes sense only if len(b) is large enough (>= 256 bytes). 1646 // Otherwise it could affect strongly performance or it will not improve the randomness. 1647 // 1648 // Applied PRNG method: 1649 // Uint32AddRotateMultiply is a fast analog of `math/rand.Uint32`. 1650 // 1651 // The reliability on statistical tests of this method is unknown. This is 1652 // improved LCG method, so see also Uint32MultiplyAdd. 1653 func (prng *PRNG) ReadUint32AddRotateMultiplyWithReseed(b []byte) (l int, err error) { 1654 l = len(b) 1655 s := (uintptr)((unsafe.Pointer)(&b[0])) 1656 p := s 1657 e := s + uintptr(l) 1658 { 1659 state32Temp0 := prng.state32[0] 1660 for f := e - 4; p <= f; p += 4 { 1661 state32Temp0 += primeNumber32bit1 1662 state32Temp0 = rotateLeft32(state32Temp0, 32) 1663 state32Temp0 *= primeNumber32bit0 1664 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 1665 if p&0xff < 4 { 1666 continue 1667 } 1668 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 1669 } 1670 prng.state32[0] = state32Temp0 1671 } 1672 1673 if e-p == 0 { 1674 return 1675 } 1676 rest := prng.Uint32AddRotateMultiply() 1677 if e-p >= 2 { 1678 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1679 rest >>= 16 1680 p += 2 1681 } 1682 if e-p >= 1 { 1683 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1684 } 1685 return 1686 } 1687 1688 // XORReadUint32AddRotateMultiplyWithReseed XORs argument "b" with a pseudo-random value. 1689 // The result is the same (but faster) as: 1690 // 1691 // x := make([]byte, len(b)) 1692 // mathrand.ReadUint32AddRotateMultiplyWithReseed(x) 1693 // for i := range b { 1694 // b[i] ^= x[i] 1695 // } 1696 func (prng *PRNG) XORReadUint32AddRotateMultiplyWithReseed(b []byte) (l int, err error) { 1697 l = len(b) 1698 s := (uintptr)((unsafe.Pointer)(&b[0])) 1699 p := s 1700 e := s + uintptr(l) 1701 { 1702 state32Temp0 := prng.state32[0] 1703 for f := e - 4; p <= f; p += 4 { 1704 state32Temp0 += primeNumber32bit1 1705 state32Temp0 = rotateLeft32(state32Temp0, 32) 1706 state32Temp0 *= primeNumber32bit0 1707 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 1708 if p&0xff < 4 { 1709 continue 1710 } 1711 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 1712 } 1713 prng.state32[0] = state32Temp0 1714 } 1715 1716 if e-p == 0 { 1717 return 1718 } 1719 rest := prng.Uint32AddRotateMultiply() 1720 if e-p >= 2 { 1721 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1722 rest >>= 16 1723 p += 2 1724 } 1725 if e-p >= 1 { 1726 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1727 } 1728 return 1729 } 1730 1731 // ReadUint32MultiplyAdd is an analog of math/rand.Read. This random 1732 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1733 // 1734 // Applied PRNG method: 1735 // Uint32MultiplyAdd is a fast (but week) analog of `math/rand.Uint32`. 1736 // 1737 // See also: https://en.wikipedia.org/wiki/Linear_congruential_generator 1738 func (prng *PRNG) ReadUint32MultiplyAdd(b []byte) (l int, err error) { 1739 l = len(b) 1740 s := (uintptr)((unsafe.Pointer)(&b[0])) 1741 p := s 1742 e := s + uintptr(l) 1743 { 1744 state32Temp0 := prng.state32[0] 1745 for f := e - 4; p <= f; p += 4 { 1746 state32Temp0 *= primeNumber32bit0 1747 state32Temp0 += primeNumber32bit1 1748 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 1749 } 1750 prng.state32[0] = state32Temp0 1751 } 1752 1753 if e-p == 0 { 1754 return 1755 } 1756 rest := prng.Uint32MultiplyAdd() 1757 if e-p >= 2 { 1758 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1759 rest >>= 16 1760 p += 2 1761 } 1762 if e-p >= 1 { 1763 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1764 } 1765 return 1766 } 1767 1768 // XORReadUint32MultiplyAdd XORs argument "b" with a pseudo-random value. 1769 // The result is the same (but faster) as: 1770 // 1771 // x := make([]byte, len(b)) 1772 // mathrand.ReadUint32MultiplyAdd(x) 1773 // for i := range b { 1774 // b[i] ^= x[i] 1775 // } 1776 func (prng *PRNG) XORReadUint32MultiplyAdd(b []byte) (l int, err error) { 1777 l = len(b) 1778 s := (uintptr)((unsafe.Pointer)(&b[0])) 1779 p := s 1780 e := s + uintptr(l) 1781 { 1782 state32Temp0 := prng.state32[0] 1783 for f := e - 4; p <= f; p += 4 { 1784 state32Temp0 *= primeNumber32bit0 1785 state32Temp0 += primeNumber32bit1 1786 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 1787 } 1788 prng.state32[0] = state32Temp0 1789 } 1790 1791 if e-p == 0 { 1792 return 1793 } 1794 rest := prng.Uint32MultiplyAdd() 1795 if e-p >= 2 { 1796 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1797 rest >>= 16 1798 p += 2 1799 } 1800 if e-p >= 1 { 1801 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1802 } 1803 return 1804 } 1805 1806 // ReadUint32MultiplyAddWithReseed is an analog of math/rand.Read. This random 1807 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1808 // 1809 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 1810 // a pointer `& 0xff < 4`. Sometimes it allows to improve randomness of random numbers with a 1811 // small performance impact. 1812 // This method makes sense only if len(b) is large enough (>= 256 bytes). 1813 // Otherwise it could affect strongly performance or it will not improve the randomness. 1814 // 1815 // Applied PRNG method: 1816 // Uint32MultiplyAdd is a fast (but week) analog of `math/rand.Uint32`. 1817 // 1818 // See also: https://en.wikipedia.org/wiki/Linear_congruential_generator 1819 func (prng *PRNG) ReadUint32MultiplyAddWithReseed(b []byte) (l int, err error) { 1820 l = len(b) 1821 s := (uintptr)((unsafe.Pointer)(&b[0])) 1822 p := s 1823 e := s + uintptr(l) 1824 { 1825 state32Temp0 := prng.state32[0] 1826 for f := e - 4; p <= f; p += 4 { 1827 state32Temp0 *= primeNumber32bit0 1828 state32Temp0 += primeNumber32bit1 1829 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 1830 if p&0xff < 4 { 1831 continue 1832 } 1833 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 1834 } 1835 prng.state32[0] = state32Temp0 1836 } 1837 1838 if e-p == 0 { 1839 return 1840 } 1841 rest := prng.Uint32MultiplyAdd() 1842 if e-p >= 2 { 1843 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1844 rest >>= 16 1845 p += 2 1846 } 1847 if e-p >= 1 { 1848 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1849 } 1850 return 1851 } 1852 1853 // XORReadUint32MultiplyAddWithReseed XORs argument "b" with a pseudo-random value. 1854 // The result is the same (but faster) as: 1855 // 1856 // x := make([]byte, len(b)) 1857 // mathrand.ReadUint32MultiplyAddWithReseed(x) 1858 // for i := range b { 1859 // b[i] ^= x[i] 1860 // } 1861 func (prng *PRNG) XORReadUint32MultiplyAddWithReseed(b []byte) (l int, err error) { 1862 l = len(b) 1863 s := (uintptr)((unsafe.Pointer)(&b[0])) 1864 p := s 1865 e := s + uintptr(l) 1866 { 1867 state32Temp0 := prng.state32[0] 1868 for f := e - 4; p <= f; p += 4 { 1869 state32Temp0 *= primeNumber32bit0 1870 state32Temp0 += primeNumber32bit1 1871 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 1872 if p&0xff < 4 { 1873 continue 1874 } 1875 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 1876 } 1877 prng.state32[0] = state32Temp0 1878 } 1879 1880 if e-p == 0 { 1881 return 1882 } 1883 rest := prng.Uint32MultiplyAdd() 1884 if e-p >= 2 { 1885 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1886 rest >>= 16 1887 p += 2 1888 } 1889 if e-p >= 1 { 1890 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1891 } 1892 return 1893 } 1894 1895 // ReadUint32AddRotate is an analog of math/rand.Read. This random 1896 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1897 // 1898 // Applied PRNG method: 1899 // Uint32AddRotate is a very fast (but weak) analog of `math/rand.Uint32`. 1900 func (prng *PRNG) ReadUint32AddRotate(b []byte) (l int, err error) { 1901 l = len(b) 1902 s := (uintptr)((unsafe.Pointer)(&b[0])) 1903 p := s 1904 e := s + uintptr(l) 1905 { 1906 state32Temp0 := prng.state32[0] 1907 for f := e - 4; p <= f; p += 4 { 1908 state32Temp0 += primeNumber32bit0 1909 state32Temp0 = rotateLeft32(state32Temp0, 32) 1910 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 1911 } 1912 prng.state32[0] = state32Temp0 1913 } 1914 1915 if e-p == 0 { 1916 return 1917 } 1918 rest := prng.Uint32AddRotate() 1919 if e-p >= 2 { 1920 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 1921 rest >>= 16 1922 p += 2 1923 } 1924 if e-p >= 1 { 1925 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 1926 } 1927 return 1928 } 1929 1930 // XORReadUint32AddRotate XORs argument "b" with a pseudo-random value. 1931 // The result is the same (but faster) as: 1932 // 1933 // x := make([]byte, len(b)) 1934 // mathrand.ReadUint32AddRotate(x) 1935 // for i := range b { 1936 // b[i] ^= x[i] 1937 // } 1938 func (prng *PRNG) XORReadUint32AddRotate(b []byte) (l int, err error) { 1939 l = len(b) 1940 s := (uintptr)((unsafe.Pointer)(&b[0])) 1941 p := s 1942 e := s + uintptr(l) 1943 { 1944 state32Temp0 := prng.state32[0] 1945 for f := e - 4; p <= f; p += 4 { 1946 state32Temp0 += primeNumber32bit0 1947 state32Temp0 = rotateLeft32(state32Temp0, 32) 1948 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 1949 } 1950 prng.state32[0] = state32Temp0 1951 } 1952 1953 if e-p == 0 { 1954 return 1955 } 1956 rest := prng.Uint32AddRotate() 1957 if e-p >= 2 { 1958 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 1959 rest >>= 16 1960 p += 2 1961 } 1962 if e-p >= 1 { 1963 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 1964 } 1965 return 1966 } 1967 1968 // ReadUint32AddRotateWithReseed is an analog of math/rand.Read. This random 1969 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 1970 // 1971 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 1972 // a pointer `& 0xff < 4`. Sometimes it allows to improve randomness of random numbers with a 1973 // small performance impact. 1974 // This method makes sense only if len(b) is large enough (>= 256 bytes). 1975 // Otherwise it could affect strongly performance or it will not improve the randomness. 1976 // 1977 // Applied PRNG method: 1978 // Uint32AddRotate is a very fast (but weak) analog of `math/rand.Uint32`. 1979 func (prng *PRNG) ReadUint32AddRotateWithReseed(b []byte) (l int, err error) { 1980 l = len(b) 1981 s := (uintptr)((unsafe.Pointer)(&b[0])) 1982 p := s 1983 e := s + uintptr(l) 1984 { 1985 state32Temp0 := prng.state32[0] 1986 for f := e - 4; p <= f; p += 4 { 1987 state32Temp0 += primeNumber32bit0 1988 state32Temp0 = rotateLeft32(state32Temp0, 32) 1989 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 1990 if p&0xff < 4 { 1991 continue 1992 } 1993 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 1994 } 1995 prng.state32[0] = state32Temp0 1996 } 1997 1998 if e-p == 0 { 1999 return 2000 } 2001 rest := prng.Uint32AddRotate() 2002 if e-p >= 2 { 2003 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 2004 rest >>= 16 2005 p += 2 2006 } 2007 if e-p >= 1 { 2008 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 2009 } 2010 return 2011 } 2012 2013 // XORReadUint32AddRotateWithReseed XORs argument "b" with a pseudo-random value. 2014 // The result is the same (but faster) as: 2015 // 2016 // x := make([]byte, len(b)) 2017 // mathrand.ReadUint32AddRotateWithReseed(x) 2018 // for i := range b { 2019 // b[i] ^= x[i] 2020 // } 2021 func (prng *PRNG) XORReadUint32AddRotateWithReseed(b []byte) (l int, err error) { 2022 l = len(b) 2023 s := (uintptr)((unsafe.Pointer)(&b[0])) 2024 p := s 2025 e := s + uintptr(l) 2026 { 2027 state32Temp0 := prng.state32[0] 2028 for f := e - 4; p <= f; p += 4 { 2029 state32Temp0 += primeNumber32bit0 2030 state32Temp0 = rotateLeft32(state32Temp0, 32) 2031 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 2032 if p&0xff < 4 { 2033 continue 2034 } 2035 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 2036 } 2037 prng.state32[0] = state32Temp0 2038 } 2039 2040 if e-p == 0 { 2041 return 2042 } 2043 rest := prng.Uint32AddRotate() 2044 if e-p >= 2 { 2045 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 2046 rest >>= 16 2047 p += 2 2048 } 2049 if e-p >= 1 { 2050 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 2051 } 2052 return 2053 } 2054 2055 // ReadUint32AddIfShiftXOR is an analog of math/rand.Read. This random 2056 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 2057 // 2058 // Applied PRNG method: 2059 // Uint32AddIfShiftXOR is a very fast (but weak) analog of `math/rand.Uint32`. 2060 func (prng *PRNG) ReadUint32AddIfShiftXOR(b []byte) (l int, err error) { 2061 l = len(b) 2062 s := (uintptr)((unsafe.Pointer)(&b[0])) 2063 p := s 2064 e := s + uintptr(l) 2065 { 2066 state32Temp0 := prng.state32[0] 2067 for f := e - 4; p <= f; p += 4 { 2068 state32Temp0 += primeNumber32bit1 2069 if state32Temp0&0x02 == 0 { 2070 state32Temp0 ^= state32Temp0 >> 16 2071 } 2072 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 2073 } 2074 prng.state32[0] = state32Temp0 2075 } 2076 2077 if e-p == 0 { 2078 return 2079 } 2080 rest := prng.Uint32AddIfShiftXOR() 2081 if e-p >= 2 { 2082 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 2083 rest >>= 16 2084 p += 2 2085 } 2086 if e-p >= 1 { 2087 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 2088 } 2089 return 2090 } 2091 2092 // XORReadUint32AddIfShiftXOR XORs argument "b" with a pseudo-random value. 2093 // The result is the same (but faster) as: 2094 // 2095 // x := make([]byte, len(b)) 2096 // mathrand.ReadUint32AddIfShiftXOR(x) 2097 // for i := range b { 2098 // b[i] ^= x[i] 2099 // } 2100 func (prng *PRNG) XORReadUint32AddIfShiftXOR(b []byte) (l int, err error) { 2101 l = len(b) 2102 s := (uintptr)((unsafe.Pointer)(&b[0])) 2103 p := s 2104 e := s + uintptr(l) 2105 { 2106 state32Temp0 := prng.state32[0] 2107 for f := e - 4; p <= f; p += 4 { 2108 state32Temp0 += primeNumber32bit1 2109 if state32Temp0&0x02 == 0 { 2110 state32Temp0 ^= state32Temp0 >> 16 2111 } 2112 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 2113 } 2114 prng.state32[0] = state32Temp0 2115 } 2116 2117 if e-p == 0 { 2118 return 2119 } 2120 rest := prng.Uint32AddIfShiftXOR() 2121 if e-p >= 2 { 2122 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 2123 rest >>= 16 2124 p += 2 2125 } 2126 if e-p >= 1 { 2127 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 2128 } 2129 return 2130 } 2131 2132 // ReadUint32AddIfShiftXORWithReseed is an analog of math/rand.Read. This random 2133 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 2134 // 2135 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 2136 // a pointer `& 0xff < 4`. Sometimes it allows to improve randomness of random numbers with a 2137 // small performance impact. 2138 // This method makes sense only if len(b) is large enough (>= 256 bytes). 2139 // Otherwise it could affect strongly performance or it will not improve the randomness. 2140 // 2141 // Applied PRNG method: 2142 // Uint32AddIfShiftXOR is a very fast (but weak) analog of `math/rand.Uint32`. 2143 func (prng *PRNG) ReadUint32AddIfShiftXORWithReseed(b []byte) (l int, err error) { 2144 l = len(b) 2145 s := (uintptr)((unsafe.Pointer)(&b[0])) 2146 p := s 2147 e := s + uintptr(l) 2148 { 2149 state32Temp0 := prng.state32[0] 2150 for f := e - 4; p <= f; p += 4 { 2151 state32Temp0 += primeNumber32bit1 2152 if state32Temp0&0x02 == 0 { 2153 state32Temp0 ^= state32Temp0 >> 16 2154 } 2155 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 2156 if p&0xff < 4 { 2157 continue 2158 } 2159 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 2160 } 2161 prng.state32[0] = state32Temp0 2162 } 2163 2164 if e-p == 0 { 2165 return 2166 } 2167 rest := prng.Uint32AddIfShiftXOR() 2168 if e-p >= 2 { 2169 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 2170 rest >>= 16 2171 p += 2 2172 } 2173 if e-p >= 1 { 2174 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 2175 } 2176 return 2177 } 2178 2179 // XORReadUint32AddIfShiftXORWithReseed XORs argument "b" with a pseudo-random value. 2180 // The result is the same (but faster) as: 2181 // 2182 // x := make([]byte, len(b)) 2183 // mathrand.ReadUint32AddIfShiftXORWithReseed(x) 2184 // for i := range b { 2185 // b[i] ^= x[i] 2186 // } 2187 func (prng *PRNG) XORReadUint32AddIfShiftXORWithReseed(b []byte) (l int, err error) { 2188 l = len(b) 2189 s := (uintptr)((unsafe.Pointer)(&b[0])) 2190 p := s 2191 e := s + uintptr(l) 2192 { 2193 state32Temp0 := prng.state32[0] 2194 for f := e - 4; p <= f; p += 4 { 2195 state32Temp0 += primeNumber32bit1 2196 if state32Temp0&0x02 == 0 { 2197 state32Temp0 ^= state32Temp0 >> 16 2198 } 2199 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 2200 if p&0xff < 4 { 2201 continue 2202 } 2203 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 2204 } 2205 prng.state32[0] = state32Temp0 2206 } 2207 2208 if e-p == 0 { 2209 return 2210 } 2211 rest := prng.Uint32AddIfShiftXOR() 2212 if e-p >= 2 { 2213 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 2214 rest >>= 16 2215 p += 2 2216 } 2217 if e-p >= 1 { 2218 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 2219 } 2220 return 2221 } 2222 2223 // ReadUint32Xorshift is an analog of math/rand.Read. This random 2224 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 2225 // 2226 // Applied PRNG method: 2227 // Uint32Xorshift is a very fast (but weak) analog of `math/rand.Uint32`. 2228 // 2229 // See also: https://en.wikipedia.org/wiki/Xorshift 2230 func (prng *PRNG) ReadUint32Xorshift(b []byte) (l int, err error) { 2231 l = len(b) 2232 s := (uintptr)((unsafe.Pointer)(&b[0])) 2233 p := s 2234 e := s + uintptr(l) 2235 { 2236 state32Temp0 := prng.state32[0] 2237 for f := e - 4; p <= f; p += 4 { 2238 state32Temp0 ^= state32Temp0 << 13 2239 state32Temp0 ^= state32Temp0 >> 17 2240 state32Temp0 ^= state32Temp0 << 5 2241 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 2242 } 2243 prng.state32[0] = state32Temp0 2244 } 2245 2246 if e-p == 0 { 2247 return 2248 } 2249 rest := prng.Uint32Xorshift() 2250 if e-p >= 2 { 2251 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 2252 rest >>= 16 2253 p += 2 2254 } 2255 if e-p >= 1 { 2256 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 2257 } 2258 return 2259 } 2260 2261 // XORReadUint32Xorshift XORs argument "b" with a pseudo-random value. 2262 // The result is the same (but faster) as: 2263 // 2264 // x := make([]byte, len(b)) 2265 // mathrand.ReadUint32Xorshift(x) 2266 // for i := range b { 2267 // b[i] ^= x[i] 2268 // } 2269 func (prng *PRNG) XORReadUint32Xorshift(b []byte) (l int, err error) { 2270 l = len(b) 2271 s := (uintptr)((unsafe.Pointer)(&b[0])) 2272 p := s 2273 e := s + uintptr(l) 2274 { 2275 state32Temp0 := prng.state32[0] 2276 for f := e - 4; p <= f; p += 4 { 2277 state32Temp0 ^= state32Temp0 << 13 2278 state32Temp0 ^= state32Temp0 >> 17 2279 state32Temp0 ^= state32Temp0 << 5 2280 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 2281 } 2282 prng.state32[0] = state32Temp0 2283 } 2284 2285 if e-p == 0 { 2286 return 2287 } 2288 rest := prng.Uint32Xorshift() 2289 if e-p >= 2 { 2290 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 2291 rest >>= 16 2292 p += 2 2293 } 2294 if e-p >= 1 { 2295 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 2296 } 2297 return 2298 } 2299 2300 // ReadUint32XorshiftWithReseed is an analog of math/rand.Read. This random 2301 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 2302 // 2303 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 2304 // a pointer `& 0xff < 4`. Sometimes it allows to improve randomness of random numbers with a 2305 // small performance impact. 2306 // This method makes sense only if len(b) is large enough (>= 256 bytes). 2307 // Otherwise it could affect strongly performance or it will not improve the randomness. 2308 // 2309 // Applied PRNG method: 2310 // Uint32Xorshift is a very fast (but weak) analog of `math/rand.Uint32`. 2311 // 2312 // See also: https://en.wikipedia.org/wiki/Xorshift 2313 func (prng *PRNG) ReadUint32XorshiftWithReseed(b []byte) (l int, err error) { 2314 l = len(b) 2315 s := (uintptr)((unsafe.Pointer)(&b[0])) 2316 p := s 2317 e := s + uintptr(l) 2318 { 2319 state32Temp0 := prng.state32[0] 2320 for f := e - 4; p <= f; p += 4 { 2321 state32Temp0 ^= state32Temp0 << 13 2322 state32Temp0 ^= state32Temp0 >> 17 2323 state32Temp0 ^= state32Temp0 << 5 2324 *(*uint32)((unsafe.Pointer)(p)) = state32Temp0 2325 if p&0xff < 4 { 2326 continue 2327 } 2328 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 2329 } 2330 prng.state32[0] = state32Temp0 2331 } 2332 2333 if e-p == 0 { 2334 return 2335 } 2336 rest := prng.Uint32Xorshift() 2337 if e-p >= 2 { 2338 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 2339 rest >>= 16 2340 p += 2 2341 } 2342 if e-p >= 1 { 2343 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 2344 } 2345 return 2346 } 2347 2348 // XORReadUint32XorshiftWithReseed XORs argument "b" with a pseudo-random value. 2349 // The result is the same (but faster) as: 2350 // 2351 // x := make([]byte, len(b)) 2352 // mathrand.ReadUint32XorshiftWithReseed(x) 2353 // for i := range b { 2354 // b[i] ^= x[i] 2355 // } 2356 func (prng *PRNG) XORReadUint32XorshiftWithReseed(b []byte) (l int, err error) { 2357 l = len(b) 2358 s := (uintptr)((unsafe.Pointer)(&b[0])) 2359 p := s 2360 e := s + uintptr(l) 2361 { 2362 state32Temp0 := prng.state32[0] 2363 for f := e - 4; p <= f; p += 4 { 2364 state32Temp0 ^= state32Temp0 << 13 2365 state32Temp0 ^= state32Temp0 >> 17 2366 state32Temp0 ^= state32Temp0 << 5 2367 *(*uint32)((unsafe.Pointer)(p)) ^= state32Temp0 2368 if p&0xff < 4 { 2369 continue 2370 } 2371 state32Temp0 = (uint32)(xorShift32(state32Temp0 ^ primeNumber32bit0)) 2372 } 2373 prng.state32[0] = state32Temp0 2374 } 2375 2376 if e-p == 0 { 2377 return 2378 } 2379 rest := prng.Uint32Xorshift() 2380 if e-p >= 2 { 2381 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 2382 rest >>= 16 2383 p += 2 2384 } 2385 if e-p >= 1 { 2386 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 2387 } 2388 return 2389 } 2390 2391 // ReadUint32PCG is an analog of math/rand.Read. This random 2392 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 2393 // 2394 // Applied PRNG method: 2395 // See also: https://en.wikipedia.org/wiki/Permuted_congruential_generator 2396 func (prng *PRNG) ReadUint32PCG(b []byte) (l int, err error) { 2397 l = len(b) 2398 s := (uintptr)((unsafe.Pointer)(&b[0])) 2399 p := s 2400 e := s + uintptr(l) 2401 { 2402 pcgStateTemp := prng.pcgState 2403 for f := e - 4; p <= f; p += 4 { 2404 x := pcgStateTemp 2405 count := int(x >> 59) 2406 pcgStateTemp = x*pcgMultiplier + pcgIncrement 2407 x ^= x >> 18 2408 *(*uint32)((unsafe.Pointer)(p)) = rotateRight32(uint32(x>>27), count) 2409 } 2410 prng.pcgState = pcgStateTemp 2411 } 2412 2413 if e-p == 0 { 2414 return 2415 } 2416 rest := prng.Uint32PCG() 2417 if e-p >= 2 { 2418 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 2419 rest >>= 16 2420 p += 2 2421 } 2422 if e-p >= 1 { 2423 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 2424 } 2425 return 2426 } 2427 2428 // XORReadUint32PCG XORs argument "b" with a pseudo-random value. 2429 // The result is the same (but faster) as: 2430 // 2431 // x := make([]byte, len(b)) 2432 // mathrand.ReadUint32PCG(x) 2433 // for i := range b { 2434 // b[i] ^= x[i] 2435 // } 2436 func (prng *PRNG) XORReadUint32PCG(b []byte) (l int, err error) { 2437 l = len(b) 2438 s := (uintptr)((unsafe.Pointer)(&b[0])) 2439 p := s 2440 e := s + uintptr(l) 2441 { 2442 pcgStateTemp := prng.pcgState 2443 for f := e - 4; p <= f; p += 4 { 2444 x := pcgStateTemp 2445 count := int(x >> 59) 2446 pcgStateTemp = x*pcgMultiplier + pcgIncrement 2447 x ^= x >> 18 2448 *(*uint32)((unsafe.Pointer)(p)) ^= rotateRight32(uint32(x>>27), count) 2449 } 2450 prng.pcgState = pcgStateTemp 2451 } 2452 2453 if e-p == 0 { 2454 return 2455 } 2456 rest := prng.Uint32PCG() 2457 if e-p >= 2 { 2458 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 2459 rest >>= 16 2460 p += 2 2461 } 2462 if e-p >= 1 { 2463 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 2464 } 2465 return 2466 } 2467 2468 // ReadUint32PCGWithReseed is an analog of math/rand.Read. This random 2469 // numbers could easily be predicted (it's not an analog of crypto/rand.Read). 2470 // 2471 // "Reseed" forces to use a new seed (generated using XORShift method) on setting value to 2472 // a pointer `& 0xff < 4`. Sometimes it allows to improve randomness of random numbers with a 2473 // small performance impact. 2474 // This method makes sense only if len(b) is large enough (>= 256 bytes). 2475 // Otherwise it could affect strongly performance or it will not improve the randomness. 2476 // 2477 // Applied PRNG method: 2478 // See also: https://en.wikipedia.org/wiki/Permuted_congruential_generator 2479 func (prng *PRNG) ReadUint32PCGWithReseed(b []byte) (l int, err error) { 2480 l = len(b) 2481 s := (uintptr)((unsafe.Pointer)(&b[0])) 2482 p := s 2483 e := s + uintptr(l) 2484 { 2485 pcgStateTemp := prng.pcgState 2486 for f := e - 4; p <= f; p += 4 { 2487 x := pcgStateTemp 2488 count := int(x >> 59) 2489 pcgStateTemp = x*pcgMultiplier + pcgIncrement 2490 x ^= x >> 18 2491 *(*uint32)((unsafe.Pointer)(p)) = rotateRight32(uint32(x>>27), count) 2492 if p&0xff < 4 { 2493 continue 2494 } 2495 pcgStateTemp = xorShift64(pcgStateTemp^primeNumber64bit0)<<1 + 1 2496 } 2497 prng.pcgState = pcgStateTemp 2498 } 2499 2500 if e-p == 0 { 2501 return 2502 } 2503 rest := prng.Uint32PCG() 2504 if e-p >= 2 { 2505 *(*uint16)((unsafe.Pointer)(p)) = uint16(rest) 2506 rest >>= 16 2507 p += 2 2508 } 2509 if e-p >= 1 { 2510 *(*uint8)((unsafe.Pointer)(p)) = uint8(rest) 2511 } 2512 return 2513 } 2514 2515 // XORReadUint32PCGWithReseed XORs argument "b" with a pseudo-random value. 2516 // The result is the same (but faster) as: 2517 // 2518 // x := make([]byte, len(b)) 2519 // mathrand.ReadUint32PCGWithReseed(x) 2520 // for i := range b { 2521 // b[i] ^= x[i] 2522 // } 2523 func (prng *PRNG) XORReadUint32PCGWithReseed(b []byte) (l int, err error) { 2524 l = len(b) 2525 s := (uintptr)((unsafe.Pointer)(&b[0])) 2526 p := s 2527 e := s + uintptr(l) 2528 { 2529 pcgStateTemp := prng.pcgState 2530 for f := e - 4; p <= f; p += 4 { 2531 x := pcgStateTemp 2532 count := int(x >> 59) 2533 pcgStateTemp = x*pcgMultiplier + pcgIncrement 2534 x ^= x >> 18 2535 *(*uint32)((unsafe.Pointer)(p)) ^= rotateRight32(uint32(x>>27), count) 2536 if p&0xff < 4 { 2537 continue 2538 } 2539 pcgStateTemp = xorShift64(pcgStateTemp^primeNumber64bit0)<<1 + 1 2540 } 2541 prng.pcgState = pcgStateTemp 2542 } 2543 2544 if e-p == 0 { 2545 return 2546 } 2547 rest := prng.Uint32PCG() 2548 if e-p >= 2 { 2549 *(*uint16)((unsafe.Pointer)(p)) ^= uint16(rest) 2550 rest >>= 16 2551 p += 2 2552 } 2553 if e-p >= 1 { 2554 *(*uint8)((unsafe.Pointer)(p)) ^= uint8(rest) 2555 } 2556 return 2557 }