From bb57d61add2c956b57ea83b31f7011a83caa7c6a Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Tue, 19 Nov 2024 06:24:23 -0800 Subject: [PATCH] util: add util_linear_map This has been needed elsewhere but generally shortcuts could be taken mapping with ranges starting/ending with zero. This is a more general linear mapping utility to map values between any two ranges. --- src/util.c | 30 ++++++++++++++++++++++++++++++ src/util.h | 11 +++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/util.c b/src/util.c index a4a78fb6..a6ab9d85 100644 --- a/src/util.c +++ b/src/util.c @@ -312,6 +312,36 @@ bool util_ip_prefix_tohl(const char *ip, uint8_t *prefix_out, return true; } +/* + * Linearly maps @value (expected to be within range @a_start and @a_end) to + * a new value between @b_start and @b_end. + * + * Returns: false if + * @value is not between @a_start and @a_end + * @a_start/@a_end or @b_start/@b_end are equal. + */ +bool util_linear_map(double value, double a_start, double a_end, + double b_start, double b_end, double *mapped_value) +{ + /* Check value is within a's range */ + if (a_start < a_end) { + if (value < a_start || value > a_end) + return false; + } else if (a_start > a_end) { + if (value > a_start || value < a_end) + return false; + } else + return false; + + if (b_start == b_end) + return false; + + *mapped_value = b_start + (((b_end - b_start) / (a_end - a_start)) * + (value - a_start)); + + return true; +} + struct scan_freq_set { uint16_t channels_2ghz; struct l_uintset *channels_5ghz; diff --git a/src/util.h b/src/util.h index dafa446d..9f3f0a57 100644 --- a/src/util.h +++ b/src/util.h @@ -106,6 +106,17 @@ static inline bool util_ip_subnet_match(uint8_t prefix_len, ~((1u << (8 - (prefix_len % 8))) - 1)); } +/* + * Linearly maps (interpolates) 'value' from range 'a' to range 'b' + * + * Fails if: + * - value is not between a and b + * - a_start == a_end + * - b_start == b_end + */ +bool util_linear_map(double value, double a_start, double a_end, + double b_start, double b_end, double *mapped_value); + typedef void (*scan_freq_set_func_t)(uint32_t freq, void *userdata); struct scan_freq_set *scan_freq_set_new(void);