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
@@ -1,4 +1,5 @@
1
1
  data_type = []
2
+ type_const = {}
2
3
  %w[
3
4
  CA_FIXLEN
4
5
  CA_BOOLEAN
@@ -20,8 +21,22 @@ data_type = []
20
21
  ].each_with_index do |name, i|
21
22
  eval("#{name} = #{i}")
22
23
  data_type.push(i)
24
+ type_const[i] = name
23
25
  end
24
26
 
27
+ # The open interval (lo, hi) of doubles whose integer part a type holds:
28
+ # a cast truncates toward zero, so -128.5 still fits int8.
29
+ INTEGER_TRUNC_RANGE = {
30
+ CA_INT8 => ["-129.0", "128.0"],
31
+ CA_UINT8 => ["-1.0", "256.0"],
32
+ CA_INT16 => ["-32769.0", "32768.0"],
33
+ CA_UINT16 => ["-1.0", "65536.0"],
34
+ CA_INT32 => ["-2147483649.0", "2147483648.0"],
35
+ CA_UINT32 => ["-1.0", "4294967296.0"],
36
+ CA_INT64 => ["-9223372036854775808.0", "9223372036854775808.0"],
37
+ CA_UINT64 => ["-1.0", "18446744073709551616.0"],
38
+ }
39
+
25
40
  ctype = {
26
41
  CA_FIXLEN => "fixlen",
27
42
  CA_BOOLEAN => "boolean8_t",
@@ -40,6 +55,12 @@ ctype = {
40
55
  CA_OBJECT => "VALUE"
41
56
  }
42
57
 
58
+ # The type a cast reads and writes a cell through. A view's cells need not
59
+ # be aligned to their size (a struct member at offset 1, a refer with a
60
+ # byte offset), so a pointer to a multi-byte cell is the unaligned typedef
61
+ # from carray.h; ctype stays the plain name the functions are called by.
62
+ utype = Hash.new { |h, c| h[c] = %w[fixlen boolean8_t int8_t uint8_t].include?(c) ? c : "ca_u_#{c}" }
63
+
43
64
  obj2cval = {
44
65
  CA_FIXLEN => nil,
45
66
  CA_BOOLEAN => "OBJ2BOOL",
@@ -254,7 +275,7 @@ FIXLEN.each do |type1|
254
275
  {
255
276
  char *p1 = ptr1;
256
277
  ca_size_t bytes;
257
- VALUE *p2 = ptr2;
278
+ ca_u_VALUE *p2 = ptr2;
258
279
  if ( a1 == NULL ) {
259
280
  rb_raise(rb_eRuntimeError, "[BUG] failed to cast fixlen -> object");
260
281
  }
@@ -289,8 +310,8 @@ puts
289
310
  static void
290
311
  ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
291
312
  {
292
- #{ctype1} *p1 = ptr1;
293
- #{ctype2} *p2 = ptr2;
313
+ #{utype[ctype1]} *p1 = ptr1;
314
+ #{utype[ctype2]} *p2 = ptr2;
294
315
  #{ctype1} q;
295
316
  if ( m ) {
296
317
  while ( n-- ) {
@@ -300,7 +321,8 @@ puts
300
321
  *p2 = q;
301
322
  }
302
323
  else {
303
- rb_raise(rb_eRangeError, "out of range to cast to boolean (0 or 1)");
324
+ rb_raise(rb_eRangeError, "%s: out of range to cast to boolean (0 or 1)",
325
+ ca_calling_method_name());
304
326
  }
305
327
  }
306
328
  p1++; p2++; m++;
@@ -313,7 +335,8 @@ puts
313
335
  *p2 = q;
314
336
  }
315
337
  else {
316
- rb_raise(rb_eRangeError, "out of range to cast to boolean (0 or 1)");
338
+ rb_raise(rb_eRangeError, "%s: out of range to cast to boolean (0 or 1)",
339
+ ca_calling_method_name());
317
340
  }
318
341
  p1++; p2++;
319
342
  }
@@ -332,15 +355,54 @@ puts
332
355
  ctype1 = ctype[type1]
333
356
  ctype2 = ctype[type2]
334
357
  CA_CAST_TABLE[type1][type2] = "ca_cast_#{ctype1}_#{ctype2}"
335
- puts <<-END_DEF .gsub(/^ {6}/, '')
358
+ # float / complex -> integer: a NaN, an infinity, or a value whose
359
+ # integer part the type cannot hold has no integer, and C leaves its
360
+ # conversion undefined (x86 gives the type's minimum, ARM saturates). A
361
+ # cell that is not masked refuses it before anything is written.
362
+ # #to_type masks such cells first (UNDEF), so only a store, a view and a
363
+ # single cell reach the raise. The range is the open interval of values
364
+ # that truncate into the type, in double; for int64 the lower end is
365
+ # taken as closed, since -2**63-1 rounds to -2**63 in double.
366
+ nan_check = ""
367
+ if (FLOAT+[CA_CMPLX64, CA_CMPLX128]).include?(type1) && INTEGER.include?(type2)
368
+ complex = [CA_CMPLX64, CA_CMPLX128].include?(type1)
369
+ real = complex ? "creal(q1[k])" : "q1[k]"
370
+ lo, hi = INTEGER_TRUNC_RANGE[type2]
371
+ lo_cmp = ( type2 == CA_INT64 ) ? ">=" : ">"
372
+ fits = "( v #{lo_cmp} #{lo} && v < #{hi} )"
373
+ fits = "( #{fits} && ! isnan(cimag(q1[k])) )" if complex
374
+ nan_check = <<-END_CHECK.gsub(/^ {6}/, '')
375
+ for (k=0; k<n; k++) {
376
+ double v = (double) #{real};
377
+ if ( ( ! m || ! m[k] ) && ! #{fits} ) {
378
+ if ( isfinite(v)#{complex ? " && ! isnan(cimag(q1[k]))" : ""} ) {
379
+ rb_raise(rb_eRangeError, "%s: %.17g is out of range for %s",
380
+ ca_calling_method_name(), v, ca_type_name[#{type_const[type2]}]);
381
+ }
382
+ rb_raise(rb_eFloatDomainError, "%s: %s cannot be converted to %s",
383
+ ca_calling_method_name(), isinf(v) ? "an infinity" : "NaN",
384
+ ca_type_name[#{type_const[type2]}]);
385
+ }
386
+ }
387
+ END_CHECK
388
+ end
389
+ # int64 / uint64 -> float32 / cmplx64 goes through double, as a Ruby
390
+ # Integer stored into a float32 cell does (Integer#to_f). Converting in
391
+ # one step rounds once where the compiler keeps the loop scalar and twice
392
+ # where it vectorises it through double, so the answer for a value past
393
+ # 2**53 would depend on its place in the array.
394
+ via = ( [CA_INT64, CA_UINT64].include?(type1) &&
395
+ [CA_FLOAT32, CA_CMPLX64].include?(type2) ) ? "(double) " : ""
396
+ puts <<-END_DEF.gsub(/^ {6}/, '').sub("@@NAN_CHECK@@\n", nan_check).gsub("@@VIA@@", via)
336
397
  static void
337
398
  ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
338
399
  {
339
- #{ctype1} *q1 = ptr1;
340
- #{ctype1} *p1 = q1;
341
- #{ctype2} *q2 = ptr2;
342
- #{ctype2} *p2 = q2;
400
+ #{utype[ctype1]} *q1 = ptr1;
401
+ #{utype[ctype1]} *p1 = q1;
402
+ #{utype[ctype2]} *q2 = ptr2;
403
+ #{utype[ctype2]} *p2 = q2;
343
404
  ca_size_t k;
405
+ @@NAN_CHECK@@
344
406
  if ( m ) {
345
407
  boolean8_t *pm = m;
346
408
  for (k=0; k<n; k++) {
@@ -348,7 +410,7 @@ puts
348
410
  if ( ! *pm ) {
349
411
  p1 = q1 + k;
350
412
  p2 = q2 + k;
351
- *p2 = (#{ctype2}) *p1;
413
+ *p2 = (#{ctype2}) @@VIA@@*p1;
352
414
  }
353
415
  }
354
416
  }
@@ -356,7 +418,7 @@ puts
356
418
  for (k=0; k<n; k++) {
357
419
  p1 = q1 + k;
358
420
  p2 = q2 + k;
359
- *p2 = (#{ctype2}) *p1;
421
+ *p2 = (#{ctype2}) @@VIA@@*p1;
360
422
  }
361
423
  }
362
424
  return;
@@ -380,8 +442,8 @@ puts
380
442
  static void
381
443
  ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
382
444
  {
383
- #{ctype1} *p1 = ptr1;
384
- VALUE *p2 = ptr2;
445
+ #{utype[ctype1]} *p1 = ptr1;
446
+ ca_u_VALUE *p2 = ptr2;
385
447
  if ( m ) {
386
448
  while ( n-- ) {
387
449
  if ( !*m ) { *p2 = (VALUE) #{conv}(*p1); }
@@ -409,7 +471,7 @@ OBJECT.each do |type1|
409
471
  static void
410
472
  ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
411
473
  {
412
- VALUE *p1 = ptr1;
474
+ ca_u_VALUE *p1 = ptr1;
413
475
  char *p2 = ptr2;
414
476
  ca_size_t bytes;
415
477
  if ( a2 == NULL ) {
@@ -478,9 +540,17 @@ OBJECT.each do |type1|
478
540
  read_ok = "( RB_TYPE_P(*p1, T_STRING) ? " \
479
541
  "ca_decimal_string_to(*p1, #{type_name}, p2) : " \
480
542
  "( #{conv_ok}(*p1, &tmp) ? ( *p2 = (#{ctype2}) tmp, 1 ) : 0 ) )"
543
+ # A store refuses an integer the cell cannot hold
544
+ # (ca_obj2integer_fitting); to_type, above, keeps the C conversion.
545
+ store_conv = if INTEGER.include?(type2)
546
+ num = [CA_UINT8, CA_UINT16, CA_UINT32, CA_UINT64].include?(type2) ? "rb_num2ull" : "NUM2LL"
547
+ "#{num}(ca_obj2integer_fitting(*p1, #{type_name}))"
548
+ else
549
+ "#{conv}(*p1)"
550
+ end
481
551
  read = "if ( RB_TYPE_P(*p1, T_STRING) ) { " \
482
552
  "ca_decimal_string_store(*p1, #{type_name}, p2); } " \
483
- "else { *p2 = (#{ctype2}) #{conv}(*p1); }"
553
+ "else { *p2 = (#{ctype2}) #{store_conv}; }"
484
554
  else
485
555
  read_ok = "( #{conv_ok}(*p1, &tmp) ? ( *p2 = (#{ctype2}) tmp, 1 ) : 0 )"
486
556
  read = "*p2 = (#{ctype2}) #{conv}(*p1);"
@@ -489,8 +559,8 @@ OBJECT.each do |type1|
489
559
  static void
490
560
  ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
491
561
  {
492
- VALUE *p1 = ptr1;
493
- #{ctype2} *p2 = ptr2;
562
+ ca_u_VALUE *p1 = ptr1;
563
+ #{utype[ctype2]} *p2 = ptr2;
494
564
  #{oktype2} tmp;
495
565
  if ( m ) {
496
566
  while ( n-- ) {
@@ -517,8 +587,8 @@ OBJECT.each do |type1|
517
587
  static void
518
588
  ca_cast_#{ctype1}_#{ctype2}(ca_size_t n, CArray *a1, void *ptr1, CArray *a2, void *ptr2, boolean8_t *m)
519
589
  {
520
- VALUE *p1 = ptr1;
521
- #{ctype2} *p2 = ptr2;
590
+ ca_u_VALUE *p1 = ptr1;
591
+ #{utype[ctype2]} *p2 = ptr2;
522
592
  if ( m ) {
523
593
  while ( n-- ) {
524
594
  if ( !*m ) { *p2 = (#{ctype2}) #{conv}(*p1); }
data/ext/carray_class.c CHANGED
@@ -6,6 +6,7 @@
6
6
  ---------------------------------------------------------------------------- */
7
7
 
8
8
  #include "carray.h"
9
+ #include "carray_internal.h" /* CA_CHECK_*_GIVEN */
9
10
 
10
11
  /* ------------------------------------------------------------------- */
11
12
  /* Symbol cache for data_type code → Symbol lookup.
@@ -25,7 +26,7 @@ ID ca_data_type_sym[CA_NTYPE];
25
26
  VALUE
26
27
  rb_ca_data_type_to_sym (int8_t data_type)
27
28
  {
28
- CA_CHECK_DATA_TYPE(data_type);
29
+ CA_CHECK_DATA_TYPE_GIVEN(data_type);
29
30
  return ID2SYM(ca_data_type_sym[data_type]);
30
31
  }
31
32
 
@@ -69,7 +70,7 @@ static VALUE
69
70
  rb_ca_s_data_type_name (VALUE klass, VALUE type)
70
71
  {
71
72
  int8_t data_type = rb_ca_guess_type(type);
72
- CA_CHECK_DATA_TYPE(data_type);
73
+ CA_CHECK_DATA_TYPE_GIVEN(data_type);
73
74
  return rb_str_new2(ca_type_name[data_type]);
74
75
  }
75
76
 
@@ -84,7 +85,7 @@ static VALUE
84
85
  rb_ca_s_data_type_code (VALUE klass, VALUE type)
85
86
  {
86
87
  int8_t data_type = rb_ca_guess_type(type);
87
- CA_CHECK_DATA_TYPE(data_type);
88
+ CA_CHECK_DATA_TYPE_GIVEN(data_type);
88
89
  return INT2NUM(data_type);
89
90
  }
90
91
 
@@ -0,0 +1,28 @@
1
+ #ifndef CARRAY_CONFIG_H
2
+ #define CARRAY_CONFIG_H
3
+ #define HAVE_SYS_TYPES_H 1
4
+ #define HAVE_STDINT_H 1
5
+ #define HAVE_TYPE_INT8_T 1
6
+ #define HAVE_TYPE_UINT8_T 1
7
+ #define HAVE_TYPE_INT16_T 1
8
+ #define HAVE_TYPE_UINT16_T 1
9
+ #define HAVE_TYPE_INT32_T 1
10
+ #define HAVE_TYPE_UINT32_T 1
11
+ #define HAVE_TYPE_INT64_T 1
12
+ #define HAVE_TYPE_UINT64_T 1
13
+ #define HAVE_TYPE_LONG_LONG 1
14
+ #define HAVE_TYPE_FLOAT 1
15
+ #define HAVE_TYPE_DOUBLE 1
16
+ #define HAVE_COMPLEX_H 1
17
+ #define HAVE_TYPE_FLOAT_COMPLEX 1
18
+ #define HAVE_TYPE_DOUBLE_COMPLEX 1
19
+ #define HAVE_TGMATH_H 1
20
+ #define HAVE_ATAN2 1
21
+ #define HAVE_HYPOT 1
22
+ #define HAVE_LGAMMA 1
23
+ #define HAVE_EXPM1 1
24
+ #define HAVE_MERGESORT 1
25
+ #define HAVE_STRPTIME 1
26
+ #define HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT 1
27
+ #define HAVE_RUBY_MEMORY_VIEW_H 1
28
+ #endif
@@ -30,14 +30,14 @@
30
30
  /* Leaf macro: data type-specialized inner loop. Produces `n` VALUE objects
31
31
  from a contig ptr base + element width, storing into `dst` (Ruby Array). */
32
32
  #define TO_A_LEAF_LOOP(T, TO_VALUE) do { \
33
- const T *src = (const T *) base; \
33
+ const CA_U(T) *src = (const CA_U(T) *) base; \
34
34
  for (li = 0; li < n; li++) { \
35
35
  rb_ary_store(dst, li, TO_VALUE(src[li])); \
36
36
  } \
37
37
  } while (0)
38
38
 
39
39
  #define TO_A_LEAF_LOOP_MASKED(T, TO_VALUE) do { \
40
- const T *src = (const T *) base; \
40
+ const CA_U(T) *src = (const CA_U(T) *) base; \
41
41
  for (li = 0; li < n; li++) { \
42
42
  rb_ary_store(dst, li, mask[li] ? CA_UNDEF : TO_VALUE(src[li])); \
43
43
  } \
@@ -480,10 +480,16 @@ rb_ca_load_binary (VALUE self, VALUE io)
480
480
  case T_STRING:
481
481
  if ( ca_length(ca) != RSTRING_LEN(io) ) {
482
482
  rb_raise(rb_eArgError,
483
- "data size mismatch (got %" PRId64 " bytes, expected %" PRId64 ")",
484
- (ca_size_t) RSTRING_LEN(io), (ca_size_t) ca_length(ca));
483
+ "%s: data size mismatch (got %" PRId64 " bytes, expected %" PRId64 ")",
484
+ ca_calling_method_name(), (ca_size_t) RSTRING_LEN(io), (ca_size_t) ca_length(ca));
485
+ }
486
+ if ( ca->data_type == CA_BOOLEAN ) {
487
+ io = rb_str_dup(io);
488
+ rb_str_modify(io);
489
+ ca_boolean_normalize_bytes(RSTRING_PTR(io), ca->elements);
485
490
  }
486
491
  ca_sync_data(ca, RSTRING_PTR(io));
492
+ RB_GC_GUARD(io);
487
493
  return self;
488
494
  break;
489
495
  default:
@@ -511,6 +517,9 @@ rb_ca_load_binary (VALUE self, VALUE io)
511
517
  memcpy(ca->ptr + off, RSTRING_PTR(r), want);
512
518
  off += want;
513
519
  }
520
+ if ( ca->data_type == CA_BOOLEAN ) {
521
+ ca_boolean_normalize_bytes(ca->ptr, ca->elements);
522
+ }
514
523
  ca_sync_detach(ca);
515
524
  }
516
525
  else {
@@ -540,7 +549,7 @@ rb_ca_load_binary (VALUE self, VALUE io)
540
549
  to float. Its digits are those of the decimal (at most 9, which a double
541
550
  holds), so Float#to_s writes them. */
542
551
  static double
543
- ca_float32_shortest (float x)
552
+ ca_double_of_shortest_decimal_of_float32 (float x)
544
553
  {
545
554
  char buf[32];
546
555
  int lo = 1, hi = 9;
@@ -576,7 +585,7 @@ ca_float32_shortest (float x)
576
585
  double its shortest decimal reads as, for to_csv to write that decimal.
577
586
  The mask is kept. */
578
587
  static VALUE
579
- rb_ca_shortest_float64 (VALUE self)
588
+ rb_ca_widen_keeping_shortest_decimal (VALUE self)
580
589
  {
581
590
  volatile VALUE out, holder = 0;
582
591
  CArray *ca, *co;
@@ -591,7 +600,7 @@ rb_ca_shortest_float64 (VALUE self)
591
600
  type = CA_CMPLX128;
592
601
  }
593
602
  else {
594
- rb_raise(rb_eCADataTypeError, "__shortest_float64__ takes float32 or cmplx64");
603
+ rb_raise(rb_eCADataTypeError, "__widen_keeping_shortest_decimal__ takes float32 or cmplx64");
595
604
  }
596
605
  n = ca->elements * (ca->data_type == CA_CMPLX64 ? 2 : 1);
597
606
  out = rb_carray_new_safe(type, ca->ndim, ca->dim, 0, NULL);
@@ -601,7 +610,7 @@ rb_ca_shortest_float64 (VALUE self)
601
610
  double *dst = (double *) co->ptr;
602
611
  ca_copy_data(ca, (char *) src);
603
612
  for (i = 0; i < n; i++) {
604
- dst[i] = ca_float32_shortest(src[i]);
613
+ dst[i] = ca_double_of_shortest_decimal_of_float32(src[i]);
605
614
  }
606
615
  ALLOCV_END(holder);
607
616
  }
@@ -627,7 +636,7 @@ Init_carray_conversion (void)
627
636
  rb_define_method(rb_cCArray, "dump_binary", rb_ca_dump_binary, -1);
628
637
  rb_define_method(rb_cCArray, "to_s", rb_ca_to_s, 0);
629
638
  rb_define_method(rb_cCArray, "load_binary", rb_ca_load_binary, 1);
630
- rb_define_method(rb_cCArray, "__shortest_float64__", rb_ca_shortest_float64, 0);
639
+ rb_define_method(rb_cCArray, "__widen_keeping_shortest_decimal__", rb_ca_widen_keeping_shortest_decimal, 0);
631
640
 
632
641
  /* CAREFUL: do not bind #to_ary — implicit array coercion in Ruby core
633
642
  (splat / multiple assignment / Array()) then triggers on any CArray
data/ext/carray_copy.c CHANGED
@@ -36,6 +36,42 @@ ca_fill_or_free (CArray *co, VALUE (*fill)(VALUE), VALUE arg)
36
36
  }
37
37
  }
38
38
 
39
+ void
40
+ ca_fill_or_xfree (void *buf, VALUE (*fill)(VALUE), VALUE arg)
41
+ {
42
+ int tag = 0;
43
+ rb_protect(fill, arg, &tag);
44
+ if ( tag ) {
45
+ xfree(buf);
46
+ rb_jump_tag(tag);
47
+ }
48
+ }
49
+
50
+ void
51
+ ca_fill_or_detach (int n, CArray **list, VALUE (*fill)(VALUE), VALUE arg)
52
+ {
53
+ int tag = 0;
54
+ int k;
55
+ rb_protect(fill, arg, &tag);
56
+ if ( tag ) {
57
+ for ( k = 0; k < n; k++ ) {
58
+ ca_detach(list[k]);
59
+ }
60
+ rb_jump_tag(tag);
61
+ }
62
+ }
63
+
64
+ VALUE
65
+ ca_view_inherit_mask (VALUE view)
66
+ {
67
+ CArray *ca = (CArray *) view;
68
+ CArray *parent = ((CAView *) ca)->parent;
69
+ if ( parent && ca_has_mask(parent) ) {
70
+ ca_create_mask(ca);
71
+ }
72
+ return Qnil;
73
+ }
74
+
39
75
  static VALUE
40
76
  ca_copy_fill (VALUE arg)
41
77
  {
@@ -173,7 +209,7 @@ rb_ca_to_ca (int argc, VALUE *argv, VALUE self)
173
209
  CArray *ca;
174
210
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
175
211
  if ( ca_is_readonly(ca) ) {
176
- rb_raise(rb_eRuntimeError, "can not modify read-only array");
212
+ ca_refuse_read_only();
177
213
  }
178
214
  }
179
215
  return self;
@@ -220,7 +256,7 @@ CArray *
220
256
  ca_template_safe2 (void *ap, int8_t data_type, ca_size_t bytes)
221
257
  {
222
258
  CArray *ca = (CArray *) ap;
223
- CA_CHECK_DATA_TYPE(data_type);
259
+ CA_CHECK_DATA_TYPE_GIVEN(data_type);
224
260
  if ( ca_is_scalar(ca) ) {
225
261
  return (CArray*) cscalar_new(data_type, bytes, NULL);
226
262
  }
@@ -261,6 +297,19 @@ rb_ca_template_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
261
297
  obj = ca_wrap_struct(co);
262
298
  }
263
299
 
300
+ /* Preserve the Face identity only for a same-type template (no explicit
301
+ * retype). A retype (template(:boolean)) is a different-typed buffer and
302
+ * must not be re-wrapped as the Face. A same-type template of a Face with
303
+ * a valid blank form (CARecord carries its data_class through the struct
304
+ * tail; identity Faces alias same-type storage) is lifted so the class is
305
+ * preserved. A Face with no valid blank form (CAConstString's content-
306
+ * defined offset+buffer) overrides `template` in Ruby to return a plain
307
+ * array instead of a broken same-class shell. The lift comes before the
308
+ * block initialiser so its values are stored through the Face. */
309
+ if ( NIL_P(rtype) ) {
310
+ CA_FACE_LIFT_IF_FACE(obj, self, ca);
311
+ }
312
+
264
313
  if ( rb_block_given_p() ) {
265
314
  if ( rb_proc_arity(rb_block_proc()) == 0 ) {
266
315
  volatile VALUE rval = rb_yield_values2(0, NULL);
@@ -283,18 +332,6 @@ rb_ca_template_kw (int argc, VALUE *argv, VALUE ropt, VALUE self)
283
332
  }
284
333
  }
285
334
 
286
- /* Preserve the Face identity only for a same-type template (no explicit
287
- * retype). A retype (template(:boolean)) is a different-typed buffer and
288
- * must not be re-wrapped as the Face. A same-type template of a Face with
289
- * a valid blank form (CARecord carries its data_class through the struct
290
- * tail; identity Faces alias same-type storage) is lifted so the class is
291
- * preserved. A Face with no valid blank form (CAConstString's content-
292
- * defined offset+buffer) overrides `template` in Ruby to return a plain
293
- * array instead of a broken same-class shell. */
294
- if ( NIL_P(rtype) ) {
295
- CA_FACE_LIFT_IF_FACE(obj, self, ca);
296
- }
297
-
298
335
  return obj;
299
336
  }
300
337