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
@@ -14,7 +14,7 @@
14
14
 
15
15
  #include "ruby.h"
16
16
  #include "carray.h"
17
- #include "carray_internal.h" /* ca_axis_integer */
17
+ #include "carray_internal.h" /* ca_normalize_axis_arg */
18
18
  #include "ca_kernel_iterator.h" /* CA_FOR_EACH_FIBER_INOUT */
19
19
  #include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE */
20
20
  #include "ca_sort_kernels.h" /* ca_partition_quick_* / ca_partition_nan_* */
@@ -155,7 +155,7 @@ rb_ca_partition_copy_c (VALUE self, VALUE vkth, VALUE vaxis)
155
155
  }
156
156
 
157
157
  /* Normalize axis. */
158
- int axis = rb_ca_normalize_axis_for_ndim(ca_axis_integer(vaxis, NULL), cat->ndim, NULL);
158
+ int axis = ca_normalize_axis_arg(vaxis, cat->ndim, NULL);
159
159
 
160
160
  ca_size_t fiber_n = cat->dim[axis];
161
161
  ca_size_t kth = partition_kth(fiber_n, vkth);
@@ -166,14 +166,9 @@ rb_ca_partition_copy_c (VALUE self, VALUE vkth, VALUE vaxis)
166
166
  * but the cost is the per-pair rb_funcall, not an architectural
167
167
  * penalty. */
168
168
  if ( cat->data_type == CA_OBJECT ) {
169
- static ID id_partition_index_ki = 0;
170
- static ID id_take_along_axis = 0;
171
- static ID id_axis_sym = 0;
172
- if ( !id_partition_index_ki ) {
173
- id_partition_index_ki = rb_intern("partition_index_ki");
174
- id_take_along_axis = rb_intern("take_along_axis");
175
- id_axis_sym = rb_intern("axis");
176
- }
169
+ ID id_partition_index_ki = rb_intern("partition_index_ki");
170
+ ID id_take_along_axis = rb_intern("take_along_axis");
171
+ ID id_axis_sym = rb_intern("axis");
177
172
  VALUE idx = rb_funcall(target, id_partition_index_ki, 2,
178
173
  INT2NUM(axis), SIZET2NUM(kth));
179
174
  VALUE kw = rb_hash_new();
@@ -297,8 +292,7 @@ rb_ca_partition_copy_c_mp (VALUE self, VALUE vkth, VALUE vaxis, int masked_last)
297
292
  /* Check axis and kth here, so a bad one is reported as partition_copy's
298
293
  rather than as the partition this delegates to. */
299
294
  {
300
- int axis = rb_ca_normalize_axis_for_ndim(ca_axis_integer(vaxis, NULL),
301
- ca->ndim, NULL);
295
+ int axis = ca_normalize_axis_arg(vaxis, ca->ndim, NULL);
302
296
  partition_kth(ca->dim[axis], vkth);
303
297
  }
304
298
  /* rb_ca_partitioned_view's rb_scan_args "1:" pattern needs call-frame
@@ -337,26 +331,30 @@ rb_ca_partition_copy_body (int argc, VALUE *argv, VALUE self)
337
331
  int masked_last = NIL_P(vmasked_position) ? 1
338
332
  : ca_symbol_choice(vmasked_position, "masked_position", "first", "last", NULL);
339
333
 
340
- /* Face gate, the same policy as the sort family's: a fixlen storage
341
- partitions by memcmp, a numeric storage only when ORDERABLE (its order
342
- is the surface order). The selection runs on the storage and the Face
343
- is put back on the result. Without this the surface fixlen bytes were
344
- selected by memcmp, which is not the order of a little-endian integer
345
- (CATime) and not the label order of a code (CACategorical). */
334
+ /* Face gate, the same policy as the sort family's. An ORDERABLE Face
335
+ is selected on its storage and put back on the result. A Face that
336
+ orders by itself (ca_face_orders_by_itself) is partitioned by the view,
337
+ which orders by that order (ca_order_key), and its copy is the answer.
338
+ Any other Face raises. */
346
339
  volatile VALUE face = Qnil;
347
340
  {
348
341
  CArray *ca;
349
342
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
350
343
  if ( ca_is_face(ca) ) {
351
- VALUE st = rb_ca_strip_face_value(self);
352
- CArray *sc;
353
- TypedData_Get_Struct(st, CArray, &carray_data_type, sc);
354
- if ( sc->data_type != CA_FIXLEN
355
- && ! ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
356
- ca_face_refuse_order("partition_copy", self, "order");
344
+ if ( ca_face_orders_by_itself(self) ) {
345
+ VALUE kw = rb_hash_new();
346
+ VALUE pv_argv[2];
347
+ rb_hash_aset(kw, ID2SYM(rb_intern("axis")), vaxis);
348
+ rb_hash_aset(kw, ID2SYM(rb_intern("masked_position")),
349
+ masked_last ? ID2SYM(rb_intern("last")) : ID2SYM(rb_intern("first")));
350
+ pv_argv[0] = vkth;
351
+ pv_argv[1] = kw;
352
+ return rb_ca_copy(rb_funcallv_kw(self, rb_intern("partition"), 2, pv_argv,
353
+ RB_PASS_KEYWORDS));
357
354
  }
355
+ ca_face_require_orderable(self, "partition_copy", "order");
358
356
  face = self;
359
- self = st;
357
+ self = rb_ca_strip_face_value(self);
360
358
  }
361
359
  }
362
360
 
@@ -418,7 +416,8 @@ rb_ca_partitioned_view (int argc, VALUE *argv, VALUE self)
418
416
  suitable for direct ca_remap_new wrap; the remap gather carries
419
417
  target's mask bits through so masked cells stay masked at their
420
418
  clustered position (no extra output-mask step needed here). */
421
- volatile VALUE sigma_addr = rb_ca_partition_addr_ki_mp(target, vaxis, vkth, masked_last);
419
+ volatile VALUE sigma_addr =
420
+ rb_ca_partition_addr_ki_mp(target, vaxis, vkth, masked_last);
422
421
  {
423
422
  VALUE obj = rb_ca_remap_new(target, sigma_addr);
424
423
  CA_FACE_LIFT_IF_FACE(obj, self, ca);
@@ -443,7 +442,9 @@ static VALUE
443
442
  rb_ca_partition_copy (int argc, VALUE *argv, VALUE self)
444
443
  {
445
444
  pc_call_t c = { argc, argv, self };
446
- return ca_answer_as_caller(pc_answer_body, (VALUE) &c);
445
+ VALUE out = ca_answer_as_caller(pc_answer_body, (VALUE) &c);
446
+ rb_ca_inherit_attr(out, self);
447
+ return out;
447
448
  }
448
449
 
449
450
  void
data/ext/carray_random.c CHANGED
@@ -88,16 +88,18 @@ typedef struct {
88
88
  long low_long;
89
89
  unsigned long limit;
90
90
  int axis; /* shuffle!: -1 = all cells */
91
+ CArray *mask; /* shuffle!: self's mask, moved with the values */
91
92
  } ca_random_ctx_t;
92
93
 
93
94
  static void
94
95
  ca_random_run (ca_random_ctx_t *c, VALUE rng, VALUE (*fill)(VALUE))
95
96
  {
96
- CArray *list[2];
97
+ CArray *list[3];
97
98
  ca_rng_resolve(rng, &c->source);
98
99
  list[0] = c->ca;
99
100
  list[1] = c->source.state;
100
- ca_attach_window(2, list, "ww", fill, (VALUE) c);
101
+ list[2] = c->mask;
102
+ ca_attach_window(c->mask ? 3 : 2, list, "www", fill, (VALUE) c);
101
103
  }
102
104
 
103
105
  /* The state is attached once the window is open. */
@@ -163,7 +165,7 @@ ca_random_bang_fill (VALUE arg)
163
165
  ca_rng_bind(&c->source);
164
166
  switch (ca->data_type) {
165
167
  case CA_FLOAT64: {
166
- double *p = (double *)ca->ptr;
168
+ CA_U(double) *p = (CA_U(double) *)ca->ptr;
167
169
  if (is_default) {
168
170
  for (i = 0; i < n; i++)
169
171
  p[i] = ca_random_real(&c->source);
@@ -175,7 +177,7 @@ ca_random_bang_fill (VALUE arg)
175
177
  break;
176
178
  }
177
179
  case CA_FLOAT32: {
178
- float *p = (float *)ca->ptr;
180
+ CA_U(float) *p = (CA_U(float) *)ca->ptr;
179
181
  if (is_default) {
180
182
  for (i = 0; i < n; i++)
181
183
  p[i] = (float)ca_random_real(&c->source);
@@ -187,7 +189,7 @@ ca_random_bang_fill (VALUE arg)
187
189
  break;
188
190
  }
189
191
  case CA_CMPLX128: {
190
- double complex *p = (double complex *)ca->ptr;
192
+ ca_u_cmplx128_t *p = (ca_u_cmplx128_t *)ca->ptr;
191
193
  if (is_default) {
192
194
  for (i = 0; i < n; i++)
193
195
  p[i] = ca_random_real(&c->source) + ca_random_real(&c->source) * I;
@@ -200,7 +202,7 @@ ca_random_bang_fill (VALUE arg)
200
202
  break;
201
203
  }
202
204
  case CA_CMPLX64: {
203
- float complex *p = (float complex *)ca->ptr;
205
+ ca_u_cmplx64_t *p = (ca_u_cmplx64_t *)ca->ptr;
204
206
  if (is_default) {
205
207
  for (i = 0; i < n; i++)
206
208
  p[i] = (float)ca_random_real(&c->source) + (float)ca_random_real(&c->source) * I;
@@ -240,37 +242,37 @@ ca_random_bang_fill (VALUE arg)
240
242
  break;
241
243
  }
242
244
  case CA_INT16: {
243
- int16_t *p = (int16_t *)ca->ptr;
245
+ CA_U(int16_t) *p = (CA_U(int16_t) *)ca->ptr;
244
246
  for (i = 0; i < n; i++)
245
247
  p[i] = (int16_t)(low_long + ca_random_ulong_limited(&c->source, limit));
246
248
  break;
247
249
  }
248
250
  case CA_UINT16: {
249
- uint16_t *p = (uint16_t *)ca->ptr;
251
+ CA_U(uint16_t) *p = (CA_U(uint16_t) *)ca->ptr;
250
252
  for (i = 0; i < n; i++)
251
253
  p[i] = (uint16_t)(low_long + ca_random_ulong_limited(&c->source, limit));
252
254
  break;
253
255
  }
254
256
  case CA_INT32: {
255
- int32_t *p = (int32_t *)ca->ptr;
257
+ CA_U(int32_t) *p = (CA_U(int32_t) *)ca->ptr;
256
258
  for (i = 0; i < n; i++)
257
259
  p[i] = (int32_t)(low_long + ca_random_ulong_limited(&c->source, limit));
258
260
  break;
259
261
  }
260
262
  case CA_UINT32: {
261
- uint32_t *p = (uint32_t *)ca->ptr;
263
+ CA_U(uint32_t) *p = (CA_U(uint32_t) *)ca->ptr;
262
264
  for (i = 0; i < n; i++)
263
265
  p[i] = (uint32_t)(low_long + ca_random_ulong_limited(&c->source, limit));
264
266
  break;
265
267
  }
266
268
  case CA_INT64: {
267
- int64_t *p = (int64_t *)ca->ptr;
269
+ CA_U(int64_t) *p = (CA_U(int64_t) *)ca->ptr;
268
270
  for (i = 0; i < n; i++)
269
271
  p[i] = (int64_t)(low_long + ca_random_ulong_limited(&c->source, limit));
270
272
  break;
271
273
  }
272
274
  case CA_UINT64: {
273
- uint64_t *p = (uint64_t *)ca->ptr;
275
+ CA_U(uint64_t) *p = (CA_U(uint64_t) *)ca->ptr;
274
276
  for (i = 0; i < n; i++)
275
277
  p[i] = (uint64_t)(low_long + ca_random_ulong_limited(&c->source, limit));
276
278
  break;
@@ -359,19 +361,55 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
359
361
  int is_integer_type = (ca->data_type >= CA_INT8
360
362
  && ca->data_type <= CA_UINT64);
361
363
  if (is_integer_type) {
362
- low_long = NUM2LONG(low_val);
363
- high_long = NUM2LONG(high_val);
364
- if (high_is_closed) high_long += 1;
365
- if (low_long >= high_long) {
364
+ /* The bounds stay Ruby Integers until they are known to fit: the
365
+ last value drawn is high (closed) or high - 1, and every value
366
+ from low to it must be one of the type's. The draw is low plus
367
+ an offset up to last - low, which holds even the whole int64 or
368
+ uint64 range. */
369
+ VALUE last, type_min, type_max;
370
+ if (!RB_INTEGER_TYPE_P(low_val) || !RB_INTEGER_TYPE_P(high_val)) {
371
+ rb_raise(rb_eTypeError,
372
+ "random: an integer array takes Integer bounds "
373
+ "(got %"PRIsVALUE", %"PRIsVALUE")",
374
+ rb_inspect(low_val), rb_inspect(high_val));
375
+ }
376
+ last = high_is_closed ? high_val
377
+ : rb_funcall(high_val, '-', 1, INT2FIX(1));
378
+ if (RTEST(rb_funcall(low_val, '>', 1, last))) {
366
379
  rb_raise(rb_eArgError,
367
380
  "random: low must be less than high "
368
- "(got low=%ld, high=%ld)",
369
- low_long, high_long);
381
+ "(got low=%"PRIsVALUE", high=%"PRIsVALUE")",
382
+ low_val, high_val);
383
+ }
384
+ switch (ca->data_type) {
385
+ case CA_INT8: type_min = INT2FIX(INT8_MIN); type_max = INT2FIX(INT8_MAX); break;
386
+ case CA_UINT8: type_min = INT2FIX(0); type_max = INT2FIX(UINT8_MAX); break;
387
+ case CA_INT16: type_min = INT2FIX(INT16_MIN); type_max = INT2FIX(INT16_MAX); break;
388
+ case CA_UINT16: type_min = INT2FIX(0); type_max = INT2FIX(UINT16_MAX); break;
389
+ case CA_INT32: type_min = LL2NUM(INT32_MIN); type_max = LL2NUM(INT32_MAX); break;
390
+ case CA_UINT32: type_min = INT2FIX(0); type_max = ULL2NUM(UINT32_MAX); break;
391
+ case CA_INT64: type_min = LL2NUM(INT64_MIN); type_max = LL2NUM(INT64_MAX); break;
392
+ default: type_min = INT2FIX(0); type_max = ULL2NUM(UINT64_MAX); break;
393
+ }
394
+ if (RTEST(rb_funcall(low_val, '<', 1, type_min)) ||
395
+ RTEST(rb_funcall(last, '>', 1, type_max))) {
396
+ rb_raise(rb_eRangeError,
397
+ "random: the values %"PRIsVALUE"..%"PRIsVALUE" are not all %s "
398
+ "(%"PRIsVALUE"..%"PRIsVALUE")",
399
+ low_val, last, ca_type_name[ca->data_type], type_min, type_max);
370
400
  }
371
- limit = (unsigned long)(high_long - low_long) - 1;
401
+ low_long = RTEST(rb_funcall(low_val, '<', 1, INT2FIX(0)))
402
+ ? (long) NUM2LL(low_val) : (long) NUM2ULL(low_val);
403
+ limit = (unsigned long) NUM2ULL(rb_funcall(last, '-', 1, low_val));
404
+ (void) high_long;
372
405
  } else {
373
406
  low_dbl = NUM2DBL(low_val);
374
407
  high_dbl = NUM2DBL(high_val);
408
+ if (!isfinite(low_dbl) || !isfinite(high_dbl)) {
409
+ rb_raise(rb_eArgError,
410
+ "random: the bounds are finite numbers "
411
+ "(got low=%g, high=%g)", low_dbl, high_dbl);
412
+ }
375
413
  if (low_dbl >= high_dbl) {
376
414
  rb_raise(rb_eArgError,
377
415
  "random: low must be less than high "
@@ -382,7 +420,7 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
382
420
  }
383
421
 
384
422
  {
385
- ca_random_ctx_t c;
423
+ ca_random_ctx_t c = { 0 };
386
424
  c.ca = ca;
387
425
  c.n = ca->elements;
388
426
  c.is_default = is_default;
@@ -392,6 +430,8 @@ rb_ca_random_bang(int argc, VALUE *argv, VALUE self)
392
430
  c.limit = limit;
393
431
  ca_random_run(&c, rng, ca_random_bang_fill);
394
432
  }
433
+ /* Every cell now holds a value, as after seq! or fill. */
434
+ ca_clear_mask(ca);
395
435
  return self;
396
436
  }
397
437
 
@@ -443,19 +483,19 @@ ca_randomn_bang_fill (VALUE arg)
443
483
  if (c->source.kind == CA_RNG_OWN) {
444
484
  switch (ca->data_type) {
445
485
  case CA_FLOAT64: {
446
- double *p = (double *)ca->ptr;
486
+ CA_U(double) *p = (CA_U(double) *)ca->ptr;
447
487
  for (i = 0; i < n; i++)
448
488
  p[i] = ca_random_normal(&c->source);
449
489
  break;
450
490
  }
451
491
  case CA_FLOAT32: {
452
- float *p = (float *)ca->ptr;
492
+ CA_U(float) *p = (CA_U(float) *)ca->ptr;
453
493
  for (i = 0; i < n; i++)
454
494
  p[i] = (float) ca_random_normal(&c->source);
455
495
  break;
456
496
  }
457
497
  case CA_CMPLX128: {
458
- double complex *p = (double complex *)ca->ptr;
498
+ ca_u_cmplx128_t *p = (ca_u_cmplx128_t *)ca->ptr;
459
499
  for (i = 0; i < n; i++) {
460
500
  /* Into locals first: C does not say which order a call's
461
501
  arguments are evaluated in, and these two advance a state. */
@@ -466,7 +506,7 @@ ca_randomn_bang_fill (VALUE arg)
466
506
  break;
467
507
  }
468
508
  case CA_CMPLX64: {
469
- float complex *p = (float complex *)ca->ptr;
509
+ ca_u_cmplx64_t *p = (ca_u_cmplx64_t *)ca->ptr;
470
510
  for (i = 0; i < n; i++) {
471
511
  double re = ca_random_normal(&c->source);
472
512
  double im = ca_random_normal(&c->source);
@@ -482,7 +522,7 @@ ca_randomn_bang_fill (VALUE arg)
482
522
 
483
523
  switch (ca->data_type) {
484
524
  case CA_FLOAT64: {
485
- double *p = (double *)ca->ptr;
525
+ CA_U(double) *p = (CA_U(double) *)ca->ptr;
486
526
  ca_size_t pairs = n / 2;
487
527
  for (i = 0; i < pairs; i++) {
488
528
  box_muller_pair(&c->source, &p[2*i], &p[2*i+1]);
@@ -495,7 +535,7 @@ ca_randomn_bang_fill (VALUE arg)
495
535
  break;
496
536
  }
497
537
  case CA_FLOAT32: {
498
- float *p = (float *)ca->ptr;
538
+ CA_U(float) *p = (CA_U(float) *)ca->ptr;
499
539
  ca_size_t pairs = n / 2;
500
540
  for (i = 0; i < pairs; i++) {
501
541
  double r1, r2;
@@ -511,7 +551,7 @@ ca_randomn_bang_fill (VALUE arg)
511
551
  break;
512
552
  }
513
553
  case CA_CMPLX128: {
514
- double complex *p = (double complex *)ca->ptr;
554
+ ca_u_cmplx128_t *p = (ca_u_cmplx128_t *)ca->ptr;
515
555
  for (i = 0; i < n; i++) {
516
556
  double r1, r2;
517
557
  box_muller_pair(&c->source, &r1, &r2);
@@ -520,7 +560,7 @@ ca_randomn_bang_fill (VALUE arg)
520
560
  break;
521
561
  }
522
562
  case CA_CMPLX64: {
523
- float complex *p = (float complex *)ca->ptr;
563
+ ca_u_cmplx64_t *p = (ca_u_cmplx64_t *)ca->ptr;
524
564
  for (i = 0; i < n; i++) {
525
565
  double r1, r2;
526
566
  box_muller_pair(&c->source, &r1, &r2);
@@ -560,11 +600,13 @@ rb_ca_randomn_bang(int argc, VALUE *argv, VALUE self)
560
600
  }
561
601
 
562
602
  {
563
- ca_random_ctx_t c;
603
+ ca_random_ctx_t c = { 0 };
564
604
  c.ca = ca;
565
605
  c.n = ca->elements;
566
606
  ca_random_run(&c, rng, ca_randomn_bang_fill);
567
607
  }
608
+ /* Every cell now holds a value, as after seq! or fill. */
609
+ ca_clear_mask(ca);
568
610
  return self;
569
611
  }
570
612
 
@@ -600,12 +642,16 @@ ca_shuffle_bang_fill (VALUE arg)
600
642
  ca_size_t elem_bytes = ca->bytes;
601
643
  char *tmp = ALLOCV_N(char, tmp_holder, elem_bytes);
602
644
  char *p = ca->ptr;
645
+ char *m = c->mask ? c->mask->ptr : NULL;
603
646
 
604
647
  n = ca->elements;
605
648
  for (ca_size_t i = n - 1; i > 0; i--) {
606
649
  unsigned long j = ca_random_ulong_limited(&c->source, (unsigned long)i);
607
650
  if ((ca_size_t)j != i) {
608
651
  swap_chunks(p + i * elem_bytes, p + j * elem_bytes, elem_bytes, tmp);
652
+ if ( m ) {
653
+ char b = m[i]; m[i] = m[j]; m[j] = b;
654
+ }
609
655
  }
610
656
  }
611
657
  ALLOCV_END(tmp_holder);
@@ -630,12 +676,16 @@ ca_shuffle_bang_fill (VALUE arg)
630
676
 
631
677
  for (ca_size_t o = 0; o < outer; o++) {
632
678
  char *base = ca->ptr + o * stride;
679
+ char *mbase = c->mask ? c->mask->ptr + o * n * inner : NULL;
633
680
  for (ca_size_t i = n - 1; i > 0; i--) {
634
681
  unsigned long j = ca_random_ulong_limited(&c->source, (unsigned long)i);
635
682
  if ((ca_size_t)j != i) {
636
683
  swap_chunks(base + i * chunk_bytes,
637
684
  base + j * chunk_bytes,
638
685
  chunk_bytes, tmp);
686
+ if ( mbase ) {
687
+ swap_chunks(mbase + i * inner, mbase + j * inner, inner, tmp);
688
+ }
639
689
  }
640
690
  }
641
691
  }
@@ -650,7 +700,7 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
650
700
  CArray *ca;
651
701
  VALUE opts = Qnil, v_axis = Qnil;
652
702
  int axis = -1;
653
- ca_random_ctx_t c;
703
+ ca_random_ctx_t c = { 0 };
654
704
 
655
705
  rb_scan_args(argc, argv, "0:", &opts);
656
706
  VALUE rng = Qnil;
@@ -662,7 +712,7 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
662
712
  if (ca->elements <= 1) return self;
663
713
 
664
714
  if (!NIL_P(v_axis)) {
665
- axis = rb_ca_normalize_axis_for_ndim(ca_axis_integer(v_axis, NULL), ca->ndim, NULL);
715
+ axis = ca_normalize_axis_arg(v_axis, ca->ndim, NULL);
666
716
  if (ca->dim[axis] <= 1) {
667
717
  return self;
668
718
  }
@@ -670,6 +720,10 @@ rb_ca_shuffle_bang(int argc, VALUE *argv, VALUE self)
670
720
 
671
721
  c.ca = ca;
672
722
  c.axis = axis;
723
+ /* The mask moves with the values: a masked cell stays masked wherever
724
+ it lands. */
725
+ ca_update_mask(ca);
726
+ c.mask = ca->mask;
673
727
  ca_random_run(&c, rng, ca_shuffle_bang_fill);
674
728
  return self;
675
729
  }