55 static int compare_tree_asc(
const void *p1,
const void *p2);
100 typedef int (*avl_compare_t)(
const void *,
const void *);
105 typedef void (*avl_freeitem_t)(
void *);
107 typedef struct avl_node_t {
108 struct avl_node_t *next;
109 struct avl_node_t *prev;
110 struct avl_node_t *parent;
111 struct avl_node_t *left;
112 struct avl_node_t *right;
120 typedef struct avl_tree_t {
125 avl_freeitem_t freeitem;
135 static void avl_rebalance(avl_tree_t *, avl_node_t *);
138 #define NODE_DEPTH(n) ((n) ? (n)->depth : 0)
139 #define L_DEPTH(n) (NODE_DEPTH((n)->left))
140 #define R_DEPTH(n) (NODE_DEPTH((n)->right))
141 #define CALC_DEPTH(n) ((L_DEPTH(n)>R_DEPTH(n)?L_DEPTH(n):R_DEPTH(n)) + 1)
144 static int avl_check_balance(avl_node_t *avlnode) {
147 d = R_DEPTH(avlnode) - L_DEPTH(avlnode);
148 return d<-1?-1:d>1?1:0;
153 avl_search_closest(
const avl_tree_t *avltree,
const void *item, avl_node_t **avlnode) {
163 return *avlnode = NULL, 0;
167 c = compare_tree_asc(item, node->item);
173 return *avlnode = node, -1;
178 return *avlnode = node, 1;
180 return *avlnode = node, 0;
186 avl_init_tree(avl_tree_t *rc, avl_compare_t cmp, avl_freeitem_t freeitem) {
192 rc->freeitem = freeitem;
198 avl_alloc_tree(avl_compare_t cmp, avl_freeitem_t freeitem) {
199 return avl_init_tree(malloc(
sizeof(avl_tree_t)), cmp, freeitem);
203 avl_clear_tree(avl_tree_t *avltree) {
204 avltree->top = avltree->head = avltree->tail = NULL;
208 avl_clear_node(avl_node_t *newnode) {
209 newnode->left = newnode->right = NULL;
219 avl_insert_top(avl_tree_t *avltree, avl_node_t *newnode) {
220 avl_clear_node(newnode);
221 newnode->prev = newnode->next = newnode->parent = NULL;
222 avltree->head = avltree->tail = avltree->top = newnode;
227 avl_insert_before(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) {
237 assert (!node->left);
239 avl_clear_node(newnode);
241 newnode->next = node;
242 newnode->parent = node;
244 newnode->prev = node->prev;
246 node->prev->next = newnode;
248 avltree->head = newnode;
249 node->prev = newnode;
251 node->left = newnode;
252 avl_rebalance(avltree, node);
257 avl_insert_after(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) {
267 assert (!node->right);
269 avl_clear_node(newnode);
271 newnode->prev = node;
272 newnode->parent = node;
274 newnode->next = node->next;
276 node->next->prev = newnode;
278 avltree->tail = newnode;
279 node->next = newnode;
281 node->right = newnode;
282 avl_rebalance(avltree, node);
293 avl_unlink_node(avl_tree_t *avltree, avl_node_t *avlnode) {
295 avl_node_t **superparent;
296 avl_node_t *subst, *left, *right;
300 avlnode->prev->next = avlnode->next;
302 avltree->head = avlnode->next;
305 avlnode->next->prev = avlnode->prev;
307 avltree->tail = avlnode->prev;
309 parent = avlnode->parent;
312 ? avlnode == parent->left ? &parent->left : &parent->right
315 left = avlnode->left;
316 right = avlnode->right;
318 *superparent = right;
320 right->parent = parent;
324 left->parent = parent;
327 subst = avlnode->prev;
331 balnode = subst->parent;
332 balnode->right = subst->left;
334 balnode->right->parent = balnode;
336 left->parent = subst;
338 subst->right = right;
339 subst->parent = parent;
340 right->parent = subst;
341 *superparent = subst;
344 avl_rebalance(avltree, balnode);
357 avl_rebalance(avl_tree_t *avltree, avl_node_t *avlnode) {
361 avl_node_t **superparent;
366 parent = avlnode->parent;
369 ? avlnode == parent->left ? &parent->left : &parent->right
372 switch(avl_check_balance(avlnode)) {
374 child = avlnode->left;
376 if(L_DEPTH(child) >= R_DEPTH(child)) {
379 if(L_COUNT(child) >= R_COUNT(child)) {
381 #error No balancing possible.
384 avlnode->left = child->right;
386 avlnode->left->parent = avlnode;
387 child->right = avlnode;
388 avlnode->parent = child;
389 *superparent = child;
390 child->parent = parent;
392 avlnode->count = CALC_COUNT(avlnode);
393 child->count = CALC_COUNT(child);
396 avlnode->depth = CALC_DEPTH(avlnode);
397 child->depth = CALC_DEPTH(child);
400 gchild = child->right;
401 avlnode->left = gchild->right;
403 avlnode->left->parent = avlnode;
404 child->right = gchild->left;
406 child->right->parent = child;
407 gchild->right = avlnode;
409 gchild->right->parent = gchild;
410 gchild->left = child;
412 gchild->left->parent = gchild;
413 *superparent = gchild;
414 gchild->parent = parent;
416 avlnode->count = CALC_COUNT(avlnode);
417 child->count = CALC_COUNT(child);
418 gchild->count = CALC_COUNT(gchild);
421 avlnode->depth = CALC_DEPTH(avlnode);
422 child->depth = CALC_DEPTH(child);
423 gchild->depth = CALC_DEPTH(gchild);
428 child = avlnode->right;
430 if(R_DEPTH(child) >= L_DEPTH(child)) {
433 if(R_COUNT(child) >= L_COUNT(child)) {
435 #error No balancing possible.
438 avlnode->right = child->left;
440 avlnode->right->parent = avlnode;
441 child->left = avlnode;
442 avlnode->parent = child;
443 *superparent = child;
444 child->parent = parent;
446 avlnode->count = CALC_COUNT(avlnode);
447 child->count = CALC_COUNT(child);
450 avlnode->depth = CALC_DEPTH(avlnode);
451 child->depth = CALC_DEPTH(child);
454 gchild = child->left;
455 avlnode->right = gchild->left;
457 avlnode->right->parent = avlnode;
458 child->left = gchild->right;
460 child->left->parent = child;
461 gchild->left = avlnode;
463 gchild->left->parent = gchild;
464 gchild->right = child;
466 gchild->right->parent = gchild;
467 *superparent = gchild;
468 gchild->parent = parent;
470 avlnode->count = CALC_COUNT(avlnode);
471 child->count = CALC_COUNT(child);
472 gchild->count = CALC_COUNT(gchild);
475 avlnode->depth = CALC_DEPTH(avlnode);
476 child->depth = CALC_DEPTH(child);
477 gchild->depth = CALC_DEPTH(gchild);
483 avlnode->count = CALC_COUNT(avlnode);
486 avlnode->depth = CALC_DEPTH(avlnode);
497 #if !defined(VARIANT) || VARIANT < 1 || VARIANT > 4
498 #error VARIANT must be either 1, 2, 3 or 4, e.g., 'make VARIANT=4'
502 # define __hv_unused __attribute__ ((unused))
508 # define __variant3_only __hv_unused
510 # define __variant3_only
514 # define __variant2_only __hv_unused
516 # define __variant2_only
519 typedef struct dlnode {
521 struct dlnode **next;
522 struct dlnode **prev;
523 struct avl_node_t * tnode;
534 static avl_tree_t *tree;
536 int stop_dimension = 1;
538 int stop_dimension = 2;
541 static int compare_node(
const void *p1,
const void* p2)
543 const double x1 = *((*(
const dlnode_t **)p1)->x);
544 const double x2 = *((*(
const dlnode_t **)p2)->x);
546 return (x1 < x2) ? -1 : (x1 > x2) ? 1 : 0;
549 static int compare_tree_asc(
const void *p1,
const void *p2)
551 const double *x1 = (
const double *)p1;
552 const double *x2 = (
const double *)p2;
554 return (x1[1] > x2[1]) ? -1 : (x1[1] < x2[1]) ? 1
555 : (x1[0] >= x2[0]) ? -1 : 1;
563 setup_cdllist(
double *data,
int d,
int n)
569 head = malloc ((n+1) *
sizeof(dlnode_t));
573 head->next = malloc( d * (n+1) *
sizeof(dlnode_t*));
574 head->prev = malloc( d * (n+1) *
sizeof(dlnode_t*));
575 head->tnode = malloc ((n+1) *
sizeof(avl_node_t));
578 head->area = malloc(d * (n+1) *
sizeof(
double));
581 head->vol = malloc(d * (n+1) *
sizeof(
double));
584 for (i = 1; i <= n; i++) {
585 head[i].x = head[i-1].x + d;
587 head[i].next = head[i-1].next + d;
588 head[i].prev = head[i-1].prev + d;
589 head[i].tnode = head[i-1].tnode + 1;
591 head[i].area = head[i-1].area + d;
594 head[i].vol = head[i-1].vol + d;
599 scratch = malloc(n *
sizeof(dlnode_t*));
600 for (i = 0; i < n; i++)
601 scratch[i] = head + i + 1;
603 for (j = d-1; j >= 0; j--) {
604 for (i = 0; i < n; i++)
606 qsort(scratch, n,
sizeof(dlnode_t*), compare_node);
607 head->next[j] = scratch[0];
608 scratch[0]->prev[j] = head;
609 for (i = 1; i < n; i++) {
610 scratch[i-1]->next[j] = scratch[i];
611 scratch[i]->prev[j] = scratch[i-1];
613 scratch[n-1]->next[j] = head;
614 head->prev[j] = scratch[n-1];
619 for (i = 1; i <= n; i++) {
620 (head[i].tnode)->item = head[i].x;
626 static void free_cdllist(dlnode_t * head)
640 static void delete (dlnode_t *nodep,
int dim,
double * bound __variant3_only)
644 for (i = stop_dimension; i < dim; i++) {
645 nodep->prev[i]->next[i] = nodep->next[i];
646 nodep->next[i]->prev[i] = nodep->prev[i];
648 if (bound[i] > nodep->x[i])
649 bound[i] = nodep->x[i];
655 static void delete_dom (dlnode_t *nodep,
int dim)
659 for (i = stop_dimension; i < dim; i++) {
660 nodep->prev[i]->next[i] = nodep->next[i];
661 nodep->next[i]->prev[i] = nodep->prev[i];
666 static void reinsert (dlnode_t *nodep,
int dim,
double * bound __variant3_only)
670 for (i = stop_dimension; i < dim; i++) {
671 nodep->prev[i]->next[i] = nodep;
672 nodep->next[i]->prev[i] = nodep;
674 if (bound[i] > nodep->x[i])
675 bound[i] = nodep->x[i];
681 static void reinsert_dom (dlnode_t *nodep,
int dim)
684 for (i = stop_dimension; i < dim; i++) {
685 dlnode_t *p = nodep->prev[i];
687 nodep->next[i]->prev[i] = nodep;
688 nodep->area[i] = p->area[i];
691 nodep->vol[i] = p->vol[i] + p->area[i] * (nodep->x[i] - p->x[i]);
698 hv_recursive(dlnode_t *list,
int dim,
int c,
const double * ref,
704 if ( dim > stop_dimension ) {
706 dlnode_t *p1 = list->prev[dim];
713 for (pp = p1; pp->x; pp = pp->prev[dim]) {
714 if (pp->ignore < dim)
723 && (p1->x[dim] > bound[dim]
724 || p1->prev[dim]->x[dim] >= bound[dim])
729 if (p0->ignore >= dim)
732 delete(p0, dim, bound);
734 delete(p0, dim, bound);
741 hypera = hv_recursive(list, dim-1, c, ref, bound);
746 for (i = 1; i <= dim; i++)
747 p1->area[i] = p1->area[i-1] * (ref[i-1] - p1->x[i-1]);
751 hyperv = p1->prev[dim]->vol[dim] + p1->prev[dim]->area[dim]
752 * (p1->x[dim] - p1->prev[dim]->x[dim]);
754 if (p1->ignore >= dim)
755 p1->area[dim] = p1->prev[dim]->area[dim];
757 p1->area[dim] = hv_recursive(list, dim - 1, c, ref, bound);
762 if (p1->ignore == (dim - 1))
768 for (i = 1; i <= dim; i++)
769 p1->area[i] = p1->area[i-1] * (ref[i-1] - p1->x[i-1]);
771 p1->vol[dim] = hyperv;
774 while (p0->x != NULL) {
777 hyperv += hypera * (p0->x[dim] - p1->x[dim]);
779 hyperv += p1->area[dim] * (p0->x[dim] - p1->x[dim]);
783 if (p0->ignore >= dim) {
784 reinsert_dom (p0, dim);
785 p0->area[dim] = p1->area[dim];
788 reinsert (p0, dim, bound);
790 p0->area[dim] = hv_recursive (list, dim-1, c, ref, bound);
791 if (p0->ignore == (dim - 1))
795 hypera = hv_recursive (list, dim-1, c, ref, NULL);
800 p1->vol[dim] = hyperv;
804 bound[dim] = p1->x[dim];
808 hyperv += hypera * (ref[dim] - p1->x[dim]);
810 hyperv += p1->area[dim] * (ref[dim] - p1->x[dim]);
825 dlnode_t *pp = list->prev[2];
832 if (pp->x[2] < bound[2])
833 return pp->vol[2] + pp->area[2] * (ref[2] - pp->x[2]);
838 if (pp->x[2] >= bound[2]) {
839 pp->tnode->domr = ref[2];
840 pp->area[2] = (ref[0] - pp->x[0]) * (ref[1] - pp->x[1]);
849 while (pp->tnode->domr < bound[2]) {
855 avl_insert_top(tree,pp->tnode);
856 pp->tnode->domr = ref[2];
861 for (pp = pp->next[2]; pp->x[2] < bound[2]; pp = pp->next[2]) {
862 if (pp->tnode->domr >= bound[2]) {
863 avl_node_t *tnodeaux = pp->tnode;
864 tnodeaux->domr = ref[2];
865 if (avl_search_closest(tree, pp->x, &tnode) <= 0)
866 avl_insert_before(tree, tnode, tnodeaux);
868 avl_insert_after(tree, tnode, tnodeaux);
873 hypera = pp->area[2];
875 height = (pp->next[2]->x)
876 ? pp->next[2]->x[2] - pp->x[2]
879 bound[2] = list->prev[2]->x[2];
882 dlnode_t *pp = list->next[2];
885 hypera = (ref[0] - pp->x[0])*(ref[1] - pp->x[1]);
888 : pp->next[2]->x[2] - pp->x[2];
890 avl_insert_top(tree,pp->tnode);
892 hyperv += hypera * height;
893 for (pp = pp->next[2]; pp->x != NULL; pp = pp->next[2]) {
894 const double * prv_ip, * nxt_ip;
901 height = (pp == list->prev[2])
903 : pp->next[2]->x[2] - pp->x[2];
905 if (pp->ignore >= 2) {
906 hyperv += hypera * height;
908 pp->area[2] = hypera;
913 cmp = avl_search_closest(tree, pp->x, &tnode);
915 nxt_ip = (
double *)(tnode->item);
917 nxt_ip = (tnode->next != NULL)
918 ? (
double *)(tnode->next->item)
921 if (nxt_ip[0] <= pp->x[0]) {
924 pp->tnode->domr = pp->x[2];
925 pp->area[2] = hypera;
928 hyperv += hypera * height;
932 avl_insert_before(tree, tnode, pp->tnode);
933 tnode = pp->tnode->prev;
935 avl_insert_after(tree, tnode, pp->tnode);
938 pp->tnode->domr = ref[2];
941 prv_ip = (
double *)(tnode->item);
942 if (prv_ip[0] >= pp->x[0]) {
943 const double * cur_ip;
945 tnode = pp->tnode->prev;
948 cur_ip = (
double *)(tnode->item);
949 while (tnode->prev) {
950 prv_ip = (
double *)(tnode->prev->item);
951 hypera -= (prv_ip[1] - cur_ip[1]) * (nxt_ip[0] - cur_ip[0]);
952 if (prv_ip[0] < pp->x[0])
955 avl_unlink_node(tree,tnode);
959 tnode->domr = pp->x[2];
964 avl_unlink_node(tree, tnode);
966 tnode->domr = pp->x[2];
969 hypera -= (ref[1] - cur_ip[1]) * (nxt_ip[0] - cur_ip[0]);
976 hypera += (prv_ip[1] - pp->x[1]) * (nxt_ip[0] - pp->x[0]);
979 hyperv += hypera * height;
981 pp->area[2] = hypera;
984 avl_clear_tree(tree);
990 const dlnode_t *p1 = list->next[1];
991 double hypera = p1->x[0];
995 while ((p0 = p1->next[1])->x) {
996 hyperv += (ref[0] - hypera) * (p0->x[1] - p1->x[1]);
997 if (p0->x[0] < hypera)
999 else if (p0->ignore == 0)
1003 hyperv += (ref[0] - hypera) * (ref[1] - p1->x[1]);
1008 else if (dim == 0) {
1009 list->next[0]->ignore = -1;
1010 return (ref[0] - list->next[0]->x[0]);
1013 fprintf(stderr,
"%s:%d: unreachable condition! \n"
1014 "This is a bug, please report it to "
1015 "manuel.lopez-ibanez@ulb.ac.be\n", __FILE__, __LINE__);
1025 filter_delete_node(dlnode_t *node,
int d)
1029 for (i = 0; i < d; i++) {
1030 node->next[i]->prev[i] = node->prev[i];
1031 node->prev[i]->next[i] = node->next[i];
1041 filter(dlnode_t *list,
int d,
int n,
const double *ref)
1046 for (i = 0; i < d; i++) {
1047 dlnode_t *aux = list->prev[i];
1049 for (j = 0; j < np; j++) {
1050 if (aux->x[i] < ref[i])
1052 filter_delete_node (aux, d);
1068 test_domr(dlnode_t *p, dlnode_t *domr,
int dim,
int *order)
1071 for(i = 1; i <= dim; i++){
1072 if (p->x[order[i]] < domr->x[order[i]])
1085 test_dom(dlnode_t *list, dlnode_t *pp,
int dim,
int *order)
1109 if (p0->ignore < dim) {
1110 r = test_domr (pp, p0, dim, order);
1115 if (r == dim)
return r;
1116 else if (r > r_b) r_b = r;
1127 static void determine_ndom(dlnode_t *list,
int dim,
int *order,
int *count)
1133 for (i = 0; i <= dim; i++)
1136 p1 = list->next[ord];
1139 p1 = list->next[ord];
1141 while (p1 != list) {
1142 if (p1->ignore <= dim) {
1143 dom = test_dom(list, p1, dim, order);
1151 static void delete_dominated(dlnode_t *nodep,
int dim)
1154 for (i = 0; i <= dim; i++) {
1155 nodep->prev[i]->next[i] = nodep->next[i];
1156 nodep->next[i]->prev[i] = nodep->prev[i];
1174 determine_ndomf(dlnode_t *list,
int dim,
int c,
int *order,
int *count)
1180 for(i = 0; i <= dim; i++)
1183 p1 = list->next[ord];
1184 p1->ignore = p1->ignore_best = 0;
1186 p1 = list->next[ord];
1197 if (p1->ignore <= dim) {
1198 dom = test_dom(list, p1, dim, order);
1200 p1->ignore = p1->ignore_best = dom;
1207 if (count[dim] > 0) {
1210 if (p1->ignore == dim) {
1211 delete_dominated(p1, dim);
1232 static int define_order(dlnode_t *list,
int dim,
int c,
int *order)
1245 int *best_order = malloc(dim *
sizeof(
int));
1254 int *count = malloc(dim *
sizeof(
int));
1258 int *best_count = malloc(dim *
sizeof(
int));
1262 for (i = 0; i < dim; i++) {
1263 best_order[i] = order[i] = i;
1264 best_count[i] = count[i] = 0;
1269 c = determine_ndomf(list, dim-1, c, order, count);
1274 for (i = 0; i < dim; i++) {
1275 best_count[i] = count[i];
1288 for (i = dim - 1; i > 2; i--) {
1316 for (j = 0; j < i; j++) {
1318 order[i] = order[j];
1326 determine_ndom(list, i-1, order, count);
1336 if (best_count[i-1] < count[i-1]
1337 || (best_count[i-1] == count[i-1]
1338 && best_count[i-2] < count[i-2])) {
1339 for (k = 0; k <= i; k++) {
1340 best_count[k] = count[k];
1341 best_order[k] = order[k];
1345 p->ignore_best = p->ignore;
1359 if (order[i] != best_order[i]) {
1360 for (j = 0; j <= i; j++) {
1361 count[j] = best_count[j];
1362 order[j] = best_order[j];
1371 p->ignore = p->ignore_best;
1387 static void reorder_reference(
double *reference,
int d,
int *order)
1390 double *tmp = (
double *) malloc(d *
sizeof(
double));
1391 for (j = 0; j < d; j++) {
1392 tmp[j] = reference[j];
1394 for (j = 0; j < d; j++) {
1395 reference[j] = tmp[order[j]];
1403 void reorder_list(dlnode_t *list,
int d,
int *order)
1407 double *tmp = (
double *) malloc(d *
sizeof(
double));
1408 dlnode_t **prev = (dlnode_t **) malloc(d *
sizeof(dlnode_t *));
1409 dlnode_t **next = (dlnode_t **) malloc(d *
sizeof(dlnode_t *));
1412 for(j = 0; j < d; j++) {
1413 prev[j] = list->prev[j];
1414 next[j] = list->next[j];
1417 for(j = 0; j < d; j++) {
1418 list->prev[j] = prev[order[j]];
1419 list->next[j] = next[order[j]];
1426 for(j = 0; j < d; j++) {
1428 prev[j] = p->prev[j];
1429 next[j] = p->next[j];
1432 for(j = 0; j < d; j++) {
1433 x[j] = tmp[order[j]];
1434 p->prev[j] = prev[order[j]];
1435 p->next[j] = next[order[j]];
1445 double fpli_hv(
double *data,
int d,
int n,
const double *ref)
1449 double * bound = NULL;
1454 bound = malloc (d *
sizeof(
double));
1455 for (i = 0; i < d; i++) bound[i] = -DBL_MAX;
1458 tree = avl_alloc_tree ((avl_compare_t) compare_tree_asc,
1459 (avl_freeitem_t) NULL);
1461 list = setup_cdllist(data, d, n);
1463 n = filter(list, d, n, ref);
1466 }
else if (n == 1) {
1467 dlnode_t * p = list->next[0];
1469 for (i = 0; i < d; i++)
1470 hyperv *= ref[i] - p->x[i];
1472 hyperv = hv_recursive(list, d-1, n, ref, bound);
1475 free_cdllist (list);
1485 double fpli_hv_order(
double *data,
int d,
int n,
const double *ref,
int *order,
1486 double *order_time,
double *hv_time)
1490 double * bound = NULL;
1491 double * ref_ord = (
double *) malloc(d *
sizeof(
double));
1496 bound = malloc (d *
sizeof(
double));
1497 for (i = 0; i < d; i++) bound[i] = -DBL_MAX;
1500 tree = avl_alloc_tree ((avl_compare_t) compare_tree_asc,
1501 (avl_freeitem_t) NULL);
1503 list = setup_cdllist(data, d, n);
1506 n = define_order(list, d, n, order);
1507 reorder_list(list, d, order);
1510 for (i = 0; i < d; i++)
1511 ref_ord[i] = ref[i];
1513 reorder_reference(ref_ord, d, order);
1516 for(i = 0; i < d; i++)
1517 ref_ord[i] = ref[i];
1520 *order_time = Timer_elapsed_virtual ();
1523 n = filter(list, d, n, ref_ord);
1526 }
else if (n == 1) {
1528 dlnode_t * p = list->next[0];
1529 for (i = 0; i < d; i++)
1530 hyperv *= ref[i] - p->x[i];
1532 hyperv = hv_recursive(list, d-1, n, ref, bound);
1535 free_cdllist (list);
1540 *hv_time = Timer_elapsed_virtual ();