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)