(* Copyright (C) 1990, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Wed Sep 9 12:51:41 PDT 1992 by rustan *) (* modified on Fri Feb 28 08:47:01 PST 1992 by kalsow *) MODULE RTMathSet EXPORTS RTMath; IMPORT Word; CONST Grain = BITSIZE (INTEGER); (* new KRML *) PROCEDURE SetIncl (VAR x: ARRAY [0..MAXSET] OF INTEGER; a, b: INTEGER) = (* This version of SetIncl may be slower than the version below, but it is more space efficient *) VAR a_word := a DIV Grain; VAR b_word := b DIV Grain; VAR a_bit := a MOD Grain; VAR b_bit := b MOD Grain; (* The following line is to force non-inlining of the Word.Insert procedure. This procedure takes a lot of space to inline, and it already exists in the run-time anyway, so it might as well be used. *) CONST wordInsert: PROCEDURE ( x, y: Word.T; i, n: CARDINAL ): Word.T = Word.Insert; (* The following line assumes that 0 is represented by a Grain 0's. That seems like an even larger certainty than assuming that -1 is represented by Grain 1's. *) CONST AllOnes = Word.Not( 0 ); BEGIN (* cause a range fault if either a or b is negative *) VAR aa, bb: CARDINAL; BEGIN aa := a; bb := b END; IF (a_word = b_word) THEN WITH w = x[a_word] DO w := wordInsert( w, AllOnes, a_bit, b_bit-a_bit+1 ) END ELSE WITH w = x[a_word] DO w := wordInsert( w, AllOnes, a_bit, Grain-a_bit ) END; FOR i := a_word+1 TO b_word-1 DO x[i] := AllOnes END; WITH w = x[b_word] DO w := wordInsert( w, AllOnes, 0, b_bit+1 ) END END; END SetIncl; (* end KRML *) (********************************************************** KRML TYPE BitCnt = [0 .. Grain - 1]; VAR initialized := FALSE; LoBits: ARRAY BitCnt OF INTEGER; (* LoBits[i] == SET { 0..i } *) HiBits: ARRAY BitCnt OF INTEGER; (* HiBits[i] == SET { i..Grain-1 } *) PROCEDURE SetIncl (VAR x: ARRAY [0..MAXSET] OF INTEGER; a, b: INTEGER) = VAR a_word := a DIV Grain; VAR b_word := b DIV Grain; VAR a_bit := a MOD Grain; VAR b_bit := b MOD Grain; BEGIN IF (NOT initialized) THEN Init () END; IF (a < 0) OR (b < 0) THEN RTMisc.RangeFault (NIL, 0) END; IF (a_word = b_word) THEN x [a_word] := Word.Or (x [a_word], Word.And (HiBits [a_bit], LoBits [b_bit])); ELSE x [a_word] := Word.Or (x [a_word], HiBits [a_bit]); FOR i := a_word+1 TO b_word-1 DO x[i] := HiBits [0] END; x [b_word] := Word.Or (x [b_word], LoBits [b_bit]); END; END SetIncl; PROCEDURE Init () = VAR x: INTEGER; BEGIN x := 0; FOR i := 0 TO LAST (LoBits) DO x := Word.Or (x, Word.Shift (1, i)); LoBits [i] := x; END; <*ASSERT LoBits[0] = 1 *> <*ASSERT LoBits [LAST (LoBits)] = Word.Not (0) *> x := 0; FOR i := LAST (HiBits) TO 0 BY -1 DO x := Word.Or (x, Word.Shift (1, i)); HiBits [i] := x; END; <*ASSERT HiBits[0] = Word.Not (0) *> initialized := TRUE; END Init; ******************************************************** KRML *) BEGIN END RTMathSet.