carray 3.0.2 → 3.0.3
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 +4 -4
- data/CHANGELOG.md +304 -0
- data/README.md +3 -4
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +225 -0
- data/ext/ca_axis_group.c +177 -99
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +66 -71
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +663 -214
- data/ext/ca_kernel_iterator.h +231 -167
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +132 -22
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +1 -0
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +96 -25
- data/ext/ca_obj_face.c +406 -64
- data/ext/ca_obj_face.h +92 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +21 -21
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +189 -107
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +543 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +47 -49
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -118
- data/ext/ca_obj_stride.c +195 -34
- data/ext/ca_obj_string.c +17 -18
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +149 -27
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +102 -79
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +70 -27
- data/ext/carray_access.c +455 -211
- data/ext/carray_address_basis.c +177 -36
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +46 -14
- data/ext/carray_call_cfunc.c +0 -28
- data/ext/carray_cast.c +1444 -209
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +32 -11
- data/ext/carray_core.c +514 -122
- data/ext/carray_count.c +140 -87
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +569 -277
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +385 -3
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +682 -316
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +221 -76
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1089 -359
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +273 -239
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +170 -70
- data/ext/carray_sort.c +215 -218
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +0 -2
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1076 -846
- data/ext/ruby_carray.c +7 -1
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +19 -0
- data/lib/carray/autoload_method_extension.rb +6 -0
- data/lib/carray/axis_group.rb +174 -26
- data/lib/carray/basics.rb +91 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +118 -48
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +94 -26
- data/lib/carray/categorical_iterator.rb +333 -826
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +46 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +589 -82
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +124 -25
- data/lib/carray/frame/group.rb +189 -63
- data/lib/carray/frame/io.rb +412 -72
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +37 -16
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +715 -48
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +29 -11
- data/lib/carray/iterator.rb +14 -2
- data/lib/carray/lazy.rb +54 -30
- data/lib/carray/mask_gap_fill.rb +66 -52
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +117 -4
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +177 -36
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +51 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +4 -3
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +517 -103
- data/lib/carray/window_iterator.rb +127 -72
- data/lib/carray.rb +2 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +1 -2
- data/yard-stubs/carray_access.rb +5 -4
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +25 -13
- data/yard-stubs/carray_median_percentile.rb +10 -6
- data/yard-stubs/carray_order.rb +34 -13
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +2 -1
- data/yard-stubs/carray_sort.rb +43 -3
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +11 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -26005
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14862
- data/ext/carray_kernels_reduce_extreme.c +0 -17494
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32218
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/carray_random.c
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
---------------------------------------------------------------------------- */
|
|
19
19
|
|
|
20
20
|
#include "carray.h"
|
|
21
|
+
#include "carray_internal.h" /* ca_attach_window */
|
|
21
22
|
#include <math.h>
|
|
22
23
|
#include <string.h>
|
|
23
24
|
#include <stdint.h>
|
|
@@ -47,12 +48,12 @@ enum {
|
|
|
47
48
|
typedef struct {
|
|
48
49
|
int kind;
|
|
49
50
|
VALUE rng;
|
|
50
|
-
CArray *state; /*
|
|
51
|
-
int64_t *cells;
|
|
51
|
+
CArray *state; /* the CArray::Rng state for CA_RNG_OWN, else NULL */
|
|
52
|
+
int64_t *cells; /* state->ptr, once the window has attached it */
|
|
52
53
|
} ca_rng_t;
|
|
53
54
|
|
|
54
55
|
static void
|
|
55
|
-
|
|
56
|
+
ca_rng_resolve (VALUE rng, ca_rng_t *source)
|
|
56
57
|
{
|
|
57
58
|
source->rng = rng;
|
|
58
59
|
source->state = NULL;
|
|
@@ -64,27 +65,46 @@ ca_rng_open (VALUE rng, ca_rng_t *source)
|
|
|
64
65
|
VALUE state = rb_ivar_get(rng, rb_intern("@state"));
|
|
65
66
|
CArray *ca;
|
|
66
67
|
TypedData_Get_Struct(state, CArray, &carray_data_type, ca);
|
|
67
|
-
ca_attach(ca);
|
|
68
68
|
source->kind = CA_RNG_OWN;
|
|
69
69
|
source->state = ca;
|
|
70
|
-
source->cells = (int64_t *) ca->ptr;
|
|
71
70
|
}
|
|
72
71
|
else {
|
|
73
72
|
source->kind = CA_RNG_RUBY;
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
/*
|
|
78
|
-
|
|
76
|
+
/* The fills below draw inside a window over the array and, for a
|
|
77
|
+
CArray::Rng, the generator's state. A Ruby generator (rng: a
|
|
78
|
+
::Random or anything with #rand) is called per draw and can raise part
|
|
79
|
+
way; the window then pushes back the cells drawn so far, and the state
|
|
80
|
+
they advanced, as it does when the fill completes. */
|
|
81
|
+
|
|
82
|
+
typedef struct {
|
|
83
|
+
CArray *ca;
|
|
84
|
+
ca_rng_t source;
|
|
85
|
+
ca_size_t n;
|
|
86
|
+
int is_default;
|
|
87
|
+
double low_dbl, high_dbl;
|
|
88
|
+
long low_long;
|
|
89
|
+
unsigned long limit;
|
|
90
|
+
int axis; /* shuffle!: -1 = all cells */
|
|
91
|
+
} ca_random_ctx_t;
|
|
92
|
+
|
|
79
93
|
static void
|
|
80
|
-
|
|
94
|
+
ca_random_run (ca_random_ctx_t *c, VALUE rng, VALUE (*fill)(VALUE))
|
|
81
95
|
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
96
|
+
CArray *list[2];
|
|
97
|
+
ca_rng_resolve(rng, &c->source);
|
|
98
|
+
list[0] = c->ca;
|
|
99
|
+
list[1] = c->source.state;
|
|
100
|
+
ca_attach_window(2, list, "ww", fill, (VALUE) c);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* The state is attached once the window is open. */
|
|
104
|
+
static void
|
|
105
|
+
ca_rng_bind (ca_rng_t *source)
|
|
106
|
+
{
|
|
107
|
+
source->cells = source->state ? (int64_t *) source->state->ptr : NULL;
|
|
88
108
|
}
|
|
89
109
|
|
|
90
110
|
static inline double
|
|
@@ -129,117 +149,28 @@ ca_random_ulong_limited (ca_rng_t *source, unsigned long limit)
|
|
|
129
149
|
|
|
130
150
|
/* ---- random! ----------------------------------------------------------- */
|
|
131
151
|
|
|
132
|
-
/* CArray#random!([low,] [high], rng:) — fill self with uniform random
|
|
133
|
-
* numbers in-place, returning self. Range surface mirrors Numo/NumPy
|
|
134
|
-
* (half-open [low, high) as the default) plus Ruby idiom (`..` closed,
|
|
135
|
-
* `...` half-open):
|
|
136
|
-
*
|
|
137
|
-
* random! float [0.0, 1.0); integer -> ArgumentError
|
|
138
|
-
* random!(high) [0, high) (Ruby rand shorthand)
|
|
139
|
-
* random!(low, high) [low, high) (Numo positional)
|
|
140
|
-
* random!(a..b) [a, b] closed (integer: b included)
|
|
141
|
-
* random!(a...b) [a, b) half-open
|
|
142
|
-
* random!(..., rng: r) any of the above with a custom Random source
|
|
143
|
-
*
|
|
144
|
-
* For float, `..` and `...` return the same distribution (endpoint
|
|
145
|
-
* probability ~2^-53); the closed form is honored syntactically but not
|
|
146
|
-
* enforced at the mantissa level, matching NumPy/SciPy convention.
|
|
147
|
-
* Boolean fills 0/1 with 50% probability each and ignores the range
|
|
148
|
-
* argument. Rejects CA_OBJECT / CA_FIXLEN. */
|
|
149
152
|
static VALUE
|
|
150
|
-
|
|
153
|
+
ca_random_bang_fill (VALUE arg)
|
|
151
154
|
{
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
int is_default =
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
long
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
VALUE rng = Qnil;
|
|
162
|
-
ca_rng_t source;
|
|
163
|
-
|
|
164
|
-
rb_scan_args(argc, argv, "02:", &arg1, &arg2, &opts);
|
|
165
|
-
rb_scan_options(opts, "rng", &rng);
|
|
166
|
-
|
|
167
|
-
/* Parse positional args into (low_val, high_val) + high_is_closed. */
|
|
168
|
-
if (rb_obj_is_kind_of(arg1, rb_cRange)) {
|
|
169
|
-
if (!NIL_P(arg2)) {
|
|
170
|
-
rb_raise(rb_eArgError,
|
|
171
|
-
"random: cannot combine a Range with a second positional arg");
|
|
172
|
-
}
|
|
173
|
-
low_val = rb_funcall(arg1, rb_intern("begin"), 0);
|
|
174
|
-
high_val = rb_funcall(arg1, rb_intern("end"), 0);
|
|
175
|
-
if (NIL_P(low_val) || NIL_P(high_val)) {
|
|
176
|
-
rb_raise(rb_eArgError,
|
|
177
|
-
"random: Range must have finite begin and end");
|
|
178
|
-
}
|
|
179
|
-
high_is_closed = ! RTEST(rb_funcall(arg1, rb_intern("exclude_end?"), 0));
|
|
180
|
-
is_default = 0;
|
|
181
|
-
} else if (!NIL_P(arg1) && !NIL_P(arg2)) {
|
|
182
|
-
low_val = arg1;
|
|
183
|
-
high_val = arg2;
|
|
184
|
-
is_default = 0;
|
|
185
|
-
} else if (!NIL_P(arg1)) {
|
|
186
|
-
low_val = INT2FIX(0);
|
|
187
|
-
high_val = arg1;
|
|
188
|
-
is_default = 0;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
rb_ca_modify(self);
|
|
192
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
193
|
-
|
|
194
|
-
if (ca->data_type == CA_OBJECT || ca->data_type == CA_FIXLEN) {
|
|
195
|
-
rb_raise(rb_eCADataTypeError,
|
|
196
|
-
"random! is not supported for object/fixlen arrays");
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/* Materialize (low, high) as the correct scalar type and validate.
|
|
200
|
-
* For integer data types, `..` closed adds 1 to high (turns into half-open
|
|
201
|
-
* for the sampler); for float data types, closed and half-open are
|
|
202
|
-
* equivalent so no adjustment. */
|
|
203
|
-
if (!is_default) {
|
|
204
|
-
int is_integer_type = (ca->data_type >= CA_INT8
|
|
205
|
-
&& ca->data_type <= CA_UINT64);
|
|
206
|
-
if (is_integer_type) {
|
|
207
|
-
low_long = NUM2LONG(low_val);
|
|
208
|
-
high_long = NUM2LONG(high_val);
|
|
209
|
-
if (high_is_closed) high_long += 1;
|
|
210
|
-
if (low_long >= high_long) {
|
|
211
|
-
rb_raise(rb_eArgError,
|
|
212
|
-
"random: low must be less than high "
|
|
213
|
-
"(got low=%ld, high=%ld)",
|
|
214
|
-
low_long, high_long);
|
|
215
|
-
}
|
|
216
|
-
limit = (unsigned long)(high_long - low_long) - 1;
|
|
217
|
-
} else {
|
|
218
|
-
low_dbl = NUM2DBL(low_val);
|
|
219
|
-
high_dbl = NUM2DBL(high_val);
|
|
220
|
-
if (low_dbl >= high_dbl) {
|
|
221
|
-
rb_raise(rb_eArgError,
|
|
222
|
-
"random: low must be less than high "
|
|
223
|
-
"(got low=%g, high=%g)",
|
|
224
|
-
low_dbl, high_dbl);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
n = ca->elements;
|
|
230
|
-
ca_attach(ca);
|
|
231
|
-
ca_rng_open(rng, &source);
|
|
232
|
-
|
|
155
|
+
ca_random_ctx_t *c = (ca_random_ctx_t *) arg;
|
|
156
|
+
CArray *ca = c->ca;
|
|
157
|
+
ca_size_t i, n = c->n;
|
|
158
|
+
int is_default = c->is_default;
|
|
159
|
+
double low_dbl = c->low_dbl, high_dbl = c->high_dbl;
|
|
160
|
+
long low_long = c->low_long;
|
|
161
|
+
unsigned long limit = c->limit;
|
|
162
|
+
|
|
163
|
+
ca_rng_bind(&c->source);
|
|
233
164
|
switch (ca->data_type) {
|
|
234
165
|
case CA_FLOAT64: {
|
|
235
166
|
double *p = (double *)ca->ptr;
|
|
236
167
|
if (is_default) {
|
|
237
168
|
for (i = 0; i < n; i++)
|
|
238
|
-
p[i] = ca_random_real(&source);
|
|
169
|
+
p[i] = ca_random_real(&c->source);
|
|
239
170
|
} else {
|
|
240
171
|
double range = high_dbl - low_dbl;
|
|
241
172
|
for (i = 0; i < n; i++)
|
|
242
|
-
p[i] = low_dbl + ca_random_real(&source) * range;
|
|
173
|
+
p[i] = low_dbl + ca_random_real(&c->source) * range;
|
|
243
174
|
}
|
|
244
175
|
break;
|
|
245
176
|
}
|
|
@@ -247,11 +178,11 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
247
178
|
float *p = (float *)ca->ptr;
|
|
248
179
|
if (is_default) {
|
|
249
180
|
for (i = 0; i < n; i++)
|
|
250
|
-
p[i] = (float)ca_random_real(&source);
|
|
181
|
+
p[i] = (float)ca_random_real(&c->source);
|
|
251
182
|
} else {
|
|
252
183
|
double range = high_dbl - low_dbl;
|
|
253
184
|
for (i = 0; i < n; i++)
|
|
254
|
-
p[i] = (float)(low_dbl + ca_random_real(&source) * range);
|
|
185
|
+
p[i] = (float)(low_dbl + ca_random_real(&c->source) * range);
|
|
255
186
|
}
|
|
256
187
|
break;
|
|
257
188
|
}
|
|
@@ -259,12 +190,12 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
259
190
|
double complex *p = (double complex *)ca->ptr;
|
|
260
191
|
if (is_default) {
|
|
261
192
|
for (i = 0; i < n; i++)
|
|
262
|
-
p[i] = ca_random_real(&source) + ca_random_real(&source) * I;
|
|
193
|
+
p[i] = ca_random_real(&c->source) + ca_random_real(&c->source) * I;
|
|
263
194
|
} else {
|
|
264
195
|
double range = high_dbl - low_dbl;
|
|
265
196
|
for (i = 0; i < n; i++)
|
|
266
|
-
p[i] = (low_dbl + ca_random_real(&source) * range)
|
|
267
|
-
+ (low_dbl + ca_random_real(&source) * range) * I;
|
|
197
|
+
p[i] = (low_dbl + ca_random_real(&c->source) * range)
|
|
198
|
+
+ (low_dbl + ca_random_real(&c->source) * range) * I;
|
|
268
199
|
}
|
|
269
200
|
break;
|
|
270
201
|
}
|
|
@@ -272,27 +203,24 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
272
203
|
float complex *p = (float complex *)ca->ptr;
|
|
273
204
|
if (is_default) {
|
|
274
205
|
for (i = 0; i < n; i++)
|
|
275
|
-
p[i] = (float)ca_random_real(&source) + (float)ca_random_real(&source) * I;
|
|
206
|
+
p[i] = (float)ca_random_real(&c->source) + (float)ca_random_real(&c->source) * I;
|
|
276
207
|
} else {
|
|
277
208
|
double range = high_dbl - low_dbl;
|
|
278
209
|
for (i = 0; i < n; i++)
|
|
279
|
-
p[i] = (float)(low_dbl + ca_random_real(&source) * range)
|
|
280
|
-
+ (float)(low_dbl + ca_random_real(&source) * range) * I;
|
|
210
|
+
p[i] = (float)(low_dbl + ca_random_real(&c->source) * range)
|
|
211
|
+
+ (float)(low_dbl + ca_random_real(&c->source) * range) * I;
|
|
281
212
|
}
|
|
282
213
|
break;
|
|
283
214
|
}
|
|
284
215
|
case CA_BOOLEAN: {
|
|
285
216
|
boolean8_t *p = (boolean8_t *)ca->ptr;
|
|
286
217
|
for (i = 0; i < n; i++)
|
|
287
|
-
p[i] = (ca_random_real(&source) < 0.5) ? 1 : 0;
|
|
218
|
+
p[i] = (ca_random_real(&c->source) < 0.5) ? 1 : 0;
|
|
288
219
|
break;
|
|
289
220
|
}
|
|
290
221
|
default: {
|
|
291
222
|
/* integer types: CA_INT8..CA_UINT64 */
|
|
292
223
|
if (is_default) {
|
|
293
|
-
ca_rng_close(&source);
|
|
294
|
-
ca_sync(ca);
|
|
295
|
-
ca_detach(ca);
|
|
296
224
|
rb_raise(rb_eArgError,
|
|
297
225
|
"random! on an integer array requires a range: "
|
|
298
226
|
"a.random!(high), a.random!(low, high), or "
|
|
@@ -302,55 +230,52 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
302
230
|
case CA_INT8: {
|
|
303
231
|
int8_t *p = (int8_t *)ca->ptr;
|
|
304
232
|
for (i = 0; i < n; i++)
|
|
305
|
-
p[i] = (int8_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
233
|
+
p[i] = (int8_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
306
234
|
break;
|
|
307
235
|
}
|
|
308
236
|
case CA_UINT8: {
|
|
309
237
|
uint8_t *p = (uint8_t *)ca->ptr;
|
|
310
238
|
for (i = 0; i < n; i++)
|
|
311
|
-
p[i] = (uint8_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
239
|
+
p[i] = (uint8_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
312
240
|
break;
|
|
313
241
|
}
|
|
314
242
|
case CA_INT16: {
|
|
315
243
|
int16_t *p = (int16_t *)ca->ptr;
|
|
316
244
|
for (i = 0; i < n; i++)
|
|
317
|
-
p[i] = (int16_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
245
|
+
p[i] = (int16_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
318
246
|
break;
|
|
319
247
|
}
|
|
320
248
|
case CA_UINT16: {
|
|
321
249
|
uint16_t *p = (uint16_t *)ca->ptr;
|
|
322
250
|
for (i = 0; i < n; i++)
|
|
323
|
-
p[i] = (uint16_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
251
|
+
p[i] = (uint16_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
324
252
|
break;
|
|
325
253
|
}
|
|
326
254
|
case CA_INT32: {
|
|
327
255
|
int32_t *p = (int32_t *)ca->ptr;
|
|
328
256
|
for (i = 0; i < n; i++)
|
|
329
|
-
p[i] = (int32_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
257
|
+
p[i] = (int32_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
330
258
|
break;
|
|
331
259
|
}
|
|
332
260
|
case CA_UINT32: {
|
|
333
261
|
uint32_t *p = (uint32_t *)ca->ptr;
|
|
334
262
|
for (i = 0; i < n; i++)
|
|
335
|
-
p[i] = (uint32_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
263
|
+
p[i] = (uint32_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
336
264
|
break;
|
|
337
265
|
}
|
|
338
266
|
case CA_INT64: {
|
|
339
267
|
int64_t *p = (int64_t *)ca->ptr;
|
|
340
268
|
for (i = 0; i < n; i++)
|
|
341
|
-
p[i] = (int64_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
269
|
+
p[i] = (int64_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
342
270
|
break;
|
|
343
271
|
}
|
|
344
272
|
case CA_UINT64: {
|
|
345
273
|
uint64_t *p = (uint64_t *)ca->ptr;
|
|
346
274
|
for (i = 0; i < n; i++)
|
|
347
|
-
p[i] = (uint64_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
275
|
+
p[i] = (uint64_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
348
276
|
break;
|
|
349
277
|
}
|
|
350
278
|
default:
|
|
351
|
-
ca_rng_close(&source);
|
|
352
|
-
ca_sync(ca);
|
|
353
|
-
ca_detach(ca);
|
|
354
279
|
rb_raise(rb_eCADataTypeError,
|
|
355
280
|
"random! is not supported for this data type");
|
|
356
281
|
}
|
|
@@ -358,9 +283,115 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
358
283
|
}
|
|
359
284
|
}
|
|
360
285
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
286
|
+
return Qnil;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* CArray#random!([low,] [high], rng:) — fill self with uniform random
|
|
290
|
+
* numbers in-place, returning self. Range surface mirrors Numo/NumPy
|
|
291
|
+
* (half-open [low, high) as the default) plus Ruby idiom (`..` closed,
|
|
292
|
+
* `...` half-open):
|
|
293
|
+
*
|
|
294
|
+
* random! float [0.0, 1.0); integer -> ArgumentError
|
|
295
|
+
* random!(high) [0, high) (Ruby rand shorthand)
|
|
296
|
+
* random!(low, high) [low, high) (Numo positional)
|
|
297
|
+
* random!(a..b) [a, b] closed (integer: b included)
|
|
298
|
+
* random!(a...b) [a, b) half-open
|
|
299
|
+
* random!(..., rng: r) any of the above with a custom Random source
|
|
300
|
+
*
|
|
301
|
+
* For float, `..` and `...` return the same distribution (endpoint
|
|
302
|
+
* probability ~2^-53); the closed form is honored syntactically but not
|
|
303
|
+
* enforced at the mantissa level, matching NumPy/SciPy convention.
|
|
304
|
+
* Boolean fills 0/1 with 50% probability each and ignores the range
|
|
305
|
+
* argument. Rejects CA_OBJECT / CA_FIXLEN. */
|
|
306
|
+
static VALUE
|
|
307
|
+
rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
308
|
+
{
|
|
309
|
+
CArray *ca;
|
|
310
|
+
VALUE arg1 = Qnil, arg2 = Qnil, opts = Qnil;
|
|
311
|
+
VALUE low_val = Qnil, high_val = Qnil;
|
|
312
|
+
int is_default = 1;
|
|
313
|
+
int high_is_closed = 0;
|
|
314
|
+
double low_dbl = 0.0, high_dbl = 0.0;
|
|
315
|
+
long low_long = 0, high_long = 0;
|
|
316
|
+
unsigned long limit = 0;
|
|
317
|
+
VALUE rng = Qnil;
|
|
318
|
+
|
|
319
|
+
rb_scan_args(argc, argv, "02:", &arg1, &arg2, &opts);
|
|
320
|
+
rb_scan_options(opts, "rng", &rng);
|
|
321
|
+
|
|
322
|
+
/* Parse positional args into (low_val, high_val) + high_is_closed. */
|
|
323
|
+
if (rb_obj_is_kind_of(arg1, rb_cRange)) {
|
|
324
|
+
if (!NIL_P(arg2)) {
|
|
325
|
+
rb_raise(rb_eArgError,
|
|
326
|
+
"random: cannot combine a Range with a second positional arg");
|
|
327
|
+
}
|
|
328
|
+
low_val = rb_funcall(arg1, rb_intern("begin"), 0);
|
|
329
|
+
high_val = rb_funcall(arg1, rb_intern("end"), 0);
|
|
330
|
+
if (NIL_P(low_val) || NIL_P(high_val)) {
|
|
331
|
+
rb_raise(rb_eArgError,
|
|
332
|
+
"random: Range must have finite begin and end");
|
|
333
|
+
}
|
|
334
|
+
high_is_closed = ! RTEST(rb_funcall(arg1, rb_intern("exclude_end?"), 0));
|
|
335
|
+
is_default = 0;
|
|
336
|
+
} else if (!NIL_P(arg1) && !NIL_P(arg2)) {
|
|
337
|
+
low_val = arg1;
|
|
338
|
+
high_val = arg2;
|
|
339
|
+
is_default = 0;
|
|
340
|
+
} else if (!NIL_P(arg1)) {
|
|
341
|
+
low_val = INT2FIX(0);
|
|
342
|
+
high_val = arg1;
|
|
343
|
+
is_default = 0;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
rb_ca_modify(self);
|
|
347
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
348
|
+
|
|
349
|
+
if (ca->data_type == CA_OBJECT || ca->data_type == CA_FIXLEN) {
|
|
350
|
+
rb_raise(rb_eCADataTypeError,
|
|
351
|
+
"random! is not supported for object/fixlen arrays");
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/* Materialize (low, high) as the correct scalar type and validate.
|
|
355
|
+
* For integer data types, `..` closed adds 1 to high (turns into half-open
|
|
356
|
+
* for the sampler); for float data types, closed and half-open are
|
|
357
|
+
* equivalent so no adjustment. */
|
|
358
|
+
if (!is_default) {
|
|
359
|
+
int is_integer_type = (ca->data_type >= CA_INT8
|
|
360
|
+
&& ca->data_type <= CA_UINT64);
|
|
361
|
+
if (is_integer_type) {
|
|
362
|
+
low_long = NUM2LONG(low_val);
|
|
363
|
+
high_long = NUM2LONG(high_val);
|
|
364
|
+
if (high_is_closed) high_long += 1;
|
|
365
|
+
if (low_long >= high_long) {
|
|
366
|
+
rb_raise(rb_eArgError,
|
|
367
|
+
"random: low must be less than high "
|
|
368
|
+
"(got low=%ld, high=%ld)",
|
|
369
|
+
low_long, high_long);
|
|
370
|
+
}
|
|
371
|
+
limit = (unsigned long)(high_long - low_long) - 1;
|
|
372
|
+
} else {
|
|
373
|
+
low_dbl = NUM2DBL(low_val);
|
|
374
|
+
high_dbl = NUM2DBL(high_val);
|
|
375
|
+
if (low_dbl >= high_dbl) {
|
|
376
|
+
rb_raise(rb_eArgError,
|
|
377
|
+
"random: low must be less than high "
|
|
378
|
+
"(got low=%g, high=%g)",
|
|
379
|
+
low_dbl, high_dbl);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
{
|
|
385
|
+
ca_random_ctx_t c;
|
|
386
|
+
c.ca = ca;
|
|
387
|
+
c.n = ca->elements;
|
|
388
|
+
c.is_default = is_default;
|
|
389
|
+
c.low_dbl = low_dbl;
|
|
390
|
+
c.high_dbl = high_dbl;
|
|
391
|
+
c.low_long = low_long;
|
|
392
|
+
c.limit = limit;
|
|
393
|
+
ca_random_run(&c, rng, ca_random_bang_fill);
|
|
394
|
+
}
|
|
364
395
|
return self;
|
|
365
396
|
}
|
|
366
397
|
|
|
@@ -396,53 +427,31 @@ box_muller_pair(ca_rng_t *source, double *r1, double *r2)
|
|
|
396
427
|
*r2 = r * sin(theta);
|
|
397
428
|
}
|
|
398
429
|
|
|
399
|
-
/* CArray#randomn!(rng:) — fill self with standard normal N(0, 1)
|
|
400
|
-
* samples in-place via Box-Muller, returning self.
|
|
401
|
-
*
|
|
402
|
-
* Restricted to float / complex data types. Complex fills real + imag as
|
|
403
|
-
* two independent normals per cell. */
|
|
404
430
|
static VALUE
|
|
405
|
-
|
|
431
|
+
ca_randomn_bang_fill (VALUE arg)
|
|
406
432
|
{
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
ca_size_t i, n;
|
|
410
|
-
|
|
411
|
-
rb_scan_args(argc, argv, "0:", &opts);
|
|
412
|
-
VALUE rng = Qnil;
|
|
413
|
-
ca_rng_t source;
|
|
414
|
-
rb_scan_options(opts, "rng", &rng);
|
|
415
|
-
|
|
416
|
-
rb_ca_modify(self);
|
|
417
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
418
|
-
|
|
419
|
-
if (ca->data_type != CA_FLOAT64 && ca->data_type != CA_FLOAT32 &&
|
|
420
|
-
ca->data_type != CA_CMPLX128 && ca->data_type != CA_CMPLX64) {
|
|
421
|
-
rb_raise(rb_eCADataTypeError,
|
|
422
|
-
"randomn! requires float or complex array");
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
n = ca->elements;
|
|
426
|
-
ca_attach(ca);
|
|
427
|
-
ca_rng_open(rng, &source);
|
|
433
|
+
ca_random_ctx_t *c = (ca_random_ctx_t *) arg;
|
|
434
|
+
CArray *ca = c->ca;
|
|
435
|
+
ca_size_t i, n = c->n;
|
|
428
436
|
|
|
437
|
+
ca_rng_bind(&c->source);
|
|
429
438
|
/* A CArray::Rng fills one cell per call rather than two, so that this
|
|
430
439
|
and a kernel drawing afterwards are the one sequence: both are
|
|
431
440
|
`ca_random_normal` run once per cell. It costs a draw a cell over
|
|
432
441
|
the paired form, and what it buys is that where the generator
|
|
433
442
|
stands can be worked out rather than run. */
|
|
434
|
-
if (source.kind == CA_RNG_OWN) {
|
|
443
|
+
if (c->source.kind == CA_RNG_OWN) {
|
|
435
444
|
switch (ca->data_type) {
|
|
436
445
|
case CA_FLOAT64: {
|
|
437
446
|
double *p = (double *)ca->ptr;
|
|
438
447
|
for (i = 0; i < n; i++)
|
|
439
|
-
p[i] = ca_random_normal(&source);
|
|
448
|
+
p[i] = ca_random_normal(&c->source);
|
|
440
449
|
break;
|
|
441
450
|
}
|
|
442
451
|
case CA_FLOAT32: {
|
|
443
452
|
float *p = (float *)ca->ptr;
|
|
444
453
|
for (i = 0; i < n; i++)
|
|
445
|
-
p[i] = (float) ca_random_normal(&source);
|
|
454
|
+
p[i] = (float) ca_random_normal(&c->source);
|
|
446
455
|
break;
|
|
447
456
|
}
|
|
448
457
|
case CA_CMPLX128: {
|
|
@@ -450,8 +459,8 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
450
459
|
for (i = 0; i < n; i++) {
|
|
451
460
|
/* Into locals first: C does not say which order a call's
|
|
452
461
|
arguments are evaluated in, and these two advance a state. */
|
|
453
|
-
double re = ca_random_normal(&source);
|
|
454
|
-
double im = ca_random_normal(&source);
|
|
462
|
+
double re = ca_random_normal(&c->source);
|
|
463
|
+
double im = ca_random_normal(&c->source);
|
|
455
464
|
p[i] = re + im * I;
|
|
456
465
|
}
|
|
457
466
|
break;
|
|
@@ -459,8 +468,8 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
459
468
|
case CA_CMPLX64: {
|
|
460
469
|
float complex *p = (float complex *)ca->ptr;
|
|
461
470
|
for (i = 0; i < n; i++) {
|
|
462
|
-
double re = ca_random_normal(&source);
|
|
463
|
-
double im = ca_random_normal(&source);
|
|
471
|
+
double re = ca_random_normal(&c->source);
|
|
472
|
+
double im = ca_random_normal(&c->source);
|
|
464
473
|
p[i] = (float) re + (float) im * I;
|
|
465
474
|
}
|
|
466
475
|
break;
|
|
@@ -468,10 +477,7 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
468
477
|
default:
|
|
469
478
|
break;
|
|
470
479
|
}
|
|
471
|
-
|
|
472
|
-
ca_sync(ca);
|
|
473
|
-
ca_detach(ca);
|
|
474
|
-
return self;
|
|
480
|
+
return Qnil;
|
|
475
481
|
}
|
|
476
482
|
|
|
477
483
|
switch (ca->data_type) {
|
|
@@ -479,11 +485,11 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
479
485
|
double *p = (double *)ca->ptr;
|
|
480
486
|
ca_size_t pairs = n / 2;
|
|
481
487
|
for (i = 0; i < pairs; i++) {
|
|
482
|
-
box_muller_pair(&source, &p[2*i], &p[2*i+1]);
|
|
488
|
+
box_muller_pair(&c->source, &p[2*i], &p[2*i+1]);
|
|
483
489
|
}
|
|
484
490
|
if (n % 2 == 1) {
|
|
485
491
|
double r1, r2;
|
|
486
|
-
box_muller_pair(&source, &r1, &r2);
|
|
492
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
487
493
|
p[n-1] = r1;
|
|
488
494
|
}
|
|
489
495
|
break;
|
|
@@ -493,13 +499,13 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
493
499
|
ca_size_t pairs = n / 2;
|
|
494
500
|
for (i = 0; i < pairs; i++) {
|
|
495
501
|
double r1, r2;
|
|
496
|
-
box_muller_pair(&source, &r1, &r2);
|
|
502
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
497
503
|
p[2*i] = (float)r1;
|
|
498
504
|
p[2*i+1] = (float)r2;
|
|
499
505
|
}
|
|
500
506
|
if (n % 2 == 1) {
|
|
501
507
|
double r1, r2;
|
|
502
|
-
box_muller_pair(&source, &r1, &r2);
|
|
508
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
503
509
|
p[n-1] = (float)r1;
|
|
504
510
|
}
|
|
505
511
|
break;
|
|
@@ -508,7 +514,7 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
508
514
|
double complex *p = (double complex *)ca->ptr;
|
|
509
515
|
for (i = 0; i < n; i++) {
|
|
510
516
|
double r1, r2;
|
|
511
|
-
box_muller_pair(&source, &r1, &r2);
|
|
517
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
512
518
|
p[i] = r1 + r2 * I;
|
|
513
519
|
}
|
|
514
520
|
break;
|
|
@@ -517,7 +523,7 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
517
523
|
float complex *p = (float complex *)ca->ptr;
|
|
518
524
|
for (i = 0; i < n; i++) {
|
|
519
525
|
double r1, r2;
|
|
520
|
-
box_muller_pair(&source, &r1, &r2);
|
|
526
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
521
527
|
p[i] = (float)r1 + (float)r2 * I;
|
|
522
528
|
}
|
|
523
529
|
break;
|
|
@@ -526,9 +532,39 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
526
532
|
break;
|
|
527
533
|
}
|
|
528
534
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
535
|
+
return Qnil;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/* CArray#randomn!(rng:) — fill self with standard normal N(0, 1)
|
|
539
|
+
* samples in-place via Box-Muller, returning self.
|
|
540
|
+
*
|
|
541
|
+
* Restricted to float / complex data types. Complex fills real + imag as
|
|
542
|
+
* two independent normals per cell. */
|
|
543
|
+
static VALUE
|
|
544
|
+
rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
545
|
+
{
|
|
546
|
+
CArray *ca;
|
|
547
|
+
VALUE opts = Qnil;
|
|
548
|
+
|
|
549
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
550
|
+
VALUE rng = Qnil;
|
|
551
|
+
rb_scan_options(opts, "rng", &rng);
|
|
552
|
+
|
|
553
|
+
rb_ca_modify(self);
|
|
554
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
555
|
+
|
|
556
|
+
if (ca->data_type != CA_FLOAT64 && ca->data_type != CA_FLOAT32 &&
|
|
557
|
+
ca->data_type != CA_CMPLX128 && ca->data_type != CA_CMPLX64) {
|
|
558
|
+
rb_raise(rb_eCADataTypeError,
|
|
559
|
+
"randomn! requires float or complex array");
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
{
|
|
563
|
+
ca_random_ctx_t c;
|
|
564
|
+
c.ca = ca;
|
|
565
|
+
c.n = ca->elements;
|
|
566
|
+
ca_random_run(&c, rng, ca_randomn_bang_fill);
|
|
567
|
+
}
|
|
532
568
|
return self;
|
|
533
569
|
}
|
|
534
570
|
|
|
@@ -550,59 +586,35 @@ swap_chunks(char *a, char *b, ca_size_t chunk_bytes, char *tmp)
|
|
|
550
586
|
* as a byte chunk and swapped whole, so multi-dim slices move
|
|
551
587
|
* together). */
|
|
552
588
|
static VALUE
|
|
553
|
-
|
|
589
|
+
ca_shuffle_bang_fill (VALUE arg)
|
|
554
590
|
{
|
|
555
|
-
|
|
556
|
-
|
|
591
|
+
ca_random_ctx_t *c = (ca_random_ctx_t *) arg;
|
|
592
|
+
CArray *ca = c->ca;
|
|
557
593
|
ca_size_t n;
|
|
558
|
-
int axis = -1;
|
|
559
594
|
|
|
560
|
-
|
|
561
|
-
VALUE rng = Qnil;
|
|
562
|
-
ca_rng_t source;
|
|
563
|
-
rb_scan_options(opts, "rng,axis", &rng, &v_axis);
|
|
564
|
-
|
|
565
|
-
rb_ca_modify(self);
|
|
566
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
567
|
-
|
|
568
|
-
if (ca->elements <= 1) return self;
|
|
569
|
-
|
|
570
|
-
ca_attach(ca);
|
|
571
|
-
ca_rng_open(rng, &source);
|
|
595
|
+
ca_rng_bind(&c->source);
|
|
572
596
|
|
|
573
|
-
if (
|
|
597
|
+
if (c->axis < 0) {
|
|
574
598
|
/* shuffle all elements */
|
|
575
|
-
|
|
599
|
+
volatile VALUE tmp_holder;
|
|
576
600
|
ca_size_t elem_bytes = ca->bytes;
|
|
577
|
-
char *tmp = (char
|
|
601
|
+
char *tmp = ALLOCV_N(char, tmp_holder, elem_bytes);
|
|
578
602
|
char *p = ca->ptr;
|
|
579
603
|
|
|
604
|
+
n = ca->elements;
|
|
580
605
|
for (ca_size_t i = n - 1; i > 0; i--) {
|
|
581
|
-
unsigned long j = ca_random_ulong_limited(&source, (unsigned long)i);
|
|
606
|
+
unsigned long j = ca_random_ulong_limited(&c->source, (unsigned long)i);
|
|
582
607
|
if ((ca_size_t)j != i) {
|
|
583
608
|
swap_chunks(p + i * elem_bytes, p + j * elem_bytes, elem_bytes, tmp);
|
|
584
609
|
}
|
|
585
610
|
}
|
|
586
|
-
|
|
611
|
+
ALLOCV_END(tmp_holder);
|
|
587
612
|
}
|
|
588
613
|
else {
|
|
589
|
-
axis =
|
|
590
|
-
|
|
591
|
-
if (axis < 0 || axis >= ca->ndim) {
|
|
592
|
-
ca_rng_close(&source);
|
|
593
|
-
ca_sync(ca);
|
|
594
|
-
ca_detach(ca);
|
|
595
|
-
rb_raise(rb_eArgError,
|
|
596
|
-
"axis %d is out of range for ndim %d", axis, ca->ndim);
|
|
597
|
-
}
|
|
614
|
+
int axis = c->axis;
|
|
615
|
+
volatile VALUE tmp_holder;
|
|
598
616
|
|
|
599
617
|
n = ca->dim[axis];
|
|
600
|
-
if (n <= 1) {
|
|
601
|
-
ca_rng_close(&source);
|
|
602
|
-
ca_sync(ca);
|
|
603
|
-
ca_detach(ca);
|
|
604
|
-
return self;
|
|
605
|
-
}
|
|
606
618
|
|
|
607
619
|
ca_size_t outer = 1;
|
|
608
620
|
for (int d = 0; d < axis; d++)
|
|
@@ -614,12 +626,12 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
614
626
|
|
|
615
627
|
ca_size_t chunk_bytes = inner * ca->bytes;
|
|
616
628
|
ca_size_t stride = n * chunk_bytes;
|
|
617
|
-
char *tmp = (char
|
|
629
|
+
char *tmp = ALLOCV_N(char, tmp_holder, chunk_bytes);
|
|
618
630
|
|
|
619
631
|
for (ca_size_t o = 0; o < outer; o++) {
|
|
620
632
|
char *base = ca->ptr + o * stride;
|
|
621
633
|
for (ca_size_t i = n - 1; i > 0; i--) {
|
|
622
|
-
unsigned long j = ca_random_ulong_limited(&source, (unsigned long)i);
|
|
634
|
+
unsigned long j = ca_random_ulong_limited(&c->source, (unsigned long)i);
|
|
623
635
|
if ((ca_size_t)j != i) {
|
|
624
636
|
swap_chunks(base + i * chunk_bytes,
|
|
625
637
|
base + j * chunk_bytes,
|
|
@@ -627,12 +639,38 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
627
639
|
}
|
|
628
640
|
}
|
|
629
641
|
}
|
|
630
|
-
|
|
642
|
+
ALLOCV_END(tmp_holder);
|
|
643
|
+
}
|
|
644
|
+
return Qnil;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
static VALUE
|
|
648
|
+
rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
649
|
+
{
|
|
650
|
+
CArray *ca;
|
|
651
|
+
VALUE opts = Qnil, v_axis = Qnil;
|
|
652
|
+
int axis = -1;
|
|
653
|
+
ca_random_ctx_t c;
|
|
654
|
+
|
|
655
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
656
|
+
VALUE rng = Qnil;
|
|
657
|
+
rb_scan_options(opts, "rng,axis", &rng, &v_axis);
|
|
658
|
+
|
|
659
|
+
rb_ca_modify(self);
|
|
660
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
661
|
+
|
|
662
|
+
if (ca->elements <= 1) return self;
|
|
663
|
+
|
|
664
|
+
if (!NIL_P(v_axis)) {
|
|
665
|
+
axis = rb_ca_normalize_axis_for_ndim(ca_axis_integer(v_axis, NULL), ca->ndim, NULL);
|
|
666
|
+
if (ca->dim[axis] <= 1) {
|
|
667
|
+
return self;
|
|
668
|
+
}
|
|
631
669
|
}
|
|
632
670
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
671
|
+
c.ca = ca;
|
|
672
|
+
c.axis = axis;
|
|
673
|
+
ca_random_run(&c, rng, ca_shuffle_bang_fill);
|
|
636
674
|
return self;
|
|
637
675
|
}
|
|
638
676
|
|
|
@@ -698,7 +736,7 @@ ca_rng_cells (VALUE self, int64_t **cells)
|
|
|
698
736
|
CArray *ca;
|
|
699
737
|
VALUE state = rb_ivar_get(self, rb_intern("@state"));
|
|
700
738
|
TypedData_Get_Struct(state, CArray, &carray_data_type, ca);
|
|
701
|
-
ca_attach(ca);
|
|
739
|
+
ca_attach(ca); /* window: the state is an entity, whose attach holds nothing */
|
|
702
740
|
*cells = (int64_t *) ca->ptr;
|
|
703
741
|
return ca;
|
|
704
742
|
}
|
|
@@ -752,8 +790,7 @@ rb_ca_rng_reset (int argc, VALUE *argv, VALUE self)
|
|
|
752
790
|
|
|
753
791
|
ca = ca_rng_cells(self, &cells);
|
|
754
792
|
ca_xoshiro256pp_seed(cells, (uint64_t) NUM2ULL(masked));
|
|
755
|
-
|
|
756
|
-
ca_detach(ca);
|
|
793
|
+
ca_sync_detach(ca);
|
|
757
794
|
|
|
758
795
|
rb_ivar_set(self, rb_intern("@seed"), seed);
|
|
759
796
|
return self;
|
|
@@ -779,8 +816,7 @@ rb_ca_rng_random (VALUE self)
|
|
|
779
816
|
|
|
780
817
|
ca = ca_rng_cells(self, &cells);
|
|
781
818
|
value = ca_xoshiro256pp_next_real(cells);
|
|
782
|
-
|
|
783
|
-
ca_detach(ca);
|
|
819
|
+
ca_sync_detach(ca);
|
|
784
820
|
return rb_float_new(value);
|
|
785
821
|
}
|
|
786
822
|
|
|
@@ -799,8 +835,7 @@ rb_ca_rng_bits (VALUE self)
|
|
|
799
835
|
|
|
800
836
|
ca = ca_rng_cells(self, &cells);
|
|
801
837
|
value = ca_xoshiro256pp_next(cells);
|
|
802
|
-
|
|
803
|
-
ca_detach(ca);
|
|
838
|
+
ca_sync_detach(ca);
|
|
804
839
|
return ULL2NUM(value);
|
|
805
840
|
}
|
|
806
841
|
|
|
@@ -823,8 +858,7 @@ rb_ca_rng_randomn (VALUE self)
|
|
|
823
858
|
source.state = NULL;
|
|
824
859
|
source.cells = cells;
|
|
825
860
|
value = ca_random_normal(&source);
|
|
826
|
-
|
|
827
|
-
ca_detach(ca);
|
|
861
|
+
ca_sync_detach(ca);
|
|
828
862
|
return rb_float_new(value);
|
|
829
863
|
}
|
|
830
864
|
|