Robbepop / apint

Arbitrary precision integers library.
Other
26 stars 4 forks source link

Implement methods to convert ApInt instances to primitives #5

Closed Robbepop closed 6 years ago

Robbepop commented 6 years ago

ApInt offers a lot of functionality to convert primitive data types such as u8, i16, u64 and even i128 into ApInt instances, however, there is no support for the other way around.

The proposed API additions are the following:

The truncate_to_* methods will simply truncate the ApInt bits to the correct bit width and return the value. If the ApInt has a bit width smaller than the primitive type the ApInts value is simply taken for conversion. This has the effect that ApInts with a bit width smaller than the primitive cannot represent a negative value. So a 1-bit bit width ApInt with value 1 will convert to 1_u8 upon conversion to u8.

The second proposed API tries to reinterpret the ApInt into the given primitive but won't truncate bits of it. Instead, if the ApInt instance requires a greater bit width for its value representation that what can be represented with the primitive data type an Error is returned instead.

Unit tests for

Robbepop commented 6 years ago

Commit 4a9948fc1f3f202202e504fdc5889ccf641caef5 added this new to_primitive module and documentation and stubs for its entire API. The full implementation and tests are still required.

Robbepop commented 6 years ago

Design question: How should ApInt::try_to_iN and ApInt::truncate_to_iN behave for any N when the sign bit is 1? Should there be an implicit sign extension so that -1 will properly be casted into a -1 or will it be a simple reinterpretation of the digit's bits?

Answer I answered this myself by looking at how Rust treats casts from e.g. i32 to i64 for negative numbers. Gladly it is also sign and value preserving, so a -27_i32 will be cast to -27_i64 which is what users want generally - and if not they might take the unsigned bridge.

Robbepop commented 6 years ago

A decent chunk of the functionality proposed by this issue was implemented in e7902aed7002727b595153e8ef896d952225e01c and 231aabb52a7bd4cb26b067bf428513388a9b14a5.

Robbepop commented 6 years ago

What needs to be done before this issue can be closed: Write tests for the new API.

Problem

To cover enough cases one needs to create tests over several different dimensions. We need different input values (e.g. i64 values) and construct ApInt instances of them for many different bit widths and then test all the different resize_to_* and try_to_* methods for them. This is a lot of work that needs to be automated. One can not simply write so many direct assertions.

Also for resize_to_* methods there needs to be a case distinction for ApInt instances that have a greater than or less than bit width compared to the target resize bit width since they either truncate or sign-resize their original values.

Note: Here again the PrimitiveTy utility may be of help.

Robbepop commented 6 years ago

Finished this task in commit 64402b4167aaa2270670706e068bf9219564ffd9.