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_face.c
CHANGED
|
@@ -132,10 +132,18 @@ rb_ca_face_template (VALUE original_face, CArray *new_parent,
|
|
|
132
132
|
TypedData_Get_Struct(original_face, CArray, &carray_data_type, src);
|
|
133
133
|
tdata = ca_typeddata[src->obj_type];
|
|
134
134
|
|
|
135
|
-
/*
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
/* The struct with its subclass tail. struct_size is the struct alone;
|
|
136
|
+
a dsize callback also counts the buffers the struct points to (dim),
|
|
137
|
+
so it is only the fallback for a type registered without struct_size,
|
|
138
|
+
and copying that many bytes reads past the struct. */
|
|
139
|
+
if ( ca_func[src->obj_type].struct_size ) {
|
|
140
|
+
size = ca_func[src->obj_type].struct_size;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
size = (tdata && tdata->function.dsize)
|
|
144
|
+
? tdata->function.dsize(src)
|
|
145
|
+
: sizeof(CAView);
|
|
146
|
+
}
|
|
139
147
|
|
|
140
148
|
dst = (CArray *) xmalloc(size);
|
|
141
149
|
/* CAREFUL: the whole-struct memcpy is how a C-tail Face
|
|
@@ -198,6 +206,23 @@ ca_face_relift_entity (VALUE face, VALUE result)
|
|
|
198
206
|
return lifted;
|
|
199
207
|
}
|
|
200
208
|
|
|
209
|
+
/* A lift moves a view built on a wrapper (a Face or the lazy marker) one
|
|
210
|
+
* level down, onto what the wrapper wraps, so the view no longer keeps the
|
|
211
|
+
* wrapper alive. The view's mask was built over the wrapper's mask, which
|
|
212
|
+
* the wrapper owns and frees with itself; move it down the same level.
|
|
213
|
+
* The wrapper's mask is a same-shape refer of its parent's mask, so the
|
|
214
|
+
* mask view addresses the same cells there. */
|
|
215
|
+
static void
|
|
216
|
+
ca_lift_move_mask_down (CArray *view_ca, CArray *wp)
|
|
217
|
+
{
|
|
218
|
+
CArray *below = ((CAView *) wp)->parent;
|
|
219
|
+
if ( view_ca->mask && wp->mask && ca_is_view(wp->mask)
|
|
220
|
+
&& ((CAView *) wp->mask)->parent == below->mask
|
|
221
|
+
&& ((CAView *) view_ca->mask)->parent == wp->mask ) {
|
|
222
|
+
((CAView *) view_ca->mask)->parent = below->mask;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
201
226
|
/* ca_face_lift(view, face_parent) — at the tail of user-facing entry
|
|
202
227
|
* points (`ca[...]` etc.), when the operand was a Face, re-wrap the
|
|
203
228
|
* resulting view as a Face of the same subclass. Thin wrapper over
|
|
@@ -256,10 +281,12 @@ ca_face_lift (VALUE view, VALUE face_parent)
|
|
|
256
281
|
handled by builder-side pre-strip. data_type above stays a full strip
|
|
257
282
|
(surface concern, §8 #7) — the parent pointer is the structural concern
|
|
258
283
|
(§8.3); the two axes are deliberately separate. */
|
|
259
|
-
if ( ((
|
|
284
|
+
if ( ca_is_view(view_ca) /* an entity (a copy) has no parent field */
|
|
285
|
+
&& ((CAView *) view_ca)->parent == fp
|
|
260
286
|
&& ! ca_test_flag(view_ca, CA_FLAG_MULTI_PARENTS) ) {
|
|
261
287
|
((CAView *) view_ca)->parent = ((CAView *) fp)->parent; /* C pointer: one level */
|
|
262
288
|
rb_ca_set_parent(view, rb_ca_parent(face_parent)); /* @parent ivar: lockstep */
|
|
289
|
+
ca_lift_move_mask_down(view_ca, fp);
|
|
263
290
|
}
|
|
264
291
|
}
|
|
265
292
|
|
|
@@ -269,6 +296,12 @@ ca_face_lift (VALUE view, VALUE face_parent)
|
|
|
269
296
|
lifted = rb_ca_face_template(face_parent, view_ca, view_ca->dim);
|
|
270
297
|
/* Pin view as a GC root of lifted so the slice is not collected. */
|
|
271
298
|
rb_ca_set_parent(lifted, view);
|
|
299
|
+
/* The Face the view was taken from is off the parent chain now; keep it
|
|
300
|
+
for the attributes set on it. A fresh result the ordering kernels
|
|
301
|
+
re-wrap is not a view of it and takes none. */
|
|
302
|
+
if ( ca_is_view(view_ca) ) {
|
|
303
|
+
rb_ca_set_lifted_from(lifted, face_parent);
|
|
304
|
+
}
|
|
272
305
|
|
|
273
306
|
/* Optional Ruby callback for ivar / state carry. Faces holding
|
|
274
307
|
semantic state in the struct tail (CATime / CATimedelta
|
|
@@ -346,6 +379,7 @@ ca_lazy_marker_lift (VALUE view, VALUE marker)
|
|
|
346
379
|
&& ! ca_test_flag(view_ca, CA_FLAG_MULTI_PARENTS) ) {
|
|
347
380
|
((CAView *) view_ca)->parent = ((CAView *) mp)->parent; /* C pointer */
|
|
348
381
|
rb_ca_set_parent(view, rb_ca_parent(marker)); /* @parent ivar */
|
|
382
|
+
ca_lift_move_mask_down(view_ca, mp);
|
|
349
383
|
}
|
|
350
384
|
|
|
351
385
|
return rb_ca_lazy_marker_new(view);
|
|
@@ -522,15 +556,10 @@ ca_face_register_state_compatible (int obj_type, ca_face_state_compatible_fn fn)
|
|
|
522
556
|
static int
|
|
523
557
|
ca_face_has_ruby_state_check (VALUE va)
|
|
524
558
|
{
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
559
|
+
ID id_face_state_compatible_p = rb_intern("face_state_compatible?");
|
|
560
|
+
ID id_method = rb_intern("method");
|
|
561
|
+
ID id_owner = rb_intern("owner");
|
|
528
562
|
VALUE m, owner;
|
|
529
|
-
if ( id_face_state_compatible_p == 0 ) {
|
|
530
|
-
id_face_state_compatible_p = rb_intern("face_state_compatible?");
|
|
531
|
-
id_method = rb_intern("method");
|
|
532
|
-
id_owner = rb_intern("owner");
|
|
533
|
-
}
|
|
534
563
|
m = rb_funcall(va, id_method, 1, ID2SYM(id_face_state_compatible_p));
|
|
535
564
|
owner = rb_funcall(m, id_owner, 0);
|
|
536
565
|
return ( owner != rb_cCArray ) ? 1 : 0;
|
|
@@ -650,16 +679,11 @@ ca_face_register_state_portable (int obj_type, int portable)
|
|
|
650
679
|
static int
|
|
651
680
|
ca_face_class_has_portable_method (VALUE klass)
|
|
652
681
|
{
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
682
|
+
ID id_face_state_portable_p = rb_intern("face_state_portable?");
|
|
683
|
+
ID id_method = rb_intern("method");
|
|
684
|
+
ID id_owner = rb_intern("owner");
|
|
656
685
|
VALUE m, owner;
|
|
657
686
|
if ( NIL_P(klass) ) return 0;
|
|
658
|
-
if ( id_face_state_portable_p == 0 ) {
|
|
659
|
-
id_face_state_portable_p = rb_intern("face_state_portable?");
|
|
660
|
-
id_method = rb_intern("method");
|
|
661
|
-
id_owner = rb_intern("owner");
|
|
662
|
-
}
|
|
663
687
|
if ( !rb_respond_to(klass, id_face_state_portable_p) ) return 0;
|
|
664
688
|
m = rb_funcall(klass, id_method, 1, ID2SYM(id_face_state_portable_p));
|
|
665
689
|
owner = rb_funcall(m, id_owner, 0);
|
|
@@ -680,18 +704,88 @@ ca_face_conversion_hint (VALUE face)
|
|
|
680
704
|
: "to_type(:object) gives its values";
|
|
681
705
|
}
|
|
682
706
|
|
|
707
|
+
/* The method that gives the storage under a Face, for a refusal to point
|
|
708
|
+
at: #ticks for a time or a duration, #codes for a categorical. NULL for
|
|
709
|
+
a Face that names its storage some other way, or not at all. */
|
|
710
|
+
const char *
|
|
711
|
+
ca_face_storage_method (VALUE face)
|
|
712
|
+
{
|
|
713
|
+
static const char *names[] = { "ticks", "codes" };
|
|
714
|
+
size_t i;
|
|
715
|
+
for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
|
|
716
|
+
if ( rb_respond_to(face, rb_intern(names[i])) ) {
|
|
717
|
+
return names[i];
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return NULL;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/* ca.face_storage_method -- the name of the method that gives the storage
|
|
724
|
+
under ca (ca_face_storage_method), as a String, or nil. For refusals
|
|
725
|
+
written in Ruby. */
|
|
726
|
+
static VALUE
|
|
727
|
+
rb_ca_face_storage_method (VALUE self)
|
|
728
|
+
{
|
|
729
|
+
const char *name = ca_face_storage_method(self);
|
|
730
|
+
return name ? rb_str_new_cstr(name) : Qnil;
|
|
731
|
+
}
|
|
732
|
+
|
|
683
733
|
/* Refuse to order (or, with verb "count", to count by value) a Face whose
|
|
684
734
|
storage does not hold its values in order, pointing at what does: its
|
|
685
735
|
values, or its storage when that is what is meant. */
|
|
686
736
|
void
|
|
687
737
|
ca_face_refuse_order (const char *name, VALUE face, const char *verb)
|
|
688
738
|
{
|
|
739
|
+
const char *storage = ca_face_storage_method(face);
|
|
740
|
+
if ( storage ) {
|
|
741
|
+
rb_raise(rb_eArgError,
|
|
742
|
+
"%s: %s is not orderable by storage (a cell encodes the value "
|
|
743
|
+
"rather than being it); %s its values instead -- %s -- or %s "
|
|
744
|
+
"its storage, which #%s gives",
|
|
745
|
+
name, rb_obj_classname(face), verb,
|
|
746
|
+
ca_face_conversion_hint(face), verb, storage);
|
|
747
|
+
}
|
|
689
748
|
rb_raise(rb_eArgError,
|
|
690
749
|
"%s: %s is not orderable by storage (a cell encodes the value "
|
|
691
|
-
"rather than being it); %s its values instead -- %s
|
|
692
|
-
".parent to %s its storage",
|
|
750
|
+
"rather than being it); %s its values instead -- %s",
|
|
693
751
|
name, rb_obj_classname(face), verb,
|
|
694
|
-
ca_face_conversion_hint(face)
|
|
752
|
+
ca_face_conversion_hint(face));
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/* The rule every family that orders, compares, searches or hashes the cells
|
|
756
|
+
of a Face reference keeps: the storage stands for the values only when the
|
|
757
|
+
Face declares ORDERABLE_STORAGE. A fixlen storage is no exception -- its
|
|
758
|
+
bytes are an order only when the Face says so (CAFixlenString). Returns
|
|
759
|
+
when the Face is ORDERABLE; refuses otherwise (ca_face_refuse_order). A
|
|
760
|
+
family that can order by a key asks ca_face_orders_by_itself first. */
|
|
761
|
+
void
|
|
762
|
+
ca_face_require_orderable (VALUE face, const char *name, const char *verb)
|
|
763
|
+
{
|
|
764
|
+
CArray *ca;
|
|
765
|
+
TypedData_Get_Struct(face, CArray, &carray_data_type, ca);
|
|
766
|
+
if ( ! ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
|
|
767
|
+
ca_face_refuse_order(name, face, verb);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/* Whether a Face is ordered by its own #order rather than by its storage:
|
|
772
|
+
it is not ORDERABLE and answers #order itself (CAConstString, CARecord),
|
|
773
|
+
so a family that orders by a key can take that order. CArray#order is
|
|
774
|
+
not one: it sorts the storage and comes back to the gate. */
|
|
775
|
+
int
|
|
776
|
+
ca_face_orders_by_itself (VALUE face)
|
|
777
|
+
{
|
|
778
|
+
ID id_order = rb_intern("order");
|
|
779
|
+
ID id_method = rb_intern("method");
|
|
780
|
+
ID id_owner = rb_intern("owner");
|
|
781
|
+
CArray *ca;
|
|
782
|
+
VALUE m;
|
|
783
|
+
TypedData_Get_Struct(face, CArray, &carray_data_type, ca);
|
|
784
|
+
if ( ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
|
|
785
|
+
return 0;
|
|
786
|
+
}
|
|
787
|
+
m = rb_funcall(face, id_method, 1, ID2SYM(id_order));
|
|
788
|
+
return ( rb_funcall(m, id_owner, 0) != rb_cCArray ) ? 1 : 0;
|
|
695
789
|
}
|
|
696
790
|
|
|
697
791
|
/* Refuse a numeric operation (arithmetic, math, a reduction) on a Face,
|
|
@@ -708,10 +802,20 @@ ca_face_refuse_numeric (VALUE self, const char *name, VALUE eclass)
|
|
|
708
802
|
if ( ! ca_is_face(ca) ) {
|
|
709
803
|
return;
|
|
710
804
|
}
|
|
805
|
+
{
|
|
806
|
+
const char *storage = ca_face_storage_method(self);
|
|
807
|
+
if ( storage ) {
|
|
808
|
+
rb_raise(eclass,
|
|
809
|
+
"%s: %s does not define it (a cell encodes the value rather "
|
|
810
|
+
"than being a number); compute on its values instead -- %s -- "
|
|
811
|
+
"or on its storage, which #%s gives",
|
|
812
|
+
name, rb_obj_classname(self), ca_face_conversion_hint(self),
|
|
813
|
+
storage);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
711
816
|
rb_raise(eclass,
|
|
712
817
|
"%s: %s does not define it (a cell encodes the value rather than "
|
|
713
|
-
"being a number); compute on its values instead -- %s
|
|
714
|
-
".parent to compute on its storage",
|
|
818
|
+
"being a number); compute on its values instead -- %s",
|
|
715
819
|
name, rb_obj_classname(self), ca_face_conversion_hint(self));
|
|
716
820
|
}
|
|
717
821
|
|
|
@@ -729,12 +833,24 @@ ca_face_operand_descend (VALUE operand, const char *name)
|
|
|
729
833
|
if ( ca_test_flag(op, CA_FLAG_FACE_COMPARABLE_STORAGE) ) {
|
|
730
834
|
return rb_ca_strip_face_value(operand);
|
|
731
835
|
}
|
|
836
|
+
{
|
|
837
|
+
const char *storage = ca_face_storage_method(operand);
|
|
838
|
+
if ( storage ) {
|
|
839
|
+
rb_raise(rb_eArgError,
|
|
840
|
+
"%s: cannot take a %s operand: its storage is not its surface "
|
|
841
|
+
"(a cell encodes the value rather than being it), so comparing "
|
|
842
|
+
"the storage would compare the encoding. Convert the operand "
|
|
843
|
+
"to the receiver's space first -- %s -- or compare the storage "
|
|
844
|
+
"of both sides, which #%s gives",
|
|
845
|
+
name, rb_obj_classname(operand),
|
|
846
|
+
ca_face_conversion_hint(operand), storage);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
732
849
|
rb_raise(rb_eArgError,
|
|
733
850
|
"%s: cannot take a %s operand: its storage is not its surface "
|
|
734
851
|
"(a cell encodes the value rather than being it), so comparing "
|
|
735
852
|
"the storage would compare the encoding. Convert the operand to "
|
|
736
|
-
"the receiver's space first -- %s
|
|
737
|
-
"or pass .parent on both sides to work in storage space",
|
|
853
|
+
"the receiver's space first -- %s",
|
|
738
854
|
name, rb_obj_classname(operand), ca_face_conversion_hint(operand));
|
|
739
855
|
return Qnil; /* not reached */
|
|
740
856
|
}
|
|
@@ -823,11 +939,16 @@ ca_face_operand_values (VALUE operand)
|
|
|
823
939
|
- A reference with to_comparable brings any operand into its own space
|
|
824
940
|
(a unit, an instant), and refuses what it cannot convert.
|
|
825
941
|
- Any other reference has no way to read the operand in its space, and
|
|
826
|
-
refuses it.
|
|
942
|
+
refuses it.
|
|
943
|
+
UNDEF is undefined in every space, so it passes as it is and the entry
|
|
944
|
+
answers it as it does for a plain array. */
|
|
827
945
|
VALUE
|
|
828
946
|
ca_face_reconcile_operand (VALUE reference, VALUE operand, const char *name)
|
|
829
947
|
{
|
|
830
948
|
CArray *ca;
|
|
949
|
+
if ( operand == CA_UNDEF ) {
|
|
950
|
+
return operand;
|
|
951
|
+
}
|
|
831
952
|
TypedData_Get_Struct(reference, CArray, &carray_data_type, ca);
|
|
832
953
|
if ( ca->obj_type == CA_OBJ_RECORD ) {
|
|
833
954
|
if ( RTEST(rb_obj_is_carray(operand)) ) {
|
|
@@ -854,22 +975,61 @@ ca_face_reconcile_operand (VALUE reference, VALUE operand, const char *name)
|
|
|
854
975
|
if ( ca_test_flag(ca, CA_FLAG_FACE_COMPARABLE_STORAGE) ) {
|
|
855
976
|
return ca_face_operand_descend(ca_face_operand_values(operand), name);
|
|
856
977
|
}
|
|
857
|
-
|
|
858
|
-
ca_face_refuse_order(name, reference, "compare");
|
|
859
|
-
}
|
|
978
|
+
ca_face_require_orderable(reference, name, "compare");
|
|
860
979
|
if ( rb_respond_to(reference, rb_intern("to_comparable")) ) {
|
|
861
980
|
return rb_ca_strip_face_value(rb_funcall(reference,
|
|
862
981
|
rb_intern("to_comparable"),
|
|
863
982
|
1, operand));
|
|
864
983
|
}
|
|
984
|
+
{
|
|
985
|
+
const char *storage = ca_face_storage_method(reference);
|
|
986
|
+
if ( storage ) {
|
|
987
|
+
rb_raise(rb_eArgError,
|
|
988
|
+
"%s: %s is not comparable by storage and has no to_comparable "
|
|
989
|
+
"to bring the operand into its space; compare the storage of "
|
|
990
|
+
"both sides, which #%s gives",
|
|
991
|
+
name, rb_obj_classname(reference), storage);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
865
994
|
rb_raise(rb_eArgError,
|
|
866
995
|
"%s: %s is not comparable by storage and has no to_comparable "
|
|
867
|
-
"to bring the operand into its space
|
|
868
|
-
"sides to work in storage space",
|
|
996
|
+
"to bring the operand into its space",
|
|
869
997
|
name, rb_obj_classname(reference));
|
|
870
998
|
return Qnil; /* not reached */
|
|
871
999
|
}
|
|
872
1000
|
|
|
1001
|
+
/* The reference and the operand of a comparison (an operator, count(v), a
|
|
1002
|
+
search, linear_section) brought into one space. A time reference answers
|
|
1003
|
+
both through comparable_pair: it keeps itself when the operand sits on its
|
|
1004
|
+
grid, and otherwise meets the operand in the finer unit the two share,
|
|
1005
|
+
where to_comparable would refuse a value off its grid. Every other
|
|
1006
|
+
reference keeps itself and reconciles the operand
|
|
1007
|
+
(ca_face_reconcile_operand). An assignment, which has to land on the
|
|
1008
|
+
reference's grid, uses ca_face_reconcile_operand. */
|
|
1009
|
+
void
|
|
1010
|
+
ca_face_reconcile_pair (volatile VALUE *pref, volatile VALUE *poperand,
|
|
1011
|
+
const char *name)
|
|
1012
|
+
{
|
|
1013
|
+
static ID id_comparable_pair = 0;
|
|
1014
|
+
VALUE ref = *pref, operand = *poperand;
|
|
1015
|
+
CArray *ca;
|
|
1016
|
+
if ( id_comparable_pair == 0 ) {
|
|
1017
|
+
id_comparable_pair = rb_intern("comparable_pair");
|
|
1018
|
+
}
|
|
1019
|
+
TypedData_Get_Struct(ref, CArray, &carray_data_type, ca);
|
|
1020
|
+
if ( operand != CA_UNDEF
|
|
1021
|
+
&& ca->obj_type != CA_OBJ_RECORD
|
|
1022
|
+
&& ! ca_test_flag(ca, CA_FLAG_FACE_COMPARABLE_STORAGE)
|
|
1023
|
+
&& ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE)
|
|
1024
|
+
&& rb_respond_to(ref, id_comparable_pair) ) {
|
|
1025
|
+
VALUE pair = rb_funcall(ref, id_comparable_pair, 1, operand);
|
|
1026
|
+
*pref = rb_ary_entry(pair, 0);
|
|
1027
|
+
*poperand = rb_ca_strip_face_value(rb_ary_entry(pair, 1));
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
*poperand = ca_face_reconcile_operand(ref, operand, name);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
873
1033
|
int
|
|
874
1034
|
ca_face_state_portable (int obj_type, VALUE klass)
|
|
875
1035
|
{
|
|
@@ -891,7 +1051,7 @@ ca_face_list_class (VALUE list, const char *who)
|
|
|
891
1051
|
{
|
|
892
1052
|
long n = RARRAY_LEN(list), i;
|
|
893
1053
|
int any_face = 0, all_face = 1;
|
|
894
|
-
VALUE face_class = Qnil;
|
|
1054
|
+
VALUE face_class = Qnil, face = Qnil;
|
|
895
1055
|
CArray *ref = NULL;
|
|
896
1056
|
|
|
897
1057
|
for ( i = 0; i < n; i++ ) {
|
|
@@ -903,6 +1063,7 @@ ca_face_list_class (VALUE list, const char *who)
|
|
|
903
1063
|
any_face = 1;
|
|
904
1064
|
if ( NIL_P(face_class) ) {
|
|
905
1065
|
face_class = rb_obj_class(p);
|
|
1066
|
+
face = p;
|
|
906
1067
|
ref = ca;
|
|
907
1068
|
}
|
|
908
1069
|
else if ( rb_obj_class(p) != face_class ) {
|
|
@@ -911,19 +1072,36 @@ ca_face_list_class (VALUE list, const char *who)
|
|
|
911
1072
|
}
|
|
912
1073
|
if ( ! any_face ) return Qnil;
|
|
913
1074
|
if ( ! all_face ) {
|
|
1075
|
+
const char *storage = ca_face_storage_method(face);
|
|
1076
|
+
if ( ref->obj_type == CA_OBJ_STRING ) {
|
|
1077
|
+
rb_raise(rb_eArgError,
|
|
1078
|
+
"%s: cannot mix Face and non-Face arrays, or arrays of "
|
|
1079
|
+
"different Face classes; convert them first to one Face "
|
|
1080
|
+
"class or to no Face (CArray.string(a) makes a CAString of "
|
|
1081
|
+
"an object array of Strings)",
|
|
1082
|
+
who);
|
|
1083
|
+
}
|
|
1084
|
+
if ( storage ) {
|
|
1085
|
+
rb_raise(rb_eArgError,
|
|
1086
|
+
"%s: cannot mix Face and non-Face arrays, or arrays of "
|
|
1087
|
+
"different Face classes; convert them first to one Face "
|
|
1088
|
+
"class or to no Face, or combine their storage (#%s gives "
|
|
1089
|
+
"the storage of a %s)",
|
|
1090
|
+
who, storage, rb_obj_classname(face));
|
|
1091
|
+
}
|
|
914
1092
|
rb_raise(rb_eArgError,
|
|
915
1093
|
"%s: cannot mix Face and non-Face arrays, or arrays of "
|
|
916
|
-
"different Face classes; convert them to one Face
|
|
917
|
-
"
|
|
1094
|
+
"different Face classes; convert them first to one Face "
|
|
1095
|
+
"class or to no Face",
|
|
918
1096
|
who);
|
|
919
1097
|
}
|
|
920
1098
|
if ( n > 1 && ! ca_face_state_portable(ref->obj_type, face_class) ) {
|
|
921
1099
|
rb_raise(rb_eArgError,
|
|
922
1100
|
"%s: %s state is not portable across several arrays (each "
|
|
923
1101
|
"keeps its values in storage of its own); convert them first "
|
|
924
|
-
"(
|
|
925
|
-
|
|
926
|
-
|
|
1102
|
+
"(%s)",
|
|
1103
|
+
who, rb_class2name(face_class),
|
|
1104
|
+
ca_face_conversion_hint(face));
|
|
927
1105
|
}
|
|
928
1106
|
for ( i = 1; i < n; i++ ) {
|
|
929
1107
|
VALUE p = rb_ary_entry(list, i);
|
|
@@ -956,7 +1134,7 @@ rb_ca_s_face_state_portable_p (VALUE klass)
|
|
|
956
1134
|
return Qtrue;
|
|
957
1135
|
}
|
|
958
1136
|
|
|
959
|
-
/* ca.
|
|
1137
|
+
/* ca.orderable_storage? -- whether ca's storage holds its values, in
|
|
960
1138
|
their order, so that a lookup may compare the storage: true for an array
|
|
961
1139
|
that is not a Face and for a Face that declares
|
|
962
1140
|
CA_FLAG_FACE_ORDERABLE_STORAGE, false for a Face whose cells encode the
|
|
@@ -970,7 +1148,7 @@ rb_ca_orderable_storage_p (VALUE self)
|
|
|
970
1148
|
return ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE) ? Qtrue : Qfalse;
|
|
971
1149
|
}
|
|
972
1150
|
|
|
973
|
-
/* ca.
|
|
1151
|
+
/* ca.comparable_storage? -- whether ca's storage holds its values as
|
|
974
1152
|
they are, so that a plain operand may be compared with the storage: true
|
|
975
1153
|
for an array that is not a Face and for a Face that declares
|
|
976
1154
|
CA_FLAG_FACE_COMPARABLE_STORAGE. */
|
|
@@ -983,7 +1161,7 @@ rb_ca_comparable_storage_p (VALUE self)
|
|
|
983
1161
|
return ca_test_flag(ca, CA_FLAG_FACE_COMPARABLE_STORAGE) ? Qtrue : Qfalse;
|
|
984
1162
|
}
|
|
985
1163
|
|
|
986
|
-
/* ca.
|
|
1164
|
+
/* ca.face_storage -- the storage under a Face (ca itself when it is not
|
|
987
1165
|
a Face). */
|
|
988
1166
|
static VALUE
|
|
989
1167
|
rb_ca_face_storage (VALUE self)
|
|
@@ -991,7 +1169,7 @@ rb_ca_face_storage (VALUE self)
|
|
|
991
1169
|
return rb_ca_strip_face_value(self);
|
|
992
1170
|
}
|
|
993
1171
|
|
|
994
|
-
/* ca.
|
|
1172
|
+
/* ca.reconcile_operand(operand, name) -- operand brought into ca's
|
|
995
1173
|
storage space by the rule every operand family follows
|
|
996
1174
|
(ca_face_reconcile_operand for a Face, ca_face_operand_descend for an
|
|
997
1175
|
array that is not one). For the families written in Ruby. */
|
|
@@ -1056,6 +1234,25 @@ ca_face_reconcile_comparison (volatile VALUE *pself, volatile VALUE *pother)
|
|
|
1056
1234
|
return;
|
|
1057
1235
|
}
|
|
1058
1236
|
|
|
1237
|
+
/* Two string arrays of different kinds (CAString, CAFixlenString,
|
|
1238
|
+
CAConstString) or of different cell widths hold their strings in
|
|
1239
|
+
different storage: the padded bytes of one are not the bytes of the
|
|
1240
|
+
other. They are compared by their strings. */
|
|
1241
|
+
if ( RTEST(rb_obj_is_carray(other)) ) {
|
|
1242
|
+
static ID id_to_string = 0;
|
|
1243
|
+
CArray *oc;
|
|
1244
|
+
if ( id_to_string == 0 ) id_to_string = rb_intern("to_string");
|
|
1245
|
+
TypedData_Get_Struct(other, CArray, &carray_data_type, oc);
|
|
1246
|
+
if ( ca_is_face(oc) && rb_respond_to(self, id_to_string)
|
|
1247
|
+
&& rb_respond_to(other, id_to_string)
|
|
1248
|
+
&& ( rb_obj_class(self) != rb_obj_class(other)
|
|
1249
|
+
|| sc->bytes != oc->bytes ) ) {
|
|
1250
|
+
*pself = rb_ca_strip_face_value(rb_funcall(self, id_to_string, 0));
|
|
1251
|
+
*pother = rb_ca_strip_face_value(rb_funcall(other, id_to_string, 0));
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1059
1256
|
storage = ca_strip_face(sc);
|
|
1060
1257
|
if ( storage->data_type == CA_FIXLEN ) {
|
|
1061
1258
|
/* genuine fixlen semantics: memcmp is the correct comparison, so self
|
|
@@ -1065,22 +1262,44 @@ ca_face_reconcile_comparison (volatile VALUE *pself, volatile VALUE *pother)
|
|
|
1065
1262
|
return;
|
|
1066
1263
|
}
|
|
1067
1264
|
|
|
1068
|
-
|
|
1069
|
-
ca_face_refuse_order("comparison", self, "compare");
|
|
1070
|
-
}
|
|
1265
|
+
ca_face_require_orderable(self, "comparison", "compare");
|
|
1071
1266
|
|
|
1072
1267
|
{
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1268
|
+
/* A Ruby Array is a list of values (to_comparable reads it cell by
|
|
1269
|
+
cell), not one value, so it keeps the length it was given. */
|
|
1270
|
+
int other_was_scalar = ! RTEST(rb_obj_is_carray(other))
|
|
1271
|
+
&& ! RB_TYPE_P(other, T_ARRAY);
|
|
1272
|
+
volatile VALUE ref = self, op = other;
|
|
1273
|
+
ca_face_reconcile_pair(&ref, &op, "comparison");
|
|
1274
|
+
/* The reconcile lifts a scalar operand to a length-1 array; unwrap it
|
|
1076
1275
|
so the comparison stays array-vs-scalar instead of a shape check
|
|
1077
1276
|
against [1] (which only a 1-D reference would pass). */
|
|
1078
|
-
if ( other_was_scalar && RTEST(rb_obj_is_carray(
|
|
1079
|
-
|
|
1277
|
+
if ( other_was_scalar && RTEST(rb_obj_is_carray(op)) ) {
|
|
1278
|
+
op = rb_ca_fetch_addr(op, 0);
|
|
1080
1279
|
}
|
|
1081
|
-
*pself = rb_ca_strip_face_value(
|
|
1082
|
-
*pother =
|
|
1280
|
+
*pself = rb_ca_strip_face_value(ref);
|
|
1281
|
+
*pother = op;
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
/* A Face's parent, the array its values are stored in, is handed out as a
|
|
1286
|
+
read-only view: a write through it would change the Face's values
|
|
1287
|
+
without the Face's conversion (a tick count stored into a time, bytes
|
|
1288
|
+
into a record). The storage is written through the Face's own named
|
|
1289
|
+
methods (CATime#ticks), which take it with face_storage. */
|
|
1290
|
+
static VALUE
|
|
1291
|
+
rb_ca_face_parent (VALUE self)
|
|
1292
|
+
{
|
|
1293
|
+
volatile VALUE st = rb_ca_parent(self), view;
|
|
1294
|
+
CArray *cs, *cv;
|
|
1295
|
+
if ( NIL_P(st) ) {
|
|
1296
|
+
return st;
|
|
1083
1297
|
}
|
|
1298
|
+
TypedData_Get_Struct(st, CArray, &carray_data_type, cs);
|
|
1299
|
+
view = rb_ca_refer_new(st, cs->data_type, cs->ndim, cs->dim, cs->bytes, 0);
|
|
1300
|
+
TypedData_Get_Struct(view, CArray, &carray_data_type, cv);
|
|
1301
|
+
ca_set_flag(cv, CA_FLAG_READ_ONLY);
|
|
1302
|
+
return view;
|
|
1084
1303
|
}
|
|
1085
1304
|
|
|
1086
1305
|
void
|
|
@@ -1092,6 +1311,7 @@ Init_ca_face (void)
|
|
|
1092
1311
|
ahead of this Init) — CAFace inherits from it. */
|
|
1093
1312
|
rb_cCAFace = rb_define_class("CAFace", rb_cCAView);
|
|
1094
1313
|
rb_define_alloc_func(rb_cCAFace, rb_ca_face_s_allocate_forbidden);
|
|
1314
|
+
rb_define_method(rb_cCAFace, "parent", rb_ca_face_parent, 0);
|
|
1095
1315
|
|
|
1096
1316
|
/* Initialise the portable table to -1 for every slot so dispatch
|
|
1097
1317
|
can distinguish "explicitly registered 0" (CAConstString) from
|
|
@@ -1105,12 +1325,14 @@ Init_ca_face (void)
|
|
|
1105
1325
|
rb_define_singleton_method(rb_cCArray, "face_state_portable?",
|
|
1106
1326
|
rb_ca_s_face_state_portable_p, 0);
|
|
1107
1327
|
rb_define_method(rb_cCArray, "face_lift", rb_ca_face_lift_method, 1);
|
|
1108
|
-
rb_define_private_method(rb_cCArray, "
|
|
1328
|
+
rb_define_private_method(rb_cCArray, "orderable_storage?",
|
|
1109
1329
|
rb_ca_orderable_storage_p, 0);
|
|
1110
|
-
rb_define_private_method(rb_cCArray, "
|
|
1330
|
+
rb_define_private_method(rb_cCArray, "comparable_storage?",
|
|
1111
1331
|
rb_ca_comparable_storage_p, 0);
|
|
1112
|
-
rb_define_private_method(rb_cCArray, "
|
|
1332
|
+
rb_define_private_method(rb_cCArray, "face_storage",
|
|
1113
1333
|
rb_ca_face_storage, 0);
|
|
1114
|
-
rb_define_private_method(rb_cCArray, "
|
|
1334
|
+
rb_define_private_method(rb_cCArray, "reconcile_operand",
|
|
1115
1335
|
rb_ca_reconcile_operand, 2);
|
|
1336
|
+
rb_define_private_method(rb_cCArray, "face_storage_method",
|
|
1337
|
+
rb_ca_face_storage_method, 0);
|
|
1116
1338
|
}
|
data/ext/ca_obj_face.h
CHANGED
|
@@ -104,6 +104,10 @@ void Init_ca_face (void);
|
|
|
104
104
|
extern int8_t CA_OBJ_RECORD;
|
|
105
105
|
VALUE rb_ca_record_get_data_class (CArray *ca);
|
|
106
106
|
|
|
107
|
+
/* CA_OBJ_STRING identifies CAString, read by the store path
|
|
108
|
+
(carray_access.c) to send an array source through the write hook. */
|
|
109
|
+
extern int8_t CA_OBJ_STRING;
|
|
110
|
+
|
|
107
111
|
/* -- Convenience macro for view-creating method deployment --
|
|
108
112
|
Insert at the tail of each view-creating Ruby method (= rb_ca_transpose
|
|
109
113
|
/ rb_ca_reshape / etc.) just before return. `ca` is self's CArray *,
|
|
@@ -288,10 +292,25 @@ VALUE ca_face_strip_one (VALUE v);
|
|
|
288
292
|
NORETURN(void ca_face_refuse_order (const char *name, VALUE face,
|
|
289
293
|
const char *verb));
|
|
290
294
|
|
|
295
|
+
/* The gate of every family that orders, compares, searches or hashes a Face
|
|
296
|
+
reference: returns when the Face is ORDERABLE_STORAGE, refuses otherwise
|
|
297
|
+
(ca_face_refuse_order). Call this rather than testing the flag. */
|
|
298
|
+
void ca_face_require_orderable (VALUE face, const char *name,
|
|
299
|
+
const char *verb);
|
|
300
|
+
|
|
301
|
+
/* Whether a Face is not ORDERABLE and answers #order itself (CAConstString,
|
|
302
|
+
CARecord), so a family that orders by a key takes that order instead of
|
|
303
|
+
the storage. */
|
|
304
|
+
int ca_face_orders_by_itself (VALUE face);
|
|
305
|
+
|
|
291
306
|
/* The conversion a refusal of a Face whose cells encode its values points
|
|
292
307
|
at (#to_string for a string Face, to_type(:object) for any other). */
|
|
293
308
|
const char *ca_face_conversion_hint (VALUE face);
|
|
294
309
|
|
|
310
|
+
/* The method that gives the storage under a Face (#ticks, #codes), or NULL
|
|
311
|
+
when the Face has none of those. */
|
|
312
|
+
const char *ca_face_storage_method (VALUE face);
|
|
313
|
+
|
|
295
314
|
/* Raise eclass naming a Face that does not define the numeric operation
|
|
296
315
|
`name`; returns when self is not a Face. See ca_obj_face.c. */
|
|
297
316
|
void ca_face_refuse_numeric (VALUE self, const char *name, VALUE eclass);
|
data/ext/ca_obj_fake.c
CHANGED
|
@@ -78,8 +78,14 @@ ca_fake_setup (CAFake *ca, CArray *parent, int8_t data_type, ca_size_t bytes)
|
|
|
78
78
|
|
|
79
79
|
/* check arguments */
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
CA_CHECK_DATA_TYPE_GIVEN(data_type);
|
|
82
|
+
CA_CHECK_BYTES_GIVEN(data_type, bytes);
|
|
83
|
+
|
|
84
|
+
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
85
|
+
run them before it allocates. */
|
|
86
|
+
if ( ca == NULL ) {
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
83
89
|
|
|
84
90
|
ndim = parent->ndim;
|
|
85
91
|
dim = parent->dim;
|
|
@@ -103,9 +109,6 @@ ca_fake_setup (CAFake *ca, CArray *parent, int8_t data_type, ca_size_t bytes)
|
|
|
103
109
|
|
|
104
110
|
memcpy(ca->dim, dim, ndim * sizeof(ca_size_t));
|
|
105
111
|
|
|
106
|
-
if ( ca_has_mask(parent) ) {
|
|
107
|
-
ca_create_mask(ca);
|
|
108
|
-
}
|
|
109
112
|
|
|
110
113
|
if ( ca_is_scalar(parent) ) {
|
|
111
114
|
ca_set_flag(ca, CA_FLAG_SCALAR);
|
|
@@ -117,8 +120,11 @@ ca_fake_setup (CAFake *ca, CArray *parent, int8_t data_type, ca_size_t bytes)
|
|
|
117
120
|
CAFake *
|
|
118
121
|
ca_fake_new (CArray *parent, int8_t data_type, ca_size_t bytes)
|
|
119
122
|
{
|
|
120
|
-
CAFake *ca
|
|
123
|
+
CAFake *ca;
|
|
124
|
+
ca_fake_setup(NULL, parent, data_type, bytes);
|
|
125
|
+
ca = (CAFake *) ca_array_alloc(CA_OBJ_FAKE, parent->ndim);
|
|
121
126
|
ca_fake_setup(ca, parent, data_type, bytes);
|
|
127
|
+
ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
|
|
122
128
|
return ca;
|
|
123
129
|
}
|
|
124
130
|
|
|
@@ -277,18 +283,7 @@ ca_fake_func_allocate (void *ap)
|
|
|
277
283
|
{
|
|
278
284
|
CAFake *ca = (CAFake *) ap;
|
|
279
285
|
ca_attach(ca->parent);
|
|
280
|
-
ca->ptr =
|
|
281
|
-
|
|
282
|
-
/* CAREFUL: CA_OBJECT storage must contain valid VALUEs before GC can
|
|
283
|
-
scan it, so seed with Fixnum 0 rather than leaving raw xmalloc bytes. */
|
|
284
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
285
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
286
|
-
VALUE zero = SIZE2NUM(0);
|
|
287
|
-
ca_size_t i;
|
|
288
|
-
for (i=0; i<ca->elements; i++) {
|
|
289
|
-
*p++ = zero;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
286
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
292
287
|
}
|
|
293
288
|
|
|
294
289
|
static void
|
|
@@ -296,17 +291,7 @@ ca_fake_func_attach (void *ap)
|
|
|
296
291
|
{
|
|
297
292
|
CAFake *ca = (CAFake *) ap;
|
|
298
293
|
ca_attach(ca->parent);
|
|
299
|
-
ca->ptr =
|
|
300
|
-
|
|
301
|
-
/* CAREFUL: same VALUE-seed rule as ca_fake_func_allocate. */
|
|
302
|
-
if ( ca->data_type == CA_OBJECT ) {
|
|
303
|
-
VALUE *p = (VALUE *) ca->ptr;
|
|
304
|
-
VALUE zero = SIZE2NUM(0);
|
|
305
|
-
ca_size_t i;
|
|
306
|
-
for (i=0; i<ca->elements; i++) {
|
|
307
|
-
*p++ = zero;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
294
|
+
ca->ptr = ca_alloc_cells((CArray *) ca);
|
|
310
295
|
|
|
311
296
|
if ( ca->parent->mask ) {
|
|
312
297
|
ca_cast_block_with_mask(ca->elements, ca->parent, ca->parent->ptr,
|
|
@@ -499,6 +484,7 @@ rb_ca_fake_initialize_copy (VALUE self, VALUE other)
|
|
|
499
484
|
ca_array_pool_alloc(ca, CA_OBJ_FAKE, cs->parent->ndim);
|
|
500
485
|
}
|
|
501
486
|
ca_fake_setup(ca, cs->parent, cs->data_type, cs->bytes);
|
|
487
|
+
ca_view_inherit_mask((VALUE) ca);
|
|
502
488
|
|
|
503
489
|
return self;
|
|
504
490
|
}
|