carray 3.0.1 → 3.0.2

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +520 -0
  3. data/README.md +2 -2
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +33 -4
  6. data/ext/ca_axis_group.c +202 -96
  7. data/ext/ca_categorical_iterator.c +108 -54
  8. data/ext/ca_kernel_iterator.c +317 -51
  9. data/ext/ca_kernel_iterator.h +142 -35
  10. data/ext/ca_obj_array.c +62 -20
  11. data/ext/ca_obj_block.c +4 -4
  12. data/ext/ca_obj_const_string.c +85 -26
  13. data/ext/ca_obj_face.c +24 -0
  14. data/ext/ca_obj_face.h +15 -0
  15. data/ext/ca_obj_fixlen_string.c +18 -5
  16. data/ext/ca_obj_meld.c +123 -25
  17. data/ext/ca_obj_object.c +8 -0
  18. data/ext/ca_obj_select.c +49 -34
  19. data/ext/ca_obj_stack.c +3 -8
  20. data/ext/ca_obj_stride.c +72 -1
  21. data/ext/ca_obj_string.c +8 -4
  22. data/ext/ca_obj_window.c +8 -2
  23. data/ext/ca_op_ipower.c +1 -2
  24. data/ext/ca_rng_normal.h +42 -0
  25. data/ext/ca_rng_xoshiro256pp.h +105 -0
  26. data/ext/ca_sweep_engine.c +307 -143
  27. data/ext/ca_sweep_engine.h +26 -5
  28. data/ext/carray.h +21 -2
  29. data/ext/carray_access.c +32 -20
  30. data/ext/carray_address_basis.c +590 -0
  31. data/ext/carray_broadcast.c +3 -3
  32. data/ext/carray_call_cfunc.c +667 -483
  33. data/ext/carray_cast.c +115 -41
  34. data/ext/carray_copy.c +55 -30
  35. data/ext/carray_core.c +83 -3
  36. data/ext/carray_count.c +9 -10
  37. data/ext/carray_factorize.c +46 -25
  38. data/ext/carray_internal.h +17 -0
  39. data/ext/carray_kernels_reduce_aggregate.c +168 -0
  40. data/ext/carray_kernels_reduce_cumulative.c +270 -1
  41. data/ext/carray_kernels_reduce_extreme.c +554 -8
  42. data/ext/carray_kernels_scan.c +4 -4
  43. data/ext/carray_kernels_search.c +94 -14
  44. data/ext/carray_loop.c +7 -1
  45. data/ext/carray_mask.c +23 -8
  46. data/ext/carray_median_percentile.c +55 -0
  47. data/ext/carray_operator.c +4 -4
  48. data/ext/carray_order.c +1 -1
  49. data/ext/carray_random.c +384 -40
  50. data/ext/carray_slab.c +13 -0
  51. data/ext/carray_sort.c +20 -22
  52. data/ext/mk_call_cfunc.rb +103 -116
  53. data/ext/mkkernel.rb +297 -29
  54. data/ext/ruby_carray.c +10 -1
  55. data/ext/version.h +4 -4
  56. data/lib/carray/autoload_carray.rb +5 -3
  57. data/lib/carray/autoload_method_extension.rb +12 -0
  58. data/lib/carray/axis_group.rb +77 -0
  59. data/lib/carray/basics.rb +4 -0
  60. data/lib/carray/block_iterator.rb +92 -16
  61. data/lib/carray/categorical.rb +150 -33
  62. data/lib/carray/categorical_iterator.rb +207 -80
  63. data/lib/carray/const_string.rb +131 -27
  64. data/lib/carray/construct.rb +40 -0
  65. data/lib/carray/data_type_extension.rb +3 -0
  66. data/lib/carray/data_type_limits.rb +91 -0
  67. data/lib/carray/fixlen_string.rb +1 -1
  68. data/lib/carray/frame/csv_parser.rb +11 -4
  69. data/lib/carray/frame/frame.rb +81 -10
  70. data/lib/carray/frame/group.rb +36 -3
  71. data/lib/carray/frame/io.rb +67 -15
  72. data/lib/carray/frame/records.rb +18 -4
  73. data/lib/carray/frame/verbs.rb +14 -11
  74. data/lib/carray/inspect.rb +42 -9
  75. data/lib/carray/iterator.rb +143 -0
  76. data/lib/carray/lazy.rb +0 -37
  77. data/lib/carray/mask_gap_fill.rb +3 -1
  78. data/lib/carray/methods/discovery_along.rb +74 -0
  79. data/lib/carray/methods/factorize.rb +50 -0
  80. data/lib/carray/methods/is_in.rb +13 -2
  81. data/lib/carray/methods/locate_addr.rb +75 -2
  82. data/lib/carray/methods/mask_duplicates.rb +35 -1
  83. data/lib/carray/methods/nunique.rb +22 -1
  84. data/lib/carray/methods/repeat.rb +110 -0
  85. data/lib/carray/methods/unique.rb +41 -1
  86. data/lib/carray/rng.rb +86 -0
  87. data/lib/carray/slab_iterator.rb +58 -13
  88. data/lib/carray/string_operation_extension.rb +5 -1
  89. data/lib/carray/time.rb +18 -2
  90. data/lib/carray/window_iterator.rb +142 -20
  91. data/lib/carray.rb +2 -0
  92. data/yard-stubs/ca_obj_block.rb +2 -7
  93. data/yard-stubs/ca_obj_window.rb +10 -2
  94. data/yard-stubs/carray_access.rb +1 -1
  95. data/yard-stubs/carray_broadcast.rb +1 -1
  96. data/yard-stubs/carray_core.rb +0 -80
  97. data/yard-stubs/carray_count.rb +7 -2
  98. data/yard-stubs/carray_lazy.rb +205 -0
  99. data/yard-stubs/carray_math.rb +1486 -3
  100. data/yard-stubs/carray_median_percentile.rb +16 -2
  101. data/yard-stubs/carray_order.rb +9 -69
  102. data/yard-stubs/carray_slab.rb +9 -7
  103. data/yard-stubs/carray_sort.rb +7 -5
  104. metadata +9 -1
@@ -13,7 +13,7 @@
13
13
  * OUTPUT (fsync=='1') -> ca_attach + use ca->ptr (sync on release)
14
14
  * INPUT (fsync=='0') alias-able -> ca_attach + use ca->ptr
15
15
  * INPUT (fsync=='0') non-alias -> xmalloc + ca_xfer_all(GET)
16
- * (2) broadcast shape check (scalar collapse + n_kernel agreement)
16
+ * (2) operand pairing (scalar collapse; arrays must agree in shape)
17
17
  * (3) mask OR across INPUT operands -> m0 (xmalloc, NULL if none)
18
18
  * (4) mask propagate to OUTPUT operands (overwrite output->mask)
19
19
  * (5) caller runs the per-cell loop using base[] + stride[]
@@ -84,14 +84,20 @@ typedef struct ca_sweep_state {
84
84
  ca_size_t chunk_n_max; /* max chunk size from ca_chunk_compute_n */
85
85
  ca_size_t inner; /* product of dims except outermost (= row
86
86
  size in elements for outer-axis chunking) */
87
- int chunked_state; /* 0=pre-init, 1=active, 2=done */
87
+ int chunked_state; /* 0=pre-init, 1=active, 2=done,
88
+ 3=aborted (a read raised; resources
89
+ already given back) */
88
90
  boolean8_t *mask_scratch; /* chunk-sized staging for the per-chunk
89
91
  mask OR; NULL when no INPUT is masked */
90
92
  } ca_sweep_state_t;
91
93
 
92
- /* Validate fsync length, acquire per-op buffers, compute broadcast shape +
93
- * strides, build mask m0, propagate mask to OUTPUTs. May raise (fsync
94
- * length mismatch, shape mismatch). */
94
+ /* Validate fsync length, pair the operands (shape), acquire per-op
95
+ * buffers, build mask m0, propagate mask to OUTPUTs. May raise: refusals
96
+ * (fsync length, shape mismatch, masked INPUT in a NO_MASK form) before
97
+ * anything is held, and a raising operand read after -- in which case
98
+ * everything acquired so far is detached / freed before the raise
99
+ * propagates, so the caller must not call release. The chunked path
100
+ * does the same for acquire_chunked and each ca_sweep_next_chunk. */
95
101
  void ca_sweep_acquire (ca_sweep_state_t *st);
96
102
 
97
103
  /* Reverse-order release: sync OUTPUTs, detach attached / xfree owned_buf,
@@ -99,6 +105,21 @@ void ca_sweep_acquire (ca_sweep_state_t *st);
99
105
  * state without re-initializing the caller-owned arrays. */
100
106
  void ca_sweep_release (ca_sweep_state_t *st);
101
107
 
108
+ /* Run walk(arg) -- the caller's loop over the acquired state -- and then
109
+ * release. If walk raises (a callback refusing a value), everything the
110
+ * engine holds is detached / freed without syncing before the raise
111
+ * propagates. Use in place of calling ca_sweep_release /
112
+ * ca_sweep_release_chunked yourself whenever the loop can raise. The
113
+ * chunked walk calls ca_sweep_next_chunk itself. */
114
+ void ca_sweep_run (ca_sweep_state_t *st, VALUE (*walk)(VALUE), VALUE arg);
115
+ void ca_sweep_run_chunked (ca_sweep_state_t *st, VALUE (*walk)(VALUE), VALUE arg);
116
+
117
+ /* Shape pairing shared with rb_ca_template_n: non-zero when a and b have
118
+ * the same ndim and dims; the refusal raises ArgumentError naming both
119
+ * shapes. */
120
+ int ca_sweep_same_shape (CArray *a, CArray *b);
121
+ NORETURN(void ca_sweep_refuse_shapes (CArray *a, CArray *b));
122
+
102
123
  /* Strict full-shape equality check used by INOUT macros (AC5: silent-
103
124
  * corruption seam prevention). Raises if ndim differs or any dim[k]
104
125
  * differs. Returns void; raises on mismatch. */
data/ext/carray.h CHANGED
@@ -922,7 +922,6 @@ extern const rb_data_type_t careduce_data_type;
922
922
  extern const rb_data_type_t carefer_data_type;
923
923
  extern const rb_data_type_t caselect_data_type;
924
924
  extern const rb_data_type_t cashift_data_type;
925
- extern const rb_data_type_t caunboundrepeat_data_type;
926
925
  extern const rb_data_type_t cawindow_data_type;
927
926
 
928
927
  extern const rb_data_type_t carray_mask_data_type;
@@ -933,7 +932,6 @@ extern const rb_data_type_t careduce_mask_data_type;
933
932
  extern const rb_data_type_t carefer_mask_data_type;
934
933
  extern const rb_data_type_t caselect_mask_data_type;
935
934
  extern const rb_data_type_t cashift_mask_data_type;
936
- extern const rb_data_type_t caunboundrepeat_mask_data_type;
937
935
  extern const rb_data_type_t cawindow_mask_data_type;
938
936
 
939
937
  /* -------------------------------------------------------------------- */
@@ -1476,6 +1474,27 @@ int ca_is_valid_index (void *ap, ca_size_t *idx);
1476
1474
 
1477
1475
  /* API : allocate, attach, update, sync, detach */
1478
1476
 
1477
+ /* Attach lifecycle contract (R1-R5). Ownership-based, and NOT transitive.
1478
+ This block is the canonical statement of the contract; the other documents
1479
+ copy it. guides/devel/04_attach_lifecycle.md discusses it at length.
1480
+
1481
+ R1 (validity) ca_attach(x) makes x->ptr only valid. It says nothing
1482
+ about any other array.
1483
+ R2 (no transit) Attaching a child does not attach its parent. An
1484
+ implementation may do so as an internal optimisation;
1485
+ never rely on it.
1486
+ R3 (necessity) To touch ca->parent->ptr, call ca_attach(ca->parent)
1487
+ yourself.
1488
+ R4 (ordering) Attaching both parent and child: open parent -> child,
1489
+ close child -> parent, sync in attach order. Symmetric
1490
+ nesting stays correct when a view double-attaches
1491
+ internally (views carry an attach refcount; entities do
1492
+ not).
1493
+ R5 (traffic) Attach hands you a buffer, not a live array. Use x->ptr;
1494
+ a view derived from x composes past the buffer to the
1495
+ root.
1496
+ */
1497
+
1479
1498
  void ca_allocate (void *ap);
1480
1499
  void ca_attach (void *ca);
1481
1500
  void ca_update (void *ca);
data/ext/carray_access.c CHANGED
@@ -19,7 +19,7 @@ static ID id_begin, id_end, id_excl_end;
19
19
  #define RANGE_EXCL(r) (rb_funcall(r, id_excl_end, 0))
20
20
 
21
21
  static ID id_to_ca;
22
- static VALUE sym_star, sym_perc, sym_under, sym_gt, sym_tilde;
22
+ static VALUE sym_perc, sym_under, sym_gt, sym_tilde;
23
23
  static VALUE S_CAInfo;
24
24
 
25
25
  VALUE
@@ -1089,11 +1089,8 @@ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
1089
1089
  already-a-Face case (some builders lift their own result) is handled
1090
1090
  inside ca_wrapper_lift.
1091
1091
 
1092
- Every CA_REG_* branch converges here, so this one line covers all of
1093
- them -- but not every index form: `a[:*, nil]` builds a CAUnboundRepeat,
1094
- whose shape stays open until an operand binds it, and a marker copies
1095
- shape at construction. ca_wrapper_lift refuses that one, in one place,
1096
- because `unbound_repeat` reaches it by a second route. */
1092
+ Every CA_REG_* branch converges here, so this one line covers every
1093
+ index form that returns a CArray. */
1097
1094
  CA_WRAPPER_LIFT(obj, self, ca);
1098
1095
 
1099
1096
  return obj;
@@ -1107,6 +1104,8 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
1107
1104
  {
1108
1105
  int i;
1109
1106
  int nclean = 0;
1107
+ int nscalar = 0;
1108
+ int nunder = 0;
1110
1109
  VALUE clean[CA_RANK_MAX];
1111
1110
  volatile VALUE base;
1112
1111
  ca_size_t final_dims[CA_RANK_MAX];
@@ -1118,11 +1117,17 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
1118
1117
  /* Build clean argv (strip :_); reject disjoint sigils + rubber dim. */
1119
1118
  for (i = 0; i < argc; i++) {
1120
1119
  VALUE a = argv[i];
1121
- if ( a == sym_under ) continue;
1122
- if ( a == sym_gt || a == sym_star || a == sym_perc
1120
+ if ( a == sym_under ) {
1121
+ nunder++;
1122
+ continue;
1123
+ }
1124
+ if ( FIXNUM_P(a) || RB_TYPE_P(a, T_BIGNUM) ) {
1125
+ nscalar++;
1126
+ }
1127
+ if ( a == sym_gt || a == sym_perc
1123
1128
  || a == Qfalse || a == sym_tilde ) {
1124
1129
  rb_raise(rb_eIndexError,
1125
- "newaxis (:_) cannot be combined with :>, :*, :%%, "
1130
+ "newaxis (:_) cannot be combined with :>, :%%, "
1126
1131
  "or rubber dim (false / :~)");
1127
1132
  }
1128
1133
  if ( nclean >= CA_RANK_MAX ) {
@@ -1140,18 +1145,26 @@ rb_ca_fetch_newaxis (int argc, VALUE *argv, VALUE self, CArray *ca)
1140
1145
  nclean, (int) ca->ndim);
1141
1146
  }
1142
1147
 
1143
- base = rb_ca_fetch_method(nclean, clean, self);
1144
-
1145
- /* Degenerate: all real axes scalar -> base is a scalar element, not a
1146
- CArray. Out of scope (rare + degenerate); user indexes the element
1147
- and reshapes explicitly. IndexError keeps it catchable + consistent
1148
- with the other newaxis rejects. */
1149
- if ( ! rb_obj_is_kind_of(base, rb_cCArray) ) {
1150
- rb_raise(rb_eIndexError,
1151
- "newaxis (:_) needs at least one non-scalar axis "
1152
- "(all-scalar indexing yields a single element)");
1148
+ /* Every real axis indexed by a scalar: fetching `clean` would yield the
1149
+ element itself, and there would be nothing left to reshape. Ask for a
1150
+ length-1 block on each axis instead, so the base stays a CArray and the
1151
+ result is a view into self. The result carries exactly the axes :_ asked
1152
+ for, all of length 1 -- an operand that states rank nunder and one
1153
+ element, which is what the shape rules then hold it to. */
1154
+ if ( nscalar == nclean ) {
1155
+ VALUE blocks[CA_RANK_MAX];
1156
+ for (i = 0; i < nclean; i++) {
1157
+ blocks[i] = rb_assoc_new(clean[i], INT2FIX(1));
1158
+ }
1159
+ base = rb_ca_fetch_method(nclean, blocks, self);
1160
+ for (i = 0; i < nunder; i++) {
1161
+ dim_argv[i] = INT2FIX(1);
1162
+ }
1163
+ return rb_ca_reshape(nunder, dim_argv, base);
1153
1164
  }
1154
1165
 
1166
+ base = rb_ca_fetch_method(nclean, clean, self);
1167
+
1155
1168
  TypedData_Get_Struct(base, CArray, &carray_data_type, cb);
1156
1169
 
1157
1170
  /* Reconstruct final shape: walk original argv. :_ -> size-1, scalar
@@ -2076,7 +2089,6 @@ Init_carray_access (void)
2076
2089
  id_excl_end = rb_intern("exclude_end?");
2077
2090
 
2078
2091
  id_to_ca = rb_intern("to_ca");
2079
- sym_star = ID2SYM(rb_intern("*"));
2080
2092
  sym_perc = ID2SYM(rb_intern("%"));
2081
2093
  sym_under = ID2SYM(rb_intern("_"));
2082
2094
  sym_gt = ID2SYM(rb_intern(">"));