BitSets.Mod 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. MODULE BitSets; (** AUTHOR "negelef"; PURPOSE "generic bit container"; *)
  2. IMPORT SYSTEM;
  3. CONST Elements = MAX (SET) - MIN (SET) + 1;
  4. TYPE Data = POINTER TO ARRAY OF SET;
  5. TYPE BitSet* = OBJECT
  6. VAR size: LONGINT;
  7. VAR data: Data;
  8. PROCEDURE & InitBitSet* (size: LONGINT);
  9. BEGIN SELF.size := size; Resize (size);
  10. END InitBitSet;
  11. PROCEDURE Zero*;
  12. VAR i: SIZE;
  13. BEGIN FOR i := 0 TO LEN(data)-1 DO data[i] := {} END;
  14. END Zero;
  15. PROCEDURE Resize* (size: LONGINT);
  16. VAR newData: Data; i: SIZE;
  17. BEGIN
  18. ASSERT (size >= 0);
  19. SELF.size := size;
  20. size := MAX (size - 1, 0) DIV Elements + 1;
  21. IF data # NIL THEN
  22. IF size <= LEN (data) THEN RETURN; END;
  23. size := MAX (size, LEN (data) * 2);
  24. END;
  25. NEW (newData, size);
  26. IF data # NIL THEN
  27. FOR i := 0 TO LEN (data) - 1 DO newData[i] := data[i]; END;
  28. END;
  29. data := newData;
  30. END Resize;
  31. PROCEDURE GetSize* (): LONGINT;
  32. BEGIN RETURN size;
  33. END GetSize;
  34. PROCEDURE SetBit* (pos: SIZE; value: BOOLEAN);
  35. BEGIN
  36. ASSERT (pos >= 0); ASSERT (pos < size);
  37. IF value THEN
  38. INCL (data[pos DIV Elements], pos MOD Elements);
  39. ELSE
  40. EXCL (data[pos DIV Elements], pos MOD Elements);
  41. END;
  42. END SetBit;
  43. PROCEDURE GetBit* (pos: SIZE): BOOLEAN;
  44. BEGIN
  45. ASSERT (pos >= 0); ASSERT (pos < size);
  46. RETURN pos MOD Elements IN data[pos DIV Elements];
  47. END GetBit;
  48. PROCEDURE SetBits* (startPos, bits: SIZE; value: HUGEINT);
  49. VAR adr: ADDRESS;
  50. BEGIN
  51. ASSERT (startPos >= 0); ASSERT (startPos+bits <= size);
  52. IF (bits = 8) & (startPos MOD 8 = 0) THEN
  53. adr := ADDRESS OF data[0] + startPos DIV 8;
  54. SYSTEM.PUT(adr, CHR(value));
  55. ELSE
  56. WHILE bits > 0 DO
  57. SetBit (startPos, ODD (value)); value := value DIV 2;
  58. INC(startPos); DEC(bits)
  59. END;
  60. WHILE bits < 0 DO
  61. SetBit (startPos, ODD (value)); value := value DIV 2;
  62. DEC(startPos); INC(bits)
  63. END;
  64. END;
  65. END SetBits;
  66. PROCEDURE SetBytes*(startPos, bytes: SIZE; CONST values: ARRAY OF CHAR);
  67. VAR adr: ADDRESS;
  68. BEGIN
  69. ASSERT (startPos >= 0); ASSERT (startPos+8*bytes <= size); ASSERT(startPos MOD 8 = 0);
  70. adr := ADDRESS OF data[0] + startPos DIV 8;
  71. SYSTEM.MOVE(ADDRESS OF values[0], adr, bytes);
  72. END SetBytes;
  73. PROCEDURE GetBits* (startPos, bits: SIZE): WORD;
  74. VAR value: WORD; adr: ADDRESS;
  75. BEGIN
  76. ASSERT (startPos >= 0); ASSERT (startPos+bits <= size);
  77. IF (bits = 8) & (startPos MOD 8 =0) THEN
  78. adr := ADDRESS OF data[0] + startPos DIV 8;
  79. value := SYSTEM.GET8(adr)
  80. ELSE
  81. INC (startPos, bits); value := 0;
  82. WHILE bits > 0 DO
  83. value := value*2; DEC (startPos); DEC (bits);
  84. IF GetBit (startPos) THEN INC (value) END;
  85. END;
  86. WHILE bits < 0 DO
  87. value := value*2; INC (startPos); INC (bits);
  88. IF GetBit (startPos) THEN INC (value) END;
  89. END;
  90. END;
  91. RETURN value;
  92. END GetBits;
  93. PROCEDURE CopyTo*(address: ADDRESS; bits: SIZE);
  94. BEGIN
  95. ASSERT(bits MOD 8 = 0);
  96. SYSTEM.MOVE(ADDRESS OF data[0], address, bits DIV 8);
  97. END CopyTo;
  98. END BitSet;
  99. PROCEDURE CopyBits* (source: BitSet; sourcePos: SIZE; dest: BitSet; destPos, count: SIZE);
  100. CONST setSize= MAX(SET)+1;
  101. BEGIN
  102. ASSERT (count >= 0);
  103. IF sourcePos MOD setSize = destPos MOD setSize THEN
  104. WHILE (count # 0) & (sourcePos MOD setSize # 0) DO
  105. dest.SetBit (destPos, source.GetBit (sourcePos));
  106. INC (sourcePos); INC (destPos); DEC (count);
  107. END;
  108. WHILE (count >= setSize) DO
  109. dest.data[destPos DIV setSize] := source.data[sourcePos DIV setSize];
  110. INC(sourcePos,setSize); INC(destPos,setSize); DEC(count,setSize);
  111. END;
  112. WHILE count # 0 DO
  113. dest.SetBit (destPos, source.GetBit (sourcePos));
  114. INC (sourcePos); INC (destPos); DEC (count);
  115. END;
  116. ELSE
  117. WHILE count # 0 DO
  118. dest.SetBit (destPos, source.GetBit (sourcePos));
  119. INC (sourcePos); INC (destPos); DEC (count);
  120. END;
  121. END;
  122. END CopyBits;
  123. END BitSets.