prng-isaac 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fd8d645800d3a280bb5a18a530c4f16ffb90d916
4
+ data.tar.gz: f5b5184556e7a028239a1f7510cde907d2dae435
5
+ SHA512:
6
+ metadata.gz: 16898f276eb280b6d476252acf75ccf84dc21f257734e7d0facf13a63cd86bd4ea912930927ddacd4b4953aa0b6e09f5cb31935d11f7be06d8f1c247500cd404
7
+ data.tar.gz: 717f2707e46c45b6192e4dfa7244d07c2a23a80c93ec9dabd1cf5ada547b0f5e806f769c0dacccf218fc584bcdaf625b73ca869d35c8dced004a668ef5dd6d37
data/COPYING ADDED
@@ -0,0 +1,3 @@
1
+ The ISAAC implementation is Public Domain, created by Bob Jenkins.
2
+
3
+ The ruby wrapping is by Joel VanderWerf, and all wrapping code distinct from the ISAAC code is also public domain.
data/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # ISAAC #
2
+
3
+ A pseudorandom number generator based on http://burtleburtle.net/bob/rand/isaac.html.
4
+
5
+ Sometimes useful for simulation in place of MT19937 (which ruby's #rand is based on), even though ISAAC's number distribution quality is not as good, because it is faster and the state is lighter, so you can have many of them.
6
+
7
+ This is useful when you need multiple pseudo-random sequences that are _independent_ and _recreatable_.
8
+
9
+ If you care about small state and not cryptographic security, use ISAAC4: the state is about 48 bytes rather then 2K.
data/RELEASE-NOTES ADDED
@@ -0,0 +1,29 @@
1
+ isaac 0.0.5
2
+
3
+ * Classes are in PRNG module.
4
+
5
+ * Added ISAAC4 for simulation (not crypo).
6
+
7
+ * Add unit tests.
8
+
9
+ isaac 0.0.4
10
+
11
+ * Update for ruby 1.9 and 2.0.
12
+
13
+ isaac 0.0.3
14
+
15
+ * Based on Bob Jenkins' comments on ruby-talk, use 256-entry state vectors, rather than 16-entry. Also, some benchmarking (bench/bench.rb) verifies that,
16
+ for long sequences, 256-entry state vectors are slightly faster, so even for simulation there is not much reason to use 16-entry vectors, unless you have a large number of sequences.
17
+
18
+ * Fixed #srand so that it clears the entire state before setting the seed, so
19
+ that an instance can be reset to produce the same sequence. However, #srand no
20
+ longer returns the current state values, since they may differ from the original seed values.
21
+
22
+ isaac 0.0.2
23
+
24
+ * First public release
25
+
26
+ isaac 0.0.1
27
+
28
+ * Working wrapper around Bob Jenkins' ISAAC code.
29
+
data/bench/bench.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'benchmark'
2
+ require 'isaac'
3
+
4
+ include PRNG
5
+
6
+ srand(1) # use ruby's prng to seed isaac
7
+ ary = (0..255).map {rand(2**32-1)}
8
+ r = ISAAC.new
9
+ r.srand(ary)
10
+
11
+ times = Benchmark.measure do
12
+ 1_000_000.times do
13
+ r.rand32
14
+ end
15
+ end
16
+
17
+ puts times
18
+
19
+ __END__
20
+
21
+ Times to generate 1_000_000 numbers:
22
+
23
+ With 256 entry state vectors (crypto):
24
+ 1.860000 0.200000 2.060000 ( 2.185345) # 2005 ThinkPad
25
+ 0.780000 0.000000 0.780000 ( 0.782771) # 2008 Eee901
26
+
27
+ With 16 entry state vectors (ok for simulation):
28
+ 1.900000 0.200000 2.100000 ( 2.224832) # 2005 ThinkPad
29
+ 0.940000 0.000000 0.940000 ( 0.947986) # 2008 Eee901
30
+
@@ -0,0 +1,236 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ # V=0 quiet, V=1 verbose. other values don't work.
5
+ V = 0
6
+ Q1 = $(V:1=)
7
+ Q = $(Q1:0=@)
8
+ ECHO1 = $(V:1=@:)
9
+ ECHO = $(ECHO1:0=@echo)
10
+
11
+ #### Start of system configuration section. ####
12
+
13
+ srcdir = .
14
+ topdir = $(includedir)/$(RUBY_VERSION_NAME)
15
+ hdrdir = $(includedir)/$(RUBY_VERSION_NAME)
16
+ arch_hdrdir = $(rubyhdrdir)/$(arch)
17
+ PATH_SEPARATOR = :
18
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
19
+ prefix = $(DESTDIR)/usr/local
20
+ rubysitearchprefix = $(rubylibprefix)/$(sitearch)
21
+ rubyarchprefix = $(rubylibprefix)/$(arch)
22
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
23
+ exec_prefix = $(prefix)
24
+ vendorarchhdrdir = $(vendorhdrdir)/$(sitearch)
25
+ sitearchhdrdir = $(sitehdrdir)/$(sitearch)
26
+ rubyarchhdrdir = $(rubyhdrdir)/$(arch)
27
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
28
+ sitehdrdir = $(rubyhdrdir)/site_ruby
29
+ rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME)
30
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
31
+ vendorlibdir = $(vendordir)/$(ruby_version)
32
+ vendordir = $(rubylibprefix)/vendor_ruby
33
+ sitearchdir = $(sitelibdir)/$(sitearch)
34
+ sitelibdir = $(sitedir)/$(ruby_version)
35
+ sitedir = $(rubylibprefix)/site_ruby
36
+ rubyarchdir = $(rubylibdir)/$(arch)
37
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
38
+ sitearchincludedir = $(includedir)/$(sitearch)
39
+ archincludedir = $(includedir)/$(arch)
40
+ sitearchlibdir = $(libdir)/$(sitearch)
41
+ archlibdir = $(libdir)/$(arch)
42
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
43
+ mandir = $(datarootdir)/man
44
+ localedir = $(datarootdir)/locale
45
+ libdir = $(exec_prefix)/lib
46
+ psdir = $(docdir)
47
+ pdfdir = $(docdir)
48
+ dvidir = $(docdir)
49
+ htmldir = $(docdir)
50
+ infodir = $(datarootdir)/info
51
+ docdir = $(datarootdir)/doc/$(PACKAGE)
52
+ oldincludedir = $(DESTDIR)/usr/include
53
+ includedir = $(prefix)/include
54
+ localstatedir = $(prefix)/var
55
+ sharedstatedir = $(prefix)/com
56
+ sysconfdir = $(prefix)/etc
57
+ datadir = $(datarootdir)
58
+ datarootdir = $(prefix)/share
59
+ libexecdir = $(exec_prefix)/libexec
60
+ sbindir = $(exec_prefix)/sbin
61
+ bindir = $(exec_prefix)/bin
62
+ archdir = $(rubyarchdir)
63
+
64
+
65
+ CC = gcc
66
+ CXX = g++
67
+ LIBRUBY = $(LIBRUBY_A)
68
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
69
+ LIBRUBYARG_SHARED = -Wl,-R -Wl,$(libdir) -L$(libdir)
70
+ LIBRUBYARG_STATIC = -Wl,-R -Wl,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static
71
+ empty =
72
+ OUTFLAG = -o $(empty)
73
+ COUTFLAG = -o $(empty)
74
+
75
+ RUBY_EXTCONF_H =
76
+ cflags = $(optflags) $(debugflags) $(warnflags)
77
+ optflags = -O3 -fno-fast-math
78
+ debugflags = -ggdb3
79
+ warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration
80
+ CFLAGS = -fPIC $(cflags) $(ARCH_FLAG)
81
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
82
+ DEFS =
83
+ CPPFLAGS = $(DEFS) $(cppflags)
84
+ CXXFLAGS = $(CFLAGS) $(cxxflags)
85
+ ldflags = -L. -fstack-protector -rdynamic -Wl,-export-dynamic
86
+ dldflags =
87
+ ARCH_FLAG =
88
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
89
+ LDSHARED = $(CC) -shared
90
+ LDSHAREDXX = $(CXX) -shared
91
+ AR = ar
92
+ EXEEXT =
93
+
94
+ RUBY_INSTALL_NAME = ruby
95
+ RUBY_SO_NAME = ruby
96
+ RUBYW_INSTALL_NAME =
97
+ RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
98
+ RUBYW_BASE_NAME = rubyw
99
+ RUBY_BASE_NAME = ruby
100
+
101
+ arch = x86_64-linux
102
+ sitearch = $(arch)
103
+ ruby_version = 2.0.0
104
+ ruby = $(bindir)/ruby
105
+ RUBY = $(ruby)
106
+ ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
107
+
108
+ RM = rm -f
109
+ RM_RF = $(RUBY) -run -e rm -- -rf
110
+ RMDIRS = rmdir --ignore-fail-on-non-empty -p
111
+ MAKEDIRS = /bin/mkdir -p
112
+ INSTALL = /usr/bin/install -c
113
+ INSTALL_PROG = $(INSTALL) -m 0755
114
+ INSTALL_DATA = $(INSTALL) -m 644
115
+ COPY = cp
116
+ TOUCH = exit >
117
+
118
+ #### End of system configuration section. ####
119
+
120
+ preload =
121
+
122
+ libpath = . $(libdir)
123
+ LIBPATH = -L. -L$(libdir) -Wl,-R$(libdir)
124
+ DEFFILE =
125
+
126
+ CLEANFILES = mkmf.log
127
+ DISTCLEANFILES =
128
+ DISTCLEANDIRS =
129
+
130
+ extout =
131
+ extout_prefix =
132
+ target_prefix =
133
+ LOCAL_LIBS =
134
+ LIBS = -lpthread -lrt -ldl -lcrypt -lm -lc
135
+ ORIG_SRCS = isaac.c rand4.c rand.c
136
+ SRCS = $(ORIG_SRCS)
137
+ OBJS = isaac.o rand4.o rand.o
138
+ HDRS = $(srcdir)/rand4.h $(srcdir)/rand.h
139
+ TARGET = isaac
140
+ TARGET_NAME = isaac
141
+ TARGET_ENTRY = Init_$(TARGET_NAME)
142
+ DLLIB = $(TARGET).so
143
+ EXTSTATIC =
144
+ STATIC_LIB =
145
+
146
+ BINDIR = $(bindir)
147
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
148
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
149
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
150
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
151
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
152
+
153
+ TARGET_SO = $(DLLIB)
154
+ CLEANLIBS = $(TARGET).so
155
+ CLEANOBJS = *.o *.bak
156
+
157
+ all: $(DLLIB)
158
+ static: $(STATIC_LIB)
159
+ .PHONY: all install static install-so install-rb
160
+ .PHONY: clean clean-so clean-static clean-rb
161
+
162
+ clean-static::
163
+ clean-rb-default::
164
+ clean-rb::
165
+ clean-so::
166
+ clean: clean-so clean-static clean-rb-default clean-rb
167
+ -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
168
+
169
+ distclean-rb-default::
170
+ distclean-rb::
171
+ distclean-so::
172
+ distclean-static::
173
+ distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
174
+ -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
175
+ -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
176
+ -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
177
+
178
+ realclean: distclean
179
+ install: install-so install-rb
180
+
181
+ install-so: $(DLLIB) ./.RUBYARCHDIR.time
182
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
183
+ clean-static::
184
+ -$(Q)$(RM) $(STATIC_LIB)
185
+ install-rb: pre-install-rb install-rb-default
186
+ install-rb-default: pre-install-rb-default
187
+ pre-install-rb: Makefile
188
+ pre-install-rb-default: Makefile
189
+ pre-install-rb-default:
190
+ $(ECHO) installing default isaac libraries
191
+ ./.RUBYARCHDIR.time:
192
+ $(Q) $(MAKEDIRS) $(RUBYARCHDIR)
193
+ $(Q) $(TOUCH) $@
194
+
195
+ site-install: site-install-so site-install-rb
196
+ site-install-so: install-so
197
+ site-install-rb: install-rb
198
+
199
+ .SUFFIXES: .c .m .cc .mm .cxx .cpp .C .o
200
+
201
+ .cc.o:
202
+ $(ECHO) compiling $(<)
203
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
204
+
205
+ .mm.o:
206
+ $(ECHO) compiling $(<)
207
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
208
+
209
+ .cxx.o:
210
+ $(ECHO) compiling $(<)
211
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
212
+
213
+ .cpp.o:
214
+ $(ECHO) compiling $(<)
215
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
216
+
217
+ .C.o:
218
+ $(ECHO) compiling $(<)
219
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
220
+
221
+ .c.o:
222
+ $(ECHO) compiling $(<)
223
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
224
+
225
+ .m.o:
226
+ $(ECHO) compiling $(<)
227
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
228
+
229
+ $(DLLIB): $(OBJS) Makefile
230
+ $(ECHO) linking shared-object $(DLLIB)
231
+ -$(Q)$(RM) $(@)
232
+ $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
233
+
234
+
235
+
236
+ $(OBJS): $(HDRS) $(ruby_headers)
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'isaac'
data/ext/isaac/isaac.c ADDED
@@ -0,0 +1,246 @@
1
+ #include "ruby.h"
2
+ #include "rand.h"
3
+ #include "rand4.h"
4
+
5
+ #ifndef min
6
+ # define min(a,b) (((a)<(b)) ? (a) : (b))
7
+ #endif /* min */
8
+
9
+ static VALUE
10
+ ISAAC_s_allocate(VALUE klass)
11
+ {
12
+ randctx *ctx;
13
+
14
+ return Data_Make_Struct(klass, randctx, NULL, NULL, ctx);
15
+ }
16
+
17
+ static VALUE
18
+ ISAAC4_s_allocate(VALUE klass)
19
+ {
20
+ randctx4 *ctx;
21
+
22
+ return Data_Make_Struct(klass, randctx4, NULL, NULL, ctx);
23
+ }
24
+
25
+ /*
26
+ * Seed the generator with an array of up to ISAAC::RANDSIZ integers in the
27
+ * range 0..2**32-1. More entries are ignored. Missing entries are treated
28
+ * as 0. Returns +nil+.
29
+ */
30
+ static VALUE
31
+ ISAAC_srand(VALUE self, VALUE ary)
32
+ {
33
+ int i;
34
+ randctx *ctx;
35
+
36
+ Check_Type(ary, T_ARRAY);
37
+
38
+ Data_Get_Struct(self, randctx, ctx);
39
+
40
+ MEMZERO(ctx, randctx, 1);
41
+ for (i=min(RANDSIZ, RARRAY_LEN(ary))-1; i>=0; i--) {
42
+ ctx->randrsl[i] = NUM2UINT(RARRAY_PTR(ary)[i]);
43
+ }
44
+ isaac_init(ctx, 1);
45
+
46
+ return Qnil;
47
+ }
48
+
49
+ /*
50
+ * Seed the generator with an array of up to ISAAC::RANDSIZ integers in the
51
+ * range 0..2**32-1. More entries are ignored. Missing entries are treated
52
+ * as 0. Returns +nil+.
53
+ */
54
+ static VALUE
55
+ ISAAC4_srand(VALUE self, VALUE ary)
56
+ {
57
+ int i;
58
+ randctx4 *ctx;
59
+
60
+ Check_Type(ary, T_ARRAY);
61
+
62
+ Data_Get_Struct(self, randctx4, ctx);
63
+
64
+ MEMZERO(ctx, randctx4, 1);
65
+ for (i=min(RANDSIZ4, RARRAY_LEN(ary))-1; i>=0; i--) {
66
+ ctx->randrsl[i] = NUM2UINT(RARRAY_PTR(ary)[i]);
67
+ }
68
+ isaac_init4(ctx, 1);
69
+
70
+ return Qnil;
71
+ }
72
+
73
+ /*
74
+ * Return a random integer in the range 0..2**32-1.
75
+ */
76
+ static VALUE
77
+ ISAAC_rand32(VALUE self)
78
+ {
79
+ randctx *ctx;
80
+
81
+ Data_Get_Struct(self, randctx, ctx);
82
+
83
+ if (!ctx->randcnt--) {
84
+ isaac_rand(ctx);
85
+ ctx->randcnt=RANDSIZ-1;
86
+ }
87
+
88
+ return UINT2NUM(ctx->randrsl[ctx->randcnt]);
89
+ }
90
+
91
+ /*
92
+ * Return a random integer in the range 0..2**32-1.
93
+ */
94
+ static VALUE
95
+ ISAAC4_rand32(VALUE self)
96
+ {
97
+ randctx4 *ctx;
98
+
99
+ Data_Get_Struct(self, randctx4, ctx);
100
+
101
+ if (!ctx->randcnt--) {
102
+ isaac_rand4(ctx);
103
+ ctx->randcnt=RANDSIZ4-1;
104
+ }
105
+
106
+ return UINT2NUM(ctx->randrsl[ctx->randcnt]);
107
+ }
108
+
109
+ /*
110
+ * Return a random float in the range 0..1.
111
+ */
112
+ static VALUE
113
+ ISAAC_rand(VALUE self)
114
+ {
115
+ randctx *ctx;
116
+
117
+ Data_Get_Struct(self, randctx, ctx);
118
+
119
+ if (!ctx->randcnt--) {
120
+ isaac_rand(ctx);
121
+ ctx->randcnt=RANDSIZ-1;
122
+ }
123
+
124
+ return rb_float_new(ctx->randrsl[ctx->randcnt] / 4294967295.0);
125
+ }
126
+
127
+ /*
128
+ * Return a random float in the range 0..1.
129
+ */
130
+ static VALUE
131
+ ISAAC4_rand(VALUE self)
132
+ {
133
+ randctx4 *ctx;
134
+
135
+ Data_Get_Struct(self, randctx4, ctx);
136
+
137
+ if (!ctx->randcnt--) {
138
+ isaac_rand4(ctx);
139
+ ctx->randcnt=RANDSIZ4-1;
140
+ }
141
+
142
+ return rb_float_new(ctx->randrsl[ctx->randcnt] / 4294967295.0);
143
+ }
144
+
145
+ static VALUE
146
+ ISAAC_marshal_dump(VALUE self)
147
+ {
148
+ randctx *ctx;
149
+ int i;
150
+ int ary_size = sizeof(randctx)/sizeof(ub4);
151
+ VALUE ary;
152
+
153
+ Data_Get_Struct(self, randctx, ctx);
154
+
155
+ ary = rb_ary_new2(ary_size);
156
+ for (i = 0; i < ary_size; i++) {
157
+ rb_ary_push(ary, UINT2NUM(((ub4 *)ctx)[i]));
158
+ }
159
+
160
+ return ary;
161
+ }
162
+
163
+ static VALUE
164
+ ISAAC4_marshal_dump(VALUE self)
165
+ {
166
+ randctx4 *ctx;
167
+ int i;
168
+ int ary_size = sizeof(randctx4)/sizeof(ub4);
169
+ VALUE ary;
170
+
171
+ Data_Get_Struct(self, randctx4, ctx);
172
+
173
+ ary = rb_ary_new2(ary_size);
174
+ for (i = 0; i < ary_size; i++) {
175
+ rb_ary_push(ary, UINT2NUM(((ub4 *)ctx)[i]));
176
+ }
177
+
178
+ return ary;
179
+ }
180
+
181
+ static VALUE
182
+ ISAAC_marshal_load(VALUE self, VALUE ary)
183
+ {
184
+ randctx *ctx;
185
+ int i;
186
+ int ary_size = sizeof(randctx)/sizeof(ub4);
187
+
188
+ Data_Get_Struct(self, randctx, ctx);
189
+
190
+ if (RARRAY_LEN(ary) != ary_size)
191
+ rb_raise(rb_eArgError, "bad length in loaded ISAAC data");
192
+
193
+ for (i = 0; i < ary_size; i++) {
194
+ ((ub4 *)ctx)[i] = NUM2UINT(RARRAY_PTR(ary)[i]);
195
+ }
196
+
197
+ return self;
198
+ }
199
+
200
+ static VALUE
201
+ ISAAC4_marshal_load(VALUE self, VALUE ary)
202
+ {
203
+ randctx4 *ctx;
204
+ int i;
205
+ int ary_size = sizeof(randctx4)/sizeof(ub4);
206
+
207
+ Data_Get_Struct(self, randctx4, ctx);
208
+
209
+ if (RARRAY_LEN(ary) != ary_size)
210
+ rb_raise(rb_eArgError, "bad length in loaded ISAAC4 data");
211
+
212
+ for (i = 0; i < ary_size; i++) {
213
+ ((ub4 *)ctx)[i] = NUM2UINT(RARRAY_PTR(ary)[i]);
214
+ }
215
+
216
+ return self;
217
+ }
218
+
219
+ void
220
+ Init_isaac()
221
+ {
222
+ VALUE ISAAC;
223
+ VALUE ISAAC4;
224
+ VALUE mPRNG;
225
+
226
+ mPRNG = rb_define_module("PRNG");
227
+ ISAAC = rb_define_class_under(mPRNG, "ISAAC", rb_cObject);
228
+ ISAAC4 = rb_define_class_under(mPRNG, "ISAAC4", rb_cObject);
229
+
230
+ rb_define_alloc_func(ISAAC, ISAAC_s_allocate);
231
+ rb_define_method(ISAAC, "srand", ISAAC_srand, 1);
232
+ rb_define_method(ISAAC, "rand32", ISAAC_rand32, 0);
233
+ rb_define_method(ISAAC, "rand", ISAAC_rand, 0);
234
+ rb_define_method(ISAAC, "marshal_dump", ISAAC_marshal_dump, 0);
235
+ rb_define_method(ISAAC, "marshal_load", ISAAC_marshal_load, 1);
236
+
237
+ rb_define_alloc_func(ISAAC4, ISAAC4_s_allocate);
238
+ rb_define_method(ISAAC4, "srand", ISAAC4_srand, 1);
239
+ rb_define_method(ISAAC4, "rand32", ISAAC4_rand32, 0);
240
+ rb_define_method(ISAAC4, "rand", ISAAC4_rand, 0);
241
+ rb_define_method(ISAAC4, "marshal_dump", ISAAC4_marshal_dump, 0);
242
+ rb_define_method(ISAAC4, "marshal_load", ISAAC4_marshal_load, 1);
243
+
244
+ rb_const_set(ISAAC, rb_intern("RANDSIZ"), UINT2NUM(RANDSIZ));
245
+ rb_const_set(ISAAC4, rb_intern("RANDSIZ"), UINT2NUM(RANDSIZ4));
246
+ }
data/ext/isaac/rand.c ADDED
@@ -0,0 +1,139 @@
1
+ /*
2
+ ------------------------------------------------------------------------------
3
+ rand.c: By Bob Jenkins. My random number generator, ISAAC. Public Domain.
4
+ MODIFIED:
5
+ 960327: Creation (addition of randinit, really)
6
+ 970719: use context, not global variables, for internal state
7
+ 980324: added main (ifdef'ed out), also rearranged randinit()
8
+ 010626: Note that this is public domain
9
+
10
+ ADAPTED Aug2004 for use in Ruby by Joel VanderWerf
11
+ ADAPTED Jan2010 for 64 bit systems (same algorithm and results as 32 bit)
12
+ ------------------------------------------------------------------------------
13
+ */
14
+ #ifndef RAND
15
+ #include "rand.h"
16
+ #endif
17
+
18
+
19
+ #define ind(mm,x) ((mm)[(x>>2)&(RANDSIZ-1)])
20
+ #define rngstep(mix,a,b,mm,m,m2,r,x) \
21
+ { \
22
+ x = *m; \
23
+ a = ((a^(mix)) + *(m2++)); \
24
+ *(m++) = y = (ind(mm,x) + a + b); \
25
+ *(r++) = b = (ind(mm,y>>RANDSIZL) + x); \
26
+ }
27
+
28
+ void isaac_rand(ctx)
29
+ randctx *ctx;
30
+ {
31
+ register ub4 a,b,x,y,*m,*mm,*m2,*r,*mend;
32
+ mm=ctx->randmem; r=ctx->randrsl;
33
+ a = ctx->randa; b = (ctx->randb + (++ctx->randc));
34
+ for (m = mm, mend = m2 = m+(RANDSIZ/2); m<mend; )
35
+ {
36
+ rngstep( a<<13, a, b, mm, m, m2, r, x);
37
+ rngstep( a>>6 , a, b, mm, m, m2, r, x);
38
+ rngstep( a<<2 , a, b, mm, m, m2, r, x);
39
+ rngstep( a>>16, a, b, mm, m, m2, r, x);
40
+ }
41
+ for (m2 = mm; m2<mend; )
42
+ {
43
+ rngstep( a<<13, a, b, mm, m, m2, r, x);
44
+ rngstep( a>>6 , a, b, mm, m, m2, r, x);
45
+ rngstep( a<<2 , a, b, mm, m, m2, r, x);
46
+ rngstep( a>>16, a, b, mm, m, m2, r, x);
47
+ }
48
+ ctx->randb = b; ctx->randa = a;
49
+ }
50
+
51
+
52
+ #define mix(a,b,c,d,e,f,g,h) \
53
+ { \
54
+ a^=b<<11; d+=a; b+=c; \
55
+ b^=c>>2; e+=b; c+=d; \
56
+ c^=d<<8; f+=c; d+=e; \
57
+ d^=e>>16; g+=d; e+=f; \
58
+ e^=f<<10; h+=e; f+=g; \
59
+ f^=g>>4; a+=f; g+=h; \
60
+ g^=h<<8; b+=g; h+=a; \
61
+ h^=a>>9; c+=h; a+=b; \
62
+ }
63
+
64
+ /* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */
65
+ void isaac_init(ctx, flag)
66
+ randctx *ctx;
67
+ int flag;
68
+ {
69
+ int i;
70
+ ub4 a,b,c,d,e,f,g,h;
71
+ ub4 *m,*r;
72
+ ctx->randa = ctx->randb = ctx->randc = 0;
73
+ m=ctx->randmem;
74
+ r=ctx->randrsl;
75
+ a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */
76
+
77
+ for (i=0; i<4; ++i) /* scramble it */
78
+ {
79
+ mix(a,b,c,d,e,f,g,h);
80
+ }
81
+
82
+ if (flag)
83
+ {
84
+ /* initialize using the contents of r[] as the seed */
85
+ for (i=0; i<RANDSIZ; i+=8)
86
+ {
87
+ a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
88
+ e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
89
+ mix(a,b,c,d,e,f,g,h);
90
+ m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
91
+ m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
92
+ }
93
+ /* do a second pass to make all of the seed affect all of m */
94
+ for (i=0; i<RANDSIZ; i+=8)
95
+ {
96
+ a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
97
+ e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
98
+ mix(a,b,c,d,e,f,g,h);
99
+ m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
100
+ m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
101
+ }
102
+ }
103
+ else
104
+ {
105
+ /* fill in mm[] with messy stuff */
106
+ for (i=0; i<RANDSIZ; i+=8)
107
+ {
108
+ mix(a,b,c,d,e,f,g,h);
109
+ m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
110
+ m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
111
+ }
112
+ }
113
+
114
+ isaac_rand(ctx); /* fill in the first set of results */
115
+ ctx->randcnt=RANDSIZ; /* prepare to use the first set of results */
116
+ }
117
+
118
+
119
+ #ifdef NEVER
120
+ #include <stdio.h>
121
+
122
+ int main()
123
+ {
124
+ ub4 i,j;
125
+ randctx ctx;
126
+ ctx.randa=ctx.randb=ctx.randc=(ub4)0;
127
+ for (i=0; i<RANDSIZ; ++i) ctx.randrsl[i]=(ub4)0;
128
+ isaac_init(&ctx, 1);
129
+ for (i=0; i<2; ++i)
130
+ {
131
+ isaac_rand(&ctx);
132
+ for (j=0; j<RANDSIZ; ++j)
133
+ {
134
+ printf("%.8lx",(long unsigned int)ctx.randrsl[j]);
135
+ if ((j&7)==7) printf("\n");
136
+ }
137
+ }
138
+ }
139
+ #endif
data/ext/isaac/rand.h ADDED
@@ -0,0 +1,60 @@
1
+ /*
2
+ ------------------------------------------------------------------------------
3
+ rand.h: definitions for a random number generator
4
+ By Bob Jenkins, 1996, Public Domain
5
+ MODIFIED:
6
+ 960327: Creation (addition of randinit, really)
7
+ 970719: use context, not global variables, for internal state
8
+ 980324: renamed seed to flag
9
+ 980605: recommend RANDSIZL=4 for noncryptography.
10
+ 010626: note this is public domain
11
+
12
+ ADAPTED Aug2004 for use in Ruby by Joel VanderWerf
13
+ ADAPTED Jan2010 for 64 bit systems (same algorithm and results as 32 bit)
14
+ ------------------------------------------------------------------------------
15
+ */
16
+
17
+ #include <stdint.h>
18
+
19
+ typedef uint32_t ub4;
20
+
21
+ #ifndef RAND
22
+ #define RAND
23
+ #define RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */
24
+ #define RANDSIZ (1<<RANDSIZL)
25
+
26
+ /* context of random number generator */
27
+ struct randctx
28
+ {
29
+ ub4 randcnt;
30
+ ub4 randrsl[RANDSIZ];
31
+ ub4 randmem[RANDSIZ];
32
+ ub4 randa;
33
+ ub4 randb;
34
+ ub4 randc;
35
+ };
36
+ typedef struct randctx randctx;
37
+
38
+ /*
39
+ ------------------------------------------------------------------------------
40
+ If (flag==TRUE), then use the contents of randrsl[0..RANDSIZ-1] as the seed.
41
+ ------------------------------------------------------------------------------
42
+ */
43
+ void isaac_init(randctx *r, int flag);
44
+
45
+ void isaac_rand(randctx *r);
46
+
47
+
48
+ /*
49
+ ------------------------------------------------------------------------------
50
+ Call rand(/o_ randctx *r _o/) to retrieve a single 32-bit random value
51
+ ------------------------------------------------------------------------------
52
+ */
53
+ #define rand(r) \
54
+ (!(r)->randcnt-- ? \
55
+ (isaac_rand(r), (r)->randcnt=RANDSIZ-1, (r)->randrsl[(r)->randcnt]) : \
56
+ (r)->randrsl[(r)->randcnt])
57
+
58
+ #endif /* RAND */
59
+
60
+
data/ext/isaac/rand4.c ADDED
@@ -0,0 +1,131 @@
1
+ /*
2
+ ------------------------------------------------------------------------------
3
+ rand4.c: rand.c specialized to RANDSIZL=4
4
+ ------------------------------------------------------------------------------
5
+ */
6
+ #ifndef RAND4
7
+ #include "rand4.h"
8
+ #endif
9
+
10
+
11
+ #define ind(mm,x) ((mm)[(x>>2)&(RANDSIZ4-1)])
12
+ #define rngstep(mix,a,b,mm,m,m2,r,x) \
13
+ { \
14
+ x = *m; \
15
+ a = ((a^(mix)) + *(m2++)); \
16
+ *(m++) = y = (ind(mm,x) + a + b); \
17
+ *(r++) = b = (ind(mm,y>>4) + x); \
18
+ }
19
+
20
+ void isaac_rand4(ctx)
21
+ randctx4 *ctx;
22
+ {
23
+ register ub4 a,b,x,y,*m,*mm,*m2,*r,*mend;
24
+ mm=ctx->randmem; r=ctx->randrsl;
25
+ a = ctx->randa; b = (ctx->randb + (++ctx->randc));
26
+ for (m = mm, mend = m2 = m+(RANDSIZ4/2); m<mend; )
27
+ {
28
+ rngstep( a<<13, a, b, mm, m, m2, r, x);
29
+ rngstep( a>>6 , a, b, mm, m, m2, r, x);
30
+ rngstep( a<<2 , a, b, mm, m, m2, r, x);
31
+ rngstep( a>>16, a, b, mm, m, m2, r, x);
32
+ }
33
+ for (m2 = mm; m2<mend; )
34
+ {
35
+ rngstep( a<<13, a, b, mm, m, m2, r, x);
36
+ rngstep( a>>6 , a, b, mm, m, m2, r, x);
37
+ rngstep( a<<2 , a, b, mm, m, m2, r, x);
38
+ rngstep( a>>16, a, b, mm, m, m2, r, x);
39
+ }
40
+ ctx->randb = b; ctx->randa = a;
41
+ }
42
+
43
+
44
+ #define mix(a,b,c,d,e,f,g,h) \
45
+ { \
46
+ a^=b<<11; d+=a; b+=c; \
47
+ b^=c>>2; e+=b; c+=d; \
48
+ c^=d<<8; f+=c; d+=e; \
49
+ d^=e>>16; g+=d; e+=f; \
50
+ e^=f<<10; h+=e; f+=g; \
51
+ f^=g>>4; a+=f; g+=h; \
52
+ g^=h<<8; b+=g; h+=a; \
53
+ h^=a>>9; c+=h; a+=b; \
54
+ }
55
+
56
+ /* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */
57
+ void isaac_init4(ctx, flag)
58
+ randctx4 *ctx;
59
+ int flag;
60
+ {
61
+ int i;
62
+ ub4 a,b,c,d,e,f,g,h;
63
+ ub4 *m,*r;
64
+ ctx->randa = ctx->randb = ctx->randc = 0;
65
+ m=ctx->randmem;
66
+ r=ctx->randrsl;
67
+ a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */
68
+
69
+ for (i=0; i<4; ++i) /* scramble it */
70
+ {
71
+ mix(a,b,c,d,e,f,g,h);
72
+ }
73
+
74
+ if (flag)
75
+ {
76
+ /* initialize using the contents of r[] as the seed */
77
+ for (i=0; i<RANDSIZ4; i+=8)
78
+ {
79
+ a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
80
+ e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
81
+ mix(a,b,c,d,e,f,g,h);
82
+ m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
83
+ m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
84
+ }
85
+ /* do a second pass to make all of the seed affect all of m */
86
+ for (i=0; i<RANDSIZ4; i+=8)
87
+ {
88
+ a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
89
+ e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
90
+ mix(a,b,c,d,e,f,g,h);
91
+ m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
92
+ m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
93
+ }
94
+ }
95
+ else
96
+ {
97
+ /* fill in mm[] with messy stuff */
98
+ for (i=0; i<RANDSIZ4; i+=8)
99
+ {
100
+ mix(a,b,c,d,e,f,g,h);
101
+ m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
102
+ m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
103
+ }
104
+ }
105
+
106
+ isaac_rand4(ctx); /* fill in the first set of results */
107
+ ctx->randcnt=RANDSIZ4; /* prepare to use the first set of results */
108
+ }
109
+
110
+
111
+ #ifdef NEVER
112
+ #include <stdio.h>
113
+
114
+ int main()
115
+ {
116
+ ub4 i,j;
117
+ randctx4 ctx;
118
+ ctx.randa=ctx.randb=ctx.randc=(ub4)0;
119
+ for (i=0; i<RANDSIZ4; ++i) ctx.randrsl[i]=(ub4)0;
120
+ isaac_init4(&ctx, 1);
121
+ for (i=0; i<2; ++i)
122
+ {
123
+ isaac_rand4(&ctx);
124
+ for (j=0; j<RANDSIZ4; ++j)
125
+ {
126
+ printf("%.8lx",(long unsigned int)ctx.randrsl[j]);
127
+ if ((j&7)==7) printf("\n");
128
+ }
129
+ }
130
+ }
131
+ #endif
data/ext/isaac/rand4.h ADDED
@@ -0,0 +1,49 @@
1
+ /*
2
+ ------------------------------------------------------------------------------
3
+ rand4.h: rand.h specialized to RANDSIZL=4
4
+ ------------------------------------------------------------------------------
5
+ */
6
+
7
+ #include <stdint.h>
8
+
9
+ #include "rand.h"
10
+
11
+ #ifndef RAND4
12
+ #define RAND4
13
+ #define RANDSIZ4 (1<<4)
14
+
15
+ /* context of random number generator */
16
+ struct randctx4
17
+ {
18
+ ub4 randcnt;
19
+ ub4 randrsl[RANDSIZ4];
20
+ ub4 randmem[RANDSIZ4];
21
+ ub4 randa;
22
+ ub4 randb;
23
+ ub4 randc;
24
+ };
25
+ typedef struct randctx4 randctx4;
26
+
27
+ /*
28
+ ------------------------------------------------------------------------------
29
+ If (flag==TRUE), then use the contents of randrsl[0..RANDSIZ4-1] as the seed.
30
+ ------------------------------------------------------------------------------
31
+ */
32
+ void isaac_init4(randctx4 *r, int flag);
33
+
34
+ void isaac_rand4(randctx4 *r);
35
+
36
+
37
+ /*
38
+ ------------------------------------------------------------------------------
39
+ Call rand4(/o_ randctx4 *r _o/) to retrieve a single 32-bit random value
40
+ ------------------------------------------------------------------------------
41
+ */
42
+ #define rand4(r) \
43
+ (!(r)->randcnt-- ? \
44
+ (isaac_rand4(r), (r)->randcnt=RANDSIZ4-1, (r)->randrsl[(r)->randcnt]) : \
45
+ (r)->randrsl[(r)->randcnt])
46
+
47
+ #endif /* RAND4 */
48
+
49
+
@@ -0,0 +1,63 @@
1
+ require 'minitest/autorun'
2
+ require 'isaac'
3
+
4
+ include PRNG
5
+
6
+ class TestIsaac < MiniTest::Unit::TestCase
7
+ SEED = (0..255).map {rand(2**32-1)}
8
+ # note that minitest supplies the seed to ruby's Kernel#rand
9
+ # use '--seed N' to select a particular seed
10
+
11
+ SEQ_1_2_3 = {
12
+ ISAAC4 => [
13
+ 200253249, 3829869937, 4163837080, 3505347059, 4075830238,
14
+ 2736331801, 3164829547, 410071848, 1780052116, 1192885451],
15
+ ISAAC => [
16
+ 2356990817, 1396826555, 488165990, 3792500048, 3350490136,
17
+ 3216315542, 2855747110, 2938836516, 2909213788, 1662784833]
18
+ }
19
+
20
+ CASES = [ISAAC4, ISAAC]
21
+
22
+ def setup
23
+ @rs = CASES.map {|cl| r=cl.new; r.srand SEED; r}
24
+ end
25
+
26
+ def test_ranges
27
+ @rs.each do |r|
28
+ range = 0..1
29
+ range32 = 0..2**32-1
30
+
31
+ 10.times do
32
+ assert_includes range, r.rand, r.class
33
+ assert_includes range32, r.rand32, r.class
34
+ end
35
+ end
36
+ end
37
+
38
+ def test_repeatable
39
+ @rs.each do |r|
40
+ r2 = r.class.new
41
+ r2.srand SEED
42
+ 10.times do
43
+ assert_equal(r.rand32, r2.rand32, r.class)
44
+ end
45
+ end
46
+ end
47
+
48
+ def test_predictable
49
+ @rs.each do |r|
50
+ r.srand [1,2,3]
51
+ assert_equal(SEQ_1_2_3[r.class], (0..9).map {r.rand32}, r.class)
52
+ end
53
+ end
54
+
55
+ def test_marshal
56
+ @rs.each do |r|
57
+ r2 = Marshal.load(Marshal.dump(r))
58
+ 10.times do
59
+ assert_equal(r.rand32, r2.rand32, r.class)
60
+ end
61
+ end
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prng-isaac
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Joel VanderWerf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-04-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A pseudorandom number generator based on Bob Jenkins' ISAAC; useful for
14
+ both simulation and crypto.
15
+ email: vjoel@users.sourceforge.net
16
+ executables: []
17
+ extensions:
18
+ - ext/isaac/extconf.rb
19
+ extra_rdoc_files:
20
+ - RELEASE-NOTES
21
+ - README.md
22
+ - COPYING
23
+ files:
24
+ - RELEASE-NOTES
25
+ - README.md
26
+ - COPYING
27
+ - ext/isaac/extconf.rb
28
+ - ext/isaac/isaac.c
29
+ - ext/isaac/rand4.c
30
+ - ext/isaac/rand.c
31
+ - ext/isaac/rand4.h
32
+ - ext/isaac/rand.h
33
+ - ext/isaac/Makefile
34
+ - bench/bench.rb
35
+ - test/test_isaac.rb
36
+ homepage: https://github.com/vjoel/isaac
37
+ licenses: []
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options:
41
+ - --quiet
42
+ - --line-numbers
43
+ - --inline-source
44
+ - --title
45
+ - ISAAC
46
+ - --main
47
+ - README.md
48
+ require_paths:
49
+ - lib
50
+ - ext
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 2.0.3
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: ISAAC pseudorandom number generator
67
+ test_files:
68
+ - test/test_isaac.rb