bazel-0003 + kicad-0002: build toolchain feature check + PCB zone filler O(Z²×L²); count 601→603
This commit is contained in:
parent
1d6a8b8ccd
commit
212d313185
292 changed files with 924 additions and 7 deletions
126
defects/kicad/unit/KicadZoneFillerAlgorithmTest.java
Normal file
126
defects/kicad/unit/KicadZoneFillerAlgorithmTest.java
Normal 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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue