Closed Lonsdaleiter closed 9 months ago
Hi @Lonsdaleiter, sorry for taking so long to reply to this... to access the underlying representation ([u64; N]
) of a BUint
, you can use the BUint::digits
method (this returns a reference to the array) or From<BUint<N>>
is implemented for [u64; N]
.
To access the raw bytes, it depends whether you want the bytes as a vector (without padding zeros) or as an array of the same byte size as the integer (with padding zeros):
to_radix_{be, le}
methods, specifying the radix
argument as 256
.nightly
crate feature enabled, use the to_{be, le, ne}_bytes
methods.As
trait to cast the BInt<N>
to a BUintD8<N * 8>
(you need to know the concrete value of N
here, it can't be a const
-generic), then use the methods mentioned above to access the underlying representation of the BUintD8
as an array of bytes.Hopefully this is what you were looking for!
@isaacholt100 Thanks so much for the patient reply! I don't know how I missed those functions they're pretty important.
Relatedly, is there a reason why the BUint and BInt aren't marked #[repr(transparent)]
? Getting a reference to the underlying representation is helpful, but if I want to send a tightly packed array of big integers to the GPU, being able to just pass an array of BInts directly through without needing to construct a new array from their underlying representation would be nice.
Apologies for the late response again, it's been another busy week... to be honest, I think when I originally published bnum I wasn't aware of the different repr
s that structs could have. As I've never used them for anything, I'm not that experienced with this stuff - would adding #[repr(transparent)]
to the integer types be a breaking change? If not then I'm more than happy to add this for the next release. And if even it is a breaking change, I could still consider it when bnum hits v1. Are there any reasons for leaving it as the default repr
? Thanks
I found an official thread discussing what semver guidelines should be for repr changes: https://github.com/rust-lang/cargo/pull/10276.
This person makes the point (which I agree with) that going from #[repr(Rust)]
to #[repr(transparent)]
should be harmless (going from no guarantee to some guarantee), but going the other way could silently break things (going from some guarantee to no guarantee).
So, I don't think it counts as a breaking change to change from default to transparent.
I'm not aware of any downside #[repr(transparent)]
would have -- I don't know of anything that making the guarantee would prevent the compiler from doing but I suppose it's theoretically possible. Still, it'd be useful to be able to treat the wrapper type as its underlying array.
I see, that makes sense. I think I might have read somewhere that adding #[repr(transparent)]
prevents certain optimisations from the compiler, but I'll read into this and check, and do some benchmarks if necessary. Do you mind quickly explaining why adding #[repr(transparent)]
is necessary/preferable for your use case? I thought that if the struct has a single field then it wouldn't make a difference, but I could be wrong?
I've read into this a bit more now, the struct isn't guaranteed to have the same layout as the single field unless it's marked as #[repr(transparent)]
. Benchmarks are looking like it doesn't make a difference, I'll need to run through them a few more times just to check. If adding this repr doesn't make a difference to performance, then I can add this to the next version.
v0.9.0
has just been released, which adds #[repr(transparent)]
to bnum
integers, so closing this issue. Thanks!
I'm trying to send a BInt to the GPU (I have an equivalent big two's complement integer structure there), but to do that I need to access the raw bytes of a BUint/BInt.
I've looked through the documentation and source of the project, but I can't find a way to access the raw bytes of a BUint/BInt. BUint is a wrapper around
[$Digit; N]
, but it isn't#[repr(transparent)]
, so I can't transmute BUint to the equivalent array. Is there no way to access the raw bytes or internal representation of either big integer type?