algorithm.mx raw

   1  package runtime
   2  
   3  // This file implements various core algorithms used in the runtime package and
   4  // standard library.
   5  
   6  import (
   7  	"unsafe"
   8  )
   9  
  10  // This function is needed by math/rand since Go 1.20.
  11  // See: https://github.com/golang/go/issues/54880
  12  //
  13  //go:linkname rand_fastrand64 math/rand.fastrand64
  14  func rand_fastrand64() uint64 {
  15  	return fastrand64()
  16  }
  17  
  18  // This function is used by hash/maphash.
  19  // This function isn't required anymore since Go 1.22, so should be removed once
  20  // that becomes the minimum requirement.
  21  func fastrand() uint32 {
  22  	xorshift32State = xorshift32(xorshift32State)
  23  	return xorshift32State
  24  }
  25  
  26  func initRand() {
  27  	r, _ := hardwareRand()
  28  	xorshift64State = uint64(r | 1) // protect against 0
  29  	xorshift32State = uint32(xorshift64State)
  30  }
  31  
  32  var xorshift32State uint32 = 1
  33  
  34  func xorshift32(x uint32) uint32 {
  35  	// Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs".
  36  	// Improved sequence based on
  37  	// http://www.iro.umontreal.ca/~lecuyer/myftp/papers/xorshift.pdf
  38  	x ^= x << 7
  39  	x ^= x >> 1
  40  	x ^= x << 9
  41  	return x
  42  }
  43  
  44  // This function is used by hash/maphash.
  45  // This function isn't required anymore since Go 1.22, so should be removed once
  46  // that becomes the minimum requirement.
  47  func fastrand64() uint64 {
  48  	xorshift64State = xorshiftMult64(xorshift64State)
  49  	return xorshift64State
  50  }
  51  
  52  var xorshift64State uint64 = 1
  53  
  54  // 64-bit xorshift multiply rng from http://vigna.di.unimi.it/ftp/papers/xorshift.pdf
  55  func xorshiftMult64(x uint64) uint64 {
  56  	x ^= x >> 12 // a
  57  	x ^= x << 25 // b
  58  	x ^= x >> 27 // c
  59  	return x * 2685821657736338717
  60  }
  61  
  62  // This function is used by hash/maphash.
  63  func memhash(p unsafe.Pointer, seed, s uintptr) uintptr {
  64  	if unsafe.Sizeof(uintptr(0)) > 4 {
  65  		return uintptr(hash64(p, s, seed))
  66  	}
  67  	return uintptr(hash32(p, s, seed))
  68  }
  69  
  70  // Function that's called from various packages starting with Go 1.22.
  71  func rand() uint64 {
  72  	// Return a random number from hardware, falling back to software if
  73  	// unavailable.
  74  	n, ok := hardwareRand()
  75  	if !ok {
  76  		// Fallback to static random number.
  77  		// Not great, but we can't do much better than this.
  78  		n = fastrand64()
  79  	}
  80  	return n
  81  }
  82