58 # define __hv_unused __attribute__ ((unused))
65 typedef struct dlnode {
75 static int compare_node(
const void *p1,
const void* p2)
77 const double x1 = *((*(
const dlnode_t **)p1)->x+3);
78 const double x2 = *((*(
const dlnode_t **)p2)->x+3);
80 return (x1 < x2) ? -1 : (x1 > x2) ? 1 : 0;
89 setup_cdllist(
double *data,
int n,
const double *ref)
97 head = malloc ((n+1) *
sizeof(dlnode_t));
101 for (i = 1; i <= n; i++) {
102 for(j = 0; j < d; j++)
103 head[i-1].x[j] = data[(i-1)*d + j];
107 head[n].x[0] = head[n].x[1] = head[n].x[2] = -DBL_MAX;
108 head[n].x[3] = ref[3];
111 scratch = malloc(n *
sizeof(dlnode_t*));
113 for (i = 0; i < n; i++){
114 scratch[i] = head + i;
117 qsort(scratch, n,
sizeof(dlnode_t*), compare_node);
119 data2 = (
double *) malloc (n * 4 *
sizeof(
double));
120 for(i = 0; i < n; i++){
121 for(j = 0; j < d; j++){
122 data2[i*d + j] = scratch[i]->x[j];
127 for(i = 0; i < n; i++){
128 for(j = 0; j < d; j++)
129 head[i].x[j] = data2[i*d + j];
139 static void free_cdllist(dlnode_t * head)
144 static void free_sentinels(dlnode_t * list){
170 static box * new_box(
double lx,
double ly,
double lz,
double ux,
double uy,
double uz){
171 box * b = (box *)malloc(
sizeof(box));
185 static void push_left(boxlist * bl, box * b){
195 static void push_left_e(boxlist * bl, box * b){
196 if(bl->head == NULL){
215 static double close_box(box *b){
216 double volume = (b->ux - b->lx) * (b->uy - b->ly) * (b->uz - b->lz);
222 static double shrink_box(box *b,
double ux){
223 double volume = (b->ux - ux) * (b->uy - b->ly) * (b->uz - b->lz);
228 static double close_boxes_right(boxlist *bl,
double x,
double uz){
233 bl->tail->next = NULL;
235 volume += close_box(b);
241 volume += shrink_box(b, x);
249 static double close_boxes_left(boxlist *bl,
double y,
double uz){
258 if(y >= bl->head->uy)
269 while(b != NULL && b->uy >= y){
276 volume += close_box(b);
281 bl->head->prev = NULL;
285 b = new_box(lx, ly, lz, lastlx, y, 0);
293 static double close_all_boxes(boxlist *bl,
double uz){
299 volume += close_box(b);
303 bl->head = bl->tail = NULL;
309 static void insert_after_y(dlnode_t *
new, dlnode_t *prev){
312 new->nexty = prev->nexty;
313 new->nexty->prevy =
new;
318 static void insert_after_z(dlnode_t *
new, dlnode_t *prev){
321 new->nextz = prev->nextz;
322 new->nextz->prevz =
new;
328 static void remove_y(dlnode_t *p){
330 p->prevy->nexty = p->nexty;
331 p->nexty->prevy = p->prevy;
335 static void remove_z(dlnode_t *p){
337 p->prevz->nextz = p->nextz;
338 p->nextz->prevz = p->prevz;
343 static boxlist * init_box_list(dlnode_t *p, dlnode_t * ynext){
346 double previous_x = p->xrightbelow;
348 dlnode_t * q = ynext;
350 boxlist * bl = (boxlist *)malloc(
sizeof(boxlist));
351 box * b = (box *)malloc(
sizeof(box));
353 b->prev = b->next = NULL;
354 bl->head = bl->tail = b;
357 while(q->x[0] > p->x[0] || q->x[2] > p->x[2]){
360 if(q->x[2] <= p->x[2] && q->x[0] < previous_x && q->x[0] > p->x[0]){
361 b = new_box(q->x[0], p->x[1], p->x[2], previous_x, q->x[1], 0);
364 previous_x = q->x[0];
370 b = new_box(p->x[0], p->x[1], p->x[2], previous_x, q->x[1], 0);
375 bl->tail = bl->tail->prev;
376 free(bl->tail->next);
377 bl->tail->next = NULL;
385 static double update_boxes(boxlist * bl, dlnode_t *p, dlnode_t * znext){
392 while(bl->head != NULL){
393 if(q->x[0] <= p->x[0]){
395 if(q->x[1] <= p->x[1]){
400 volume += close_all_boxes(bl, q->x[2]);
406 volume += close_boxes_left(bl, q->x[1], q->x[2]);
409 if(q->x[1] >= p->x[1] && p->x[0] < q->xrightbelow){
410 q->xrightbelow = p->x[0];
421 volume += close_boxes_right(bl, q->x[0], q->x[2]);
438 hv_increment3DA(dlnode_t *p, dlnode_t * ynext, dlnode_t *znext){
440 boxlist * bl = init_box_list(p, ynext);
444 return update_boxes(bl, p, znext);
454 hv_increment3D(dlnode_t *list, dlnode_t *p,
const double * ref){
455 double loss = 0, gain;
456 dlnode_t * q = list->prevz;
457 dlnode_t * yprev = list->nexty;
458 double xrightbelow = ref[0];
459 dlnode_t * zprev = list->nextz;
460 dlnode_t * head3 = list->nextz;
464 if(q->x[2] >= p->x[2] && q->x[1] >= p->x[1] && q->x[0] >= p->x[0]){
467 loss += hv_increment3DA(q, q->nexty, q->nextz);
471 if(q->x[2] > zprev->x[2] && (q->x[2] < p->x[2] || (q->x[2] == p->x[2] && q->x[1] <= p->x[1]))){
476 if(q->x[1] > yprev->x[1] && (q->x[1] < p->x[1] || (q->x[1] == p->x[1] && q->x[2] <= p->x[2]))){
480 if(q->x[2] <= p->x[2] && q->x[1] <= p->x[1]){
482 if(q->x[0] <= p->x[0]){
484 }
else if(q->x[0] < xrightbelow){
485 xrightbelow = q->x[0];
493 p->xrightbelow = xrightbelow;
496 gain = hv_increment3DA(p, yprev->nexty, zprev->nextz);
499 insert_after_z(p, zprev);
500 insert_after_y(p, yprev);
508 hv(dlnode_t *list,
int c,
const double * ref)
516 for (i = 0; i < c; i++) {
518 hypera = hypera + hv_increment3D(list+c, p, ref);
519 hyperv = hyperv + hypera * ((p+1)->x[3] - p->x[3]);
531 static void add_sentinels(dlnode_t * list,
const double * ref){
535 for(i = 0; i <= 1; i++){
536 dlnode_t * sentineli, * sentinelf;
537 sentineli = (dlnode_t *) malloc(
sizeof(dlnode_t));
538 sentinelf = (dlnode_t *) malloc(
sizeof(dlnode_t));
540 sentineli->xrightbelow = -DBL_MAX;
541 sentinelf->xrightbelow = -DBL_MAX;
545 sentineli->nexty = sentinelf;
546 sentinelf->prevy = sentineli;
547 list->nexty = sentineli;
548 sentineli->prevy = list;
549 list->prevy = sentinelf;
550 sentinelf->nexty = list;
553 sentineli->x[0] = ref[0];
554 sentineli->x[1] = -DBL_MAX;
555 sentineli->x[2] = -DBL_MAX;
557 sentinelf->x[0] = -DBL_MAX;
558 sentinelf->x[1] = ref[1];
559 sentinelf->x[2] = -DBL_MAX;
561 sentineli->nextz = sentinelf;
562 sentinelf->prevz = sentineli;
563 list->nextz = sentineli;
564 sentineli->prevz = list;
565 list->prevz = sentinelf;
566 sentinelf->nextz = list;
568 sentineli->x[0] = DBL_MAX;
569 sentineli->x[1] = DBL_MAX;
570 sentineli->x[2] = -DBL_MAX;
572 sentinelf->x[0] = -DBL_MAX;
573 sentinelf->x[1] = -DBL_MAX;
574 sentinelf->x[2] = ref[2];
578 sentineli->x[3] = DBL_MAX;
579 sentinelf->x[3] = DBL_MAX;
587 double guerreiro_hv4d(
double *data,
int n,
const double *ref)
597 list = setup_cdllist(data, n, ref);
599 add_sentinels(list+n, ref);
601 hyperv = hv(list, n, ref);
603 free_sentinels(list+n);