/*
  Copyright 2008 Intel Corporation
 
  Use, modification and distribution are subject to the Boost Software License,
  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  http://www.boost.org/LICENSE_1_0.txt).
*/
#ifndef BOOST_POLYGON_INTERVAL_CONCEPT_HPP
#define BOOST_POLYGON_INTERVAL_CONCEPT_HPP
#include "isotropy.hpp"
#include "interval_data.hpp"
#include "interval_traits.hpp"

namespace boost { namespace polygon{
  struct interval_concept {};
 
  template <typename T>
  struct is_interval_concept { typedef gtl_no type; };
  template <>
  struct is_interval_concept<interval_concept> { typedef gtl_yes type; };

  template <typename T>
  struct is_mutable_interval_concept { typedef gtl_no type; };
  template <>
  struct is_mutable_interval_concept<interval_concept> { typedef gtl_yes type; };

  template <typename T, typename CT>
  struct interval_coordinate_type_by_concept { typedef void type; };
  template <typename T>
  struct interval_coordinate_type_by_concept<T, gtl_yes> { typedef typename interval_traits<T>::coordinate_type type; };

  template <typename T>
  struct interval_coordinate_type {
      typedef typename interval_coordinate_type_by_concept<
            T, typename is_interval_concept<typename geometry_concept<T>::type>::type>::type type;
  };

  template <typename T, typename CT>
  struct interval_difference_type_by_concept { typedef void type; };
  template <typename T>
  struct interval_difference_type_by_concept<T, gtl_yes> { 
    typedef typename coordinate_traits<typename interval_traits<T>::coordinate_type>::coordinate_difference type; };

  template <typename T>
  struct interval_difference_type {
      typedef typename interval_difference_type_by_concept<
            T, typename is_interval_concept<typename geometry_concept<T>::type>::type>::type type;
  };


  template <typename T>
  typename interval_coordinate_type<T>::type
  get(const T& interval, direction_1d dir,
  typename enable_if<typename gtl_if<typename is_interval_concept<typename geometry_concept<T>::type>::type>::type>::type * = 0
  ) {
    return interval_traits<T>::get(interval, dir); 
  }

  template <typename T, typename coordinate_type>
  void 
  set(T& interval, direction_1d dir, coordinate_type value,
  typename enable_if<typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type>::type * = 0
  ) {
    //this may need to be refined
    interval_mutable_traits<T>::set(interval, dir, value); 
    if(high(interval) < low(interval))
      interval_mutable_traits<T>::set(interval, dir.backward(), value);
  }
  
  template <typename T, typename T2, typename T3>
  T
  construct(T2 low_value, T3 high_value,
            typename enable_if<typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type>::type * = 0
  ) {
    if(low_value > high_value) std::swap(low_value, high_value);
    return interval_mutable_traits<T>::construct(low_value, high_value); 
  }
  
  template <typename T, typename T2>
  T
  copy_construct(const T2& interval,
  typename enable_if< typename gtl_and<typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type,
  typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0
  ) {
    return construct<T>
      (get(interval, LOW ),
       get(interval, HIGH));
  }

  template <typename T1, typename T2>
  T1 &
  assign(T1& lvalue, const T2& rvalue,
  typename enable_if< typename gtl_and< typename is_mutable_interval_concept<typename geometry_concept<T1>::type>::type,
  typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0) {
    lvalue = copy_construct<T1>(rvalue);
    return lvalue;
  }

  template <typename T, typename T2>
  bool 
  equivalence(const T& interval1, const T2& interval2,
  typename enable_if< typename gtl_and< typename is_interval_concept<typename geometry_concept<T>::type>::type,
  typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0
  ) {
    return get(interval1, LOW) ==
      get(interval2, LOW) &&
      get(interval1, HIGH) ==
      get(interval2, HIGH); 
  }
  
  struct y_i_contains : gtl_yes {};

  template <typename interval_type>
  typename enable_if< typename gtl_and< y_i_contains, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type >::type, bool>::type 
  contains(const interval_type& interval,
           typename interval_traits<interval_type>::coordinate_type value, 
           bool consider_touch = true ) {
    if(consider_touch) {
      return value <= high(interval) && value >= low(interval);
    } else {
      return value < high(interval) && value > low(interval);
    }
  }
  
  template <typename interval_type, typename interval_type_2>
  bool 
  contains(const interval_type& interval,
           const interval_type_2& value, bool consider_touch = true,
           typename enable_if< typename gtl_and< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type,
           typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type>::type * = 0
           ) {
    return contains(interval, get(value, LOW), consider_touch) &&
      contains(interval, get(value, HIGH), consider_touch);
  }
  
  // get the low coordinate
  template <typename interval_type>
  typename interval_traits<interval_type>::coordinate_type 
  low(const interval_type& interval,
  typename enable_if< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
  ) { return get(interval, LOW); }

  // get the high coordinate
  template <typename interval_type>
  typename interval_traits<interval_type>::coordinate_type 
  high(const interval_type& interval,
  typename enable_if< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
  ) { return get(interval, HIGH); }

  // get the center coordinate
  template <typename interval_type>
  typename interval_traits<interval_type>::coordinate_type
  center(const interval_type& interval,
  typename enable_if< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
  ) { return (high(interval) + low(interval))/2; }


  struct y_i_low : gtl_yes {};

  // set the low coordinate to v
  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_low, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, void>::type 
  low(interval_type& interval,
      typename interval_traits<interval_type>::coordinate_type v) { set(interval, LOW, v); }
  
  struct y_i_high : gtl_yes {};

  // set the high coordinate to v
  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_high, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, void>::type 
  high(interval_type& interval,
      typename interval_traits<interval_type>::coordinate_type v) { set(interval, HIGH, v); }
  
  // get the magnitude of the interval
  template <typename interval_type>
  typename interval_difference_type<interval_type>::type 
  delta(const interval_type& interval,
  typename enable_if< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
  ) { 
    typedef typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::coordinate_difference diffT;
    return (diffT)high(interval) - (diffT)low(interval); }

  struct y_i_flip : gtl_yes {};

  // flip this about coordinate
  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_flip, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
  flip(interval_type& interval,
       typename interval_traits<interval_type>::coordinate_type axis = 0) {
    typename interval_traits<interval_type>::coordinate_type newLow, newHigh;
    newLow  = 2 * axis - high(interval);
    newHigh = 2 * axis - low(interval);
    low(interval, newLow);
    high(interval, newHigh);
    return interval;
  }

  struct y_i_scale_up : gtl_yes {};

  // scale interval by factor
  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_scale_up, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
  scale_up(interval_type& interval, 
           typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::unsigned_area_type factor) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit newHigh = high(interval) * (Unit)factor;
    low(interval, low(interval) * (Unit)factor);
    high(interval, (newHigh));
    return interval;
  }

  struct y_i_scale_down : gtl_yes {};

  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_scale_down, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
  scale_down(interval_type& interval, 
             typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::unsigned_area_type factor) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    typedef typename coordinate_traits<Unit>::coordinate_distance dt;
    Unit newHigh = scaling_policy<Unit>::round((dt)(high(interval)) / (dt)factor); 
    low(interval, scaling_policy<Unit>::round((dt)(low(interval)) / (dt)factor)); 
    high(interval, (newHigh));
    return interval;
  }

  struct y_i_scale : gtl_yes {};

  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_scale, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
  scale(interval_type& interval, double factor) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit newHigh = scaling_policy<Unit>::round((double)(high(interval)) * factor);
    low(interval, scaling_policy<Unit>::round((double)low(interval)* factor));
    high(interval, (newHigh));
    return interval;
  }
  
  // move interval by delta
  template <typename interval_type>
  interval_type&
  move(interval_type& interval,
       typename interval_difference_type<interval_type>::type displacement,
       typename enable_if<typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
       ) {
    typedef typename interval_traits<interval_type>::coordinate_type ctype;
    typedef typename coordinate_traits<ctype>::coordinate_difference Unit;
    Unit len = delta(interval);
    low(interval, static_cast<ctype>(static_cast<Unit>(low(interval)) + displacement));
    high(interval, static_cast<ctype>(static_cast<Unit>(low(interval)) + len));
    return interval;
  }
  
  struct y_i_convolve : gtl_yes {};

  // convolve this with b
  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_convolve, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
  convolve(interval_type& interval,
           typename interval_traits<interval_type>::coordinate_type b) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit newLow  = low(interval) + b;
    Unit newHigh = high(interval) + b;
    low(interval, newLow);
    high(interval, newHigh);
    return interval;
  }

  struct y_i_deconvolve : gtl_yes {};

  // deconvolve this with b
  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_deconvolve, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
  deconvolve(interval_type& interval,
             typename interval_traits<interval_type>::coordinate_type b) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit newLow  = low(interval)  - b;
    Unit newHigh = high(interval) - b;
    low(interval, newLow);
    high(interval, newHigh);
    return interval;
  }

  struct y_i_convolve2 : gtl_yes {};

  // convolve this with b
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3<y_i_convolve2,
                       typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type, 
                       typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    interval_type>::type &
  convolve(interval_type& interval,
           const interval_type_2& b) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit newLow  = low(interval)  + low(b);
    Unit newHigh = high(interval) + high(b);
    low(interval, newLow);
                         high(interval, newHigh);
                         return interval;
  }
  
  struct y_i_deconvolve2 : gtl_yes {};

  // deconvolve this with b
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3< y_i_deconvolve2,
                        typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type,
                        typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    interval_type>::type &
  deconvolve(interval_type& interval,
             const interval_type_2& b) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit newLow  = low(interval)  - low(b);
    Unit newHigh = high(interval) - high(b);
    low(interval, newLow);
    high(interval, newHigh);
    return interval;
  }
  
  struct y_i_reconvolve : gtl_yes {};

  // reflected convolve this with b
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3<y_i_reconvolve,
                       typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type,
                       typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    interval_type>::type &
  reflected_convolve(interval_type& interval,
                     const interval_type_2& b) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit newLow  = low(interval)  - high(b);
    Unit newHigh = high(interval) - low(b);
    low(interval, newLow);
    high(interval, newHigh);
    return interval;
  }
  
  struct y_i_redeconvolve : gtl_yes {};

  // reflected deconvolve this with b
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3< y_i_redeconvolve,
                        typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type, 
                        typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type, 
    interval_type>::type &
  reflected_deconvolve(interval_type& interval,
                       const interval_type_2& b) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit newLow  = low(interval)  + high(b);
    Unit newHigh = high(interval) + low(b);
    low(interval, newLow);
    high(interval, newHigh);
    return interval;
  }
  
  struct y_i_e_dist1 : gtl_yes {};

  // distance from a coordinate to an interval
  template <typename interval_type>
  typename enable_if< typename gtl_and<y_i_e_dist1, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                       typename interval_difference_type<interval_type>::type>::type
  euclidean_distance(const interval_type& interval,
                     typename interval_traits<interval_type>::coordinate_type position) {
    typedef typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::coordinate_difference Unit;
    Unit dist[3] = {0, (Unit)low(interval) - (Unit)position, (Unit)position - (Unit)high(interval)};
    return dist[ (dist[1] > 0) + ((dist[2] > 0) << 1) ];
  }

  struct y_i_e_dist2 : gtl_yes {};
  
  // distance between two intervals
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3<y_i_e_dist2, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type,
                       typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    typename interval_difference_type<interval_type>::type>::type
  euclidean_distance(const interval_type& interval,
                     const interval_type_2& b) {
    typedef typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::coordinate_difference Unit;
    Unit dist[3] = {0, (Unit)low(interval) - (Unit)high(b), (Unit)low(b) - (Unit)high(interval)};
    return dist[ (dist[1] > 0) + ((dist[2] > 0) << 1) ];
  }
  
  struct y_i_e_intersects : gtl_yes {};

  // check if Interval b intersects `this` Interval
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3<y_i_e_intersects, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type,
                       typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    bool>::type 
    intersects(const interval_type& interval, const interval_type_2& b, 
               bool consider_touch = true) {
                         return consider_touch ? 
                           (low(interval) <= high(b)) & (high(interval) >= low(b)) :
                           (low(interval) < high(b)) & (high(interval) > low(b));
  }

  struct y_i_e_bintersect : gtl_yes {};

  // check if Interval b partially overlaps `this` Interval
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3<y_i_e_bintersect, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type,
                       typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    bool>::type 
  boundaries_intersect(const interval_type& interval, const interval_type_2& b, 
                       bool consider_touch = true) {
    return (contains(interval, low(b), consider_touch) || 
            contains(interval, high(b), consider_touch)) &&
      (contains(b, low(interval), consider_touch) || 
       contains(b, high(interval), consider_touch));
  }

  struct y_i_abuts1 : gtl_yes {};

  // check if they are end to end
  template <typename interval_type, typename interval_type_2>
  typename enable_if< typename gtl_and_3<y_i_abuts1, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type,
                                         typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
                       bool>::type 
  abuts(const interval_type& interval, const interval_type_2& b, direction_1d dir) {
    return dir.to_int() ? low(b) == high(interval) : low(interval) == high(b);
  }

  struct y_i_abuts2 : gtl_yes {};

  // check if they are end to end
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3<y_i_abuts2, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type,
                       typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    bool>::type 
  abuts(const interval_type& interval, const interval_type_2& b) {
    return abuts(interval, b, HIGH) || abuts(interval, b, LOW);
  } 

  struct y_i_intersect : gtl_yes {};

  // set 'this' interval to the intersection of 'this' and b
  template <typename interval_type, typename interval_type_2>
  typename enable_if< typename gtl_and_3<y_i_intersect, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type,
                                         typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
                       bool>::type 
  intersect(interval_type& interval, const interval_type_2& b, bool consider_touch = true) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit lowVal = (std::max)(low(interval), low(b));
    Unit highVal = (std::min)(high(interval), high(b));
    bool valid = consider_touch ?
      lowVal <= highVal :
      lowVal < highVal;
    if(valid) {
      low(interval, lowVal);
      high(interval, highVal);
    }
    return valid;
  }

  struct y_i_g_intersect : gtl_yes {};

  // set 'this' interval to the generalized intersection of 'this' and b
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3<y_i_g_intersect, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type,
                      typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    interval_type>::type &
  generalized_intersect(interval_type& interval, const interval_type_2& b) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit coords[4] = {low(interval), high(interval), low(b), high(b)};
    //consider implementing faster sorting of small fixed length range
    gtlsort(coords, coords+4);
    low(interval, coords[1]);
    high(interval, coords[2]);
    return interval;
  }

  struct y_i_bloat : gtl_yes {};

  // bloat the Interval
  template <typename interval_type>
  typename enable_if< typename gtl_and<y_i_bloat, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                       interval_type>::type &
  bloat(interval_type& interval, typename interval_traits<interval_type>::coordinate_type bloating) {
    low(interval, low(interval)-bloating);
    high(interval, high(interval)+bloating);
    return interval;
  }
  
  struct y_i_bloat2 : gtl_yes {};

  // bloat the specified side of `this` Interval
  template <typename interval_type>
  typename enable_if< typename gtl_and<y_i_bloat2, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                       interval_type>::type &
  bloat(interval_type& interval, direction_1d dir, typename interval_traits<interval_type>::coordinate_type bloating) {
    set(interval, dir, get(interval, dir) + dir.get_sign() * bloating);
    return interval;
  }

  struct y_i_shrink : gtl_yes {};

  // shrink the Interval
  template <typename interval_type>
  typename enable_if< typename gtl_and<y_i_shrink, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                       interval_type>::type &
  shrink(interval_type& interval, typename interval_traits<interval_type>::coordinate_type shrinking) {
    return bloat(interval, -shrinking);
  }

  struct y_i_shrink2 : gtl_yes {};

  // shrink the specified side of `this` Interval
  template <typename interval_type>
  typename enable_if< typename gtl_and<y_i_shrink2, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                       interval_type>::type &
  shrink(interval_type& interval, direction_1d dir, typename interval_traits<interval_type>::coordinate_type shrinking) {
    return bloat(interval, dir, -shrinking);
  }

  // Enlarge `this` Interval to encompass the specified Interval
  template <typename interval_type, typename interval_type_2>
  bool
  encompass(interval_type& interval, const interval_type_2& b,
  typename enable_if<
    typename gtl_and< typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type,
            typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type>::type * = 0
  ) {
    bool retval = !contains(interval, b, true);
    low(interval, (std::min)(low(interval), low(b)));
    high(interval, (std::max)(high(interval), high(b)));
    return retval;
  }    

  struct y_i_encompass : gtl_yes {};

  // Enlarge `this` Interval to encompass the specified Interval
  template <typename interval_type>
  typename enable_if< typename gtl_and<y_i_encompass, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                       bool>::type
  encompass(interval_type& interval, typename interval_traits<interval_type>::coordinate_type b) {
    bool retval = !contains(interval, b, true);
    low(interval, (std::min)(low(interval), b));
    high(interval, (std::max)(high(interval), b));
    return retval;
  }    

  struct y_i_get_half : gtl_yes {};

  // gets the half of the interval as an interval
  template <typename interval_type>
  typename enable_if<typename gtl_and<y_i_get_half, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type 
  get_half(const interval_type& interval, direction_1d d1d) {
    typedef typename interval_traits<interval_type>::coordinate_type Unit;
    Unit c = (get(interval, LOW) + get(interval, HIGH)) / 2;
    return construct<interval_type>((d1d == LOW) ? get(interval, LOW) : c,
                                    (d1d == LOW) ? c : get(interval, HIGH));
  }

  struct y_i_join_with : gtl_yes {};

  // returns true if the 2 intervals exactly touch at one value, like in  l1 <= h1 == l2 <= h2
  // sets the argument to the joined interval
  template <typename interval_type, typename interval_type_2>
  typename enable_if< 
    typename gtl_and_3<y_i_join_with, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type,
                      typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
    bool>::type 
  join_with(interval_type& interval, const interval_type_2& b) {
    if(abuts(interval, b)) {
      encompass(interval, b);
      return true;
    }
    return false;
  }

  template <class T>
  template <class T2>
  interval_data<T>& interval_data<T>::operator=(const T2& rvalue) {
    assign(*this, rvalue);
    return *this;
  }

  template <typename T>
  struct geometry_concept<interval_data<T> > {
    typedef interval_concept type;
  };
}
}
#endif
