# Generics: how to test if negative

I'm practicing some Rust by going through Numerical Recipes, but I'm not getting very far because I don't understand how to work with generic types. Here's the function I'm trying to implement.

``````/// Return a value with the magnitude of `a` and and the sign of `b`
pub fn sign<T>(a: T, b: T) -> T
where T: PartialOrd + std::ops::Neg<Output = T>,
{
if b >= 0 {
if a >= 0 {
a
} else {
-a
}
} else {
if a >= 0 {
-a
} else {
a
}
}
}
``````

This doesn't work because 0 is an integer and not a T. What's the right way to do this?

I'm not familiar with this "Numerical Recipes" thing, but using generic integers is generally rather cumbersome in Rust. I would recommend just picking an integer type and using that.

The `num_traits` crate has traits for working with generic number types. I believe you could use a `num_traits::Num` bound to get the comparison to zero, though you'd have to rewrite it slightly so you aren't using a `0` literal.

Technically you can get a zero with just std

``````pub fn zero<T: std::iter::Sum>() -> T { std::iter::empty().sum() }
``````

But yes, `num_traits` is the way to go if you really want to do generic math.

1 Like

Thanks for the help. I was able to get it to work with num_traits like this...

``````use num_traits::{self, Signed};

/// Return a value with the magnitude of `a` and and the sign of `b`
pub fn sign<T>(a: T, b: T) -> T
where T: PartialOrd + Signed,
{
if b.is_positive() {
if a.is_positive() {
a
} else {
-a
}
} else {
if a.is_positive(){
-a
} else {
a
}
}
}
``````
``````pub fn sign<T: Signed>(a: T, b: T) -> T {
if a.is_positive() == b.is_positive() {
a
} else {
-a
}
}
``````

(Also check what you want to happen with 0s, maybe you want `is_negative`.)

1 Like

I think the most literal translation of your original code would be

``````pub fn sign<T>(a: T, b: T) -> T
where
T: PartialOrd + std::ops::Neg<Output = T> + num_traits::Num,
{
if b >= T::zero() {
if a >= T::zero() {
a
} else {
-a
}
} else {
if a >= T::zero() {
-a
} else {
a
}
}
}
``````
1 Like

I'd write it like this, which doesn't need any constants like `0`:

``````pub fn sign<T>(a: T, b: T) -> T
where
T: Signed,
{
b.signum() * a.abs()
}
``````

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.