Seems impossible to rnd*(ulongint range)

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

Seems impossible to rnd*(ulongint range)

Post by dodicat »

-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: 3373
Joined: Sep 25, 2005 21:54

Re: Seems impossible to rnd*(ulongint range)

Post by srvaldez »

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: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Seems impossible to rnd*(ulongint range)

Post by dodicat »

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

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

Re: Seems impossible to rnd*(ulongint range)

Post by srvaldez »

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: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Seems impossible to rnd*(ulongint range)

Post by dodicat »

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: 3373
Joined: Sep 25, 2005 21:54

Re: Seems impossible to rnd*(ulongint range)

Post by srvaldez »

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)

Post by MichaelW »

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.
Post Reply