BWAPI
|
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