nim-lang / bigints

BigInts for Nim
MIT License
124 stars 32 forks source link

Type conversion for small BigInts into integers #72

Closed dlesnoff closed 1 year ago

dlesnoff commented 2 years ago

Since BigInt's limb parameter has become private, thus we can not easily cast BigInts with absolute value less than 2^32 to an int or even a uint32. The only workaround yet is to use the keyword cast[int]. But this does not always do what we want. To get only the smallest limb, we also have to define a mask like 2^32 - 1 and to apply an ineffective and. Can we implement some functions like … ?:

konsumlamm commented 2 years ago

The only workaround yet is to use the keyword cast[int]. But this does not always do what we want.

That never does what you want. I suggest you read the documentation for cast, it merely reinterprets the underlying bits.

I generally agree that functions to convert a BigInt to some integer types are useful, but how should we handle the case of the BigInt being out of range? I see several possibilities:

EDIT: Added a 4th option.

narimiran commented 2 years ago

@Araq: you might be interested in this discussion, i.e. give your opinion on how to best proceed with this.

dlesnoff commented 2 years ago

We can not return the lowest/highest value for type conversions to integers as a BigInt can be any value that an int can contain. The first solution forces the user to wrap any potentially dangerous cast in a try .. except .. finally clause. I have not used Option in my programs yet, if I understand the user will have to check (everytime ?) whether the Option contains a value ?

Araq commented 2 years ago

IMO the prototype should be:


proc toFixedInt*[T](b: BigInt): Option[T]

with the hopefully obvious semantics.

konsumlamm commented 2 years ago

This issue should be reopened, toSignedInt only provides conversion to signed integers. I'd also argue that it should be renamed to toInt and also support unsigned integers (rather than adding a new toUnsignedInt function).

Araq commented 2 years ago

I also really need pred and succ. Implementation can be as simple as:


proc pred*(a: BigInt; def = 1): BigInt =
  a - initBigInt(def)

proc succ*(a: BigInt; def = 1): BigInt =
  a + initBigInt(def)
konsumlamm commented 1 year ago

This has been addressed in https://github.com/nim-lang/bigints/pull/100.