// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// 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$
// $Id$
// 
//
// Author(s)     : Michael Hemmer <hemmer@mpi-inf.mpg.de>    
//                 Sebastian Limbach <slimbach@mpi-inf.mpg.de>
//                 Michael Kerber    <mkerber@mpi-inf.mpg.de>
//
// ============================================================================

#ifndef CGAL_ALGEBRAIC_KERNEL_D_1_H
#define CGAL_ALGEBRAIC_KERNEL_D_1_H

#ifndef CGAL_AK_ENABLE_DEPRECATED_INTERFACE 
#define CGAL_AK_ENABLE_DEPRECATED_INTERFACE 0
#endif 

#include <CGAL/basic.h>
#include <CGAL/Algebraic_kernel_d/flags.h>
#include <CGAL/Polynomial.h>

#include <CGAL/Arithmetic_kernel.h>
#include <CGAL/Algebraic_kernel_d/Algebraic_real_d_1.h>
#include <CGAL/Algebraic_kernel_d/Descartes.h>
#include <CGAL/Algebraic_kernel_d/Real_roots.h>
#include <CGAL/Algebraic_kernel_d/refine_zero_against.h>
#include <CGAL/Algebraic_kernel_d/Interval_evaluate_1.h>
#include <CGAL/Algebraic_kernel_d/bound_between_1.h>
#include <CGAL/ipower.h>

namespace CGAL {

namespace internal {
template< class AlgebraicReal1, class Isolator_ >
class Algebraic_kernel_d_1_base {
  
public:
  typedef AlgebraicReal1                              Algebraic_real_1;
  typedef Isolator_                                   Isolator;
            
  typedef typename Algebraic_real_1::Coefficient      Coefficient;
  typedef typename Algebraic_real_1::Bound            Bound;
  typedef typename Algebraic_real_1::Polynomial_1     Polynomial_1;

  // TODO: Other choice?
  typedef int size_type;
  typedef int Multiplicity_type;

private:
  typedef CGAL::Polynomial_traits_d< Polynomial_1 >   PT_1;


protected:

  // Some functors used for STL calls
  template<typename A,typename B>
    struct Pair_first : public std::unary_function<std::pair<A,B>,A> {
      A operator() (std::pair<A,B> pair) const { return pair.first; }
  };

  template<typename A,typename B>
    struct Pair_second : public std::unary_function<std::pair<A,B>,B> {
      B operator() (std::pair<A,B> pair) const { return pair.second; }
  };
  
public:    
  class Algebraic_real_traits {
  public:
    typedef Algebraic_real_1                      Type;
    
    struct Bound_between 
      : public std::binary_function< Type, Type, Bound > {
      Bound operator()( const Type& t1, 
          const Type& t2 ) const {
#if CGAL_AK_DONT_USE_SIMPLE_BOUND_BETWEEN
#warning uses deprecated bound_between_1 functor
        return t1.rational_between( t2 );
#else
	return internal::simple_bound_between(t1,t2);
#endif
      }
    };
                                
    struct Lower_bound
      : public std::unary_function< Type, Bound > {
      Bound operator()( const Type& t ) const {
        return t.low();
      }
    };
                
    struct Upper_bound
      : public std::unary_function< Type, Bound > {
      Bound operator()( const Type& t ) const {
        return t.high();
      }
    };
                
    struct Refine
      : public std::unary_function< Type, void > {
      void operator()( const Type& t ) const {
        t.refine();
      }
                    
      void operator()( Type& t, int rel_prec ) const {
        // If t is zero, we can refine the interval to
        //  infinite precission
        if( CGAL::is_zero( t ) ) {
          t = Type(0);                            
        } else {
          // Refine until both boundaries have the same sign
          while( CGAL::sign( t.high() ) != 
              CGAL::sign( t.low() ) )
            t.refine();
                            
          CGAL_assertion( CGAL::sign( t.high() ) != CGAL::ZERO &&
              CGAL::sign( t.low() ) != CGAL::ZERO );
                            
          // Calculate the needed precision
          Bound prec = Bound(1) / 
            CGAL::ipower( Bound(2), rel_prec );
                            
          // Refine until precision is reached
          while( CGAL::abs( t.high() - t.low() ) /
                 (CGAL::max)( CGAL::abs( t.high() ),
                              CGAL::abs( t.low() ) ) > prec ) {
            t.refine();

            CGAL_assertion( CGAL::sign( t.high() ) != CGAL::ZERO &&
                CGAL::sign( t.low() ) != CGAL::ZERO );
                                
          } 
        }                        
      }
    };              
    
    struct Approximate_absolute_1:
      public std::binary_function<Algebraic_real_1,int,std::pair<Bound,Bound> >{
      std::pair<Bound,Bound> 
      operator()(const Algebraic_real_1& x, int prec) const {
        Lower_bound lower; 
        Upper_bound upper; 
        Refine refine; 
        Bound l = lower(x);  
        Bound u = upper(x);
        Bound error = CGAL::ipower(Bound(2),CGAL::abs(prec));
        while((prec>0)?((u-l)*error>Bound(1)):((u-l)>error)){
          refine(x);
          u = upper(x);
          l = lower(x);
        }
        return std::make_pair(l,u);
      }
    }; 
    
    struct Approximate_relative_1:
      public std::binary_function<Algebraic_real_1,int,std::pair<Bound,Bound> >{
      std::pair<Bound,Bound> 
      operator()(const Algebraic_real_1& x, int prec) const {
        
        if(CGAL::is_zero(x)) return std::make_pair(Bound(0),Bound(0));
        
        Lower_bound lower; 
        Upper_bound upper; 
        Refine refine; 
        Bound l = lower(x);  
        Bound u = upper(x);
        Bound error = CGAL::ipower(Bound(2),CGAL::abs(prec));
        Bound min_b = (CGAL::min)(CGAL::abs(u),CGAL::abs(l));
        while((prec>0)?((u-l)*error>min_b):((u-l)>error*min_b)){
          refine(x);
          u = upper(x);
          l = lower(x);
          min_b = (CGAL::min)(CGAL::abs(u),CGAL::abs(l));
        }
        return std::make_pair(l,u);
      }
    };

#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
    typedef Lower_bound Lower_boundary;
    typedef Upper_bound Upper_boundary;
    typedef Bound_between Boundary_between; 
#endif    


  }; // class Algebraic_real_traits
            
  // Functors of Algebraic_kernel_d_1
  struct Solve_1 {
  public:
    template <class OutputIterator>
    OutputIterator 
    operator()(const Polynomial_1& p, OutputIterator oi) const {  
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
#else
      CGAL_precondition(!CGAL::is_zero(p));
#endif
      internal::Real_roots< Algebraic_real_1, Isolator > real_roots; 
      std::list< int > mults;
      std::list< Algebraic_real_1 > roots; 
      real_roots( p, std::back_inserter(roots), std::back_inserter( mults ) );
      CGAL_assertion(roots.size()==mults.size());
      std::list<int>::iterator mit =mults.begin();
      typename std::list< Algebraic_real_1 >::iterator rit = roots.begin();
      while(rit != roots.end()) {
        //*oi++ = std::make_pair(*rit, (unsigned int)(*mit));
        *oi++ = std::make_pair(*rit, *mit);
        rit++;
        mit++;
      }
      return oi;
    }
    
#if 1 || CGAL_AK_ENABLE_DEPRECATED_INTERFACE
    template< class OutputIterator >
    OutputIterator operator()( 
        const Polynomial_1& p, 
        OutputIterator oi , 
        bool known_to_be_square_free) const {
      return this->operator()(p,known_to_be_square_free,oi);
    }
#endif

    template< class OutputIterator >
    OutputIterator operator()( 
        const Polynomial_1& p, 
        bool known_to_be_square_free,
        OutputIterator oi) const {

      internal::Real_roots< Algebraic_real_1, Isolator > real_roots; 
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
#else
      CGAL_precondition(!CGAL::is_zero(p));
#endif
      std::list<Algebraic_real_1> roots; 
      if( known_to_be_square_free ){
        real_roots(p,std::back_inserter(roots));
      }else{
        std::list<int> dummy;
        real_roots(p,std::back_inserter(roots),std::back_inserter(dummy));
      }
      return std::copy(roots.begin(),roots.end(),oi);
    }

#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
    template< class OutputIteratorRoots , class OutputIteratorMults >
    std::pair<OutputIteratorRoots,OutputIteratorMults> 
    operator()( 
        const Polynomial_1& p, 
        OutputIteratorRoots roi,
        OutputIteratorMults moi) const {

      internal::Real_roots< Algebraic_real_1, Isolator > real_roots; 
      real_roots(p,roi,moi);
      return std::make_pair(roi,moi);
    }
#endif

    protected:
    
    /*
    // TODO: Can we avoid to use this?
    struct Greater_compare : 
      public std::binary_function<Algebraic_real_1,Algebraic_real_1,bool> {
      
      bool operator() (const Algebraic_real_1& a, const Algebraic_real_1& b)
	const {
	return a>b;
      }
      
    };
    */

    public:

    template< class OutputIterator >
    OutputIterator operator()(const Polynomial_1& p, Bound l, Bound u,
			      OutputIterator res) const {
      
      std::vector<std::pair<Algebraic_real_1,Multiplicity_type> > roots;
      this->operator() (p,std::back_inserter(roots));
      Algebraic_real_1 alg_l=Construct_algebraic_real_1()(l);
      Algebraic_real_1 alg_u=Construct_algebraic_real_1()(u);
      typedef typename
	std::vector<std::pair<Algebraic_real_1,Multiplicity_type> >::iterator
	Iterator;
      Pair_first<Algebraic_real_1,Multiplicity_type> pair_first;
      Iterator it_start=std::lower_bound
	(::boost::make_transform_iterator(roots.begin(),pair_first),
	 ::boost::make_transform_iterator(roots.end(),pair_first),
	 alg_l).base();
      Iterator it_end=std::upper_bound
	(::boost::make_transform_iterator(it_start,pair_first),
	 ::boost::make_transform_iterator(roots.end(),pair_first),
	 alg_u).base();
      std::copy(it_start,it_end,res);
      return res;
    }

    template< class OutputIterator >
    OutputIterator operator()(const Polynomial_1& p, 
			      bool known_to_be_square_free,
			      Bound l, Bound u,
			      OutputIterator res) const {
      
      std::vector<Algebraic_real_1 > roots;
      this->operator() (p,known_to_be_square_free,std::back_inserter(roots));
      Algebraic_real_1 alg_l=Construct_algebraic_real_1()(l);
      Algebraic_real_1 alg_u=Construct_algebraic_real_1()(u);
      typedef typename
	std::vector<Algebraic_real_1>::iterator
	Iterator;
      Iterator it_start=std::lower_bound(roots.begin(),roots.end(),alg_l);
      Iterator it_end=std::upper_bound(it_start,roots.end(),alg_u);
      std::copy(it_start,it_end,res);
      return res;
    }

  };

  class Number_of_solutions_1 
      : public std::unary_function<Polynomial_1,size_type> {
    
    public:
	
      size_type operator() 
	(const Polynomial_1& p) const {

	std::vector<std::pair<Algebraic_real_1,Multiplicity_type> > roots;
	Solve_1()(p,std::back_inserter(roots));
	return roots.size(); 
      }

  };

            
  struct Sign_at_1 
    : public std::binary_function< Polynomial_1, Algebraic_real_1, CGAL::Sign > {
    CGAL::Sign operator()( const Polynomial_1& p, const Algebraic_real_1& ar ) const {
      if(CGAL::is_zero(p)) return ZERO; 
      if(CGAL::degree(p)==0) return p.sign_at(0);
      if( ar.low() == ar.high() ) return p.sign_at( ar.low() );

      if (p == ar.polynomial()) {
        return ZERO;
      }

      Polynomial_1 g = gcd_utcf(p,ar.polynomial());
      if (g.sign_at(ar.low()) != g.sign_at(ar.high())) return ZERO; 
     
      while(internal::descartes(p,ar.low(),ar.high()) > 0) ar.refine();
      while( p.sign_at(ar.low())  == ZERO )  ar.refine();
      while( p.sign_at(ar.high()) == ZERO )  ar.refine();

      CGAL::Sign result = p.sign_at(ar.low());
      CGAL_assertion(result == p.sign_at(ar.high()));
      return result; 
    }
  };                
  struct Is_zero_at_1 
    : public std::binary_function< Polynomial_1, Algebraic_real_1, bool > {
    bool operator()( const Polynomial_1& p, const Algebraic_real_1& ar ) const {
      if(CGAL::is_zero(p)) return true; 
      if( ar.low() == ar.high() ) return p.sign_at( ar.low() ) == ZERO;
      Polynomial_1 g = gcd_utcf(p,ar.polynomial());
      return g.sign_at(ar.low()) != g.sign_at(ar.high());
    }
  };                
                   
  struct Is_square_free_1 
    : public std::unary_function< Polynomial_1, bool > {
    bool operator()( const Polynomial_1& p ) const {
      typename CGAL::Polynomial_traits_d< Polynomial_1 >::Is_square_free isf;
      return isf(p);
    }
  };
            
  struct Is_coprime_1
    : public std::binary_function< Polynomial_1, Polynomial_1, bool > {
    bool operator()( const Polynomial_1& p1, const Polynomial_1& p2 ) const {
      typename CGAL::Polynomial_traits_d< Polynomial_1 >::Total_degree total_degree;
                        
      // TODO: Is GCD already filtered? 
      return( total_degree( gcd_utcf( p1, p2 ) ) == 0 );                        
    } 
  }; 
            
  struct Make_square_free_1
    : public std::unary_function< Polynomial_1, Polynomial_1 > {
    Polynomial_1 operator()( const Polynomial_1& p ) const {
      return typename CGAL::Polynomial_traits_d< Polynomial_1 >::Make_square_free()( p );
    }
  };
            
  struct Make_coprime_1 {
    typedef bool         result_type;
    typedef Polynomial_1 first_argument_type;
    typedef Polynomial_1 second_argument_type;
    typedef Polynomial_1 third_argument_type;
    typedef Polynomial_1 fourth_argument_type;
    typedef Polynomial_1 fifth_argument_type;
                
    bool operator()( const Polynomial_1& p1,
        const Polynomial_1& p2,
        Polynomial_1& g, // ggT utcf 
        Polynomial_1& q1, // Rest utcf
        Polynomial_1& q2 ) const {
      g = typename CGAL::Polynomial_traits_d< Polynomial_1 >::Gcd_up_to_constant_factor()( p1, p2 );
      q1 = p1 / g;
      q2 = p2 / g;
      return CGAL::is_one(g);
    }                 
  };
            

  struct Square_free_factorize_1 {
    template< class OutputIterator>
    OutputIterator operator()( const Polynomial_1& p, OutputIterator it) const {
      typename PT_1::Square_free_factorize_up_to_constant_factor sqff;
      return sqff(p,it);
    } 
  };

  struct Compute_polynomial_1 : public std::unary_function<Algebraic_real_1,
                                                           Polynomial_1> {
    Polynomial_1 operator()(const Algebraic_real_1& x) const {
      return x.polynomial();
    }
  };
  
  struct Construct_algebraic_real_1 {

    public:

      typedef Algebraic_real_1 result_type;

      result_type operator() (int a) const {
	return Algebraic_real_1(a);
      }

      result_type operator() (Bound a) const {
	return Algebraic_real_1(a);
      }

      result_type operator() 
      (typename CGAL::First_if_different<Coefficient,Bound>::Type a) const {
	Coefficient coeffs[2] = {a,Coefficient(-1)};
	Polynomial_1 p = typename PT_1::Construct_polynomial()
	  (coeffs,coeffs+2);
	std::vector<Algebraic_real_1 > roots;
	Solve_1()(p,true,std::back_inserter(roots));
	CGAL_assertion(roots.size() == size_type(1));
	return roots[0];
      }
      

      result_type operator() (Polynomial_1 p,size_type i) 
	const {
	std::vector<Algebraic_real_1 > roots;
	Solve_1()(p,true,std::back_inserter(roots));
	CGAL_assertion( size_type(roots.size()) > i);
	return roots[i];
      }

      result_type operator() (Polynomial_1 p,
			      Bound l, Bound u) const {
	CGAL_precondition(l<u);
	return Algebraic_real_1(p,l,u);
      }

  };

  struct Compare_1
    : public std::binary_function<Algebraic_real_1,
	                          Algebraic_real_1,
                                  CGAL::Comparison_result>{
    
    typedef CGAL::Comparison_result result_type;

    result_type operator() (Algebraic_real_1 a,Algebraic_real_1 b) const {
      return typename Real_embeddable_traits<Algebraic_real_1>
	                ::Compare() (a,b);
    }

    result_type operator() (Algebraic_real_1 a,int b) const {
      return this->operator()(a,Construct_algebraic_real_1()(b));
    }

    result_type operator() (Algebraic_real_1 a,Bound b) const {
      return this->operator()(a,Construct_algebraic_real_1()(b));
    }

    
    result_type operator() 
      (Algebraic_real_1 a,
       typename CGAL::First_if_different<Coefficient,Bound>::Type b) const {
      return this->operator()(a,Construct_algebraic_real_1()(b));
    }

    result_type operator() (int a, Algebraic_real_1 b) const {
      return this->operator()(Construct_algebraic_real_1()(a),b);
    }

    result_type operator() (Bound a,Algebraic_real_1 b) const {
      return this->operator()(Construct_algebraic_real_1()(a),b);
    }

    
    result_type operator() 
      (typename CGAL::First_if_different<Coefficient,Bound>::Type a,
       Algebraic_real_1 b) const {
      return this->operator()(Construct_algebraic_real_1()(a),b);
    }

  };

 public:

  struct Isolate_1 : public std::binary_function
    < Algebraic_real_1,Polynomial_1,std::pair<Bound,Bound> > {
    
    public:

    std::pair<Bound,Bound> operator() (const Algebraic_real_1 a,
				       const Polynomial_1 p) const {

      if(p == a.polynomial()) return std::make_pair(a.low(),a.high()); 
      
      std::vector<Algebraic_real_1> roots;
      // First isolate p...
      Solve_1()(p,false,std::back_inserter(roots));
      typedef typename std::vector<Algebraic_real_1>::iterator Iterator;
      // Binary search on the root to find a place where a could be inserted
      std::pair<Iterator,Iterator> it_pair
	= equal_range(roots.begin(),roots.end(),a);
      CGAL_assertion(std::distance(it_pair.first,it_pair.second)==0 ||
		     std::distance(it_pair.first,it_pair.second)==1);
      // If we can insert a in two places, it must have been in roots already
      bool a_in_roots = std::distance(it_pair.first,it_pair.second)==1;
      if(a_in_roots) {
	// TODO: can we rely on the property that the isolating intervals
	// of the roots in p are isolating from each other. What
	// if p was factorized during isolation? Is that still
	// guaranteed? To be sure, we do it this way:
	if(it_pair.first!=roots.begin()) {
	  it_pair.first->strong_refine(*(it_pair.first-1)); 
	}
	if(it_pair.second!=roots.end()) {
	  it_pair.first->strong_refine(*(it_pair.second)); 
	}
	return std::make_pair(it_pair.first->low(),it_pair.first->high());
      } else {
	// Refine a until disjoint from neighbors 
	// This is probably not even necessary since the isolating
	// interval of a isolates against all roots of p thanks to the
	// comparisons. But to be sure...
	if(it_pair.first!=roots.begin()) {
	  a.strong_refine(*(it_pair.first-1)); 
	}
	if(it_pair.first!=roots.end()) {
	  a.strong_refine(*(it_pair.first));
	}
	return std::make_pair(a.low(),a.high());
      }
    }

  };

  typedef typename Algebraic_real_traits::Bound_between Bound_between_1;
  typedef typename Algebraic_real_traits::Approximate_absolute_1 Approximate_absolute_1;
  typedef typename Algebraic_real_traits::Approximate_relative_1 Approximate_relative_1;


  
      
#define CGAL_ALGEBRAIC_KERNEL_1_PRED(Y,Z) Y Z() const { return Y(); }
#define CGAL_ALGEBRAIC_KERNEL_1_PRED_WITH_KERNEL \
            Y Z() const { return Y((const Algebraic_kernel_d_1*)this); }


  CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_square_free_1,
      is_square_free_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Make_square_free_1,
      make_square_free_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Square_free_factorize_1,
      square_free_factorize_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_coprime_1,
      is_coprime_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Make_coprime_1,
      make_coprime_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Solve_1,
      solve_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Number_of_solutions_1,
      number_of_solutions_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Construct_algebraic_real_1,
      construct_algebraic_real_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Sign_at_1,
      sign_at_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_zero_at_1,
      is_zero_at_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Compare_1,compare_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Bound_between_1,
      bound_between_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Approximate_absolute_1,
      approximate_absolute_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Approximate_relative_1,
      approximate_relative_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Compute_polynomial_1,
      compute_polynomial_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Isolate_1,
      isolate_1_object);

  // Deprecated 
#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE
  typedef Bound Boundary;  
  typedef typename Algebraic_real_traits::Refine Refine_1;
  typedef typename Algebraic_real_traits::Lower_bound Lower_bound_1;
  typedef typename Algebraic_real_traits::Upper_bound Upper_bound_1;
  typedef typename Algebraic_real_traits::Lower_bound Lower_boundary_1;
  typedef typename Algebraic_real_traits::Upper_bound Upper_boundary_1;
  typedef Bound_between_1 Boundary_between_1;

  CGAL_ALGEBRAIC_KERNEL_1_PRED(Refine_1,      refine_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Lower_bound_1, lower_bound_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Upper_bound_1, upper_bound_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Lower_boundary_1, lower_boundary_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Upper_boundary_1, upper_boundary_1_object);
  CGAL_ALGEBRAIC_KERNEL_1_PRED(Boundary_between_1, boundary_between_1_object);
#endif
      
#undef CGAL_ALGEBRAIC_KERNEL_1_PRED  
          
};
} // namespace internal


template< class Coefficient,
          class Bound = typename CGAL::Get_arithmetic_kernel< Coefficient >::Arithmetic_kernel::Rational,
          class RepClass = internal::Algebraic_real_rep< Coefficient, Bound >,
          class Isolator = internal::Descartes< typename CGAL::Polynomial_type_generator<Coefficient,1>::Type, Bound > >
class Algebraic_kernel_d_1    
  : public internal::Algebraic_kernel_d_1_base< 

    // Template argument #1 (AlgebraicReal1)        
        internal::Algebraic_real_d_1< 
            Coefficient, 
            Bound,
            ::CGAL::Handle_policy_no_union,     
            RepClass >,
        
    // Template argument #2 (Isolator_)
        Isolator >
            
{};


} //namespace CGAL



#endif // CGAL_ALGEBRAIC_KERNEL_D_1_H
