diff --git a/src/bigints.nim b/src/bigints.nim index 9ef5abb..fe1498c 100644 --- a/src/bigints.nim +++ b/src/bigints.nim @@ -1,6 +1,6 @@ ## Arbitrary precision integers. -import std/[algorithm, bitops, math, options] +import std/[algorithm, bitops, fenv, math, options] type BigInt* = object @@ -1140,6 +1140,12 @@ func fastLog2*(a: BigInt): int = return -1 bitops.fastLog2(a.limbs[^1]) + 32*(a.limbs.high) +func to*(x: BigInt, T:type SomeFloat): T = + let lolimb = max(x.limbs.low, x.limbs.high - 1 - mantissaDigits(T) div 32) + for i in lolimb..x.limbs.high: + result += T(x.limbs[i].int64) * pow(2.0, 32.0 * T(i)) + if x.isNegative: + result = -result func invmod*(a, modulus: BigInt): BigInt = ## Compute the modular inverse of `a` modulo `modulus`. diff --git a/tests/tbigints.nim b/tests/tbigints.nim index 3b3a59d..c3fd267 100644 --- a/tests/tbigints.nim +++ b/tests/tbigints.nim @@ -786,6 +786,35 @@ proc main() = doAssert pred(a, 3) == initBigInt(4) doAssert succ(a, 3) == initBigInt(10) + block: # to float + doAssert initBigInt("1").to(float32) is float32 + doAssert initBigInt("1").to(float64) is float64 + doAssert initBigInt("1").to(BiggestFloat) is BiggestFloat + doAssert initBigInt("1").to(float) is float + + doAssert initBigInt("0").to(BiggestFloat) == 0.0 + doAssert initBigInt("1").to(BiggestFloat) == 1.0 + doAssert initBigInt("1").to(float32) == 1.0 + doAssert initBigInt("1").to(float64) == 1.0 + + doAssert initBigInt("-1").to(BiggestFloat) == -1.0 + doAssert initBigInt(BiggestInt.high).to(BiggestFloat) == BiggestFloat(BiggestInt.high) + doAssert initBigInt(BiggestInt.low).to(BiggestFloat) == BiggestFloat(BiggestInt.low) + doAssert (initBigInt(BiggestInt.high) * initBigInt(4)).to(BiggestFloat) == BiggestFloat(BiggestInt.high) * 4.0 + doAssert (initBigInt(BiggestInt.low) * initBigInt(4)).to(BiggestFloat) == BiggestFloat(BiggestInt.low) * 4.0 + doAssert (initBigInt("17976931348623157") * initBigInt(10).pow(292)).to(BiggestFloat) == 17976931348623157e292 + + # limits of exact representability + doAssert initBigInt(1 shl 24).to(float32) == float32(1 shl 24) + doAssert initBigInt(-1 shl 24).to(float32) == float32(-1 shl 24) + doAssert initBigInt(1 shl 53).to(float64) == float64(1 shl 53) + doAssert initBigInt(-1 shl 53).to(float64) == float64(-1 shl 53) + # out of exact integer representation range + doAssert initBigInt(int32.high).to(float32) == float32(int32.high) + doAssert initBigInt(int64.high).to(float64) == float64(int64.high) + # well out out of finite range + doAssert initBigInt("-10").pow(400).to(float64) == Inf + doAssert initBigInt("-10").pow(401).to(float64) == -Inf static: main() main()