Listerone
Listerone

Reputation: 1621

How to unify functions taking f64 and Complex<f64>?

I have two functions:

fn f1(k1: f64, k2: f64, k3: f64) -> (f64, f64) {
    let a = k1 + k2;
    let b = k2 * k3.sqrt();
    (a + b, a - b)
}
type Z64 = num::complex::Complex<f64>;

fn f2(k1: Z64, k2: Z64, k3: Z64) -> (Z64, Z64) {
    let a = k1 + k2;
    let b = k2 * k3.sqrt();
    (a + b, a - b)
}

The code is identical, only the types are different. One is f64. The other is Complex<f64>. Is it possible to have a single function polymorphic on both types?

Upvotes: 1

Views: 126

Answers (1)

JayDepp
JayDepp

Reputation: 1245

Since there's no trait for sqrt in std, and Complex doesn't implement num_traits::Float, you would have to make your own trait for it.

trait Sqrt {
    fn sqrt(self) -> Self;
}

impl Sqrt for f64 {
    fn sqrt(self) -> Self {
        f64::sqrt(self)
    }
}

impl Sqrt for Z64 {
    fn sqrt(self) -> Self {
        Z64::sqrt(&self)
    }
}

Then, you can simply require the needed traits.

use std::ops::{Add, Mul, Sub};

fn calc<T>(k1: T, k2: T, k3: T) -> (T, T)
where
    T: Add<Output = T> + Mul<Output = T> + Sub<Output = T> + Sqrt + Copy
{
    let a = k1 + k2;
    let b = k2 * k3.sqrt();
    (a + b, a - b)
}

If you use these same bounds in many places, consider making a trait that requires all of them and a universal bound.

Upvotes: 3

Related Questions