I have a struct Vec3<T>
, 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: mismatched types: expected _
, found T
(expected floating-point variable, found type parameter)
Type of 1.0
is _
while type of (*self % *self).sqrt()
is T
. And it seems it can't divide a _ by a T.
I tried various casting for 1.0 :
*self * ((1.0 as T) / (*self % *self).sqrt())
error: non-scalar cast: _
as T
*self * (1.0.div((*self % *self).sqrt()))
error: mismatched types: expected &_
, found T
(expected &-ptr, found type parameter)
What is the sleekest way to implement this method ?
Edit 1: As requested, here is my full 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 have used Num
instead of Float
to be able to have integer vectors, but since it's deprecated, I think the better option is to use macro to duplicate code for all types. Here I duplicated Not
for f32
and f64
Literals can only be of primitive types. You can't cast a literal to some generic type.
For constants like 1.0
you can use methods like Float::one()
, so your specific example could 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
bound because it is deprecated and in this case it is entirely superseded by Float
)
To convert arbitrary values to instances of some specific Float
type you can use NumCast::from()
method:
let x: T = num::NumCast::from(3.14f64);
BTW, you may find this accepted RFC interesting.
Update
It is likely that you won't be able to implement Float
for your structure because it has a lot of methods specific to bare floats, like mantissa size. I guess you will have to add methods like one()
and zero()
and probably casts from numbers yourself. Then you will be able to write
impl<T: num::Float> Not<Vec3<T>> for Vec3<T> {
fn not(&self) -> Vec3<T> {
*self * (Vec3::one() / (*self % *self).sqrt())
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With