second rnd sequence

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
multineu
Posts: 22
Joined: Oct 15, 2010 7:29

second rnd sequence

Post by multineu »

Hello guys,
does anyone ever had the need to have a second random sequence? That is the possibility to generalize the randomize and rnd functions with a parameter that indicates the number of the sequence to use.
Thanks
St_W
Posts: 1626
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: second rnd sequence

Post by St_W »

FreeBasic's rtlib uses static variables to maintain the RNG-state internally, so I think it is not possible with the RNG built into FB. However, I'm sure there do exist external RNG libraries that just provide that.

See https://github.com/freebasic/fbc/blob/m ... math_rnd.c for the FB rtlib implementation. You could also use a slightly modified copy of that, which allows maintaining multiple states.

When you don't need reproducible sequences you just can use the RND function everywhere, you don't need two separate generators in that case.
multineu
Posts: 22
Joined: Oct 15, 2010 7:29

Re: second rnd sequence

Post by multineu »

Thankyou for your very precious answer; I will soon take a look at that.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: second rnd sequence

Post by MichaelW »

I'm not sure I understand the question fully, but you can use the randomize seed argument to specify a sequence.

Code: Select all

randomize 1
for i as integer = 1 to 10
    print int(rnd*100);chr(9);
next
randomize 2
for i as integer = 1 to 10
    print int(rnd*100);chr(9);
next
randomize 3
for i as integer = 1 to 10
    print int(rnd*100);chr(9);
next
print
randomize 1
for i as integer = 1 to 10
    print int(rnd*100);chr(9);
next
randomize 2
for i as integer = 1 to 10
    print int(rnd*100);chr(9);
next
randomize 3
for i as integer = 1 to 10
    print int(rnd*100);chr(9);
next
print
sleep

Code: Select all

 47      53      64      98      23      68      47      54      98      99
 86      3       80      47      58      84      23      62      93      3
 45      33      14      79      78      17      62      33      6       89

 47      53      64      98      23      68      47      54      98      99
 86      3       80      47      58      84      23      62      93      3
 45      33      14      79      78      17      62      33      6       89

jevans4949
Posts: 1186
Joined: May 08, 2006 21:58
Location: Crewe, England

Re: second rnd sequence

Post by jevans4949 »

@MichaelW: This is not what the OP is looking for. What he wants is to be able to generate two random number series at the same time. Precisely why, I don't know.

The obvious solution is to modify the static variables of the existing random number generators to arrays of some finite size, and modify the rnd function (renaming it multirnd?) to have an additional parameter specifying the series to be used.
St_W
Posts: 1626
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: second rnd sequence

Post by St_W »

jevans4949 wrote:@MichaelW: This is not what the OP is looking for. What he wants is to be able to generate two random number series at the same time. Precisely why, I don't know.

The obvious solution is to modify the static variables of the existing random number generators to arrays of some finite size, and modify the rnd function (renaming it multirnd?) to have an additional parameter specifying the series to be used.
I don't know why the OP needs that either, but e.g. reproducability of random number sequences in two parallel threads would be a possible use case.

Maintaining multiple states internally would be one solution, another one is to let the user of the function maintain the state. e.g. see the POSIX C rand_r function: http://linux.die.net/man/3/rand_r
You have to pass a pointer to a state variable. That allows an unlimited number of states, but of course the user has to allocate such (a) state variable(s) in that case him/herself. As far as I've seen the current RND implementation isn't thread safe (maybe I missed something?), that would be an additional advantage (if different states, thus different sequences) are used.
jevans4949
Posts: 1186
Joined: May 08, 2006 21:58
Location: Crewe, England

Re: second rnd sequence

Post by jevans4949 »

@St_W: Your suggestion is good, and could also be thread-safe. One would probably want to set up a class for the state variable(s?), with the data specified as private, to discourage VW programmers from poking it.
Imortis
Moderator
Posts: 1924
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: second rnd sequence

Post by Imortis »

I made a RND object a while back which allows you to make multiple sequences by just DIMming an new object:

https://www.dropbox.com/s/wxfyloei38omr ... m.zip?dl=0
multineu
Posts: 22
Joined: Oct 15, 2010 7:29

Re: second rnd sequence

Post by multineu »

Well I make many experiments about spiking neural networks and would like to see the behaviour of two identical nets feeding them with two different random inputs. Of course I cannot limit the sequence after a buffer is fulfilled. If the buffer is done then I cannot see the next evolving of the nets.
I did an object of my own as Imortis did. Thankyou Imortis for your answer and your interesting RND object.

Code: Select all

#define NO_SEQUENCES 10

type pseudo
	dim as ulong s1(NO_SEQUENCES),s2(NO_SEQUENCES),s3(NO_SEQUENCES)
	declare constructor()
	declare sub nextrand(idx as ulong)
	declare function rand01(i as ulong) as single
	declare function rand(i as ulong) as ulong
	declare sub init_all(a as ulong,b as ulong,c as ulong)
	declare sub init(s as ulong,a as ulong,b as ulong,c as ulong)
end type
constructor pseudo()
end constructor
sub pseudo.nextrand(idx as ulong)
	s1(idx) = (((s1(idx) and 4294967294) shl  2) xor (((s1(idx) shl 13) xor s1(idx)) shr 19))
	s2(idx) = (((s2(idx) and 4294967288) shl  4) xor (((s2(idx) shl  2) xor s2(idx)) shr 25))
	s3(idx) = (((s3(idx) and 4294967280) shl 17) xor (((s3(idx) shl  3) xor s3(idx)) shr 11))
	s1(idx) = (((s1(idx) and 4294967294) shl 12) xor (((s1(idx) shl 13) xor s1(idx)) shr 19))
	s2(idx) = (((s2(idx) and 4294967288) shl  4) xor (((s2(idx) shl  2) xor s2(idx)) shr 25))
	s3(idx) = (((s3(idx) and 4294967280) shl 17) xor (((s3(idx) shl  3) xor s3(idx)) shr 11))
	s1(idx) = (((s1(idx) and 4294967294) shl 12) xor (((s1(idx) shl 13) xor s1(idx)) shr 19))
	s2(idx) = (((s2(idx) and 4294967288) shl  4) xor (((s2(idx) shl  2) xor s2(idx)) shr 25))
	s3(idx) = (((s3(idx) and 4294967280) shl 17) xor (((s3(idx) shl  3) xor s3(idx)) shr 11))
end sub
function pseudo.rand01(i as ulong) as single
	dim as ulong r
	r=s1(i) xor s2(i) xor s3(i)
	nextrand(i)
	return cast(single,r) / 4294967295.0
end function
function pseudo.rand(i as ulong) as ulong
	dim as ulong x
	x=s1(i) xor s2(i) xor s3(i)
	nextrand(i)
	return x
end function
sub pseudo.init_all(a as ulong,b as ulong,c as ulong)
	dim as ulong i
	for i=0 to NO_SEQUENCES-1
		s1(i)=a
		s2(i)=b
		s3(i)=c
	next
end sub
sub pseudo.init(s as ulong,a as ulong,b as ulong,c as ulong)
	s1(s)=a
	s2(s)=b
	s3(s)=c
end sub

---------------------8<---------------------8<------------------8<-------------------8<------------------------

' And here it is the .bas using it
#include "pseudo.bi"

screenres 1200,800,32

dim p as pseudo
dim as ulong i,t

for i=0 to NO_SEQUENCES-1
	'random seed of i-th sequence
	p.init(i,i*103278+34543,i,4353*i*i+773453)
next

for t=0 to 100
	for i=0 to NO_SEQUENCES-1
		print using "########### ";p.rand(i);
	next
	sleep
	print
next
Post Reply