Skip to main content

multiversx_sc/math/
weighted_average.rs

1use core::ops::{Add, Div, Mul, Sub};
2
3/// Computes the weighted average of two values.
4///
5/// Returns `(first_value * first_weight + second_value * second_weight) / (first_weight + second_weight)`.
6///
7/// # Panics
8///
9/// Panics on division by zero if both weights are zero.
10pub fn weighted_average<T>(first_value: T, first_weight: T, second_value: T, second_weight: T) -> T
11where
12    T: Add<Output = T> + Mul<Output = T> + Div<Output = T> + Clone,
13{
14    let weight_sum = first_weight.clone() + second_weight.clone();
15    let weighted_sum = first_value * first_weight + second_value * second_weight;
16    weighted_sum / weight_sum
17}
18
19/// Computes the weighted average of two values, rounded up (ceiling division).
20///
21/// Equivalent to [`weighted_average`], but rounds the result up instead of truncating:
22/// `(weighted_sum + weight_sum - 1) / weight_sum`.
23///
24/// # Panics
25///
26/// Panics on division by zero if both weights are zero.
27pub fn weighted_average_round_up<T>(
28    first_value: T,
29    first_weight: T,
30    second_value: T,
31    second_weight: T,
32) -> T
33where
34    T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T> + Clone + From<u32>,
35{
36    let weight_sum = first_weight.clone() + second_weight.clone();
37    let weighted_sum = first_value * first_weight + second_value * second_weight;
38    (weighted_sum + weight_sum.clone() - T::from(1u32)) / weight_sum
39}