/* See frb_match.h */ /* Last edited on 2023-02-12 07:53:53 by stolfi */ #include #include #include #include #include #include #include #include #include frb_match_t frb_match_most_perfect ( int n0, int n1 ) { int np = frb_imax(n0, n1); frb_match_t mt = frb_match_new(np); frb_match_domost_perfect(n0, n1, &mt); return mt; } void frb_match_domost_perfect ( int n0, int n1, frb_match_t *mt ) { affirm(n0 > 0, "bad n0"); affirm(n1 > 0, "bad n1"); int np = mt->nel; affirm(np == frb_imax(n0,n1), "bad length"); if (np == 1) { mt->el[0] = (i2_t){{0,0}}; } else { double fn0 = (double)(n0-1); double fn1 = (double)(n1-1); double fnp = (double)(np-1); int i; for (i = 0; i < np; i++) { double fi = (double)i; int p0 = frb_round((fn0 * fi)/fnp); int p1 = frb_round((fn1 * fi)/fnp); mt->el[i] = (i2_t){{p0, p1}}; } } } frb_match_t frb_match_unpack ( frb_match_packed_t *pm ) { int np = pm->np; frb_match_t mt = frb_match_new(np); frb_match_do_unpack(pm, &mt); return mt; } void frb_match_do_unpack ( frb_match_packed_t *pm, frb_match_t *mt ) { int np = pm->np; int i; affirm(mt->nel == np, "size mismatch"); affirm(strlen(pm->steps) == np, "wrong size"); affirm(pm->steps[0] == '|', "bad start"); mt->el[0] = pm->ini; for (i = 1; i < np; i++) { char c = pm->steps[i]; i2_t *ant = &(mt->el[i-1]), *ths = &(mt->el[i]); if (c == '/') { ths->c[0] = ant->c[0] + 1; ths->c[1] = ant->c[1]; } else if (c == '\\') { ths->c[0] = ant->c[0]; ths->c[1] = ant->c[1] + 1; } else if (c == '|') { ths->c[0] = ant->c[0] + 1; ths->c[1] = ant->c[1] + 1; } else { affirm(FALSE, "bad char"); } } affirm(mt->el[np-1].c[0] == pm->fin.c[0], "ends dont match"); affirm(mt->el[np-1].c[1] == pm->fin.c[1], "ends dont match"); } frb_match_packed_t *frb_match_pack( frb_match_t *mt ) { int np = (mt->nel); char *ch = (char *)notnull(malloc((1+np)*sizeof(char)), "no mem"); char *q = ch; int i; (*q) = '|'; q++; for (i = 1; i < np; i++) { int ri = mt->el[i].c[0], ra = mt->el[i-1].c[0]; int si = mt->el[i].c[1], sa = mt->el[i-1].c[1]; if ((ri == ra+1) && (si == sa)) { (*q) = '/'; } else if ((ri == ra) && (si == sa+1)) { (*q) = '\\'; } else if ((ri == ra+1) && (si == sa+1)) { (*q) = '|'; } else { fprintf(stderr, "bad matching: (%d,%d) (%d,%d)\n", ra, sa, ri, si); assert(FALSE); } q++; } (*q) = '\000'; frb_match_packed_t *pm = (frb_match_packed_t *) notnull(malloc(sizeof(frb_match_packed_t)), "no mem"); pm->np = np; pm->ini = mt->el[0]; pm->fin = mt->el[np-1]; pm->steps = ch; return pm; } frb_match_packed_t *frb_match_pack_perfect( int nSamples ) { int np = nSamples; /* One pair per sample. */ char *ch = (char *)notnull(malloc((1+np)*sizeof(char)), "no mem"); char *q = ch; int i; for (i = 0; i < np; i++) { (*q) = '|'; q++; } (*q) = '\000'; frb_match_packed_t *pm = (frb_match_packed_t *) notnull(malloc(sizeof(frb_match_packed_t)), "no mem"); pm->np = np; pm->ini = (i2_t){{0,0}}; pm->fin = (i2_t){{nSamples-1,nSamples-1}}; pm->steps = ch; return pm; } void frb_match_write_packed ( FILE *wr, frb_match_packed_t *pm ) { int np = pm->np; int j; assert(strlen(pm->steps) == np ); fprintf(wr, "%d (", np); for (j = 0; j <= 1 ; j++) { fprintf(wr, "%d %d ", pm->ini.c[j], pm->fin.c[j]); } fprintf(wr, "%s)", pm->steps); } frb_match_packed_t *frb_match_read_packed ( FILE *rd ) { frb_match_packed_t *pm = (frb_match_packed_t *) notnull(malloc(sizeof(frb_match_packed_t)), "no mem"); int np = fget_int32(rd); pm->np = np; fget_skip_spaces(rd); fget_match(rd, "("); int i, j; for (j = 0; j <= 1; j++) { pm->ini.c[j] = fget_int32(rd); pm->fin.c[j] = fget_int32(rd); } /* Read the packed pairing: */ fget_skip_spaces(rd); char *ch = (char *)notnull(malloc((1+np)*sizeof(char)), "no mem"); fget_match(rd, "|"); ch[0] = '|'; for (i = 1; i < np; i++) { int c = fgetc(rd); affirm(c != EOF, "unexpected end-of-file"); affirm((c == '/') || (c == '|') || (c == '\\'), "invalid char"); ch[i] = c; } ch[np] = '\000'; fget_skip_spaces(rd); fget_match(rd, ")"); pm->steps = ch; return pm; } void frb_debug_int_pair ( char *title, int r, int s ) { fprintf(stderr, "%s %d %d\n", title, r, s); }