// // file name: sparse_mask.C // // This file is written by Ee-Chien Chang // //----------------------------------------------------- // // S P A R S E M A S K // // maintance a sparse mask using linked list. // //------------------------------------------------------ // usage // sparse_mask M (16,16,1) ; // a 16 by 16 mask. 1 is the level // // initially, everythins is set to zero // // to set the entry (5,6) to 1... // M[5].set(6,6); // // to set the entry (5,6), (5,7),...,(5,20) to 1 // M[5].set(6,20); // // to read the entry (5,6) // M[5][6]; // // to get a list of zeros // q= M[5].zeros ( &total, 6,20 ); // total return the number of zeros. // Remember to dispose the list after used. // //------------------------------------------------------ // // Note: (1) setting to zero is not supported. // (2) assignment // M[5][6] = 1; // is illegal. //------------------------------------------------------ //--------------------------------------------------- // M A S K T R E E //--------------------------------------------------- // just an array of sparse mask. // // for usage... check sparse_mask_test.c //--------------------------------------------------- #include #include "sparse_mask.h" //----------------------------------------------------- // // S P A R S E M A S K // // maintance a sparse mask using linked list. // //------------------------------------------------------ // usage // sparse_mask M (16,16,1) ; a 16 by 16 mask. 1 is the level // // initially, everythins is set to zero // // to set the entry (5,6) to 1... // M[5].set(6,6); // // to set the entry (5,6), (5,7),...,(5,20) to 1 // M[5].set(6,20); // // to read the entry (5,6) // M[5][6]; //------------------------------------------------------ // // Note: (1) setting to zero is not supported. // (2) assignment // M[5][6] = 1; // is illegal. //------------------------------------------------------ //--------------------------------------------------- // M A S K T R E E //--------------------------------------------------- // just an array of sparse mask. // // for usage... check sparse_mask_test.c //--------------------------------------------------- //--------------------------------------------------- // I T E M //--------------------------------------------------- ostream& operator << ( ostream & os, item * it ) { item * next = it; int total= 0; if (next==0 ) cout << "EMPTY LIST "; while (next !=0 ) { cout << " item ( " << next -> start_from << "," << next -> end_at << ") "; next = next -> next; total ++; } cout << endl; cout << "total number of request is " << total << endl; return os; } //---------------------------------------------------- // L I N K E D _ L I S T //---------------------------------------------------- linked_list::~linked_list() { // cout << "deleting linked_list " << endl; item * curr = list; while (curr!=0) { item * prev = curr; curr = curr -> next; delete prev; } } int linked_list::nos_item () { item * curr = list; int count = 0; while (curr) { curr = curr -> next; count ++; } return (count); } void linked_list::insertItem ( int st, int en, item *prev ) { if (prev ==0 ) { item *ptr = new item ( st,en,list ); list = ptr; } else { item *ptr = new item ( st,en, prev->next); prev->next = ptr; } } void linked_list::set ( int st, int en ) { #ifdef BOUND_CHECK if ( (st< 0) || (en start_from > en. // update I_0 to ( ... , max(I_2.end_at, en ) ) //---------------------------------------------- // in order to merge two consecutive item // e.g (1,3) and (4,5) into (1,5) // we will treat (1,3) and (4,5) have non-empty // intersection //---------------------------------------------- //------------ S T E P ( 1 ) -------------- while ( curr ) { if ( ( curr->end_at >= (st-1)) && ( curr->start_from <= (en+1)) ) { break; } else if ( curr->start_from > en ) { curr = 0;} else { prev = curr; curr = curr->next; } } //------------ S T E P ( 2 ) -------------- // if prev ==0, then insert from the head //---------------------------------------------- if ( curr == 0 ) { insertItem (st,en,prev); } else { //------------ S T E P ( 3 ) -------------- item * I_0 = curr; int prev_value = curr -> end_at; int last_item_not_yet_reach = 1; curr = curr -> next; while ( (curr) && (last_item_not_yet_reach) ) { if ( curr -> start_from > (en+1) ) { last_item_not_yet_reach = 0; } else { item * dummytmp = curr -> next; prev_value = curr -> end_at; delete curr; curr = dummytmp; } } I_0->start_from = min ( I_0->start_from, st ); I_0->end_at = max ( prev_value , en ); I_0->next = curr; } } int linked_list::unset ( int st, int en ) { #ifdef BOUND_CHECK if ( (st< 0) || (en start_from > en. // update I_0 to ( ... , max(I_2.end_at, en ) ) //---------------------------------------------- // in order to merge two consecutive item // e.g (1,3) and (4,5) into (1,5) // we will treat (1,3) and (4,5) have non-empty // intersection //---------------------------------------------- //------------ S T E P ( 1 ) -------------- int count = 0; while (curr) { if ( ( curr->end_at >= (st-1)) && ( curr->start_from <= (en+1)) ) { break; } else if ( curr->start_from > en ) { curr = 0;} else { prev = curr; curr = curr->next; } } //------------ S T E P ( 2 ) -------------- // if prev ==0, then insert from the head //---------------------------------------------- if ( curr != 0 ) { //------------ S T E P ( 3 ) -------------- if (curr-> start_from < st) { count = curr -> end_at - st + 1; curr -> end_at = st - 1; prev = curr; curr = curr->next; } else { count = curr -> end_at - curr->start_from + 1; item *I_0 = curr; curr = curr-> next; delete I_0; } while (curr) { if (curr-> start_from > en+1) { break; } else if (curr -> end_at > en) { count += curr -> end_at - en; curr -> start_from = en + 1; break; } else { count += curr -> end_at - curr->start_from + 1; item *I_0 = curr; curr = curr->next; delete I_0; } } prev->next = curr; } return count; } //------------------------------------------------------- // output the list that is zero, and set everything to 1 //------------------------------------------------------- item * linked_list::set_disjoint ( int &total, int st, int en ) { #ifdef BOUND_CHECK if ( (st< 0) || (en start_from > en. // update I_0 to ( ... , max(I_2.end_at, en ) ) //---------------------------------------------- // in order to merge two consecutive item // e.g (1,3) and (4,5) into (1,5) // we will treat (1,3) and (4,5) have non-empty // intersection //---------------------------------------------- // output a list of item which are those // intervals orginally not set in the mask but // are subset of (st,en). //---------------------------------------------- // format of output // // return 0 if the output list is empty. // if non-zero, then it is a sorted linked list. // // that is... // (s1,e1) -- (s2,e2) -- (s3,e3) --.... // where s1end_at >= (st-1)) && ( curr->start_from <= (en+1)) ) { notfound =0; } else if ( curr->start_from > en ) { curr = 0;} else { prev = curr; curr = curr->next; } } //-------------------------------------------------- // total number of bytes in the interval. // we will substract the repetition as we scan along. //-------------------------------------------------- total = en - st + 1; //------------ S T E P ( 2 ) -------------- // if prev ==0, then insert from the head // output are just (st,en). //---------------------------------------------- if ( curr == 0 ) { insertItem (st,en,prev); req = new item ( st, en,0 ); } else { //------------ S T E P ( 3 ) -------------- // // rather complicated. // // curr_outputlist and outputlist are as the name suggest, // the output list. // prev_end_point is used to compose the output. // // I_0, prev, curr are used for the scaning and searching of the list //---------------------------------------------------- // refer to the previous routine ::set for // a much neat program. //---------------------------------------------------- item * I_0 = curr; if (I_0 -> start_from > st ) { //------------------------------------- // a p p e n d t o o u t p u t //------------------------------------- req = new item ( st, I_0->start_from-1, 0); curr_outputlist = req ; } int prev_end_point = I_0 -> end_at+1; int last_item_not_yet_reach = 1; curr = curr -> next; while ( (curr) && (last_item_not_yet_reach) ) { // cout << "LOOP " << curr << endl; if ( curr -> start_from > (en+1) ) { // cout << "GETTING OUT OF THE LOOP " << endl; last_item_not_yet_reach = 0; } else { // cout << "Create a new node " << endl; //------------------------------------------- // a p p e n d a n e w // i t e m t o o u t p u t //------------------------------------------- if (req == 0 ) { req = new item (prev_end_point, curr->start_from-1,0); curr_outputlist = req ; } else { curr_outputlist->next = new item (prev_end_point, curr->start_from-1,0); curr_outputlist = curr_outputlist -> next; } prev_end_point = (curr -> end_at) +1; // cout << "prev_end_point " << prev_end_point << endl; //------------------------------------------- item * dummytmp = curr->next; total -= (curr -> end_at - curr -> start_from + 1 ); // cout << " substract " // << (curr -> end_at - curr -> start_from + 1) <next = new item (prev_end_point, en,0); curr_outputlist = curr_outputlist -> next; } } // substract the very first item total -= ( I_0 -> end_at - I_0 -> start_from + 1); int tmp_start = I_0 ->start_from; I_0->start_from = min ( I_0->start_from, st ); I_0->end_at = max ( prev_end_point -1 , en ); I_0->next = curr; // adjust total... total = total + ( st - I_0 ->start_from ); total = total + ( I_0 -> end_at - en ); } // if (curr==0) else... return req; } item * linked_list::zeros ( int * total, int st, int en ) { // find the first interval that > st. (*total) = 0; item * curr = list; //---------- find first occurance -------------// while ( ( curr !=0 ) && (curr->end_at < st ) ) { curr = curr -> next; } if (curr==0) { (*total) = en - st + 1; item * tmp = new item ( st, en,0 ); return ( tmp ); } else if (curr->start_from > en ) { (*total) = en -st + 1; item * tmp = new item ( st, en,0 ); return ( tmp ); } else { item * output = new item (0,0,0); // act as dummy node item * curr_output = output; int prev_end = st; if (curr->start_from > st ) { curr_output -> next= new item (st, curr->start_from -1, 0 ); (*total) += curr->start_from - st; curr_output = curr_output-> next; } prev_end = curr -> end_at + 1; curr = curr -> next; while ( (curr!=0) && (curr->start_from <= en ) ) { curr_output->next = new item (prev_end, curr->start_from -1,0); (*total) += curr->start_from - prev_end; prev_end = curr -> end_at + 1; curr_output = curr_output-> next; curr = curr -> next; } if (prev_end <= en) { curr_output->next = new item (prev_end, en,0); (*total) += en - prev_end + 1; } item * tmp = output->next; output->next = 0; delete output; return ( tmp ); } } int linked_list::operator[] ( int index ) { int found =0; item *next = list; while ( (!found) && (next ) ) { if ( (index >= next->start_from)&& (index <= next->end_at )) {found =1; } else if (index < next->start_from ) {next = 0;} else {next = next -> next;} } return found; } // first first occurance of the intersection of start_col and end_col item * linked_list::first_occurance ( int start_col, int end_col) { item *curr = list; while ( curr ) { if (start_col <= curr->end_at ) { if (end_col >= curr->start_from) { break; } else { curr = 0;} } else { curr = curr -> next; } } return curr; } //------------------------------------------------------- // S P A R S E _ M A S K //------------------------------------------------------- // just an array of linked list //------------------------------------------------------- sparse_mask::sparse_mask () { nos_row = 0; nos_col = 0; table = 0; } sparse_mask::sparse_mask (int width, int height ) { nos_row = height; nos_col = width; table = new linked_list * [ nos_row ]; for (int i = 0; i< nos_row; i++) { table[i] = new linked_list(); } } int sparse_mask::unset(int st_row, int st_col, int en_row, int en_col) { int count = 0; for (int i = st_row; i< en_row; i ++) count += table[i]->unset(st_col, en_col); return count; } sparse_mask::~sparse_mask() { for (int i=0; i< nos_row; i++) { delete table[i]; } delete [] table; } //--------------------------------------------------- // M A S K T R E E //--------------------------------------------------- // just an array of sparse mask. //--------------------------------------------------- mask_tree::mask_tree ( int level, int width, int height ) { reInit ( level, width, height); } void mask_tree::reInit (int level, int width, int height ) { nos_level = level; mask_list = new sparse_mask* [nos_level]; int h = height; int w = width; if (h%2) h++; if (w%2) w++; for (int i =0; i< level; i++ ) { h= h/2; w= w/2; mask_list [i] = new sparse_mask (w,h); if (h%2) h++; if (w%2) w++; } } mask_tree::~mask_tree () { for (int i =0; i< nos_level; i++) { delete mask_list[i]; } delete [] mask_list; }