CGAL's Lazy_exact_nt - PullRequest
       6

CGAL's Lazy_exact_nt

0 голосов
/ 11 мая 2018

Я использую Exact_predicates_exact_constructions_kernel в CGAL, чтобы тип числа K :: FT был CGAL :: Lazy_exact_nt.Возникают два вопроса:

  1. Есть ли способ проверить, является ли K :: FT внутренне просто двойным или значением GMPQ?

Обратите внимание, можно задать (val== to_double (val)), но если true, то val может иметь GMPQ под капотом.

Есть ли способ узнать, зависит ли определенный экземпляр K :: FT от DAG?

РЕДАКТИРОВАТЬ: Спасибо комментариям ниже, я пришел к решению, которое работает для простых чисел и для результатов операций.Но я не могу привести декартовы координаты, возвращенные, например, Point_3 :: x ():

#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
union LazyTool
{
    LazyTool(const CGAL::Lazy_exact_nt<CGAL::Gmpq>* a_):a(a_){}
    LazyTool(const CGAL::Lazy_exact_nt<CGAL::Gmpq>& a_):a(&a_){}

    class AccessLazy:public CGAL::Lazy_exact_nt<CGAL::Gmpq>
    {
    public:
        Self_rep* getPtr() const {return (Self_rep*) PTR;}
    };

    template<class T> bool canCast() const
    {
        return (dynamic_cast<T*>(b->getPtr()) != NULL);
    }

    std::string getInfo() const
    {
        if(b->getPtr()==NULL) return "T_INVALID";
        typedef const CGAL::Lazy_exact_Cst<CGAL::Gmpq,double> T_DOUBLE;
        typedef const CGAL::Lazy_exact_Cst<CGAL::Gmpq,int> T_INT;
        typedef const CGAL::Lazy_exact_Ex_Cst<CGAL::Gmpq> T_GMPQ;
        typedef const CGAL::Lazy_exact_unary<CGAL::Gmpq> T_UNARY_OPERATION;
        typedef const CGAL::Lazy_exact_binary<CGAL::Gmpq> T_BINARY_OPERATION;
        if(canCast<T_DOUBLE>()) return "T_DOUBLE";
        if(canCast<T_INT>()) return "T_INT";
        if(canCast<T_GMPQ>()) return "T_GMPQ";
        if(canCast<T_UNARY_OPERATION>()) return "T_UNARY_OPERATION";
        if(canCast<T_BINARY_OPERATION>()) return "T_BINARY_OPERATION";
        return "T_UNKNOWN";
    }
    bool isLazy() const
    {
        return b->getPtr()->is_lazy();
    }
    const CGAL::Lazy_exact_nt<CGAL::Gmpq>* a;
    const AccessLazy* b;
};

int main(int,char** )
{
    typedef K::FT dbl;

    dbl a(1);
    dbl b(1.0);
    dbl c(std::string("1/10"));
    dbl d(abs(c));
    dbl e(b+c);
    Point_3 p(a,a,a);
    dbl x(p.x());

    cout<<"a="<<LazyTool(a).getInfo()<<endl;
    cout<<"b="<<LazyTool(b).getInfo()<<endl;
    cout<<"c="<<LazyTool(c).getInfo()<<endl;
    cout<<"d="<<LazyTool(d).getInfo()<<endl;
    cout<<"e="<<LazyTool(e).getInfo()<<endl;
    cout<<"x="<<LazyTool(x).getInfo()<<endl;
}

В результате получается

a=T_INT
b=T_DOUBLE
c=T_GMPQ
d=T_UNARY_OPERATION
e=T_BINARY_OPERATION
x=T_UNKNOWN

Я попытался выяснить тип, возвращаемыйPoint_3 :: x (), но Point_3 :: x () использует Functor Compute_x_3, который, кажется, возвращает только Interval_nt \ даже для точных значений (что не имеет смысла - хотя это работает очевидно, но я не понимаю магию за кадром)).

В: К какому типу мне нужно привести x?

EDIT2: Эта функция разъединяет, возможно, ленивые значения (использование fit_in_double (..), вероятно, будет более эффективным):

typedef K::FT dbl;
void decouple(const dbl& val,dbl& decoupled)
{
    // Representable as a double value? Then reconstruct from double
    double dval(to_double(val));
    if(dval==val)
    {
        decoupled=dval;
        return;
    }

    // Otherwise reconstruct from string
    stringstream ss;
    ss<<val.exact();
    decoupled=dbl(ss.str());
}
...