carray 3.0.1 → 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.
Files changed (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +824 -0
  3. data/README.md +5 -6
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +258 -4
  6. data/ext/ca_axis_group.c +368 -184
  7. data/ext/ca_binop_dispatch.c +54 -32
  8. data/ext/ca_binop_dispatch.h +1 -0
  9. data/ext/ca_categorical_iterator.c +90 -41
  10. data/ext/ca_compare.c +8 -2
  11. data/ext/ca_for_buffer.h +21 -68
  12. data/ext/ca_group_iter.c +27 -11
  13. data/ext/ca_kernel_iterator.c +960 -245
  14. data/ext/ca_kernel_iterator.h +352 -181
  15. data/ext/ca_monop_dispatch.c +4 -4
  16. data/ext/ca_monop_dispatch.h +4 -0
  17. data/ext/ca_obj_array.c +194 -42
  18. data/ext/ca_obj_bincmp.c +152 -121
  19. data/ext/ca_obj_binop.c +107 -210
  20. data/ext/ca_obj_bitarray.c +37 -24
  21. data/ext/ca_obj_bitfield.c +95 -62
  22. data/ext/ca_obj_block.c +5 -4
  23. data/ext/ca_obj_byte_swap.c +40 -40
  24. data/ext/ca_obj_const_string.c +180 -50
  25. data/ext/ca_obj_face.c +428 -62
  26. data/ext/ca_obj_face.h +107 -47
  27. data/ext/ca_obj_fake.c +21 -50
  28. data/ext/ca_obj_farray.c +1 -0
  29. data/ext/ca_obj_field.c +16 -3
  30. data/ext/ca_obj_fixlen_string.c +39 -26
  31. data/ext/ca_obj_grid.c +181 -124
  32. data/ext/ca_obj_meld.c +235 -55
  33. data/ext/ca_obj_moncmp.c +61 -61
  34. data/ext/ca_obj_monop.c +125 -107
  35. data/ext/ca_obj_object.c +551 -233
  36. data/ext/ca_obj_record.c +51 -16
  37. data/ext/ca_obj_reduce.c +5 -8
  38. data/ext/ca_obj_refer.c +117 -33
  39. data/ext/ca_obj_remap.c +57 -17
  40. data/ext/ca_obj_repeat.c +21 -5
  41. data/ext/ca_obj_roll.c +115 -11
  42. data/ext/ca_obj_select.c +88 -75
  43. data/ext/ca_obj_select_axis.c +58 -60
  44. data/ext/ca_obj_shift.c +22 -102
  45. data/ext/ca_obj_stack.c +223 -123
  46. data/ext/ca_obj_stride.c +267 -35
  47. data/ext/ca_obj_string.c +25 -22
  48. data/ext/ca_obj_tile.c +32 -16
  49. data/ext/ca_obj_time.c +23 -25
  50. data/ext/ca_obj_timedelta.c +21 -23
  51. data/ext/ca_obj_transpose.c +12 -3
  52. data/ext/ca_obj_triop.c +110 -117
  53. data/ext/ca_obj_window.c +157 -29
  54. data/ext/ca_op_ipower.c +25 -13
  55. data/ext/ca_op_powi.h +57 -30
  56. data/ext/ca_pow5_table.h +656 -0
  57. data/ext/ca_rng_normal.h +42 -0
  58. data/ext/ca_rng_xoshiro256pp.h +105 -0
  59. data/ext/ca_sort_kernels.h +70 -0
  60. data/ext/ca_sweep_engine.c +385 -198
  61. data/ext/ca_sweep_engine.h +31 -23
  62. data/ext/ca_triop_dispatch.c +4 -1
  63. data/ext/ca_triop_dispatch.h +5 -2
  64. data/ext/caframe_csv_reader.c +463 -0
  65. data/ext/carray.h +90 -28
  66. data/ext/carray_access.c +487 -231
  67. data/ext/carray_address_basis.c +731 -0
  68. data/ext/carray_attribute.c +45 -3
  69. data/ext/carray_bincount.c +32 -2
  70. data/ext/carray_broadcast.c +49 -17
  71. data/ext/carray_call_cfunc.c +667 -511
  72. data/ext/carray_cast.c +1556 -247
  73. data/ext/carray_cast_func.rb +34 -21
  74. data/ext/carray_conversion.c +197 -73
  75. data/ext/carray_copy.c +84 -38
  76. data/ext/carray_core.c +591 -119
  77. data/ext/carray_count.c +148 -96
  78. data/ext/carray_element.c +18 -27
  79. data/ext/carray_factorize.c +604 -291
  80. data/ext/carray_generate.c +76 -40
  81. data/ext/carray_histogram.c +152 -94
  82. data/ext/carray_hold.c +2 -1
  83. data/ext/carray_index_classifier.c +63 -96
  84. data/ext/carray_internal.h +400 -1
  85. data/ext/carray_lazy.c +834 -79
  86. data/ext/carray_loop.c +88 -66
  87. data/ext/carray_mask.c +705 -324
  88. data/ext/carray_math_kernel.h +1 -0
  89. data/ext/carray_median_percentile.c +263 -63
  90. data/ext/carray_memory_view.c +254 -248
  91. data/ext/carray_operator.c +1093 -363
  92. data/ext/carray_order.c +133 -69
  93. data/ext/carray_partition.c +102 -56
  94. data/ext/carray_random.c +582 -204
  95. data/ext/carray_scatter.c +308 -65
  96. data/ext/carray_segment.c +257 -0
  97. data/ext/carray_slab.c +183 -70
  98. data/ext/carray_sort.c +235 -240
  99. data/ext/carray_sort_kernel.c +8 -1
  100. data/ext/carray_struct.c +99 -21
  101. data/ext/carray_test.c +167 -64
  102. data/ext/carray_time_text.c +1182 -0
  103. data/ext/carray_utils.c +363 -98
  104. data/ext/extconf.rb +27 -2
  105. data/ext/mk_call_cfunc.rb +103 -118
  106. data/ext/mk_pow5_table.rb +35 -0
  107. data/ext/mkkernel.rb +1349 -851
  108. data/ext/ruby_carray.c +17 -2
  109. data/ext/version.h +4 -4
  110. data/ext/version.rb +4 -2
  111. data/lib/carray/attribute.rb +39 -0
  112. data/lib/carray/autoload_carray.rb +24 -3
  113. data/lib/carray/autoload_method_extension.rb +18 -0
  114. data/lib/carray/axis_group.rb +245 -20
  115. data/lib/carray/basics.rb +95 -25
  116. data/lib/carray/bincount_nd.rb +6 -0
  117. data/lib/carray/block_iterator.rb +200 -54
  118. data/lib/carray/boolean_reduce.rb +21 -29
  119. data/lib/carray/categorical.rb +244 -59
  120. data/lib/carray/categorical_iterator.rb +391 -757
  121. data/lib/carray/complex.rb +36 -29
  122. data/lib/carray/conditional.rb +94 -7
  123. data/lib/carray/const_string.rb +177 -27
  124. data/lib/carray/construct.rb +40 -0
  125. data/lib/carray/data_type_extension.rb +3 -0
  126. data/lib/carray/data_type_limits.rb +91 -0
  127. data/lib/carray/fixlen_string.rb +1 -1
  128. data/lib/carray/frame/concat.rb +157 -6
  129. data/lib/carray/frame/convert.rb +13 -7
  130. data/lib/carray/frame/csv_parser.rb +590 -76
  131. data/lib/carray/frame/describe.rb +79 -0
  132. data/lib/carray/frame/frame.rb +205 -35
  133. data/lib/carray/frame/group.rb +199 -40
  134. data/lib/carray/frame/io.rb +452 -60
  135. data/lib/carray/frame/join.rb +134 -46
  136. data/lib/carray/frame/records.rb +54 -19
  137. data/lib/carray/frame/reshape.rb +448 -0
  138. data/lib/carray/frame/sort.rb +26 -2
  139. data/lib/carray/frame/verbs.rb +726 -56
  140. data/lib/carray/frame.rb +2 -0
  141. data/lib/carray/fuse_source.rb +111 -2
  142. data/lib/carray/fusion.rb +229 -38
  143. data/lib/carray/inspect.rb +71 -20
  144. data/lib/carray/iterator.rb +157 -2
  145. data/lib/carray/lazy.rb +54 -67
  146. data/lib/carray/mask_gap_fill.rb +66 -50
  147. data/lib/carray/math.rb +32 -19
  148. data/lib/carray/meld_reduce.rb +40 -7
  149. data/lib/carray/methods/align_addr.rb +8 -4
  150. data/lib/carray/methods/bincount.rb +2 -2
  151. data/lib/carray/methods/bit_string.rb +14 -3
  152. data/lib/carray/methods/composition.rb +16 -10
  153. data/lib/carray/methods/discovery_along.rb +74 -0
  154. data/lib/carray/methods/factorize.rb +50 -0
  155. data/lib/carray/methods/gather_nd.rb +13 -2
  156. data/lib/carray/methods/insert_block.rb +9 -14
  157. data/lib/carray/methods/is_in.rb +130 -6
  158. data/lib/carray/methods/join.rb +1 -1
  159. data/lib/carray/methods/locate_addr.rb +235 -21
  160. data/lib/carray/methods/mask_duplicates.rb +35 -1
  161. data/lib/carray/methods/mode.rb +18 -1
  162. data/lib/carray/methods/nunique.rb +22 -1
  163. data/lib/carray/methods/repeat.rb +91 -0
  164. data/lib/carray/methods/resize.rb +21 -23
  165. data/lib/carray/methods/snap.rb +34 -12
  166. data/lib/carray/methods/unique.rb +52 -3
  167. data/lib/carray/record_order.rb +208 -0
  168. data/lib/carray/rng.rb +86 -0
  169. data/lib/carray/runtime.rb +14 -11
  170. data/lib/carray/segment_iterator.rb +990 -0
  171. data/lib/carray/serialize.rb +197 -27
  172. data/lib/carray/slab_iterator.rb +109 -40
  173. data/lib/carray/stack.rb +10 -4
  174. data/lib/carray/string_operation_extension.rb +9 -4
  175. data/lib/carray/struct.rb +142 -51
  176. data/lib/carray/struct_builder.rb +110 -14
  177. data/lib/carray/table.rb +2 -2
  178. data/lib/carray/time.rb +535 -105
  179. data/lib/carray/window_iterator.rb +259 -82
  180. data/lib/carray.rb +4 -2
  181. data/yard-stubs/ca_obj_array.rb +4 -4
  182. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  183. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  184. data/yard-stubs/ca_obj_block.rb +2 -7
  185. data/yard-stubs/ca_obj_fake.rb +1 -1
  186. data/yard-stubs/ca_obj_field.rb +1 -1
  187. data/yard-stubs/ca_obj_refer.rb +3 -3
  188. data/yard-stubs/ca_obj_roll.rb +0 -1
  189. data/yard-stubs/ca_obj_stride.rb +10 -7
  190. data/yard-stubs/ca_obj_transpose.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +11 -4
  192. data/yard-stubs/carray_access.rb +6 -5
  193. data/yard-stubs/carray_broadcast.rb +2 -2
  194. data/yard-stubs/carray_cast.rb +78 -43
  195. data/yard-stubs/carray_conversion.rb +13 -1
  196. data/yard-stubs/carray_copy.rb +8 -3
  197. data/yard-stubs/carray_core.rb +3 -83
  198. data/yard-stubs/carray_count.rb +16 -2
  199. data/yard-stubs/carray_lazy.rb +210 -1
  200. data/yard-stubs/carray_loop.rb +4 -1
  201. data/yard-stubs/carray_mask.rb +34 -10
  202. data/yard-stubs/carray_math.rb +1499 -4
  203. data/yard-stubs/carray_median_percentile.rb +26 -8
  204. data/yard-stubs/carray_order.rb +43 -82
  205. data/yard-stubs/carray_scatter.rb +10 -3
  206. data/yard-stubs/carray_segment.rb +72 -0
  207. data/yard-stubs/carray_slab.rb +11 -8
  208. data/yard-stubs/carray_sort.rb +50 -8
  209. data/yard-stubs/carray_test.rb +10 -0
  210. data/yard-stubs/carray_utils.rb +0 -26
  211. metadata +19 -19
  212. data/ext/ca_for_each_element.h +0 -239
  213. data/ext/carray_build_flags.h +0 -3
  214. data/ext/carray_config.h +0 -28
  215. data/ext/carray_kernels_bincmp.c +0 -4446
  216. data/ext/carray_kernels_binop.c +0 -11001
  217. data/ext/carray_kernels_init.c +0 -1131
  218. data/ext/carray_kernels_map.c +0 -3467
  219. data/ext/carray_kernels_moncmp.c +0 -2097
  220. data/ext/carray_kernels_monop.c +0 -18313
  221. data/ext/carray_kernels_reduce_aggregate.c +0 -25837
  222. data/ext/carray_kernels_reduce_boolean.c +0 -330
  223. data/ext/carray_kernels_reduce_cumulative.c +0 -14593
  224. data/ext/carray_kernels_reduce_extreme.c +0 -16948
  225. data/ext/carray_kernels_reduce_variance.c +0 -3910
  226. data/ext/carray_kernels_scan.c +0 -3693
  227. data/ext/carray_kernels_search.c +0 -32138
  228. data/ext/carray_kernels_sort.c +0 -10626
  229. data/ext/carray_kernels_triop.c +0 -1392
@@ -13,6 +13,7 @@
13
13
 
14
14
  #include "carray.h"
15
15
  #include "ca_obj_face.h" /* CA_OBJ_RECORD + rb_ca_record_get_data_class */
16
+ #include "carray_internal.h" /* rb_ca_inherit_attr */
16
17
 
17
18
  /* ------------------------------------------------------------------- */
18
19
 
@@ -436,6 +437,8 @@ rb_ca_is_object_type (VALUE self)
436
437
  /* ------------------------------------------------------------------- */
437
438
 
438
439
  static ID id_parent;
440
+ static ID id_attr;
441
+ static ID id_attrs;
439
442
 
440
443
  VALUE
441
444
  rb_ca_parent (VALUE self)
@@ -443,13 +446,41 @@ rb_ca_parent (VALUE self)
443
446
  return rb_ivar_get(self, id_parent);
444
447
  }
445
448
 
449
+ /* Give dst the attributes (lib/carray/attribute.rb) that src shows, as its
450
+ own Hash. Used by the methods that produce a new entity holding the
451
+ same values -- copy, to_type. The parent walk here only decides
452
+ whether any array on the chain has an @attr at all; which of them
453
+ src actually shows (a lazy op view stops the chain) is left to #attrs,
454
+ so the rule lives in one place. */
455
+ void
456
+ rb_ca_inherit_attr (VALUE dst, VALUE src)
457
+ {
458
+ VALUE obj = src, attrs;
459
+ int depth;
460
+
461
+ for (depth = 0; depth < 64 && ! NIL_P(obj); depth++) {
462
+ if ( rb_ivar_defined(obj, id_attr) ) {
463
+ break;
464
+ }
465
+ obj = rb_ivar_get(obj, id_parent);
466
+ }
467
+ if ( depth == 64 || NIL_P(obj) ) {
468
+ return;
469
+ }
470
+ attrs = rb_funcall(src, id_attrs, 0);
471
+ if ( RHASH_SIZE(attrs) > 0 ) {
472
+ rb_ivar_set(dst, id_attr, rb_hash_dup(attrs));
473
+ }
474
+ }
475
+
476
+ /* A view of a frozen array is not frozen itself: building it may still set
477
+ it up after this (an ivar, a lift that moves it onto another parent), and
478
+ writes through it are refused by ca_is_readonly, which walks to the
479
+ frozen root and finds CA_FLAG_READ_ONLY there. */
446
480
  VALUE
447
481
  rb_ca_set_parent (VALUE self, VALUE obj)
448
482
  {
449
483
  rb_ivar_set(self, id_parent, obj);
450
- if ( OBJ_FROZEN(obj) ) {
451
- rb_ca_freeze(self);
452
- }
453
484
  return obj;
454
485
  }
455
486
 
@@ -521,6 +552,15 @@ ca_root_array (void *ap)
521
552
  }
522
553
  }
523
554
 
555
+ /* Whether two arrays may share memory: their cells live in the same
556
+ root. An operation that writes one while reading the other must read
557
+ from a copy taken before it writes. */
558
+ int
559
+ ca_shares_root (void *ap, void *aq)
560
+ {
561
+ return ca_root_array(ap) == ca_root_array(aq);
562
+ }
563
+
524
564
  static VALUE
525
565
  rb_ca_root_array (VALUE self)
526
566
  {
@@ -584,6 +624,8 @@ void
584
624
  Init_carray_attribute (void)
585
625
  {
586
626
  id_parent = rb_intern("parent");
627
+ id_attr = rb_intern("@attr");
628
+ id_attrs = rb_intern("attrs");
587
629
 
588
630
  rb_define_method(rb_cCArray, "obj_type", rb_ca_obj_type, 0);
589
631
  rb_define_method(rb_cCArray, "data_type", rb_ca_data_type, 0);
@@ -72,6 +72,34 @@
72
72
  } \
73
73
  } while (0)
74
74
 
75
+ /* Checked before a window opens: the dispatches above raise on a type
76
+ they do not cover, which would leave the labels (and weights) attached. */
77
+ static void
78
+ bincount_check_types (CArray *cl, CArray *cw)
79
+ {
80
+ switch ( cl->data_type ) {
81
+ case CA_INT8: case CA_INT16: case CA_INT32: case CA_INT64:
82
+ case CA_UINT8: case CA_UINT16: case CA_UINT32: case CA_UINT64:
83
+ break;
84
+ default:
85
+ rb_raise(rb_eCADataTypeError,
86
+ "bincount: integer label array required (got %d)",
87
+ cl->data_type);
88
+ }
89
+ if ( ! cw ) {
90
+ return;
91
+ }
92
+ switch ( cw->data_type ) {
93
+ case CA_FLOAT64: case CA_FLOAT32:
94
+ case CA_INT8: case CA_INT16: case CA_INT32: case CA_INT64:
95
+ case CA_UINT8: case CA_UINT16: case CA_UINT32: case CA_UINT64:
96
+ break;
97
+ default:
98
+ rb_raise(rb_eCADataTypeError,
99
+ "bincount: weights must be numeric (got %d)", cw->data_type);
100
+ }
101
+ }
102
+
75
103
  /* __bincount_count__(length) -- count occurrences of each label in
76
104
  self. Allocates a zero-filled UInt32 (or UInt64 if length >= 2^32)
77
105
  output of size `length`, then runs the 8-way label dispatch. */
@@ -104,7 +132,8 @@ rb_ca_bincount_count_kernel (VALUE self, VALUE rlength)
104
132
  return vout;
105
133
  }
106
134
 
107
- ca_attach(cl);
135
+ bincount_check_types(cl, NULL);
136
+ ca_attach(cl); /* window: nothing raises inside */
108
137
  n = cl->elements;
109
138
  mlabel = cl->mask ? (boolean8_t *) cl->mask->ptr : NULL;
110
139
 
@@ -213,7 +242,8 @@ rb_ca_bincount_weighted_kernel (VALUE self, VALUE rweights, VALUE rlength)
213
242
  return vout;
214
243
  }
215
244
 
216
- ca_attach_n(2, cl, cw);
245
+ bincount_check_types(cl, cw);
246
+ ca_attach_n(2, cl, cw); /* window: nothing raises inside */
217
247
  n = cl->elements;
218
248
  mlabel = cl->mask ? (boolean8_t *) cl->mask->ptr : NULL;
219
249
  mweight = cw->mask ? (boolean8_t *) cw->mask->ptr : NULL;
@@ -23,13 +23,14 @@
23
23
  (right-to-left axis pairing; see the docstring at the function).
24
24
 
25
25
  Case B (cross-ndim dim-prepending) is not handled by the implicit
26
- helpers; users with cross-ndim operands keep using the explicit :*
27
- form or #broadcast_to (which does accept cross-ndim with target axes
28
- pinned to size 1). See PROPOSAL_BROADCASTING_AND_UNBOUND.md.
26
+ helpers; a cross-ndim operand has to declare the axis itself, either
27
+ with the newaxis sigil (`a + c[:_, nil]`) or with #broadcast_to (which
28
+ does accept cross-ndim with target axes pinned to size 1).
29
29
 
30
30
  ---------------------------------------------------------------------------- */
31
31
 
32
32
  #include "carray.h"
33
+ #include "ca_obj_face.h" /* CA_WRAPPER_LIFT */
33
34
 
34
35
  NORETURN(static void ca_broadcast_refuse_write (VALUE dst, VALUE src));
35
36
 
@@ -39,7 +40,7 @@ ca_broadcast_refuse_write (VALUE dst, VALUE src)
39
40
  {
40
41
  volatile VALUE dst_s = rb_inspect(rb_funcall(dst, rb_intern("shape"), 0));
41
42
  volatile VALUE src_s = rb_inspect(rb_funcall(src, rb_intern("shape"), 0));
42
- rb_raise(rb_eRuntimeError,
43
+ rb_raise(rb_eArgError,
43
44
  "shape mismatch writing to carray (%s <- %s); shapes must agree "
44
45
  "once size-1 axes are dropped, or one side must be 1-D, or the "
45
46
  "source must be smaller and broadcastable -- use .flatten to "
@@ -119,7 +120,7 @@ ca_broadcast_view (VALUE src, int8_t ndim, ca_size_t *target_dim)
119
120
  TypedData_Get_Struct(src, CArray, &carray_data_type, cs);
120
121
 
121
122
  if (cs->ndim != ndim) {
122
- rb_raise(rb_eRuntimeError,
123
+ rb_raise(rb_eArgError,
123
124
  "broadcast: ndim mismatch (%d vs %d)",
124
125
  (int) cs->ndim, (int) ndim);
125
126
  }
@@ -143,7 +144,7 @@ ca_broadcast_view (VALUE src, int8_t ndim, ca_size_t *target_dim)
143
144
  needs_broadcast = 1;
144
145
  }
145
146
  else {
146
- rb_raise(rb_eRuntimeError,
147
+ rb_raise(rb_eArgError,
147
148
  "broadcast: cannot broadcast axis %d (%lld vs %lld)",
148
149
  i, (long long) cs->dim[i], (long long) target_dim[i]);
149
150
  }
@@ -172,20 +173,48 @@ ca_broadcast_view (VALUE src, int8_t ndim, ca_size_t *target_dim)
172
173
  raises). */
173
174
  NORETURN(static void ca_broadcast_refuse (VALUE self, VALUE other));
174
175
 
175
- /* Report a pair that cannot be brought to a common shape. Naming both
176
- shapes is the point of the message: the caller wrote two arrays that
177
- cannot be combined, and the only remedy is to say which two. */
176
+ /* Report a pair that cannot be brought to a common shape. The message
177
+ names both shapes and points to the remedy that fits the pair: when
178
+ the ndim differs, the missing axes are added with :_; when the
179
+ element counts are equal, .flatten pairs the values in the order
180
+ they lie. */
178
181
  static void
179
182
  ca_broadcast_refuse (VALUE self, VALUE other)
180
183
  {
184
+ CArray *ca, *cb;
181
185
  volatile VALUE self_s = rb_inspect(rb_funcall(self, rb_intern("shape"), 0));
182
186
  volatile VALUE other_s = rb_inspect(rb_funcall(other, rb_intern("shape"), 0));
187
+ const char *flatten_hint;
188
+ int i;
189
+
190
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
191
+ TypedData_Get_Struct(other, CArray, &carray_data_type, cb);
192
+
193
+ flatten_hint = (ca->elements == cb->elements)
194
+ ? "; to pair the values in the order they lie, use .flatten on both sides"
195
+ : "";
196
+
197
+ if (ca->ndim != cb->ndim) {
198
+ rb_raise(rb_eArgError,
199
+ "shape mismatch between operands (%s and %s): the operands "
200
+ "have different numbers of axes, and axes are not added "
201
+ "implicitly -- add size-1 axes with :_ so both have the same "
202
+ "number (x[:_, nil] makes a 1-D x a row, x[nil, :_] a column)%s",
203
+ StringValueCStr(self_s), StringValueCStr(other_s),
204
+ flatten_hint);
205
+ }
206
+
207
+ for (i = 0; i < ca->ndim; i++) {
208
+ if (ca->dim[i] != cb->dim[i] && ca->dim[i] != 1 && cb->dim[i] != 1) {
209
+ break;
210
+ }
211
+ }
183
212
  rb_raise(rb_eArgError,
184
- "shape mismatch between operands (%s and %s); shapes must "
185
- "agree, or differ only in size-1 axes with equal ndim -- use "
186
- ".flatten on both sides to operate on the values in the order "
187
- "they lie",
188
- StringValueCStr(self_s), StringValueCStr(other_s));
213
+ "shape mismatch between operands (%s and %s): axis %d has "
214
+ "sizes %lld and %lld; each axis must have the same size, or "
215
+ "size 1 on one side%s",
216
+ StringValueCStr(self_s), StringValueCStr(other_s), i,
217
+ (long long) ca->dim[i], (long long) cb->dim[i], flatten_hint);
189
218
  }
190
219
 
191
220
  void
@@ -272,7 +301,7 @@ rb_ca_broadcast_to (int argc, VALUE *argv, VALUE self)
272
301
  target_ndim = (int8_t) argc;
273
302
 
274
303
  if (target_ndim < cs->ndim) {
275
- rb_raise(rb_eRuntimeError,
304
+ rb_raise(rb_eArgError,
276
305
  "broadcast_to: target ndim %d smaller than source ndim %d",
277
306
  (int) target_ndim, (int) cs->ndim);
278
307
  }
@@ -303,6 +332,7 @@ rb_ca_broadcast_to (int argc, VALUE *argv, VALUE self)
303
332
  }
304
333
  obj = ca_wrap_struct(view);
305
334
  rb_ca_set_parent(obj, self);
335
+ CA_WRAPPER_LIFT(obj, self, cs);
306
336
  return obj;
307
337
  }
308
338
 
@@ -340,7 +370,7 @@ rb_ca_broadcast_to (int argc, VALUE *argv, VALUE self)
340
370
  else {
341
371
  /* sd == -1 (source exhausted) with dd > 1, or sd > 1 with
342
372
  dd > 1 and not equal: cannot broadcast. */
343
- rb_raise(rb_eRuntimeError,
373
+ rb_raise(rb_eArgError,
344
374
  "broadcast_to: cannot broadcast axis %d "
345
375
  "(source %s, target %lld)",
346
376
  t_idx,
@@ -351,7 +381,7 @@ rb_ca_broadcast_to (int argc, VALUE *argv, VALUE self)
351
381
  }
352
382
 
353
383
  if (s_idx >= 0) {
354
- rb_raise(rb_eRuntimeError,
384
+ rb_raise(rb_eArgError,
355
385
  "broadcast_to: %d source axes left unmatched", s_idx + 1);
356
386
  }
357
387
 
@@ -366,6 +396,8 @@ rb_ca_broadcast_to (int argc, VALUE *argv, VALUE self)
366
396
  }
367
397
  obj = ca_wrap_struct(view);
368
398
  rb_ca_set_parent(obj, self);
399
+ /* The Face stays on top, as for every view. */
400
+ CA_WRAPPER_LIFT(obj, self, cs);
369
401
  return obj;
370
402
  }
371
403