00001
00063 #include "util.h"
00064 #include "mtrInt.h"
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #ifndef lint
00083 static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.18 2009/02/20 02:03:47 fabio Exp $";
00084 #endif
00085
00086
00087
00088
00089
00092
00093
00094
00095
00096 static int mtrShiftHL (MtrNode *node, int shift);
00097
00100
00101
00102
00103
00104
00118 MtrNode *
00119 Mtr_InitGroupTree(
00120 int lower,
00121 int size)
00122 {
00123 MtrNode *root;
00124
00125 root = Mtr_InitTree();
00126 if (root == NULL) return(NULL);
00127 root->flags = MTR_DEFAULT;
00128 root->low = lower;
00129 root->size = size;
00130 return(root);
00131
00132 }
00133
00134
00155 MtrNode *
00156 Mtr_MakeGroup(
00157 MtrNode * root ,
00158 unsigned int low ,
00159 unsigned int size ,
00160 unsigned int flags )
00161 {
00162 MtrNode *node,
00163 *first,
00164 *last,
00165 *previous,
00166 *newn;
00167
00168
00169 if (size == 0)
00170 return(NULL);
00171
00172
00173
00174
00175 if (low < (unsigned int) root->low ||
00176 low + size > (unsigned int) (root->low + root->size))
00177 return(NULL);
00178
00179
00180
00181 if (root->size == size && root->low == low) {
00182 root->flags = flags;
00183 return(root);
00184 }
00185
00186
00187
00188
00189
00190
00191 if (root->child == NULL) {
00192 newn = Mtr_AllocNode();
00193 if (newn == NULL) return(NULL);
00194 newn->low = low;
00195 newn->size = size;
00196 newn->flags = flags;
00197 newn->parent = root;
00198 newn->elder = newn->younger = newn->child = NULL;
00199 root->child = newn;
00200 return(newn);
00201 }
00202
00203
00204
00205
00206 previous = NULL;
00207 first = root->child;
00208 while (first != NULL && low >= (unsigned int) (first->low + first->size)) {
00209 previous = first;
00210 first = first->younger;
00211 }
00212 if (first == NULL) {
00213
00214
00215
00216 newn = Mtr_AllocNode();
00217 if (newn == NULL) return(NULL);
00218 newn->low = low;
00219 newn->size = size;
00220 newn->flags = flags;
00221 newn->parent = root;
00222 newn->elder = previous;
00223 previous->younger = newn;
00224 newn->younger = newn->child = NULL;
00225 return(newn);
00226 }
00227
00228 if (low >= (unsigned int) first->low &&
00229 low + size <= (unsigned int) (first->low + first->size)) {
00230
00231 newn = Mtr_MakeGroup(first, low, size, flags);
00232 return(newn);
00233 } else if (low + size <= first->low) {
00234
00235
00236 newn = Mtr_AllocNode();
00237 if (newn == NULL) return(NULL);
00238 newn->low = low;
00239 newn->size = size;
00240 newn->flags = flags;
00241 newn->child = NULL;
00242 newn->parent = root;
00243 newn->elder = previous;
00244 newn->younger = first;
00245 first->elder = newn;
00246 if (previous != NULL) {
00247 previous->younger = newn;
00248 } else {
00249 root->child = newn;
00250 }
00251 return(newn);
00252 } else if (low < (unsigned int) first->low &&
00253 low + size < (unsigned int) (first->low + first->size)) {
00254
00255 return(NULL);
00256 } else if (low > first->low) {
00257
00258
00259
00260 return(NULL);
00261 }
00262
00263
00264
00265
00266 last = first->younger;
00267 while (last != NULL &&
00268 (unsigned int) (last->low + last->size) < low + size) {
00269 last = last->younger;
00270 }
00271 if (last == NULL) {
00272
00273
00274 newn = Mtr_AllocNode();
00275 if (newn == NULL) return(NULL);
00276 newn->low = low;
00277 newn->size = size;
00278 newn->flags = flags;
00279 newn->child = first;
00280 newn->parent = root;
00281 newn->elder = previous;
00282 newn->younger = NULL;
00283 first->elder = NULL;
00284 if (previous != NULL) {
00285 previous->younger = newn;
00286 } else {
00287 root->child = newn;
00288 }
00289 last = first;
00290 while (last != NULL) {
00291 last->parent = newn;
00292 last = last->younger;
00293 }
00294 return(newn);
00295 }
00296
00297
00298 if (low + size - 1 >= (unsigned int) last->low &&
00299 low + size < (unsigned int) (last->low + last->size)) {
00300
00301 return(NULL);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310 newn = Mtr_AllocNode();
00311 if (newn == NULL) return(NULL);
00312 newn->low = low;
00313 newn->size = size;
00314 newn->flags = flags;
00315 newn->child = first;
00316 newn->parent = root;
00317 if (previous == NULL) {
00318 root->child = newn;
00319 } else {
00320 previous->younger = newn;
00321 }
00322 newn->elder = previous;
00323 newn->younger = last->younger;
00324 if (last->younger != NULL) {
00325 last->younger->elder = newn;
00326 }
00327 last->younger = NULL;
00328 first->elder = NULL;
00329 for (node = first; node != NULL; node = node->younger) {
00330 node->parent = newn;
00331 }
00332
00333 return(newn);
00334
00335 }
00336
00337
00354 MtrNode *
00355 Mtr_DissolveGroup(
00356 MtrNode * group )
00357 {
00358 MtrNode *parent;
00359 MtrNode *last;
00360
00361 parent = group->parent;
00362
00363 if (parent == NULL) return(NULL);
00364 if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL);
00365
00366
00367
00368 for (last = group->child; last->younger != NULL; last = last->younger) {
00369 last->parent = parent;
00370 }
00371 last->parent = parent;
00372
00373 last->younger = group->younger;
00374 if (group->younger != NULL) {
00375 group->younger->elder = last;
00376 }
00377
00378 group->child->elder = group->elder;
00379 if (group == parent->child) {
00380 parent->child = group->child;
00381 } else {
00382 group->elder->younger = group->child;
00383 }
00384
00385 Mtr_DeallocNode(group);
00386 return(parent);
00387
00388 }
00389
00390
00406 MtrNode *
00407 Mtr_FindGroup(
00408 MtrNode * root ,
00409 unsigned int low ,
00410 unsigned int size )
00411 {
00412 MtrNode *node;
00413
00414 #ifdef MTR_DEBUG
00415
00416 assert(!MTR_TEST(root,MTR_TERMINAL));
00417 #endif
00418
00419
00420 if (size < 1) return(NULL);
00421
00422
00423
00424
00425 if (low < (unsigned int) root->low ||
00426 low + size > (unsigned int) (root->low + root->size))
00427 return(NULL);
00428
00429 if (root->size == size && root->low == low)
00430 return(root);
00431
00432 if (root->child == NULL)
00433 return(NULL);
00434
00435
00436
00437
00438 node = root->child;
00439 while (low >= (unsigned int) (node->low + node->size)) {
00440 node = node->younger;
00441 }
00442 if (low + size <= (unsigned int) (node->low + node->size)) {
00443
00444 node = Mtr_FindGroup(node, low, size);
00445 return(node);
00446 } else {
00447 return(NULL);
00448 }
00449
00450 }
00451
00452
00467 int
00468 Mtr_SwapGroups(
00469 MtrNode * first ,
00470 MtrNode * second )
00471 {
00472 MtrNode *node;
00473 MtrNode *parent;
00474 int sizeFirst;
00475 int sizeSecond;
00476
00477 if (second->younger == first) {
00478 node = first;
00479 first = second;
00480 second = node;
00481 } else if (first->younger != second) {
00482 return(0);
00483 }
00484
00485 sizeFirst = first->size;
00486 sizeSecond = second->size;
00487
00488
00489 parent = first->parent;
00490 if (parent == NULL || second->parent != parent) return(0);
00491 if (parent->child == first) {
00492 parent->child = second;
00493 } else {
00494 first->elder->younger = second;
00495 }
00496 if (second->younger != NULL) {
00497 second->younger->elder = first;
00498 }
00499 first->younger = second->younger;
00500 second->elder = first->elder;
00501 first->elder = second;
00502 second->younger = first;
00503
00504
00505 if (!mtrShiftHL(first,sizeSecond)) return(0);
00506 if (!mtrShiftHL(second,-sizeFirst)) return(0);
00507
00508 return(1);
00509
00510 }
00511
00512
00534 void
00535 Mtr_PrintGroups(
00536 MtrNode * root ,
00537 int silent )
00538 {
00539 MtrNode *node;
00540
00541 assert(root != NULL);
00542 assert(root->younger == NULL || root->younger->elder == root);
00543 assert(root->elder == NULL || root->elder->younger == root);
00544 #if SIZEOF_VOID_P == 8
00545 if (!silent) (void) printf("(%u",root->low);
00546 #else
00547 if (!silent) (void) printf("(%hu",root->low);
00548 #endif
00549 if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
00550 if (!silent) (void) printf(",");
00551 } else {
00552 node = root->child;
00553 while (node != NULL) {
00554 assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
00555 assert(node->parent == root);
00556 Mtr_PrintGroups(node,silent);
00557 node = node->younger;
00558 }
00559 }
00560 if (!silent) {
00561 #if SIZEOF_VOID_P == 8
00562 (void) printf("%u", root->low + root->size - 1);
00563 #else
00564 (void) printf("%hu", root->low + root->size - 1);
00565 #endif
00566 if (root->flags != MTR_DEFAULT) {
00567 (void) printf("|");
00568 if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
00569 if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
00570 if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
00571 }
00572 (void) printf(")");
00573 if (root->parent == NULL) (void) printf("\n");
00574 }
00575 assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
00576 return;
00577
00578 }
00579
00580
00608 MtrNode *
00609 Mtr_ReadGroups(
00610 FILE * fp ,
00611 int nleaves )
00612 {
00613 int low;
00614 int size;
00615 int err;
00616 unsigned int flags;
00617 MtrNode *root;
00618 MtrNode *node;
00619 char attrib[8*sizeof(unsigned int)+1];
00620 char *c;
00621
00622 root = Mtr_InitGroupTree(0,nleaves);
00623 if (root == NULL) return NULL;
00624
00625 while (! feof(fp)) {
00626
00627 err = fscanf(fp, "%d %d %s", &low, &size, attrib);
00628 if (err == EOF) {
00629 break;
00630 } else if (err != 3) {
00631 Mtr_FreeTree(root);
00632 return(NULL);
00633 } else if (low < 0 || low+size > nleaves || size < 1) {
00634 Mtr_FreeTree(root);
00635 return(NULL);
00636 } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) {
00637
00638
00639 Mtr_FreeTree(root);
00640 return(NULL);
00641 }
00642
00643
00644
00645
00646 flags = MTR_DEFAULT;
00647 for (c=attrib; *c != 0; c++) {
00648 switch (*c) {
00649 case 'D':
00650 break;
00651 case 'F':
00652 flags |= MTR_FIXED;
00653 break;
00654 case 'N':
00655 flags |= MTR_NEWNODE;
00656 break;
00657 case 'S':
00658 flags |= MTR_SOFT;
00659 break;
00660 case 'T':
00661 flags |= MTR_TERMINAL;
00662 break;
00663 default:
00664 return NULL;
00665 }
00666 }
00667 node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size,
00668 flags);
00669 if (node == NULL) {
00670 Mtr_FreeTree(root);
00671 return(NULL);
00672 }
00673 }
00674
00675 return(root);
00676
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00703 static int
00704 mtrShiftHL(
00705 MtrNode * node ,
00706 int shift )
00707 {
00708 MtrNode *auxnode;
00709 int low;
00710
00711 low = (int) node->low;
00712
00713
00714 low += shift;
00715
00716 if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0);
00717
00718 node->low = (MtrHalfWord) low;
00719
00720 if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) {
00721 auxnode = node->child;
00722 do {
00723 if (!mtrShiftHL(auxnode,shift)) return(0);
00724 auxnode = auxnode->younger;
00725 } while (auxnode != NULL);
00726 }
00727
00728 return(1);
00729
00730 }