Get double precision version of integer type

Viewed 73

I'm looking for a generic mechanism that will allow me to get double precision version of given integer type

u8 -> u16
u16 -> u32

and so on.

In C++ we can define template structure

#include <cstddef>

using undefined = void;

template <class T>
struct double_precision {
  using type = undefined;
};

template <class T>
using double_precision_t = typename double_precision<T>::type;

and add specializations

template <>
struct double_precision<std::uint8_t> {
  using type = std::uint16_t;
};

template <>
struct double_precision<std::uint16_t> {
  using type = std::uint32_t;
};

template <>
struct double_precision<std::uint32_t> {
  using type = std::uint64_t;
};

and after that get double precision version with double_precision_t<T> like in

template<class T>
double_precision_t<T> square(T value) {
  double_precision_t<T> double_precision_value = value;
  return double_precision_value * double_precision_value;
}

How can we do similar thing in Rust?

2 Answers

You can do it with traits:

trait DoublePrecision {
    type Output: From<Self>;
}

impl DoublePrecision for u16 {
    type Output = u32;
}

// etc...

Then use it as follows:

fn square<T: DoublePrecision>(value: T) -> T::Output
where
    T::Output: std::ops::Mul<T::Output, Output = T::Output>
{
   value.into() * value.into()
}

For more complex usage, see the num trait to add requirements to T.

You can use a trait and some num trait to make it quite generic:

use num::cast::AsPrimitive;

trait DoublePrecision: AsPrimitive<Self::Output> {
    type Output: std::ops::Mul<Output = Self::Output> + Copy;

    fn double_precision(self) -> Self::Output {
        self.as_() * self.as_()
    }
}

impl DoublePrecision for u8 {
    type Output = u16;
}

fn main() {
    assert_eq!(16, 4.double_precision());
}

You could just make a little macro to write the impl block.

Related