Trying to declare multiple implementations of same function

I have this function which calculates number of digits in an Integer. This function can have two variants, i.e., signed numbers and unsigned numbers, the implementations are defined for both variants respectively below.

fn number_of_digits<T: Integer + Copy + NumCast>(mut num: T) -> T where T: Signed{
    let TEN: T = NumCast::from(10).unwrap();
    if num < T::zero() {
        num =-num;
    }
    let mut sum = T::zero();
    while num >= TEN {
        sum = sum + T::one();
        num = num % TEN;
    }
    sum + T::one()
}
fn number_of_digits<T: Integer + Copy + NumCast>(mut num: T) -> T where T: UnSigned{
    let TEN: T = NumCast::from(10).unwrap();

    let mut sum = T::zero();
    while num >= TEN {
        sum = sum + T::one();
        num = num % TEN;
    }
    sum + T::one()
}

So, how do I rewrite the function so that it can have respective implementations for both signed and unsigned without any compiler error?
And also in this line (let TEN: T = NumCast::from(10).unwrap();) inside the number_of_digits function, I initially used const keyword but it is giving me this compiler error. So, how to use const here instead of let?

Can you not just use the first version for both? The x < 0 if should get optimized out when compiled for unsigned integer types.

2 Likes

Unrelated comment: For an input of 0 I think your functions returns 1. Is that intended? (It might totally be of course)

In the general case, this is not possible. The rust compiler always assumes that some type in the future might implement both Signed and UnSigned at the same time, and then it wouldn't be able to decide which implementation should be used.

2 Likes

No, I can't because it will throw compiler error as

error[E0600]: cannot apply unary operator `-` to type `T`

  |
7 |         num =-num;
  |              ^^^^ cannot apply unary operator `-`

This should work:

if num < T::zero() {
    num = T::zero() - num;
}
1 Like

yes, because 0 can be considered as single digit

Ok, this actually worked for me for both unsigned and signed numbers Thanks for the answer. I also have another problem.I cannot declare this variable TEN inside the function as const. I tried it but it gives this this compiler error. So, how can I declare it as const?

That's not the error I get. I get this:

error[E0401]: can't use generic parameters from outer function
 --> src/lib.rs:4:16
  |
3 | fn number_of_digits<T: Integer + Copy + NumCast>(mut num: T) -> T {
  |                     - type parameter from outer function
4 |     const TEN: T = NumCast::from(10).unwrap();
  |                ^ use of generic parameter from outer function

playground

I don't think you can guarantee that it is a compile-time constant. For example, if T is a bigint, the NumCast::from method would probably require allocating memory, which you can't do in const-exprs.

Of course, it will be optimized into a compile time constant when T is an ordinary integer.

1 Like

Sorry :sweat_smile: about the error code. I was getting a lot of errors while I was writing the function. I had accidentally pasted here.

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.