When computing the dot-product of two nalgebra::Vector3
structs using specific values, I get the following behaviour (link to playground):
use nalgebra::{Point3, Vector3}; // 0.31.0
fn dot(v1: Vector3<f32>, v2: Vector3<f32>) -> f32 {
v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
}
fn main() {
println!("Run 1:");
let u = Vector3::new(1000., -1000., 0.);
let v = Vector3::new(-0.69294637441651, 0.720989108085632, 0.);
println!(
"self-written dot-product: \t{:.32}",
dot(u, v)
);
println!(
"nalgebra dot-product: \t\t{:.32}",
u.dot(&v)
);
println!("\nRun2:");
let u = Vector3::new(1000., -1000., 0.);
let v = Vector3::new(-0.69294637441651, 0.720989108085632, 0.);
println!(
"nalgebra dot-product: \t\t{:.32}",
u.dot(&v)
);
}
Output:
Run 1:
self-written dot-product: -1413.93554687500000000000000000000000
nalgebra dot-product: -1413.93554687500000000000000000000000
Run2:
nalgebra dot-product: -1413.93548250214189465623348951339722
I must be able to rely on the computation to always be the same. Any thoughts?
Related to my previous question, which I closed due to non-working examples previous question
As @aedm has mentioned in the comment, your dot()
function is the cause for this behavior. As a beginner rustacean it wasn't quite obvious to me how it is exactly a cause, so I put an explanation here.
When you define variables for the first time,
9| println!("Run 1:");
10| let u = Vector3::new(1000., -1000., 0.);
11| let v = Vector3::new(-0.69294637441651, 0.720989108085632, 0.);
Rust compiler doesn't know exact type of the values, it only understands that it's float
. And if there would be no extra information, the compiler would fall for f64
as a default float type in Rust.
When you call dot(u, v)
- you're letting the compiler know the exact types because you specified them on function declaration:
3| fn dot(v1: Vector3<f32>, v2: Vector3<f32>) -> f32 {
The compiler is now certain that the values of u
and v
are of a type f32
.
Then you're using .dot()
method, which can handle both f32
and f64
. The type of u
and v
is already defined as f32
, and the type of variables cannot be changed, but cause .dot()
can handle f32
, it makes the compiler happy. At this point you get:
Run 1:
-1413.93554687500000000000000000000000
-1413.93554687500000000000000000000000
After that you're defining new variables with the same names - again the compiler has no explicit information about the type of the variables. But this time there's no dot(u, v)
call, only .dot()
and the latter one doesn't require f32
, so the compiler goes for the default f64
. In the end you get:
Run2:
-1413.93548250214189465623348951339722