Skip to content

Instantly share code, notes, and snippets.

@ynkdir
Created January 17, 2011 12:42
Show Gist options
  • Save ynkdir/782810 to your computer and use it in GitHub Desktop.
Save ynkdir/782810 to your computer and use it in GitHub Desktop.
glibc rand()
" glibc-2.12.1: random_r.c
let s:RAND_MAX = 2147483647
function! Srand(seed)
call s:srandom_r(a:seed, s:state)
endfunction
function! Rand()
return s:random_r(s:state)
endfunction
" Linear congruential.
let s:TYPE_0 = 0
let s:BREAK_0 = 8
let s:DEG_0 = 0
let s:SEP_0 = 0
" x**7 + x**3 + 1.
let s:TYPE_1 = 1
let s:BREAK_1 = 32
let s:DEG_1 = 7
let s:SEP_1 = 3
" x**15 + x + 1.
let s:TYPE_2 = 2
let s:BREAK_2 = 64
let s:DEG_2 = 15
let s:SEP_2 = 1
" x**31 + x**3 + 1.
let s:TYPE_3 = 3
let s:BREAK_3 = 128
let s:DEG_3 = 31
let s:SEP_3 = 3
" x**63 + x + 1.
let s:TYPE_4 = 4
let s:BREAK_4 = 256
let s:DEG_4 = 63
let s:SEP_4 = 1
let s:MAX_TYPES = 5
let s:randtbl = [
\ s:TYPE_3,
\
\ -1726662223, 379960547, 1735697613, 1040273694, 1313901226,
\ 1627687941, -179304937, -2073333483, 1780058412, -1989503057,
\ -615974602, 344556628, 939512070, -1249116260, 1507946756,
\ -812545463, 154635395, 1388815473, -1926676823, 525320961,
\ -1009028674, 968117788, -123449607, 1284210865, 435012392,
\ -2017506339, -911064859, -370259173, 1132637927, 1398500161,
\ -205601318,
\ ]
let s:state = {
\ 'tbl': s:randtbl,
\ 'fptr': s:SEP_3 + 1,
\ 'rptr': 1,
\ 'state': 1,
\ 'rand_type': s:TYPE_3,
\ 'rand_deg': s:DEG_3,
\ 'rand_sep': s:SEP_3,
\ 'end_ptr': len(s:randtbl),
\ }
function! s:srandom_r(seed, buf)
let type = a:buf.rand_type
let state = a:buf.state
let seed = (a:seed == 0) ? 1 : a:seed
let a:buf.tbl[state] = seed
if type == s:TYPE_0
return
endif
let dst = state
let word = seed
let kc = a:buf.rand_deg
for i in range(kc - 1)
let hi = word / 127773
let lo = word % 127773
let word = 16807 * lo - 2836 * hi
if word < 0
let word += 2147483647
endif
let dst += 1
let a:buf.tbl[dst] = word
endfor
let a:buf.fptr = state + a:buf.rand_sep
let a:buf.rptr = state
let kc = kc * 10
for i in range(kc)
call s:random_r(a:buf)
endfor
endfunction
function! s:random_r(buf)
let state = a:buf.state
if a:buf.rand_type == s:TYPE_0
" val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
let val = (a:buf.tbl[state] * 1103515245) + 12345
if val < 0
let val -= 0x80000000
endif
let a:buf.tbl[state] = val
let result = val
else
let fptr = a:buf.fptr
let rptr = a:buf.rptr
let end_ptr = a:buf.end_ptr
let a:buf.tbl[fptr] += a:buf.tbl[rptr]
let val = a:buf.tbl[fptr]
" result = (val >> 1) & 0x7fffffff
if val < 0
let result = ((val - 0x80000000) / 2) + 0x40000000
else
let result = val / 2
endif
let fptr += 1
if fptr >= end_ptr
let fptr = state
let rptr += 1
else
let rptr += 1
if rptr >= end_ptr
let rptr = state
endif
endif
let a:buf.fptr = fptr
let a:buf.rptr = rptr
endif
return result
endfunction
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment