whitepaper: 366/178 — wave5 defect tables + PDF rebuild

This commit is contained in:
russell@unturf.com 2026-03-27 15:37:42 -04:00
parent 835ae73b0f
commit a4b0cf4edd
79 changed files with 3829 additions and 17 deletions

View file

@ -0,0 +1,124 @@
package unit;
import java.util.*;
/**
* CWE-407 unit test: Swift RequirementMachine isInMinimizationDomain
*
* Models the Swift compiler's RewriteSystem where:
* - Protos = list of protocol declarations in the minimization domain
* - Rules = rewrite rules over those protocols
*
* The defect: isInMinimizationDomain() does a linear scan over Protos
* on every call, and is called once per rule in loops over all rules.
* Total cost: O(R × P) where R = rule count, P = protocol count.
*
* The fix: replace the linear scan with a HashSet lookup O(1) per call.
*
* Test measures ops count (comparisons) at N=800 (protos and rules both N).
*/
public class SwiftRequirementMachineAlgorithm {
// ---- Defective version: std::find equivalent (linear scan) ----------------
static long defectiveIsInDomain(List<Integer> protos, int proto) {
// models: std::find(Protos.begin(), Protos.end(), proto)
// returns ops performed
long ops = 0;
for (Integer p : protos) {
ops++;
if (p.equals(proto)) return ops;
}
return ops;
}
/**
* Simulate the rule-loop pattern from HomotopyReduction.cpp:611
* for (const auto &rule : getLocalRules()) {
* if (!isInMinimizationDomain(rule.getLHS().getRootProtocol())) continue;
* ...
* }
*/
static long defectiveMinimize(List<Integer> protos, List<Integer> rules) {
long totalOps = 0;
for (int rule : rules) {
// Each rule references a protocol; check membership linearly
totalOps += defectiveIsInDomain(protos, rule % protos.size());
}
return totalOps;
}
// ---- Fixed version: HashSet O(1) lookup -----------------------------------
static long fixedMinimize(Set<Integer> protoSet, List<Integer> rules) {
long totalOps = 0;
for (int rule : rules) {
// O(1) hash set lookup
totalOps++;
protoSet.contains(rule % protoSet.size());
}
return totalOps;
}
// ---- Test harness ----------------------------------------------------------
static final int N = 800;
public static void main(String[] args) {
int passed = 0;
int total = 0;
// Build protos list (P = N protocols) and rules list (R = N rules)
List<Integer> protos = new ArrayList<>(N);
for (int i = 0; i < N; i++) protos.add(i);
List<Integer> rules = new ArrayList<>(N);
for (int i = 0; i < N; i++) rules.add(i);
Set<Integer> protoSet = new HashSet<>(protos);
// Test 1: defective version is O(R*P) ops >= N*N/2 on average
total++;
long slowOps = defectiveMinimize(protos, rules);
// Each rule on average scans half the protos list
long expectedMinSlow = (long) N * N / 4; // conservative lower bound
assert slowOps >= expectedMinSlow
: "Slow ops " + slowOps + " unexpectedly low, expected >= " + expectedMinSlow;
System.out.println("PASS test1: defective ops=" + slowOps + " (O(N^2) confirmed, N=" + N + ")");
passed++;
// Test 2: fixed version is O(R) ops == N exactly
total++;
long fastOps = fixedMinimize(protoSet, rules);
assert fastOps == N
: "Fast ops should be exactly N=" + N + ", got " + fastOps;
System.out.println("PASS test2: fixed ops=" + fastOps + " (O(N) confirmed, N=" + N + ")");
passed++;
// Test 3: speedup is at least 10x
total++;
double speedup = (double) slowOps / fastOps;
assert speedup >= 10.0
: "Expected speedup >= 10x, got " + speedup;
System.out.printf("PASS test3: speedup=%.1fx%n", speedup);
passed++;
// Test 4: correctness both find the same items in domain
total++;
List<Integer> smallProtos = Arrays.asList(10, 20, 30, 40, 50);
Set<Integer> smallSet = new HashSet<>(smallProtos);
// Probe 5 different values
int[] probeVals = {10, 25, 30, 99, 50};
for (int v : probeVals) {
boolean defectResult = defectiveIsInDomain(smallProtos, v) > 0 && smallProtos.contains(v);
boolean fixedResult = smallSet.contains(v);
assert defectResult == fixedResult
: "Mismatch for value " + v + ": defect=" + defectResult + " fixed=" + fixedResult;
}
System.out.println("PASS test4: correctness — defective and fixed agree on all probes");
passed++;
System.out.println(passed + "/" + total + " PASS");
}
}