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
data/ext/ca_obj_time.c ADDED
@@ -0,0 +1,546 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ ca_obj_time.c
4
+
5
+ CATime — semantic mask (Face) over int64 storage. Datetime
6
+ values represented as an int64 count in a chosen `unit`.
7
+
8
+ A Face is a mask of a semantic type (= same storage type, identifier +
9
+ unit layered on top); sibling to CAFake (= mask of data_type
10
+ conversion). Storage ops are thin-forwarded to the parent via the
11
+ ca_face_* helpers (ca_obj_face.h). The Ruby-side Comparable / to_time
12
+ / <=> surface lives in lib/carray/time.rb.
13
+
14
+ --------------------------------------------------------------------------- */
15
+
16
+ #include "carray.h"
17
+ #include "ca_obj_face.h"
18
+
19
+ /* unit enum (base epoch is 1970-01-01) */
20
+ enum {
21
+ CA_DATETIME_UNIT_Y = 0,
22
+ CA_DATETIME_UNIT_M = 1,
23
+ CA_DATETIME_UNIT_W = 2,
24
+ CA_DATETIME_UNIT_D = 3,
25
+ CA_DATETIME_UNIT_h = 4,
26
+ CA_DATETIME_UNIT_m = 5,
27
+ CA_DATETIME_UNIT_s = 6,
28
+ CA_DATETIME_UNIT_ms = 7,
29
+ CA_DATETIME_UNIT_us = 8,
30
+ CA_DATETIME_UNIT_ns = 9, /* pandas default */
31
+ CA_DATETIME_UNIT_ps = 10,
32
+ CA_DATETIME_UNIT_fs = 11,
33
+ CA_DATETIME_UNIT_as = 12
34
+ };
35
+
36
+ typedef struct {
37
+ /* === CAView prefix === */
38
+ int16_t obj_type;
39
+ int8_t data_type; /* fixed to CA_INT64 */
40
+ int8_t ndim;
41
+ int32_t flags; /* CA_FLAG_IS_FACE set */
42
+ ca_size_t bytes; /* fixed to sizeof(int64_t) */
43
+ ca_size_t elements;
44
+ ca_size_t *dim;
45
+ char *ptr;
46
+ CArray *mask;
47
+ char *_pool; /* framework-managed pool buffer (NULL = legacy ALLOC_N path). */
48
+ CArray *parent;
49
+ uint32_t attach;
50
+ uint8_t nosync;
51
+ /* === Face tail === */
52
+ int8_t unit; /* CA_DATETIME_UNIT_* (the tick base) */
53
+ int64_t count; /* tick multiplier N (tick = count * base) */
54
+ } CATime;
55
+
56
+ static size_t
57
+ ca_time_dsize (const void *ap)
58
+ {
59
+ const CATime *ca = (const CATime *) ap;
60
+ return sizeof(CATime) + ca->ndim * sizeof(ca_size_t);
61
+ }
62
+
63
+ /* Pool framework hooks. CATime owns a single ndim-sized tail
64
+ (dim) in the _pool buffer. No alloc collapse (1 tail), but routes the
65
+ class onto the uniform pool alloc/free discipline (ca_array_alloc /
66
+ ca_array_free). */
67
+ static size_t
68
+ ca_time_pool_bytes (int8_t ndim)
69
+ {
70
+ ca_size_t n = (ndim > 0) ? ndim : 1;
71
+ return (size_t) n * sizeof(ca_size_t);
72
+ }
73
+
74
+ static void
75
+ ca_time_pool_init (void *ap, int8_t ndim)
76
+ {
77
+ CATime *ca = (CATime *) ap;
78
+ ca->dim = (ca_size_t *) ca->_pool;
79
+ }
80
+
81
+ const rb_data_type_t catime_data_type = {
82
+ .parent = &caface_data_type,
83
+ .wrap_struct_name = "CATime",
84
+ .function = {
85
+ .dmark = ca_mark,
86
+ .dfree = ca_free,
87
+ .dsize = ca_time_dsize,
88
+ .dcompact = NULL
89
+ },
90
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
91
+ };
92
+
93
+ static int8_t CA_OBJ_TIME;
94
+ static VALUE rb_cCATime;
95
+ static VALUE rb_cCATimeElement;
96
+
97
+ /* forward decls (defined later in the file) */
98
+ int8_t ca_time_unit_value (VALUE sym);
99
+ VALUE ca_time_unit_to_symbol (int8_t unit);
100
+ VALUE ca_time_resolution (int64_t count, int8_t unit);
101
+ void ca_time_extract_unit (VALUE unit, int8_t *base, int64_t *count);
102
+
103
+ /* CATime::Element as a C TypedData struct: storing value + unit in
104
+ the struct avoids per-cell Ruby Integer boxing and Ruby `initialize`
105
+ dispatch on the fetch hot path. value is the raw parent int64 (= the
106
+ tick index under self's resolution); unit is the CA_DATETIME_UNIT_*
107
+ base enum and count is the tick multiplier (tick = count * base). */
108
+ typedef struct {
109
+ int64_t value;
110
+ int8_t unit;
111
+ int64_t count;
112
+ } CATimeElement;
113
+
114
+ static size_t
115
+ ca_time_element_dsize (const void *ap)
116
+ {
117
+ (void) ap;
118
+ return sizeof(CATimeElement);
119
+ }
120
+
121
+ static void
122
+ ca_time_element_free (void *ap)
123
+ {
124
+ if (ap) xfree(ap);
125
+ }
126
+
127
+ const rb_data_type_t catime_element_data_type = {
128
+ .wrap_struct_name = "CATime::Element",
129
+ .function = {
130
+ .dmark = NULL,
131
+ .dfree = ca_time_element_free,
132
+ .dsize = ca_time_element_dsize,
133
+ },
134
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
135
+ };
136
+
137
+ static VALUE
138
+ rb_ca_time_element_s_allocate (VALUE klass)
139
+ {
140
+ CATimeElement *s;
141
+ return TypedData_Make_Struct(klass, CATimeElement,
142
+ &catime_element_data_type, s);
143
+ }
144
+
145
+ static VALUE
146
+ rb_ca_time_element_initialize (VALUE self, VALUE value, VALUE unit)
147
+ {
148
+ CATimeElement *s;
149
+ TypedData_Get_Struct(self, CATimeElement,
150
+ &catime_element_data_type, s);
151
+ s->value = NUM2LL(value);
152
+ ca_time_extract_unit(unit, &s->unit, &s->count);
153
+ return self;
154
+ }
155
+
156
+ static VALUE
157
+ rb_ca_time_element_value (VALUE self)
158
+ {
159
+ CATimeElement *s;
160
+ TypedData_Get_Struct(self, CATimeElement,
161
+ &catime_element_data_type, s);
162
+ return LL2NUM(s->value);
163
+ }
164
+
165
+ /* unit → CATime::Resolution(count, base) */
166
+ static VALUE
167
+ rb_ca_time_element_unit (VALUE self)
168
+ {
169
+ CATimeElement *s;
170
+ TypedData_Get_Struct(self, CATimeElement,
171
+ &catime_element_data_type, s);
172
+ return ca_time_resolution(s->count, s->unit);
173
+ }
174
+
175
+ /* ------------------------------------------------------------------- */
176
+
177
+ int
178
+ ca_time_setup (CATime *ca, CArray *parent, int8_t unit, int64_t count)
179
+ {
180
+ if ( parent->data_type != CA_INT64 ) {
181
+ rb_raise(rb_eTypeError,
182
+ "CATime requires int64 storage (parent.data_type != CA_INT64)");
183
+ }
184
+
185
+ ca->obj_type = CA_OBJ_TIME;
186
+ /* The surface data_type is CA_FIXLEN, not CA_INT64: this routes
187
+ mkkernel dispatch onto the ca_*_not_implement stubs so numeric
188
+ kernels are gated off automatically. bytes stays at 8 to match the
189
+ parent int64 storage. */
190
+ ca->data_type = CA_FIXLEN;
191
+ /* ORDERABLE: int64 storage order == datetime <=> order, so sort family may
192
+ descend to storage. NOT COMPARABLE: an external query may carry a
193
+ different unit, so raw storage compare against a query is unsafe. */
194
+ ca->flags = CA_FLAG_IS_FACE | CA_FLAG_FACE_ORDERABLE_STORAGE;
195
+ ca->ndim = parent->ndim;
196
+ ca->bytes = sizeof(int64_t);
197
+ ca->elements = parent->elements;
198
+ ca->ptr = NULL;
199
+ ca->mask = NULL;
200
+ if ( ! ca->_pool ) {
201
+ ca->dim = ALLOC_N(ca_size_t, parent->ndim);
202
+ }
203
+ memcpy(ca->dim, parent->dim, sizeof(ca_size_t) * parent->ndim);
204
+
205
+ ca->parent = parent;
206
+ ca->attach = 0;
207
+ ca->nosync = 0;
208
+
209
+ ca->unit = unit;
210
+ ca->count = count;
211
+
212
+ if ( ca_has_mask(parent) ) {
213
+ ca_create_mask((CArray *) ca);
214
+ }
215
+
216
+ if ( ca_is_scalar(parent) ) {
217
+ ca_set_flag(ca, CA_FLAG_SCALAR);
218
+ }
219
+
220
+ if ( ca_test_flag(parent, CA_FLAG_READ_ONLY) ) {
221
+ ca_set_flag(ca, CA_FLAG_READ_ONLY);
222
+ }
223
+
224
+ return 0;
225
+ }
226
+
227
+ CATime *
228
+ ca_time_new (CArray *parent, int8_t unit, int64_t count)
229
+ {
230
+ CATime *ca = (CATime *) ca_array_alloc(CA_OBJ_TIME, parent->ndim);
231
+ ca_time_setup(ca, parent, unit, count);
232
+ return ca;
233
+ }
234
+
235
+ static void
236
+ free_ca_time (void *ap)
237
+ {
238
+ CATime *ca = (CATime *) ap;
239
+ if ( ca != NULL ) {
240
+ ca_free(ca->mask);
241
+ if ( ca->_pool ) {
242
+ ca_array_free(ca); /* dim lives in _pool */
243
+ }
244
+ else {
245
+ xfree(ca->dim);
246
+ xfree(ca);
247
+ }
248
+ }
249
+ }
250
+
251
+ /* ------------------------------------------------------------------- */
252
+
253
+ static void *
254
+ ca_time_func_clone (void *ap)
255
+ {
256
+ CATime *ca = (CATime *) ap;
257
+ return ca_time_new(ca->parent, ca->unit, ca->count);
258
+ }
259
+
260
+ static void
261
+ ca_time_func_allocate (void *ap)
262
+ {
263
+ CATime *ca = (CATime *) ap;
264
+ /* alias: parent attach + alias parent->ptr (= no malloc; Face has identical data) */
265
+ ca_attach(ca->parent);
266
+ ca->ptr = ca->parent->ptr;
267
+ }
268
+
269
+ static void
270
+ ca_time_func_create_mask (void *ap)
271
+ {
272
+ CATime *ca = (CATime *) ap;
273
+ ca_update_mask(ca->parent);
274
+ if ( ! ca->parent->mask ) {
275
+ ca_create_mask(ca->parent);
276
+ }
277
+ ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
278
+ CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
279
+ }
280
+
281
+ ca_operation_function_t ca_time_func = {
282
+ -1, /* CA_OBJ_TIME — filled by ca_install_obj_type */
283
+ CA_VIEW_ARRAY,
284
+ free_ca_time,
285
+ ca_time_func_clone,
286
+ ca_time_func_allocate,
287
+ ca_face_attach,
288
+ ca_face_sync,
289
+ ca_face_detach,
290
+ ca_face_fill_data,
291
+ ca_time_func_create_mask,
292
+ ca_face_xfer_index,
293
+ ca_face_xfer_addrs,
294
+ NULL, /* fold_stride: identity Face is not foldable */
295
+ ca_face_xfer_stride,
296
+ ca_face_xfer_all
297
+ };
298
+
299
+ /* ------------------------------------------------------------------- */
300
+
301
+ /* parse unit symbol → enum (also referenced by CATimedelta) */
302
+ int8_t
303
+ ca_time_unit_value (VALUE sym)
304
+ {
305
+ if ( NIL_P(sym) ) return CA_DATETIME_UNIT_ns; /* default: pandas-style */
306
+ if ( TYPE(sym) != T_SYMBOL ) {
307
+ rb_raise(rb_eArgError, "unit must be a Symbol (e.g. :ns, :us, :s, :D)");
308
+ }
309
+ ID id = SYM2ID(sym);
310
+ if ( id == rb_intern("Y") ) return CA_DATETIME_UNIT_Y;
311
+ if ( id == rb_intern("M") ) return CA_DATETIME_UNIT_M;
312
+ if ( id == rb_intern("W") ) return CA_DATETIME_UNIT_W;
313
+ if ( id == rb_intern("D") ) return CA_DATETIME_UNIT_D;
314
+ if ( id == rb_intern("h") ) return CA_DATETIME_UNIT_h;
315
+ if ( id == rb_intern("m") ) return CA_DATETIME_UNIT_m;
316
+ if ( id == rb_intern("s") ) return CA_DATETIME_UNIT_s;
317
+ if ( id == rb_intern("ms") ) return CA_DATETIME_UNIT_ms;
318
+ if ( id == rb_intern("us") ) return CA_DATETIME_UNIT_us;
319
+ if ( id == rb_intern("ns") ) return CA_DATETIME_UNIT_ns;
320
+ if ( id == rb_intern("ps") ) return CA_DATETIME_UNIT_ps;
321
+ if ( id == rb_intern("fs") ) return CA_DATETIME_UNIT_fs;
322
+ if ( id == rb_intern("as") ) return CA_DATETIME_UNIT_as;
323
+ rb_raise(rb_eArgError, "unknown datetime unit: %"PRIsVALUE, sym);
324
+ return 0; /* unreachable */
325
+ }
326
+
327
+ VALUE
328
+ ca_time_unit_to_symbol (int8_t unit)
329
+ {
330
+ switch (unit) {
331
+ case CA_DATETIME_UNIT_Y: return ID2SYM(rb_intern("Y"));
332
+ case CA_DATETIME_UNIT_M: return ID2SYM(rb_intern("M"));
333
+ case CA_DATETIME_UNIT_W: return ID2SYM(rb_intern("W"));
334
+ case CA_DATETIME_UNIT_D: return ID2SYM(rb_intern("D"));
335
+ case CA_DATETIME_UNIT_h: return ID2SYM(rb_intern("h"));
336
+ case CA_DATETIME_UNIT_m: return ID2SYM(rb_intern("m"));
337
+ case CA_DATETIME_UNIT_s: return ID2SYM(rb_intern("s"));
338
+ case CA_DATETIME_UNIT_ms: return ID2SYM(rb_intern("ms"));
339
+ case CA_DATETIME_UNIT_us: return ID2SYM(rb_intern("us"));
340
+ case CA_DATETIME_UNIT_ns: return ID2SYM(rb_intern("ns"));
341
+ case CA_DATETIME_UNIT_ps: return ID2SYM(rb_intern("ps"));
342
+ case CA_DATETIME_UNIT_fs: return ID2SYM(rb_intern("fs"));
343
+ case CA_DATETIME_UNIT_as: return ID2SYM(rb_intern("as"));
344
+ }
345
+ return Qnil;
346
+ }
347
+
348
+ /* Build a CATime::Resolution(count, base) descriptor. Shared by
349
+ CATime and CATimedelta (the descriptor type is nested under
350
+ CATime and carries no group-specific state). */
351
+ VALUE
352
+ ca_time_resolution (int64_t count, int8_t unit)
353
+ {
354
+ VALUE rescls = rb_const_get(rb_cCATime, rb_intern("Resolution"));
355
+ return rb_funcall(rescls, rb_intern("new"), 2,
356
+ LL2NUM(count), ca_time_unit_to_symbol(unit));
357
+ }
358
+
359
+ /* Normalize a unit spec (Symbol / String / Resolution / nil) into a base
360
+ enum + count multiplier. nil defaults to (1, :ns); a bare Symbol is the
361
+ count-1 shorthand; a String / Resolution routes through Resolution.parse. */
362
+ void
363
+ ca_time_extract_unit (VALUE unit, int8_t *base, int64_t *count)
364
+ {
365
+ if ( NIL_P(unit) ) {
366
+ *base = CA_DATETIME_UNIT_ns;
367
+ *count = 1;
368
+ return;
369
+ }
370
+ if ( TYPE(unit) == T_SYMBOL ) {
371
+ *base = ca_time_unit_value(unit);
372
+ *count = 1;
373
+ return;
374
+ }
375
+ VALUE rescls = rb_const_get(rb_cCATime, rb_intern("Resolution"));
376
+ VALUE res = RTEST(rb_obj_is_kind_of(unit, rescls))
377
+ ? unit
378
+ : rb_funcall(rescls, rb_intern("parse"), 1, unit);
379
+ *base = ca_time_unit_value(rb_funcall(res, rb_intern("base"), 0));
380
+ *count = NUM2LL(rb_funcall(res, rb_intern("count"), 0));
381
+ }
382
+
383
+ /* CATime.wrap(int64_array, base_enum, count) — zero-copy Face wrap.
384
+ The public unit-spec normalization (Symbol / String / Resolution) is done
385
+ on the Ruby side; this primitive takes the resolved base enum + count. */
386
+ VALUE
387
+ rb_ca_time_wrap (VALUE parent_val, int8_t unit, int64_t count)
388
+ {
389
+ volatile VALUE obj;
390
+ CArray *parent;
391
+ CATime *ca;
392
+
393
+ rb_check_carray_object(parent_val);
394
+ TypedData_Get_Struct(parent_val, CArray, &carray_data_type, parent);
395
+
396
+ ca = ca_time_new(parent, unit, count);
397
+ obj = ca_wrap_struct(ca);
398
+ rb_ca_set_parent(obj, parent_val);
399
+ return obj;
400
+ }
401
+
402
+ /* __wrap__(raw, unit_spec) — primitive; unit_spec is Symbol / String /
403
+ Resolution / nil (normalized here). */
404
+ static VALUE
405
+ rb_ca_time_wrap_method (VALUE klass, VALUE raw, VALUE unit_spec)
406
+ {
407
+ int8_t base;
408
+ int64_t count;
409
+ (void) klass;
410
+ ca_time_extract_unit(unit_spec, &base, &count);
411
+ return rb_ca_time_wrap(raw, base, count);
412
+ }
413
+
414
+ /* CATime#unit → CATime::Resolution(count, base) */
415
+ static VALUE
416
+ rb_ca_time_unit (VALUE self)
417
+ {
418
+ CATime *ca;
419
+ TypedData_Get_Struct(self, CATime, &catime_data_type, ca);
420
+ return ca_time_resolution(ca->count, ca->unit);
421
+ }
422
+
423
+ /* storage_to_scalar implemented in C to avoid per-cell Ruby method dispatch
424
+ on the fetch hot path. CAREFUL: there must be no Ruby `storage_to_scalar`
425
+ def in lib/carray/time.rb — require order would let a Ruby version
426
+ shadow this C method (the Ruby `scalar_to_storage` write hook is a
427
+ distinct method and does not collide).
428
+ Since the Face surface is CA_FIXLEN, fetch delivers an 8-byte raw
429
+ String. Decode it as the parent int64 (= storage), then construct
430
+ CATime::Element(epoch, unit). */
431
+ static VALUE
432
+ rb_ca_time_storage_to_scalar (VALUE self, VALUE raw)
433
+ {
434
+ CATime *ca;
435
+ CATimeElement *s;
436
+ VALUE scalar_obj;
437
+ int64_t epoch;
438
+
439
+ TypedData_Get_Struct(self, CATime, &catime_data_type, ca);
440
+
441
+ if ( TYPE(raw) == T_STRING ) {
442
+ if ( RSTRING_LEN(raw) != (long) sizeof(int64_t) ) {
443
+ rb_raise(rb_eArgError,
444
+ "CATime#storage_to_scalar: expected %lu bytes, got %ld",
445
+ (unsigned long) sizeof(int64_t), RSTRING_LEN(raw));
446
+ }
447
+ memcpy(&epoch, RSTRING_PTR(raw), sizeof(int64_t));
448
+ }
449
+ else {
450
+ epoch = NUM2LL(raw);
451
+ }
452
+
453
+ /* Direct alloc + struct field write — no LL2NUM, no rb_class_new_instance,
454
+ no Ruby initialize dispatch. */
455
+ scalar_obj = TypedData_Make_Struct(rb_cCATimeElement,
456
+ CATimeElement,
457
+ &catime_element_data_type, s);
458
+ s->value = epoch;
459
+ s->unit = ca->unit;
460
+ s->count = ca->count;
461
+ return scalar_obj;
462
+ }
463
+
464
+ static VALUE
465
+ rb_ca_time_s_allocate (VALUE klass)
466
+ {
467
+ CATime *ca;
468
+ return TypedData_Make_Struct(klass, CATime,
469
+ &catime_data_type, ca);
470
+ }
471
+
472
+ static VALUE
473
+ rb_ca_time_initialize_copy (VALUE self, VALUE other)
474
+ {
475
+ CATime *ca, *cs;
476
+ TypedData_Get_Struct(self, CATime, &catime_data_type, ca);
477
+ TypedData_Get_Struct(other, CATime, &catime_data_type, cs);
478
+ if ( ca_func[CA_OBJ_TIME].pool_init ) {
479
+ ca_array_pool_alloc(ca, CA_OBJ_TIME, cs->parent->ndim);
480
+ }
481
+ ca_time_setup(ca, cs->parent, cs->unit, cs->count);
482
+ return self;
483
+ }
484
+
485
+ /* Face state homogeneity check — two CATime instances are
486
+ compatible iff their resolution (base + count) matches. */
487
+ static int
488
+ ca_time_state_compatible (CArray *a, CArray *b)
489
+ {
490
+ CATime *da = (CATime *) a;
491
+ CATime *db = (CATime *) b;
492
+ return ( da->unit == db->unit && da->count == db->count ) ? 1 : 0;
493
+ }
494
+
495
+ void
496
+ Init_ca_obj_time (void)
497
+ {
498
+ rb_cCATime = rb_define_class("CATime", rb_cCAFace);
499
+
500
+ ca_time_func.struct_size = sizeof(CATime);
501
+ ca_time_func.pool_bytes = ca_time_pool_bytes;
502
+ ca_time_func.pool_init = ca_time_pool_init;
503
+
504
+ CA_OBJ_TIME = ca_install_obj_type(rb_cCATime,
505
+ &catime_data_type,
506
+ rb_cCArrayMask,
507
+ &carray_mask_data_type,
508
+ &ca_time_func, sizeof(ca_time_func));
509
+ rb_define_const(rb_cObject, "CA_OBJ_TIME", INT2NUM(CA_OBJ_TIME));
510
+
511
+ rb_define_alloc_func(rb_cCATime, rb_ca_time_s_allocate);
512
+ rb_define_method(rb_cCATime, "initialize_copy",
513
+ rb_ca_time_initialize_copy, 1);
514
+
515
+ rb_define_singleton_method(rb_cCATime, "__wrap__",
516
+ rb_ca_time_wrap_method, 2);
517
+ rb_define_method(rb_cCATime, "unit", rb_ca_time_unit, 0);
518
+ rb_define_method(rb_cCATime, "storage_to_scalar",
519
+ rb_ca_time_storage_to_scalar, 1);
520
+ /* Registers the C-level fast path so CA_FACE_STORAGE_TO_SCALAR_IF_FACE can
521
+ skip rb_funcall on the hot path. */
522
+ ca_face_register_storage_to_scalar(CA_OBJ_TIME,
523
+ rb_ca_time_storage_to_scalar);
524
+ ca_face_register_state_compatible(CA_OBJ_TIME,
525
+ ca_time_state_compatible);
526
+ /* unit is pure metadata (= no per-parent buffer), so the Face wrap can
527
+ be carried across multi-parent constructions like CAStack
528
+ (portable = 1). */
529
+ ca_face_register_state_portable(CA_OBJ_TIME, 1);
530
+
531
+ /* CATime::Element as a C-backed TypedData class. The Ruby-side
532
+ definition in lib/carray/time.rb keeps the Comparable include +
533
+ to_time / to_s / inspect / <=> / == methods; the C side owns the
534
+ storage (int64 value + int8 unit) and the allocator + initialize +
535
+ value + unit accessors. */
536
+ rb_cCATimeElement = rb_define_class_under(rb_cCATime,
537
+ "Element", rb_cObject);
538
+ rb_define_alloc_func(rb_cCATimeElement,
539
+ rb_ca_time_element_s_allocate);
540
+ rb_define_method(rb_cCATimeElement, "initialize",
541
+ rb_ca_time_element_initialize, 2);
542
+ rb_define_method(rb_cCATimeElement, "value",
543
+ rb_ca_time_element_value, 0);
544
+ rb_define_method(rb_cCATimeElement, "unit",
545
+ rb_ca_time_element_unit, 0);
546
+ }