Skip to content

BigintOperations::ToDouble returns platform dependent result for integers in uint64_t range #19213

@mraleph

Description

@mraleph
Member

It contains the following code:

  if (AbsFitsIntoUint64(bigint)) {
    double absolute_value = static_cast<double>(AbsToUint64(bigint));
    double result = bigint.IsNegative() ? -absolute_value : absolute_value;
    return Double::New(result);
  }

all previously supported systems agreed on what they do when compiling static_cast<double>(uint64_value) however MSVC 2010 on Windows 64 does not agree with other systems. Here is a demo:

if defined(_MSC_VER)

include <stdint.h>

define PRIu64 "I64u"

else

ifndef __STDC_FORMAT_MACROS

define __STDC_FORMAT_MACROS

endif

include <inttypes.h>

endif

include <cstdio>

double convert(uint64_t x) {
  return static_cast<double>(x);
}

uint64_t bitcast(double x) {
  return (uint64_t)&x;
}

int main(int argc, char* argv[]) {
  const uint64_t a = 12345678901234567891ULL;
  const double b = convert(a);
  const uint64_t c = bitcast(b);
  const uint64_t d = 4892433759222981601ULL;

  printf("{%" PRIu64 " => %lf (%" PRIu64 ")} %s %" PRIu64 "\n",
         a, b, c, c == d ? "==" : "!=", d);

  return 0;
}

∮ g++ -m32 -o test test.cc
∮ ./test
{12345678901234567891 => 12345678901234567168.000000 (4892433759222981601)} == 4892433759222981601
∮ g++ -m64 -o test test.cc
∮ ./test
{12345678901234567891 => 12345678901234567168.000000 (4892433759222981601)} == 4892433759222981601

On MSVC x86
D:\src\temp3>cl /nologo test.cc
D:\src\temp3>test.exe
{12345678901234567891 => 12345678901234567000.000000� (4892433759222981601)} == 4892433759222981601

On MSVC x64
D:\src\temp3>cl /nologo test.cc
D:\src\temp3>test.exe
{12345678901234567891 => 12345678901234569000.000000 (4892433759222981602)} != 4892433759222981601

This difference causes corelib/big_integer_vm_test to fail on Windows x64. I am going to mark this failure as expected for now but we need to have a work-around for this incompatibility.

Activity

lrhn

lrhn commented on Jun 5, 2014

@lrhn
Member

We should be aware that MSVC x86 has a different double->string conversion than g++, if we use the system's conversion.

The x64 result is .. bad. It is not the nearest double to the original integer value. I'm surprised that it is the x64 version that differs, since I should be able to uuse a SSE2 instruction that does the right thing. Unless its FPU rounding flag is set to round up for some reason.

mraleph

mraleph commented on Jun 6, 2014

@mraleph
MemberAuthor

I landed the fix in r37078 by using the same code that GCC generates to match the rounding.


Added Fixed label.

added
P3A lower priority bug or feature request
area-vmUse area-vm for VM related issues, including code coverage, and the AOT and JIT backends.
on Jun 6, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3A lower priority bug or feature requestarea-vmUse area-vm for VM related issues, including code coverage, and the AOT and JIT backends.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @mraleph@lrhn

        Issue actions

          BigintOperations::ToDouble returns platform dependent result for integers in uint64_t range · Issue #19213 · dart-lang/sdk