carray 2.0.1 → 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 +772 -297
  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 +229 -791
  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 +207 -240
  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 -329
  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 +1341 -198
  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 +5 -15
  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/mailmap +0 -1
  269. data/misc/Methods.ja.md +0 -182
  270. data/misc/NOTE +0 -51
  271. data/spec/Classes/CABitfield_spec.rb +0 -58
  272. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  273. data/spec/Classes/CABlock_spec.rb +0 -205
  274. data/spec/Classes/CAField_spec.rb +0 -39
  275. data/spec/Classes/CAGrid_spec.rb +0 -75
  276. data/spec/Classes/CAMap_spec.rb +0 -0
  277. data/spec/Classes/CAMapping_spec.rb +0 -105
  278. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  279. data/spec/Classes/CAObject_spec.rb +0 -33
  280. data/spec/Classes/CARefer_spec.rb +0 -93
  281. data/spec/Classes/CARepeat_spec.rb +0 -65
  282. data/spec/Classes/CASelect_spec.rb +0 -22
  283. data/spec/Classes/CAShift_spec.rb +0 -16
  284. data/spec/Classes/CAStruct_spec.rb +0 -71
  285. data/spec/Classes/CATranspose_spec.rb +0 -60
  286. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  287. data/spec/Classes/CAWindow_spec.rb +0 -54
  288. data/spec/Classes/CAWrap_spec.rb +0 -8
  289. data/spec/Classes/CArray_spec.rb +0 -184
  290. data/spec/Classes/CScalar_spec.rb +0 -55
  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_compare.c ADDED
@@ -0,0 +1,94 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Shared element comparators by data_type (see ca_compare.h). The per-type
4
+ comparators take the (const void *, const void *) prototype directly, so
5
+ the dispatch table needs no function-pointer casts.
6
+
7
+ Internal C API (no Ruby surface). Indexed by data_type id via
8
+ `ca_elem_cmp[data_type]`. Callers include sort_addr_cmp
9
+ (carray_sort.c) and the comparator-based ca_quickselect_bytes path
10
+ (carray_partition.c).
11
+
12
+ --------------------------------------------------------------------------- */
13
+
14
+ #include "ruby.h"
15
+ #include "carray.h"
16
+ #include "ca_compare.h"
17
+ #include <math.h>
18
+
19
+ #define DEFINE_ELEM_CMP(type) \
20
+ static int \
21
+ elem_cmp_## type (const void *va, const void *vb) \
22
+ { \
23
+ const type *a = (const type *) va; \
24
+ const type *b = (const type *) vb; \
25
+ if ( *a > *b ) return 1; \
26
+ if ( *a < *b ) return -1; \
27
+ return 0; \
28
+ }
29
+
30
+ /* Float order: NaN sorts last (matches the sort kernels' NaN-at-end). */
31
+ #define DEFINE_ELEM_CMP_FLOAT(type) \
32
+ static int \
33
+ elem_cmp_## type (const void *va, const void *vb) \
34
+ { \
35
+ const type *a = (const type *) va; \
36
+ const type *b = (const type *) vb; \
37
+ if ( isnan(*a) && ( ! isnan(*b) ) ) return 1; \
38
+ if ( isnan(*b) && ( ! isnan(*a) ) ) return -1; \
39
+ if ( *a > *b ) return 1; \
40
+ if ( *a < *b ) return -1; \
41
+ return 0; \
42
+ }
43
+
44
+ DEFINE_ELEM_CMP(boolean8_t)
45
+ DEFINE_ELEM_CMP(int8_t)
46
+ DEFINE_ELEM_CMP(uint8_t)
47
+ DEFINE_ELEM_CMP(int16_t)
48
+ DEFINE_ELEM_CMP(uint16_t)
49
+ DEFINE_ELEM_CMP(int32_t)
50
+ DEFINE_ELEM_CMP(uint32_t)
51
+ DEFINE_ELEM_CMP(int64_t)
52
+ DEFINE_ELEM_CMP(uint64_t)
53
+ DEFINE_ELEM_CMP_FLOAT(float32_t)
54
+ DEFINE_ELEM_CMP_FLOAT(float64_t)
55
+
56
+ /* CA_OBJECT: compare via Ruby Comparable (`<=>`). */
57
+ static int
58
+ elem_cmp_VALUE (const void *va, const void *vb)
59
+ {
60
+ const VALUE *a = (const VALUE *) va;
61
+ const VALUE *b = (const VALUE *) vb;
62
+ return NUM2INT(rb_funcall(*a, rb_intern("<=>"), 1, *b));
63
+ }
64
+
65
+ /* FIXLEN / retired / otherwise unorderable data_types: callers must handle
66
+ these themselves; reaching the table for them is a bug. */
67
+ static int
68
+ elem_cmp_unsupported (const void *va, const void *vb)
69
+ {
70
+ (void) va; (void) vb;
71
+ rb_raise(rb_eNotImpError,
72
+ "element comparison is not implemented for the data type");
73
+ }
74
+
75
+ ca_cmp_func
76
+ ca_elem_cmp[CA_NTYPE] = {
77
+ elem_cmp_unsupported, /* CA_FIXLEN -- caller compares packed blobs itself */
78
+ elem_cmp_boolean8_t,
79
+ elem_cmp_int8_t,
80
+ elem_cmp_uint8_t,
81
+ elem_cmp_int16_t,
82
+ elem_cmp_uint16_t,
83
+ elem_cmp_int32_t,
84
+ elem_cmp_uint32_t,
85
+ elem_cmp_int64_t,
86
+ elem_cmp_uint64_t,
87
+ elem_cmp_float32_t,
88
+ elem_cmp_float64_t,
89
+ elem_cmp_unsupported, /* float128_t -- not supported */
90
+ elem_cmp_unsupported,
91
+ elem_cmp_unsupported,
92
+ elem_cmp_unsupported, /* cmplx256_t -- not supported */
93
+ elem_cmp_VALUE,
94
+ };
data/ext/ca_compare.h ADDED
@@ -0,0 +1,26 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Element comparators by data_type: a 3-way compare (-1 / 0 / +1) of two
4
+ same-typed cells, with the (const void *, const void *) prototype that
5
+ libc qsort / bsearch expect. This is a shared *ordering primitive*, not
6
+ tied to any one algorithm: the index sort (carray_sort.c) and the binary
7
+ search (carray_order.c) both dispatch through ca_elem_cmp[data_type].
8
+
9
+ CA_FIXLEN (packed byte blobs) is intentionally `unsupported` in the table:
10
+ a 2-arg comparator cannot carry the element byte width, so each caller
11
+ compares fixlen cells itself (carray_order.c via a cmp_data wrapper for
12
+ bsearch; carray_sort.c via a direct memcmp). Float slots order NaN last.
13
+
14
+ --------------------------------------------------------------------------- */
15
+
16
+ #ifndef CA_COMPARE_H
17
+ #define CA_COMPARE_H
18
+
19
+ /* 3-way element comparator, qsort/bsearch-compatible signature. */
20
+ typedef int (*ca_cmp_func)(const void *, const void *);
21
+
22
+ /* Per-data_type element comparators, indexed by data_type (CA_NTYPE wide).
23
+ FIXLEN / retired / unused slots hold an unsupported stub that raises. */
24
+ extern ca_cmp_func ca_elem_cmp[CA_NTYPE];
25
+
26
+ #endif /* CA_COMPARE_H */
@@ -0,0 +1,414 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Geometric primitives for region-mapped views (CAWindow / CATile /
4
+ CARoll): per-region strided gather, scatter, and broadcast fill.
5
+ See ca_composite_dispatch.h for the full per-function API contract.
6
+
7
+ Routines here are pure C, no Ruby VALUE handling. They operate on
8
+ raw pointers + byte stride arrays. Caller is responsible for parent
9
+ attach state and output buffer allocation.
10
+
11
+ ---------------------------------------------------------------------------- */
12
+
13
+ #include "ca_composite_dispatch.h"
14
+ #include <string.h>
15
+
16
+ /* --------------------------------------------------------------------- */
17
+ /* ca_fill_typed */
18
+ /* */
19
+ /* Per-size typed-store loops let the compiler autovectorize (NEON / */
20
+ /* SSE), converting N tight memcpy(bytes) calls into one O(N) SIMD'd */
21
+ /* typed-store loop. Generic memcpy fallback covers CA_FIXLEN and */
22
+ /* unusual widths. */
23
+ /* --------------------------------------------------------------------- */
24
+
25
+ void
26
+ ca_fill_typed (char *dst, const char *val, ca_size_t bytes, ca_size_t n)
27
+ {
28
+ ca_size_t i;
29
+ switch ( bytes ) {
30
+ case 1: {
31
+ memset(dst, *(const unsigned char *)val, n);
32
+ break;
33
+ }
34
+ case 2: {
35
+ uint16_t v = *(const uint16_t *)val;
36
+ uint16_t *p = (uint16_t *)dst;
37
+ for ( i = 0; i < n; i++ ) p[i] = v;
38
+ break;
39
+ }
40
+ case 4: {
41
+ uint32_t v = *(const uint32_t *)val;
42
+ uint32_t *p = (uint32_t *)dst;
43
+ for ( i = 0; i < n; i++ ) p[i] = v;
44
+ break;
45
+ }
46
+ case 8: {
47
+ uint64_t v = *(const uint64_t *)val;
48
+ uint64_t *p = (uint64_t *)dst;
49
+ for ( i = 0; i < n; i++ ) p[i] = v;
50
+ break;
51
+ }
52
+ case 16: {
53
+ /* complex128 etc. Two uint64_t stores per element. Compiler
54
+ pairs them into a NEON 128-bit or SSE2 store. */
55
+ uint64_t v0 = ((const uint64_t *)val)[0];
56
+ uint64_t v1 = ((const uint64_t *)val)[1];
57
+ uint64_t *p = (uint64_t *)dst;
58
+ for ( i = 0; i < n; i++ ) {
59
+ p[2*i] = v0;
60
+ p[2*i + 1] = v1;
61
+ }
62
+ break;
63
+ }
64
+ default: {
65
+ /* Generic fallback: CA_FIXLEN (struct types), unusual widths. */
66
+ for ( i = 0; i < n; i++ ) memcpy(dst + i * bytes, val, bytes);
67
+ break;
68
+ }
69
+ }
70
+ }
71
+
72
+ /* --------------------------------------------------------------------- */
73
+ /* ca_composite_region_gather */
74
+ /* */
75
+ /* Per-region strided memcpy from a parent sub-rectangle to an output */
76
+ /* sub-rectangle, with 1D / 2D / N-D fast paths. */
77
+ /* --------------------------------------------------------------------- */
78
+
79
+ void
80
+ ca_composite_region_gather (char *parent_ptr,
81
+ const ca_size_t *parent_strides,
82
+ const ca_size_t *parent_start,
83
+ char *out_ptr,
84
+ const ca_size_t *output_strides,
85
+ const ca_size_t *output_offset,
86
+ const ca_size_t *count,
87
+ int8_t ndim,
88
+ ca_size_t bytes)
89
+ {
90
+ ca_size_t idx[CA_RANK_MAX];
91
+ ca_size_t parent_off, output_off, run_bytes, total_slabs, slab;
92
+ int8_t k;
93
+ int8_t outer_axes;
94
+
95
+ /* Initial byte offsets into parent and output. */
96
+ parent_off = 0;
97
+ output_off = 0;
98
+ for ( k = 0; k < ndim; k++ ) {
99
+ parent_off += parent_start[k] * parent_strides[k];
100
+ output_off += output_offset[k] * output_strides[k];
101
+ idx[k] = 0;
102
+ }
103
+
104
+ /* Innermost axis contributes the contig run; outer axes are walked. */
105
+ run_bytes = count[ndim - 1] * bytes;
106
+ outer_axes = ndim - 1;
107
+
108
+ if ( outer_axes <= 0 ) {
109
+ /* 1-D shortcut: single memcpy. */
110
+ memcpy(out_ptr + output_off, parent_ptr + parent_off, run_bytes);
111
+ return;
112
+ }
113
+
114
+ if ( outer_axes == 1 ) {
115
+ /* 2-D fast path: single outer axis, pointer-advancing loop. No
116
+ multi-dim cursor, no idx[] array — keeps the per-iter body tight
117
+ so SIMD-friendly memcpy can dominate. */
118
+ char *src = parent_ptr + parent_off;
119
+ char *dst = out_ptr + output_off;
120
+ ca_size_t step_p = parent_strides[0];
121
+ ca_size_t step_o = output_strides[0];
122
+ ca_size_t count0 = count[0];
123
+ ca_size_t i;
124
+ for ( i = 0; i < count0; i++ ) {
125
+ memcpy(dst, src, run_bytes);
126
+ dst += step_o;
127
+ src += step_p;
128
+ }
129
+ return;
130
+ }
131
+
132
+ /* General N-D path (ndim >= 3): multi-dim cursor walk over outer axes. */
133
+ total_slabs = 1;
134
+ for ( k = 0; k < outer_axes; k++ ) {
135
+ total_slabs *= count[k];
136
+ }
137
+
138
+ for ( slab = 0; slab < total_slabs; slab++ ) {
139
+ memcpy(out_ptr + output_off, parent_ptr + parent_off, run_bytes);
140
+
141
+ /* Increment the multi-dim cursor (row-major, outer axes only). */
142
+ for ( k = outer_axes - 1; k >= 0; k-- ) {
143
+ idx[k]++;
144
+ parent_off += parent_strides[k];
145
+ output_off += output_strides[k];
146
+ if ( idx[k] < count[k] ) break;
147
+ parent_off -= parent_strides[k] * count[k];
148
+ output_off -= output_strides[k] * count[k];
149
+ idx[k] = 0;
150
+ }
151
+ }
152
+ }
153
+
154
+ /* --------------------------------------------------------------------- */
155
+ /* ca_composite_region_scatter */
156
+ /* */
157
+ /* Reverse direction of _gather: copies an input sub-rectangle back into */
158
+ /* a parent sub-rectangle (in_ptr -> parent_ptr). */
159
+ /* --------------------------------------------------------------------- */
160
+
161
+ void
162
+ ca_composite_region_scatter (char *parent_ptr,
163
+ const ca_size_t *parent_strides,
164
+ const ca_size_t *parent_start,
165
+ const char *in_ptr,
166
+ const ca_size_t *input_strides,
167
+ const ca_size_t *input_offset,
168
+ const ca_size_t *count,
169
+ int8_t ndim,
170
+ ca_size_t bytes)
171
+ {
172
+ ca_size_t idx[CA_RANK_MAX];
173
+ ca_size_t parent_off, input_off, run_bytes, total_slabs, slab;
174
+ int8_t k;
175
+ int8_t outer_axes;
176
+
177
+ parent_off = 0;
178
+ input_off = 0;
179
+ for ( k = 0; k < ndim; k++ ) {
180
+ parent_off += parent_start[k] * parent_strides[k];
181
+ input_off += input_offset[k] * input_strides[k];
182
+ idx[k] = 0;
183
+ }
184
+
185
+ run_bytes = count[ndim - 1] * bytes;
186
+ outer_axes = ndim - 1;
187
+
188
+ if ( outer_axes <= 0 ) {
189
+ memcpy(parent_ptr + parent_off, in_ptr + input_off, run_bytes);
190
+ return;
191
+ }
192
+
193
+ if ( outer_axes == 1 ) {
194
+ char *dst = parent_ptr + parent_off;
195
+ const char *src = in_ptr + input_off;
196
+ ca_size_t step_p = parent_strides[0];
197
+ ca_size_t step_i = input_strides[0];
198
+ ca_size_t count0 = count[0];
199
+ ca_size_t i;
200
+ for ( i = 0; i < count0; i++ ) {
201
+ memcpy(dst, src, run_bytes);
202
+ dst += step_p;
203
+ src += step_i;
204
+ }
205
+ return;
206
+ }
207
+
208
+ total_slabs = 1;
209
+ for ( k = 0; k < outer_axes; k++ ) {
210
+ total_slabs *= count[k];
211
+ }
212
+
213
+ for ( slab = 0; slab < total_slabs; slab++ ) {
214
+ memcpy(parent_ptr + parent_off, in_ptr + input_off, run_bytes);
215
+
216
+ for ( k = outer_axes - 1; k >= 0; k-- ) {
217
+ idx[k]++;
218
+ parent_off += parent_strides[k];
219
+ input_off += input_strides[k];
220
+ if ( idx[k] < count[k] ) break;
221
+ parent_off -= parent_strides[k] * count[k];
222
+ input_off -= input_strides[k] * count[k];
223
+ idx[k] = 0;
224
+ }
225
+ }
226
+ }
227
+
228
+ /* --------------------------------------------------------------------- */
229
+ /* ca_composite_fill_rect */
230
+ /* */
231
+ /* Fill a rectangle sub-region of out_ptr with `fill_value` (broadcast). */
232
+ /* Mirrors _region_gather but with a fixed source value (no source */
233
+ /* pointer/strides). 1D / 2D / N-D fast paths. */
234
+ /* --------------------------------------------------------------------- */
235
+
236
+ void
237
+ ca_composite_fill_rect (char *out_ptr,
238
+ const ca_size_t *output_strides,
239
+ const ca_size_t *offset,
240
+ const ca_size_t *count,
241
+ const char *fill_value,
242
+ ca_size_t bytes,
243
+ int8_t ndim)
244
+ {
245
+ ca_size_t idx[CA_RANK_MAX];
246
+ ca_size_t output_off, total_slabs, slab;
247
+ int8_t k;
248
+ int8_t outer_axes;
249
+ ca_size_t inner_count;
250
+
251
+ /* Initial byte offset into output. */
252
+ output_off = 0;
253
+ for ( k = 0; k < ndim; k++ ) {
254
+ output_off += offset[k] * output_strides[k];
255
+ idx[k] = 0;
256
+ }
257
+
258
+ /* Innermost axis = SIMD typed fill of `count[ndim-1]` cells per slab. */
259
+ inner_count = count[ndim - 1];
260
+ outer_axes = ndim - 1;
261
+
262
+ /* Early exit on empty inner. */
263
+ if ( inner_count <= 0 ) return;
264
+
265
+ if ( outer_axes <= 0 ) {
266
+ /* 1-D: single typed-fill. */
267
+ ca_fill_typed(out_ptr + output_off, fill_value, bytes, inner_count);
268
+ return;
269
+ }
270
+
271
+ if ( outer_axes == 1 ) {
272
+ /* 2-D fast path. */
273
+ ca_size_t step_o = output_strides[0];
274
+ ca_size_t count0 = count[0];
275
+ if ( count0 <= 0 ) return;
276
+ /* Contig-in-output detection: if successive "rows" of the strip
277
+ are adjacent in output memory (= step_o == inner_count * bytes),
278
+ merge into a single big typed-fill so SIMD bandwidth is fully used.
279
+ For complement-fill axis-0 strips this case fires (= the strip spans
280
+ the full inner extent of output along the rows it covers). */
281
+ if ( step_o == inner_count * bytes ) {
282
+ ca_fill_typed(out_ptr + output_off, fill_value, bytes,
283
+ count0 * inner_count);
284
+ return;
285
+ }
286
+ /* Generic per-row fill. */
287
+ {
288
+ char *dst = out_ptr + output_off;
289
+ ca_size_t i;
290
+ for ( i = 0; i < count0; i++ ) {
291
+ ca_fill_typed(dst, fill_value, bytes, inner_count);
292
+ dst += step_o;
293
+ }
294
+ }
295
+ return;
296
+ }
297
+
298
+ /* General N-D path (ndim >= 3): collapse all trailing axes whose
299
+ count == output_dim (= step matches contig stride) into the inner
300
+ run, walk only the truly outer axes via multi-dim cursor. */
301
+ {
302
+ int8_t walk_axes = outer_axes;
303
+ ca_size_t merged_inner = inner_count;
304
+ while ( walk_axes > 0
305
+ && output_strides[walk_axes - 1] == merged_inner * bytes
306
+ && count[walk_axes - 1] > 0 ) {
307
+ merged_inner *= count[walk_axes - 1];
308
+ walk_axes--;
309
+ }
310
+
311
+ if ( walk_axes == 0 ) {
312
+ /* Whole strip is contig in output. */
313
+ ca_fill_typed(out_ptr + output_off, fill_value, bytes, merged_inner);
314
+ return;
315
+ }
316
+
317
+ total_slabs = 1;
318
+ for ( k = 0; k < walk_axes; k++ ) {
319
+ if ( count[k] <= 0 ) return;
320
+ total_slabs *= count[k];
321
+ }
322
+
323
+ for ( slab = 0; slab < total_slabs; slab++ ) {
324
+ ca_fill_typed(out_ptr + output_off, fill_value, bytes, merged_inner);
325
+
326
+ for ( k = walk_axes - 1; k >= 0; k-- ) {
327
+ idx[k]++;
328
+ output_off += output_strides[k];
329
+ if ( idx[k] < count[k] ) break;
330
+ output_off -= output_strides[k] * count[k];
331
+ idx[k] = 0;
332
+ }
333
+ }
334
+ }
335
+ }
336
+
337
+ /* --------------------------------------------------------------------- */
338
+ /* ca_composite_fill_complement */
339
+ /* */
340
+ /* Fill the complement of an alias rectangle. Enumerates up to 2*ndim */
341
+ /* disjoint strips and calls _fill_rect for each non-empty strip. */
342
+ /* */
343
+ /* Strip k "before": alias range on dims 0..k-1, */
344
+ /* [0..alias_offset[k]) on dim k, */
345
+ /* full [0..output_dim[i]) on dims k+1..ndim-1 */
346
+ /* Strip k "after": alias range on dims 0..k-1, */
347
+ /* [alias_offset[k]+alias_count[k]..output_dim[k]) */
348
+ /* on dim k, */
349
+ /* full on dims k+1..ndim-1 */
350
+ /* */
351
+ /* Strips are pairwise disjoint and together cover output minus alias. */
352
+ /* Caller must ensure alias rectangle is within output bounds. */
353
+ /* --------------------------------------------------------------------- */
354
+
355
+ void
356
+ ca_composite_fill_complement (char *out_ptr,
357
+ const ca_size_t *output_strides,
358
+ const ca_size_t *output_dim,
359
+ const ca_size_t *alias_offset,
360
+ const ca_size_t *alias_count,
361
+ const char *fill_value,
362
+ ca_size_t bytes,
363
+ int8_t ndim)
364
+ {
365
+ ca_size_t strip_offset[CA_RANK_MAX];
366
+ ca_size_t strip_count[CA_RANK_MAX];
367
+ int8_t k, m;
368
+
369
+ for ( k = 0; k < ndim; k++ ) {
370
+ ca_size_t a_off = alias_offset[k];
371
+ ca_size_t a_cnt = alias_count[k];
372
+ ca_size_t a_end = a_off + a_cnt;
373
+
374
+ /* "Before" strip on axis k:
375
+ dims 0..k-1: alias range
376
+ dim k: [0..a_off)
377
+ dims k+1..N-1: full output extent */
378
+ if ( a_off > 0 ) {
379
+ for ( m = 0; m < k; m++ ) {
380
+ strip_offset[m] = alias_offset[m];
381
+ strip_count[m] = alias_count[m];
382
+ }
383
+ strip_offset[k] = 0;
384
+ strip_count[k] = a_off;
385
+ for ( m = k + 1; m < ndim; m++ ) {
386
+ strip_offset[m] = 0;
387
+ strip_count[m] = output_dim[m];
388
+ }
389
+ ca_composite_fill_rect(out_ptr, output_strides,
390
+ strip_offset, strip_count,
391
+ fill_value, bytes, ndim);
392
+ }
393
+
394
+ /* "After" strip on axis k:
395
+ dims 0..k-1: alias range
396
+ dim k: [a_end..output_dim[k])
397
+ dims k+1..N-1: full output extent */
398
+ if ( a_end < output_dim[k] ) {
399
+ for ( m = 0; m < k; m++ ) {
400
+ strip_offset[m] = alias_offset[m];
401
+ strip_count[m] = alias_count[m];
402
+ }
403
+ strip_offset[k] = a_end;
404
+ strip_count[k] = output_dim[k] - a_end;
405
+ for ( m = k + 1; m < ndim; m++ ) {
406
+ strip_offset[m] = 0;
407
+ strip_count[m] = output_dim[m];
408
+ }
409
+ ca_composite_fill_rect(out_ptr, output_strides,
410
+ strip_offset, strip_count,
411
+ fill_value, bytes, ndim);
412
+ }
413
+ }
414
+ }
@@ -0,0 +1,116 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ Geometric primitives for region-mapped views (CAWindow / CATile /
4
+ CARoll). These helpers are the "per-region routine" called by each
5
+ region-mapped view's attach/sync path.
6
+
7
+ Design pattern (= split routines, not a tagged union over source kind):
8
+ - the region descriptor carries only geometric metadata
9
+ (output_offset, count); source info (parent, parent_start, fill_value)
10
+ is passed as a per-call parameter.
11
+ - ALIAS regions use _region_gather / _region_scatter; broadcast fill
12
+ is ca_fill_typed (full output) or _fill_rect / _fill_complement for
13
+ sub-regions.
14
+
15
+ ---------------------------------------------------------------------------- */
16
+
17
+ #ifndef CA_COMPOSITE_DISPATCH_H
18
+ #define CA_COMPOSITE_DISPATCH_H
19
+
20
+ #include "carray.h"
21
+
22
+ /* Fill `n` cells of `dst`, each `bytes` wide, with the value at `val`.
23
+
24
+ SIMD-friendly typed-store dispatch on bytes ∈ {1, 2, 4, 8, 16}, generic
25
+ memcpy fallback for other widths (CA_FIXLEN, unusual struct sizes).
26
+ Compiler vectorises the uint16/32/64 stores into NEON / SSE2 stores.
27
+
28
+ Called from ca_obj_window.c and ca_axis_dispatch.c for the
29
+ broadcast-fill step. */
30
+ void ca_fill_typed (char *dst, const char *val,
31
+ ca_size_t bytes, ca_size_t n);
32
+
33
+ /* Strided memcpy from a sub-rectangle of `parent_ptr` to a sub-rectangle
34
+ of `out_ptr`. Both rectangles have the same shape (`count`).
35
+
36
+ parent_ptr : base pointer of parent's row-major contig buffer
37
+ (caller has attached parent; parent->ptr is valid)
38
+ parent_strides : per-axis byte stride within parent (row-major)
39
+ parent_start : per-axis start index in parent for the source rectangle
40
+ out_ptr : base pointer of the output buffer (row-major contig
41
+ over the view's own shape)
42
+ output_strides : per-axis byte stride within output
43
+ output_offset : per-axis start index in output for the destination rectangle
44
+ count : per-axis size of the rectangle (same for both)
45
+ ndim, bytes : view ndim and element bytes
46
+
47
+ Internal fast paths:
48
+ - ndim == 1: single memcpy
49
+ - ndim == 2 (outer_axes == 1): pointer-advancing 2D loop, no idx[]
50
+ - ndim >= 3: multi-dim cursor walk over outer axes
51
+
52
+ Called from the attach paths of ca_obj_window.c, ca_obj_tile.c and
53
+ ca_obj_roll.c. */
54
+ void ca_composite_region_gather (char *parent_ptr,
55
+ const ca_size_t *parent_strides,
56
+ const ca_size_t *parent_start,
57
+ char *out_ptr,
58
+ const ca_size_t *output_strides,
59
+ const ca_size_t *output_offset,
60
+ const ca_size_t *count,
61
+ int8_t ndim,
62
+ ca_size_t bytes);
63
+
64
+ /* Reverse direction: copy from out_ptr rectangle to parent rectangle.
65
+ Called from the sync (write-back) paths of ca_obj_window.c,
66
+ ca_obj_tile.c and ca_obj_roll.c. Same parameter geometry as
67
+ _region_gather. */
68
+ void ca_composite_region_scatter (char *parent_ptr,
69
+ const ca_size_t *parent_strides,
70
+ const ca_size_t *parent_start,
71
+ const char *in_ptr,
72
+ const ca_size_t *input_strides,
73
+ const ca_size_t *input_offset,
74
+ const ca_size_t *count,
75
+ int8_t ndim,
76
+ ca_size_t bytes);
77
+
78
+ /* Complement-aware fill.
79
+
80
+ ca_composite_fill_rect: fill a rectangle sub-region of out_ptr with
81
+ typed value `fill_value` (broadcast). Same rectangle geometry as
82
+ _region_gather but the source is a single value, not a parent
83
+ rectangle. 1D / 2D / N-D internal fast paths.
84
+
85
+ ca_composite_fill_complement: fill the complement of an alias
86
+ rectangle (= output minus alias). Enumerates up to 2*ndim disjoint
87
+ strip regions and calls _fill_rect for each non-empty strip. Each
88
+ strip is a rectangle:
89
+ axis k "before" strip: alias range on dims 0..k-1, [0..alias_offset[k])
90
+ on dim k, full on dims k+1..ndim-1
91
+ axis k "after" strip: alias range on dims 0..k-1,
92
+ [alias_offset[k]+alias_count[k]..output_dim[k])
93
+ on dim k, full on dims k+1..ndim-1
94
+ Strips are pairwise disjoint and together cover output minus alias.
95
+
96
+ Called from CAWindow's attach path: rather than fill_typed over the
97
+ entire output and then overwrite the alias rectangle, fill only the
98
+ complement strips (= no wasted writes on the alias region). */
99
+ void ca_composite_fill_rect (char *out_ptr,
100
+ const ca_size_t *output_strides,
101
+ const ca_size_t *offset,
102
+ const ca_size_t *count,
103
+ const char *fill_value,
104
+ ca_size_t bytes,
105
+ int8_t ndim);
106
+
107
+ void ca_composite_fill_complement (char *out_ptr,
108
+ const ca_size_t *output_strides,
109
+ const ca_size_t *output_dim,
110
+ const ca_size_t *alias_offset,
111
+ const ca_size_t *alias_count,
112
+ const char *fill_value,
113
+ ca_size_t bytes,
114
+ int8_t ndim);
115
+
116
+ #endif /* CA_COMPOSITE_DISPATCH_H */