Я использую Exact_predicates_exact_constructions_kernel в CGAL, чтобы тип числа K :: FT был CGAL :: Lazy_exact_nt.Возникают два вопроса:
- Есть ли способ проверить, является ли 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());
}