I leave it to someone with more insights to comment on the efficiency of nested functions, but this seems at least to be substantially faster:
type State a::Uint64 b::Uint64 aa::Uint64 bb::Uint64 cc::Uint64 RANDSIZL::Int RANDSIZ::Int end function ind(s::State, mm, x) return mm[1 + (x & ((s.RANDSIZ-1)<<3))>>3] end function rngstep(s::State, randrsl, mm, a_mix, m1, m2, r, i) x = mm[m1 + i] s.a = a_mix + mm[m2 + i] mm[m1 + i] = y = ind(s, mm, x) + s.a + s.b randrsl[r + i] = s.b = ind(s, mm, y >> s.RANDSIZL) + x end function isaac64(s::State, randrsl, mm) s.a = s.aa s.cc += 1 s.b = s.bb + s.cc m1 = r = 0 mid = m2 = s.RANDSIZ >> 1 for i = 1:4:mid-2 rngstep(s, randrsl, mm, ~(s.a $ (s.a << 21)), m1, m2, r, i) rngstep(s, randrsl, mm, s.a $ (s.a >> 5), m1, m2, r, i + 1) rngstep(s, randrsl, mm, s.a $ (s.a << 12), m1, m2, r, i + 2) rngstep(s, randrsl, mm, s.a $ (s.a >> 33), m1, m2, r, i + 3) end m2 = 0 r = m1 = s.RANDSIZ >> 1 for i = 1:4:mid-2 rngstep(s, randrsl, mm, ~(s.a $ (s.a << 21)), m1, m2, r, i) rngstep(s, randrsl, mm, s.a $ (s.a >> 5), m1, m2, r, i + 1) rngstep(s, randrsl, mm, s.a $ (s.a << 12), m1, m2, r, i + 2) rngstep(s, randrsl, mm, s.a $ (s.a >> 33), m1, m2, r, i + 3) end s.bb = s.b s.aa = s.a; end macro mix() quote a -= e; f $= h >> 9; h += a b -= f; g $= a << 9; a += b c -= g; h $= b >> 23; b += c d -= h; a $= c << 15; c += d e -= a; b $= d >> 14; d += e f -= b; c $= e << 20; e += f g -= c; d $= f >> 17; f += g h -= d; e $= g << 14; g += h end end function randinit(randrsl, mm, RANDSIZL, RANDSIZ, flag=false) a = b = c = d = e = f = g = h = 0x9e3779b97f4a7c13 for i = 1:4 @mix end for i = 1:8:RANDSIZ if flag a += randrsl[i ] b += randrsl[i+1] c += randrsl[i+2] d += randrsl[i+3] e += randrsl[i+4] f += randrsl[i+5] g += randrsl[i+6] h += randrsl[i+7] end @mix mm[i ] = a mm[i+1] = b mm[i+2] = c mm[i+3] = d mm[i+4] = e mm[i+5] = f mm[i+6] = g mm[i+7] = h end if flag for i = 1:8:RANDSIZ a += mm[i ] b += mm[i+1] c += mm[i+2] d += mm[i+3] e += mm[i+4] f += mm[i+5] g += mm[i+6] h += mm[i+7] @mix mm[i ] = a mm[i+1] = b mm[i+2] = c mm[i+3] = d mm[i+4] = e mm[i+5] = f mm[i+6] = g mm[i+7] = h end end z = 0x0000000000000000 s2 = State(z, z, z, z, z, RANDSIZL, RANDSIZ) isaac64(s2, randrsl, mm) return s2 end function main(randrsl::Vector{Uint64}=Uint64[]) RANDSIZL = 8 RANDSIZ = length(randrsl) if RANDSIZ == 0 RANDSIZ = 256 resize!(randrsl, RANDSIZ) fill!(randrsl, uint64(0)) elseif RANDSIZ % 8 != 0 error("dimension of seeding array must be a factor of 8") end mm = zeros(Uint64, RANDSIZ) s = randinit(randrsl, mm, RANDSIZL, RANDSIZ, true) for i = 1:2 isaac64(s, randrsl, mm) end end function timeit(f, n=10^4) f() t = time() for i = 1:n f() end @printf("avg running time: %llf \n", ((time() -t) / n )) end Den fredagen den 17:e oktober 2014 kl. 22:58:35 UTC+2 skrev alexander maznev: > > I was trying out Julia for the first time and did not seem to find a > CSPRNG available. Below is a port of Isaac64 ( > http://burtleburtle.net/bob/rand/isaacafa.html). My runtime meassurements > seem to be very poor - reading a little bit about Julia prior to trying the > language, and especially looking at the benchmarks I was under the > impression that run times should be relatively comparable with C. Would > appreciate some feedback, thanks. > > > function main(randrsl::Array{Uint64}=Uint64[]) #takes Uint64 array as a > seed > #wrap everything to pass variables into sub-scopes implicitly > function isaac64() > function ind(mm,x) #nesting ind() into rngstep > makes it another 2-3 times slower -! > return mm[int((x & ((RANDSIZ-1)<<3))/8)+1] > end > function rngstep(a_mix,m1,m2,r) > x = mm[m1+i] > a = (a_mix) + mm[m2+i] > mm[m1+i] = y = (ind(mm, x) + a + b) > randrsl[r+i] = b = (ind(mm, y>>RANDSIZL) + x) > i+=1 > end > a=aa; cc+=1; b=bb+cc; x=0x0000000000::Uint64; > m1=r=0;mid=m2=int(RANDSIZ/2); i=1; > while (i < (mid-2)) #do it without pointers > rngstep(~(a$(a<<21)), m1, m2, r) #sub-indexing an array > creates a new object, pass indexes as variables > rngstep(a$(a>>5), m1, m2, r) > rngstep(a$(a<<12), m1, m2, r) > rngstep(a$(a>>33), m1, m2, r) > end > i=1; m2=0; r=m1=(RANDSIZ/2); > while (i<(mid-2)) > rngstep(~(a$(a<<21)),m1, m2, r) > rngstep(a$(a>>5), m1, m2, r) > rngstep(a$(a<<12), m1, m2, r) > rngstep(a$(a>>33), m1, m2, r) > end > bb = b; aa=a; > end > > function randinit(flag=false) > function mix!() > a-=e; f$=h>>9; h+=a; #$ for bitwise xor > b-=f; g$=a<<9; a+=b; #glad they didn't remove semi-columns > c-=g; h$=b>>23; b+=c; > d-=h; a$=c<<15; c+=d; > e-=a; b$=d>>14; d+=e; > f-=b; c$=e<<20; e+=f; > g-=c; d$=f>>17; f+=g; > h-=d; e$=g<<14; g+=h; > end > a=b=c=d=e=f=g=h= 0x9e3779b97f4a7c13::Uint64 > for i in range(1,4) > mix!() > end > for i in range(1,8, int(RANDSIZ/8)) #dividing 256/8 produced a > float > if flag > a+= randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; > d+=randrsl[i+3]; > e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; > h+=randrsl[i+7]; > end > mix!() > mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d; > mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h; > end > if flag > for i in range(1,8, int(RANDSIZ/8)) > a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3]; > e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7]; > mix!() > mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d; > mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h; > end > end > isaac64() > randcnt=RANDSIZ > end > #main scope variables > RANDSIZL=8; RANDSIZ = length(randrsl); #add a function to allow 32byte > input array > if RANDSIZ == 0 > RANDSIZ = 256 > for i in range(1,RANDSIZ) > push!(randrsl, 0) > end #end statement for each conditional > elseif RANDSIZ % 8 != 0 # would have prefered elif > error("dimension of seeding array must be a factor of 8") > end > aa=bb=cc=0x0000000000::Uint64 #really won't take 0::Uint64 ? > mm=Uint64[] > for i in range(1,RANDSIZ) #indexes start with 1 > push!(mm, 0) > end > randinit(true) > for i in range(1,2) > isaac64() > for j in range(1,RANDSIZ) > @printf("%llx",randrsl[j]) #@printf for c string formatting > end > end > end > function timeit(f, n=10^4) > t = time() > for i in range(1,n) > f() > end > @printf("avg running time: %llf \n", ((time() -t) / n )) > end > timeit(main) >