Несоответствие типов для std :: op trait "Not" - PullRequest
0 голосов
/ 28 октября 2019

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

error[E0271]: type mismatch resolving `<i32 as std::ops::Not>::Output == bool`                                                                                                                                                                                                                                                                                                                                                                                                           
   --> src/matrix.rs:223:15                                                                                                                                                                                                                                                                                                                                                                                                                                                              
    |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
90  | pub fn reduce<T>(mat: &mut Matrix<T>) -> Result<Matrix<T>, &'static str>                                                                                                                                                                                                                                                                                                                                                                                                     
    |        ------                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
...                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
97  |         + Not<Output = bool>                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    |               ------------- required by this bound in `matrix::reduce`                                                                                                                                                                                                                                                                                                                                                                                                             
...                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
223 |     let res = reduce(&mut mat).unwrap();                                                                                                                                                                                                                                                                                                                                                                                                                                           
    |               ^^^^^^ expected i32, found bool                                                                                                                                                                                                                                                                                                                                                                                                                                      

error: aborting due to previous error  

Это особенно сбивает с толку, потому что я не уверен, как иначе я бы реализовал черту Not и правильно ее работал. Когда тип вывода bool, он прекрасно компилируется, но кажется, что он лает во время выполнения.

Вот мой код:

/// Performs a reduction operation on a given matrix, giving the reduced row echelon form                                                                                                                                                                                                                                                                                                                                                                                                
pub fn reduce<T>(mat: &mut Matrix<T>) -> Result<Matrix<T>, &'static str>                                                                                                                                                                                                                                                                                                                                                                                                                 
where                                                                                                                                                                                                                         
    T: num_traits::Zero                                                                                                                                                                                                       
        + num_traits::One                                                                                                                                                                                                     
        + Mul<T, Output = T>                                                                                                                                                                                                  
        + Add<T, Output = T>                                                                                                                                                                                                  
        + Sub<T, Output = T>                                                                                                                                                                                                  
        + Not<Output = bool>                                                                                                                                                                                                  
        + Neg<Output = T>                                                                                                                                                                                                     
        + Div<T, Output = T>                                                                                                                                                                                                  
        + Copy,                                                                                                                                                                                                               
{                                                                                                                                                                                                                             
    let exchange = |matrix: &mut Matrix<T>, i: usize, j: usize| {                                                                                                                                                             
        matrix.data.swap(i, j);                                                                                                                                                                                               
    };                                                                                                                                                                                                                        

    let scale = |matrix: &mut Matrix<T>, row: usize, factor: T| {                                                                                                                                                             
        for i in 0..matrix.data[row].len() {                                                                                                                                                                                  
            matrix.data[row][i] = matrix.data[row][i] * factor;                                                                                                                                                               
        }                                                                                                                                                                                                                     
    };                                                                                                                                                                                                                        

    let row_replace = |matrix: &mut Matrix<T>, i: usize, j: usize, factor: T| {                                                                                                                                               
        for k in 0..matrix.data[j].len() {                                                                                                                                                                                    
            matrix.data[j][k] = matrix.data[j][k] + (matrix.data[i][k] * factor);                                                                                                                                             
        }                                                                                                                                                                                                                     
    };                                                                                                                                                                                                                        

    // Reduction steps                                                                                                                                                                                                        
    let n = mat.data.len();                                                                                                                                                                                                   

    for i in 0..n {                                                                                                                                                                                                           
        // Find a pivot point                                                                                                                                                                                                 
        for j in i..n {                                                                                                                                                                                                       
            if !mat.data[j][i] { // <------- Error Here *********                                                                                                                                                                                             
                if i != j {                                                                                                                                                                                                   
                    exchange(mat, i, j);                                                                                                                                                                                      
                    break;                                                                                                                                                                                                    
                }                                                                                                                                                                                                             
            }                                                                                                                                                                                                                 

            if j == n - 1 {                                                                                                                                                                                                   
                return Err("No pivot found")                                                                                                                                                                                  
            }                                                                                                                                                                                                                 
        }                                                                                                                                                                                                                     

        // Put zeros below diagonal                                                                                                                                                                                           
        for j in i + 1..n {                                                                                                                                                                                                   
            row_replace(mat, i, j, -mat.data[j][i] / mat.data[i][i]);                                                                                                                                                         
        }                                                                                                                                                                                                                     
    }                                                                                                                                                                                                                         

    // Back substitution (bottom up)                                                                                                                                                                                          
    for i in (0..n - 1).rev() {                                                                                                                                                                                               
        for j in 0..i {                                                                                                                                                                                                       
            row_replace(mat, i, j, -mat.data[j][i] / mat.data[i][i]);                                                                                                                                                         
        }                                                                                                                                                                                                                     
    }                                                                                                                                                                                                                         

    // Add 1's to the diagonal                                                                                                                                                                                                
    for i in 0..n {                                                                                                                                                                                                           
        scale(mat, i, T::one() / mat.data[i][i]);
    }

    Ok(mat.clone())
}

#[test]
fn it_row_reduces() {
    let mat = Matrix {
        data: vec![vec![2, 1, 4], vec![1, 2, 5]],
        nrows: 2,
        ncols: 3,
    };

    let comp = Matrix {
        data: vec![vec![1, 0, 1], vec![0, 1, 2]],
        nrows: 2,
        ncols: 3,
    };

    let res = reduce(&mut mat).unwrap();
    assert_eq!(res.data, comp.data);
}

Первоначально код выглядел следующим образом:

if mat.data[j][i] != T::zero() {                                                                                                                                                                                             
   if i != j {                                                                                                                                                                                                   
       exchange(mat, i, j);                                                                                                                                                                                      
       break;                                                                                                                                                                                                    
   }                                                                                                                                                                                                             
} 

Но, похоже, что даже с чертой Not, добавленной к сигнатуре функции, эта операция никогда не будет работать, выдавая следующую ошибку:

binary operation `!=` cannot be applied to type `T`: T 

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

1 Ответ

2 голосов
/ 28 октября 2019

В Rust ! служит как логическим НЕ, так и побитовым НЕ, в зависимости от типа аргумента. Он выполняет логическое НЕ, когда аргумент является bool, и побитовое НЕ, когда аргумент является целочисленным типом. Единственный встроенный тип, который реализует Not<Output = bool>, это bool.

. Вы должны придерживаться if mat.data[j][i] != T::zero() {. != обеспечивается чертой PartialEq. Вместо границы T: Not<Output = bool> вам понадобится T: PartialEq<T> или просто T: Eq.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...