carray 2.0.0 → 3.0.0

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 (339) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -25
  3. data/CHANGELOG.md +16 -0
  4. data/LICENSE +1 -1
  5. data/NEWS.md +3 -0
  6. data/README.md +128 -44
  7. data/carray.gemspec +22 -24
  8. data/ext/ca_array_pool.c +91 -0
  9. data/ext/ca_axis_descriptor.h +186 -0
  10. data/ext/ca_axis_dispatch.c +924 -0
  11. data/ext/ca_axis_group.c +1208 -0
  12. data/ext/ca_bincmp_dispatch.c +76 -0
  13. data/ext/ca_bincmp_dispatch.h +85 -0
  14. data/ext/ca_binop_dispatch.c +125 -0
  15. data/ext/ca_binop_dispatch.h +159 -0
  16. data/ext/ca_categorical_iterator.c +1375 -0
  17. data/ext/ca_compare.c +94 -0
  18. data/ext/ca_compare.h +26 -0
  19. data/ext/ca_composite_dispatch.c +414 -0
  20. data/ext/ca_composite_dispatch.h +116 -0
  21. data/ext/ca_for_buffer.h +96 -0
  22. data/ext/ca_for_each_element.h +241 -0
  23. data/ext/ca_group_iter.c +304 -0
  24. data/ext/ca_iter_substrate.h +325 -0
  25. data/ext/ca_kernel_iterator.c +4321 -0
  26. data/ext/ca_kernel_iterator.h +2603 -0
  27. data/ext/ca_moncmp_dispatch.c +37 -0
  28. data/ext/ca_moncmp_dispatch.h +62 -0
  29. data/ext/ca_monop_dispatch.c +200 -0
  30. data/ext/ca_monop_dispatch.h +235 -0
  31. data/ext/ca_obj_array.c +355 -359
  32. data/ext/ca_obj_bincmp.c +809 -0
  33. data/ext/ca_obj_binop.c +892 -0
  34. data/ext/ca_obj_bitarray.c +369 -164
  35. data/ext/ca_obj_bitfield.c +294 -234
  36. data/ext/ca_obj_block.c +189 -711
  37. data/ext/ca_obj_byte_swap.c +766 -0
  38. data/ext/ca_obj_const_string.c +965 -0
  39. data/ext/ca_obj_face.c +670 -0
  40. data/ext/ca_obj_face.h +247 -0
  41. data/ext/ca_obj_fake.c +228 -100
  42. data/ext/ca_obj_farray.c +54 -441
  43. data/ext/ca_obj_field.c +82 -529
  44. data/ext/ca_obj_fixlen_string.c +306 -0
  45. data/ext/ca_obj_grid.c +858 -440
  46. data/ext/ca_obj_meld.c +1034 -0
  47. data/ext/ca_obj_moncmp.c +569 -0
  48. data/ext/ca_obj_monop.c +1111 -0
  49. data/ext/ca_obj_object.c +774 -298
  50. data/ext/ca_obj_record.c +468 -0
  51. data/ext/ca_obj_reduce.c +97 -82
  52. data/ext/ca_obj_refer.c +569 -459
  53. data/ext/ca_obj_remap.c +475 -0
  54. data/ext/ca_obj_repeat.c +92 -477
  55. data/ext/ca_obj_roll.c +616 -0
  56. data/ext/ca_obj_select.c +344 -296
  57. data/ext/ca_obj_select_axis.c +1296 -0
  58. data/ext/ca_obj_shift.c +230 -792
  59. data/ext/ca_obj_source.c +78 -0
  60. data/ext/ca_obj_stack.c +1173 -0
  61. data/ext/ca_obj_stride.c +2501 -0
  62. data/ext/ca_obj_string.c +268 -0
  63. data/ext/ca_obj_tile.c +614 -0
  64. data/ext/ca_obj_time.c +546 -0
  65. data/ext/ca_obj_timedelta.c +435 -0
  66. data/ext/ca_obj_transpose.c +62 -516
  67. data/ext/ca_obj_triop.c +746 -0
  68. data/ext/ca_obj_unbound_repeat.c +208 -241
  69. data/ext/ca_obj_window.c +1131 -563
  70. data/ext/ca_op_byte_swap.c +175 -0
  71. data/ext/ca_op_ipower.c +319 -0
  72. data/ext/ca_op_powi.h +88 -0
  73. data/ext/ca_sort_kernels.h +132 -0
  74. data/ext/ca_sweep_engine.c +430 -0
  75. data/ext/ca_sweep_engine.h +157 -0
  76. data/ext/ca_transform_common.c +228 -0
  77. data/ext/ca_triop_dispatch.c +55 -0
  78. data/ext/ca_triop_dispatch.h +62 -0
  79. data/ext/carray.h +795 -402
  80. data/ext/carray_access.c +831 -711
  81. data/ext/carray_attribute.c +98 -330
  82. data/ext/carray_bincount.c +255 -0
  83. data/ext/carray_broadcast.c +283 -0
  84. data/ext/carray_call_cfunc.c +1360 -828
  85. data/ext/carray_call_cfunc.h +160 -0
  86. data/ext/carray_cast.c +1212 -301
  87. data/ext/carray_cast_func.rb +81 -40
  88. data/ext/carray_class.c +53 -63
  89. data/ext/carray_config.h +28 -0
  90. data/ext/carray_conversion.c +350 -346
  91. data/ext/carray_copy.c +156 -268
  92. data/ext/carray_core.c +1342 -199
  93. data/ext/carray_count.c +312 -0
  94. data/ext/carray_data_type.c +43 -19
  95. data/ext/carray_element.c +585 -213
  96. data/ext/carray_factorize.c +2542 -0
  97. data/ext/carray_generate.c +230 -559
  98. data/ext/carray_histogram.c +490 -0
  99. data/ext/carray_hold.c +228 -0
  100. data/ext/carray_index_classifier.c +1035 -0
  101. data/ext/carray_index_classifier.h +27 -0
  102. data/ext/carray_internal.h +120 -0
  103. data/ext/carray_kernels_bincmp.c +4445 -0
  104. data/ext/carray_kernels_binop.c +10979 -0
  105. data/ext/carray_kernels_init.c +36 -0
  106. data/ext/carray_kernels_map.c +3466 -0
  107. data/ext/carray_kernels_moncmp.c +2096 -0
  108. data/ext/carray_kernels_monop.c +18312 -0
  109. data/ext/carray_kernels_reduce_aggregate.c +25836 -0
  110. data/ext/carray_kernels_reduce_boolean.c +329 -0
  111. data/ext/carray_kernels_reduce_cumulative.c +14592 -0
  112. data/ext/carray_kernels_reduce_extreme.c +16947 -0
  113. data/ext/carray_kernels_reduce_variance.c +3909 -0
  114. data/ext/carray_kernels_scan.c +3692 -0
  115. data/ext/carray_kernels_search.c +32137 -0
  116. data/ext/carray_kernels_sort.c +10625 -0
  117. data/ext/carray_kernels_triop.c +1391 -0
  118. data/ext/carray_lazy.c +567 -0
  119. data/ext/carray_loop.c +88 -200
  120. data/ext/carray_mask.c +848 -154
  121. data/ext/carray_math_kernel.h +120 -0
  122. data/ext/carray_mathfunc.c +10 -241
  123. data/ext/carray_median_percentile.c +1257 -0
  124. data/ext/carray_memory_view.c +1625 -0
  125. data/ext/carray_operator.c +1526 -318
  126. data/ext/carray_order.c +664 -1394
  127. data/ext/carray_partition.c +416 -0
  128. data/ext/carray_random.c +518 -0
  129. data/ext/carray_scatter.c +357 -0
  130. data/ext/carray_slab.c +1219 -0
  131. data/ext/carray_slab.h +84 -0
  132. data/ext/carray_sort.c +829 -0
  133. data/ext/carray_sort_kernel.c +620 -0
  134. data/ext/carray_struct.c +695 -0
  135. data/ext/carray_test.c +343 -229
  136. data/ext/carray_undef.c +34 -17
  137. data/ext/carray_utils.c +175 -74
  138. data/ext/extconf.rb +216 -55
  139. data/ext/mk_call_cfunc.rb +480 -0
  140. data/ext/mkkernel.rb +8842 -0
  141. data/ext/ruby_carray.c +202 -101
  142. data/ext/version.h +4 -14
  143. data/ext/version.rb +5 -13
  144. data/lib/carray/arrow_tensor.rb +401 -0
  145. data/lib/carray/attribute.rb +166 -0
  146. data/lib/carray/autoload_carray.rb +220 -0
  147. data/lib/carray/autoload_method_extension.rb +44 -0
  148. data/lib/carray/axis_group.rb +711 -0
  149. data/lib/carray/basics.rb +481 -0
  150. data/lib/carray/bincount_nd.rb +358 -0
  151. data/lib/carray/block_iterator.rb +604 -0
  152. data/lib/carray/boolean_reduce.rb +109 -0
  153. data/lib/carray/categorical.rb +561 -0
  154. data/lib/carray/categorical_iterator.rb +1062 -0
  155. data/lib/carray/complex.rb +150 -0
  156. data/lib/carray/conditional.rb +216 -0
  157. data/lib/carray/const_string.rb +228 -0
  158. data/lib/carray/construct.rb +139 -328
  159. data/lib/carray/core_extensions.rb +240 -0
  160. data/lib/carray/data_type_extension.rb +233 -0
  161. data/lib/carray/fixlen_string.rb +95 -0
  162. data/lib/carray/frame/concat.rb +132 -0
  163. data/lib/carray/frame/convert.rb +95 -0
  164. data/lib/carray/frame/csv_parser.rb +211 -0
  165. data/lib/carray/frame/frame.rb +649 -0
  166. data/lib/carray/frame/group.rb +186 -0
  167. data/lib/carray/frame/io.rb +164 -0
  168. data/lib/carray/frame/join.rb +248 -0
  169. data/lib/carray/frame/records.rb +99 -0
  170. data/lib/carray/frame/sort.rb +113 -0
  171. data/lib/carray/frame/verbs.rb +299 -0
  172. data/lib/carray/frame.rb +16 -0
  173. data/lib/carray/histogram.rb +512 -0
  174. data/lib/carray/inspect.rb +37 -20
  175. data/lib/carray/iterator.rb +57 -349
  176. data/lib/carray/lazy.rb +889 -0
  177. data/lib/carray/mask_gap_fill.rb +200 -0
  178. data/lib/carray/math.rb +78 -342
  179. data/lib/carray/meld_reduce.rb +289 -0
  180. data/lib/carray/methods/align_addr.rb +116 -0
  181. data/lib/carray/methods/bin.rb +128 -0
  182. data/lib/carray/methods/bincount.rb +87 -0
  183. data/lib/carray/methods/bit_string.rb +92 -0
  184. data/lib/carray/methods/broadcast.rb +63 -0
  185. data/lib/carray/methods/choose.rb +39 -0
  186. data/lib/carray/methods/composition.rb +280 -0
  187. data/lib/carray/methods/gather_nd.rb +206 -0
  188. data/lib/carray/methods/index.rb +39 -0
  189. data/lib/carray/methods/insert_block.rb +99 -0
  190. data/lib/carray/methods/is_in.rb +141 -0
  191. data/lib/carray/methods/join.rb +90 -0
  192. data/lib/carray/methods/locate_addr.rb +47 -0
  193. data/lib/carray/methods/mask_duplicates.rb +41 -0
  194. data/lib/carray/methods/meshgrid.rb +91 -0
  195. data/lib/carray/methods/mode.rb +126 -0
  196. data/lib/carray/methods/nunique.rb +46 -0
  197. data/lib/carray/methods/resize.rb +56 -0
  198. data/lib/carray/methods/snap.rb +156 -0
  199. data/lib/carray/methods/string_format.rb +57 -0
  200. data/lib/carray/methods/unique.rb +47 -0
  201. data/lib/carray/methods/value_counts.rb +71 -0
  202. data/lib/carray/mkmf.rb +124 -101
  203. data/lib/carray/runtime.rb +108 -0
  204. data/lib/carray/serialize.rb +478 -167
  205. data/lib/carray/slab_iterator.rb +292 -0
  206. data/lib/carray/stack.rb +291 -0
  207. data/lib/carray/string.rb +56 -180
  208. data/lib/carray/string_operation_extension.rb +289 -0
  209. data/lib/carray/struct.rb +335 -323
  210. data/lib/carray/struct_builder.rb +697 -0
  211. data/lib/carray/table.rb +41 -2
  212. data/lib/carray/time.rb +2255 -38
  213. data/lib/carray/window_iterator.rb +655 -0
  214. data/lib/carray.rb +55 -57
  215. metadata +163 -130
  216. data/Rakefile +0 -51
  217. data/TODO.md +0 -18
  218. data/ext/ca_iter_block.c +0 -257
  219. data/ext/ca_iter_dimension.c +0 -299
  220. data/ext/ca_iter_window.c +0 -214
  221. data/ext/ca_obj_mapping.c +0 -644
  222. data/ext/carray_iterator.c +0 -641
  223. data/ext/carray_math.rb +0 -850
  224. data/ext/carray_numeric.c +0 -259
  225. data/ext/carray_sort_addr.c +0 -254
  226. data/ext/carray_stat.c +0 -2100
  227. data/ext/carray_stat_proc.rb +0 -1999
  228. data/ext/mkmath.rb +0 -741
  229. data/ext/ruby_ccomplex.c +0 -509
  230. data/ext/ruby_float_func.c +0 -86
  231. data/lib/carray/array.rb +0 -8
  232. data/lib/carray/autoload/autoload_base.rb +0 -19
  233. data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
  234. data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
  235. data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
  236. data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
  237. data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
  238. data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
  239. data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
  240. data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
  241. data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
  242. data/lib/carray/autoload/autoload_gem_random.rb +0 -8
  243. data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
  244. data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
  245. data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
  246. data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
  247. data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
  248. data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
  249. data/lib/carray/autoload/autoload_object_link.rb +0 -1
  250. data/lib/carray/autoload/autoload_object_pack.rb +0 -2
  251. data/lib/carray/autoload.rb +0 -141
  252. data/lib/carray/basic.rb +0 -191
  253. data/lib/carray/broadcast.rb +0 -101
  254. data/lib/carray/compose.rb +0 -315
  255. data/lib/carray/convert.rb +0 -115
  256. data/lib/carray/info.rb +0 -110
  257. data/lib/carray/io/imagemagick.rb +0 -235
  258. data/lib/carray/mask.rb +0 -102
  259. data/lib/carray/math/histogram.rb +0 -177
  260. data/lib/carray/math/recurrence.rb +0 -93
  261. data/lib/carray/object/ca_obj_iterator.rb +0 -50
  262. data/lib/carray/object/ca_obj_link.rb +0 -50
  263. data/lib/carray/object/ca_obj_pack.rb +0 -99
  264. data/lib/carray/obsolete.rb +0 -256
  265. data/lib/carray/ordering.rb +0 -181
  266. data/lib/carray/testing.rb +0 -51
  267. data/lib/carray/transform.rb +0 -109
  268. data/misc/Methods.ja.md +0 -182
  269. data/misc/NOTE +0 -51
  270. data/spec/Classes/CABitfield_spec.rb +0 -58
  271. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  272. data/spec/Classes/CABlock_spec.rb +0 -205
  273. data/spec/Classes/CAField_spec.rb +0 -39
  274. data/spec/Classes/CAGrid_spec.rb +0 -75
  275. data/spec/Classes/CAMap_spec.rb +0 -0
  276. data/spec/Classes/CAMapping_spec.rb +0 -105
  277. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  278. data/spec/Classes/CAObject_spec.rb +0 -33
  279. data/spec/Classes/CARefer_spec.rb +0 -93
  280. data/spec/Classes/CARepeat_spec.rb +0 -65
  281. data/spec/Classes/CASelect_spec.rb +0 -22
  282. data/spec/Classes/CAShift_spec.rb +0 -16
  283. data/spec/Classes/CAStruct_spec.rb +0 -71
  284. data/spec/Classes/CATranspose_spec.rb +0 -60
  285. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  286. data/spec/Classes/CAWindow_spec.rb +0 -54
  287. data/spec/Classes/CAWrap_spec.rb +0 -8
  288. data/spec/Classes/CArray_spec.rb +0 -184
  289. data/spec/Classes/CScalar_spec.rb +0 -55
  290. data/spec/Classes/ex1.rb +0 -46
  291. data/spec/Features/feature_130_spec.rb +0 -19
  292. data/spec/Features/feature_attributes_spec.rb +0 -280
  293. data/spec/Features/feature_boolean_spec.rb +0 -98
  294. data/spec/Features/feature_broadcast.rb +0 -116
  295. data/spec/Features/feature_cast_function.rb +0 -19
  296. data/spec/Features/feature_cast_spec.rb +0 -33
  297. data/spec/Features/feature_class_spec.rb +0 -84
  298. data/spec/Features/feature_complex_spec.rb +0 -42
  299. data/spec/Features/feature_composite_spec.rb +0 -124
  300. data/spec/Features/feature_convert_spec.rb +0 -46
  301. data/spec/Features/feature_copy_spec.rb +0 -123
  302. data/spec/Features/feature_creation_spec.rb +0 -84
  303. data/spec/Features/feature_element_spec.rb +0 -144
  304. data/spec/Features/feature_extream_spec.rb +0 -54
  305. data/spec/Features/feature_generate_spec.rb +0 -74
  306. data/spec/Features/feature_index_spec.rb +0 -69
  307. data/spec/Features/feature_mask_spec.rb +0 -580
  308. data/spec/Features/feature_math_spec.rb +0 -97
  309. data/spec/Features/feature_order_spec.rb +0 -146
  310. data/spec/Features/feature_ref_store_spec.rb +0 -209
  311. data/spec/Features/feature_serialization_spec.rb +0 -125
  312. data/spec/Features/feature_stat_spec.rb +0 -397
  313. data/spec/Features/feature_virtual_spec.rb +0 -48
  314. data/spec/Features/method_eq_spec.rb +0 -81
  315. data/spec/Features/method_is_nan_spec.rb +0 -12
  316. data/spec/Features/method_map_spec.rb +0 -54
  317. data/spec/Features/method_max_with.rb +0 -20
  318. data/spec/Features/method_min_with.rb +0 -19
  319. data/spec/Features/method_ne_spec.rb +0 -18
  320. data/spec/Features/method_project_spec.rb +0 -188
  321. data/spec/Features/method_ref_spec.rb +0 -27
  322. data/spec/Features/method_round_spec.rb +0 -11
  323. data/spec/Features/method_s_linspace_spec.rb +0 -48
  324. data/spec/Features/method_s_span_spec.rb +0 -14
  325. data/spec/Features/method_seq_spec.rb +0 -47
  326. data/spec/Features/method_sort_with.rb +0 -43
  327. data/spec/Features/method_sorted_with.rb +0 -29
  328. data/spec/Features/method_span_spec.rb +0 -42
  329. data/spec/Features/method_wrap_readonly_spec.rb +0 -43
  330. data/spec/UnitTest/test_CAVirtual.rb +0 -214
  331. data/spec/spec_all.rb +0 -10
  332. data/utils/ca_ase.rb +0 -21
  333. data/utils/ca_methods.rb +0 -15
  334. data/utils/cast_checker.rb +0 -30
  335. data/utils/convert_test.rb +0 -73
  336. data/utils/extract_yard.rb +0 -22
  337. data/utils/guess_shape.rb +0 -76
  338. data/utils/monkey_patch_methods.rb +0 -62
  339. data/utils/remove_resource_fork.sh +0 -5
@@ -0,0 +1,200 @@
1
+ # Mask gap-fill: the `method:` keyword on #unmask / #strip_mask.
2
+ #
3
+ # #unmask and #strip_mask clear a mask by *supplying values*. The value
4
+ # source is either a constant (the existing positional argument) or a
5
+ # scan-method derived from neighbouring valid cells:
6
+ #
7
+ # unmask(v) # in-place, constant fill (C primitive)
8
+ # strip_mask(v) # copy, constant fill (C primitive)
9
+ # unmask(method: :forward) # in-place, carry last valid value (hold)
10
+ # strip_mask(method: :backward)# copy, carry next valid value (hold)
11
+ # unmask(method: :linear) # in-place, linear-by-index interpolation
12
+ #
13
+ # The constant path stays positional; the method path is keyword-only
14
+ # (a positional Symbol is already a valid constant fill, e.g.
15
+ # `strip_mask(:na)`). Passing both raises ArgumentError.
16
+ #
17
+ # Design / rationale: devel/PROPOSAL_UNMASK_FILL_METHOD.md. The forward
18
+ # hold is the C primitive #__hold__; backward = flip -> forward -> flip,
19
+ # flatten = flatten -> hold -> reshape, and :linear composes
20
+ # linear_section / linear_fetch. User-facing YARD docs live in
21
+ # yard-stubs/carray_mask.rb.
22
+ #
23
+ # A Face (CATime, CATimedelta, a categorical) rides both paths through its
24
+ # storage: hold copies bytes, so it never invents a value and needs nothing
25
+ # from the Face; :linear goes through the Face's own linear_fetch, so the
26
+ # filled values land on the array's unit. In place, the write-back goes to
27
+ # the storage -- a bulk store into a Face's surface would try to cast the
28
+ # storage values to it (int64 ticks to fixlen, for a time array).
29
+
30
+ class CArray
31
+
32
+ # Preserve the C constant-fill primitives under private names so the
33
+ # Ruby wrappers can delegate the non-method path unchanged.
34
+ alias __unmask_const__ unmask
35
+ alias __strip_mask_const__ strip_mask
36
+ private :__unmask_const__, :__strip_mask_const__
37
+
38
+ # Sentinel for "no positional fill value given" (distinct from any real
39
+ # fill value, including nil / false / a Symbol).
40
+ MASK_FILL_UNSET = ::Object.new
41
+ private_constant :MASK_FILL_UNSET
42
+
43
+ def unmask (fill = MASK_FILL_UNSET, method: nil, axis: nil)
44
+ if method
45
+ unless fill.equal?(MASK_FILL_UNSET)
46
+ raise ArgumentError,
47
+ "unmask: pass either a constant fill value or method:, not both"
48
+ end
49
+ held = __gap_fill__(method, axis)
50
+ # Copy the filled values in place. A Face writes through its storage: a
51
+ # bulk store into its surface would try to cast the storage values to the
52
+ # surface type (int64 ticks to fixlen, for a time array).
53
+ if face?
54
+ parent.value[] = held.parent.value
55
+ else
56
+ value[] = held.value
57
+ end
58
+ if held.has_mask?
59
+ self.mask = held.mask # residual leading/trailing mask
60
+ else
61
+ __unmask_const__ # fully filled: drop the mask
62
+ end
63
+ return self
64
+ end
65
+ fill.equal?(MASK_FILL_UNSET) ? __unmask_const__ : __unmask_const__(fill)
66
+ end
67
+
68
+ def strip_mask (fill = MASK_FILL_UNSET, method: nil, axis: nil)
69
+ if method
70
+ unless fill.equal?(MASK_FILL_UNSET)
71
+ raise ArgumentError,
72
+ "strip_mask: pass either a constant fill value or method:, not both"
73
+ end
74
+ return __gap_fill__(method, axis)
75
+ end
76
+ if fill.equal?(MASK_FILL_UNSET)
77
+ raise ArgumentError, "strip_mask: a fill value is required (or method:)"
78
+ end
79
+ __strip_mask_const__(fill)
80
+ end
81
+
82
+ private
83
+
84
+ # Dispatch a method-fill to a fresh array. Residual (leading/trailing)
85
+ # unfillable cells stay masked; a fully filled result carries no mask
86
+ # (hold allocates the output mask only when a leading run goes UNDEF;
87
+ # :linear masks only the exterior via mask_invalid).
88
+ def __gap_fill__ (method, axis)
89
+ case method
90
+ when :forward, :ffill
91
+ __hold_axis__(axis, false)
92
+ when :backward, :bfill
93
+ __hold_axis__(axis, true)
94
+ when :linear
95
+ __gap_fill_linear__(axis)
96
+ else
97
+ raise ArgumentError,
98
+ "unmask/strip_mask: unknown method: #{method.inspect} " \
99
+ "(:forward | :backward | :linear)"
100
+ end
101
+ end
102
+
103
+ # Forward (backward = false) or backward (true) hold along `axis`
104
+ # (axis nil = flatten). Backward reuses the forward primitive on the
105
+ # reversed view; flatten flattens, holds axis 0, reshapes back.
106
+ def __hold_axis__ (axis, backward)
107
+ if axis.nil?
108
+ flat = flatten
109
+ flat = flat.reverse if backward
110
+ held = flat.send(:__hold__, 0)
111
+ held = held.reverse if backward
112
+ held.reshape(*shape)
113
+ else
114
+ ax = axis < 0 ? axis + ndim : axis
115
+ if backward
116
+ flip(ax).send(:__hold__, ax).flip(ax)
117
+ else
118
+ send(:__hold__, ax)
119
+ end
120
+ end
121
+ end
122
+
123
+ # Linear-by-index gap fill: interpolate each masked cell from the two
124
+ # bracketing valid cells, x = cell index along the axis. Cells outside the
125
+ # valid range (leading/trailing) stay masked. A Face goes through its own
126
+ # linear_fetch, which keeps its unit and rounds to its grid; whether that
127
+ # means anything is the Face's call (an ORDERABLE numeric one answers, the
128
+ # rest raise from there), so this gate only asks that it be one.
129
+ def __gap_fill_linear__ (axis)
130
+ unless numeric? || face?
131
+ raise ArgumentError,
132
+ "unmask/strip_mask(method: :linear): numeric or time data_type " \
133
+ "required (got #{data_type_name})"
134
+ end
135
+ if axis.nil?
136
+ return __linear_fiber__(flatten).reshape(*shape)
137
+ end
138
+ ax = axis < 0 ? axis + ndim : axis
139
+ if ax < 0 || ax >= ndim
140
+ raise ArgumentError, "axis #{axis} out of range for ndim #{ndim}"
141
+ end
142
+ # A Face assembles in storage space -- its linear_fetch has already rounded
143
+ # to the grid, so there is nothing left to hold in float64. A numeric
144
+ # array assembles in float64 and casts back once at the end.
145
+ out = face? ? template : float64.copy
146
+ sink = face? ? out.parent : out
147
+ __each_fiber_key__(ax) do |key|
148
+ fiber = __linear_fiber__(self[*key])
149
+ sink[*key] = face? ? fiber.parent : fiber
150
+ end
151
+ face? ? out : out.to_type(data_type)
152
+ end
153
+
154
+ # 1-D linear-by-index fill of a single (possibly masked) fiber. Present
155
+ # cells reproduce exactly; interior masked cells interpolate; exterior
156
+ # masked cells become UNDEF (linear_section returns NaN out of range,
157
+ # mask_invalid marks it). Returns the same kind as `vec`: a Face fiber
158
+ # comes back as that Face, on its own unit.
159
+ def __linear_fiber__ (vec)
160
+ n = vec.elements
161
+ present = vec.is_not_masked
162
+ # Fewer than two valid points -> nothing to interpolate between; leave
163
+ # every masked cell masked (the copy carries vec's mask).
164
+ if present.count(true) < 2
165
+ return vec.face? ? vec.copy : vec.float64.copy
166
+ end
167
+ pos = CArray.float64(n) { |i| i.to_f }
168
+ addr = pos[present].linear_section(pos) # valid positions -> monotonic grid
169
+ if vec.face?
170
+ # The Face's linear_fetch already masks the exterior (out of range) and
171
+ # lands on its own grid, so it needs no cast and no mask_invalid.
172
+ return vec[present].linear_fetch(addr)
173
+ end
174
+ vval = vec.value.float64[present] # valid values
175
+ vval.linear_fetch(addr).to_type(vec.data_type).mask_invalid
176
+ end
177
+
178
+ # Yield an index key (Array with `nil` at `axis`, integers elsewhere)
179
+ # for every fiber along `axis`. `self[*key]` is that fiber as a masked
180
+ # 1-D view.
181
+ def __each_fiber_key__ (axis)
182
+ outer = shape
183
+ outer_dims = outer.each_index.reject { |k| k == axis }.map { |k| outer[k] }
184
+ idx = Array.new(outer_dims.size, 0)
185
+ total = outer_dims.inject(1, :*)
186
+ total.times do
187
+ key = idx.dup
188
+ key.insert(axis, nil)
189
+ yield key
190
+ (outer_dims.size - 1).downto(0) do |k|
191
+ idx[k] += 1
192
+ break if idx[k] < outer_dims[k]
193
+ idx[k] = 0
194
+ end
195
+ end
196
+ end
197
+ private :__hold_axis__, :__gap_fill_linear__, :__linear_fiber__,
198
+ :__each_fiber_key__
199
+
200
+ end
data/lib/carray/math.rb CHANGED
@@ -1,169 +1,80 @@
1
- # ----------------------------------------------------------------------------
2
- #
3
- # carray/math.rb
4
- #
5
- # This file is part of Ruby/CArray extension library.
6
- #
7
- # Copyright (C) 2005-2020 Hiroki Motoyoshi
8
- #
9
- # ----------------------------------------------------------------------------
10
-
11
- class CArray
12
-
13
- # complex number
14
-
15
- # Return the real part of +self+.
16
- # If +self+ is a complex array, the resulted array is CAMember object
17
- # refers the appropriate part of +self+.
18
- # Otherwise, the resulted array is CARefer object refers +self+.
19
- # If you change the resulted array, the original array is also changed.
20
- #
21
- def real
22
- if not @__real__
23
- if complex?
24
- @__real__ = case data_type
25
- when CA_CMPLX64
26
- field(0, CA_FLOAT32)
27
- when CA_CMPLX128
28
- field(0, CA_FLOAT64)
29
- when CA_CMPLX128
30
- field(0, CA_FLOAT128)
31
- end
32
- else
33
- @__real__ = self[]
34
- end
35
- end
36
- @__real__
37
- end
38
-
39
- def real= (val)
40
- real[] = val
41
- end
42
-
43
- # Return the imaginary part of +self+.
44
- # If +self+ is a complex array, the resulted array is CAMember object
45
- # refers the appropriate part of +self+. In this case,
46
- # you change the resulted array, the original array is also changed.
47
- #
48
- # Otherwise, the resulted array is a dummy CArray object filled with 0.
49
- # In this case, the change in the resulted array does not affect
50
- # the original array. For this purpose, you should explicitly convert
51
- # the array to complex array.
52
- #
53
- def imag
54
- if not @__imag__
55
- if complex?
56
- @__imag__ = case data_type
57
- when CA_CMPLX64
58
- field(4, CA_FLOAT32)
59
- when CA_CMPLX128
60
- field(8, CA_FLOAT64)
61
- when CA_CMPLX128
62
- field(16, CA_FLOAT128)
63
- end
64
- else
65
- @__imag__ = self.template { 0 }
66
- end
67
- end
68
- return @__imag__
69
- end
70
-
71
- def imag= (val)
72
- if complex?
73
- imag[] = val
74
- else
75
- raise "not a complex array"
76
- end
77
- end
78
-
79
- # comparison operators
80
-
81
- def <=> (other)
82
- lower = self < other
83
- upper = self > other
84
- out = CArray.new(CA_INT8, lower.dim)
85
- out[lower] = -1
86
- out[upper] = 1
87
- return out
88
- end
89
-
90
- alias cmp <=>
91
-
92
- def is_equiv (other, rtol)
93
- exact_eq = self.eq(other)
94
- relative_eq = ((self - other).abs/CAMath.max(self.abs, other.abs) <= rtol)
95
- return (exact_eq).or(relative_eq)
96
- end
97
-
98
- def is_close (other, atol)
99
- return ((self - other).abs <= atol)
100
- end
101
-
102
- def is_divisible (n)
103
- unless integer?
104
- raise "data type of reciever of CArray#divisible? should be integer."
105
- end
106
- return (self % n).eq(0)
107
- end
108
-
109
- def is_not_divisible (n)
110
- unless integer?
111
- raise "data type of reciever of CArray#divisible? should be integer."
112
- end
113
- return (self % n).ne(0)
114
- end
115
-
116
- def real?
117
- if complex?
118
- imag.all_equal?(0)
119
- elsif numeric?
120
- true
121
- else
122
- nil
123
- end
124
- end
125
-
126
- def is_real
127
- if complex?
128
- imag.eq(0)
129
- elsif numeric?
130
- self.true
131
- else
132
- nil
133
- end
134
- end
135
-
136
- def sign
137
- out = self.zero
138
- out[self.lt(0)] = -1
139
- out[self.gt(0)] = 1
140
- if float?
141
- out[self.is_nan] = 0.0/0.0
142
- end
143
- return out
144
- end
145
-
146
- def quo (other)
147
- case
148
- when integer?
149
- return object.quo_i(other)
150
- when object?
151
- return quo_i(other)
152
- else
153
- return self/other
154
- end
155
- end
156
-
157
- end
158
-
159
-
160
1
  module CAMath
161
2
 
162
3
  module_function
163
4
 
5
+ # Module-function front-ends for binop math methods registered on
6
+ # CArray by mkkernel. The first argument is auto-wrapped to CArray
7
+ # via `CArray.wrap_readonly`, so `CAMath.hypot(3, arr)` continues to
8
+ # work. Integer input is unsupported at the kernel layer -- the
9
+ # caller must cast to float64 explicitly (e.g.
10
+ # `arr.as_float64.hypot(...)`).
11
+
12
+ # @overload expm1(x)
13
+ # Returns `exp(x) - 1` element-wise as float64.
14
+ # @param x [CArray, Numeric] input value.
15
+ # @return [CArray]
16
+ def expm1(x); CArray.wrap_readonly(x, :float64).expm1; end
17
+
18
+ # @overload log1p(x)
19
+ # Returns `log(1 + x)` element-wise as float64.
20
+ # @param x [CArray, Numeric] input value.
21
+ # @return [CArray]
22
+ def log1p(x); CArray.wrap_readonly(x, :float64).log1p; end
23
+
24
+ # @overload atan2(y, x)
25
+ # Returns the element-wise arc tangent of `y / x` with quadrant
26
+ # selection.
27
+ # @param y [CArray, Numeric] numerator.
28
+ # @param x [CArray, Numeric] denominator.
29
+ # @return [CArray]
30
+ def atan2(y, x); CArray.wrap_readonly(y, :float64).atan2(x); end
31
+
32
+ # @overload hypot(x, y)
33
+ # Returns the element-wise Euclidean distance `sqrt(x^2 + y^2)`.
34
+ # @param x [CArray, Numeric] first leg.
35
+ # @param y [CArray, Numeric] second leg.
36
+ # @return [CArray]
37
+ def hypot(x, y); CArray.wrap_readonly(x, :float64).hypot(y); end
38
+
39
+ # @overload copysign(x, y)
40
+ # Returns `|x|` with the sign of `y`, element-wise.
41
+ # @param x [CArray, Numeric] magnitude source.
42
+ # @param y [CArray, Numeric] sign source.
43
+ # @return [CArray]
44
+ def copysign(x, y); CArray.wrap_readonly(x, :float64).copysign(y); end
45
+
46
+ # @overload logaddexp(x, y)
47
+ # Returns `log(exp(x) + exp(y))` computed to avoid overflow,
48
+ # element-wise.
49
+ # @param x [CArray, Numeric] first log-space value.
50
+ # @param y [CArray, Numeric] second log-space value.
51
+ # @return [CArray]
52
+ def logaddexp(x, y); CArray.wrap_readonly(x, :float64).logaddexp(y); end
53
+
54
+ # @overload nextafter(x, y)
55
+ # Returns the next representable float from `x` toward `y`,
56
+ # element-wise.
57
+ # @param x [CArray, Numeric] starting value.
58
+ # @param y [CArray, Numeric] direction target.
59
+ # @return [CArray]
60
+ def nextafter(x, y); CArray.wrap_readonly(x, :float64).nextafter(y); end
61
+
62
+ # @overload fmod(x, y)
63
+ # Returns the C-style `fmod(x, y)` element-wise (sign follows `x`).
64
+ # @param x [CArray, Numeric] dividend.
65
+ # @param y [CArray, Numeric] divisor.
66
+ # @return [CArray]
67
+ def fmod(x, y); CArray.wrap_readonly(x, :float64).fmod(y); end
68
+
69
+ # @overload min(*argv)
70
+ # Returns the element-wise minimum of the given CArray and other
71
+ # arguments. At least one argument must be a CArray.
72
+ # @param argv [Array<CArray, Numeric>] operands.
73
+ # @return [CArray] fresh CArray holding the running min.
74
+ # @raise [RuntimeError] when no CArray argument is present.
164
75
  def min (*argv)
165
76
  if ary = argv.find{|x| x.is_a?(CArray) }
166
- out = ary.to_ca
77
+ out = ary.copy
167
78
  argv.delete(ary)
168
79
  argv.each do |x|
169
80
  out.pmin!(x)
@@ -174,9 +85,15 @@ module CAMath
174
85
  return out
175
86
  end
176
87
 
88
+ # @overload max(*argv)
89
+ # Returns the element-wise maximum of the given CArray and other
90
+ # arguments. At least one argument must be a CArray.
91
+ # @param argv [Array<CArray, Numeric>] operands.
92
+ # @return [CArray] fresh CArray holding the running max.
93
+ # @raise [RuntimeError] when no CArray argument is present.
177
94
  def max (*argv)
178
95
  if ary = argv.find{|x| x.is_a?(CArray) }
179
- out = ary.to_ca
96
+ out = ary.copy
180
97
  argv.delete(ary)
181
98
  argv.each do |x|
182
99
  out.pmax!(x)
@@ -188,184 +105,3 @@ module CAMath
188
105
  end
189
106
 
190
107
  end
191
-
192
- class CArray
193
-
194
- #
195
- # statistics
196
- #
197
-
198
- def random (*argv)
199
- return template.random!(*argv)
200
- end
201
-
202
- def randomn!
203
- if elements == 1
204
- self[0] = CArray.new(data_type,[2]).randomn![0]
205
- return self
206
- end
207
- x1 = CArray.new(data_type, [elements/2])
208
- x2 = CArray.new(data_type, [elements/2])
209
- fac = x1.random!.log!.mul!(-2.0).sqrt! ### fac = sqrt(-2*log(rnd()))
210
- x2.random!.mul!(2.0*Math::PI) ### x2 = 2*PI*rnd()
211
- x3 = x2.to_ca
212
- self2 = reshape(2,elements/2)
213
- self2[0,nil] = x2.cos!.mul!(fac) ### self[even] = fac*cos(x2)
214
- self2[1,nil] = x3.sin!.mul!(fac) ### self[odd] = fac*sin(x2)
215
- if elements % 2 == 1
216
- self[[-1]].randomn!
217
- end
218
- return self
219
- end
220
-
221
- def randomn
222
- return template.randomn!
223
- end
224
-
225
- def anomaly (*argv)
226
- opt = argv.last.is_a?(Hash) ? argv.pop : {}
227
- idxs = Array.new(self.ndim) { |i| argv.include?(i) ? :* : nil }
228
- if mn = opt[:mean]
229
- return self - mn[*idxs]
230
- else
231
- return self - self.mean(*argv)[*idxs]
232
- end
233
- end
234
-
235
- alias anom anomaly
236
-
237
- def median (*argv)
238
- opt = argv.last.is_a?(Hash) ? argv.pop : {}
239
- min_count = opt[:mask_limit]
240
- if min_count and min_count < 0
241
- min_count += elements
242
- end
243
- fill_value = opt[:fill_value]
244
- if argv.empty?
245
- if has_mask?
246
- if min_count and count_masked() > min_count
247
- return fill_value || UNDEF
248
- end
249
- c = self[:is_not_masked].sort
250
- n = self.count_not_masked
251
- else
252
- c = self.sort
253
- n = c.elements
254
- end
255
- if n == 0
256
- return fill_value || UNDEF
257
- else
258
- return (c[(n-1)/2] + c[n/2])/2.0
259
- end
260
- else
261
- raise "CArray#median is not implemented for multiple ndims"
262
- end
263
-
264
- end
265
-
266
- def percentile (*argv)
267
- opt = argv.last.is_a?(Hash) ? argv.pop : {}
268
- pers = argv
269
- min_count = opt[:mask_limit]
270
- if min_count and min_count < 0
271
- min_count += elements
272
- end
273
- fill_value = opt[:fill_value]
274
- if has_mask?
275
- if min_count and count_masked() > min_count
276
- return argv.map { fill_value || UNDEF }
277
- end
278
- ca = self[:is_not_masked].sort
279
- n = self.count_not_masked
280
- else
281
- ca = self.sort
282
- n = ca.elements
283
- end
284
- out = []
285
- begin
286
- pers.each do |per|
287
- if per == 100
288
- out << ca[n-1]
289
- elsif per >= 0 and per < 100
290
- if n > 1
291
- f = (n-1)*per/100.0
292
- k = f.floor
293
- r = f - k
294
- out << (1-r)*ca[k] + r*ca[k+1]
295
- else
296
- out << ca[0]
297
- end
298
- else
299
- out << CA_NAN
300
- end
301
- end
302
- end
303
- return out
304
- end
305
-
306
- def quantile
307
- return percentile(0, 25, 50, 75, 100)
308
- end
309
-
310
- def covariancep (y, min_count = nil, fill_value = nil)
311
- x = self.double
312
- y = y.double
313
- if x.has_mask? or y.has_mask?
314
- x.inherit_mask(y)
315
- y.inherit_mask(x)
316
- count = x.count_not_masked
317
- xm = x.mean(:min_count => min_count)
318
- ym = y.mean(:min_count => min_count)
319
- if ( xm == UNDEF or ym == UNDEF )
320
- return fill_value || UNDEF
321
- else
322
- return (x-xm).wsum(y-ym)/count
323
- end
324
- else
325
- return (x-x.mean).wsum(y-y.mean)/elements
326
- end
327
- end
328
-
329
- def covariance (y, min_count = nil, fill_value = nil)
330
- x = self.double
331
- y = y.double
332
- if x.has_mask? or y.has_mask?
333
- x.inherit_mask(y)
334
- y.inherit_mask(x)
335
- count = x.count_not_masked
336
- xm = x.mean(:min_count=>min_count)
337
- ym = y.mean(:min_count=>min_count)
338
- if ( xm == UNDEF or ym == UNDEF )
339
- return fill_value || UNDEF
340
- else
341
- return (x-xm).wsum(y-ym)/(count-1)
342
- end
343
- else
344
- return (x-x.mean).wsum(y-y.mean)/(elements-1)
345
- end
346
- end
347
-
348
- def correlation (y, min_count = nil, fill_value = nil)
349
- x = self.double
350
- y = y.double
351
- if x.has_mask? or y.has_mask?
352
- x.inherit_mask(y)
353
- y.inherit_mask(x)
354
- xm = x.mean(:min_count=>min_count)
355
- ym = y.mean(:min_count=>min_count)
356
- if ( xm == UNDEF or ym == UNDEF )
357
- return fill_value || UNDEF
358
- else
359
- xd, yd = x-xm, y-ym
360
- return xd.wsum(yd)/(xd.wsum(xd)*yd.wsum(yd)).sqrt
361
- end
362
- else
363
- xd, yd = x-x.mean, y-y.mean
364
- return xd.wsum(yd)/(xd.wsum(xd)*yd.wsum(yd)).sqrt
365
- end
366
- end
367
-
368
- end
369
-
370
-
371
-