pcg_random 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e26f09fa3ea5290710f41975fcf1a22e4265e794
4
- data.tar.gz: 792f5b3ffddb3c984d58aa93c8146443e7837682
3
+ metadata.gz: e613759fc11837de964926f2067b38d770100cd6
4
+ data.tar.gz: c72b3c2996301edeeb5084c5d785342219c99b59
5
5
  SHA512:
6
- metadata.gz: 8bf992989aa751a8cd99dc153f78469dc3da4c16b6e2ec3e8dc8a8589aaa1407d0f78b42b9b1a33123ef6b0b83b3b700853afbac5bb23ccc9151e799cd8d7b92
7
- data.tar.gz: 8addc87f54888e50b8bdeb08f6959da746054f5d8014c498842121596b6b0c64c314d1b5cd841fd650a97924cc6a69778cd2f36633428b1a352fd0f801ac73b4
6
+ metadata.gz: 9dd5e22f22437be3e1cf6fa105f984d12cda521462e284a14d373d1f7c3b45b029a07e84a099f2fdbc833e54fe0748dd69f05f972119fa015a6f7c8da5e1754c
7
+ data.tar.gz: ac91b8a84e7cdb204905fe05453d63fd7aa23900b3416a5dd60606938156e4a84e05dd9dcee033d18b34ce341096c713865dbff672227545dbefc687991b01e0
data/README.md CHANGED
@@ -1,41 +1,113 @@
1
- # PcgRandom
1
+ # PCGRandom
2
+ [![Gem Version](https://badge.fury.io/rb/pcg_random.svg)](https://badge.fury.io/rb/pcg_random)
2
3
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/pcg_random`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+ ```
5
+ _____ _____ _____ _____ _
6
+ | _ | | __| __ |___ ___ _| |___ _____
7
+ | __| --| | | -| .'| | . | . | |
8
+ |__| |_____|_____|__|__|__,|_|_|___|___|_|_|_|
9
+
10
+ ```
4
11
 
5
- TODO: Delete this and the text above, and describe your gem
12
+ Ruby wrappers for the PCGRandom family of random number generators.
6
13
 
7
14
  ## Installation
8
15
 
9
- Add this line to your application's Gemfile:
16
+ ### Prerequisites
10
17
 
11
- ```ruby
12
- gem 'pcg_random'
13
- ```
18
+ * A C-compiler (any modern C compiler is supported on *nix, Windows isn't supported yet)
19
+ * Modified C source code for pcg_random [available here](https://github.com/vaibhav-y/pcg-c/archive/master.zip) for building libpcg_random.
20
+ * Follow the build instructions [given here](https://github.com/vaibhav-y/pcg-c#building) to build `libpcg_random`
14
21
 
15
- And then execute:
22
+ ### Installing the gem:
16
23
 
17
- $ bundle
24
+ * Rubygems:
18
25
 
19
- Or install it yourself as:
26
+ ``` bash
27
+ gem install pcg_random
28
+ ```
29
+
30
+ You can also configure the path to `libpcg_random` by specifying it's path explicitly:
20
31
 
21
- $ gem install pcg_random
32
+ ``` bash
33
+ # specify the custome include path
34
+ gem install pcg_random --with-pcg_random-include=directory/containing/pcg_variants.h
22
35
 
23
- ## Usage
36
+ # or, specify the custom path to the libpcg_random binary
37
+ gem install pcg_random --with-pcg_random-lib=directory/containing/libpcg_random.a
24
38
 
25
- TODO: Write usage instructions here
39
+ # Or, specify both the lib/ and include/ together to be under path/to/some/directory
40
+ gem install pcg_random --with-pcg_random-dir=path/to/some/directory
41
+ ```
26
42
 
27
43
  ## Development
44
+ `TODO: Create a CONTRIBTING.md`
28
45
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+ Install pcg_random *from source* using the above steps. Using the above links are important because the library must be compiled with additional flags to be used for gem-development. There are also some issues in the original repository that are addressed in my fork.
30
47
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
48
+ ## Using the extension
49
+
50
+ Either jump into your REPL of choice:
51
+
52
+ ``` ruby
53
+ ~$ irb
54
+ 2.3.0 :001 > require 'pcg_random'
55
+ => true
56
+ ```
57
+
58
+ Or go ahead and try the API, it's built to be as close to `Kernel::Random` as possible!
59
+
60
+ ``` ruby
61
+ 2.3.0 :002 > seed = PCGRanom.new_seed
62
+ => 315431527813695542666700950080169144774
63
+ 2.3.0 :003 > rng = PCGRanom.new 1234
64
+ => #<PCGRandom:0x00000001bf3eb0 @seed=1234>
65
+ ```
32
66
 
33
- ## Contributing
67
+ For detailed instructions, keep checking this repo, I'm working on getting a wiki up.
34
68
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/pcg_random.
36
69
 
70
+ ## Benchmarks
37
71
 
38
- ## License
72
+ ### PCGRandom.new_seed
73
+ ```
74
+ Benchmark of Random.new_seed vs PCGRandom.new_seed
75
+ ==================================================
76
+
77
+ Benchmark created around: 2016-03-30 14:54:16 +0000
78
+
79
+ Running for: 100000 iterations
80
+
81
+ Rehearsal ------------------------------------------------------
82
+ Random.new_seed 0.090000 1.240000 1.330000 ( 1.323970)
83
+ PCGRandom.new_seed 0.100000 1.150000 1.250000 ( 1.254944)
84
+ --------------------------------------------- total: 2.580000sec
85
+
86
+ user system total real
87
+ Random.new_seed 0.110000 1.200000 1.310000 ( 1.321571)
88
+ PCGRandom.new_seed 0.100000 1.130000 1.230000 ( 1.222634)
89
+ ```
90
+ ### PCGRandom.raw_seed(16)
91
+ ```
92
+ Benchmark of Random.raw_seed(16) vs PCGRandom.raw_seed(16)
93
+ ==================================================
94
+
95
+ Benchmark created around: 2016-03-30 14:41:26 +0000
96
+
97
+ Running for: 100000 iterations
98
+
99
+ Rehearsal ----------------------------------------------------------
100
+ Random.raw_seed(16) 0.080000 1.440000 1.520000 ( 1.515513)
101
+ PCGRandom.raw_seed(16) 0.110000 1.320000 1.430000 ( 1.444519)
102
+ ------------------------------------------------- total: 2.950000sec
103
+
104
+ user system total real
105
+ Random.raw_seed(16) 0.080000 1.470000 1.550000 ( 1.563351)
106
+ PCGRandom.raw_seed(16) 0.090000 1.340000 1.430000 ( 1.441253)
107
+ ```
39
108
 
40
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
109
+ ## Roadmap
41
110
 
111
+ * Achieve full parity with `Kernel::Random`
112
+ * Get a wiki explaining how to go about using this gem
113
+ * Showcase benchmarks in some other place
data/Rakefile CHANGED
@@ -1,16 +1,14 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'bundler'
2
3
  require 'rspec/core/rake_task'
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
4
  require "rake/extensiontask"
7
5
 
8
- task :build => :compile
6
+ RSpec::Core::RakeTask.new(:spec)
9
7
 
10
8
  Rake::ExtensionTask.new("pcg_random") do |ext|
11
9
  ext.lib_dir = "lib/pcg_random"
12
10
  end
13
11
 
12
+ task :build => :compile
14
13
  task :cc => [:clean, :compile]
15
-
16
14
  task :default => [:clobber, :compile, :spec]
@@ -2,16 +2,16 @@
2
2
  Benchmark of Random.new_seed vs PCGRandom.new_seed
3
3
  ==================================================
4
4
 
5
- Benchmark created around: 2016-03-25 18:27:27 +0000
5
+ Benchmark created around: 2016-03-30 14:54:16 +0000
6
6
 
7
7
  Running for: 100000 iterations
8
8
 
9
9
  Rehearsal ------------------------------------------------------
10
- Random.new_seed 0.120000 1.060000 1.180000 ( 1.173928)
11
- PCGRandom.new_seed 0.070000 1.020000 1.090000 ( 1.096108)
12
- --------------------------------------------- total: 2.270000sec
10
+ Random.new_seed 0.090000 1.240000 1.330000 ( 1.323970)
11
+ PCGRandom.new_seed 0.100000 1.150000 1.250000 ( 1.254944)
12
+ --------------------------------------------- total: 2.580000sec
13
13
 
14
14
  user system total real
15
- Random.new_seed 0.100000 1.090000 1.190000 ( 1.188864)
16
- PCGRandom.new_seed 0.110000 1.090000 1.200000 ( 1.197528)
15
+ Random.new_seed 0.110000 1.200000 1.310000 ( 1.321571)
16
+ PCGRandom.new_seed 0.100000 1.130000 1.230000 ( 1.222634)
17
17
  ```
@@ -2,16 +2,16 @@
2
2
  Benchmark of Random.raw_seed(16) vs PCGRandom.raw_seed(16)
3
3
  ==================================================
4
4
 
5
- Benchmark created around: 2016-03-25 18:27:35 +0000
5
+ Benchmark created around: 2016-03-30 14:41:26 +0000
6
6
 
7
7
  Running for: 100000 iterations
8
8
 
9
9
  Rehearsal ----------------------------------------------------------
10
- Random.raw_seed(16) 0.040000 0.980000 1.020000 ( 1.031410)
11
- PCGRandom.raw_seed(16) 0.050000 0.970000 1.020000 ( 1.021024)
12
- ------------------------------------------------- total: 2.040000sec
10
+ Random.raw_seed(16) 0.080000 1.440000 1.520000 ( 1.515513)
11
+ PCGRandom.raw_seed(16) 0.110000 1.320000 1.430000 ( 1.444519)
12
+ ------------------------------------------------- total: 2.950000sec
13
13
 
14
14
  user system total real
15
- Random.raw_seed(16) 0.090000 0.990000 1.080000 ( 1.076778)
16
- PCGRandom.raw_seed(16) 0.060000 1.000000 1.060000 ( 1.067268)
15
+ Random.raw_seed(16) 0.080000 1.470000 1.550000 ( 1.563351)
16
+ PCGRandom.raw_seed(16) 0.090000 1.340000 1.430000 ( 1.441253)
17
17
  ```
@@ -1,172 +1,20 @@
1
1
  #include <ruby.h>
2
+ #include <ruby/util.h>
2
3
  #include <stdbool.h>
3
4
  #include <stdint.h>
5
+ #include <limits.h>
4
6
  #include <math.h>
5
7
  #include <pcg_variants.h>
6
8
 
7
9
  #include "pcg_random.h"
8
10
  #include "pcg_seed.h"
11
+ #include "pcg_rng.h"
9
12
 
10
13
  VALUE rb_cPCGRandom;
11
14
 
12
- static void pcg_random_mark(void *ptr);
13
- static void pcg_random_free(void *rand_data);
14
- static size_t pcg_random_memsize(const void *ptr);
15
- static pcg_rb_rand_t *pcg_get_rand_type(VALUE obj);
16
- static VALUE pcg_random_alloc(VALUE klass);
17
- static VALUE pcg_func_init(int argc, VALUE *argv, VALUE self);
18
- static VALUE pcg_func_get_state(VALUE self);
19
- static VALUE pcg_func_get_seq(VALUE self);
20
-
21
- /*
22
- * Structure wrapping our rng's data type's GC related functions
23
- */
24
- static const rb_data_type_t pcg_rand_data_t = {
25
- "pcg_random",
26
- {
27
- pcg_random_mark,
28
- pcg_random_free,
29
- pcg_random_memsize,
30
- },
31
- };
32
-
33
- /*
34
- * Internal - Mark the internal seed value for garbage collection since a VALUE
35
- * inside a C struct is not marked by the GC automatically, and isn't freed
36
- * correctly either.
37
- */
38
- static void
39
- pcg_random_mark(void *ptr)
40
- {
41
- rb_gc_mark(((pcg_rb_rand_t *) ptr)->seed.val);
42
- }
43
-
44
- /*
45
- * Internal - Free internal C-types in the `pcg_rb_rand_t` struct
46
- */
47
- static void
48
- pcg_random_free(void *rand_data)
49
- {
50
- xfree(((pcg_rb_rand_t *) rand_data)->rng);
51
- xfree((pcg_rb_rand_t *)(rand_data));
52
- }
53
-
54
- /*
55
- * Internal - Get the size of a valid pcg_rb_rand_t pointer
56
- *
57
- * @return the size of `pcg_rb_rand_t` struct if it is initialized correctly.
58
- * 0 if given a NULL pointer
59
- */
60
- static size_t
61
- pcg_random_memsize(const void *ptr)
62
- {
63
- return ptr ? sizeof(pcg_rb_rand_t) : 0;
64
- }
65
-
66
- /*
67
- * Internal - Helper function to get a pointer to a pcg_rb_rand_t struct given
68
- * an instance of the `PCGRandom` class
69
- *
70
- * Returns an object wrapping a C struct, with default initializations
71
- */
72
- static pcg_rb_rand_t *
73
- pcg_get_rand_type(VALUE obj)
74
- {
75
- pcg_rb_rand_t *ptr;
76
- TypedData_Get_Struct(obj, pcg_rb_rand_t, &pcg_rand_data_t, ptr);
77
- return ptr;
78
- }
79
-
80
- /*
81
- * Memory allocation function that is called by new before `initialize` is
82
- * The chain is similar to: `new -> allocate -> initialize`
83
- *
84
- * Returns an object wrapping a C struct, with default initializations
85
- */
86
- static VALUE
87
- pcg_random_alloc(VALUE klass)
88
- {
89
- pcg_rb_rand_t *rand_data;
90
- VALUE obj;
91
- /*
92
- * ISO C forbids braced-groups within expressions
93
- * See: http://stackoverflow.com/questions/1238016/
94
- */
95
- obj = __extension__ TypedData_Make_Struct(klass, pcg_rb_rand_t, &pcg_rand_data_t, rand_data);
96
-
97
- rand_data->seed.val = INT2FIX(0);
98
- rand_data->seed.state = 0;
99
- rand_data->seed.seq = 0;
100
- rand_data->rng = ALLOC(pcg32_random_t);
101
-
102
- return obj;
103
- }
104
-
105
- /*
106
- * Internal - Initialize the requested instance using a pre-allocated ruby
107
- * object (TypedStruct). Sets the instance variables and relevant accessor
108
- * methods where applicable.
109
- */
110
- static VALUE
111
- pcg_func_init(int argc, VALUE *argv, VALUE self)
112
- {
113
- VALUE seed;
114
- uint64_t cseeds[2];
115
- pcg_rb_rand_t* rand_data = pcg_get_rand_type(self);
116
-
117
- if(argc == 0)
118
- {
119
- seed = DEFAULT_SEED_VALUE;
120
- }
121
- else
122
- {
123
- rb_scan_args(argc, argv, "01", &seed);
124
- }
125
-
126
- rb_integer_pack(seed, (void *) cseeds, 2, sizeof(uint64_t), 0,
127
- INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
128
-
129
- rand_data->seed.val = seed;
130
- rand_data->seed.state = cseeds[0];
131
- rand_data->seed.seq = cseeds[1];
132
- pcg32_srandom_r(rand_data->rng, cseeds[0], cseeds[1]);
133
-
134
- /* Add & set private instance variables */
135
- rb_iv_set(self, "@seed", seed);
136
- rb_iv_set(self, "state", LONG2NUM(rand_data->seed.state));
137
- rb_iv_set(self, "sequence", LONG2NUM(rand_data->seed.seq));
138
- return self;
139
- }
140
-
141
- /*
142
- * Internal - Private method to access internal rng state parameter
143
- * (Most significant word of seed)
144
- */
145
- static VALUE
146
- pcg_func_get_state(VALUE self)
147
- {
148
- VALUE state;
149
- state = rb_iv_get(self, "state");
150
- return state;
151
- }
152
-
153
- /*
154
- * Internal - Private method to access internal rng state parameter
155
- * (Most significant word of seed)
156
- */
157
- static VALUE
158
- pcg_func_get_seq(VALUE self)
159
- {
160
- VALUE seq;
161
- seq = rb_iv_get(self, "sequence");
162
- return seq;
163
- }
164
-
165
15
  void
166
16
  Init_pcg_random(void)
167
17
  {
168
- /* Initializations */
169
-
170
18
  /* Constants / Classes */
171
19
  rb_cPCGRandom = rb_define_class("PCGRandom", rb_cObject);
172
20
 
@@ -176,18 +24,14 @@ Init_pcg_random(void)
176
24
  rb_define_singleton_method(rb_cPCGRandom, "new_seed", pcg_func_new_seed, 0);
177
25
  rb_define_singleton_method(rb_cPCGRandom, "raw_seed", pcg_func_raw_seed, 1);
178
26
 
179
- /* Public instance methods */
27
+ /* Instance methods */
180
28
  rb_define_alloc_func(rb_cPCGRandom, pcg_random_alloc);
181
- rb_define_attr(rb_cPCGRandom, "seed", 1, 0);
182
- // rb_define_method(rb_cPCGRandom, "rand", pcg_func_rand, -1);
183
- // rb_define_method(rb_cPCGRandom, "bytes", pcg_func_rand_bytes, 1);
184
- // rb_define_method(rb_cPCGRandom, "initialize_copy", pcg_func_rand_copy, 1);
185
- // rb_define_method(rb_cPCGRandom, "==", pcg_func_equal, 1);
186
-
187
- /* Private instance methods */
188
29
  rb_define_method(rb_cPCGRandom, "initialize", pcg_func_init, -1);
189
- // rb_define_private_method(rb_cPCGRandom, "marshal_dump", pcg_func_dump, 0);
190
- // rb_define_private_method(rb_cPCGRandom, "marshal_load", pcg_func_load, 1);
191
- rb_define_private_method(rb_cPCGRandom, "state", pcg_func_get_state, 0);
192
- rb_define_private_method(rb_cPCGRandom, "sequence", pcg_func_get_seq, 0);
30
+
31
+ rb_define_attr(rb_cPCGRandom, "seed", 1, 0);
32
+
33
+ rb_define_method(rb_cPCGRandom, "rand", pcg_func_rand, -1);
34
+ rb_define_method(rb_cPCGRandom, "bytes", pcg_func_rand_bytes, 1);
35
+
36
+ rb_define_method(rb_cPCGRandom, "==", pcg_func_eql, 1);
193
37
  }
@@ -2,21 +2,7 @@
2
2
  #define PCG_RANDOM_H 1
3
3
 
4
4
  #include <ruby.h>
5
- #include <stdint.h>
6
5
 
7
6
  extern VALUE rb_cPCGRandom;
8
7
 
9
- struct pcg_rb_seed
10
- {
11
- VALUE val;
12
- uint64_t state;
13
- uint64_t seq;
14
- };
15
-
16
- typedef struct
17
- {
18
- struct pcg_rb_seed seed;
19
- pcg32_random_t *rng;
20
- } pcg_rb_rand_t;
21
-
22
8
  #endif /* PCG_RANDOM_H */
@@ -0,0 +1,248 @@
1
+ #include <ruby.h>
2
+ #include <ruby/util.h>
3
+ #include <stdbool.h>
4
+ #include <stdint.h>
5
+ #include <limits.h>
6
+ #include <math.h>
7
+ #include <pcg_variants.h>
8
+
9
+ #include "pcg_random.h"
10
+ #include "pcg_seed.h"
11
+ #include "pcg_rng.h"
12
+
13
+ VALUE rb_cPCGRandom;
14
+
15
+ static void pcg_random_mark(void *ptr);
16
+ static void pcg_random_free(void *rand_data);
17
+
18
+ static size_t pcg_random_memsize(const void *ptr);
19
+
20
+ static VALUE pcg_rb_float64_rand(pcg32_random_t *rng);
21
+
22
+ /*
23
+ * Structure wrapping our rng's data type's GC related functions
24
+ */
25
+ static const rb_data_type_t pcg_rand_data_t = {
26
+ "pcg_random",
27
+ {
28
+ pcg_random_mark,
29
+ pcg_random_free,
30
+ pcg_random_memsize,
31
+ },
32
+ };
33
+
34
+ /*
35
+ * Internal - Mark the internal seed value for garbage collection since a VALUE
36
+ * inside a C struct is not marked by the GC automatically, and isn't freed
37
+ * correctly either.
38
+ */
39
+ static void
40
+ pcg_random_mark(void *ptr)
41
+ {
42
+ rb_gc_mark(((pcg_rb_rand_t *) ptr)->seed.val);
43
+ }
44
+
45
+ /*
46
+ * Internal - Free internal C-types in the `pcg_rb_rand_t` struct
47
+ */
48
+ static void
49
+ pcg_random_free(void *rand_data)
50
+ {
51
+ xfree(((pcg_rb_rand_t *) rand_data)->rng);
52
+ xfree(rand_data);
53
+ }
54
+
55
+ /*
56
+ * Internal - Get the size of a valid pcg_rb_rand_t pointer
57
+ *
58
+ * @return the size of `pcg_rb_rand_t` struct if it is initialized correctly.
59
+ * 0 if given a NULL pointer
60
+ */
61
+ static size_t
62
+ pcg_random_memsize(const void *ptr)
63
+ {
64
+ return ptr ? sizeof(pcg_rb_rand_t) : 0;
65
+ }
66
+
67
+ /*
68
+ * Internal - Helper function to get a pointer to a pcg_rb_rand_t struct given
69
+ * an instance of the `PCGRandom` class
70
+ *
71
+ * Returns an object wrapping a C struct, with default initializations
72
+ */
73
+ pcg_rb_rand_t *
74
+ pcg_get_rand_type(VALUE obj)
75
+ {
76
+ pcg_rb_rand_t *ptr;
77
+ TypedData_Get_Struct(obj, pcg_rb_rand_t, &pcg_rand_data_t, ptr);
78
+ return ptr;
79
+ }
80
+
81
+ /*
82
+ * Memory allocation function that is called by `new` before `initialize` is
83
+ * The chain is similar to: `new -> allocate -> initialize`
84
+ *
85
+ * Returns an object wrapping a C struct, with default initializations
86
+ */
87
+ VALUE
88
+ pcg_random_alloc(VALUE klass)
89
+ {
90
+ pcg_rb_rand_t *rand_data;
91
+ VALUE obj;
92
+ /*
93
+ * ISO C forbids braced-groups within expressions
94
+ * See: http://stackoverflow.com/questions/1238016/
95
+ */
96
+ obj = __extension__ TypedData_Make_Struct(klass, pcg_rb_rand_t, &pcg_rand_data_t, rand_data);
97
+
98
+ rand_data->seed.val = INT2FIX(0);
99
+ rand_data->seed.state = 0;
100
+ rand_data->seed.seq = 0;
101
+ rand_data->rng = ALLOC(pcg32_random_t);
102
+
103
+ return obj;
104
+ }
105
+
106
+ /*
107
+ * Initialize the requested instance using a pre-allocated ruby
108
+ * object (TypedStruct). Sets the instance variables and relevant accessor
109
+ * methods where applicable.
110
+ *
111
+ * @param seed [Fixnum, Bignum] The seed to use use for initilization
112
+ *
113
+ * @raise TypeError unless parameters are Fixnum / Bignum
114
+ */
115
+ VALUE
116
+ pcg_func_init(int argc, VALUE *argv, VALUE self)
117
+ {
118
+ VALUE seed;
119
+ uint64_t cseeds[2];
120
+ pcg_rb_rand_t* rand_data = pcg_get_rand_type(self);
121
+
122
+ if(argc == 0)
123
+ {
124
+ seed = DEFAULT_SEED_VALUE;
125
+ }
126
+ else
127
+ {
128
+ rb_scan_args(argc, argv, "01", &seed);
129
+ }
130
+
131
+ if( !(RB_TYPE_P(seed, T_FIXNUM) || RB_TYPE_P(seed, T_BIGNUM)) )
132
+ {
133
+ rb_raise(rb_eTypeError,"Expected Fixnum or Bignum, found %s",
134
+ rb_obj_classname(seed));
135
+ }
136
+
137
+ rb_integer_pack(seed, (void *) cseeds, 2, sizeof(uint64_t), 0,
138
+ INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
139
+
140
+ rand_data->seed.val = seed;
141
+ rand_data->seed.state = cseeds[0];
142
+ rand_data->seed.seq = cseeds[1];
143
+ pcg32_srandom_r(rand_data->rng, cseeds[0], cseeds[1]);
144
+
145
+ /* Add & set private instance variables */
146
+ rb_iv_set(self, "@seed", seed);
147
+ rb_iv_set(self, "state", LONG2NUM(rand_data->seed.state));
148
+ rb_iv_set(self, "sequence", LONG2NUM(rand_data->seed.seq));
149
+ return self;
150
+ }
151
+
152
+ /*
153
+ * Get a random string of the given length
154
+ *
155
+ * @param max The upperbound on numbers to generate
156
+ */
157
+ VALUE
158
+ pcg_func_rand_bytes(VALUE self, VALUE size)
159
+ {
160
+ VALUE result;
161
+ pcg_rb_rand_t *rdata = pcg_get_rand_type(self);
162
+ size_t len = NUM2ULONG(size);
163
+ char *str = ALLOC_N(char, len);
164
+
165
+ for(int i = 0; i < len; ++i)
166
+ {
167
+ str[i] = (char) pcg32_boundedrand_r(rdata->rng, CHAR_MAX);
168
+ }
169
+ result = rb_str_new(str, len);
170
+ xfree(str);
171
+ return result;
172
+ }
173
+
174
+ /*
175
+ * Return a random number between 0 and 1
176
+ *
177
+ * @param max Upper bound for the rng or the range of values that are acceptable
178
+ */
179
+ VALUE
180
+ pcg_func_rand(int argc, VALUE *argv, VALUE self)
181
+ {
182
+ VALUE max, result;
183
+ long ubound;
184
+ double num, lim;
185
+ pcg_rb_rand_t *rdata = pcg_get_rand_type(self);
186
+
187
+ if(argc == 0)
188
+ {
189
+ return pcg_rb_float64_rand(rdata->rng);
190
+ }
191
+
192
+ rb_scan_args(argc, argv, "01", &max);
193
+
194
+ switch(TYPE(max))
195
+ {
196
+ case T_FIXNUM:
197
+ ubound = FIX2LONG(max);
198
+ return LONG2FIX(pcg32_boundedrand_r(rdata->rng, ubound));
199
+ case T_FLOAT:
200
+ num = ldexp((double) pcg32_boundedrand_r(rdata->rng, UINT32_MAX), -32);
201
+ lim = NUM2DBL(max);
202
+ return DBL2NUM(num * lim);
203
+ case T_BIGNUM:
204
+ num = ldexp((double) pcg32_boundedrand_r(rdata->rng, UINT32_MAX), -32);
205
+ result = rb_big_mul(max, DBL2NUM(num));
206
+ return rb_funcall(result, rb_intern("floor"), 0);
207
+ break;
208
+ case T_NIL:
209
+ rb_raise(rb_eArgError, "Invalid argument - nil");
210
+ break;
211
+ default:
212
+ rb_raise(rb_eTypeError, "Argument of type %s not supported (yet)",
213
+ rb_obj_classname(max));
214
+ }
215
+ return Qnil;
216
+ }
217
+
218
+ /*
219
+ * Return a random number in [0, 1) with double precision rounded to the closest
220
+ * multiple for 1/(2**64)
221
+ */
222
+ static VALUE
223
+ pcg_rb_float64_rand(pcg32_random_t *rng)
224
+ {
225
+ double d = ldexp((double) pcg32_boundedrand_r(rng, UINT32_MAX), -32);
226
+ return DBL2NUM(d);
227
+ }
228
+
229
+ /*
230
+ * Compares two instances of the class, returns true if they had the same
231
+ * initial state
232
+ *
233
+ * @param other [Object] Object to compare this instance to
234
+ *
235
+ * @return
236
+ */
237
+ VALUE
238
+ pcg_func_eql(VALUE self, VALUE other)
239
+ {
240
+ VALUE s, o;
241
+ if( !strcmp(rb_obj_classname(self), rb_obj_classname(other)) )
242
+ {
243
+ s = rb_iv_get(self, "@seed");
244
+ o = rb_iv_get(other, "@seed");
245
+ return rb_funcall(s, rb_intern("=="), 1, o);
246
+ }
247
+ return Qfalse;
248
+ }
@@ -0,0 +1,29 @@
1
+ #ifndef PCG_RNG_H
2
+ #define PCG_RNG_H 1
3
+
4
+ #include <ruby.h>
5
+ #include <stdint.h>
6
+
7
+ struct pcg_rb_seed
8
+ {
9
+ VALUE val;
10
+ uint64_t state;
11
+ uint64_t seq;
12
+ };
13
+
14
+ typedef struct
15
+ {
16
+ struct pcg_rb_seed seed;
17
+ pcg32_random_t *rng;
18
+ } pcg_rb_rand_t;
19
+
20
+
21
+ pcg_rb_rand_t *pcg_get_rand_type(VALUE obj);
22
+
23
+ VALUE pcg_random_alloc(VALUE klass);
24
+ VALUE pcg_func_init(int argc, VALUE *argv, VALUE self);
25
+ VALUE pcg_func_rand(int argc, VALUE *argv, VALUE self);
26
+ VALUE pcg_func_rand_bytes(VALUE self, VALUE size);
27
+ VALUE pcg_func_eql(VALUE self, VALUE other);
28
+
29
+ #endif /* PCG_RNG_H */
@@ -1,3 +1,3 @@
1
1
  class PCGRandom
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.6"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pcg_random
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vaibhav Yenamandra
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-30 00:00:00.000000000 Z
11
+ date: 2016-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,6 +108,8 @@ files:
108
108
  - ext/pcg_random/extconf.rb
109
109
  - ext/pcg_random/pcg_random.c
110
110
  - ext/pcg_random/pcg_random.h
111
+ - ext/pcg_random/pcg_rng.c
112
+ - ext/pcg_random/pcg_rng.h
111
113
  - ext/pcg_random/pcg_seed.c
112
114
  - ext/pcg_random/pcg_seed.h
113
115
  - ext/pcg_random/pcg_spinlock.h