I need random data for an audio processing app and would like to have better performance than what random.InRange (or Gaussian) delivers. Is there any way to achieve this on macOS? (In this case please without plugin solutions, but declares or links to API functions are of course ok.)
I’ve used the method described by Wichmann and Hill:
I’ve got Xojo code for it that I can provide, but the algorithm is so simple that the code should be fairly obvious.
Thank you! The quality of the randomity is much less important to me than performance. What I need is basically noise. Is your algorithm noticeably faster than Xojos Random class?
I was just heading off to bed, but then I remembered where I filed the algorithm. Here it is:
Public Function Rnd3() as Double
//A random number generator based on
//Wichmann and Hill, per their 2005 paper: Generating good pseudo-random numbers
// Generates 2^121 numbers before repeating. Variables iw, ix, iy, iz are Int64 properties that hold their last
// value between calls to this routine.
Dim temp As Double
ix = ix * 11600 mod 2147483579
iy = iy * 47003 mod 2147483543
iz = iz * 23000 mod 2147483423
iw = iw * 33000 mod 2147483123
temp = ix/2147483579.0 + iy/2147483543.0+iz/2147483423.0 + iw/2147483123.0
I’ll let you test it out to see if it’s any faster. I suspect that it won’t be faster than anything built in to Xojo, but you never know. It’s definitely more random though.
It returns a type double value between 0 and 1.
Here is the older 1982 version which is probably a bit faster because there are only 3 cycles:
Public Function Rnd2() as Double
// A random number generator based on
// Wichmann and Hill, Algorithm AS 183:
// 'An Efficient and Portable Pseudo-Random Number Generator',
// Applied Statistics, 31, 188-190, 1982
// According to authors, more than 10^13 numbers will be generated before repetition
Dim temp As Double
ix=ix*171 mod 30269
iy=iy*172 mod 30307
iz=iz*170 mod 30323
temp = ix/30269.0 + iy/30307.0 + iz/30323.0
Thank you, Robert! Good to have it, but its a bit slower than Random.
Well, I found this one which is remarkably fast:
and declaring into kernels random function is also slower than Random, so I guess Ill let it be the way it is. If this feature should be too slow, I can always use a piece of pre-calculated noise.
Have a look at the man page for arc4random_buf.
The benefit is that you can use just one call to fill a whole buffer with random data.
It should be fast.
Have you looked at the Crypto methods? I believe theres a random data generator in there.
You know: You can spend years with Xojo and still discover new things installed years ago.
I am currently testing arc4random_buf which in terms of speed compares to the other wave creation methods I am using with Accelerate framework (Yes, not much time left until end of October). Ill test it against Crypto later.
arc4random beats Crypto by numbers. Forgive the pun.
Just curious since I used arc4random_buf not in Xojo:
Can you share code (declares) and times in relation to other random number creation methods?
Public Sub FillWithUint32Random(Buffer as memoryblock)
Declare Sub arc4random_buf Lib "/usr/lib/libobjc.dylib" (buffer as ptr, size as UInteger)
(not sure if the lib is the best way to address the function, but it works.)
Currently I do only have “benchmarks” taken from the sound editor I am working on, so there are other aspects which can be taken into account.
Pure Xojo code takes 0.06 s to calculate 44100 Gaussian random double values into a memory block.
Crypto.GenerateRandomBytes + a few adjustments done via Accelerate to obtain double values use 0.006 s, so only 10%. Nice!
arc4random_buf + the same adjustments “burns” 0.00034 s processing time for the same task. Around 0.6%. Amazing!
And additionally: Using arc4random_uniform instead of Random.inRange + the necessary Accelerate adjustments makes the code run in 0.02 s, so about 1/3rd of the pure Xojo time.
It should be noted that the distribution profiles of both arc4random functions look much more random than the Random.InRange results.
Many years ago I read about a simple random number generator that started with an N digit seed value. To get the next value:
Square the previous value to get a 2N digit number, then take the middle N digits of this result as the new random number. In Xojo code it would be:
Public Function Rnd4() as UInt32 // Mid-Square pseudorandom number generator Static r As Uint64 = 123456789 'seed value r=Bitwise.ShiftRight(r*r,16) AND &hFFFFFFFF return r End Function
I have no idea how it would compare speed-wise.
Maybe worth a try: SQLite’s randomblob(N) function.