shithub: fnt

Download patch

ref: e2426e3277266e230b352bb843c4f58a91a0eb2e
parent: 3582b9cc27bf2a83800c00b4a84873037e99642d
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Jul 31 20:59:41 EDT 2024

qslv: sort and remove duplicates on the go

--- a/rast.c
+++ b/rast.c
@@ -75,47 +75,54 @@
 	return v + 1;
 }
 
-static int
+static Sval *
 qslv(Sval *qs, Sval a, Sval b, Sval c)
 {
-	Sval p, q, d;
-	int n;
+	Sval p, q, d, t;
+	int i;
 
-	if(unlikely(is₀(a))){
-		if(is₀(b))
-			return 0;
-		qs[0] = -c/b;
-		return qs[0] > 0 && qs[0] < 1;
+#define ins(q) \
+	if(q > 0 && q < 1){ \
+		i = -1; \
+		if((t = qs[i]) < q){ \
+			*qs++ = q; \
+		}else if(q < t){ \
+			qs++; \
+			do{ \
+				qs[i--] = t; \
+				qs[i] = q; \
+				t = qs[i-1]; \
+			}while(q < t); \
+		} \
 	}
 
-	p = b/(2.0*a);
-	d = p*p - c/a;
-	if(d < ε)
-		return 0;
-
-	d = sqrt(d);
-	n = 0;
-	if((q = -d-p) > 0 && q < 1)
-		qs[n++] = q;
-	if((q = d-p) > 0 && q < 1)
-		qs[n++] = q;
-    return n;
+	if(unlikely(is₀(a))){
+		if(!is₀(b)){
+			q = -c/b;
+			ins(q);
+		}
+	}else{
+		p = b/(2.0*a);
+		d = p*p - c/a;
+		if(d > ε){
+			d = sqrt(d);
+			q = -d-p;
+			ins(q);
+			q = d-p;
+			ins(q);
+		}
+	}
+#undef ins
+	return qs;
 }
 
 static int
-Svalcmp(void *a_, void *b_)
-{
-	Sval a = *(Sval*)a_, b = *(Sval*)b_;
-	return (a > b) - (a < b);
-}
-
-static int
 qKL(SegQ *s₀, int jj, Sval px, Sval py, Sval *K, Sval *L)
 {
-	Sval qs[1+4*2+1];
+	Sval *q, *e, qs[1+1+4*2+1];
 	Sval a, b, c, w, v;
+	int i, n, r;
 	SegQ s, z;
-	int i, j, n, r;
 
 	/* transform */
 	s.p0.x = s₀->p0.x*jj - px;
@@ -129,43 +136,34 @@
 #define within(v) ((w = e(v, x)) >= -ε && w <= 1+ε && (w = e(v, y)) >= -ε && w <= 1+ε)
 
 	/* clip to quadtree cell */
-	n = 0;
+	q = qs;
+	*q++ = -1;
 	if(s.p0.x >= 0 && s.p0.x <= 1 && s.p0.y >= 0 && s.p0.y <= 1)
-		qs[n++] = 0;
-
+		*q++ = 0;
 	c = s.p0.x;
 	a = c - 2*s.p1.x + s.p2.x;
 	b = 2*(s.p1.x - c);
-	n += qslv(qs+n, a, b, c);
-	n += qslv(qs+n, a, b, c-1);
+	q = qslv(q, a, b, c);
+	q = qslv(q, a, b, c-1);
 	c = s.p0.y;
 	a = c - 2*s.p1.y + s.p2.y;
 	b = 2*(s.p1.y - c);
-	n += qslv(qs+n, a, b, c);
-	n += qslv(qs+n, a, b, c-1);
-	qsort(qs, n, sizeof(Sval), Svalcmp);
-
+	q = qslv(q, a, b, c);
+	q = qslv(q, a, b, c-1);
 	if(s.p2.x >= 0 && s.p2.x <= 1 && s.p2.y >= 0 && s.p2.y <= 1)
-		qs[n++] = 1;
-	j = 0;
-	for(i = 0; i < n; i++){
-		v = qs[i];
-		if(within(v))
-			qs[j++] = v;
-	}
-#undef within
+		*q++ = 1;
 
-	/* remove duplicates */
 	n = 1;
-	for(i = 1; i < j; i++){
-		v = qs[i];
-		if(v != qs[i-1])
+	for(e = qs+1; e < q; e++){
+		v = *e;
+		if(within(v))
 			qs[n++] = v;
 	}
+#undef within
 
 	/* calculate K & L on subsections */
 	r = 0;
-	for(i = 0; i < n-1; i++){
+	for(i = 1; i < n-1; i++){
 		a = qs[i];
 		b = qs[i+1];
 
@@ -257,7 +255,7 @@
 Cxy(SegQ *s, int ns, int jj, int px, int py, Sval *c, u64int *m, u64int tm)
 {
 	int (*f)(SegQ*, int, Sval, Sval, Sval*, Sval*);
-	Sval K[4][2], L[4][2], q[6], j;
+	Sval K[4][2], L[4][2], x₀, x₁, x₂, y₀, y₁, y₂, psz;
 	u64int tx₀, tx₁, z, all;
 	u8int w;
 	int i;
@@ -272,20 +270,20 @@
 		tx₀ = 1ULL<<(px*jj + py);
 		tx₁ = 1ULL<<((px+1)*jj + py);
 	}
-	j = 1.0/(Sval)jj;
-	q[0] = j*px;
-	q[1] = j*py;
-	q[2] = q[0]+j;
-	q[3] = q[1]+j;
-	q[4] = q[2]+j;
-	q[5] = q[3]+j;
+	psz = 1.0/(Sval)jj;
+	x₀ = psz*px;
+	y₀ = psz*py;
+	x₁ = psz+x₀;
+	y₁ = psz+y₀;
+	x₂ = psz+x₁;
+	y₂ = psz+y₁;
 	all = 0;
 	for(i = 0; i < ns; i++, s++){
 		if((m[i] & tm) == 0 ||
-		   s->p0.x <= q[0] && s->p1.x <= q[0] && s->p2.x <= q[0] ||
-		   s->p0.x >= q[4] && s->p1.x >= q[4] && s->p2.x >= q[4] ||
-		   s->p0.y <= q[1] && s->p1.y <= q[1] && s->p2.y <= q[1] ||
-		   s->p0.y >= q[5] && s->p1.y >= q[5] && s->p2.y >= q[5])
+		   s->p0.x >= x₂ && s->p1.x >= x₂ && s->p2.x >= x₂ ||
+		   s->p0.x <= x₀ && s->p1.x <= x₀ && s->p2.x <= x₀ ||
+		   s->p0.y >= y₂ && s->p1.y >= y₂ && s->p2.y >= y₂ ||
+		   s->p0.y <= y₀ && s->p1.y <= y₀ && s->p2.y <= y₀)
 			continue;
 
 		K[0][0] = K[0][1] = 0;
@@ -298,12 +296,11 @@
 		L[3][0] = L[3][1] = 0;
 		z = 0;
 		f = s->p1.x == s->p2.x && s->p1.y == s->p2.y ? lKL : qKL;
-
 		w =
-			(s->p0.x <= q[2] || s->p1.x <= q[2] || s->p2.x <= q[2])<<0 |
-			(s->p0.x >= q[2] || s->p1.x >= q[2] || s->p2.x >= q[2])<<1 |
-			(s->p0.y <= q[3] || s->p1.y <= q[3] || s->p2.y <= q[3])<<2 |
-			(s->p0.y >= q[3] || s->p1.y >= q[3] || s->p2.y >= q[3])<<3;
+			(s->p0.x <= x₁ || s->p1.x <= x₁ || s->p2.x <= x₁)<<0 |
+			(s->p0.x >= x₁ || s->p1.x >= x₁ || s->p2.x >= x₁)<<1 |
+			(s->p0.y <= y₁ || s->p1.y <= y₁ || s->p2.y <= y₁)<<2 |
+			(s->p0.y >= y₁ || s->p1.y >= y₁ || s->p2.y >= y₁)<<3;
 
 		if(tx₀ == 0){
 			if((w & 5) == 5) z |= f(s, jj, px+0, py+0, K[0], L[0]);