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; }