The best way to iterate over sections of 2D arrays in Rust

て烟熏妆下的殇ゞ 提交于 2020-02-07 17:19:39

问题


I'm learning Rust by porting a small program that was written in C. It works with comparable performance to the C version. Still, I can't help but feeling my code could be better, hence this post.

The following code solves a matrix equation using Gaussian elimination, which requires iterating over portions of an array.

pub struct MatrixEquation {
    vec: Vec<f64>,
    mat: Vec<Vec<f64>>,
}

impl MatrixEquation {
    fn solve(&mut self) {
        let size = self.vec.len();
        // Transform matrix to upper triangular
        for row in 0..size {
            let mut rfabs = self.mat[row][row].abs();
            let mut pivot = row;

            for trow in row + 1..size {
                let tfabs = self.mat[trow][row].abs();
                if tfabs > rfabs {
                    pivot = trow;
                    rfabs = tfabs;
                }
            }

            if pivot != row {
                self.vec.swap(pivot, row);
                self.mat.swap(pivot, row);
            }

            if !self.mat[row][row].is_normal() {
                die!("Matrix is singular");
            }

            for elem in row + 1..size {
                if self.mat[elem][row] != 0.0 {
                    let scale = self.mat[elem][row] / self.mat[row][row];
                    for tcol in row..size {
                        self.mat[elem][tcol] -= self.mat[row][tcol] * scale;
                    }
                    self.vec[elem] -= self.vec[row] * scale;
                }
            }
        }

        for row in (0..size).rev() {
            self.vec[row] /= self.mat[row][row];
            let backsub = self.vec[row];
            for trow in 0..row {
                self.vec[trow] -= self.mat[trow][row] * backsub;
            }
        }
    }
}

My first concern is the back substitution loop at the end. I have to loop through the rows backwards. It seems like there would be a straight forward way to do this. Constructing a range and calling rev() seems to be an accepted way to do this, but it seems heavy handed. What is regarded as best practice for doing something like this?

My other concern is that I'm using numerical indices rather than iterators, and I don't want to do anything which forces the compiler to do bounds checking. I found the zip() method which could potentially be useful for what I'm trying to do, but since I am not starting at the beginning of the rows when I traverse them, I'd have to call skip() which I think is less efficient than numerically indexing into the middle of the row. If you were writing the elem loop in the program above, how would you do it?

来源:https://stackoverflow.com/questions/43293834/the-best-way-to-iterate-over-sections-of-2d-arrays-in-rust

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!