Splitting const into common in Rust

I have a Vec3<T> structure, how can I implement the following method?

 impl<T: num::Num + num::Float> Not<Vec3<T>> for Vec3<T> { fn not(&self) -> Vec3<T> { *self * (1.0 / (*self % *self).sqrt()) } } 

error: inappropriate types: expected _ , found T (expected floating point variable, type parameter found)

Type 1.0 is _ , and type (*self % *self).sqrt() is T And, it seems he cannot divide a by T.

I tried a different cast for 1.0:

 *self * ((1.0 as T) / (*self % *self).sqrt()) 

error: non-scalar cast: _ like T

 *self * (1.0.div((*self % *self).sqrt())) 

error: inconsistent types: expected &_ , found T (expected & -ptr, found type parameter)

What is the best way to implement this method?

Edit 1: As requested, here is my complete code:

 use std::num::Float; pub struct Vec3<T> { pub x: T, pub y: T, pub z: T, } impl<T> Vec3<T> { pub fn new(x: T, y: T, z: T) -> Vec3<T> { Vec3 { x: x, y: y, z: z } } } impl<T: Float> Add<T, Vec3<T>> for Vec3<T> { fn add(&self, rhs: &T) -> Vec3<T> { Vec3 { x: self.x + *rhs, y: self.y + *rhs, z: self.z + *rhs } } } impl<T: Float> Add<Vec3<T>, Vec3<T>> for Vec3<T> { fn add(&self, rhs: &Vec3<T>) -> Vec3<T> { Vec3 { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z } } } impl<T: Float> Mul<T, Vec3<T>> for Vec3<T> { fn mul(&self, rhs: &T) -> Vec3<T> { Vec3 { x: self.x * *rhs, y: self.y * *rhs, z: self.z * *rhs } } } // x % y : dot-product impl<T: Float> Rem<Vec3<T>, T> for Vec3<T> { fn rem(&self, rhs: &Vec3<T>) -> T { self.x + rhs.x * self.y + rhs.y * self.z + rhs.z } } // x ^ y : cross-product impl<T: Float> BitXor<Vec3<T>, Vec3<T>> for Vec3<T> { fn bitxor(&self, rhs: &Vec3<T>) -> Vec3<T> { Vec3 { x: self.y * rhs.z - self.z * rhs.y, y: self.z * rhs.x - self.x * rhs.z, z: self.x * rhs.y - self.y * rhs.x } } } // !x : Norm impl Not<Vec3<f32>> for Vec3<f32> { fn not(&self) -> Vec3<f32> { *self * (1.0f32 / (*self % *self).sqrt()) } } impl Not<Vec3<f64>> for Vec3<f64> { fn not(&self) -> Vec3<f64> { *self * (1.0f64 / (*self % *self).sqrt()) } } 

I would use Num instead of Float to have integer vectors, but since it is deprecated, I think the best option is to use a macro to duplicate code for all types. Here I duplicated Not for f32 and f64

+6
source share
1 answer

Literals can only be primitive types. You cannot superimpose a literal on some general type.

For constants like 1.0 you can use methods like Float::one() , so your concrete example can be rewritten as

 impl<T: num::Float> Not<Vec3<T>> for Vec3<T> { fn not(&self) -> Vec3<T> { *self * (num::Float::one() / (*self % *self).sqrt()) } } 

(note that I removed Num because it is deprecated, in which case it is completely replaced by Float )

To convert arbitrary values ​​to instances of a specific Float type, you can use the NumCast::from() method:

 let x: T = num::NumCast::from(3.14f64); 

By the way, you can find this accepted RFC .

Update

You probably won’t be able to implement Float for your structure, because it has many methods specific to bare floating numbers, such as the size of the mantissa. I think you will have to add methods such as one() and zero() , and perhaps lay out the numbers yourself. Then you can write

 impl<T: num::Float> Not<Vec3<T>> for Vec3<T> { fn not(&self) -> Vec3<T> { *self * (Vec3::one() / (*self % *self).sqrt()) } } 
+4
source

Source: https://habr.com/ru/post/979496/


All Articles