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_bincmp.c CHANGED
@@ -74,10 +74,7 @@ typedef struct CABinCmp {
74
74
  target of both left & right, also the
75
75
  kernel lookup key) */
76
76
  double eps; /* Runtime tolerance slot for IS_CLOSE /
77
- IS_EQUIV; ignored for other ops. The
78
- `eps` name is retained to keep the
79
- `__eps__` Ruby accessor stable across
80
- the dual purpose. */
77
+ IS_EQUIV; ignored for other ops. */
81
78
  int8_t sign_fix; /* 0, or the side (1 left, 2 right) of an
82
79
  int64 operand compared with a uint64 one:
83
80
  the kernel compares both as uint64 and
@@ -179,6 +176,7 @@ ca_bincmp_setup (CABinCmp *ca, CArray *left, CArray *right, uint16_t op_id,
179
176
  CABinCmp *
180
177
  ca_bincmp_new (CArray *left, CArray *right, uint16_t op_id, double eps)
181
178
  {
179
+ /* check: the setup checks nothing */
182
180
  CABinCmp *ca = (CABinCmp *) ca_array_alloc(CA_OBJ_BINCMP, left->ndim);
183
181
  ca_bincmp_setup(ca, left, right, op_id, eps);
184
182
  return ca;
@@ -226,7 +224,7 @@ ca_bincmp_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
226
224
  int8_t k;
227
225
 
228
226
  if ( dir != CA_XFER_GET ) {
229
- rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_index PUT)");
227
+ ca_refuse_read_only();
230
228
  }
231
229
 
232
230
  for ( k = ca->ndim - 1; k >= 0; k-- ) {
@@ -412,7 +410,7 @@ ca_bincmp_eval (CABinCmp *bc, const ca_lazy_req_t *req, void *data)
412
410
  "CABinCmp: kernel not implemented (op_id=%u data_type=%d)",
413
411
  (unsigned) bc->op_id, (int) bc->common_dt);
414
412
  }
415
- if ( bc->common_dt == CA_OBJECT ) {
413
+ if ( ca_op_raises_on_cell(CA_OP_KIND_BINCMP, bc->op_id, bc->common_dt) ) {
416
414
  slab_mask = ca_lazy_req_mask(req, 2, bc->operands);
417
415
  }
418
416
  fn(slab_n, slab_mask,
@@ -446,7 +444,7 @@ ca_bincmp_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
446
444
  if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
447
445
  ca_lazy_req_t req;
448
446
  if ( dir != CA_XFER_GET ) {
449
- rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_stride PUT)");
447
+ ca_refuse_read_only();
450
448
  }
451
449
  ca_lazy_req_region(&req, ap, starts, counts, strides);
452
450
  ca_bincmp_eval((CABinCmp *) ap, &req, data);
@@ -459,7 +457,7 @@ ca_bincmp_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
459
457
  {
460
458
  ca_lazy_req_t req;
461
459
  if ( dir != CA_XFER_GET ) {
462
- rb_raise(rb_eRuntimeError, "CABinCmp is read-only (xfer_addrs PUT)");
460
+ ca_refuse_read_only();
463
461
  }
464
462
  ca_lazy_req_addrs(&req, n, addrs);
465
463
  ca_bincmp_eval((CABinCmp *) ap, &req, data);
@@ -482,7 +480,7 @@ static void
482
480
  ca_bincmp_func_allocate (void *ap)
483
481
  {
484
482
  CABinCmp *ca = (CABinCmp *) ap;
485
- ca->ptr = xmalloc(ca_length(ca));
483
+ ca->ptr = ca_alloc_cells((CArray *) ca);
486
484
  }
487
485
 
488
486
  static void
@@ -499,7 +497,7 @@ ca_bincmp_func_attach (void *ap)
499
497
  int8_t k;
500
498
  ca_size_t s;
501
499
 
502
- ca->ptr = xmalloc(ca_length(ca));
500
+ ca->ptr = ca_alloc_cells((CArray *) ca);
503
501
 
504
502
  s = ca->bytes;
505
503
  for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
@@ -525,7 +523,7 @@ NORETURN(static void ca_bincmp_func_fill_data (void *ap, void *ptr));
525
523
  static void
526
524
  ca_bincmp_func_fill_data (void *ap, void *ptr)
527
525
  {
528
- rb_raise(rb_eRuntimeError, "CABinCmp is read-only (fill_data)");
526
+ ca_refuse_read_only();
529
527
  }
530
528
 
531
529
  /* mask = left.mask | right.mask, computed on each read (CAMaskOfOperands). */
@@ -580,6 +578,14 @@ rb_ca_bincmp_new (VALUE l_cary, VALUE r_cary, uint16_t op_id, double eps)
580
578
  rb_check_carray_object(r_cary);
581
579
  TypedData_Get_Struct(l_cary, CArray, &carray_data_type, l);
582
580
  TypedData_Get_Struct(r_cary, CArray, &carray_data_type, r);
581
+ /* No kernel for the type the builder cast to: refuse as the eager
582
+ comparison does, before anything is allocated. */
583
+ {
584
+ ca_bincmp_func_t fn = ca_bincmp_kernel_lookup(op_id, l->data_type);
585
+ if ( fn == NULL || fn == ca_bincmp_not_implement ) {
586
+ ca_op_refuse_unimplemented(l_cary, l->data_type, rb_eTypeError);
587
+ }
588
+ }
583
589
  ca = ca_bincmp_new(l, r, op_id, eps);
584
590
  obj = ca_wrap_struct(ca);
585
591
  rb_ca_set_parent(obj, l_cary);
@@ -641,6 +647,7 @@ rb_ca_bincmp_build (VALUE l_cary, VALUE r_cary, uint16_t op_id, double eps)
641
647
  r_resolved = ca_lazy_settle_scalar(r_resolved, r_scalar);
642
648
  }
643
649
 
650
+ ca_refuse_without_common_type(l_resolved, r_resolved);
644
651
  TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
645
652
  TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
646
653
 
@@ -711,6 +718,7 @@ rb_ca_bincmp_s_build (int argc, VALUE *argv, VALUE klass)
711
718
  double eps = 0.0;
712
719
  (void) klass;
713
720
  rb_scan_args(argc, argv, "31", &l_cary, &r_cary, &op_id_val, &eps_val);
721
+ /* fits: an operation number from the library's own table */
714
722
  op_id = (uint16_t) NUM2UINT(op_id_val);
715
723
  if ( argc >= 4 ) eps = NUM2DBL(eps_val);
716
724
  return rb_ca_bincmp_build(l_cary, r_cary, op_id, eps);
@@ -724,7 +732,8 @@ rb_ca_bincmp_trapping (VALUE self)
724
732
  {
725
733
  CABinCmp *bc;
726
734
  TypedData_Get_Struct(self, CABinCmp, &cabincmp_data_type, bc);
727
- return ( bc->common_dt == CA_OBJECT ) ? Qtrue : Qfalse;
735
+ return ca_op_raises_on_cell(CA_OP_KIND_BINCMP, bc->op_id, bc->common_dt)
736
+ ? Qtrue : Qfalse;
728
737
  }
729
738
 
730
739
  static VALUE
@@ -741,14 +750,7 @@ rb_ca_bincmp_right (VALUE self)
741
750
  return rb_ivar_get(self, rb_intern("__bincmp_right__"));
742
751
  }
743
752
 
744
- static VALUE
745
- rb_ca_bincmp_eps (VALUE self)
746
- {
747
- CABinCmp *bc;
748
- TypedData_Get_Struct(self, CABinCmp, &cabincmp_data_type, bc);
749
- return rb_float_new(bc->eps);
750
- }
751
-
753
+ #ifdef CARRAY_DEV_BUILD
752
754
  static VALUE
753
755
  rb_ca_bincmp_s_reset_scratch_counter (VALUE klass)
754
756
  {
@@ -793,6 +795,7 @@ rb_ca_bincmp_s_leaf_inplace_count (VALUE klass)
793
795
  (void) klass;
794
796
  return SIZE2NUM(ca_bincmp_leaf_inplace_count);
795
797
  }
798
+ #endif /* CARRAY_DEV_BUILD */
796
799
 
797
800
  static VALUE
798
801
  rb_ca_bincmp_s_allocate (VALUE klass)
@@ -853,8 +856,8 @@ Init_ca_obj_bincmp (void)
853
856
  rb_define_method(rb_cCABinCmp, "__trapping__", rb_ca_bincmp_trapping, 0);
854
857
  rb_define_method(rb_cCABinCmp, "__bincmp_right__",
855
858
  rb_ca_bincmp_right, 0);
856
- rb_define_method(rb_cCABinCmp, "__eps__", rb_ca_bincmp_eps, 0);
857
859
 
860
+ #ifdef CARRAY_DEV_BUILD
858
861
  rb_define_singleton_method(rb_cCABinCmp, "__reset_scratch_counter__",
859
862
  rb_ca_bincmp_s_reset_scratch_counter, 0);
860
863
  rb_define_singleton_method(rb_cCABinCmp, "__scratch_count__",
@@ -867,4 +870,5 @@ Init_ca_obj_bincmp (void)
867
870
  rb_ca_bincmp_s_reset_leaf_inplace_counter, 0);
868
871
  rb_define_singleton_method(rb_cCABinCmp, "__leaf_inplace_count__",
869
872
  rb_ca_bincmp_s_leaf_inplace_count, 0);
873
+ #endif
870
874
  }
data/ext/ca_obj_binop.c CHANGED
@@ -177,6 +177,7 @@ ca_binop_setup (CABinOp *ca, CArray *left, CArray *right, uint16_t op_id)
177
177
  CABinOp *
178
178
  ca_binop_new (CArray *left, CArray *right, uint16_t op_id)
179
179
  {
180
+ /* check: the setup checks nothing */
180
181
  CABinOp *ca = (CABinOp *) ca_array_alloc(CA_OBJ_BINOP, left->ndim);
181
182
  ca_binop_setup(ca, left, right, op_id);
182
183
  return ca;
@@ -227,7 +228,7 @@ ca_binop_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
227
228
  ca_size_t s;
228
229
 
229
230
  if ( dir != CA_XFER_GET ) {
230
- rb_raise(rb_eRuntimeError, "CABinOp is read-only (xfer_index PUT)");
231
+ ca_refuse_read_only();
231
232
  }
232
233
 
233
234
  s = ca->bytes;
@@ -322,7 +323,7 @@ ca_binop_eval (CABinOp *bo, const ca_lazy_req_t *req, void *data)
322
323
  boolean8_t *slab_mask = NULL;
323
324
  void *mscratch = NULL;
324
325
 
325
- if ( ca_binop_is_trapping(bo->op_id, bo->data_type) ) {
326
+ if ( ca_op_raises_on_cell(CA_OP_KIND_BINOP, bo->op_id, bo->data_type) ) {
326
327
  CArray *ops[2];
327
328
  ops[0] = bo->parent;
328
329
  ops[1] = bo->right;
@@ -356,7 +357,7 @@ ca_binop_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
356
357
  if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
357
358
  ca_lazy_req_t req;
358
359
  if ( dir != CA_XFER_GET ) {
359
- rb_raise(rb_eRuntimeError, "CABinOp is read-only (xfer_stride PUT)");
360
+ ca_refuse_read_only();
360
361
  }
361
362
  ca_lazy_req_region(&req, ap, starts, counts, strides);
362
363
  ca_binop_eval((CABinOp *) ap, &req, data);
@@ -370,7 +371,7 @@ ca_binop_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
370
371
  {
371
372
  ca_lazy_req_t req;
372
373
  if ( dir != CA_XFER_GET ) {
373
- rb_raise(rb_eRuntimeError, "CABinOp is read-only (xfer_addrs PUT)");
374
+ ca_refuse_read_only();
374
375
  }
375
376
  ca_lazy_req_addrs(&req, n, addrs);
376
377
  ca_binop_eval((CABinOp *) ap, &req, data);
@@ -393,15 +394,7 @@ static void
393
394
  ca_binop_func_allocate (void *ap)
394
395
  {
395
396
  CABinOp *ca = (CABinOp *) ap;
396
- ca->ptr = xmalloc(ca_length(ca));
397
- /* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
398
- soon as the view is, so it must not be handed to the GC as raw
399
- xmalloc garbage. */
400
- if ( ca->data_type == CA_OBJECT ) {
401
- VALUE *p = (VALUE *) ca->ptr;
402
- ca_size_t i;
403
- for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
404
- }
397
+ ca->ptr = ca_alloc_cells((CArray *) ca);
405
398
  }
406
399
 
407
400
  static void
@@ -418,19 +411,11 @@ ca_binop_func_attach (void *ap)
418
411
  int8_t k;
419
412
  ca_size_t s;
420
413
 
421
- ca->ptr = xmalloc(ca_length(ca));
414
+ ca->ptr = ca_alloc_cells((CArray *) ca);
422
415
 
423
416
  s = ca->bytes;
424
417
  for ( k = ca->ndim - 1; k >= 0; k-- ) { native[k] = s; s *= ca->dim[k]; }
425
418
  for ( k = 0; k < ca->ndim; k++ ) starts[k] = 0;
426
- /* CA_OBJECT cells are VALUEs and this buffer is about to be marked as
427
- soon as the view is, so it must not be handed to the GC as raw
428
- xmalloc garbage. */
429
- if ( ca->data_type == CA_OBJECT ) {
430
- VALUE *p = (VALUE *) ca->ptr;
431
- ca_size_t i;
432
- for ( i = 0; i < ca->elements; i++ ) *p++ = Qnil;
433
- }
434
419
  ca_binop_func_xfer_stride(ca, starts, ca->dim, native, ca->ptr, CA_XFER_GET);
435
420
  }
436
421
 
@@ -452,7 +437,7 @@ NORETURN(static void ca_binop_func_fill_data (void *ap, void *ptr));
452
437
  static void
453
438
  ca_binop_func_fill_data (void *ap, void *ptr)
454
439
  {
455
- rb_raise(rb_eRuntimeError, "CABinOp is read-only (fill_data)");
440
+ ca_refuse_read_only();
456
441
  }
457
442
 
458
443
  /* Build out.mask: the operands' masks ORed on each read (CAMaskOfOperands), so
@@ -584,6 +569,7 @@ rb_ca_binop_build (VALUE l_cary, VALUE r_cary, uint16_t op_id)
584
569
  r_resolved = ca_lazy_settle_scalar(r_resolved, r_scalar);
585
570
  }
586
571
 
572
+ ca_refuse_without_common_type(l_resolved, r_resolved);
587
573
  TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
588
574
  TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
589
575
 
@@ -605,8 +591,7 @@ rb_ca_binop_build (VALUE l_cary, VALUE r_cary, uint16_t op_id)
605
591
  /* No kernel for that data_type (fixlen arithmetic, ...): raise as the
606
592
  eager binop does, before a view is built over it. */
607
593
  if ( ca_binop_kernel_lookup_vv(op_id, l_in_dt) == ca_binop_not_implement ) {
608
- rb_raise(rb_eCADataTypeError,
609
- "invalid data_type for binop (not implemented)");
594
+ ca_op_refuse_unimplemented(l_cary, l_in_dt, rb_eCADataTypeError);
610
595
  }
611
596
 
612
597
  if ( l_in_dt != l->data_type ) {
@@ -694,6 +679,7 @@ rb_ca_binop_build (VALUE l_cary, VALUE r_cary, uint16_t op_id)
694
679
  static VALUE
695
680
  rb_ca_binop_s_build (VALUE klass, VALUE l_cary, VALUE r_cary, VALUE op_id_val)
696
681
  {
682
+ /* fits: an operation number from the library's own table */
697
683
  uint16_t op_id = (uint16_t) NUM2UINT(op_id_val);
698
684
  (void) klass;
699
685
  return rb_ca_binop_build(l_cary, r_cary, op_id);
@@ -708,7 +694,7 @@ rb_ca_binop_trapping (VALUE self)
708
694
  {
709
695
  CABinOp *bo;
710
696
  TypedData_Get_Struct(self, CABinOp, &cabinop_data_type, bo);
711
- return ca_binop_is_trapping(bo->op_id, bo->data_type) ? Qtrue : Qfalse;
697
+ return ca_op_raises_on_cell(CA_OP_KIND_BINOP, bo->op_id, bo->data_type) ? Qtrue : Qfalse;
712
698
  }
713
699
 
714
700
  static VALUE
@@ -729,6 +715,7 @@ rb_ca_binop_right (VALUE self)
729
715
  }
730
716
 
731
717
  /* Test instrumentation (mirrors CAMonOp counters). */
718
+ #ifdef CARRAY_DEV_BUILD
732
719
  static VALUE
733
720
  rb_ca_binop_s_reset_scratch_counter (VALUE klass)
734
721
  {
@@ -754,6 +741,7 @@ rb_ca_binop_s_materialise_count (VALUE klass)
754
741
  {
755
742
  return SIZE2NUM(ca_binop_materialise_call_count);
756
743
  }
744
+ #endif /* CARRAY_DEV_BUILD */
757
745
 
758
746
  static VALUE
759
747
  rb_ca_binop_s_allocate (VALUE klass)
@@ -834,6 +822,7 @@ Init_ca_obj_binop (void)
834
822
  rb_ca_binop_right, 0);
835
823
 
836
824
  /* Test instrumentation, not user-facing. */
825
+ #ifdef CARRAY_DEV_BUILD
837
826
  rb_define_singleton_method(rb_cCABinOp, "__reset_scratch_counter__",
838
827
  rb_ca_binop_s_reset_scratch_counter, 0);
839
828
  rb_define_singleton_method(rb_cCABinOp, "__scratch_count__",
@@ -842,4 +831,5 @@ Init_ca_obj_binop (void)
842
831
  rb_ca_binop_s_reset_materialise_counter, 0);
843
832
  rb_define_singleton_method(rb_cCABinOp, "__materialise_count__",
844
833
  rb_ca_binop_s_materialise_count, 0);
834
+ #endif
845
835
  }
@@ -93,11 +93,13 @@ ca_bitarray_setup (CABitarray *ca, CArray *parent)
93
93
  ca_size_t bitlen, elements;
94
94
 
95
95
  if ( ca_is_complex_type(parent) || ( ca_is_object_type(parent) ) ) {
96
- rb_raise(rb_eCADataTypeError, "invalid data_type for bitarray");
96
+ rb_raise(rb_eCADataTypeError, "%s: can't view the bits of a cell of %s",
97
+ ca_calling_method_name(), ca_type_name[parent->data_type]);
97
98
  }
98
99
 
99
100
  /* The bits of one byte would share that byte's one mask cell, so a bit
100
101
  view takes no masked array and holds no mask of its own. */
102
+ /* mask: the constructor asks first, before it allocates (ca == NULL) */
101
103
  if ( ca_has_mask(parent) ) {
102
104
  rb_raise(rb_eArgError,
103
105
  "bitarray: the array has a mask, which a bit view can not "
@@ -105,6 +107,9 @@ ca_bitarray_setup (CABitarray *ca, CArray *parent)
105
107
  "use .value.bitarray to read the bits without it");
106
108
  }
107
109
 
110
+ /* The bits add an axis to the parent's. */
111
+ ca_check_rank_fits(parent->ndim + 1, "bitarray");
112
+
108
113
  /* ca == NULL asks for the checks above only, so that a constructor can
109
114
  run them before it allocates. */
110
115
  if ( ca == NULL ) {
@@ -395,7 +400,7 @@ ca_bitarray_func_allocate (void *ap)
395
400
  {
396
401
  CABitarray *ca = (CABitarray *) ap;
397
402
  ca_attach(ca->parent);
398
- ca->ptr = xmalloc(ca_length(ca));
403
+ ca->ptr = ca_alloc_cells((CArray *) ca);
399
404
  }
400
405
 
401
406
  static void
@@ -403,7 +408,7 @@ ca_bitarray_func_attach (void *ap)
403
408
  {
404
409
  CABitarray *ca = (CABitarray *) ap;
405
410
  ca_attach(ca->parent);
406
- ca->ptr = xmalloc(ca_length(ca));
411
+ ca->ptr = ca_alloc_cells((CArray *) ca);
407
412
  ca_bitarray_attach(ca);
408
413
  }
409
414
 
@@ -4,10 +4,11 @@
4
4
  cell, exposing it as an unsigned-integer (or boolean, when
5
5
  bitlen == 1) CArray of the same shape as the parent.
6
6
 
7
- Byte-straddling fields are handled by loading up to 8 bytes from
8
- the parent starting at `byte_offset`, masking with `bit_mask`, and
9
- shifting by `bit_offset`. Big-endian hosts adjust byte_offset /
10
- bit_offset so the field selection is invariant to host byte order.
7
+ Bits are counted from the least significant bit of the parent cell
8
+ read as a host-order integer. Byte-straddling fields are handled
9
+ by loading up to 8 bytes, the least significant first, starting
10
+ `byte_offset` bytes above the least significant byte, masking with
11
+ `bit_mask`, and shifting by `bit_offset`.
11
12
 
12
13
  ---------------------------------------------------------------------------- */
13
14
 
@@ -32,7 +33,7 @@ typedef struct {
32
33
  ca_size_t byte_offset;
33
34
  ca_size_t bit_offset;
34
35
  uint64_t bit_mask;
35
- ca_size_t bit_start; /* original offset before endian adjustment */
36
+ ca_size_t bit_start; /* the offset of the field's lowest bit */
36
37
  ca_size_t bit_length; /* width of the field in bits */
37
38
  int8_t sign_extend; /* the field is read as a signed integer */
38
39
  } CABitfield;
@@ -85,6 +86,40 @@ static VALUE rb_cCABitfield;
85
86
  * 8-bit field starting at bit 4 of a 2-byte parent) sees the full
86
87
  * bit_mask. A dbytes-typed cast would silently truncate bit_mask
87
88
  * to `1 << (dbytes * 8)`, dropping the upper bits of the field. */
89
+ /* The `span` bytes of a cell from `lo` bytes above its least
90
+ significant byte, as an integer. On a big-endian host the least
91
+ significant byte is the last one. */
92
+ static inline uint64_t
93
+ bitfield_load (const char *cell, ca_size_t cbytes, ca_size_t lo, ca_size_t span)
94
+ {
95
+ uint64_t v = 0;
96
+ #ifdef WORDS_BIGENDIAN
97
+ ca_size_t j;
98
+ for (j = 0; j < span; j++) {
99
+ v |= (uint64_t) (uint8_t) cell[cbytes - 1 - lo - j] << (8 * j);
100
+ }
101
+ #else
102
+ (void) cbytes;
103
+ memcpy(&v, cell + lo, (size_t) span);
104
+ #endif
105
+ return v;
106
+ }
107
+
108
+ static inline void
109
+ bitfield_save (char *cell, ca_size_t cbytes, ca_size_t lo, ca_size_t span,
110
+ uint64_t v)
111
+ {
112
+ #ifdef WORDS_BIGENDIAN
113
+ ca_size_t j;
114
+ for (j = 0; j < span; j++) {
115
+ cell[cbytes - 1 - lo - j] = (char) (v >> (8 * j));
116
+ }
117
+ #else
118
+ (void) cbytes;
119
+ memcpy(cell + lo, &v, (size_t) span);
120
+ #endif
121
+ }
122
+
88
123
  static void
89
124
  bitfield_fetch(char *dst, ca_size_t dbytes,
90
125
  char *src, ca_size_t sbytes,
@@ -98,13 +133,12 @@ bitfield_fetch(char *dst, ca_size_t dbytes,
98
133
  if (span > 8) span = 8;
99
134
  ca_size_t dwrite = (dbytes > 8) ? 8 : dbytes;
100
135
  for (k = 0; k < elements; k++) {
101
- uint64_t tmp = 0;
102
- memcpy(&tmp, src + k * sbytes + byte_offset, (size_t) span);
136
+ uint64_t tmp = bitfield_load(src + k * sbytes, sbytes, byte_offset, span);
103
137
  uint64_t result = (tmp & bit_mask) >> bit_offset;
104
138
  if ( result & sign ) {
105
139
  result |= ~( ( sign << 1 ) - 1 ); /* the field's top bit is its sign */
106
140
  }
107
- memcpy(dst + k * dbytes, &result, (size_t) dwrite);
141
+ bitfield_save(dst + k * dbytes, dwrite, 0, dwrite, result);
108
142
  }
109
143
  }
110
144
 
@@ -124,12 +158,10 @@ bitfield_store(char *src, ca_size_t sbytes,
124
158
  if (span > 8) span = 8;
125
159
  ca_size_t sread = (sbytes > 8) ? 8 : sbytes;
126
160
  for (k = 0; k < elements; k++) {
127
- uint64_t srcv = 0;
128
- memcpy(&srcv, src + k * sbytes, (size_t) sread);
129
- uint64_t tmp = 0;
130
- memcpy(&tmp, dst + k * dbytes + byte_offset, (size_t) span);
161
+ uint64_t srcv = bitfield_load(src + k * sbytes, sread, 0, sread);
162
+ uint64_t tmp = bitfield_load(dst + k * dbytes, dbytes, byte_offset, span);
131
163
  tmp = (tmp & ~bit_mask) | ((srcv << bit_offset) & bit_mask);
132
- memcpy(dst + k * dbytes + byte_offset, &tmp, (size_t) span);
164
+ bitfield_save(dst + k * dbytes, dbytes, byte_offset, span, tmp);
133
165
  }
134
166
  }
135
167
 
@@ -160,14 +192,16 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
160
192
  }
161
193
 
162
194
  if ( offset < 0 || offset + bitlen -1 >= bitsize ) {
163
- rb_raise(rb_eIndexError, "invalid offset for bit field");
195
+ rb_raise(rb_eIndexError, "%s: bits out of range for a cell of %d bits",
196
+ ca_calling_method_name(), (int) bitsize);
164
197
  }
165
198
 
166
199
  /* The bits of an object cell are a reference: writing them would leave
167
200
  the cell pointing nowhere. A complex cell is refused as bitarray
168
201
  refuses it. */
169
202
  if ( ca_is_object_type(parent) || ca_is_complex_type(parent) ) {
170
- rb_raise(rb_eCADataTypeError, "invalid data_type for bitfield");
203
+ rb_raise(rb_eCADataTypeError, "%s: can't view the bits of a cell of %s",
204
+ ca_calling_method_name(), ca_type_name[parent->data_type]);
171
205
  }
172
206
 
173
207
  /* A field is read with one 8-byte load from the byte it starts in. */
@@ -205,7 +239,7 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
205
239
  data_type = CA_UINT64;
206
240
  }
207
241
 
208
- CA_CHECK_BYTES(data_type, bytes);
242
+ CA_CHECK_BYTES_GIVEN(data_type, bytes);
209
243
 
210
244
  if ( bitlen > bytes * 8 ||
211
245
  ( ( data_type == CA_BOOLEAN ) && ( bitlen > 1 ) ) ) {
@@ -213,32 +247,11 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
213
247
  (long long) bitlen, ca_type_name[data_type]);
214
248
  }
215
249
 
216
- if ( ca_endian == CA_BIG_ENDIAN ) {
217
- /* The window is placed by the narrowest width that holds the field,
218
- not by the type it is read as, which may be wider. */
219
- ca_size_t window = ( bitlen <= 8 ) ? 1 : ( bitlen <= 16 ) ? 2 :
220
- ( bitlen <= 32 ) ? 4 : 8;
221
- byte_offset = parent->bytes - offset/8 - window;
222
- bit_offset = offset % 8;
223
- bit_mask = 0;
224
- for (i=0; i<bitlen; i++) {
225
- bit_mask += 1ULL << ( bit_offset + i );
226
- }
227
- if ( byte_offset < 0 ) {
228
- for (i=0; i<-byte_offset; i++) {
229
- bit_mask = bit_mask << 8;
230
- bit_offset += 8;
231
- }
232
- byte_offset = 0;
233
- }
234
- }
235
- else {
236
- byte_offset = offset / 8;
237
- bit_offset = offset % 8;
238
- bit_mask = 0;
239
- for (i=0; i<bitlen; i++) {
240
- bit_mask += 1ULL << ( bit_offset + i );
241
- }
250
+ byte_offset = offset / 8;
251
+ bit_offset = offset % 8;
252
+ bit_mask = 0;
253
+ for (i=0; i<bitlen; i++) {
254
+ bit_mask += 1ULL << ( bit_offset + i );
242
255
  }
243
256
 
244
257
  /* ca == NULL asks for the checks above only, so that a constructor can
@@ -273,9 +286,6 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
273
286
 
274
287
  memcpy(ca->dim, parent->dim, ndim * sizeof(ca_size_t));
275
288
 
276
- if ( ca_has_mask(parent) ) {
277
- ca_create_mask(ca);
278
- }
279
289
 
280
290
  return 0;
281
291
  }
@@ -288,6 +298,7 @@ ca_bitfield_new (CArray *parent, ca_size_t offset, ca_size_t bitlen,
288
298
  ca_bitfield_setup(NULL, parent, offset, bitlen, data_type);
289
299
  ca = (CABitfield *) ca_array_alloc(CA_OBJ_BITFIELD, parent->ndim);
290
300
  ca_bitfield_setup(ca, parent, offset, bitlen, data_type);
301
+ ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
291
302
  return ca;
292
303
  }
293
304
 
@@ -452,7 +463,7 @@ ca_bitfield_func_allocate (void *ap)
452
463
  {
453
464
  CABitfield *ca = (CABitfield *) ap;
454
465
  ca_attach(ca->parent);
455
- ca->ptr = xmalloc(ca_length(ca));
466
+ ca->ptr = ca_alloc_cells((CArray *) ca);
456
467
  }
457
468
 
458
469
  static void
@@ -460,7 +471,7 @@ ca_bitfield_func_attach (void *ap)
460
471
  {
461
472
  CABitfield *ca = (CABitfield *) ap;
462
473
  ca_attach(ca->parent);
463
- ca->ptr = xmalloc(ca_length(ca));
474
+ ca->ptr = ca_alloc_cells((CArray *) ca);
464
475
  ca_bitfield_attach(ca);
465
476
  }
466
477
 
@@ -668,8 +679,10 @@ rb_ca_bitfield (int argc, VALUE *argv, VALUE self)
668
679
 
669
680
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
670
681
 
671
- if ( TYPE(rrange) == T_FIXNUM ) {
672
- offset = NUM2INT(rrange);
682
+ if ( RB_INTEGER_TYPE_P(rrange) ) {
683
+ /* A bit of a cell: negative from the last. One beyond any cell is
684
+ refused by the setup's range check, as an offset past the cell is. */
685
+ offset = RB_FIXNUM_P(rrange) ? FIX2LONG(rrange) : CA_LENGTH_MAX;
673
686
  if ( offset < 0 ) {
674
687
  offset += ca->bytes * 8;
675
688
  }
@@ -708,6 +721,7 @@ rb_ca_bitfield_initialize_copy (VALUE self, VALUE other)
708
721
  }
709
722
  ca_bitfield_setup(ca, cs->parent, cs->bit_start, cs->bit_length,
710
723
  cs->data_type);
724
+ ca_view_inherit_mask((VALUE) ca);
711
725
 
712
726
  return self;
713
727
  }
data/ext/ca_obj_block.c CHANGED
@@ -124,6 +124,12 @@ ca_block_setup (CABlock *ca, CArray *parent, int8_t ndim, ca_size_t *dim,
124
124
  }
125
125
  }
126
126
 
127
+ /* ca == NULL asks for the checks above only, so that a constructor can
128
+ run them before it allocates. */
129
+ if ( ca == NULL ) {
130
+ return 0;
131
+ }
132
+
127
133
  /* strides[k] = step[k] * Pi_{j>k} size0[j] * parent->bytes */
128
134
  suffix = parent->bytes;
129
135
  for (i = ndim - 1; i >= 0; i--) {
@@ -141,10 +147,9 @@ ca_block_setup (CABlock *ca, CArray *parent, int8_t ndim, ca_size_t *dim,
141
147
  }
142
148
  }
143
149
 
144
- /* CAREFUL: the CABlock tail (offset / start / step / count / size0)
145
- must be filled BEFORE ca_stride_setup. ca_stride_setup may auto-
146
- dispatch ca_create_mask when the parent has a mask, and
147
- ca_block_func_create_mask reads those tail fields.
150
+ /* The CABlock tail (offset / start / step / count / size0) is filled
151
+ here; ca_block_func_create_mask reads it when the constructor takes
152
+ the parent's mask (ca_view_inherit_mask) after this setup.
148
153
 
149
154
  Pool path: start/step/count/size0 already point into _pool (wired
150
155
  by ca_block_pool_init); only memcpy the values. Non-pool path:
@@ -161,10 +166,10 @@ ca_block_setup (CABlock *ca, CArray *parent, int8_t ndim, ca_size_t *dim,
161
166
  memcpy(ca->count, count, ndim * sizeof(ca_size_t));
162
167
  memcpy(ca->size0, dim, ndim * sizeof(ca_size_t));
163
168
 
164
- ca_stride_setup((CAStride *) ca, CA_OBJ_BLOCK, parent,
165
- parent->data_type, parent->bytes,
166
- ndim, count, strides,
167
- base_offset_elements * parent->bytes);
169
+ ca_stride_setup_view((CAStride *) ca, CA_OBJ_BLOCK, parent,
170
+ parent->data_type, parent->bytes,
171
+ ndim, count, strides,
172
+ base_offset_elements * parent->bytes);
168
173
 
169
174
  return 0;
170
175
  }
@@ -174,8 +179,11 @@ ca_block_new (CArray *parent, int8_t ndim, ca_size_t *dim,
174
179
  ca_size_t *start, ca_size_t *step, ca_size_t *count,
175
180
  ca_size_t offset)
176
181
  {
177
- CABlock *ca = (CABlock *) ca_array_alloc(CA_OBJ_BLOCK, ndim);
182
+ CABlock *ca;
183
+ ca_block_setup(NULL, parent, ndim, dim, start, step, count, offset);
184
+ ca = (CABlock *) ca_array_alloc(CA_OBJ_BLOCK, ndim);
178
185
  ca_block_setup(ca, parent, ndim, dim, start, step, count, offset);
186
+ ca_fill_or_free((CArray *) ca, ca_view_inherit_mask, (VALUE) ca);
179
187
  return ca;
180
188
  }
181
189
 
@@ -265,6 +273,7 @@ rb_cb_initialize_copy (VALUE self, VALUE other)
265
273
  }
266
274
  ca_block_setup(ca, cs->parent, cs->ndim, cs->size0,
267
275
  cs->start, cs->step, cs->count, cs->offset);
276
+ ca_view_inherit_mask((VALUE) ca);
268
277
  rb_ca_set_parent(self, rb_ca_parent(other));
269
278
  return self;
270
279
  }