sphor_accum.c (7389B)
1 /* Copyright (C) 2024-2026 Centre National de la Recherche Scientifique 2 * Copyright (C) 2024-2026 Clermont Auvergne INP 3 * Copyright (C) 2024-2026 INSA Lyon 4 * Copyright (C) 2024-2026 Institut Mines Télécom Albi-Carmaux 5 * Copyright (C) 2024-2026 Institut National Polytechnique de Toulouse 6 * Copyright (C) 2024-2026 |Méso|Star> (contact@meso-star.com) 7 * Copyright (C) 2024-2026 PhotonLyX (info@photonlyx.com) 8 * Copyright (C) 2024-2026 Université de Lorraine 9 * Copyright (C) 2024-2026 Université Paul Sabatier 10 * Copyright (C) 2024-2026 Université Toulouse - Jean Jaurès 11 * 12 * This program is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation, either version 3 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 24 25 #include "sphor_accum.h" 26 27 #include <math.h> 28 29 struct mem_allocator; 30 31 /******************************************************************************* 32 * Local functions 33 ******************************************************************************/ 34 extern LOCAL_SYM void 35 accum_init 36 (struct mem_allocator* allocator, 37 struct accum* accum) 38 { 39 ASSERT(NULL != allocator); 40 ASSERT(NULL != accum); 41 42 *accum = ACCUM_NULL; 43 str_init(allocator, &accum->observable); 44 str_init(allocator, &accum->sensor); 45 str_init(allocator, &accum->component); 46 } 47 48 extern LOCAL_SYM void 49 accum_release 50 (struct accum* accum) 51 { 52 ASSERT(NULL != accum); 53 54 str_release(&accum->observable); 55 str_release(&accum->sensor); 56 str_release(&accum->component); 57 } 58 59 extern LOCAL_SYM res_T 60 accum_copy 61 (struct accum* dst, 62 const struct accum* src) 63 { 64 res_T res = RES_OK; 65 66 ASSERT(NULL != dst); 67 ASSERT(NULL != src); 68 69 dst->sum = src->sum; 70 dst->sum2 = src->sum2; 71 dst->n_realizations = src->n_realizations; 72 res = str_copy(&dst->observable, &src->observable); 73 if (RES_OK != res) { return res; } 74 res = str_copy(&dst->sensor, &src->sensor); 75 if (RES_OK != res) { return res; } 76 res = str_copy(&dst->component, &src->component); 77 return res; 78 } 79 80 extern LOCAL_SYM res_T 81 accum_copy_and_release 82 (struct accum* dst, 83 struct accum* src) 84 { 85 res_T res = RES_OK; 86 87 ASSERT(NULL != dst); 88 ASSERT(NULL != src); 89 90 dst->sum = src->sum; 91 dst->sum2 = src->sum2; 92 dst->n_realizations = src->n_realizations; 93 res = str_copy_and_release(&dst->observable, &src->observable); 94 if (RES_OK != res) { return res; } 95 res = str_copy_and_release(&dst->sensor, &src->sensor); 96 if (RES_OK != res) { return res; } 97 res = str_copy_and_release(&dst->component, &src->component); 98 return res; 99 } 100 101 extern LOCAL_SYM res_T 102 register_accum 103 (struct mem_allocator* allocator, 104 char* observable, 105 char* sensor, 106 char* component, 107 struct darray_accum *accums) 108 { 109 struct accum accum = ACCUM_NULL; 110 res_T res = RES_OK; 111 112 accum_init(allocator, &accum); 113 114 str_set(&accum.observable, observable); 115 str_set(&accum.sensor, sensor); 116 str_set(&accum.component, component); 117 118 res = darray_accum_push_back(accums, &accum); 119 if (res != RES_OK) { goto error; } 120 exit: 121 accum_release(&accum); 122 return res; 123 error: 124 goto exit; 125 } 126 127 extern LOCAL_SYM void 128 accum_compute_estim 129 (const struct accum* accum, 130 struct estim* estim) 131 { 132 double sum = 0; 133 double sum2 = 0; 134 double samples = 0; 135 double mean = 0; 136 double var = 0; 137 double std_err = 0; 138 139 ASSERT(NULL != accum); 140 ASSERT(NULL != estim); 141 142 samples = (double)accum->n_realizations; 143 sum = accum->sum; 144 sum2 = accum->sum2; 145 146 mean = sum / samples; 147 /* Compute the sample variance. This formula is equivalent to 148 * var = 1 / (n-1) sum(x_i - <x>)^2 */ 149 var = (sum2 - sum * sum / samples) / (samples - 1); 150 /* Clamp variance to 0 to guard against small negative values 151 * caused by floating-point rounding errors */ 152 var = var < 0 ? 0 : var; 153 std_err = sqrt (var / samples); 154 155 estim->mean = mean; 156 estim->var = var; 157 estim->std_err = std_err; 158 } 159 160 extern LOCAL_SYM void 161 write_accum_estim 162 (const struct accum* accum, 163 FILE* stream) 164 { 165 struct estim estim = ESTIM_NULL; 166 167 ASSERT(NULL != accum); 168 ASSERT(NULL != stream); 169 170 accum_compute_estim(accum, &estim); 171 172 if (0 != strcmp("\0", str_cget(&accum->component))){ 173 fprintf 174 (stream, "%s:%s:%s:%lf:%lf\n", 175 str_cget(&accum->observable), 176 str_cget(&accum->sensor), 177 str_cget(&accum->component), 178 estim.mean, estim.std_err); 179 } else if (0 != strcmp("\0", str_cget(&accum->sensor))){ 180 fprintf 181 (stream, "%s:%s:%lf:%lf\n", 182 str_cget(&accum->observable), 183 str_cget(&accum->sensor), 184 estim.mean, estim.std_err); 185 } else { 186 fprintf 187 (stream, "%s:%lf:%lf\n", 188 str_cget(&accum->observable), 189 estim.mean, estim.std_err); 190 } 191 } 192 193 extern LOCAL_SYM void 194 accum_add 195 (const struct accum* op0, 196 const struct accum* op1, 197 struct accum* result) 198 { 199 ASSERT(NULL != op0); 200 ASSERT(NULL != op1); 201 ASSERT(NULL != result); 202 203 result->sum = op0->sum + op1->sum; 204 result->sum2 = op0->sum2 + op1->sum2; 205 } 206 207 extern LOCAL_SYM void 208 accums_add 209 (const struct darray_accum* op0, 210 const struct darray_accum* op1, 211 struct darray_accum* result) 212 { 213 size_t i = 0; 214 size_t naccums = 0; 215 216 ASSERT(NULL != op0); 217 ASSERT(NULL != op1); 218 ASSERT(NULL != result); 219 220 naccums = darray_accum_size_get(result); 221 ASSERT(darray_accum_size_get(op0) == darray_accum_size_get(op1)); 222 ASSERT(darray_accum_size_get(op0) == naccums); 223 224 FOR_EACH(i, 0, naccums){ 225 accum_add(darray_accum_cdata_get(op0) + i, 226 darray_accum_cdata_get(op1) + i, 227 darray_accum_data_get(result) + i); 228 } 229 } 230 231 extern LOCAL_SYM void 232 sum_accums 233 (const struct darray_accum* accums, 234 struct accum* tot_accum) 235 { 236 size_t j = 0; 237 size_t accum_count = 0; 238 239 ASSERT(NULL != accums); 240 ASSERT(NULL != tot_accum); 241 242 accum_count = darray_accum_size_get(accums); 243 244 FOR_EACH(j, 0, accum_count) { 245 struct accum* accum = NULL; 246 accum = (struct accum*)darray_accum_cdata_get(accums) + j; 247 accum_add(tot_accum, accum, tot_accum); 248 } 249 } 250 251 extern LOCAL_SYM void 252 sum_accum_lists 253 (const struct darray_accum_list* accum_lists, 254 struct darray_accum* accums) 255 { 256 size_t list_len = 0; 257 size_t i; 258 259 ASSERT(NULL != accum_lists); 260 ASSERT(NULL != accums); 261 262 list_len = darray_accum_list_size_get(accum_lists); 263 264 FOR_EACH(i, 0, list_len) { 265 struct darray_accum* accums_i = NULL; 266 accums_i = (struct darray_accum*)darray_accum_list_cdata_get(accum_lists)+i; 267 accums_add(accums, accums_i, accums); 268 } 269 } 270 271 extern LOCAL_SYM void 272 update_accum 273 (const struct htable_accum2id* accum2id, 274 const struct accum_key* accum_key, 275 const double weight, 276 struct darray_accum* accums) 277 { 278 size_t* paccum_id = NULL; 279 struct accum* accum = NULL; 280 281 ASSERT(NULL != accum2id); 282 ASSERT(NULL != accums); 283 284 paccum_id = htable_accum2id_find 285 ((struct htable_accum2id *)accum2id, accum_key); 286 ASSERT(NULL != paccum_id); 287 288 accum = &darray_accum_data_get(accums)[*paccum_id]; 289 290 accum->sum += weight; 291 accum->sum2 += weight*weight; 292 }