carray 3.0.2 → 3.0.4
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 +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- 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 +104 -81
- 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 +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- 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/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -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 +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
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,48 @@ 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
|
+
CArray *mask; /* shuffle!: self's mask, moved with the values */
|
|
92
|
+
} ca_random_ctx_t;
|
|
93
|
+
|
|
79
94
|
static void
|
|
80
|
-
|
|
95
|
+
ca_random_run (ca_random_ctx_t *c, VALUE rng, VALUE (*fill)(VALUE))
|
|
81
96
|
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
97
|
+
CArray *list[3];
|
|
98
|
+
ca_rng_resolve(rng, &c->source);
|
|
99
|
+
list[0] = c->ca;
|
|
100
|
+
list[1] = c->source.state;
|
|
101
|
+
list[2] = c->mask;
|
|
102
|
+
ca_attach_window(c->mask ? 3 : 2, list, "www", fill, (VALUE) c);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* The state is attached once the window is open. */
|
|
106
|
+
static void
|
|
107
|
+
ca_rng_bind (ca_rng_t *source)
|
|
108
|
+
{
|
|
109
|
+
source->cells = source->state ? (int64_t *) source->state->ptr : NULL;
|
|
88
110
|
}
|
|
89
111
|
|
|
90
112
|
static inline double
|
|
@@ -129,117 +151,28 @@ ca_random_ulong_limited (ca_rng_t *source, unsigned long limit)
|
|
|
129
151
|
|
|
130
152
|
/* ---- random! ----------------------------------------------------------- */
|
|
131
153
|
|
|
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
154
|
static VALUE
|
|
150
|
-
|
|
155
|
+
ca_random_bang_fill (VALUE arg)
|
|
151
156
|
{
|
|
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
|
-
|
|
157
|
+
ca_random_ctx_t *c = (ca_random_ctx_t *) arg;
|
|
158
|
+
CArray *ca = c->ca;
|
|
159
|
+
ca_size_t i, n = c->n;
|
|
160
|
+
int is_default = c->is_default;
|
|
161
|
+
double low_dbl = c->low_dbl, high_dbl = c->high_dbl;
|
|
162
|
+
long low_long = c->low_long;
|
|
163
|
+
unsigned long limit = c->limit;
|
|
164
|
+
|
|
165
|
+
ca_rng_bind(&c->source);
|
|
233
166
|
switch (ca->data_type) {
|
|
234
167
|
case CA_FLOAT64: {
|
|
235
168
|
double *p = (double *)ca->ptr;
|
|
236
169
|
if (is_default) {
|
|
237
170
|
for (i = 0; i < n; i++)
|
|
238
|
-
p[i] = ca_random_real(&source);
|
|
171
|
+
p[i] = ca_random_real(&c->source);
|
|
239
172
|
} else {
|
|
240
173
|
double range = high_dbl - low_dbl;
|
|
241
174
|
for (i = 0; i < n; i++)
|
|
242
|
-
p[i] = low_dbl + ca_random_real(&source) * range;
|
|
175
|
+
p[i] = low_dbl + ca_random_real(&c->source) * range;
|
|
243
176
|
}
|
|
244
177
|
break;
|
|
245
178
|
}
|
|
@@ -247,11 +180,11 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
247
180
|
float *p = (float *)ca->ptr;
|
|
248
181
|
if (is_default) {
|
|
249
182
|
for (i = 0; i < n; i++)
|
|
250
|
-
p[i] = (float)ca_random_real(&source);
|
|
183
|
+
p[i] = (float)ca_random_real(&c->source);
|
|
251
184
|
} else {
|
|
252
185
|
double range = high_dbl - low_dbl;
|
|
253
186
|
for (i = 0; i < n; i++)
|
|
254
|
-
p[i] = (float)(low_dbl + ca_random_real(&source) * range);
|
|
187
|
+
p[i] = (float)(low_dbl + ca_random_real(&c->source) * range);
|
|
255
188
|
}
|
|
256
189
|
break;
|
|
257
190
|
}
|
|
@@ -259,12 +192,12 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
259
192
|
double complex *p = (double complex *)ca->ptr;
|
|
260
193
|
if (is_default) {
|
|
261
194
|
for (i = 0; i < n; i++)
|
|
262
|
-
p[i] = ca_random_real(&source) + ca_random_real(&source) * I;
|
|
195
|
+
p[i] = ca_random_real(&c->source) + ca_random_real(&c->source) * I;
|
|
263
196
|
} else {
|
|
264
197
|
double range = high_dbl - low_dbl;
|
|
265
198
|
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;
|
|
199
|
+
p[i] = (low_dbl + ca_random_real(&c->source) * range)
|
|
200
|
+
+ (low_dbl + ca_random_real(&c->source) * range) * I;
|
|
268
201
|
}
|
|
269
202
|
break;
|
|
270
203
|
}
|
|
@@ -272,27 +205,24 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
272
205
|
float complex *p = (float complex *)ca->ptr;
|
|
273
206
|
if (is_default) {
|
|
274
207
|
for (i = 0; i < n; i++)
|
|
275
|
-
p[i] = (float)ca_random_real(&source) + (float)ca_random_real(&source) * I;
|
|
208
|
+
p[i] = (float)ca_random_real(&c->source) + (float)ca_random_real(&c->source) * I;
|
|
276
209
|
} else {
|
|
277
210
|
double range = high_dbl - low_dbl;
|
|
278
211
|
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;
|
|
212
|
+
p[i] = (float)(low_dbl + ca_random_real(&c->source) * range)
|
|
213
|
+
+ (float)(low_dbl + ca_random_real(&c->source) * range) * I;
|
|
281
214
|
}
|
|
282
215
|
break;
|
|
283
216
|
}
|
|
284
217
|
case CA_BOOLEAN: {
|
|
285
218
|
boolean8_t *p = (boolean8_t *)ca->ptr;
|
|
286
219
|
for (i = 0; i < n; i++)
|
|
287
|
-
p[i] = (ca_random_real(&source) < 0.5) ? 1 : 0;
|
|
220
|
+
p[i] = (ca_random_real(&c->source) < 0.5) ? 1 : 0;
|
|
288
221
|
break;
|
|
289
222
|
}
|
|
290
223
|
default: {
|
|
291
224
|
/* integer types: CA_INT8..CA_UINT64 */
|
|
292
225
|
if (is_default) {
|
|
293
|
-
ca_rng_close(&source);
|
|
294
|
-
ca_sync(ca);
|
|
295
|
-
ca_detach(ca);
|
|
296
226
|
rb_raise(rb_eArgError,
|
|
297
227
|
"random! on an integer array requires a range: "
|
|
298
228
|
"a.random!(high), a.random!(low, high), or "
|
|
@@ -302,55 +232,52 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
302
232
|
case CA_INT8: {
|
|
303
233
|
int8_t *p = (int8_t *)ca->ptr;
|
|
304
234
|
for (i = 0; i < n; i++)
|
|
305
|
-
p[i] = (int8_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
235
|
+
p[i] = (int8_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
306
236
|
break;
|
|
307
237
|
}
|
|
308
238
|
case CA_UINT8: {
|
|
309
239
|
uint8_t *p = (uint8_t *)ca->ptr;
|
|
310
240
|
for (i = 0; i < n; i++)
|
|
311
|
-
p[i] = (uint8_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
241
|
+
p[i] = (uint8_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
312
242
|
break;
|
|
313
243
|
}
|
|
314
244
|
case CA_INT16: {
|
|
315
245
|
int16_t *p = (int16_t *)ca->ptr;
|
|
316
246
|
for (i = 0; i < n; i++)
|
|
317
|
-
p[i] = (int16_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
247
|
+
p[i] = (int16_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
318
248
|
break;
|
|
319
249
|
}
|
|
320
250
|
case CA_UINT16: {
|
|
321
251
|
uint16_t *p = (uint16_t *)ca->ptr;
|
|
322
252
|
for (i = 0; i < n; i++)
|
|
323
|
-
p[i] = (uint16_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
253
|
+
p[i] = (uint16_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
324
254
|
break;
|
|
325
255
|
}
|
|
326
256
|
case CA_INT32: {
|
|
327
257
|
int32_t *p = (int32_t *)ca->ptr;
|
|
328
258
|
for (i = 0; i < n; i++)
|
|
329
|
-
p[i] = (int32_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
259
|
+
p[i] = (int32_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
330
260
|
break;
|
|
331
261
|
}
|
|
332
262
|
case CA_UINT32: {
|
|
333
263
|
uint32_t *p = (uint32_t *)ca->ptr;
|
|
334
264
|
for (i = 0; i < n; i++)
|
|
335
|
-
p[i] = (uint32_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
265
|
+
p[i] = (uint32_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
336
266
|
break;
|
|
337
267
|
}
|
|
338
268
|
case CA_INT64: {
|
|
339
269
|
int64_t *p = (int64_t *)ca->ptr;
|
|
340
270
|
for (i = 0; i < n; i++)
|
|
341
|
-
p[i] = (int64_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
271
|
+
p[i] = (int64_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
342
272
|
break;
|
|
343
273
|
}
|
|
344
274
|
case CA_UINT64: {
|
|
345
275
|
uint64_t *p = (uint64_t *)ca->ptr;
|
|
346
276
|
for (i = 0; i < n; i++)
|
|
347
|
-
p[i] = (uint64_t)(low_long + ca_random_ulong_limited(&source, limit));
|
|
277
|
+
p[i] = (uint64_t)(low_long + ca_random_ulong_limited(&c->source, limit));
|
|
348
278
|
break;
|
|
349
279
|
}
|
|
350
280
|
default:
|
|
351
|
-
ca_rng_close(&source);
|
|
352
|
-
ca_sync(ca);
|
|
353
|
-
ca_detach(ca);
|
|
354
281
|
rb_raise(rb_eCADataTypeError,
|
|
355
282
|
"random! is not supported for this data type");
|
|
356
283
|
}
|
|
@@ -358,9 +285,153 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
|
358
285
|
}
|
|
359
286
|
}
|
|
360
287
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
288
|
+
return Qnil;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* CArray#random!([low,] [high], rng:) — fill self with uniform random
|
|
292
|
+
* numbers in-place, returning self. Range surface mirrors Numo/NumPy
|
|
293
|
+
* (half-open [low, high) as the default) plus Ruby idiom (`..` closed,
|
|
294
|
+
* `...` half-open):
|
|
295
|
+
*
|
|
296
|
+
* random! float [0.0, 1.0); integer -> ArgumentError
|
|
297
|
+
* random!(high) [0, high) (Ruby rand shorthand)
|
|
298
|
+
* random!(low, high) [low, high) (Numo positional)
|
|
299
|
+
* random!(a..b) [a, b] closed (integer: b included)
|
|
300
|
+
* random!(a...b) [a, b) half-open
|
|
301
|
+
* random!(..., rng: r) any of the above with a custom Random source
|
|
302
|
+
*
|
|
303
|
+
* For float, `..` and `...` return the same distribution (endpoint
|
|
304
|
+
* probability ~2^-53); the closed form is honored syntactically but not
|
|
305
|
+
* enforced at the mantissa level, matching NumPy/SciPy convention.
|
|
306
|
+
* Boolean fills 0/1 with 50% probability each and ignores the range
|
|
307
|
+
* argument. Rejects CA_OBJECT / CA_FIXLEN. */
|
|
308
|
+
static VALUE
|
|
309
|
+
rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
|
|
310
|
+
{
|
|
311
|
+
CArray *ca;
|
|
312
|
+
VALUE arg1 = Qnil, arg2 = Qnil, opts = Qnil;
|
|
313
|
+
VALUE low_val = Qnil, high_val = Qnil;
|
|
314
|
+
int is_default = 1;
|
|
315
|
+
int high_is_closed = 0;
|
|
316
|
+
double low_dbl = 0.0, high_dbl = 0.0;
|
|
317
|
+
long low_long = 0, high_long = 0;
|
|
318
|
+
unsigned long limit = 0;
|
|
319
|
+
VALUE rng = Qnil;
|
|
320
|
+
|
|
321
|
+
rb_scan_args(argc, argv, "02:", &arg1, &arg2, &opts);
|
|
322
|
+
rb_scan_options(opts, "rng", &rng);
|
|
323
|
+
|
|
324
|
+
/* Parse positional args into (low_val, high_val) + high_is_closed. */
|
|
325
|
+
if (rb_obj_is_kind_of(arg1, rb_cRange)) {
|
|
326
|
+
if (!NIL_P(arg2)) {
|
|
327
|
+
rb_raise(rb_eArgError,
|
|
328
|
+
"random: cannot combine a Range with a second positional arg");
|
|
329
|
+
}
|
|
330
|
+
low_val = rb_funcall(arg1, rb_intern("begin"), 0);
|
|
331
|
+
high_val = rb_funcall(arg1, rb_intern("end"), 0);
|
|
332
|
+
if (NIL_P(low_val) || NIL_P(high_val)) {
|
|
333
|
+
rb_raise(rb_eArgError,
|
|
334
|
+
"random: Range must have finite begin and end");
|
|
335
|
+
}
|
|
336
|
+
high_is_closed = ! RTEST(rb_funcall(arg1, rb_intern("exclude_end?"), 0));
|
|
337
|
+
is_default = 0;
|
|
338
|
+
} else if (!NIL_P(arg1) && !NIL_P(arg2)) {
|
|
339
|
+
low_val = arg1;
|
|
340
|
+
high_val = arg2;
|
|
341
|
+
is_default = 0;
|
|
342
|
+
} else if (!NIL_P(arg1)) {
|
|
343
|
+
low_val = INT2FIX(0);
|
|
344
|
+
high_val = arg1;
|
|
345
|
+
is_default = 0;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
rb_ca_modify(self);
|
|
349
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
350
|
+
|
|
351
|
+
if (ca->data_type == CA_OBJECT || ca->data_type == CA_FIXLEN) {
|
|
352
|
+
rb_raise(rb_eCADataTypeError,
|
|
353
|
+
"random! is not supported for object/fixlen arrays");
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/* Materialize (low, high) as the correct scalar type and validate.
|
|
357
|
+
* For integer data types, `..` closed adds 1 to high (turns into half-open
|
|
358
|
+
* for the sampler); for float data types, closed and half-open are
|
|
359
|
+
* equivalent so no adjustment. */
|
|
360
|
+
if (!is_default) {
|
|
361
|
+
int is_integer_type = (ca->data_type >= CA_INT8
|
|
362
|
+
&& ca->data_type <= CA_UINT64);
|
|
363
|
+
if (is_integer_type) {
|
|
364
|
+
/* The bounds stay Ruby Integers until they are known to fit: the
|
|
365
|
+
last value drawn is high (closed) or high - 1, and every value
|
|
366
|
+
from low to it must be one of the type's. The draw is low plus
|
|
367
|
+
an offset up to last - low, which holds even the whole int64 or
|
|
368
|
+
uint64 range. */
|
|
369
|
+
VALUE last, type_min, type_max;
|
|
370
|
+
if (!RB_INTEGER_TYPE_P(low_val) || !RB_INTEGER_TYPE_P(high_val)) {
|
|
371
|
+
rb_raise(rb_eTypeError,
|
|
372
|
+
"random: an integer array takes Integer bounds "
|
|
373
|
+
"(got %"PRIsVALUE", %"PRIsVALUE")",
|
|
374
|
+
rb_inspect(low_val), rb_inspect(high_val));
|
|
375
|
+
}
|
|
376
|
+
last = high_is_closed ? high_val
|
|
377
|
+
: rb_funcall(high_val, '-', 1, INT2FIX(1));
|
|
378
|
+
if (RTEST(rb_funcall(low_val, '>', 1, last))) {
|
|
379
|
+
rb_raise(rb_eArgError,
|
|
380
|
+
"random: low must be less than high "
|
|
381
|
+
"(got low=%"PRIsVALUE", high=%"PRIsVALUE")",
|
|
382
|
+
low_val, high_val);
|
|
383
|
+
}
|
|
384
|
+
switch (ca->data_type) {
|
|
385
|
+
case CA_INT8: type_min = INT2FIX(INT8_MIN); type_max = INT2FIX(INT8_MAX); break;
|
|
386
|
+
case CA_UINT8: type_min = INT2FIX(0); type_max = INT2FIX(UINT8_MAX); break;
|
|
387
|
+
case CA_INT16: type_min = INT2FIX(INT16_MIN); type_max = INT2FIX(INT16_MAX); break;
|
|
388
|
+
case CA_UINT16: type_min = INT2FIX(0); type_max = INT2FIX(UINT16_MAX); break;
|
|
389
|
+
case CA_INT32: type_min = LL2NUM(INT32_MIN); type_max = LL2NUM(INT32_MAX); break;
|
|
390
|
+
case CA_UINT32: type_min = INT2FIX(0); type_max = ULL2NUM(UINT32_MAX); break;
|
|
391
|
+
case CA_INT64: type_min = LL2NUM(INT64_MIN); type_max = LL2NUM(INT64_MAX); break;
|
|
392
|
+
default: type_min = INT2FIX(0); type_max = ULL2NUM(UINT64_MAX); break;
|
|
393
|
+
}
|
|
394
|
+
if (RTEST(rb_funcall(low_val, '<', 1, type_min)) ||
|
|
395
|
+
RTEST(rb_funcall(last, '>', 1, type_max))) {
|
|
396
|
+
rb_raise(rb_eRangeError,
|
|
397
|
+
"random: the values %"PRIsVALUE"..%"PRIsVALUE" are not all %s "
|
|
398
|
+
"(%"PRIsVALUE"..%"PRIsVALUE")",
|
|
399
|
+
low_val, last, ca_type_name[ca->data_type], type_min, type_max);
|
|
400
|
+
}
|
|
401
|
+
low_long = RTEST(rb_funcall(low_val, '<', 1, INT2FIX(0)))
|
|
402
|
+
? (long) NUM2LL(low_val) : (long) NUM2ULL(low_val);
|
|
403
|
+
limit = (unsigned long) NUM2ULL(rb_funcall(last, '-', 1, low_val));
|
|
404
|
+
(void) high_long;
|
|
405
|
+
} else {
|
|
406
|
+
low_dbl = NUM2DBL(low_val);
|
|
407
|
+
high_dbl = NUM2DBL(high_val);
|
|
408
|
+
if (!isfinite(low_dbl) || !isfinite(high_dbl)) {
|
|
409
|
+
rb_raise(rb_eArgError,
|
|
410
|
+
"random: the bounds are finite numbers "
|
|
411
|
+
"(got low=%g, high=%g)", low_dbl, high_dbl);
|
|
412
|
+
}
|
|
413
|
+
if (low_dbl >= high_dbl) {
|
|
414
|
+
rb_raise(rb_eArgError,
|
|
415
|
+
"random: low must be less than high "
|
|
416
|
+
"(got low=%g, high=%g)",
|
|
417
|
+
low_dbl, high_dbl);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
{
|
|
423
|
+
ca_random_ctx_t c = { 0 };
|
|
424
|
+
c.ca = ca;
|
|
425
|
+
c.n = ca->elements;
|
|
426
|
+
c.is_default = is_default;
|
|
427
|
+
c.low_dbl = low_dbl;
|
|
428
|
+
c.high_dbl = high_dbl;
|
|
429
|
+
c.low_long = low_long;
|
|
430
|
+
c.limit = limit;
|
|
431
|
+
ca_random_run(&c, rng, ca_random_bang_fill);
|
|
432
|
+
}
|
|
433
|
+
/* Every cell now holds a value, as after seq! or fill. */
|
|
434
|
+
ca_clear_mask(ca);
|
|
364
435
|
return self;
|
|
365
436
|
}
|
|
366
437
|
|
|
@@ -396,53 +467,31 @@ box_muller_pair(ca_rng_t *source, double *r1, double *r2)
|
|
|
396
467
|
*r2 = r * sin(theta);
|
|
397
468
|
}
|
|
398
469
|
|
|
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
470
|
static VALUE
|
|
405
|
-
|
|
471
|
+
ca_randomn_bang_fill (VALUE arg)
|
|
406
472
|
{
|
|
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);
|
|
473
|
+
ca_random_ctx_t *c = (ca_random_ctx_t *) arg;
|
|
474
|
+
CArray *ca = c->ca;
|
|
475
|
+
ca_size_t i, n = c->n;
|
|
428
476
|
|
|
477
|
+
ca_rng_bind(&c->source);
|
|
429
478
|
/* A CArray::Rng fills one cell per call rather than two, so that this
|
|
430
479
|
and a kernel drawing afterwards are the one sequence: both are
|
|
431
480
|
`ca_random_normal` run once per cell. It costs a draw a cell over
|
|
432
481
|
the paired form, and what it buys is that where the generator
|
|
433
482
|
stands can be worked out rather than run. */
|
|
434
|
-
if (source.kind == CA_RNG_OWN) {
|
|
483
|
+
if (c->source.kind == CA_RNG_OWN) {
|
|
435
484
|
switch (ca->data_type) {
|
|
436
485
|
case CA_FLOAT64: {
|
|
437
486
|
double *p = (double *)ca->ptr;
|
|
438
487
|
for (i = 0; i < n; i++)
|
|
439
|
-
p[i] = ca_random_normal(&source);
|
|
488
|
+
p[i] = ca_random_normal(&c->source);
|
|
440
489
|
break;
|
|
441
490
|
}
|
|
442
491
|
case CA_FLOAT32: {
|
|
443
492
|
float *p = (float *)ca->ptr;
|
|
444
493
|
for (i = 0; i < n; i++)
|
|
445
|
-
p[i] = (float) ca_random_normal(&source);
|
|
494
|
+
p[i] = (float) ca_random_normal(&c->source);
|
|
446
495
|
break;
|
|
447
496
|
}
|
|
448
497
|
case CA_CMPLX128: {
|
|
@@ -450,8 +499,8 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
450
499
|
for (i = 0; i < n; i++) {
|
|
451
500
|
/* Into locals first: C does not say which order a call's
|
|
452
501
|
arguments are evaluated in, and these two advance a state. */
|
|
453
|
-
double re = ca_random_normal(&source);
|
|
454
|
-
double im = ca_random_normal(&source);
|
|
502
|
+
double re = ca_random_normal(&c->source);
|
|
503
|
+
double im = ca_random_normal(&c->source);
|
|
455
504
|
p[i] = re + im * I;
|
|
456
505
|
}
|
|
457
506
|
break;
|
|
@@ -459,8 +508,8 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
459
508
|
case CA_CMPLX64: {
|
|
460
509
|
float complex *p = (float complex *)ca->ptr;
|
|
461
510
|
for (i = 0; i < n; i++) {
|
|
462
|
-
double re = ca_random_normal(&source);
|
|
463
|
-
double im = ca_random_normal(&source);
|
|
511
|
+
double re = ca_random_normal(&c->source);
|
|
512
|
+
double im = ca_random_normal(&c->source);
|
|
464
513
|
p[i] = (float) re + (float) im * I;
|
|
465
514
|
}
|
|
466
515
|
break;
|
|
@@ -468,10 +517,7 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
468
517
|
default:
|
|
469
518
|
break;
|
|
470
519
|
}
|
|
471
|
-
|
|
472
|
-
ca_sync(ca);
|
|
473
|
-
ca_detach(ca);
|
|
474
|
-
return self;
|
|
520
|
+
return Qnil;
|
|
475
521
|
}
|
|
476
522
|
|
|
477
523
|
switch (ca->data_type) {
|
|
@@ -479,11 +525,11 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
479
525
|
double *p = (double *)ca->ptr;
|
|
480
526
|
ca_size_t pairs = n / 2;
|
|
481
527
|
for (i = 0; i < pairs; i++) {
|
|
482
|
-
box_muller_pair(&source, &p[2*i], &p[2*i+1]);
|
|
528
|
+
box_muller_pair(&c->source, &p[2*i], &p[2*i+1]);
|
|
483
529
|
}
|
|
484
530
|
if (n % 2 == 1) {
|
|
485
531
|
double r1, r2;
|
|
486
|
-
box_muller_pair(&source, &r1, &r2);
|
|
532
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
487
533
|
p[n-1] = r1;
|
|
488
534
|
}
|
|
489
535
|
break;
|
|
@@ -493,13 +539,13 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
493
539
|
ca_size_t pairs = n / 2;
|
|
494
540
|
for (i = 0; i < pairs; i++) {
|
|
495
541
|
double r1, r2;
|
|
496
|
-
box_muller_pair(&source, &r1, &r2);
|
|
542
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
497
543
|
p[2*i] = (float)r1;
|
|
498
544
|
p[2*i+1] = (float)r2;
|
|
499
545
|
}
|
|
500
546
|
if (n % 2 == 1) {
|
|
501
547
|
double r1, r2;
|
|
502
|
-
box_muller_pair(&source, &r1, &r2);
|
|
548
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
503
549
|
p[n-1] = (float)r1;
|
|
504
550
|
}
|
|
505
551
|
break;
|
|
@@ -508,7 +554,7 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
508
554
|
double complex *p = (double complex *)ca->ptr;
|
|
509
555
|
for (i = 0; i < n; i++) {
|
|
510
556
|
double r1, r2;
|
|
511
|
-
box_muller_pair(&source, &r1, &r2);
|
|
557
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
512
558
|
p[i] = r1 + r2 * I;
|
|
513
559
|
}
|
|
514
560
|
break;
|
|
@@ -517,7 +563,7 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
517
563
|
float complex *p = (float complex *)ca->ptr;
|
|
518
564
|
for (i = 0; i < n; i++) {
|
|
519
565
|
double r1, r2;
|
|
520
|
-
box_muller_pair(&source, &r1, &r2);
|
|
566
|
+
box_muller_pair(&c->source, &r1, &r2);
|
|
521
567
|
p[i] = (float)r1 + (float)r2 * I;
|
|
522
568
|
}
|
|
523
569
|
break;
|
|
@@ -526,9 +572,41 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
|
526
572
|
break;
|
|
527
573
|
}
|
|
528
574
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
575
|
+
return Qnil;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/* CArray#randomn!(rng:) — fill self with standard normal N(0, 1)
|
|
579
|
+
* samples in-place via Box-Muller, returning self.
|
|
580
|
+
*
|
|
581
|
+
* Restricted to float / complex data types. Complex fills real + imag as
|
|
582
|
+
* two independent normals per cell. */
|
|
583
|
+
static VALUE
|
|
584
|
+
rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
|
|
585
|
+
{
|
|
586
|
+
CArray *ca;
|
|
587
|
+
VALUE opts = Qnil;
|
|
588
|
+
|
|
589
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
590
|
+
VALUE rng = Qnil;
|
|
591
|
+
rb_scan_options(opts, "rng", &rng);
|
|
592
|
+
|
|
593
|
+
rb_ca_modify(self);
|
|
594
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
595
|
+
|
|
596
|
+
if (ca->data_type != CA_FLOAT64 && ca->data_type != CA_FLOAT32 &&
|
|
597
|
+
ca->data_type != CA_CMPLX128 && ca->data_type != CA_CMPLX64) {
|
|
598
|
+
rb_raise(rb_eCADataTypeError,
|
|
599
|
+
"randomn! requires float or complex array");
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
{
|
|
603
|
+
ca_random_ctx_t c = { 0 };
|
|
604
|
+
c.ca = ca;
|
|
605
|
+
c.n = ca->elements;
|
|
606
|
+
ca_random_run(&c, rng, ca_randomn_bang_fill);
|
|
607
|
+
}
|
|
608
|
+
/* Every cell now holds a value, as after seq! or fill. */
|
|
609
|
+
ca_clear_mask(ca);
|
|
532
610
|
return self;
|
|
533
611
|
}
|
|
534
612
|
|
|
@@ -550,59 +628,39 @@ swap_chunks(char *a, char *b, ca_size_t chunk_bytes, char *tmp)
|
|
|
550
628
|
* as a byte chunk and swapped whole, so multi-dim slices move
|
|
551
629
|
* together). */
|
|
552
630
|
static VALUE
|
|
553
|
-
|
|
631
|
+
ca_shuffle_bang_fill (VALUE arg)
|
|
554
632
|
{
|
|
555
|
-
|
|
556
|
-
|
|
633
|
+
ca_random_ctx_t *c = (ca_random_ctx_t *) arg;
|
|
634
|
+
CArray *ca = c->ca;
|
|
557
635
|
ca_size_t n;
|
|
558
|
-
int axis = -1;
|
|
559
636
|
|
|
560
|
-
|
|
561
|
-
VALUE rng = Qnil;
|
|
562
|
-
ca_rng_t source;
|
|
563
|
-
rb_scan_options(opts, "rng,axis", &rng, &v_axis);
|
|
637
|
+
ca_rng_bind(&c->source);
|
|
564
638
|
|
|
565
|
-
|
|
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);
|
|
572
|
-
|
|
573
|
-
if (NIL_P(v_axis)) {
|
|
639
|
+
if (c->axis < 0) {
|
|
574
640
|
/* shuffle all elements */
|
|
575
|
-
|
|
641
|
+
volatile VALUE tmp_holder;
|
|
576
642
|
ca_size_t elem_bytes = ca->bytes;
|
|
577
|
-
char *tmp = (char
|
|
643
|
+
char *tmp = ALLOCV_N(char, tmp_holder, elem_bytes);
|
|
578
644
|
char *p = ca->ptr;
|
|
645
|
+
char *m = c->mask ? c->mask->ptr : NULL;
|
|
579
646
|
|
|
647
|
+
n = ca->elements;
|
|
580
648
|
for (ca_size_t i = n - 1; i > 0; i--) {
|
|
581
|
-
unsigned long j = ca_random_ulong_limited(&source, (unsigned long)i);
|
|
649
|
+
unsigned long j = ca_random_ulong_limited(&c->source, (unsigned long)i);
|
|
582
650
|
if ((ca_size_t)j != i) {
|
|
583
651
|
swap_chunks(p + i * elem_bytes, p + j * elem_bytes, elem_bytes, tmp);
|
|
652
|
+
if ( m ) {
|
|
653
|
+
char b = m[i]; m[i] = m[j]; m[j] = b;
|
|
654
|
+
}
|
|
584
655
|
}
|
|
585
656
|
}
|
|
586
|
-
|
|
657
|
+
ALLOCV_END(tmp_holder);
|
|
587
658
|
}
|
|
588
659
|
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
|
-
}
|
|
660
|
+
int axis = c->axis;
|
|
661
|
+
volatile VALUE tmp_holder;
|
|
598
662
|
|
|
599
663
|
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
664
|
|
|
607
665
|
ca_size_t outer = 1;
|
|
608
666
|
for (int d = 0; d < axis; d++)
|
|
@@ -614,25 +672,59 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
|
614
672
|
|
|
615
673
|
ca_size_t chunk_bytes = inner * ca->bytes;
|
|
616
674
|
ca_size_t stride = n * chunk_bytes;
|
|
617
|
-
char *tmp = (char
|
|
675
|
+
char *tmp = ALLOCV_N(char, tmp_holder, chunk_bytes);
|
|
618
676
|
|
|
619
677
|
for (ca_size_t o = 0; o < outer; o++) {
|
|
620
678
|
char *base = ca->ptr + o * stride;
|
|
679
|
+
char *mbase = c->mask ? c->mask->ptr + o * n * inner : NULL;
|
|
621
680
|
for (ca_size_t i = n - 1; i > 0; i--) {
|
|
622
|
-
unsigned long j = ca_random_ulong_limited(&source, (unsigned long)i);
|
|
681
|
+
unsigned long j = ca_random_ulong_limited(&c->source, (unsigned long)i);
|
|
623
682
|
if ((ca_size_t)j != i) {
|
|
624
683
|
swap_chunks(base + i * chunk_bytes,
|
|
625
684
|
base + j * chunk_bytes,
|
|
626
685
|
chunk_bytes, tmp);
|
|
686
|
+
if ( mbase ) {
|
|
687
|
+
swap_chunks(mbase + i * inner, mbase + j * inner, inner, tmp);
|
|
688
|
+
}
|
|
627
689
|
}
|
|
628
690
|
}
|
|
629
691
|
}
|
|
630
|
-
|
|
692
|
+
ALLOCV_END(tmp_holder);
|
|
693
|
+
}
|
|
694
|
+
return Qnil;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
static VALUE
|
|
698
|
+
rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
|
|
699
|
+
{
|
|
700
|
+
CArray *ca;
|
|
701
|
+
VALUE opts = Qnil, v_axis = Qnil;
|
|
702
|
+
int axis = -1;
|
|
703
|
+
ca_random_ctx_t c = { 0 };
|
|
704
|
+
|
|
705
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
706
|
+
VALUE rng = Qnil;
|
|
707
|
+
rb_scan_options(opts, "rng,axis", &rng, &v_axis);
|
|
708
|
+
|
|
709
|
+
rb_ca_modify(self);
|
|
710
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
711
|
+
|
|
712
|
+
if (ca->elements <= 1) return self;
|
|
713
|
+
|
|
714
|
+
if (!NIL_P(v_axis)) {
|
|
715
|
+
axis = ca_normalize_axis_arg(v_axis, ca->ndim, NULL);
|
|
716
|
+
if (ca->dim[axis] <= 1) {
|
|
717
|
+
return self;
|
|
718
|
+
}
|
|
631
719
|
}
|
|
632
720
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
721
|
+
c.ca = ca;
|
|
722
|
+
c.axis = axis;
|
|
723
|
+
/* The mask moves with the values: a masked cell stays masked wherever
|
|
724
|
+
it lands. */
|
|
725
|
+
ca_update_mask(ca);
|
|
726
|
+
c.mask = ca->mask;
|
|
727
|
+
ca_random_run(&c, rng, ca_shuffle_bang_fill);
|
|
636
728
|
return self;
|
|
637
729
|
}
|
|
638
730
|
|
|
@@ -698,7 +790,7 @@ ca_rng_cells (VALUE self, int64_t **cells)
|
|
|
698
790
|
CArray *ca;
|
|
699
791
|
VALUE state = rb_ivar_get(self, rb_intern("@state"));
|
|
700
792
|
TypedData_Get_Struct(state, CArray, &carray_data_type, ca);
|
|
701
|
-
ca_attach(ca);
|
|
793
|
+
ca_attach(ca); /* window: the state is an entity, whose attach holds nothing */
|
|
702
794
|
*cells = (int64_t *) ca->ptr;
|
|
703
795
|
return ca;
|
|
704
796
|
}
|
|
@@ -752,8 +844,7 @@ rb_ca_rng_reset (int argc, VALUE *argv, VALUE self)
|
|
|
752
844
|
|
|
753
845
|
ca = ca_rng_cells(self, &cells);
|
|
754
846
|
ca_xoshiro256pp_seed(cells, (uint64_t) NUM2ULL(masked));
|
|
755
|
-
|
|
756
|
-
ca_detach(ca);
|
|
847
|
+
ca_sync_detach(ca);
|
|
757
848
|
|
|
758
849
|
rb_ivar_set(self, rb_intern("@seed"), seed);
|
|
759
850
|
return self;
|
|
@@ -779,8 +870,7 @@ rb_ca_rng_random (VALUE self)
|
|
|
779
870
|
|
|
780
871
|
ca = ca_rng_cells(self, &cells);
|
|
781
872
|
value = ca_xoshiro256pp_next_real(cells);
|
|
782
|
-
|
|
783
|
-
ca_detach(ca);
|
|
873
|
+
ca_sync_detach(ca);
|
|
784
874
|
return rb_float_new(value);
|
|
785
875
|
}
|
|
786
876
|
|
|
@@ -799,8 +889,7 @@ rb_ca_rng_bits (VALUE self)
|
|
|
799
889
|
|
|
800
890
|
ca = ca_rng_cells(self, &cells);
|
|
801
891
|
value = ca_xoshiro256pp_next(cells);
|
|
802
|
-
|
|
803
|
-
ca_detach(ca);
|
|
892
|
+
ca_sync_detach(ca);
|
|
804
893
|
return ULL2NUM(value);
|
|
805
894
|
}
|
|
806
895
|
|
|
@@ -823,8 +912,7 @@ rb_ca_rng_randomn (VALUE self)
|
|
|
823
912
|
source.state = NULL;
|
|
824
913
|
source.cells = cells;
|
|
825
914
|
value = ca_random_normal(&source);
|
|
826
|
-
|
|
827
|
-
ca_detach(ca);
|
|
915
|
+
ca_sync_detach(ca);
|
|
828
916
|
return rb_float_new(value);
|
|
829
917
|
}
|
|
830
918
|
|