Making my function more generic

Hi,
I want to implement a Numpy.polyfit() equivalent in Rust and deliver it as a library. Therefore I want to make it generic. The user should be able to pass different types like &[f32], &[f64], &[i32], &[i64].
Currently, my function supports only &[f64].

How can I make this function more generic?

extern crate nalgebra as na;

pub mod polyfit_rs {
    
    type PolyMatrix = na::MatrixMN<f64, na::Dynamic, na::Dynamic>;

    /// @param x_values The x-values
    /// @param y_values The y-values
    /// @param polynomial_degree The order of the polynomial. I. e. 2 for a parabola.
    /// @return Order of monomials increases with the vector index
    pub fn polyfit<'a>(x_values : &'a [f64], y_values : &'a [f64], polynomial_degree: usize) -> Vec<f64>
    {
        let number_of_columns = polynomial_degree + 1;
        let number_of_rows = x_values.len();
        let mut a = PolyMatrix::zeros(number_of_rows, number_of_columns);

        for row in 0..number_of_rows 
        {
            // First column is always 1
            a[(row, 0)] = 1.0;
            let x = x_values[row];
    
            for col in 1..number_of_columns
            {
                a[(row, col)] = x.powf(col as f64);
            }
        }

        let b = na::DVector::from_row_slice(y_values);

        let decomp = na::SVD::new(a, true, true);
        let x = decomp.solve(&b, 0.000000000000000001).unwrap();

        return x.data.into();
    }
}

I tried na::Scalar, but svd.solve() couldn’t handle it, because it expected &[f64].

Btw.: My lib can be found on Github and crates.io.

Thanks in advance!

Hi!

We can make it generic, but it won’t support integer types like i32 because they are not supported by SVD. In order to accept both f32 and f64 you can make the following modifications:

  • type PolyMatrix<T> = na::DMatrix<T>; Here the DMatrix is equivalent to writing MatrixMN<_, Dynamic, Dynamic>.
  • pub fn polyfit<'a, T: na::RealField>(x_values: &'a [T], y_values: &'a [T], polynomial_degree: usize) -> Vec<T> This adds the T scalar type as a type parameter.
  • Convert all constants to the type T by replacing 1.0 by T::one(), col as f64 by na::convert(col as f64) and 0.000000000000000001 by na::convert(0.000000000000000001).
1 Like

Thank you, very much!!! :slight_smile:
Do you think it makes sense to merge my implementation to nalgebra?
I have although to add more tests and I think my function should return Option<Vec<T>>.
What do you think a good value of epsilon of the SVD function could be?