§ Coverage
1/*2 * sc_vote.c -- implementation. Blocks are tagged with the low-level3 * requirement they satisfy; see requirements/sc_vote.md.4 *5 * The cluster scan is O(n^2) over at most SC_VOTE_MAX_INPUTS channels, with6 * both loop variables bounded by the compile-time array size *and* the7 * validated channel count, so every index is provably in range.8 */9#include "sc_vote.h"1011/* LLR-VOTE-9: |a - b| <= tol, computed in 64-bit so no int32_t pair can12 * overflow the subtraction. */13268static bool within(int32_t a, int32_t b, int32_t tolerance)14{15268 int64_t diff = (int64_t)a - (int64_t)b;1617268 if (diff < 0)condition outcomes covered 2/218 {1966 diff = -diff;20 }2122268 return (diff <= (int64_t)tolerance);23}242512sc_status_t sc_vote_config_valid(const sc_vote_config_t *cfg)26{27 sc_status_t status;282912 if (cfg == NULL)condition outcomes covered 2/230 {311 status = SC_ERR_NULL; /* LLR-VOTE-1 */32 }3311 else if ((cfg->count < 2) || (cfg->count > SC_VOTE_MAX_INPUTS))condition outcomes covered 4/434 {352 status = SC_ERR_PARAM; /* LLR-VOTE-2 */36 }379 else if ((cfg->agree == 0u) || (cfg->agree > cfg->count))condition outcomes covered 4/438 {392 status = SC_ERR_PARAM; /* LLR-VOTE-3 */40 }417 else if (cfg->tolerance < 0)condition outcomes covered 2/242 {431 status = SC_ERR_PARAM; /* LLR-VOTE-4 */44 }45 else46 {476 status = SC_OK; /* LLR-VOTE-5 */48 }495012 return status;51}525317sc_status_t sc_vote_evaluate(const sc_vote_config_t *cfg,54 const int32_t *inputs, uint8_t n,55 sc_vote_result_t *out)56{57 sc_status_t status;585917 if ((cfg == NULL) || (inputs == NULL) || (out == NULL))condition outcomes covered 6/660 {613 status = SC_ERR_NULL; /* LLR-VOTE-6 */62 }6314 else if (n != cfg->count)condition outcomes covered 2/264 {652 status = SC_ERR_PARAM; /* LLR-VOTE-7 */66 }67 else68 {6912 uint8_t sizes[SC_VOTE_MAX_INPUTS] = { 0u };7012 uint8_t winner = 0u;7112 uint8_t mask = 0u;72 uint8_t i;73 uint8_t j;747558 for (i = 0u; (i < SC_VOTE_MAX_INPUTS) && (i < n); i++) /* LLR-VOTE-8 */condition outcomes covered 4/476 {7746 uint8_t cluster = 0u;78268 for (j = 0u; (j < SC_VOTE_MAX_INPUTS) && (j < n); j++)condition outcomes covered 4/479 {80222 if (within(inputs[i], inputs[j], cfg->tolerance))condition outcomes covered 2/281 {82134 cluster = (uint8_t)(cluster + 1u);83 }84 }8546 sizes[i] = cluster;868746 if (sizes[i] > sizes[winner]) /* LLR-VOTE-10 */condition outcomes covered 2/288 {892 winner = i;90 }91 }929312 out->value = inputs[winner]; /* LLR-VOTE-11 */9412 out->agreeing = sizes[winner];959658 for (i = 0u; (i < SC_VOTE_MAX_INPUTS) && (i < n); i++) /* LLR-VOTE-13 */condition outcomes covered 4/497 {9846 if (!within(inputs[i], out->value, cfg->tolerance))condition outcomes covered 2/299 {10014 mask = (uint8_t)(mask | (uint8_t)(1u << i));101 }102 }10312 out->dissenting = mask;10410512 out->verdict = (out->agreeing >= cfg->agree) /* LLR-VOTE-12 */106 ? SC_VOTE_OK10712 : SC_VOTE_NO_CONSENSUS;10810912 status = SC_OK; /* LLR-VOTE-14 */110 }11111217 return status;113}