IMPLEMENTATION MODULE Interval;

  -----------------------------
  -- The Interval parameterized class denotes an interval
  -- made of any couple of two similar comparables.
  -----------------------------
  CLASS Interval (Element IN Comparable);
    INHERITS Couple(Element);
    
    REDEFINE METHOD Set (One, Two: Element);
      BEGIN
      ASSERT One <> VOID;
      ASSERT Two <> VOID;
      IF One.IsGreater (Two) THEN
        BASE (Two, One);
       ELSE
        BASE (One, Two);
        END;
      END Set;
      
    METHOD First: Element;
      BEGIN
      RESULT := One;
      END First;
      
    METHOD Last: Element;
      BEGIN
      RESULT := Two;
      END Last;
      
    METHOD Includes (El: Element): BOOLEAN;
      BEGIN
      RESULT := NOT (El.IsGreater(Two) OR One.IsGreater(El));
      END Includes;
      
    REDEFINE METHOD IsGreater (Other: Comparable): BOOLEAN;
      BEGIN
      WHAT Other OF
        IN Interval:
          RESULT := One.IsGreater (TAG.One);
          END;
        IN Element:
          RESULT := One.IsGreater (TAG);
          END;
       ELSE
        END;
      END IsGreater;
      
    METHOD IncludesInterval (Other: Interval(Element)): BOOLEAN;
      BEGIN
      RESULT := Includes(Other.First) AND Includes(Other.Last);
      END IncludesInterval;
      
    METHOD Intersects (Other: Interval(Element)): BOOLEAN;
      BEGIN
      RESULT := NOT Other.First.IsGreater (Last) AND
                NOT First.IsGreater (Other.Last);
      END Intersects;
      
    METHOD Intersection (Other: Interval(Element)): Interval(Element);
      VAR
        One, Two: Element;
      BEGIN
      IF Intersects(Other) THEN
        IF First.IsGreater (Other.First) THEN
          One := First;
         ELSE
          One := Other.First;
          END;
        IF Last.IsGreater (Other.Last) THEN
          Two := Other.Last;
         ELSE
          Two := Last;
          END;
        RESULT.CREATE (One, Two);        
        END;
      END Intersection;
      
    METHOD Union (Other: Interval(Element)): Interval(Element);
      VAR
        One, Two: Element;
      BEGIN
      IF First.IsGreater (Other.First) THEN
        One := Other.First;
       ELSE
        One := First;
        END;
      IF Last.IsGreater (Other.Last) THEN
        Two := Last;
       ELSE
        Two := Other.Last;
        END;
      RESULT.CREATE (One, Two);        
      END Union;
      
  END Interval;
  
END Interval;
