Big_int and traits

I'm struggling to create a BigUint (from num_bigint from a usize.

The num_bigint crate contains the ToBigUint trait, but I'm unclear as to how to use that to instantiate a BigUint with the value 10. The num_bigint crate docs contain a (to me) strange idom for creating zero and one, but they don't seem to use the ToBigUint trait from what I can see, and I can't see how to clare that to arbitrary integers.

As well as the specific issue at hand, I think part of my issue is that I'm unclear on what rust traits are used for. I understand trait == "interface", but I have the feeling that there's something more going on - traits can somehow provide functionality as well as define an interface? Because I'm confused about traits, I'm struggling to parse the ToBigUInt documentation

Backgound: I'm a python programmer learning Rust. Thanks for any help you can give me!

BigUInt implelments From<usize> (among other implementations for other numbers. This means you can do the following

let v: num_bigint::BigUint = 10usize.into();

Regarding your other questions. The zero and one are just basic properties of numbers which are used in building up calculations in a type generic way. Those don't use any sort of conversion and are just defined as methods. The following is the definition of the basic Num trait from num_traits, which says that the requirements are such that to be used as a number with the num crate a number needs to implement equals, zero, one and various numeric operations. I don't know enough about number theory or how to develop a generic numerics library to give a better answer than that.

trait Num: PartialEq + Zero + One + NumOps 

The basics of reading the documentation for ToBigUInt is that it is a trait that the implementer of the trait is required to define fn to_biguint(&self) which means that the type that implements it must have a function called to_biguint that takes an instance of the type as a reference and returns Option<BigUint>. Reading the rest of the documentation, you can see that the num_biguint crate implemented this trait for isize, i8, i16, etc. That means that for numbers of each of those types, you can call to_biguint on it like the following code. The only other thing to note is that the use num_bigint::ToBigUInt is required here to tell the compiler that you would like to use the trait methods in your code.

use num_bigint::ToBigUInt;
let a: i8 = 10;
let big_a = a.to_biguint().expect("Can't convert to BigUInt. Probably a negative number");

EDIT
Fixed non working code in first example

1 Like

drewkett,
thanks very much for your response. It's been a real lightbulb moment for me. I feel like a bunch of stuff has clicked into place in my head.

Looking at the BigUInt docs with fresh eyes, I can see that it implements the From trait (as you pointed out), and implements it on all of the relevant(*) numeric types.

I think this was a key point where I was confused - the num_bigint package implements traits on a whole bunch of existing numeric data types.

So, either by reading the From documents, or just recognising one of the core traits that any Rustacean should be familiar with, that leads me to

let v = BigUint::from(10u8);

Which works like a treat!

And the well-known Into trait which is magically constructed out of From leads us to

let x: BigUint = 10u8.into();

which also works.

(*) minor point for future learners who discover this post: drewkett's first example doesn't quite work, because 10 is interpreted as isize, and big unsigned numbers don't implement From on signed integers. That's why the ToBigUInt::to_biguint() returns Option - to handle the case where you try to convert a negative number into an unsigned big integer. Changing the literal to 10u8 does the trick.