type OryxResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
fn foo(x: &[&Vec<f64>], y: &[&Vec<f64>]) -> OryxResult<Vec<f64>> {
// n x m * m x p = n x p
let m = x.len(); // 2 // number of vecs
let n = x[0].len(); // 3 // vec length
let _m = y[0].len(); // 2 // vec length
let p = y.len(); // 1 // number of vecs
if x.len() != y[0].len() {
Err(format!("cross dimentional is invalid"))?
} else {
//let mut array: Vec<Vec<i32>> = vec![vec![Default::default(); p]; n];
let mut array: Vec<f64> = vec![Default::default(); n];
for i in 0..n { // 3;
for j in 0..m { // 2
for k in 0..p { // 1
// array[i][k] += x[j][i] * y[k][j];
array[i] += x[j][i] * y[k][j];
}
}
}
Ok(array)
}
}
That is called using example below:
fn main() {
let apple_pie = vec![1., 0., 0.];
let burger = vec![0., 1., 0.];
let chekin = vec![0., 0., 1.];
let food: [&Vec<f64>; 2] = [&apple_pie, &burger];
let all_food: [&Vec<f64>; 3] = [&apple_pie, &burger, &chekin];
let sunny = vec![1., 0.];
let rainy = vec![0., 1.];
let weather: [&Vec<f64>; 1] = [&rainy];
match foo(&food, &weather) {
Err(e) => println!("Error = {:?}", e),
Ok(r) => {
match all_food.iter().position(|&v| *v == r) {
None => println!("Not found"),
Some(i) => match i {
0 => println!("Apple Pie"),
1 => println!("Chekin"),
2 => println!("Burger"),
_ => println!("check again"),
}
}
}
} ;
}
Which is working fine.
I'm looking for making it an extension, something below, but I stucked:
use std::ops::Mul;
type OryxResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
impl Mul<Vec<f64>> Vec<f64> {
type Output = Self;
fn mul(self, rhs: Vec<f64>) -> OryxResult<Vec<f64>> {
...
}
}
This implementetion is prohibited by the orphan rules, since neither the trait nor the type is yours. In this cases, multiplication should be implemented for the custom wrapper.
Multiplication can (technically) be fallible, but this must be reflected in the associated type - type Output: OryxResult<Self>. However, AFAIK this is bad taste: operations which can result in error usually go into different functions (think f64::checked_mul and friends), and ordinary operations usually contain either a debug_assert! or an explicit panic! in the case of wrong inputs.
use std::ops::Mul;
#[derive(Debug, PartialEq)]
struct Layer { value: Vec<Vec<f64>> }
#[derive(Debug, PartialEq)]
struct Vector { value: Vec<Vec<f64>> }
impl Layer {
fn vecs_len(&self) -> &usize {
&self.value[0].len()
}
fn vecs_num(&self) -> &usize {
&self.value.len()
}
}
impl Vector {
fn vecs_len(&self) -> &usize {
&self.value[0].len()
}
fn vecs_num(&self) -> &usize {
&self.value.len()
}
}
// 3 x 2 * 2 x 1 = 3 x 1
impl Mul<Layer> for Vector {
type Output = OryxResult<Self>;
fn mul(self, rhs: Layer) -> Self::Output {
let m = *self.vecs_num(); // 2 // number of vecs
let n = *self.vecs_len(); // 3 // vec length
let _m = *rhs.vecs_len(); // 2 // vec length
let p = *rhs.vecs_num();
if self.vecs_num() != rhs.vecs_len() {
Err(format!("cross dimentional is invalid"))?
} else {
let mut array: Vector; // = vec![vec![Default::default(); p]; n];
//let mut array: Vec<f64> = vec![Default::default(); n];
for i in 0..n { // 3;
for j in 0..m { // 2
for k in 0..p { // 1
array[i][k] += slef[j][i] * rhs[k][j];
// array[i] += self[j][i] * rhs[k][j];
}
}
}
Ok(array)
}
}
}
But got the below errors:
error[E0425]: cannot find value `slef` in this scope
--> src\main.rs:49:40
|
49 | array[i][k] += slef[j][i] * rhs[k][j];
| ^^^^ not found in this scope
error[E0608]: cannot index into a value of type `Vector`
--> src\main.rs:49:25
|
49 | array[i][k] += slef[j][i] * rhs[k][j];
| ^^^^^^^^
error[E0608]: cannot index into a value of type `Layer`
--> src\main.rs:49:53
|
49 | array[i][k] += slef[j][i] * rhs[k][j];
| ^^^^^^
error: aborting due to 3 previous errors
You have a typo on that line - slef should be self.
Since you're now using a wrapper type, you can't directly index - you either need to do array.value[i][k] or implement Index/IndexMut for your wrappers.