IF you have been here before THEN GOTO post #4 for another idea (Needs PB9 and/or CC5)
RND2 is simply John Gleason's rndExt function introduced at post #6 in Walter Henn's Random Number (RND) Problem thread here with some functionality similar to PB's RND.
RND2 is a bit cheeky but not carved in stone, is it?
Blue text use following indicates a macro name.
Simplest form: Print RND2 or x = RND2. This is equivalent to RND's floating point mode. As with RND a default sequence is used and with no argument generates the next number in sequence. This is also true if RND has a positive argument but not so for RND2 - a positive argument has a different role, covered later in ToggleScope.
With RND we have one sequence and a user seed determines a starting position in that sequence. With RND2 we have a multiplier which sets up a unique sequence and two user seeds determine where in that sequence we start from.
To ensure a different starting position with RND we could use Randomize (same as Randomize Timer). Recently, John Gleason sent me a large batch of multipliers and I have used the 384 largest for RND2. The period for the method used here is dependent upon the multiplier and the multipliers used are greater than the one used with rndExt. The two user seeds may not be any old seeds and must adhere to rules but they are not that restrictive. To make life simple RND2 uses default seeds and to ensure a different start RND2 firstly chooses one of the 384 multipliers at random. The first seed is then 'shuffled' by making use of the Time Stamp Counter. The chosen multiplier, 'shuffled' first seed and default second seed are then fed into the generator. This further 'shuffles' the first seed and 'shuffles' the second seed.
To achieve this we simply use the macro Randomise ie 's' instead of 'z'.
Notice that we do not have 'Randomise n' where n is a numeric expression. RND fixes a multiplier, it is assumed, and varies the seed. The above tack, which does make life easier, fixes the seeds, initially, and varies the multiplier.
The generator has a period close to 2^63. It is used more than once in RND2, as it is in rndExt, thus reducing the effective period which is about 2^61. On my machine RND's sequence in a tight loop will be used up in about 330 seconds. If RND2 were as fast as RND its sequence would be used up in about 5617 years. It is not as fast so you may need to change the motherboard's battery.
The default seed for RND can be duplicated by Randomize Cvs(Chr$(255,255,255,255)). With RND2 we use the macro DefaultSequence. This simply uses the two default seeds, mentioned above, and the largest multiplier from our list of 384.
RND has a special effects mode. RND(0) repeats the last number generated and so does RND2(0) and the macro RepeatLastRND2.
If RND has a negative argument then the generator is re-seeded giving then a fixed sequence or, rather, a fixed starting point. For example, Print RND(-123) which, of course, is effectively the same as Randomize -123: Print RND. We do not have a 'Randomise n' but we do have access to 384 multipliers and we get to them via RandomiseInt(n) with n = 1,2,...,384. The 'Int' is to remind us an integer parameter is required.
In general, re-seeding may lead to sequence overlapping and should then be avoided. However, if we are comparing two algorithms, for example, then having them 'fed' with the same sequence may be desirable.
With RND we can re-seed from a random position. For example, t = Timer: Randomize t. Later we can 'Randomize t' again.
With RND2 we use RepeatLastSequence.
In practice we could have something like the following pseudo code:
With the fixed sequence approach we would use a RandomiseInt(n) twice but the second instance could be replaced with RepeatLastSequence. RepeatLastSequence then works with both fixed starting positions and random starting positions.
Whilst in this vein there is a final command which does not have a RND equivalent. Suppose we have some initialization code which makes use of random numbers and we then want to consider two algorithms. The first part would probably need to be random but the two algorithms may be better tested with the same sequence. To this end Bookmark can be used just prior to algorithm 1 to capture the chosen multiplier and the two current user seeds. To return to the bookmark just prior to algorithm 2 we can use either GotoBookmark or RepeatLastSequence - they are identical in execution.
Pseudo code example:
With the exception of RepeatLastRND2 all of the above commands return either false if no error or true in the event of an error.
ToggleScope is also a departure from RND. RND2's default scope is, as with RND, [0,1). Numbers generated after the first use of ToggleScope fall in the range (0,1), and back to [0,1] when invoked again. This additional scope was introduced by John Gleason in RndExt. However, in RndExt the generator is used to assign the sign which, obviously, has an effect on the period. More importantly, care would have to be taken when using ToggleScope and RepeatLastSequence else we lose synchronisation. Both of these issues can be eliminated by giving ToggleScope its own generator. It also has its own set of multipliers apart rom the 384 already used and the sequence is set up in exactly the same way as Randomise. ToggleScope is the macro for RND2 with a positive parameter.
RND's Integer Range mode, RND(a,b) is replicated with RND2 as RND2(a,b).
How fast?
On my machine 10,000,000 iterations of RND take about 321 milliseconds. RND2 takes about 587ms and with the enhanced scope takes about 637ms. With all the bells and whistles stripped out of RND2, number generation and nothing else, we are looking at about 460ms. On the one hand this shows how fast the generator is but, on the other hand, it shows how fast RND is - it still has the bells and whistles.
The function RND2 is in post #2 and PBMAIN gives it a little work out.
In this particular case nothing much is gained by the new compilers so the code is left as compiled with PBCC4.
Final comment: Thanks John.
RND2 is simply John Gleason's rndExt function introduced at post #6 in Walter Henn's Random Number (RND) Problem thread here with some functionality similar to PB's RND.
RND2 is a bit cheeky but not carved in stone, is it?

Blue text use following indicates a macro name.
Simplest form: Print RND2 or x = RND2. This is equivalent to RND's floating point mode. As with RND a default sequence is used and with no argument generates the next number in sequence. This is also true if RND has a positive argument but not so for RND2 - a positive argument has a different role, covered later in ToggleScope.
With RND we have one sequence and a user seed determines a starting position in that sequence. With RND2 we have a multiplier which sets up a unique sequence and two user seeds determine where in that sequence we start from.
To ensure a different starting position with RND we could use Randomize (same as Randomize Timer). Recently, John Gleason sent me a large batch of multipliers and I have used the 384 largest for RND2. The period for the method used here is dependent upon the multiplier and the multipliers used are greater than the one used with rndExt. The two user seeds may not be any old seeds and must adhere to rules but they are not that restrictive. To make life simple RND2 uses default seeds and to ensure a different start RND2 firstly chooses one of the 384 multipliers at random. The first seed is then 'shuffled' by making use of the Time Stamp Counter. The chosen multiplier, 'shuffled' first seed and default second seed are then fed into the generator. This further 'shuffles' the first seed and 'shuffles' the second seed.
To achieve this we simply use the macro Randomise ie 's' instead of 'z'.
Notice that we do not have 'Randomise n' where n is a numeric expression. RND fixes a multiplier, it is assumed, and varies the seed. The above tack, which does make life easier, fixes the seeds, initially, and varies the multiplier.
The generator has a period close to 2^63. It is used more than once in RND2, as it is in rndExt, thus reducing the effective period which is about 2^61. On my machine RND's sequence in a tight loop will be used up in about 330 seconds. If RND2 were as fast as RND its sequence would be used up in about 5617 years. It is not as fast so you may need to change the motherboard's battery.

The default seed for RND can be duplicated by Randomize Cvs(Chr$(255,255,255,255)). With RND2 we use the macro DefaultSequence. This simply uses the two default seeds, mentioned above, and the largest multiplier from our list of 384.
RND has a special effects mode. RND(0) repeats the last number generated and so does RND2(0) and the macro RepeatLastRND2.
If RND has a negative argument then the generator is re-seeded giving then a fixed sequence or, rather, a fixed starting point. For example, Print RND(-123) which, of course, is effectively the same as Randomize -123: Print RND. We do not have a 'Randomise n' but we do have access to 384 multipliers and we get to them via RandomiseInt(n) with n = 1,2,...,384. The 'Int' is to remind us an integer parameter is required.
In general, re-seeding may lead to sequence overlapping and should then be avoided. However, if we are comparing two algorithms, for example, then having them 'fed' with the same sequence may be desirable.
With RND we can re-seed from a random position. For example, t = Timer: Randomize t. Later we can 'Randomize t' again.
With RND2 we use RepeatLastSequence.
In practice we could have something like the following pseudo code:
Code:
RND RND2 t = Timer Randomize t Randomise Execute algorithm 1 Execute algorithm 1 Randomize t RepeatLastSequence Execute algorithm 2 Execute algorithm 2
Whilst in this vein there is a final command which does not have a RND equivalent. Suppose we have some initialization code which makes use of random numbers and we then want to consider two algorithms. The first part would probably need to be random but the two algorithms may be better tested with the same sequence. To this end Bookmark can be used just prior to algorithm 1 to capture the chosen multiplier and the two current user seeds. To return to the bookmark just prior to algorithm 2 we can use either GotoBookmark or RepeatLastSequence - they are identical in execution.
Pseudo code example:
Code:
Randomise Initialize Bookmark Execute algorithm 1 GotoBookmark ( or RepeatLastSequence ) Execute algorithm 2
ToggleScope is also a departure from RND. RND2's default scope is, as with RND, [0,1). Numbers generated after the first use of ToggleScope fall in the range (0,1), and back to [0,1] when invoked again. This additional scope was introduced by John Gleason in RndExt. However, in RndExt the generator is used to assign the sign which, obviously, has an effect on the period. More importantly, care would have to be taken when using ToggleScope and RepeatLastSequence else we lose synchronisation. Both of these issues can be eliminated by giving ToggleScope its own generator. It also has its own set of multipliers apart rom the 384 already used and the sequence is set up in exactly the same way as Randomise. ToggleScope is the macro for RND2 with a positive parameter.
RND's Integer Range mode, RND(a,b) is replicated with RND2 as RND2(a,b).
How fast?
On my machine 10,000,000 iterations of RND take about 321 milliseconds. RND2 takes about 587ms and with the enhanced scope takes about 637ms. With all the bells and whistles stripped out of RND2, number generation and nothing else, we are looking at about 460ms. On the one hand this shows how fast the generator is but, on the other hand, it shows how fast RND is - it still has the bells and whistles.

The function RND2 is in post #2 and PBMAIN gives it a little work out.
In this particular case nothing much is gained by the new compilers so the code is left as compiled with PBCC4.
Final comment: Thanks John.

Comment