BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arr_geometry_traits/One_root_number.h
Go to the documentation of this file.
00001 // Copyright (c) 2005  Tel-Aviv University (Israel).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/One_root_number.h $
00015 // $Id: One_root_number.h 40832 2007-11-08 00:27:20Z ameyer $
00016 // 
00017 //
00018 // Author(s)     : Ron Wein        <wein@post.tau.ac.il>
00019 //                 Baruch Zukerman <baruchzu@post.tau.ac.il>
00020                
00021 #ifndef CGAL_ONE_ROOT_NUMBER_H
00022 #define CGAL_ONE_ROOT_NUMBER_H
00023 
00027 #include <CGAL/Interval_arithmetic.h> 
00028 
00029 CGAL_BEGIN_NAMESPACE
00030 
00037 template <class NumberType_, bool Filter_ = true>
00038 class _One_root_number
00039 {
00040 public:
00041 
00042   typedef NumberType_                       NT;
00043   typedef _One_root_number<NT, Filter_>     Self;
00044 
00045 private:
00046 
00047   // The rational coefficients defining the one-root number:
00048   NT        m_alpha;
00049   NT        m_beta;
00050   NT        m_gamma;
00051   bool      m_is_rational;      // Is the number rational (that is, m_beta = 0).
00052 
00053 public:
00054 
00056   _One_root_number () :
00057     m_alpha (0),
00058     m_beta (0),
00059     m_gamma (0),
00060     m_is_rational (true)
00061   {}
00062 
00064   _One_root_number (const NT& val) :
00065     m_alpha (val),
00066     m_beta (0),
00067     m_gamma (0),
00068     m_is_rational (true)
00069   {}
00070 
00072   _One_root_number (const NT& a, const NT& b, const NT& c) :
00073     m_alpha (a),
00074     m_beta (b),
00075     m_gamma (c),
00076     m_is_rational (false)
00077   {
00078     CGAL_precondition (CGAL::sign(c) == POSITIVE);
00079   }
00080 
00082   Self operator- () const
00083   {
00084     if (m_is_rational)
00085       return Self (-m_alpha);
00086     else
00087       return Self (-m_alpha, -m_beta, m_gamma);
00088   }
00089 
00091   Self operator+ (const NT& val) const
00092   {
00093     if (m_is_rational)
00094       return Self (m_alpha + val);
00095     else
00096       return Self (m_alpha + val, m_beta, m_gamma);
00097   }
00098 
00100   Self operator- (const NT& val) const
00101   {
00102     if (m_is_rational)
00103       return Self (m_alpha - val);
00104     else
00105       return Self (m_alpha - val, m_beta, m_gamma);
00106   }
00107 
00109   Self operator* (const NT& val) const
00110   {
00111     if (m_is_rational)
00112       return Self (m_alpha * val);
00113     else
00114       return Self (m_alpha * val, m_beta * val, m_gamma);
00115   }
00116 
00118   Self operator/ (const NT& val) const
00119   {
00120     CGAL_precondition (CGAL::sign(val) != ZERO);
00121 
00122     if (m_is_rational)
00123       return Self (m_alpha / val);
00124     else
00125       return Self (m_alpha / val, m_beta / val, m_gamma);
00126   }
00127 
00128 
00130   void operator+= (const NT& val)
00131   {
00132     m_alpha += val;
00133     return;
00134   }
00135 
00137   void operator-= (const NT& val)
00138   {
00139     m_alpha -= val;
00140     return;
00141   }
00142 
00144   void operator*= (const NT& val)
00145   {
00146     m_alpha *= val;
00147     if (! m_is_rational)
00148       m_beta *= val;
00149     return;
00150   }
00151 
00153   void operator/= (const NT& val)
00154   {
00155     m_alpha /= val;
00156     if (! m_is_rational)
00157       m_beta /= val;
00158     return;
00159   }
00160 
00161   NT alpha() const
00162   {
00163     return (m_alpha);
00164   }
00165 
00166   NT beta() const
00167   {
00168     return (m_beta);
00169   }
00170 
00171   NT gamma() const
00172   {
00173     return (m_gamma);
00174   }
00175 
00176   bool is_rational() const
00177   {
00178     return (m_is_rational);
00179   }
00180 
00181 //private:
00182 
00183   CGAL::Sign _sign () const
00184   {
00185     const CGAL::Sign    sign_alpha = CGAL::sign (m_alpha);
00186 
00187     if (m_is_rational)
00188       return (sign_alpha);
00189 
00190     // If m_alpha and m_beta have the same sign, return this sign.
00191     const CGAL::Sign    sign_beta = CGAL::sign (m_beta);
00192 
00193     if (sign_alpha == sign_beta)
00194       return (sign_alpha);
00195 
00196     if (sign_alpha == ZERO)
00197       return (sign_beta);
00198 
00199     // Compare the squared values of m_alpha and of m_beta*sqrt(m_gamma):
00200     const Comparison_result  res = CGAL::compare (m_alpha*m_alpha,
00201                                                   m_beta*m_beta * m_gamma);
00202 
00203     if (res == LARGER)
00204       return (sign_alpha);
00205     else if (res == SMALLER)
00206       return (sign_beta);
00207     else
00208       return (ZERO);
00209   }
00210 };
00211 
00215 template <class NT, bool FL>
00216 std::pair<double, double> to_interval (const _One_root_number<NT, FL>& x)
00217 {
00218   const CGAL::Interval_nt<true>   alpha_in = to_interval(x.alpha());
00219   const CGAL::Interval_nt<true>   beta_in = to_interval(x.beta());
00220   const CGAL::Interval_nt<true>   gamma_in = to_interval(x.gamma());
00221   const CGAL::Interval_nt<true>&  x_in = alpha_in + 
00222                                          (beta_in * CGAL::sqrt(gamma_in));
00223 
00224   return (std::make_pair (x_in.inf(), x_in.sup()));
00225 }
00226 
00230 template <class NT, bool FL>
00231 _One_root_number<NT, FL> operator+ (const NT& val,
00232                                     const _One_root_number<NT, FL>& x)
00233 {
00234   if (x.is_rational())
00235     return _One_root_number<NT, FL> (val + x.alpha());
00236   else
00237     return _One_root_number<NT, FL> (val + x.alpha(), x.beta(), x.gamma());
00238 }
00239 
00243 template <class NT, bool FL>
00244 _One_root_number<NT, FL> operator- (const NT& val,
00245                                     const _One_root_number<NT, FL>& x)
00246 {
00247   if (x.is_rational())
00248     return _One_root_number<NT, FL> (val - x.alpha());
00249   else
00250     return _One_root_number<NT, FL> (val - x.alpha(), -x.beta(), x.gamma());
00251 }
00252 
00256 template <class NT, bool FL>
00257 _One_root_number<NT, FL> operator* (const NT& val, 
00258                                     const _One_root_number<NT, FL>& x)
00259 {
00260   if (x.is_rational())
00261     return _One_root_number<NT, FL> (val * x.alpha());
00262   else
00263     return _One_root_number<NT, FL> (val * x.alpha(), val * x.beta(), x.gamma());
00264 }
00265 
00269 template <class NT, bool FL>
00270 _One_root_number<NT, FL> operator/ (const NT& val,
00271                                     const _One_root_number<NT, FL>& x)
00272 {
00273   if (x.is_rational())
00274   {
00275     // Simple rational division:
00276     CGAL_precondition (CGAL::sign (x.alpha()) != ZERO);
00277     return _One_root_number<NT, FL> (val / x.alpha());
00278   }
00279 
00280   // Use the fact that:
00281   //
00282   //        v            v * (a - b*sqrt(c))
00283   //   -------------- = ---------------------
00284   //    a + b*sqrt(c)       a^2 - b^2 * c
00285   //
00286   NT   denom = x.alpha()*x.alpha() - x.beta()*x.beta() * x.gamma(); 
00287 
00288   CGAL_precondition (CGAL::sign(denom) != ZERO);
00289 
00290   return _One_root_number<NT, FL> (val * x.alpha() / denom,
00291                                -val * x.beta() / denom, x.gamma());
00292 }
00293 
00297 template <class NT, bool FL>
00298 double to_double (const _One_root_number<NT, FL>& x)
00299 {
00300   if (x.is_rational())
00301     return (CGAL::to_double(x.alpha()));
00302 
00303   return (CGAL::to_double(x.alpha()) +
00304           CGAL::to_double(x.beta()) * std::sqrt(CGAL::to_double(x.gamma()))); 
00305 }
00306 
00310 template <class NT, bool FL>
00311 _One_root_number<NT, FL> square (const _One_root_number<NT, FL>& x)
00312 {
00313   if (x.is_rational())
00314     return _One_root_number<NT, FL> (x.alpha() * x.alpha());
00315 
00316   // Use the equation:
00317   //
00318   //   (a + b*sqrt(c))^2 = (a^2 + b^2*c) + 2ab*sqrt(c)
00319   //
00320   return (_One_root_number<NT, FL> (x.alpha()*x.alpha() + x.beta()*x.beta() * x.gamma(),
00321                                 2 * x.alpha() * x.beta(),
00322                                 x.gamma()));
00323 }
00324 
00328 template <class NT, bool FL>
00329 CGAL::Sign sign (const _One_root_number<NT, FL>& x)
00330 {
00331   if (FL)
00332   {
00333     // Try to filter the sign computation using interval arithmetic.
00334     const std::pair<double, double>&  x_in = CGAL::to_interval (x); 
00335 
00336     if (x_in.first > 0)
00337       return (CGAL::POSITIVE);
00338     else if (x_in.second < 0)
00339       return (CGAL::NEGATIVE);
00340   }
00341 
00342   // Perform the exact sign computation.
00343   return (x._sign());
00344 }
00345 
00349 template <class NT, bool FL>
00350 CGAL::Comparison_result compare (const NT& val,
00351                                  const _One_root_number<NT, FL>& x)
00352 {
00353   if (x.is_rational())
00354     return (CGAL::compare (val, x.alpha()));
00355 
00356   if (FL)
00357   {
00358     // Try to filter the comparison using interval arithmetic.
00359     const std::pair<double, double>&  x_in = CGAL::to_interval (val); 
00360     const std::pair<double, double>&  y_in = CGAL::to_interval (x); 
00361     
00362     if (x_in.second < y_in.first)
00363       return (SMALLER);
00364     else if (x_in.first > y_in.second)
00365       return (LARGER);
00366   }
00367 
00368   // Perform the exact comparison.
00369   const CGAL::Sign   sgn = (val - x)._sign();
00370 
00371   if (sgn == POSITIVE)
00372     return (LARGER);
00373   else if (sgn == NEGATIVE)
00374     return (SMALLER);
00375   else
00376     return (EQUAL);
00377 }
00378 
00382 template <class NT, bool FL>
00383 CGAL::Comparison_result compare (const _One_root_number<NT, FL>& x,
00384                                  const NT& val)
00385 {
00386   if (x.is_rational())
00387     return (CGAL::compare (x.alpha(), val));
00388 
00389   if (FL)
00390   {
00391     // Try to filter the comparison using interval arithmetic.
00392     const std::pair<double, double>&  x_in = CGAL::to_interval (x); 
00393     const std::pair<double, double>&  y_in = CGAL::to_interval (val); 
00394 
00395     if (x_in.second < y_in.first)
00396       return (SMALLER);
00397     else if (x_in.first > y_in.second)
00398       return (LARGER);
00399   }
00400 
00401   // Perform the exact comparison.
00402   const CGAL::Sign   sgn = (x - val)._sign();
00403 
00404   if (sgn == POSITIVE)
00405     return (LARGER);
00406   else if (sgn == NEGATIVE)
00407     return (SMALLER);
00408   else
00409     return (EQUAL);
00410 }
00411 
00415 template <class NT, bool FL>
00416 CGAL::Comparison_result compare (const _One_root_number<NT, FL>& x,
00417                                  const _One_root_number<NT, FL>& y)
00418 {
00419   if (x.is_rational())
00420     return (CGAL::compare (x.alpha(), y));
00421   else if (y.is_rational())
00422     return (CGAL::compare (x, y.alpha()));
00423 
00424   if (FL)
00425   {
00426     // Try to filter the comparison using interval arithmetic.
00427     const std::pair<double, double>&  x_in = CGAL::to_interval (x); 
00428     const std::pair<double, double>&  y_in = CGAL::to_interval (y); 
00429     
00430     if (x_in.second < y_in.first)
00431       return (SMALLER);
00432     else if (x_in.first > y_in.second)
00433       return (LARGER);
00434   }
00435 
00436   // Perform the exact comparison:
00437   // Note that the comparison of (a1 + b1*sqrt(c1)) and (a2 + b2*sqrt(c2))
00438   // is equivalent to comparing (a1 - a2) and (b2*sqrt(c2) -  b1*sqrt(c1)).
00439   // We first determine the signs of these terms.
00440   const NT          diff_alpha = x.alpha() - y.alpha();
00441   const CGAL::Sign  sign_left = CGAL::sign (diff_alpha);
00442   const NT          x_sqr = x.beta()*x.beta() * x.gamma();
00443   const NT          y_sqr = y.beta()*y.beta() * y.gamma();
00444   Comparison_result right_res = CGAL::compare (y_sqr, x_sqr);
00445   CGAL::Sign        sign_right = ZERO;
00446   
00447   if (right_res == LARGER)
00448   {
00449     // Take the sign of b2:
00450     sign_right = CGAL::sign (y.beta());
00451   }
00452   else if (right_res == SMALLER)
00453   {
00454     // Take the opposite sign of b1:
00455     switch (CGAL::sign (x.beta()))
00456     {
00457     case POSITIVE :
00458       sign_right = NEGATIVE;
00459       break;
00460     case NEGATIVE:
00461       sign_right = POSITIVE;
00462       break;
00463     case ZERO:
00464       sign_right = ZERO;
00465       break;
00466     default:
00467       // We should never reach here.
00468       CGAL_error();
00469     }
00470   }
00471   else
00472   {
00473     // We take the sign of (b2*sqrt(c2) -  b1*sqrt(c1)), where both terms
00474     // have the same absolute value. The sign is equal to the sign of b2,
00475     // unless both terms have the same sign, so the whole expression is 0.
00476     sign_right = CGAL::sign (y.beta());
00477     if (sign_right == CGAL::sign (x.beta()))
00478       sign_right = ZERO;
00479   }
00480 
00481   // Check whether on of the terms is zero. In this case, the comparsion
00482   // result is simpler:
00483   if (sign_left == ZERO)
00484   {
00485     if (sign_right == POSITIVE)
00486       return (SMALLER);
00487     else if (sign_right == NEGATIVE)
00488       return (LARGER);
00489     else
00490       return (EQUAL);
00491   }
00492   else if (sign_right == ZERO)
00493   {
00494     if (sign_left == POSITIVE)
00495       return (LARGER);
00496     else if (sign_left == NEGATIVE)
00497       return (SMALLER);
00498     else
00499       return (EQUAL);
00500   }
00501 
00502   // If the signs are not equal, we can determine the comparison result:
00503   if (sign_left != sign_right)
00504   {
00505     if (sign_left == POSITIVE)
00506       return (LARGER);
00507     else
00508       return (SMALLER);
00509   }
00510 
00511   // We now square both terms and look at the sign of the one-root number:
00512   //   ((a1 - a2)^2 - (b1^2*c1 + b2^2*c2)) + 2*b1*b2*sqrt(c1*c2)
00513   //
00514   // If both signs are negative, we should swap the comparsion result
00515   // we eventually compute.
00516   const NT          A = diff_alpha*diff_alpha - (x_sqr + y_sqr);
00517   const NT          B = 2 * x.beta() * y.beta();
00518   const NT          C = x.gamma() * y.gamma();
00519   const CGAL::Sign  sgn = (_One_root_number<NT, FL> (A, B, C))._sign();
00520   const bool        swap_res = (sign_left == NEGATIVE);
00521 
00522   if (sgn == POSITIVE)
00523     return (swap_res ? SMALLER : LARGER);
00524   else if (sgn == NEGATIVE)
00525     return (swap_res ? LARGER : SMALLER);
00526   else
00527     return (EQUAL);
00528 }
00529 
00530 CGAL_END_NAMESPACE
00531 
00532 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines