我通过移植一个用C编写的小程序来学习Rust。它的工作性能与C版本相当。尽管如此,我仍然无法帮助,但感觉我的代码可能更好,因此这篇文章。
以下代码使用高斯消元法求解矩阵方程,这需要迭代数组的部分。
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;
}
}
}
}
我的第一个问题是最后的替代循环。我必须向后循环行。似乎有一种直接的方式来做到这一点。构造一个范围并调用rev()似乎是一种可以接受的方式,但它似乎很重要。做这样的事情被视为最佳做法?
我的另一个担心是我使用数字索引而不是迭代器,我不想做任何迫使编译器进行边界检查的事情。我找到了zip()方法,它可能对我尝试做的事情很有用,但由于我在遍历它时没有从行的开头开始,所以我必须调用skip( )我认为效率低于数字索引到行的中间。如果你在上面的程序中编写elem循环,你会怎么做?
答案 0 :(得分:0)
您的问题和代码表明您的工作处于错误的抽象层次。要编写专注于手头问题而不会迷失在内存表示细节中的优雅代码,您应该将其基于提供适当抽象的包。
经常需要密集的N维数组,因此您可以选择实现它们的多个包 - 例如,rust-ndarray
提供以下功能:
这些正是您认为代码中缺少的内容。