SDDSlib
Loading...
Searching...
No Matches
rowmedian.c
Go to the documentation of this file.
1/**
2 * @file rowmedian.c
3 * @brief Computes statistical measures such as median, percentiles, average, and middle values for arrays.
4 *
5 * This file contains functions to compute the median, specific percentiles, the average, and the middle value of
6 * datasets. It also includes functions to compute these statistics for specific rows in a 2D array. These
7 * functions return the index of the closest point to the computed statistic. Requires libsort.a routines.
8 *
9 * See also: median.c (doesn't require libsort.a, but doesn't return index).
10 *
11 * @copyright
12 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
13 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
14 *
15 * @license
16 * This file is distributed under the terms of the Software License Agreement
17 * found in the file LICENSE included with this distribution.
18 *
19 * @author M. Borland, C. Saunders, R. Soliday
20 */
21
22#include "mdb.h"
23
24/**
25 * @brief Finds the median value of an array of doubles and returns the index of the median.
26 *
27 * @param value Pointer to store the computed median value.
28 * @param x Pointer to the array of doubles.
29 * @param n Number of elements in the array.
30 * @return Returns the index of the median element on success, -1 on failure.
31 */
32long find_median(double *value, double *x, long n) {
33 static double **data = NULL;
34 static long last_n = 0;
35 long i;
36
37 if (n <= 0)
38 return (-1);
39 if (n > last_n) {
40 if (data)
41 free_zarray_2d((void **)data, last_n, 2);
42 data = (double **)zarray_2d(sizeof(**data), n, 2);
43 last_n = n;
44 }
45
46 for (i = 0; i < n; i++) {
47 data[i][0] = x[i];
48 data[i][1] = i;
49 }
50 set_up_row_sort(0, 2, sizeof(**data), double_cmpasc);
51 qsort((void *)data, n, sizeof(*data), row_compare);
52
53 *value = data[n / 2][0];
54 i = data[n / 2][1];
55
56 return (i);
57}
58
59/**
60 * @brief Finds a specific percentile of an array of doubles and returns the index of the percentile.
61 *
62 * @param value Pointer to store the computed percentile value.
63 * @param x Pointer to the array of doubles.
64 * @param n Number of elements in the array.
65 * @param percentile The desired percentile to compute (0-100).
66 * @return Returns the index of the percentile element on success, -1 on failure.
67 */
68long find_percentile(double *value, double *x, long n, double percentile) {
69 static double **data = NULL;
70 static long last_n = 0;
71 long i;
72
73 if (n <= 0)
74 return (-1);
75 if (percentile < 0 || percentile > 100)
76 return -1;
77 if (n > last_n) {
78 if (data)
79 free_zarray_2d((void **)data, last_n, 2);
80 data = (double **)zarray_2d(sizeof(**data), n, 2);
81 last_n = n;
82 }
83
84 for (i = 0; i < n; i++) {
85 data[i][0] = x[i];
86 data[i][1] = i;
87 }
88 set_up_row_sort(0, 2, sizeof(**data), double_cmpasc);
89 qsort((void *)data, n, sizeof(*data), row_compare);
90
91 *value = data[(long)((n - 1) * (percentile / 100.0))][0];
92 i = data[(long)((n - 1) * (percentile / 100.0))][1];
93
94 return (i);
95}
96
97/**
98 * @brief Finds the median value of a specific row in a 2D array of doubles and returns the index of the median.
99 *
100 * @param value Pointer to store the computed median value.
101 * @param x Pointer to the 2D array of doubles.
102 * @param index The row index for which the median is to be computed.
103 * @param n Number of elements in the row.
104 * @return Returns the index of the median element in the specified row on success, -1 on failure.
105 */
106long find_median_of_row(double *value, double **x, long index, long n) {
107 static double **data = NULL;
108 static long last_n = 0;
109 long i;
110
111 if (index < 0 && n <= 0)
112 return (-1);
113
114 if (n > last_n) {
115 if (data)
116 free_zarray_2d((void **)data, last_n, 2);
117 data = (double **)zarray_2d(sizeof(**data), n, 2);
118 last_n = n;
119 }
120
121 for (i = 0; i < n; i++) {
122 data[i][0] = x[i][index];
123 data[i][1] = i;
124 }
125 set_up_row_sort(0, 2, sizeof(**data), double_cmpasc);
126 qsort((void *)data, n, sizeof(*data), row_compare);
127
128 *value = data[n / 2][0];
129 i = data[n / 2][1];
130
131 return (i);
132}
133
134/**
135 * @brief Finds the average of an array of doubles and returns the index of the element closest to the average.
136 *
137 * @param value Pointer to store the computed average value.
138 * @param data Pointer to the array of doubles.
139 * @param n Number of elements in the array.
140 * @return Returns the index of the element closest to the average on success, -1 on failure.
141 */
142long find_average(double *value, double *data, long n) {
143 double sum, min_dist, dist;
144 long i, i_best;
145
146 if (n <= 0)
147 return (-1);
148
149 for (i = sum = 0; i < n; i++)
150 sum += data[i];
151 sum /= n;
152
153 min_dist = DBL_MAX;
154 i_best = -1;
155 for (i = 0; i < n; i++)
156 if ((dist = fabs(data[i] - sum)) < min_dist) {
157 min_dist = dist;
158 i_best = i;
159 }
160 *value = sum;
161 return (i_best);
162}
163
164/**
165 * @brief Finds the middle value between the minimum and maximum of an array of doubles and returns the index of the closest element.
166 *
167 * @param value Pointer to store the computed middle value.
168 * @param data Pointer to the array of doubles.
169 * @param n Number of elements in the array.
170 * @return Returns the index of the element closest to the middle value on success, -1 on failure.
171 */
172long find_middle(double *value, double *data, long n) {
173 double target, min_dist, dist, min, max;
174 long i, i_best;
175
176 if (n <= 0)
177 return (-1);
178
179 if (!find_min_max(&min, &max, data, n))
180 return (-1);
181 target = (min + max) / 2;
182
183 min_dist = DBL_MAX;
184 i_best = -1;
185 for (i = 0; i < n; i++)
186 if ((dist = fabs(data[i] - target)) < min_dist) {
187 min_dist = dist;
188 i_best = i;
189 }
190 *value = target;
191 return (i_best);
192}
void ** zarray_2d(uint64_t size, uint64_t n1, uint64_t n2)
Allocates a 2D array with specified dimensions.
Definition array.c:93
int free_zarray_2d(void **array, uint64_t n1, uint64_t n2)
Frees a 2D array and its associated memory.
Definition array.c:155
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
Definition findMinMax.c:33
long find_median(double *value, double *x, long n)
Finds the median value of an array of doubles and returns the index of the median.
Definition rowmedian.c:32
long find_average(double *value, double *data, long n)
Finds the average of an array of doubles and returns the index of the element closest to the average.
Definition rowmedian.c:142
long find_percentile(double *value, double *x, long n, double percentile)
Finds a specific percentile of an array of doubles and returns the index of the percentile.
Definition rowmedian.c:68
long find_middle(double *value, double *data, long n)
Finds the middle value between the minimum and maximum of an array of doubles and returns the index o...
Definition rowmedian.c:172
long find_median_of_row(double *value, double **x, long index, long n)
Finds the median value of a specific row in a 2D array of doubles and returns the index of the median...
Definition rowmedian.c:106
void set_up_row_sort(int sort_by_column, size_t n_columns, size_t element_size, int(*compare)(const void *a, const void *b))
Set up parameters for row-based sorting.
int double_cmpasc(const void *a, const void *b)
Compare two doubles in ascending order.
int row_compare(const void *av, const void *bv)
Compare two rows based on the previously set sorting parameters.