Seems impossible to rnd*(ulongint range)

General FreeBASIC programming questions.
dodicat
Posts: 5828
Joined: Jan 10, 2006 20:30
Location: Scotland

Seems impossible to rnd*(ulongint range)

Postby dodicat » Nov 28, 2016 16:08

-gen gas performs a little better than -gen gcc.

Code: Select all

'max ulongint = 18446744073709551615
screen 19
color 0 ,15
cls
'randomize ,0
locate ,loword(width)-24:print "ulongintrange"
for n as long=1 to 10000000
   Dim As ulongint u=culngint(rnd*18446744073709551615ull) mod 600
   Dim As ulongint v=culngint(rnd*18446744073709551615ull) mod 600
   pset(u,v),0
next
print "Press a key"
sleep
cls
locate ,loword(width)-24:print "ulongintrange/10"
for n as long=1 to 10000000
   Dim As ulongint u=culngint(rnd*18446744073709551615ull/10) mod 600
   Dim As ulongint v=culngint(rnd*18446744073709551615ull/10) mod 600
   pset(u,v),0
next
print "Press a key"

sleep
cls
locate ,loword(width)-24:print "ulongintrange/100"
for n as long=1 to 10000000
   Dim As ulongint u=culngint(rnd*18446744073709551615ull/100) mod 600
   Dim As ulongint v=culngint(rnd*18446744073709551615ull/100) mod 600
   pset(u,v),0
next
print "Press a key"
sleep
cls
locate ,loword(width)-24:print "ulongintrange/1000"
for n as long=1 to 10000000
   Dim As ulongint u=culngint(rnd*18446744073709551615ull/1000) mod 600
   Dim As ulongint v=culngint(rnd*18446744073709551615ull/1000) mod 600
   pset(u,v),0
next

print "Press a key"
sleep
cls
locate ,loword(width)-24:print "ulongintrange/10000"
for n as long=1 to 10000000
   Dim As ulongint u=culngint(rnd*18446744073709551615ull/10000) mod 600
   Dim As ulongint v=culngint(rnd*18446744073709551615ull/10000) mod 600
   pset(u,v),0
next
print "done"
sleep
 
srvaldez
Posts: 2007
Joined: Sep 25, 2005 21:54

Re: Seems impossible to rnd*(ulongint range)

Postby srvaldez » Nov 28, 2016 21:48

hello dodicat
was searching for random number generator and found this https://groups.google.com/forum/#!msg/c ... 8KGZZFJx4J
but for the life of me can't get the macros to work in FB

Code: Select all

dim shared x as ulongint = 1234567890987654321ull
dim shared c as ulongint = 123456123456123456ull
dim shared y as ulongint = 362436362436362436ull
dim shared z as ulongint = 1066149217761810ull
dim shared t as ulongint

#macro MWC
   scope
      t = (x shl 58) + c
      c = x shr 6
      x += t
      c += -(x < t)
      x
   end scope
#endmacro
#macro XSH
   scope
      y xor= y shl 13
      y xor= y shr 17
      y xor= y shl 43
   end scope
#endmacro
#define CNG scope : z = (6906969069ll * z) + 1234567 : end scope
#define KISS ((MWC + XSH) + CNG)

but here's the code without macros, perhaps you may find it useful

Code: Select all

dim shared x as ulongint = 1234567890987654321ull
dim shared c as ulongint = 123456123456123456ull
dim shared y as ulongint = 362436362436362436ull
dim shared z as ulongint = 1066149217761810ull
dim shared t as ulongint

dim as integer i
for i=0 to 100000000-1
   t = (x shl 58) + c:c = x shr 6:x += t:c += -(x < t):y xor= y shl 13:y xor= y shr 17:y xor= y shl 43:z = (6906969069ll * z) + 1234567
   t=x+y+z
next
if t=1666297717051644203ULL then
   print "100 million uses of KISS OK"
else
   print "Fail"
end if

sleep
dodicat
Posts: 5828
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Seems impossible to rnd*(ulongint range)

Postby dodicat » Nov 29, 2016 1:05

Thanks srvaldez.
I was wanting very large random ulongint primes.

However, in FreeBASIC the road is hardly ever straight.
srvaldez
Posts: 2007
Joined: Sep 25, 2005 21:54

Re: Seems impossible to rnd*(ulongint range)

Postby srvaldez » Nov 29, 2016 23:35

hi dodicat
the code I referenced above can easily be converted to function, included is your test from earlier.

Code: Select all

function kiss() as ulongint
   static x as ulongint = 1234567890987654321ull
   static c as ulongint = 123456123456123456ull
   static y as ulongint = 362436362436362436ull
   static z as ulongint = 1066149217761810ull
   static t as ulongint
   
   t = ((x shl 58) + c)
   c = (x shr 6)
   x += t
   c += (-(x < t))
   
   y xor= (y shl 13)
   y xor= (y shr 17)
   y xor= (y shl 43)
   
   z = ((6906969069ll * z) + 1234567)
   t=x+y+z
   return t
end function

 #define Intrange(f,l) int(kiss*(((l)+1)-(f))+(f))
 
 function range(f as ulongint,l as ulongint) as ulongint
    return int(kiss*(l+1-f)+f) 
 end function
dim as long z
 do
z+=1

randomize z
  Dim As ulongint u = IntRange(1844674407370955161ull,18446744073709551613ull)
randomize z 
  Dim As ulongint v = Range(1844674407370955161ull,18446744073709551613ull)
  print u,v
  sleep
loop until inkey=chr(27)
dodicat
Posts: 5828
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Seems impossible to rnd*(ulongint range)

Postby dodicat » Dec 02, 2016 21:01

srvaldez:
Thanks.
For ranges at the top end of ulongint:

Your kiss function returns an answer outside the range required., both gas and gcc.
rnd with -gen gas returns an answer in the range.
rnd with -gen gcc seems broken at the top end of ulongint.

Code: Select all

function kiss() as ulongint
   static x as ulongint = 1234567890987654321ull
   static c as ulongint = 123456123456123456ull
   static y as ulongint = 362436362436362436ull
   static z as ulongint = 1066149217761810ull
   static t as ulongint
   
   t = ((x shl 58) + c)
   c = (x shr 6)
   x += t
   c += (-(x < t))
   
   y xor= (y shl 13)
   y xor= (y shr 17)
   y xor= (y shl 43)
   
   z = ((6906969069ll * z) + 1234567)
   t=x+y+z
   return t
end function


 function intrange(f as ulongint,l as ulongint) as ulongint
    return int(rnd*(l+1-f)+f)
 end function
 
 function range(f as ulongint,l as ulongint) as ulongint
    return int(kiss*(l+1-f)+f) 
 end function

 do

print 18446744073709551000ull;"   to";tab(29);18446744073709551613ull;tab(60);"<------ range required"

  Dim As ulongint u =  intRange(18446744073709551000ull,18446744073709551613ull)

  Dim As ulongint v =     Range(18446744073709551000ull,18446744073709551613ull)

  print tab(29);u;tab(60);"<-----  rnd"
  print tab(29);v;tab(60);"<-----  kiss"
  print
  sleep
loop until inkey=chr(27)

screen 19
color 0 ,15
cls
'randomize ,0
locate ,loword(width)-24:print "ulongint range"
for n as long=1 to 10000000
   Dim As ulongint u=(intRange(18446744073709551000ull,18446744073709551613ull)) mod 600
   Dim As ulongint v=(intRange(18446744073709551000ull,18446744073709551613ull)) mod 600
   pset(u,v),0
next
print "Press a key"
sleep
 
srvaldez
Posts: 2007
Joined: Sep 25, 2005 21:54

Re: Seems impossible to rnd*(ulongint range)

Postby srvaldez » Dec 02, 2016 21:20

hi dodicat
yes, the kiss function ceartingly needs tweaking.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Seems impossible to rnd*(ulongint range)

Postby MichaelW » Dec 03, 2016 2:58

There is (64-bit, Windows only) code here that will return a 64-bit cryptographic random number, hardware-generated if the CPU supports the RDRAND instruction, or otherwise generated by the default Cryptographic Service Provider.

I forgot to add that the function is relatively slow when returning random numbers from the CSP at the rate of one random number per CSP call. The problem can be effectively corrected by coding the function to maintain a buffer of perhaps 100 elements, calling the CSP as necessary to replenish the buffer.

Return to “General”

Who is online

Users browsing this forum: Google [Bot], Linuxbob and 4 guests