diff --git a/Packages/Nef_2/changes.txt b/Packages/Nef_2/changes.txt index 0880c22f5c8..7aa3112fc42 100644 --- a/Packages/Nef_2/changes.txt +++ b/Packages/Nef_2/changes.txt @@ -1,6 +1,10 @@ Nef_2 Package: Release changes ---------------------------------------------------------------------- +1.5 (24 Mar 2002) + - added iterator access function documentation + - converted to use of CGAL_NTS gcd function + 1.4 (22 Mar 2002) - Changed conditional compilation for _MSC_VER to diff --git a/Packages/Nef_2/demo/Nef_2/Nef_polyhedron_2-demo.C b/Packages/Nef_2/demo/Nef_2/Nef_polyhedron_2-demo.C index aeb0783909a..7a2b7f5f912 100644 --- a/Packages/Nef_2/demo/Nef_2/Nef_polyhedron_2-demo.C +++ b/Packages/Nef_2/demo/Nef_2/Nef_polyhedron_2-demo.C @@ -11,14 +11,6 @@ #include #include -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef leda_integer RT; - static RT gcd(const RT& r1, const RT& r2) - { return CGAL_LEDA_SCOPE::gcd(r1,r2); } -}; - #define FILTERED_KERNEL #ifndef FILTERED_KERNEL typedef CGAL::Extended_homogeneous EKernel; diff --git a/Packages/Nef_2/demo/Nef_2/Simple-demo.C b/Packages/Nef_2/demo/Nef_2/Simple-demo.C index dfbb14426e9..36a81d84f38 100644 --- a/Packages/Nef_2/demo/Nef_2/Simple-demo.C +++ b/Packages/Nef_2/demo/Nef_2/Simple-demo.C @@ -6,14 +6,6 @@ #include #include -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef leda_integer RT; - static RT gcd(const RT& r1, const RT& r2) - { return CGAL_LEDA_SCOPE::gcd(r1,r2); } -}; - typedef CGAL::Extended_homogeneous EKernel; typedef CGAL::Nef_polyhedron_2 Nef_polyhedron; typedef Nef_polyhedron::Point Point; diff --git a/Packages/Nef_2/doc_tex/Nef_2_ref/Extended_homogeneous.tex b/Packages/Nef_2/doc_tex/Nef_2_ref/Extended_homogeneous.tex index 68687782e64..14368385b80 100644 --- a/Packages/Nef_2/doc_tex/Nef_2_ref/Extended_homogeneous.tex +++ b/Packages/Nef_2/doc_tex/Nef_2_ref/Extended_homogeneous.tex @@ -32,17 +32,13 @@ representation based on a Euclidean ring number type \ccc{RT}. \ccHeading{Requirements} To make an Euclidean ring number type -\ccc{RT_model} work with this class you have to provide the following -number type traits class in global namespace. +\ccc{RT_model} work with this class the number type must support +a gcd computation in namespace \ccc{CGAL::NTS}. \cgal\ provides +a function template for this, which will be used by default when +your number type is not one of the built-in number types, one of +the number types distrubuted with \cgal\ or one of the \leda\ +number types. -\begin{ccExampleCode} -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - static RT_model gcd(const RT_model& a, const RT_model& b) - { /* provide gcd operation on RT_model here */ } -}; -\end{ccExampleCode} \ccOperations diff --git a/Packages/Nef_2/doc_tex/basic/Nef_2_ref/Extended_homogeneous.tex b/Packages/Nef_2/doc_tex/basic/Nef_2_ref/Extended_homogeneous.tex index 68687782e64..14368385b80 100644 --- a/Packages/Nef_2/doc_tex/basic/Nef_2_ref/Extended_homogeneous.tex +++ b/Packages/Nef_2/doc_tex/basic/Nef_2_ref/Extended_homogeneous.tex @@ -32,17 +32,13 @@ representation based on a Euclidean ring number type \ccc{RT}. \ccHeading{Requirements} To make an Euclidean ring number type -\ccc{RT_model} work with this class you have to provide the following -number type traits class in global namespace. +\ccc{RT_model} work with this class the number type must support +a gcd computation in namespace \ccc{CGAL::NTS}. \cgal\ provides +a function template for this, which will be used by default when +your number type is not one of the built-in number types, one of +the number types distrubuted with \cgal\ or one of the \leda\ +number types. -\begin{ccExampleCode} -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - static RT_model gcd(const RT_model& a, const RT_model& b) - { /* provide gcd operation on RT_model here */ } -}; -\end{ccExampleCode} \ccOperations diff --git a/Packages/Nef_2/include/CGAL/Extended_homogeneous.h b/Packages/Nef_2/include/CGAL/Extended_homogeneous.h index c1ad0b0eb59..3ec40ac68af 100644 --- a/Packages/Nef_2/include/CGAL/Extended_homogeneous.h +++ b/Packages/Nef_2/include/CGAL/Extended_homogeneous.h @@ -357,8 +357,8 @@ on the extended geometric objects.}*/ /*{\Xop only used internally.}*/ { TRACEN("simplify("< #include #include +#include #include #undef _DEBUG #define _DEBUG 3 @@ -50,57 +51,6 @@ #define SNIINST #endif -#define GCD_FOR_BUILTIN(RT) \ -static RT gcd(const RT& a, const RT& b) \ -{ if (a == 0) \ - if (b == 0) return 1; \ - else return CGAL_NTS abs(b); \ - if (b == 0) return CGAL_NTS abs(a); \ - int u = CGAL_NTS abs(a); \ - int v = CGAL_NTS abs(b); \ - if (u < v) v = v%u; \ - while (v != 0) \ - { int tmp = u % v; \ - u = v; \ - v = tmp; \ - } \ - return u; \ -} - -class ring_or_field_dont_know {}; -class ring_with_gcd {}; -class field_with_div {}; - -template -struct ring_or_field { - typedef ring_or_field_dont_know kind; -}; - - - -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef int NT; - GCD_FOR_BUILTIN(int) -}; - -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef long NT; - GCD_FOR_BUILTIN(long) -}; - - -template <> -struct ring_or_field { - typedef field_with_div kind; - typedef double NT; - static double gcd(const double&, const double&) - { return 1.0; } -}; - CGAL_BEGIN_NAMESPACE template class Polynomial_rep; @@ -120,6 +70,14 @@ CGAL_TEMPLATE_NULL class Polynomial ; template typename std::iterator_traits::value_type gcd_of_range(Forward_iterator its, Forward_iterator ite) +{ + typedef typename std::iterator_traits::value_type NT; + return gcd_of_range(its,ite,Number_type_traits::Has_gcd()); +} + +template +typename std::iterator_traits::value_type +gcd_of_range(Forward_iterator its, Forward_iterator ite, Tag_true) /*{\Mfunc calculates the greates common divisor of the set of numbers $\{ |*its|, |*++its|, \ldots, |*it| \}$ of type |NT|, where |++it == ite| and |NT| is the value type of |Forward_iterator|. @@ -129,7 +87,23 @@ where |++it == ite| and |NT| is the value type of |Forward_iterator|. typedef typename std::iterator_traits::value_type NT; NT res = *its++; for(; its!=ite; ++its) res = - (*its==0 ? res : ring_or_field::gcd(res, *its)); + (*its==0 ? res : CGAL_NTS gcd(res, *its)); + if (res==0) res = 1; + return res; +} + +template +typename std::iterator_traits::value_type +gcd_of_range(Forward_iterator its, Forward_iterator ite, Tag_false) +/*{\Mfunc calculates the greates common divisor of the +set of numbers $\{ |*its|, |*++its|, \ldots, |*it| \}$ of type |NT|, +where |++it == ite| and |NT| is the value type of |Forward_iterator|. +\precond |its!=ite|.}*/ +{ CGAL_assertion(its!=ite); + typedef typename std::iterator_traits::value_type NT; + NT res = *its++; + for(; its!=ite; ++its) res = + (*its==0 ? res : 1); if (res==0) res = 1; return res; } @@ -424,8 +398,7 @@ determines the sign for the limit process $x \rightarrow \infty$. #ifndef CGAL_SIMPLE_NEF_INTERFACE NT content() const - /*{\Mop returns the content of |\Mvar| (the gcd of its coefficients). - \precond Requires |NT| to provide a |gdc| operation.}*/ + /*{\Mop returns the content of |\Mvar| (the gcd of its coefficients).}*/ { CGAL_assertion( degree()>=0 ); return gcd_of_range(ptr()->coeff.begin(),ptr()->coeff.end()); } @@ -437,7 +410,7 @@ determines the sign for the limit process $x \rightarrow \infty$. const_iterator its=ptr()->coeff.begin(),ite=ptr()->coeff.end(); NT res = *its++; for(; its!=ite; ++its) res = - (*its==0 ? res : ring_or_field::gcd(res, *its)); + (*its==0 ? res : CGAL_NTS gcd(res, *its)); if (res==0) res = 1; return res; } @@ -475,9 +448,9 @@ determines the sign for the limit process $x \rightarrow \infty$. |p1 = p2 * p3| then |p2| is returned. The result is undefined if |p3| does not exist in |NT[x]|. The correct division algorithm is chosen according to a traits class |ring_or_field| provided by the user. - If |ring_or_field::kind == ring_with_gcd| then the division is + If |Number_type_traits::Has_gcd == Tag_true| then the division is done by \emph{pseudo division} based on a |gcd| operation of |NT|. If - |ring_or_field::kind == field_with_div| then the division is done + |Number_type_traits::Has_gcd == Tag_false| then the division is done by \emph{euclidean division} based on the division operation of the field |NT|. @@ -491,7 +464,7 @@ determines the sign for the limit process $x \rightarrow \infty$. /*{\Mstatic returns the greatest common divisor of |p1| and |p2|. \textbf{Note} that |NT=int| quickly leads to overflow errors when using this operation. \precond Requires |NT| to be a unique - factorization domain, i.e. to provide a |gdc| operation.}*/ + factorization domain, i.e. to provide a |gcd| operation.}*/ static void pseudo_div (const Polynomial& f, const Polynomial& g, @@ -765,7 +738,7 @@ determines the sign for the limit process $x \rightarrow \infty$. int content() const /*{\Xop returns the content of |\Mvar| (the gcd of its coefficients). - \precond Requires |int| to provide a |gdc| operation.}*/ + \precond Requires |int| to provide a |gcd| operation.}*/ { CGAL_assertion( degree()>=0 ); return gcd_of_range(ptr()->coeff.begin(),ptr()->coeff.end()); } @@ -777,7 +750,7 @@ determines the sign for the limit process $x \rightarrow \infty$. const_iterator its=ptr()->coeff.begin(),ite=ptr()->coeff.end(); int res = *its++; for(; its!=ite; ++its) res = - (*its==0 ? res : ring_or_field::gcd(res, *its)); + (*its==0 ? res : CGAL_NTS gcd(res, *its)); if (res==0) res = 1; return res; } @@ -815,9 +788,9 @@ determines the sign for the limit process $x \rightarrow \infty$. |p1 = p2 * p3| then |p2| is returned. The result is undefined if |p3| does not exist in |int[x]|. The correct division algorithm is chosen according to a traits class |ring_or_field| provided by the user. - If |ring_or_field::kind == ring_with_gcd| then the division is + If |Number_type_traits::Has_gcd == Tag_true| then the division is done by \emph{pseudo division} based on a |gcd| operation of |int|. If - |ring_or_field::kind == field_with_div| then the division is done + |Number_type_traits::Has_gcd == Tag_false| then the division is done by \emph{euclidean division} based on the division operation of the field |int|. @@ -831,7 +804,7 @@ determines the sign for the limit process $x \rightarrow \infty$. /*{\Xstatic returns the greatest common divisor of |p1| and |p2|. \textbf{Note} that |int=int| quickly leads to overflow errors when using this operation. \precond Requires |int| to be a unique - factorization domain, i.e. to provide a |gdc| operation.}*/ + factorization domain, i.e. to provide a |gcd| operation.}*/ static void pseudo_div (const Polynomial& f, const Polynomial& g, @@ -1098,7 +1071,7 @@ determines the sign for the limit process $x \rightarrow \infty$. const_iterator its=ptr()->coeff.begin(),ite=ptr()->coeff.end(); double res = *its++; for(; its!=ite; ++its) res = - (*its==0 ? res : ring_or_field::gcd(res, *its)); + (*its==0 ? res : CGAL_NTS gcd(res, *its)); if (res==0) res = 1; return res; } @@ -1136,9 +1109,9 @@ determines the sign for the limit process $x \rightarrow \infty$. |p1 = p2 * p3| then |p2| is returned. The result is undefined if |p3| does not exist in |double[x]|. The correct division algorithm is chosen according to a traits class |ring_or_field| provided by the user. - If |ring_or_field::kind == ring_with_gcd| then the division is + If |Number_type_traits::Has_gcd == Tag_true| then the division is done by \emph{pseudo division} based on a |gcd| operation of |double|. If - |ring_or_field::kind == field_with_div| then the division is done + |Number_type_traits::Has_gcd == Tag_false| then the division is done by \emph{euclidean division} based on the division operation of the field |double|. @@ -1338,33 +1311,16 @@ Polynomial operator * (const Polynomial& p1, return p; } -template /*CGAL_KERNEL_MEDIUM_INLINE*/ -Polynomial divop (const Polynomial& p1, - const Polynomial& p2, - ring_or_field_dont_know) -{ - CGAL_assertion_msg(0,"\n\ - The division operation on polynomials requires that you\n\ - specify if your number type provides a binary gcd() operation\n\ - or is a field type including an operator/().\n\ - You do this by creating a specialized class:\n\ - template <> class ring_or_field with a member type:\n\ - typedef ring_with_gcd kind; OR\n\ - typedef field_with_div kind;\n"); - return Polynomial(); // never reached -} - - template inline Polynomial operator / (const Polynomial& p1, const Polynomial& p2) -{ return divop(p1,p2,ring_or_field::kind()); } +{ return divop(p1,p2,Number_type_traits::Has_gcd()); } template /*CGAL_KERNEL_MEDIUM_INLINE*/ Polynomial divop (const Polynomial& p1, const Polynomial& p2, - field_with_div) + Tag_false) { CGAL_assertion(!p2.is_zero()); if (p1.is_zero()) return 0; Polynomial q,r; @@ -1376,7 +1332,7 @@ Polynomial divop (const Polynomial& p1, template /*CGAL_KERNEL_MEDIUM_INLINE*/ Polynomial divop (const Polynomial& p1, const Polynomial& p2, - ring_with_gcd) + Tag_true) { CGAL_assertion(!p2.is_zero()); if (p1.is_zero()) return 0; Polynomial q,r; NT D; @@ -1933,7 +1889,7 @@ Polynomial Polynomial::gcd( Polynomial f2 = p2.abs(); int f1c = f1.content(), f2c = f2.content(); f1 /= f1c; f2 /= f2c; - int F = ring_or_field::gcd(f1c,f2c); + int F = CGAL_NTS gcd(f1c,f2c); Polynomial q,r; int M=1,D; bool first = true; while ( ! f2.is_zero() ) { @@ -2002,8 +1958,6 @@ void Polynomial::pseudo_div( TRACEN(" returning "< Polynomial::gcd( const Polynomial& p1, const Polynomial& p2) { TRACEN("gcd("< Polynomial::gcd( Polynomial f2 = p2.abs(); double f1c = f1.content(), f2c = f2.content(); f1 /= f1c; f2 /= f2c; - double F = ring_or_field::gcd(f1c,f2c); Polynomial q,r; double M=1,D; bool first = true; while ( ! f2.is_zero() ) { @@ -2029,7 +1982,7 @@ Polynomial Polynomial::gcd( first=false; } TRACEV(f1.content()); - return Polynomial(F)*f1.abs(); + return Polynomial(1)*f1.abs(); } @@ -2101,7 +2054,7 @@ Polynomial Polynomial::gcd( Polynomial f2 = p2.abs(); NT f1c = f1.content(), f2c = f2.content(); f1 /= f1c; f2 /= f2c; - NT F = ring_or_field::gcd(f1c,f2c); + NT F = CGAL_NTS gcd(f1c,f2c); Polynomial q,r; NT M=1,D; bool first = true; while ( ! f2.is_zero() ) { diff --git a/Packages/Nef_2/include/CGAL/Nef_2/Polynomial_MSC.h b/Packages/Nef_2/include/CGAL/Nef_2/Polynomial_MSC.h index 42ab8024703..348937b10ce 100644 --- a/Packages/Nef_2/include/CGAL/Nef_2/Polynomial_MSC.h +++ b/Packages/Nef_2/include/CGAL/Nef_2/Polynomial_MSC.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #undef _DEBUG #define _DEBUG 3 @@ -43,69 +44,6 @@ #define SNIHACK ,char,char #define SNIINST ,'c','c' -class ring_or_field_dont_know {}; -class ring_with_gcd {}; -class field_with_div {}; - -template -struct ring_or_field { - typedef ring_or_field_dont_know kind; -}; - -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef int RT; - static RT gcd(const RT& a, const RT& b) - { if (a == 0) - if (b == 0) return 1; - else return CGAL_NTS abs(b); - if (b == 0) return CGAL_NTS abs(a); - // here both a and b are non-zero - int u = CGAL_NTS abs(a); - int v = CGAL_NTS abs(b); - if (u < v) v = v%u; - while (v != 0) - { int tmp = u % v; - u = v; - v = tmp; - } - return u; - } -}; - -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef long RT; - static RT gcd(const RT& a, const RT& b) - { if (a == 0) - if (b == 0) return 1; - else return CGAL_NTS abs(b); - if (b == 0) return CGAL_NTS abs(a); - // here both a and b are non-zero - int u = CGAL_NTS abs(a); - int v = CGAL_NTS abs(b); - if (u < v) v = v%u; - while (v != 0) - { int tmp = u % v; - u = v; - v = tmp; - } - return u; - } -}; - - -template <> -struct ring_or_field { - typedef field_with_div kind; - typedef double RT; - static RT gcd(const RT& a, const RT& b) - { return 1.0; } -}; - - CGAL_BEGIN_NAMESPACE template class Polynomial_rep_MSC; @@ -252,7 +190,7 @@ public: const_iterator its=ptr()->coeff.begin(),ite=ptr()->coeff.end(); NT res = *its++; for(; its!=ite; ++its) res = - (*its==0 ? res : ring_or_field::gcd(res, *its)); + (*its==0 ? res : CGAL_NTS gcd(res, *its)); if (res==0) res = 1; return res; } @@ -291,7 +229,7 @@ static Polynomial_MSC gcd Polynomial_MSC f2 = p2.abs(); NT f1c = f1.content(), f2c = f2.content(); f1 /= f1c; f2 /= f2c; - NT F = ring_or_field::gcd(f1c,f2c); + NT F = CGAL_NTS gcd(f1c,f2c); Polynomial_MSC q,r; NT M=1,D; bool first = true; while ( ! f2.is_zero() ) { @@ -498,34 +436,18 @@ Polynomial_MSC operator * (const Polynomial_MSC& p1, return p; } -template /*CGAL_KERNEL_MEDIUM_INLINE*/ -Polynomial_MSC divop (const Polynomial_MSC& p1, - const Polynomial_MSC& p2, - ring_or_field_dont_know) -{ - CGAL_assertion_msg(0,"\n\ - The division operation on polynomials requires that you\n\ - specify if your number type provides a binary gcd() operation\n\ - or is a field type including an operator/().\n\ - You do this by creating a specialized class:\n\ - template <> class ring_or_field with a member type:\n\ - typedef ring_with_gcd kind; OR\n\ - typedef field_with_div kind;\n"); - return Polynomial_MSC(); // never reached -} - template inline Polynomial_MSC operator / (const Polynomial_MSC& p1, const Polynomial_MSC& p2) -{ typedef typename ring_or_field::kind KIND; - return divop(p1,p2,KIND()); } +{ typedef typename Number_type_traits::Has_gcd HAS_GCD; + return divop(p1,p2,HAS_GCD()); } template /*CGAL_KERNEL_MEDIUM_INLINE*/ Polynomial_MSC divop (const Polynomial_MSC& p1, const Polynomial_MSC& p2, - field_with_div) + Tag_false) { CGAL_assertion(!p2.is_zero()); if (p1.is_zero()) return 0; Polynomial_MSC q,r; @@ -538,7 +460,7 @@ Polynomial_MSC divop (const Polynomial_MSC& p1, template /*CGAL_KERNEL_MEDIUM_INLINE*/ Polynomial_MSC divop (const Polynomial_MSC& p1, const Polynomial_MSC& p2, - ring_with_gcd) + Tag_true) { CGAL_assertion(!p2.is_zero()); if (p1.is_zero()) return Polynomial_MSC(NT(0)); Polynomial_MSC q,r; NT D; diff --git a/Packages/Nef_2/test/Nef_2/EPoint-test.C b/Packages/Nef_2/test/Nef_2/EPoint-test.C index 9868f3bce7b..82c53789501 100644 --- a/Packages/Nef_2/test/Nef_2/EPoint-test.C +++ b/Packages/Nef_2/test/Nef_2/EPoint-test.C @@ -8,36 +8,14 @@ #ifdef CGAL_USE_LEDA #include typedef leda_integer Integer; -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef leda_integer RT; - static RT gcd(const RT& r1, const RT& r2) - { return ::gcd(r1,r2); } -}; #include typedef leda_real Real; -template <> -struct ring_or_field { - typedef field_with_div kind; -}; #else #ifdef CGAL_USE_GMP #include #include typedef CGAL::Gmpz Integer; -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef CGAL::Gmpz RT; - static RT gcd(const RT& r1, const RT& r2) - { return CGAL::gcd(r1,r2); } -}; typedef CGAL::Quotient Real; -template <> -struct ring_or_field { - typedef field_with_div kind; -}; #else typedef long Integer; typedef double Real; diff --git a/Packages/Nef_2/test/Nef_2/Nef_polyhedron_2-test.C b/Packages/Nef_2/test/Nef_2/Nef_polyhedron_2-test.C index 2ee98235bdb..4edec806c73 100644 --- a/Packages/Nef_2/test/Nef_2/Nef_polyhedron_2-test.C +++ b/Packages/Nef_2/test/Nef_2/Nef_polyhedron_2-test.C @@ -8,24 +8,10 @@ #ifdef CGAL_USE_LEDA #include typedef leda_integer Integer; -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef leda_integer RT; - static RT gcd(const RT& r1, const RT& r2) - { return ::gcd(r1,r2); } -}; #else #ifdef CGAL_USE_GMP #include typedef CGAL::Gmpz Integer; -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef CGAL::Gmpz RT; - static RT gcd(const RT& r1, const RT& r2) - { return CGAL::gcd(r1,r2); } -}; #else typedef long Integer; #endif diff --git a/Packages/Nef_2/test/Nef_2/Polynomial-test.C b/Packages/Nef_2/test/Nef_2/Polynomial-test.C index 5b9133b3c81..b2a15945e18 100644 --- a/Packages/Nef_2/test/Nef_2/Polynomial-test.C +++ b/Packages/Nef_2/test/Nef_2/Polynomial-test.C @@ -9,24 +9,10 @@ #ifdef CGAL_USE_LEDA #include typedef leda_integer Integer; -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef leda_integer RT; - static RT gcd(const RT& r1, const RT& r2) - { return ::gcd(r1,r2); } -}; #else #ifdef CGAL_USE_GMP #include typedef CGAL::Gmpz Integer; -template <> -struct ring_or_field { - typedef ring_with_gcd kind; - typedef CGAL::Gmpz RT; - static RT gcd(const RT& r1, const RT& r2) - { return CGAL::gcd(r1,r2); } -}; #else typedef int Integer; #endif