/* See frb_match.h */ /* Last edited on 2005-01-16 14:20:39 by stolfi */ /* Copyright © 2005 Universidade Estadual de Campinas. See note at end of file. */ #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_int(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_int(rd); pm->fin.c[j] = fget_int(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); } /* COPYRIGHT AND AUTHORSHIP NOTICE Copyright © 2005 Universidade Estadual de Campinas (UNICAMP). Created by Helena C. G. Leitão and Jorge Stolfi in 1995--2005. This source file can be freely distributed, used, and modified, provided that this copyright and authorship notice is preserved in all copies, and that any modified versions of this file are clearly marked as such. This software has NO WARRANTY of correctness or applicability for any purpose. Neither the authors nor their employers shall be held responsible for any losses or damages that may result from its use. END OF NOTICE */