xref: /inferno-os/appl/math/polyfill.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Polyfill;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsyth	draw: Draw;
7*37da2899SCharles.Forsyth	Point, Rect, Image, Endsquare: import draw;
8*37da2899SCharles.Forsythinclude "math/polyfill.m";
9*37da2899SCharles.Forsyth
10*37da2899SCharles.Forsyth∞: con 16r7fffffff;
11*37da2899SCharles.Forsyth
12*37da2899SCharles.Forsythinit()
13*37da2899SCharles.Forsyth{
14*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
15*37da2899SCharles.Forsyth	draw = load Draw Draw->PATH;
16*37da2899SCharles.Forsyth}
17*37da2899SCharles.Forsyth
18*37da2899SCharles.Forsythinitzbuf(r: Rect): ref Zstate
19*37da2899SCharles.Forsyth{
20*37da2899SCharles.Forsyth	if(sys == nil)
21*37da2899SCharles.Forsyth		init();
22*37da2899SCharles.Forsyth	s := ref Zstate;
23*37da2899SCharles.Forsyth	s.r = r;
24*37da2899SCharles.Forsyth	s.xlen = r.dx();
25*37da2899SCharles.Forsyth	s.ylen = r.dy();
26*37da2899SCharles.Forsyth	s.xylen = s.xlen*s.ylen;
27*37da2899SCharles.Forsyth	s.zbuf0 = array[s.xylen] of int;
28*37da2899SCharles.Forsyth	s.zbuf1 = array[s.xylen] of int;
29*37da2899SCharles.Forsyth	return s;
30*37da2899SCharles.Forsyth}
31*37da2899SCharles.Forsyth
32*37da2899SCharles.Forsythclearzbuf(s: ref Zstate)
33*37da2899SCharles.Forsyth{
34*37da2899SCharles.Forsyth	b0 := s.zbuf0;
35*37da2899SCharles.Forsyth	b1 := s.zbuf1;
36*37da2899SCharles.Forsyth	n := s.xylen;
37*37da2899SCharles.Forsyth	for(i := 0; i < n; i++)
38*37da2899SCharles.Forsyth		b0[i] = b1[i] = ∞;
39*37da2899SCharles.Forsyth}
40*37da2899SCharles.Forsyth
41*37da2899SCharles.Forsythsetzbuf(s: ref Zstate, zd: int)
42*37da2899SCharles.Forsyth{
43*37da2899SCharles.Forsyth	b0 := s.zbuf0;
44*37da2899SCharles.Forsyth	b1 := s.zbuf1;
45*37da2899SCharles.Forsyth	n := s.xylen;
46*37da2899SCharles.Forsyth	for(i := 0; i < n; i++)
47*37da2899SCharles.Forsyth		b0[i] = b1[i] = zd;
48*37da2899SCharles.Forsyth}
49*37da2899SCharles.Forsyth
50*37da2899SCharles.ForsythSeg: adt
51*37da2899SCharles.Forsyth{
52*37da2899SCharles.Forsyth	p0: Point;
53*37da2899SCharles.Forsyth	p1: Point;
54*37da2899SCharles.Forsyth	num: int;
55*37da2899SCharles.Forsyth	den: int;
56*37da2899SCharles.Forsyth	dz: int;
57*37da2899SCharles.Forsyth	dzrem: int;
58*37da2899SCharles.Forsyth	z: int;
59*37da2899SCharles.Forsyth	zerr: int;
60*37da2899SCharles.Forsyth	d: int;
61*37da2899SCharles.Forsyth};
62*37da2899SCharles.Forsyth
63*37da2899SCharles.Forsythfillline(dst: ref Image, left: int, right: int, y: int, src: ref Image, p: Point)
64*37da2899SCharles.Forsyth{
65*37da2899SCharles.Forsyth	p.x += left;
66*37da2899SCharles.Forsyth	p.y += y;
67*37da2899SCharles.Forsyth	dst.line((left, y), (right, y), Endsquare, Endsquare, 0, src, p);
68*37da2899SCharles.Forsyth}
69*37da2899SCharles.Forsyth
70*37da2899SCharles.Forsythfilllinez(dst: ref Image, left: int, right: int, y: int, z: int, e: int, dx: int, k: int, zbuf0: array of int, zbuf1: array of int, src: ref Image, p: Point)
71*37da2899SCharles.Forsyth{
72*37da2899SCharles.Forsyth	prevx := ∞;
73*37da2899SCharles.Forsyth	for(x := left; x <= right; x++){
74*37da2899SCharles.Forsyth		if(z+e < zbuf0[k] || (z-e <= zbuf1[k] && x != right && prevx != ∞)){
75*37da2899SCharles.Forsyth			zbuf0[k] = z-e;
76*37da2899SCharles.Forsyth			zbuf1[k] = z+e;
77*37da2899SCharles.Forsyth			if(prevx == ∞)
78*37da2899SCharles.Forsyth				prevx = x;
79*37da2899SCharles.Forsyth		}
80*37da2899SCharles.Forsyth		else if(prevx != ∞){
81*37da2899SCharles.Forsyth			fillline(dst, prevx, x-1, y, src, p);
82*37da2899SCharles.Forsyth			prevx = ∞;
83*37da2899SCharles.Forsyth		}
84*37da2899SCharles.Forsyth		z += dx;
85*37da2899SCharles.Forsyth		k++;
86*37da2899SCharles.Forsyth	}
87*37da2899SCharles.Forsyth	if(prevx != ∞)
88*37da2899SCharles.Forsyth		fillline(dst, prevx, right, y, src, p);
89*37da2899SCharles.Forsyth}
90*37da2899SCharles.Forsyth
91*37da2899SCharles.Forsythfillpoly(dst: ref Image, vert: array of Point, w: int, src: ref Image, sp: Point, zstate: ref Zstate, dc: int, dx: int, dy: int)
92*37da2899SCharles.Forsyth{
93*37da2899SCharles.Forsyth	p0: Point;
94*37da2899SCharles.Forsyth	i: int;
95*37da2899SCharles.Forsyth
96*37da2899SCharles.Forsyth	nvert := len vert;
97*37da2899SCharles.Forsyth	if(nvert == 0)
98*37da2899SCharles.Forsyth		return;
99*37da2899SCharles.Forsyth	fixshift := 0;
100*37da2899SCharles.Forsyth	seg := array[nvert+2] of ref Seg;
101*37da2899SCharles.Forsyth	if(seg == nil)
102*37da2899SCharles.Forsyth		return;
103*37da2899SCharles.Forsyth	segtab := array[nvert+1] of ref Seg;
104*37da2899SCharles.Forsyth	if(segtab == nil)
105*37da2899SCharles.Forsyth		return;
106*37da2899SCharles.Forsyth
107*37da2899SCharles.Forsyth	sp.x = (sp.x - vert[0].x) >> fixshift;
108*37da2899SCharles.Forsyth	sp.y = (sp.y - vert[0].y) >> fixshift;
109*37da2899SCharles.Forsyth	p0 = vert[nvert-1];
110*37da2899SCharles.Forsyth	if(!fixshift) {
111*37da2899SCharles.Forsyth		p0.x <<= 1;
112*37da2899SCharles.Forsyth		p0.y <<= 1;
113*37da2899SCharles.Forsyth	}
114*37da2899SCharles.Forsyth	for(i = 0; i < nvert; i++) {
115*37da2899SCharles.Forsyth		segtab[i] = ref Seg;
116*37da2899SCharles.Forsyth		segtab[i].p0 = p0;
117*37da2899SCharles.Forsyth		p0 = vert[i];
118*37da2899SCharles.Forsyth		if(!fixshift) {
119*37da2899SCharles.Forsyth			p0.x <<= 1;
120*37da2899SCharles.Forsyth			p0.y <<= 1;
121*37da2899SCharles.Forsyth		}
122*37da2899SCharles.Forsyth		segtab[i].p1 = p0;
123*37da2899SCharles.Forsyth		segtab[i].d = 1;
124*37da2899SCharles.Forsyth	}
125*37da2899SCharles.Forsyth	if(!fixshift)
126*37da2899SCharles.Forsyth		fixshift = 1;
127*37da2899SCharles.Forsyth
128*37da2899SCharles.Forsyth	xscan(dst, seg, segtab, nvert, w, src, sp, zstate, dc, dx, dy, fixshift);
129*37da2899SCharles.Forsyth}
130*37da2899SCharles.Forsyth
131*37da2899SCharles.Forsythmod(x: int, y: int): int
132*37da2899SCharles.Forsyth{
133*37da2899SCharles.Forsyth	z: int;
134*37da2899SCharles.Forsyth
135*37da2899SCharles.Forsyth	z = x%y;
136*37da2899SCharles.Forsyth	if((z^y) > 0 || z == 0)
137*37da2899SCharles.Forsyth		return z;
138*37da2899SCharles.Forsyth	return z + y;
139*37da2899SCharles.Forsyth}
140*37da2899SCharles.Forsyth
141*37da2899SCharles.Forsythsdiv(x: int, y: int): int
142*37da2899SCharles.Forsyth{
143*37da2899SCharles.Forsyth	if((x^y) >= 0 || x == 0)
144*37da2899SCharles.Forsyth		return x/y;
145*37da2899SCharles.Forsyth	return (x+((y>>30)|1))/y-1;
146*37da2899SCharles.Forsyth}
147*37da2899SCharles.Forsyth
148*37da2899SCharles.Forsythsmuldivmod(x: int, y: int, z: int): (int, int)
149*37da2899SCharles.Forsyth{
150*37da2899SCharles.Forsyth	mod: int;
151*37da2899SCharles.Forsyth	vx: int;
152*37da2899SCharles.Forsyth
153*37da2899SCharles.Forsyth	if(x == 0 || y == 0)
154*37da2899SCharles.Forsyth		return (0, 0);
155*37da2899SCharles.Forsyth	vx = x;
156*37da2899SCharles.Forsyth	vx *= y;
157*37da2899SCharles.Forsyth	mod = vx % z;
158*37da2899SCharles.Forsyth	if(mod < 0)
159*37da2899SCharles.Forsyth		mod += z;
160*37da2899SCharles.Forsyth	if((vx < 0) == (z < 0))
161*37da2899SCharles.Forsyth		return (vx/z, mod);
162*37da2899SCharles.Forsyth	return (-((-vx)/z), mod);
163*37da2899SCharles.Forsyth}
164*37da2899SCharles.Forsyth
165*37da2899SCharles.Forsythxscan(dst: ref Image, seg: array of ref Seg, segtab: array of ref Seg, nseg: int, wind: int, src: ref Image, spt: Point, zstate: ref Zstate, dc: int, dx: int, dy: int, fixshift: int)
166*37da2899SCharles.Forsyth{
167*37da2899SCharles.Forsyth	y, maxy, x, x2, onehalf: int;
168*37da2899SCharles.Forsyth	ep, next, p, q, s: int;
169*37da2899SCharles.Forsyth	n, i, iy, cnt, ix, ix2, minx, maxx, zinc, k, zv: int;
170*37da2899SCharles.Forsyth	pt: Point;
171*37da2899SCharles.Forsyth	sp: ref Seg;
172*37da2899SCharles.Forsyth
173*37da2899SCharles.Forsyth	er := (abs(dx)+abs(dy)+1)/2;
174*37da2899SCharles.Forsyth	zr := zstate.r;
175*37da2899SCharles.Forsyth	xlen := zstate.xlen;
176*37da2899SCharles.Forsyth	zbuf0 := zstate.zbuf0;
177*37da2899SCharles.Forsyth	zbuf1 := zstate.zbuf1;
178*37da2899SCharles.Forsyth	s = 0;
179*37da2899SCharles.Forsyth	p = 0;
180*37da2899SCharles.Forsyth	for(i=0; i<nseg; i++) {
181*37da2899SCharles.Forsyth		sp = seg[p] = segtab[s];
182*37da2899SCharles.Forsyth		if(sp.p0.y == sp.p1.y){
183*37da2899SCharles.Forsyth			s++;
184*37da2899SCharles.Forsyth			continue;
185*37da2899SCharles.Forsyth		}
186*37da2899SCharles.Forsyth		if(sp.p0.y > sp.p1.y) {
187*37da2899SCharles.Forsyth			pt = sp.p0;
188*37da2899SCharles.Forsyth			sp.p0 = sp.p1;
189*37da2899SCharles.Forsyth			sp.p1 = pt;
190*37da2899SCharles.Forsyth			sp.d = -sp.d;
191*37da2899SCharles.Forsyth		}
192*37da2899SCharles.Forsyth		sp.num = sp.p1.x - sp.p0.x;
193*37da2899SCharles.Forsyth		sp.den = sp.p1.y - sp.p0.y;
194*37da2899SCharles.Forsyth		sp.dz = sdiv(sp.num, sp.den) << fixshift;
195*37da2899SCharles.Forsyth		sp.dzrem = mod(sp.num, sp.den) << fixshift;
196*37da2899SCharles.Forsyth		sp.dz += sdiv(sp.dzrem, sp.den);
197*37da2899SCharles.Forsyth		sp.dzrem = mod(sp.dzrem, sp.den);
198*37da2899SCharles.Forsyth		p++;
199*37da2899SCharles.Forsyth		s++;
200*37da2899SCharles.Forsyth	}
201*37da2899SCharles.Forsyth	n = p;
202*37da2899SCharles.Forsyth	if(n == 0)
203*37da2899SCharles.Forsyth		return;
204*37da2899SCharles.Forsyth	seg[p] = nil;
205*37da2899SCharles.Forsyth	qsortycompare(seg, p);
206*37da2899SCharles.Forsyth
207*37da2899SCharles.Forsyth	onehalf = 0;
208*37da2899SCharles.Forsyth	if(fixshift)
209*37da2899SCharles.Forsyth		onehalf = 1 << (fixshift-1);
210*37da2899SCharles.Forsyth
211*37da2899SCharles.Forsyth	minx = dst.clipr.min.x;
212*37da2899SCharles.Forsyth	maxx = dst.clipr.max.x;
213*37da2899SCharles.Forsyth
214*37da2899SCharles.Forsyth	y = seg[0].p0.y;
215*37da2899SCharles.Forsyth	if(y < (dst.clipr.min.y << fixshift))
216*37da2899SCharles.Forsyth		y = dst.clipr.min.y << fixshift;
217*37da2899SCharles.Forsyth	iy = (y + onehalf) >> fixshift;
218*37da2899SCharles.Forsyth	y = (iy << fixshift) + onehalf;
219*37da2899SCharles.Forsyth	maxy = dst.clipr.max.y << fixshift;
220*37da2899SCharles.Forsyth	k = (iy-zr.min.y)*xlen;
221*37da2899SCharles.Forsyth	zv = dc+iy*dy;
222*37da2899SCharles.Forsyth
223*37da2899SCharles.Forsyth	ep = next = 0;
224*37da2899SCharles.Forsyth
225*37da2899SCharles.Forsyth	while(y<maxy) {
226*37da2899SCharles.Forsyth		for(q = p = 0; p < ep; p++) {
227*37da2899SCharles.Forsyth			sp = seg[p];
228*37da2899SCharles.Forsyth			if(sp.p1.y < y)
229*37da2899SCharles.Forsyth				continue;
230*37da2899SCharles.Forsyth			sp.z += sp.dz;
231*37da2899SCharles.Forsyth			sp.zerr += sp.dzrem;
232*37da2899SCharles.Forsyth			if(sp.zerr >= sp.den) {
233*37da2899SCharles.Forsyth				sp.z++;
234*37da2899SCharles.Forsyth				sp.zerr -= sp.den;
235*37da2899SCharles.Forsyth				if(sp.zerr < 0 || sp.zerr >= sp.den)
236*37da2899SCharles.Forsyth					sys->print("bad ratzerr1: %d den %d dzrem %d\n", sp.zerr, sp.den, sp.dzrem);
237*37da2899SCharles.Forsyth			}
238*37da2899SCharles.Forsyth			seg[q] = sp;
239*37da2899SCharles.Forsyth			q++;
240*37da2899SCharles.Forsyth		}
241*37da2899SCharles.Forsyth
242*37da2899SCharles.Forsyth		for(p = next; seg[p] != nil; p++) {
243*37da2899SCharles.Forsyth			sp = seg[p];
244*37da2899SCharles.Forsyth			if(sp.p0.y >= y)
245*37da2899SCharles.Forsyth				break;
246*37da2899SCharles.Forsyth			if(sp.p1.y < y)
247*37da2899SCharles.Forsyth				continue;
248*37da2899SCharles.Forsyth			sp.z = sp.p0.x;
249*37da2899SCharles.Forsyth			(zinc, sp.zerr) = smuldivmod(y - sp.p0.y, sp.num, sp.den);
250*37da2899SCharles.Forsyth			sp.z += zinc;
251*37da2899SCharles.Forsyth			if(sp.zerr < 0 || sp.zerr >= sp.den)
252*37da2899SCharles.Forsyth				sys->print("bad ratzerr2: %d den %d ratdzrem %d\n", sp.zerr, sp.den, sp.dzrem);
253*37da2899SCharles.Forsyth			seg[q] = sp;
254*37da2899SCharles.Forsyth			q++;
255*37da2899SCharles.Forsyth		}
256*37da2899SCharles.Forsyth		ep = q;
257*37da2899SCharles.Forsyth		next = p;
258*37da2899SCharles.Forsyth
259*37da2899SCharles.Forsyth		if(ep == 0) {
260*37da2899SCharles.Forsyth			if(seg[next] == nil)
261*37da2899SCharles.Forsyth				break;
262*37da2899SCharles.Forsyth			iy = (seg[next].p0.y + onehalf) >> fixshift;
263*37da2899SCharles.Forsyth			y = (iy << fixshift) + onehalf;
264*37da2899SCharles.Forsyth			k = (iy-zr.min.y)*xlen;
265*37da2899SCharles.Forsyth			zv = dc+iy*dy;
266*37da2899SCharles.Forsyth			continue;
267*37da2899SCharles.Forsyth		}
268*37da2899SCharles.Forsyth
269*37da2899SCharles.Forsyth		zsort(seg, ep);
270*37da2899SCharles.Forsyth
271*37da2899SCharles.Forsyth		for(p = 0; p < ep; p++) {
272*37da2899SCharles.Forsyth			sp = seg[p];
273*37da2899SCharles.Forsyth			cnt = 0;
274*37da2899SCharles.Forsyth			x = sp.z;
275*37da2899SCharles.Forsyth			ix = (x + onehalf) >> fixshift;
276*37da2899SCharles.Forsyth			if(ix >= maxx)
277*37da2899SCharles.Forsyth				break;
278*37da2899SCharles.Forsyth			if(ix < minx)
279*37da2899SCharles.Forsyth				ix = minx;
280*37da2899SCharles.Forsyth			cnt += sp.d;
281*37da2899SCharles.Forsyth			p++;
282*37da2899SCharles.Forsyth			sp = seg[p];
283*37da2899SCharles.Forsyth			for(;;) {
284*37da2899SCharles.Forsyth				if(p == ep) {
285*37da2899SCharles.Forsyth					sys->print("xscan: fill to infinity");
286*37da2899SCharles.Forsyth					return;
287*37da2899SCharles.Forsyth				}
288*37da2899SCharles.Forsyth				cnt += sp.d;
289*37da2899SCharles.Forsyth				if((cnt&wind) == 0)
290*37da2899SCharles.Forsyth					break;
291*37da2899SCharles.Forsyth				p++;
292*37da2899SCharles.Forsyth				sp = seg[p];
293*37da2899SCharles.Forsyth			}
294*37da2899SCharles.Forsyth			x2 = sp.z;
295*37da2899SCharles.Forsyth			ix2 = (x2 + onehalf) >> fixshift;
296*37da2899SCharles.Forsyth			if(ix2 <= minx)
297*37da2899SCharles.Forsyth				continue;
298*37da2899SCharles.Forsyth			if(ix2 > maxx)
299*37da2899SCharles.Forsyth				ix2 = maxx;
300*37da2899SCharles.Forsyth			filllinez(dst, ix, ix2, iy, zv+ix*dx, er, dx, k+ix-zr.min.x, zbuf0, zbuf1, src, spt);
301*37da2899SCharles.Forsyth		}
302*37da2899SCharles.Forsyth		y += (1<<fixshift);
303*37da2899SCharles.Forsyth		iy++;
304*37da2899SCharles.Forsyth		k += xlen;
305*37da2899SCharles.Forsyth		zv += dy;
306*37da2899SCharles.Forsyth	}
307*37da2899SCharles.Forsyth}
308*37da2899SCharles.Forsyth
309*37da2899SCharles.Forsythzsort(seg: array of ref Seg, ep: int)
310*37da2899SCharles.Forsyth{
311*37da2899SCharles.Forsyth	done: int;
312*37da2899SCharles.Forsyth	s: ref Seg;
313*37da2899SCharles.Forsyth	q, p: int;
314*37da2899SCharles.Forsyth
315*37da2899SCharles.Forsyth	if(ep < 20) {
316*37da2899SCharles.Forsyth		# bubble sort by z - they should be almost sorted already
317*37da2899SCharles.Forsyth		q = ep;
318*37da2899SCharles.Forsyth		do {
319*37da2899SCharles.Forsyth			done = 1;
320*37da2899SCharles.Forsyth			q--;
321*37da2899SCharles.Forsyth			for(p = 0; p < q; p++) {
322*37da2899SCharles.Forsyth				if(seg[p].z > seg[p+1].z) {
323*37da2899SCharles.Forsyth					s = seg[p];
324*37da2899SCharles.Forsyth					seg[p] = seg[p+1];
325*37da2899SCharles.Forsyth					seg[p+1] = s;
326*37da2899SCharles.Forsyth					done = 0;
327*37da2899SCharles.Forsyth				}
328*37da2899SCharles.Forsyth			}
329*37da2899SCharles.Forsyth		} while(!done);
330*37da2899SCharles.Forsyth	} else {
331*37da2899SCharles.Forsyth		q = ep-1;
332*37da2899SCharles.Forsyth		for(p = 0; p < q; p++) {
333*37da2899SCharles.Forsyth			if(seg[p].z > seg[p+1].z) {
334*37da2899SCharles.Forsyth				qsortzcompare(seg, ep);
335*37da2899SCharles.Forsyth				break;
336*37da2899SCharles.Forsyth			}
337*37da2899SCharles.Forsyth		}
338*37da2899SCharles.Forsyth	}
339*37da2899SCharles.Forsyth}
340*37da2899SCharles.Forsyth
341*37da2899SCharles.Forsythycompare(s0: ref Seg, s1: ref Seg): int
342*37da2899SCharles.Forsyth{
343*37da2899SCharles.Forsyth	y0, y1: int;
344*37da2899SCharles.Forsyth
345*37da2899SCharles.Forsyth	y0 = s0.p0.y;
346*37da2899SCharles.Forsyth	y1 = s1.p0.y;
347*37da2899SCharles.Forsyth
348*37da2899SCharles.Forsyth	if(y0 < y1)
349*37da2899SCharles.Forsyth		return -1;
350*37da2899SCharles.Forsyth	if(y0 == y1)
351*37da2899SCharles.Forsyth		return 0;
352*37da2899SCharles.Forsyth	return 1;
353*37da2899SCharles.Forsyth}
354*37da2899SCharles.Forsyth
355*37da2899SCharles.Forsythzcompare(s0: ref Seg, s1: ref Seg): int
356*37da2899SCharles.Forsyth{
357*37da2899SCharles.Forsyth	z0, z1: int;
358*37da2899SCharles.Forsyth
359*37da2899SCharles.Forsyth	z0 = s0.z;
360*37da2899SCharles.Forsyth	z1 = s1.z;
361*37da2899SCharles.Forsyth
362*37da2899SCharles.Forsyth	if(z0 < z1)
363*37da2899SCharles.Forsyth		return -1;
364*37da2899SCharles.Forsyth	if(z0 == z1)
365*37da2899SCharles.Forsyth		return 0;
366*37da2899SCharles.Forsyth	return 1;
367*37da2899SCharles.Forsyth}
368*37da2899SCharles.Forsyth
369*37da2899SCharles.Forsythqsortycompare(a : array of ref Seg, n : int)
370*37da2899SCharles.Forsyth{
371*37da2899SCharles.Forsyth	i, j : int;
372*37da2899SCharles.Forsyth	t : ref Seg;
373*37da2899SCharles.Forsyth
374*37da2899SCharles.Forsyth	while(n > 1) {
375*37da2899SCharles.Forsyth		i = n>>1;
376*37da2899SCharles.Forsyth		t = a[0]; a[0] = a[i]; a[i] = t;
377*37da2899SCharles.Forsyth		i = 0;
378*37da2899SCharles.Forsyth		j = n;
379*37da2899SCharles.Forsyth		for(;;) {
380*37da2899SCharles.Forsyth			do
381*37da2899SCharles.Forsyth				i++;
382*37da2899SCharles.Forsyth			while(i < n && ycompare(a[i], a[0]) < 0);
383*37da2899SCharles.Forsyth			do
384*37da2899SCharles.Forsyth				j--;
385*37da2899SCharles.Forsyth			while(j > 0 && ycompare(a[j], a[0]) > 0);
386*37da2899SCharles.Forsyth			if(j < i)
387*37da2899SCharles.Forsyth				break;
388*37da2899SCharles.Forsyth			t = a[i]; a[i] = a[j]; a[j] = t;
389*37da2899SCharles.Forsyth		}
390*37da2899SCharles.Forsyth		t = a[0]; a[0] = a[j]; a[j] = t;
391*37da2899SCharles.Forsyth		n = n-j-1;
392*37da2899SCharles.Forsyth		if(j >= n) {
393*37da2899SCharles.Forsyth			qsortycompare(a, j);
394*37da2899SCharles.Forsyth			a = a[j+1:];
395*37da2899SCharles.Forsyth		} else {
396*37da2899SCharles.Forsyth			qsortycompare(a[j+1:], n);
397*37da2899SCharles.Forsyth			n = j;
398*37da2899SCharles.Forsyth		}
399*37da2899SCharles.Forsyth	}
400*37da2899SCharles.Forsyth}
401*37da2899SCharles.Forsyth
402*37da2899SCharles.Forsythqsortzcompare(a : array of ref Seg, n : int)
403*37da2899SCharles.Forsyth{
404*37da2899SCharles.Forsyth	i, j : int;
405*37da2899SCharles.Forsyth	t : ref Seg;
406*37da2899SCharles.Forsyth
407*37da2899SCharles.Forsyth	while(n > 1) {
408*37da2899SCharles.Forsyth		i = n>>1;
409*37da2899SCharles.Forsyth		t = a[0]; a[0] = a[i]; a[i] = t;
410*37da2899SCharles.Forsyth		i = 0;
411*37da2899SCharles.Forsyth		j = n;
412*37da2899SCharles.Forsyth		for(;;) {
413*37da2899SCharles.Forsyth			do
414*37da2899SCharles.Forsyth				i++;
415*37da2899SCharles.Forsyth			while(i < n && zcompare(a[i], a[0]) < 0);
416*37da2899SCharles.Forsyth			do
417*37da2899SCharles.Forsyth				j--;
418*37da2899SCharles.Forsyth			while(j > 0 && zcompare(a[j], a[0]) > 0);
419*37da2899SCharles.Forsyth			if(j < i)
420*37da2899SCharles.Forsyth				break;
421*37da2899SCharles.Forsyth			t = a[i]; a[i] = a[j]; a[j] = t;
422*37da2899SCharles.Forsyth		}
423*37da2899SCharles.Forsyth		t = a[0]; a[0] = a[j]; a[j] = t;
424*37da2899SCharles.Forsyth		n = n-j-1;
425*37da2899SCharles.Forsyth		if(j >= n) {
426*37da2899SCharles.Forsyth			qsortzcompare(a, j);
427*37da2899SCharles.Forsyth			a = a[j+1:];
428*37da2899SCharles.Forsyth		} else {
429*37da2899SCharles.Forsyth			qsortzcompare(a[j+1:], n);
430*37da2899SCharles.Forsyth			n = j;
431*37da2899SCharles.Forsyth		}
432*37da2899SCharles.Forsyth	}
433*37da2899SCharles.Forsyth}
434*37da2899SCharles.Forsyth
435*37da2899SCharles.Forsythabs(n: int): int
436*37da2899SCharles.Forsyth{
437*37da2899SCharles.Forsyth	if(n < 0)
438*37da2899SCharles.Forsyth		return -n;
439*37da2899SCharles.Forsyth	return n;
440*37da2899SCharles.Forsyth}
441