Opened 5 years ago

Closed 5 years ago

#13109 closed Bugs (fixed)

Incorrect result when casting from multiprecision::uint128_t to unsigned long long.

Reported by: gvisser@… Owned by: John Maddock
Milestone: To Be Determined Component: multiprecision
Version: Boost 1.63.0 Severity: Problem
Keywords: Cc:

Description

I found in Boost 1.63.0 on: Ubuntu 14.04.5 with g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4, 64-bit Windows 10's Windows Subsystem for Linux with g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609.

code snippet: uint128_t b128 = 0xFFFFFFFFFFFFFFFFFFFFFFFFC0A800FF_cppui; unsigned long long ull( static_cast<unsigned long long>( b128 ) ); printf( "ull: %016llX\n", ull );

The output is: ull: FFFFFFFFFFFFFFFF

Under Windows 10 and Visual Studio 2015 the output is: ull: FFFFFFFFC0A800FF

The work around I'm using is to mask out the upper 64 bits: ull = static_cast<unsigned long long>(b128 & 0x0FFFFFFFFFFFFFFFF);

Thanks, Gary Visser

Change History (1)

comment:1 by John Maddock, 5 years ago

Resolution: fixed
Status: newclosed

The intended behaviour is to return the maximum value of the target type when a narrowing conversion overflows (I realise this is different behaviour to most built in integer types, but then you're into undefined behaviour).

This patch: https://github.com/boostorg/multiprecision/commit/b35f1c8f613db66ad80ce260f94b7027814ede71 enforces uniform behaviour across all backend integer types.

In future, if you really want just the low order N bits, then you will need to mask these out - the same is true of built in integers actually if you want to avoid code-sanitizer errors (cland usan etc).

Note: See TracTickets for help on using tickets.