Fable icon indicating copy to clipboard operation
Fable copied to clipboard

Converting negative bigint numbers to decimal does not work

Open ThisFunctionalTom opened this issue 2 years ago • 2 comments
trafficstars

Description

Converting Decimal.MinValue to bigint and back to decimal returns -1 instead of Decimal.MinValue.

Actually, I just found out that all negative bigint numbers cannot be converted to decimal.

Repro code

Added two tests for the edge cases in this PR

Expected and actual results

As defined in the tests in PR.

Related information

  • Fable version: latest main branch
  • Operating system: Windows

ThisFunctionalTom avatar Jul 30 '23 15:07 ThisFunctionalTom

I created the smallest repro in fable REPL:

open System

let actual = decimal -1I
let expected = -1M
printfn $"Actual: {actual} <> Expected: {expected}"

https://fable.io/repl/#?code=PTAEHUCcEsBcFNQGMD2ATRLKgDYoIZqj6gDO+AtgA46IBmkKFZ0GARvpALABQKV8AHagAygE9SCCr161YxJLACu+HKAC8oDEmgVVoALQBGAJKz48+AA8Bi+EU3GAsryoxBsOsIAkAIgCCiio4AFygAN74QaoAvqAAPAB8oACiNvB2aGHh1rYIaDG+MjxAA&html=Q&css=Q

ThisFunctionalTom avatar Jul 30 '23 21:07 ThisFunctionalTom

I followed the rabbit into the hole and I believe that the problem is in toDecimal function in the BigInt.js file in fable-library.

export function toDecimal(x) {
    const low = Number(BigInt.asUintN(32, x));
    const mid = Number(BigInt.asUintN(32, x >> 32n));
    const high = Number(BigInt.asUintN(32, x >> 64n));
    const isNegative = x < zero;
    const scale = 0;
    return fromParts(low, mid, high, isNegative, scale);
}

Executing this test code:

const x = fromString("-79228162514264337593543950335");
const low = Number(BigInt.asUintN(32, x));
const mid = Number(BigInt.asUintN(32, x >> 32n));
const high = Number(BigInt.asUintN(32, x >> 64n));
const isNegative = x < 0n;
const scale = 0;
const actual = fromParts(low, mid, high, isNegative, scale);
const expected = fromParts(-1, -1, -1, true, 0);
toConsole(interpolate("x: %A%P()", [x]));
toConsole(interpolate("low: %A%P()", [low]));
toConsole(interpolate("mid: %A%P()", [mid]));
toConsole(interpolate("high: %A%P()", [high]));
toConsole(interpolate("isNegative: %A%P()", [isNegative]));
toConsole(interpolate("Actual: %A%P()", [actual]));
toConsole(interpolate("Expected: %A%P()", [expected]));
Expect_isTrue(true)("");

the low, mid, high values are 1, 0, 0 respectively and the code generated from fable for the same number is actually -1, -1, -1.

ThisFunctionalTom avatar Jul 30 '23 21:07 ThisFunctionalTom

@ThisFunctionalTom Sorry it took so long, somehow I didn't notice this and it fell through the cracks. Should be fixed in the next release.

ncave avatar Jun 13 '24 19:06 ncave

This has been released with Fable 4.19.2

MangelMaxime avatar Jun 13 '24 19:06 MangelMaxime