How to use Numbers in a Generic way?

What if one wants to write a function that can accept all numeric types?
How can this be achieved?
In this example the abs() method doesn't work.

Is this possible at all?
Where can I find a list of traits that are supported in standard rust types like i32, i64, f32, f64?
I understand a bit about generic functions but can not find the appropriate traits to narrow down the functions generic input and output type.
Searched the rust docs but ended up even more confused.

Any help appreciated!

use std::ops::Mul;

fn main() {
    let x: i32 = -15;
    let a: i32 = absolute(&x);
    println!("absolute of x: {}", a);
}

fn absolute<T: Mul> (x: &T) -> T {
    x.abs()
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `abs` found for reference `&T` in the current scope
  --> src/main.rs:10:7
   |
10 |     x.abs()
   |       ^^^ method not found in `&T`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

The num-traits crate has many additional traits for generic number types. For example:

fn absolute<T: num_traits::Signed>(x: &T) -> T {
    x.abs()
}

However, even with num-traits, I often find that generic code for arithmetic in Rust is a bit annoying. For example, you can't use simple literals in a generic context. You can write the code, but it sometimes has a lot of boilerplate that makes it hard to read and maintain.

In relatively simple cases, the high-level traits like num_traits::Num or num_traits::Float are often sufficient. But for other cases, I often prefer to implement code for just a single hard-coded type, or use macros rather than generic code to implement it for a handful of types.

3 Likes