carray 3.0.3 → 3.0.4
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/CHANGELOG.md +264 -0
- data/README.md +3 -2
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +1 -6
- data/ext/ca_axis_group.c +27 -27
- data/ext/ca_binop_dispatch.c +1 -29
- data/ext/ca_binop_dispatch.h +0 -1
- data/ext/ca_categorical_iterator.c +205 -134
- data/ext/ca_compare.c +7 -18
- data/ext/ca_group_iter.c +16 -17
- data/ext/ca_kernel_iterator.c +1234 -1994
- data/ext/ca_kernel_iterator.h +391 -437
- data/ext/ca_monop_dispatch.c +82 -59
- data/ext/ca_monop_dispatch.h +1 -0
- data/ext/ca_obj_array.c +96 -39
- data/ext/ca_obj_bincmp.c +24 -21
- data/ext/ca_obj_binop.c +15 -26
- data/ext/ca_obj_bitarray.c +3 -2
- data/ext/ca_obj_bitfield.c +5 -6
- data/ext/ca_obj_block.c +18 -9
- data/ext/ca_obj_byte_swap.c +5 -6
- data/ext/ca_obj_const_string.c +173 -19
- data/ext/ca_obj_face.c +238 -57
- data/ext/ca_obj_face.h +19 -0
- data/ext/ca_obj_fake.c +15 -29
- data/ext/ca_obj_farray.c +6 -3
- data/ext/ca_obj_field.c +17 -5
- data/ext/ca_obj_fixlen_string.c +2 -3
- data/ext/ca_obj_grid.c +406 -132
- data/ext/ca_obj_meld.c +172 -34
- data/ext/ca_obj_moncmp.c +23 -8
- data/ext/ca_obj_monop.c +67 -57
- data/ext/ca_obj_object.c +157 -51
- data/ext/ca_obj_record.c +12 -7
- data/ext/ca_obj_reduce.c +13 -8
- data/ext/ca_obj_refer.c +25 -27
- data/ext/ca_obj_remap.c +30 -9
- data/ext/ca_obj_repeat.c +9 -10
- data/ext/ca_obj_roll.c +6 -5
- data/ext/ca_obj_select.c +14 -9
- data/ext/ca_obj_select_axis.c +15 -47
- data/ext/ca_obj_shift.c +11 -1
- data/ext/ca_obj_stack.c +179 -34
- data/ext/ca_obj_stride.c +162 -115
- data/ext/ca_obj_string.c +71 -4
- data/ext/ca_obj_tile.c +6 -5
- data/ext/ca_obj_time.c +22 -6
- data/ext/ca_obj_timedelta.c +22 -6
- data/ext/ca_obj_transpose.c +5 -3
- data/ext/ca_obj_triop.c +23 -32
- data/ext/ca_obj_window.c +190 -26
- data/ext/ca_sweep_engine.c +2 -2
- data/ext/caframe_csv_reader.c +80 -1
- data/ext/carray.h +181 -75
- data/ext/carray_access.c +184 -96
- data/ext/carray_address_basis.c +343 -87
- data/ext/carray_attribute.c +89 -6
- data/ext/carray_bincount.c +10 -8
- data/ext/carray_broadcast.c +13 -8
- data/ext/carray_build_flags.h +3 -0
- data/ext/carray_call_cfunc.c +108 -0
- data/ext/carray_cast.c +142 -24
- data/ext/carray_cast_func.rb +46 -6
- data/ext/carray_class.c +4 -3
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +16 -7
- data/ext/carray_copy.c +51 -14
- data/ext/carray_core.c +147 -55
- data/ext/carray_count.c +50 -20
- data/ext/carray_element.c +76 -33
- data/ext/carray_factorize.c +118 -64
- data/ext/carray_generate.c +191 -50
- data/ext/carray_histogram.c +62 -17
- data/ext/carray_hold.c +12 -15
- data/ext/carray_index_classifier.c +388 -176
- data/ext/carray_internal.h +336 -29
- data/ext/carray_kernels_bincmp.c +4453 -0
- data/ext/carray_kernels_binop.c +11368 -0
- data/ext/carray_kernels_init.c +1734 -0
- data/ext/carray_kernels_moncmp.c +2104 -0
- data/ext/carray_kernels_monop.c +18369 -0
- data/ext/carray_kernels_reduce_aggregate.c +23818 -0
- data/ext/carray_kernels_reduce_boolean.c +406 -0
- data/ext/carray_kernels_reduce_cumulative.c +10086 -0
- data/ext/carray_kernels_reduce_extreme.c +17634 -0
- data/ext/carray_kernels_reduce_variance.c +3849 -0
- data/ext/carray_kernels_scan.c +4302 -0
- data/ext/carray_kernels_search.c +33829 -0
- data/ext/carray_kernels_sort.c +10906 -0
- data/ext/carray_kernels_triop.c +1864 -0
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +170 -111
- data/ext/carray_mask.c +292 -72
- data/ext/carray_median_percentile.c +82 -28
- data/ext/carray_memory_view.c +669 -561
- data/ext/carray_operator.c +124 -47
- data/ext/carray_order.c +384 -76
- data/ext/carray_partition.c +28 -27
- data/ext/carray_random.c +67 -13
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +63 -38
- data/ext/carray_segment.c +3 -3
- data/ext/carray_slab.c +91 -28
- data/ext/carray_sort.c +35 -35
- data/ext/carray_struct.c +19 -18
- data/ext/carray_test.c +26 -5
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +246 -45
- data/ext/mk_call_cfunc.rb +19 -2
- data/ext/mkkernel.rb +198 -240
- data/ext/ruby_carray.c +10 -4
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +126 -22
- data/lib/carray/autoload_carray.rb +8 -31
- data/lib/carray/autoload_method_extension.rb +14 -5
- data/lib/carray/axis_group.rb +255 -106
- data/lib/carray/basics.rb +78 -10
- data/lib/carray/bincount_nd.rb +12 -2
- data/lib/carray/block_iterator.rb +126 -23
- data/lib/carray/boolean_reduce.rb +17 -17
- data/lib/carray/categorical.rb +165 -43
- data/lib/carray/categorical_iterator.rb +130 -27
- data/lib/carray/complex.rb +5 -5
- data/lib/carray/conditional.rb +67 -18
- data/lib/carray/const_string.rb +14 -5
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/convert.rb +69 -0
- data/lib/carray/frame/csv_parser.rb +111 -17
- data/lib/carray/frame/describe.rb +3 -2
- data/lib/carray/frame/frame.rb +246 -21
- data/lib/carray/frame/group.rb +510 -95
- data/lib/carray/frame/io.rb +115 -28
- data/lib/carray/frame/join.rb +312 -51
- data/lib/carray/frame/records.rb +83 -7
- data/lib/carray/frame/reshape.rb +42 -35
- data/lib/carray/frame/sort.rb +7 -19
- data/lib/carray/frame/verbs.rb +188 -48
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +11 -4
- data/lib/carray/fusion.rb +40 -16
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +31 -8
- data/lib/carray/iterator.rb +85 -7
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +182 -183
- data/lib/carray/mask_gap_fill.rb +63 -57
- data/lib/carray/meld_reduce.rb +12 -14
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +16 -0
- data/lib/carray/methods/bit_string.rb +1 -1
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +3 -1
- data/lib/carray/methods/gather_nd.rb +14 -5
- data/lib/carray/methods/insert_block.rb +2 -2
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +53 -36
- data/lib/carray/methods/join.rb +1 -6
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +47 -51
- data/lib/carray/methods/mode.rb +1 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/resize.rb +3 -3
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +3 -3
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +53 -8
- data/lib/carray/segment_iterator.rb +313 -82
- data/lib/carray/serialize.rb +24 -10
- data/lib/carray/slab_iterator.rb +50 -0
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +8 -1
- data/lib/carray/struct.rb +9 -21
- data/lib/carray/struct_builder.rb +19 -8
- data/lib/carray/time.rb +726 -104
- data/lib/carray/window_iterator.rb +122 -16
- data/lib/carray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +4 -0
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +2 -1
- data/yard-stubs/ca_obj_roll.rb +2 -2
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +8 -3
- data/yard-stubs/carray_access.rb +6 -1
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_cast.rb +10 -0
- data/yard-stubs/carray_conversion.rb +2 -1
- data/yard-stubs/carray_copy.rb +4 -2
- data/yard-stubs/carray_count.rb +4 -4
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_mask.rb +26 -2
- data/yard-stubs/carray_math.rb +27 -1
- data/yard-stubs/carray_median_percentile.rb +5 -2
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +29 -18
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +14 -9
- data/yard-stubs/carray_slab.rb +9 -2
- data/yard-stubs/carray_sort.rb +6 -5
- data/yard-stubs/carray_test.rb +5 -3
- metadata +25 -3
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
|
@@ -0,0 +1,3849 @@
|
|
|
1
|
+
/* ---------------------------------------------------------------------------
|
|
2
|
+
|
|
3
|
+
carray_kernels.c -- GENERATED by ext/mkkernel.rb -- DO NOT EDIT
|
|
4
|
+
|
|
5
|
+
Kernel definitions live in mkkernel.rb (search for `MkKernel.reduce`).
|
|
6
|
+
Regenerate by running:
|
|
7
|
+
|
|
8
|
+
cd ext && ruby mkkernel.rb > carray_kernels.c
|
|
9
|
+
|
|
10
|
+
extconf.rb regenerates automatically when mkkernel.rb is touched.
|
|
11
|
+
|
|
12
|
+
--------------------------------------------------------------------------- */
|
|
13
|
+
|
|
14
|
+
#include "carray.h"
|
|
15
|
+
#include "ca_kernel_iterator.h"
|
|
16
|
+
#include "ca_sort_kernels.h" /* sort kernels: internal, not via the carray.h umbrella */
|
|
17
|
+
#include "carray_internal.h" /* ca_lazy_arena_*, ca_is_lazy_view (streaming reduce) */
|
|
18
|
+
#include "ca_obj_face.h" /* rb_ca_strip_face_value (Face ordering gate) */
|
|
19
|
+
#include <math.h>
|
|
20
|
+
#include <stdint.h>
|
|
21
|
+
#include <stdlib.h> /* qsort, mergesort (HAVE_MERGESORT) -- for :sort kind */
|
|
22
|
+
|
|
23
|
+
/* MEMO_REDUCTION_FASTPATH_ENTITY_ONLY_GUARD Tier 2: CAStack identity is
|
|
24
|
+
probed by operation-table function pointer (obj_type is runtime-
|
|
25
|
+
assigned, so no CA_OBJ_STACK compile-time constant exists). */
|
|
26
|
+
extern ca_operation_function_t ca_stack_func;
|
|
27
|
+
/* The square root of a variance: an ε-negative from rounding becomes 0,
|
|
28
|
+
a NaN stays NaN (fmax(NaN, 0.0) is 0.0). */
|
|
29
|
+
#ifndef CARRAY_SQRT_CLAMP_DEFINED
|
|
30
|
+
#define CARRAY_SQRT_CLAMP_DEFINED
|
|
31
|
+
static inline double ca_sqrt_clamp (double v) { return sqrt(v < 0.0 ? 0.0 : v); }
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
/* BOOL2VAL: bool -> Ruby (Qtrue/Qfalse). Used as ruby_scalar wrapper
|
|
35
|
+
for the all/any flat-reduction Ruby surface so `a.all` / `a.any`
|
|
36
|
+
return real true/false, not Integer 0/1. (BOOL2OBJ already exists
|
|
37
|
+
but returns Integer per CArray's boolean-as-int convention.) */
|
|
38
|
+
#ifndef CARRAY_BOOL2VAL_DEFINED
|
|
39
|
+
#define CARRAY_BOOL2VAL_DEFINED
|
|
40
|
+
static inline VALUE BOOL2VAL (boolean8_t x) { return x ? Qtrue : Qfalse; }
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
#include "ca_op_powi.h"
|
|
44
|
+
#include "ca_op_cmplx64.h"
|
|
45
|
+
|
|
46
|
+
/* ===== variancep_ki ============================================ */
|
|
47
|
+
|
|
48
|
+
#define __variancep_i8_P1EXPR(__x) ((double)(__x))
|
|
49
|
+
#define __variancep_i8_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
50
|
+
static VALUE
|
|
51
|
+
variancep_ki_native_i8 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
52
|
+
{
|
|
53
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
54
|
+
CArray *co;
|
|
55
|
+
GetCArray(vout, co);
|
|
56
|
+
double *op = (double *) co->ptr;
|
|
57
|
+
ca_iter_state st;
|
|
58
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
59
|
+
slab_axes, naxes, 0);
|
|
60
|
+
if ( rc != CA_ITER_OK ) {
|
|
61
|
+
rb_raise(rb_eRuntimeError,
|
|
62
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
63
|
+
}
|
|
64
|
+
char *p;
|
|
65
|
+
boolean8_t *m;
|
|
66
|
+
ca_size_t out_i = 0;
|
|
67
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
68
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
69
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
70
|
+
double sum = 0.0;
|
|
71
|
+
ca_size_t masked_cnt = 0;
|
|
72
|
+
CA_SLAB_REDUCE_SUM8_EX(int8_t, double, st, p, m, sum, 0.0, __variancep_i8_P1EXPR, masked_cnt);
|
|
73
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
74
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
75
|
+
if ( __trigger ) {
|
|
76
|
+
if ( ! op_mask ) {
|
|
77
|
+
ca_create_mask(co);
|
|
78
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
79
|
+
}
|
|
80
|
+
op_mask[out_i] = 1;
|
|
81
|
+
op[out_i++] = (double) 0.0;
|
|
82
|
+
} else {
|
|
83
|
+
double mean = sum / (double) n_valid;
|
|
84
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
85
|
+
double M2 = 0.0;
|
|
86
|
+
ca_size_t __unused_mc = 0;
|
|
87
|
+
CA_SLAB_REDUCE_SUM8_EX(int8_t, double, st, p, m, M2, 0.0, __variancep_i8_P2EXPR, __unused_mc);
|
|
88
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
ca_iter_state_finish(&st);
|
|
92
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
93
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
94
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
95
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
96
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
97
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
98
|
+
return rb_float_new(op[0]);
|
|
99
|
+
}
|
|
100
|
+
return vout;
|
|
101
|
+
}
|
|
102
|
+
#undef __variancep_i8_P1EXPR
|
|
103
|
+
#undef __variancep_i8_P2EXPR
|
|
104
|
+
|
|
105
|
+
#define __variancep_u8_P1EXPR(__x) ((double)(__x))
|
|
106
|
+
#define __variancep_u8_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
107
|
+
static VALUE
|
|
108
|
+
variancep_ki_native_u8 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
109
|
+
{
|
|
110
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
111
|
+
CArray *co;
|
|
112
|
+
GetCArray(vout, co);
|
|
113
|
+
double *op = (double *) co->ptr;
|
|
114
|
+
ca_iter_state st;
|
|
115
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
116
|
+
slab_axes, naxes, 0);
|
|
117
|
+
if ( rc != CA_ITER_OK ) {
|
|
118
|
+
rb_raise(rb_eRuntimeError,
|
|
119
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
120
|
+
}
|
|
121
|
+
char *p;
|
|
122
|
+
boolean8_t *m;
|
|
123
|
+
ca_size_t out_i = 0;
|
|
124
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
125
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
126
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
127
|
+
double sum = 0.0;
|
|
128
|
+
ca_size_t masked_cnt = 0;
|
|
129
|
+
CA_SLAB_REDUCE_SUM8_EX(uint8_t, double, st, p, m, sum, 0.0, __variancep_u8_P1EXPR, masked_cnt);
|
|
130
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
131
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
132
|
+
if ( __trigger ) {
|
|
133
|
+
if ( ! op_mask ) {
|
|
134
|
+
ca_create_mask(co);
|
|
135
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
136
|
+
}
|
|
137
|
+
op_mask[out_i] = 1;
|
|
138
|
+
op[out_i++] = (double) 0.0;
|
|
139
|
+
} else {
|
|
140
|
+
double mean = sum / (double) n_valid;
|
|
141
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
142
|
+
double M2 = 0.0;
|
|
143
|
+
ca_size_t __unused_mc = 0;
|
|
144
|
+
CA_SLAB_REDUCE_SUM8_EX(uint8_t, double, st, p, m, M2, 0.0, __variancep_u8_P2EXPR, __unused_mc);
|
|
145
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
ca_iter_state_finish(&st);
|
|
149
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
150
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
151
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
152
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
153
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
154
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
155
|
+
return rb_float_new(op[0]);
|
|
156
|
+
}
|
|
157
|
+
return vout;
|
|
158
|
+
}
|
|
159
|
+
#undef __variancep_u8_P1EXPR
|
|
160
|
+
#undef __variancep_u8_P2EXPR
|
|
161
|
+
|
|
162
|
+
#define __variancep_i16_P1EXPR(__x) ((double)(__x))
|
|
163
|
+
#define __variancep_i16_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
164
|
+
static VALUE
|
|
165
|
+
variancep_ki_native_i16 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
166
|
+
{
|
|
167
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
168
|
+
CArray *co;
|
|
169
|
+
GetCArray(vout, co);
|
|
170
|
+
double *op = (double *) co->ptr;
|
|
171
|
+
ca_iter_state st;
|
|
172
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
173
|
+
slab_axes, naxes, 0);
|
|
174
|
+
if ( rc != CA_ITER_OK ) {
|
|
175
|
+
rb_raise(rb_eRuntimeError,
|
|
176
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
177
|
+
}
|
|
178
|
+
char *p;
|
|
179
|
+
boolean8_t *m;
|
|
180
|
+
ca_size_t out_i = 0;
|
|
181
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
182
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
183
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
184
|
+
double sum = 0.0;
|
|
185
|
+
ca_size_t masked_cnt = 0;
|
|
186
|
+
CA_SLAB_REDUCE_SUM8_EX(int16_t, double, st, p, m, sum, 0.0, __variancep_i16_P1EXPR, masked_cnt);
|
|
187
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
188
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
189
|
+
if ( __trigger ) {
|
|
190
|
+
if ( ! op_mask ) {
|
|
191
|
+
ca_create_mask(co);
|
|
192
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
193
|
+
}
|
|
194
|
+
op_mask[out_i] = 1;
|
|
195
|
+
op[out_i++] = (double) 0.0;
|
|
196
|
+
} else {
|
|
197
|
+
double mean = sum / (double) n_valid;
|
|
198
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
199
|
+
double M2 = 0.0;
|
|
200
|
+
ca_size_t __unused_mc = 0;
|
|
201
|
+
CA_SLAB_REDUCE_SUM8_EX(int16_t, double, st, p, m, M2, 0.0, __variancep_i16_P2EXPR, __unused_mc);
|
|
202
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
ca_iter_state_finish(&st);
|
|
206
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
207
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
208
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
209
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
210
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
211
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
212
|
+
return rb_float_new(op[0]);
|
|
213
|
+
}
|
|
214
|
+
return vout;
|
|
215
|
+
}
|
|
216
|
+
#undef __variancep_i16_P1EXPR
|
|
217
|
+
#undef __variancep_i16_P2EXPR
|
|
218
|
+
|
|
219
|
+
#define __variancep_u16_P1EXPR(__x) ((double)(__x))
|
|
220
|
+
#define __variancep_u16_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
221
|
+
static VALUE
|
|
222
|
+
variancep_ki_native_u16 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
223
|
+
{
|
|
224
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
225
|
+
CArray *co;
|
|
226
|
+
GetCArray(vout, co);
|
|
227
|
+
double *op = (double *) co->ptr;
|
|
228
|
+
ca_iter_state st;
|
|
229
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
230
|
+
slab_axes, naxes, 0);
|
|
231
|
+
if ( rc != CA_ITER_OK ) {
|
|
232
|
+
rb_raise(rb_eRuntimeError,
|
|
233
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
234
|
+
}
|
|
235
|
+
char *p;
|
|
236
|
+
boolean8_t *m;
|
|
237
|
+
ca_size_t out_i = 0;
|
|
238
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
239
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
240
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
241
|
+
double sum = 0.0;
|
|
242
|
+
ca_size_t masked_cnt = 0;
|
|
243
|
+
CA_SLAB_REDUCE_SUM8_EX(uint16_t, double, st, p, m, sum, 0.0, __variancep_u16_P1EXPR, masked_cnt);
|
|
244
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
245
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
246
|
+
if ( __trigger ) {
|
|
247
|
+
if ( ! op_mask ) {
|
|
248
|
+
ca_create_mask(co);
|
|
249
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
250
|
+
}
|
|
251
|
+
op_mask[out_i] = 1;
|
|
252
|
+
op[out_i++] = (double) 0.0;
|
|
253
|
+
} else {
|
|
254
|
+
double mean = sum / (double) n_valid;
|
|
255
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
256
|
+
double M2 = 0.0;
|
|
257
|
+
ca_size_t __unused_mc = 0;
|
|
258
|
+
CA_SLAB_REDUCE_SUM8_EX(uint16_t, double, st, p, m, M2, 0.0, __variancep_u16_P2EXPR, __unused_mc);
|
|
259
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
ca_iter_state_finish(&st);
|
|
263
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
264
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
265
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
266
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
267
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
268
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
269
|
+
return rb_float_new(op[0]);
|
|
270
|
+
}
|
|
271
|
+
return vout;
|
|
272
|
+
}
|
|
273
|
+
#undef __variancep_u16_P1EXPR
|
|
274
|
+
#undef __variancep_u16_P2EXPR
|
|
275
|
+
|
|
276
|
+
#define __variancep_i32_P1EXPR(__x) ((double)(__x))
|
|
277
|
+
#define __variancep_i32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
278
|
+
static VALUE
|
|
279
|
+
variancep_ki_native_i32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
280
|
+
{
|
|
281
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
282
|
+
CArray *co;
|
|
283
|
+
GetCArray(vout, co);
|
|
284
|
+
double *op = (double *) co->ptr;
|
|
285
|
+
ca_iter_state st;
|
|
286
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
287
|
+
slab_axes, naxes, 0);
|
|
288
|
+
if ( rc != CA_ITER_OK ) {
|
|
289
|
+
rb_raise(rb_eRuntimeError,
|
|
290
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
291
|
+
}
|
|
292
|
+
char *p;
|
|
293
|
+
boolean8_t *m;
|
|
294
|
+
ca_size_t out_i = 0;
|
|
295
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
296
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
297
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
298
|
+
double sum = 0.0;
|
|
299
|
+
ca_size_t masked_cnt = 0;
|
|
300
|
+
CA_SLAB_REDUCE_SUM8_EX(int32_t, double, st, p, m, sum, 0.0, __variancep_i32_P1EXPR, masked_cnt);
|
|
301
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
302
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
303
|
+
if ( __trigger ) {
|
|
304
|
+
if ( ! op_mask ) {
|
|
305
|
+
ca_create_mask(co);
|
|
306
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
307
|
+
}
|
|
308
|
+
op_mask[out_i] = 1;
|
|
309
|
+
op[out_i++] = (double) 0.0;
|
|
310
|
+
} else {
|
|
311
|
+
double mean = sum / (double) n_valid;
|
|
312
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
313
|
+
double M2 = 0.0;
|
|
314
|
+
ca_size_t __unused_mc = 0;
|
|
315
|
+
CA_SLAB_REDUCE_SUM8_EX(int32_t, double, st, p, m, M2, 0.0, __variancep_i32_P2EXPR, __unused_mc);
|
|
316
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
ca_iter_state_finish(&st);
|
|
320
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
321
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
322
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
323
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
324
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
325
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
326
|
+
return rb_float_new(op[0]);
|
|
327
|
+
}
|
|
328
|
+
return vout;
|
|
329
|
+
}
|
|
330
|
+
#undef __variancep_i32_P1EXPR
|
|
331
|
+
#undef __variancep_i32_P2EXPR
|
|
332
|
+
|
|
333
|
+
#define __variancep_u32_P1EXPR(__x) ((double)(__x))
|
|
334
|
+
#define __variancep_u32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
335
|
+
static VALUE
|
|
336
|
+
variancep_ki_native_u32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
337
|
+
{
|
|
338
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
339
|
+
CArray *co;
|
|
340
|
+
GetCArray(vout, co);
|
|
341
|
+
double *op = (double *) co->ptr;
|
|
342
|
+
ca_iter_state st;
|
|
343
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
344
|
+
slab_axes, naxes, 0);
|
|
345
|
+
if ( rc != CA_ITER_OK ) {
|
|
346
|
+
rb_raise(rb_eRuntimeError,
|
|
347
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
348
|
+
}
|
|
349
|
+
char *p;
|
|
350
|
+
boolean8_t *m;
|
|
351
|
+
ca_size_t out_i = 0;
|
|
352
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
353
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
354
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
355
|
+
double sum = 0.0;
|
|
356
|
+
ca_size_t masked_cnt = 0;
|
|
357
|
+
CA_SLAB_REDUCE_SUM8_EX(uint32_t, double, st, p, m, sum, 0.0, __variancep_u32_P1EXPR, masked_cnt);
|
|
358
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
359
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
360
|
+
if ( __trigger ) {
|
|
361
|
+
if ( ! op_mask ) {
|
|
362
|
+
ca_create_mask(co);
|
|
363
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
364
|
+
}
|
|
365
|
+
op_mask[out_i] = 1;
|
|
366
|
+
op[out_i++] = (double) 0.0;
|
|
367
|
+
} else {
|
|
368
|
+
double mean = sum / (double) n_valid;
|
|
369
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
370
|
+
double M2 = 0.0;
|
|
371
|
+
ca_size_t __unused_mc = 0;
|
|
372
|
+
CA_SLAB_REDUCE_SUM8_EX(uint32_t, double, st, p, m, M2, 0.0, __variancep_u32_P2EXPR, __unused_mc);
|
|
373
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
ca_iter_state_finish(&st);
|
|
377
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
378
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
379
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
380
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
381
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
382
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
383
|
+
return rb_float_new(op[0]);
|
|
384
|
+
}
|
|
385
|
+
return vout;
|
|
386
|
+
}
|
|
387
|
+
#undef __variancep_u32_P1EXPR
|
|
388
|
+
#undef __variancep_u32_P2EXPR
|
|
389
|
+
|
|
390
|
+
#define __variancep_i64_P1EXPR(__x) ((double)(__x))
|
|
391
|
+
#define __variancep_i64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
392
|
+
static VALUE
|
|
393
|
+
variancep_ki_native_i64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
394
|
+
{
|
|
395
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
396
|
+
CArray *co;
|
|
397
|
+
GetCArray(vout, co);
|
|
398
|
+
double *op = (double *) co->ptr;
|
|
399
|
+
ca_iter_state st;
|
|
400
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
401
|
+
slab_axes, naxes, 0);
|
|
402
|
+
if ( rc != CA_ITER_OK ) {
|
|
403
|
+
rb_raise(rb_eRuntimeError,
|
|
404
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
405
|
+
}
|
|
406
|
+
char *p;
|
|
407
|
+
boolean8_t *m;
|
|
408
|
+
ca_size_t out_i = 0;
|
|
409
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
410
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
411
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
412
|
+
double sum = 0.0;
|
|
413
|
+
ca_size_t masked_cnt = 0;
|
|
414
|
+
CA_SLAB_REDUCE_SUM8_EX(int64_t, double, st, p, m, sum, 0.0, __variancep_i64_P1EXPR, masked_cnt);
|
|
415
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
416
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
417
|
+
if ( __trigger ) {
|
|
418
|
+
if ( ! op_mask ) {
|
|
419
|
+
ca_create_mask(co);
|
|
420
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
421
|
+
}
|
|
422
|
+
op_mask[out_i] = 1;
|
|
423
|
+
op[out_i++] = (double) 0.0;
|
|
424
|
+
} else {
|
|
425
|
+
double mean = sum / (double) n_valid;
|
|
426
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
427
|
+
double M2 = 0.0;
|
|
428
|
+
ca_size_t __unused_mc = 0;
|
|
429
|
+
CA_SLAB_REDUCE_SUM8_EX(int64_t, double, st, p, m, M2, 0.0, __variancep_i64_P2EXPR, __unused_mc);
|
|
430
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
ca_iter_state_finish(&st);
|
|
434
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
435
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
436
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
437
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
438
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
439
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
440
|
+
return rb_float_new(op[0]);
|
|
441
|
+
}
|
|
442
|
+
return vout;
|
|
443
|
+
}
|
|
444
|
+
#undef __variancep_i64_P1EXPR
|
|
445
|
+
#undef __variancep_i64_P2EXPR
|
|
446
|
+
|
|
447
|
+
#define __variancep_u64_P1EXPR(__x) ((double)(__x))
|
|
448
|
+
#define __variancep_u64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
449
|
+
static VALUE
|
|
450
|
+
variancep_ki_native_u64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
451
|
+
{
|
|
452
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
453
|
+
CArray *co;
|
|
454
|
+
GetCArray(vout, co);
|
|
455
|
+
double *op = (double *) co->ptr;
|
|
456
|
+
ca_iter_state st;
|
|
457
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
458
|
+
slab_axes, naxes, 0);
|
|
459
|
+
if ( rc != CA_ITER_OK ) {
|
|
460
|
+
rb_raise(rb_eRuntimeError,
|
|
461
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
462
|
+
}
|
|
463
|
+
char *p;
|
|
464
|
+
boolean8_t *m;
|
|
465
|
+
ca_size_t out_i = 0;
|
|
466
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
467
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
468
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
469
|
+
double sum = 0.0;
|
|
470
|
+
ca_size_t masked_cnt = 0;
|
|
471
|
+
CA_SLAB_REDUCE_SUM8_EX(uint64_t, double, st, p, m, sum, 0.0, __variancep_u64_P1EXPR, masked_cnt);
|
|
472
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
473
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
474
|
+
if ( __trigger ) {
|
|
475
|
+
if ( ! op_mask ) {
|
|
476
|
+
ca_create_mask(co);
|
|
477
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
478
|
+
}
|
|
479
|
+
op_mask[out_i] = 1;
|
|
480
|
+
op[out_i++] = (double) 0.0;
|
|
481
|
+
} else {
|
|
482
|
+
double mean = sum / (double) n_valid;
|
|
483
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
484
|
+
double M2 = 0.0;
|
|
485
|
+
ca_size_t __unused_mc = 0;
|
|
486
|
+
CA_SLAB_REDUCE_SUM8_EX(uint64_t, double, st, p, m, M2, 0.0, __variancep_u64_P2EXPR, __unused_mc);
|
|
487
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
ca_iter_state_finish(&st);
|
|
491
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
492
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
493
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
494
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
495
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
496
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
497
|
+
return rb_float_new(op[0]);
|
|
498
|
+
}
|
|
499
|
+
return vout;
|
|
500
|
+
}
|
|
501
|
+
#undef __variancep_u64_P1EXPR
|
|
502
|
+
#undef __variancep_u64_P2EXPR
|
|
503
|
+
|
|
504
|
+
#define __variancep_f32_P1EXPR(__x) ((double)(__x))
|
|
505
|
+
#define __variancep_f32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
506
|
+
static VALUE
|
|
507
|
+
variancep_ki_native_f32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
508
|
+
{
|
|
509
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
510
|
+
CArray *co;
|
|
511
|
+
GetCArray(vout, co);
|
|
512
|
+
double *op = (double *) co->ptr;
|
|
513
|
+
ca_iter_state st;
|
|
514
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
515
|
+
slab_axes, naxes, 0);
|
|
516
|
+
if ( rc != CA_ITER_OK ) {
|
|
517
|
+
rb_raise(rb_eRuntimeError,
|
|
518
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
519
|
+
}
|
|
520
|
+
char *p;
|
|
521
|
+
boolean8_t *m;
|
|
522
|
+
ca_size_t out_i = 0;
|
|
523
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
524
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
525
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
526
|
+
double sum = 0.0;
|
|
527
|
+
ca_size_t masked_cnt = 0;
|
|
528
|
+
CA_SLAB_REDUCE_SUM8_EX(float, double, st, p, m, sum, 0.0, __variancep_f32_P1EXPR, masked_cnt);
|
|
529
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
530
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
531
|
+
if ( __trigger ) {
|
|
532
|
+
if ( ! op_mask ) {
|
|
533
|
+
ca_create_mask(co);
|
|
534
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
535
|
+
}
|
|
536
|
+
op_mask[out_i] = 1;
|
|
537
|
+
op[out_i++] = (double) 0.0;
|
|
538
|
+
} else {
|
|
539
|
+
double mean = sum / (double) n_valid;
|
|
540
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
541
|
+
double M2 = 0.0;
|
|
542
|
+
ca_size_t __unused_mc = 0;
|
|
543
|
+
CA_SLAB_REDUCE_SUM8_EX(float, double, st, p, m, M2, 0.0, __variancep_f32_P2EXPR, __unused_mc);
|
|
544
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
ca_iter_state_finish(&st);
|
|
548
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
549
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
550
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
551
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
552
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
553
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
554
|
+
return rb_float_new(op[0]);
|
|
555
|
+
}
|
|
556
|
+
return vout;
|
|
557
|
+
}
|
|
558
|
+
#undef __variancep_f32_P1EXPR
|
|
559
|
+
#undef __variancep_f32_P2EXPR
|
|
560
|
+
|
|
561
|
+
#define __variancep_f64_P1EXPR(__x) ((double)(__x))
|
|
562
|
+
#define __variancep_f64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
563
|
+
static VALUE
|
|
564
|
+
variancep_ki_native_f64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
565
|
+
{
|
|
566
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
567
|
+
CArray *co;
|
|
568
|
+
GetCArray(vout, co);
|
|
569
|
+
double *op = (double *) co->ptr;
|
|
570
|
+
ca_iter_state st;
|
|
571
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
572
|
+
slab_axes, naxes, 0);
|
|
573
|
+
if ( rc != CA_ITER_OK ) {
|
|
574
|
+
rb_raise(rb_eRuntimeError,
|
|
575
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
576
|
+
}
|
|
577
|
+
char *p;
|
|
578
|
+
boolean8_t *m;
|
|
579
|
+
ca_size_t out_i = 0;
|
|
580
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
581
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
582
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
583
|
+
double sum = 0.0;
|
|
584
|
+
ca_size_t masked_cnt = 0;
|
|
585
|
+
CA_SLAB_REDUCE_SUM8_EX(double, double, st, p, m, sum, 0.0, __variancep_f64_P1EXPR, masked_cnt);
|
|
586
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
587
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
588
|
+
if ( __trigger ) {
|
|
589
|
+
if ( ! op_mask ) {
|
|
590
|
+
ca_create_mask(co);
|
|
591
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
592
|
+
}
|
|
593
|
+
op_mask[out_i] = 1;
|
|
594
|
+
op[out_i++] = (double) 0.0;
|
|
595
|
+
} else {
|
|
596
|
+
double mean = sum / (double) n_valid;
|
|
597
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
598
|
+
double M2 = 0.0;
|
|
599
|
+
ca_size_t __unused_mc = 0;
|
|
600
|
+
CA_SLAB_REDUCE_SUM8_EX(double, double, st, p, m, M2, 0.0, __variancep_f64_P2EXPR, __unused_mc);
|
|
601
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
ca_iter_state_finish(&st);
|
|
605
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
606
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
607
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
608
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
609
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
610
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
611
|
+
return rb_float_new(op[0]);
|
|
612
|
+
}
|
|
613
|
+
return vout;
|
|
614
|
+
}
|
|
615
|
+
#undef __variancep_f64_P1EXPR
|
|
616
|
+
#undef __variancep_f64_P2EXPR
|
|
617
|
+
|
|
618
|
+
#define __variancep_cmplx64_P1EXPR(__x) (__x)
|
|
619
|
+
#define __variancep_cmplx64_P2EXPR(__x) (creal((__x) - mean) * creal((__x) - mean) + cimag((__x) - mean) * cimag((__x) - mean))
|
|
620
|
+
static VALUE
|
|
621
|
+
variancep_ki_native_cmplx64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
622
|
+
{
|
|
623
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
624
|
+
CArray *co;
|
|
625
|
+
GetCArray(vout, co);
|
|
626
|
+
double *op = (double *) co->ptr;
|
|
627
|
+
ca_iter_state st;
|
|
628
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
629
|
+
slab_axes, naxes, 0);
|
|
630
|
+
if ( rc != CA_ITER_OK ) {
|
|
631
|
+
rb_raise(rb_eRuntimeError,
|
|
632
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
633
|
+
}
|
|
634
|
+
char *p;
|
|
635
|
+
boolean8_t *m;
|
|
636
|
+
ca_size_t out_i = 0;
|
|
637
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
638
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
639
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
640
|
+
cmplx64_t sum = 0;
|
|
641
|
+
ca_size_t masked_cnt = 0;
|
|
642
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx64_t, cmplx64_t, st, p, m, sum, 0, __variancep_cmplx64_P1EXPR, masked_cnt);
|
|
643
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
644
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
645
|
+
if ( __trigger ) {
|
|
646
|
+
if ( ! op_mask ) {
|
|
647
|
+
ca_create_mask(co);
|
|
648
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
649
|
+
}
|
|
650
|
+
op_mask[out_i] = 1;
|
|
651
|
+
op[out_i++] = (double) 0.0;
|
|
652
|
+
} else {
|
|
653
|
+
cmplx64_t mean = sum / (cmplx64_t)(double) n_valid;
|
|
654
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
655
|
+
double M2 = 0.0;
|
|
656
|
+
ca_size_t __unused_mc = 0;
|
|
657
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx64_t, double, st, p, m, M2, 0.0, __variancep_cmplx64_P2EXPR, __unused_mc);
|
|
658
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
ca_iter_state_finish(&st);
|
|
662
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
663
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
664
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
665
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
666
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
667
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
668
|
+
return rb_float_new(op[0]);
|
|
669
|
+
}
|
|
670
|
+
return vout;
|
|
671
|
+
}
|
|
672
|
+
#undef __variancep_cmplx64_P1EXPR
|
|
673
|
+
#undef __variancep_cmplx64_P2EXPR
|
|
674
|
+
|
|
675
|
+
#define __variancep_cmplx128_P1EXPR(__x) (__x)
|
|
676
|
+
#define __variancep_cmplx128_P2EXPR(__x) (creal((__x) - mean) * creal((__x) - mean) + cimag((__x) - mean) * cimag((__x) - mean))
|
|
677
|
+
static VALUE
|
|
678
|
+
variancep_ki_native_cmplx128 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
679
|
+
{
|
|
680
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
681
|
+
CArray *co;
|
|
682
|
+
GetCArray(vout, co);
|
|
683
|
+
double *op = (double *) co->ptr;
|
|
684
|
+
ca_iter_state st;
|
|
685
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
686
|
+
slab_axes, naxes, 0);
|
|
687
|
+
if ( rc != CA_ITER_OK ) {
|
|
688
|
+
rb_raise(rb_eRuntimeError,
|
|
689
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
690
|
+
}
|
|
691
|
+
char *p;
|
|
692
|
+
boolean8_t *m;
|
|
693
|
+
ca_size_t out_i = 0;
|
|
694
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
695
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
696
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
697
|
+
cmplx128_t sum = 0;
|
|
698
|
+
ca_size_t masked_cnt = 0;
|
|
699
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx128_t, cmplx128_t, st, p, m, sum, 0, __variancep_cmplx128_P1EXPR, masked_cnt);
|
|
700
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
701
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
702
|
+
if ( __trigger ) {
|
|
703
|
+
if ( ! op_mask ) {
|
|
704
|
+
ca_create_mask(co);
|
|
705
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
706
|
+
}
|
|
707
|
+
op_mask[out_i] = 1;
|
|
708
|
+
op[out_i++] = (double) 0.0;
|
|
709
|
+
} else {
|
|
710
|
+
cmplx128_t mean = sum / (cmplx128_t)(double) n_valid;
|
|
711
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
712
|
+
double M2 = 0.0;
|
|
713
|
+
ca_size_t __unused_mc = 0;
|
|
714
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx128_t, double, st, p, m, M2, 0.0, __variancep_cmplx128_P2EXPR, __unused_mc);
|
|
715
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
ca_iter_state_finish(&st);
|
|
719
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
720
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
721
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
722
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
723
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
724
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
725
|
+
return rb_float_new(op[0]);
|
|
726
|
+
}
|
|
727
|
+
return vout;
|
|
728
|
+
}
|
|
729
|
+
#undef __variancep_cmplx128_P1EXPR
|
|
730
|
+
#undef __variancep_cmplx128_P2EXPR
|
|
731
|
+
|
|
732
|
+
#define __variancep_bool_P1EXPR(__x) ((double)(__x))
|
|
733
|
+
#define __variancep_bool_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
734
|
+
static VALUE
|
|
735
|
+
variancep_ki_native_bool (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
736
|
+
{
|
|
737
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
738
|
+
CArray *co;
|
|
739
|
+
GetCArray(vout, co);
|
|
740
|
+
double *op = (double *) co->ptr;
|
|
741
|
+
ca_iter_state st;
|
|
742
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
743
|
+
slab_axes, naxes, 0);
|
|
744
|
+
if ( rc != CA_ITER_OK ) {
|
|
745
|
+
rb_raise(rb_eRuntimeError,
|
|
746
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
747
|
+
}
|
|
748
|
+
char *p;
|
|
749
|
+
boolean8_t *m;
|
|
750
|
+
ca_size_t out_i = 0;
|
|
751
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
752
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
753
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
754
|
+
double sum = 0.0;
|
|
755
|
+
ca_size_t masked_cnt = 0;
|
|
756
|
+
CA_SLAB_REDUCE_SUM8_EX(boolean8_t, double, st, p, m, sum, 0.0, __variancep_bool_P1EXPR, masked_cnt);
|
|
757
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
758
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
759
|
+
if ( __trigger ) {
|
|
760
|
+
if ( ! op_mask ) {
|
|
761
|
+
ca_create_mask(co);
|
|
762
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
763
|
+
}
|
|
764
|
+
op_mask[out_i] = 1;
|
|
765
|
+
op[out_i++] = (double) 0.0;
|
|
766
|
+
} else {
|
|
767
|
+
double mean = sum / (double) n_valid;
|
|
768
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
769
|
+
double M2 = 0.0;
|
|
770
|
+
ca_size_t __unused_mc = 0;
|
|
771
|
+
CA_SLAB_REDUCE_SUM8_EX(boolean8_t, double, st, p, m, M2, 0.0, __variancep_bool_P2EXPR, __unused_mc);
|
|
772
|
+
op[out_i++] = (double)(M2 / (double)(n_valid));
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
ca_iter_state_finish(&st);
|
|
776
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
777
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
778
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
779
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
780
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
781
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
782
|
+
return rb_float_new(op[0]);
|
|
783
|
+
}
|
|
784
|
+
return vout;
|
|
785
|
+
}
|
|
786
|
+
#undef __variancep_bool_P1EXPR
|
|
787
|
+
#undef __variancep_bool_P2EXPR
|
|
788
|
+
|
|
789
|
+
/* The object lane calls Ruby for every cell, so a walk can raise part
|
|
790
|
+
way. Its states live in the caller's frame, and ca_iter_ensure
|
|
791
|
+
finishes them however the body leaves. */
|
|
792
|
+
typedef struct {
|
|
793
|
+
ca_iter_state states[1];
|
|
794
|
+
VALUE self;
|
|
795
|
+
CArray *ca;
|
|
796
|
+
int8_t *slab_axes;
|
|
797
|
+
int8_t naxes;
|
|
798
|
+
int keep_axis;
|
|
799
|
+
ca_size_t min_count;
|
|
800
|
+
} variancep_ki_native_object_frame;
|
|
801
|
+
|
|
802
|
+
static VALUE
|
|
803
|
+
variancep_ki_native_object_body (VALUE arg)
|
|
804
|
+
{
|
|
805
|
+
variancep_ki_native_object_frame *fr = (variancep_ki_native_object_frame *) arg;
|
|
806
|
+
VALUE self = fr->self;
|
|
807
|
+
(void) self;
|
|
808
|
+
CArray *ca = fr->ca;
|
|
809
|
+
(void) ca;
|
|
810
|
+
int8_t *slab_axes = fr->slab_axes;
|
|
811
|
+
(void) slab_axes;
|
|
812
|
+
int8_t naxes = fr->naxes;
|
|
813
|
+
(void) naxes;
|
|
814
|
+
int keep_axis = fr->keep_axis;
|
|
815
|
+
(void) keep_axis;
|
|
816
|
+
ca_size_t min_count = fr->min_count;
|
|
817
|
+
(void) min_count;
|
|
818
|
+
#define st (fr->states[0])
|
|
819
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_OBJECT, keep_axis);
|
|
820
|
+
CArray *co;
|
|
821
|
+
GetCArray(vout, co);
|
|
822
|
+
VALUE *op = (VALUE *) co->ptr;
|
|
823
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
824
|
+
slab_axes, naxes, 0);
|
|
825
|
+
if ( rc != CA_ITER_OK ) {
|
|
826
|
+
rb_raise(rb_eRuntimeError,
|
|
827
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
828
|
+
}
|
|
829
|
+
char *p;
|
|
830
|
+
boolean8_t *m;
|
|
831
|
+
ca_size_t out_i = 0;
|
|
832
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
833
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
834
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
835
|
+
VALUE sum = INT2FIX(0);
|
|
836
|
+
ca_size_t masked_cnt = 0;
|
|
837
|
+
CA_SLAB_REDUCE_T_EX(VALUE, st, p, m, sum, INT2FIX(0), sum = rb_funcall(sum, rb_intern("+"), 1, v), masked_cnt);
|
|
838
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
839
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
840
|
+
if ( __trigger ) {
|
|
841
|
+
if ( ! op_mask ) {
|
|
842
|
+
ca_create_mask(co);
|
|
843
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
844
|
+
}
|
|
845
|
+
op_mask[out_i] = 1;
|
|
846
|
+
op[out_i++] = (VALUE) INT2FIX(0);
|
|
847
|
+
} else {
|
|
848
|
+
VALUE mean = rb_funcall(sum, rb_intern("/"), 1, LONG2NUM(n_valid));
|
|
849
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
850
|
+
VALUE M2 = INT2FIX(0);
|
|
851
|
+
ca_size_t __unused_mc = 0;
|
|
852
|
+
CA_SLAB_REDUCE_T_EX(VALUE, st, p, m, M2, INT2FIX(0), VALUE __d = rb_funcall(v, rb_intern("-"), 1, mean);
|
|
853
|
+
M2 = rb_funcall(M2, rb_intern("+"), 1, rb_funcall(__d, rb_intern("*"), 1, __d)), __unused_mc);
|
|
854
|
+
op[out_i++] = (VALUE)(rb_funcall(M2, rb_intern("/"), 1, LONG2NUM(n_valid)));
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
ca_iter_state_finish(&st);
|
|
858
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
859
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
860
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
861
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
862
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
863
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
864
|
+
return (VALUE)(op[0]);
|
|
865
|
+
}
|
|
866
|
+
return vout;
|
|
867
|
+
#undef st
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
static VALUE
|
|
871
|
+
variancep_ki_native_object (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
872
|
+
{
|
|
873
|
+
variancep_ki_native_object_frame fr;
|
|
874
|
+
fr.self = self;
|
|
875
|
+
fr.ca = ca;
|
|
876
|
+
fr.slab_axes = slab_axes;
|
|
877
|
+
fr.naxes = naxes;
|
|
878
|
+
fr.keep_axis = keep_axis;
|
|
879
|
+
fr.min_count = min_count;
|
|
880
|
+
return ca_iter_ensure(1, fr.states, variancep_ki_native_object_body, (VALUE) &fr);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
VALUE
|
|
885
|
+
rb_ca_variancep_ki (int argc, VALUE *argv, VALUE self)
|
|
886
|
+
{
|
|
887
|
+
CArray *src;
|
|
888
|
+
GetCArray(self, src);
|
|
889
|
+
volatile VALUE ropt = rb_pop_options(&argc, &argv);
|
|
890
|
+
volatile VALUE raxis = Qnil, rkeep_axis = Qnil, rmin_count = Qnil, rfval = Qnil;
|
|
891
|
+
rb_scan_options(ropt, "axis,keep_axis,min_count,fill_value", &raxis, &rkeep_axis, &rmin_count, &rfval);
|
|
892
|
+
int keep_axis = RTEST(rkeep_axis);
|
|
893
|
+
int8_t slab_axes[CA_RANK_MAX];
|
|
894
|
+
int8_t naxes = rb_ca_parse_reduce_axes_kw(raxis, src, slab_axes);
|
|
895
|
+
if ( ca_is_lazy_view(src) ) {
|
|
896
|
+
volatile VALUE evaluated = ca_lazy_evaluated(self);
|
|
897
|
+
if ( ! NIL_P(evaluated) ) {
|
|
898
|
+
self = evaluated;
|
|
899
|
+
GetCArray(self, src);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
ca_size_t min_count = ca_min_count_arg(rmin_count, NULL);
|
|
903
|
+
if ( rfval == CA_UNDEF ) rfval = Qnil;
|
|
904
|
+
int fill_whole = 0;
|
|
905
|
+
if ( ! NIL_P(rfval) && naxes == src->ndim && ! keep_axis ) {
|
|
906
|
+
keep_axis = 1;
|
|
907
|
+
fill_whole = 1;
|
|
908
|
+
}
|
|
909
|
+
VALUE result;
|
|
910
|
+
if ( argc > 0 ) {
|
|
911
|
+
rb_raise(rb_eArgError, "%s: positional axis arguments are no longer accepted (got %d); use the axis: keyword, e.g. a.%s(axis: 0) or a.%s(axis: [0, 1])", ca_calling_method_name(), argc, ca_calling_method_name(), ca_calling_method_name());
|
|
912
|
+
}
|
|
913
|
+
switch ( src->data_type ) {
|
|
914
|
+
case CA_INT8: {
|
|
915
|
+
result = variancep_ki_native_i8(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
916
|
+
RB_GC_GUARD(self);
|
|
917
|
+
break;
|
|
918
|
+
}
|
|
919
|
+
case CA_UINT8: {
|
|
920
|
+
result = variancep_ki_native_u8(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
921
|
+
RB_GC_GUARD(self);
|
|
922
|
+
break;
|
|
923
|
+
}
|
|
924
|
+
case CA_INT16: {
|
|
925
|
+
result = variancep_ki_native_i16(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
926
|
+
RB_GC_GUARD(self);
|
|
927
|
+
break;
|
|
928
|
+
}
|
|
929
|
+
case CA_UINT16: {
|
|
930
|
+
result = variancep_ki_native_u16(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
931
|
+
RB_GC_GUARD(self);
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
case CA_INT32: {
|
|
935
|
+
result = variancep_ki_native_i32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
936
|
+
RB_GC_GUARD(self);
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
case CA_UINT32: {
|
|
940
|
+
result = variancep_ki_native_u32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
941
|
+
RB_GC_GUARD(self);
|
|
942
|
+
break;
|
|
943
|
+
}
|
|
944
|
+
case CA_INT64: {
|
|
945
|
+
result = variancep_ki_native_i64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
946
|
+
RB_GC_GUARD(self);
|
|
947
|
+
break;
|
|
948
|
+
}
|
|
949
|
+
case CA_UINT64: {
|
|
950
|
+
result = variancep_ki_native_u64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
951
|
+
RB_GC_GUARD(self);
|
|
952
|
+
break;
|
|
953
|
+
}
|
|
954
|
+
case CA_FLOAT32: {
|
|
955
|
+
result = variancep_ki_native_f32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
956
|
+
RB_GC_GUARD(self);
|
|
957
|
+
break;
|
|
958
|
+
}
|
|
959
|
+
case CA_FLOAT64: {
|
|
960
|
+
result = variancep_ki_native_f64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
961
|
+
RB_GC_GUARD(self);
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
case CA_CMPLX64: {
|
|
965
|
+
result = variancep_ki_native_cmplx64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
966
|
+
RB_GC_GUARD(self);
|
|
967
|
+
break;
|
|
968
|
+
}
|
|
969
|
+
case CA_CMPLX128: {
|
|
970
|
+
result = variancep_ki_native_cmplx128(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
971
|
+
RB_GC_GUARD(self);
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
974
|
+
case CA_BOOLEAN: {
|
|
975
|
+
result = variancep_ki_native_bool(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
976
|
+
RB_GC_GUARD(self);
|
|
977
|
+
break;
|
|
978
|
+
}
|
|
979
|
+
case CA_OBJECT: {
|
|
980
|
+
result = variancep_ki_native_object(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
981
|
+
RB_GC_GUARD(self);
|
|
982
|
+
break;
|
|
983
|
+
}
|
|
984
|
+
default:
|
|
985
|
+
ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
|
|
986
|
+
rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, cmplx64, cmplx128, boolean, object)", ca_calling_method_name(), ca_type_name[src->data_type]);
|
|
987
|
+
}
|
|
988
|
+
if ( ! NIL_P(rfval) ) {
|
|
989
|
+
result = ca_reduce_fill(result, rfval, fill_whole);
|
|
990
|
+
}
|
|
991
|
+
return result;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
/* ===== variance_ki ============================================ */
|
|
995
|
+
|
|
996
|
+
#define __variance_i8_P1EXPR(__x) ((double)(__x))
|
|
997
|
+
#define __variance_i8_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
998
|
+
static VALUE
|
|
999
|
+
variance_ki_native_i8 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1000
|
+
{
|
|
1001
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1002
|
+
CArray *co;
|
|
1003
|
+
GetCArray(vout, co);
|
|
1004
|
+
double *op = (double *) co->ptr;
|
|
1005
|
+
ca_iter_state st;
|
|
1006
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1007
|
+
slab_axes, naxes, 0);
|
|
1008
|
+
if ( rc != CA_ITER_OK ) {
|
|
1009
|
+
rb_raise(rb_eRuntimeError,
|
|
1010
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1011
|
+
}
|
|
1012
|
+
char *p;
|
|
1013
|
+
boolean8_t *m;
|
|
1014
|
+
ca_size_t out_i = 0;
|
|
1015
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1016
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1017
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1018
|
+
double sum = 0.0;
|
|
1019
|
+
ca_size_t masked_cnt = 0;
|
|
1020
|
+
CA_SLAB_REDUCE_SUM8_EX(int8_t, double, st, p, m, sum, 0.0, __variance_i8_P1EXPR, masked_cnt);
|
|
1021
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1022
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1023
|
+
if ( __trigger ) {
|
|
1024
|
+
if ( ! op_mask ) {
|
|
1025
|
+
ca_create_mask(co);
|
|
1026
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1027
|
+
}
|
|
1028
|
+
op_mask[out_i] = 1;
|
|
1029
|
+
op[out_i++] = (double) 0.0;
|
|
1030
|
+
} else {
|
|
1031
|
+
double mean = sum / (double) n_valid;
|
|
1032
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1033
|
+
double M2 = 0.0;
|
|
1034
|
+
ca_size_t __unused_mc = 0;
|
|
1035
|
+
CA_SLAB_REDUCE_SUM8_EX(int8_t, double, st, p, m, M2, 0.0, __variance_i8_P2EXPR, __unused_mc);
|
|
1036
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
ca_iter_state_finish(&st);
|
|
1040
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1041
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1042
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1043
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1044
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1045
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1046
|
+
return rb_float_new(op[0]);
|
|
1047
|
+
}
|
|
1048
|
+
return vout;
|
|
1049
|
+
}
|
|
1050
|
+
#undef __variance_i8_P1EXPR
|
|
1051
|
+
#undef __variance_i8_P2EXPR
|
|
1052
|
+
|
|
1053
|
+
#define __variance_u8_P1EXPR(__x) ((double)(__x))
|
|
1054
|
+
#define __variance_u8_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1055
|
+
static VALUE
|
|
1056
|
+
variance_ki_native_u8 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1057
|
+
{
|
|
1058
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1059
|
+
CArray *co;
|
|
1060
|
+
GetCArray(vout, co);
|
|
1061
|
+
double *op = (double *) co->ptr;
|
|
1062
|
+
ca_iter_state st;
|
|
1063
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1064
|
+
slab_axes, naxes, 0);
|
|
1065
|
+
if ( rc != CA_ITER_OK ) {
|
|
1066
|
+
rb_raise(rb_eRuntimeError,
|
|
1067
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1068
|
+
}
|
|
1069
|
+
char *p;
|
|
1070
|
+
boolean8_t *m;
|
|
1071
|
+
ca_size_t out_i = 0;
|
|
1072
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1073
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1074
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1075
|
+
double sum = 0.0;
|
|
1076
|
+
ca_size_t masked_cnt = 0;
|
|
1077
|
+
CA_SLAB_REDUCE_SUM8_EX(uint8_t, double, st, p, m, sum, 0.0, __variance_u8_P1EXPR, masked_cnt);
|
|
1078
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1079
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1080
|
+
if ( __trigger ) {
|
|
1081
|
+
if ( ! op_mask ) {
|
|
1082
|
+
ca_create_mask(co);
|
|
1083
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1084
|
+
}
|
|
1085
|
+
op_mask[out_i] = 1;
|
|
1086
|
+
op[out_i++] = (double) 0.0;
|
|
1087
|
+
} else {
|
|
1088
|
+
double mean = sum / (double) n_valid;
|
|
1089
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1090
|
+
double M2 = 0.0;
|
|
1091
|
+
ca_size_t __unused_mc = 0;
|
|
1092
|
+
CA_SLAB_REDUCE_SUM8_EX(uint8_t, double, st, p, m, M2, 0.0, __variance_u8_P2EXPR, __unused_mc);
|
|
1093
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
ca_iter_state_finish(&st);
|
|
1097
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1098
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1099
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1100
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1101
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1102
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1103
|
+
return rb_float_new(op[0]);
|
|
1104
|
+
}
|
|
1105
|
+
return vout;
|
|
1106
|
+
}
|
|
1107
|
+
#undef __variance_u8_P1EXPR
|
|
1108
|
+
#undef __variance_u8_P2EXPR
|
|
1109
|
+
|
|
1110
|
+
#define __variance_i16_P1EXPR(__x) ((double)(__x))
|
|
1111
|
+
#define __variance_i16_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1112
|
+
static VALUE
|
|
1113
|
+
variance_ki_native_i16 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1114
|
+
{
|
|
1115
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1116
|
+
CArray *co;
|
|
1117
|
+
GetCArray(vout, co);
|
|
1118
|
+
double *op = (double *) co->ptr;
|
|
1119
|
+
ca_iter_state st;
|
|
1120
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1121
|
+
slab_axes, naxes, 0);
|
|
1122
|
+
if ( rc != CA_ITER_OK ) {
|
|
1123
|
+
rb_raise(rb_eRuntimeError,
|
|
1124
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1125
|
+
}
|
|
1126
|
+
char *p;
|
|
1127
|
+
boolean8_t *m;
|
|
1128
|
+
ca_size_t out_i = 0;
|
|
1129
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1130
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1131
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1132
|
+
double sum = 0.0;
|
|
1133
|
+
ca_size_t masked_cnt = 0;
|
|
1134
|
+
CA_SLAB_REDUCE_SUM8_EX(int16_t, double, st, p, m, sum, 0.0, __variance_i16_P1EXPR, masked_cnt);
|
|
1135
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1136
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1137
|
+
if ( __trigger ) {
|
|
1138
|
+
if ( ! op_mask ) {
|
|
1139
|
+
ca_create_mask(co);
|
|
1140
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1141
|
+
}
|
|
1142
|
+
op_mask[out_i] = 1;
|
|
1143
|
+
op[out_i++] = (double) 0.0;
|
|
1144
|
+
} else {
|
|
1145
|
+
double mean = sum / (double) n_valid;
|
|
1146
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1147
|
+
double M2 = 0.0;
|
|
1148
|
+
ca_size_t __unused_mc = 0;
|
|
1149
|
+
CA_SLAB_REDUCE_SUM8_EX(int16_t, double, st, p, m, M2, 0.0, __variance_i16_P2EXPR, __unused_mc);
|
|
1150
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
ca_iter_state_finish(&st);
|
|
1154
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1155
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1156
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1157
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1158
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1159
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1160
|
+
return rb_float_new(op[0]);
|
|
1161
|
+
}
|
|
1162
|
+
return vout;
|
|
1163
|
+
}
|
|
1164
|
+
#undef __variance_i16_P1EXPR
|
|
1165
|
+
#undef __variance_i16_P2EXPR
|
|
1166
|
+
|
|
1167
|
+
#define __variance_u16_P1EXPR(__x) ((double)(__x))
|
|
1168
|
+
#define __variance_u16_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1169
|
+
static VALUE
|
|
1170
|
+
variance_ki_native_u16 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1171
|
+
{
|
|
1172
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1173
|
+
CArray *co;
|
|
1174
|
+
GetCArray(vout, co);
|
|
1175
|
+
double *op = (double *) co->ptr;
|
|
1176
|
+
ca_iter_state st;
|
|
1177
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1178
|
+
slab_axes, naxes, 0);
|
|
1179
|
+
if ( rc != CA_ITER_OK ) {
|
|
1180
|
+
rb_raise(rb_eRuntimeError,
|
|
1181
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1182
|
+
}
|
|
1183
|
+
char *p;
|
|
1184
|
+
boolean8_t *m;
|
|
1185
|
+
ca_size_t out_i = 0;
|
|
1186
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1187
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1188
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1189
|
+
double sum = 0.0;
|
|
1190
|
+
ca_size_t masked_cnt = 0;
|
|
1191
|
+
CA_SLAB_REDUCE_SUM8_EX(uint16_t, double, st, p, m, sum, 0.0, __variance_u16_P1EXPR, masked_cnt);
|
|
1192
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1193
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1194
|
+
if ( __trigger ) {
|
|
1195
|
+
if ( ! op_mask ) {
|
|
1196
|
+
ca_create_mask(co);
|
|
1197
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1198
|
+
}
|
|
1199
|
+
op_mask[out_i] = 1;
|
|
1200
|
+
op[out_i++] = (double) 0.0;
|
|
1201
|
+
} else {
|
|
1202
|
+
double mean = sum / (double) n_valid;
|
|
1203
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1204
|
+
double M2 = 0.0;
|
|
1205
|
+
ca_size_t __unused_mc = 0;
|
|
1206
|
+
CA_SLAB_REDUCE_SUM8_EX(uint16_t, double, st, p, m, M2, 0.0, __variance_u16_P2EXPR, __unused_mc);
|
|
1207
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
ca_iter_state_finish(&st);
|
|
1211
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1212
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1213
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1214
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1215
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1216
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1217
|
+
return rb_float_new(op[0]);
|
|
1218
|
+
}
|
|
1219
|
+
return vout;
|
|
1220
|
+
}
|
|
1221
|
+
#undef __variance_u16_P1EXPR
|
|
1222
|
+
#undef __variance_u16_P2EXPR
|
|
1223
|
+
|
|
1224
|
+
#define __variance_i32_P1EXPR(__x) ((double)(__x))
|
|
1225
|
+
#define __variance_i32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1226
|
+
static VALUE
|
|
1227
|
+
variance_ki_native_i32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1228
|
+
{
|
|
1229
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1230
|
+
CArray *co;
|
|
1231
|
+
GetCArray(vout, co);
|
|
1232
|
+
double *op = (double *) co->ptr;
|
|
1233
|
+
ca_iter_state st;
|
|
1234
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1235
|
+
slab_axes, naxes, 0);
|
|
1236
|
+
if ( rc != CA_ITER_OK ) {
|
|
1237
|
+
rb_raise(rb_eRuntimeError,
|
|
1238
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1239
|
+
}
|
|
1240
|
+
char *p;
|
|
1241
|
+
boolean8_t *m;
|
|
1242
|
+
ca_size_t out_i = 0;
|
|
1243
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1244
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1245
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1246
|
+
double sum = 0.0;
|
|
1247
|
+
ca_size_t masked_cnt = 0;
|
|
1248
|
+
CA_SLAB_REDUCE_SUM8_EX(int32_t, double, st, p, m, sum, 0.0, __variance_i32_P1EXPR, masked_cnt);
|
|
1249
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1250
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1251
|
+
if ( __trigger ) {
|
|
1252
|
+
if ( ! op_mask ) {
|
|
1253
|
+
ca_create_mask(co);
|
|
1254
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1255
|
+
}
|
|
1256
|
+
op_mask[out_i] = 1;
|
|
1257
|
+
op[out_i++] = (double) 0.0;
|
|
1258
|
+
} else {
|
|
1259
|
+
double mean = sum / (double) n_valid;
|
|
1260
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1261
|
+
double M2 = 0.0;
|
|
1262
|
+
ca_size_t __unused_mc = 0;
|
|
1263
|
+
CA_SLAB_REDUCE_SUM8_EX(int32_t, double, st, p, m, M2, 0.0, __variance_i32_P2EXPR, __unused_mc);
|
|
1264
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
ca_iter_state_finish(&st);
|
|
1268
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1269
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1270
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1271
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1272
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1273
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1274
|
+
return rb_float_new(op[0]);
|
|
1275
|
+
}
|
|
1276
|
+
return vout;
|
|
1277
|
+
}
|
|
1278
|
+
#undef __variance_i32_P1EXPR
|
|
1279
|
+
#undef __variance_i32_P2EXPR
|
|
1280
|
+
|
|
1281
|
+
#define __variance_u32_P1EXPR(__x) ((double)(__x))
|
|
1282
|
+
#define __variance_u32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1283
|
+
static VALUE
|
|
1284
|
+
variance_ki_native_u32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1285
|
+
{
|
|
1286
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1287
|
+
CArray *co;
|
|
1288
|
+
GetCArray(vout, co);
|
|
1289
|
+
double *op = (double *) co->ptr;
|
|
1290
|
+
ca_iter_state st;
|
|
1291
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1292
|
+
slab_axes, naxes, 0);
|
|
1293
|
+
if ( rc != CA_ITER_OK ) {
|
|
1294
|
+
rb_raise(rb_eRuntimeError,
|
|
1295
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1296
|
+
}
|
|
1297
|
+
char *p;
|
|
1298
|
+
boolean8_t *m;
|
|
1299
|
+
ca_size_t out_i = 0;
|
|
1300
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1301
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1302
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1303
|
+
double sum = 0.0;
|
|
1304
|
+
ca_size_t masked_cnt = 0;
|
|
1305
|
+
CA_SLAB_REDUCE_SUM8_EX(uint32_t, double, st, p, m, sum, 0.0, __variance_u32_P1EXPR, masked_cnt);
|
|
1306
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1307
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1308
|
+
if ( __trigger ) {
|
|
1309
|
+
if ( ! op_mask ) {
|
|
1310
|
+
ca_create_mask(co);
|
|
1311
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1312
|
+
}
|
|
1313
|
+
op_mask[out_i] = 1;
|
|
1314
|
+
op[out_i++] = (double) 0.0;
|
|
1315
|
+
} else {
|
|
1316
|
+
double mean = sum / (double) n_valid;
|
|
1317
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1318
|
+
double M2 = 0.0;
|
|
1319
|
+
ca_size_t __unused_mc = 0;
|
|
1320
|
+
CA_SLAB_REDUCE_SUM8_EX(uint32_t, double, st, p, m, M2, 0.0, __variance_u32_P2EXPR, __unused_mc);
|
|
1321
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
ca_iter_state_finish(&st);
|
|
1325
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1326
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1327
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1328
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1329
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1330
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1331
|
+
return rb_float_new(op[0]);
|
|
1332
|
+
}
|
|
1333
|
+
return vout;
|
|
1334
|
+
}
|
|
1335
|
+
#undef __variance_u32_P1EXPR
|
|
1336
|
+
#undef __variance_u32_P2EXPR
|
|
1337
|
+
|
|
1338
|
+
#define __variance_i64_P1EXPR(__x) ((double)(__x))
|
|
1339
|
+
#define __variance_i64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1340
|
+
static VALUE
|
|
1341
|
+
variance_ki_native_i64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1342
|
+
{
|
|
1343
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1344
|
+
CArray *co;
|
|
1345
|
+
GetCArray(vout, co);
|
|
1346
|
+
double *op = (double *) co->ptr;
|
|
1347
|
+
ca_iter_state st;
|
|
1348
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1349
|
+
slab_axes, naxes, 0);
|
|
1350
|
+
if ( rc != CA_ITER_OK ) {
|
|
1351
|
+
rb_raise(rb_eRuntimeError,
|
|
1352
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1353
|
+
}
|
|
1354
|
+
char *p;
|
|
1355
|
+
boolean8_t *m;
|
|
1356
|
+
ca_size_t out_i = 0;
|
|
1357
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1358
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1359
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1360
|
+
double sum = 0.0;
|
|
1361
|
+
ca_size_t masked_cnt = 0;
|
|
1362
|
+
CA_SLAB_REDUCE_SUM8_EX(int64_t, double, st, p, m, sum, 0.0, __variance_i64_P1EXPR, masked_cnt);
|
|
1363
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1364
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1365
|
+
if ( __trigger ) {
|
|
1366
|
+
if ( ! op_mask ) {
|
|
1367
|
+
ca_create_mask(co);
|
|
1368
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1369
|
+
}
|
|
1370
|
+
op_mask[out_i] = 1;
|
|
1371
|
+
op[out_i++] = (double) 0.0;
|
|
1372
|
+
} else {
|
|
1373
|
+
double mean = sum / (double) n_valid;
|
|
1374
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1375
|
+
double M2 = 0.0;
|
|
1376
|
+
ca_size_t __unused_mc = 0;
|
|
1377
|
+
CA_SLAB_REDUCE_SUM8_EX(int64_t, double, st, p, m, M2, 0.0, __variance_i64_P2EXPR, __unused_mc);
|
|
1378
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
ca_iter_state_finish(&st);
|
|
1382
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1383
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1384
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1385
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1386
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1387
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1388
|
+
return rb_float_new(op[0]);
|
|
1389
|
+
}
|
|
1390
|
+
return vout;
|
|
1391
|
+
}
|
|
1392
|
+
#undef __variance_i64_P1EXPR
|
|
1393
|
+
#undef __variance_i64_P2EXPR
|
|
1394
|
+
|
|
1395
|
+
#define __variance_u64_P1EXPR(__x) ((double)(__x))
|
|
1396
|
+
#define __variance_u64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1397
|
+
static VALUE
|
|
1398
|
+
variance_ki_native_u64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1399
|
+
{
|
|
1400
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1401
|
+
CArray *co;
|
|
1402
|
+
GetCArray(vout, co);
|
|
1403
|
+
double *op = (double *) co->ptr;
|
|
1404
|
+
ca_iter_state st;
|
|
1405
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1406
|
+
slab_axes, naxes, 0);
|
|
1407
|
+
if ( rc != CA_ITER_OK ) {
|
|
1408
|
+
rb_raise(rb_eRuntimeError,
|
|
1409
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1410
|
+
}
|
|
1411
|
+
char *p;
|
|
1412
|
+
boolean8_t *m;
|
|
1413
|
+
ca_size_t out_i = 0;
|
|
1414
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1415
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1416
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1417
|
+
double sum = 0.0;
|
|
1418
|
+
ca_size_t masked_cnt = 0;
|
|
1419
|
+
CA_SLAB_REDUCE_SUM8_EX(uint64_t, double, st, p, m, sum, 0.0, __variance_u64_P1EXPR, masked_cnt);
|
|
1420
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1421
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1422
|
+
if ( __trigger ) {
|
|
1423
|
+
if ( ! op_mask ) {
|
|
1424
|
+
ca_create_mask(co);
|
|
1425
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1426
|
+
}
|
|
1427
|
+
op_mask[out_i] = 1;
|
|
1428
|
+
op[out_i++] = (double) 0.0;
|
|
1429
|
+
} else {
|
|
1430
|
+
double mean = sum / (double) n_valid;
|
|
1431
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1432
|
+
double M2 = 0.0;
|
|
1433
|
+
ca_size_t __unused_mc = 0;
|
|
1434
|
+
CA_SLAB_REDUCE_SUM8_EX(uint64_t, double, st, p, m, M2, 0.0, __variance_u64_P2EXPR, __unused_mc);
|
|
1435
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
ca_iter_state_finish(&st);
|
|
1439
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1440
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1441
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1442
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1443
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1444
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1445
|
+
return rb_float_new(op[0]);
|
|
1446
|
+
}
|
|
1447
|
+
return vout;
|
|
1448
|
+
}
|
|
1449
|
+
#undef __variance_u64_P1EXPR
|
|
1450
|
+
#undef __variance_u64_P2EXPR
|
|
1451
|
+
|
|
1452
|
+
#define __variance_f32_P1EXPR(__x) ((double)(__x))
|
|
1453
|
+
#define __variance_f32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1454
|
+
static VALUE
|
|
1455
|
+
variance_ki_native_f32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1456
|
+
{
|
|
1457
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1458
|
+
CArray *co;
|
|
1459
|
+
GetCArray(vout, co);
|
|
1460
|
+
double *op = (double *) co->ptr;
|
|
1461
|
+
ca_iter_state st;
|
|
1462
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1463
|
+
slab_axes, naxes, 0);
|
|
1464
|
+
if ( rc != CA_ITER_OK ) {
|
|
1465
|
+
rb_raise(rb_eRuntimeError,
|
|
1466
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1467
|
+
}
|
|
1468
|
+
char *p;
|
|
1469
|
+
boolean8_t *m;
|
|
1470
|
+
ca_size_t out_i = 0;
|
|
1471
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1472
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1473
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1474
|
+
double sum = 0.0;
|
|
1475
|
+
ca_size_t masked_cnt = 0;
|
|
1476
|
+
CA_SLAB_REDUCE_SUM8_EX(float, double, st, p, m, sum, 0.0, __variance_f32_P1EXPR, masked_cnt);
|
|
1477
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1478
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1479
|
+
if ( __trigger ) {
|
|
1480
|
+
if ( ! op_mask ) {
|
|
1481
|
+
ca_create_mask(co);
|
|
1482
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1483
|
+
}
|
|
1484
|
+
op_mask[out_i] = 1;
|
|
1485
|
+
op[out_i++] = (double) 0.0;
|
|
1486
|
+
} else {
|
|
1487
|
+
double mean = sum / (double) n_valid;
|
|
1488
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1489
|
+
double M2 = 0.0;
|
|
1490
|
+
ca_size_t __unused_mc = 0;
|
|
1491
|
+
CA_SLAB_REDUCE_SUM8_EX(float, double, st, p, m, M2, 0.0, __variance_f32_P2EXPR, __unused_mc);
|
|
1492
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
ca_iter_state_finish(&st);
|
|
1496
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1497
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1498
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1499
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1500
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1501
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1502
|
+
return rb_float_new(op[0]);
|
|
1503
|
+
}
|
|
1504
|
+
return vout;
|
|
1505
|
+
}
|
|
1506
|
+
#undef __variance_f32_P1EXPR
|
|
1507
|
+
#undef __variance_f32_P2EXPR
|
|
1508
|
+
|
|
1509
|
+
#define __variance_f64_P1EXPR(__x) ((double)(__x))
|
|
1510
|
+
#define __variance_f64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1511
|
+
static VALUE
|
|
1512
|
+
variance_ki_native_f64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1513
|
+
{
|
|
1514
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1515
|
+
CArray *co;
|
|
1516
|
+
GetCArray(vout, co);
|
|
1517
|
+
double *op = (double *) co->ptr;
|
|
1518
|
+
ca_iter_state st;
|
|
1519
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1520
|
+
slab_axes, naxes, 0);
|
|
1521
|
+
if ( rc != CA_ITER_OK ) {
|
|
1522
|
+
rb_raise(rb_eRuntimeError,
|
|
1523
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1524
|
+
}
|
|
1525
|
+
char *p;
|
|
1526
|
+
boolean8_t *m;
|
|
1527
|
+
ca_size_t out_i = 0;
|
|
1528
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1529
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1530
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1531
|
+
double sum = 0.0;
|
|
1532
|
+
ca_size_t masked_cnt = 0;
|
|
1533
|
+
CA_SLAB_REDUCE_SUM8_EX(double, double, st, p, m, sum, 0.0, __variance_f64_P1EXPR, masked_cnt);
|
|
1534
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1535
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1536
|
+
if ( __trigger ) {
|
|
1537
|
+
if ( ! op_mask ) {
|
|
1538
|
+
ca_create_mask(co);
|
|
1539
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1540
|
+
}
|
|
1541
|
+
op_mask[out_i] = 1;
|
|
1542
|
+
op[out_i++] = (double) 0.0;
|
|
1543
|
+
} else {
|
|
1544
|
+
double mean = sum / (double) n_valid;
|
|
1545
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1546
|
+
double M2 = 0.0;
|
|
1547
|
+
ca_size_t __unused_mc = 0;
|
|
1548
|
+
CA_SLAB_REDUCE_SUM8_EX(double, double, st, p, m, M2, 0.0, __variance_f64_P2EXPR, __unused_mc);
|
|
1549
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
ca_iter_state_finish(&st);
|
|
1553
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1554
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1555
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1556
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1557
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1558
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1559
|
+
return rb_float_new(op[0]);
|
|
1560
|
+
}
|
|
1561
|
+
return vout;
|
|
1562
|
+
}
|
|
1563
|
+
#undef __variance_f64_P1EXPR
|
|
1564
|
+
#undef __variance_f64_P2EXPR
|
|
1565
|
+
|
|
1566
|
+
#define __variance_cmplx64_P1EXPR(__x) (__x)
|
|
1567
|
+
#define __variance_cmplx64_P2EXPR(__x) (creal((__x) - mean) * creal((__x) - mean) + cimag((__x) - mean) * cimag((__x) - mean))
|
|
1568
|
+
static VALUE
|
|
1569
|
+
variance_ki_native_cmplx64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1570
|
+
{
|
|
1571
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1572
|
+
CArray *co;
|
|
1573
|
+
GetCArray(vout, co);
|
|
1574
|
+
double *op = (double *) co->ptr;
|
|
1575
|
+
ca_iter_state st;
|
|
1576
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1577
|
+
slab_axes, naxes, 0);
|
|
1578
|
+
if ( rc != CA_ITER_OK ) {
|
|
1579
|
+
rb_raise(rb_eRuntimeError,
|
|
1580
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1581
|
+
}
|
|
1582
|
+
char *p;
|
|
1583
|
+
boolean8_t *m;
|
|
1584
|
+
ca_size_t out_i = 0;
|
|
1585
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1586
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1587
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1588
|
+
cmplx64_t sum = 0;
|
|
1589
|
+
ca_size_t masked_cnt = 0;
|
|
1590
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx64_t, cmplx64_t, st, p, m, sum, 0, __variance_cmplx64_P1EXPR, masked_cnt);
|
|
1591
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1592
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1593
|
+
if ( __trigger ) {
|
|
1594
|
+
if ( ! op_mask ) {
|
|
1595
|
+
ca_create_mask(co);
|
|
1596
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1597
|
+
}
|
|
1598
|
+
op_mask[out_i] = 1;
|
|
1599
|
+
op[out_i++] = (double) 0.0;
|
|
1600
|
+
} else {
|
|
1601
|
+
cmplx64_t mean = sum / (cmplx64_t)(double) n_valid;
|
|
1602
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1603
|
+
double M2 = 0.0;
|
|
1604
|
+
ca_size_t __unused_mc = 0;
|
|
1605
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx64_t, double, st, p, m, M2, 0.0, __variance_cmplx64_P2EXPR, __unused_mc);
|
|
1606
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
ca_iter_state_finish(&st);
|
|
1610
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1611
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1612
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1613
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1614
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1615
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1616
|
+
return rb_float_new(op[0]);
|
|
1617
|
+
}
|
|
1618
|
+
return vout;
|
|
1619
|
+
}
|
|
1620
|
+
#undef __variance_cmplx64_P1EXPR
|
|
1621
|
+
#undef __variance_cmplx64_P2EXPR
|
|
1622
|
+
|
|
1623
|
+
#define __variance_cmplx128_P1EXPR(__x) (__x)
|
|
1624
|
+
#define __variance_cmplx128_P2EXPR(__x) (creal((__x) - mean) * creal((__x) - mean) + cimag((__x) - mean) * cimag((__x) - mean))
|
|
1625
|
+
static VALUE
|
|
1626
|
+
variance_ki_native_cmplx128 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1627
|
+
{
|
|
1628
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1629
|
+
CArray *co;
|
|
1630
|
+
GetCArray(vout, co);
|
|
1631
|
+
double *op = (double *) co->ptr;
|
|
1632
|
+
ca_iter_state st;
|
|
1633
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1634
|
+
slab_axes, naxes, 0);
|
|
1635
|
+
if ( rc != CA_ITER_OK ) {
|
|
1636
|
+
rb_raise(rb_eRuntimeError,
|
|
1637
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1638
|
+
}
|
|
1639
|
+
char *p;
|
|
1640
|
+
boolean8_t *m;
|
|
1641
|
+
ca_size_t out_i = 0;
|
|
1642
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1643
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1644
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1645
|
+
cmplx128_t sum = 0;
|
|
1646
|
+
ca_size_t masked_cnt = 0;
|
|
1647
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx128_t, cmplx128_t, st, p, m, sum, 0, __variance_cmplx128_P1EXPR, masked_cnt);
|
|
1648
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1649
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1650
|
+
if ( __trigger ) {
|
|
1651
|
+
if ( ! op_mask ) {
|
|
1652
|
+
ca_create_mask(co);
|
|
1653
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1654
|
+
}
|
|
1655
|
+
op_mask[out_i] = 1;
|
|
1656
|
+
op[out_i++] = (double) 0.0;
|
|
1657
|
+
} else {
|
|
1658
|
+
cmplx128_t mean = sum / (cmplx128_t)(double) n_valid;
|
|
1659
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1660
|
+
double M2 = 0.0;
|
|
1661
|
+
ca_size_t __unused_mc = 0;
|
|
1662
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx128_t, double, st, p, m, M2, 0.0, __variance_cmplx128_P2EXPR, __unused_mc);
|
|
1663
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
ca_iter_state_finish(&st);
|
|
1667
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1668
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1669
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1670
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1671
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1672
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1673
|
+
return rb_float_new(op[0]);
|
|
1674
|
+
}
|
|
1675
|
+
return vout;
|
|
1676
|
+
}
|
|
1677
|
+
#undef __variance_cmplx128_P1EXPR
|
|
1678
|
+
#undef __variance_cmplx128_P2EXPR
|
|
1679
|
+
|
|
1680
|
+
#define __variance_bool_P1EXPR(__x) ((double)(__x))
|
|
1681
|
+
#define __variance_bool_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1682
|
+
static VALUE
|
|
1683
|
+
variance_ki_native_bool (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1684
|
+
{
|
|
1685
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1686
|
+
CArray *co;
|
|
1687
|
+
GetCArray(vout, co);
|
|
1688
|
+
double *op = (double *) co->ptr;
|
|
1689
|
+
ca_iter_state st;
|
|
1690
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1691
|
+
slab_axes, naxes, 0);
|
|
1692
|
+
if ( rc != CA_ITER_OK ) {
|
|
1693
|
+
rb_raise(rb_eRuntimeError,
|
|
1694
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1695
|
+
}
|
|
1696
|
+
char *p;
|
|
1697
|
+
boolean8_t *m;
|
|
1698
|
+
ca_size_t out_i = 0;
|
|
1699
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1700
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1701
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1702
|
+
double sum = 0.0;
|
|
1703
|
+
ca_size_t masked_cnt = 0;
|
|
1704
|
+
CA_SLAB_REDUCE_SUM8_EX(boolean8_t, double, st, p, m, sum, 0.0, __variance_bool_P1EXPR, masked_cnt);
|
|
1705
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1706
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1707
|
+
if ( __trigger ) {
|
|
1708
|
+
if ( ! op_mask ) {
|
|
1709
|
+
ca_create_mask(co);
|
|
1710
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1711
|
+
}
|
|
1712
|
+
op_mask[out_i] = 1;
|
|
1713
|
+
op[out_i++] = (double) 0.0;
|
|
1714
|
+
} else {
|
|
1715
|
+
double mean = sum / (double) n_valid;
|
|
1716
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1717
|
+
double M2 = 0.0;
|
|
1718
|
+
ca_size_t __unused_mc = 0;
|
|
1719
|
+
CA_SLAB_REDUCE_SUM8_EX(boolean8_t, double, st, p, m, M2, 0.0, __variance_bool_P2EXPR, __unused_mc);
|
|
1720
|
+
op[out_i++] = (double)(M2 / (double)(n_valid - 1));
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
ca_iter_state_finish(&st);
|
|
1724
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1725
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1726
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1727
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1728
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1729
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1730
|
+
return rb_float_new(op[0]);
|
|
1731
|
+
}
|
|
1732
|
+
return vout;
|
|
1733
|
+
}
|
|
1734
|
+
#undef __variance_bool_P1EXPR
|
|
1735
|
+
#undef __variance_bool_P2EXPR
|
|
1736
|
+
|
|
1737
|
+
/* The object lane calls Ruby for every cell, so a walk can raise part
|
|
1738
|
+
way. Its states live in the caller's frame, and ca_iter_ensure
|
|
1739
|
+
finishes them however the body leaves. */
|
|
1740
|
+
typedef struct {
|
|
1741
|
+
ca_iter_state states[1];
|
|
1742
|
+
VALUE self;
|
|
1743
|
+
CArray *ca;
|
|
1744
|
+
int8_t *slab_axes;
|
|
1745
|
+
int8_t naxes;
|
|
1746
|
+
int keep_axis;
|
|
1747
|
+
ca_size_t min_count;
|
|
1748
|
+
} variance_ki_native_object_frame;
|
|
1749
|
+
|
|
1750
|
+
static VALUE
|
|
1751
|
+
variance_ki_native_object_body (VALUE arg)
|
|
1752
|
+
{
|
|
1753
|
+
variance_ki_native_object_frame *fr = (variance_ki_native_object_frame *) arg;
|
|
1754
|
+
VALUE self = fr->self;
|
|
1755
|
+
(void) self;
|
|
1756
|
+
CArray *ca = fr->ca;
|
|
1757
|
+
(void) ca;
|
|
1758
|
+
int8_t *slab_axes = fr->slab_axes;
|
|
1759
|
+
(void) slab_axes;
|
|
1760
|
+
int8_t naxes = fr->naxes;
|
|
1761
|
+
(void) naxes;
|
|
1762
|
+
int keep_axis = fr->keep_axis;
|
|
1763
|
+
(void) keep_axis;
|
|
1764
|
+
ca_size_t min_count = fr->min_count;
|
|
1765
|
+
(void) min_count;
|
|
1766
|
+
#define st (fr->states[0])
|
|
1767
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_OBJECT, keep_axis);
|
|
1768
|
+
CArray *co;
|
|
1769
|
+
GetCArray(vout, co);
|
|
1770
|
+
VALUE *op = (VALUE *) co->ptr;
|
|
1771
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1772
|
+
slab_axes, naxes, 0);
|
|
1773
|
+
if ( rc != CA_ITER_OK ) {
|
|
1774
|
+
rb_raise(rb_eRuntimeError,
|
|
1775
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1776
|
+
}
|
|
1777
|
+
char *p;
|
|
1778
|
+
boolean8_t *m;
|
|
1779
|
+
ca_size_t out_i = 0;
|
|
1780
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1781
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1782
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1783
|
+
VALUE sum = INT2FIX(0);
|
|
1784
|
+
ca_size_t masked_cnt = 0;
|
|
1785
|
+
CA_SLAB_REDUCE_T_EX(VALUE, st, p, m, sum, INT2FIX(0), sum = rb_funcall(sum, rb_intern("+"), 1, v), masked_cnt);
|
|
1786
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1787
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
1788
|
+
if ( __trigger ) {
|
|
1789
|
+
if ( ! op_mask ) {
|
|
1790
|
+
ca_create_mask(co);
|
|
1791
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1792
|
+
}
|
|
1793
|
+
op_mask[out_i] = 1;
|
|
1794
|
+
op[out_i++] = (VALUE) INT2FIX(0);
|
|
1795
|
+
} else {
|
|
1796
|
+
VALUE mean = rb_funcall(sum, rb_intern("/"), 1, LONG2NUM(n_valid));
|
|
1797
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1798
|
+
VALUE M2 = INT2FIX(0);
|
|
1799
|
+
ca_size_t __unused_mc = 0;
|
|
1800
|
+
CA_SLAB_REDUCE_T_EX(VALUE, st, p, m, M2, INT2FIX(0), VALUE __d = rb_funcall(v, rb_intern("-"), 1, mean);
|
|
1801
|
+
M2 = rb_funcall(M2, rb_intern("+"), 1, rb_funcall(__d, rb_intern("*"), 1, __d)), __unused_mc);
|
|
1802
|
+
op[out_i++] = (VALUE)(rb_funcall(M2, rb_intern("/"), 1, LONG2NUM(n_valid - 1)));
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
ca_iter_state_finish(&st);
|
|
1806
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1807
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1808
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1809
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1810
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1811
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1812
|
+
return (VALUE)(op[0]);
|
|
1813
|
+
}
|
|
1814
|
+
return vout;
|
|
1815
|
+
#undef st
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
static VALUE
|
|
1819
|
+
variance_ki_native_object (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1820
|
+
{
|
|
1821
|
+
variance_ki_native_object_frame fr;
|
|
1822
|
+
fr.self = self;
|
|
1823
|
+
fr.ca = ca;
|
|
1824
|
+
fr.slab_axes = slab_axes;
|
|
1825
|
+
fr.naxes = naxes;
|
|
1826
|
+
fr.keep_axis = keep_axis;
|
|
1827
|
+
fr.min_count = min_count;
|
|
1828
|
+
return ca_iter_ensure(1, fr.states, variance_ki_native_object_body, (VALUE) &fr);
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
VALUE
|
|
1833
|
+
rb_ca_variance_ki (int argc, VALUE *argv, VALUE self)
|
|
1834
|
+
{
|
|
1835
|
+
CArray *src;
|
|
1836
|
+
GetCArray(self, src);
|
|
1837
|
+
volatile VALUE ropt = rb_pop_options(&argc, &argv);
|
|
1838
|
+
volatile VALUE raxis = Qnil, rkeep_axis = Qnil, rmin_count = Qnil, rfval = Qnil;
|
|
1839
|
+
rb_scan_options(ropt, "axis,keep_axis,min_count,fill_value", &raxis, &rkeep_axis, &rmin_count, &rfval);
|
|
1840
|
+
int keep_axis = RTEST(rkeep_axis);
|
|
1841
|
+
int8_t slab_axes[CA_RANK_MAX];
|
|
1842
|
+
int8_t naxes = rb_ca_parse_reduce_axes_kw(raxis, src, slab_axes);
|
|
1843
|
+
if ( ca_is_lazy_view(src) ) {
|
|
1844
|
+
volatile VALUE evaluated = ca_lazy_evaluated(self);
|
|
1845
|
+
if ( ! NIL_P(evaluated) ) {
|
|
1846
|
+
self = evaluated;
|
|
1847
|
+
GetCArray(self, src);
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
ca_size_t min_count = ca_min_count_arg(rmin_count, NULL);
|
|
1851
|
+
if ( rfval == CA_UNDEF ) rfval = Qnil;
|
|
1852
|
+
int fill_whole = 0;
|
|
1853
|
+
if ( ! NIL_P(rfval) && naxes == src->ndim && ! keep_axis ) {
|
|
1854
|
+
keep_axis = 1;
|
|
1855
|
+
fill_whole = 1;
|
|
1856
|
+
}
|
|
1857
|
+
VALUE result;
|
|
1858
|
+
if ( argc > 0 ) {
|
|
1859
|
+
rb_raise(rb_eArgError, "%s: positional axis arguments are no longer accepted (got %d); use the axis: keyword, e.g. a.%s(axis: 0) or a.%s(axis: [0, 1])", ca_calling_method_name(), argc, ca_calling_method_name(), ca_calling_method_name());
|
|
1860
|
+
}
|
|
1861
|
+
switch ( src->data_type ) {
|
|
1862
|
+
case CA_INT8: {
|
|
1863
|
+
result = variance_ki_native_i8(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1864
|
+
RB_GC_GUARD(self);
|
|
1865
|
+
break;
|
|
1866
|
+
}
|
|
1867
|
+
case CA_UINT8: {
|
|
1868
|
+
result = variance_ki_native_u8(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1869
|
+
RB_GC_GUARD(self);
|
|
1870
|
+
break;
|
|
1871
|
+
}
|
|
1872
|
+
case CA_INT16: {
|
|
1873
|
+
result = variance_ki_native_i16(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1874
|
+
RB_GC_GUARD(self);
|
|
1875
|
+
break;
|
|
1876
|
+
}
|
|
1877
|
+
case CA_UINT16: {
|
|
1878
|
+
result = variance_ki_native_u16(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1879
|
+
RB_GC_GUARD(self);
|
|
1880
|
+
break;
|
|
1881
|
+
}
|
|
1882
|
+
case CA_INT32: {
|
|
1883
|
+
result = variance_ki_native_i32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1884
|
+
RB_GC_GUARD(self);
|
|
1885
|
+
break;
|
|
1886
|
+
}
|
|
1887
|
+
case CA_UINT32: {
|
|
1888
|
+
result = variance_ki_native_u32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1889
|
+
RB_GC_GUARD(self);
|
|
1890
|
+
break;
|
|
1891
|
+
}
|
|
1892
|
+
case CA_INT64: {
|
|
1893
|
+
result = variance_ki_native_i64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1894
|
+
RB_GC_GUARD(self);
|
|
1895
|
+
break;
|
|
1896
|
+
}
|
|
1897
|
+
case CA_UINT64: {
|
|
1898
|
+
result = variance_ki_native_u64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1899
|
+
RB_GC_GUARD(self);
|
|
1900
|
+
break;
|
|
1901
|
+
}
|
|
1902
|
+
case CA_FLOAT32: {
|
|
1903
|
+
result = variance_ki_native_f32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1904
|
+
RB_GC_GUARD(self);
|
|
1905
|
+
break;
|
|
1906
|
+
}
|
|
1907
|
+
case CA_FLOAT64: {
|
|
1908
|
+
result = variance_ki_native_f64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1909
|
+
RB_GC_GUARD(self);
|
|
1910
|
+
break;
|
|
1911
|
+
}
|
|
1912
|
+
case CA_CMPLX64: {
|
|
1913
|
+
result = variance_ki_native_cmplx64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1914
|
+
RB_GC_GUARD(self);
|
|
1915
|
+
break;
|
|
1916
|
+
}
|
|
1917
|
+
case CA_CMPLX128: {
|
|
1918
|
+
result = variance_ki_native_cmplx128(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1919
|
+
RB_GC_GUARD(self);
|
|
1920
|
+
break;
|
|
1921
|
+
}
|
|
1922
|
+
case CA_BOOLEAN: {
|
|
1923
|
+
result = variance_ki_native_bool(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1924
|
+
RB_GC_GUARD(self);
|
|
1925
|
+
break;
|
|
1926
|
+
}
|
|
1927
|
+
case CA_OBJECT: {
|
|
1928
|
+
result = variance_ki_native_object(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
1929
|
+
RB_GC_GUARD(self);
|
|
1930
|
+
break;
|
|
1931
|
+
}
|
|
1932
|
+
default:
|
|
1933
|
+
ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
|
|
1934
|
+
rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, cmplx64, cmplx128, boolean, object)", ca_calling_method_name(), ca_type_name[src->data_type]);
|
|
1935
|
+
}
|
|
1936
|
+
if ( ! NIL_P(rfval) ) {
|
|
1937
|
+
result = ca_reduce_fill(result, rfval, fill_whole);
|
|
1938
|
+
}
|
|
1939
|
+
return result;
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
/* ===== stddevp_ki ============================================ */
|
|
1943
|
+
|
|
1944
|
+
#define __stddevp_i8_P1EXPR(__x) ((double)(__x))
|
|
1945
|
+
#define __stddevp_i8_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
1946
|
+
static VALUE
|
|
1947
|
+
stddevp_ki_native_i8 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
1948
|
+
{
|
|
1949
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
1950
|
+
CArray *co;
|
|
1951
|
+
GetCArray(vout, co);
|
|
1952
|
+
double *op = (double *) co->ptr;
|
|
1953
|
+
ca_iter_state st;
|
|
1954
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
1955
|
+
slab_axes, naxes, 0);
|
|
1956
|
+
if ( rc != CA_ITER_OK ) {
|
|
1957
|
+
rb_raise(rb_eRuntimeError,
|
|
1958
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
1959
|
+
}
|
|
1960
|
+
char *p;
|
|
1961
|
+
boolean8_t *m;
|
|
1962
|
+
ca_size_t out_i = 0;
|
|
1963
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
1964
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
1965
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
1966
|
+
double sum = 0.0;
|
|
1967
|
+
ca_size_t masked_cnt = 0;
|
|
1968
|
+
CA_SLAB_REDUCE_SUM8_EX(int8_t, double, st, p, m, sum, 0.0, __stddevp_i8_P1EXPR, masked_cnt);
|
|
1969
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
1970
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
1971
|
+
if ( __trigger ) {
|
|
1972
|
+
if ( ! op_mask ) {
|
|
1973
|
+
ca_create_mask(co);
|
|
1974
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
1975
|
+
}
|
|
1976
|
+
op_mask[out_i] = 1;
|
|
1977
|
+
op[out_i++] = (double) 0.0;
|
|
1978
|
+
} else {
|
|
1979
|
+
double mean = sum / (double) n_valid;
|
|
1980
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
1981
|
+
double M2 = 0.0;
|
|
1982
|
+
ca_size_t __unused_mc = 0;
|
|
1983
|
+
CA_SLAB_REDUCE_SUM8_EX(int8_t, double, st, p, m, M2, 0.0, __stddevp_i8_P2EXPR, __unused_mc);
|
|
1984
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
ca_iter_state_finish(&st);
|
|
1988
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
1989
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
1990
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
1991
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
1992
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
1993
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
1994
|
+
return rb_float_new(op[0]);
|
|
1995
|
+
}
|
|
1996
|
+
return vout;
|
|
1997
|
+
}
|
|
1998
|
+
#undef __stddevp_i8_P1EXPR
|
|
1999
|
+
#undef __stddevp_i8_P2EXPR
|
|
2000
|
+
|
|
2001
|
+
#define __stddevp_u8_P1EXPR(__x) ((double)(__x))
|
|
2002
|
+
#define __stddevp_u8_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2003
|
+
static VALUE
|
|
2004
|
+
stddevp_ki_native_u8 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2005
|
+
{
|
|
2006
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2007
|
+
CArray *co;
|
|
2008
|
+
GetCArray(vout, co);
|
|
2009
|
+
double *op = (double *) co->ptr;
|
|
2010
|
+
ca_iter_state st;
|
|
2011
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2012
|
+
slab_axes, naxes, 0);
|
|
2013
|
+
if ( rc != CA_ITER_OK ) {
|
|
2014
|
+
rb_raise(rb_eRuntimeError,
|
|
2015
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2016
|
+
}
|
|
2017
|
+
char *p;
|
|
2018
|
+
boolean8_t *m;
|
|
2019
|
+
ca_size_t out_i = 0;
|
|
2020
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2021
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2022
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2023
|
+
double sum = 0.0;
|
|
2024
|
+
ca_size_t masked_cnt = 0;
|
|
2025
|
+
CA_SLAB_REDUCE_SUM8_EX(uint8_t, double, st, p, m, sum, 0.0, __stddevp_u8_P1EXPR, masked_cnt);
|
|
2026
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2027
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2028
|
+
if ( __trigger ) {
|
|
2029
|
+
if ( ! op_mask ) {
|
|
2030
|
+
ca_create_mask(co);
|
|
2031
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2032
|
+
}
|
|
2033
|
+
op_mask[out_i] = 1;
|
|
2034
|
+
op[out_i++] = (double) 0.0;
|
|
2035
|
+
} else {
|
|
2036
|
+
double mean = sum / (double) n_valid;
|
|
2037
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2038
|
+
double M2 = 0.0;
|
|
2039
|
+
ca_size_t __unused_mc = 0;
|
|
2040
|
+
CA_SLAB_REDUCE_SUM8_EX(uint8_t, double, st, p, m, M2, 0.0, __stddevp_u8_P2EXPR, __unused_mc);
|
|
2041
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
ca_iter_state_finish(&st);
|
|
2045
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2046
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2047
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2048
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2049
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2050
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2051
|
+
return rb_float_new(op[0]);
|
|
2052
|
+
}
|
|
2053
|
+
return vout;
|
|
2054
|
+
}
|
|
2055
|
+
#undef __stddevp_u8_P1EXPR
|
|
2056
|
+
#undef __stddevp_u8_P2EXPR
|
|
2057
|
+
|
|
2058
|
+
#define __stddevp_i16_P1EXPR(__x) ((double)(__x))
|
|
2059
|
+
#define __stddevp_i16_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2060
|
+
static VALUE
|
|
2061
|
+
stddevp_ki_native_i16 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2062
|
+
{
|
|
2063
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2064
|
+
CArray *co;
|
|
2065
|
+
GetCArray(vout, co);
|
|
2066
|
+
double *op = (double *) co->ptr;
|
|
2067
|
+
ca_iter_state st;
|
|
2068
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2069
|
+
slab_axes, naxes, 0);
|
|
2070
|
+
if ( rc != CA_ITER_OK ) {
|
|
2071
|
+
rb_raise(rb_eRuntimeError,
|
|
2072
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2073
|
+
}
|
|
2074
|
+
char *p;
|
|
2075
|
+
boolean8_t *m;
|
|
2076
|
+
ca_size_t out_i = 0;
|
|
2077
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2078
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2079
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2080
|
+
double sum = 0.0;
|
|
2081
|
+
ca_size_t masked_cnt = 0;
|
|
2082
|
+
CA_SLAB_REDUCE_SUM8_EX(int16_t, double, st, p, m, sum, 0.0, __stddevp_i16_P1EXPR, masked_cnt);
|
|
2083
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2084
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2085
|
+
if ( __trigger ) {
|
|
2086
|
+
if ( ! op_mask ) {
|
|
2087
|
+
ca_create_mask(co);
|
|
2088
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2089
|
+
}
|
|
2090
|
+
op_mask[out_i] = 1;
|
|
2091
|
+
op[out_i++] = (double) 0.0;
|
|
2092
|
+
} else {
|
|
2093
|
+
double mean = sum / (double) n_valid;
|
|
2094
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2095
|
+
double M2 = 0.0;
|
|
2096
|
+
ca_size_t __unused_mc = 0;
|
|
2097
|
+
CA_SLAB_REDUCE_SUM8_EX(int16_t, double, st, p, m, M2, 0.0, __stddevp_i16_P2EXPR, __unused_mc);
|
|
2098
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
ca_iter_state_finish(&st);
|
|
2102
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2103
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2104
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2105
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2106
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2107
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2108
|
+
return rb_float_new(op[0]);
|
|
2109
|
+
}
|
|
2110
|
+
return vout;
|
|
2111
|
+
}
|
|
2112
|
+
#undef __stddevp_i16_P1EXPR
|
|
2113
|
+
#undef __stddevp_i16_P2EXPR
|
|
2114
|
+
|
|
2115
|
+
#define __stddevp_u16_P1EXPR(__x) ((double)(__x))
|
|
2116
|
+
#define __stddevp_u16_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2117
|
+
static VALUE
|
|
2118
|
+
stddevp_ki_native_u16 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2119
|
+
{
|
|
2120
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2121
|
+
CArray *co;
|
|
2122
|
+
GetCArray(vout, co);
|
|
2123
|
+
double *op = (double *) co->ptr;
|
|
2124
|
+
ca_iter_state st;
|
|
2125
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2126
|
+
slab_axes, naxes, 0);
|
|
2127
|
+
if ( rc != CA_ITER_OK ) {
|
|
2128
|
+
rb_raise(rb_eRuntimeError,
|
|
2129
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2130
|
+
}
|
|
2131
|
+
char *p;
|
|
2132
|
+
boolean8_t *m;
|
|
2133
|
+
ca_size_t out_i = 0;
|
|
2134
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2135
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2136
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2137
|
+
double sum = 0.0;
|
|
2138
|
+
ca_size_t masked_cnt = 0;
|
|
2139
|
+
CA_SLAB_REDUCE_SUM8_EX(uint16_t, double, st, p, m, sum, 0.0, __stddevp_u16_P1EXPR, masked_cnt);
|
|
2140
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2141
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2142
|
+
if ( __trigger ) {
|
|
2143
|
+
if ( ! op_mask ) {
|
|
2144
|
+
ca_create_mask(co);
|
|
2145
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2146
|
+
}
|
|
2147
|
+
op_mask[out_i] = 1;
|
|
2148
|
+
op[out_i++] = (double) 0.0;
|
|
2149
|
+
} else {
|
|
2150
|
+
double mean = sum / (double) n_valid;
|
|
2151
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2152
|
+
double M2 = 0.0;
|
|
2153
|
+
ca_size_t __unused_mc = 0;
|
|
2154
|
+
CA_SLAB_REDUCE_SUM8_EX(uint16_t, double, st, p, m, M2, 0.0, __stddevp_u16_P2EXPR, __unused_mc);
|
|
2155
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
ca_iter_state_finish(&st);
|
|
2159
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2160
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2161
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2162
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2163
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2164
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2165
|
+
return rb_float_new(op[0]);
|
|
2166
|
+
}
|
|
2167
|
+
return vout;
|
|
2168
|
+
}
|
|
2169
|
+
#undef __stddevp_u16_P1EXPR
|
|
2170
|
+
#undef __stddevp_u16_P2EXPR
|
|
2171
|
+
|
|
2172
|
+
#define __stddevp_i32_P1EXPR(__x) ((double)(__x))
|
|
2173
|
+
#define __stddevp_i32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2174
|
+
static VALUE
|
|
2175
|
+
stddevp_ki_native_i32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2176
|
+
{
|
|
2177
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2178
|
+
CArray *co;
|
|
2179
|
+
GetCArray(vout, co);
|
|
2180
|
+
double *op = (double *) co->ptr;
|
|
2181
|
+
ca_iter_state st;
|
|
2182
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2183
|
+
slab_axes, naxes, 0);
|
|
2184
|
+
if ( rc != CA_ITER_OK ) {
|
|
2185
|
+
rb_raise(rb_eRuntimeError,
|
|
2186
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2187
|
+
}
|
|
2188
|
+
char *p;
|
|
2189
|
+
boolean8_t *m;
|
|
2190
|
+
ca_size_t out_i = 0;
|
|
2191
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2192
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2193
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2194
|
+
double sum = 0.0;
|
|
2195
|
+
ca_size_t masked_cnt = 0;
|
|
2196
|
+
CA_SLAB_REDUCE_SUM8_EX(int32_t, double, st, p, m, sum, 0.0, __stddevp_i32_P1EXPR, masked_cnt);
|
|
2197
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2198
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2199
|
+
if ( __trigger ) {
|
|
2200
|
+
if ( ! op_mask ) {
|
|
2201
|
+
ca_create_mask(co);
|
|
2202
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2203
|
+
}
|
|
2204
|
+
op_mask[out_i] = 1;
|
|
2205
|
+
op[out_i++] = (double) 0.0;
|
|
2206
|
+
} else {
|
|
2207
|
+
double mean = sum / (double) n_valid;
|
|
2208
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2209
|
+
double M2 = 0.0;
|
|
2210
|
+
ca_size_t __unused_mc = 0;
|
|
2211
|
+
CA_SLAB_REDUCE_SUM8_EX(int32_t, double, st, p, m, M2, 0.0, __stddevp_i32_P2EXPR, __unused_mc);
|
|
2212
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
ca_iter_state_finish(&st);
|
|
2216
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2217
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2218
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2219
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2220
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2221
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2222
|
+
return rb_float_new(op[0]);
|
|
2223
|
+
}
|
|
2224
|
+
return vout;
|
|
2225
|
+
}
|
|
2226
|
+
#undef __stddevp_i32_P1EXPR
|
|
2227
|
+
#undef __stddevp_i32_P2EXPR
|
|
2228
|
+
|
|
2229
|
+
#define __stddevp_u32_P1EXPR(__x) ((double)(__x))
|
|
2230
|
+
#define __stddevp_u32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2231
|
+
static VALUE
|
|
2232
|
+
stddevp_ki_native_u32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2233
|
+
{
|
|
2234
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2235
|
+
CArray *co;
|
|
2236
|
+
GetCArray(vout, co);
|
|
2237
|
+
double *op = (double *) co->ptr;
|
|
2238
|
+
ca_iter_state st;
|
|
2239
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2240
|
+
slab_axes, naxes, 0);
|
|
2241
|
+
if ( rc != CA_ITER_OK ) {
|
|
2242
|
+
rb_raise(rb_eRuntimeError,
|
|
2243
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2244
|
+
}
|
|
2245
|
+
char *p;
|
|
2246
|
+
boolean8_t *m;
|
|
2247
|
+
ca_size_t out_i = 0;
|
|
2248
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2249
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2250
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2251
|
+
double sum = 0.0;
|
|
2252
|
+
ca_size_t masked_cnt = 0;
|
|
2253
|
+
CA_SLAB_REDUCE_SUM8_EX(uint32_t, double, st, p, m, sum, 0.0, __stddevp_u32_P1EXPR, masked_cnt);
|
|
2254
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2255
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2256
|
+
if ( __trigger ) {
|
|
2257
|
+
if ( ! op_mask ) {
|
|
2258
|
+
ca_create_mask(co);
|
|
2259
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2260
|
+
}
|
|
2261
|
+
op_mask[out_i] = 1;
|
|
2262
|
+
op[out_i++] = (double) 0.0;
|
|
2263
|
+
} else {
|
|
2264
|
+
double mean = sum / (double) n_valid;
|
|
2265
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2266
|
+
double M2 = 0.0;
|
|
2267
|
+
ca_size_t __unused_mc = 0;
|
|
2268
|
+
CA_SLAB_REDUCE_SUM8_EX(uint32_t, double, st, p, m, M2, 0.0, __stddevp_u32_P2EXPR, __unused_mc);
|
|
2269
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
ca_iter_state_finish(&st);
|
|
2273
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2274
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2275
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2276
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2277
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2278
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2279
|
+
return rb_float_new(op[0]);
|
|
2280
|
+
}
|
|
2281
|
+
return vout;
|
|
2282
|
+
}
|
|
2283
|
+
#undef __stddevp_u32_P1EXPR
|
|
2284
|
+
#undef __stddevp_u32_P2EXPR
|
|
2285
|
+
|
|
2286
|
+
#define __stddevp_i64_P1EXPR(__x) ((double)(__x))
|
|
2287
|
+
#define __stddevp_i64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2288
|
+
static VALUE
|
|
2289
|
+
stddevp_ki_native_i64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2290
|
+
{
|
|
2291
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2292
|
+
CArray *co;
|
|
2293
|
+
GetCArray(vout, co);
|
|
2294
|
+
double *op = (double *) co->ptr;
|
|
2295
|
+
ca_iter_state st;
|
|
2296
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2297
|
+
slab_axes, naxes, 0);
|
|
2298
|
+
if ( rc != CA_ITER_OK ) {
|
|
2299
|
+
rb_raise(rb_eRuntimeError,
|
|
2300
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2301
|
+
}
|
|
2302
|
+
char *p;
|
|
2303
|
+
boolean8_t *m;
|
|
2304
|
+
ca_size_t out_i = 0;
|
|
2305
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2306
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2307
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2308
|
+
double sum = 0.0;
|
|
2309
|
+
ca_size_t masked_cnt = 0;
|
|
2310
|
+
CA_SLAB_REDUCE_SUM8_EX(int64_t, double, st, p, m, sum, 0.0, __stddevp_i64_P1EXPR, masked_cnt);
|
|
2311
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2312
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2313
|
+
if ( __trigger ) {
|
|
2314
|
+
if ( ! op_mask ) {
|
|
2315
|
+
ca_create_mask(co);
|
|
2316
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2317
|
+
}
|
|
2318
|
+
op_mask[out_i] = 1;
|
|
2319
|
+
op[out_i++] = (double) 0.0;
|
|
2320
|
+
} else {
|
|
2321
|
+
double mean = sum / (double) n_valid;
|
|
2322
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2323
|
+
double M2 = 0.0;
|
|
2324
|
+
ca_size_t __unused_mc = 0;
|
|
2325
|
+
CA_SLAB_REDUCE_SUM8_EX(int64_t, double, st, p, m, M2, 0.0, __stddevp_i64_P2EXPR, __unused_mc);
|
|
2326
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
ca_iter_state_finish(&st);
|
|
2330
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2331
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2332
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2333
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2334
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2335
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2336
|
+
return rb_float_new(op[0]);
|
|
2337
|
+
}
|
|
2338
|
+
return vout;
|
|
2339
|
+
}
|
|
2340
|
+
#undef __stddevp_i64_P1EXPR
|
|
2341
|
+
#undef __stddevp_i64_P2EXPR
|
|
2342
|
+
|
|
2343
|
+
#define __stddevp_u64_P1EXPR(__x) ((double)(__x))
|
|
2344
|
+
#define __stddevp_u64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2345
|
+
static VALUE
|
|
2346
|
+
stddevp_ki_native_u64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2347
|
+
{
|
|
2348
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2349
|
+
CArray *co;
|
|
2350
|
+
GetCArray(vout, co);
|
|
2351
|
+
double *op = (double *) co->ptr;
|
|
2352
|
+
ca_iter_state st;
|
|
2353
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2354
|
+
slab_axes, naxes, 0);
|
|
2355
|
+
if ( rc != CA_ITER_OK ) {
|
|
2356
|
+
rb_raise(rb_eRuntimeError,
|
|
2357
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2358
|
+
}
|
|
2359
|
+
char *p;
|
|
2360
|
+
boolean8_t *m;
|
|
2361
|
+
ca_size_t out_i = 0;
|
|
2362
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2363
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2364
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2365
|
+
double sum = 0.0;
|
|
2366
|
+
ca_size_t masked_cnt = 0;
|
|
2367
|
+
CA_SLAB_REDUCE_SUM8_EX(uint64_t, double, st, p, m, sum, 0.0, __stddevp_u64_P1EXPR, masked_cnt);
|
|
2368
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2369
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2370
|
+
if ( __trigger ) {
|
|
2371
|
+
if ( ! op_mask ) {
|
|
2372
|
+
ca_create_mask(co);
|
|
2373
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2374
|
+
}
|
|
2375
|
+
op_mask[out_i] = 1;
|
|
2376
|
+
op[out_i++] = (double) 0.0;
|
|
2377
|
+
} else {
|
|
2378
|
+
double mean = sum / (double) n_valid;
|
|
2379
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2380
|
+
double M2 = 0.0;
|
|
2381
|
+
ca_size_t __unused_mc = 0;
|
|
2382
|
+
CA_SLAB_REDUCE_SUM8_EX(uint64_t, double, st, p, m, M2, 0.0, __stddevp_u64_P2EXPR, __unused_mc);
|
|
2383
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
ca_iter_state_finish(&st);
|
|
2387
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2388
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2389
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2390
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2391
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2392
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2393
|
+
return rb_float_new(op[0]);
|
|
2394
|
+
}
|
|
2395
|
+
return vout;
|
|
2396
|
+
}
|
|
2397
|
+
#undef __stddevp_u64_P1EXPR
|
|
2398
|
+
#undef __stddevp_u64_P2EXPR
|
|
2399
|
+
|
|
2400
|
+
#define __stddevp_f32_P1EXPR(__x) ((double)(__x))
|
|
2401
|
+
#define __stddevp_f32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2402
|
+
static VALUE
|
|
2403
|
+
stddevp_ki_native_f32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2404
|
+
{
|
|
2405
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2406
|
+
CArray *co;
|
|
2407
|
+
GetCArray(vout, co);
|
|
2408
|
+
double *op = (double *) co->ptr;
|
|
2409
|
+
ca_iter_state st;
|
|
2410
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2411
|
+
slab_axes, naxes, 0);
|
|
2412
|
+
if ( rc != CA_ITER_OK ) {
|
|
2413
|
+
rb_raise(rb_eRuntimeError,
|
|
2414
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2415
|
+
}
|
|
2416
|
+
char *p;
|
|
2417
|
+
boolean8_t *m;
|
|
2418
|
+
ca_size_t out_i = 0;
|
|
2419
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2420
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2421
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2422
|
+
double sum = 0.0;
|
|
2423
|
+
ca_size_t masked_cnt = 0;
|
|
2424
|
+
CA_SLAB_REDUCE_SUM8_EX(float, double, st, p, m, sum, 0.0, __stddevp_f32_P1EXPR, masked_cnt);
|
|
2425
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2426
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2427
|
+
if ( __trigger ) {
|
|
2428
|
+
if ( ! op_mask ) {
|
|
2429
|
+
ca_create_mask(co);
|
|
2430
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2431
|
+
}
|
|
2432
|
+
op_mask[out_i] = 1;
|
|
2433
|
+
op[out_i++] = (double) 0.0;
|
|
2434
|
+
} else {
|
|
2435
|
+
double mean = sum / (double) n_valid;
|
|
2436
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2437
|
+
double M2 = 0.0;
|
|
2438
|
+
ca_size_t __unused_mc = 0;
|
|
2439
|
+
CA_SLAB_REDUCE_SUM8_EX(float, double, st, p, m, M2, 0.0, __stddevp_f32_P2EXPR, __unused_mc);
|
|
2440
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
ca_iter_state_finish(&st);
|
|
2444
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2445
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2446
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2447
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2448
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2449
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2450
|
+
return rb_float_new(op[0]);
|
|
2451
|
+
}
|
|
2452
|
+
return vout;
|
|
2453
|
+
}
|
|
2454
|
+
#undef __stddevp_f32_P1EXPR
|
|
2455
|
+
#undef __stddevp_f32_P2EXPR
|
|
2456
|
+
|
|
2457
|
+
#define __stddevp_f64_P1EXPR(__x) ((double)(__x))
|
|
2458
|
+
#define __stddevp_f64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2459
|
+
static VALUE
|
|
2460
|
+
stddevp_ki_native_f64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2461
|
+
{
|
|
2462
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2463
|
+
CArray *co;
|
|
2464
|
+
GetCArray(vout, co);
|
|
2465
|
+
double *op = (double *) co->ptr;
|
|
2466
|
+
ca_iter_state st;
|
|
2467
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2468
|
+
slab_axes, naxes, 0);
|
|
2469
|
+
if ( rc != CA_ITER_OK ) {
|
|
2470
|
+
rb_raise(rb_eRuntimeError,
|
|
2471
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2472
|
+
}
|
|
2473
|
+
char *p;
|
|
2474
|
+
boolean8_t *m;
|
|
2475
|
+
ca_size_t out_i = 0;
|
|
2476
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2477
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2478
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2479
|
+
double sum = 0.0;
|
|
2480
|
+
ca_size_t masked_cnt = 0;
|
|
2481
|
+
CA_SLAB_REDUCE_SUM8_EX(double, double, st, p, m, sum, 0.0, __stddevp_f64_P1EXPR, masked_cnt);
|
|
2482
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2483
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2484
|
+
if ( __trigger ) {
|
|
2485
|
+
if ( ! op_mask ) {
|
|
2486
|
+
ca_create_mask(co);
|
|
2487
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2488
|
+
}
|
|
2489
|
+
op_mask[out_i] = 1;
|
|
2490
|
+
op[out_i++] = (double) 0.0;
|
|
2491
|
+
} else {
|
|
2492
|
+
double mean = sum / (double) n_valid;
|
|
2493
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2494
|
+
double M2 = 0.0;
|
|
2495
|
+
ca_size_t __unused_mc = 0;
|
|
2496
|
+
CA_SLAB_REDUCE_SUM8_EX(double, double, st, p, m, M2, 0.0, __stddevp_f64_P2EXPR, __unused_mc);
|
|
2497
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
ca_iter_state_finish(&st);
|
|
2501
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2502
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2503
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2504
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2505
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2506
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2507
|
+
return rb_float_new(op[0]);
|
|
2508
|
+
}
|
|
2509
|
+
return vout;
|
|
2510
|
+
}
|
|
2511
|
+
#undef __stddevp_f64_P1EXPR
|
|
2512
|
+
#undef __stddevp_f64_P2EXPR
|
|
2513
|
+
|
|
2514
|
+
#define __stddevp_cmplx64_P1EXPR(__x) (__x)
|
|
2515
|
+
#define __stddevp_cmplx64_P2EXPR(__x) (creal((__x) - mean) * creal((__x) - mean) + cimag((__x) - mean) * cimag((__x) - mean))
|
|
2516
|
+
static VALUE
|
|
2517
|
+
stddevp_ki_native_cmplx64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2518
|
+
{
|
|
2519
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2520
|
+
CArray *co;
|
|
2521
|
+
GetCArray(vout, co);
|
|
2522
|
+
double *op = (double *) co->ptr;
|
|
2523
|
+
ca_iter_state st;
|
|
2524
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2525
|
+
slab_axes, naxes, 0);
|
|
2526
|
+
if ( rc != CA_ITER_OK ) {
|
|
2527
|
+
rb_raise(rb_eRuntimeError,
|
|
2528
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2529
|
+
}
|
|
2530
|
+
char *p;
|
|
2531
|
+
boolean8_t *m;
|
|
2532
|
+
ca_size_t out_i = 0;
|
|
2533
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2534
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2535
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2536
|
+
cmplx64_t sum = 0;
|
|
2537
|
+
ca_size_t masked_cnt = 0;
|
|
2538
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx64_t, cmplx64_t, st, p, m, sum, 0, __stddevp_cmplx64_P1EXPR, masked_cnt);
|
|
2539
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2540
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2541
|
+
if ( __trigger ) {
|
|
2542
|
+
if ( ! op_mask ) {
|
|
2543
|
+
ca_create_mask(co);
|
|
2544
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2545
|
+
}
|
|
2546
|
+
op_mask[out_i] = 1;
|
|
2547
|
+
op[out_i++] = (double) 0.0;
|
|
2548
|
+
} else {
|
|
2549
|
+
cmplx64_t mean = sum / (cmplx64_t)(double) n_valid;
|
|
2550
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2551
|
+
double M2 = 0.0;
|
|
2552
|
+
ca_size_t __unused_mc = 0;
|
|
2553
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx64_t, double, st, p, m, M2, 0.0, __stddevp_cmplx64_P2EXPR, __unused_mc);
|
|
2554
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
ca_iter_state_finish(&st);
|
|
2558
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2559
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2560
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2561
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2562
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2563
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2564
|
+
return rb_float_new(op[0]);
|
|
2565
|
+
}
|
|
2566
|
+
return vout;
|
|
2567
|
+
}
|
|
2568
|
+
#undef __stddevp_cmplx64_P1EXPR
|
|
2569
|
+
#undef __stddevp_cmplx64_P2EXPR
|
|
2570
|
+
|
|
2571
|
+
#define __stddevp_cmplx128_P1EXPR(__x) (__x)
|
|
2572
|
+
#define __stddevp_cmplx128_P2EXPR(__x) (creal((__x) - mean) * creal((__x) - mean) + cimag((__x) - mean) * cimag((__x) - mean))
|
|
2573
|
+
static VALUE
|
|
2574
|
+
stddevp_ki_native_cmplx128 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2575
|
+
{
|
|
2576
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2577
|
+
CArray *co;
|
|
2578
|
+
GetCArray(vout, co);
|
|
2579
|
+
double *op = (double *) co->ptr;
|
|
2580
|
+
ca_iter_state st;
|
|
2581
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2582
|
+
slab_axes, naxes, 0);
|
|
2583
|
+
if ( rc != CA_ITER_OK ) {
|
|
2584
|
+
rb_raise(rb_eRuntimeError,
|
|
2585
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2586
|
+
}
|
|
2587
|
+
char *p;
|
|
2588
|
+
boolean8_t *m;
|
|
2589
|
+
ca_size_t out_i = 0;
|
|
2590
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2591
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2592
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2593
|
+
cmplx128_t sum = 0;
|
|
2594
|
+
ca_size_t masked_cnt = 0;
|
|
2595
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx128_t, cmplx128_t, st, p, m, sum, 0, __stddevp_cmplx128_P1EXPR, masked_cnt);
|
|
2596
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2597
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2598
|
+
if ( __trigger ) {
|
|
2599
|
+
if ( ! op_mask ) {
|
|
2600
|
+
ca_create_mask(co);
|
|
2601
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2602
|
+
}
|
|
2603
|
+
op_mask[out_i] = 1;
|
|
2604
|
+
op[out_i++] = (double) 0.0;
|
|
2605
|
+
} else {
|
|
2606
|
+
cmplx128_t mean = sum / (cmplx128_t)(double) n_valid;
|
|
2607
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2608
|
+
double M2 = 0.0;
|
|
2609
|
+
ca_size_t __unused_mc = 0;
|
|
2610
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx128_t, double, st, p, m, M2, 0.0, __stddevp_cmplx128_P2EXPR, __unused_mc);
|
|
2611
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
ca_iter_state_finish(&st);
|
|
2615
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2616
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2617
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2618
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2619
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2620
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2621
|
+
return rb_float_new(op[0]);
|
|
2622
|
+
}
|
|
2623
|
+
return vout;
|
|
2624
|
+
}
|
|
2625
|
+
#undef __stddevp_cmplx128_P1EXPR
|
|
2626
|
+
#undef __stddevp_cmplx128_P2EXPR
|
|
2627
|
+
|
|
2628
|
+
#define __stddevp_bool_P1EXPR(__x) ((double)(__x))
|
|
2629
|
+
#define __stddevp_bool_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2630
|
+
static VALUE
|
|
2631
|
+
stddevp_ki_native_bool (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2632
|
+
{
|
|
2633
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2634
|
+
CArray *co;
|
|
2635
|
+
GetCArray(vout, co);
|
|
2636
|
+
double *op = (double *) co->ptr;
|
|
2637
|
+
ca_iter_state st;
|
|
2638
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2639
|
+
slab_axes, naxes, 0);
|
|
2640
|
+
if ( rc != CA_ITER_OK ) {
|
|
2641
|
+
rb_raise(rb_eRuntimeError,
|
|
2642
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2643
|
+
}
|
|
2644
|
+
char *p;
|
|
2645
|
+
boolean8_t *m;
|
|
2646
|
+
ca_size_t out_i = 0;
|
|
2647
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2648
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2649
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2650
|
+
double sum = 0.0;
|
|
2651
|
+
ca_size_t masked_cnt = 0;
|
|
2652
|
+
CA_SLAB_REDUCE_SUM8_EX(boolean8_t, double, st, p, m, sum, 0.0, __stddevp_bool_P1EXPR, masked_cnt);
|
|
2653
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2654
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2655
|
+
if ( __trigger ) {
|
|
2656
|
+
if ( ! op_mask ) {
|
|
2657
|
+
ca_create_mask(co);
|
|
2658
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2659
|
+
}
|
|
2660
|
+
op_mask[out_i] = 1;
|
|
2661
|
+
op[out_i++] = (double) 0.0;
|
|
2662
|
+
} else {
|
|
2663
|
+
double mean = sum / (double) n_valid;
|
|
2664
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2665
|
+
double M2 = 0.0;
|
|
2666
|
+
ca_size_t __unused_mc = 0;
|
|
2667
|
+
CA_SLAB_REDUCE_SUM8_EX(boolean8_t, double, st, p, m, M2, 0.0, __stddevp_bool_P2EXPR, __unused_mc);
|
|
2668
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid)));
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
ca_iter_state_finish(&st);
|
|
2672
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2673
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2674
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2675
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2676
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2677
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2678
|
+
return rb_float_new(op[0]);
|
|
2679
|
+
}
|
|
2680
|
+
return vout;
|
|
2681
|
+
}
|
|
2682
|
+
#undef __stddevp_bool_P1EXPR
|
|
2683
|
+
#undef __stddevp_bool_P2EXPR
|
|
2684
|
+
|
|
2685
|
+
/* The object lane calls Ruby for every cell, so a walk can raise part
|
|
2686
|
+
way. Its states live in the caller's frame, and ca_iter_ensure
|
|
2687
|
+
finishes them however the body leaves. */
|
|
2688
|
+
typedef struct {
|
|
2689
|
+
ca_iter_state states[1];
|
|
2690
|
+
VALUE self;
|
|
2691
|
+
CArray *ca;
|
|
2692
|
+
int8_t *slab_axes;
|
|
2693
|
+
int8_t naxes;
|
|
2694
|
+
int keep_axis;
|
|
2695
|
+
ca_size_t min_count;
|
|
2696
|
+
} stddevp_ki_native_object_frame;
|
|
2697
|
+
|
|
2698
|
+
static VALUE
|
|
2699
|
+
stddevp_ki_native_object_body (VALUE arg)
|
|
2700
|
+
{
|
|
2701
|
+
stddevp_ki_native_object_frame *fr = (stddevp_ki_native_object_frame *) arg;
|
|
2702
|
+
VALUE self = fr->self;
|
|
2703
|
+
(void) self;
|
|
2704
|
+
CArray *ca = fr->ca;
|
|
2705
|
+
(void) ca;
|
|
2706
|
+
int8_t *slab_axes = fr->slab_axes;
|
|
2707
|
+
(void) slab_axes;
|
|
2708
|
+
int8_t naxes = fr->naxes;
|
|
2709
|
+
(void) naxes;
|
|
2710
|
+
int keep_axis = fr->keep_axis;
|
|
2711
|
+
(void) keep_axis;
|
|
2712
|
+
ca_size_t min_count = fr->min_count;
|
|
2713
|
+
(void) min_count;
|
|
2714
|
+
#define st (fr->states[0])
|
|
2715
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2716
|
+
CArray *co;
|
|
2717
|
+
GetCArray(vout, co);
|
|
2718
|
+
double *op = (double *) co->ptr;
|
|
2719
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2720
|
+
slab_axes, naxes, 0);
|
|
2721
|
+
if ( rc != CA_ITER_OK ) {
|
|
2722
|
+
rb_raise(rb_eRuntimeError,
|
|
2723
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2724
|
+
}
|
|
2725
|
+
char *p;
|
|
2726
|
+
boolean8_t *m;
|
|
2727
|
+
ca_size_t out_i = 0;
|
|
2728
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2729
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2730
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2731
|
+
VALUE sum = INT2FIX(0);
|
|
2732
|
+
ca_size_t masked_cnt = 0;
|
|
2733
|
+
CA_SLAB_REDUCE_T_EX(VALUE, st, p, m, sum, INT2FIX(0), sum = rb_funcall(sum, rb_intern("+"), 1, v), masked_cnt);
|
|
2734
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2735
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 1);
|
|
2736
|
+
if ( __trigger ) {
|
|
2737
|
+
if ( ! op_mask ) {
|
|
2738
|
+
ca_create_mask(co);
|
|
2739
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2740
|
+
}
|
|
2741
|
+
op_mask[out_i] = 1;
|
|
2742
|
+
op[out_i++] = (double) 0.0;
|
|
2743
|
+
} else {
|
|
2744
|
+
VALUE mean = rb_funcall(sum, rb_intern("/"), 1, LONG2NUM(n_valid));
|
|
2745
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2746
|
+
VALUE M2 = INT2FIX(0);
|
|
2747
|
+
ca_size_t __unused_mc = 0;
|
|
2748
|
+
CA_SLAB_REDUCE_T_EX(VALUE, st, p, m, M2, INT2FIX(0), VALUE __d = rb_funcall(v, rb_intern("-"), 1, mean);
|
|
2749
|
+
M2 = rb_funcall(M2, rb_intern("+"), 1, rb_funcall(__d, rb_intern("*"), 1, __d)), __unused_mc);
|
|
2750
|
+
op[out_i++] = (double)(ca_sqrt_clamp(NUM2DBL(rb_funcall(M2, rb_intern("/"), 1, LONG2NUM(n_valid)))));
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
ca_iter_state_finish(&st);
|
|
2754
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2755
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2756
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2757
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2758
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2759
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2760
|
+
return rb_float_new(op[0]);
|
|
2761
|
+
}
|
|
2762
|
+
return vout;
|
|
2763
|
+
#undef st
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
static VALUE
|
|
2767
|
+
stddevp_ki_native_object (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2768
|
+
{
|
|
2769
|
+
stddevp_ki_native_object_frame fr;
|
|
2770
|
+
fr.self = self;
|
|
2771
|
+
fr.ca = ca;
|
|
2772
|
+
fr.slab_axes = slab_axes;
|
|
2773
|
+
fr.naxes = naxes;
|
|
2774
|
+
fr.keep_axis = keep_axis;
|
|
2775
|
+
fr.min_count = min_count;
|
|
2776
|
+
return ca_iter_ensure(1, fr.states, stddevp_ki_native_object_body, (VALUE) &fr);
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
|
|
2780
|
+
VALUE
|
|
2781
|
+
rb_ca_stddevp_ki (int argc, VALUE *argv, VALUE self)
|
|
2782
|
+
{
|
|
2783
|
+
CArray *src;
|
|
2784
|
+
GetCArray(self, src);
|
|
2785
|
+
volatile VALUE ropt = rb_pop_options(&argc, &argv);
|
|
2786
|
+
volatile VALUE raxis = Qnil, rkeep_axis = Qnil, rmin_count = Qnil, rfval = Qnil;
|
|
2787
|
+
rb_scan_options(ropt, "axis,keep_axis,min_count,fill_value", &raxis, &rkeep_axis, &rmin_count, &rfval);
|
|
2788
|
+
int keep_axis = RTEST(rkeep_axis);
|
|
2789
|
+
int8_t slab_axes[CA_RANK_MAX];
|
|
2790
|
+
int8_t naxes = rb_ca_parse_reduce_axes_kw(raxis, src, slab_axes);
|
|
2791
|
+
if ( ca_is_lazy_view(src) ) {
|
|
2792
|
+
volatile VALUE evaluated = ca_lazy_evaluated(self);
|
|
2793
|
+
if ( ! NIL_P(evaluated) ) {
|
|
2794
|
+
self = evaluated;
|
|
2795
|
+
GetCArray(self, src);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
ca_size_t min_count = ca_min_count_arg(rmin_count, NULL);
|
|
2799
|
+
if ( rfval == CA_UNDEF ) rfval = Qnil;
|
|
2800
|
+
int fill_whole = 0;
|
|
2801
|
+
if ( ! NIL_P(rfval) && naxes == src->ndim && ! keep_axis ) {
|
|
2802
|
+
keep_axis = 1;
|
|
2803
|
+
fill_whole = 1;
|
|
2804
|
+
}
|
|
2805
|
+
VALUE result;
|
|
2806
|
+
if ( argc > 0 ) {
|
|
2807
|
+
rb_raise(rb_eArgError, "%s: positional axis arguments are no longer accepted (got %d); use the axis: keyword, e.g. a.%s(axis: 0) or a.%s(axis: [0, 1])", ca_calling_method_name(), argc, ca_calling_method_name(), ca_calling_method_name());
|
|
2808
|
+
}
|
|
2809
|
+
switch ( src->data_type ) {
|
|
2810
|
+
case CA_INT8: {
|
|
2811
|
+
result = stddevp_ki_native_i8(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2812
|
+
RB_GC_GUARD(self);
|
|
2813
|
+
break;
|
|
2814
|
+
}
|
|
2815
|
+
case CA_UINT8: {
|
|
2816
|
+
result = stddevp_ki_native_u8(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2817
|
+
RB_GC_GUARD(self);
|
|
2818
|
+
break;
|
|
2819
|
+
}
|
|
2820
|
+
case CA_INT16: {
|
|
2821
|
+
result = stddevp_ki_native_i16(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2822
|
+
RB_GC_GUARD(self);
|
|
2823
|
+
break;
|
|
2824
|
+
}
|
|
2825
|
+
case CA_UINT16: {
|
|
2826
|
+
result = stddevp_ki_native_u16(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2827
|
+
RB_GC_GUARD(self);
|
|
2828
|
+
break;
|
|
2829
|
+
}
|
|
2830
|
+
case CA_INT32: {
|
|
2831
|
+
result = stddevp_ki_native_i32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2832
|
+
RB_GC_GUARD(self);
|
|
2833
|
+
break;
|
|
2834
|
+
}
|
|
2835
|
+
case CA_UINT32: {
|
|
2836
|
+
result = stddevp_ki_native_u32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2837
|
+
RB_GC_GUARD(self);
|
|
2838
|
+
break;
|
|
2839
|
+
}
|
|
2840
|
+
case CA_INT64: {
|
|
2841
|
+
result = stddevp_ki_native_i64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2842
|
+
RB_GC_GUARD(self);
|
|
2843
|
+
break;
|
|
2844
|
+
}
|
|
2845
|
+
case CA_UINT64: {
|
|
2846
|
+
result = stddevp_ki_native_u64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2847
|
+
RB_GC_GUARD(self);
|
|
2848
|
+
break;
|
|
2849
|
+
}
|
|
2850
|
+
case CA_FLOAT32: {
|
|
2851
|
+
result = stddevp_ki_native_f32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2852
|
+
RB_GC_GUARD(self);
|
|
2853
|
+
break;
|
|
2854
|
+
}
|
|
2855
|
+
case CA_FLOAT64: {
|
|
2856
|
+
result = stddevp_ki_native_f64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2857
|
+
RB_GC_GUARD(self);
|
|
2858
|
+
break;
|
|
2859
|
+
}
|
|
2860
|
+
case CA_CMPLX64: {
|
|
2861
|
+
result = stddevp_ki_native_cmplx64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2862
|
+
RB_GC_GUARD(self);
|
|
2863
|
+
break;
|
|
2864
|
+
}
|
|
2865
|
+
case CA_CMPLX128: {
|
|
2866
|
+
result = stddevp_ki_native_cmplx128(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2867
|
+
RB_GC_GUARD(self);
|
|
2868
|
+
break;
|
|
2869
|
+
}
|
|
2870
|
+
case CA_BOOLEAN: {
|
|
2871
|
+
result = stddevp_ki_native_bool(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2872
|
+
RB_GC_GUARD(self);
|
|
2873
|
+
break;
|
|
2874
|
+
}
|
|
2875
|
+
case CA_OBJECT: {
|
|
2876
|
+
result = stddevp_ki_native_object(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
2877
|
+
RB_GC_GUARD(self);
|
|
2878
|
+
break;
|
|
2879
|
+
}
|
|
2880
|
+
default:
|
|
2881
|
+
ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
|
|
2882
|
+
rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, cmplx64, cmplx128, boolean, object)", ca_calling_method_name(), ca_type_name[src->data_type]);
|
|
2883
|
+
}
|
|
2884
|
+
if ( ! NIL_P(rfval) ) {
|
|
2885
|
+
result = ca_reduce_fill(result, rfval, fill_whole);
|
|
2886
|
+
}
|
|
2887
|
+
return result;
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2890
|
+
/* ===== stddev_ki ============================================ */
|
|
2891
|
+
|
|
2892
|
+
#define __stddev_i8_P1EXPR(__x) ((double)(__x))
|
|
2893
|
+
#define __stddev_i8_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2894
|
+
static VALUE
|
|
2895
|
+
stddev_ki_native_i8 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2896
|
+
{
|
|
2897
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2898
|
+
CArray *co;
|
|
2899
|
+
GetCArray(vout, co);
|
|
2900
|
+
double *op = (double *) co->ptr;
|
|
2901
|
+
ca_iter_state st;
|
|
2902
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2903
|
+
slab_axes, naxes, 0);
|
|
2904
|
+
if ( rc != CA_ITER_OK ) {
|
|
2905
|
+
rb_raise(rb_eRuntimeError,
|
|
2906
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2907
|
+
}
|
|
2908
|
+
char *p;
|
|
2909
|
+
boolean8_t *m;
|
|
2910
|
+
ca_size_t out_i = 0;
|
|
2911
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2912
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2913
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2914
|
+
double sum = 0.0;
|
|
2915
|
+
ca_size_t masked_cnt = 0;
|
|
2916
|
+
CA_SLAB_REDUCE_SUM8_EX(int8_t, double, st, p, m, sum, 0.0, __stddev_i8_P1EXPR, masked_cnt);
|
|
2917
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2918
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
2919
|
+
if ( __trigger ) {
|
|
2920
|
+
if ( ! op_mask ) {
|
|
2921
|
+
ca_create_mask(co);
|
|
2922
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2923
|
+
}
|
|
2924
|
+
op_mask[out_i] = 1;
|
|
2925
|
+
op[out_i++] = (double) 0.0;
|
|
2926
|
+
} else {
|
|
2927
|
+
double mean = sum / (double) n_valid;
|
|
2928
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2929
|
+
double M2 = 0.0;
|
|
2930
|
+
ca_size_t __unused_mc = 0;
|
|
2931
|
+
CA_SLAB_REDUCE_SUM8_EX(int8_t, double, st, p, m, M2, 0.0, __stddev_i8_P2EXPR, __unused_mc);
|
|
2932
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
ca_iter_state_finish(&st);
|
|
2936
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2937
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2938
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2939
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2940
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2941
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2942
|
+
return rb_float_new(op[0]);
|
|
2943
|
+
}
|
|
2944
|
+
return vout;
|
|
2945
|
+
}
|
|
2946
|
+
#undef __stddev_i8_P1EXPR
|
|
2947
|
+
#undef __stddev_i8_P2EXPR
|
|
2948
|
+
|
|
2949
|
+
#define __stddev_u8_P1EXPR(__x) ((double)(__x))
|
|
2950
|
+
#define __stddev_u8_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
2951
|
+
static VALUE
|
|
2952
|
+
stddev_ki_native_u8 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
2953
|
+
{
|
|
2954
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
2955
|
+
CArray *co;
|
|
2956
|
+
GetCArray(vout, co);
|
|
2957
|
+
double *op = (double *) co->ptr;
|
|
2958
|
+
ca_iter_state st;
|
|
2959
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
2960
|
+
slab_axes, naxes, 0);
|
|
2961
|
+
if ( rc != CA_ITER_OK ) {
|
|
2962
|
+
rb_raise(rb_eRuntimeError,
|
|
2963
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
2964
|
+
}
|
|
2965
|
+
char *p;
|
|
2966
|
+
boolean8_t *m;
|
|
2967
|
+
ca_size_t out_i = 0;
|
|
2968
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
2969
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
2970
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
2971
|
+
double sum = 0.0;
|
|
2972
|
+
ca_size_t masked_cnt = 0;
|
|
2973
|
+
CA_SLAB_REDUCE_SUM8_EX(uint8_t, double, st, p, m, sum, 0.0, __stddev_u8_P1EXPR, masked_cnt);
|
|
2974
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
2975
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
2976
|
+
if ( __trigger ) {
|
|
2977
|
+
if ( ! op_mask ) {
|
|
2978
|
+
ca_create_mask(co);
|
|
2979
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
2980
|
+
}
|
|
2981
|
+
op_mask[out_i] = 1;
|
|
2982
|
+
op[out_i++] = (double) 0.0;
|
|
2983
|
+
} else {
|
|
2984
|
+
double mean = sum / (double) n_valid;
|
|
2985
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
2986
|
+
double M2 = 0.0;
|
|
2987
|
+
ca_size_t __unused_mc = 0;
|
|
2988
|
+
CA_SLAB_REDUCE_SUM8_EX(uint8_t, double, st, p, m, M2, 0.0, __stddev_u8_P2EXPR, __unused_mc);
|
|
2989
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
ca_iter_state_finish(&st);
|
|
2993
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
2994
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
2995
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
2996
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
2997
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
2998
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
2999
|
+
return rb_float_new(op[0]);
|
|
3000
|
+
}
|
|
3001
|
+
return vout;
|
|
3002
|
+
}
|
|
3003
|
+
#undef __stddev_u8_P1EXPR
|
|
3004
|
+
#undef __stddev_u8_P2EXPR
|
|
3005
|
+
|
|
3006
|
+
#define __stddev_i16_P1EXPR(__x) ((double)(__x))
|
|
3007
|
+
#define __stddev_i16_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3008
|
+
static VALUE
|
|
3009
|
+
stddev_ki_native_i16 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3010
|
+
{
|
|
3011
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3012
|
+
CArray *co;
|
|
3013
|
+
GetCArray(vout, co);
|
|
3014
|
+
double *op = (double *) co->ptr;
|
|
3015
|
+
ca_iter_state st;
|
|
3016
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3017
|
+
slab_axes, naxes, 0);
|
|
3018
|
+
if ( rc != CA_ITER_OK ) {
|
|
3019
|
+
rb_raise(rb_eRuntimeError,
|
|
3020
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3021
|
+
}
|
|
3022
|
+
char *p;
|
|
3023
|
+
boolean8_t *m;
|
|
3024
|
+
ca_size_t out_i = 0;
|
|
3025
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3026
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3027
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3028
|
+
double sum = 0.0;
|
|
3029
|
+
ca_size_t masked_cnt = 0;
|
|
3030
|
+
CA_SLAB_REDUCE_SUM8_EX(int16_t, double, st, p, m, sum, 0.0, __stddev_i16_P1EXPR, masked_cnt);
|
|
3031
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3032
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3033
|
+
if ( __trigger ) {
|
|
3034
|
+
if ( ! op_mask ) {
|
|
3035
|
+
ca_create_mask(co);
|
|
3036
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3037
|
+
}
|
|
3038
|
+
op_mask[out_i] = 1;
|
|
3039
|
+
op[out_i++] = (double) 0.0;
|
|
3040
|
+
} else {
|
|
3041
|
+
double mean = sum / (double) n_valid;
|
|
3042
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3043
|
+
double M2 = 0.0;
|
|
3044
|
+
ca_size_t __unused_mc = 0;
|
|
3045
|
+
CA_SLAB_REDUCE_SUM8_EX(int16_t, double, st, p, m, M2, 0.0, __stddev_i16_P2EXPR, __unused_mc);
|
|
3046
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
ca_iter_state_finish(&st);
|
|
3050
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3051
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3052
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3053
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3054
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3055
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3056
|
+
return rb_float_new(op[0]);
|
|
3057
|
+
}
|
|
3058
|
+
return vout;
|
|
3059
|
+
}
|
|
3060
|
+
#undef __stddev_i16_P1EXPR
|
|
3061
|
+
#undef __stddev_i16_P2EXPR
|
|
3062
|
+
|
|
3063
|
+
#define __stddev_u16_P1EXPR(__x) ((double)(__x))
|
|
3064
|
+
#define __stddev_u16_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3065
|
+
static VALUE
|
|
3066
|
+
stddev_ki_native_u16 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3067
|
+
{
|
|
3068
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3069
|
+
CArray *co;
|
|
3070
|
+
GetCArray(vout, co);
|
|
3071
|
+
double *op = (double *) co->ptr;
|
|
3072
|
+
ca_iter_state st;
|
|
3073
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3074
|
+
slab_axes, naxes, 0);
|
|
3075
|
+
if ( rc != CA_ITER_OK ) {
|
|
3076
|
+
rb_raise(rb_eRuntimeError,
|
|
3077
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3078
|
+
}
|
|
3079
|
+
char *p;
|
|
3080
|
+
boolean8_t *m;
|
|
3081
|
+
ca_size_t out_i = 0;
|
|
3082
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3083
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3084
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3085
|
+
double sum = 0.0;
|
|
3086
|
+
ca_size_t masked_cnt = 0;
|
|
3087
|
+
CA_SLAB_REDUCE_SUM8_EX(uint16_t, double, st, p, m, sum, 0.0, __stddev_u16_P1EXPR, masked_cnt);
|
|
3088
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3089
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3090
|
+
if ( __trigger ) {
|
|
3091
|
+
if ( ! op_mask ) {
|
|
3092
|
+
ca_create_mask(co);
|
|
3093
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3094
|
+
}
|
|
3095
|
+
op_mask[out_i] = 1;
|
|
3096
|
+
op[out_i++] = (double) 0.0;
|
|
3097
|
+
} else {
|
|
3098
|
+
double mean = sum / (double) n_valid;
|
|
3099
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3100
|
+
double M2 = 0.0;
|
|
3101
|
+
ca_size_t __unused_mc = 0;
|
|
3102
|
+
CA_SLAB_REDUCE_SUM8_EX(uint16_t, double, st, p, m, M2, 0.0, __stddev_u16_P2EXPR, __unused_mc);
|
|
3103
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
ca_iter_state_finish(&st);
|
|
3107
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3108
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3109
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3110
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3111
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3112
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3113
|
+
return rb_float_new(op[0]);
|
|
3114
|
+
}
|
|
3115
|
+
return vout;
|
|
3116
|
+
}
|
|
3117
|
+
#undef __stddev_u16_P1EXPR
|
|
3118
|
+
#undef __stddev_u16_P2EXPR
|
|
3119
|
+
|
|
3120
|
+
#define __stddev_i32_P1EXPR(__x) ((double)(__x))
|
|
3121
|
+
#define __stddev_i32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3122
|
+
static VALUE
|
|
3123
|
+
stddev_ki_native_i32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3124
|
+
{
|
|
3125
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3126
|
+
CArray *co;
|
|
3127
|
+
GetCArray(vout, co);
|
|
3128
|
+
double *op = (double *) co->ptr;
|
|
3129
|
+
ca_iter_state st;
|
|
3130
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3131
|
+
slab_axes, naxes, 0);
|
|
3132
|
+
if ( rc != CA_ITER_OK ) {
|
|
3133
|
+
rb_raise(rb_eRuntimeError,
|
|
3134
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3135
|
+
}
|
|
3136
|
+
char *p;
|
|
3137
|
+
boolean8_t *m;
|
|
3138
|
+
ca_size_t out_i = 0;
|
|
3139
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3140
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3141
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3142
|
+
double sum = 0.0;
|
|
3143
|
+
ca_size_t masked_cnt = 0;
|
|
3144
|
+
CA_SLAB_REDUCE_SUM8_EX(int32_t, double, st, p, m, sum, 0.0, __stddev_i32_P1EXPR, masked_cnt);
|
|
3145
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3146
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3147
|
+
if ( __trigger ) {
|
|
3148
|
+
if ( ! op_mask ) {
|
|
3149
|
+
ca_create_mask(co);
|
|
3150
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3151
|
+
}
|
|
3152
|
+
op_mask[out_i] = 1;
|
|
3153
|
+
op[out_i++] = (double) 0.0;
|
|
3154
|
+
} else {
|
|
3155
|
+
double mean = sum / (double) n_valid;
|
|
3156
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3157
|
+
double M2 = 0.0;
|
|
3158
|
+
ca_size_t __unused_mc = 0;
|
|
3159
|
+
CA_SLAB_REDUCE_SUM8_EX(int32_t, double, st, p, m, M2, 0.0, __stddev_i32_P2EXPR, __unused_mc);
|
|
3160
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
3163
|
+
ca_iter_state_finish(&st);
|
|
3164
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3165
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3166
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3167
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3168
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3169
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3170
|
+
return rb_float_new(op[0]);
|
|
3171
|
+
}
|
|
3172
|
+
return vout;
|
|
3173
|
+
}
|
|
3174
|
+
#undef __stddev_i32_P1EXPR
|
|
3175
|
+
#undef __stddev_i32_P2EXPR
|
|
3176
|
+
|
|
3177
|
+
#define __stddev_u32_P1EXPR(__x) ((double)(__x))
|
|
3178
|
+
#define __stddev_u32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3179
|
+
static VALUE
|
|
3180
|
+
stddev_ki_native_u32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3181
|
+
{
|
|
3182
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3183
|
+
CArray *co;
|
|
3184
|
+
GetCArray(vout, co);
|
|
3185
|
+
double *op = (double *) co->ptr;
|
|
3186
|
+
ca_iter_state st;
|
|
3187
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3188
|
+
slab_axes, naxes, 0);
|
|
3189
|
+
if ( rc != CA_ITER_OK ) {
|
|
3190
|
+
rb_raise(rb_eRuntimeError,
|
|
3191
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3192
|
+
}
|
|
3193
|
+
char *p;
|
|
3194
|
+
boolean8_t *m;
|
|
3195
|
+
ca_size_t out_i = 0;
|
|
3196
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3197
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3198
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3199
|
+
double sum = 0.0;
|
|
3200
|
+
ca_size_t masked_cnt = 0;
|
|
3201
|
+
CA_SLAB_REDUCE_SUM8_EX(uint32_t, double, st, p, m, sum, 0.0, __stddev_u32_P1EXPR, masked_cnt);
|
|
3202
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3203
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3204
|
+
if ( __trigger ) {
|
|
3205
|
+
if ( ! op_mask ) {
|
|
3206
|
+
ca_create_mask(co);
|
|
3207
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3208
|
+
}
|
|
3209
|
+
op_mask[out_i] = 1;
|
|
3210
|
+
op[out_i++] = (double) 0.0;
|
|
3211
|
+
} else {
|
|
3212
|
+
double mean = sum / (double) n_valid;
|
|
3213
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3214
|
+
double M2 = 0.0;
|
|
3215
|
+
ca_size_t __unused_mc = 0;
|
|
3216
|
+
CA_SLAB_REDUCE_SUM8_EX(uint32_t, double, st, p, m, M2, 0.0, __stddev_u32_P2EXPR, __unused_mc);
|
|
3217
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
ca_iter_state_finish(&st);
|
|
3221
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3222
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3223
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3224
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3225
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3226
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3227
|
+
return rb_float_new(op[0]);
|
|
3228
|
+
}
|
|
3229
|
+
return vout;
|
|
3230
|
+
}
|
|
3231
|
+
#undef __stddev_u32_P1EXPR
|
|
3232
|
+
#undef __stddev_u32_P2EXPR
|
|
3233
|
+
|
|
3234
|
+
#define __stddev_i64_P1EXPR(__x) ((double)(__x))
|
|
3235
|
+
#define __stddev_i64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3236
|
+
static VALUE
|
|
3237
|
+
stddev_ki_native_i64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3238
|
+
{
|
|
3239
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3240
|
+
CArray *co;
|
|
3241
|
+
GetCArray(vout, co);
|
|
3242
|
+
double *op = (double *) co->ptr;
|
|
3243
|
+
ca_iter_state st;
|
|
3244
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3245
|
+
slab_axes, naxes, 0);
|
|
3246
|
+
if ( rc != CA_ITER_OK ) {
|
|
3247
|
+
rb_raise(rb_eRuntimeError,
|
|
3248
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3249
|
+
}
|
|
3250
|
+
char *p;
|
|
3251
|
+
boolean8_t *m;
|
|
3252
|
+
ca_size_t out_i = 0;
|
|
3253
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3254
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3255
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3256
|
+
double sum = 0.0;
|
|
3257
|
+
ca_size_t masked_cnt = 0;
|
|
3258
|
+
CA_SLAB_REDUCE_SUM8_EX(int64_t, double, st, p, m, sum, 0.0, __stddev_i64_P1EXPR, masked_cnt);
|
|
3259
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3260
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3261
|
+
if ( __trigger ) {
|
|
3262
|
+
if ( ! op_mask ) {
|
|
3263
|
+
ca_create_mask(co);
|
|
3264
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3265
|
+
}
|
|
3266
|
+
op_mask[out_i] = 1;
|
|
3267
|
+
op[out_i++] = (double) 0.0;
|
|
3268
|
+
} else {
|
|
3269
|
+
double mean = sum / (double) n_valid;
|
|
3270
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3271
|
+
double M2 = 0.0;
|
|
3272
|
+
ca_size_t __unused_mc = 0;
|
|
3273
|
+
CA_SLAB_REDUCE_SUM8_EX(int64_t, double, st, p, m, M2, 0.0, __stddev_i64_P2EXPR, __unused_mc);
|
|
3274
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
ca_iter_state_finish(&st);
|
|
3278
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3279
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3280
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3281
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3282
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3283
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3284
|
+
return rb_float_new(op[0]);
|
|
3285
|
+
}
|
|
3286
|
+
return vout;
|
|
3287
|
+
}
|
|
3288
|
+
#undef __stddev_i64_P1EXPR
|
|
3289
|
+
#undef __stddev_i64_P2EXPR
|
|
3290
|
+
|
|
3291
|
+
#define __stddev_u64_P1EXPR(__x) ((double)(__x))
|
|
3292
|
+
#define __stddev_u64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3293
|
+
static VALUE
|
|
3294
|
+
stddev_ki_native_u64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3295
|
+
{
|
|
3296
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3297
|
+
CArray *co;
|
|
3298
|
+
GetCArray(vout, co);
|
|
3299
|
+
double *op = (double *) co->ptr;
|
|
3300
|
+
ca_iter_state st;
|
|
3301
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3302
|
+
slab_axes, naxes, 0);
|
|
3303
|
+
if ( rc != CA_ITER_OK ) {
|
|
3304
|
+
rb_raise(rb_eRuntimeError,
|
|
3305
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3306
|
+
}
|
|
3307
|
+
char *p;
|
|
3308
|
+
boolean8_t *m;
|
|
3309
|
+
ca_size_t out_i = 0;
|
|
3310
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3311
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3312
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3313
|
+
double sum = 0.0;
|
|
3314
|
+
ca_size_t masked_cnt = 0;
|
|
3315
|
+
CA_SLAB_REDUCE_SUM8_EX(uint64_t, double, st, p, m, sum, 0.0, __stddev_u64_P1EXPR, masked_cnt);
|
|
3316
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3317
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3318
|
+
if ( __trigger ) {
|
|
3319
|
+
if ( ! op_mask ) {
|
|
3320
|
+
ca_create_mask(co);
|
|
3321
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3322
|
+
}
|
|
3323
|
+
op_mask[out_i] = 1;
|
|
3324
|
+
op[out_i++] = (double) 0.0;
|
|
3325
|
+
} else {
|
|
3326
|
+
double mean = sum / (double) n_valid;
|
|
3327
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3328
|
+
double M2 = 0.0;
|
|
3329
|
+
ca_size_t __unused_mc = 0;
|
|
3330
|
+
CA_SLAB_REDUCE_SUM8_EX(uint64_t, double, st, p, m, M2, 0.0, __stddev_u64_P2EXPR, __unused_mc);
|
|
3331
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3334
|
+
ca_iter_state_finish(&st);
|
|
3335
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3336
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3337
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3338
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3339
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3340
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3341
|
+
return rb_float_new(op[0]);
|
|
3342
|
+
}
|
|
3343
|
+
return vout;
|
|
3344
|
+
}
|
|
3345
|
+
#undef __stddev_u64_P1EXPR
|
|
3346
|
+
#undef __stddev_u64_P2EXPR
|
|
3347
|
+
|
|
3348
|
+
#define __stddev_f32_P1EXPR(__x) ((double)(__x))
|
|
3349
|
+
#define __stddev_f32_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3350
|
+
static VALUE
|
|
3351
|
+
stddev_ki_native_f32 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3352
|
+
{
|
|
3353
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3354
|
+
CArray *co;
|
|
3355
|
+
GetCArray(vout, co);
|
|
3356
|
+
double *op = (double *) co->ptr;
|
|
3357
|
+
ca_iter_state st;
|
|
3358
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3359
|
+
slab_axes, naxes, 0);
|
|
3360
|
+
if ( rc != CA_ITER_OK ) {
|
|
3361
|
+
rb_raise(rb_eRuntimeError,
|
|
3362
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3363
|
+
}
|
|
3364
|
+
char *p;
|
|
3365
|
+
boolean8_t *m;
|
|
3366
|
+
ca_size_t out_i = 0;
|
|
3367
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3368
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3369
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3370
|
+
double sum = 0.0;
|
|
3371
|
+
ca_size_t masked_cnt = 0;
|
|
3372
|
+
CA_SLAB_REDUCE_SUM8_EX(float, double, st, p, m, sum, 0.0, __stddev_f32_P1EXPR, masked_cnt);
|
|
3373
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3374
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3375
|
+
if ( __trigger ) {
|
|
3376
|
+
if ( ! op_mask ) {
|
|
3377
|
+
ca_create_mask(co);
|
|
3378
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3379
|
+
}
|
|
3380
|
+
op_mask[out_i] = 1;
|
|
3381
|
+
op[out_i++] = (double) 0.0;
|
|
3382
|
+
} else {
|
|
3383
|
+
double mean = sum / (double) n_valid;
|
|
3384
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3385
|
+
double M2 = 0.0;
|
|
3386
|
+
ca_size_t __unused_mc = 0;
|
|
3387
|
+
CA_SLAB_REDUCE_SUM8_EX(float, double, st, p, m, M2, 0.0, __stddev_f32_P2EXPR, __unused_mc);
|
|
3388
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
ca_iter_state_finish(&st);
|
|
3392
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3393
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3394
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3395
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3396
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3397
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3398
|
+
return rb_float_new(op[0]);
|
|
3399
|
+
}
|
|
3400
|
+
return vout;
|
|
3401
|
+
}
|
|
3402
|
+
#undef __stddev_f32_P1EXPR
|
|
3403
|
+
#undef __stddev_f32_P2EXPR
|
|
3404
|
+
|
|
3405
|
+
#define __stddev_f64_P1EXPR(__x) ((double)(__x))
|
|
3406
|
+
#define __stddev_f64_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3407
|
+
static VALUE
|
|
3408
|
+
stddev_ki_native_f64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3409
|
+
{
|
|
3410
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3411
|
+
CArray *co;
|
|
3412
|
+
GetCArray(vout, co);
|
|
3413
|
+
double *op = (double *) co->ptr;
|
|
3414
|
+
ca_iter_state st;
|
|
3415
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3416
|
+
slab_axes, naxes, 0);
|
|
3417
|
+
if ( rc != CA_ITER_OK ) {
|
|
3418
|
+
rb_raise(rb_eRuntimeError,
|
|
3419
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3420
|
+
}
|
|
3421
|
+
char *p;
|
|
3422
|
+
boolean8_t *m;
|
|
3423
|
+
ca_size_t out_i = 0;
|
|
3424
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3425
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3426
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3427
|
+
double sum = 0.0;
|
|
3428
|
+
ca_size_t masked_cnt = 0;
|
|
3429
|
+
CA_SLAB_REDUCE_SUM8_EX(double, double, st, p, m, sum, 0.0, __stddev_f64_P1EXPR, masked_cnt);
|
|
3430
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3431
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3432
|
+
if ( __trigger ) {
|
|
3433
|
+
if ( ! op_mask ) {
|
|
3434
|
+
ca_create_mask(co);
|
|
3435
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3436
|
+
}
|
|
3437
|
+
op_mask[out_i] = 1;
|
|
3438
|
+
op[out_i++] = (double) 0.0;
|
|
3439
|
+
} else {
|
|
3440
|
+
double mean = sum / (double) n_valid;
|
|
3441
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3442
|
+
double M2 = 0.0;
|
|
3443
|
+
ca_size_t __unused_mc = 0;
|
|
3444
|
+
CA_SLAB_REDUCE_SUM8_EX(double, double, st, p, m, M2, 0.0, __stddev_f64_P2EXPR, __unused_mc);
|
|
3445
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
ca_iter_state_finish(&st);
|
|
3449
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3450
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3451
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3452
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3453
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3454
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3455
|
+
return rb_float_new(op[0]);
|
|
3456
|
+
}
|
|
3457
|
+
return vout;
|
|
3458
|
+
}
|
|
3459
|
+
#undef __stddev_f64_P1EXPR
|
|
3460
|
+
#undef __stddev_f64_P2EXPR
|
|
3461
|
+
|
|
3462
|
+
#define __stddev_cmplx64_P1EXPR(__x) (__x)
|
|
3463
|
+
#define __stddev_cmplx64_P2EXPR(__x) (creal((__x) - mean) * creal((__x) - mean) + cimag((__x) - mean) * cimag((__x) - mean))
|
|
3464
|
+
static VALUE
|
|
3465
|
+
stddev_ki_native_cmplx64 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3466
|
+
{
|
|
3467
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3468
|
+
CArray *co;
|
|
3469
|
+
GetCArray(vout, co);
|
|
3470
|
+
double *op = (double *) co->ptr;
|
|
3471
|
+
ca_iter_state st;
|
|
3472
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3473
|
+
slab_axes, naxes, 0);
|
|
3474
|
+
if ( rc != CA_ITER_OK ) {
|
|
3475
|
+
rb_raise(rb_eRuntimeError,
|
|
3476
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3477
|
+
}
|
|
3478
|
+
char *p;
|
|
3479
|
+
boolean8_t *m;
|
|
3480
|
+
ca_size_t out_i = 0;
|
|
3481
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3482
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3483
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3484
|
+
cmplx64_t sum = 0;
|
|
3485
|
+
ca_size_t masked_cnt = 0;
|
|
3486
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx64_t, cmplx64_t, st, p, m, sum, 0, __stddev_cmplx64_P1EXPR, masked_cnt);
|
|
3487
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3488
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3489
|
+
if ( __trigger ) {
|
|
3490
|
+
if ( ! op_mask ) {
|
|
3491
|
+
ca_create_mask(co);
|
|
3492
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3493
|
+
}
|
|
3494
|
+
op_mask[out_i] = 1;
|
|
3495
|
+
op[out_i++] = (double) 0.0;
|
|
3496
|
+
} else {
|
|
3497
|
+
cmplx64_t mean = sum / (cmplx64_t)(double) n_valid;
|
|
3498
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3499
|
+
double M2 = 0.0;
|
|
3500
|
+
ca_size_t __unused_mc = 0;
|
|
3501
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx64_t, double, st, p, m, M2, 0.0, __stddev_cmplx64_P2EXPR, __unused_mc);
|
|
3502
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
ca_iter_state_finish(&st);
|
|
3506
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3507
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3508
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3509
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3510
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3511
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3512
|
+
return rb_float_new(op[0]);
|
|
3513
|
+
}
|
|
3514
|
+
return vout;
|
|
3515
|
+
}
|
|
3516
|
+
#undef __stddev_cmplx64_P1EXPR
|
|
3517
|
+
#undef __stddev_cmplx64_P2EXPR
|
|
3518
|
+
|
|
3519
|
+
#define __stddev_cmplx128_P1EXPR(__x) (__x)
|
|
3520
|
+
#define __stddev_cmplx128_P2EXPR(__x) (creal((__x) - mean) * creal((__x) - mean) + cimag((__x) - mean) * cimag((__x) - mean))
|
|
3521
|
+
static VALUE
|
|
3522
|
+
stddev_ki_native_cmplx128 (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3523
|
+
{
|
|
3524
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3525
|
+
CArray *co;
|
|
3526
|
+
GetCArray(vout, co);
|
|
3527
|
+
double *op = (double *) co->ptr;
|
|
3528
|
+
ca_iter_state st;
|
|
3529
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3530
|
+
slab_axes, naxes, 0);
|
|
3531
|
+
if ( rc != CA_ITER_OK ) {
|
|
3532
|
+
rb_raise(rb_eRuntimeError,
|
|
3533
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3534
|
+
}
|
|
3535
|
+
char *p;
|
|
3536
|
+
boolean8_t *m;
|
|
3537
|
+
ca_size_t out_i = 0;
|
|
3538
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3539
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3540
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3541
|
+
cmplx128_t sum = 0;
|
|
3542
|
+
ca_size_t masked_cnt = 0;
|
|
3543
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx128_t, cmplx128_t, st, p, m, sum, 0, __stddev_cmplx128_P1EXPR, masked_cnt);
|
|
3544
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3545
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3546
|
+
if ( __trigger ) {
|
|
3547
|
+
if ( ! op_mask ) {
|
|
3548
|
+
ca_create_mask(co);
|
|
3549
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3550
|
+
}
|
|
3551
|
+
op_mask[out_i] = 1;
|
|
3552
|
+
op[out_i++] = (double) 0.0;
|
|
3553
|
+
} else {
|
|
3554
|
+
cmplx128_t mean = sum / (cmplx128_t)(double) n_valid;
|
|
3555
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3556
|
+
double M2 = 0.0;
|
|
3557
|
+
ca_size_t __unused_mc = 0;
|
|
3558
|
+
CA_SLAB_REDUCE_SUM8_EX(cmplx128_t, double, st, p, m, M2, 0.0, __stddev_cmplx128_P2EXPR, __unused_mc);
|
|
3559
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
ca_iter_state_finish(&st);
|
|
3563
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3564
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3565
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3566
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3567
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3568
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3569
|
+
return rb_float_new(op[0]);
|
|
3570
|
+
}
|
|
3571
|
+
return vout;
|
|
3572
|
+
}
|
|
3573
|
+
#undef __stddev_cmplx128_P1EXPR
|
|
3574
|
+
#undef __stddev_cmplx128_P2EXPR
|
|
3575
|
+
|
|
3576
|
+
#define __stddev_bool_P1EXPR(__x) ((double)(__x))
|
|
3577
|
+
#define __stddev_bool_P2EXPR(__x) (((double)(__x) - mean) * ((double)(__x) - mean))
|
|
3578
|
+
static VALUE
|
|
3579
|
+
stddev_ki_native_bool (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3580
|
+
{
|
|
3581
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3582
|
+
CArray *co;
|
|
3583
|
+
GetCArray(vout, co);
|
|
3584
|
+
double *op = (double *) co->ptr;
|
|
3585
|
+
ca_iter_state st;
|
|
3586
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3587
|
+
slab_axes, naxes, 0);
|
|
3588
|
+
if ( rc != CA_ITER_OK ) {
|
|
3589
|
+
rb_raise(rb_eRuntimeError,
|
|
3590
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3591
|
+
}
|
|
3592
|
+
char *p;
|
|
3593
|
+
boolean8_t *m;
|
|
3594
|
+
ca_size_t out_i = 0;
|
|
3595
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3596
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3597
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3598
|
+
double sum = 0.0;
|
|
3599
|
+
ca_size_t masked_cnt = 0;
|
|
3600
|
+
CA_SLAB_REDUCE_SUM8_EX(boolean8_t, double, st, p, m, sum, 0.0, __stddev_bool_P1EXPR, masked_cnt);
|
|
3601
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3602
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3603
|
+
if ( __trigger ) {
|
|
3604
|
+
if ( ! op_mask ) {
|
|
3605
|
+
ca_create_mask(co);
|
|
3606
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3607
|
+
}
|
|
3608
|
+
op_mask[out_i] = 1;
|
|
3609
|
+
op[out_i++] = (double) 0.0;
|
|
3610
|
+
} else {
|
|
3611
|
+
double mean = sum / (double) n_valid;
|
|
3612
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3613
|
+
double M2 = 0.0;
|
|
3614
|
+
ca_size_t __unused_mc = 0;
|
|
3615
|
+
CA_SLAB_REDUCE_SUM8_EX(boolean8_t, double, st, p, m, M2, 0.0, __stddev_bool_P2EXPR, __unused_mc);
|
|
3616
|
+
op[out_i++] = (double)(ca_sqrt_clamp(M2 / (double)(n_valid - 1)));
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
ca_iter_state_finish(&st);
|
|
3620
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3621
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3622
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3623
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3624
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3625
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3626
|
+
return rb_float_new(op[0]);
|
|
3627
|
+
}
|
|
3628
|
+
return vout;
|
|
3629
|
+
}
|
|
3630
|
+
#undef __stddev_bool_P1EXPR
|
|
3631
|
+
#undef __stddev_bool_P2EXPR
|
|
3632
|
+
|
|
3633
|
+
/* The object lane calls Ruby for every cell, so a walk can raise part
|
|
3634
|
+
way. Its states live in the caller's frame, and ca_iter_ensure
|
|
3635
|
+
finishes them however the body leaves. */
|
|
3636
|
+
typedef struct {
|
|
3637
|
+
ca_iter_state states[1];
|
|
3638
|
+
VALUE self;
|
|
3639
|
+
CArray *ca;
|
|
3640
|
+
int8_t *slab_axes;
|
|
3641
|
+
int8_t naxes;
|
|
3642
|
+
int keep_axis;
|
|
3643
|
+
ca_size_t min_count;
|
|
3644
|
+
} stddev_ki_native_object_frame;
|
|
3645
|
+
|
|
3646
|
+
static VALUE
|
|
3647
|
+
stddev_ki_native_object_body (VALUE arg)
|
|
3648
|
+
{
|
|
3649
|
+
stddev_ki_native_object_frame *fr = (stddev_ki_native_object_frame *) arg;
|
|
3650
|
+
VALUE self = fr->self;
|
|
3651
|
+
(void) self;
|
|
3652
|
+
CArray *ca = fr->ca;
|
|
3653
|
+
(void) ca;
|
|
3654
|
+
int8_t *slab_axes = fr->slab_axes;
|
|
3655
|
+
(void) slab_axes;
|
|
3656
|
+
int8_t naxes = fr->naxes;
|
|
3657
|
+
(void) naxes;
|
|
3658
|
+
int keep_axis = fr->keep_axis;
|
|
3659
|
+
(void) keep_axis;
|
|
3660
|
+
ca_size_t min_count = fr->min_count;
|
|
3661
|
+
(void) min_count;
|
|
3662
|
+
#define st (fr->states[0])
|
|
3663
|
+
VALUE vout = rb_ca_new_reduced(self, slab_axes, naxes, CA_FLOAT64, keep_axis);
|
|
3664
|
+
CArray *co;
|
|
3665
|
+
GetCArray(vout, co);
|
|
3666
|
+
double *op = (double *) co->ptr;
|
|
3667
|
+
int rc = ca_iter_state_init_l2(&st, ca, CA_SLAB_AXES,
|
|
3668
|
+
slab_axes, naxes, 0);
|
|
3669
|
+
if ( rc != CA_ITER_OK ) {
|
|
3670
|
+
rb_raise(rb_eRuntimeError,
|
|
3671
|
+
"%s: kernel_iterator init failed rc=%d", ca_calling_method_name(), rc);
|
|
3672
|
+
}
|
|
3673
|
+
char *p;
|
|
3674
|
+
boolean8_t *m;
|
|
3675
|
+
ca_size_t out_i = 0;
|
|
3676
|
+
boolean8_t *op_mask = NULL; /* lazily allocated on first UNDEF */
|
|
3677
|
+
while ( ca_iter_state_next_slab_axes(&st, &p, &m) ) {
|
|
3678
|
+
/* Pass 1: sum = Σx (+ masked_cnt) */
|
|
3679
|
+
VALUE sum = INT2FIX(0);
|
|
3680
|
+
ca_size_t masked_cnt = 0;
|
|
3681
|
+
CA_SLAB_REDUCE_T_EX(VALUE, st, p, m, sum, INT2FIX(0), sum = rb_funcall(sum, rb_intern("+"), 1, v), masked_cnt);
|
|
3682
|
+
ca_size_t n_valid = st.slab_elements - masked_cnt;
|
|
3683
|
+
int __trigger = ca_too_few_present(n_valid, min_count, 2);
|
|
3684
|
+
if ( __trigger ) {
|
|
3685
|
+
if ( ! op_mask ) {
|
|
3686
|
+
ca_create_mask(co);
|
|
3687
|
+
op_mask = (boolean8_t *) co->mask->ptr;
|
|
3688
|
+
}
|
|
3689
|
+
op_mask[out_i] = 1;
|
|
3690
|
+
op[out_i++] = (double) 0.0;
|
|
3691
|
+
} else {
|
|
3692
|
+
VALUE mean = rb_funcall(sum, rb_intern("/"), 1, LONG2NUM(n_valid));
|
|
3693
|
+
/* Pass 2: M2 = Σ (x - mean)² */
|
|
3694
|
+
VALUE M2 = INT2FIX(0);
|
|
3695
|
+
ca_size_t __unused_mc = 0;
|
|
3696
|
+
CA_SLAB_REDUCE_T_EX(VALUE, st, p, m, M2, INT2FIX(0), VALUE __d = rb_funcall(v, rb_intern("-"), 1, mean);
|
|
3697
|
+
M2 = rb_funcall(M2, rb_intern("+"), 1, rb_funcall(__d, rb_intern("*"), 1, __d)), __unused_mc);
|
|
3698
|
+
op[out_i++] = (double)(ca_sqrt_clamp(NUM2DBL(rb_funcall(M2, rb_intern("/"), 1, LONG2NUM(n_valid - 1)))));
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
ca_iter_state_finish(&st);
|
|
3702
|
+
/* Full-reduction scalar shortcut: naxes == ca->ndim and no
|
|
3703
|
+
keep_axis means the output is a 1-element CArray; unwrap it to
|
|
3704
|
+
the ruby scalar (matches the standard reduce emit path lines
|
|
3705
|
+
1811-1817). Full reduction with all-masked returns CA_UNDEF. */
|
|
3706
|
+
if ( naxes == ca->ndim && !keep_axis ) {
|
|
3707
|
+
if ( op_mask && op_mask[0] ) return CA_UNDEF;
|
|
3708
|
+
return rb_float_new(op[0]);
|
|
3709
|
+
}
|
|
3710
|
+
return vout;
|
|
3711
|
+
#undef st
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3714
|
+
static VALUE
|
|
3715
|
+
stddev_ki_native_object (VALUE self, CArray *ca, int8_t *slab_axes, int8_t naxes, int keep_axis, ca_size_t min_count)
|
|
3716
|
+
{
|
|
3717
|
+
stddev_ki_native_object_frame fr;
|
|
3718
|
+
fr.self = self;
|
|
3719
|
+
fr.ca = ca;
|
|
3720
|
+
fr.slab_axes = slab_axes;
|
|
3721
|
+
fr.naxes = naxes;
|
|
3722
|
+
fr.keep_axis = keep_axis;
|
|
3723
|
+
fr.min_count = min_count;
|
|
3724
|
+
return ca_iter_ensure(1, fr.states, stddev_ki_native_object_body, (VALUE) &fr);
|
|
3725
|
+
}
|
|
3726
|
+
|
|
3727
|
+
|
|
3728
|
+
VALUE
|
|
3729
|
+
rb_ca_stddev_ki (int argc, VALUE *argv, VALUE self)
|
|
3730
|
+
{
|
|
3731
|
+
CArray *src;
|
|
3732
|
+
GetCArray(self, src);
|
|
3733
|
+
volatile VALUE ropt = rb_pop_options(&argc, &argv);
|
|
3734
|
+
volatile VALUE raxis = Qnil, rkeep_axis = Qnil, rmin_count = Qnil, rfval = Qnil;
|
|
3735
|
+
rb_scan_options(ropt, "axis,keep_axis,min_count,fill_value", &raxis, &rkeep_axis, &rmin_count, &rfval);
|
|
3736
|
+
int keep_axis = RTEST(rkeep_axis);
|
|
3737
|
+
int8_t slab_axes[CA_RANK_MAX];
|
|
3738
|
+
int8_t naxes = rb_ca_parse_reduce_axes_kw(raxis, src, slab_axes);
|
|
3739
|
+
if ( ca_is_lazy_view(src) ) {
|
|
3740
|
+
volatile VALUE evaluated = ca_lazy_evaluated(self);
|
|
3741
|
+
if ( ! NIL_P(evaluated) ) {
|
|
3742
|
+
self = evaluated;
|
|
3743
|
+
GetCArray(self, src);
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
ca_size_t min_count = ca_min_count_arg(rmin_count, NULL);
|
|
3747
|
+
if ( rfval == CA_UNDEF ) rfval = Qnil;
|
|
3748
|
+
int fill_whole = 0;
|
|
3749
|
+
if ( ! NIL_P(rfval) && naxes == src->ndim && ! keep_axis ) {
|
|
3750
|
+
keep_axis = 1;
|
|
3751
|
+
fill_whole = 1;
|
|
3752
|
+
}
|
|
3753
|
+
VALUE result;
|
|
3754
|
+
if ( argc > 0 ) {
|
|
3755
|
+
rb_raise(rb_eArgError, "%s: positional axis arguments are no longer accepted (got %d); use the axis: keyword, e.g. a.%s(axis: 0) or a.%s(axis: [0, 1])", ca_calling_method_name(), argc, ca_calling_method_name(), ca_calling_method_name());
|
|
3756
|
+
}
|
|
3757
|
+
switch ( src->data_type ) {
|
|
3758
|
+
case CA_INT8: {
|
|
3759
|
+
result = stddev_ki_native_i8(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3760
|
+
RB_GC_GUARD(self);
|
|
3761
|
+
break;
|
|
3762
|
+
}
|
|
3763
|
+
case CA_UINT8: {
|
|
3764
|
+
result = stddev_ki_native_u8(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3765
|
+
RB_GC_GUARD(self);
|
|
3766
|
+
break;
|
|
3767
|
+
}
|
|
3768
|
+
case CA_INT16: {
|
|
3769
|
+
result = stddev_ki_native_i16(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3770
|
+
RB_GC_GUARD(self);
|
|
3771
|
+
break;
|
|
3772
|
+
}
|
|
3773
|
+
case CA_UINT16: {
|
|
3774
|
+
result = stddev_ki_native_u16(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3775
|
+
RB_GC_GUARD(self);
|
|
3776
|
+
break;
|
|
3777
|
+
}
|
|
3778
|
+
case CA_INT32: {
|
|
3779
|
+
result = stddev_ki_native_i32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3780
|
+
RB_GC_GUARD(self);
|
|
3781
|
+
break;
|
|
3782
|
+
}
|
|
3783
|
+
case CA_UINT32: {
|
|
3784
|
+
result = stddev_ki_native_u32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3785
|
+
RB_GC_GUARD(self);
|
|
3786
|
+
break;
|
|
3787
|
+
}
|
|
3788
|
+
case CA_INT64: {
|
|
3789
|
+
result = stddev_ki_native_i64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3790
|
+
RB_GC_GUARD(self);
|
|
3791
|
+
break;
|
|
3792
|
+
}
|
|
3793
|
+
case CA_UINT64: {
|
|
3794
|
+
result = stddev_ki_native_u64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3795
|
+
RB_GC_GUARD(self);
|
|
3796
|
+
break;
|
|
3797
|
+
}
|
|
3798
|
+
case CA_FLOAT32: {
|
|
3799
|
+
result = stddev_ki_native_f32(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3800
|
+
RB_GC_GUARD(self);
|
|
3801
|
+
break;
|
|
3802
|
+
}
|
|
3803
|
+
case CA_FLOAT64: {
|
|
3804
|
+
result = stddev_ki_native_f64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3805
|
+
RB_GC_GUARD(self);
|
|
3806
|
+
break;
|
|
3807
|
+
}
|
|
3808
|
+
case CA_CMPLX64: {
|
|
3809
|
+
result = stddev_ki_native_cmplx64(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3810
|
+
RB_GC_GUARD(self);
|
|
3811
|
+
break;
|
|
3812
|
+
}
|
|
3813
|
+
case CA_CMPLX128: {
|
|
3814
|
+
result = stddev_ki_native_cmplx128(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3815
|
+
RB_GC_GUARD(self);
|
|
3816
|
+
break;
|
|
3817
|
+
}
|
|
3818
|
+
case CA_BOOLEAN: {
|
|
3819
|
+
result = stddev_ki_native_bool(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3820
|
+
RB_GC_GUARD(self);
|
|
3821
|
+
break;
|
|
3822
|
+
}
|
|
3823
|
+
case CA_OBJECT: {
|
|
3824
|
+
result = stddev_ki_native_object(self, src, slab_axes, naxes, keep_axis, min_count);
|
|
3825
|
+
RB_GC_GUARD(self);
|
|
3826
|
+
break;
|
|
3827
|
+
}
|
|
3828
|
+
default:
|
|
3829
|
+
ca_face_refuse_numeric(self, ca_calling_method_name(), rb_eCADataTypeError);
|
|
3830
|
+
rb_raise(rb_eCADataTypeError, "%s: source data_type :%s not supported (expected one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, cmplx64, cmplx128, boolean, object)", ca_calling_method_name(), ca_type_name[src->data_type]);
|
|
3831
|
+
}
|
|
3832
|
+
if ( ! NIL_P(rfval) ) {
|
|
3833
|
+
result = ca_reduce_fill(result, rfval, fill_whole);
|
|
3834
|
+
}
|
|
3835
|
+
return result;
|
|
3836
|
+
}
|
|
3837
|
+
|
|
3838
|
+
void
|
|
3839
|
+
Init_carray_kernels_reduce_variance (void)
|
|
3840
|
+
{
|
|
3841
|
+
/* Phase E rewire: legacy 'variancep' now dispatches via variancep_ki */
|
|
3842
|
+
rb_define_method(rb_cCArray, "variancep", rb_ca_variancep_ki, -1);
|
|
3843
|
+
/* Phase E rewire: legacy 'variance' now dispatches via variance_ki */
|
|
3844
|
+
rb_define_method(rb_cCArray, "variance", rb_ca_variance_ki, -1);
|
|
3845
|
+
/* Phase E rewire: legacy 'stddevp' now dispatches via stddevp_ki */
|
|
3846
|
+
rb_define_method(rb_cCArray, "stddevp", rb_ca_stddevp_ki, -1);
|
|
3847
|
+
/* Phase E rewire: legacy 'stddev' now dispatches via stddev_ki */
|
|
3848
|
+
rb_define_method(rb_cCArray, "stddev", rb_ca_stddev_ki, -1);
|
|
3849
|
+
}
|