Yes that's much better, I did a similar rewrite last night. Would be glad
to hear on the nested functions from someone that's worked with the
compiler.
-----
Another curious thing I noticed about the loops is that incrementing i in a
scoped function. i.e.
function rngstep()
#do stuff
i+=1
end
or alternatively
function rngstep()
#do stuff
return 1; end
i += rngstep()
both take about 6-7 times longer than a loop with a non-scoped increment.
On Saturday, October 18, 2014 1:31:25 PM UTC-4, Gunnar Farnebäck wrote:
>
> 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)
>>
>