github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/algorithm.go (about)

     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  var xorshift32State uint32 = 1
    27  
    28  func xorshift32(x uint32) uint32 {
    29  	// Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs".
    30  	// Improved sequence based on
    31  	// http://www.iro.umontreal.ca/~lecuyer/myftp/papers/xorshift.pdf
    32  	x ^= x << 7
    33  	x ^= x >> 1
    34  	x ^= x << 9
    35  	return x
    36  }
    37  
    38  // This function is used by hash/maphash.
    39  // This function isn't required anymore since Go 1.22, so should be removed once
    40  // that becomes the minimum requirement.
    41  func fastrand64() uint64 {
    42  	xorshift64State = xorshiftMult64(xorshift64State)
    43  	return xorshift64State
    44  }
    45  
    46  var xorshift64State uint64 = 1
    47  
    48  // 64-bit xorshift multiply rng from http://vigna.di.unimi.it/ftp/papers/xorshift.pdf
    49  func xorshiftMult64(x uint64) uint64 {
    50  	x ^= x >> 12 // a
    51  	x ^= x << 25 // b
    52  	x ^= x >> 27 // c
    53  	return x * 2685821657736338717
    54  }
    55  
    56  // This function is used by hash/maphash.
    57  func memhash(p unsafe.Pointer, seed, s uintptr) uintptr {
    58  	if unsafe.Sizeof(uintptr(0)) > 4 {
    59  		return uintptr(hash64(p, s, seed))
    60  	}
    61  	return uintptr(hash32(p, s, seed))
    62  }
    63  
    64  // Function that's called from various packages starting with Go 1.22.
    65  func rand() uint64 {
    66  	// Return a random number from hardware, falling back to software if
    67  	// unavailable.
    68  	n, ok := hardwareRand()
    69  	if !ok {
    70  		// Fallback to static random number.
    71  		// Not great, but we can't do much better than this.
    72  		n = fastrand64()
    73  	}
    74  	return n
    75  }