[mp_int] Incorrect comparison with native types

When I create an negative mp_int outside the range of a native type and compare it to a number of that type, I get incorrect results. Here is an example to reproduce the behavior: #include <iostream> #include <limits> #include <boost/cstdint.hpp> #include <boost/mp_math/mp_int.hpp> using namespace boost::mp_math; using namespace std; int main() { int32_t MIN = numeric_limits<int32_t>::min(); mp_int<> a = MIN; cout << a << endl; a -= 1; // Should print "-2147483649 1" but prints "-2147483649 0" instead cout << a << ' ' << (a < MIN) << endl; return 0; }

I can't reproduce that behavior, please try the latest code from the sandbox. I committed fixes to the other bugs you were reporting today. I shall upload a new version to the vault tomorrow or so.

On Sat, Jan 10, 2009 at 5:19 PM, Kevin Sopp <baraclese@googlemail.com> wrote:
I can't reproduce that behavior, please try the latest code from the sandbox. I committed fixes to the other bugs you were reporting today. I shall upload a new version to the vault tomorrow or so.
I tried the same example code with a fresh checkout from the sandbox (rev 50541) embedded within a freshly downloaded copy of Boost 1.37.0, and I got the same result: (mp_int<>(INT32_MIN) - 1 < INT32_MIN) == 0. This is with gcc 4.2.4 on Linux. I get the same result when I use a fresh checkout of Boost (again, rev 50541) rather than the latest release. -- Nathan

Other operations with incorrect results: (1) mp_int<> a = "0x100000000"; a = -a; cout << (a < -1) << endl; This can be fixed by changing line 228 of mp_math/mp_int/detail/integral_ops.hpp (in integral_ops_impl<..., true>::less): if (lhs.size() > q) - return false; + return lhs.sign() == -1; (2) mp_int<> a = 13; int b = -1; cout << (a | b) << endl; // Should be -1, right? Likewise for bitwise AND and XOR. -- Nathan

(2)
mp_int<> a = 13; int b = -1; cout << (a | b) << endl; // Should be -1, right?
No, -13 is the correct answer here. You're ORing the magnitude of both numbers when using mp_ints. Unlike the built in integral types for which the answer depends on the internal binary representation of numbers (usually it's two's complement). I fixed the other bugs now. Kevin

On Sun, Jan 11, 2009 at 5:58 AM, Kevin Sopp <baraclese@googlemail.com> wrote:
(2)
mp_int<> a = 13; int b = -1; cout << (a | b) << endl; // Should be -1, right?
No, -13 is the correct answer here. You're ORing the magnitude of both numbers when using mp_ints. Unlike the built in integral types for which the answer depends on the internal binary representation of numbers (usually it's two's complement).
The interpretation of OR that you describe is consistent with libtommath (of course) but not with other arbitrary-precision-integer packages that I have tried. When I try either 13 OR -1 or (BIG(1) << 200) | -1, I get -1 from all of the following: gmp java.math.BigInteger Python's built-in long type Ruby's built-in Bignum type Likewise, all of these give me -14 for (BIG(13) ^ -1), while libtommath and mp_int give -12. -- Nathan -- Nathan

The interpretation of OR that you describe is consistent with libtommath (of course) but not with other arbitrary-precision-integer packages that I have tried. When I try either 13 OR -1 or (BIG(1) << 200) | -1, I get -1 from all of the following:
gmp java.math.BigInteger Python's built-in long type Ruby's built-in Bignum type
Likewise, all of these give me -14 for (BIG(13) ^ -1), while libtommath and mp_int give -12.
Are you trying to say that you prefer the behavior of the other libraries?

On Tue, Jan 13, 2009 at 6:11 AM, Kevin Sopp <baraclese@googlemail.com> wrote:
The interpretation of OR that you describe is consistent with libtommath (of course) but not with other arbitrary-precision-integer packages that I have tried. When I try either 13 OR -1 or (BIG(1) << 200) | -1, I get -1 from all of the following:
gmp java.math.BigInteger Python's built-in long type Ruby's built-in Bignum type
Likewise, all of these give me -14 for (BIG(13) ^ -1), while libtommath and mp_int give -12.
Are you trying to say that you prefer the behavior of the other libraries?
Yes, I think the common behavior is the most natural expectation, since it makes the behavior of mp_ints consistent with that of native types, at least on platforms that use two's-complement for negative numbers. I understand that two's-complement is not required by the language standard, but as best I know it's used practically everywhere. -- Nathan
participants (2)
-
Kevin Sopp
-
Nathan Kitchen