summaryrefslogtreecommitdiff
path: root/appl/lib/sets32.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/sets32.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/lib/sets32.b')
-rw-r--r--appl/lib/sets32.b226
1 files changed, 226 insertions, 0 deletions
diff --git a/appl/lib/sets32.b b/appl/lib/sets32.b
new file mode 100644
index 00000000..01edea46
--- /dev/null
+++ b/appl/lib/sets32.b
@@ -0,0 +1,226 @@
+implement Sets;
+include "sys.m";
+ sys: Sys;
+include "sets32.m";
+
+init()
+{
+ sys = load Sys Sys->PATH;
+}
+
+set(): Set
+{
+ return Set(0);
+}
+
+BITS: con 32;
+MSB: con 1 << (BITS - 1);
+
+Set.X(s1: self Set, o: int, s2: Set): Set
+{
+ return Set(op(o, s1.s, s2.s));
+}
+
+Set.invert(s: self Set): Set
+{
+ return Set(~s.s);
+}
+
+Set.add(s: self Set, n: int): Set
+{
+ return Set(s.s | (1 << n));
+}
+
+Set.del(s: self Set, n: int): Set
+{
+ return Set(s.s & ~(1 << n));
+}
+
+Set.addlist(s: self Set, ns: list of int): Set
+{
+ for (; ns != nil; ns = tl ns)
+ s.s |= (1 << hd ns);
+ return s;
+}
+
+Set.holds(s: self Set, n: int): int
+{
+ return s.s & (1 << n);
+}
+
+Set.str(s: self Set): string
+{
+ msb := s.s >> (BITS - 1);
+
+ # discard all top bits that are the same as msb
+ t := 16rf << (BITS - 4);
+ sig := 8;
+ while (t != 0) {
+ if ((msb & t) != (s.s & t))
+ break;
+ sig--;
+ t = (t >> 4) & 16r0fffffff; # logical shift right
+ }
+ str: string;
+ if (sig > 0) {
+ top := ~MSB & s.s;
+ if (sig < 8) # shifting left by 32 bits is undefined.
+ top &= (1 << (sig << 2)) - 1;
+ str = sys->sprint("%.*ux", sig, top);
+ }
+ return str + ":" + string (msb & 1);
+}
+
+Set.bytes(s: self Set, n: int): array of byte
+{
+ m := (s.limit() >> 3) + 1;
+ if(m > n)
+ n = m;
+ d := array[n] of byte;
+ case len d {
+ 1 =>
+ d[0] = byte s.s;
+ 2 =>
+ d[0] = byte s.s;
+ d[1] = byte (s.s >> 8);
+ 3 =>
+ d[0] = byte s.s;
+ d[1] = byte (s.s >> 8);
+ d[2] = byte (s.s >> 16);
+ 4 =>
+ d[0] = byte s.s;
+ d[1] = byte (s.s >> 8);
+ d[2] = byte (s.s >> 16);
+ d[3] = byte (s.s >> 24);
+ * =>
+ d[0] = byte s.s;
+ d[1] = byte (s.s >> 8);
+ d[2] = byte (s.s >> 16);
+ d[3] = byte (s.s >> 24);
+ msb := byte (s.s >> (BITS - 1)); # sign extension
+ for(i := 4; i < len d; i++)
+ d[i] = msb;
+ }
+ return d;
+}
+
+bytes2set(d: array of byte): Set
+{
+ if(len d == 0)
+ return Set(0);
+ msb := ~(int (d[len d - 1] >> 7) - 1);
+ v: int;
+ case len d {
+ 1 =>
+ v = int d[0] | (msb & int 16rffffff00);
+ 2 =>
+ v = int d[0] | (int d[1] << 8) | (msb & int 16rffff0000);
+ 3 =>
+ v = int d[0] | (int d[1] << 8) | (int d[2] << 16) | (msb & int 16rff000000);
+ * or # XXX could raise (or return) an error for len d > 4
+ 4 =>
+ v = int d[0] | (int d[1] << 8) | (int d[2] << 16) | (int d[3] << 24);
+ }
+ return Set(v);
+}
+
+
+Set.debugstr(s: self Set): string
+{
+ return sys->sprint("%ux", s.s);
+}
+
+Set.eq(s1: self Set, s2: Set): int
+{
+ return s1.s == s2.s;
+}
+
+Set.isempty(s: self Set): int
+{
+ return s.s == 0;
+}
+
+Set.msb(s: self Set): int
+{
+ return (s.s & MSB) != 0;
+}
+
+Set.limit(s: self Set): int
+{
+ m := s.s >> (BITS - 1); # sign extension
+ return topbit(s.s ^ m);
+}
+
+topbit(v: int): int
+{
+ if (v == 0)
+ return 0;
+ (b, n, mask) := (1, 16, int 16rffff0000);
+ while (n != 0) {
+ if (v & mask) {
+ b += n;
+ v >>= n; # could return if v==0 here if we thought it worth it
+ }
+ n >>= 1;
+ mask >>= n;
+ }
+ return b;
+}
+
+
+str2set(str: string): Set
+{
+ n := len str;
+ if (n < 2 || str[n - 2] != ':')
+ return Set(0);
+ c := str[n - 1];
+ if (c != '0' && c != '1')
+ return Set(0);
+ n -= 2;
+ msb := ~(c - '1');
+ # XXX should we give some sort of error if there
+ # are more bits than we can hold?
+ return Set((hex2int(str[0:n], msb) & ~MSB) | (msb & MSB));
+}
+
+hex2int(s: string, fill: int): int
+{
+ n := fill;
+ for (i := 0; i < len s; i++) {
+ c := s[i];
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'F')
+ c -= 'A' - 10;
+ else
+ c = 0;
+ n = (n << 4) | c;
+ }
+ return n;
+}
+
+
+op(o: int, a, b: int): int
+{
+ case o & 2r1111 {
+ 2r0000 => return 0;
+ 2r0001 => return ~(a | b);
+ 2r0010 => return a & ~b;
+ 2r0011 => return ~b;
+ 2r0100 => return ~a & b;
+ 2r0101 => return ~a;
+ 2r0110 => return a ^ b;
+ 2r0111 => return ~(a & b);
+ 2r1000 => return a & b;
+ 2r1001 => return ~(a ^ b);
+ 2r1010 => return a;
+ 2r1011 => return a | ~b;
+ 2r1100 => return b;
+ 2r1101 => return ~(a | b);
+ 2r1110 => return a | b;
+ 2r1111 => return ~0;
+ }
+ return 0;
+}