⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 one_root_number.h

📁 很多二维 三维几何计算算法 C++ 类库
💻 H
字号:
// Copyright (c) 2005  Tel-Aviv University (Israel).// All rights reserved.//// This file is part of CGAL (www.cgal.org); you may redistribute it under// the terms of the Q Public License version 1.0.// See the file LICENSE.QPL distributed with CGAL.//// Licensees holding a valid commercial license may use this file in// accordance with the commercial license agreement provided with the software.//// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.3-branch/Arrangement_2/include/CGAL/Arr_traits_2/One_root_number.h $// $Id: One_root_number.h 34763 2006-10-11 12:41:46Z wein $// //// Author(s)     : Ron Wein        <wein@post.tau.ac.il>//                 Baruch Zukerman <baruchzu@post.tau.ac.il>               #ifndef CGAL_ONE_ROOT_NUMBER_H#define CGAL_ONE_ROOT_NUMBER_H/*! \file * Header file for the One_root_number<NT> class. */#include <CGAL/Interval_arithmetic.h> CGAL_BEGIN_NAMESPACE/*! \class * Representation of a one-root number - that is, a number of the form * m_alpha + m_beta*sqrt(m_gamma), where m_alpha, m_beta and m_gamma are all rational * numbers (actually they should be represented by a number type that supports * the operators +, -, * and / in an exact manner). */template <class NumberType_, bool Filter_ = true>class _One_root_number{public:  typedef NumberType_                       NT;  typedef _One_root_number<NT, Filter_>     Self;private:  // The rational coefficients defining the one-root number:  NT        m_alpha;  NT        m_beta;  NT        m_gamma;  bool      m_is_rational;      // Is the number rational (i.e., m_beta = 0).public:  /*! Default constructor. */  _One_root_number () :    m_alpha (0),    m_beta (0),    m_gamma (0),    m_is_rational (true)  {}  /*! Constructor from a rational number. */  _One_root_number (const NT& val) :    m_alpha (val),    m_beta (0),    m_gamma (0),    m_is_rational (true)  {}  /*! Construct the one-root number a + b*sqrt(c). */  _One_root_number (const NT& a, const NT& b, const NT& c) :    m_alpha (a),    m_beta (b),    m_gamma (c),    m_is_rational (false)  {    CGAL_precondition (CGAL::sign(c) == POSITIVE);  }  /*! Unary minus. */  Self operator- () const  {    if (m_is_rational)      return Self (-m_alpha);    else      return Self (-m_alpha, -m_beta, m_gamma);  }  /*! Add a rational number. */  Self operator+ (const NT& val) const  {    if (m_is_rational)      return Self (m_alpha + val);    else      return Self (m_alpha + val, m_beta, m_gamma);  }  /*! Subtract a rational number. */  Self operator- (const NT& val) const  {    if (m_is_rational)      return Self (m_alpha - val);    else      return Self (m_alpha - val, m_beta, m_gamma);  }  /*! Multiply by a rational number. */  Self operator* (const NT& val) const  {    if (m_is_rational)      return Self (m_alpha * val);    else      return Self (m_alpha * val, m_beta * val, m_gamma);  }  /*! Divide by a rational number. */  Self operator/ (const NT& val) const  {    CGAL_precondition (CGAL::sign(val) != ZERO);    if (m_is_rational)      return Self (m_alpha / val);    else      return Self (m_alpha / val, m_beta / val, m_gamma);  }  /*! Add and assign a rational number. */  void operator+= (const NT& val)  {    m_alpha += val;    return;  }  /*! Subtract and assign a rational number. */  void operator-= (const NT& val)  {    m_alpha -= val;    return;  }  /*! Multiply and assign by a rational number. */  void operator*= (const NT& val)  {    m_alpha *= val;    if (! m_is_rational)      m_beta *= val;    return;  }  /*! Divide and assign by a rational number. */  void operator/= (const NT& val)  {    m_alpha /= val;    if (! m_is_rational)      m_beta /= val;    return;  }  /// \name Get the rational coefficients defining the one-root number.  //@{  const NT& alpha() const  {    return (m_alpha);  }  const NT& beta() const  {    return (m_beta);  }  const NT& gamma() const  {    return (m_gamma);  }  //@}  /*! Check if the number is rational. */  bool is_rational() const  {    return (m_is_rational);  }  /// \name Auxiliary functions (not for public usage).  //@{  CGAL::Sign _sign () const  {    const CGAL::Sign    sign_alpha = CGAL::sign (m_alpha);    if (m_is_rational)      return (sign_alpha);    // If m_alpha and m_beta have the same sign, return this sign.    const CGAL::Sign    sign_beta = CGAL::sign (m_beta);    if (sign_alpha == sign_beta)      return (sign_alpha);    if (sign_alpha == ZERO)      return (sign_beta);    // Compare the squared values of m_alpha and of m_beta*sqrt(m_gamma):    const Comparison_result  res = CGAL::compare (m_alpha*m_alpha,                                                  m_beta*m_beta * m_gamma);    if (res == LARGER)      return (sign_alpha);    else if (res == SMALLER)      return (sign_beta);    else      return (ZERO);  }  //@}};/*! * Compute an isolating interval for the one-root number. */template <class NT, bool FL>std::pair<double, double> to_interval (const _One_root_number<NT, FL>& x){  const CGAL::Interval_nt<true>   alpha_in = to_interval(x.alpha());  const CGAL::Interval_nt<true>   beta_in = to_interval(x.beta());  const CGAL::Interval_nt<true>   gamma_in = to_interval(x.gamma());  const CGAL::Interval_nt<true>&  x_in = alpha_in +                                          (beta_in * CGAL::sqrt(gamma_in));  return (std::make_pair (x_in.inf(), x_in.sup()));}/*! * Add a rational number and a one-root number. */template <class NT, bool FL>_One_root_number<NT, FL> operator+ (const NT& val,                                    const _One_root_number<NT, FL>& x){  if (x.is_rational())    return _One_root_number<NT, FL> (val + x.alpha());  else    return _One_root_number<NT, FL> (val + x.alpha(), x.beta(), x.gamma());}/*! * Subtract a one-root number from a rational number. */template <class NT, bool FL>_One_root_number<NT, FL> operator- (const NT& val,                                    const _One_root_number<NT, FL>& x){  if (x.is_rational())    return _One_root_number<NT, FL> (val - x.alpha());  else    return _One_root_number<NT, FL> (val - x.alpha(), -x.beta(), x.gamma());}/*! * Multiply a rational number and a one-root number. */template <class NT, bool FL>_One_root_number<NT, FL> operator* (const NT& val,                                     const _One_root_number<NT, FL>& x){  if (x.is_rational())    return _One_root_number<NT, FL> (val * x.alpha());  else    return _One_root_number<NT, FL> (val * x.alpha(), val * x.beta(), x.gamma());}/*! * Divide a rational number by a one-root number. */template <class NT, bool FL>_One_root_number<NT, FL> operator/ (const NT& val,                                    const _One_root_number<NT, FL>& x){  if (x.is_rational())  {    // Simple rational division:    CGAL_precondition (CGAL::sign (x.alpha()) != ZERO);    return _One_root_number<NT, FL> (val / x.alpha());  }  // Use the fact that:  //  //        v            v * (a - b*sqrt(c))  //   -------------- = ---------------------  //    a + b*sqrt(c)       a^2 - b^2 * c  //  NT   denom = x.alpha()*x.alpha() - x.beta()*x.beta() * x.gamma();   CGAL_precondition (CGAL::sign(denom) != ZERO);  return _One_root_number<NT, FL> (val * x.alpha() / denom,                               -val * x.beta() / denom, x.gamma());}/*! * Get a double-precision approximation of the one-root number. */template <class NT, bool FL>double to_double (const _One_root_number<NT, FL>& x){  if (x.is_rational())    return (CGAL::to_double(x.alpha()));  return (CGAL::to_double(x.alpha()) +          CGAL::to_double(x.beta()) * std::sqrt(CGAL::to_double(x.gamma()))); }/*! * Compute the square of a one-root number. */template <class NT, bool FL>_One_root_number<NT, FL> square (const _One_root_number<NT, FL>& x){  if (x.is_rational())    return _One_root_number<NT, FL> (x.alpha() * x.alpha());  // Use the equation:  //  //   (a + b*sqrt(c))^2 = (a^2 + b^2*c) + 2ab*sqrt(c)  //  return (_One_root_number<NT, FL> (x.alpha()*x.alpha() + x.beta()*x.beta() * x.gamma(),                                2 * x.alpha() * x.beta(),                                x.gamma()));}/*! * Evaluate the sign of a one-root number. */template <class NT, bool FL>CGAL::Sign sign (const _One_root_number<NT, FL>& x){  if (FL)  {    // Try to filter the sign computation using interval arithmetic.    const std::pair<double, double>&  x_in = CGAL::to_interval (x);     if (x_in.first > 0)      return (CGAL::POSITIVE);    else if (x_in.second < 0)      return (CGAL::NEGATIVE);  }  // Perform the exact sign computation.  return (x._sign());}/*! * Compare a rational number and a one-root number. */template <class NT, bool FL>CGAL::Comparison_result compare (const NT& val,                                 const _One_root_number<NT, FL>& x){  if (x.is_rational())    return (CGAL::compare (val, x.alpha()));  if (FL)  {    // Try to filter the comparison using interval arithmetic.    const std::pair<double, double>&  x_in = CGAL::to_interval (val);     const std::pair<double, double>&  y_in = CGAL::to_interval (x);         if (x_in.second < y_in.first)      return (SMALLER);    else if (x_in.first > y_in.second)      return (LARGER);  }  // Perform the exact comparison.  const CGAL::Sign   sgn = (val - x)._sign();  if (sgn == POSITIVE)    return (LARGER);  else if (sgn == NEGATIVE)    return (SMALLER);  else    return (EQUAL);}/*! * Compare a rational number and a one-root number. */template <class NT, bool FL>CGAL::Comparison_result compare (const _One_root_number<NT, FL>& x,                                 const NT& val){  if (x.is_rational())    return (CGAL::compare (x.alpha(), val));  if (FL)  {    // Try to filter the comparison using interval arithmetic.    const std::pair<double, double>&  x_in = CGAL::to_interval (x);     const std::pair<double, double>&  y_in = CGAL::to_interval (val);     if (x_in.second < y_in.first)      return (SMALLER);    else if (x_in.first > y_in.second)      return (LARGER);  }  // Perform the exact comparison.  const CGAL::Sign   sgn = (x - val)._sign();  if (sgn == POSITIVE)    return (LARGER);  else if (sgn == NEGATIVE)    return (SMALLER);  else    return (EQUAL);}/*! * Compare two one-root numbers. */template <class NT, bool FL>CGAL::Comparison_result compare (const _One_root_number<NT, FL>& x,                                 const _One_root_number<NT, FL>& y){  if (x.is_rational())    return (CGAL::compare (x.alpha(), y));  else if (y.is_rational())    return (CGAL::compare (x, y.alpha()));  if (FL)  {    // Try to filter the comparison using interval arithmetic.    const std::pair<double, double>&  x_in = CGAL::to_interval (x);     const std::pair<double, double>&  y_in = CGAL::to_interval (y);         if (x_in.second < y_in.first)      return (SMALLER);    else if (x_in.first > y_in.second)      return (LARGER);  }  // Perform the exact comparison:  // Note that the comparison of (a1 + b1*sqrt(c1)) and (a2 + b2*sqrt(c2))  // is equivalent to comparing (a1 - a2) and (b2*sqrt(c2) -  b1*sqrt(c1)).  // We first determine the signs of these terms.  const NT          diff_alpha = x.alpha() - y.alpha();  const CGAL::Sign  sign_left = CGAL::sign (diff_alpha);  const NT          x_sqr = x.beta()*x.beta() * x.gamma();  const NT          y_sqr = y.beta()*y.beta() * y.gamma();  Comparison_result right_res = CGAL::compare (y_sqr, x_sqr);  CGAL::Sign        sign_right = ZERO;    if (right_res == LARGER)  {    // Take the sign of b2:    sign_right = CGAL::sign (y.beta());  }  else if (right_res == SMALLER)  {    // Take the opposite sign of b1:    switch (CGAL::sign (x.beta()))    {    case POSITIVE :      sign_right = NEGATIVE;      break;    case NEGATIVE:      sign_right = POSITIVE;      break;    case ZERO:      sign_right = ZERO;      break;    default:      // We should never reach here.      CGAL_assertion (false);    }  }  else  {    // We take the sign of (b2*sqrt(c2) -  b1*sqrt(c1)), where both terms    // have the same absolute value. The sign is equal to the sign of b2,    // unless both terms have the same sign, so the whole expression is 0.    sign_right = CGAL::sign (y.beta());    if (sign_right == CGAL::sign (x.beta()))      sign_right = ZERO;  }  // Check whether on of the terms is zero. In this case, the comparsion  // result is simpler:  if (sign_left == ZERO)  {    if (sign_right == POSITIVE)      return (SMALLER);    else if (sign_right == NEGATIVE)      return (LARGER);    else      return (EQUAL);  }  else if (sign_right == ZERO)  {    if (sign_left == POSITIVE)      return (LARGER);    else if (sign_left == NEGATIVE)      return (SMALLER);    else      return (EQUAL);  }  // If the signs are not equal, we can determine the comparison result:  if (sign_left != sign_right)  {    if (sign_left == POSITIVE)      return (LARGER);    else      return (SMALLER);  }  // We now square both terms and look at the sign of the one-root number:  //   ((a1 - a2)^2 - (b1^2*c1 + b2^2*c2)) + 2*b1*b2*sqrt(c1*c2)  //  // If both signs are negative, we should swap the comparsion result  // we eventually compute.  const NT          A = diff_alpha*diff_alpha - (x_sqr + y_sqr);  const NT          B = 2 * x.beta() * y.beta();  const NT          C = x.gamma() * y.gamma();  const CGAL::Sign  sgn = (_One_root_number<NT, FL> (A, B, C))._sign();  const bool        swap_res = (sign_left == NEGATIVE);  if (sgn == POSITIVE)    return (swap_res ? SMALLER : LARGER);  else if (sgn == NEGATIVE)    return (swap_res ? LARGER : SMALLER);  else    return (EQUAL);}/*! * Casting to a rational number. * \param x A one-root number. * \pre The number is indeed rational. */template <class NT, bool FL>const NT& to_rational (const _One_root_number<NT, FL>& x){  CGAL_precondition (x.is_rational());  return (x.alpha());}CGAL_END_NAMESPACE#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -