Question about types and generics

āš“ Rust    šŸ“… 2026-01-15    šŸ‘¤ surdeus    šŸ‘ļø 1      

surdeus

Hello everyone on the forum,

Please excuse my limited English. I have some questions regarding types and generics in Rust.

Currently, my implementation is as follows. Suppose I want to create a fairly general Complex type ( I know that there is a well-designed library num_complex for Complex, I’m just using it to introduce this as a question.)and its from_polar method. I defined NumOps and FloatOps traits.

However, I feel that my implementation and type abstractions are somewhat lacking. I’m not exactly sure where the shortcomings are at my current level. Could anyone take a look and suggest better ways to implement this, or share some tips on abstraction techniques?

This is the code:

pub trait NumOps<Rhs = Self, Output = Self>:
    Add<Rhs, Output = Output>
    + Sub<Rhs, Output = Output>
    + Mul<Rhs, Output = Output>
    + Div<Rhs, Output = Output>
    + Rem<Rhs, Output = Output>
{
}

impl<T, Rhs, Output> NumOps<Rhs, Output> for T where
    T: Add<Rhs, Output = Output>
        + Sub<Rhs, Output = Output>
        + Mul<Rhs, Output = Output>
        + Div<Rhs, Output = Output>
        + Rem<Rhs, Output = Output>
{
}

pub trait NumCmp<Rhs = Self>: PartialEq<Rhs> + PartialOrd<Rhs> + Eq + Ord {}
impl<T> NumCmp for T where T: PartialEq + PartialOrd + Eq + Ord {}

pub trait FloatOps: Clone {
    fn sin(self) -> Self;
    fn cos(self) -> Self;
    fn tan(self) -> Self;
    fn sqrt(self) -> Self;
    fn ln(self) -> Self;
    fn exp(self) -> Self;
}

impl FloatOps for f32 {
    fn sin(self) -> Self { f32::sin(self) }
    fn cos(self) -> Self { f32::cos(self) }
    fn tan(self) -> Self { f32::tan(self) }
    fn sqrt(self) -> Self { f32::sqrt(self) }
    fn ln(self) -> Self { f32::ln(self) }
    fn exp(self) -> Self { f32::exp(self) }
}

impl FloatOps for f64 {
    fn sin(self) -> Self { f64::sin(self) }
    fn cos(self) -> Self { f64::cos(self) }
    fn tan(self) -> Self { f64::tan(self) }
    fn sqrt(self) -> Self { f64::sqrt(self) }
    fn ln(self) -> Self { f64::ln(self) }
    fn exp(self) -> Self { f64::exp(self) }
}

/// Complex
pub struct Complex<T> {
    /// Real
    pub re: T,
    /// Imaginary
    pub im: T,
}

impl<T: FloatOps + NumOps> Complex<T> {
    #[inline]
    /// Create a new `Complex` from polar coordinates
    pub fn from_polar(r: T, theta: T) -> Complex<T> {
        Complex { 
            re: r.clone() * theta.clone().cos(),
            im: r * theta.sin() 
        }
    }
}

8 posts - 4 participants

Read full topic

šŸ·ļø Rust_feed