boostorg / multiprecision

Boost.Multiprecision
Boost Software License 1.0
194 stars 111 forks source link

Initializing cpp_rational with 1 / X yields wrong value #540

Closed Xirema closed 1 year ago

Xirema commented 1 year ago

It appears this has been a problem since 1.78.0, and is still affecting the current version of multiprecision.

Attempting to construct a cpp_rational with a rational value of 1 divided by a cpp_int value of anything else results in the final value being 1, instead of the correct value.

This can be worked-around by ensuring that the divided-by value is explicitly cast to a cpp_rational type before performing the division.

Curiously, this only occurs if the Numerator is 1; if the Numerator is any other value, the rational is correctly initialized.

Godbolt Link demonstrating that the behavior was different (correct) in 1.77.0 and persists up through 1.81.0

Sample Code to reproduce the issue:

#include<boost/multiprecision/cpp_int.hpp>
#include<iostream>

int main() {
    using Integer = boost::multiprecision::cpp_int;
    using Rational = boost::multiprecision::cpp_rational;

    Integer one = 1;
    Integer tenThousand = 10000;
    Integer threeFourFiveSix = 3456;
    Rational oneInTenThousand = Rational(one) / tenThousand;
    Rational oneInThreeFourFiveSix = Rational(one) / threeFourFiveSix;

    std::cout << one << "\n" << tenThousand << "\n" << oneInTenThousand << "\n";
    std::cout << oneInThreeFourFiveSix << "\n";

    Integer two = 2;
    Rational twoInTenThousand = Rational(two) / tenThousand;
    std::cout << twoInTenThousand << "\n";

    Rational oneInTenThousandCorrected = Rational(one) / Rational(tenThousand);
    std::cout << oneInTenThousandCorrected << "\n";
}

Output in 1.77.0:

1
10000
1/10000
1/3456
1/5000
1/10000

Output in 1.81.0:

1
10000
1
1
1/5000
1/10000
mborland commented 1 year ago

In 1.78.0 the rational adapter was changed here. This looks to be similar to #541 where implicit conversions were dropped by the change. @jzmaddock would know best.

jzmaddock commented 1 year ago

Testing a fix now.