Преобразование массива комплексных чисел в контейнер общего типа в Rust

Я реализую математический вектор в Rust с общим типом K, который следует использовать для f32 и Complex<f32>.

Однако по какой-то причине реализация поддерживает только тип f32.

Это код из файла Vector.rs:

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();
        }
    }
}

Файл main.rs:

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());
    });
 }

В сообщении об ошибке говорится, что компилятор ожидает vec на основе функции Vector::from_vec(), которую я ранее показывал:

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 {
   |            ^^^^^^^^ -----------

Ваш код неполный, и причиной могут быть отсутствующие части. Пожалуйста, предоставьте минимально воспроизводимый пример.

kmdreko 16.06.2024 19:52

Спасибо, не буду публиковать изображения сообщений об ошибках.

Fab_x 16.06.2024 20:37

Пожалуйста, также отредактируйте этот вопрос, включив ошибку в виде текста. В конце концов, мы не пытаемся ответить на этот вопрос только для вас, а пытаемся создать хранилище вопросов, которые будущие посетители смогут прочитать и извлечь из них уроки.

cafce25 16.06.2024 21:13

Примечание: нет абсолютно никакой причины клонировать вектор в from_vec.

Sebastian Redl 17.06.2024 10:38

@Sebastian Redl Он не компилируется без клонирования, потому что vec<K> не реализует признак копирования...

Fab_x 17.06.2024 11:17

Это потому, что вам все еще нужен исходный vec, чтобы получить его длину, чтобы вы могли сохранить его в другой переменной. Но вы можете либо просто заранее указать длину в локальном поле, либо просто полностью избавиться от этого поля, поскольку оно полностью избыточно и всегда совпадает с длиной внутреннего Vec.

Sebastian Redl 17.06.2024 14:14

@Себастьян Редл, я понимаю, что ты имеешь в виду, большое спасибо

Fab_x 19.06.2024 14:30
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Помимо встроенных типов, модуль типизации в Python предоставляет возможность определения общих типов, что позволяет вам определять типы, которые могут...
0
8
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

линейная_алгебра.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);
    }
}

и 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();
    });
}

Проблема заключалась в наличии num::float в файле Linear_algebra.rs, поскольку Complex не реализует черту num::float.

Однако сообщение об ошибке появилось после того, как я вырезал половину кода.

Обновлено: у меня есть файл matrix.rs, вызывающий функции файла Linear_algebra.rs.

А в matrix.rs я не добавил строчку:

use super::Complex;

Другие вопросы по теме