genericsrustcomplex-numbers

Convert an array of complex numbers to a generic type container in Rust


I'm implementing a mathematical vector in Rust with a generic type K that should be used for f32 and Complex<f32>.

However, for some reason, the implementation seems to support only f32 type.

This is the code from the vector.rs file:

pub use core::fmt;
pub use core::ops::Neg;

pub use num::complex::Complex;
pub use num::Num;
pub use num::Zero;

impl<K> Vector<K>
where Vector<K>: std::fmt::Display, Matrix<K>: std::fmt::Display,
K: Copy + Clone + num::Num + num::Float + std::ops::AddAssign
+ std::ops::SubAssign + std::ops::MulAssign + std::fmt::Display
+ std::ops::Neg<Output = K> {
    pub fn new() -> Self {
        Vector {
            values: Vec::new(),
            rows: 0
        }
    }
    
    pub fn from(arr: &[K]) -> Self {
        Vector {
            values: arr.to_vec(),
            rows: arr.len()
        }
    }

    pub fn from_vec(vec: Vec<K>) -> Self {
        Vector {
            values: vec.clone(),
            rows: vec.len()
        }
    }

    pub fn print(&self) {
        println!("{}", self);
    }

    pub fn add(&mut self, other: Vector<K>) {
        self.vectors_have_equal_length(other.clone());
        for (a, b) in self.values.iter_mut().zip(other.values.iter()) {
            *a += b.clone();
        }
    }

    pub fn sub(&mut self, other: Vector<K>) {
        self.vectors_have_equal_length(other.clone());
        for (a, b) in self.values.iter_mut().zip(other.values.iter()) {
            *a -= b.clone();
        }
    }

    pub fn scl(&mut self, scalar: K) {
        for el in self.values.iter_mut() {
            *el *= scalar.clone();
        }
    }
}

The main.rs file:

fn main() {
    let _ = panic::catch_unwind(|| {
        let complex_numbers = [
            Complex::new(1.0, 1.0),
            Complex::new(1.0, -1.0)
        ];

        let mut vec: Vec<Complex<f32>> = complex_numbers.to_vec();

        let mut t = Vector::from_vec(vec);

        println!("{}", t.norm());
    });
 }

The error message states that the compiler expects a vec based on the Vector::from_vec() function I previously showed:

error[E0308]: mismatched types
  --> src/main.rs:68:28
   |
68 |         let t = Vector::from_vec(vec);
   |                 ---------------- ^^^ expected `Vec<f32>`, found `Vec<Complex<f32>>`
   |                 |
   |                 arguments to this function are incorrect
   |
   = note: expected struct `Vec<f32>`
              found struct `Vec<Complex<f32>>`
note: associated function defined here
  --> src/linear_algebra/vector.rs:79:9
   |
79 |     pub fn from_vec(vec: Vec<K>) -> Self {
   |            ^^^^^^^^ -----------


Solution

  • linear_algebra.rs:

    pub use core::fmt;
    pub use core::ops::Neg;
    
    pub use num::complex::Complex;
    pub use num::Num;
    pub use num::Zero;
    
    #[derive(Debug, PartialEq, Clone)]
    pub struct Vector<K> {
        values: Vec<K>,
        rows: usize
    }
    
    impl<K> Vector<K>
    where Vector<K>: std::fmt::Display,
    K: Copy + Clone + num::Num + std::ops::AddAssign
    + std::ops::SubAssign + std::ops::MulAssign + std::fmt::Display
    + std::ops::Neg<Output = K> {
        pub fn new() -> Self {
            Vector {
                values: Vec::new(),
                rows: 0
            }
        }
        
        pub fn from(arr: &[K]) -> Self {
            Vector {
                values: arr.to_vec(),
                rows: arr.len()
            }
        }
    
        pub fn from_vec(vec: Vec<K>) -> Self {
            Vector {
                values: vec.clone(),
                rows: vec.len()
            }
        }
    
        pub fn print(&self) {
            println!("{}", self);
        }
    }
    
    impl std::ops::Mul<Vector<f32>> for f32 {
        type Output = Vector<f32>;
    
        fn mul(self, _rhs: Vector<f32>) -> Vector<f32> {
            let mut a: Vector<f32> = Vector::new();
            for el in _rhs.values.iter() {
                a.values.push(*el * self);
                a.rows += 1;
            }
            a
        }
    }
    
    impl fmt::Display for Vector<f32> {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            for n in self.values.iter() {
                write!(fmt, "[")?;
                write!(fmt, "{}", (n * 100.).round() / 100.)?;
                write!(fmt, "]")?;
                write!(fmt, "\n")?;
            }
            println!("The vector has {} rows.", self.rows);
            Ok(())
        }
    }
    
    impl fmt::Display for Vector<Complex<f32>> {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            for n in self.values.iter() {
                write!(fmt, "[")?;
                write!(fmt, "{}", n)?;
                write!(fmt, "]")?;
                write!(fmt, "\n")?;
            }
            println!("The vector has {} rows.", self.rows);
            Ok(())
        }
    }
    
    impl std::ops::Mul<Vector<Complex<f32>>> for Complex<f32> {
        type Output = Vector<Complex<f32>>;
    
        fn mul(self, _rhs: Vector<Complex<f32>>) -> Vector<Complex<f32>> {
            let mut a: Vector<Complex<f32>> = Vector::new();
            for el in _rhs.values.iter() {
                a.values.push(*el * self);
                a.rows += 1;
            }
            a
        }
    }
    
    impl Vector<Complex<f32>> {
        pub fn norm(&self) -> Complex<f32> {
            let mut sum = Complex::<f32>::zero();
            for el in self.values.iter() {
                sum += el.powf(2.);
            }
            return sum.powf(0.5);
        }
    }
    

    and main.rs:

    use std::panic;
    use crate::linear_algebra::Vector;
    use crate::linear_algebra::Complex;
    
    pub mod linear_algebra;
    
    fn main() {
        println!("\n\x1b[31;1;4mThe Norm\x1b[0m\n");
    
        let _ = panic::catch_unwind(|| {
            let complex_numbers = [
                Complex::new(1.0, 1.0),
                Complex::new(1.0, -1.0)
            ];
    
            let vec: Vec<Complex<f32>> = complex_numbers.to_vec();
    
            let mut t = Vector::from_vec(vec);
            t.print();
        });
    }
    

    The problem was the presence of num::float in linear_algebra.rs, since Complex does not implement the num::float trait.

    However, the error message appeared after I cut out half of the code.

    Edit: I have a file matrix.rs calling functions of the linear_algebra.rs file.

    And in matrix.rs I didn't add the line:

    use super::Complex;