(Inari crate) : How to use a generic function with Float as trait bound for a type that does not implement Float trait?

I am quite new to Rust, so sorry by advance if I'm misunderstanding something.

I have some code where I have generic functions such as this one :

pub(crate) fn square_root<T: Float>(value_array: &[T]) -> T {
    value_array[0].sqrt()
}

I also have this macro :

macro_rules! print_queries {
    ($INTERVAL:ty, $INTERVAL_INIT:expr, $TYPE_NAME:expr, $METHOD:expr, $PRINT_METHOD:expr, $VARIABLE_COUNT:expr) => {
        {
            let mut used_variables: Vec<$INTERVAL> = Vec::with_capacity($VARIABLE_COUNT);
            for i in 0..$VARIABLE_COUNT {
                used_variables.push($INTERVAL_INIT(COMP_DOUBLES[i]));
            }
            match std::panic::catch_unwind(|| $METHOD(&used_variables)) {
                Ok(result) => {
                    println!("{}: ", $TYPE_NAME);
                    print_query(lower(result), upper(result), $PRINT_METHOD(COMP_GMP_RATIONALS.as_slice()));
                }
                Err(_) => {
                    println!("{}: ", $TYPE_NAME);
                    print_query(1.0, -1.0, $PRINT_METHOD(COMP_GMP_RATIONALS.as_slice()));
                }
            }
        }
    }
}

The macro is used with the first function as the parameter $METHOD, e.g.

print_queries!(InariInterval, inari_interval, "INARI", square_root, print_square_root, 1);

As you can see, I'm using this method with the Inari crate, which is a crate for interval arithmetic : inari - Rust
InariInterval is a copy of the type inari::Interval, and inari_interval is a method creating an Interval from one float.

However, this does not work, and here is the error I get :

error[E0277]: the trait bound `inari::Interval: num_traits::Float` is not satisfied
   --> src/query.rs:65:5
    |
65  |     run_query!(square_root, print_square_root, 1, square_root_range, check_input_square_root);
    |     ^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     |          |
    |     |          required by a bound introduced by this call
    |     the trait `num_traits::Float` is not implemented for `inari::Interval`
    |
    = help: the following other types implement trait `num_traits::Float`:
              f32
              f64
note: required by a bound in `methods::square_root`
   --> src/methods.rs:803:30
    |
803 | pub(crate) fn square_root<T: Float>(value_array: &[T]) -> T {
    |                              ^^^^^ required by this bound in `square_root`

I'd like as much as possible to keep my functions generic. I don't think I can implement square_root without using Float, and that would only partly solve the problem since I have other functions with the same issue.

I tried to implement the Float trait for Inari but it doesn't seem to be possible. I got this error : Only traits defined in the current crate can be implemented for arbitrary types [E0117]

Thus, I'm a little bit stuck and I don't know if I can find a solution while keeping my functions generic.

Thanks for advance for your help and suggestions.

One way is to ask the maintainers of inari to implement the appropriate Num traits.

In order to do it yourself, you'll need to wrap inari::Interval in your own type.

struct FloatInterval(inari::Interval);

impl num::Float for FloatInterval { /* ... */ }

Alternatively you can make your own trait to replace num::Float and implement that for each concrete type you need it for (perhaps by macro), including inari::Interval.

1 Like

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.