-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Random::ISAAC pseudo random number generator #330
Conversation
Enables to select an engine for Random. The Engine may be initialized with a seed and must respond to #next_number Removed Random#srand and other srand methods that don't work anymore (one may seed the Engine instead).
I'm wondering about |
How about adding another overload |
Wow! You are amazing! Seriously! One day @Scidom suggests we add an ISAAC generator, the other day you send a pull request! I really can't tell you how much I appreciate your (all of you) contribution. The speed is OK for now, we can always optimize it later, specially because we have those accurate specs. I'm thinking, maybe instead of having Random have an engine, why not make Random a module that can be included in a random generator implementation? What I don't like about the
But those "unless" solutions seem too complex. Instead, we can do this: # Include this into your random engine. You only need to implement next_int
module Random
def next_float
next_int * (1.0/4294967295.0)
end
def next_int(max : Int)
if x > 0
next_int % x
else
raise ArgumentError.new "incorrect rand value: #{x}"
end
end
# and so on...
end Java almost does this: it has a Random class which by default uses this algorithm, and subclasses must override a next(int bits) method to provide other algorithms. Then there's, for example SecureRandom, which inherits Random. We could do the same as Java, but I think it's cleaner if we use a module so that each Random implementation has its own internal state. Then we can make SecureRandom include Random to share some implementation, as suggested by @rhysd. Then we can have a puts Random.new #=> #<Random::MT19937:0x106503000> I don't think it matters much that What do you think? Oh, @ysbaddaden, also thanks for moving the engines to their particular source files, I was going to do that but you were faster! :-) I'll accept your pull request, which is perfect, and then we can do those changes later. |
Random::ISAAC pseudo random number generator
Oh, I didn't expect the pull request to be merged so quickly! I like your Random module suggestion @asterite. I'll do the changes. Better design, better performance, less indirections: that's a win! |
Great to see that you implemented Isaac @ysbaddaden. A few general remarks in relation to the above thread:
|
As suggested by @Scidom in #329 here comes a Crystal implementation of the ISAAC generator.
I implemented the readable algorithm, since the fast C implementation uses lots of pointers, that don't make much sense in Crystal (I think). I'm not sure how much safer, or less biased, it is compared to MT19937. It's current performance is ~36% slower than MT19937: 0.072s vs 0.046s for 10 million numbers.
Notes:
Random.new/1
which now expects an engine class instead of a seed.srand
methods that were broken —they called the missingRandom#init_by_array
method, which could be made to point to the engine's method (private for now). I'm not sure if they are required.