Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:13

0001 // name=insertionSortIndirect ; gcc $name.cc -std=c++11 -lstdc++ -I$OPTICKS_PREFIX/include/SysRap -o /tmp/$name && /tmp/$name
0002 
0003 /**
0004 Exploring How To Sort CSG Leaf nodes into intersect Enter order for n-ary intersection
0005 ------------------------------------------------------------------------------------------
0006 
0007 Problem characteristics
0008 ~~~~~~~~~~~~~~~~~~~~~~~~~
0009 
0010 * typically small number of leaf Enter for each ray, ie 1,2,3,4,5 
0011   (depending on layout of solid constituents)
0012 
0013 * t_enter array will often be mostly sorted (or reversed) initially as leaf sub-ordering 
0014   usually follows geometrical positioning. Reversed as rays come from anywhere in any direction.
0015 
0016 * dont actually want to sort an array of t_enter, want to sort the CSGNode* pointers of the leaves
0017   based on their intersect distances and do not want to keep repeating the intersects : 
0018   so collect array of t_enter and and indices array and do indirect sort  (like np.argsort)
0019 
0020 * only a subset of all subs have Enter for each ray : requires mapping from enter index
0021   back to sub index OR planting a large token value  for non-Enter and doing some sweeping 
0022   before sorting
0023 
0024 * currently using insertion sort small size probably means hard coded 
0025   sorting networks for : 1,2,3,4,5,6,7,8  would be better
0026 
0027   * BUT : needs to be indirect, and need mapping back to isub 
0028 
0029 
0030 Available sort techniques
0031 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0032 
0033 https://en.wikipedia.org/wiki/Selection_sort
0034 
0035 https://en.wikipedia.org/wiki/Sorting_network
0036 
0037 https://en.wikipedia.org/wiki/Bitonic_sorter
0038 
0039 https://www.tools-of-computing.com/tc/CS/Sorts/bitonic_sort.htm
0040 
0041 https://stackoverflow.com/questions/32172144/fastest-way-to-sort-10-numbers-numbers-are-32-bit
0042 
0043 https://www.toptal.com/developers/sorting-algorithms
0044 
0045 .. selection sort is greatly outperformed on larger arrays by divide-and-conquer algorithms such as mergesort. 
0046 However, insertion sort or selection sort are both typically faster for small arrays (i.e. fewer than 10–20 elements). 
0047 A useful optimization in practice for the recursive algorithms is to switch to insertion sort or selection sort 
0048 for "small enough" sublists.
0049 
0050 
0051 Insertion Sort Algorithm 
0052 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0053 
0054 To sort an array of size n in ascending order: 
0055 
0056 1. Iterate from arr[1] to arr[n] over the array. 
0057 2. Compare the current element (key) to its predecessor. 
0058 3. If the key element is smaller than its predecessor, compare it to the
0059    elements before. Move the greater elements one position up to make space for
0060    the swapped element.
0061 
0062 **/
0063 
0064 #include "NPX.h"
0065 #include <iomanip>
0066 
0067 
0068 void insertionSort(float* enter, int n)
0069 {
0070     /* Move elements of arr[0..i-1], that are
0071        greater than key, to one position ahead
0072        of their current position */
0073 
0074     int i, j;
0075 
0076     for (i = 1; i < n; i++) 
0077     {
0078         float key = enter[i];   // move key thru the array 
0079         j = i - 1;
0080 
0081         // j is less than i, so want the enter[j] values to be less than key
0082         while (j >= 0 && enter[j] > key) 
0083         {
0084             enter[j + 1] = enter[j];
0085             j = j - 1;    // keep decrementing j down to zero 
0086         }
0087         enter[j + 1] = key;
0088     }
0089 }
0090 
0091 void insertionSortIndirect_0( int* idx, const float* enter, int count, int* aux )
0092 {
0093     int i, j ; 
0094 
0095     for (i = 1; i < count ; i++) 
0096     {  
0097         int key = idx[i] ;    
0098         j = i - 1 ;   
0099 
0100         // descending j below i whilst find out of order  
0101         while( j >= 0 && enter[idx[j]] > enter[key] )     // need to use the idx here otherwise not seeing the shuffle
0102         {
0103             idx[j+1] = idx[j] ;  
0104 
0105             // sliding values that are greater than the key one upwards
0106             // no need to "swap" as are holding the key out of the pack
0107             // ready to place it into the slot opened by the slide up   
0108 
0109             j = j - 1; 
0110         }   
0111 
0112         idx[j+1] = key ; 
0113 
0114         // if values below i are already ascending, then this 
0115         // puts the key back in the pack at the same place it came from  
0116     }   
0117 }
0118 
0119 void insertionSortIndirect_1( int* idx, const float* enter, int count, int* aux )
0120 {
0121     int i, j ; 
0122 
0123     for (i = 1; i < count ; i++) 
0124     {  
0125         int key = idx[i] ;    
0126         int akey = aux ? aux[i] : -1  ; 
0127 
0128         j = i - 1 ;   
0129 
0130         // descending j below i whilst find out of order  
0131         while( j >= 0 && enter[idx[j]] > enter[key] )     // need to use the idx here otherwise not seeing the shuffle
0132         {
0133             idx[j+1] = idx[j] ;  
0134 
0135             if(aux) aux[j+1] = aux[j] ; 
0136 
0137             // sliding values that are greater than the key one upwards
0138             // no need to "swap" as are holding the key out of the pack
0139             // ready to place it into the slot opened by the slide up   
0140 
0141             j = j - 1; 
0142         }   
0143 
0144         idx[j+1] = key ; 
0145         if(aux) aux[j+1] = akey ; 
0146 
0147         // if values below i are already ascending, then this 
0148         // puts the key back in the pack at the same place it came from  
0149     }   
0150 }
0151 
0152 
0153 
0154 void insertionSortIndirect_1_WRONG( int* idx, const float* enter, int count )
0155 {
0156     int i, j ; 
0157 
0158     for (i = 1; i < count ; i++) 
0159     {  
0160         int key = idx[i] ;    
0161         j = i - 1 ;   
0162 
0163         // descending j below i whilst find out of order  
0164         while( j >= 0 && enter[j] > enter[i] )     // <--- WRONG : NEEDS TO BE enter[idx[j]] > enter[key] TO FEEL THE SHUFFLE
0165         {
0166             idx[j+1] = idx[j] ;  
0167 
0168             // sliding values that are greater than the key one upwards
0169             // no need to "swap" as are holding the key out of the pack
0170             // ready to place it into the slot opened by the slide up   
0171 
0172             j = j - 1; 
0173         }   
0174 
0175         idx[j+1] = key ; 
0176 
0177         // if values below i are already ascending, then this 
0178         // puts the key back in the pack at the same place it came from  
0179     }   
0180 }
0181 
0182 /**
0183 THIS IS CORRECT BUT UNCLEAR COMPARED TO OTHER IMPS : MAYBE IT DOES MORE SHUFFLES WITH THE SWAPPING ?
0184 **/
0185 
0186 void insertionSortIndirect_2( int* idx, const float* enter, int count, int* aux )
0187 {
0188     for (int i = 1; i < count ; i++)
0189     {
0190         for (int j = i; j > 0 && enter[idx[j]] < enter[idx[j-1]] ; j-- )
0191         {
0192             int swap = idx[j] ; 
0193             idx[j] = idx[j-1] ; 
0194             idx[j-1] = swap ; 
0195 
0196             if(aux)
0197             {
0198                 int a_swap = aux[j] ; 
0199                 aux[j] = aux[j-1] ; 
0200                 aux[j-1] = a_swap ; 
0201             }
0202         }
0203     }
0204 }
0205 
0206 
0207 
0208 void insertionSortIndirect( int* idx, const float* enter, int count, int* aux, int imp )
0209 {
0210     switch(imp)
0211     {
0212        case 0: insertionSortIndirect_0(idx, enter, count, aux);  break ; 
0213        case 1: insertionSortIndirect_1(idx, enter, count, aux);  break ; 
0214        case 2: insertionSortIndirect_2(idx, enter, count, aux);  break ; 
0215     }
0216 }
0217 
0218 
0219 unsigned compare( const int* idx0, const int* idx1, unsigned count )
0220 {
0221     unsigned mm = 0 ; 
0222     for(int i=0 ; i < count ; i++)
0223     {
0224        int i0 = idx0[i] ; 
0225        int i1 = idx1[i] ; 
0226        std::cout 
0227            << " i0 " << std::setw(5) << i0 
0228            << " i1 " << std::setw(5) << i1
0229            << " mm " << std::setw(5) << mm
0230            << std::endl
0231            ;
0232 
0233        if(i0 != i1) mm +=1 ; 
0234     }
0235     return mm ; 
0236 }
0237 
0238 
0239 // TODO: mock the isub subsetting 
0240 // to make a fuller test of CSG/csg_intersect_node.h
0241 
0242 
0243 
0244 void test_insertionSortIndirect(const NP* e, int imp, const char* fold)
0245 {
0246     const float* enter = e->cvalues<float>(); 
0247     int enter_count = e->shape[0]; 
0248 
0249     NP* i = NP::Make<int>(enter_count);
0250     i->fillIndexFlat();  
0251     int* idx = i->values<int>(); 
0252     int* aux = nullptr ; 
0253 
0254     insertionSortIndirect(idx, enter, enter_count, aux, imp ); 
0255 
0256     std::string name = U::FormName("i", imp, ".npy");     
0257     std::cout << "insertionSortIndirect saving to " << fold << "/" << name  << std::endl ; 
0258     i->save(fold, name.c_str() );  
0259 }
0260 
0261 
0262 void test_insertionSortIndirect(const char* fold)
0263 {
0264     NP* e = NP::Load(fold, "e.npy"); 
0265 
0266     test_insertionSortIndirect(e, 0, fold);
0267     test_insertionSortIndirect(e, 1, fold);
0268     test_insertionSortIndirect(e, 2, fold);     
0269 }
0270 
0271 
0272 
0273 void dump( const int* idx, const float* enter, int count, const int* aux, const char* msg, const int* aux0 )
0274 {
0275     int w = 30 ; 
0276     int v = 7 ; 
0277 
0278     std::cout << msg << " count " << count << std::endl ; 
0279     std::cout << std::setw(w) << " idx[i] "  ; 
0280     for(int i=0 ; i < count ; i++) std::cout << std::setw(v) << idx[i] << " " ; 
0281     std::cout << std::endl ; 
0282 
0283     if(aux)
0284     {
0285         std::cout << std::setw(w) << " aux[i] "  ; 
0286         for(int i=0 ; i < count ; i++) std::cout << std::setw(v) << aux[i] << " " ; 
0287         std::cout << std::endl ; 
0288     }
0289     if(aux0)
0290     {
0291         std::cout << std::setw(w) << " aux0[i] "  ; 
0292         for(int i=0 ; i < count ; i++) std::cout << std::setw(v) << aux0[i] << " " ; 
0293         std::cout << " (original aux0, unshuffled by sorting, maps enter index to value index ) " << std::endl ; 
0294 
0295 
0296         std::cout << std::setw(w) <<  " aux0[idx[i]] " ; 
0297         for(int i=0 ; i < count ; i++) std::cout << std::setw(v) << aux0[idx[i]] << " " ; 
0298         std::cout << " using shuffled idx order to get original value index in sort order " << std::endl ; 
0299     }
0300 
0301 
0302     std::cout <<  std::setw(w) << " enter[i] " ; 
0303     for(int i=0 ; i < count ; i++) std::cout << std::setw(v) << enter[i] << " " ; 
0304     std::cout << " (untouched by sorting) " << std::endl ; 
0305 
0306     std::cout << std::setw(w) <<  " enter[idx[i]] " ; 
0307     for(int i=0 ; i < count ; i++) std::cout << std::setw(v) << enter[idx[i]] << " " ; 
0308     std::cout << " using shuffled idx to get sorted enters " << std::endl ; 
0309 
0310 
0311 
0312 
0313 
0314 
0315 }
0316 
0317 
0318 void test_small()
0319 {
0320     NP* e = NPX::FromString<float>("10 110 -20 120 30 130 -10"); 
0321     float* enter = e->values<float>(); 
0322     int enter_count = e->shape[0]; 
0323 
0324     NP* i = NP::Make<int>(enter_count);
0325     i->fillIndexFlat();  
0326     int* idx = i->values<int>(); 
0327 
0328     int* aux = nullptr ; 
0329     int* aux0 = nullptr ; 
0330 
0331     dump(idx, enter, enter_count, aux, "before sort", aux0 ); 
0332 
0333     //insertionSort( enter, enter_count ); 
0334 
0335     int imp = 0 ; 
0336     insertionSortIndirect(idx, enter, enter_count, aux, imp ); 
0337 
0338     dump(idx, enter, enter_count, aux, "after sort", aux0 ); 
0339 }
0340 
0341 
0342 
0343 
0344 NP* make_idx(int n)
0345 {
0346     NP* i = NP::Make<int>(n);
0347     i->fillIndexFlat();  
0348     //int* idx = i->values<int>(); 
0349     return i ; 
0350 } 
0351 
0352 
0353 
0354 void test_small_isub()
0355 {
0356     NP* v = NPX::FromString<float>("-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 10 110 20 120 30 130 43"); 
0357     float* vals = v->values<float>(); 
0358     int  vals_count = v->shape[0]; 
0359 
0360     
0361     float enter[32] ; 
0362     int   aux0[32] ;
0363     int   aux[32] ;
0364     int   idx[32] ;
0365     int enter_count = 0 ; 
0366 
0367     for(int i=0 ; i < vals_count ; i++)
0368     {
0369         float v = vals[i] ; 
0370         if( v > 0.f)
0371         {  
0372             enter[enter_count] = v ; 
0373             aux0[enter_count] = i ; // maps from enter index to original value index             
0374             aux[enter_count] = i ;  // ATTEMPTING 2 LEVELS OF INDIRECTION : NOT GOING TO WORK WITH SORT  
0375             idx[enter_count] = enter_count ;   
0376             // ONE LEVEL INDIRECT IS OK
0377             enter_count += 1 ; 
0378             assert( enter_count < 32 ); 
0379         }
0380     }
0381 
0382     
0383    /*
0384     NP* e = NP::Make<float>(enter_count);
0385     e->read2(&enter[0]) ; 
0386 
0387     NP* i = NP::Make<int>(enter_count);
0388     i->read2(&[0]) ; 
0389 
0390    */
0391 
0392     int imp = 1 ; 
0393 
0394     dump(idx, enter, enter_count, aux, "before sort", aux0 ); 
0395 
0396     insertionSortIndirect(idx, enter, enter_count, aux, imp ); 
0397 
0398     dump(idx, enter, enter_count, aux, "after sort", aux0  ); 
0399 
0400 
0401 
0402 }
0403 
0404 
0405 
0406 
0407 int main(int argc, char** argv)
0408 {
0409     test_insertionSortIndirect("/tmp"); 
0410     //test_small();  
0411     //test_small_isub();  
0412 
0413     return 0 ; 
0414 }