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.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +469 -0
  3. data/README.md +3 -2
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_array_pool.c +25 -1
  6. data/ext/ca_axis_descriptor.h +27 -24
  7. data/ext/ca_axis_dispatch.c +14 -26
  8. data/ext/ca_axis_group.c +27 -27
  9. data/ext/ca_binop_dispatch.c +1 -29
  10. data/ext/ca_binop_dispatch.h +0 -1
  11. data/ext/ca_categorical_iterator.c +231 -153
  12. data/ext/ca_compare.c +9 -20
  13. data/ext/ca_composite_dispatch.c +9 -9
  14. data/ext/ca_group_iter.c +16 -17
  15. data/ext/ca_kernel_iterator.c +1240 -2000
  16. data/ext/ca_kernel_iterator.h +502 -519
  17. data/ext/ca_monop_dispatch.c +82 -59
  18. data/ext/ca_monop_dispatch.h +1 -0
  19. data/ext/ca_obj_array.c +152 -45
  20. data/ext/ca_obj_bincmp.c +25 -21
  21. data/ext/ca_obj_binop.c +16 -26
  22. data/ext/ca_obj_bitarray.c +8 -3
  23. data/ext/ca_obj_bitfield.c +63 -49
  24. data/ext/ca_obj_block.c +18 -9
  25. data/ext/ca_obj_byte_swap.c +7 -7
  26. data/ext/ca_obj_const_string.c +188 -22
  27. data/ext/ca_obj_face.c +280 -58
  28. data/ext/ca_obj_face.h +19 -0
  29. data/ext/ca_obj_fake.c +15 -29
  30. data/ext/ca_obj_farray.c +6 -3
  31. data/ext/ca_obj_field.c +30 -8
  32. data/ext/ca_obj_fixlen_string.c +2 -3
  33. data/ext/ca_obj_grid.c +455 -134
  34. data/ext/ca_obj_meld.c +172 -34
  35. data/ext/ca_obj_moncmp.c +23 -8
  36. data/ext/ca_obj_monop.c +113 -67
  37. data/ext/ca_obj_object.c +210 -52
  38. data/ext/ca_obj_record.c +15 -7
  39. data/ext/ca_obj_reduce.c +17 -8
  40. data/ext/ca_obj_refer.c +42 -35
  41. data/ext/ca_obj_remap.c +30 -9
  42. data/ext/ca_obj_repeat.c +9 -10
  43. data/ext/ca_obj_roll.c +31 -10
  44. data/ext/ca_obj_select.c +48 -14
  45. data/ext/ca_obj_select_axis.c +15 -47
  46. data/ext/ca_obj_shift.c +41 -7
  47. data/ext/ca_obj_stack.c +180 -34
  48. data/ext/ca_obj_stride.c +190 -134
  49. data/ext/ca_obj_string.c +80 -4
  50. data/ext/ca_obj_tile.c +32 -11
  51. data/ext/ca_obj_time.c +22 -6
  52. data/ext/ca_obj_timedelta.c +22 -6
  53. data/ext/ca_obj_transpose.c +13 -7
  54. data/ext/ca_obj_triop.c +26 -32
  55. data/ext/ca_obj_window.c +267 -74
  56. data/ext/ca_op_ipower.c +4 -4
  57. data/ext/ca_sort_kernels.h +6 -3
  58. data/ext/ca_sweep_engine.c +2 -2
  59. data/ext/caframe_csv_reader.c +80 -1
  60. data/ext/carray.h +214 -75
  61. data/ext/carray_access.c +200 -99
  62. data/ext/carray_address_basis.c +343 -87
  63. data/ext/carray_attribute.c +113 -6
  64. data/ext/carray_bincount.c +10 -8
  65. data/ext/carray_broadcast.c +13 -8
  66. data/ext/carray_build_flags.h +3 -0
  67. data/ext/carray_call_cfunc.c +108 -0
  68. data/ext/carray_cast.c +375 -96
  69. data/ext/carray_cast_func.rb +90 -20
  70. data/ext/carray_class.c +4 -3
  71. data/ext/carray_config.h +28 -0
  72. data/ext/carray_conversion.c +18 -9
  73. data/ext/carray_copy.c +51 -14
  74. data/ext/carray_core.c +150 -55
  75. data/ext/carray_count.c +56 -20
  76. data/ext/carray_element.c +81 -33
  77. data/ext/carray_factorize.c +138 -84
  78. data/ext/carray_generate.c +199 -52
  79. data/ext/carray_histogram.c +63 -18
  80. data/ext/carray_hold.c +12 -15
  81. data/ext/carray_index_classifier.c +388 -176
  82. data/ext/carray_internal.h +348 -29
  83. data/ext/carray_kernels_bincmp.c +4453 -0
  84. data/ext/carray_kernels_binop.c +11368 -0
  85. data/ext/carray_kernels_init.c +1734 -0
  86. data/ext/carray_kernels_moncmp.c +2104 -0
  87. data/ext/carray_kernels_monop.c +18369 -0
  88. data/ext/carray_kernels_reduce_aggregate.c +23818 -0
  89. data/ext/carray_kernels_reduce_boolean.c +406 -0
  90. data/ext/carray_kernels_reduce_cumulative.c +10086 -0
  91. data/ext/carray_kernels_reduce_extreme.c +17634 -0
  92. data/ext/carray_kernels_reduce_variance.c +3849 -0
  93. data/ext/carray_kernels_scan.c +4302 -0
  94. data/ext/carray_kernels_search.c +33829 -0
  95. data/ext/carray_kernels_sort.c +10897 -0
  96. data/ext/carray_kernels_triop.c +1864 -0
  97. data/ext/carray_key_windows.c +220 -0
  98. data/ext/carray_lazy.c +170 -111
  99. data/ext/carray_mask.c +337 -94
  100. data/ext/carray_median_percentile.c +82 -28
  101. data/ext/carray_memory_view.c +669 -561
  102. data/ext/carray_operator.c +129 -52
  103. data/ext/carray_order.c +604 -77
  104. data/ext/carray_partition.c +28 -27
  105. data/ext/carray_random.c +85 -31
  106. data/ext/carray_round.c +273 -0
  107. data/ext/carray_scatter.c +87 -45
  108. data/ext/carray_segment.c +3 -3
  109. data/ext/carray_slab.c +123 -37
  110. data/ext/carray_sort.c +259 -51
  111. data/ext/carray_sort_kernel.c +5 -7
  112. data/ext/carray_struct.c +54 -61
  113. data/ext/carray_test.c +26 -5
  114. data/ext/carray_time_text.c +4 -2
  115. data/ext/carray_undef.c +4 -0
  116. data/ext/carray_utils.c +309 -66
  117. data/ext/mk_call_cfunc.rb +19 -2
  118. data/ext/mkkernel.rb +403 -350
  119. data/ext/ruby_carray.c +10 -4
  120. data/ext/version.h +4 -4
  121. data/lib/carray/attribute.rb +139 -22
  122. data/lib/carray/autoload_carray.rb +8 -31
  123. data/lib/carray/autoload_method_extension.rb +14 -5
  124. data/lib/carray/axis_group.rb +255 -106
  125. data/lib/carray/basics.rb +105 -17
  126. data/lib/carray/bincount_nd.rb +12 -2
  127. data/lib/carray/block_iterator.rb +126 -23
  128. data/lib/carray/boolean_reduce.rb +17 -17
  129. data/lib/carray/categorical.rb +195 -59
  130. data/lib/carray/categorical_iterator.rb +132 -29
  131. data/lib/carray/complex.rb +5 -5
  132. data/lib/carray/conditional.rb +67 -18
  133. data/lib/carray/const_string.rb +24 -5
  134. data/lib/carray/construct.rb +15 -11
  135. data/lib/carray/data_type_extension.rb +9 -1
  136. data/lib/carray/distance_limit.rb +77 -0
  137. data/lib/carray/fixlen_string.rb +48 -3
  138. data/lib/carray/frame/column_verbs.rb +71 -0
  139. data/lib/carray/frame/concat.rb +17 -3
  140. data/lib/carray/frame/convert.rb +69 -0
  141. data/lib/carray/frame/csv_parser.rb +111 -17
  142. data/lib/carray/frame/describe.rb +3 -2
  143. data/lib/carray/frame/frame.rb +252 -28
  144. data/lib/carray/frame/group.rb +603 -101
  145. data/lib/carray/frame/io.rb +117 -28
  146. data/lib/carray/frame/join.rb +312 -51
  147. data/lib/carray/frame/records.rb +83 -7
  148. data/lib/carray/frame/reshape.rb +42 -35
  149. data/lib/carray/frame/sort.rb +7 -19
  150. data/lib/carray/frame/verbs.rb +188 -48
  151. data/lib/carray/frame/windows.rb +117 -0
  152. data/lib/carray/frame.rb +2 -0
  153. data/lib/carray/fuse_source.rb +42 -6
  154. data/lib/carray/fusion.rb +40 -16
  155. data/lib/carray/histogram.rb +6 -1
  156. data/lib/carray/inspect.rb +31 -8
  157. data/lib/carray/iterator.rb +85 -7
  158. data/lib/carray/key_windows.rb +620 -0
  159. data/lib/carray/lazy.rb +217 -183
  160. data/lib/carray/mask_gap_fill.rb +63 -57
  161. data/lib/carray/meld_reduce.rb +12 -14
  162. data/lib/carray/methods/bin.rb +26 -18
  163. data/lib/carray/methods/bincount.rb +16 -0
  164. data/lib/carray/methods/bit_string.rb +1 -1
  165. data/lib/carray/methods/choose.rb +16 -3
  166. data/lib/carray/methods/composition.rb +3 -1
  167. data/lib/carray/methods/gather_nd.rb +14 -5
  168. data/lib/carray/methods/insert_block.rb +2 -2
  169. data/lib/carray/methods/is_between.rb +59 -0
  170. data/lib/carray/methods/is_in.rb +61 -37
  171. data/lib/carray/methods/join.rb +1 -6
  172. data/lib/carray/methods/lag.rb +49 -0
  173. data/lib/carray/methods/locate_addr.rb +47 -51
  174. data/lib/carray/methods/mode.rb +1 -1
  175. data/lib/carray/methods/nunique.rb +11 -6
  176. data/lib/carray/methods/resize.rb +3 -3
  177. data/lib/carray/methods/value_counts.rb +4 -11
  178. data/lib/carray/record_order.rb +3 -3
  179. data/lib/carray/rng.rb +3 -0
  180. data/lib/carray/runtime.rb +53 -8
  181. data/lib/carray/segment_iterator.rb +323 -88
  182. data/lib/carray/serialize.rb +45 -14
  183. data/lib/carray/slab_iterator.rb +50 -0
  184. data/lib/carray/stack.rb +15 -12
  185. data/lib/carray/string.rb +113 -5
  186. data/lib/carray/string_operation_extension.rb +21 -6
  187. data/lib/carray/struct.rb +9 -21
  188. data/lib/carray/struct_builder.rb +24 -11
  189. data/lib/carray/time.rb +819 -158
  190. data/lib/carray/window_iterator.rb +122 -16
  191. data/lib/carray.rb +7 -0
  192. data/yard-stubs/ca_obj_bitfield.rb +1 -1
  193. data/yard-stubs/ca_obj_field.rb +4 -0
  194. data/yard-stubs/ca_obj_grid.rb +21 -10
  195. data/yard-stubs/ca_obj_refer.rb +2 -1
  196. data/yard-stubs/ca_obj_roll.rb +2 -2
  197. data/yard-stubs/ca_obj_shift.rb +5 -1
  198. data/yard-stubs/ca_obj_tile.rb +1 -1
  199. data/yard-stubs/ca_obj_transpose.rb +5 -4
  200. data/yard-stubs/ca_obj_window.rb +8 -3
  201. data/yard-stubs/carray_access.rb +6 -1
  202. data/yard-stubs/carray_attribute.rb +3 -6
  203. data/yard-stubs/carray_cast.rb +12 -0
  204. data/yard-stubs/carray_conversion.rb +7 -2
  205. data/yard-stubs/carray_copy.rb +4 -2
  206. data/yard-stubs/carray_count.rb +4 -4
  207. data/yard-stubs/carray_element.rb +17 -10
  208. data/yard-stubs/carray_generate.rb +21 -1
  209. data/yard-stubs/carray_mask.rb +32 -3
  210. data/yard-stubs/carray_math.rb +41 -5
  211. data/yard-stubs/carray_median_percentile.rb +5 -2
  212. data/yard-stubs/carray_memory_view.rb +40 -23
  213. data/yard-stubs/carray_order.rb +129 -22
  214. data/yard-stubs/carray_random.rb +13 -4
  215. data/yard-stubs/carray_scatter.rb +17 -10
  216. data/yard-stubs/carray_slab.rb +9 -2
  217. data/yard-stubs/carray_sort.rb +6 -5
  218. data/yard-stubs/carray_test.rb +5 -3
  219. metadata +25 -3
  220. data/lib/carray/arrow_tensor.rb +0 -401
  221. 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
- /* Actual subclass size (incl. tail) — via TypedData's dsize callback */
136
- size = (tdata && tdata->function.dsize)
137
- ? tdata->function.dsize(src)
138
- : sizeof(CAView);
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 ( ((CAView *) view_ca)->parent == fp
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
- static ID id_face_state_compatible_p = 0;
526
- static ID id_method = 0;
527
- static ID id_owner = 0;
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
- static ID id_face_state_portable_p = 0;
654
- static ID id_method = 0;
655
- static ID id_owner = 0;
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 -- or pass "
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), verb);
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 -- or pass "
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
- if ( ! ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
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; pass .parent on both "
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 class, or "
917
- "none, first, or take .parent of each to combine the storage",
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
- "(a CAConstString with to_string), or take .parent of each to "
925
- "combine the storage",
926
- who, rb_class2name(face_class));
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.__orderable_storage__ -- whether ca's storage holds its values, in
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.__comparable_storage__ -- whether ca's storage holds its values as
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.__face_storage__ -- the storage under a Face (ca itself when it is not
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.__reconcile_operand__(operand, name) -- operand brought into ca's
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
- if ( ! ca_test_flag(sc, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
1069
- ca_face_refuse_order("comparison", self, "compare");
1070
- }
1265
+ ca_face_require_orderable(self, "comparison", "compare");
1071
1266
 
1072
1267
  {
1073
- int other_was_scalar = ! RTEST(rb_obj_is_carray(other));
1074
- other = ca_face_reconcile_operand(self, other, "comparison");
1075
- /* to_comparable lifts a scalar operand to a length-1 array; unwrap it
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(other)) ) {
1079
- other = rb_ca_fetch_addr(other, 0);
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(self);
1082
- *pother = other;
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, "__orderable_storage__",
1328
+ rb_define_private_method(rb_cCArray, "orderable_storage?",
1109
1329
  rb_ca_orderable_storage_p, 0);
1110
- rb_define_private_method(rb_cCArray, "__comparable_storage__",
1330
+ rb_define_private_method(rb_cCArray, "comparable_storage?",
1111
1331
  rb_ca_comparable_storage_p, 0);
1112
- rb_define_private_method(rb_cCArray, "__face_storage__",
1332
+ rb_define_private_method(rb_cCArray, "face_storage",
1113
1333
  rb_ca_face_storage, 0);
1114
- rb_define_private_method(rb_cCArray, "__reconcile_operand__",
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
- CA_CHECK_DATA_TYPE(data_type);
82
- CA_CHECK_BYTES(data_type, bytes);
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 = (CAFake *) ca_array_alloc(CA_OBJ_FAKE, parent->ndim);
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 = xmalloc(ca_length(ca));
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 = xmalloc(ca_length(ca));
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
  }