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.
- checksums.yaml +4 -4
- data/.yardopts +5 -25
- data/CHANGELOG.md +16 -0
- data/LICENSE +1 -1
- data/NEWS.md +3 -0
- data/README.md +128 -44
- data/carray.gemspec +22 -24
- data/ext/ca_array_pool.c +91 -0
- data/ext/ca_axis_descriptor.h +186 -0
- data/ext/ca_axis_dispatch.c +924 -0
- data/ext/ca_axis_group.c +1208 -0
- data/ext/ca_bincmp_dispatch.c +76 -0
- data/ext/ca_bincmp_dispatch.h +85 -0
- data/ext/ca_binop_dispatch.c +125 -0
- data/ext/ca_binop_dispatch.h +159 -0
- data/ext/ca_categorical_iterator.c +1375 -0
- data/ext/ca_compare.c +94 -0
- data/ext/ca_compare.h +26 -0
- data/ext/ca_composite_dispatch.c +414 -0
- data/ext/ca_composite_dispatch.h +116 -0
- data/ext/ca_for_buffer.h +96 -0
- data/ext/ca_for_each_element.h +241 -0
- data/ext/ca_group_iter.c +304 -0
- data/ext/ca_iter_substrate.h +325 -0
- data/ext/ca_kernel_iterator.c +4321 -0
- data/ext/ca_kernel_iterator.h +2603 -0
- data/ext/ca_moncmp_dispatch.c +37 -0
- data/ext/ca_moncmp_dispatch.h +62 -0
- data/ext/ca_monop_dispatch.c +200 -0
- data/ext/ca_monop_dispatch.h +235 -0
- data/ext/ca_obj_array.c +355 -359
- data/ext/ca_obj_bincmp.c +809 -0
- data/ext/ca_obj_binop.c +892 -0
- data/ext/ca_obj_bitarray.c +369 -164
- data/ext/ca_obj_bitfield.c +294 -234
- data/ext/ca_obj_block.c +189 -711
- data/ext/ca_obj_byte_swap.c +766 -0
- data/ext/ca_obj_const_string.c +965 -0
- data/ext/ca_obj_face.c +670 -0
- data/ext/ca_obj_face.h +247 -0
- data/ext/ca_obj_fake.c +228 -100
- data/ext/ca_obj_farray.c +54 -441
- data/ext/ca_obj_field.c +82 -529
- data/ext/ca_obj_fixlen_string.c +306 -0
- data/ext/ca_obj_grid.c +858 -440
- data/ext/ca_obj_meld.c +1034 -0
- data/ext/ca_obj_moncmp.c +569 -0
- data/ext/ca_obj_monop.c +1111 -0
- data/ext/ca_obj_object.c +774 -298
- data/ext/ca_obj_record.c +468 -0
- data/ext/ca_obj_reduce.c +97 -82
- data/ext/ca_obj_refer.c +569 -459
- data/ext/ca_obj_remap.c +475 -0
- data/ext/ca_obj_repeat.c +92 -477
- data/ext/ca_obj_roll.c +616 -0
- data/ext/ca_obj_select.c +344 -296
- data/ext/ca_obj_select_axis.c +1296 -0
- data/ext/ca_obj_shift.c +230 -792
- data/ext/ca_obj_source.c +78 -0
- data/ext/ca_obj_stack.c +1173 -0
- data/ext/ca_obj_stride.c +2501 -0
- data/ext/ca_obj_string.c +268 -0
- data/ext/ca_obj_tile.c +614 -0
- data/ext/ca_obj_time.c +546 -0
- data/ext/ca_obj_timedelta.c +435 -0
- data/ext/ca_obj_transpose.c +62 -516
- data/ext/ca_obj_triop.c +746 -0
- data/ext/ca_obj_unbound_repeat.c +208 -241
- data/ext/ca_obj_window.c +1131 -563
- data/ext/ca_op_byte_swap.c +175 -0
- data/ext/ca_op_ipower.c +319 -0
- data/ext/ca_op_powi.h +88 -0
- data/ext/ca_sort_kernels.h +132 -0
- data/ext/ca_sweep_engine.c +430 -0
- data/ext/ca_sweep_engine.h +157 -0
- data/ext/ca_transform_common.c +228 -0
- data/ext/ca_triop_dispatch.c +55 -0
- data/ext/ca_triop_dispatch.h +62 -0
- data/ext/carray.h +795 -402
- data/ext/carray_access.c +831 -711
- data/ext/carray_attribute.c +98 -330
- data/ext/carray_bincount.c +255 -0
- data/ext/carray_broadcast.c +283 -0
- data/ext/carray_call_cfunc.c +1360 -828
- data/ext/carray_call_cfunc.h +160 -0
- data/ext/carray_cast.c +1212 -301
- data/ext/carray_cast_func.rb +81 -40
- data/ext/carray_class.c +53 -63
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +350 -346
- data/ext/carray_copy.c +156 -268
- data/ext/carray_core.c +1342 -199
- data/ext/carray_count.c +312 -0
- data/ext/carray_data_type.c +43 -19
- data/ext/carray_element.c +585 -213
- data/ext/carray_factorize.c +2542 -0
- data/ext/carray_generate.c +230 -559
- data/ext/carray_histogram.c +490 -0
- data/ext/carray_hold.c +228 -0
- data/ext/carray_index_classifier.c +1035 -0
- data/ext/carray_index_classifier.h +27 -0
- data/ext/carray_internal.h +120 -0
- data/ext/carray_kernels_bincmp.c +4445 -0
- data/ext/carray_kernels_binop.c +10979 -0
- data/ext/carray_kernels_init.c +36 -0
- data/ext/carray_kernels_map.c +3466 -0
- data/ext/carray_kernels_moncmp.c +2096 -0
- data/ext/carray_kernels_monop.c +18312 -0
- data/ext/carray_kernels_reduce_aggregate.c +25836 -0
- data/ext/carray_kernels_reduce_boolean.c +329 -0
- data/ext/carray_kernels_reduce_cumulative.c +14592 -0
- data/ext/carray_kernels_reduce_extreme.c +16947 -0
- data/ext/carray_kernels_reduce_variance.c +3909 -0
- data/ext/carray_kernels_scan.c +3692 -0
- data/ext/carray_kernels_search.c +32137 -0
- data/ext/carray_kernels_sort.c +10625 -0
- data/ext/carray_kernels_triop.c +1391 -0
- data/ext/carray_lazy.c +567 -0
- data/ext/carray_loop.c +88 -200
- data/ext/carray_mask.c +848 -154
- data/ext/carray_math_kernel.h +120 -0
- data/ext/carray_mathfunc.c +10 -241
- data/ext/carray_median_percentile.c +1257 -0
- data/ext/carray_memory_view.c +1625 -0
- data/ext/carray_operator.c +1526 -318
- data/ext/carray_order.c +664 -1394
- data/ext/carray_partition.c +416 -0
- data/ext/carray_random.c +518 -0
- data/ext/carray_scatter.c +357 -0
- data/ext/carray_slab.c +1219 -0
- data/ext/carray_slab.h +84 -0
- data/ext/carray_sort.c +829 -0
- data/ext/carray_sort_kernel.c +620 -0
- data/ext/carray_struct.c +695 -0
- data/ext/carray_test.c +343 -229
- data/ext/carray_undef.c +34 -17
- data/ext/carray_utils.c +175 -74
- data/ext/extconf.rb +216 -55
- data/ext/mk_call_cfunc.rb +480 -0
- data/ext/mkkernel.rb +8842 -0
- data/ext/ruby_carray.c +202 -101
- data/ext/version.h +4 -14
- data/ext/version.rb +5 -13
- data/lib/carray/arrow_tensor.rb +401 -0
- data/lib/carray/attribute.rb +166 -0
- data/lib/carray/autoload_carray.rb +220 -0
- data/lib/carray/autoload_method_extension.rb +44 -0
- data/lib/carray/axis_group.rb +711 -0
- data/lib/carray/basics.rb +481 -0
- data/lib/carray/bincount_nd.rb +358 -0
- data/lib/carray/block_iterator.rb +604 -0
- data/lib/carray/boolean_reduce.rb +109 -0
- data/lib/carray/categorical.rb +561 -0
- data/lib/carray/categorical_iterator.rb +1062 -0
- data/lib/carray/complex.rb +150 -0
- data/lib/carray/conditional.rb +216 -0
- data/lib/carray/const_string.rb +228 -0
- data/lib/carray/construct.rb +139 -328
- data/lib/carray/core_extensions.rb +240 -0
- data/lib/carray/data_type_extension.rb +233 -0
- data/lib/carray/fixlen_string.rb +95 -0
- data/lib/carray/frame/concat.rb +132 -0
- data/lib/carray/frame/convert.rb +95 -0
- data/lib/carray/frame/csv_parser.rb +211 -0
- data/lib/carray/frame/frame.rb +649 -0
- data/lib/carray/frame/group.rb +186 -0
- data/lib/carray/frame/io.rb +164 -0
- data/lib/carray/frame/join.rb +248 -0
- data/lib/carray/frame/records.rb +99 -0
- data/lib/carray/frame/sort.rb +113 -0
- data/lib/carray/frame/verbs.rb +299 -0
- data/lib/carray/frame.rb +16 -0
- data/lib/carray/histogram.rb +512 -0
- data/lib/carray/inspect.rb +37 -20
- data/lib/carray/iterator.rb +57 -349
- data/lib/carray/lazy.rb +889 -0
- data/lib/carray/mask_gap_fill.rb +200 -0
- data/lib/carray/math.rb +78 -342
- data/lib/carray/meld_reduce.rb +289 -0
- data/lib/carray/methods/align_addr.rb +116 -0
- data/lib/carray/methods/bin.rb +128 -0
- data/lib/carray/methods/bincount.rb +87 -0
- data/lib/carray/methods/bit_string.rb +92 -0
- data/lib/carray/methods/broadcast.rb +63 -0
- data/lib/carray/methods/choose.rb +39 -0
- data/lib/carray/methods/composition.rb +280 -0
- data/lib/carray/methods/gather_nd.rb +206 -0
- data/lib/carray/methods/index.rb +39 -0
- data/lib/carray/methods/insert_block.rb +99 -0
- data/lib/carray/methods/is_in.rb +141 -0
- data/lib/carray/methods/join.rb +90 -0
- data/lib/carray/methods/locate_addr.rb +47 -0
- data/lib/carray/methods/mask_duplicates.rb +41 -0
- data/lib/carray/methods/meshgrid.rb +91 -0
- data/lib/carray/methods/mode.rb +126 -0
- data/lib/carray/methods/nunique.rb +46 -0
- data/lib/carray/methods/resize.rb +56 -0
- data/lib/carray/methods/snap.rb +156 -0
- data/lib/carray/methods/string_format.rb +57 -0
- data/lib/carray/methods/unique.rb +47 -0
- data/lib/carray/methods/value_counts.rb +71 -0
- data/lib/carray/mkmf.rb +124 -101
- data/lib/carray/runtime.rb +108 -0
- data/lib/carray/serialize.rb +478 -167
- data/lib/carray/slab_iterator.rb +292 -0
- data/lib/carray/stack.rb +291 -0
- data/lib/carray/string.rb +56 -180
- data/lib/carray/string_operation_extension.rb +289 -0
- data/lib/carray/struct.rb +335 -323
- data/lib/carray/struct_builder.rb +697 -0
- data/lib/carray/table.rb +41 -2
- data/lib/carray/time.rb +2255 -38
- data/lib/carray/window_iterator.rb +655 -0
- data/lib/carray.rb +55 -57
- metadata +163 -130
- data/Rakefile +0 -51
- data/TODO.md +0 -18
- data/ext/ca_iter_block.c +0 -257
- data/ext/ca_iter_dimension.c +0 -299
- data/ext/ca_iter_window.c +0 -214
- data/ext/ca_obj_mapping.c +0 -644
- data/ext/carray_iterator.c +0 -641
- data/ext/carray_math.rb +0 -850
- data/ext/carray_numeric.c +0 -259
- data/ext/carray_sort_addr.c +0 -254
- data/ext/carray_stat.c +0 -2100
- data/ext/carray_stat_proc.rb +0 -1999
- data/ext/mkmath.rb +0 -741
- data/ext/ruby_ccomplex.c +0 -509
- data/ext/ruby_float_func.c +0 -86
- data/lib/carray/array.rb +0 -8
- data/lib/carray/autoload/autoload_base.rb +0 -19
- data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
- data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
- data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
- data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
- data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
- data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
- data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
- data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
- data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
- data/lib/carray/autoload/autoload_gem_random.rb +0 -8
- data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
- data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
- data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
- data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
- data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
- data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
- data/lib/carray/autoload/autoload_object_link.rb +0 -1
- data/lib/carray/autoload/autoload_object_pack.rb +0 -2
- data/lib/carray/autoload.rb +0 -141
- data/lib/carray/basic.rb +0 -191
- data/lib/carray/broadcast.rb +0 -101
- data/lib/carray/compose.rb +0 -315
- data/lib/carray/convert.rb +0 -115
- data/lib/carray/info.rb +0 -110
- data/lib/carray/io/imagemagick.rb +0 -235
- data/lib/carray/mask.rb +0 -102
- data/lib/carray/math/histogram.rb +0 -177
- data/lib/carray/math/recurrence.rb +0 -93
- data/lib/carray/object/ca_obj_iterator.rb +0 -50
- data/lib/carray/object/ca_obj_link.rb +0 -50
- data/lib/carray/object/ca_obj_pack.rb +0 -99
- data/lib/carray/obsolete.rb +0 -256
- data/lib/carray/ordering.rb +0 -181
- data/lib/carray/testing.rb +0 -51
- data/lib/carray/transform.rb +0 -109
- data/misc/Methods.ja.md +0 -182
- data/misc/NOTE +0 -51
- data/spec/Classes/CABitfield_spec.rb +0 -58
- data/spec/Classes/CABlockIterator_spec.rb +0 -114
- data/spec/Classes/CABlock_spec.rb +0 -205
- data/spec/Classes/CAField_spec.rb +0 -39
- data/spec/Classes/CAGrid_spec.rb +0 -75
- data/spec/Classes/CAMap_spec.rb +0 -0
- data/spec/Classes/CAMapping_spec.rb +0 -105
- data/spec/Classes/CAObject_attribute_spec.rb +0 -33
- data/spec/Classes/CAObject_spec.rb +0 -33
- data/spec/Classes/CARefer_spec.rb +0 -93
- data/spec/Classes/CARepeat_spec.rb +0 -65
- data/spec/Classes/CASelect_spec.rb +0 -22
- data/spec/Classes/CAShift_spec.rb +0 -16
- data/spec/Classes/CAStruct_spec.rb +0 -71
- data/spec/Classes/CATranspose_spec.rb +0 -60
- data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
- data/spec/Classes/CAWindow_spec.rb +0 -54
- data/spec/Classes/CAWrap_spec.rb +0 -8
- data/spec/Classes/CArray_spec.rb +0 -184
- data/spec/Classes/CScalar_spec.rb +0 -55
- data/spec/Classes/ex1.rb +0 -46
- data/spec/Features/feature_130_spec.rb +0 -19
- data/spec/Features/feature_attributes_spec.rb +0 -280
- data/spec/Features/feature_boolean_spec.rb +0 -98
- data/spec/Features/feature_broadcast.rb +0 -116
- data/spec/Features/feature_cast_function.rb +0 -19
- data/spec/Features/feature_cast_spec.rb +0 -33
- data/spec/Features/feature_class_spec.rb +0 -84
- data/spec/Features/feature_complex_spec.rb +0 -42
- data/spec/Features/feature_composite_spec.rb +0 -124
- data/spec/Features/feature_convert_spec.rb +0 -46
- data/spec/Features/feature_copy_spec.rb +0 -123
- data/spec/Features/feature_creation_spec.rb +0 -84
- data/spec/Features/feature_element_spec.rb +0 -144
- data/spec/Features/feature_extream_spec.rb +0 -54
- data/spec/Features/feature_generate_spec.rb +0 -74
- data/spec/Features/feature_index_spec.rb +0 -69
- data/spec/Features/feature_mask_spec.rb +0 -580
- data/spec/Features/feature_math_spec.rb +0 -97
- data/spec/Features/feature_order_spec.rb +0 -146
- data/spec/Features/feature_ref_store_spec.rb +0 -209
- data/spec/Features/feature_serialization_spec.rb +0 -125
- data/spec/Features/feature_stat_spec.rb +0 -397
- data/spec/Features/feature_virtual_spec.rb +0 -48
- data/spec/Features/method_eq_spec.rb +0 -81
- data/spec/Features/method_is_nan_spec.rb +0 -12
- data/spec/Features/method_map_spec.rb +0 -54
- data/spec/Features/method_max_with.rb +0 -20
- data/spec/Features/method_min_with.rb +0 -19
- data/spec/Features/method_ne_spec.rb +0 -18
- data/spec/Features/method_project_spec.rb +0 -188
- data/spec/Features/method_ref_spec.rb +0 -27
- data/spec/Features/method_round_spec.rb +0 -11
- data/spec/Features/method_s_linspace_spec.rb +0 -48
- data/spec/Features/method_s_span_spec.rb +0 -14
- data/spec/Features/method_seq_spec.rb +0 -47
- data/spec/Features/method_sort_with.rb +0 -43
- data/spec/Features/method_sorted_with.rb +0 -29
- data/spec/Features/method_span_spec.rb +0 -42
- data/spec/Features/method_wrap_readonly_spec.rb +0 -43
- data/spec/UnitTest/test_CAVirtual.rb +0 -214
- data/spec/spec_all.rb +0 -10
- data/utils/ca_ase.rb +0 -21
- data/utils/ca_methods.rb +0 -15
- data/utils/cast_checker.rb +0 -30
- data/utils/convert_test.rb +0 -73
- data/utils/extract_yard.rb +0 -22
- data/utils/guess_shape.rb +0 -76
- data/utils/monkey_patch_methods.rb +0 -62
- data/utils/remove_resource_fork.sh +0 -5
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
Per-data_type kernel table for the CAMonOp `byte_swap` op
|
|
4
|
+
(`CA_MONOP_BYTE_SWAP`): reverses the byte order of each cell in place
|
|
5
|
+
after copying src to dst. byte_swap is data_type-preserving
|
|
6
|
+
(output.bytes == input.bytes).
|
|
7
|
+
|
|
8
|
+
Sibling of ca_monop_dispatch.c (looks up `ca_monop_byte_swap[in_dt]`)
|
|
9
|
+
and ca_obj_byte_swap.c (the eager CAByteSwap view + `ca_swap_bytes`
|
|
10
|
+
primitive that this file delegates to for the actual reversal).
|
|
11
|
+
|
|
12
|
+
Dispatch by data_type:
|
|
13
|
+
1-byte cells (boolean / int8 / uint8) -> 1byte kernel (memcpy only)
|
|
14
|
+
fixed-width numeric (int16..float64) -> nbyte kernel (memcpy + reverse)
|
|
15
|
+
CA_CMPLX64 / CA_CMPLX128 -> cmplx kernel (half-independent)
|
|
16
|
+
CA_FIXLEN / CA_FLOAT128 / CA_CMPLX256 -> not_impl trampoline
|
|
17
|
+
CA_OBJECT -> not_impl trampoline
|
|
18
|
+
|
|
19
|
+
CMPLX cells are byte-swapped as two independent halves (real / imag),
|
|
20
|
+
not as one wide cell — this matches the eager `ca_byte_swap_buffer`
|
|
21
|
+
contract in ca_obj_byte_swap.c.
|
|
22
|
+
|
|
23
|
+
CA_FIXLEN is excluded here: bytes-per-cell is parent-specific and
|
|
24
|
+
data_class field-recursion requires a Ruby callback path; the CAByteSwap
|
|
25
|
+
view handles those. CA_OBJECT byte-swap on VALUE refs is meaningless.
|
|
26
|
+
|
|
27
|
+
---------------------------------------------------------------------------- */
|
|
28
|
+
|
|
29
|
+
#include "carray.h"
|
|
30
|
+
#include "ca_monop_dispatch.h"
|
|
31
|
+
#include <string.h>
|
|
32
|
+
|
|
33
|
+
/* Reverses `bytes` bytes per cell across `elements` cells in place.
|
|
34
|
+
* Defined in ca_obj_byte_swap.c. */
|
|
35
|
+
extern void ca_swap_bytes (char *ptr, ca_size_t bytes, ca_size_t elements);
|
|
36
|
+
|
|
37
|
+
/* ------------------------------------------------------------------- */
|
|
38
|
+
/* per-data_type kernels */
|
|
39
|
+
/* ------------------------------------------------------------------- */
|
|
40
|
+
|
|
41
|
+
/* 1-byte cell: byte-swap is a no-op on a single byte. The kernel just
|
|
42
|
+
copies src to dst when they differ; included so boolean / int8 / uint8
|
|
43
|
+
share the dispatch shape with the wider kernels. */
|
|
44
|
+
#define DEFINE_BYTE_SWAP_1BYTE(name) \
|
|
45
|
+
static void \
|
|
46
|
+
name (ca_size_t n, boolean8_t *m, \
|
|
47
|
+
char *ptr1, ca_size_t i1, char *ptr2, ca_size_t i2) \
|
|
48
|
+
{ \
|
|
49
|
+
ca_size_t k; \
|
|
50
|
+
if ( m ) { \
|
|
51
|
+
for (k = 0; k < n; k++) { \
|
|
52
|
+
if (!m[k]) { \
|
|
53
|
+
*(ptr2 + k*i2) = *(ptr1 + k*i1); \
|
|
54
|
+
} \
|
|
55
|
+
} \
|
|
56
|
+
} else { \
|
|
57
|
+
for (k = 0; k < n; k++) { \
|
|
58
|
+
*(ptr2 + k*i2) = *(ptr1 + k*i1); \
|
|
59
|
+
} \
|
|
60
|
+
} \
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* N-byte cell: copy src to dst (if different) then reverse the N
|
|
64
|
+
bytes within the cell. */
|
|
65
|
+
#define DEFINE_BYTE_SWAP_NBYTE(name, BYTES) \
|
|
66
|
+
static void \
|
|
67
|
+
name (ca_size_t n, boolean8_t *m, \
|
|
68
|
+
char *ptr1, ca_size_t i1, char *ptr2, ca_size_t i2) \
|
|
69
|
+
{ \
|
|
70
|
+
ca_size_t k; \
|
|
71
|
+
if ( m ) { \
|
|
72
|
+
for (k = 0; k < n; k++) { \
|
|
73
|
+
if (!m[k]) { \
|
|
74
|
+
char *p1 = ptr1 + k*i1*(BYTES); \
|
|
75
|
+
char *p2 = ptr2 + k*i2*(BYTES); \
|
|
76
|
+
if (p2 != p1) memcpy(p2, p1, (BYTES)); \
|
|
77
|
+
ca_swap_bytes(p2, (BYTES), 1); \
|
|
78
|
+
} \
|
|
79
|
+
} \
|
|
80
|
+
} else { \
|
|
81
|
+
for (k = 0; k < n; k++) { \
|
|
82
|
+
char *p1 = ptr1 + k*i1*(BYTES); \
|
|
83
|
+
char *p2 = ptr2 + k*i2*(BYTES); \
|
|
84
|
+
if (p2 != p1) memcpy(p2, p1, (BYTES)); \
|
|
85
|
+
ca_swap_bytes(p2, (BYTES), 1); \
|
|
86
|
+
} \
|
|
87
|
+
} \
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* CMPLX cell (TOTAL bytes = 2 * HALF): swap the real half and the imag
|
|
91
|
+
half independently rather than reversing the whole TOTAL-byte cell. */
|
|
92
|
+
#define DEFINE_BYTE_SWAP_CMPLX(name, TOTAL, HALF) \
|
|
93
|
+
static void \
|
|
94
|
+
name (ca_size_t n, boolean8_t *m, \
|
|
95
|
+
char *ptr1, ca_size_t i1, char *ptr2, ca_size_t i2) \
|
|
96
|
+
{ \
|
|
97
|
+
ca_size_t k; \
|
|
98
|
+
if ( m ) { \
|
|
99
|
+
for (k = 0; k < n; k++) { \
|
|
100
|
+
if (!m[k]) { \
|
|
101
|
+
char *p1 = ptr1 + k*i1*(TOTAL); \
|
|
102
|
+
char *p2 = ptr2 + k*i2*(TOTAL); \
|
|
103
|
+
if (p2 != p1) memcpy(p2, p1, (TOTAL)); \
|
|
104
|
+
ca_swap_bytes(p2, (HALF), 2); \
|
|
105
|
+
} \
|
|
106
|
+
} \
|
|
107
|
+
} else { \
|
|
108
|
+
for (k = 0; k < n; k++) { \
|
|
109
|
+
char *p1 = ptr1 + k*i1*(TOTAL); \
|
|
110
|
+
char *p2 = ptr2 + k*i2*(TOTAL); \
|
|
111
|
+
if (p2 != p1) memcpy(p2, p1, (TOTAL)); \
|
|
112
|
+
ca_swap_bytes(p2, (HALF), 2); \
|
|
113
|
+
} \
|
|
114
|
+
} \
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
DEFINE_BYTE_SWAP_1BYTE(ca_monop_byte_swap_boolean_t)
|
|
118
|
+
DEFINE_BYTE_SWAP_1BYTE(ca_monop_byte_swap_int8_t)
|
|
119
|
+
DEFINE_BYTE_SWAP_1BYTE(ca_monop_byte_swap_uint8_t)
|
|
120
|
+
|
|
121
|
+
DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_int16_t, 2)
|
|
122
|
+
DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_uint16_t, 2)
|
|
123
|
+
|
|
124
|
+
DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_int32_t, 4)
|
|
125
|
+
DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_uint32_t, 4)
|
|
126
|
+
|
|
127
|
+
DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_int64_t, 8)
|
|
128
|
+
DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_uint64_t, 8)
|
|
129
|
+
|
|
130
|
+
DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_float32_t, 4)
|
|
131
|
+
DEFINE_BYTE_SWAP_NBYTE(ca_monop_byte_swap_float64_t, 8)
|
|
132
|
+
|
|
133
|
+
DEFINE_BYTE_SWAP_CMPLX(ca_monop_byte_swap_cmplx64_t, 8, 4)
|
|
134
|
+
DEFINE_BYTE_SWAP_CMPLX(ca_monop_byte_swap_cmplx128_t, 16, 8)
|
|
135
|
+
|
|
136
|
+
/* Trampoline installed at unsupported data_type slots in the dispatch
|
|
137
|
+
table below. Raises rather than returning so the caller never sees
|
|
138
|
+
silent no-op behaviour on an out-of-scope data_type. */
|
|
139
|
+
NORETURN(static void ca_monop_byte_swap_not_impl (ca_size_t n, boolean8_t *m,
|
|
140
|
+
char *ptr1, ca_size_t i1,
|
|
141
|
+
char *ptr2, ca_size_t i2));
|
|
142
|
+
static void
|
|
143
|
+
ca_monop_byte_swap_not_impl (ca_size_t n, boolean8_t *m,
|
|
144
|
+
char *ptr1, ca_size_t i1,
|
|
145
|
+
char *ptr2, ca_size_t i2)
|
|
146
|
+
{
|
|
147
|
+
(void) n; (void) m; (void) ptr1; (void) i1; (void) ptr2; (void) i2;
|
|
148
|
+
rb_raise(rb_eRuntimeError,
|
|
149
|
+
"CAMonOp(byte_swap): not implemented for this data_type");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* ------------------------------------------------------------------- */
|
|
153
|
+
/* dispatch table */
|
|
154
|
+
/* ------------------------------------------------------------------- */
|
|
155
|
+
|
|
156
|
+
ca_monop_func_t
|
|
157
|
+
ca_monop_byte_swap[CA_NTYPE] = {
|
|
158
|
+
/* CA_FIXLEN */ ca_monop_byte_swap_not_impl,
|
|
159
|
+
/* CA_BOOLEAN */ ca_monop_byte_swap_boolean_t,
|
|
160
|
+
/* CA_INT8 */ ca_monop_byte_swap_int8_t,
|
|
161
|
+
/* CA_UINT8 */ ca_monop_byte_swap_uint8_t,
|
|
162
|
+
/* CA_INT16 */ ca_monop_byte_swap_int16_t,
|
|
163
|
+
/* CA_UINT16 */ ca_monop_byte_swap_uint16_t,
|
|
164
|
+
/* CA_INT32 */ ca_monop_byte_swap_int32_t,
|
|
165
|
+
/* CA_UINT32 */ ca_monop_byte_swap_uint32_t,
|
|
166
|
+
/* CA_INT64 */ ca_monop_byte_swap_int64_t,
|
|
167
|
+
/* CA_UINT64 */ ca_monop_byte_swap_uint64_t,
|
|
168
|
+
/* CA_FLOAT32 */ ca_monop_byte_swap_float32_t,
|
|
169
|
+
/* CA_FLOAT64 */ ca_monop_byte_swap_float64_t,
|
|
170
|
+
/* CA_FLOAT128 */ ca_monop_byte_swap_not_impl, /* reserved hole */
|
|
171
|
+
/* CA_CMPLX64 */ ca_monop_byte_swap_cmplx64_t,
|
|
172
|
+
/* CA_CMPLX128 */ ca_monop_byte_swap_cmplx128_t,
|
|
173
|
+
/* CA_CMPLX256 */ ca_monop_byte_swap_not_impl, /* reserved hole */
|
|
174
|
+
/* CA_OBJECT */ ca_monop_byte_swap_not_impl,
|
|
175
|
+
};
|
data/ext/ca_op_ipower.c
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
Float/Complex ** Integer integer-exponent fast path via
|
|
4
|
+
binary exponentiation (O(log p)).
|
|
5
|
+
|
|
6
|
+
Contents:
|
|
7
|
+
(1) LAZY kernel table `ca_binop_ipower[CA_NTYPE]` — CABinOp dispatch
|
|
8
|
+
entry taken when lazy `**` sees an Integer exponent on a
|
|
9
|
+
Float / Complex receiver. Called from ca_binop_dispatch.c.
|
|
10
|
+
(2) EAGER kernels + Ruby surface `pow` / `pow!` (alias `**`).
|
|
11
|
+
`rb_ca_pow{,_bang}` dispatch between ipower (Float/Complex **
|
|
12
|
+
Integer) and mkkernel-generated `rb_ca_power` (general pow).
|
|
13
|
+
|
|
14
|
+
Both paths share `op_powi_<type>` from ca_op_powi.h (= repeated
|
|
15
|
+
squaring, ~1-3 mul/cell for typical p).
|
|
16
|
+
|
|
17
|
+
---------------------------------------------------------------------------- */
|
|
18
|
+
|
|
19
|
+
#include "carray.h"
|
|
20
|
+
#include "ca_binop_dispatch.h"
|
|
21
|
+
#include "ca_op_powi.h"
|
|
22
|
+
|
|
23
|
+
/* Defined in ext/carray_kernels.c (mkkernel-generated general pow /
|
|
24
|
+
cpow binop). Called by rb_ca_pow{,_bang} when the fast path does
|
|
25
|
+
not apply (rhs not Integer, or lhs not Float/Complex). */
|
|
26
|
+
extern VALUE rb_ca_power (VALUE self, VALUE other);
|
|
27
|
+
extern VALUE rb_ca_power_bang (VALUE self, VALUE other);
|
|
28
|
+
|
|
29
|
+
/* ========================================================================== */
|
|
30
|
+
/* (1) LAZY kernel table — CABinOp ipower dispatch */
|
|
31
|
+
/* ========================================================================== */
|
|
32
|
+
|
|
33
|
+
/* Kernel template: T = source/output data_type; right operand is
|
|
34
|
+
int64_t. Signature (n, m, ptr1, i1, ptr2, i2, ptr3, i3) mirrors
|
|
35
|
+
the mkkernel binop kernels so the CABinOp xfer_stride dispatcher
|
|
36
|
+
calls it uniformly.
|
|
37
|
+
|
|
38
|
+
Heterogeneous binop:
|
|
39
|
+
ptr1 = left (float32/float64/cmplx64/cmplx128, vector)
|
|
40
|
+
ptr2 = right (int64, scalar via i2=0)
|
|
41
|
+
ptr3 = dst (same data_type as left, vector)
|
|
42
|
+
|
|
43
|
+
Output data_type preserves the left data_type (= no cast-before
|
|
44
|
+
promotion). CAREFUL: cast-before / promo are overridden for
|
|
45
|
+
CA_BINOP_IPOWER in ca_binop_dispatch.c; changing this file's
|
|
46
|
+
dispatch table shape without matching that override leaks integer
|
|
47
|
+
promotion into the output.
|
|
48
|
+
|
|
49
|
+
Non-Float / non-Complex slots are NULL: lazy `**` routes only
|
|
50
|
+
Float / Complex parents through IPOWER; Integer parents stay on
|
|
51
|
+
the general CA_BINOP_POW path. */
|
|
52
|
+
|
|
53
|
+
#define DEFINE_LAZY_IPOWER_KERNEL(T) \
|
|
54
|
+
static void \
|
|
55
|
+
ca_binop_ipower_##T (ca_size_t n, boolean8_t *m, \
|
|
56
|
+
char *ptr1, ca_size_t i1, \
|
|
57
|
+
char *ptr2, ca_size_t i2, \
|
|
58
|
+
char *ptr3, ca_size_t i3) \
|
|
59
|
+
{ \
|
|
60
|
+
T *q1 = (T *) ptr1, *q3 = (T *) ptr3; \
|
|
61
|
+
int64_t *q2 = (int64_t *) ptr2; \
|
|
62
|
+
T *p1, *p3; \
|
|
63
|
+
int64_t *p2; \
|
|
64
|
+
ca_size_t k; \
|
|
65
|
+
(void) i2; /* right is scalar broadcast (i2 == 0), q2 stays put */ \
|
|
66
|
+
if ( m ) { \
|
|
67
|
+
boolean8_t *pm; \
|
|
68
|
+
for (k = 0; k < n; k++) { \
|
|
69
|
+
pm = m + k; \
|
|
70
|
+
if ( ! *pm ) { \
|
|
71
|
+
p1 = q1 + k*i1; \
|
|
72
|
+
p2 = q2 + k*i2; \
|
|
73
|
+
p3 = q3 + k*i3; \
|
|
74
|
+
*p3 = op_powi_##T(*p1, *p2); \
|
|
75
|
+
} \
|
|
76
|
+
} \
|
|
77
|
+
} else { \
|
|
78
|
+
for (k = 0; k < n; k++) { \
|
|
79
|
+
p1 = q1 + k*i1; \
|
|
80
|
+
p2 = q2 + k*i2; \
|
|
81
|
+
p3 = q3 + k*i3; \
|
|
82
|
+
*p3 = op_powi_##T(*p1, *p2); \
|
|
83
|
+
} \
|
|
84
|
+
} \
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
DEFINE_LAZY_IPOWER_KERNEL(float32_t)
|
|
88
|
+
DEFINE_LAZY_IPOWER_KERNEL(float64_t)
|
|
89
|
+
DEFINE_LAZY_IPOWER_KERNEL(cmplx64_t)
|
|
90
|
+
DEFINE_LAZY_IPOWER_KERNEL(cmplx128_t)
|
|
91
|
+
|
|
92
|
+
#undef DEFINE_LAZY_IPOWER_KERNEL
|
|
93
|
+
|
|
94
|
+
/* Per-data_type dispatch table — NULL for slots not covered (= integer /
|
|
95
|
+
bool / object / fixlen / VL). Indexed by CA_FLOAT32 .. CA_CMPLX128. */
|
|
96
|
+
ca_binop_func_t ca_binop_ipower[CA_NTYPE] = {
|
|
97
|
+
[CA_FLOAT32] = ca_binop_ipower_float32_t,
|
|
98
|
+
[CA_FLOAT64] = ca_binop_ipower_float64_t,
|
|
99
|
+
[CA_CMPLX64] = ca_binop_ipower_cmplx64_t,
|
|
100
|
+
[CA_CMPLX128] = ca_binop_ipower_cmplx128_t,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/* ========================================================================== */
|
|
104
|
+
/* (2) EAGER kernels + Ruby surface */
|
|
105
|
+
/* ========================================================================== */
|
|
106
|
+
|
|
107
|
+
/* Per-data_type eager kernel: writes ipower(p1[k], ipow) → p2[k] for each
|
|
108
|
+
unmasked cell, using stride 1 on both input and output (= eager
|
|
109
|
+
driver materialises inputs to contig before calling). */
|
|
110
|
+
|
|
111
|
+
static void
|
|
112
|
+
ca_ipower_float32_t (ca_size_t n, boolean8_t *m,
|
|
113
|
+
char *ptr1, int32_t ipow, char *ptr2)
|
|
114
|
+
{
|
|
115
|
+
float32_t *p1 = (float32_t *) ptr1, *p2 = (float32_t *) ptr2;
|
|
116
|
+
if ( m ) {
|
|
117
|
+
while (n--) {
|
|
118
|
+
if ( ! *m++ ) { *p2 = op_powi_float32_t(*p1, ipow); }
|
|
119
|
+
p1++; p2++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else
|
|
123
|
+
while (n--) { (*p2) = op_powi_float32_t(*p1, ipow); p1++; p2++; }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
static void
|
|
127
|
+
ca_ipower_float64_t (ca_size_t n, boolean8_t *m,
|
|
128
|
+
char *ptr1, int32_t ipow, char *ptr2)
|
|
129
|
+
{
|
|
130
|
+
float64_t *p1 = (float64_t *) ptr1, *p2 = (float64_t *) ptr2;
|
|
131
|
+
if ( m ) {
|
|
132
|
+
while (n--) {
|
|
133
|
+
if ( ! *m++ ) { *p2 = op_powi_float64_t(*p1, ipow); }
|
|
134
|
+
p1++; p2++;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else
|
|
138
|
+
while (n--) { (*p2) = op_powi_float64_t(*p1, ipow); p1++; p2++; }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
static void
|
|
142
|
+
ca_ipower_cmplx64_t (ca_size_t n, boolean8_t *m,
|
|
143
|
+
char *ptr1, int32_t ipow, char *ptr2)
|
|
144
|
+
{
|
|
145
|
+
cmplx64_t *p1 = (cmplx64_t *) ptr1, *p2 = (cmplx64_t *) ptr2;
|
|
146
|
+
if ( m ) {
|
|
147
|
+
while (n--) {
|
|
148
|
+
if ( ! *m++ ) { *p2 = op_powi_cmplx64_t(*p1, ipow); }
|
|
149
|
+
p1++; p2++;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else
|
|
153
|
+
while (n--) { (*p2) = op_powi_cmplx64_t(*p1, ipow); p1++; p2++; }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static void
|
|
157
|
+
ca_ipower_cmplx128_t (ca_size_t n, boolean8_t *m,
|
|
158
|
+
char *ptr1, int32_t ipow, char *ptr2)
|
|
159
|
+
{
|
|
160
|
+
cmplx128_t *p1 = (cmplx128_t *) ptr1, *p2 = (cmplx128_t *) ptr2;
|
|
161
|
+
if ( m ) {
|
|
162
|
+
while (n--) {
|
|
163
|
+
if ( ! *m++ ) { *p2 = op_powi_cmplx128_t(*p1, ipow); }
|
|
164
|
+
p1++; p2++;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else
|
|
168
|
+
while (n--) { (*p2) = op_powi_cmplx128_t(*p1, ipow); p1++; p2++; }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* Eager Float/Complex ** Integer producing a fresh entity output.
|
|
172
|
+
* ca is input-only, co is the write target. Mirrors rb_ca_call_monop
|
|
173
|
+
* (see carray_math* / carray_kernels.c) so operand attach is elided:
|
|
174
|
+
* alias-cheap ca -> 1-shot ca_attach, use ca->ptr directly
|
|
175
|
+
* otherwise -> ALLOCV + ca_xfer_all(CA_XFER_GET) into a scratch
|
|
176
|
+
* buffer, no operand attach
|
|
177
|
+
* Mask goes through ca_mask_overlay_safe (also without an operand
|
|
178
|
+
* mask attach). Called by rb_ca_pow when the fast-path predicate
|
|
179
|
+
* matches. */
|
|
180
|
+
static VALUE
|
|
181
|
+
rb_ca_ipower (VALUE self, VALUE other)
|
|
182
|
+
{
|
|
183
|
+
volatile VALUE obj;
|
|
184
|
+
CArray *ca, *co;
|
|
185
|
+
int32_t ipow;
|
|
186
|
+
boolean8_t *m;
|
|
187
|
+
|
|
188
|
+
ipow = NUM2INT(other);
|
|
189
|
+
|
|
190
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
191
|
+
|
|
192
|
+
co = ca_has_mask(ca) ? ca_template_safe(ca) : ca_template(ca);
|
|
193
|
+
obj = ca_wrap_struct(co);
|
|
194
|
+
|
|
195
|
+
ca_mask_overlay_safe(co, 1, ca);
|
|
196
|
+
m = ( co->mask ) ? (boolean8_t *)co->mask->ptr : NULL;
|
|
197
|
+
|
|
198
|
+
if ( ca_attach_is_alias(ca) ) {
|
|
199
|
+
ca_attach(ca);
|
|
200
|
+
switch ( ca->data_type ) {
|
|
201
|
+
case CA_FLOAT32:
|
|
202
|
+
ca_ipower_float32_t(ca->elements, m, ca->ptr, ipow, co->ptr); break;
|
|
203
|
+
case CA_FLOAT64:
|
|
204
|
+
ca_ipower_float64_t(ca->elements, m, ca->ptr, ipow, co->ptr); break;
|
|
205
|
+
case CA_CMPLX64:
|
|
206
|
+
ca_ipower_cmplx64_t(ca->elements, m, ca->ptr, ipow, co->ptr); break;
|
|
207
|
+
case CA_CMPLX128:
|
|
208
|
+
ca_ipower_cmplx128_t(ca->elements, m, ca->ptr, ipow, co->ptr); break;
|
|
209
|
+
default:
|
|
210
|
+
rb_raise(rb_eCADataTypeError, "invalid data type for ipower");
|
|
211
|
+
}
|
|
212
|
+
ca_detach(ca);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
volatile VALUE h1 = Qnil;
|
|
216
|
+
char *p1;
|
|
217
|
+
(void) h1;
|
|
218
|
+
p1 = ALLOCV_N(char, h1, ca->elements * ca->bytes);
|
|
219
|
+
ca_xfer_all(ca, p1, CA_XFER_GET);
|
|
220
|
+
switch ( ca->data_type ) {
|
|
221
|
+
case CA_FLOAT32:
|
|
222
|
+
ca_ipower_float32_t(ca->elements, m, p1, ipow, co->ptr); break;
|
|
223
|
+
case CA_FLOAT64:
|
|
224
|
+
ca_ipower_float64_t(ca->elements, m, p1, ipow, co->ptr); break;
|
|
225
|
+
case CA_CMPLX64:
|
|
226
|
+
ca_ipower_cmplx64_t(ca->elements, m, p1, ipow, co->ptr); break;
|
|
227
|
+
case CA_CMPLX128:
|
|
228
|
+
ca_ipower_cmplx128_t(ca->elements, m, p1, ipow, co->ptr); break;
|
|
229
|
+
default:
|
|
230
|
+
ALLOCV_END(h1);
|
|
231
|
+
rb_raise(rb_eCADataTypeError, "invalid data type for ipower");
|
|
232
|
+
}
|
|
233
|
+
ALLOCV_END(h1);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
obj = rb_ca_rewrap_unbound_repeat(self, obj);
|
|
237
|
+
|
|
238
|
+
return obj;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static VALUE
|
|
242
|
+
rb_ca_ipower_bang (VALUE self, VALUE other)
|
|
243
|
+
{
|
|
244
|
+
CArray *ca;
|
|
245
|
+
int32_t ipow;
|
|
246
|
+
boolean8_t *m;
|
|
247
|
+
|
|
248
|
+
ipow = NUM2INT(other);
|
|
249
|
+
|
|
250
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
251
|
+
|
|
252
|
+
ca_attach(ca);
|
|
253
|
+
|
|
254
|
+
m = ( ca->mask ) ? (boolean8_t *)ca->mask->ptr : NULL;
|
|
255
|
+
|
|
256
|
+
switch ( ca->data_type ) {
|
|
257
|
+
case CA_FLOAT32:
|
|
258
|
+
ca_ipower_float32_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
|
|
259
|
+
case CA_FLOAT64:
|
|
260
|
+
ca_ipower_float64_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
|
|
261
|
+
case CA_CMPLX64:
|
|
262
|
+
ca_ipower_cmplx64_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
|
|
263
|
+
case CA_CMPLX128:
|
|
264
|
+
ca_ipower_cmplx128_t(ca->elements, m, ca->ptr, ipow, ca->ptr); break;
|
|
265
|
+
default:
|
|
266
|
+
rb_raise(rb_eRuntimeError, "invalid data type for ipower");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
ca_sync(ca);
|
|
270
|
+
ca_detach(ca);
|
|
271
|
+
|
|
272
|
+
return self;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/* CArray#pow(other) (alias `**`) — Float/Complex ** Integer takes the
|
|
276
|
+
* ipower fast path in this file; everything else falls through to the
|
|
277
|
+
* mkkernel-generated general pow/cpow (rb_ca_power in
|
|
278
|
+
* ext/carray_kernels.c). Non-bang variant preserves UnboundRepeat
|
|
279
|
+
* wrapping on the result. */
|
|
280
|
+
static VALUE rb_ca_pow (VALUE self, VALUE other)
|
|
281
|
+
{
|
|
282
|
+
volatile VALUE obj;
|
|
283
|
+
CArray *ca;
|
|
284
|
+
|
|
285
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
286
|
+
if ( ( ca_is_float_type(ca) || ca_is_complex_type(ca) ) &&
|
|
287
|
+
rb_obj_is_kind_of(other, rb_cInteger) ) {
|
|
288
|
+
return rb_ca_ipower(self, other);
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
obj = rb_ca_power(self, other);
|
|
292
|
+
obj = rb_ca_rewrap_unbound_repeat(self, obj);
|
|
293
|
+
return obj;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* CArray#pow!(other) — in-place variant of #pow. Dispatch mirrors
|
|
298
|
+
* rb_ca_pow (fast path for Float/Complex ** Integer, otherwise
|
|
299
|
+
* general rb_ca_power_bang). */
|
|
300
|
+
static VALUE rb_ca_pow_bang (VALUE self, VALUE other)
|
|
301
|
+
{
|
|
302
|
+
CArray *ca;
|
|
303
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
304
|
+
if ( ( ca_is_float_type(ca) || ca_is_complex_type(ca) ) &&
|
|
305
|
+
rb_obj_is_kind_of(other, rb_cInteger) ) {
|
|
306
|
+
return rb_ca_ipower_bang(self, other);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
return rb_ca_power_bang(self, other);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
void
|
|
314
|
+
Init_ca_op_ipower (void)
|
|
315
|
+
{
|
|
316
|
+
rb_define_method(rb_cCArray, "pow", rb_ca_pow, 1);
|
|
317
|
+
rb_define_method(rb_cCArray, "pow!", rb_ca_pow_bang, 1);
|
|
318
|
+
rb_define_alias(rb_cCArray, "**", "pow");
|
|
319
|
+
}
|
data/ext/ca_op_powi.h
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
ca_op_powi.h -- shared `op_powi_<type>` integer-power helpers
|
|
4
|
+
|
|
5
|
+
Used by:
|
|
6
|
+
- ext/carray_kernels.c (generated from ext/mkkernel.rb)
|
|
7
|
+
the `power` binop kernel's integer variants call
|
|
8
|
+
`op_powi_<type>` to compute integer exponentiation by binary
|
|
9
|
+
exponentiation (O(log p) vs pow's general path).
|
|
10
|
+
- ext/carray_math.c (hand-written, P.5b.5)
|
|
11
|
+
the `ipower` family (rb_ca_ipower, rb_ca_ipower_bang) uses
|
|
12
|
+
`op_powi_<type>` for the Float**Integer / Complex**Integer
|
|
13
|
+
fast path when invoked via CArray#pow with an Integer rhs.
|
|
14
|
+
|
|
15
|
+
Both files include this header independently; each TU gets its own
|
|
16
|
+
`static inline` copy with no linker conflicts.
|
|
17
|
+
|
|
18
|
+
--------------------------------------------------------------------------- */
|
|
19
|
+
|
|
20
|
+
#ifndef CA_OP_POWI_H
|
|
21
|
+
#define CA_OP_POWI_H
|
|
22
|
+
|
|
23
|
+
#include "carray.h"
|
|
24
|
+
#include <stdint.h>
|
|
25
|
+
|
|
26
|
+
#define op_powi(type) \
|
|
27
|
+
static inline type \
|
|
28
|
+
op_powi_## type (type x, int64_t p) \
|
|
29
|
+
{ \
|
|
30
|
+
type r=1; \
|
|
31
|
+
\
|
|
32
|
+
switch(p) { \
|
|
33
|
+
case 2: return x*x; \
|
|
34
|
+
case 3: return x*x*x; \
|
|
35
|
+
case 0: return 1; \
|
|
36
|
+
case 1: return x; \
|
|
37
|
+
} \
|
|
38
|
+
if (p<0) { \
|
|
39
|
+
type den = op_powi_## type(x, -p); \
|
|
40
|
+
if (den==0) ca_zerodiv(); \
|
|
41
|
+
return 1/den; \
|
|
42
|
+
}\
|
|
43
|
+
while (p) { \
|
|
44
|
+
if ( (p%2) == 1 ) r *= x; \
|
|
45
|
+
x *= x; \
|
|
46
|
+
p /= 2; \
|
|
47
|
+
} \
|
|
48
|
+
return r; \
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#define op_powi_fc(type) \
|
|
52
|
+
static inline type \
|
|
53
|
+
op_powi_## type (type x, int64_t p) \
|
|
54
|
+
{ \
|
|
55
|
+
type r=1; \
|
|
56
|
+
\
|
|
57
|
+
switch(p) { \
|
|
58
|
+
case 2: return x*x; \
|
|
59
|
+
case 3: return x*x*x; \
|
|
60
|
+
case 0: return 1; \
|
|
61
|
+
case 1: return x; \
|
|
62
|
+
} \
|
|
63
|
+
if (p<0) { \
|
|
64
|
+
type den = op_powi_## type(x, -p); \
|
|
65
|
+
return 1/den; \
|
|
66
|
+
}\
|
|
67
|
+
while (p) { \
|
|
68
|
+
if ( (p%2) == 1 ) r *= x; \
|
|
69
|
+
x *= x; \
|
|
70
|
+
p /= 2; \
|
|
71
|
+
} \
|
|
72
|
+
return r; \
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
op_powi(int8_t)
|
|
76
|
+
op_powi(uint8_t)
|
|
77
|
+
op_powi(int16_t)
|
|
78
|
+
op_powi(uint16_t)
|
|
79
|
+
op_powi(int32_t)
|
|
80
|
+
op_powi(uint32_t)
|
|
81
|
+
op_powi(int64_t)
|
|
82
|
+
op_powi(uint64_t)
|
|
83
|
+
op_powi_fc(float32_t)
|
|
84
|
+
op_powi_fc(float64_t)
|
|
85
|
+
op_powi_fc(cmplx64_t)
|
|
86
|
+
op_powi_fc(cmplx128_t)
|
|
87
|
+
|
|
88
|
+
#endif /* CA_OP_POWI_H */
|