context: /*
  Copyright (C) 2008  P. Oscar Boykin <boykin@pobox.com>, University of Florida
  
  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
  
  #if BRUNET_NUNIT
  using NUnit.Framework;
  #endif
  
  using System;
  using System.Collections;
  using System.Collections.Generic;
  
  namespace Brunet.Util
  {
  /**
   * This class represents intervals.  We need to supply
   * a comparer, or Comparer<T>.Default must exist.
   */
  public class Interval<T> : IComparable, IComparable<Interval<T>>, IComparable<T> {
  
    readonly IComparer<T> _comp;
  
    /** This is the start of the interval
     */
    readonly public T Start;
    ///True if the interval DOES NOT include Start
    readonly public bool StartIsOpen;
    /** This is the end of the interval
     */
    readonly public T End;
    ///True if the interval DOES NOT include End 
    readonly public bool EndIsOpen;
  
    /** Create a new open or closed interval
     * @param start the starting point
     * @param s_open if true, the interval does not include the starting point
     * @param end the ending point
     * @param e_open if true, the interval does not include the ending point
     * @param comp the Comparer to use for Interval computations
     * @throw ArgumentException if there is no overlap
     */
    public Interval(T start, bool start_open, T end, bool end_open, IComparer<T> comp) {
      if( comp.Compare(start, end) > 0 ) {
        string err = String.Format(
                      "Start({0}) must be less than or equal to End({1})",
                      start, end);
        throw new System.ArgumentException(err);
      }
      Start = start;
      StartIsOpen = start_open;
      End = end;
      EndIsOpen = end_open;
      _comp = comp; 
    }
  
    /** Create a new open or closed interval
     * @param start the starting point
     * @param s_open if true, the interval does not include the starting point
     * @param end the ending point
     * @param e_open if true, the interval does not include the ending point
     * @throw ArgumentException if there is no overlap
     */
    public Interval(T start, bool s_open, T end, bool e_open) : this(start, s_open, end, e_open, Comparer<T>.Default) { }
  
    /** Factory method to create an open interval
     */
    public static Interval<T> CreateOpen(T start, T end) {
      return CreateOpen(start, end, Comparer<T>.Default);
    }
    /** Factory method to create an open interval
     */
    public static Interval<T> CreateOpen(T start, T end, IComparer<T> comp) {
      return new Interval<T>(start, true, end, true, comp);
    }
    /** Factory method to create a closed interval
     */
    public static Interval<T> CreateClosed(T start, T end) {
      return CreateClosed(start, end, Comparer<T>.Default);
    }
    /** Factory method to create a closed interval
     */
    public static Interval<T> CreateClosed(T start, T end, IComparer<T> comp) {
      return new Interval<T>(start, false, end, false, comp);
    }
  
    /**
     * Sort an interval based first on start, then on end, if they have
     * Equal underlying IComparer<T> objects
     * @throw ArgumentException if they do not have Equal IComparer<T>
     */
    public int CompareTo(Interval<T> other) {
      if( false == _comp.Equals(other._comp) ) {
        throw new ArgumentException("Intervals do not share a comparer"); 
      }
      int start_cmp = _comp.Compare(Start, other.Start);
      if( start_cmp != 0 ) {
        return start_cmp;
      }
      else {
        if (StartIsOpen == other.StartIsOpen) {
          int end_cmp = _comp.Compare(End, other.End);
          if( end_cmp == 0 ) {
            if( EndIsOpen == other.EndIsOpen ) {
              return 0;
            }
            else {
              //Put the open end interval first:
              return EndIsOpen ? -1 : 1;
            }
          }
          else {
            return end_cmp;
          }
        }
        else {
          /*
           * these intervals start at the same point, but only one is open.
           * put the closed interval first
           */
          return StartIsOpen ? 1 : -1;
        }
      }
    }
  
    int IComparable.CompareTo(object o) {
      Interval<T> o_int = o as Interval<T>;
      if( o_int != null ) {
        return CompareTo(o_int);
      }
      else {
        return CompareTo((T)o);
      }
    }
    /** Is the point below, in, or above the interval
     * @return 1 if everything in the interval is greater than 1, -1 if
     * everything is below, 0 if the point is in the interval
     */
    public int CompareTo(T point) {
      int scmp = _comp.Compare(Start, point);
      if( scmp > 0 ) {
        //point is strictly below
        return 1;
      }
      int ecmp = _comp.Compare(point, End);
      if( ecmp > 0 ) {
        //point is strictly above
        return -1;
      }
      if( (scmp < 0) && (ecmp < 0) ) {
        //Strictly inside
        return 0;
      }
      //Not strictly inside or out, it must be on the boundary:
      if( scmp == 0 ) {
        //Point is same as Start
        return StartIsOpen ? 1 : 0;
      }
      else {
        //Must be on the end:
        return EndIsOpen ? -1 : 0;
      }
    }
  
  
    public bool Contains(T point) {
      return CompareTo(point) == 0;
    }
    /** @return true if this interval completely contains the argument
     * Use the Comparer from this instance
     */
    public bool Contains(Interval<T> other) {
      int start_cmp = _comp.Compare(Start, other.Start);
      int end_cmp = _comp.Compare(End, other.End);
      bool strictly_not_bigger = (start_cmp > 0) || (end_cmp < 0);
      if( strictly_not_bigger ) {
        return false;
      }
      else {
        bool start_is_good = (start_cmp < 0);
        bool end_is_good = (end_cmp > 0);
        if(  false == start_is_good ) {
          if( start_cmp == 0 ) {
            start_is_good = (StartIsOpen == false) || other.StartIsOpen;
          }
        }
        if( false == end_is_good ) {
          if( end_cmp == 0 ) {
            end_is_good = (EndIsOpen == false) || other.EndIsOpen;
          }
        }
        return start_is_good && end_is_good;
      }
    }
  
    public override bool Equals(object other) {
      if( System.Object.ReferenceEquals(other, this) ) { return true; }
      Interval<T> other_int = other as Interval<T>;
      if( other_int != null ) {
        return _comp.Equals(other_int._comp) &&
  
gt:              (_comp.Compare(Start, other_int.Start) == 0) &&