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)
>>
>

Reply via email to