carray 3.0.2 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +304 -0
- data/README.md +3 -4
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +225 -0
- data/ext/ca_axis_group.c +177 -99
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +66 -71
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +663 -214
- data/ext/ca_kernel_iterator.h +231 -167
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +132 -22
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +1 -0
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +96 -25
- data/ext/ca_obj_face.c +406 -64
- data/ext/ca_obj_face.h +92 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +21 -21
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +189 -107
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +543 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +47 -49
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -118
- data/ext/ca_obj_stride.c +195 -34
- data/ext/ca_obj_string.c +17 -18
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +149 -27
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +102 -79
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +70 -27
- data/ext/carray_access.c +455 -211
- data/ext/carray_address_basis.c +177 -36
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +46 -14
- data/ext/carray_call_cfunc.c +0 -28
- data/ext/carray_cast.c +1444 -209
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +32 -11
- data/ext/carray_core.c +514 -122
- data/ext/carray_count.c +140 -87
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +569 -277
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +385 -3
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +682 -316
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +221 -76
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1089 -359
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +273 -239
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +170 -70
- data/ext/carray_sort.c +215 -218
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +0 -2
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1076 -846
- data/ext/ruby_carray.c +7 -1
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +19 -0
- data/lib/carray/autoload_method_extension.rb +6 -0
- data/lib/carray/axis_group.rb +174 -26
- data/lib/carray/basics.rb +91 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +118 -48
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +94 -26
- data/lib/carray/categorical_iterator.rb +333 -826
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +46 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +589 -82
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +124 -25
- data/lib/carray/frame/group.rb +189 -63
- data/lib/carray/frame/io.rb +412 -72
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +37 -16
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +715 -48
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +29 -11
- data/lib/carray/iterator.rb +14 -2
- data/lib/carray/lazy.rb +54 -30
- data/lib/carray/mask_gap_fill.rb +66 -52
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +117 -4
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +177 -36
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +51 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +4 -3
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +517 -103
- data/lib/carray/window_iterator.rb +127 -72
- data/lib/carray.rb +2 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +1 -2
- data/yard-stubs/carray_access.rb +5 -4
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +25 -13
- data/yard-stubs/carray_median_percentile.rb +10 -6
- data/yard-stubs/carray_order.rb +34 -13
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +2 -1
- data/yard-stubs/carray_sort.rb +43 -3
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +11 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -26005
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14862
- data/ext/carray_kernels_reduce_extreme.c +0 -17494
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32218
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/ca_obj_object.c
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
36
|
#include "carray.h"
|
|
37
|
+
#include "carray_internal.h"
|
|
37
38
|
#include "ca_obj_face.h" /* ca_face_* helpers for Face mode shortcuts */
|
|
38
39
|
|
|
39
40
|
static size_t
|
|
@@ -82,11 +83,21 @@ ca_objectmask_dsize (const void *ap)
|
|
|
82
83
|
return sizeof(CAObjectMask) + ca->ndim * sizeof(ca_size_t);
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
/* The mask reads and writes through its CAObject, and its cache is the
|
|
87
|
+
CAObject's; it keeps the CAObject alive. */
|
|
88
|
+
static void
|
|
89
|
+
ca_objmask_mark (void *ap)
|
|
90
|
+
{
|
|
91
|
+
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
92
|
+
rb_gc_mark(ca->array);
|
|
93
|
+
ca_mark(ap);
|
|
94
|
+
}
|
|
95
|
+
|
|
85
96
|
const rb_data_type_t caobjectmask_data_type = {
|
|
86
97
|
.parent = &carray_data_type,
|
|
87
98
|
.wrap_struct_name = "CAObjectMask",
|
|
88
99
|
.function = {
|
|
89
|
-
.dmark =
|
|
100
|
+
.dmark = ca_objmask_mark,
|
|
90
101
|
.dfree = ca_free,
|
|
91
102
|
.dsize = ca_objectmask_dsize,
|
|
92
103
|
.dcompact = NULL
|
|
@@ -110,6 +121,8 @@ ca_objmask_new (VALUE array, int8_t ndim, ca_size_t *dim)
|
|
|
110
121
|
ca_wrap_setup_null((CArray *)ca, CA_BOOLEAN, ndim, dim, 0, NULL);
|
|
111
122
|
ca->obj_type = CA_OBJ_OBJECT_MASK;
|
|
112
123
|
ca->array = array;
|
|
124
|
+
ca->cache = NULL;
|
|
125
|
+
ca->holds = 0;
|
|
113
126
|
|
|
114
127
|
return ca;
|
|
115
128
|
}
|
|
@@ -122,125 +135,358 @@ ca_objmask_mask_data (void *ap)
|
|
|
122
135
|
rb_intern("mask"), 0);
|
|
123
136
|
}
|
|
124
137
|
|
|
138
|
+
/* Calls recv.mid(arg(ap)) with *slot pointing at a caller's buffer for
|
|
139
|
+
the duration, and puts *slot back however the call leaves. The bulk
|
|
140
|
+
bridge lends the buffer this way so that copy_data / sync_data write
|
|
141
|
+
straight into it; a raise that skipped the restore would leave the
|
|
142
|
+
array pointing at a buffer its caller is about to free. */
|
|
143
|
+
|
|
144
|
+
typedef struct {
|
|
145
|
+
char **slot;
|
|
146
|
+
char *saved;
|
|
147
|
+
VALUE recv;
|
|
148
|
+
ID mid;
|
|
149
|
+
VALUE (*arg)(void *);
|
|
150
|
+
void *ap;
|
|
151
|
+
} ca_object_lend_t;
|
|
152
|
+
|
|
153
|
+
static VALUE
|
|
154
|
+
ca_object_lend_body (VALUE varg)
|
|
155
|
+
{
|
|
156
|
+
ca_object_lend_t *l = (ca_object_lend_t *) varg;
|
|
157
|
+
return rb_funcall(l->recv, l->mid, 1, l->arg(l->ap));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static VALUE
|
|
161
|
+
ca_object_lend_restore (VALUE varg)
|
|
162
|
+
{
|
|
163
|
+
ca_object_lend_t *l = (ca_object_lend_t *) varg;
|
|
164
|
+
*l->slot = l->saved;
|
|
165
|
+
return Qnil;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static void
|
|
169
|
+
ca_object_call_lending (char **slot, void *ptr, VALUE recv, const char *mid,
|
|
170
|
+
VALUE (*arg)(void *), void *ap)
|
|
171
|
+
{
|
|
172
|
+
ca_object_lend_t l;
|
|
173
|
+
l.slot = slot;
|
|
174
|
+
l.saved = *slot;
|
|
175
|
+
l.recv = recv;
|
|
176
|
+
l.mid = rb_intern(mid);
|
|
177
|
+
l.arg = arg;
|
|
178
|
+
l.ap = ap;
|
|
179
|
+
*slot = (char *) ptr;
|
|
180
|
+
rb_ensure(ca_object_lend_body, (VALUE) &l,
|
|
181
|
+
ca_object_lend_restore, (VALUE) &l);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* Calls recv.mid(*argv), where some of argv are transient wraps of a
|
|
185
|
+
caller's buffer (ca_object_wrap_transient), and takes the buffer back
|
|
186
|
+
from each of them however the call leaves. The caller frees its buffer
|
|
187
|
+
when it returns, and a wrap outlives the call: the collector scans the
|
|
188
|
+
machine stack conservatively and still finds it there, and an object
|
|
189
|
+
wrap is marked cell by cell -- through a buffer that is gone. A wrap
|
|
190
|
+
taken back points at nothing; a hook that kept it holds an empty
|
|
191
|
+
handle, not a stale one. */
|
|
192
|
+
|
|
193
|
+
typedef struct {
|
|
194
|
+
VALUE recv;
|
|
195
|
+
ID mid;
|
|
196
|
+
int argc;
|
|
197
|
+
const VALUE *argv;
|
|
198
|
+
int ntrans;
|
|
199
|
+
const VALUE *trans;
|
|
200
|
+
} ca_object_hook_t;
|
|
201
|
+
|
|
202
|
+
static VALUE
|
|
203
|
+
ca_object_hook_body (VALUE varg)
|
|
204
|
+
{
|
|
205
|
+
ca_object_hook_t *h = (ca_object_hook_t *) varg;
|
|
206
|
+
return rb_funcallv(h->recv, h->mid, h->argc, h->argv);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
static VALUE
|
|
210
|
+
ca_object_hook_release (VALUE varg)
|
|
211
|
+
{
|
|
212
|
+
ca_object_hook_t *h = (ca_object_hook_t *) varg;
|
|
213
|
+
int i;
|
|
214
|
+
for ( i = 0; i < h->ntrans; i++ ) {
|
|
215
|
+
((CArray *) DATA_PTR(h->trans[i]))->ptr = NULL;
|
|
216
|
+
}
|
|
217
|
+
return Qnil;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static void
|
|
221
|
+
ca_object_call_transient (VALUE recv, const char *mid,
|
|
222
|
+
int argc, const VALUE *argv,
|
|
223
|
+
int ntrans, const VALUE *trans)
|
|
224
|
+
{
|
|
225
|
+
ca_object_hook_t h;
|
|
226
|
+
h.recv = recv;
|
|
227
|
+
h.mid = rb_intern(mid);
|
|
228
|
+
h.argc = argc;
|
|
229
|
+
h.argv = argv;
|
|
230
|
+
h.ntrans = ntrans;
|
|
231
|
+
h.trans = trans;
|
|
232
|
+
rb_ensure(ca_object_hook_body, (VALUE) &h,
|
|
233
|
+
ca_object_hook_release, (VALUE) &h);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
static VALUE
|
|
237
|
+
ca_object_data_of (void *ap)
|
|
238
|
+
{
|
|
239
|
+
return rb_ivar_get(((CAObject *) ap)->self, rb_intern("__data__"));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
/* Forward declaration: ca_object_wrap_transient (defined further down,
|
|
244
|
+
near the data-side xfer functions). */
|
|
245
|
+
static VALUE
|
|
246
|
+
ca_object_wrap_transient (int8_t data_type, ca_size_t bytes,
|
|
247
|
+
int8_t ndim, ca_size_t *dim, void *data, int dir);
|
|
248
|
+
|
|
125
249
|
static void *
|
|
126
250
|
ca_objmask_func_clone (void *ap)
|
|
127
251
|
{
|
|
128
252
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
129
|
-
|
|
253
|
+
CAObjectMask *co = ca_objmask_new(ca->array, ca->ndim, ca->dim);
|
|
254
|
+
co->cache = ca->cache;
|
|
255
|
+
return co;
|
|
130
256
|
}
|
|
131
257
|
|
|
132
|
-
/*
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
direction-unified; the slots below forward. */
|
|
137
|
-
static void
|
|
138
|
-
ca_objmask_xfer_addr_one (CAObjectMask *ca, ca_size_t addr, void *ptr, int dir)
|
|
258
|
+
/* Whether the CAObject answers one of the mask hooks. A copy made by dup
|
|
259
|
+
holds its own bits and answers none (array is nil). */
|
|
260
|
+
static int
|
|
261
|
+
ca_objmask_answers (CAObjectMask *ca, const char *mid)
|
|
139
262
|
{
|
|
140
|
-
|
|
263
|
+
return ! NIL_P(ca->array) && rb_obj_respond_to(ca->array, rb_intern(mid), Qtrue);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
static VALUE
|
|
267
|
+
ca_objmask_index_of (CAObjectMask *ca, ca_size_t addr)
|
|
268
|
+
{
|
|
269
|
+
ca_size_t idx[CA_RANK_MAX];
|
|
270
|
+
VALUE ridx;
|
|
141
271
|
int i;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
272
|
+
ca_addr2index((CArray *) ca, addr, idx);
|
|
273
|
+
ridx = rb_ary_new2(ca->ndim);
|
|
274
|
+
for (i=0; i<ca->ndim; i++) {
|
|
275
|
+
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
276
|
+
}
|
|
277
|
+
return ridx;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* The bit the per-cell hooks give for addr (1 / 0 / true / false), or -1
|
|
281
|
+
when the object has neither mask_fetch_addr nor mask_fetch_index. */
|
|
282
|
+
static int
|
|
283
|
+
ca_objmask_fetch_one (CAObjectMask *ca, ca_size_t addr)
|
|
284
|
+
{
|
|
285
|
+
volatile VALUE rval;
|
|
286
|
+
if ( ca_objmask_answers(ca, "mask_fetch_addr") ) {
|
|
287
|
+
rval = rb_funcall(ca->array, rb_intern("mask_fetch_addr"), 1, SIZE2NUM(addr));
|
|
288
|
+
}
|
|
289
|
+
else if ( ca_objmask_answers(ca, "mask_fetch_index") ) {
|
|
290
|
+
rval = rb_funcall(ca->array, rb_intern("mask_fetch_index"), 1,
|
|
291
|
+
ca_objmask_index_of(ca, addr));
|
|
163
292
|
}
|
|
164
293
|
else {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
294
|
+
return -1;
|
|
295
|
+
}
|
|
296
|
+
if ( rval == Qtrue || rval == Qfalse ) {
|
|
297
|
+
return RTEST(rval);
|
|
298
|
+
}
|
|
299
|
+
return NUM2INT(rval) != 0;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* Hands one bit to the per-cell hooks; 0 when the object has neither
|
|
303
|
+
mask_store_addr nor mask_store_index. */
|
|
304
|
+
static int
|
|
305
|
+
ca_objmask_store_one (CAObjectMask *ca, ca_size_t addr, boolean8_t bit)
|
|
306
|
+
{
|
|
307
|
+
if ( ca_objmask_answers(ca, "mask_store_addr") ) {
|
|
308
|
+
rb_funcall(ca->array, rb_intern("mask_store_addr"), 2,
|
|
309
|
+
SIZE2NUM(addr), INT2NUM(bit ? 1 : 0));
|
|
310
|
+
return 1;
|
|
311
|
+
}
|
|
312
|
+
if ( ca_objmask_answers(ca, "mask_store_index") ) {
|
|
313
|
+
rb_funcall(ca->array, rb_intern("mask_store_index"), 2,
|
|
314
|
+
ca_objmask_index_of(ca, addr), INT2NUM(bit ? 1 : 0));
|
|
315
|
+
return 1;
|
|
316
|
+
}
|
|
317
|
+
return 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
static int
|
|
321
|
+
ca_objmask_stores_cells (CAObjectMask *ca)
|
|
322
|
+
{
|
|
323
|
+
return ca_objmask_answers(ca, "mask_store_addr") ||
|
|
324
|
+
ca_objmask_answers(ca, "mask_store_index");
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/* Brings the cache up to date from the hooks that give the mask: the bulk
|
|
328
|
+
one, else the per-cell one. With neither, the cache is the mask. */
|
|
329
|
+
static void
|
|
330
|
+
ca_objmask_refresh (CAObjectMask *ca)
|
|
331
|
+
{
|
|
332
|
+
boolean8_t *c = (boolean8_t *) ca->cache;
|
|
333
|
+
ca_size_t addr;
|
|
334
|
+
int bit;
|
|
335
|
+
if ( ca_objmask_answers(ca, "mask_copy_data") ) {
|
|
336
|
+
rb_funcall(ca->array, rb_intern("mask_copy_data"), 1,
|
|
337
|
+
ca_objmask_mask_data(ca));
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
for ( addr = 0; addr < ca->elements; addr++ ) {
|
|
341
|
+
if ( ( bit = ca_objmask_fetch_one(ca, addr) ) < 0 ) {
|
|
342
|
+
return;
|
|
170
343
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
344
|
+
c[addr] = (boolean8_t) bit;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* Hands the whole cache to the hooks that take the mask: the bulk one,
|
|
349
|
+
else the per-cell one. */
|
|
350
|
+
static void
|
|
351
|
+
ca_objmask_push (CAObjectMask *ca)
|
|
352
|
+
{
|
|
353
|
+
const boolean8_t *c = (const boolean8_t *) ca->cache;
|
|
354
|
+
ca_size_t addr;
|
|
355
|
+
if ( ca_objmask_answers(ca, "mask_sync_data") ) {
|
|
356
|
+
rb_funcall(ca->array, rb_intern("mask_sync_data"), 1,
|
|
357
|
+
ca_objmask_mask_data(ca));
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
for ( addr = 0; addr < ca->elements; addr++ ) {
|
|
361
|
+
if ( ! ca_objmask_store_one(ca, addr, c[addr]) ) {
|
|
362
|
+
return;
|
|
179
363
|
}
|
|
180
364
|
}
|
|
181
365
|
}
|
|
182
366
|
|
|
367
|
+
/* Reads n bits at addrs while the mask is closed: mask_copy_addrs, else
|
|
368
|
+
the per-cell hooks, else the whole mask brought up to date. */
|
|
183
369
|
static void
|
|
184
|
-
|
|
370
|
+
ca_objmask_get_cells (CAObjectMask *ca, ca_size_t n, ca_size_t *addrs,
|
|
371
|
+
boolean8_t *bits)
|
|
185
372
|
{
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
373
|
+
boolean8_t *c = (boolean8_t *) ca->cache;
|
|
374
|
+
ca_size_t i;
|
|
375
|
+
int bit;
|
|
376
|
+
if ( n > 0 && ca_objmask_answers(ca, "mask_copy_addrs") ) {
|
|
377
|
+
volatile VALUE raddrs, rdata;
|
|
378
|
+
ca_size_t dim1[1] = { n };
|
|
379
|
+
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
380
|
+
1, dim1, addrs, CA_XFER_PUT);
|
|
381
|
+
rdata = ca_object_wrap_transient(CA_BOOLEAN, 1, 1, dim1, bits,
|
|
382
|
+
CA_XFER_GET);
|
|
383
|
+
{
|
|
384
|
+
VALUE args[2];
|
|
385
|
+
args[0] = raddrs;
|
|
386
|
+
args[1] = rdata;
|
|
387
|
+
ca_object_call_transient(ca->array, "mask_copy_addrs", 2, args, 2, args);
|
|
197
388
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if ( n > 0 && ( bit = ca_objmask_fetch_one(ca, addrs[0]) ) >= 0 ) {
|
|
392
|
+
c[addrs[0]] = bits[0] = (boolean8_t) bit;
|
|
393
|
+
for ( i = 1; i < n; i++ ) {
|
|
394
|
+
c[addrs[i]] = bits[i] = (boolean8_t) ca_objmask_fetch_one(ca, addrs[i]);
|
|
204
395
|
}
|
|
205
|
-
|
|
206
|
-
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
ca_objmask_refresh(ca);
|
|
399
|
+
for ( i = 0; i < n; i++ ) {
|
|
400
|
+
bits[i] = c[addrs[i]];
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* Writes n bits at addrs while the mask is closed, and hands them over:
|
|
405
|
+
one by one to the per-cell hooks, as a list to mask_sync_addrs, or else
|
|
406
|
+
the whole mask to mask_sync_data -- brought up to date first, so that
|
|
407
|
+
the cells not written go back as they were. */
|
|
408
|
+
static void
|
|
409
|
+
ca_objmask_put_cells (CAObjectMask *ca, ca_size_t n, ca_size_t *addrs,
|
|
410
|
+
const boolean8_t *bits)
|
|
411
|
+
{
|
|
412
|
+
boolean8_t *c = (boolean8_t *) ca->cache;
|
|
413
|
+
ca_size_t i;
|
|
414
|
+
if ( ca_objmask_stores_cells(ca) ) {
|
|
415
|
+
for ( i = 0; i < n; i++ ) {
|
|
416
|
+
c[addrs[i]] = bits[i] ? 1 : 0;
|
|
417
|
+
ca_objmask_store_one(ca, addrs[i], c[addrs[i]]);
|
|
207
418
|
}
|
|
419
|
+
return;
|
|
208
420
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
for (i=0; i<ca->ndim; i++) {
|
|
215
|
-
rb_ary_store(ridx, i, SIZE2NUM(idx[i]));
|
|
216
|
-
}
|
|
217
|
-
rb_funcall(ca->array, rb_intern("mask_store_index"), 2, ridx, rval);
|
|
421
|
+
if ( n > 0 && ca_objmask_answers(ca, "mask_sync_addrs") ) {
|
|
422
|
+
volatile VALUE raddrs, rdata;
|
|
423
|
+
ca_size_t dim1[1] = { n };
|
|
424
|
+
for ( i = 0; i < n; i++ ) {
|
|
425
|
+
c[addrs[i]] = bits[i] ? 1 : 0;
|
|
218
426
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
427
|
+
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
428
|
+
1, dim1, addrs, CA_XFER_PUT);
|
|
429
|
+
rdata = ca_object_wrap_transient(CA_BOOLEAN, 1, 1, dim1, (void *) bits,
|
|
430
|
+
CA_XFER_PUT);
|
|
431
|
+
{
|
|
432
|
+
VALUE args[2];
|
|
433
|
+
args[0] = raddrs;
|
|
434
|
+
args[1] = rdata;
|
|
435
|
+
ca_object_call_transient(ca->array, "mask_sync_addrs", 2, args, 2, args);
|
|
223
436
|
}
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if ( ca_objmask_answers(ca, "mask_sync_data") ) {
|
|
440
|
+
ca_objmask_refresh(ca);
|
|
224
441
|
}
|
|
442
|
+
for ( i = 0; i < n; i++ ) {
|
|
443
|
+
c[addrs[i]] = bits[i] ? 1 : 0;
|
|
444
|
+
}
|
|
445
|
+
ca_objmask_push(ca);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/* Open: the cache is published in ptr, and it is the mask until the sync
|
|
449
|
+
hands it over. The first attach reads the mask in; an allocate does
|
|
450
|
+
not, since whoever allocates writes every cell. */
|
|
451
|
+
static void
|
|
452
|
+
ca_objmask_open (CAObjectMask *ca, int refresh)
|
|
453
|
+
{
|
|
454
|
+
if ( ca->holds == 0 ) {
|
|
455
|
+
if ( refresh ) {
|
|
456
|
+
ca_objmask_refresh(ca);
|
|
457
|
+
}
|
|
458
|
+
ca->ptr = ca->cache;
|
|
459
|
+
}
|
|
460
|
+
ca->holds++;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
static void
|
|
464
|
+
ca_objmask_func_allocate (void *ap)
|
|
465
|
+
{
|
|
466
|
+
ca_objmask_open((CAObjectMask *) ap, 0);
|
|
225
467
|
}
|
|
226
468
|
|
|
227
469
|
static void
|
|
228
470
|
ca_objmask_func_attach (void *ap)
|
|
471
|
+
{
|
|
472
|
+
ca_objmask_open((CAObjectMask *) ap, 1);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
static void
|
|
476
|
+
ca_objmask_func_sync (void *ap)
|
|
229
477
|
{
|
|
230
478
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
1, ca_objmask_mask_data(ca));
|
|
479
|
+
if ( ca->ptr ) {
|
|
480
|
+
ca_objmask_push(ca);
|
|
234
481
|
}
|
|
235
482
|
}
|
|
236
483
|
|
|
237
|
-
void
|
|
238
|
-
|
|
484
|
+
static void
|
|
485
|
+
ca_objmask_func_detach (void *ap)
|
|
239
486
|
{
|
|
240
487
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
241
|
-
if (
|
|
242
|
-
|
|
243
|
-
1, ca_objmask_mask_data(ca));
|
|
488
|
+
if ( ca->holds > 0 && --ca->holds == 0 ) {
|
|
489
|
+
ca->ptr = NULL;
|
|
244
490
|
}
|
|
245
491
|
}
|
|
246
492
|
|
|
@@ -248,83 +494,76 @@ static void
|
|
|
248
494
|
ca_objmask_func_xfer_all (void *ap, void *data, int dir)
|
|
249
495
|
{
|
|
250
496
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
497
|
+
size_t len = (size_t) ca->elements * (size_t) ca->bytes;
|
|
251
498
|
if ( dir == CA_XFER_GET ) {
|
|
252
|
-
if (
|
|
253
|
-
|
|
254
|
-
ca->ptr = (char *) data;
|
|
255
|
-
rb_funcall(ca->array, rb_intern("mask_copy_data"),
|
|
256
|
-
1, ca_objmask_mask_data(ca));
|
|
257
|
-
ca->ptr = ptr0;
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
ca_array_func_xfer_all(ca, data, CA_XFER_GET);
|
|
499
|
+
if ( ! ca->ptr ) {
|
|
500
|
+
ca_objmask_refresh(ca);
|
|
261
501
|
}
|
|
502
|
+
memcpy(data, ca->cache, len);
|
|
262
503
|
}
|
|
263
504
|
else {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
ca
|
|
267
|
-
rb_funcall(ca->array, rb_intern("mask_sync_data"),
|
|
268
|
-
1, ca_objmask_mask_data(ca));
|
|
269
|
-
ca->ptr = ptr0;
|
|
270
|
-
}
|
|
271
|
-
else {
|
|
272
|
-
ca_array_func_xfer_all(ca, data, CA_XFER_PUT);
|
|
505
|
+
memcpy(ca->cache, data, len);
|
|
506
|
+
if ( ! ca->ptr ) {
|
|
507
|
+
ca_objmask_push(ca);
|
|
273
508
|
}
|
|
274
509
|
}
|
|
275
510
|
}
|
|
276
511
|
|
|
277
|
-
void
|
|
278
|
-
|
|
512
|
+
static void
|
|
513
|
+
ca_objmask_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
514
|
+
void *data, int dir)
|
|
279
515
|
{
|
|
280
516
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
517
|
+
boolean8_t *c = (boolean8_t *) ca->cache;
|
|
518
|
+
boolean8_t *d = (boolean8_t *) data;
|
|
519
|
+
ca_size_t i;
|
|
520
|
+
if ( ca->ptr ) {
|
|
521
|
+
for ( i = 0; i < n; i++ ) {
|
|
522
|
+
if ( dir == CA_XFER_GET ) { d[i] = c[addrs[i]]; }
|
|
523
|
+
else { c[addrs[i]] = d[i] ? 1 : 0; }
|
|
524
|
+
}
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
if ( dir == CA_XFER_GET ) {
|
|
528
|
+
ca_objmask_get_cells(ca, n, addrs, d);
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
ca_objmask_put_cells(ca, n, addrs, d);
|
|
285
532
|
}
|
|
286
533
|
}
|
|
287
534
|
|
|
288
535
|
static void
|
|
289
536
|
ca_objmask_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
290
537
|
{
|
|
291
|
-
|
|
538
|
+
ca_size_t addr = ca_index2addr((CArray *) ap, idx);
|
|
539
|
+
ca_objmask_func_xfer_addrs(ap, 1, &addr, data, dir);
|
|
292
540
|
}
|
|
293
541
|
|
|
294
|
-
/* Forward declaration: ca_object_wrap_transient (defined further down,
|
|
295
|
-
near the data-side xfer functions). */
|
|
296
|
-
static VALUE
|
|
297
|
-
ca_object_wrap_transient (int8_t data_type, ca_size_t bytes,
|
|
298
|
-
int8_t ndim, ca_size_t *dim, void *data, int dir);
|
|
299
|
-
|
|
300
|
-
/* Mask parallel of the bulk-addrs path. When `mask_copy_addrs` /
|
|
301
|
-
`mask_sync_addrs` is defined, 1-call bulk dispatch; else per-cell loop. */
|
|
302
542
|
static void
|
|
303
|
-
|
|
304
|
-
void *data, int dir)
|
|
543
|
+
ca_objmask_func_fill_data (void *ap, void *val)
|
|
305
544
|
{
|
|
306
545
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if ( n > 0 && rb_obj_respond_to(ca->array, mid, Qtrue) ) {
|
|
311
|
-
volatile VALUE raddrs, rdata;
|
|
312
|
-
ca_size_t dim1[1] = { n };
|
|
313
|
-
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
314
|
-
1, dim1, addrs, CA_XFER_PUT);
|
|
315
|
-
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
316
|
-
1, dim1, data, dir);
|
|
317
|
-
rb_funcall(ca->array, mid, 2, raddrs, rdata);
|
|
546
|
+
boolean8_t bit = *(boolean8_t *) val ? 1 : 0;
|
|
547
|
+
memset(ca->cache, bit, (size_t) ca->elements);
|
|
548
|
+
if ( ca->ptr ) {
|
|
318
549
|
return;
|
|
319
550
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
ca_size_t i;
|
|
324
|
-
for ( i = 0; i < n; i++ ) {
|
|
325
|
-
ca_objmask_xfer_addr_one(ca, addrs[i], d + i * ca->bytes, dir);
|
|
326
|
-
}
|
|
551
|
+
if ( ca_objmask_answers(ca, "mask_fill_data") ) {
|
|
552
|
+
rb_funcall(ca->array, rb_intern("mask_fill_data"), 1, INT2NUM(bit));
|
|
553
|
+
return;
|
|
327
554
|
}
|
|
555
|
+
ca_objmask_push(ca);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
static void
|
|
559
|
+
ca_objmask_func_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *val)
|
|
560
|
+
{
|
|
561
|
+
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
562
|
+
volatile VALUE hold = 0;
|
|
563
|
+
boolean8_t *bits = ALLOCV_N(boolean8_t, hold, n > 0 ? n : 1);
|
|
564
|
+
memset(bits, *(boolean8_t *) val ? 1 : 0, (size_t) n);
|
|
565
|
+
ca_objmask_func_xfer_addrs(ca, n, addrs, bits, CA_XFER_PUT);
|
|
566
|
+
ALLOCV_END(hold);
|
|
328
567
|
}
|
|
329
568
|
|
|
330
569
|
/* Mask parallel of the partial-region path. Same per-axis index-step
|
|
@@ -335,6 +574,7 @@ static void
|
|
|
335
574
|
ca_objmask_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
336
575
|
ca_size_t *strides, void *data, int dir)
|
|
337
576
|
{
|
|
577
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
338
578
|
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
339
579
|
int8_t ndim = ca->ndim;
|
|
340
580
|
ca_size_t native[CA_RANK_MAX], steps[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
@@ -351,7 +591,8 @@ ca_objmask_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
351
591
|
|
|
352
592
|
if ( n == 0 ) return;
|
|
353
593
|
|
|
354
|
-
if (
|
|
594
|
+
if ( ! ca->ptr && ca_objmask_answers(ca, dir == CA_XFER_GET ? "mask_copy_block"
|
|
595
|
+
: "mask_sync_block") ) {
|
|
355
596
|
/* The request is over the view's addresses, so a transposed / flat
|
|
356
597
|
request is legal; the per-axis copy_block dispatch below would
|
|
357
598
|
misread it. See ca_xfer_stride_request_is_axis_box (carray.h). */
|
|
@@ -372,7 +613,15 @@ ca_objmask_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
372
613
|
}
|
|
373
614
|
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
374
615
|
ndim, counts, data, dir);
|
|
375
|
-
|
|
616
|
+
{
|
|
617
|
+
VALUE args[4];
|
|
618
|
+
args[0] = rstarts;
|
|
619
|
+
args[1] = rcounts;
|
|
620
|
+
args[2] = rsteps;
|
|
621
|
+
args[3] = rdata;
|
|
622
|
+
ca_object_call_transient(ca->array, rb_id2name(mid_block),
|
|
623
|
+
4, args, 1, args + 3);
|
|
624
|
+
}
|
|
376
625
|
return;
|
|
377
626
|
}
|
|
378
627
|
}
|
|
@@ -390,15 +639,27 @@ ca_objmask_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
390
639
|
ALLOCV_END(holder);
|
|
391
640
|
}
|
|
392
641
|
|
|
642
|
+
/* A mask copied by dup holds its own bits, and frees them. */
|
|
643
|
+
static void
|
|
644
|
+
ca_objmask_free (void *ap)
|
|
645
|
+
{
|
|
646
|
+
CAObjectMask *ca = (CAObjectMask *) ap;
|
|
647
|
+
if ( ca != NULL && NIL_P(ca->array) && ca->cache ) {
|
|
648
|
+
xfree(ca->cache);
|
|
649
|
+
ca->cache = NULL;
|
|
650
|
+
}
|
|
651
|
+
free_ca_wrap(ap);
|
|
652
|
+
}
|
|
653
|
+
|
|
393
654
|
static ca_operation_function_t ca_objmask_func = {
|
|
394
655
|
-1, /* CA_OBJ_OBJECT_MASK */
|
|
395
656
|
CA_REAL_ARRAY,
|
|
396
|
-
|
|
657
|
+
ca_objmask_free,
|
|
397
658
|
ca_objmask_func_clone,
|
|
398
|
-
|
|
659
|
+
ca_objmask_func_allocate,
|
|
399
660
|
ca_objmask_func_attach,
|
|
400
661
|
ca_objmask_func_sync,
|
|
401
|
-
|
|
662
|
+
ca_objmask_func_detach,
|
|
402
663
|
ca_objmask_func_fill_data,
|
|
403
664
|
ca_array_func_create_mask,
|
|
404
665
|
ca_objmask_func_xfer_index,
|
|
@@ -406,6 +667,7 @@ static ca_operation_function_t ca_objmask_func = {
|
|
|
406
667
|
NULL, /* fold_stride: never-fold (callback boundary) */
|
|
407
668
|
ca_objmask_func_xfer_stride,
|
|
408
669
|
ca_objmask_func_xfer_all,
|
|
670
|
+
.fill_addrs = ca_objmask_func_fill_addrs,
|
|
409
671
|
};
|
|
410
672
|
|
|
411
673
|
static VALUE
|
|
@@ -421,11 +683,18 @@ rb_ca_objmask_initialize_copy (VALUE self, VALUE other)
|
|
|
421
683
|
CAObjectMask *ca, *cs;
|
|
422
684
|
|
|
423
685
|
TypedData_Get_Struct(self, CAObjectMask, &caobjectmask_data_type, ca);
|
|
686
|
+
ca_check_uninitialized(ca);
|
|
424
687
|
TypedData_Get_Struct(other, CAObjectMask, &caobjectmask_data_type, cs);
|
|
425
688
|
|
|
689
|
+
/* A copy of the mask as it reads now, with bits of its own: writing to
|
|
690
|
+
it does not reach the CAObject's hooks. */
|
|
426
691
|
carray_setup((CArray *)ca, CA_BOOLEAN, cs->ndim, cs->dim, 0, NULL);
|
|
427
692
|
ca->obj_type = CA_OBJ_OBJECT_MASK;
|
|
428
|
-
ca->array =
|
|
693
|
+
ca->array = Qnil;
|
|
694
|
+
ca->cache = ca->ptr;
|
|
695
|
+
ca->holds = 0;
|
|
696
|
+
ca_copy_data((CArray *) cs, ca->cache);
|
|
697
|
+
ca->ptr = NULL;
|
|
429
698
|
|
|
430
699
|
return self;
|
|
431
700
|
}
|
|
@@ -437,7 +706,6 @@ ca_object_setup (CAObject *ca,
|
|
|
437
706
|
int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes)
|
|
438
707
|
{
|
|
439
708
|
ca_size_t elements;
|
|
440
|
-
double length;
|
|
441
709
|
int8_t i;
|
|
442
710
|
|
|
443
711
|
/* check arguments */
|
|
@@ -449,16 +717,7 @@ ca_object_setup (CAObject *ca,
|
|
|
449
717
|
|
|
450
718
|
/* calculate total number of elements */
|
|
451
719
|
|
|
452
|
-
elements =
|
|
453
|
-
length = bytes;
|
|
454
|
-
for (i=0; i<ndim; i++) {
|
|
455
|
-
elements *= dim[i];
|
|
456
|
-
length *= dim[i];
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
if ( length > CA_LENGTH_MAX ) {
|
|
460
|
-
rb_raise(rb_eRuntimeError, "too large byte length");
|
|
461
|
-
}
|
|
720
|
+
elements = ca_shape_elements(ndim, dim, bytes);
|
|
462
721
|
|
|
463
722
|
ca->obj_type = CA_OBJ_OBJECT;
|
|
464
723
|
ca->data_type = data_type;
|
|
@@ -519,6 +778,17 @@ ca_object_func_clone (void *ap)
|
|
|
519
778
|
#define ca_object_func_ptr_at_addr ca_array_func_ptr_at_addr
|
|
520
779
|
#define ca_object_func_ptr_at_index ca_array_func_ptr_at_index
|
|
521
780
|
|
|
781
|
+
/* The bytes of this array's mask. A fetcher that answers UNDEF marks the
|
|
782
|
+
cell there, whether or not the mask is open. */
|
|
783
|
+
static boolean8_t *
|
|
784
|
+
ca_object_mask_bytes (CAObject *ca)
|
|
785
|
+
{
|
|
786
|
+
if ( ca->mask->obj_type == CA_OBJ_OBJECT_MASK ) {
|
|
787
|
+
return (boolean8_t *) ((CAObjectMask *) ca->mask)->cache;
|
|
788
|
+
}
|
|
789
|
+
return (boolean8_t *) ca->mask->ptr;
|
|
790
|
+
}
|
|
791
|
+
|
|
522
792
|
/* per-cell cores: the addr- and index-primary Ruby-callback bridge logic,
|
|
523
793
|
direction-unified. The fetch_* / store_* slots below are thin
|
|
524
794
|
forwarders onto these. */
|
|
@@ -532,18 +802,15 @@ ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
|
532
802
|
raddr = SIZE2NUM(addr);
|
|
533
803
|
rval = rb_funcall(ca->self, rb_intern("fetch_addr"), 1, raddr);
|
|
534
804
|
if ( rval == CA_UNDEF ) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
ca_create_mask(ca);
|
|
538
|
-
}
|
|
539
|
-
*((boolean8_t*)ca->mask->ptr + addr) = 1;
|
|
805
|
+
ca_create_mask(ca);
|
|
806
|
+
ca_object_mask_bytes(ca)[addr] = 1;
|
|
540
807
|
if ( ca->data_type == CA_OBJECT ) {
|
|
541
808
|
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
542
809
|
}
|
|
543
810
|
}
|
|
544
811
|
else {
|
|
545
812
|
if ( ca_has_mask(ca) ) {
|
|
546
|
-
|
|
813
|
+
ca_object_mask_bytes(ca)[addr] = 0;
|
|
547
814
|
}
|
|
548
815
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
549
816
|
}
|
|
@@ -557,18 +824,15 @@ ca_object_xfer_addr_one (CAObject *ca, ca_size_t addr, void *ptr, int dir)
|
|
|
557
824
|
}
|
|
558
825
|
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
559
826
|
if ( rval == CA_UNDEF ) {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
ca_create_mask(ca);
|
|
563
|
-
}
|
|
564
|
-
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 1;
|
|
827
|
+
ca_create_mask(ca);
|
|
828
|
+
ca_object_mask_bytes(ca)[ca_index2addr(ca->mask, idx)] = 1;
|
|
565
829
|
if ( ca->data_type == CA_OBJECT ) {
|
|
566
830
|
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
567
831
|
}
|
|
568
832
|
}
|
|
569
833
|
else {
|
|
570
834
|
if ( ca_has_mask(ca) ) {
|
|
571
|
-
|
|
835
|
+
ca_object_mask_bytes(ca)[ca_index2addr(ca->mask, idx)] = 0;
|
|
572
836
|
}
|
|
573
837
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
574
838
|
}
|
|
@@ -606,18 +870,15 @@ ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
|
606
870
|
}
|
|
607
871
|
rval = rb_funcall(ca->self, rb_intern("fetch_index"), 1, ridx);
|
|
608
872
|
if ( rval == CA_UNDEF ) {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
ca_create_mask(ca);
|
|
612
|
-
}
|
|
613
|
-
*((boolean8_t*)ca->mask->ptr + ca_index2addr(ca->mask, idx)) = 1;
|
|
873
|
+
ca_create_mask(ca);
|
|
874
|
+
ca_object_mask_bytes(ca)[ca_index2addr(ca->mask, idx)] = 1;
|
|
614
875
|
if ( ca->data_type == CA_OBJECT ) {
|
|
615
876
|
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
616
877
|
}
|
|
617
878
|
}
|
|
618
879
|
else {
|
|
619
880
|
if ( ca_has_mask(ca) ) {
|
|
620
|
-
|
|
881
|
+
ca_object_mask_bytes(ca)[ca_index2addr(ca->mask, idx)] = 0;
|
|
621
882
|
}
|
|
622
883
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
623
884
|
}
|
|
@@ -627,18 +888,15 @@ ca_object_xfer_index_one (CAObject *ca, ca_size_t *idx, void *ptr, int dir)
|
|
|
627
888
|
raddr = SIZE2NUM(addr);
|
|
628
889
|
rval = rb_funcall(ca->self, rb_intern("fetch_addr"), 1, raddr);
|
|
629
890
|
if ( rval == CA_UNDEF ) {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
ca_create_mask(ca);
|
|
633
|
-
}
|
|
634
|
-
*((boolean8_t*)ca->mask->ptr + addr) = 1;
|
|
891
|
+
ca_create_mask(ca);
|
|
892
|
+
ca_object_mask_bytes(ca)[addr] = 1;
|
|
635
893
|
if ( ca->data_type == CA_OBJECT ) {
|
|
636
894
|
rb_ca_obj2ptr(ca->self, INT2NUM(0), ptr);
|
|
637
895
|
}
|
|
638
896
|
}
|
|
639
897
|
else {
|
|
640
898
|
if ( ca_has_mask(ca) ) {
|
|
641
|
-
|
|
899
|
+
ca_object_mask_bytes(ca)[addr] = 0;
|
|
642
900
|
}
|
|
643
901
|
rb_ca_obj2ptr(ca->self, rval, ptr);
|
|
644
902
|
}
|
|
@@ -697,11 +955,8 @@ static void
|
|
|
697
955
|
ca_object_dispatch_copy (CAObject *ca, void *ptr)
|
|
698
956
|
{
|
|
699
957
|
if ( rb_obj_respond_to(ca->self, rb_intern("copy_data"), Qtrue) ) {
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
rb_funcall(ca->self, rb_intern("copy_data"),
|
|
703
|
-
1, rb_ivar_get(ca->self, rb_intern("__data__")));
|
|
704
|
-
ca->data->ptr = ptr0;
|
|
958
|
+
ca_object_call_lending(&ca->data->ptr, ptr, ca->self, "copy_data",
|
|
959
|
+
ca_object_data_of, ca);
|
|
705
960
|
}
|
|
706
961
|
else {
|
|
707
962
|
ca_size_t addr;
|
|
@@ -716,11 +971,8 @@ static void
|
|
|
716
971
|
ca_object_dispatch_sync (CAObject *ca, void *ptr)
|
|
717
972
|
{
|
|
718
973
|
if ( rb_obj_respond_to(ca->self, rb_intern("sync_data"), Qtrue) ) {
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
rb_funcall(ca->self, rb_intern("sync_data"),
|
|
722
|
-
1, rb_ivar_get(ca->self, rb_intern("__data__")));
|
|
723
|
-
ca->data->ptr = ptr0;
|
|
974
|
+
ca_object_call_lending(&ca->data->ptr, ptr, ca->self, "sync_data",
|
|
975
|
+
ca_object_data_of, ca);
|
|
724
976
|
}
|
|
725
977
|
else {
|
|
726
978
|
ca_size_t addr;
|
|
@@ -778,10 +1030,7 @@ ca_object_func_attach (void *ap)
|
|
|
778
1030
|
ca->ptr = ca->data->ptr;
|
|
779
1031
|
ca_object_dispatch_copy(ca, ca->ptr);
|
|
780
1032
|
if ( ca_has_mask(ca->data) ) {
|
|
781
|
-
|
|
782
|
-
if ( ! ca->mask ) {
|
|
783
|
-
ca_create_mask(ca);
|
|
784
|
-
}
|
|
1033
|
+
ca_create_mask(ca);
|
|
785
1034
|
}
|
|
786
1035
|
}
|
|
787
1036
|
|
|
@@ -822,7 +1071,8 @@ ca_object_func_detach (void *ap)
|
|
|
822
1071
|
[n] for addrs) before invoking copy_block / sync_block / copy_addrs /
|
|
823
1072
|
sync_addrs. Lifecycle: buffer is owned by the slot caller; the wrapper
|
|
824
1073
|
installs free_ca_wrap as dfree, so the underlying ptr is NOT freed when
|
|
825
|
-
the wrapper is GC'd.
|
|
1074
|
+
the wrapper is GC'd. Call the hook through ca_object_call_transient,
|
|
1075
|
+
which takes the buffer back from the wrapper when the hook returns.
|
|
826
1076
|
|
|
827
1077
|
Object data_type GC safety: for GET (dir == CA_XFER_GET) the buffer may be
|
|
828
1078
|
uninitialized garbage on entry, so we INT2NUM(0) zero-fill before
|
|
@@ -880,7 +1130,12 @@ ca_object_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
880
1130
|
1, dim1, addrs, CA_XFER_PUT);
|
|
881
1131
|
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
882
1132
|
1, dim1, data, dir);
|
|
883
|
-
|
|
1133
|
+
{
|
|
1134
|
+
VALUE args[2];
|
|
1135
|
+
args[0] = raddrs;
|
|
1136
|
+
args[1] = rdata;
|
|
1137
|
+
ca_object_call_transient(ca->self, rb_id2name(mid), 2, args, 2, args);
|
|
1138
|
+
}
|
|
884
1139
|
return;
|
|
885
1140
|
}
|
|
886
1141
|
|
|
@@ -917,6 +1172,7 @@ static void
|
|
|
917
1172
|
ca_object_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
918
1173
|
ca_size_t *strides, void *data, int dir)
|
|
919
1174
|
{
|
|
1175
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
920
1176
|
CAObject *ca = (CAObject *) ap;
|
|
921
1177
|
int8_t ndim;
|
|
922
1178
|
ca_size_t native[CA_RANK_MAX], steps[CA_RANK_MAX], idx[CA_RANK_MAX];
|
|
@@ -969,7 +1225,15 @@ ca_object_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
969
1225
|
}
|
|
970
1226
|
rdata = ca_object_wrap_transient(ca->data_type, ca->bytes,
|
|
971
1227
|
ndim, counts, data, dir);
|
|
972
|
-
|
|
1228
|
+
{
|
|
1229
|
+
VALUE args[4];
|
|
1230
|
+
args[0] = rstarts;
|
|
1231
|
+
args[1] = rcounts;
|
|
1232
|
+
args[2] = rsteps;
|
|
1233
|
+
args[3] = rdata;
|
|
1234
|
+
ca_object_call_transient(ca->self, rb_id2name(mid_block),
|
|
1235
|
+
4, args, 1, args + 3);
|
|
1236
|
+
}
|
|
973
1237
|
return;
|
|
974
1238
|
}
|
|
975
1239
|
}
|
|
@@ -1040,7 +1304,12 @@ ca_object_func_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *ptr)
|
|
|
1040
1304
|
raddrs = ca_object_wrap_transient(CA_SIZE, sizeof(ca_size_t),
|
|
1041
1305
|
1, dim1, addrs, CA_XFER_PUT);
|
|
1042
1306
|
rval = rb_ca_ptr2obj(ca->self, ptr);
|
|
1043
|
-
|
|
1307
|
+
{
|
|
1308
|
+
VALUE args[2];
|
|
1309
|
+
args[0] = raddrs;
|
|
1310
|
+
args[1] = rval;
|
|
1311
|
+
ca_object_call_transient(ca->self, rb_id2name(mid), 2, args, 1, args);
|
|
1312
|
+
}
|
|
1044
1313
|
return;
|
|
1045
1314
|
}
|
|
1046
1315
|
|
|
@@ -1108,31 +1377,32 @@ ca_object_func_create_mask (void *ap)
|
|
|
1108
1377
|
CAObject *ca = (CAObject *) ap;
|
|
1109
1378
|
volatile VALUE rmask;
|
|
1110
1379
|
if ( ca_is_face(ca) ) {
|
|
1111
|
-
/* Face: the mask
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
ca_update_mask(ca->parent);
|
|
1115
|
-
if ( ! ca->parent->mask ) {
|
|
1116
|
-
ca_create_mask(ca->parent);
|
|
1117
|
-
}
|
|
1118
|
-
ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
|
|
1119
|
-
CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
|
|
1380
|
+
/* Face: storage is the parent, so the mask is the parent's (as for the
|
|
1381
|
+
C-level Faces), not the internal __data__'s. */
|
|
1382
|
+
ca_view_func_create_mask(ca);
|
|
1120
1383
|
return;
|
|
1121
1384
|
}
|
|
1122
1385
|
if ( rb_obj_respond_to(ca->self, rb_intern("create_mask"), Qtrue) ) {
|
|
1123
1386
|
rb_funcall(ca->self, rb_intern("create_mask"), 0);
|
|
1124
1387
|
}
|
|
1125
1388
|
else {
|
|
1126
|
-
rb_raise(
|
|
1389
|
+
rb_raise(rb_eTypeError, "can't create mask for CAObject");
|
|
1127
1390
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1391
|
+
ca_create_mask(ca->data);
|
|
1392
|
+
{
|
|
1393
|
+
CAObjectMask *cm = ca_objmask_new(ca->self, ca->ndim, ca->dim);
|
|
1394
|
+
cm->cache = ca->data->mask->ptr;
|
|
1395
|
+
ca->mask = (CArray *) cm;
|
|
1396
|
+
rmask = ca_wrap_struct(ca->mask);
|
|
1397
|
+
rb_ivar_set(ca->self, rb_intern("mask"), rmask);
|
|
1398
|
+
/* Made while this array is attached, the mask joins it at its level:
|
|
1399
|
+
ca_create_mask attaches it once more when this returns. */
|
|
1400
|
+
if ( ca->attach > 1 ) {
|
|
1401
|
+
ca_objmask_refresh(cm);
|
|
1402
|
+
cm->ptr = cm->cache;
|
|
1403
|
+
cm->holds = ca->attach - 1;
|
|
1404
|
+
}
|
|
1131
1405
|
}
|
|
1132
|
-
ca->mask = (CArray*) ca_objmask_new(ca->self, ca->ndim, ca->dim);
|
|
1133
|
-
ca->mask->ptr = ca->data->mask->ptr;
|
|
1134
|
-
rmask = ca_wrap_struct(ca->mask);
|
|
1135
|
-
rb_ivar_set(ca->self, rb_intern("mask"), rmask);
|
|
1136
1406
|
}
|
|
1137
1407
|
|
|
1138
1408
|
ca_operation_function_t ca_object_func = {
|
|
@@ -1171,6 +1441,7 @@ rb_ca_object_initialize_copy (VALUE self, VALUE other)
|
|
|
1171
1441
|
CAObject *ca, *cs;
|
|
1172
1442
|
|
|
1173
1443
|
TypedData_Get_Struct(self, CAObject, &caobject_data_type, ca);
|
|
1444
|
+
ca_check_uninitialized(ca);
|
|
1174
1445
|
TypedData_Get_Struct(other, CAObject, &caobject_data_type, cs);
|
|
1175
1446
|
|
|
1176
1447
|
if ( ca_func[CA_OBJ_OBJECT].pool_init ) {
|
|
@@ -1212,20 +1483,21 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1212
1483
|
{
|
|
1213
1484
|
volatile VALUE rtype, rdim, ropt, rbytes = Qnil, rrdonly = Qnil,
|
|
1214
1485
|
rparent = Qnil, rface = Qnil, rstorage = Qnil, rdata,
|
|
1215
|
-
rorderable = Qnil, rcomparable = Qnil;
|
|
1486
|
+
rorderable = Qnil, rcomparable = Qnil, rnumeric = Qnil;
|
|
1216
1487
|
CAObject *ca;
|
|
1217
1488
|
int8_t data_type, ndim;
|
|
1218
1489
|
ca_size_t dim[CA_RANK_MAX];
|
|
1219
1490
|
ca_size_t bytes;
|
|
1220
1491
|
int i;
|
|
1492
|
+
int storage_named = 0; /* :storage given by the caller */
|
|
1221
1493
|
|
|
1222
1494
|
rb_scan_args(argc, argv, "21", (VALUE *) &rtype, (VALUE *) &rdim, (VALUE *) &ropt);
|
|
1223
|
-
rb_scan_options(ropt, "bytes,read_only,parent,face,storage,orderable_storage,comparable_storage",
|
|
1495
|
+
rb_scan_options(ropt, "bytes,read_only,parent,face,storage,orderable_storage,comparable_storage,numeric",
|
|
1224
1496
|
&rbytes, &rrdonly, &rparent, &rface, &rstorage,
|
|
1225
|
-
&rorderable, &rcomparable);
|
|
1497
|
+
&rorderable, &rcomparable, &rnumeric);
|
|
1226
1498
|
|
|
1227
1499
|
if ( ( ! NIL_P(rparent) ) && ( ! rb_obj_is_carray(rparent) ) ) {
|
|
1228
|
-
rb_raise(
|
|
1500
|
+
rb_raise(rb_eTypeError, "option :parent should be a carray");
|
|
1229
1501
|
}
|
|
1230
1502
|
|
|
1231
1503
|
/* :storage is meaningful only under face: true (= it documents the
|
|
@@ -1246,6 +1518,16 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1246
1518
|
"meaningful with face: true");
|
|
1247
1519
|
}
|
|
1248
1520
|
|
|
1521
|
+
if ( ! NIL_P(rnumeric) && ! RTEST(rface) ) {
|
|
1522
|
+
rb_raise(rb_eArgError,
|
|
1523
|
+
"CAObject: :numeric is only meaningful with face: true");
|
|
1524
|
+
}
|
|
1525
|
+
if ( ! NIL_P(rnumeric) && ! NIL_P(rstorage) ) {
|
|
1526
|
+
rb_raise(rb_eArgError,
|
|
1527
|
+
"CAObject: give either :numeric or :storage, not both "
|
|
1528
|
+
"(:storage declares a surface of its own)");
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1249
1531
|
/* face: true requires :parent. Under Face semantics the parent is the
|
|
1250
1532
|
true storage owner and CAObject itself carries the semantic identity.
|
|
1251
1533
|
The declared data_type is the SURFACE (= what dispatch sees);
|
|
@@ -1262,7 +1544,30 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1262
1544
|
|
|
1263
1545
|
rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
|
|
1264
1546
|
|
|
1547
|
+
/* Without :storage the data_type argument names the storage of a Face.
|
|
1548
|
+
A numeric storage is gated by default: the surface becomes CA_FIXLEN,
|
|
1549
|
+
so arithmetic, math and reductions raise instead of computing on the
|
|
1550
|
+
stored numbers, which the Face exists to give another meaning.
|
|
1551
|
+
numeric: true lets them through. An object or fixlen storage keeps
|
|
1552
|
+
its own data_type: fixlen kernels already raise, and an object cell
|
|
1553
|
+
may not be read as bytes. */
|
|
1554
|
+
storage_named = ! NIL_P(rstorage);
|
|
1555
|
+
if ( RTEST(rface) && NIL_P(rstorage) ) {
|
|
1556
|
+
if ( data_type == CA_OBJECT || data_type == CA_FIXLEN ) {
|
|
1557
|
+
if ( ! NIL_P(rnumeric) ) {
|
|
1558
|
+
rb_raise(rb_eArgError,
|
|
1559
|
+
"CAObject Face: :numeric applies to a numeric storage only "
|
|
1560
|
+
"(the storage is %s)", ca_type_name[data_type]);
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
else if ( ! RTEST(rnumeric) ) {
|
|
1564
|
+
rstorage = INT2NUM(data_type);
|
|
1565
|
+
data_type = CA_FIXLEN;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1265
1569
|
Check_Type(rdim, T_ARRAY);
|
|
1570
|
+
CA_CHECK_RANK(RARRAY_LEN(rdim)); /* before dim[] is filled */
|
|
1266
1571
|
|
|
1267
1572
|
ndim = RARRAY_LEN(rdim);
|
|
1268
1573
|
for (i=0; i<ndim; i++) {
|
|
@@ -1270,6 +1575,7 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1270
1575
|
}
|
|
1271
1576
|
|
|
1272
1577
|
TypedData_Get_Struct(self, CAObject, &caobject_data_type, ca);
|
|
1578
|
+
ca_check_uninitialized(ca);
|
|
1273
1579
|
ca_object_setup(ca, data_type, ndim, dim, bytes);
|
|
1274
1580
|
ca->self = self;
|
|
1275
1581
|
|
|
@@ -1287,17 +1593,11 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1287
1593
|
ca->parent = cp;
|
|
1288
1594
|
rb_ca_set_parent(self, rparent);
|
|
1289
1595
|
|
|
1290
|
-
/* Face mode invariants
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
Numeric Face authors who didn't intend
|
|
1296
|
-
surface/storage to differ.
|
|
1297
|
-
- :storage given → "surface != storage" opted-in:
|
|
1298
|
-
surface is free (= e.g. CA_FIXLEN for
|
|
1299
|
-
NonNumeric Face), :storage must agree with
|
|
1300
|
-
parent.data_type, and bytes must match. */
|
|
1596
|
+
/* Face mode invariants: bytes match the parent's, and the storage
|
|
1597
|
+
(:storage, or the data_type argument when :storage was omitted)
|
|
1598
|
+
is the parent's data_type. The surface is the data_type argument
|
|
1599
|
+
under :storage, CA_FIXLEN for a gated numeric storage (decided
|
|
1600
|
+
above), and the storage itself otherwise. */
|
|
1301
1601
|
if ( RTEST(rface) ) {
|
|
1302
1602
|
if ( bytes != cp->bytes ) {
|
|
1303
1603
|
rb_raise(rb_eTypeError,
|
|
@@ -1306,12 +1606,12 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1306
1606
|
(long long) bytes, (long long) cp->bytes);
|
|
1307
1607
|
}
|
|
1308
1608
|
if ( NIL_P(rstorage) ) {
|
|
1309
|
-
/*
|
|
1609
|
+
/* The data_type argument names the storage. */
|
|
1310
1610
|
if ( cp->data_type != data_type ) {
|
|
1311
1611
|
rb_raise(rb_eTypeError,
|
|
1312
1612
|
"CAObject Face: parent data_type mismatch "
|
|
1313
1613
|
"(declared=%d, parent=%d). Use :storage option to "
|
|
1314
|
-
"
|
|
1614
|
+
"declare a surface that differs from the storage.",
|
|
1315
1615
|
(int) data_type, (int) cp->data_type);
|
|
1316
1616
|
}
|
|
1317
1617
|
}
|
|
@@ -1323,10 +1623,20 @@ rb_ca_object_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1323
1623
|
&declared_storage, &declared_storage_bytes);
|
|
1324
1624
|
if ( cp->data_type != declared_storage ) {
|
|
1325
1625
|
rb_raise(rb_eTypeError,
|
|
1326
|
-
|
|
1327
|
-
"
|
|
1626
|
+
storage_named
|
|
1627
|
+
? "CAObject Face: :storage mismatch "
|
|
1628
|
+
"(declared=%d, parent.data_type=%d)"
|
|
1629
|
+
: "CAObject Face: parent data_type mismatch "
|
|
1630
|
+
"(declared=%d, parent=%d)",
|
|
1328
1631
|
(int) declared_storage, (int) cp->data_type);
|
|
1329
1632
|
}
|
|
1633
|
+
/* An object cell is a VALUE: reading it under another surface hands
|
|
1634
|
+
out its address, and writing one forges it. */
|
|
1635
|
+
if ( ca_is_object_type(cp) && data_type != CA_OBJECT ) {
|
|
1636
|
+
rb_raise(rb_eTypeError,
|
|
1637
|
+
"CAObject Face: an object storage can't be given "
|
|
1638
|
+
"another surface data_type");
|
|
1639
|
+
}
|
|
1330
1640
|
}
|
|
1331
1641
|
ca_set_flag(ca, CA_FLAG_IS_FACE);
|
|
1332
1642
|
if ( RTEST(rorderable) ) {
|