xref: /inferno-os/appl/lib/sets.b (revision 6e425a9de8c003b5a733621a6b6730ec3cc902b8)
137da2899SCharles.Forsythimplement Sets;
237da2899SCharles.Forsythinclude "sys.m";
337da2899SCharles.Forsyth	sys: Sys;
437da2899SCharles.Forsythinclude "draw.m";
537da2899SCharles.Forsythinclude "sets.m";
637da2899SCharles.Forsyth
737da2899SCharles.Forsythinit()
837da2899SCharles.Forsyth{
937da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
1037da2899SCharles.Forsyth}
1137da2899SCharles.Forsyth
1237da2899SCharles.ForsythBPW: con 32;
1337da2899SCharles.ForsythSHIFT: con 5;
1437da2899SCharles.ForsythMASK: con 31;
1537da2899SCharles.Forsyth
1637da2899SCharles.Forsyth# Set adt contains:
1737da2899SCharles.Forsyth#	a - array holding membership of set s for n (0 ≤ n < len a * BPW).
1837da2899SCharles.Forsyth#		∀ n: 0≤n<(len a*BPW), (s.a[n >> SHIFT] & (1 << (n & MASK)) != 0) iff s ∋ n
1937da2899SCharles.Forsyth#	m - "most significant bits", extrapolate membership for n >= len a * BPW.
2037da2899SCharles.Forsyth#		m is 0 if members are excluded by default,
2137da2899SCharles.Forsyth#		or ~0 if members are included by default.
2237da2899SCharles.Forsyth
2337da2899SCharles.Forsythswapops := array[16] of {
2437da2899SCharles.Forsyth	byte 2r0000, byte 2r0001, byte 2r0100, byte 2r0101,
2537da2899SCharles.Forsyth	byte 2r0010, byte 2r0011, byte 2r0110, byte 2r0111,
2637da2899SCharles.Forsyth	byte 2r1000, byte 2r1001, byte 2r1100, byte 2r1101,
2737da2899SCharles.Forsyth	byte 2r1010, byte 2r1011, byte 2r1110, byte 2r1111,
2837da2899SCharles.Forsyth};
2937da2899SCharles.Forsyth
3037da2899SCharles.ForsythSet.X(s1: self Set, o: int, s2: Set): Set
3137da2899SCharles.Forsyth{
3237da2899SCharles.Forsyth	if (len s1.a > len s2.a) {
3337da2899SCharles.Forsyth		(s1, s2) = (s2, s1);
3437da2899SCharles.Forsyth		o = int swapops[o & 2r1111];
3537da2899SCharles.Forsyth	}
3637da2899SCharles.Forsyth	r := Set(0, array[len s2.a] of int);
3737da2899SCharles.Forsyth	for (i := 0; i < len s1.a; i++)
3837da2899SCharles.Forsyth		r.a[i] = op(o, s1.a[i], s2.a[i]);
3937da2899SCharles.Forsyth	for (; i < len s2.a; i++)
4037da2899SCharles.Forsyth		r.a[i] = op(o, s1.m, s2.a[i]);
4137da2899SCharles.Forsyth	r.m = op(o, s1.m, s2.m);
4237da2899SCharles.Forsyth	return r;
4337da2899SCharles.Forsyth}
4437da2899SCharles.Forsyth
4537da2899SCharles.ForsythSet.invert(s: self Set): Set
4637da2899SCharles.Forsyth{
4737da2899SCharles.Forsyth	r := Set(~s.m, array[len s.a] of int);
4837da2899SCharles.Forsyth	for (i := 0; i < len s.a; i++)
4937da2899SCharles.Forsyth		r.a[i] = ~s.a[i];
5037da2899SCharles.Forsyth	return r;
5137da2899SCharles.Forsyth}
5237da2899SCharles.Forsyth
5337da2899SCharles.Forsyth# copy s, ensuring that the copy is big enough to hold n.
5437da2899SCharles.Forsythcopy(s: Set, n: int): Set
5537da2899SCharles.Forsyth{
5637da2899SCharles.Forsyth	if (n >= 0) {
5737da2899SCharles.Forsyth		req := (n >> SHIFT) + 1;
5837da2899SCharles.Forsyth		if (req > len s.a) {
5937da2899SCharles.Forsyth			a := array[req] of int;
6037da2899SCharles.Forsyth			a[0:] = s.a;
6137da2899SCharles.Forsyth			for (i := len s.a; i < len a; i++)
6237da2899SCharles.Forsyth				a[i] = s.m;
6337da2899SCharles.Forsyth			return (s.m, a);
6437da2899SCharles.Forsyth		}
6537da2899SCharles.Forsyth	}
6637da2899SCharles.Forsyth	a: array of int;
6737da2899SCharles.Forsyth	if (len s.a > 0) {
6837da2899SCharles.Forsyth		a = array[len s.a] of int;
6937da2899SCharles.Forsyth		a[0:] = s.a;
7037da2899SCharles.Forsyth	}
7137da2899SCharles.Forsyth	return (s.m, a);
7237da2899SCharles.Forsyth}
7337da2899SCharles.Forsyth
7437da2899SCharles.ForsythSet.add(s: self Set, n: int): Set
7537da2899SCharles.Forsyth{
7637da2899SCharles.Forsyth	d := n >> SHIFT;
7737da2899SCharles.Forsyth	if (s.m && d >= len s.a)
7837da2899SCharles.Forsyth		return s;
7937da2899SCharles.Forsyth	r := copy(s, n);
8037da2899SCharles.Forsyth	r.a[d] |= 1<< (n & MASK);
8137da2899SCharles.Forsyth	return r;
8237da2899SCharles.Forsyth}
8337da2899SCharles.Forsyth
8437da2899SCharles.ForsythSet.addlist(s: self Set, ns: list of int): Set
8537da2899SCharles.Forsyth{
8637da2899SCharles.Forsyth	r: Set;
8737da2899SCharles.Forsyth	if (s.m == 0) {
8837da2899SCharles.Forsyth		max := -1;
8937da2899SCharles.Forsyth		for (l := ns; l != nil; l = tl l)
9037da2899SCharles.Forsyth			if (hd l > max)
9137da2899SCharles.Forsyth				max = hd l;
9237da2899SCharles.Forsyth		r = copy(s, max);
9337da2899SCharles.Forsyth	} else
9437da2899SCharles.Forsyth		r = copy(s, -1);
9537da2899SCharles.Forsyth	for (; ns != nil; ns = tl ns) {
9637da2899SCharles.Forsyth		n := hd ns;
9737da2899SCharles.Forsyth		d := n >> SHIFT;
9837da2899SCharles.Forsyth		if (d < len r.a)
9937da2899SCharles.Forsyth			r.a[d] |= 1 << (n & MASK);
10037da2899SCharles.Forsyth	}
10137da2899SCharles.Forsyth	return r;
10237da2899SCharles.Forsyth}
10337da2899SCharles.Forsyth
10437da2899SCharles.Forsyth
10537da2899SCharles.ForsythSet.del(s: self Set, n: int): Set
10637da2899SCharles.Forsyth{
10737da2899SCharles.Forsyth	d := n >> SHIFT;
10837da2899SCharles.Forsyth	if (!s.m && d >= len s.a)
10937da2899SCharles.Forsyth		return s;
11037da2899SCharles.Forsyth	r := copy(s, n);
11137da2899SCharles.Forsyth	r.a[d] &= ~(1 << (n & MASK));
11237da2899SCharles.Forsyth	return r;
11337da2899SCharles.Forsyth}
11437da2899SCharles.Forsyth
11537da2899SCharles.ForsythSet.holds(s: self Set, n: int): int
11637da2899SCharles.Forsyth{
11737da2899SCharles.Forsyth	d := n >> SHIFT;
11837da2899SCharles.Forsyth	if (d >= len s.a)
11937da2899SCharles.Forsyth		return s.m;
12037da2899SCharles.Forsyth	return s.a[d] & (1 << (n & MASK));
12137da2899SCharles.Forsyth}
12237da2899SCharles.Forsyth
12337da2899SCharles.ForsythSet.limit(s: self Set): int
12437da2899SCharles.Forsyth{
12537da2899SCharles.Forsyth	for (i := len s.a - 1; i >= 0; i--)
12637da2899SCharles.Forsyth		if (s.a[i] != s.m)
12737da2899SCharles.Forsyth			return (i<<SHIFT) + topbit(s.m ^ s.a[i]);
12837da2899SCharles.Forsyth	return 0;
12937da2899SCharles.Forsyth}
13037da2899SCharles.Forsyth
13137da2899SCharles.ForsythSet.eq(s1: self Set, s2: Set): int
13237da2899SCharles.Forsyth{
13337da2899SCharles.Forsyth	if (len s1.a > len s2.a)
13437da2899SCharles.Forsyth		(s1, s2) = (s2, s1);
13537da2899SCharles.Forsyth	for (i := 0; i < len s1.a; i++)
13637da2899SCharles.Forsyth		if (s1.a[i] != s2.a[i])
13737da2899SCharles.Forsyth			return 0;
13837da2899SCharles.Forsyth	for (; i < len s2.a; i++)
13937da2899SCharles.Forsyth		if (s1.m != s2.a[i])
14037da2899SCharles.Forsyth			return 0;
14137da2899SCharles.Forsyth	return s1.m == s2.m;
14237da2899SCharles.Forsyth}
14337da2899SCharles.Forsyth
14437da2899SCharles.ForsythSet.isempty(s: self Set): int
14537da2899SCharles.Forsyth{
14637da2899SCharles.Forsyth	return Set(0, nil).eq(s);
14737da2899SCharles.Forsyth}
14837da2899SCharles.Forsyth
14937da2899SCharles.ForsythSet.msb(s: self Set): int
15037da2899SCharles.Forsyth{
15137da2899SCharles.Forsyth	return s.m != 0;
15237da2899SCharles.Forsyth}
15337da2899SCharles.Forsyth
15437da2899SCharles.ForsythSet.bytes(s: self Set, n: int): array of byte
15537da2899SCharles.Forsyth{
15637da2899SCharles.Forsyth	m := (s.limit() >> 3) + 1;
15737da2899SCharles.Forsyth	if(m > n)
15837da2899SCharles.Forsyth		n = m;
15937da2899SCharles.Forsyth	d := array[n] of byte;
16037da2899SCharles.Forsyth	# XXX this could proably be made substantially faster by unrolling the
16137da2899SCharles.Forsyth	# loop a little.
16237da2899SCharles.Forsyth	for(i := 0; i < len d; i++){
16337da2899SCharles.Forsyth		j := i >> 2;
16437da2899SCharles.Forsyth		if(j >= len s.a)
16537da2899SCharles.Forsyth			d[i] = byte s.m;
16637da2899SCharles.Forsyth		else
16737da2899SCharles.Forsyth			d[i] = byte (s.a[j] >> ((i & 3) << 3));
16837da2899SCharles.Forsyth	}
16937da2899SCharles.Forsyth	return d;
17037da2899SCharles.Forsyth}
17137da2899SCharles.Forsyth
17237da2899SCharles.Forsythbytes2set(d: array of byte): Set
17337da2899SCharles.Forsyth{
17437da2899SCharles.Forsyth	if(len d == 0)
17537da2899SCharles.Forsyth		return (0, nil);
17637da2899SCharles.Forsyth	a := array[(len d + 3) >> 2] of int;		# round up
17737da2899SCharles.Forsyth	n := len d >> 2;
17837da2899SCharles.Forsyth	for(i := 0; i < n; i++){
17937da2899SCharles.Forsyth		j := i << 2;
18037da2899SCharles.Forsyth		a[i] = int d[j] + (int d[j+1] << 8) + (int d[j+2] << 16) + (int d[j+3] << 24);
18137da2899SCharles.Forsyth	}
18237da2899SCharles.Forsyth	msb := ~(int (d[len d - 1] >> 7) - 1);
18337da2899SCharles.Forsyth	j := i << 2;
18437da2899SCharles.Forsyth	case len d & 3 {
18537da2899SCharles.Forsyth	0 =>
18637da2899SCharles.Forsyth		;
18737da2899SCharles.Forsyth	1 =>
18837da2899SCharles.Forsyth		a[i] = int d[j] | (msb & int 16rffffff00);
18937da2899SCharles.Forsyth	2 =>
19037da2899SCharles.Forsyth		a[i] = int d[j] | (int d[j+1] << 8) | (msb & int 16rffff0000);
19137da2899SCharles.Forsyth	3 =>
19237da2899SCharles.Forsyth		a[i] = int d[j] | (int d[j+1] << 8) | (int d[j+2] << 16) | (msb & int 16rff000000);
19337da2899SCharles.Forsyth	}
19437da2899SCharles.Forsyth	return (msb, a);
19537da2899SCharles.Forsyth}
19637da2899SCharles.Forsyth
19737da2899SCharles.ForsythSet.str(s: self Set): string
19837da2899SCharles.Forsyth{
19937da2899SCharles.Forsyth	str: string;
20037da2899SCharles.Forsyth
20137da2899SCharles.Forsyth	# discard all top bits that are the same as msb.
20237da2899SCharles.Forsyth	sig := 0;
20337da2899SCharles.Forsythloop:
20437da2899SCharles.Forsyth	for (i := len s.a - 1; i >= 0; i--) {
20537da2899SCharles.Forsyth		t := 16rf << (BPW - 4);
20637da2899SCharles.Forsyth		sig = 8;
20737da2899SCharles.Forsyth		while (t != 0) {
20837da2899SCharles.Forsyth			if ((s.m & t) != (s.a[i] & t))
20937da2899SCharles.Forsyth				break loop;
21037da2899SCharles.Forsyth			sig--;
21137da2899SCharles.Forsyth			t = (t >> 4) & 16r0fffffff;		# logical shift right
21237da2899SCharles.Forsyth		}
21337da2899SCharles.Forsyth	}
21437da2899SCharles.Forsyth	if (i >= 0) {
21537da2899SCharles.Forsyth		top := s.a[i];
21637da2899SCharles.Forsyth		if (sig < 8)		# shifting left by 32 bits is undefined.
21737da2899SCharles.Forsyth			top &= (1 << (sig << 2)) - 1;
21837da2899SCharles.Forsyth		str = sys->sprint("%.*ux", sig, top);
21937da2899SCharles.Forsyth		for (i--; i >= 0; i--)
22037da2899SCharles.Forsyth			str += sys->sprint("%.8ux", s.a[i]);
22137da2899SCharles.Forsyth	}
22237da2899SCharles.Forsyth	return str + ":" + string (s.m & 1);
22337da2899SCharles.Forsyth}
22437da2899SCharles.Forsyth
22537da2899SCharles.Forsythstr2set(str: string): Set
22637da2899SCharles.Forsyth{
22737da2899SCharles.Forsyth	n := len str;
22837da2899SCharles.Forsyth	if (n < 2 || str[n - 2] != ':')
22937da2899SCharles.Forsyth		return (0, nil);
23037da2899SCharles.Forsyth	c := str[n - 1];
23137da2899SCharles.Forsyth	if (c != '0' && c != '1')
23237da2899SCharles.Forsyth		return (0, nil);
23337da2899SCharles.Forsyth	msb := ~(c - '1');
23437da2899SCharles.Forsyth
23537da2899SCharles.Forsyth	n -= 2;
23637da2899SCharles.Forsyth	if (n == 0)
23737da2899SCharles.Forsyth		return (msb, nil);
23837da2899SCharles.Forsyth	req := ((n * 4 - 1) >> SHIFT) + 1;
23937da2899SCharles.Forsyth	a := array[req] of int;
24037da2899SCharles.Forsyth	d := 0;
24137da2899SCharles.Forsyth	for (i := n; i > 0; ) {
24237da2899SCharles.Forsyth		j := i - 8;
24337da2899SCharles.Forsyth		if (j < 0)
24437da2899SCharles.Forsyth			j = 0;
24537da2899SCharles.Forsyth		a[d++] = hex2int(str[j:i], msb);
24637da2899SCharles.Forsyth		i = j;
24737da2899SCharles.Forsyth	}
24837da2899SCharles.Forsyth	return (msb, a);
24937da2899SCharles.Forsyth}
25037da2899SCharles.Forsyth
25137da2899SCharles.ForsythSet.debugstr(s: self Set): string
25237da2899SCharles.Forsyth{
25337da2899SCharles.Forsyth	str: string;
25437da2899SCharles.Forsyth	for (i := len s.a - 1; i >= 0; i--)
25537da2899SCharles.Forsyth		str += sys->sprint("%ux:", s.a[i]);
25637da2899SCharles.Forsyth	str += sys->sprint(":%ux", s.m);
25737da2899SCharles.Forsyth	return str;
25837da2899SCharles.Forsyth}
25937da2899SCharles.Forsyth
26037da2899SCharles.Forsythset(): Set
26137da2899SCharles.Forsyth{
26237da2899SCharles.Forsyth	return (0, nil);
26337da2899SCharles.Forsyth}
26437da2899SCharles.Forsyth
26537da2899SCharles.Forsythhex2int(s: string, fill: int): int
26637da2899SCharles.Forsyth{
26737da2899SCharles.Forsyth	n := fill;
26837da2899SCharles.Forsyth	for (i := 0; i < len s; i++) {
26937da2899SCharles.Forsyth		c := s[i];
27037da2899SCharles.Forsyth		if (c >= '0' && c <= '9')
27137da2899SCharles.Forsyth			c -= '0';
27237da2899SCharles.Forsyth		else if (c >= 'a' && c <= 'f')
27337da2899SCharles.Forsyth			c -= 'a' - 10;
27437da2899SCharles.Forsyth		else if (c >= 'A' && c <= 'F')
27537da2899SCharles.Forsyth			c -= 'A' - 10;
27637da2899SCharles.Forsyth		else
27737da2899SCharles.Forsyth			c = 0;
27837da2899SCharles.Forsyth		n = (n << 4) | c;
27937da2899SCharles.Forsyth	}
28037da2899SCharles.Forsyth	return n;
28137da2899SCharles.Forsyth}
28237da2899SCharles.Forsyth
28337da2899SCharles.Forsythop(o: int, a, b: int): int
28437da2899SCharles.Forsyth{
28537da2899SCharles.Forsyth	case o &  2r1111 {
28637da2899SCharles.Forsyth	2r0000 => return 0;
28737da2899SCharles.Forsyth	2r0001 => return ~(a | b);
28837da2899SCharles.Forsyth	2r0010 => return a & ~b;
28937da2899SCharles.Forsyth	2r0011 => return ~b;
29037da2899SCharles.Forsyth	2r0100 => return ~a & b;
29137da2899SCharles.Forsyth	2r0101 => return ~a;
29237da2899SCharles.Forsyth	2r0110 => return a ^ b;
29337da2899SCharles.Forsyth	2r0111 => return ~(a & b);
29437da2899SCharles.Forsyth	2r1000 => return a & b;
29537da2899SCharles.Forsyth	2r1001 => return ~(a ^ b);
29637da2899SCharles.Forsyth	2r1010 => return a;
29737da2899SCharles.Forsyth	2r1011 => return a | ~b;
29837da2899SCharles.Forsyth	2r1100 => return b;
299*6e425a9dSCharles.Forsyth	2r1101 => return ~a | b;
30037da2899SCharles.Forsyth	2r1110 => return a | b;
30137da2899SCharles.Forsyth	2r1111 => return ~0;
30237da2899SCharles.Forsyth	}
30337da2899SCharles.Forsyth	return 0;
30437da2899SCharles.Forsyth}
30537da2899SCharles.Forsyth
30637da2899SCharles.Forsythtopbit(v: int): int
30737da2899SCharles.Forsyth{
30837da2899SCharles.Forsyth	if (v == 0)
30937da2899SCharles.Forsyth		return 0;
31037da2899SCharles.Forsyth	(b, n, mask) := (1, 16, int 16rffff0000);
31137da2899SCharles.Forsyth	while (n != 0) {
31237da2899SCharles.Forsyth		if (v & mask) {
31337da2899SCharles.Forsyth			b += n;
31437da2899SCharles.Forsyth			v >>= n;		# could return if v==0 here if we thought it worth it
31537da2899SCharles.Forsyth		}
31637da2899SCharles.Forsyth		n >>= 1;
31737da2899SCharles.Forsyth		mask >>= n;
31837da2899SCharles.Forsyth	}
31937da2899SCharles.Forsyth	return b;
32037da2899SCharles.Forsyth}
32137da2899SCharles.Forsyth
32237da2899SCharles.Forsythnbits(n: int): int
32337da2899SCharles.Forsyth{
32437da2899SCharles.Forsyth	n = ((n >> 1) & 16r55555555) + (n & 16r55555555) ;
32537da2899SCharles.Forsyth	n = ((n >> 2) & 16r33333333) + (n & 16r33333333) ;
32637da2899SCharles.Forsyth	n = ((n >> 4) + n) & 16r0F0F0F0F ;
32737da2899SCharles.Forsyth	n = ((n >> 8) + n) ;
32837da2899SCharles.Forsyth	return ((n >> 16) + n) & 16rFF ;
32937da2899SCharles.Forsyth}
330