Coder Social home page Coder Social logo

One testcase fails about mppp HOT 17 CLOSED

bluescarni avatar bluescarni commented on May 10, 2024
One testcase fails

from mppp.

Comments (17)

bluescarni avatar bluescarni commented on May 10, 2024 1

I was planning to add a section about platform-specific notes in the documentation, perhaps I could add a warning about FreeBSD's issues with pow() in there.

from mppp.

bluescarni avatar bluescarni commented on May 10, 2024

Hello @yurivict,

could you run the individual test and report back the output that it produces?

from mppp.

yurivict avatar yurivict commented on May 10, 2024

Here's the log:

$ ./work/.build/test/integer_pow

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
integer_pow is a Catch v2.1.1 host application.
Run with -? for options

-------------------------------------------------------------------------------
pow
-------------------------------------------------------------------------------
/usr/ports/math/mppp/work/mppp-0.9/test/integer_pow.cpp:201
...............................................................................

/usr/ports/math/mppp/work/mppp-0.9/test/integer_pow.cpp:189: FAILED:
  REQUIRE( pow(integer{2}, 4.5l) == std::pow(2.l, 4.5l) )
with expansion:
  22.6274 == 22.6274

===============================================================================
test cases:     1 |     0 passed | 1 failed
assertions: 15068 | 15067 passed | 1 failed

Cleaning up the mpz alloc cache.
Cleaning up MPFR caches.

from mppp.

bluescarni avatar bluescarni commented on May 10, 2024

I was able to reproduce the problem in a FreeBSD virtual machine. The problem here appears only in Release builds and not in Debug builds.

The statement pow(integer{2}, 4.5l) should produce exactly the same identical result as std::pow(2.l, 4.5l), because both functions eventually end up calling the std::pow() overload for long double with base 2 and exponent 4.5 (and both numbers are exactly representable in a binary floating-point format). Indeed, on all my machines and operating systems, and on the automated unit testing pipeline, this is always the case. The only difference between those two expressions is that one can be computed at compile-time (std::pow(2.l, 4.5l)), while the other cannot. However, on FreeBSD two slightly different values are being produced for those two expressions:

22.62741699796952078
22.62741699796951877

Perhaps related, it seems like on FreeBSD there might be some issue with the pow() overload for long double. When compiling this test, the linker warns me that:

warning: powl has lower than advertised precision

So my guess is that there is something funny going on with extended precision floating-point computations involving the C99 powl() function. Do you have any idea of what might be going on?

Note that the test failure can be silenced easily by introducing some small tolerance instead of an exact equality, and this is an issue of the testing code and not of mp++ per se. But it would be nice to get to the bottom of it.

from mppp.

yurivict avatar yurivict commented on May 10, 2024

I'm getting the same results with this program:

#include <stdio.h>
#include <math.h>
#include <cmath>

int main(int argc, const char *argv[]) {
  printf("pow(integer{2}, 4.5l) -> %.30Lf\n", pow(2, 4.5l));
  printf("std::pow(2.l, 4.5l) -> %.30Lf\n", std::pow(2.l, 4.5l));
}

Output:

pow(integer{2}, 4.5l) -> 22.627416997969518774880270939320
std::pow(2.l, 4.5l) -> 22.627416997969518774880270939320

Pari gives 22.627416997969520780827019587355169257 with 28-decimal digit precision.

from mppp.

bluescarni avatar bluescarni commented on May 10, 2024

Ok I think I know what is going on. In a Debug build, the compiler ends up calling the pow() function at runtime for both expressions. This gives the result in double precision, not in long double precision, which is:

22.62741699796951877

So the linker warning is correct, the pow() function for long double is not actually returning a result accurate to the last significant digit. If, however, the build is set to Release, the compiler computes at compile time the result of the expression std::pow(2.l, 4.5l), presumably with some internal arbitrary precision library (GCC uses MPFR for compile time computations, not sure about clang). The result of std::pow(2.l, 4.5l) computed at compile time is the correct result for long double precision:

22.62741699796952078

As a proof, consider this program:

#include <iostream>
#include <cmath>

int main(int argc, char **)
{
        std::cout.precision(40);
        std::cout << std::pow(2l, 4.5l) << '\n';
        std::cout << std::pow(static_cast<long double>(argc), 4.5l) << '\n';
}

compile it first without optimisation, and run it with ./a.out 2. It will print:

22.62741699796951877488027093932032585144
22.62741699796951877488027093932032585144

If you recompile it with -O2 optimisation level, the output will be:

22.62741699796952078022060916850932699163
22.62741699796951877488027093932032585144

Can you confirm this?

from mppp.

yurivict avatar yurivict commented on May 10, 2024

Can you confirm this?

Yes, I got the same results.

from mppp.

bluescarni avatar bluescarni commented on May 10, 2024

Ok, I'll open a PR and put a workaround in the tests. Thanks for testing!

from mppp.

yurivict avatar yurivict commented on May 10, 2024

You're welcome!

from mppp.

bluescarni avatar bluescarni commented on May 10, 2024

PR is up at #134. I will do a 0.10 release in the next few days, so you can have a stable release with working tests on FreeBSD.

from mppp.

yurivict avatar yurivict commented on May 10, 2024

Great, thanks!

from mppp.

yurivict avatar yurivict commented on May 10, 2024

If this is due to a bug in FreeBSD, IMO you should just leave it failing as it is.
There's nothing wrong with mppp in this regard, no need to fix it.

Instead, I've created this bug report so that they can fix it: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=227179

from mppp.

bluescarni avatar bluescarni commented on May 10, 2024

Thanks for opening the report!

I just disabled that specific test on FreeBSD, I did not actually touch the library's code. Once the issue is fixed on FreeBSD's side, I can conditionally re-enable the test.

from mppp.

yurivict avatar yurivict commented on May 10, 2024

Sounds good!
Even better solution is, I think, to keep the failure, but to add an explanation for this case.
This is because 0 failures shouldn't be a goal. The goal should be to have users informed. -)

from mppp.

yurivict avatar yurivict commented on May 10, 2024

Yes, test failure + a warning and an explanation is better than to hide the failure IMO.

from mppp.

bluescarni avatar bluescarni commented on May 10, 2024

I've released mp++ 0.10 with the fixes and doc additions mentioned in this report. Please let me know if you have any further issues on FreeBSD!

from mppp.

yurivict avatar yurivict commented on May 10, 2024

It all works. I've updated the port. Thank you!

from mppp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.