/// Calculates the rate of change across a vector of dB measurements by determining
/// the slope of the line of best fit using least squares regression. Return is technically
/// dB(i8)/t where t is the unit of time used in the vector. Returns error if integer overflows.
///
/// Note: This is the linear velocity (not the logarithmic velocity), but it is a useful
/// abstraction for monitoring real-world signal changes.
///
/// Intended to be used for RSSI Values, ranging from -128 to -1.
Calculates the rate of change across a vector of dB measurements by determining
the slope of the line of best fit using least squares regression. Return is technically
dB(i8)/t where t is the unit of time used in the vector. Returns error if integer overflows.

This is the linear velocity (not the logarithmic velocity), but it is a useful
abstraction for monitoring real-world signal changes.

Intended to be used for RSSI Values, ranging from -128 to -1.
Calculates the rate of change across a vector of dB measurements by determining the slope of the line of best fit using least squares regression . Return is technically dB ( i8 ) / t where t is the unit of time used in the vector . Returns error if integer overflows . This is the linear velocity ( not the logarithmic velocity ) but it is a useful abstraction for monitoring real - world signal changes . Intended to be used for RSSI Values ranging from - 128 to - 1 .
pub fn calculate_pseudodecibel_velocity(
    historical_pdb: Vec<PseudoDecibel>,
) -> Result<PseudoDecibel, Error> {
    let n = i32::try_from(historical_pdb.len()).expect("overflow");
    if n < 2 {
        return Err(format_err!("At least two data points required to calculate velocity"));
    }
    // Using i32 for the calculations, to allow more room for preventing overflows
    let mut sum_x: i32 = 0;
    let mut sum_y: i32 = 0;
    let mut sum_xy: i32 = 0;
    let mut sum_x2: i32 = 0;
    // Least squares regression summations, returning an error if there are any overflows
    for (i, y) in historical_pdb.iter().enumerate() {
        if *y >= 0 {
            return Err(format_err!(
                "Function is intended for RSSI values, which should be -128 < n < 0"
            ));
        }
        let x = i32::try_from(i).map_err(|_| format_err!("failed to convert index to i32"))?;
        sum_x = sum_x.checked_add(x).ok_or_else(|| format_err!("overflow of X summation"))?;
        sum_y =
            sum_y.checked_add(*y as i32).ok_or_else(|| format_err!("overflow of Y summation"))?;
        sum_xy = sum_xy
            .checked_add(x.checked_mul(*y as i32).ok_or_else(|| format_err!("overflow of X * Y"))?)
            .ok_or_else(|| format_err!("overflow of XY summation"))?;
        sum_x2 = sum_x2
            .checked_add(x.checked_mul(x).ok_or_else(|| format_err!("overflow of X**2"))?)
            .ok_or_else(|| format_err!("overflow of X2 summation"))?;
    }
    // Calculate velocity from summations, returning an error if there are any overflows. Note that
    // in practice, the try_from should never fail, since the input values are bound from 0 to -128.
    let velocity: i8 = i8::try_from(
        (n.checked_mul(sum_xy).ok_or_else(|| format_err!("overflow in n * sum_xy"))?
            - sum_x.checked_mul(sum_y).ok_or_else(|| format_err!("overflow in sum_x * sum_y"))?)
            / (n.checked_mul(sum_x2).ok_or_else(|| format_err!("overflow in n * sum_x2"))?
                - sum_x.checked_mul(sum_x).ok_or_else(|| format_err!("overflow in sum_x**2"))?),
    )
    .map_err(|_| format_err!("failed to convert final velocity to i8"))?;
    Ok(velocity)
}
pub fn calculate_pseudodecibel_velocity ( historical_pdb : Vec < PseudoDecibel > , ) -> Result < PseudoDecibel , Error > { let n = i32 :: try_from ( historical_pdb . len ( ) ) . expect ( " " ) ; if n < 2 { return Err ( format_err ! ( " " ) ) ; } // Using i32 for the calculations, to allow more room for preventing overflows let mut sum_x : i32 = 0 ; let mut sum_y : i32 = 0 ; let mut sum_xy : i32 = 0 ; let mut sum_x2 : i32 = 0 ; // Least squares regression summations, returning an error if there are any overflows for ( i , y ) in historical_pdb . iter ( ) . enumerate ( ) { if * y >= 0 { return Err ( format_err ! ( " " ) ) ; } let x = i32 :: try_from ( i ) . map_err ( | _ | format_err ! ( " " ) ) ? ; sum_x = sum_x . checked_add ( x ) . ok_or_else ( | | format_err ! ( " " ) ) ? ; sum_y = sum_y . checked_add ( * y as i32 ) . ok_or_else ( | | format_err ! ( " " ) ) ? ; sum_xy = sum_xy . checked_add ( x . checked_mul ( * y as i32 ) . ok_or_else ( | | format_err ! ( " " ) ) ? ) . ok_or_else ( | | format_err ! ( " " ) ) ? ; sum_x2 = sum_x2 . checked_add ( x . checked_mul ( x ) . ok_or_else ( | | format_err ! ( " " ) ) ? ) . ok_or_else ( | | format_err ! ( " " ) ) ? ; } // Calculate velocity from summations, returning an error if there are any overflows. Note that // in practice, the try_from should never fail, since the input values are bound from 0 to -128. let velocity : i8 = i8 :: try_from ( ( n . checked_mul ( sum_xy ) . ok_or_else ( | | format_err ! ( " " ) ) ? - sum_x . checked_mul ( sum_y ) . ok_or_else ( | | format_err ! ( " " ) ) ? ) / ( n . checked_mul ( sum_x2 ) . ok_or_else ( | | format_err ! ( " " ) ) ? - sum_x . checked_mul ( sum_x ) . ok_or_else ( | | format_err ! ( " " ) ) ? ) , ) . map_err ( | _ | format_err ! ( " " ) ) ? ; Ok ( velocity ) }
Calculates the rate of change across a vector of dB measurements by determining
the slope of the line of best fit using least squares regression.
Calculates the rate of change across a vector of dB measurements by determining the slope of the line of best fit using least squares regression .
historical_pdb
Vec<PseudoDecibel>