Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrkn/1066601 to your computer and use it in GitHub Desktop.
Save mrkn/1066601 to your computer and use it in GitHub Desktop.
" Knuth Subtractive Random Number Generator
let s:knuth_random = { 'index': 0, 'state': repeat([0], 56) }
function! s:knuth_random.seed(seed) dict
let l:seed = 161803398 - (a:seed < 0 ? -a:seed : a:seed)
let self.state[55] = l:seed
let [l:i, l:j, l:k] = [0, 0, 1]
for l:i in range(1, 54)
let l:j = (21 * l:i) % 55
let self.state[l:j] = l:k
let l:k = l:seed - l:k
if l:k < 0
let l:k = l:k + 2147483647
endif
let l:seed = self.state[l:j]
endfor
for l:j in range(1, 4)
for l:i in range(1, 55)
let self.state[l:i] = self.state[l:i] - self.state[1 + (l:i + 30) % 55]
if self.state[l:i] < 0
let self.state[l:i] = self.state[l:i] + 2147483647
endif
endfor
endfor
let self.index = 1
endfunction
function! s:knuth_random.next() dict
if self.index >= 56
let self.index = 1
endif
let l:r = self.state[self.index]
if self.index <= 34
let l:r = l:r - self.state[self.index + 21]
else
let l:r = l:r - self.state[self.index - 34]
endif
if l:r < 0
let l:r = l:r + 2147483647
endif
let self.index = self.index + 1
return l:r
endfunction
function! s:_sum(xs)
let memo = 0
for x in a:xs
let memo += x
endfor
return memo
endfunction
function! s:rand_number()
if s:knuth_random.index ==# 0
if filereadable('/dev/urandom')
let randoms = map(
\ split(join(readfile('/dev/urandom', 'b', 4), '\n')[0:3], '\zs'),
\ 'char2nr(v:val)')
else
let randoms = repeat([0], 4)
endif
if has('reltime')
let [sec, usec] = reltime()
else
let [sec, usec] = [localtime(), 0]
endif
let randoms[0] = randoms[0] ^ sec
let randoms[1] = randoms[1] ^ usec
let randoms[2] = randoms[2] ^ getpid()
let seed = s:_sum(randoms)
call s:knuth_random.seed(seed)
endif
return s:knuth_random.next()
endfunction
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment