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/ca_obj_refer.c
CHANGED
|
@@ -74,34 +74,51 @@ ca_refer_setup (CARefer *ca, CArray *parent,
|
|
|
74
74
|
ca_size_t s;
|
|
75
75
|
int8_t i;
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
78
|
+
CA_CHECK_RANK_GIVEN(ndim);
|
|
79
|
+
CA_CHECK_DIM_GIVEN(ndim, dim);
|
|
80
|
+
CA_CHECK_BYTES_GIVEN(data_type, bytes);
|
|
81
81
|
|
|
82
|
+
/* An object cell is a VALUE the GC marks: reading other bytes as one
|
|
83
|
+
marks garbage, and reading one as bytes exposes an address. */
|
|
82
84
|
if (ca_is_object_type(parent) && data_type != CA_OBJECT) {
|
|
83
|
-
rb_raise(
|
|
85
|
+
rb_raise(rb_eCADataTypeError,
|
|
84
86
|
"object array can't be referred by other data type");
|
|
85
87
|
}
|
|
88
|
+
if (! ca_is_object_type(parent) && data_type == CA_OBJECT) {
|
|
89
|
+
rb_raise(rb_eCADataTypeError,
|
|
90
|
+
"non-object array can't be referred as object data type");
|
|
91
|
+
}
|
|
92
|
+
/* A boolean cell holds 0 or 1, and a view that reads other bytes as
|
|
93
|
+
boolean cannot keep them so: the parent is written as what it is. */
|
|
94
|
+
if (data_type == CA_BOOLEAN && parent->data_type != CA_BOOLEAN) {
|
|
95
|
+
rb_raise(rb_eCADataTypeError,
|
|
96
|
+
"%s: a %s array can't be referred as boolean (its bytes need not "
|
|
97
|
+
"be 0 or 1); compare it instead, e.g. ne(0)",
|
|
98
|
+
ca_calling_method_name(), ca_type_name[parent->data_type]);
|
|
99
|
+
}
|
|
86
100
|
if (parent->elements && bytes > parent_bytes * parent->elements) {
|
|
87
|
-
rb_raise(
|
|
101
|
+
rb_raise(rb_eArgError, "bytes exceeds the data size of referent");
|
|
88
102
|
}
|
|
89
103
|
if (bytes < parent_bytes && parent_bytes % bytes != 0) {
|
|
90
|
-
rb_raise(
|
|
104
|
+
rb_raise(rb_eArgError,
|
|
91
105
|
"bytes of reference array must be a multiple of that of referent");
|
|
92
106
|
}
|
|
93
107
|
if (bytes > parent_bytes && bytes % parent_bytes != 0) {
|
|
94
|
-
rb_raise(
|
|
108
|
+
rb_raise(rb_eArgError,
|
|
95
109
|
"bytes of reference array must be a multiple of that of referent");
|
|
96
110
|
}
|
|
97
111
|
if (offset < 0) {
|
|
98
|
-
rb_raise(
|
|
112
|
+
rb_raise(rb_eArgError, "negative offset is not permitted for CARefer");
|
|
113
|
+
}
|
|
114
|
+
elements = ca_shape_elements(ndim, dim, bytes);
|
|
115
|
+
if (offset > parent->elements) {
|
|
116
|
+
rb_raise(rb_eArgError,
|
|
117
|
+
"data size of reference array must not exceed that of referent");
|
|
99
118
|
}
|
|
100
|
-
elements = 1;
|
|
101
|
-
for (i = 0; i < ndim; i++) elements *= dim[i];
|
|
102
119
|
if ((bytes * elements + parent_bytes * offset) >
|
|
103
120
|
(parent_bytes * parent->elements)) {
|
|
104
|
-
rb_raise(
|
|
121
|
+
rb_raise(rb_eArgError,
|
|
105
122
|
"data size of reference array must not exceed that of referent");
|
|
106
123
|
}
|
|
107
124
|
|
|
@@ -114,14 +131,19 @@ ca_refer_setup (CARefer *ca, CArray *parent,
|
|
|
114
131
|
/* base_offset is in bytes: `offset` is in parent-element units. */
|
|
115
132
|
base_offset = offset * parent_bytes;
|
|
116
133
|
|
|
117
|
-
/*
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
134
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
135
|
+
run them before it allocates. */
|
|
136
|
+
if ( ca == NULL ) {
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* mask0 is written by ca_refer_func_create_mask when the constructor
|
|
141
|
+
takes the parent's mask, and freed on error unwind, so it starts
|
|
142
|
+
NULL. */
|
|
121
143
|
ca->mask0 = NULL;
|
|
122
144
|
|
|
123
|
-
|
|
124
|
-
|
|
145
|
+
ca_stride_setup_view((CAStride *) ca, CA_OBJ_REFER, parent,
|
|
146
|
+
data_type, bytes, ndim, dim, strides, base_offset);
|
|
125
147
|
|
|
126
148
|
if (ca_is_scalar(parent)) {
|
|
127
149
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
@@ -134,8 +156,11 @@ ca_refer_new (CArray *parent,
|
|
|
134
156
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
135
157
|
ca_size_t offset)
|
|
136
158
|
{
|
|
137
|
-
CARefer *ca
|
|
159
|
+
CARefer *ca;
|
|
160
|
+
ca_refer_setup(NULL, parent, data_type, ndim, dim, bytes, offset);
|
|
161
|
+
ca = (CARefer *) ca_array_alloc(CA_OBJ_REFER, ndim);
|
|
138
162
|
ca_refer_setup(ca, parent, data_type, ndim, dim, bytes, offset);
|
|
163
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
139
164
|
return ca;
|
|
140
165
|
}
|
|
141
166
|
|
|
@@ -172,10 +197,7 @@ ca_refer_func_create_mask (void *ap)
|
|
|
172
197
|
ca_size_t parent_bytes = ca->parent->bytes;
|
|
173
198
|
ca_size_t parent_offset;
|
|
174
199
|
|
|
175
|
-
|
|
176
|
-
if (! ca->parent->mask) {
|
|
177
|
-
ca_create_mask(ca->parent);
|
|
178
|
-
}
|
|
200
|
+
ca_create_mask(ca->parent);
|
|
179
201
|
|
|
180
202
|
parent_offset = ca->base_offset / parent_bytes;
|
|
181
203
|
|
|
@@ -200,9 +222,12 @@ ca_refer_func_create_mask (void *ap)
|
|
|
200
222
|
ca->mask0 =
|
|
201
223
|
(CArray *) ca_repeat_new(ca->parent->mask, ca->parent->ndim + 1, count);
|
|
202
224
|
ca_unset_flag(ca->mask0, CA_FLAG_READ_ONLY);
|
|
225
|
+
/* mask0 has ratio cells per parent element, so the offset is counted
|
|
226
|
+
in those. */
|
|
203
227
|
ca->mask =
|
|
204
228
|
(CArray *) ca_refer_new(ca->mask0,
|
|
205
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0,
|
|
229
|
+
CA_BOOLEAN, ca->ndim, ca->dim, 0,
|
|
230
|
+
parent_offset * ratio);
|
|
206
231
|
}
|
|
207
232
|
else {
|
|
208
233
|
/* Spanned reinterpret: ratio = bytes / parent_bytes parent
|
|
@@ -232,6 +257,7 @@ rb_ca_refer_initialize_copy (VALUE self, VALUE other)
|
|
|
232
257
|
{
|
|
233
258
|
CARefer *ca, *cs;
|
|
234
259
|
TypedData_Get_Struct(self, CARefer, &carefer_data_type, ca);
|
|
260
|
+
ca_check_uninitialized(ca);
|
|
235
261
|
TypedData_Get_Struct(other, CARefer, &carefer_data_type, cs);
|
|
236
262
|
if ( ca_func[CA_OBJ_REFER].pool_init ) {
|
|
237
263
|
ca_array_pool_alloc(ca, CA_OBJ_REFER, cs->ndim);
|
|
@@ -242,6 +268,7 @@ rb_ca_refer_initialize_copy (VALUE self, VALUE other)
|
|
|
242
268
|
unusual mod-bytes alignments. */
|
|
243
269
|
ca_refer_setup(ca, cs->parent, cs->data_type, cs->ndim, cs->dim,
|
|
244
270
|
cs->bytes, cs->base_offset / cs->parent->bytes);
|
|
271
|
+
ca_view_inherit_mask((VALUE) ca);
|
|
245
272
|
return self;
|
|
246
273
|
}
|
|
247
274
|
|
|
@@ -275,6 +302,34 @@ rb_ca_refer_initialize_copy (VALUE self, VALUE other)
|
|
|
275
302
|
* 2. Match ranges of parent axes to new axes so element products
|
|
276
303
|
* agree. Inside each matched range, root_strides must be
|
|
277
304
|
* inter-axis contiguous. */
|
|
305
|
+
/* Three properties of an array are answered by walking its C parent chain:
|
|
306
|
+
ca_is_value_array, ca_is_readonly and ca_is_mask_array. An array that is
|
|
307
|
+
built somewhere other than as a child of `src` -- a reshape that folds
|
|
308
|
+
onto the root, the copy that dup / clone makes -- does not have `src` on
|
|
309
|
+
that chain, so carry each property across from `src`. Without this a
|
|
310
|
+
reshape or a dup of x.value reads the mask of x again (and takes UNDEF
|
|
311
|
+
into it), and a reshape of a broadcast view becomes writable. */
|
|
312
|
+
void
|
|
313
|
+
ca_keep_chain_flags (CArray *view, CArray *src)
|
|
314
|
+
{
|
|
315
|
+
if ( ca_is_value_array(src) ) {
|
|
316
|
+
if ( view->mask ) {
|
|
317
|
+
ca_free(view->mask);
|
|
318
|
+
view->mask = NULL;
|
|
319
|
+
}
|
|
320
|
+
ca_set_flag(view, CA_FLAG_VALUE_ARRAY);
|
|
321
|
+
}
|
|
322
|
+
if ( ca_is_readonly(src) ) {
|
|
323
|
+
ca_set_flag(view, CA_FLAG_READ_ONLY);
|
|
324
|
+
if ( view->mask ) {
|
|
325
|
+
ca_set_flag(view->mask, CA_FLAG_READ_ONLY);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if ( ca_is_mask_array(src) ) {
|
|
329
|
+
ca_set_flag(view, CA_FLAG_MASK_ARRAY);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
278
333
|
static int
|
|
279
334
|
ca_reshape_try_strides (CArray *parent,
|
|
280
335
|
const ca_size_t *new_dim,
|
|
@@ -401,8 +456,11 @@ ca_reshape_try_strides (CArray *parent,
|
|
|
401
456
|
return 1;
|
|
402
457
|
}
|
|
403
458
|
|
|
459
|
+
/* `refer` with its options given apart from argv, for callers in C that
|
|
460
|
+
build the options themselves (a Hash at the end of argv is read as
|
|
461
|
+
options only when the Ruby caller passed keywords). */
|
|
404
462
|
static VALUE
|
|
405
|
-
|
|
463
|
+
rb_ca_refer_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
|
|
406
464
|
{
|
|
407
465
|
volatile VALUE obj = Qnil;
|
|
408
466
|
CArray *ca;
|
|
@@ -415,7 +473,7 @@ rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
|
415
473
|
|
|
416
474
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
417
475
|
|
|
418
|
-
if (argc == 0) {
|
|
476
|
+
if (argc == 0 && NIL_P(ropt)) {
|
|
419
477
|
data_type = ca->data_type;
|
|
420
478
|
bytes = ca->bytes;
|
|
421
479
|
ndim = ca->ndim;
|
|
@@ -425,39 +483,57 @@ rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
|
425
483
|
rb_ca_set_parent(obj, self);
|
|
426
484
|
}
|
|
427
485
|
else {
|
|
428
|
-
volatile VALUE rtype, rdim,
|
|
429
|
-
ropt = rb_pop_options(&argc, &argv);
|
|
486
|
+
volatile VALUE rtype, rdim, rbytes = Qnil, roffset = Qnil;
|
|
430
487
|
rb_scan_args(argc, argv, "11", (VALUE *) &rtype, (VALUE *) &rdim);
|
|
431
488
|
rb_scan_options(ropt, "bytes,offset", &rbytes, &roffset);
|
|
432
489
|
if (NIL_P(rbytes)) rbytes = rb_ca_bytes(self);
|
|
433
490
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
434
491
|
if (NIL_P(rdim)) {
|
|
435
492
|
if (ca->bytes != bytes) {
|
|
436
|
-
rb_raise(
|
|
493
|
+
rb_raise(rb_eArgError,
|
|
437
494
|
"specify dimension shape for different byte size");
|
|
438
495
|
} else {
|
|
439
496
|
rdim = rb_ca_dim(self);
|
|
440
497
|
}
|
|
441
498
|
}
|
|
442
499
|
Check_Type(rdim, T_ARRAY);
|
|
500
|
+
CA_CHECK_RANK_GIVEN(RARRAY_LEN(rdim)); /* before dim[] is filled */
|
|
443
501
|
ndim = RARRAY_LEN(rdim);
|
|
444
502
|
for (i = 0; i < ndim; i++) dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
|
|
445
503
|
if (! NIL_P(roffset)) offset = NUM2SIZE(roffset);
|
|
504
|
+
/* When rtype is a data_class the result is a record array. It is
|
|
505
|
+
built on the storage, never on a Face, so that a Face stays on top
|
|
506
|
+
of the chain: re-reading a record array as its own data_class lifts
|
|
507
|
+
it (keeping its class), any other data_class wraps a new CARecord. */
|
|
508
|
+
if ( rb_obj_is_data_class(rtype) ) {
|
|
509
|
+
volatile VALUE base = rb_ca_strip_face_value(self);
|
|
510
|
+
CArray *base_ca;
|
|
511
|
+
TypedData_Get_Struct(base, CArray, &carray_data_type, base_ca);
|
|
512
|
+
cr = ca_refer_new(base_ca, data_type, ndim, dim, bytes, offset);
|
|
513
|
+
obj = ca_wrap_struct(cr);
|
|
514
|
+
rb_ca_set_parent(obj, base);
|
|
515
|
+
if ( ca->obj_type == CA_OBJ_RECORD
|
|
516
|
+
&& rb_ca_data_class(self) == rtype ) {
|
|
517
|
+
return ca_face_lift(obj, self);
|
|
518
|
+
}
|
|
519
|
+
return rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
|
|
520
|
+
rb_intern("wrap"), 2, obj, rtype);
|
|
521
|
+
}
|
|
446
522
|
cr = ca_refer_new((CArray *) ca, data_type, ndim, dim, bytes, offset);
|
|
447
523
|
obj = ca_wrap_struct(cr);
|
|
448
524
|
rb_ca_set_parent(obj, self);
|
|
449
|
-
/* When rtype is a data_class, wrap the result in CARecord so
|
|
450
|
-
the data_class is carried even if self is not itself a Face. */
|
|
451
|
-
if ( rb_obj_is_data_class(rtype) ) {
|
|
452
|
-
obj = rb_funcall(rb_const_get(rb_cObject, rb_intern("CARecord")),
|
|
453
|
-
rb_intern("wrap"), 2, obj, rtype);
|
|
454
|
-
return obj;
|
|
455
|
-
}
|
|
456
525
|
}
|
|
457
526
|
CA_WRAPPER_LIFT(obj, self, ca);
|
|
458
527
|
return obj;
|
|
459
528
|
}
|
|
460
529
|
|
|
530
|
+
static VALUE
|
|
531
|
+
rb_ca_refer (int argc, VALUE *argv, VALUE self)
|
|
532
|
+
{
|
|
533
|
+
volatile VALUE ropt = rb_pop_options(&argc, &argv);
|
|
534
|
+
return rb_ca_refer_kw(argc, argv, ropt, self);
|
|
535
|
+
}
|
|
536
|
+
|
|
461
537
|
VALUE
|
|
462
538
|
rb_ca_refer_new (VALUE self,
|
|
463
539
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
@@ -483,7 +559,7 @@ rb_ca_refer_new (VALUE self,
|
|
|
483
559
|
rb_ary_store(list, 2, ropt);
|
|
484
560
|
|
|
485
561
|
{
|
|
486
|
-
volatile VALUE obj =
|
|
562
|
+
volatile VALUE obj = rb_ca_refer_kw(2, (VALUE *) RARRAY_CONST_PTR(list), ropt, self);
|
|
487
563
|
CArray *co;
|
|
488
564
|
|
|
489
565
|
/* CAREFUL: this is the internal builder -- some fifteen call sites want
|
|
@@ -535,6 +611,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
535
611
|
CARefer *cr;
|
|
536
612
|
ca_size_t new_dim[CA_RANK_MAX];
|
|
537
613
|
ca_size_t prod = 1;
|
|
614
|
+
int overflow = 0, zero = 0;
|
|
538
615
|
int placeholder_idx = -1; /* axis with `-1` or `:~` infer placeholder */
|
|
539
616
|
int i;
|
|
540
617
|
volatile VALUE obj;
|
|
@@ -542,9 +619,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
542
619
|
|
|
543
620
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
544
621
|
|
|
545
|
-
|
|
546
|
-
rb_raise(rb_eArgError, "reshape: invalid number of dims (%d)", argc);
|
|
547
|
-
}
|
|
622
|
+
ca_check_rank_fits(argc, "reshape");
|
|
548
623
|
|
|
549
624
|
/* Locate the (at most one) auto-infer placeholder. `-1` is the
|
|
550
625
|
conventional spelling; `:~` is the unified auto-fill sigil
|
|
@@ -553,7 +628,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
553
628
|
if ( (FIXNUM_P(argv[i]) && FIX2LONG(argv[i]) == -1)
|
|
554
629
|
|| argv[i] == sym_tilde ) {
|
|
555
630
|
if (placeholder_idx >= 0) {
|
|
556
|
-
rb_raise(
|
|
631
|
+
rb_raise(rb_eArgError,
|
|
557
632
|
"reshape: only one auto-infer placeholder (-1 / :~) allowed");
|
|
558
633
|
}
|
|
559
634
|
placeholder_idx = i;
|
|
@@ -578,7 +653,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
578
653
|
src = (i < ca->ndim) ? i : ca->ndim - (argc - i);
|
|
579
654
|
}
|
|
580
655
|
if (src < 0 || src >= ca->ndim) {
|
|
581
|
-
rb_raise(
|
|
656
|
+
rb_raise(rb_eArgError,
|
|
582
657
|
"reshape: nil at axis %d has no source dim", i);
|
|
583
658
|
}
|
|
584
659
|
new_dim[i] = ca->dim[src];
|
|
@@ -586,13 +661,27 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
586
661
|
else {
|
|
587
662
|
new_dim[i] = NUM2SIZE(argv[i]);
|
|
588
663
|
}
|
|
589
|
-
|
|
664
|
+
/* A product too large to count cannot equal the element count; an
|
|
665
|
+
extent of zero anywhere makes it zero whatever it overflowed to. */
|
|
666
|
+
if ( __builtin_mul_overflow(prod, new_dim[i], &prod) ) {
|
|
667
|
+
overflow = 1;
|
|
668
|
+
}
|
|
669
|
+
if ( new_dim[i] == 0 ) {
|
|
670
|
+
zero = 1;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if ( zero ) {
|
|
674
|
+
prod = 0;
|
|
675
|
+
}
|
|
676
|
+
else if ( overflow ) {
|
|
677
|
+
rb_raise(rb_eArgError,
|
|
678
|
+
"reshape: the shape has more elements than an array can hold");
|
|
590
679
|
}
|
|
591
680
|
|
|
592
681
|
/* Resolve placeholder dim from the leftover total. */
|
|
593
682
|
if (placeholder_idx >= 0) {
|
|
594
683
|
if (prod == 0 || ca->elements % prod != 0) {
|
|
595
|
-
rb_raise(
|
|
684
|
+
rb_raise(rb_eArgError,
|
|
596
685
|
"reshape: cannot infer dim for `-1` placeholder");
|
|
597
686
|
}
|
|
598
687
|
new_dim[placeholder_idx] = ca->elements / prod;
|
|
@@ -604,7 +693,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
604
693
|
a subset), and on non-contiguous parents the compose-fold
|
|
605
694
|
path corrupts data outright — hence the raise. */
|
|
606
695
|
if (prod != ca->elements) {
|
|
607
|
-
rb_raise(
|
|
696
|
+
rb_raise(rb_eArgError,
|
|
608
697
|
"reshape: cannot reshape array of %lld elements into a shape "
|
|
609
698
|
"of %lld elements (use -1 / :~ to infer a dim)",
|
|
610
699
|
(long long) ca->elements, (long long) prod);
|
|
@@ -627,6 +716,7 @@ rb_ca_reshape (int argc, VALUE *argv, VALUE self)
|
|
|
627
716
|
ca->data_type, ca->bytes,
|
|
628
717
|
(int8_t) argc, new_dim,
|
|
629
718
|
out_strides, out_base);
|
|
719
|
+
ca_keep_chain_flags((CArray *) cs, ca);
|
|
630
720
|
obj = ca_wrap_struct(cs);
|
|
631
721
|
rb_ca_set_parent(obj, self);
|
|
632
722
|
CA_WRAPPER_LIFT(obj, self, ca);
|
|
@@ -664,6 +754,7 @@ rb_ca_flatten (VALUE self)
|
|
|
664
754
|
CAStride *cs = ca_stride_new(CA_OBJ_STRIDE, out_root,
|
|
665
755
|
ca->data_type, ca->bytes,
|
|
666
756
|
1, dim, out_strides, out_base);
|
|
757
|
+
ca_keep_chain_flags((CArray *) cs, ca);
|
|
667
758
|
obj = ca_wrap_struct(cs);
|
|
668
759
|
rb_ca_set_parent(obj, self);
|
|
669
760
|
CA_WRAPPER_LIFT(obj, self, ca);
|
|
@@ -691,7 +782,7 @@ rb_ca_flatten (VALUE self)
|
|
|
691
782
|
before axis 0 twice -> [1, 1, 2, 3]
|
|
692
783
|
|
|
693
784
|
Returns a CARefer view (zero-copy alias to +self+'s data, via reshape).
|
|
694
|
-
Bound to the
|
|
785
|
+
Bound to the private method insert_size_one_axes; the user-facing
|
|
695
786
|
insert_axis (with the repeat: keyword) is the Ruby method in
|
|
696
787
|
lib/carray/basics.rb, which builds on this primitive.
|
|
697
788
|
|
|
@@ -711,11 +802,7 @@ rb_ca_insert_axis (int argc, VALUE *argv, VALUE self)
|
|
|
711
802
|
|
|
712
803
|
ndim = (int) ca->ndim;
|
|
713
804
|
new_ndim = ndim + argc;
|
|
714
|
-
|
|
715
|
-
rb_raise(rb_eArgError,
|
|
716
|
-
"insert_axis: resulting ndim %d exceeds CA_RANK_MAX %d",
|
|
717
|
-
new_ndim, CA_RANK_MAX);
|
|
718
|
-
}
|
|
805
|
+
ca_check_rank_fits(new_ndim, "insert_axis");
|
|
719
806
|
|
|
720
807
|
ngap = ndim + 1; /* gaps live in [0, ndim] (ndim = the end gap) */
|
|
721
808
|
|
|
@@ -725,12 +812,7 @@ rb_ca_insert_axis (int argc, VALUE *argv, VALUE self)
|
|
|
725
812
|
gap_count[i] = 0;
|
|
726
813
|
}
|
|
727
814
|
for (i = 0; i < argc; i++) {
|
|
728
|
-
int
|
|
729
|
-
int g = (raw < 0) ? raw + ngap : raw;
|
|
730
|
-
if (g < 0 || g >= ngap) {
|
|
731
|
-
rb_raise(rb_eArgError,
|
|
732
|
-
"insert_axis: axis %d out of range for ndim %d", raw, ndim);
|
|
733
|
-
}
|
|
815
|
+
int g = ca_normalize_axis_arg(argv[i], ngap, "insert_axis");
|
|
734
816
|
gap_count[g]++;
|
|
735
817
|
}
|
|
736
818
|
|
|
@@ -774,7 +856,7 @@ Init_ca_obj_refer (void)
|
|
|
774
856
|
/* The bare size-1 primitive. The user-facing `insert_axis` (with its
|
|
775
857
|
`repeat:` keyword) is the Ruby method in lib/carray/basics.rb, which
|
|
776
858
|
owns the name and calls this primitive. */
|
|
777
|
-
|
|
859
|
+
rb_define_private_method(rb_cCArray, "insert_size_one_axes", rb_ca_insert_axis, -1);
|
|
778
860
|
rb_define_alloc_func(rb_cCARefer, rb_ca_refer_s_allocate);
|
|
779
861
|
rb_define_method(rb_cCARefer, "initialize_copy",
|
|
780
862
|
rb_ca_refer_initialize_copy, 1);
|
data/ext/ca_obj_remap.c
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
Constraints:
|
|
8
8
|
- ref.dim == idx.dim (same shape, same ndim, per-axis dim match)
|
|
9
9
|
- idx.data_type == CA_SIZE (caller responsible)
|
|
10
|
-
- No public constructor — there is no `CArray#remap(idx)`
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
- No public constructor — there is no `CArray#remap(idx)` surface; a
|
|
11
|
+
view is built by internal helpers and the `ca[idx]` same-shape
|
|
12
|
+
indexer fast path. `dup` / `clone` copy an existing one.
|
|
13
13
|
- The CARemap Ruby class IS rb_define_class'd: visibility lets users
|
|
14
14
|
see "this view came from a same-shape gather" when they inspect
|
|
15
15
|
`.class`. CA_OBJ_REMAP integer remains unexported as a Ruby
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
---------------------------------------------------------------------------- */
|
|
19
19
|
|
|
20
20
|
#include "carray.h"
|
|
21
|
+
#include "carray_internal.h"
|
|
21
22
|
|
|
22
23
|
typedef struct {
|
|
23
24
|
int16_t obj_type;
|
|
@@ -128,6 +129,12 @@ ca_remap_setup (CARemap *ca, CArray *ref, CArray *idx)
|
|
|
128
129
|
{
|
|
129
130
|
ca_remap_check_constraints(ref, idx);
|
|
130
131
|
|
|
132
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
133
|
+
run them before it allocates. */
|
|
134
|
+
if ( ca == NULL ) {
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
|
|
131
138
|
ca->obj_type = CA_OBJ_REMAP;
|
|
132
139
|
ca->data_type = ref->data_type;
|
|
133
140
|
ca->flags = 0;
|
|
@@ -146,9 +153,6 @@ ca_remap_setup (CARemap *ca, CArray *ref, CArray *idx)
|
|
|
146
153
|
ca->nosync = 0;
|
|
147
154
|
ca->idx = idx;
|
|
148
155
|
|
|
149
|
-
if ( ca_has_mask(ref) ) {
|
|
150
|
-
ca_create_mask(ca);
|
|
151
|
-
}
|
|
152
156
|
|
|
153
157
|
if ( ca_is_scalar(ref) ) {
|
|
154
158
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
@@ -160,8 +164,11 @@ ca_remap_setup (CARemap *ca, CArray *ref, CArray *idx)
|
|
|
160
164
|
CARemap *
|
|
161
165
|
ca_remap_new (CArray *ref, CArray *idx)
|
|
162
166
|
{
|
|
163
|
-
CARemap *ca
|
|
167
|
+
CARemap *ca;
|
|
168
|
+
ca_remap_setup(NULL, ref, idx);
|
|
169
|
+
ca = (CARemap *) ca_array_alloc(CA_OBJ_REMAP, ref->ndim);
|
|
164
170
|
ca_remap_setup(ca, ref, idx);
|
|
171
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
165
172
|
return ca;
|
|
166
173
|
}
|
|
167
174
|
|
|
@@ -210,15 +217,13 @@ static void
|
|
|
210
217
|
ca_remap_func_allocate (void *ap)
|
|
211
218
|
{
|
|
212
219
|
CARemap *ca = (CARemap *) ap;
|
|
213
|
-
ca->ptr =
|
|
220
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
214
221
|
}
|
|
215
222
|
|
|
216
223
|
static void
|
|
217
224
|
ca_remap_func_attach (void *ap)
|
|
218
225
|
{
|
|
219
|
-
|
|
220
|
-
ca->ptr = xmalloc(ca_length(ca));
|
|
221
|
-
ca_remap_func_xfer_all(ca, ca->ptr, CA_XFER_GET);
|
|
226
|
+
ca_axis_view_attach_owned(ap);
|
|
222
227
|
}
|
|
223
228
|
|
|
224
229
|
static void
|
|
@@ -265,10 +270,7 @@ static void
|
|
|
265
270
|
ca_remap_func_create_mask (void *ap)
|
|
266
271
|
{
|
|
267
272
|
CARemap *ca = (CARemap *) ap;
|
|
268
|
-
|
|
269
|
-
if ( ! ca->parent->mask ) {
|
|
270
|
-
ca_create_mask(ca->parent);
|
|
271
|
-
}
|
|
273
|
+
ca_create_mask(ca->parent);
|
|
272
274
|
/* Mask is a CARemap over (parent->mask, idx) — same shape, boolean. */
|
|
273
275
|
ca->mask = (CArray *) ca_remap_new(ca->parent->mask, ca->idx);
|
|
274
276
|
}
|
|
@@ -282,7 +284,7 @@ ca_remap_func_create_mask (void *ap)
|
|
|
282
284
|
2. ca_xfer_addrs(ca->idx, n, addrs, paddrs, GET) — one batched
|
|
283
285
|
read of the parent flat addresses through ca->idx's own
|
|
284
286
|
xfer_addrs dispatcher (entity, view, view chain — all
|
|
285
|
-
transparent).
|
|
287
|
+
transparent), each address then checked against the parent.
|
|
286
288
|
3. ca_xfer_addrs(ca->parent, n, paddrs, data, dir) — one batched
|
|
287
289
|
gather/scatter of the user payload against parent.
|
|
288
290
|
|
|
@@ -295,13 +297,20 @@ ca_remap_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
295
297
|
{
|
|
296
298
|
CARemap *ca = (CARemap *) ap;
|
|
297
299
|
ca_size_t *paddrs;
|
|
300
|
+
ca_size_t i;
|
|
298
301
|
volatile VALUE holder;
|
|
299
302
|
|
|
300
303
|
if ( n == 0 ) return;
|
|
301
304
|
|
|
302
305
|
paddrs = ALLOCV_N(ca_size_t, holder, n);
|
|
303
|
-
ca_xfer_addrs(ca->idx,
|
|
304
|
-
|
|
306
|
+
ca_xfer_addrs(ca->idx, n, addrs, paddrs, CA_XFER_GET);
|
|
307
|
+
/* idx is read live, so its values are checked here, not at
|
|
308
|
+
construction: negative counts from the end, out of range raises
|
|
309
|
+
before the parent is touched. */
|
|
310
|
+
for ( i = 0; i < n; i++ ) {
|
|
311
|
+
CA_CHECK_INDEX(paddrs[i], ca->parent->elements);
|
|
312
|
+
}
|
|
313
|
+
ca_xfer_addrs(ca->parent, n, paddrs, data, dir);
|
|
305
314
|
ALLOCV_END(holder);
|
|
306
315
|
}
|
|
307
316
|
|
|
@@ -329,6 +338,7 @@ static void
|
|
|
329
338
|
ca_remap_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
330
339
|
ca_size_t *strides, void *data, int dir)
|
|
331
340
|
{
|
|
341
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
332
342
|
CARemap *ca = (CARemap *) ap;
|
|
333
343
|
int8_t ndim = ca->ndim;
|
|
334
344
|
ca_size_t native[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
@@ -431,8 +441,9 @@ rb_ca_remap_new (VALUE cary, VALUE rmapper)
|
|
|
431
441
|
}
|
|
432
442
|
|
|
433
443
|
/* Read-only accessor for the per-cell index CArray that defines this
|
|
434
|
-
CARemap's mapping
|
|
435
|
-
|
|
444
|
+
CARemap's mapping: the array the view reads. For ca[mapper] it is a
|
|
445
|
+
copy of mapper taken at the call, so a later change to mapper does
|
|
446
|
+
not reach the view. Companion to
|
|
436
447
|
CABlock#start / CAStride#strides / CAWindow#count etc. — the view
|
|
437
448
|
hierarchy is preserved so each named view class exposes its own
|
|
438
449
|
defining semantic state. */
|
|
@@ -443,18 +454,68 @@ rb_ca_remap_mapper (VALUE self)
|
|
|
443
454
|
}
|
|
444
455
|
|
|
445
456
|
|
|
457
|
+
/* `dup` / `clone`. CARemap has no allocator (Ruby cannot build one), so
|
|
458
|
+
Object#dup cannot copy it; these build the copy the way the indexer
|
|
459
|
+
does: a new view over the same parent and the same index array. */
|
|
460
|
+
static VALUE
|
|
461
|
+
rb_ca_remap_dup (VALUE self)
|
|
462
|
+
{
|
|
463
|
+
volatile VALUE rmapper = rb_ivar_get(self, rb_intern("remap_idx"));
|
|
464
|
+
if ( NIL_P(rmapper) ) {
|
|
465
|
+
/* The mask of a CARemap (it holds no index array of its own): another
|
|
466
|
+
remap over the same parent mask and index. The array it is the mask
|
|
467
|
+
of keeps both alive, so the copy holds that array too. */
|
|
468
|
+
volatile VALUE obj;
|
|
469
|
+
CArray *ca, *cp;
|
|
470
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
471
|
+
cp = (CArray *) ca_remap_func_clone(ca);
|
|
472
|
+
ca_keep_chain_flags(cp, ca);
|
|
473
|
+
obj = TypedData_Wrap_Struct(rb_obj_class(self), &caremap_data_type, cp);
|
|
474
|
+
rb_ivar_set(obj, rb_intern("masked_array"),
|
|
475
|
+
rb_ivar_get(self, rb_intern("masked_array")));
|
|
476
|
+
return obj;
|
|
477
|
+
}
|
|
478
|
+
return rb_ca_remap_new(rb_ca_parent(self), rmapper);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
static VALUE
|
|
482
|
+
rb_ca_remap_clone (int argc, VALUE *argv, VALUE self)
|
|
483
|
+
{
|
|
484
|
+
VALUE opts = Qnil, vfreeze = Qnil;
|
|
485
|
+
volatile VALUE obj;
|
|
486
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
487
|
+
if ( ! NIL_P(opts) ) {
|
|
488
|
+
/* rb_get_kwargs refuses any key but freeze:, as Kernel#clone does. */
|
|
489
|
+
ID kw[1];
|
|
490
|
+
VALUE val[1];
|
|
491
|
+
kw[0] = rb_intern("freeze");
|
|
492
|
+
rb_get_kwargs(opts, kw, 0, 1, val);
|
|
493
|
+
if ( val[0] != Qundef ) {
|
|
494
|
+
vfreeze = val[0];
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
obj = rb_ca_remap_dup(self);
|
|
498
|
+
if ( RTEST(vfreeze) || ( NIL_P(vfreeze) && OBJ_FROZEN(self) ) ) {
|
|
499
|
+
rb_obj_freeze(obj);
|
|
500
|
+
}
|
|
501
|
+
return obj;
|
|
502
|
+
}
|
|
503
|
+
|
|
446
504
|
void
|
|
447
505
|
Init_ca_obj_remap (void)
|
|
448
506
|
{
|
|
449
507
|
/* CARemap is a proper Ruby class so users can see "this view is a
|
|
450
|
-
per-element gather" on .class.
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
tag, not
|
|
508
|
+
per-element gather" on .class. A view is built from C only (the
|
|
509
|
+
indexer and sort / partition): there is no allocator, and `dup` /
|
|
510
|
+
`clone` are defined here instead of going through one. CA_OBJ_REMAP
|
|
511
|
+
integer remains unexported (it's an internal type tag, not
|
|
512
|
+
user-meaningful). */
|
|
454
513
|
rb_cCARemap = rb_define_class("CARemap", rb_cCAView);
|
|
455
514
|
rb_cCARemapMask = rb_define_class("CARemapMask", rb_cCARemap);
|
|
456
515
|
rb_undef_alloc_func(rb_cCARemap);
|
|
457
516
|
rb_undef_alloc_func(rb_cCARemapMask);
|
|
517
|
+
rb_define_method(rb_cCARemap, "dup", rb_ca_remap_dup, 0);
|
|
518
|
+
rb_define_method(rb_cCARemap, "clone", rb_ca_remap_clone, -1);
|
|
458
519
|
|
|
459
520
|
ca_remap_func.struct_size = sizeof(CARemap);
|
|
460
521
|
ca_remap_func.pool_bytes = ca_remap_pool_bytes;
|