hit_cand_vec_t *obim_get_valid_cands_for_each_hit ( int32_t nh, int32_t tp[], hit_cand_vec_t *D, int32_t NC ) { int32_t nd = (int32_t)D->ne; hit_cand_vec_t *HC = talloc(nh, hit_cand_vec_t); int32_t min_ini = 0; /* Min {.ini} for next hit candidates, or {NC+1} if no space. */ for (int32_t ih = 0; ih < nh; ih++) { hit_cand_vec_t HCi = hit_cand_vec_new((vec_size_t)nd); /* To be trimmed. */ int32_t min_fin = NC+1; /* Min {.fin} of valid cands for hit {ih}, or {NC+1} if none. */ int32_t ncdi = 0; for (int32_t id = 0; id e[id]); assert((0 <= Di->ini) && (Di->ini <= Di->fin) && (Di->fin <= NC)); assert(Di->htype <= obim_MAX_HTYPE); assert(Di->hcost <= obim_MAX_COST); if ((Di->htype == tp[ih]) && (Di->ini >= min_ini)) { assert(ncdi < HCi.ne); HCi.e[ncdi] = (*Di); if (Di->fin < min_fin) { min_fin = Di->fin; } ncdi++; } } if (min_fin > NC) { assert(ncdi == 0); } hit_cand_vec_trim(&HCi, (vec_size_t)ncdi); HC[ih] = HCi; /* Min start index for next hit cands is min fin for this hit: */ min_ini = min_fin; } /* Now remove cands that are too far down the text: */ int32_t max_fin = NC; /* Max {.fin} for next hit in rev order, or {-1} if no space. */ for (int32_t ih = nh-1; ih >= 0; ih--) { /* Remove candidates that end beyond {max_fin}: */ hit_cand_vec_t HCi = HC[ih]; int32_t ncdi = (int32_t)HCi.ne; int32_t kcdi = 0; int32_t max_ini = -1; /* Max {.ini} of valid cands for hit {ih}, or {-1} if none. */ for (int32_t jh = 0; jh < ncdi; jh++) { hit_cand_t *hj = &(HCi.e[jh]); if (hj->fin <= max_fin) { HCi.e[kcdi] = (*hj); if (hj->ini > max_ini) { max_ini = hj->ini; } kcdi++; } } if (max_ini < 0) { assert(kcdi == 0); } Pr(Er, " %d valid candidates for hit %d\n", kcdi, ih); hit_cand_vec_trim(&HCi, (vec_size_t)kcdi); HC[ih] = HCi; /* Max fin for cands of hit {ih-1} is max ini for hit {ih}: */ /* Update min start index for cands of next hit: */ max_fin = max_ini; } /* Either we can fit at least one candidate for every {ih}, or we must have concluded that it is impossible to fit any candidate at any hit slot: */ for (int32_t ih = 0; ih < nh ; ih++) { assert((HC[ih].ne == 0) == (HC[0].ne == 0)); } if (HC[0].ne == 0) { Pr(Er, "cannot fit all requested hits in text[0:%d]\n", NC); } return HC; } auto int32_t compare_hit_cands(const void *a, const void *b); /* Compares {*a} and {*b} (assumed to be {hit_cand_t}s) lexicographically by {.ini}, {.fin}, {.type}, and {.hcost}. */ /* Sort hit cands: */ qsort(D.e, (size_t)nd, sizeof(hit_cand_t), compare_hit_cands); /* Remove redundancies: */ hit_cand_t *Dk = &(D.e[0]); for (int32_t id = 1; id < nd; id++) { hit_cand_t *Di = &(D.e[id]); int32_t sgn = compare_hit_cands(Dk, Di); assert(sgn <= 0); if ((Dk->ini == Di->ini) && (Dk->fin == Di->fin)) { Pr(Er, "** duplicate hit option D[%d] = ", kd); obim_print_hit_cand(Er, NULL, Dk, NULL); Pr(Er, " D[%d] = ", id); obim_print_hit_cand(Er, NULL, Di, "\n"); } Dk = Di; } fclose(rd); return HC; int32_t compare_hit_cands(const void *a, const void *b) { hit_cand_t *Da = (hit_cand_t *)a; hit_cand_t *Db = (hit_cand_t *)b; if (Da->ini != Db ->ini) { return (Da->ini < Db->ini ? -1 : +1); } else if (Da->fin != Db->fin) { return (Da->fin < Db->fin ? -1 : +1); } else if (Da->hcost != Db->hcost) { return (Da->hcost < Db->hcost ? -1 : +1); } else { return 0; } } /* Hit candidate information */ segment_vec_t *HC[2]; /* Candidate hits for each side and plane. */ for (int32_t side = 0; side < 2; side++) { HC[side] = obim_get_valid_cands_for_each_hit(nh, tp, &(D[side]), NC[side]); }