/* distance.c -- compute the distance between two words */ #include #include "ios_2.h" /* using the input/output service module */ #define ERR_L1_F1 1 #define ERR_L1_F2 2 #define ERR_LENGTHS_DIFF 3 #define ERR_L2_F1 4 #define ERR_L2_F2 5 #define ERR_HEADER1 6 #define ERR_HEADER2 7 #define ERR_HEADERS_DIFF 8 #define ERR_DATA1 9 #define ERR_DATA2 10 #define ERR_LONG_FAMILY1 11 #define ERR_LONG_FAMILY2 12 #define ERR_NONSYNC 13 #define ERR_LINE_STRANGE1 14 #define ERR_LINE_STRANGE2 15 #define INFTY 1.0e+30F #define MAXRECNO 50 typedef struct { int x, y, z; long pos, sk, p1,p2, hlim,llim; } FamilyStruct; typedef struct { int x, y, z; int pert; float tot; int exist; } ResultStruct; typedef struct { long int quot, rem; } my_ldiv_t; FamilyStruct InData1 [MAXRECNO], InData2 [MAXRECNO]; long TextLen; int WordLen1, WordLen2; int MAXM=10; /* max m of the table */ static FILE * outfile; static ResultStruct correlate ( FamilyStruct * pertvec1, int size1, int Wordlen1, FamilyStruct * pertvec2, int size2, int WordLen2 ); static float give_score ( long p1, long p2, long sk1, long sk2, int llen1, int llen2, long width ); static my_ldiv_t divmod ( long a, long b, int mode ); void main ( int argc, char * argv [] ) { long int TextLength; int Word1Length; long int Text2Length; int Word2Length; FamilyStruct curfam; FamilyStruct * p; ResultStruct res; int x,y,z; int recno1, recno2; char * from1, * from2; if ( argc < 4 ) err_command_line ( "distance infile1 infile2 outfile" ); open_input_file1 ( argv [1] ); open_input_file2 ( argv [2] ); outfile = open_output_file ( argv [3] ); get_line_sure1 ( & from1 ); if ( 2 != sscanf ( from1, "%d %ld", &Word1Length, &TextLength ) ) { printf ( "wrong first line [%s] in the first input file\n", from1 ); exit ( ERR_L1_F1 ); } get_line_sure2 ( & from2 ); if ( 2 != sscanf ( from2, "%d %ld", &Word2Length, &Text2Length ) ) { printf ( "wrong first line [%s] in the second input file\n", from2 ); exit ( ERR_L1_F2 ); } if ( TextLength != Text2Length ) { printf ("different book lengths"); exit ( ERR_LENGTHS_DIFF ); } TextLen = TextLength; WordLen1 = Word1Length; WordLen2 = Word2Length; fprintf ( outfile, "[ %3d %3d ", Word1Length, Word2Length ); fprintf ( outfile, "%7ld ]\n\n", TextLength ); get_line_sure1 ( & from1 ); if ( '*' != from1 [0] ) { printf ( "wrong second line in first input file\n" ); exit ( ERR_L2_F1 ); } get_line_sure2 ( & from2 ); if ( '*' != from2 [0] ) { printf ( "wrong second line in second input file\n" ); exit ( ERR_L2_F2 ); } do { if ( 3 != sscanf ( from1, "*** %2d %2d %2d", &curfam.x, &curfam.y, &curfam.z ) ) { printf ( "wrong family header (%s) in first file\n", from1 ); exit ( ERR_HEADER1 ); } if ( 3 != sscanf ( from2, "*** %2d %2d %2d", &x, &y, &z ) ) { printf ( "wrong family header (%s) in second file\n", from2 ); exit ( ERR_HEADER2 ); } if ( (x!=curfam.x) || (y!=curfam.y) || (z!=curfam.z) ) { printf ( "different family headers in two input files" ); exit ( ERR_HEADERS_DIFF ); } recno1 = 0; do { get_line1 ( & from1 ); if ( from1 == NULL ) break; if ( ' ' != from1 [0] ) break; if ( 6 != sscanf ( from1, " %ld %ld %ld %ld %ld %ld", &curfam.pos, &curfam.sk, &curfam.p1, &curfam.p2, &curfam.llim, &curfam.hlim ) ) { printf ( "wrong data line [%s] in first input file\n", from1 ); exit ( ERR_DATA1 ); } if ( recno1 >= MAXRECNO ) { printf ( "too long family in first input file" ); exit ( ERR_LONG_FAMILY1 ); } p = & InData1 [recno1++]; p->x = curfam.x; p->y = curfam.y; p->z = curfam.z; p->pos = curfam.pos; p->sk = curfam.sk; p->p1 = curfam.p1; p->p2 = curfam.p2; p->llim = curfam.llim; p->hlim = curfam.hlim; } while (1); recno2 = 0; do { get_line2 ( & from2 ); if ( from2 == NULL ) break; if ( ' ' != from2 [0] ) break; if ( 6 != sscanf ( from2, " %ld %ld %ld %ld %ld %ld", &curfam.pos, &curfam.sk, &curfam.p1, &curfam.p2, &curfam.llim, &curfam.hlim ) ) { printf ( "wrong data line [%s] in second input file\n", from1 ); exit ( ERR_DATA2 ); } if ( recno2 >= MAXRECNO ) { printf ( "too long family in second input file" ); exit ( ERR_LONG_FAMILY2 ); } p = & InData2 [recno2++]; p->x = curfam.x; p->y = curfam.y; p->z = curfam.z; p->pos = curfam.pos; p->sk = curfam.sk; p->p1 = curfam.p1; p->p2 = curfam.p2; p->llim = curfam.llim; p->hlim = curfam.hlim; } while (1); if ( (0!=recno1) && (0!=recno2) ) { res = correlate ( InData1, recno1, WordLen1, InData2, recno2, WordLen2 ); fprintf ( outfile, "[ %2d %2d %2d %9e ]\n", res.x, res.y, res.z, res.tot ); } if ( from1 == NULL && from2 == NULL ) exit (0); if ( from1 == NULL || from2 == NULL ) { printf ( "non-syncronous end-of-files" ); exit ( ERR_NONSYNC ); } if ( '*' != from1 [0] ) { printf ( "strange line [%s] in the first file\n", from1 ); exit ( ERR_LINE_STRANGE1 ); } if ( '*' != from2 [0] ) { printf ( "strange line [%s] in the second file\n", from1 ); exit ( ERR_LINE_STRANGE2 ); } } while (1); /* unreachable */ } static ResultStruct correlate ( FamilyStruct *pertvec1, int size1, int WordLen1, FamilyStruct *pertvec2, int size2, int WordLen2 ) { long width, p1, p2, i, j; FamilyStruct * word1, * word2; ResultStruct Result = {0, 0, 0, 0, 0.0F, 0}; float total = 0.0F; Result.x = pertvec1->x; Result.y = pertvec1->y; Result.z = pertvec1->z; word1 = pertvec1; for (i = 1; i <= size1; i++) { word2=pertvec2; for (j = 1; j <= size2; j++) { p1=word1->llim; if (word2->llim > p1) p1=word2->llim; p2=word1->hlim; if (word2->hlim < p2) p2=word2->hlim; width=p2-p1; if (width < 1) width=1; total += give_score ( word1->pos, word2->pos, word1->sk, word2->sk, WordLen1, WordLen2, width ); total += give_score ( word2->pos, word1->pos, word2->sk, word1->sk, WordLen2, WordLen1, width ); word2++; } word1++; } Result.tot=total; return Result; } static float give_score ( long p1, long p2, long sk1, long sk2, int llen1, int llen2, long width ) { my_ldiv_t aa; int k, j; long m, s, table_sk, p, l1, l2; float di, dist, score = 0.0F; float a,b; float dx, dy; float _width; float tot = 0.0F; _width = 100.0F * width; for (m = 1; m <= MAXM; m++) { aa = divmod(sk1, m, 1); table_sk = aa.quot; s = aa.rem; if (table_sk < 2) break; aa = divmod(sk2, table_sk, 0); a = (float) aa.quot; b = (float) aa.rem; l1 = p1; dist = INFTY; for (k = 1; k <= llen1; k++) { l2 = p2; for (j = 1; j <= llen2; j++) { /********* calculate distance **********/ p = labs(l2-l1); aa.quot = p / table_sk; aa.rem = p % table_sk; if (aa.rem*2 > table_sk) { aa.rem -= table_sk; aa.quot++; } dx = (float) aa.quot; dy = (float) aa.rem; di = dx*dx + dy*dy; if (di < dist) dist = di; l2 += sk2; /***************************************/ } l1 += sk1; } score = _width / (float) (dist + a*a + b*b + m*m + s*s) ; tot += score; } return tot; } my_ldiv_t divmod ( long a, long b, int mode ) { my_ldiv_t aa; a = labs(a); b = labs(b); aa.quot = a / b; aa.rem = a % b; if ( (aa.rem+aa.rem+mode) > b) { aa.rem -= b; aa.quot++; } return aa; } /* end of distance.c */