LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
statistics_selection.c
浏览该文件的文档.
1#include <float.h>
2#include <math.h>
3#include <stdlib.h>
4
5#include "memory_bridge.h"
6#include "lmmc/config.h"
7#include "lmmc/numeric.h"
8#include "lmmc/stats.h"
9
10#include "statistics_internal.h"
11
13static int lmmc_real_compare(const void* a, const void* b) {
14 lmmc_real_t va = *(const lmmc_real_t*)a;
15 lmmc_real_t vb = *(const lmmc_real_t*)b;
16 if (va < vb) { return -1; }
17 if (va > vb) { return 1; }
18 return 0;
19}
20
21
22static int lmmc_vec_values_are_finite(const lmmc_vec_t* x) {
23 return lmmc_real_range_is_finite(x->data, x->size);
24}
25
27 lmmc_real_t* sorted = NULL;
28 size_t n;
29
30 if (out == NULL) { return LMMC_STATUS_INVALID_ARGUMENT; }
31 if (x == NULL || x->data == NULL || x->size == 0) { return LMMC_STATUS_INVALID_ARGUMENT; }
32 if (!lmmc_vec_values_are_finite(x)) {
34 }
35
36 n = x->size;
37 sorted = (lmmc_real_t*)lmmc_memory_alloc_array(n, sizeof(lmmc_real_t));
38 if (sorted == NULL) { return LMMC_STATUS_ALLOCATION_FAILED; }
39
40 for (size_t i = 0; i < n; ++i) {
41 sorted[i] = x->data[i];
42 }
43 qsort(sorted, n, sizeof(lmmc_real_t), lmmc_real_compare);
44
45 if (n % 2 == 1) {
46 *out = sorted[n / 2];
47 } else {
48 *out = lmmc_interval_midpoint(
49 sorted[n / 2 - 1], sorted[n / 2]);
50 }
51
52 lmmc_memory_free(sorted);
53 return LMMC_STATUS_OK;
54}
55
57 lmmc_real_t* sorted = NULL;
58 size_t n;
59 double h, frac;
60 size_t lo, hi;
61
62 if (out == NULL) { return LMMC_STATUS_INVALID_ARGUMENT; }
63 if (x == NULL || x->data == NULL || x->size == 0) { return LMMC_STATUS_INVALID_ARGUMENT; }
64 if (!lmmc_is_finite(&p) || p < 0.0 || p > 1.0) {
66 }
67 if (!lmmc_vec_values_are_finite(x)) {
69 }
70
71 n = x->size;
72 sorted = (lmmc_real_t*)lmmc_memory_alloc_array(n, sizeof(lmmc_real_t));
73 if (sorted == NULL) { return LMMC_STATUS_ALLOCATION_FAILED; }
74
75 for (size_t i = 0; i < n; ++i) {
76 sorted[i] = x->data[i];
77 }
78 qsort(sorted, n, sizeof(lmmc_real_t), lmmc_real_compare);
79
81 h = p * (double)(n - 1);
82 lo = (size_t)h;
83 hi = lo + 1;
84 frac = h - (double)lo;
85
86 if (hi >= n) {
87 *out = sorted[n - 1];
88 } else {
89 *out = sorted[lo] * (1.0 - frac) + sorted[hi] * frac;
90 }
91
92 lmmc_memory_free(sorted);
93 return LMMC_STATUS_OK;
94}
95
96static void lmmc_histogram_bounds(
97 const lmmc_vec_t* x, lmmc_real_t* xmin, lmmc_real_t* xmax) {
98 size_t i;
99 (*xmin) = x->data[0];
100 (*xmax) = x->data[0];
101 for (i = 1; i < x->size; ++i) {
102 if (x->data[i] < (*xmin)) {
103 (*xmin) = x->data[i];
104 }
105 if (x->data[i] > (*xmax)) {
106 (*xmax) = x->data[i];
107 }
108 }
109
110 if ((*xmax) == (*xmin)) {
111 const lmmc_real_t value = (*xmin);
112 const lmmc_real_t lower = value - 0.5;
113 const lmmc_real_t upper = value + 0.5;
114 if (lower < value && upper > value &&
115 lmmc_is_finite(&lower) && lmmc_is_finite(&upper)) {
116 (*xmin) = lower;
117 (*xmax) = upper;
118 } else if (value > 0.0) {
119 (*xmin) = value * 0.5;
120 (*xmax) = value <= DBL_MAX / 1.5 ? value * 1.5 : value;
121 } else if (value < 0.0) {
122 (*xmin) = value >= -DBL_MAX / 1.5 ? value * 1.5 : value;
123 (*xmax) = value * 0.5;
124 } else {
125 (*xmin) = -0.5;
126 (*xmax) = 0.5;
127 }
128 }
129}
130
131static void lmmc_histogram_edges(
132 lmmc_real_t xmin, lmmc_real_t xmax, size_t nbins, lmmc_real_t* edges) {
133 size_t i;
134 edges[0] = xmin;
135 for (i = 1; i < nbins; ++i) {
136 const lmmc_real_t t =
137 (lmmc_real_t)i / (lmmc_real_t)nbins;
138 if ((xmin < 0.0 && xmax > 0.0) ||
139 (xmin > 0.0 && xmax < 0.0)) {
140 edges[i] = (1.0 - t) * xmin + t * xmax;
141 } else {
142 edges[i] = xmin + t * (xmax - xmin);
143 }
144 }
145 edges[nbins] = xmax;
146
147}
148
149static size_t lmmc_histogram_bin(
150 lmmc_real_t value, size_t nbins, lmmc_real_t xmin, lmmc_real_t xmax,
151 int crosses_zero, lmmc_real_t range_scale, lmmc_real_t scaled_min,
152 lmmc_real_t scaled_span) {
153 size_t bin;
154 if (value <= xmin) {
155 bin = 0;
156 } else if (value >= xmax) {
157 bin = nbins - 1;
158 } else {
159 lmmc_real_t position;
160 lmmc_real_t bin_position;
161 if (crosses_zero) {
162 position =
163 (value / range_scale - scaled_min) /
164 scaled_span;
165 } else {
166 position =
167 (value - xmin) / (xmax - xmin);
168 }
169 bin_position = position * (lmmc_real_t)nbins;
170 if (position >= 1.0 ||
171 bin_position >= (lmmc_real_t)(nbins - 1)) {
172 bin = nbins - 1;
173 } else if (position <= 0.0) {
174 bin = 0;
175 } else {
176 bin = (size_t)bin_position;
177 }
178 }
179 return bin;
180}
181
182lmmc_status_t lmmc_vec_histogram(const lmmc_vec_t* x, size_t nbins, lmmc_real_t* edges, size_t* counts) {
183 size_t n, i;
184 lmmc_real_t xmin, xmax, range_scale = 1.0;
185 lmmc_real_t scaled_min = 0.0, scaled_span = 0.0;
186 int crosses_zero;
187
188 if (x == NULL || x->data == NULL || x->size == 0) { return LMMC_STATUS_INVALID_ARGUMENT; }
189 if (nbins == 0 || edges == NULL || counts == NULL) { return LMMC_STATUS_INVALID_ARGUMENT; }
190 if (!lmmc_vec_values_are_finite(x)) {
192 }
193
194 n = x->size;
195
196 lmmc_histogram_bounds(x, &xmin, &xmax);
197 crosses_zero = xmin < 0.0 && xmax > 0.0;
198 if (crosses_zero) {
199 range_scale = fmax(-xmin, xmax);
200 scaled_min = xmin / range_scale;
201 scaled_span = xmax / range_scale - scaled_min;
202 }
203
204
205 lmmc_histogram_edges(xmin, xmax, nbins, edges);
206
207 for (i = 0; i < nbins; ++i) {
208 counts[i] = 0;
209 }
210
211 for (i = 0; i < n; ++i) {
212 const size_t bin = lmmc_histogram_bin(x->data[i], nbins, xmin, xmax,
213 crosses_zero, range_scale, scaled_min, scaled_span);
214 counts[bin]++;
215 }
216
217 return LMMC_STATUS_OK;
218}
LMMC binary real type and arithmetic spelling.
double lmmc_real_t
Public and internal LMMC real type.
lmmc_real_t * data
一维稠密向量。
void * lmmc_memory_alloc_array(size_t count, size_t element_size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
数值标量、特殊函数和 FFT 公共接口。
基础统计量与组合数学接口。
lmmc_status_t lmmc_vec_quantile(const lmmc_vec_t *x, lmmc_real_t p, lmmc_real_t *out)
计算向量的 p 分位数(线性插值法)。
lmmc_status_t lmmc_vec_histogram(const lmmc_vec_t *x, size_t nbins, lmmc_real_t *edges, size_t *counts)
计算向量的等宽直方图。
lmmc_status_t lmmc_vec_median(const lmmc_vec_t *x, lmmc_real_t *out)
计算向量中位数。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT