首页 > 解决方案 > CGAL 4.12 的 Lazy_exact_nt 不准确?

问题描述

下面的测试函数在 CGAL 4.9.1 中按预期工作,但在 CGAL 4.12 中,计算不准确。有什么想法可能导致问题(下面有更多详细信息)?

#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
typedef K::FT dbl;
void test4()
{
    // 1. Create the smallest possible double and verify
    double smallDouble(1.0);
    while(smallDouble/2.0>0) smallDouble/=2.0;
    if(smallDouble/2.0==0) cout<<"can't divide smallDouble anymore, as expected"<<endl;

    // 2. Make it a dbl (K::FT)
    dbl a(smallDouble);

    // 3. Let b be even smaller ( smaller than the smallest double )
    dbl b(a/2.0);

    // 4. Show interval and try fit_in_double
    cout<<"a.approx()="<<a.approx()<<endl;
    cout<<"b.approx()="<<b.approx()<<endl;
    double d;
    if(CGAL::internal::fit_in_double(b,d))
    {
        cout<<"Yes, b fits in double d: "<<d<<endl;
    }
    else
    {
        cout<<"Before b.exact(): b does not fit back into double (as expected)"<<endl;
    }

    // 5. Call exact and try fit_in_double again
    cout<<"\nCalling exact()"<<endl;
    b.exact();
    cout<<"a.approx()="<<a.approx()<<endl;
    cout<<"b.approx()="<<b.approx()<<endl;
    if(CGAL::internal::fit_in_double(b,d))
    {
        cout<<"Yes, after exact() b fits in double d: "<<d<<" - Huh, not as expected!"<<endl;
    }
    else
    {
        cout<<"NOK after exact()"<<endl;
    }

    if(b<a) cout<<"b<a, as expected"<<endl;
        else cout<<"b >= a, not expected"<<endl;

    double c(to_double(b));
    cout<<"c="<<c<<endl;
    if(c==b) cout<<"c==b, not as expected"<<endl;
}

CGAL4.9.1 的输出是

can't divide smallDouble anymore, as expected
a.approx()=[4.94066e-324;4.94066e-324]
b.approx()=[0;4.94066e-324]
Before b.exact(): b does not fit back into double (as expected)

Calling exact()
a.approx()=[4.94066e-324;4.94066e-324]
b.approx()=[0;4.94066e-324]
NOK after exact()
b<a, as expected
c=0

CGAL4.12 的输出是

can't divide smallDouble anymore, as expected
a.approx()=[4.94066e-324;4.94066e-324]
b.approx()=[0;4.94066e-324]
Before b.exact(): b does not fit back into double (as expected)

Calling exact()
a.approx()=[4.94066e-324;4.94066e-324]
b.approx()=[4.94066e-324;4.94066e-324]
Yes, after exact() b fits in double d: 4.94066e-324 - Huh, not as expected!
b >= a, not expected
c=4.94066e-324
c==b, not as expected

详细信息:Ubuntu 18.04,gcc 7.3。我已经使用脚本 CGAL412/Scripts/scripts/cgal_create_cmake_script 创建了 CMakeLists.txt,因此编译器选项应该是正确的。CGAL4.12 已使用从源代码编译

cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/CGAL412  ../..
make
make install

标签: cgal

解决方案


这是 CGAL 中的一个错误。mpfr_set_emin (-1073);除非您自己也直接使用 MPFR,否则您可以通过在程序开头调用来轻松解决此特定值。但是,它可能无法解决所有此类问题(我们还缺少对 mpfr_subnormalize 的调用),例如Gmpq(DBL_TRUE_MIN)*3/2. 最安全的是使用旧代码。为此,#if MPFR_VERSION_MAJOR >= 3在文件 Gmpq.h 和 mpq_class.h 中找到一个测试,并将其替换为#if 0. 我在CGAL 的 github 上提交了这个文件,所以我们不要忘记修复它。


推荐阅读