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.
- 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 +772 -297
- 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 +229 -791
- 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 +207 -240
- 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 -329
- 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 +1341 -198
- 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 +5 -15
- 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/mailmap +0 -1
- 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/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
data/ext/carray_order.c
CHANGED
|
@@ -1,27 +1,17 @@
|
|
|
1
|
-
/* ---------------------------------------------------------------------------
|
|
2
|
-
|
|
3
|
-
carray_order.c
|
|
4
|
-
|
|
5
|
-
This file is part of Ruby/CArray extension library.
|
|
6
|
-
|
|
7
|
-
Copyright (C) 2005-2025 Hiroki Motoyoshi
|
|
8
|
-
|
|
9
|
-
---------------------------------------------------------------------------- */
|
|
10
|
-
|
|
11
1
|
#include "ruby.h"
|
|
12
2
|
#include "carray.h"
|
|
3
|
+
#include "ca_kernel_iterator.h"
|
|
4
|
+
#include "ca_obj_face.h"
|
|
13
5
|
#include <math.h>
|
|
14
6
|
#include <float.h>
|
|
7
|
+
#include <stdlib.h>
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
VALUE select = rb_ca_is_not_masked(self);
|
|
23
|
-
return rb_ca_fetch(rval, select);
|
|
24
|
-
}
|
|
9
|
+
/* Interned IDs used by the dispatchers below. rb_funcall is retained
|
|
10
|
+
* only where there is no clean C entry: `-` (operator dispatch in
|
|
11
|
+
* rb_ca_order handles Integer vs CArray uniformly via method dispatch)
|
|
12
|
+
* and Symbol tag comparison for `method:` kwarg. */
|
|
13
|
+
static ID id_axis, id_sub,
|
|
14
|
+
id_sym_binary, id_sym_linear;
|
|
25
15
|
|
|
26
16
|
/* ------------------------------------------------------------------- */
|
|
27
17
|
|
|
@@ -62,6 +52,8 @@ rb_ca_value_not_masked (VALUE self)
|
|
|
62
52
|
} \
|
|
63
53
|
}
|
|
64
54
|
|
|
55
|
+
/* Inner loop of ca_project: gather ca[ci[i]] into co with optional
|
|
56
|
+
* lfill/ufill for out-of-range indices. Called only by ca_project. */
|
|
65
57
|
static void
|
|
66
58
|
ca_project_loop (CArray *co, CArray *ca, CArray *ci, char *lfill, char *ufill)
|
|
67
59
|
{
|
|
@@ -119,8 +111,8 @@ ca_project_loop (CArray *co, CArray *ca, CArray *ci, char *lfill, char *ufill)
|
|
|
119
111
|
}
|
|
120
112
|
break;
|
|
121
113
|
}
|
|
122
|
-
|
|
123
|
-
|
|
114
|
+
xfree(mi);
|
|
115
|
+
xfree(ma);
|
|
124
116
|
}
|
|
125
117
|
|
|
126
118
|
CArray *
|
|
@@ -138,27 +130,36 @@ ca_project (CArray *ca, CArray *ci, char *lfill, char *ufill)
|
|
|
138
130
|
return co;
|
|
139
131
|
}
|
|
140
132
|
|
|
141
|
-
/*
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
133
|
+
/* project(idx, lval=nil, uval=nil) — gather: for each element of `idx`,
|
|
134
|
+
* pick `self[idx[i]]`. Returns an entity CArray shaped like `idx`.
|
|
135
|
+
*
|
|
136
|
+
* Out-of-range index handling: negative or >= self.elements indices
|
|
137
|
+
* produce `lval` (lower) / `uval` (upper) if provided, otherwise mask
|
|
138
|
+
* the output cell. Masked inputs (`idx` mask or `self` mask) also
|
|
139
|
+
* propagate as masked output.
|
|
140
|
+
*/
|
|
146
141
|
VALUE
|
|
147
142
|
rb_ca_project (int argc, VALUE *argv, VALUE self)
|
|
148
143
|
{
|
|
149
|
-
volatile VALUE obj, ridx, vlfval, vufval;
|
|
144
|
+
volatile VALUE obj, ridx, vlfval, vufval, vstorage;
|
|
150
145
|
CArray *ca, *ci, *co;
|
|
151
146
|
char *lfval, *ufval;
|
|
147
|
+
int self_is_face;
|
|
152
148
|
|
|
153
149
|
rb_scan_args(argc, argv, "12", (VALUE *)&ridx, (VALUE *) &vlfval, (VALUE *) &vufval);
|
|
154
150
|
|
|
155
151
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
152
|
+
self_is_face = ca_is_face(ca);
|
|
156
153
|
|
|
157
154
|
rb_check_carray_object(ridx);
|
|
158
155
|
ci = ca_wrap_readonly(ridx, CA_SIZE);
|
|
159
156
|
|
|
160
|
-
|
|
161
|
-
|
|
157
|
+
/* The fill args arrive as surface values. rb_ca_obj2ptr owns the
|
|
158
|
+
surface->storage conversion: for a Face self it fires the scalar_to_storage
|
|
159
|
+
write hook (a datetime scalar / Time is reconciled to the Face's unit),
|
|
160
|
+
for a plain array it writes the storage bytes directly. */
|
|
161
|
+
lfval = xmalloc(ca->bytes);
|
|
162
|
+
ufval = xmalloc(ca->bytes);
|
|
162
163
|
|
|
163
164
|
if ( ! NIL_P(vlfval) ) {
|
|
164
165
|
rb_ca_obj2ptr(self, vlfval, lfval);
|
|
@@ -169,1519 +170,788 @@ rb_ca_project (int argc, VALUE *argv, VALUE self)
|
|
|
169
170
|
rb_ca_obj2ptr(self, vufval, ufval);
|
|
170
171
|
}
|
|
171
172
|
|
|
173
|
+
/* Strip Face -> gather on storage -> face-lift (the same tail sort/search
|
|
174
|
+
use, see docs/authoring/FaceOrderingSearch.md). The gather runs on the raw
|
|
175
|
+
storage so length / miss->UNDEF / fill semantics are unchanged; the
|
|
176
|
+
result is then re-wrapped as the source Face, and copy_state carries the
|
|
177
|
+
subclass state (datetime/timedelta unit, categorical labels). */
|
|
178
|
+
vstorage = self;
|
|
179
|
+
if ( self_is_face ) {
|
|
180
|
+
vstorage = rb_ca_strip_face_value(self);
|
|
181
|
+
TypedData_Get_Struct(vstorage, CArray, &carray_data_type, ca);
|
|
182
|
+
}
|
|
183
|
+
|
|
172
184
|
co = ca_project(ca, ci,
|
|
173
185
|
( ! NIL_P(vlfval) ) ? lfval : NULL,
|
|
174
186
|
( ( ! NIL_P(vufval) ) || ( ! NIL_P(vlfval) ) ) ? ufval : NULL);
|
|
175
187
|
|
|
176
|
-
|
|
177
|
-
|
|
188
|
+
xfree(lfval);
|
|
189
|
+
xfree(ufval);
|
|
178
190
|
|
|
179
191
|
obj = ca_wrap_struct(co);
|
|
180
|
-
rb_ca_data_type_inherit(obj, self);
|
|
181
192
|
|
|
182
193
|
if ( ! ca_is_any_masked(co) ) {
|
|
183
194
|
obj = rb_ca_unmask_copy(obj);
|
|
184
195
|
}
|
|
185
196
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
/* ----------------------------------------------------------------- */
|
|
190
|
-
|
|
191
|
-
#define proc_reverse_bang_mask() \
|
|
192
|
-
{ \
|
|
193
|
-
boolean8_t *p = (boolean8_t *)ca->mask->ptr; \
|
|
194
|
-
boolean8_t *q = (boolean8_t *)ca->mask->ptr + ca->elements - 1; \
|
|
195
|
-
boolean8_t v; \
|
|
196
|
-
for (; p<q; p++, q--) { \
|
|
197
|
-
v = *p; *p = *q; *q = v; \
|
|
198
|
-
} \
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
#define proc_reverse_bang(type) \
|
|
203
|
-
{ \
|
|
204
|
-
type *p = (type *)ca->ptr; \
|
|
205
|
-
type *q = (type *)ca->ptr + ca->elements - 1; \
|
|
206
|
-
type v; \
|
|
207
|
-
for (; p<q; p++, q--) { \
|
|
208
|
-
v = *p; *p = *q; *q = v; \
|
|
209
|
-
} \
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
#define proc_reverse_bang_data() \
|
|
213
|
-
{ \
|
|
214
|
-
ca_size_t bytes = ca->bytes; \
|
|
215
|
-
char *p = ca->ptr; \
|
|
216
|
-
char *q = ca->ptr + bytes * (ca->elements - 1); \
|
|
217
|
-
char *v = malloc_with_check(bytes); \
|
|
218
|
-
for (; p<q; p+=bytes, q-=bytes) { \
|
|
219
|
-
memcpy(v, p, bytes); \
|
|
220
|
-
memcpy(p, q, bytes); \
|
|
221
|
-
memcpy(q, v, bytes); \
|
|
222
|
-
} \
|
|
223
|
-
free(v); \
|
|
197
|
+
if ( self_is_face ) {
|
|
198
|
+
obj = ca_face_lift(obj, self);
|
|
224
199
|
}
|
|
225
200
|
|
|
226
|
-
|
|
201
|
+
return obj;
|
|
202
|
+
}
|
|
227
203
|
|
|
228
|
-
|
|
229
|
-
*/
|
|
204
|
+
/* ------------------------------------------------------------------------- */
|
|
230
205
|
|
|
206
|
+
/* ---- search family kwarg trampolines (dual API: index vs addr) ------
|
|
207
|
+
*
|
|
208
|
+
* Each trampoline parses the `axis:` kwarg and dispatches:
|
|
209
|
+
* axis nil -> inline no-axis flat path: flatten self + flatten query
|
|
210
|
+
* (if CArray) + call the _ki kernel at axis 0, then
|
|
211
|
+
* reshape the result to the query's shape via
|
|
212
|
+
* ca_reshape_search_result
|
|
213
|
+
* axis k -> per-axis kernel from carray_kernels.c. The "index"
|
|
214
|
+
* variants use the :fiber_local kernels (axis-local
|
|
215
|
+
* position per fiber); the "addr" variants use the
|
|
216
|
+
* :view_flat kernels (view-flat address per fiber).
|
|
217
|
+
*
|
|
218
|
+
* For the no-axis path both variant families route through the index
|
|
219
|
+
* kernel (_ki, not _addr_ki): the 1-D flattening makes addr == index,
|
|
220
|
+
* so the two names share the same implementation.
|
|
221
|
+
*/
|
|
222
|
+
|
|
223
|
+
extern VALUE rb_ca_bsearch_ki (VALUE self, VALUE rval, VALUE raxis);
|
|
224
|
+
extern VALUE rb_ca_bsearch_addr_ki (VALUE self, VALUE rval, VALUE raxis);
|
|
225
|
+
extern VALUE rb_ca_search_ki (int argc, VALUE *argv, VALUE self);
|
|
226
|
+
extern VALUE rb_ca_search_addr_ki (int argc, VALUE *argv, VALUE self);
|
|
227
|
+
extern VALUE rb_ca_search_nearest_ki (VALUE self, VALUE rval, VALUE raxis);
|
|
228
|
+
extern VALUE rb_ca_search_nearest_addr_ki (VALUE self, VALUE rval, VALUE raxis);
|
|
229
|
+
|
|
230
|
+
/* Direct C function entries used by the dispatchers below. Declared
|
|
231
|
+
* here when not already in carray.h / umbrella headers.
|
|
232
|
+
*
|
|
233
|
+
* The `_c` suffix marks "C-callable entry": a thin twin of the Ruby-
|
|
234
|
+
* binding function that skips rb_scan_args. Ruby's `:` kwarg parsing
|
|
235
|
+
* reads the call-frame keyword-splat state, which is only set by full
|
|
236
|
+
* method dispatch -- calling the Ruby entry directly from C would
|
|
237
|
+
* segfault. Pattern: Ruby entry parses argv via rb_scan_args and
|
|
238
|
+
* forwards to the `_c` twin.
|
|
239
|
+
*/
|
|
240
|
+
extern VALUE rb_ca_sort_addr_c (VALUE self, VALUE axis, int stable, int masked_last);
|
|
241
|
+
extern VALUE rb_ca_axis2addr_c (VALUE self, VALUE vindices, VALUE vaxis);
|
|
242
|
+
extern VALUE rb_ca_count_not_masked_c (VALUE self, VALUE axis_val);
|
|
243
|
+
extern VALUE rb_ca_flip_axis (VALUE self, long axis);
|
|
244
|
+
extern VALUE rb_ca_argmin_addr_ki (int argc, VALUE *argv, VALUE self);
|
|
245
|
+
extern VALUE rb_ca_argmax_addr_ki (int argc, VALUE *argv, VALUE self);
|
|
246
|
+
extern VALUE rb_ca_minmax_ki (int argc, VALUE *argv, VALUE self);
|
|
247
|
+
extern VALUE rb_ca_linear_section_binary_ki (VALUE self, VALUE rval, VALUE raxis);
|
|
248
|
+
extern VALUE rb_ca_linear_section_linear_ki (VALUE self, VALUE rval, VALUE raxis);
|
|
249
|
+
extern VALUE rb_ca_linear_fetch_ki (VALUE self, VALUE rval, VALUE raxis);
|
|
250
|
+
extern VALUE rb_ca_insert_axis (int argc, VALUE *argv, VALUE self);
|
|
251
|
+
extern VALUE rb_ca_reshape (int argc, VALUE *argv, VALUE self);
|
|
252
|
+
|
|
253
|
+
/* mkkernel-emitted kernels marked `c_callable: true`: extern symbols
|
|
254
|
+
* in carray_kernels.c that allow direct C-level dispatch without going
|
|
255
|
+
* through rb_funcall + kwarg hash construction. */
|
|
256
|
+
extern VALUE rb_ca_sort_index_ki_quick (VALUE self, VALUE vaxis);
|
|
257
|
+
extern VALUE rb_ca_partition_index_ki (VALUE self, VALUE vaxis, VALUE vkth);
|
|
258
|
+
extern VALUE rb_ca_rank_index_ki_quick_dense (VALUE self, VALUE vaxis, int dense);
|
|
259
|
+
|
|
260
|
+
/* ---- no-axis (flat) search helper -----------------------------------
|
|
261
|
+
*
|
|
262
|
+
* Contract for the no-axis path (`axis: nil`):
|
|
263
|
+
* non-CArray query -> scalar result (Integer / nil)
|
|
264
|
+
* CArray query -> query-shaped CArray result (UNDEF cells on no-match)
|
|
265
|
+
*
|
|
266
|
+
* Implementation: flatten self + flatten query, run the per-axis _ki
|
|
267
|
+
* kernel at axis 0, then reshape the raw 1-D result to query's shape
|
|
268
|
+
* via the helper below.
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
/* Rebuild a query-shaped result from the kernel output. Two paths:
|
|
272
|
+
* (a) scalar collapse: _ki returns Integer / nil when query is a
|
|
273
|
+
* single-element CArray. Build a query-shaped entity directly
|
|
274
|
+
* and store the value (CA_UNDEF for nil -> auto-mask).
|
|
275
|
+
* (b) CArray result: reshape to query.shape (the helpers flatten the
|
|
276
|
+
* query before calling _ki, so the raw result is 1-D).
|
|
277
|
+
*
|
|
278
|
+
* Called by the search family trampolines below (bsearch_kw /
|
|
279
|
+
* search_kw / search_nearest_kw and their _addr siblings) on the
|
|
280
|
+
* no-axis path. */
|
|
231
281
|
static VALUE
|
|
232
|
-
|
|
282
|
+
ca_reshape_search_result (VALUE query, VALUE rraw)
|
|
233
283
|
{
|
|
234
|
-
CArray *
|
|
235
|
-
|
|
236
|
-
rb_ca_modify(self);
|
|
284
|
+
CArray *cq;
|
|
285
|
+
GetCArray(query, cq);
|
|
237
286
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
case CA_FIXLEN: proc_reverse_bang_data(); break;
|
|
243
|
-
case CA_BOOLEAN:
|
|
244
|
-
case CA_INT8:
|
|
245
|
-
case CA_UINT8: proc_reverse_bang(int8_t); break;
|
|
246
|
-
case CA_INT16:
|
|
247
|
-
case CA_UINT16: proc_reverse_bang(int16_t); break;
|
|
248
|
-
case CA_INT32:
|
|
249
|
-
case CA_UINT32:
|
|
250
|
-
case CA_FLOAT32: proc_reverse_bang(int32_t); break;
|
|
251
|
-
case CA_INT64:
|
|
252
|
-
case CA_UINT64:
|
|
253
|
-
case CA_FLOAT64: proc_reverse_bang(float64_t); break;
|
|
254
|
-
case CA_FLOAT128: proc_reverse_bang(float128_t); break;
|
|
255
|
-
#ifdef HAVE_COMPLEX_H
|
|
256
|
-
case CA_CMPLX64: proc_reverse_bang(float64_t); break;
|
|
257
|
-
case CA_CMPLX128: proc_reverse_bang(cmplx128_t); break;
|
|
258
|
-
case CA_CMPLX256: proc_reverse_bang(cmplx256_t); break;
|
|
259
|
-
#endif
|
|
260
|
-
case CA_OBJECT: proc_reverse_bang(VALUE); break;
|
|
261
|
-
default:
|
|
262
|
-
rb_raise(rb_eCADataTypeError, "[BUG] array has an unknown data type");
|
|
287
|
+
if ( ! rb_obj_is_carray(rraw) ) {
|
|
288
|
+
VALUE vr = rb_carray_new(CA_SIZE, cq->ndim, cq->dim, 0, NULL);
|
|
289
|
+
rb_ca_store_addr(vr, 0, NIL_P(rraw) ? CA_UNDEF : rraw);
|
|
290
|
+
return vr;
|
|
263
291
|
}
|
|
264
292
|
|
|
265
|
-
|
|
266
|
-
|
|
293
|
+
VALUE shape_argv[CA_RANK_MAX];
|
|
294
|
+
for ( int8_t k = 0; k < cq->ndim; k++ ) {
|
|
295
|
+
shape_argv[k] = LONG2NUM((long) cq->dim[k]);
|
|
267
296
|
}
|
|
268
|
-
|
|
269
|
-
ca_sync(ca);
|
|
270
|
-
ca_detach(ca);
|
|
271
|
-
|
|
272
|
-
return self;
|
|
297
|
+
return rb_ca_reshape((int) cq->ndim, shape_argv, rraw);
|
|
273
298
|
}
|
|
274
299
|
|
|
275
|
-
/* @overload reverse
|
|
276
|
-
|
|
277
|
-
Returns a new CArray object containing <i>ca</i>'s elements in
|
|
278
|
-
reverse order.
|
|
279
|
-
*/
|
|
280
|
-
|
|
281
300
|
static VALUE
|
|
282
|
-
|
|
283
|
-
{
|
|
284
|
-
volatile VALUE out = rb_ca_copy(self);
|
|
285
|
-
rb_ca_data_type_inherit(out, self);
|
|
286
|
-
return rb_ca_reverse_bang(out);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/* ------------------------------------------------------------------------- */
|
|
290
|
-
|
|
291
|
-
typedef struct {
|
|
292
|
-
ca_size_t bytes;
|
|
293
|
-
char *ptr;
|
|
294
|
-
} cmp_data;
|
|
295
|
-
|
|
296
|
-
typedef int (*ca_qsort_cmp_func)();
|
|
297
|
-
|
|
298
|
-
#define qcmp_type(type) \
|
|
299
|
-
static int \
|
|
300
|
-
qcmp_## type (type *a, type *b) \
|
|
301
|
-
{ \
|
|
302
|
-
if ( *a > *b ) return 1; \
|
|
303
|
-
if ( *a < *b ) return -1; \
|
|
304
|
-
return 0; \
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
#define qcmp_f_type(type) \
|
|
308
|
-
static int \
|
|
309
|
-
qcmp_## type (type *a, type *b) \
|
|
310
|
-
{ \
|
|
311
|
-
if ( isnan(*a) && ( ! isnan(*b) ) ) return 1; \
|
|
312
|
-
if ( isnan(*b) && ( ! isnan(*a) ) ) return -1; \
|
|
313
|
-
if ( *a > *b ) return 1; \
|
|
314
|
-
if ( *a < *b ) return -1; \
|
|
315
|
-
return 0; \
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
static int
|
|
319
|
-
qcmp_VALUE (VALUE *a, VALUE *b)
|
|
301
|
+
rb_ca_bsearch_kw (int argc, VALUE *argv, VALUE self)
|
|
320
302
|
{
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
303
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
304
|
+
VALUE raxis = Qnil;
|
|
305
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
306
|
+
rb_check_arity(argc, 1, 1);
|
|
307
|
+
|
|
308
|
+
if ( NIL_P(raxis) ) {
|
|
309
|
+
VALUE flat = rb_ca_flatten(self);
|
|
310
|
+
VALUE q = rb_obj_is_carray(argv[0]) ? rb_ca_flatten(argv[0]) : argv[0];
|
|
311
|
+
VALUE r = rb_ca_bsearch_ki(flat, q, INT2FIX(0));
|
|
312
|
+
return rb_obj_is_carray(argv[0]) ? ca_reshape_search_result(argv[0], r) : r;
|
|
313
|
+
}
|
|
314
|
+
return rb_ca_bsearch_ki(self, argv[0], raxis);
|
|
325
315
|
}
|
|
326
316
|
|
|
327
|
-
static
|
|
328
|
-
|
|
317
|
+
static VALUE
|
|
318
|
+
rb_ca_bsearch_addr_kw (int argc, VALUE *argv, VALUE self)
|
|
329
319
|
{
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
320
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
321
|
+
VALUE raxis = Qnil;
|
|
322
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
323
|
+
rb_check_arity(argc, 1, 1);
|
|
324
|
+
|
|
325
|
+
if ( NIL_P(raxis) ) {
|
|
326
|
+
/* 1-D self: view-flat addr == axis-local index, so the no-axis
|
|
327
|
+
path reuses _ki (not _addr_ki) -- both variants share output. */
|
|
328
|
+
VALUE flat = rb_ca_flatten(self);
|
|
329
|
+
VALUE q = rb_obj_is_carray(argv[0]) ? rb_ca_flatten(argv[0]) : argv[0];
|
|
330
|
+
VALUE r = rb_ca_bsearch_ki(flat, q, INT2FIX(0));
|
|
331
|
+
return rb_obj_is_carray(argv[0]) ? ca_reshape_search_result(argv[0], r) : r;
|
|
332
|
+
}
|
|
333
|
+
return rb_ca_bsearch_addr_ki(self, argv[0], raxis);
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
qcmp_type(uint8_t)
|
|
339
|
-
qcmp_type(int16_t)
|
|
340
|
-
qcmp_type(uint16_t)
|
|
341
|
-
qcmp_type(int32_t)
|
|
342
|
-
qcmp_type(uint32_t)
|
|
343
|
-
qcmp_type(int64_t)
|
|
344
|
-
qcmp_type(uint64_t)
|
|
345
|
-
qcmp_f_type(float32_t)
|
|
346
|
-
qcmp_f_type(float64_t)
|
|
347
|
-
qcmp_f_type(float128_t)
|
|
348
|
-
|
|
349
|
-
static int
|
|
350
|
-
qcmp_not_implement (void *a, void *b)
|
|
336
|
+
static VALUE
|
|
337
|
+
rb_ca_search_kw (int argc, VALUE *argv, VALUE self)
|
|
351
338
|
{
|
|
352
|
-
|
|
353
|
-
|
|
339
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
340
|
+
VALUE raxis = Qnil;
|
|
341
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
342
|
+
rb_check_arity(argc, 1, 2);
|
|
343
|
+
|
|
344
|
+
if ( NIL_P(raxis) ) {
|
|
345
|
+
VALUE flat = rb_ca_flatten(self);
|
|
346
|
+
VALUE q = rb_obj_is_carray(argv[0]) ? rb_ca_flatten(argv[0]) : argv[0];
|
|
347
|
+
VALUE r;
|
|
348
|
+
VALUE ki_argv[3] = { q, INT2FIX(0), argv[1] };
|
|
349
|
+
if ( argc >= 2 ) {
|
|
350
|
+
r = rb_ca_search_ki(3, ki_argv, flat);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
r = rb_ca_search_ki(2, ki_argv, flat);
|
|
354
|
+
}
|
|
355
|
+
return rb_obj_is_carray(argv[0]) ? ca_reshape_search_result(argv[0], r) : r;
|
|
356
|
+
}
|
|
357
|
+
/* search_ki(val, axis, eps) -- argc=2 (val,axis) or 3 (val,axis,eps) */
|
|
358
|
+
VALUE ki_argv[3] = { argv[0], raxis, argv[1] };
|
|
359
|
+
if ( argc >= 2 ) {
|
|
360
|
+
return rb_ca_search_ki(3, ki_argv, self);
|
|
361
|
+
}
|
|
362
|
+
return rb_ca_search_ki(2, ki_argv, self);
|
|
354
363
|
}
|
|
355
364
|
|
|
356
|
-
ca_qsort_cmp_func
|
|
357
|
-
ca_qsort_cmp[CA_NTYPE] = {
|
|
358
|
-
qcmp_data,
|
|
359
|
-
qcmp_boolean8_t,
|
|
360
|
-
qcmp_int8_t,
|
|
361
|
-
qcmp_uint8_t,
|
|
362
|
-
qcmp_int16_t,
|
|
363
|
-
qcmp_uint16_t,
|
|
364
|
-
qcmp_int32_t,
|
|
365
|
-
qcmp_uint32_t,
|
|
366
|
-
qcmp_int64_t,
|
|
367
|
-
qcmp_uint64_t,
|
|
368
|
-
qcmp_float32_t,
|
|
369
|
-
qcmp_float64_t,
|
|
370
|
-
qcmp_float128_t,
|
|
371
|
-
qcmp_not_implement,
|
|
372
|
-
qcmp_not_implement,
|
|
373
|
-
qcmp_not_implement,
|
|
374
|
-
qcmp_VALUE,
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
/* @overload sort!
|
|
378
|
-
|
|
379
|
-
Sorts <i>ca</i>'s elements in place.
|
|
380
|
-
*/
|
|
381
|
-
|
|
382
365
|
static VALUE
|
|
383
|
-
|
|
366
|
+
rb_ca_search_addr_kw (int argc, VALUE *argv, VALUE self)
|
|
384
367
|
{
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
cmp_data *cmp_ptr, *p;
|
|
399
|
-
char *ca_ptr, *q;
|
|
400
|
-
ca_size_t i;
|
|
401
|
-
cmp_ptr = malloc_with_check(sizeof(cmp_data)*ca->elements);
|
|
402
|
-
ca_ptr = malloc_with_check(ca_length(ca));
|
|
403
|
-
for (i=0, p=cmp_ptr, q=ca->ptr; i<ca->elements; i++, p++, q+=ca->bytes) {
|
|
404
|
-
p->bytes = ca->bytes;
|
|
405
|
-
p->ptr = q;
|
|
368
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
369
|
+
VALUE raxis = Qnil;
|
|
370
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
371
|
+
rb_check_arity(argc, 1, 2);
|
|
372
|
+
|
|
373
|
+
if ( NIL_P(raxis) ) {
|
|
374
|
+
/* 1-D self: addr == index reuses _ki (not _addr_ki). */
|
|
375
|
+
VALUE flat = rb_ca_flatten(self);
|
|
376
|
+
VALUE q = rb_obj_is_carray(argv[0]) ? rb_ca_flatten(argv[0]) : argv[0];
|
|
377
|
+
VALUE r;
|
|
378
|
+
VALUE ki_argv[3] = { q, INT2FIX(0), argv[1] };
|
|
379
|
+
if ( argc >= 2 ) {
|
|
380
|
+
r = rb_ca_search_ki(3, ki_argv, flat);
|
|
406
381
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
memcpy(q, p->ptr, ca->bytes);
|
|
382
|
+
else {
|
|
383
|
+
r = rb_ca_search_ki(2, ki_argv, flat);
|
|
410
384
|
}
|
|
411
|
-
|
|
412
|
-
ca->ptr = ca_ptr;
|
|
413
|
-
free(cmp_ptr);
|
|
385
|
+
return rb_obj_is_carray(argv[0]) ? ca_reshape_search_result(argv[0], r) : r;
|
|
414
386
|
}
|
|
415
|
-
|
|
416
|
-
|
|
387
|
+
VALUE ki_argv[3] = { argv[0], raxis, argv[1] };
|
|
388
|
+
if ( argc >= 2 ) {
|
|
389
|
+
return rb_ca_search_addr_ki(3, ki_argv, self);
|
|
417
390
|
}
|
|
418
|
-
|
|
419
|
-
ca_detach(ca);
|
|
420
|
-
return self;
|
|
391
|
+
return rb_ca_search_addr_ki(2, ki_argv, self);
|
|
421
392
|
}
|
|
422
393
|
|
|
423
|
-
/* @overload sort
|
|
424
|
-
|
|
425
|
-
Returns a new CArray object containing <i>ca</i>'s elements sorted.
|
|
426
|
-
*/
|
|
427
|
-
|
|
428
394
|
static VALUE
|
|
429
|
-
|
|
395
|
+
rb_ca_search_nearest_kw (int argc, VALUE *argv, VALUE self)
|
|
430
396
|
{
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
397
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
398
|
+
VALUE raxis = Qnil;
|
|
399
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
400
|
+
rb_check_arity(argc, 1, 1);
|
|
401
|
+
|
|
402
|
+
if ( NIL_P(raxis) ) {
|
|
403
|
+
VALUE flat = rb_ca_flatten(self);
|
|
404
|
+
VALUE q = rb_obj_is_carray(argv[0]) ? rb_ca_flatten(argv[0]) : argv[0];
|
|
405
|
+
VALUE r = rb_ca_search_nearest_ki(flat, q, INT2FIX(0));
|
|
406
|
+
return rb_obj_is_carray(argv[0]) ? ca_reshape_search_result(argv[0], r) : r;
|
|
407
|
+
}
|
|
408
|
+
return rb_ca_search_nearest_ki(self, argv[0], raxis);
|
|
434
409
|
}
|
|
435
410
|
|
|
411
|
+
static VALUE
|
|
412
|
+
rb_ca_search_nearest_addr_kw (int argc, VALUE *argv, VALUE self)
|
|
413
|
+
{
|
|
414
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
415
|
+
VALUE raxis = Qnil;
|
|
416
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
417
|
+
rb_check_arity(argc, 1, 1);
|
|
418
|
+
|
|
419
|
+
if ( NIL_P(raxis) ) {
|
|
420
|
+
/* 1-D self: addr == index reuses _ki (not _addr_ki) -- same as bsearch_addr. */
|
|
421
|
+
VALUE flat = rb_ca_flatten(self);
|
|
422
|
+
VALUE q = rb_obj_is_carray(argv[0]) ? rb_ca_flatten(argv[0]) : argv[0];
|
|
423
|
+
VALUE r = rb_ca_search_nearest_ki(flat, q, INT2FIX(0));
|
|
424
|
+
return rb_obj_is_carray(argv[0]) ? ca_reshape_search_result(argv[0], r) : r;
|
|
425
|
+
}
|
|
426
|
+
return rb_ca_search_nearest_addr_ki(self, argv[0], raxis);
|
|
427
|
+
}
|
|
436
428
|
|
|
437
|
-
/* --------------------------------------------------------------- */
|
|
438
429
|
|
|
439
|
-
/*
|
|
430
|
+
/* ===========================================================================
|
|
431
|
+
* Ordering surface (C-side implementations of CArray ordering methods).
|
|
432
|
+
*
|
|
433
|
+
* Call sites use direct C function calls wherever possible; rb_funcall
|
|
434
|
+
* is retained only where there is no clean C entry: the `-` operator
|
|
435
|
+
* (Ruby method dispatch handles both `Integer - Integer` and
|
|
436
|
+
* `CArray - Integer` / `Integer - CArray` uniformly) and Symbol tag
|
|
437
|
+
* comparison for `method:` kwarg.
|
|
438
|
+
* =========================================================================== */
|
|
440
439
|
|
|
441
|
-
|
|
442
|
-
*/
|
|
440
|
+
/* ---- sort_by_key family ---------------------------------------------- */
|
|
443
441
|
|
|
442
|
+
/* sort_by_key(key, axis: 0) -- gather self at key.sort_addr(axis:). */
|
|
444
443
|
static VALUE
|
|
445
|
-
|
|
444
|
+
rb_ca_sort_by_key (int argc, VALUE *argv, VALUE self)
|
|
446
445
|
{
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
/*
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
VALUE select = rb_ca_is_not_masked(self);
|
|
457
|
-
VALUE obj = rb_funcall(val, rb_intern("[]"), 1, select);
|
|
458
|
-
return rb_ca_binary_search(obj, rval);
|
|
459
|
-
}
|
|
460
|
-
*/
|
|
446
|
+
VALUE rkey, rkw = Qnil, raxis = Qnil;
|
|
447
|
+
rb_scan_args(argc, argv, "1:", &rkey, &rkw);
|
|
448
|
+
rb_scan_options(rkw, "axis", &raxis);
|
|
449
|
+
if ( NIL_P(raxis) ) {
|
|
450
|
+
raxis = INT2FIX(0);
|
|
451
|
+
}
|
|
452
|
+
VALUE addrs = rb_ca_sort_addr_c(rkey, raxis, 0, 1); /* masked_last=1 (:last), unchanged default */
|
|
453
|
+
return rb_ca_fetch(self, addrs);
|
|
454
|
+
}
|
|
461
455
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
456
|
+
/* max_by_key(key, axis: nil) -- self[key.max_addr(axis:)] (or UNDEF if empty). */
|
|
457
|
+
static VALUE
|
|
458
|
+
rb_ca_max_by_key (int argc, VALUE *argv, VALUE self)
|
|
459
|
+
{
|
|
460
|
+
VALUE rkey, rkw = Qnil, raxis = Qnil;
|
|
461
|
+
rb_scan_args(argc, argv, "1:", &rkey, &rkw);
|
|
462
|
+
rb_scan_options(rkw, "axis", &raxis);
|
|
463
|
+
if ( RTEST(rb_ca_is_empty(self)) ) {
|
|
464
|
+
return rb_const_get(rb_cObject, rb_intern("UNDEF"));
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
-
|
|
467
|
+
VALUE addrs;
|
|
468
468
|
|
|
469
|
-
if (
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
char *ptr, *val;
|
|
473
|
-
ca_size_t i, idx;
|
|
474
|
-
TypedData_Get_Struct(rval, CArray, &carray_data_type, cv);
|
|
475
|
-
if ( ca->data_type != cv->data_type ) {
|
|
476
|
-
cv = ca_wrap_readonly(rval, ca->data_type);
|
|
477
|
-
}
|
|
478
|
-
co = carray_new(CA_SIZE, cv->ndim, cv->dim, 0, NULL);
|
|
479
|
-
out = ca_wrap_struct(co);
|
|
480
|
-
ca_attach(cv);
|
|
481
|
-
if ( ca_is_fixlen_type(ca) ) {
|
|
482
|
-
cmp_data *cmp_ptr, *p, *ptr, cmp_val;
|
|
483
|
-
char *q;
|
|
484
|
-
ca_size_t i;
|
|
485
|
-
cmp_val.bytes = ca->bytes;
|
|
486
|
-
cmp_ptr = malloc_with_check(sizeof(cmp_data)*ca->elements);
|
|
487
|
-
for (i=0, p=cmp_ptr, q=ca->ptr; i<ca->elements; i++, p++, q+=ca->bytes) {
|
|
488
|
-
p->bytes = ca->bytes;
|
|
489
|
-
p->ptr = q;
|
|
490
|
-
}
|
|
491
|
-
for (i=0; i<cv->elements; i++) {
|
|
492
|
-
cmp_val.ptr = ca_ptr_at_addr(cv, i);
|
|
493
|
-
ptr = bsearch(&cmp_val, cmp_ptr, ca->elements, sizeof(cmp_data),
|
|
494
|
-
ca_qsort_cmp[CA_FIXLEN]);
|
|
495
|
-
vidx = ( ! ptr ) ? CA_UNDEF : SIZE2NUM(ptr - cmp_ptr);
|
|
496
|
-
rb_ca_store_addr(out, i, vidx);
|
|
497
|
-
}
|
|
498
|
-
free(cmp_ptr);
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
for (i=0; i<cv->elements; i++) {
|
|
502
|
-
val = ca_ptr_at_addr(cv, i);
|
|
503
|
-
ptr = bsearch(val, ca->ptr, ca->elements, ca->bytes,
|
|
504
|
-
ca_qsort_cmp[ca->data_type]);
|
|
505
|
-
if ( ! ptr ) {
|
|
506
|
-
rb_ca_store_addr(out, i, CA_UNDEF);
|
|
507
|
-
}
|
|
508
|
-
else {
|
|
509
|
-
idx = (ptr - ca->ptr)/ca->bytes;
|
|
510
|
-
ca_store_addr(co, i, &idx);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
ca_detach(cv);
|
|
469
|
+
if ( NIL_P(raxis) ) {
|
|
470
|
+
VALUE ki_argv[1] = { Qnil }; /* non-NULL for safety, unused at argc=0 */
|
|
471
|
+
addrs = rb_ca_argmax_addr_ki(0, ki_argv, rkey);
|
|
515
472
|
}
|
|
516
473
|
else {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
cmp_data *cmp_ptr, *p, *ptr, cmp_val;
|
|
521
|
-
char *q;
|
|
522
|
-
ca_size_t i;
|
|
523
|
-
cmp_val.bytes = ca->bytes;
|
|
524
|
-
cmp_val.ptr = val;
|
|
525
|
-
cmp_ptr = malloc_with_check(sizeof(cmp_data)*ca->elements);
|
|
526
|
-
for (i=0, p=cmp_ptr, q=ca->ptr; i<ca->elements; i++, p++, q+=ca->bytes) {
|
|
527
|
-
p->bytes = ca->bytes;
|
|
528
|
-
p->ptr = q;
|
|
529
|
-
}
|
|
530
|
-
ptr = bsearch(&cmp_val, cmp_ptr, ca->elements, sizeof(cmp_data),
|
|
531
|
-
ca_qsort_cmp[CA_FIXLEN]);
|
|
532
|
-
out = ( ! ptr ) ? Qnil : SIZE2NUM((ptr - cmp_ptr));
|
|
533
|
-
free(cmp_ptr);
|
|
534
|
-
}
|
|
535
|
-
else {
|
|
536
|
-
char *ptr;
|
|
537
|
-
ptr = bsearch(val, ca->ptr, ca->elements, ca->bytes,
|
|
538
|
-
ca_qsort_cmp[ca->data_type]);
|
|
539
|
-
out = ( ! ptr ) ? Qnil : SIZE2NUM((ptr - ca->ptr)/ca->bytes);
|
|
540
|
-
}
|
|
474
|
+
VALUE kw = rb_hash_new();
|
|
475
|
+
rb_hash_aset(kw, ID2SYM(id_axis), raxis);
|
|
476
|
+
addrs = rb_ca_argmax_addr_ki(1, &kw, rkey);
|
|
541
477
|
}
|
|
542
|
-
|
|
543
|
-
return out;
|
|
478
|
+
return rb_ca_fetch(self, addrs);
|
|
544
479
|
}
|
|
545
480
|
|
|
546
|
-
/*
|
|
547
|
-
|
|
548
|
-
[TBD].
|
|
549
|
-
*/
|
|
550
|
-
|
|
481
|
+
/* min_by_key(key, axis: nil) -- self[key.min_addr(axis:)] (or UNDEF if empty). */
|
|
551
482
|
static VALUE
|
|
552
|
-
|
|
483
|
+
rb_ca_min_by_key (int argc, VALUE *argv, VALUE self)
|
|
553
484
|
{
|
|
554
|
-
VALUE
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
#define proc_find_value(type) \
|
|
561
|
-
{ \
|
|
562
|
-
type *ptr = (type *) ca->ptr; \
|
|
563
|
-
boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
|
|
564
|
-
type val = (type) NUM2LL(value); \
|
|
565
|
-
ca_size_t i; \
|
|
566
|
-
if ( m ) { \
|
|
567
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
568
|
-
if ( ! *m++ ) { \
|
|
569
|
-
if ( *ptr == val ) { \
|
|
570
|
-
addr = i; \
|
|
571
|
-
break; \
|
|
572
|
-
} \
|
|
573
|
-
} \
|
|
574
|
-
} \
|
|
575
|
-
} \
|
|
576
|
-
else { \
|
|
577
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
578
|
-
if ( *ptr == val ) { \
|
|
579
|
-
addr = i; \
|
|
580
|
-
break; \
|
|
581
|
-
} \
|
|
582
|
-
} \
|
|
583
|
-
} \
|
|
485
|
+
VALUE rkey, rkw = Qnil, raxis = Qnil;
|
|
486
|
+
rb_scan_args(argc, argv, "1:", &rkey, &rkw);
|
|
487
|
+
rb_scan_options(rkw, "axis", &raxis);
|
|
488
|
+
if ( RTEST(rb_ca_is_empty(self)) ) {
|
|
489
|
+
return rb_const_get(rb_cObject, rb_intern("UNDEF"));
|
|
584
490
|
}
|
|
585
491
|
|
|
586
|
-
|
|
587
|
-
{ \
|
|
588
|
-
type *ptr = (type *) ca->ptr; \
|
|
589
|
-
boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
|
|
590
|
-
type val = (type) NUM2DBL(value); \
|
|
591
|
-
double eps = (NIL_P(veps)) ? defeps*fabs(val) : NUM2DBL(veps); \
|
|
592
|
-
ca_size_t i; \
|
|
593
|
-
if ( m ) { \
|
|
594
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
595
|
-
if ( ! *m++ ) { \
|
|
596
|
-
if ( fabs(*ptr - val) <= eps ) { \
|
|
597
|
-
addr = i; \
|
|
598
|
-
break; \
|
|
599
|
-
} \
|
|
600
|
-
} \
|
|
601
|
-
} \
|
|
602
|
-
} \
|
|
603
|
-
else { \
|
|
604
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
605
|
-
if ( fabs(*ptr - val) <= eps ) { \
|
|
606
|
-
addr = i; \
|
|
607
|
-
break; \
|
|
608
|
-
} \
|
|
609
|
-
} \
|
|
610
|
-
} \
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
#define proc_find_value_float128(type, defeps) \
|
|
614
|
-
{ \
|
|
615
|
-
type *ptr = (type *) ca->ptr; \
|
|
616
|
-
boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
|
|
617
|
-
type val = (type) NUM2DBL(value); \
|
|
618
|
-
float128_t eps = (NIL_P(veps)) ? defeps*fabsl(val) : NUM2DBL(veps); \
|
|
619
|
-
ca_size_t i; \
|
|
620
|
-
if ( m ) { \
|
|
621
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
622
|
-
if ( ! *m++ ) { \
|
|
623
|
-
if ( fabsl(*ptr - val) <= eps ) { \
|
|
624
|
-
addr = i; \
|
|
625
|
-
break; \
|
|
626
|
-
} \
|
|
627
|
-
} \
|
|
628
|
-
} \
|
|
629
|
-
} \
|
|
630
|
-
else { \
|
|
631
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
632
|
-
if ( fabsl(*ptr - val) <= eps ) { \
|
|
633
|
-
addr = i; \
|
|
634
|
-
break; \
|
|
635
|
-
} \
|
|
636
|
-
} \
|
|
637
|
-
} \
|
|
638
|
-
}
|
|
492
|
+
VALUE addrs;
|
|
639
493
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
|
|
644
|
-
type val = (type) NUM2CC(value); \
|
|
645
|
-
double eps = (NIL_P(veps)) ? defeps*cabs(val) : NUM2DBL(veps); \
|
|
646
|
-
ca_size_t i; \
|
|
647
|
-
if ( m ) { \
|
|
648
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
649
|
-
if ( ! *m++ ) { \
|
|
650
|
-
if ( cabs(*ptr - val) <= eps ) { \
|
|
651
|
-
addr = i; \
|
|
652
|
-
break; \
|
|
653
|
-
} \
|
|
654
|
-
} \
|
|
655
|
-
} \
|
|
656
|
-
} \
|
|
657
|
-
else { \
|
|
658
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
659
|
-
if ( cabs(*ptr - val) <= eps ) { \
|
|
660
|
-
addr = i; \
|
|
661
|
-
break; \
|
|
662
|
-
} \
|
|
663
|
-
} \
|
|
664
|
-
} \
|
|
494
|
+
if ( NIL_P(raxis) ) {
|
|
495
|
+
VALUE ki_argv[1] = { Qnil };
|
|
496
|
+
addrs = rb_ca_argmin_addr_ki(0, ki_argv, rkey);
|
|
665
497
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
|
|
671
|
-
ca_size_t i; \
|
|
672
|
-
if ( m ) { \
|
|
673
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
674
|
-
if ( ! *m++ ) { \
|
|
675
|
-
if ( rb_funcall(value, id_equal, 1, *ptr) ) { \
|
|
676
|
-
addr = i; \
|
|
677
|
-
break; \
|
|
678
|
-
} \
|
|
679
|
-
} \
|
|
680
|
-
} \
|
|
681
|
-
} \
|
|
682
|
-
else { \
|
|
683
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
684
|
-
if ( rb_funcall(value, id_equal, 1, *ptr) ) { \
|
|
685
|
-
addr = i; \
|
|
686
|
-
break; \
|
|
687
|
-
} \
|
|
688
|
-
} \
|
|
689
|
-
} \
|
|
498
|
+
else {
|
|
499
|
+
VALUE kw = rb_hash_new();
|
|
500
|
+
rb_hash_aset(kw, ID2SYM(id_axis), raxis);
|
|
501
|
+
addrs = rb_ca_argmin_addr_ki(1, &kw, rkey);
|
|
690
502
|
}
|
|
503
|
+
return rb_ca_fetch(self, addrs);
|
|
504
|
+
}
|
|
691
505
|
|
|
506
|
+
/* ---- take_along_axis / put_along_axis -------------------------------- */
|
|
692
507
|
|
|
693
|
-
/*
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
*/
|
|
697
|
-
|
|
508
|
+
/* C-callable positional twin: skip rb_scan_args / kwarg hash machinery
|
|
509
|
+
so internal C consumers (e.g. nlargest / nsmallest family) can call
|
|
510
|
+
directly without a kwarg trampoline. The Ruby binding forwards here. */
|
|
698
511
|
static VALUE
|
|
699
|
-
|
|
512
|
+
rb_ca_take_along_axis_c (VALUE self, VALUE indices, VALUE raxis)
|
|
700
513
|
{
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
ca_size_t addr;
|
|
704
|
-
|
|
705
|
-
rb_scan_args(argc, argv, "11", (VALUE *) &value, (VALUE *) &veps);
|
|
706
|
-
|
|
707
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
708
|
-
|
|
709
|
-
ca_attach(ca);
|
|
710
|
-
|
|
711
|
-
addr = -1;
|
|
712
|
-
|
|
713
|
-
switch ( ca->data_type ) {
|
|
714
|
-
case CA_BOOLEAN:
|
|
715
|
-
case CA_INT8:
|
|
716
|
-
case CA_UINT8: proc_find_value(int8_t); break;
|
|
717
|
-
case CA_INT16:
|
|
718
|
-
case CA_UINT16: proc_find_value(int16_t); break;
|
|
719
|
-
case CA_INT32: proc_find_value(int32_t); break;
|
|
720
|
-
case CA_UINT32: proc_find_value(uint32_t); break;
|
|
721
|
-
case CA_INT64: proc_find_value(int64_t); break;
|
|
722
|
-
case CA_UINT64: proc_find_value(uint64_t); break;
|
|
723
|
-
case CA_FLOAT32: proc_find_value_float(float32_t, FLT_EPSILON); break;
|
|
724
|
-
case CA_FLOAT64: proc_find_value_float(float64_t, DBL_EPSILON); break;
|
|
725
|
-
case CA_FLOAT128: proc_find_value_float128(float128_t, DBL_EPSILON); break;
|
|
726
|
-
#ifdef HAVE_COMPLEX_H
|
|
727
|
-
case CA_CMPLX64: proc_find_value_cmplx(cmplx64_t, FLT_EPSILON); break;
|
|
728
|
-
case CA_CMPLX128: proc_find_value_cmplx(cmplx128_t, DBL_EPSILON); break;
|
|
729
|
-
case CA_CMPLX256: proc_find_value_cmplx(cmplx256_t, DBL_EPSILON); break;
|
|
730
|
-
#endif
|
|
731
|
-
case CA_OBJECT: proc_find_value_object(); break;
|
|
732
|
-
default:
|
|
733
|
-
rb_raise(rb_eCADataTypeError, "invalid data type");
|
|
514
|
+
if ( NIL_P(raxis) ) {
|
|
515
|
+
raxis = INT2FIX(0);
|
|
734
516
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
return ( addr == -1 ) ? Qnil : SIZE2NUM(addr);
|
|
517
|
+
VALUE addrs = rb_ca_axis2addr_c(self, indices, raxis);
|
|
518
|
+
return rb_ca_fetch(self, addrs);
|
|
739
519
|
}
|
|
740
520
|
|
|
741
|
-
/* @overload search_index
|
|
742
|
-
|
|
743
|
-
[TBD].
|
|
744
|
-
*/
|
|
745
|
-
|
|
746
521
|
static VALUE
|
|
747
|
-
|
|
522
|
+
rb_ca_take_along_axis (int argc, VALUE *argv, VALUE self)
|
|
748
523
|
{
|
|
749
|
-
VALUE
|
|
750
|
-
|
|
524
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
525
|
+
VALUE raxis = Qnil;
|
|
526
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
527
|
+
rb_check_arity(argc, 1, 1);
|
|
528
|
+
return rb_ca_take_along_axis_c(self, argv[0], raxis);
|
|
751
529
|
}
|
|
752
530
|
|
|
753
|
-
/* ----------------------------------------------------------------- */
|
|
754
|
-
|
|
755
|
-
#define proc_nearest_addr(type, from, ABS) \
|
|
756
|
-
{ \
|
|
757
|
-
type *ptr = (type *) ca->ptr; \
|
|
758
|
-
boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
|
|
759
|
-
type val = (type) from(value); \
|
|
760
|
-
double trial; \
|
|
761
|
-
double diff = 1.0/0.0; \
|
|
762
|
-
ca_size_t i; \
|
|
763
|
-
addr = -1; \
|
|
764
|
-
if ( m ) { \
|
|
765
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
766
|
-
if ( ! *m++ ) { \
|
|
767
|
-
trial = ABS(val - *ptr); \
|
|
768
|
-
if ( trial < diff ) { \
|
|
769
|
-
addr = i; \
|
|
770
|
-
diff = trial; \
|
|
771
|
-
} \
|
|
772
|
-
} \
|
|
773
|
-
} \
|
|
774
|
-
} \
|
|
775
|
-
else { \
|
|
776
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
777
|
-
trial = ABS(val - *ptr); \
|
|
778
|
-
if ( trial < diff ) { \
|
|
779
|
-
addr = i; \
|
|
780
|
-
diff = trial; \
|
|
781
|
-
} \
|
|
782
|
-
} \
|
|
783
|
-
} \
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
#define proc_nearest_addr_VALUE() \
|
|
787
|
-
{ \
|
|
788
|
-
VALUE *ptr = (VALUE *) ca->ptr; \
|
|
789
|
-
boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
|
|
790
|
-
VALUE val = value; \
|
|
791
|
-
VALUE trial; \
|
|
792
|
-
VALUE diff = rb_float_new(1.0/0.0); \
|
|
793
|
-
ca_size_t i; \
|
|
794
|
-
addr = -1; \
|
|
795
|
-
if ( m ) { \
|
|
796
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
797
|
-
if ( ! *m++ ) { \
|
|
798
|
-
trial = rb_funcall(val, rb_intern("distance"), 1, *ptr); \
|
|
799
|
-
if ( rb_funcall(trial, rb_intern("<"), 1, diff) ) { \
|
|
800
|
-
addr = i; \
|
|
801
|
-
diff = trial; \
|
|
802
|
-
} \
|
|
803
|
-
} \
|
|
804
|
-
} \
|
|
805
|
-
} \
|
|
806
|
-
else { \
|
|
807
|
-
for (i=0; i<ca->elements; i++, ptr++) { \
|
|
808
|
-
trial = rb_funcall(val, rb_intern("distance"), 1, *ptr); \
|
|
809
|
-
if ( rb_funcall(trial, rb_intern("<"), 1, diff) ) { \
|
|
810
|
-
addr = i; \
|
|
811
|
-
diff = trial; \
|
|
812
|
-
} \
|
|
813
|
-
} \
|
|
814
|
-
} \
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
/* @overload search_nearest
|
|
818
|
-
|
|
819
|
-
[TBD].
|
|
820
|
-
*/
|
|
821
|
-
|
|
822
531
|
static VALUE
|
|
823
|
-
|
|
532
|
+
rb_ca_put_along_axis (int argc, VALUE *argv, VALUE self)
|
|
824
533
|
{
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
case CA_UINT8: proc_nearest_addr(uint8_t, NUM2ULONG, fabs); break;
|
|
836
|
-
case CA_INT16: proc_nearest_addr(int16_t, NUM2LONG, fabs); break;
|
|
837
|
-
case CA_UINT16: proc_nearest_addr(uint16_t, NUM2ULONG, fabs); break;
|
|
838
|
-
case CA_INT32: proc_nearest_addr(int32_t, NUM2LONG, fabs); break;
|
|
839
|
-
case CA_UINT32: proc_nearest_addr(uint32_t, NUM2ULONG, fabs); break;
|
|
840
|
-
case CA_INT64: proc_nearest_addr(int64_t, NUM2LL, fabs); break;
|
|
841
|
-
case CA_UINT64: proc_nearest_addr(uint64_t, rb_num2ull, fabs); break;
|
|
842
|
-
case CA_FLOAT32: proc_nearest_addr(float32_t, NUM2DBL, fabs); break;
|
|
843
|
-
case CA_FLOAT64: proc_nearest_addr(float64_t, NUM2DBL, fabs); break;
|
|
844
|
-
case CA_FLOAT128: proc_nearest_addr(float128_t, NUM2DBL, fabs); break;
|
|
845
|
-
#ifdef HAVE_COMPLEX_H
|
|
846
|
-
case CA_CMPLX64: proc_nearest_addr(cmplx64_t, NUM2CC, cabs); break;
|
|
847
|
-
case CA_CMPLX128: proc_nearest_addr(cmplx128_t, NUM2CC, cabs); break;
|
|
848
|
-
case CA_CMPLX256: proc_nearest_addr(cmplx256_t, NUM2CC, cabs); break;
|
|
849
|
-
#endif
|
|
850
|
-
case CA_OBJECT: proc_nearest_addr_VALUE(); break;
|
|
851
|
-
default:
|
|
852
|
-
rb_raise(rb_eCADataTypeError, "invalid data type for nearest_addr()");
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
ca_detach(ca);
|
|
856
|
-
|
|
857
|
-
return ( addr == -1 ) ? Qnil : SIZE2NUM(addr);
|
|
534
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
535
|
+
VALUE raxis = Qnil;
|
|
536
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
537
|
+
rb_check_arity(argc, 2, 2);
|
|
538
|
+
if ( NIL_P(raxis) ) {
|
|
539
|
+
raxis = INT2FIX(0);
|
|
540
|
+
}
|
|
541
|
+
VALUE addrs = rb_ca_axis2addr_c(self, argv[0], raxis);
|
|
542
|
+
rb_ca_store(self, addrs, argv[1]);
|
|
543
|
+
return self;
|
|
858
544
|
}
|
|
859
545
|
|
|
860
|
-
/*
|
|
861
|
-
|
|
862
|
-
[TBD].
|
|
863
|
-
*/
|
|
546
|
+
/* ---- range -- (min..max) via fused minmax ----------------------------- */
|
|
864
547
|
|
|
865
548
|
static VALUE
|
|
866
|
-
|
|
549
|
+
rb_ca_range_method (VALUE self)
|
|
867
550
|
{
|
|
868
|
-
VALUE
|
|
869
|
-
|
|
551
|
+
VALUE mm_argv[1] = { Qnil };
|
|
552
|
+
VALUE pair = rb_ca_minmax_ki(0, mm_argv, self);
|
|
553
|
+
VALUE lo = rb_ary_entry(pair, 0);
|
|
554
|
+
VALUE hi = rb_ary_entry(pair, 1);
|
|
555
|
+
return rb_range_new(lo, hi, 0);
|
|
870
556
|
}
|
|
871
557
|
|
|
872
|
-
/*
|
|
558
|
+
/* ---- nlargest / nsmallest family ------------------------------------- */
|
|
873
559
|
|
|
874
|
-
|
|
875
|
-
|
|
560
|
+
/* Per-axis top-k positions (cap clamped, axis normalized).
|
|
561
|
+
* Called by rb_ca_topk_index below. */
|
|
562
|
+
static VALUE
|
|
563
|
+
rb_ca_topk_positions (VALUE self, long cap, long axis_norm, int desc)
|
|
876
564
|
{
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
if ( yy <= y[0] ) {
|
|
883
|
-
x1 = 0;
|
|
884
|
-
goto found;
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
if ( yy >= y[n-1] ) {
|
|
888
|
-
x1 = n-2;
|
|
889
|
-
goto found;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
/* check for equally spaced scale */
|
|
893
|
-
|
|
894
|
-
a = (ca_size_t)((yy-y[0])/(y[n-1]-y[0])*(n-1));
|
|
895
|
-
|
|
896
|
-
if ( a >= 0 && a < n-1 ) {
|
|
897
|
-
if ( (y[a] - yy) * (y[a+1] - yy) <= 0 ) { /* lucky case */
|
|
898
|
-
x1 = a;
|
|
899
|
-
goto found;
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
/* binary section method */
|
|
904
|
-
|
|
905
|
-
a = 0;
|
|
906
|
-
b = n-1;
|
|
907
|
-
|
|
908
|
-
ya = y[a];
|
|
909
|
-
yb = y[b];
|
|
910
|
-
|
|
911
|
-
if ( ya > yb ) {
|
|
912
|
-
return -1; /* input scale array should have accending order */
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
while ( (b - a) >= 1 ) {
|
|
916
|
-
|
|
917
|
-
c = (a + b)/2;
|
|
918
|
-
yc = y[c];
|
|
919
|
-
if ( a == c ) {
|
|
920
|
-
break;
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
if ( yc == yy ) {
|
|
924
|
-
a = c;
|
|
925
|
-
break;
|
|
926
|
-
}
|
|
927
|
-
else if ( (ya - yy) * (yc - yy) <= 0 ) {
|
|
928
|
-
b = c;
|
|
929
|
-
yb = yc;
|
|
930
|
-
}
|
|
931
|
-
else {
|
|
932
|
-
a = c;
|
|
933
|
-
ya = yc;
|
|
934
|
-
}
|
|
565
|
+
CArray *ca;
|
|
566
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
567
|
+
long dim_axis = (long) ca->dim[axis_norm];
|
|
568
|
+
VALUE raxis_norm = LONG2NUM(axis_norm);
|
|
935
569
|
|
|
936
|
-
|
|
937
|
-
|
|
570
|
+
if ( cap >= dim_axis ) {
|
|
571
|
+
VALUE full = rb_ca_sort_index_ki_quick(self, raxis_norm);
|
|
572
|
+
if ( desc ) {
|
|
573
|
+
full = rb_ca_flip_axis(full, NUM2LONG(raxis_norm));
|
|
938
574
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
575
|
+
return rb_ca_copy(full);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
long pivot = desc ? (dim_axis - cap) : (cap - 1);
|
|
579
|
+
VALUE rpivot = LONG2NUM(pivot);
|
|
580
|
+
|
|
581
|
+
/* Build a Ruby indexer spec: nil on every axis except `axis_norm`,
|
|
582
|
+
where we take the top-k (or bottom-k) range after partitioning. */
|
|
583
|
+
int ndim = (int) ca->ndim;
|
|
584
|
+
VALUE spec[CA_RANK_MAX];
|
|
585
|
+
for ( int k = 0; k < ndim; k++ ) {
|
|
586
|
+
spec[k] = Qnil;
|
|
587
|
+
}
|
|
588
|
+
spec[axis_norm] = desc
|
|
589
|
+
? rb_range_new(rpivot, LONG2NUM(dim_axis - 1), 0) /* (pivot..dim-1) */
|
|
590
|
+
: rb_range_new(INT2FIX(0), LONG2NUM(cap), 1); /* (0...cap) */
|
|
591
|
+
|
|
592
|
+
/* partidx_full[*spec] |> take_along_axis(...) |> sort_index(...) |>
|
|
593
|
+
flip(if desc) |> take_along_axis(...) |> copy. */
|
|
594
|
+
VALUE partidx_full = rb_ca_partition_index_ki(self, raxis_norm, rpivot);
|
|
595
|
+
VALUE partidx_top = rb_ca_fetch2(partidx_full, ndim, spec);
|
|
596
|
+
VALUE vals_top = rb_ca_take_along_axis_c(self, partidx_top, raxis_norm);
|
|
597
|
+
VALUE order = rb_ca_sort_index_ki_quick(vals_top, raxis_norm);
|
|
598
|
+
if ( desc ) {
|
|
599
|
+
order = rb_ca_flip_axis(order, NUM2LONG(raxis_norm));
|
|
600
|
+
}
|
|
601
|
+
VALUE picked = rb_ca_take_along_axis_c(partidx_top, order, raxis_norm);
|
|
602
|
+
return rb_ca_copy(picked);
|
|
960
603
|
}
|
|
961
604
|
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
605
|
+
/* Dispatcher: normalize axis, clamp cap, empty-cap corner.
|
|
606
|
+
* Called by rb_ca_nlargest_index / rb_ca_nsmallest_index (index
|
|
607
|
+
* variants) and indirectly by rb_ca_topk_values below. */
|
|
965
608
|
static VALUE
|
|
966
|
-
|
|
609
|
+
rb_ca_topk_index (VALUE self, VALUE rn, VALUE raxis, int desc, const char *name)
|
|
967
610
|
{
|
|
968
|
-
|
|
969
|
-
CArray *ca, *sc, *cx, *co0, *co;
|
|
970
|
-
ca_size_t n;
|
|
971
|
-
double *x;
|
|
972
|
-
double *px;
|
|
973
|
-
double *po;
|
|
974
|
-
ca_size_t i;
|
|
975
|
-
|
|
611
|
+
CArray *ca;
|
|
976
612
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
ca_attach_n(3, sc, cx, co);
|
|
990
|
-
|
|
991
|
-
n = sc->elements;
|
|
992
|
-
x = (double*) sc->ptr;
|
|
993
|
-
px = (double*) cx->ptr;
|
|
994
|
-
po = (double*) co->ptr;
|
|
995
|
-
|
|
996
|
-
ca_update_mask(cx);
|
|
997
|
-
if ( cx->mask ) {
|
|
998
|
-
boolean8_t *mx, *mo;
|
|
999
|
-
ca_create_mask(co);
|
|
1000
|
-
mx = (boolean8_t *) cx->mask->ptr;
|
|
1001
|
-
mo = (boolean8_t *) co->mask->ptr;
|
|
1002
|
-
for (i=0; i<cx->elements; i++) {
|
|
1003
|
-
if ( ! *mx ) {
|
|
1004
|
-
linear_index(n, x, *px, po);
|
|
1005
|
-
}
|
|
1006
|
-
else {
|
|
1007
|
-
*mo = 1;
|
|
1008
|
-
}
|
|
1009
|
-
mx++; mo++; px++, po++;
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
else {
|
|
1013
|
-
for (i=0; i<cx->elements; i++) {
|
|
1014
|
-
linear_index(n, x, *px, po);
|
|
1015
|
-
px++; po++;
|
|
613
|
+
long a = rb_ca_normalize_axis_value(self, raxis, name);
|
|
614
|
+
long n_val = NUM2LONG(rn);
|
|
615
|
+
long dim_a = (long) ca->dim[a];
|
|
616
|
+
long cap = (n_val < dim_a) ? n_val : dim_a;
|
|
617
|
+
if ( cap < 0 ) {
|
|
618
|
+
cap = 0;
|
|
619
|
+
}
|
|
620
|
+
if ( cap == 0 ) {
|
|
621
|
+
/* Return zero-along-axis int64 array via the C carray constructor. */
|
|
622
|
+
ca_size_t out_dim[CA_RANK_MAX];
|
|
623
|
+
for ( int k = 0; k < (int) ca->ndim; k++ ) {
|
|
624
|
+
out_dim[k] = (k == a) ? 0 : ca->dim[k];
|
|
1016
625
|
}
|
|
626
|
+
return rb_carray_new(CA_INT64, ca->ndim, out_dim, 0, NULL);
|
|
1017
627
|
}
|
|
1018
|
-
|
|
1019
|
-
ca_sync(co);
|
|
1020
|
-
ca_detach_n(3, sc, cx, co);
|
|
1021
|
-
|
|
1022
|
-
if ( rb_ca_is_scalar(vx) ) {
|
|
1023
|
-
return rb_funcall(out0, rb_intern("[]"), 1, INT2NUM(0));
|
|
1024
|
-
}
|
|
1025
|
-
else {
|
|
1026
|
-
return out0;
|
|
1027
|
-
}
|
|
628
|
+
return rb_ca_topk_positions(self, cap, a, desc);
|
|
1028
629
|
}
|
|
1029
630
|
|
|
1030
|
-
|
|
1031
631
|
static VALUE
|
|
1032
|
-
|
|
632
|
+
rb_ca_nlargest_index (int argc, VALUE *argv, VALUE self)
|
|
1033
633
|
{
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1044
|
-
|
|
1045
|
-
if ( rb_ca_is_any_masked(self) ) {
|
|
1046
|
-
rb_raise(rb_eRuntimeError, "self should not have any masked elements");
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
sc = ca_wrap_readonly(self, CA_FLOAT64);
|
|
1050
|
-
cx = ca_wrap_readonly(vx, CA_FLOAT64);
|
|
1051
|
-
|
|
1052
|
-
if ( sc->ndim < 2 ) {
|
|
1053
|
-
rb_raise(rb_eRuntimeError, "ndim of self should be larger than 2");
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
if ( cx->ndim > CA_DIM_MAX ) {
|
|
1057
|
-
rb_raise(rb_eRuntimeError, "2nd argument carray has too large dimension");
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
nseri = 1;
|
|
1061
|
-
for (i=0; i<sc->ndim-1; i++) {
|
|
1062
|
-
nseri *= sc->dim[i];
|
|
1063
|
-
}
|
|
1064
|
-
nlist = sc->dim[sc->ndim-1];
|
|
1065
|
-
|
|
1066
|
-
if ( rb_ca_is_scalar(vx) ) {
|
|
1067
|
-
for (i=0; i<sc->ndim-1; i++) {
|
|
1068
|
-
odim[i] = sc->dim[i];
|
|
1069
|
-
}
|
|
1070
|
-
co0 = carray_new(ca->data_type, sc->ndim-1, odim, 0, NULL);
|
|
1071
|
-
}
|
|
1072
|
-
else {
|
|
1073
|
-
for (i=0; i<sc->ndim-1; i++) {
|
|
1074
|
-
odim[i] = sc->dim[i];
|
|
1075
|
-
}
|
|
1076
|
-
memcpy(&odim[sc->ndim], cx->dim, cx->ndim*sizeof(ca_size_t));
|
|
1077
|
-
co0 = carray_new(ca->data_type, sc->ndim-1 + cx->ndim, odim, 0, NULL);
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
out = out0 = ca_wrap_struct(co0);
|
|
1081
|
-
co = ca_wrap_writable(out, CA_FLOAT64);
|
|
1082
|
-
|
|
1083
|
-
ca_attach_n(3, sc, cx, co);
|
|
1084
|
-
|
|
1085
|
-
x = (double*) sc->ptr;
|
|
1086
|
-
po = (double*) co->ptr;
|
|
1087
|
-
|
|
1088
|
-
ca_update_mask(cx);
|
|
1089
|
-
if ( cx->mask ) {
|
|
1090
|
-
boolean8_t *mx, *mo;
|
|
1091
|
-
ca_create_mask(co);
|
|
1092
|
-
mx = (boolean8_t *) cx->mask->ptr;
|
|
1093
|
-
mo = (boolean8_t *) co->mask->ptr;
|
|
1094
|
-
for (k=0; k<nseri; k++) {
|
|
1095
|
-
px = (double*) cx->ptr;
|
|
1096
|
-
for (i=0; i<cx->elements; i++) {
|
|
1097
|
-
if ( ! *mx ) {
|
|
1098
|
-
linear_index(nlist, x, *px, po);
|
|
1099
|
-
}
|
|
1100
|
-
else {
|
|
1101
|
-
*mo = 1;
|
|
1102
|
-
}
|
|
1103
|
-
mx++; mo++; px++, po++;
|
|
1104
|
-
}
|
|
1105
|
-
x += nlist;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
else {
|
|
1109
|
-
for (k=0; k<nseri; k++) {
|
|
1110
|
-
px = (double*) cx->ptr;
|
|
1111
|
-
for (i=0; i<cx->elements; i++) {
|
|
1112
|
-
linear_index(nlist, x, *px, po);
|
|
1113
|
-
px++; po++;
|
|
1114
|
-
}
|
|
1115
|
-
x += nlist;
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
ca_sync(co);
|
|
1120
|
-
ca_detach_n(3, sc, cx, co);
|
|
1121
|
-
|
|
1122
|
-
return out0;
|
|
634
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
635
|
+
VALUE raxis = Qnil;
|
|
636
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
637
|
+
rb_check_arity(argc, 1, 1);
|
|
638
|
+
if ( NIL_P(raxis) ) {
|
|
639
|
+
rb_raise(rb_eArgError, "nlargest_index: axis: kwarg is required");
|
|
640
|
+
}
|
|
641
|
+
return rb_ca_topk_index(self, argv[0], raxis, 1, "nlargest_index");
|
|
1123
642
|
}
|
|
1124
643
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
static ca_size_t
|
|
1128
|
-
linear_index_linear (ca_size_t n, double *y, double yy, double *idx)
|
|
644
|
+
static VALUE
|
|
645
|
+
rb_ca_nsmallest_index (int argc, VALUE *argv, VALUE self)
|
|
1129
646
|
{
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
for (k=0; k<n-1; k++) {
|
|
1139
|
-
if ( (yy - y[k])*(yy - y[k+1]) <= 0 ) {
|
|
1140
|
-
x1 = k;
|
|
1141
|
-
goto found;
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
*idx = -1;
|
|
1146
|
-
return -1;
|
|
1147
|
-
|
|
1148
|
-
found:
|
|
1149
|
-
|
|
1150
|
-
y1 = y[x1];
|
|
1151
|
-
y2 = y[x1+1];
|
|
1152
|
-
rest = (yy-y1)/(y2-y1);
|
|
1153
|
-
|
|
1154
|
-
*idx = rest + (double) x1;
|
|
1155
|
-
return 0;
|
|
647
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
648
|
+
VALUE raxis = Qnil;
|
|
649
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
650
|
+
rb_check_arity(argc, 1, 1);
|
|
651
|
+
if ( NIL_P(raxis) ) {
|
|
652
|
+
rb_raise(rb_eArgError, "nsmallest_index: axis: kwarg is required");
|
|
653
|
+
}
|
|
654
|
+
return rb_ca_topk_index(self, argv[0], raxis, 0, "nsmallest_index");
|
|
1156
655
|
}
|
|
1157
656
|
|
|
657
|
+
/* Shared body for nlargest / nsmallest (desc=1 vs desc=0).
|
|
658
|
+
* Called by rb_ca_nlargest and rb_ca_nsmallest below. */
|
|
1158
659
|
static VALUE
|
|
1159
|
-
|
|
660
|
+
rb_ca_topk_values (VALUE self, VALUE rn, VALUE raxis, int desc, const char *name)
|
|
1160
661
|
{
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
if ( rb_ca_is_any_masked(self) ) {
|
|
1172
|
-
rb_raise(rb_eRuntimeError, "self should not have any masked elements");
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
sc = ca_wrap_readonly(self, CA_FLOAT64);
|
|
1176
|
-
cx = ca_wrap_readonly(vx, CA_FLOAT64);
|
|
1177
|
-
|
|
1178
|
-
co0 = carray_new(ca->data_type, cx->ndim, cx->dim, 0, NULL);
|
|
1179
|
-
out = out0 = ca_wrap_struct(co0);
|
|
1180
|
-
co = ca_wrap_writable(out, CA_FLOAT64);
|
|
1181
|
-
|
|
1182
|
-
ca_attach_n(3, sc, cx, co);
|
|
1183
|
-
|
|
1184
|
-
n = sc->elements;
|
|
1185
|
-
x = (double*) sc->ptr;
|
|
1186
|
-
px = (double*) cx->ptr;
|
|
1187
|
-
po = (double*) co->ptr;
|
|
1188
|
-
|
|
1189
|
-
ca_update_mask(cx);
|
|
1190
|
-
if ( cx->mask ) {
|
|
1191
|
-
boolean8_t *mx, *mo;
|
|
1192
|
-
ca_create_mask(co);
|
|
1193
|
-
mx = (boolean8_t *) cx->mask->ptr;
|
|
1194
|
-
mo = (boolean8_t *) co->mask->ptr;
|
|
1195
|
-
for (i=0; i<cx->elements; i++) {
|
|
1196
|
-
if ( ! *mx ) {
|
|
1197
|
-
if ( linear_index_linear(n, x, *px, po) < 0 )
|
|
1198
|
-
*mo = 1;
|
|
1199
|
-
}
|
|
1200
|
-
else {
|
|
1201
|
-
*mo = 1;
|
|
1202
|
-
}
|
|
1203
|
-
mx++; mo++; px++, po++;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
else {
|
|
1207
|
-
for (i=0; i<cx->elements; i++) {
|
|
1208
|
-
linear_index_linear(n, x, *px, po);
|
|
1209
|
-
px++; po++;
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
ca_sync(co);
|
|
1214
|
-
ca_detach_n(3, sc, cx, co);
|
|
1215
|
-
|
|
1216
|
-
if ( rb_ca_is_scalar(vx) ) {
|
|
1217
|
-
return rb_funcall(out0, rb_intern("[]"), 1, INT2NUM(0));
|
|
1218
|
-
}
|
|
1219
|
-
else {
|
|
1220
|
-
return out0;
|
|
1221
|
-
}
|
|
662
|
+
if ( NIL_P(raxis) ) {
|
|
663
|
+
/* No-axis path: flatten + axis-0 topk + fetch. */
|
|
664
|
+
VALUE flat = rb_ca_flatten(self);
|
|
665
|
+
VALUE idx = rb_ca_topk_index(flat, rn, INT2FIX(0), desc, name);
|
|
666
|
+
return rb_ca_take_along_axis_c(flat, idx, INT2FIX(0));
|
|
667
|
+
}
|
|
668
|
+
long a = rb_ca_normalize_axis_value(self, raxis, name);
|
|
669
|
+
VALUE idx = rb_ca_topk_index(self, rn, LONG2NUM(a), desc, name);
|
|
670
|
+
return rb_ca_take_along_axis_c(self, idx, LONG2NUM(a));
|
|
1222
671
|
}
|
|
1223
672
|
|
|
1224
673
|
static VALUE
|
|
1225
|
-
|
|
674
|
+
rb_ca_nlargest (int argc, VALUE *argv, VALUE self)
|
|
1226
675
|
{
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
ca_size_t nseri, nlist;
|
|
1233
|
-
ca_size_t odim[CA_DIM_MAX];
|
|
1234
|
-
ca_size_t i, k;
|
|
1235
|
-
|
|
1236
|
-
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1237
|
-
|
|
1238
|
-
if ( rb_ca_is_any_masked(self) ) {
|
|
1239
|
-
rb_raise(rb_eRuntimeError, "self should not have any masked elements");
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
sc = ca_wrap_readonly(self, CA_FLOAT64);
|
|
1243
|
-
cx = ca_wrap_readonly(vx, CA_FLOAT64);
|
|
1244
|
-
|
|
1245
|
-
if ( sc->ndim < 2 ) {
|
|
1246
|
-
rb_raise(rb_eRuntimeError, "ndim of self should be larger than 2");
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
if ( cx->ndim > CA_DIM_MAX ) {
|
|
1250
|
-
rb_raise(rb_eRuntimeError, "2nd argument carray has too large dimension");
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
nseri = 1;
|
|
1254
|
-
for (i=0; i<sc->ndim-1; i++) {
|
|
1255
|
-
nseri *= sc->dim[i];
|
|
1256
|
-
}
|
|
1257
|
-
nlist = sc->dim[sc->ndim-1];
|
|
1258
|
-
|
|
1259
|
-
if ( rb_ca_is_scalar(vx) ) {
|
|
1260
|
-
for (i=0; i<sc->ndim-1; i++) {
|
|
1261
|
-
odim[i] = sc->dim[i];
|
|
1262
|
-
}
|
|
1263
|
-
co0 = carray_new(ca->data_type, sc->ndim-1, odim, 0, NULL);
|
|
1264
|
-
}
|
|
1265
|
-
else {
|
|
1266
|
-
for (i=0; i<sc->ndim-1; i++) {
|
|
1267
|
-
odim[i] = sc->dim[i];
|
|
1268
|
-
}
|
|
1269
|
-
memcpy(&odim[sc->ndim], cx->dim, cx->ndim*sizeof(ca_size_t));
|
|
1270
|
-
co0 = carray_new(ca->data_type, sc->ndim-1 + cx->ndim, odim, 0, NULL);
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
out = out0 = ca_wrap_struct(co0);
|
|
1274
|
-
co = ca_wrap_writable(out, CA_FLOAT64);
|
|
1275
|
-
|
|
1276
|
-
ca_attach_n(3, sc, cx, co);
|
|
1277
|
-
|
|
1278
|
-
x = (double*) sc->ptr;
|
|
1279
|
-
po = (double*) co->ptr;
|
|
1280
|
-
|
|
1281
|
-
ca_update_mask(cx);
|
|
1282
|
-
if ( cx->mask ) {
|
|
1283
|
-
boolean8_t *mx, *mo;
|
|
1284
|
-
ca_create_mask(co);
|
|
1285
|
-
mx = (boolean8_t *) cx->mask->ptr;
|
|
1286
|
-
mo = (boolean8_t *) co->mask->ptr;
|
|
1287
|
-
for (k=0; k<nseri; k++) {
|
|
1288
|
-
px = (double*) cx->ptr;
|
|
1289
|
-
for (i=0; i<cx->elements; i++) {
|
|
1290
|
-
if ( ! *mx ) {
|
|
1291
|
-
if ( linear_index_linear(nlist, x, *px, po) < 0)
|
|
1292
|
-
*mo = 1;
|
|
1293
|
-
}
|
|
1294
|
-
else {
|
|
1295
|
-
*mo = 1;
|
|
1296
|
-
}
|
|
1297
|
-
mx++; mo++; px++, po++;
|
|
1298
|
-
}
|
|
1299
|
-
x += nlist;
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
else {
|
|
1303
|
-
for (k=0; k<nseri; k++) {
|
|
1304
|
-
px = (double*) cx->ptr;
|
|
1305
|
-
for (i=0; i<cx->elements; i++) {
|
|
1306
|
-
linear_index_linear(nlist, x, *px, po);
|
|
1307
|
-
px++; po++;
|
|
1308
|
-
}
|
|
1309
|
-
x += nlist;
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
ca_sync(co);
|
|
1314
|
-
ca_detach_n(3, sc, cx, co);
|
|
1315
|
-
|
|
1316
|
-
return out0;
|
|
676
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
677
|
+
VALUE raxis = Qnil;
|
|
678
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
679
|
+
rb_check_arity(argc, 1, 1);
|
|
680
|
+
return rb_ca_topk_values(self, argv[0], raxis, 1, "nlargest");
|
|
1317
681
|
}
|
|
1318
682
|
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
static int
|
|
1322
|
-
fetch_linear_addr (ca_size_t n, double *y, double idx, double *val)
|
|
683
|
+
static VALUE
|
|
684
|
+
rb_ca_nsmallest (int argc, VALUE *argv, VALUE self)
|
|
1323
685
|
{
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
return -1;
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
il = (ca_size_t) floor(idx);
|
|
1333
|
-
iu = (ca_size_t) ceil(idx);
|
|
1334
|
-
w = idx - floor(idx);
|
|
1335
|
-
|
|
1336
|
-
*val = y[iu]*w + y[il]*(1.0-w);
|
|
1337
|
-
|
|
1338
|
-
/* printf("%g %i %i %g %g\n", idx, il, iu, w, *val); */
|
|
1339
|
-
|
|
1340
|
-
return 0;
|
|
686
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
687
|
+
VALUE raxis = Qnil;
|
|
688
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
689
|
+
rb_check_arity(argc, 1, 1);
|
|
690
|
+
return rb_ca_topk_values(self, argv[0], raxis, 0, "nsmallest");
|
|
1341
691
|
}
|
|
1342
692
|
|
|
693
|
+
/* ---- order(axis:, descending:, method:) -------------------------------
|
|
694
|
+
*
|
|
695
|
+
* method: :ordinal (default) assigns every cell a distinct rank (ties
|
|
696
|
+
* broken by stable original position, scipy.stats.rankdata 'ordinal'
|
|
697
|
+
* style). method: :dense assigns tied values the same rank (no gaps),
|
|
698
|
+
* the standard "dense rank" -- lets order(descending:) compose as a
|
|
699
|
+
* sort_addr priority key without silently dropping a lower-priority
|
|
700
|
+
* key on ties: ordinal ranks are already a total order (no two cells
|
|
701
|
+
* ever compare equal), so a later sort_addr key never gets consulted;
|
|
702
|
+
* dense ranks preserve ties, so it does.
|
|
703
|
+
*
|
|
704
|
+
* descending: still works under method: :dense via the same
|
|
705
|
+
* (n-1)-ascending transform below: n is fixed per-fiber, so within a
|
|
706
|
+
* tied group ascending values are equal and (n-1)-ascending stays
|
|
707
|
+
* equal too -- ties survive the transform, and the group-to-group
|
|
708
|
+
* order still reverses correctly. */
|
|
709
|
+
|
|
1343
710
|
static VALUE
|
|
1344
|
-
|
|
711
|
+
rb_ca_order (int argc, VALUE *argv, VALUE self)
|
|
1345
712
|
{
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
if ( sc->ndim != 1 ) {
|
|
1365
|
-
rb_raise(rb_eRuntimeError, "ndim of self should be 1");
|
|
713
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
714
|
+
VALUE raxis = Qnil, rdesc = Qfalse, rmethod = Qnil;
|
|
715
|
+
rb_scan_options(ropt, "axis,descending,method", &raxis, &rdesc, &rmethod);
|
|
716
|
+
rb_check_arity(argc, 0, 0);
|
|
717
|
+
|
|
718
|
+
int dense = 0; /* default method: :ordinal */
|
|
719
|
+
if ( ! NIL_P(rmethod) ) {
|
|
720
|
+
static ID sym_ordinal = 0, sym_dense = 0;
|
|
721
|
+
if ( ! sym_ordinal ) sym_ordinal = rb_intern("ordinal");
|
|
722
|
+
if ( ! sym_dense ) sym_dense = rb_intern("dense");
|
|
723
|
+
ID method_id = SYM2ID(rmethod);
|
|
724
|
+
if ( method_id == sym_ordinal ) dense = 0;
|
|
725
|
+
else if ( method_id == sym_dense ) dense = 1;
|
|
726
|
+
else {
|
|
727
|
+
rb_raise(rb_eArgError, "order: unknown method %s (expected :ordinal or :dense)",
|
|
728
|
+
rb_id2name(method_id));
|
|
729
|
+
}
|
|
1366
730
|
}
|
|
1367
|
-
|
|
1368
|
-
nlist = sc->dim[0];
|
|
1369
|
-
|
|
1370
|
-
nreq = 1;
|
|
1371
|
-
for (i=1; i<cx->ndim; i++) {
|
|
1372
|
-
nreq *= cx->dim[i];
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
co0 = carray_new(ca->data_type, cx->ndim, cx->dim, 0, NULL);
|
|
1376
|
-
out = out0 = ca_wrap_struct(co0);
|
|
1377
|
-
co = ca_wrap_writable(out, CA_FLOAT64);
|
|
1378
|
-
|
|
1379
|
-
ca_attach_n(3, sc, cx, co);
|
|
1380
|
-
|
|
1381
|
-
x = (double*) sc->ptr;
|
|
1382
|
-
px = (double*) cx->ptr;
|
|
1383
|
-
po = (double*) co->ptr;
|
|
1384
731
|
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
}
|
|
1397
|
-
else {
|
|
1398
|
-
*mo = 1;
|
|
1399
|
-
}
|
|
1400
|
-
mx++; mo++; px++, po++;
|
|
732
|
+
VALUE asc, n;
|
|
733
|
+
if ( NIL_P(raxis) ) {
|
|
734
|
+
VALUE flat = rb_ca_flatten(self);
|
|
735
|
+
/* Direct C-level dispatch via c_callable: true extern (mkkernel). */
|
|
736
|
+
VALUE ranked = rb_ca_rank_index_ki_quick_dense(flat, INT2FIX(0), dense);
|
|
737
|
+
/* reshape(*shape) */
|
|
738
|
+
CArray *ca;
|
|
739
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
740
|
+
VALUE shape_argv[CA_RANK_MAX];
|
|
741
|
+
for ( long k = 0; k < (long) ca->ndim; k++ ) {
|
|
742
|
+
shape_argv[k] = LONG2NUM((long) ca->dim[k]);
|
|
1401
743
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
744
|
+
asc = rb_ca_reshape((int) ca->ndim, shape_argv, ranked);
|
|
745
|
+
n = RTEST(rb_ca_has_mask(self))
|
|
746
|
+
? SIZE2NUM(ca_count_not_masked(ca)) /* = elements - count_masked */
|
|
747
|
+
: rb_ca_elements(self);
|
|
748
|
+
} else {
|
|
749
|
+
long axis_norm = rb_ca_normalize_axis_value(self, raxis, "order");
|
|
750
|
+
VALUE raxis_norm = LONG2NUM(axis_norm);
|
|
751
|
+
asc = rb_ca_rank_index_ki_quick_dense(self, raxis_norm, dense);
|
|
752
|
+
if ( RTEST(rb_ca_has_mask(self)) ) {
|
|
753
|
+
n = rb_ca_count_not_masked_c(self, raxis_norm);
|
|
754
|
+
} else {
|
|
755
|
+
CArray *ca;
|
|
756
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
757
|
+
n = LONG2NUM((long) ca->dim[axis_norm]);
|
|
758
|
+
}
|
|
759
|
+
if ( RTEST(rb_obj_is_kind_of(n, rb_cCArray)) ) {
|
|
760
|
+
VALUE ia_argv[1] = { raxis_norm };
|
|
761
|
+
n = rb_ca_insert_axis(1, ia_argv, n);
|
|
1410
762
|
}
|
|
1411
763
|
}
|
|
1412
764
|
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
765
|
+
VALUE diff;
|
|
766
|
+
if ( RTEST(rdesc) ) {
|
|
767
|
+
/* `-` via rb_funcall handles both Integer-Integer and
|
|
768
|
+
CArray/Integer mixed receivers uniformly via Ruby's operator
|
|
769
|
+
dispatch. No single C entry covers both. */
|
|
770
|
+
VALUE n_minus_1 = rb_funcall(n, id_sub, 1, INT2FIX(1));
|
|
771
|
+
diff = rb_funcall(n_minus_1, id_sub, 1, asc);
|
|
772
|
+
} else {
|
|
773
|
+
diff = asc;
|
|
774
|
+
}
|
|
775
|
+
/* Output data_type: CA_SIZE (= ca_size_t, int64 on 64-bit builds),
|
|
776
|
+
matching the rest of the *_index family (sort_index / partition_index
|
|
777
|
+
/ rank_index) that order is built on. No explicit cast needed here:
|
|
778
|
+
asc (rank_index_ki's output) is already CA_SIZE, and Integer - CArray
|
|
779
|
+
promotion in the descending branch preserves it. */
|
|
780
|
+
return diff;
|
|
1422
781
|
}
|
|
1423
782
|
|
|
783
|
+
/* ---- linear_section / linear_fetch ----------------------------------- */
|
|
1424
784
|
|
|
1425
|
-
/*
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
self: ndim >= 2
|
|
1429
|
-
0...ndim : prev dimensions are vectorized elements
|
|
1430
|
-
-1: last dimension is used for fetch_addr (as self)
|
|
1431
|
-
|
|
1432
|
-
vx: ndim >= 2
|
|
1433
|
-
0...ndim : prev dimensions are vectorized elements should be equal to self's
|
|
1434
|
-
-1: last dimension is used for fetch_addr (as addr)
|
|
1435
|
-
|
|
1436
|
-
*/
|
|
1437
|
-
|
|
1438
|
-
|
|
785
|
+
/* Coerce self to CA_FLOAT64 (no-copy when already f64 via
|
|
786
|
+
* rb_ca_to_float64), then optionally flatten when axis is nil.
|
|
787
|
+
* Called by rb_ca_linear_section_m and rb_ca_linear_fetch_m. */
|
|
1439
788
|
static VALUE
|
|
1440
|
-
|
|
789
|
+
ca_linear_prep (VALUE self, VALUE raxis, const char *name, long *axis_out)
|
|
1441
790
|
{
|
|
1442
|
-
|
|
1443
|
-
CArray *ca, *sc, *cx, *co0, *co;
|
|
1444
|
-
double *x;
|
|
1445
|
-
double *px;
|
|
1446
|
-
double *po;
|
|
1447
|
-
ca_size_t nseri, nlist, nreq, xnseri;
|
|
1448
|
-
ca_size_t i, k;
|
|
1449
|
-
boolean8_t *mx, *mo;
|
|
1450
|
-
|
|
791
|
+
CArray *ca;
|
|
1451
792
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
if (
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
rb_raise(rb_eRuntimeError, "1st dimension should be same between self and 1st argument");
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
if ( cx->ndim == sc->ndim - 1 ) {
|
|
1484
|
-
nreq = 1;
|
|
1485
|
-
}
|
|
1486
|
-
else {
|
|
1487
|
-
nreq = cx->dim[cx->ndim-1];
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
co0 = carray_new(ca->data_type, cx->ndim, cx->dim, 0, NULL);
|
|
1491
|
-
out = out0 = ca_wrap_struct(co0);
|
|
1492
|
-
co = ca_wrap_writable(out, CA_FLOAT64);
|
|
1493
|
-
|
|
1494
|
-
ca_attach_n(3, sc, cx, co);
|
|
1495
|
-
|
|
1496
|
-
x = (double*) sc->ptr;
|
|
1497
|
-
px = (double*) cx->ptr;
|
|
1498
|
-
po = (double*) co->ptr;
|
|
1499
|
-
|
|
1500
|
-
ca_create_mask(co);
|
|
1501
|
-
ca_update_mask(cx);
|
|
1502
|
-
|
|
1503
|
-
if ( cx->mask ) {
|
|
1504
|
-
mx = (boolean8_t *) cx->mask->ptr;
|
|
1505
|
-
mo = (boolean8_t *) co->mask->ptr;
|
|
1506
|
-
for (k=0; k<nseri; k++) {
|
|
1507
|
-
for (i=0; i<nreq; i++) {
|
|
1508
|
-
if ( ! *mx ) {
|
|
1509
|
-
if ( linear_index(nlist, x, *px, po) ) {
|
|
1510
|
-
*mo = 1;
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
else {
|
|
1514
|
-
*mo = 1;
|
|
1515
|
-
}
|
|
1516
|
-
mx++; mo++; px++, po++;
|
|
1517
|
-
}
|
|
1518
|
-
x += nlist;
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
else {
|
|
1522
|
-
mo = (boolean8_t *) co->mask->ptr;
|
|
1523
|
-
for (k=0; k<nseri; k++) {
|
|
1524
|
-
for (i=0; i<nreq; i++) {
|
|
1525
|
-
if ( linear_index(nlist, x, *px, po) ) {
|
|
1526
|
-
*mo = 1;
|
|
1527
|
-
}
|
|
1528
|
-
mo++; px++; po++;
|
|
1529
|
-
}
|
|
1530
|
-
x += nlist;
|
|
1531
|
-
}
|
|
793
|
+
/* Face gate: linear_section / linear_fetch treat the axis as a continuous
|
|
794
|
+
numeric coordinate (fractional index by interpolating the stored values).
|
|
795
|
+
An ORDERABLE Face (storage order == surface order) is descended to its
|
|
796
|
+
storage here; the fraction is defined in storage space, which for a
|
|
797
|
+
numeric-relabel Face (datetime int64, etc.) is exactly the coordinate.
|
|
798
|
+
Non-orderable Faces raise. Non-numeric storage (e.g. a fixlen-string
|
|
799
|
+
Face) is caught by the rb_ca_to_float64 cast below, so no separate
|
|
800
|
+
float-numeric flag is needed. */
|
|
801
|
+
if ( ca_is_face(ca) ) {
|
|
802
|
+
if ( ! ca_test_flag(ca, CA_FLAG_FACE_ORDERABLE_STORAGE) ) {
|
|
803
|
+
rb_raise(rb_eArgError,
|
|
804
|
+
"%s: Face-typed input (%s) is not orderable by storage; "
|
|
805
|
+
"use ca.parent to descend to storage",
|
|
806
|
+
name, rb_obj_classname(self));
|
|
807
|
+
}
|
|
808
|
+
self = rb_ca_strip_face_value(self);
|
|
809
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
810
|
+
}
|
|
811
|
+
VALUE sc = (ca->data_type == CA_FLOAT64) ? self : rb_ca_to_float64(self);
|
|
812
|
+
if ( NIL_P(raxis) ) {
|
|
813
|
+
CArray *sca;
|
|
814
|
+
TypedData_Get_Struct(sc, CArray, &carray_data_type, sca);
|
|
815
|
+
if ( sca->ndim > 1 ) {
|
|
816
|
+
sc = rb_ca_flatten(sc);
|
|
817
|
+
}
|
|
818
|
+
*axis_out = 0;
|
|
819
|
+
} else {
|
|
820
|
+
*axis_out = rb_ca_normalize_axis_value(sc, raxis, name);
|
|
1532
821
|
}
|
|
1533
|
-
|
|
1534
|
-
ca_sync(co);
|
|
1535
|
-
ca_detach_n(3, sc, cx, co);
|
|
1536
|
-
|
|
1537
|
-
return out0;
|
|
822
|
+
return sc;
|
|
1538
823
|
}
|
|
1539
824
|
|
|
1540
|
-
|
|
1541
825
|
static VALUE
|
|
1542
|
-
|
|
826
|
+
rb_ca_linear_section_m (int argc, VALUE *argv, VALUE self)
|
|
1543
827
|
{
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
828
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
829
|
+
VALUE raxis = Qnil, rmethod = ID2SYM(id_sym_binary);
|
|
830
|
+
rb_scan_options(ropt, "axis,method", &raxis, &rmethod);
|
|
831
|
+
rb_check_arity(argc, 1, 1);
|
|
832
|
+
VALUE val = argv[0];
|
|
833
|
+
|
|
834
|
+
/* Query gate (generic, mirror search + reference flip
|
|
835
|
+
PROPOSAL_TO_COMPARABLE_RECEIVER_FLIP): the reference axis Face reconciles
|
|
836
|
+
the query into its own space. A COMPARABLE axis is directly comparable
|
|
837
|
+
-> strip a Face query, take a plain query as-is. A non-COMPARABLE Face
|
|
838
|
+
axis calls its own to_comparable(query) for ANY query type (Face CArray,
|
|
839
|
+
our Scalar, a Ruby Time / DateTime, ...), then strips; it raises if it
|
|
840
|
+
cannot reconcile the query. `self` is still the pre-strip axis Face
|
|
841
|
+
here, so it carries the unit for to_comparable and its COMPARABLE flag. */
|
|
842
|
+
{
|
|
843
|
+
int val_is_face = 0, self_is_face = 0, self_comparable = 0;
|
|
844
|
+
CArray *sca;
|
|
845
|
+
if ( rb_obj_is_kind_of(val, rb_cCArray) ) {
|
|
846
|
+
CArray *vca;
|
|
847
|
+
TypedData_Get_Struct(val, CArray, &carray_data_type, vca);
|
|
848
|
+
val_is_face = ca_is_face(vca);
|
|
849
|
+
}
|
|
850
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, sca);
|
|
851
|
+
if ( ca_is_face(sca) ) {
|
|
852
|
+
self_is_face = 1;
|
|
853
|
+
self_comparable = ca_test_flag(sca, CA_FLAG_FACE_COMPARABLE_STORAGE);
|
|
854
|
+
}
|
|
855
|
+
if ( self_comparable ) {
|
|
856
|
+
if ( val_is_face ) {
|
|
857
|
+
val = rb_ca_strip_face_value(val);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
else if ( self_is_face ) {
|
|
861
|
+
if ( rb_respond_to(self, rb_intern("to_comparable")) ) {
|
|
862
|
+
val = rb_funcall(self, rb_intern("to_comparable"), 1, val);
|
|
863
|
+
val = rb_ca_strip_face_value(val);
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
rb_raise(rb_eArgError,
|
|
867
|
+
"linear_section: non-comparable Face axis (%s) has no "
|
|
868
|
+
"to_comparable to reconcile the query; use ca.parent to "
|
|
869
|
+
"search the hidden storage explicitly",
|
|
870
|
+
rb_obj_classname(self));
|
|
871
|
+
}
|
|
872
|
+
}
|
|
1574
873
|
}
|
|
1575
874
|
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
if ( xnseri != nseri ) {
|
|
1582
|
-
rb_raise(rb_eRuntimeError, "1st dimension should be same between self and 1st argument");
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
|
-
if ( cx->ndim == sc->ndim - 1 ) {
|
|
1586
|
-
nreq = 1;
|
|
1587
|
-
}
|
|
1588
|
-
else {
|
|
1589
|
-
nreq = cx->dim[cx->ndim-1];
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
|
-
co0 = carray_new(ca->data_type, cx->ndim, cx->dim, 0, NULL);
|
|
1593
|
-
out = out0 = ca_wrap_struct(co0);
|
|
1594
|
-
co = ca_wrap_writable(out, CA_FLOAT64);
|
|
1595
|
-
|
|
1596
|
-
ca_attach_n(3, sc, cx, co);
|
|
875
|
+
long axis_norm = 0;
|
|
876
|
+
VALUE sc = ca_linear_prep(self, raxis, "linear_section", &axis_norm);
|
|
877
|
+
VALUE raxis_norm = LONG2NUM(axis_norm);
|
|
1597
878
|
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
mo = (boolean8_t *) co->mask->ptr;
|
|
1608
|
-
for (k=0; k<nseri; k++) {
|
|
1609
|
-
for (i=0; i<nreq; i++) {
|
|
1610
|
-
if ( ! *mx ) {
|
|
1611
|
-
if ( fetch_linear_addr(nlist, x, *px, po) ) {
|
|
1612
|
-
*mo = 1;
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
else {
|
|
1616
|
-
*mo = 1;
|
|
1617
|
-
}
|
|
1618
|
-
mx++; mo++; px++, po++;
|
|
1619
|
-
}
|
|
1620
|
-
x += nlist;
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
else {
|
|
1624
|
-
mo = (boolean8_t *) co->mask->ptr;
|
|
1625
|
-
for (k=0; k<nseri; k++) {
|
|
1626
|
-
for (i=0; i<nreq; i++) {
|
|
1627
|
-
if ( fetch_linear_addr(nlist, x, *px, po) ) {
|
|
1628
|
-
*mo = 1;
|
|
1629
|
-
}
|
|
1630
|
-
mo++; px++; po++;
|
|
1631
|
-
}
|
|
1632
|
-
x += nlist;
|
|
1633
|
-
}
|
|
879
|
+
if ( rmethod == ID2SYM(id_sym_binary) ) {
|
|
880
|
+
return rb_ca_linear_section_binary_ki(sc, val, raxis_norm);
|
|
881
|
+
} else if ( rmethod == ID2SYM(id_sym_linear) ) {
|
|
882
|
+
return rb_ca_linear_section_linear_ki(sc, val, raxis_norm);
|
|
883
|
+
} else {
|
|
884
|
+
rb_raise(rb_eArgError,
|
|
885
|
+
"linear_section: unknown method %"PRIsVALUE
|
|
886
|
+
" (expected :binary or :linear)",
|
|
887
|
+
rb_inspect(rmethod));
|
|
1634
888
|
}
|
|
1635
|
-
|
|
1636
|
-
ca_sync(co);
|
|
1637
|
-
ca_detach_n(3, sc, cx, co);
|
|
1638
|
-
|
|
1639
|
-
return out0;
|
|
1640
889
|
}
|
|
1641
890
|
|
|
1642
|
-
|
|
1643
|
-
|
|
891
|
+
static VALUE
|
|
892
|
+
rb_ca_linear_fetch_m (int argc, VALUE *argv, VALUE self)
|
|
1644
893
|
{
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
rb_define_method(rb_cCArray, "bsearch", rb_ca_binary_search, 1);
|
|
1656
|
-
rb_define_method(rb_cCArray, "bsearch_index", rb_ca_binary_search_index, 1);
|
|
1657
|
-
|
|
1658
|
-
rb_define_method(rb_cCArray, "search", rb_ca_linear_search, -1);
|
|
1659
|
-
rb_define_method(rb_cCArray, "search_index", rb_ca_linear_search_index, -1);
|
|
1660
|
-
|
|
1661
|
-
rb_define_method(rb_cCArray, "search_nearest",
|
|
1662
|
-
rb_ca_linear_search_nearest, 1);
|
|
1663
|
-
rb_define_method(rb_cCArray, "search_nearest_index",
|
|
1664
|
-
rb_ca_linear_search_nearest_index, 1);
|
|
1665
|
-
|
|
1666
|
-
rb_define_method(rb_cCArray, "section",
|
|
1667
|
-
rb_ca_binary_search_linear_index, 1);
|
|
1668
|
-
|
|
1669
|
-
rb_define_method(rb_cCArray, "vectorized_section",
|
|
1670
|
-
rb_ca_binary_search_linear_index_vectorized, 1);
|
|
894
|
+
VALUE ropt = rb_pop_options(&argc, &argv);
|
|
895
|
+
VALUE raxis = Qnil;
|
|
896
|
+
rb_scan_options(ropt, "axis", &raxis);
|
|
897
|
+
rb_check_arity(argc, 1, 1);
|
|
898
|
+
VALUE addr = argv[0];
|
|
899
|
+
|
|
900
|
+
long axis_norm = 0;
|
|
901
|
+
VALUE sc = ca_linear_prep(self, raxis, "linear_fetch", &axis_norm);
|
|
902
|
+
return rb_ca_linear_fetch_ki(sc, addr, LONG2NUM(axis_norm));
|
|
903
|
+
}
|
|
1671
904
|
|
|
1672
|
-
|
|
1673
|
-
|
|
905
|
+
/* [MOVED] locate_addr / locate_nearest_addr (formerly matchup /
|
|
906
|
+
* matchup_nearest) -> lib/carray/methods/locate_addr.rb (thin
|
|
907
|
+
* compositions of sort_addr + fetch + bsearch (or linear_section +
|
|
908
|
+
* mask_invalid + round/floor/ceil + int64) + project, all of which have
|
|
909
|
+
* Ruby surfaces). */
|
|
1674
910
|
|
|
1675
|
-
|
|
1676
|
-
|
|
911
|
+
/* [MOVED] median / percentile / quantile -> ext/carray_median_percentile.c
|
|
912
|
+
* (kth-fetch + 5-method picker + partition-vs-sort dispatch). That
|
|
913
|
+
* file calls rb_ca_partition_copy_c (non-static in carray_partition.c)
|
|
914
|
+
* for the numeric path; CA_OBJECT routes through the CA_OBJECT branches
|
|
915
|
+
* of partition_copy / sort. */
|
|
1677
916
|
|
|
1678
|
-
|
|
1679
|
-
rb_ca_fetch_linear_addr, 1);
|
|
917
|
+
extern VALUE rb_ca_value_array (VALUE self); /* carray_mask.c */
|
|
1680
918
|
|
|
1681
|
-
|
|
1682
|
-
|
|
919
|
+
void
|
|
920
|
+
Init_carray_order (void)
|
|
921
|
+
{
|
|
922
|
+
id_axis = rb_intern("axis");
|
|
923
|
+
id_sub = rb_intern("-");
|
|
924
|
+
id_sym_binary = rb_intern("binary");
|
|
925
|
+
id_sym_linear = rb_intern("linear");
|
|
1683
926
|
|
|
1684
|
-
rb_define_method(rb_cCArray, "
|
|
1685
|
-
rb_ca_fetch_linear_addr_vectorized, 1);
|
|
927
|
+
rb_define_method(rb_cCArray, "project", rb_ca_project, -1);
|
|
1686
928
|
|
|
929
|
+
/* Search family (dual API: index / addr) -- see the trampoline
|
|
930
|
+
comment block above for the axis: kwarg dispatch contract. */
|
|
931
|
+
rb_define_method(rb_cCArray, "bsearch", rb_ca_bsearch_kw, -1);
|
|
932
|
+
rb_define_method(rb_cCArray, "search", rb_ca_search_kw, -1);
|
|
933
|
+
rb_define_method(rb_cCArray, "search_nearest", rb_ca_search_nearest_kw, -1);
|
|
934
|
+
rb_define_method(rb_cCArray, "bsearch_addr", rb_ca_bsearch_addr_kw, -1);
|
|
935
|
+
rb_define_method(rb_cCArray, "search_addr", rb_ca_search_addr_kw, -1);
|
|
936
|
+
rb_define_method(rb_cCArray, "search_nearest_addr", rb_ca_search_nearest_addr_kw, -1);
|
|
937
|
+
|
|
938
|
+
rb_define_method(rb_cCArray, "sort_by_key", rb_ca_sort_by_key, -1);
|
|
939
|
+
rb_define_method(rb_cCArray, "max_by_key", rb_ca_max_by_key, -1);
|
|
940
|
+
rb_define_method(rb_cCArray, "min_by_key", rb_ca_min_by_key, -1);
|
|
941
|
+
rb_define_method(rb_cCArray, "take_along_axis", rb_ca_take_along_axis, -1);
|
|
942
|
+
rb_define_method(rb_cCArray, "put_along_axis", rb_ca_put_along_axis, -1);
|
|
943
|
+
rb_define_method(rb_cCArray, "range", rb_ca_range_method, 0);
|
|
944
|
+
rb_define_method(rb_cCArray, "nlargest", rb_ca_nlargest, -1);
|
|
945
|
+
rb_define_method(rb_cCArray, "nsmallest", rb_ca_nsmallest, -1);
|
|
946
|
+
rb_define_method(rb_cCArray, "nlargest_index", rb_ca_nlargest_index, -1);
|
|
947
|
+
rb_define_method(rb_cCArray, "nsmallest_index", rb_ca_nsmallest_index, -1);
|
|
948
|
+
rb_define_method(rb_cCArray, "order", rb_ca_order, -1);
|
|
949
|
+
rb_define_method(rb_cCArray, "linear_section", rb_ca_linear_section_m, -1);
|
|
950
|
+
rb_define_method(rb_cCArray, "linear_fetch", rb_ca_linear_fetch_m, -1);
|
|
951
|
+
|
|
952
|
+
/* [MOVED] bindings for the following live elsewhere:
|
|
953
|
+
sort / sort_copy -> carray_sort.c
|
|
954
|
+
partition / partition_copy -> carray_partition.c
|
|
955
|
+
median / percentile / quantile -> carray_median_percentile.c
|
|
956
|
+
(bound by Init_carray_median_percentile) */
|
|
1687
957
|
}
|