random.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. package tools
  2. import (
  3. "encoding/binary"
  4. "github.com/Dreamacro/clash/common/pool"
  5. )
  6. // XorShift128Plus - a pseudorandom number generator
  7. type XorShift128Plus struct {
  8. s [2]uint64
  9. }
  10. func (r *XorShift128Plus) Next() uint64 {
  11. x := r.s[0]
  12. y := r.s[1]
  13. r.s[0] = y
  14. x ^= x << 23
  15. x ^= y ^ (x >> 17) ^ (y >> 26)
  16. r.s[1] = x
  17. return x + y
  18. }
  19. func (r *XorShift128Plus) InitFromBin(bin []byte) {
  20. var full []byte
  21. if len(bin) < 16 {
  22. full := pool.Get(16)[:0]
  23. defer pool.Put(full)
  24. full = append(full, bin...)
  25. for len(full) < 16 {
  26. full = append(full, 0)
  27. }
  28. } else {
  29. full = bin
  30. }
  31. r.s[0] = binary.LittleEndian.Uint64(full[:8])
  32. r.s[1] = binary.LittleEndian.Uint64(full[8:16])
  33. }
  34. func (r *XorShift128Plus) InitFromBinAndLength(bin []byte, length int) {
  35. var full []byte
  36. if len(bin) < 16 {
  37. full := pool.Get(16)[:0]
  38. defer pool.Put(full)
  39. full = append(full, bin...)
  40. for len(full) < 16 {
  41. full = append(full, 0)
  42. }
  43. }
  44. full = bin
  45. binary.LittleEndian.PutUint16(full, uint16(length))
  46. r.s[0] = binary.LittleEndian.Uint64(full[:8])
  47. r.s[1] = binary.LittleEndian.Uint64(full[8:16])
  48. for i := 0; i < 4; i++ {
  49. r.Next()
  50. }
  51. }