Last modified on Wed May 12 12:14:58 PDT 1993 by swart modified on Tue Feb 11 16:20:58 PST 1992 by muller modified on Tue Nov 19 17:47:52 PST 1991 by gnelson modified on Thu Sep 19 18:25:13 1991 by kalsow modified on Tue Jul 25 14:12:51 PDT 1989 by luca modified on Mon Jul 17 01:18:21 1989 by stolfi modified on Thu Mar 5 17:12:35 1987 by msm
MODULE; IMPORT Word, Text; PROCEDURE Interval FromBounds (lo, hi: INTEGER): T RAISES {} = VAR a: T; BEGIN IF lo < hi THEN a.lo := lo; a.hi := hi; ELSE a := Empty; END; RETURN a; END FromBounds; PROCEDUREFromAbsBounds (lo, hi: INTEGER): T RAISES {} = VAR a: T; BEGIN IF lo < hi THEN a.lo := lo; a.hi := hi; ELSIF hi < lo THEN a.lo := hi; a.hi := lo; ELSE a := Empty END; RETURN a; END FromAbsBounds; PROCEDUREFromBound (lo: INTEGER; s: CARDINAL): T RAISES {} = VAR a: T; BEGIN IF s = 0 THEN RETURN Empty; END; a.lo := lo; a.hi := lo + s; RETURN a; END FromBound; PROCEDUREFromSize (s: CARDINAL): T RAISES {} = VAR a: T; BEGIN a.lo := 0; a.hi := s; RETURN a; END FromSize; PROCEDURECenter (READONLY a: T; b: INTEGER): T RAISES {} = VAR res: T; d: INTEGER; BEGIN IF a.lo = a.hi THEN RETURN a END; d := b - (a.lo + a.hi) DIV 2; res.lo := a.lo + d; res.hi := a.hi + d; RETURN res; END Center; PROCEDURESize (READONLY a: T): CARDINAL RAISES {} = BEGIN RETURN a.hi - a.lo; END Size; PROCEDUREPickBound (READONLY a: T; n: INTEGER): Bound RAISES {} = BEGIN IF n <= Middle (a) THEN RETURN Bound.Lo ELSE RETURN Bound.Hi END; END PickBound; PROCEDUREProject (READONLY a: T; n: INTEGER): INTEGER RAISES {} = BEGIN IF (a.hi <= a.lo) THEN FAIL("Interval.Project: empty interval") END; RETURN MAX (a.lo, MIN (a.hi - 1, n)) END Project; PROCEDUREMiddle (READONLY a: T): INTEGER RAISES {} = BEGIN RETURN (a.lo + a.hi) DIV 2 END Middle; PROCEDUREMove (READONLY a: T; n: INTEGER): T RAISES {} = VAR b: T; BEGIN IF a.lo >= a.hi THEN RETURN Empty END; b.lo := a.lo + n; b.hi := a.hi + n; RETURN b; END Move; PROCEDUREInset (READONLY a: T; n: INTEGER): T RAISES {} = VAR b: T; BEGIN IF a.lo >= a.hi THEN RETURN Empty END; b.lo := a.lo + n; b.hi := a.hi - n; IF b.lo >= b.hi THEN RETURN Empty END; RETURN b END Inset; PROCEDUREChange (READONLY a: T; dlo, dhi: INTEGER): T RAISES {} = VAR b: T; BEGIN IF a.lo >= a.hi THEN RETURN Empty; END; b.lo := a.lo + dlo; b.hi := a.hi + dhi; IF b.lo >= b.hi THEN RETURN Empty; END; RETURN b; END Change; PROCEDUREMoveBound (x: Bound; READONLY a: T; dn: INTEGER): T RAISES {} = VAR b: T; BEGIN IF a.lo >= a.hi THEN RETURN Empty; END; b := a; IF (x = Bound.Lo) THEN b.lo := b.lo + dn; ELSE b.hi := b.hi + dn; END; IF b.lo >= b.hi THEN RETURN Empty; END; RETURN b; END MoveBound; PROCEDUREJoin (READONLY a, b: T): T RAISES {} = VAR c: T; BEGIN IF a.lo >= a.hi THEN RETURN b; END; IF b.lo >= b.hi THEN RETURN a; END; c.lo := MIN (a.lo, b.lo); c.hi := MAX (a.hi, b.hi); RETURN c; END Join; PROCEDUREMeet (READONLY a, b: T): T RAISES {} = VAR c: T; BEGIN c.lo := MAX (a.lo, b.lo); c.hi := MIN (a.hi, b.hi); IF c.lo >= c.hi THEN RETURN Empty; END; RETURN c; END Meet; PROCEDUREChop (READONLY a: T; n: INTEGER; VAR (* out *) b, c: T) RAISES {} = BEGIN IF n <= a.lo THEN b := Empty; c := a ELSIF n >= a.hi THEN b := a; c := Empty ELSE b.lo := a.lo; b.hi := n; c.lo := n; c.hi := a.hi END END Chop; PROCEDUREFactor (READONLY a, by: T; VAR (*out*) f: Partition; dn: INTEGER) RAISES {} = VAR index: [0..2]; temp: T; BEGIN IF dn > 0 THEN index := 2; ELSE index := 0; END; Chop (a, by.lo, f[index], temp); Chop (temp, by.hi, f[1], f[2 - index]); END Factor; PROCEDUREMod (n: INTEGER; READONLY a: T): INTEGER RAISES {} = VAR res: INTEGER; BEGIN IF (a.lo >= a.hi) THEN FAIL("Interval.Mod: a is empty!") END; res := (n - a.lo) MOD (a.hi - a.lo); RETURN res + a.lo END Mod; PROCEDUREEqual (READONLY a, b: T): BOOLEAN RAISES {} = BEGIN RETURN a = b END Equal; PROCEDUREIsEmpty (READONLY a: T): BOOLEAN RAISES {} = BEGIN RETURN a.lo >= a.hi; END IsEmpty; PROCEDUREMember (n: INTEGER; READONLY a: T): BOOLEAN RAISES {} = BEGIN RETURN (a.lo <= n) AND (n < a.hi) END Member; PROCEDUREOverlap (READONLY a, b: T): BOOLEAN RAISES {} = BEGIN RETURN MAX (a.lo, b.lo) < MIN (a.hi, b.hi); END Overlap; PROCEDURESubset (READONLY a, b: T): BOOLEAN RAISES {} = BEGIN RETURN (a.lo >= a.hi) OR ((a.lo >= b.lo) AND (a.hi <= b.hi)); END Subset; PROCEDURECompare (READONLY a, b: T): [-1..1] = BEGIN IF (a.lo < b.lo) THEN RETURN -1; ELSIF (a.lo > b.lo) THEN RETURN +1; ELSIF (a.hi = b.hi) THEN RETURN 0; ELSIF (a.hi < b.hi) THEN RETURN -1; ELSE RETURN +1; END; END Compare; PROCEDUREHash (READONLY a: T): Word.T = BEGIN RETURN Word.Xor (a.lo, a.hi); END Hash; EXCEPTION ASSERT_FAILED (Text.T); <*INLINE*> PROCEDUREFAIL (msg: Text.T := NIL) = <*FATAL ASSERT_FAILED*> BEGIN RAISE ASSERT_FAILED (msg); END FAIL; BEGIN END Interval.