carray 3.0.3 → 3.0.5
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 +469 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +14 -26
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +231 -153
- data/ext/ca_compare.c +9 -20
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1240 -2000
- data/ext/ca_kernel_iterator.h +502 -519
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +152 -45
- data/ext/ca_obj_bincmp.c +25 -21
- data/ext/ca_obj_binop.c +16 -26
- data/ext/ca_obj_bitarray.c +8 -3
- data/ext/ca_obj_bitfield.c +63 -49
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +7 -7
- data/ext/ca_obj_const_string.c +188 -22
- data/ext/ca_obj_face.c +280 -58
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +30 -8
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +455 -134
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +113 -67
- data/ext/ca_obj_object.c +210 -52
- data/ext/ca_obj_record.c +15 -7
- data/ext/ca_obj_reduce.c +17 -8
- data/ext/ca_obj_refer.c +42 -35
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +31 -10
- data/ext/ca_obj_select.c +48 -14
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +41 -7
- data/ext/ca_obj_stack.c +180 -34
- data/ext/ca_obj_stride.c +190 -134
- data/ext/ca_obj_string.c +80 -4
- data/ext/ca_obj_tile.c +32 -11
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +13 -7
- data/ext/ca_obj_triop.c +26 -32
- data/ext/ca_obj_window.c +267 -74
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +214 -75
- data/ext/carray_access.c +200 -99
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +113 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +375 -96
- data/ext/carray_cast_func.rb +90 -20
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +18 -9
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +150 -55
- data/ext/carray_count.c +56 -20
- data/ext/carray_element.c +81 -33
- data/ext/carray_factorize.c +138 -84
- data/ext/carray_generate.c +199 -52
- data/ext/carray_histogram.c +63 -18
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +348 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10897 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +220 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +337 -94
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +129 -52
- data/ext/carray_order.c +604 -77
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +85 -31
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +87 -45
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +123 -37
- data/ext/carray_sort.c +259 -51
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +54 -61
- data/ext/carray_test.c +26 -5
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +309 -66
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +403 -350
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +139 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +105 -17
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +195 -59
- data/lib/carray/categorical_iterator.rb +132 -29
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +24 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +9 -1
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +48 -3
- data/lib/carray/frame/column_verbs.rb +71 -0
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +252 -28
- data/lib/carray/frame/group.rb +603 -101
- data/lib/carray/frame/io.rb +117 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +42 -6
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +217 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +61 -37
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +323 -88
- data/lib/carray/serialize.rb +45 -14
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +113 -5
- data/lib/carray/string_operation_extension.rb +21 -6
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +24 -11
- data/lib/carray/time.rb +819 -158
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +3 -6
- data/yard-stubs/carray_cast.rb +12 -0
- data/yard-stubs/carray_conversion.rb +7 -2
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +17 -10
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +32 -3
- data/yard-stubs/carray_math.rb +41 -5
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +129 -22
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +17 -10
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/ca_obj_object.c
CHANGED
|
@@ -60,6 +60,15 @@ ca_object_pool_init (void *ap, int8_t ndim)
|
|
|
60
60
|
ca->dim = (ca_size_t *) ca->_pool;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/* ca->self is the CAObject's own VALUE, which compaction can move; the
|
|
64
|
+
hooks call back through it, so follow the object to its new slot. */
|
|
65
|
+
static void
|
|
66
|
+
ca_object_compact (void *ap)
|
|
67
|
+
{
|
|
68
|
+
CAObject *ca = (CAObject *) ap;
|
|
69
|
+
ca->self = rb_gc_location(ca->self);
|
|
70
|
+
}
|
|
71
|
+
|
|
63
72
|
const rb_data_type_t caobject_data_type = {
|
|
64
73
|
.parent = &caview_data_type,
|
|
65
74
|
.wrap_struct_name = "CAObject",
|
|
@@ -67,7 +76,7 @@ const rb_data_type_t caobject_data_type = {
|
|
|
67
76
|
.dmark = ca_mark,
|
|
68
77
|
.dfree = ca_free,
|
|
69
78
|
.dsize = ca_object_dsize,
|
|
70
|
-
.dcompact =
|
|
79
|
+
.dcompact = ca_object_compact
|
|
71
80
|
},
|
|
72
81
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
73
82
|
};
|
|
@@ -84,15 +93,23 @@ ca_objectmask_dsize (const void *ap)
|
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
/* The mask reads and writes through its CAObject, and its cache is the
|
|
87
|
-
CAObject's; it keeps the CAObject alive
|
|
96
|
+
CAObject's; it keeps the CAObject alive, and follows it when compaction
|
|
97
|
+
moves it. */
|
|
88
98
|
static void
|
|
89
99
|
ca_objmask_mark (void *ap)
|
|
90
100
|
{
|
|
91
101
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
92
|
-
|
|
102
|
+
rb_gc_mark_movable(ca->array);
|
|
93
103
|
ca_mark(ap);
|
|
94
104
|
}
|
|
95
105
|
|
|
106
|
+
static void
|
|
107
|
+
ca_objmask_compact (void *ap)
|
|
108
|
+
{
|
|
109
|
+
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
110
|
+
ca->array = rb_gc_location(ca->array);
|
|
111
|
+
}
|
|
112
|
+
|
|
96
113
|
const rb_data_type_t caobjectmask_data_type = {
|
|
97
114
|
.parent = &carray_data_type,
|
|
98
115
|
.wrap_struct_name = "CAObjectMask",
|
|
@@ -100,7 +117,7 @@ const rb_data_type_t caobjectmask_data_type = {
|
|
|
100
117
|
.dmark = ca_objmask_mark,
|
|
101
118
|
.dfree = ca_free,
|
|
102
119
|
.dsize = ca_objectmask_dsize,
|
|
103
|
-
.dcompact =
|
|
120
|
+
.dcompact = ca_objmask_compact
|
|
104
121
|
},
|
|
105
122
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
106
123
|
};
|
|
@@ -111,6 +128,7 @@ VALUE rb_cCAObjectMask;
|
|
|
111
128
|
static CAObjectMask *
|
|
112
129
|
ca_objmask_new (VALUE array, int8_t ndim, ca_size_t *dim)
|
|
113
130
|
{
|
|
131
|
+
/* check: the mask takes the CAObject's own shape, already checked */
|
|
114
132
|
CAObjectMask *ca = ALLOC(CAObjectMask);
|
|
115
133
|
/* CA_OBJ_OBJECT_MASK registers no pool_init, so it lives on the legacy
|
|
116
134
|
ALLOC_N path (dim allocated separately, freed via free_ca_wrap's else
|
|
@@ -135,50 +153,126 @@ ca_objmask_mask_data (void *ap)
|
|
|
135
153
|
rb_intern("mask"), 0);
|
|
136
154
|
}
|
|
137
155
|
|
|
138
|
-
/*
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
/* A wrap handed to a hook points at a buffer the caller frees once the
|
|
157
|
+
hook returns. Taking it back leaves an array of no cells: a hook that
|
|
158
|
+
kept it holds something that raises when read, not a pointer into freed
|
|
159
|
+
memory. */
|
|
160
|
+
static char ca_object_no_cells[16];
|
|
161
|
+
|
|
162
|
+
static void
|
|
163
|
+
ca_object_empty_wrap (CArray *w)
|
|
164
|
+
{
|
|
165
|
+
int8_t k;
|
|
166
|
+
/* Not NULL: an entity whose pointer is NULL reads as detached. */
|
|
167
|
+
w->ptr = ca_object_no_cells;
|
|
168
|
+
w->elements = 0;
|
|
169
|
+
for ( k = 0; k < w->ndim; k++ ) {
|
|
170
|
+
w->dim[k] = 0;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Moves the cells of a wrap (or of its lent mask, `w`) into an array of
|
|
175
|
+
their own, held by `holder` under `name`, and points `w` at them. The
|
|
176
|
+
cells are those the hook left in the caller's buffer. */
|
|
177
|
+
static void
|
|
178
|
+
ca_object_keep_cells (VALUE holder, const char *name, CArray *w)
|
|
179
|
+
{
|
|
180
|
+
volatile VALUE cells;
|
|
181
|
+
CArray *c;
|
|
182
|
+
cells = rb_carray_new(w->data_type, w->ndim, w->dim, w->bytes, NULL);
|
|
183
|
+
c = (CArray *) DATA_PTR(cells);
|
|
184
|
+
memcpy(c->ptr, w->ptr, (size_t) w->elements * w->bytes);
|
|
185
|
+
rb_ivar_set(holder, rb_intern(name), cells);
|
|
186
|
+
w->ptr = c->ptr;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Takes the caller's buffer back from a wrap the hook was lent, together
|
|
190
|
+
with `lent_mask`, the wrap of the data's mask bits it was lent with (or
|
|
191
|
+
NULL). When the hook took a view of either, the view outlives the call,
|
|
192
|
+
so both keep their cells; otherwise both are left with none. A mask the
|
|
193
|
+
hook made on the wrap is the wrap's own, with cells of its own. */
|
|
194
|
+
static void
|
|
195
|
+
ca_object_take_back (VALUE wrap, CArray *lent_mask)
|
|
196
|
+
{
|
|
197
|
+
CArray *w = (CArray *) DATA_PTR(wrap);
|
|
198
|
+
CArray *m = ( lent_mask != NULL && w->mask == lent_mask ) ? lent_mask : NULL;
|
|
199
|
+
int viewed = ca_test_flag(w, CA_FLAG_LENT_VIEWED) ||
|
|
200
|
+
( m != NULL && ca_test_flag(m, CA_FLAG_LENT_VIEWED) );
|
|
201
|
+
ca_unset_flag(w, CA_FLAG_LENT | CA_FLAG_LENT_VIEWED);
|
|
202
|
+
if ( lent_mask != NULL ) {
|
|
203
|
+
ca_unset_flag(lent_mask, CA_FLAG_LENT | CA_FLAG_LENT_VIEWED);
|
|
204
|
+
}
|
|
205
|
+
if ( viewed ) {
|
|
206
|
+
ca_object_keep_cells(wrap, "kept_cells", w);
|
|
207
|
+
if ( m != NULL ) {
|
|
208
|
+
ca_object_keep_cells(wrap, "kept_mask_cells", m);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
if ( m != NULL ) {
|
|
213
|
+
ca_object_empty_wrap(m);
|
|
214
|
+
}
|
|
215
|
+
ca_object_empty_wrap(w);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* Calls copy_data / sync_data with a wrap of a caller's buffer, shaped as
|
|
220
|
+
the object, and takes the buffer back however the call leaves. When the
|
|
221
|
+
data has a mask, the wrap's mask is a wrap of its bits: a hook that writes
|
|
222
|
+
masked values masks the object's cells, and the data keeps its mask
|
|
223
|
+
whatever the hook does with the wrap's. A mask the hook makes on a wrap
|
|
224
|
+
that had none is the wrap's own and goes with it. The data points at the
|
|
225
|
+
buffer for the duration too, for a hook that reads the object back while
|
|
226
|
+
it runs. */
|
|
143
227
|
|
|
144
228
|
typedef struct {
|
|
145
|
-
|
|
146
|
-
char
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
void *ap;
|
|
229
|
+
CAObject *ca;
|
|
230
|
+
char *saved;
|
|
231
|
+
ID mid;
|
|
232
|
+
VALUE wrap;
|
|
233
|
+
CArray *mask; /* the wrap of the data's mask bits, or NULL */
|
|
151
234
|
} ca_object_lend_t;
|
|
152
235
|
|
|
153
236
|
static VALUE
|
|
154
237
|
ca_object_lend_body (VALUE varg)
|
|
155
238
|
{
|
|
156
239
|
ca_object_lend_t *l = (ca_object_lend_t *) varg;
|
|
157
|
-
return rb_funcall(l->
|
|
240
|
+
return rb_funcall(l->ca->self, l->mid, 1, l->wrap);
|
|
158
241
|
}
|
|
159
242
|
|
|
160
243
|
static VALUE
|
|
161
244
|
ca_object_lend_restore (VALUE varg)
|
|
162
245
|
{
|
|
163
246
|
ca_object_lend_t *l = (ca_object_lend_t *) varg;
|
|
164
|
-
|
|
247
|
+
l->ca->data->ptr = l->saved;
|
|
248
|
+
ca_object_take_back(l->wrap, l->mask);
|
|
165
249
|
return Qnil;
|
|
166
250
|
}
|
|
167
251
|
|
|
168
252
|
static void
|
|
169
|
-
ca_object_call_lending (
|
|
170
|
-
VALUE (*arg)(void *), void *ap)
|
|
253
|
+
ca_object_call_lending (CAObject *ca, void *ptr, const char *mid)
|
|
171
254
|
{
|
|
172
255
|
ca_object_lend_t l;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
256
|
+
CArray *data = ca->data;
|
|
257
|
+
CAWrap *w;
|
|
258
|
+
w = ca_wrap_new(data->data_type, data->ndim, data->dim, data->bytes,
|
|
259
|
+
NULL, (char *) ptr);
|
|
260
|
+
l.wrap = ca_wrap_struct(w);
|
|
261
|
+
l.mask = NULL;
|
|
262
|
+
if ( data->mask != NULL ) {
|
|
263
|
+
l.mask = (CArray *) ca_wrap_new(CA_BOOLEAN, data->ndim, data->dim, 0,
|
|
264
|
+
NULL, data->mask->ptr);
|
|
265
|
+
ca_set_flag(l.mask, CA_FLAG_LENT);
|
|
266
|
+
w->mask = l.mask;
|
|
267
|
+
}
|
|
268
|
+
ca_set_flag(w, CA_FLAG_LENT);
|
|
269
|
+
l.ca = ca;
|
|
270
|
+
l.saved = data->ptr;
|
|
176
271
|
l.mid = rb_intern(mid);
|
|
177
|
-
|
|
178
|
-
l.ap = ap;
|
|
179
|
-
*slot = (char *) ptr;
|
|
272
|
+
data->ptr = (char *) ptr;
|
|
180
273
|
rb_ensure(ca_object_lend_body, (VALUE) &l,
|
|
181
274
|
ca_object_lend_restore, (VALUE) &l);
|
|
275
|
+
RB_GC_GUARD(l.wrap);
|
|
182
276
|
}
|
|
183
277
|
|
|
184
278
|
/* Calls recv.mid(*argv), where some of argv are transient wraps of a
|
|
@@ -187,8 +281,7 @@ ca_object_call_lending (char **slot, void *ptr, VALUE recv, const char *mid,
|
|
|
187
281
|
when it returns, and a wrap outlives the call: the collector scans the
|
|
188
282
|
machine stack conservatively and still finds it there, and an object
|
|
189
283
|
wrap is marked cell by cell -- through a buffer that is gone. A wrap
|
|
190
|
-
taken back
|
|
191
|
-
handle, not a stale one. */
|
|
284
|
+
taken back has no cells (ca_object_empty_wrap). */
|
|
192
285
|
|
|
193
286
|
typedef struct {
|
|
194
287
|
VALUE recv;
|
|
@@ -212,7 +305,7 @@ ca_object_hook_release (VALUE varg)
|
|
|
212
305
|
ca_object_hook_t *h = (ca_object_hook_t *) varg;
|
|
213
306
|
int i;
|
|
214
307
|
for ( i = 0; i < h->ntrans; i++ ) {
|
|
215
|
-
(
|
|
308
|
+
ca_object_take_back(h->trans[i], NULL);
|
|
216
309
|
}
|
|
217
310
|
return Qnil;
|
|
218
311
|
}
|
|
@@ -233,11 +326,6 @@ ca_object_call_transient (VALUE recv, const char *mid,
|
|
|
233
326
|
ca_object_hook_release, (VALUE) &h);
|
|
234
327
|
}
|
|
235
328
|
|
|
236
|
-
static VALUE
|
|
237
|
-
ca_object_data_of (void *ap)
|
|
238
|
-
{
|
|
239
|
-
return rb_ivar_get(((CAObject *) ap)->self, rb_intern("__data__"));
|
|
240
|
-
}
|
|
241
329
|
|
|
242
330
|
|
|
243
331
|
/* Forward declaration: ca_object_wrap_transient (defined further down,
|
|
@@ -706,14 +794,19 @@ ca_object_setup (CAObject *ca,
|
|
|
706
794
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes)
|
|
707
795
|
{
|
|
708
796
|
ca_size_t elements;
|
|
709
|
-
int8_t i;
|
|
710
797
|
|
|
711
798
|
/* check arguments */
|
|
712
799
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
800
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
801
|
+
CA_CHECK_RANK_GIVEN(ndim);
|
|
802
|
+
CA_CHECK_DIM_GIVEN(ndim, dim);
|
|
803
|
+
CA_CHECK_BYTES_GIVEN(data_type, bytes);
|
|
804
|
+
|
|
805
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
806
|
+
run them before it allocates. */
|
|
807
|
+
if ( ca == NULL ) {
|
|
808
|
+
return 0;
|
|
809
|
+
}
|
|
717
810
|
|
|
718
811
|
/* calculate total number of elements */
|
|
719
812
|
|
|
@@ -745,7 +838,9 @@ ca_object_setup (CAObject *ca,
|
|
|
745
838
|
static CAObject *
|
|
746
839
|
ca_object_new (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes)
|
|
747
840
|
{
|
|
748
|
-
CAObject *ca
|
|
841
|
+
CAObject *ca;
|
|
842
|
+
ca_object_setup(NULL, data_type, ndim, dim, bytes);
|
|
843
|
+
ca = (CAObject *) ca_array_alloc(CA_OBJ_OBJECT, ndim);
|
|
749
844
|
ca_object_setup(ca, data_type, ndim, dim, bytes);
|
|
750
845
|
return ca;
|
|
751
846
|
}
|
|
@@ -755,7 +850,12 @@ free_ca_object (void *ap)
|
|
|
755
850
|
{
|
|
756
851
|
CAObject *ca = (CAObject *) ap;
|
|
757
852
|
if ( ca != NULL ) {
|
|
758
|
-
/*
|
|
853
|
+
/* A Face's mask is a view over its parent's mask (made by
|
|
854
|
+
ca_view_func_create_mask) and belongs to this struct. Otherwise
|
|
855
|
+
the mask is a Ruby object held in @mask, and the GC frees it. */
|
|
856
|
+
if ( ca_is_face(ca) ) {
|
|
857
|
+
ca_free(ca->mask);
|
|
858
|
+
}
|
|
759
859
|
if ( ca->_pool ) {
|
|
760
860
|
ca_array_free(ca); /* dim lives in _pool */
|
|
761
861
|
}
|
|
@@ -789,6 +889,19 @@ ca_object_mask_bytes (CAObject *ca)
|
|
|
789
889
|
return (boolean8_t *) ca->mask->ptr;
|
|
790
890
|
}
|
|
791
891
|
|
|
892
|
+
/* Whether the mask of this object comes from its mask_* hooks. Then a
|
|
893
|
+
fetched value says nothing about the mask: a cell the hooks mask stays
|
|
894
|
+
masked when its value is read, and only a fetcher answering UNDEF marks
|
|
895
|
+
one. Without hooks the mask is what the fetches have answered, so a
|
|
896
|
+
value fetched clears the cell. */
|
|
897
|
+
static int
|
|
898
|
+
ca_object_mask_from_hooks (CAObject *ca)
|
|
899
|
+
{
|
|
900
|
+
return rb_obj_respond_to(ca->self, rb_intern("mask_fetch_addr"), Qtrue)
|
|
901
|
+
|| rb_obj_respond_to(ca->self, rb_intern("mask_fetch_index"), Qtrue)
|
|
902
|
+
|| rb_obj_respond_to(ca->self, rb_intern("mask_copy_data"), Qtrue);
|
|
903
|
+
}
|
|
904
|
+
|
|
792
905
|
/* per-cell cores: the addr- and index-primary Ruby-callback bridge logic,
|
|
793
906
|
direction-unified. The fetch_* / store_* slots below are thin
|
|
794
907
|
forwarders onto these. */
|
|
@@ -809,7 +922,7 @@ ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
|
809
922
|
}
|
|
810
923
|
}
|
|
811
924
|
else {
|
|
812
|
-
if ( ca_has_mask(ca) ) {
|
|
925
|
+
if ( ! ca_object_mask_from_hooks(ca) && ca_has_mask(ca) ) {
|
|
813
926
|
ca_object_mask_bytes(ca)[addr] = 0;
|
|
814
927
|
}
|
|
815
928
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
@@ -831,7 +944,7 @@ ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
|
831
944
|
}
|
|
832
945
|
}
|
|
833
946
|
else {
|
|
834
|
-
if ( ca_has_mask(ca) ) {
|
|
947
|
+
if ( ! ca_object_mask_from_hooks(ca) && ca_has_mask(ca) ) {
|
|
835
948
|
ca_object_mask_bytes(ca)[ca_index2addr(ca->mask, idx)] = 0;
|
|
836
949
|
}
|
|
837
950
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
@@ -877,7 +990,7 @@ ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
|
877
990
|
}
|
|
878
991
|
}
|
|
879
992
|
else {
|
|
880
|
-
if ( ca_has_mask(ca) ) {
|
|
993
|
+
if ( ! ca_object_mask_from_hooks(ca) && ca_has_mask(ca) ) {
|
|
881
994
|
ca_object_mask_bytes(ca)[ca_index2addr(ca->mask, idx)] = 0;
|
|
882
995
|
}
|
|
883
996
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
@@ -895,7 +1008,7 @@ ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
|
895
1008
|
}
|
|
896
1009
|
}
|
|
897
1010
|
else {
|
|
898
|
-
if ( ca_has_mask(ca) ) {
|
|
1011
|
+
if ( ! ca_object_mask_from_hooks(ca) && ca_has_mask(ca) ) {
|
|
899
1012
|
ca_object_mask_bytes(ca)[addr] = 0;
|
|
900
1013
|
}
|
|
901
1014
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
@@ -924,8 +1037,8 @@ static void
|
|
|
924
1037
|
ca_object_func_allocate (void *ap)
|
|
925
1038
|
{
|
|
926
1039
|
CAObject *ca = (CAObject *) ap;
|
|
927
|
-
/*
|
|
928
|
-
ca->data->ptr = xmalloc(ca_length(ca));
|
|
1040
|
+
/* cells: seeded with 0, which a copy_data that skips cells leaves visible */
|
|
1041
|
+
ca->data->ptr = xmalloc(ca_length(ca));
|
|
929
1042
|
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
930
1043
|
VALUE *p = (VALUE *) ca->data->ptr;
|
|
931
1044
|
VALUE zero = INT2NUM(0);
|
|
@@ -951,12 +1064,51 @@ ca_object_func_allocate (void *ap)
|
|
|
951
1064
|
arithmetic all work via the slow per-element fallback. The fast bulk
|
|
952
1065
|
path is opt-in by defining copy_data / sync_data / fill_data. */
|
|
953
1066
|
|
|
1067
|
+
/* copy_data of an object whose mask comes from its hooks: the array it is
|
|
1068
|
+
handed must not carry the mask's cache, or a store of its values into it
|
|
1069
|
+
(d[] = src) would clear the cells the hooks mask. It is handed without a
|
|
1070
|
+
mask, and a mask the call makes on it is dropped. */
|
|
1071
|
+
typedef struct {
|
|
1072
|
+
CAObject *ca;
|
|
1073
|
+
void *ptr;
|
|
1074
|
+
CArray *mask;
|
|
1075
|
+
} ca_object_copy_bare_t;
|
|
1076
|
+
|
|
1077
|
+
static VALUE
|
|
1078
|
+
ca_object_copy_bare_body (VALUE arg)
|
|
1079
|
+
{
|
|
1080
|
+
ca_object_copy_bare_t *c = (ca_object_copy_bare_t *) arg;
|
|
1081
|
+
ca_object_call_lending(c->ca, c->ptr, "copy_data");
|
|
1082
|
+
return Qnil;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
static VALUE
|
|
1086
|
+
ca_object_copy_bare_restore (VALUE arg)
|
|
1087
|
+
{
|
|
1088
|
+
ca_object_copy_bare_t *c = (ca_object_copy_bare_t *) arg;
|
|
1089
|
+
CArray *made = c->ca->data->mask;
|
|
1090
|
+
if ( made != NULL && made != c->mask ) {
|
|
1091
|
+
ca_free(made);
|
|
1092
|
+
}
|
|
1093
|
+
c->ca->data->mask = c->mask;
|
|
1094
|
+
return Qnil;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
954
1097
|
static void
|
|
955
1098
|
ca_object_dispatch_copy (CAObject *ca, void *ptr)
|
|
956
1099
|
{
|
|
957
1100
|
if ( rb_obj_respond_to(ca->self, rb_intern("copy_data"), Qtrue) ) {
|
|
958
|
-
|
|
959
|
-
|
|
1101
|
+
if ( ca->data->mask != NULL && ca_object_mask_from_hooks(ca) ) {
|
|
1102
|
+
ca_object_copy_bare_t c;
|
|
1103
|
+
c.ca = ca;
|
|
1104
|
+
c.ptr = ptr;
|
|
1105
|
+
c.mask = ca->data->mask;
|
|
1106
|
+
ca->data->mask = NULL;
|
|
1107
|
+
rb_ensure(ca_object_copy_bare_body, (VALUE) &c,
|
|
1108
|
+
ca_object_copy_bare_restore, (VALUE) &c);
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
ca_object_call_lending(ca, ptr, "copy_data");
|
|
960
1112
|
}
|
|
961
1113
|
else {
|
|
962
1114
|
ca_size_t addr;
|
|
@@ -971,8 +1123,7 @@ static void
|
|
|
971
1123
|
ca_object_dispatch_sync (CAObject *ca, void *ptr)
|
|
972
1124
|
{
|
|
973
1125
|
if ( rb_obj_respond_to(ca->self, rb_intern("sync_data"), Qtrue) ) {
|
|
974
|
-
ca_object_call_lending(
|
|
975
|
-
ca_object_data_of, ca);
|
|
1126
|
+
ca_object_call_lending(ca, ptr, "sync_data");
|
|
976
1127
|
}
|
|
977
1128
|
else {
|
|
978
1129
|
ca_size_t addr;
|
|
@@ -1017,7 +1168,7 @@ ca_object_func_attach (void *ap)
|
|
|
1017
1168
|
ca_face_attach(ap);
|
|
1018
1169
|
return;
|
|
1019
1170
|
}
|
|
1020
|
-
/*
|
|
1171
|
+
/* cells: seeded with 0, which a copy_data that skips cells leaves visible */
|
|
1021
1172
|
ca->data->ptr = xmalloc(ca_length(ca));
|
|
1022
1173
|
if ( ca_is_object_type(ca->data) ) { /* GC safe */
|
|
1023
1174
|
VALUE *p = (VALUE *) ca->data->ptr;
|
|
@@ -1094,6 +1245,7 @@ ca_object_wrap_transient (int8_t data_type, ca_size_t bytes,
|
|
|
1094
1245
|
}
|
|
1095
1246
|
|
|
1096
1247
|
wrap = ca_wrap_new(data_type, ndim, dim, bytes, NULL, (char *) data);
|
|
1248
|
+
ca_set_flag(wrap, CA_FLAG_LENT);
|
|
1097
1249
|
return ca_wrap_struct(wrap);
|
|
1098
1250
|
}
|
|
1099
1251
|
|
|
@@ -1468,6 +1620,12 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
1468
1620
|
data = ca_wrap_struct(ca->data);
|
|
1469
1621
|
rb_ivar_set(self, rb_intern("__data__"), data);
|
|
1470
1622
|
|
|
1623
|
+
/* A Face's mask is a C struct owned by the Face, so the copy makes its
|
|
1624
|
+
own from the parent when it is asked for one. */
|
|
1625
|
+
if ( ca_is_face(ca) ) {
|
|
1626
|
+
return self;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1471
1629
|
ca_update_mask(cs);
|
|
1472
1630
|
if ( cs->mask ) {
|
|
1473
1631
|
ca->mask = cs->mask;
|
|
@@ -1567,7 +1725,7 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1567
1725
|
}
|
|
1568
1726
|
|
|
1569
1727
|
Check_Type(rdim, T_ARRAY);
|
|
1570
|
-
|
|
1728
|
+
CA_CHECK_RANK_GIVEN(RARRAY_LEN(rdim)); /* before dim[] is filled */
|
|
1571
1729
|
|
|
1572
1730
|
ndim = RARRAY_LEN(rdim);
|
|
1573
1731
|
for (i=0; i<ndim; i++) {
|
data/ext/ca_obj_record.c
CHANGED
|
@@ -100,6 +100,12 @@ ca_record_setup (CARecord *ca, CArray *parent, VALUE data_class)
|
|
|
100
100
|
parent->data_type);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
104
|
+
run them before it allocates. */
|
|
105
|
+
if ( ca == NULL ) {
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
103
109
|
ca->obj_type = CA_OBJ_RECORD;
|
|
104
110
|
ca->data_type = CA_FIXLEN;
|
|
105
111
|
ca->flags = CA_FLAG_IS_FACE;
|
|
@@ -119,9 +125,6 @@ ca_record_setup (CARecord *ca, CArray *parent, VALUE data_class)
|
|
|
119
125
|
|
|
120
126
|
ca->data_class = data_class;
|
|
121
127
|
|
|
122
|
-
if ( ca_has_mask(parent) ) {
|
|
123
|
-
ca_create_mask((CArray *) ca);
|
|
124
|
-
}
|
|
125
128
|
|
|
126
129
|
if ( ca_is_scalar(parent) ) {
|
|
127
130
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
@@ -137,8 +140,11 @@ ca_record_setup (CARecord *ca, CArray *parent, VALUE data_class)
|
|
|
137
140
|
CARecord *
|
|
138
141
|
ca_record_new (CArray *parent, VALUE data_class)
|
|
139
142
|
{
|
|
140
|
-
CARecord *ca
|
|
143
|
+
CARecord *ca;
|
|
144
|
+
ca_record_setup(NULL, parent, data_class);
|
|
145
|
+
ca = (CARecord *) ca_array_alloc(CA_OBJ_RECORD, parent->ndim);
|
|
141
146
|
ca_record_setup(ca, parent, data_class);
|
|
147
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
142
148
|
return ca;
|
|
143
149
|
}
|
|
144
150
|
|
|
@@ -270,9 +276,7 @@ rb_ca_record_s_new (int argc, VALUE *argv, VALUE klass)
|
|
|
270
276
|
shape_offset = 1;
|
|
271
277
|
}
|
|
272
278
|
ndim = argc - shape_offset;
|
|
273
|
-
|
|
274
|
-
rb_raise(rb_eArgError, "invalid number of shape arguments (%d)", ndim);
|
|
275
|
-
}
|
|
279
|
+
ca_check_rank_fits(ndim, NULL);
|
|
276
280
|
for ( i = 0; i < ndim; i++ ) {
|
|
277
281
|
dim[i] = NUM2SIZE(argv[shape_offset + i]);
|
|
278
282
|
}
|
|
@@ -305,6 +309,9 @@ rb_ca_record_s_wrap (int argc, VALUE *argv, VALUE klass)
|
|
|
305
309
|
rb_scan_args(argc, argv, "2", &entity_val, &data_class);
|
|
306
310
|
}
|
|
307
311
|
rb_check_carray_object(entity_val);
|
|
312
|
+
/* A record array (or another Face) is wrapped from its storage, so the
|
|
313
|
+
new record is not a Face over a Face. */
|
|
314
|
+
entity_val = rb_ca_strip_face_value(entity_val);
|
|
308
315
|
return ca_record_build(klass, data_class, entity_val);
|
|
309
316
|
}
|
|
310
317
|
|
|
@@ -362,6 +369,7 @@ rb_ca_record_initialize_copy (VALUE self, VALUE other)
|
|
|
362
369
|
ca_array_pool_alloc(ca, CA_OBJ_RECORD, cs->parent->ndim);
|
|
363
370
|
}
|
|
364
371
|
ca_record_setup(ca, cs->parent, cs->data_class);
|
|
372
|
+
ca_view_inherit_mask((VALUE) ca);
|
|
365
373
|
/* Marshal loads into an empty instance through here without copying
|
|
366
374
|
ivars, so the parent pin is set from `other`, not inherited. */
|
|
367
375
|
rb_ca_set_parent(self, rb_ca_parent(other));
|
data/ext/ca_obj_reduce.c
CHANGED
|
@@ -56,6 +56,16 @@ ca_reduce_setup (CAReduce *ca, CArray *parent, ca_size_t count, ca_size_t offset
|
|
|
56
56
|
"[BUG] CAReduce can't inherit other than boolean array");
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
if ( count <= 0 ) {
|
|
60
|
+
rb_raise(rb_eArgError, "CAReduce: count should be positive");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
64
|
+
run them before it allocates. */
|
|
65
|
+
if ( ca == NULL ) {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
59
69
|
elements = parent->elements / count;
|
|
60
70
|
|
|
61
71
|
ca->obj_type = CA_OBJ_REDUCE;
|
|
@@ -75,9 +85,6 @@ ca_reduce_setup (CAReduce *ca, CArray *parent, ca_size_t count, ca_size_t offset
|
|
|
75
85
|
ca->count = count;
|
|
76
86
|
ca->offset = offset;
|
|
77
87
|
|
|
78
|
-
if ( ca_has_mask(parent) ) {
|
|
79
|
-
ca_create_mask(ca);
|
|
80
|
-
}
|
|
81
88
|
|
|
82
89
|
if ( ca_is_scalar(parent) ) {
|
|
83
90
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
@@ -89,8 +96,11 @@ ca_reduce_setup (CAReduce *ca, CArray *parent, ca_size_t count, ca_size_t offset
|
|
|
89
96
|
CAReduce *
|
|
90
97
|
ca_reduce_new (CArray *parent, ca_size_t count, ca_size_t offset)
|
|
91
98
|
{
|
|
92
|
-
CAReduce *ca
|
|
99
|
+
CAReduce *ca;
|
|
100
|
+
ca_reduce_setup(NULL, parent, count, offset);
|
|
101
|
+
ca = ALLOC(CAReduce);
|
|
93
102
|
ca_reduce_setup(ca, parent, count, offset);
|
|
103
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
94
104
|
return ca;
|
|
95
105
|
}
|
|
96
106
|
|
|
@@ -193,8 +203,7 @@ ca_reduce_func_allocate (void *ap)
|
|
|
193
203
|
{
|
|
194
204
|
CAReduce *ca = (CAReduce *) ap;
|
|
195
205
|
ca_attach(ca->parent);
|
|
196
|
-
|
|
197
|
-
ca->ptr = xmalloc(ca_length(ca));
|
|
206
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
198
207
|
}
|
|
199
208
|
|
|
200
209
|
static void
|
|
@@ -204,8 +213,7 @@ ca_reduce_func_attach (void *ap)
|
|
|
204
213
|
char *p;
|
|
205
214
|
ca_size_t i;
|
|
206
215
|
ca_attach(ca->parent);
|
|
207
|
-
|
|
208
|
-
ca->ptr = xmalloc(ca_length(ca));
|
|
216
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
209
217
|
p = ca->ptr;
|
|
210
218
|
for (i=0; i<ca->elements; i++) {
|
|
211
219
|
ca_reduce_func_xfer_addrs(ca, 1, &i, p, CA_XFER_GET);
|
|
@@ -314,6 +322,7 @@ rb_ca_reduce_initialize_copy (VALUE self, VALUE other)
|
|
|
314
322
|
TypedData_Get_Struct(other, CAReduce, &careduce_data_type, cs);
|
|
315
323
|
|
|
316
324
|
ca_reduce_setup(ca, cs->parent, cs->count, cs->offset);
|
|
325
|
+
ca_view_inherit_mask((VALUE) ca);
|
|
317
326
|
|
|
318
327
|
return self;
|
|
319
328
|
}
|