# Implement left operator for generic struct

**URL:** <https://users.rust-lang.org/t/implement-left-operator-for-generic-struct/53590>\
**Category:** help\
**Created:** [January 2, 2021, 7:36pm UTC](https://users.rust-lang.org/t/implement-left-operator-for-generic-struct/53590 "2021-01-02T19:36:18Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![kalin](https://avatars.discourse-cdn.com/v4/letter/k/a9a28c/32.png) [@kalin](https://users.rust-lang.org/u/kalin)\
**Post date:** [January 2, 2021, 7:36pm UTC](https://users.rust-lang.org/t/implement-left-operator-for-generic-struct/53590/1 "2021-01-02T19:36:18Z")

</div>

I want to do some 3d graphics and for that purpose want to implement vector3d  
I want this vector3d to be generic over the underlying type like f32, f64 and so on

This is what I do to have left multiplication operator with f32.  
This is actually not what I need. I want the left part is the be any type compatible with float

```rust
use num::Float;
use std::ops::{Add, Sub, Mul, Div};

pub struct Vector3d<T = f32>
where T: Float + std::ops::Sub<Output = T> + std::ops::Add<Output = T> + std::ops::Mul<Output = T> + std::ops::Div<Output = T>
{
    x : T,
    y : T,
    z : T,
}

impl Mul<Vector3d<f32>> for f32 {
    type Output = Vector3d<f32>;
    fn mul(self, rhs: Self::Output) -> Self::Output {
        Self::Output {x : rhs.x * self, y : rhs.y * self, z : rhs.z * self}
    }
}

```

also im curious how I can give this alias "Float + std::ops::Sub\<Output = T\> + std::ops::Add\<Output = T\> + std::ops::Mul\<Output = T\> + std::ops::Div\<Output = T\>  
{"

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [January 2, 2021, 10:11pm UTC](https://users.rust-lang.org/t/implement-left-operator-for-generic-struct/53590/2 "2021-01-02T22:11:29Z")

</div>

I think this is unfortunately impossible. Someone could go through the effort of implementing `Float` for their own type, e.g.

```rust
use std::num::FpCategory;
use std::ops::*;
use num::{One, Zero, Num, Float, NumCast, ToPrimitive};

#[derive(Clone, Copy, PartialOrd, PartialEq)]
struct MyFloat(f32);

impl One for MyFloat {
    fn one() -> Self { Self(1.0) }
}

impl Zero for MyFloat {
    fn zero() -> Self { Self(0.0) }
    fn is_zero(&self) -> bool { self.0.is_zero() }
    
}

impl Add for MyFloat {
    type Output = Self;
    fn add(self, other: Self) -> Self { Self(self.0 + other.0) }
}

impl Sub for MyFloat {
    type Output = Self;
    fn sub(self, other: Self) -> Self { Self(self.0 - other.0) }
}

/*
impl Mul for MyFloat {
    type Output = Self;
    fn mul(self, other: Self) -> Self { Self(self.0 * other.0) }
}
*/

impl Rem for MyFloat {
    type Output = Self;
    fn rem(self, other: Self) -> Self { Self(self.0 % other.0) }
}

impl Div for MyFloat {
    type Output = Self;
    fn div(self, other: Self) -> Self { Self(self.0 / other.0) }
}

impl Num for MyFloat {
    type FromStrRadixErr = <f32 as Num>::FromStrRadixErr;
    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
        Ok(Self(f32::from_str_radix(str, radix)?))
    }
}

impl Neg for MyFloat {
    type Output = Self;
    fn neg(self) -> Self { Self(-self.0) }
}

impl Float for MyFloat {
    fn nan() -> Self { Self(f32::nan()) }
    fn infinity() -> Self { Self(f32::infinity()) }
    fn neg_infinity() -> Self { Self(f32::neg_infinity()) }
    fn neg_zero() -> Self { Self(f32::neg_zero()) }
    fn min_value() -> Self { Self(f32::min_value()) }
    fn min_positive_value() -> Self { Self(f32::min_positive_value()) }
    fn max_value() -> Self { Self(f32::max_value()) }
    fn is_nan(self) -> bool { self.0.is_nan() }
    fn is_infinite(self) -> bool { self.0.is_infinite() }
    fn is_finite(self) -> bool { self.0.is_finite() }
    fn is_normal(self) -> bool { self.0.is_normal() }
    fn classify(self) -> FpCategory { self.0.classify() }
    fn floor(self) -> Self { Self(self.0.floor()) }
    fn ceil(self) -> Self { Self(self.0.ceil()) }
    fn round(self) -> Self { Self(self.0.round()) }
    fn trunc(self) -> Self { Self(self.0.trunc()) }
    fn fract(self) -> Self { Self(self.0.fract()) }
    fn abs(self) -> Self { Self(self.0.abs()) }
    fn signum(self) -> Self { Self(self.0.signum()) }
    fn is_sign_positive(self) -> bool { self.0.is_sign_positive() }
    fn is_sign_negative(self) -> bool { self.0.is_sign_negative() }
    fn mul_add(self, a: Self, b: Self) -> Self { Self(self.0.mul_add(a.0, b.0)) }
    fn recip(self) -> Self { Self(self.0.recip()) }
    fn powi(self, n: i32) -> Self { Self(self.0.powi(n)) }
    fn powf(self, n: Self) -> Self { Self(self.0.powf(n.0)) }
    fn sqrt(self) -> Self { Self(self.0.sqrt()) }
    fn exp(self) -> Self { Self(self.0.exp()) }
    fn exp2(self) -> Self { Self(self.0.exp2()) }
    fn ln(self) -> Self { Self(self.0.ln()) }
    fn log(self, base: Self) -> Self { Self(self.0.log(base.0)) }
    fn log2(self) -> Self { Self(self.0.log2()) }
    fn log10(self) -> Self { Self(self.0.log10()) }
    fn max(self, other: Self) -> Self { Self(self.0.max(other.0)) }
    fn min(self, other: Self) -> Self { Self(self.0.min(other.0)) }
    fn abs_sub(self, other: Self) -> Self { Self(Float::abs_sub(self.0, other.0)) }
    fn cbrt(self) -> Self { Self(self.0.cbrt()) }
    fn hypot(self, other: Self) -> Self { Self(self.0.hypot(other.0)) }
    fn sin(self) -> Self { Self(self.0.sin()) }
    fn cos(self) -> Self { Self(self.0.cos()) }
    fn tan(self) -> Self { Self(self.0.tan()) }
    fn asin(self) -> Self { Self(self.0.asin()) }
    fn acos(self) -> Self { Self(self.0.acos()) }
    fn atan(self) -> Self { Self(self.0.atan()) }
    fn atan2(self, other: Self) -> Self { Self(self.0.atan2(other.0)) }
    fn sin_cos(self) -> (Self, Self) { let (s, c) = self.0.sin_cos(); (Self(s), Self(c)) }
    fn exp_m1(self) -> Self { Self(self.0.exp_m1()) }
    fn ln_1p(self) -> Self { Self(self.0.ln_1p()) }
    fn sinh(self) -> Self { Self(self.0.sinh()) }
    fn cosh(self) -> Self { Self(self.0.cosh()) }
    fn tanh(self) -> Self { Self(self.0.tanh()) }
    fn asinh(self) -> Self { Self(self.0.asinh()) }
    fn acosh(self) -> Self { Self(self.0.acosh()) }
    fn atanh(self) -> Self { Self(self.0.atanh()) }
    fn integer_decode(self) -> (u64, i16, i8) { self.0.integer_decode() }
}

impl NumCast for MyFloat {
    fn from<T: ToPrimitive>(x: T) -> Option<Self> { Some(Self(<f32 as NumCast>::from(x)?)) }
}

impl ToPrimitive for MyFloat {
    fn to_i64(&self) -> Option<i64> { self.0.to_i64() }
    fn to_u64(&self) -> Option<u64> { self.0.to_u64() }
    fn to_isize(&self) -> Option<isize> { self.0.to_isize() }
    fn to_i8(&self) -> Option<i8> { self.0.to_i8() }
    fn to_i16(&self) -> Option<i16> { self.0.to_i16() }
    fn to_i32(&self) -> Option<i32> { self.0.to_i32() }
    fn to_i128(&self) -> Option<i128> { self.0.to_i128() }
    fn to_usize(&self) -> Option<usize> { self.0.to_usize() }
    fn to_u8(&self) -> Option<u8> { self.0.to_u8() }
    fn to_u16(&self) -> Option<u16> { self.0.to_u16() }
    fn to_u32(&self) -> Option<u32> { self.0.to_u32() }
    fn to_u128(&self) -> Option<u128> { self.0.to_u128() }
    fn to_f32(&self) -> Option<f32> { self.0.to_f32() }
    fn to_f64(&self) -> Option<f64> { self.0.to_f64() }
}

```

but then add a generic implementation like this

```rust
impl<T> Mul<T> for MyFloat {
    type Output = MyFloat;
    fn mul(self, _other: T) -> MyFloat {
        self
    }
}

```

This is the reasoning behind why you can’t write a

```rust
impl<T: Float> Mul<Vector3d<T>> for T {
    type Output = Vector3d<T>;
    fn mul(self, rhs: Self::Output) -> Self::Output {
        Self::Output {x : rhs.x * self, y : rhs.y * self, z : rhs.z * self}
    }
}

```

(by the way, note that you don’t need to add those `Sub`, `Add`, `Mul`, and `Div` bounds to the `Float` bound since they are included in the `Num` supertrait of `Float`)

Rust solves the possible conflicts from such an implementation `Mul<Vector3d<T>> for T`, as demonstrated above, by requiring, well, as the error message will explain:

```rust
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Vector3d<T>`)
  --> src/lib.rs:13:6
   |
13 | impl<T: Float> Mul<Vector3d<T>> for T {
   | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Vector3d<T>`)
   |
   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last

error: aborting due to previous error

```

or simply speaking: there is an arbitrary requirement that some plain variable `T` can only be the right operand of `Mul` but not the left. This way only one of the two conflicting implementations

```rust
impl<T: Float> Mul<Vector3d<T>> for T

```

and

```rust
impl<T> Mul<T> for MyFloat

```

are allowed.

So what _can_ you do? Implement generic multiplication from the right:

```rust
impl<T: Float> Mul<T> for Vector3d<T> {
    type Output = Vector3d<T>;
    fn mul(self, rhs: T) -> Self::Output {
        Self::Output {x : self.x * rhs, y : self.y * rhs, z : self.z * rhs}
    }
}

```

and also add a manual list of implementations of multiplication from the left, so that at least `f32` and `f64` are supporting `scalar * vector` notation:

```rust
macro_rules! left_multiplication {
    ($($T:ty),*) => {
        $(
            impl Mul<Vector3d<$T>> for $T {
                type Output = Vector3d<$T>;
                fn mul(self, rhs: Self::Output) -> Self::Output {
                    Self::Output {x : rhs.x * self, y : rhs.y * self, z : rhs.z * self}
                }
            }
        )*
    }
}

left_multiplication!{
    f32, f64
}

```

Also note that this is basically the approach taken in e.g. the [`nalgebra`](https://docs.rs/nalgebra) crate, see right multiplication [here](https://docs.rs/nalgebra/0.24.0/nalgebra/base/struct.Matrix.html#impl-Mul%3CN%3E), and left multiplication starting [here](https://docs.rs/nalgebra/0.24.0/nalgebra/base/struct.Matrix.html#impl-Mul%3C%26%27b%20Matrix%3Cf32%2C%20R%2C%20C%2C%20S%3E%3E).

---

<div class="post-metadata">

**Author:** ![kalin](https://avatars.discourse-cdn.com/v4/letter/k/a9a28c/32.png) [@kalin](https://users.rust-lang.org/u/kalin)\
**Post date:** [January 3, 2021, 11:55am UTC](https://users.rust-lang.org/t/implement-left-operator-for-generic-struct/53590/3 "2021-01-03T11:55:11Z")

</div>

Thanks for your answer. It is quite unfortunate but it is what it is..  
However how I can combine multiple traits in single bound. I expect to have something like type alias that allow me to not repeat my self

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [January 3, 2021, 12:35pm UTC](https://users.rust-lang.org/t/implement-left-operator-for-generic-struct/53590/4 "2021-01-03T12:35:40Z")

</div>

That can be done by defining a new trait with supertraits and a generic impl.

```rust
trait HashAndEq: Hash + Eq {}
impl<T: ?Sized> HashAndEq for T where T: Hash + Eq {}

```

([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9122a281d6b5daaf29ca1a53c7f150fe))

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [April 3, 2021, 12:35pm UTC](https://users.rust-lang.org/t/implement-left-operator-for-generic-struct/53590/5 "2021-04-03T12:35:49Z")

</div>

Closed on April 3, 2021, 12:35pm UTC

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
