0

I have a ndarray 2-dimensional array and I'm trying to multiply a row with the same number, as stated here.

It works fine when I'm working with a 2-dimensional array of f64 but I want it to be generic to all kinds of floats. That's why I'm using Float from num-traits. However, it doesn't compile anymore.

use ndarray::{Array2, Axis};

fn gauss(pivot: [usize; 2], table: &mut Array2<f64>) {
    for i in 0..table.len_of(Axis(0)) {
        if i != pivot[0] {
            let pivot_n = table[pivot];
            let make_zero = table[[i, pivot[1]]];
            let mut row_pivot = table.row(pivot[0]).to_owned();
            let mut row_make_zero = table.row_mut(i);
            row_make_zero *= pivot_n;
            row_pivot *= -make_zero;
            row_make_zero += &row_pivot;
        }
    }
}

use num::Float;
use std::ops::MulAssign;

fn gauss_2<T: Float + MulAssign>(pivot: [usize; 2], table: &mut Array2<T>) {
    for i in 0..table.len_of(Axis(0)) {
        if i != pivot[0] {
            let pivot_n = table[pivot];
            let make_zero = table[[i, pivot[1]]];
            let mut row_pivot = table.row(pivot[0]).to_owned();
            let mut row_make_zero = table.row_mut(i);
            row_make_zero *= pivot_n;
            row_pivot *= -make_zero;
            row_make_zero += &row_pivot;
        }
    }
}

The error it shows is:

error[E0308]: mismatched types
  --> src/lib.rs:27:30
   |
27 |             row_make_zero *= pivot_n;
   |                              ^^^^^^^ expected reference, found type parameter
   |
   = note: expected type `&ndarray::ArrayBase<_, _>`
              found type `T`

error[E0308]: mismatched types
  --> src/lib.rs:28:26
   |
28 |             row_pivot *= -make_zero;
   |                          ^^^^^^^^^^ expected reference, found type parameter
   |
   = note: expected type `&ndarray::ArrayBase<_, _>`
              found type `T`

error[E0368]: binary assignment operation `+=` cannot be applied to type `ndarray::ArrayBase<ndarray::ViewRepr<&mut T>, ndarray::dimension::dim::Dim<[usize; 1]>>`
  --> src/lib.rs:29:13
   |
29 |             row_make_zero += &row_pivot;
   |             -------------^^^^^^^^^^^^^^
   |             |
   |             cannot use `+=` on type `ndarray::ArrayBase<ndarray::ViewRepr<&mut T>, ndarray::dimension::dim::Dim<[usize; 1]>>`
   |
   = note: an implementation of `std::ops::AddAssign` might be missing for `ndarray::ArrayBase<ndarray::ViewRepr<&mut T>, ndarray::dimension::dim::Dim<[usize; 1]>>`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • I believe your question is answered by the answers of [How do I require a generic type implement an operation like Add, Sub, Mul, or Div in a generic function?](https://stackoverflow.com/q/29184358/155423) and [“Expected type parameter” error in the constructor of a generic struct](https://stackoverflow.com/q/32551177/155423). If you disagree, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Apr 27 '19 at 17:02
  • @Shepmaster no, it was a different problem related to how to use ndarray properly – Adrián Arroyo Calle Apr 27 '19 at 17:26

1 Answers1

0

If you want T to be used in that kind of operation, you must require ndarray::ScalarOperand for T. This is the fixed code:

use ndarray::{Array2, ScalarOperand};
use num::Float;
use std::ops::{AddAssign, MulAssign};

fn gauss<T>(pivot: [usize; 2], table: &mut Array2<T>)
where
    T: Float + MulAssign + AddAssign + ScalarOperand,
{
    for i in 0..table.len_of(Axis(0)) {
        if i != pivot[0] {
            // Aplicar GAUSS a la fila
            let pivot_n = table[pivot];
            let make_zero = table[[i, pivot[1]]];
            // Multiplicar la fila de make_zero por pivot_n
            let mut row_pivot = table.row(pivot[0]).to_owned();
            let mut row_make_zero = table.row_mut(i);
            row_make_zero *= pivot_n;
            row_pivot *= -make_zero;
            row_make_zero += &row_pivot;
        }
    }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366