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_test.c
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
---------------------------------------------------------------------------- */
|
|
11
11
|
|
|
12
12
|
#include "carray.h"
|
|
13
|
+
#include "carray_internal.h" /* ca_attach_window */
|
|
14
|
+
#include "ca_obj_face.h" /* ca_face_equal */
|
|
13
15
|
|
|
14
16
|
static ID id_equal;
|
|
15
17
|
static ID id_eql;
|
|
@@ -26,13 +28,34 @@ ca_check_type (void *ap, int8_t data_type)
|
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
|
|
31
|
+
/* For `initialize` and `initialize_copy`: raises unless the struct is as
|
|
32
|
+
the allocator left it. Setting up a struct that is already set up
|
|
33
|
+
would overwrite what it owns (its buffer, its shape arrays, its parent
|
|
34
|
+
list) without freeing it.
|
|
35
|
+
|
|
36
|
+
What is tested is dim: NULL means the struct owns nothing yet. That
|
|
37
|
+
holds on three conditions, which a new array class has to keep:
|
|
38
|
+
- its allocator zero-fills the struct (TypedData_Make_Struct does);
|
|
39
|
+
- its setup gives the struct a dim (there is no array without one);
|
|
40
|
+
- its `initialize` runs the argument checks before it takes the pool
|
|
41
|
+
or anything else (ca_array_pool_alloc sets dim), so that a rejected
|
|
42
|
+
argument leaves dim NULL and the object can be initialized again. */
|
|
43
|
+
void
|
|
44
|
+
ca_check_uninitialized (void *ap)
|
|
45
|
+
{
|
|
46
|
+
CArray *ca = (CArray *) ap;
|
|
47
|
+
if ( ca->dim != NULL ) {
|
|
48
|
+
rb_raise(rb_eTypeError, "already initialized array");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
29
52
|
void
|
|
30
53
|
ca_check_ndim (void *ap, int ndim)
|
|
31
54
|
{
|
|
32
55
|
CArray *ca = (CArray *) ap;
|
|
33
56
|
if ( ! ca_is_scalar(ca) ) {
|
|
34
57
|
if ( ca->ndim != ndim ) {
|
|
35
|
-
rb_raise(
|
|
58
|
+
rb_raise(rb_eArgError, "ndim mismatch");
|
|
36
59
|
}
|
|
37
60
|
}
|
|
38
61
|
}
|
|
@@ -44,11 +67,11 @@ ca_check_shape (void *ap, int ndim, ca_size_t *dim)
|
|
|
44
67
|
int i;
|
|
45
68
|
if ( ! ca_is_scalar(ca) ) {
|
|
46
69
|
if ( ca->ndim != ndim ) {
|
|
47
|
-
rb_raise(
|
|
70
|
+
rb_raise(rb_eArgError, "shape mismatch");
|
|
48
71
|
}
|
|
49
72
|
for (i=0; i<ndim; i++) {
|
|
50
73
|
if ( ca->dim[i] != dim[i] ) {
|
|
51
|
-
rb_raise(
|
|
74
|
+
rb_raise(rb_eArgError, "shape mismatch");
|
|
52
75
|
}
|
|
53
76
|
}
|
|
54
77
|
}
|
|
@@ -59,7 +82,8 @@ ca_check_same_data_type (void *ap1, void *ap2)
|
|
|
59
82
|
{
|
|
60
83
|
CArray *ca1 = (CArray *) ap1;
|
|
61
84
|
CArray *ca2 = (CArray *) ap2;
|
|
62
|
-
if ( ca1->data_type != ca2->data_type
|
|
85
|
+
if ( ca1->data_type != ca2->data_type ||
|
|
86
|
+
( ca1->data_type == CA_FIXLEN && ca1->bytes != ca2->bytes ) ) {
|
|
63
87
|
rb_raise(rb_eCADataTypeError, "data_type mismatch");
|
|
64
88
|
}
|
|
65
89
|
}
|
|
@@ -70,7 +94,7 @@ ca_check_same_ndim (void *ap1, void *ap2)
|
|
|
70
94
|
CArray *ca1 = (CArray *) ap1;
|
|
71
95
|
CArray *ca2 = (CArray *) ap2;
|
|
72
96
|
if ( ca1->ndim != ca2->ndim ) {
|
|
73
|
-
rb_raise(
|
|
97
|
+
rb_raise(rb_eArgError, "ndim mismatch");
|
|
74
98
|
}
|
|
75
99
|
}
|
|
76
100
|
|
|
@@ -80,7 +104,7 @@ ca_check_same_elements (void *ap1, void *ap2)
|
|
|
80
104
|
CArray *ca1 = (CArray *) ap1;
|
|
81
105
|
CArray *ca2 = (CArray *) ap2;
|
|
82
106
|
if ( ca1->elements != ca2->elements ) {
|
|
83
|
-
rb_raise(
|
|
107
|
+
rb_raise(rb_eArgError, "elements mismatch");
|
|
84
108
|
}
|
|
85
109
|
}
|
|
86
110
|
|
|
@@ -92,11 +116,11 @@ ca_check_same_shape (void *ap1, void *ap2)
|
|
|
92
116
|
int i;
|
|
93
117
|
if ( ( ! ca_is_scalar(ca1) ) && ( ! ca_is_scalar(ca2) ) ) {
|
|
94
118
|
if ( ca1->ndim != ca2->ndim ) {
|
|
95
|
-
rb_raise(
|
|
119
|
+
rb_raise(rb_eArgError, "shape mismatch");
|
|
96
120
|
}
|
|
97
121
|
for (i=0; i<ca1->ndim; i++) {
|
|
98
122
|
if ( ca1->dim[i] != ca2->dim[i] ) {
|
|
99
|
-
rb_raise(
|
|
123
|
+
rb_raise(rb_eArgError, "shape mismatch");
|
|
100
124
|
}
|
|
101
125
|
}
|
|
102
126
|
}
|
|
@@ -109,7 +133,7 @@ ca_check_index (void *ap, ca_size_t *idx)
|
|
|
109
133
|
int i;
|
|
110
134
|
for (i=0; i<ca->ndim; i++) {
|
|
111
135
|
if ( idx[i] < 0 || idx[i] >= ca->dim[i] ) {
|
|
112
|
-
rb_raise(
|
|
136
|
+
rb_raise(rb_eIndexError, "invalid index");
|
|
113
137
|
}
|
|
114
138
|
}
|
|
115
139
|
}
|
|
@@ -118,7 +142,7 @@ void
|
|
|
118
142
|
rb_check_carray_object (VALUE arg)
|
|
119
143
|
{
|
|
120
144
|
if ( ! rb_obj_is_carray(arg) ) {
|
|
121
|
-
rb_raise(
|
|
145
|
+
rb_raise(rb_eTypeError, "CArray required");
|
|
122
146
|
}
|
|
123
147
|
}
|
|
124
148
|
|
|
@@ -166,7 +190,7 @@ rb_ca_is_type (VALUE arg, int type)
|
|
|
166
190
|
{
|
|
167
191
|
CArray *ca;
|
|
168
192
|
if ( ! rb_obj_is_carray(arg) ) {
|
|
169
|
-
rb_raise(
|
|
193
|
+
rb_raise(rb_eTypeError, "CArray required");
|
|
170
194
|
}
|
|
171
195
|
TypedData_Get_Struct(arg, CArray, &carray_data_type, ca);
|
|
172
196
|
return ca->data_type == type;
|
|
@@ -177,8 +201,9 @@ rb_ca_is_type (VALUE arg, int type)
|
|
|
177
201
|
live in ca_obj_record.c; signatures stay in carray.h for cross-file
|
|
178
202
|
extern use. */
|
|
179
203
|
|
|
180
|
-
/* CArray#valid_index?(*idx)
|
|
181
|
-
*
|
|
204
|
+
/* CArray#valid_index?(*idx) -- whether self[*idx] names a cell: a negative
|
|
205
|
+
* index counts from the end of its axis, as it does at every door. The
|
|
206
|
+
* number of indices must equal ndim (raises otherwise). */
|
|
182
207
|
static VALUE
|
|
183
208
|
rb_ca_is_valid_index (int argc, VALUE *argv, VALUE self)
|
|
184
209
|
{
|
|
@@ -194,6 +219,9 @@ rb_ca_is_valid_index (int argc, VALUE *argv, VALUE self)
|
|
|
194
219
|
}
|
|
195
220
|
for (i=0; i<ca->ndim; i++) {
|
|
196
221
|
idx = NUM2SIZE(argv[i]);
|
|
222
|
+
if ( idx < 0 ) {
|
|
223
|
+
idx += ca->dim[i];
|
|
224
|
+
}
|
|
197
225
|
if ( idx < 0 || idx >= ca->dim[i] ) {
|
|
198
226
|
return Qfalse;
|
|
199
227
|
}
|
|
@@ -202,7 +230,8 @@ rb_ca_is_valid_index (int argc, VALUE *argv, VALUE self)
|
|
|
202
230
|
return Qtrue;
|
|
203
231
|
}
|
|
204
232
|
|
|
205
|
-
/* CArray#valid_addr?(addr)
|
|
233
|
+
/* CArray#valid_addr?(addr) -- whether addr names a cell: a negative address
|
|
234
|
+
* counts from the end. */
|
|
206
235
|
static VALUE
|
|
207
236
|
rb_ca_is_valid_addr (VALUE self, VALUE raddr)
|
|
208
237
|
{
|
|
@@ -211,6 +240,9 @@ rb_ca_is_valid_addr (VALUE self, VALUE raddr)
|
|
|
211
240
|
|
|
212
241
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
213
242
|
addr = NUM2SIZE(raddr);
|
|
243
|
+
if ( addr < 0 ) {
|
|
244
|
+
addr += ca->elements;
|
|
245
|
+
}
|
|
214
246
|
if ( addr < 0 || addr >= ca->elements ) {
|
|
215
247
|
return Qfalse;
|
|
216
248
|
}
|
|
@@ -226,6 +258,7 @@ rb_ca_has_same_shape (VALUE self, VALUE other)
|
|
|
226
258
|
{
|
|
227
259
|
CArray *ca, *cb;
|
|
228
260
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
261
|
+
/* coerce: only the shape is compared */
|
|
229
262
|
cb = ca_wrap_readonly(other, ca->data_type);
|
|
230
263
|
return ca_has_same_shape(ca, cb) ? Qtrue : Qfalse;
|
|
231
264
|
}
|
|
@@ -296,25 +329,20 @@ ca_eql[CA_NTYPE] = {
|
|
|
296
329
|
eql_VALUE,
|
|
297
330
|
};
|
|
298
331
|
|
|
299
|
-
|
|
300
|
-
*
|
|
301
|
-
*
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
* == : ca_eql[data_type] (type-specific, so float NaN != NaN)
|
|
309
|
-
* eql?: memcmp for numeric, rb_funcall(:eql?) for CA_OBJECT
|
|
310
|
-
*
|
|
311
|
-
* The unmasked-unmasked branch takes a bulk memcmp or per-cell
|
|
312
|
-
* shortcut to amortise per-element function pointer dispatch. */
|
|
313
|
-
static int
|
|
314
|
-
ca_compare_common (void *ap, void *bp, int strict)
|
|
332
|
+
typedef struct {
|
|
333
|
+
CArray *ca;
|
|
334
|
+
CArray *cb;
|
|
335
|
+
int strict;
|
|
336
|
+
int flag;
|
|
337
|
+
} ca_compare_ctx_t;
|
|
338
|
+
|
|
339
|
+
static VALUE
|
|
340
|
+
ca_compare_body (VALUE arg)
|
|
315
341
|
{
|
|
316
|
-
|
|
317
|
-
CArray *
|
|
342
|
+
ca_compare_ctx_t *c = (ca_compare_ctx_t *) arg;
|
|
343
|
+
CArray *ca = c->ca;
|
|
344
|
+
CArray *cb = c->cb;
|
|
345
|
+
int strict = c->strict;
|
|
318
346
|
int flag = 1;
|
|
319
347
|
int masked_a, masked_b;
|
|
320
348
|
boolean8_t *ma, *mb;
|
|
@@ -325,28 +353,6 @@ ca_compare_common (void *ap, void *bp, int strict)
|
|
|
325
353
|
ca_eql_func eql = NULL; /* used only when !strict */
|
|
326
354
|
int is_object;
|
|
327
355
|
|
|
328
|
-
if ( ca_is_scalar(ca) ^ ca_is_scalar(cb) ) {
|
|
329
|
-
return 0;
|
|
330
|
-
}
|
|
331
|
-
if ( ca->data_type != cb->data_type ) {
|
|
332
|
-
return 0;
|
|
333
|
-
}
|
|
334
|
-
if ( ca->bytes != cb->bytes ) {
|
|
335
|
-
return 0;
|
|
336
|
-
}
|
|
337
|
-
if ( ca->ndim != cb->ndim ) {
|
|
338
|
-
return 0;
|
|
339
|
-
}
|
|
340
|
-
if ( ca->elements != cb->elements ) {
|
|
341
|
-
return 0;
|
|
342
|
-
}
|
|
343
|
-
for (i=0; i<ca->ndim; i++) {
|
|
344
|
-
if ( ca->dim[i] != cb->dim[i] ) {
|
|
345
|
-
return 0;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
ca_attach_n(2, ca, cb); /* recurses into ca->mask / cb->mask */
|
|
350
356
|
|
|
351
357
|
masked_a = ca_is_any_masked(ca);
|
|
352
358
|
masked_b = ca_is_any_masked(cb);
|
|
@@ -441,9 +447,66 @@ ca_compare_common (void *ap, void *bp, int strict)
|
|
|
441
447
|
}
|
|
442
448
|
}
|
|
443
449
|
|
|
444
|
-
|
|
450
|
+
c->flag = flag;
|
|
451
|
+
return Qnil;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/* ca_compare_common(a, b, strict) — shared body of ca_equal (==) and
|
|
455
|
+
* ca_eql_strict (eql?). Returns 1 if arrays match under the selected
|
|
456
|
+
* semantics, else 0.
|
|
457
|
+
*
|
|
458
|
+
* Common structure: metadata pre-check (scalar / data_type / bytes /
|
|
459
|
+
* ndim / elements / dim), then ca_compare_body in a window over both
|
|
460
|
+
* arrays (attaching an array attaches its mask), a unified loop over the
|
|
461
|
+
* four masked/unmasked combinations.
|
|
462
|
+
*
|
|
463
|
+
* The only difference is the per-element comparator:
|
|
464
|
+
* == : ca_eql[data_type] (type-specific, so float NaN != NaN)
|
|
465
|
+
* eql?: memcmp for numeric, rb_funcall(:eql?) for CA_OBJECT
|
|
466
|
+
*
|
|
467
|
+
* The unmasked-unmasked branch takes a bulk memcmp or per-cell
|
|
468
|
+
* shortcut to amortise per-element function pointer dispatch. */
|
|
469
|
+
static int
|
|
470
|
+
ca_compare_common (void *ap, void *bp, int strict)
|
|
471
|
+
{
|
|
472
|
+
CArray *ca = (CArray *) ap;
|
|
473
|
+
CArray *cb = (CArray *) bp;
|
|
474
|
+
int8_t i;
|
|
475
|
+
|
|
476
|
+
if ( ca_is_scalar(ca) ^ ca_is_scalar(cb) ) {
|
|
477
|
+
return 0;
|
|
478
|
+
}
|
|
479
|
+
if ( ca->data_type != cb->data_type ) {
|
|
480
|
+
return 0;
|
|
481
|
+
}
|
|
482
|
+
if ( ca->bytes != cb->bytes ) {
|
|
483
|
+
return 0;
|
|
484
|
+
}
|
|
485
|
+
if ( ca->ndim != cb->ndim ) {
|
|
486
|
+
return 0;
|
|
487
|
+
}
|
|
488
|
+
if ( ca->elements != cb->elements ) {
|
|
489
|
+
return 0;
|
|
490
|
+
}
|
|
491
|
+
for (i=0; i<ca->ndim; i++) {
|
|
492
|
+
if ( ca->dim[i] != cb->dim[i] ) {
|
|
493
|
+
return 0;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
445
496
|
|
|
446
|
-
|
|
497
|
+
{
|
|
498
|
+
ca_compare_ctx_t c;
|
|
499
|
+
CArray *list[2];
|
|
500
|
+
c.ca = ca;
|
|
501
|
+
c.cb = cb;
|
|
502
|
+
c.strict = strict;
|
|
503
|
+
c.flag = 1;
|
|
504
|
+
list[0] = ca;
|
|
505
|
+
list[1] = cb;
|
|
506
|
+
/* The object lane calls #== / #eql? with both arrays attached. */
|
|
507
|
+
ca_attach_window(2, list, "rr", ca_compare_body, (VALUE) &c);
|
|
508
|
+
return c.flag;
|
|
509
|
+
}
|
|
447
510
|
}
|
|
448
511
|
|
|
449
512
|
int
|
|
@@ -452,8 +515,8 @@ ca_equal (void *ap, void *bp)
|
|
|
452
515
|
return ca_compare_common(ap, bp, 0);
|
|
453
516
|
}
|
|
454
517
|
|
|
455
|
-
|
|
456
|
-
|
|
518
|
+
int
|
|
519
|
+
ca_eql_storage (void *ap, void *bp)
|
|
457
520
|
{
|
|
458
521
|
return ca_compare_common(ap, bp, 1);
|
|
459
522
|
}
|
|
@@ -487,6 +550,10 @@ rb_ca_equal (VALUE self, VALUE other)
|
|
|
487
550
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
488
551
|
TypedData_Get_Struct(other, CArray, &carray_data_type, cb);
|
|
489
552
|
|
|
553
|
+
if ( ! rb_ca_has_data_class(self) && ( ca_is_face(ca) || ca_is_face(cb) ) ) {
|
|
554
|
+
return ca_face_equal(self, other, 0) ? Qtrue : Qfalse;
|
|
555
|
+
}
|
|
556
|
+
|
|
490
557
|
return ( ca_equal(ca, cb) ) ? Qtrue : Qfalse;
|
|
491
558
|
}
|
|
492
559
|
|
|
@@ -519,13 +586,20 @@ rb_ca_eql (VALUE self, VALUE other)
|
|
|
519
586
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
520
587
|
TypedData_Get_Struct(other, CArray, &carray_data_type, cb);
|
|
521
588
|
|
|
522
|
-
|
|
589
|
+
if ( ! rb_ca_has_data_class(self) && ( ca_is_face(ca) || ca_is_face(cb) ) ) {
|
|
590
|
+
return ca_face_equal(self, other, 1) ? Qtrue : Qfalse;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return ( ca_eql_storage(ca, cb) ) ? Qtrue : Qfalse;
|
|
523
594
|
}
|
|
524
595
|
|
|
525
596
|
/* ca_hash(ca) — cheap Hash key for CArray. Mixes metadata (data_type,
|
|
526
597
|
* ndim, bytes, elements, scalar-ness, shape, mask presence) and, for
|
|
527
|
-
* unmasked arrays only, samples the leading CA_HASH_SAMPLE_BYTES
|
|
528
|
-
* data
|
|
598
|
+
* unmasked arrays only, samples the leading cells (CA_HASH_SAMPLE_BYTES
|
|
599
|
+
* of data, at least one cell), read by address so a view is not
|
|
600
|
+
* materialised for them. An object array samples the #hash of those
|
|
601
|
+
* cells, matching eql?, which compares them with #eql?. Masked arrays
|
|
602
|
+
* skip the data sample entirely — otherwise
|
|
529
603
|
* masked positions would have to be zeroed in the sample to preserve
|
|
530
604
|
* the eql?→hash invariant, and masked CArrays are rare as Hash keys.
|
|
531
605
|
* The collision rate cost buys no ca->mask->ptr access and no
|
|
@@ -557,9 +631,36 @@ ca_hash (CArray *ca)
|
|
|
557
631
|
h ^= rb_memhash(&masked_flag, sizeof(masked_flag));
|
|
558
632
|
|
|
559
633
|
if ( ! masked_flag && sample > 0 ) {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
634
|
+
ca_size_t addrs[CA_HASH_SAMPLE_BYTES];
|
|
635
|
+
ca_size_t ncell = sample / ca->bytes;
|
|
636
|
+
ca_size_t i;
|
|
637
|
+
if ( ncell < 1 ) {
|
|
638
|
+
ncell = 1;
|
|
639
|
+
}
|
|
640
|
+
if ( ncell > ca->elements ) {
|
|
641
|
+
ncell = ca->elements;
|
|
642
|
+
}
|
|
643
|
+
for (i = 0; i < ncell; i++) {
|
|
644
|
+
addrs[i] = i;
|
|
645
|
+
}
|
|
646
|
+
if ( ca_is_object_type(ca) ) {
|
|
647
|
+
/* eql? compares object cells with #eql?, so the sample is their
|
|
648
|
+
#hash, not the VALUE bits. The cells sit on the stack, where the
|
|
649
|
+
GC sees them while #hash runs. */
|
|
650
|
+
VALUE cells[CA_HASH_SAMPLE_BYTES / sizeof(VALUE)];
|
|
651
|
+
ca_xfer_addrs(ca, ncell, addrs, cells, CA_XFER_GET);
|
|
652
|
+
for (i = 0; i < ncell; i++) {
|
|
653
|
+
h = rb_hash_uint(h, (st_index_t) NUM2LONG(rb_hash(cells[i])));
|
|
654
|
+
}
|
|
655
|
+
RB_GC_GUARD(cells[0]);
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
volatile VALUE holder;
|
|
659
|
+
char *buf = ALLOCV_N(char, holder, ncell * ca->bytes);
|
|
660
|
+
ca_xfer_addrs(ca, ncell, addrs, buf, CA_XFER_GET);
|
|
661
|
+
h ^= rb_memhash(buf, ncell * ca->bytes);
|
|
662
|
+
ALLOCV_END(holder);
|
|
663
|
+
}
|
|
563
664
|
}
|
|
564
665
|
|
|
565
666
|
return h;
|
|
@@ -593,10 +694,21 @@ rb_ca_modify (VALUE self)
|
|
|
593
694
|
rb_check_frozen(self);
|
|
594
695
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
595
696
|
if ( ca_is_readonly(ca) ) {
|
|
596
|
-
|
|
697
|
+
ca_refuse_read_only();
|
|
597
698
|
}
|
|
598
699
|
}
|
|
599
700
|
|
|
701
|
+
/* The refusal of a write into a read-only array that is not frozen (a
|
|
702
|
+
frozen one is Ruby's FrozenError, from rb_check_frozen): every guard
|
|
703
|
+
raises it, the entry points through rb_ca_modify and the transfers and
|
|
704
|
+
fills below them, which are the last line when an entry is missed. */
|
|
705
|
+
void
|
|
706
|
+
ca_refuse_read_only (void)
|
|
707
|
+
{
|
|
708
|
+
rb_raise(rb_eRuntimeError, "%s: can not modify read-only array",
|
|
709
|
+
ca_calling_method_name());
|
|
710
|
+
}
|
|
711
|
+
|
|
600
712
|
/* CArray#freeze — freeze self and set CA_FLAG_READ_ONLY so subsequent
|
|
601
713
|
* mutations raise FrozenError. */
|
|
602
714
|
VALUE
|
|
@@ -642,6 +754,9 @@ without_read_only_ensure (VALUE arg)
|
|
|
642
754
|
struct without_read_only_state *s = (struct without_read_only_state *) arg;
|
|
643
755
|
if (s->was_readonly) {
|
|
644
756
|
ca_set_flag(s->ca, CA_FLAG_READ_ONLY);
|
|
757
|
+
if (s->ca->mask) { /* the block may have replaced it */
|
|
758
|
+
ca_set_flag(s->ca->mask, CA_FLAG_READ_ONLY);
|
|
759
|
+
}
|
|
645
760
|
}
|
|
646
761
|
return Qnil;
|
|
647
762
|
}
|
|
@@ -679,10 +794,16 @@ without_read_only_ensure (VALUE arg)
|
|
|
679
794
|
* immutable (producer's contract) but the mask slot is CArray-side metadata
|
|
680
795
|
* the bridge owns.
|
|
681
796
|
*
|
|
682
|
-
* Mechanics: clears CA_FLAG_READ_ONLY on self
|
|
683
|
-
* rb_ensure restores
|
|
684
|
-
*
|
|
685
|
-
*
|
|
797
|
+
* Mechanics: clears CA_FLAG_READ_ONLY on self and on its mask for the
|
|
798
|
+
* duration of the block; rb_ensure restores both on normal return AND on
|
|
799
|
+
* raise, setting the flag on whatever mask self has by then. (A read-only
|
|
800
|
+
* array's mask carries the flag once CArray#mask has handed it out.) Frozen
|
|
801
|
+
* objects still raise FrozenError. Does not walk parent chains.
|
|
802
|
+
*
|
|
803
|
+
* The lift covers every write, not only the mask: a value write inside the
|
|
804
|
+
* block reaches the producer's buffer, which case (a) declares immutable (a
|
|
805
|
+
* frozen CArray wrapped through MemoryView changes). Keeping the block to
|
|
806
|
+
* the mask is the caller's part, like the choice among (a) / (b) / (c).
|
|
686
807
|
*
|
|
687
808
|
* Caller discipline (not enforced by the primitive): confine usage to
|
|
688
809
|
* entities (CArray / CScalar / CAWrap). On a view of a read-only parent,
|
|
@@ -701,6 +822,9 @@ rb_ca_without_read_only_flag (VALUE self)
|
|
|
701
822
|
s.was_readonly = ca_test_flag(ca, CA_FLAG_READ_ONLY);
|
|
702
823
|
if (s.was_readonly) {
|
|
703
824
|
ca_unset_flag(ca, CA_FLAG_READ_ONLY);
|
|
825
|
+
if (ca->mask) {
|
|
826
|
+
ca_unset_flag(ca->mask, CA_FLAG_READ_ONLY);
|
|
827
|
+
}
|
|
704
828
|
}
|
|
705
829
|
return rb_ensure(without_read_only_body, Qnil,
|
|
706
830
|
without_read_only_ensure, (VALUE) &s);
|