PROCEDURE ProcessCandidates( VAR (*IO*) iCand: PZCandidate.List; VAR (*IO*) fCand: PZCandidate.List; minSteps: NAT; maxAdjust: NAT; printGood: BOOL; printMissing: BOOL; printBogus: BOOL; printCurveMatches: BOOL; VAR (*OUT*) iNOK: NAT; VAR (*OUT*) fNOK: NAT; )= (* Compares the `found' candidates "fCand" against the `ideal' candidates "iCand". An found candidate that overlaps an ideal one (with approximately the same alignment, up to "tolerance" samples) is said to be `good', otherwise it is `bogus'. An ideal candidate that overlaps an found candidate is said to be `present', otherwise it is `missing'. Returns in "iNOK" the number of ideal cands that are present, and in "fNOK" the number of found cands that are good. Each found list is re-sorted, so that the good cands are "fCand[0..fNOK-1]" and the present candidates are "iCand[0..iNOK-1]". *) VAR iIni, fIni: NAT; iFin, fFin: NAT; PROCEDURE ComparePairs(READONLY a, b: PZCandidate.T): [-1..+1] = (* Compares the curve pair of "a" with the curve pair of "b", lexicographically. Returns 0 iff the two candidates belong to the same pair of curves. *) BEGIN WITH k0a = a.seg[0].cvx, k1a = a.seg[1].cvx, k0b = b.seg[0].cvx, k1b = b.seg[1].cvx DO IF k0a < k0b THEN RETURN -1 ELSIF k0a > k0b THEN RETURN +1 ELSIF k1a < k1b THEN RETURN -1 ELSIF k1a > k1b THEN RETURN +1 ELSE RETURN 0 END END END ComparePairs; PROCEDURE SortOK(VAR c: PZCandidate.List; VAR OK: BOOLS) = (* Rearranges the list "c" and the bit vector "OK" simultaneously so as to bring all the elements with "OK = TRUE" to the beginning. *) VAR r, s: NAT; BEGIN r := 0; s := LAST(c); WHILE r < s DO (* Invariant: OK[0..r-1] = TRUE, OK[s+1..LAST(c)] = FALSE *) (* Look for swappable pair: *) WHILE r < s AND OK[r] DO INC(r) END; WHILE r < s AND NOT OK[s] DO DEC(s) END; IF r < s THEN VAR t := c[r]; BEGIN c[r] := c[s]; c[s] := t END; VAR t := OK[r]; BEGIN OK[r] := OK[s]; OK[s] := t END; INC(r); DEC(s); END END END SortOK; VAR ra, rb: REF PZMatch.T := NIL; (* Work areas for "PZCandidate.Overlap" *) BEGIN WITH iN = NUMBER(iCand), fN = NUMBER(fCand), iOK = NEW(REF BOOLS, iN)^, fOK = NEW(REF BOOLS, fN)^ DO PZCandidate.Sort(iCand, PZCandidate.LexicallyBetter); PZCandidate.Sort(fCand, PZCandidate.LexicallyBetter); FOR fIndex := 0 TO fN-1 DO fOK[fIndex] := FALSE END; FOR iIndex := 0 TO iN-1 DO iOK[iIndex] := FALSE END; iIni := 0; fIni := 0; WHILE iIni < iN DO (* Another curve pair in the ideal set... *) (* Paranoid check of sorting: *) IF iIni > 0 AND iIni < iN THEN <* ASSERT PZCandidate.LexicallyBetter(iCand[iIni-1], iCand[iIni]) *> END; (* Locate all ideal candidates "[iIni..iFin-1]" with this curve pair: *) iFin := iIni+1; WHILE iFin < iN AND ComparePairs(iCand[iIni], iCand[iFin]) = 0 DO INC(iFin) END; (* Locate all found candidates "[fIni..fFin-1]" with this curve pair: *) WHILE fIni < fN AND ComparePairs(fCand[fIni], iCand[iIni]) < 0 DO INC(fIni) END; fFin := fIni; WHILE fFin < fN AND ComparePairs(iCand[iIni], fCand[fFin]) = 0 DO INC(fFin) END; IF printCurveMatches THEN WITH s = iCand[iIni].seg DO Wr.PutText(stderr, "curves: " & FI(s[0].cvx,4) & " × " & FI(s[1].cvx,4)); END; Wr.PutText(stderr, ": " & FI(iFin - iIni,6) & " ideal cands, "); Wr.PutText(stderr, FI(fFin - fIni,6) & " found cands\n"); END; (* Compare each ideal Cand against all found Cands with this curve pair: *) IF fIni < fFin AND fIni < fN THEN ProcessCandidatesOfCurvePair( iIni, SUBARRAY(iCand, iIni, iFin-iIni), SUBARRAY(iOK, iIni, iFin-iIni), fIni, SUBARRAY(fCand, fIni, fFin-fIni), SUBARRAY(fOK, fIni, fFin-fIni), minSteps, maxAdjust, printGood, ra, rb ); END; (* Start next curve pair: *) iIni := iFin; fIni := fFin END; (* Count matched ideal cands and print missing ones: *) IF printMissing THEN Wr.PutText(stderr, "=== ideal NOT in found ===\n") END; iNOK := 0; FOR iIndex := 0 TO iN-1 DO IF iOK[iIndex] THEN INC(iNOK) ELSIF printMissing THEN Wr.PutText(stderr, "ideal[" & Fmt.Pad(Fmt.Int(iIndex), 6) & "]\n"); PZCandidate.Print(stderr, cand := iCand[iIndex]) END END; (* Count matched found cands and print bogus ones: *) IF printBogus THEN Wr.PutText(stderr, "=== found NOT in ideal ===\n") END; fNOK := 0; FOR fIndex := 0 TO fN-1 DO IF fOK[fIndex] THEN INC(fNOK) ELSIF printBogus THEN Wr.PutText(stderr, "found [" & Fmt.Pad(Fmt.Int(fIndex), 6) & "]\n"); PZCandidate.Print(stderr, cand := fCand[fIndex]) END END; Wr.PutText(stderr, "\n"); Wr.PutText(stderr, "ideal candidates = " & Fmt.Int(iN) & "\n"); Wr.PutText(stderr, "found candidates = " & Fmt.Int(fN) & "\n"); Wr.PutText(stderr, "ideal in found = " & Fmt.Int(iNOK) & "\n"); Wr.PutText(stderr, "ideal NOT in found = " & Fmt.Int(iN - iNOK) & "\n"); Wr.PutText(stderr, "found in ideal = " & Fmt.Int(fNOK) & "\n"); Wr.PutText(stderr, "found NOT in ideal = " & Fmt.Int(fN - fNOK) & "\n"); Wr.PutText(stderr,"\n"); WITH sensitivity = FLOAT(iNOK,LONG)/FLOAT(iN,LONG), significance = FLOAT(iNOK,LONG)/FLOAT(fN,LONG), multiplicity = FLOAT(fNOK,LONG)/FLOAT(iNOK,LONG) DO Wr.PutText(stderr, "sensitivity = " & FLR(sensitivity, 6,4) & "\n"); Wr.PutText(stderr, "significance = " & FLR(significance, 6,4) & "\n"); Wr.PutText(stderr, "multiplicity = " & FLR(multiplicity, 6,4) & "\n"); END; Wr.PutText(stderr,"\n"); (* Rearrange candidates to put the good/present ones in front: *) SortOK(iCand, iOK); SortOK(fCand, fOK); END; END ProcessCandidates; PROCEDURE ProcessCandidatesOfCurvePair( iIni: NAT; (* Actual index of "iCand[0]" *) READONLY iCand: PZCandidate.List; (* Ideal candidates of a curve pair. *) VAR (*IO*) iOK: BOOLS; (* Identifies non-missing ideal candidates. *) fIni: NAT; (* Actual index of "fCand[0]" *) READONLY fCand: PZCandidate.List; (* Found candidates of a curve pair. *) VAR (*IO*) fOK: BOOLS; (* Identifies correct found candidates. *) minSteps: NAT; maxAdjust: NAT; printGood: BOOL; VAR (*WORK*) ra, rb: REF PZMatch.T; ) = (* Processes a set of ideal and found candidates belonging to the same curve pair. Sets "iOK[i]" when the ideal candidate "iCand[i]" is present in "fCand", and vice-versa. *) BEGIN FOR i := 0 TO LAST(iCand) DO WITH iC = iCand[i] DO FOR f := 0 TO LAST(fCand) DO WITH fC = fCand[f], overlap = PZCandidate.Overlap(iC, fC, minSteps := minSteps, maxAdjust := maxAdjust, ra := ra, rb := rb ) DO iOK[i] := iOK[i] OR overlap; fOK[f] := fOK[f] OR overlap; IF overlap AND printGood THEN Wr.PutText(stderr, "\n"); PrintCandidate("ideal", i + iIni, iC); PrintCandidate("found", f + fIni, fC); Wr.PutText(stderr, "\n"); END; END; END; END END END ProcessCandidatesOfCurvePair; PROCEDURE PrintCandidate(tag: TEXT; i: NAT; READONLY c: PZCandidate.T) = BEGIN Wr.PutText(stderr, Fmt.Pad(tag,5) & "[" & Fmt.Pad(Fmt.Int(i), 6) & "]\n"); PZCandidate.Print(stderr, cand := c); END PrintCandidate;