bazel-0003 + kicad-0002: build toolchain feature check + PCB zone filler O(Z²×L²); count 601→603

This commit is contained in:
russell@unturf.com 2026-03-27 22:38:32 -04:00
parent 1d6a8b8ccd
commit 212d313185
292 changed files with 924 additions and 7 deletions

View file

@ -0,0 +1,126 @@
package unit;
import java.util.*;
/**
* Models KiCad ZONE_FILLER::Fill() iterative refill dedup.
*
* SLOW: O(Z_r × Z × L × Z×L) std::find on growing vector per (zone, layer) pair.
* FAST: O(Z_r × Z × L) HashSet dedup, O(1) insert/contains.
*
* CWE-407: pcbnew/zone_filler.cpp:998 (ZONE_FILLER::Fill iterative refill path)
*/
public class KicadZoneFillerAlgorithmTest {
record ZoneLayer(int zoneId, int layerId) {}
// -------------------------------------------------------------------------
// Slow std::find O(N) scan on growing list
// -------------------------------------------------------------------------
static class SlowZoneFiller {
long cmpOps = 0;
boolean find(List<ZoneLayer> list, ZoneLayer item) {
for (ZoneLayer zl : list) {
cmpOps++;
if (zl.equals(item)) return true;
}
return false;
}
List<ZoneLayer> getZonesToRefill(int zRemoved, int zTotal, int layers) {
List<ZoneLayer> zonesToRefill = new ArrayList<>();
for (int r = 0; r < zRemoved; r++) {
for (int z = 0; z < zTotal; z++) {
for (int l = 0; l < layers; l++) {
ZoneLayer item = new ZoneLayer(z, l);
if (!find(zonesToRefill, item)) {
zonesToRefill.add(item);
}
}
}
}
return zonesToRefill;
}
long ops(int zRemoved, int zTotal, int layers) {
cmpOps = 0;
getZonesToRefill(zRemoved, zTotal, layers);
return cmpOps;
}
}
// -------------------------------------------------------------------------
// Fast HashSet O(1) dedup
// -------------------------------------------------------------------------
static class FastZoneFiller {
long cmpOps = 0;
List<ZoneLayer> getZonesToRefill(int zRemoved, int zTotal, int layers) {
Set<ZoneLayer> seen = new HashSet<>();
List<ZoneLayer> zonesToRefill = new ArrayList<>();
for (int r = 0; r < zRemoved; r++) {
for (int z = 0; z < zTotal; z++) {
for (int l = 0; l < layers; l++) {
ZoneLayer item = new ZoneLayer(z, l);
cmpOps++;
if (seen.add(item)) {
zonesToRefill.add(item);
}
}
}
}
return zonesToRefill;
}
long ops(int zRemoved, int zTotal, int layers) {
cmpOps = 0;
getZonesToRefill(zRemoved, zTotal, layers);
return cmpOps;
}
}
public static void main(String[] args) {
SlowZoneFiller slow = new SlowZoneFiller();
FastZoneFiller fast = new FastZoneFiller();
int passed = 0, total = 0;
System.out.println("=== kicad-0002: zone_filler std::find O(Z²×L²) ===");
// (zRemoved, zTotal, layers)
int[][] configs = {
{5, 20, 2}, // small board
{10, 50, 4}, // realistic (agent's estimate)
{15, 100, 6}, // large board
};
for (int[] cfg : configs) {
int zr = cfg[0], z = cfg[1], l = cfg[2];
long s = slow.ops(zr, z, l);
long f = fast.ops(zr, z, l);
double ratio = (double) s / Math.max(f, 1);
total++;
boolean ok = s > f && ratio >= 5.0;
System.out.printf("Zr=%2d Z=%3d L=%d slow=%9d fast=%6d ratio=%6.1fx %s%n",
zr, z, l, s, f, ratio, ok ? "PASS" : "FAIL");
if (ok) passed++;
}
// Correctness: both produce same set of zones to refill
SlowZoneFiller s2 = new SlowZoneFiller();
FastZoneFiller f2 = new FastZoneFiller();
List<ZoneLayer> sr = s2.getZonesToRefill(10, 50, 4);
List<ZoneLayer> fr = f2.getZonesToRefill(10, 50, 4);
Set<ZoneLayer> ss = new HashSet<>(sr), fs = new HashSet<>(fr);
total++;
boolean correct = ss.equals(fs);
System.out.printf("correctness (%d zones to refill): %s%n", sr.size(),
correct ? "PASS" : "FAIL");
if (correct) passed++;
System.out.printf("%n%d/%d PASS%n", passed, total);
if (passed < total) System.exit(1);
}
}