nysol-zdd 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/ext/zdd_so/BDD.cc +495 -0
 - data/ext/zdd_so/BDD.h +356 -0
 - data/ext/zdd_so/BDDDG.cc +1818 -0
 - data/ext/zdd_so/BDDDG.h +107 -0
 - data/ext/zdd_so/BDDHASH.cc +91 -0
 - data/ext/zdd_so/BtoI.cc +503 -0
 - data/ext/zdd_so/BtoI.h +144 -0
 - data/ext/zdd_so/CtoI.cc +1072 -0
 - data/ext/zdd_so/CtoI.h +186 -0
 - data/ext/zdd_so/MLZBDDV.cc +153 -0
 - data/ext/zdd_so/MLZBDDV.h +42 -0
 - data/ext/zdd_so/SOP.cc +608 -0
 - data/ext/zdd_so/SOP.h +199 -0
 - data/ext/zdd_so/ZBDD.cc +1035 -0
 - data/ext/zdd_so/ZBDD.h +243 -0
 - data/ext/zdd_so/ZBDDDG.cc +1834 -0
 - data/ext/zdd_so/ZBDDDG.h +105 -0
 - data/ext/zdd_so/ZBDDHASH.cc +91 -0
 - data/ext/zdd_so/bddc.c +2816 -0
 - data/ext/zdd_so/bddc.h +132 -0
 - data/ext/zdd_so/extconf.rb +25 -0
 - data/ext/zdd_so/include/aheap.c +211 -0
 - data/ext/zdd_so/include/aheap.h +111 -0
 - data/ext/zdd_so/include/base.c +93 -0
 - data/ext/zdd_so/include/base.h +60 -0
 - data/ext/zdd_so/include/itemset.c +473 -0
 - data/ext/zdd_so/include/itemset.h +153 -0
 - data/ext/zdd_so/include/problem.c +371 -0
 - data/ext/zdd_so/include/problem.h +160 -0
 - data/ext/zdd_so/include/queue.c +518 -0
 - data/ext/zdd_so/include/queue.h +177 -0
 - data/ext/zdd_so/include/sgraph.c +331 -0
 - data/ext/zdd_so/include/sgraph.h +170 -0
 - data/ext/zdd_so/include/stdlib2.c +832 -0
 - data/ext/zdd_so/include/stdlib2.h +746 -0
 - data/ext/zdd_so/include/trsact.c +723 -0
 - data/ext/zdd_so/include/trsact.h +167 -0
 - data/ext/zdd_so/include/vec.c +583 -0
 - data/ext/zdd_so/include/vec.h +159 -0
 - data/ext/zdd_so/lcm-vsop.cc +596 -0
 - data/ext/zdd_so/print.cc +683 -0
 - data/ext/zdd_so/table.cc +330 -0
 - data/ext/zdd_so/vsop.h +88 -0
 - data/ext/zdd_so/zdd_so.cpp +3277 -0
 - data/lib/nysol/zdd.rb +31 -0
 - metadata +131 -0
 
| 
         @@ -0,0 +1,160 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*  Common problem input/output routines /structure
         
     | 
| 
      
 2 
     | 
    
         
            +
                        25/Nov/2007   by Takeaki Uno  e-mail:uno@nii.jp, 
         
     | 
| 
      
 3 
     | 
    
         
            +
                homepage:   http://research.nii.ac.jp/~uno/index.html  */
         
     | 
| 
      
 4 
     | 
    
         
            +
            /* This program is available for only academic use, basically.
         
     | 
| 
      
 5 
     | 
    
         
            +
               Anyone can modify this program, but he/she has to write down 
         
     | 
| 
      
 6 
     | 
    
         
            +
                the change of the modification on the top of the source code.
         
     | 
| 
      
 7 
     | 
    
         
            +
               Neither contact nor appointment to Takeaki Uno is needed.
         
     | 
| 
      
 8 
     | 
    
         
            +
               If one wants to re-distribute this code, do not forget to 
         
     | 
| 
      
 9 
     | 
    
         
            +
                refer the newest code, and show the link to homepage of 
         
     | 
| 
      
 10 
     | 
    
         
            +
                Takeaki Uno, to notify the news about the codes for the users.
         
     | 
| 
      
 11 
     | 
    
         
            +
               For the commercial use, please make a contact to Takeaki Uno. */
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            /***************************************************/
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            #ifndef _problem_h_
         
     | 
| 
      
 16 
     | 
    
         
            +
            #define _problem_h_
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            #include"stdlib2.h"
         
     | 
| 
      
 19 
     | 
    
         
            +
            #include"queue.h"
         
     | 
| 
      
 20 
     | 
    
         
            +
            #include"itemset.h"
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            #define PROBLEM_FREQSET 1
         
     | 
| 
      
 23 
     | 
    
         
            +
            #define PROBLEM_MAXIMAL 2
         
     | 
| 
      
 24 
     | 
    
         
            +
            #define PROBLEM_CLOSED 4
         
     | 
| 
      
 25 
     | 
    
         
            +
            #define PROBLEM_EX_MAXIMAL 8
         
     | 
| 
      
 26 
     | 
    
         
            +
            #define PROBLEM_EX_CLOSED 16
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            /*****  parameters for PROBLEM initialization, given to flag  *****/
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            #define PROBLEM_PRINT_DENSE 4  // print density threshold
         
     | 
| 
      
 31 
     | 
    
         
            +
            #define PROBLEM_PRINT_SHRINK 8  // print properties of shrinked database
         
     | 
| 
      
 32 
     | 
    
         
            +
            #define PROBLEM_PRINT_FRQ   16  // print density threshold
         
     | 
| 
      
 33 
     | 
    
         
            +
            #define PROBLEM_NORMALIZE   32  // print density threshold
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            #define PROBLEM_ITEMARY 128 // alloc itemary
         
     | 
| 
      
 36 
     | 
    
         
            +
            #define PROBLEM_ITEMJUMP 256 // alloc itemjump
         
     | 
| 
      
 37 
     | 
    
         
            +
            #define PROBLEM_ITEMFLAG 512  // alloc itemflag
         
     | 
| 
      
 38 
     | 
    
         
            +
            #define PROBLEM_ITEMMARK 1024  // alloc itemmark
         
     | 
| 
      
 39 
     | 
    
         
            +
            #define PROBLEM_ITEMCAND 2048 // alloc itemcand
         
     | 
| 
      
 40 
     | 
    
         
            +
            #define PROBLEM_VECARY 4096 // alloc itemary
         
     | 
| 
      
 41 
     | 
    
         
            +
            #define PROBLEM_VECJUMP 8192 // alloc vecjump
         
     | 
| 
      
 42 
     | 
    
         
            +
            #define PROBLEM_VECFLAG 16384  // alloc vecflag
         
     | 
| 
      
 43 
     | 
    
         
            +
            #define PROBLEM_VECMARK 32768  // alloc vecmark
         
     | 
| 
      
 44 
     | 
    
         
            +
            #define PROBLEM_VECCAND 65536 // alloc veccand
         
     | 
| 
      
 45 
     | 
    
         
            +
            //4194304
         
     | 
| 
      
 46 
     | 
    
         
            +
            #define PROBLEM_OCC_T 524288 // alloc occ_t
         
     | 
| 
      
 47 
     | 
    
         
            +
            #define PROBLEM_SHIFT 1048576  // allocate shift
         
     | 
| 
      
 48 
     | 
    
         
            +
            #define PROBLEM_OCC_W 2097152  // weight/positive-weight sum for items
         
     | 
| 
      
 49 
     | 
    
         
            +
            #define PROBLEM_OCC_PW 4194304  // weight/positive-weight sum for items
         
     | 
| 
      
 50 
     | 
    
         
            +
            #define PROBLEM_OCC_W2 8388608  // weight/positive-weight sum for items
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            #define PROBLEM_OCC1 16 // alloc occ
         
     | 
| 
      
 53 
     | 
    
         
            +
            #define PROBLEM_OCC2 32 // alloc occ and ins all to list 0
         
     | 
| 
      
 54 
     | 
    
         
            +
            #define PROBLEM_OCC3 48 // alloc occ and ins all to list "siz"
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            typedef struct {
         
     | 
| 
      
 57 
     | 
    
         
            +
              clock_t start_time, end_time;
         
     | 
| 
      
 58 
     | 
    
         
            +
              int problem;
         
     | 
| 
      
 59 
     | 
    
         
            +
              LONG prog;
         
     | 
| 
      
 60 
     | 
    
         
            +
              int prog2;
         
     | 
| 
      
 61 
     | 
    
         
            +
              double dense;
         
     | 
| 
      
 62 
     | 
    
         
            +
              char *input_fname;
         
     | 
| 
      
 63 
     | 
    
         
            +
              char *output_fname;
         
     | 
| 
      
 64 
     | 
    
         
            +
              char *weight_fname;
         
     | 
| 
      
 65 
     | 
    
         
            +
              char *table_fname, *table2_fname;
         
     | 
| 
      
 66 
     | 
    
         
            +
              char *position_fname, *position2_fname;
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              char *sgraph_fname, *sgraph2_fname;
         
     | 
| 
      
 69 
     | 
    
         
            +
              char *sgraph_wfname, *sgraph2_wfname;
         
     | 
| 
      
 70 
     | 
    
         
            +
              char *agraph_fname, *agraph2_fname;
         
     | 
| 
      
 71 
     | 
    
         
            +
              char *trsact_fname, *trsact_fname2, *trsact_wfname, *trsact_wfname2, *trsact_pfname;
         
     | 
| 
      
 72 
     | 
    
         
            +
              char *trsact2_fname, *trsact2_fname2, *trsact2_wfname, *trsact2_wfname2, *trsact2_pfname;
         
     | 
| 
      
 73 
     | 
    
         
            +
              char *seq_fname, *seq2_fname;
         
     | 
| 
      
 74 
     | 
    
         
            +
              char *fstar_fname, *fstar2_fname;
         
     | 
| 
      
 75 
     | 
    
         
            +
              char *mat_fname, *mat2_fname;
         
     | 
| 
      
 76 
     | 
    
         
            +
              char *smat_fname, *smat2_fname;
         
     | 
| 
      
 77 
     | 
    
         
            +
              char *setfamily_fname, *setfamily2_fname;
         
     | 
| 
      
 78 
     | 
    
         
            +
              char *setfamily_wfname, *setfamily2_wfname;
         
     | 
| 
      
 79 
     | 
    
         
            +
              
         
     | 
| 
      
 80 
     | 
    
         
            +
              ITEMSET II, II2;
         
     | 
| 
      
 81 
     | 
    
         
            +
              QUEUE ff;      // for agraph search
         
     | 
| 
      
 82 
     | 
    
         
            +
              int *vf, *dep; // for agraph search
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              int root, dir, edge_dir;
         
     | 
| 
      
 85 
     | 
    
         
            +
              double th, th2, th3;   // thresholds
         
     | 
| 
      
 86 
     | 
    
         
            +
              double ratio, ratio2;  // ratio
         
     | 
| 
      
 87 
     | 
    
         
            +
              int num, siz, dim, len;
         
     | 
| 
      
 88 
     | 
    
         
            +
              QUEUE_INT clms;
         
     | 
| 
      
 89 
     | 
    
         
            +
              VEC_ID rows;
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              QUEUE_ID **shift;
         
     | 
| 
      
 92 
     | 
    
         
            +
              QUEUE itemjump, itemcand, vecjump, veccand, *OQ, *OQ2, *VQ, *VQ2;   // for delivery
         
     | 
| 
      
 93 
     | 
    
         
            +
              QUEUE_INT *itemary;
         
     | 
| 
      
 94 
     | 
    
         
            +
              int *itemmark, *itemflag, *vecmark, *vecflag;  // mark for vector
         
     | 
| 
      
 95 
     | 
    
         
            +
              VEC_ID *vecary, *occ_t;
         
     | 
| 
      
 96 
     | 
    
         
            +
              WEIGHT *occ_w, *occ_pw, *occ_w2, *occ_pw2;
         
     | 
| 
      
 97 
     | 
    
         
            +
              QUEUE oo;
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
              char *pat;   // pattern string
         
     | 
| 
      
 100 
     | 
    
         
            +
              int plen, perr;  // pattern length and #error allowed
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
            #ifdef _alist_h_
         
     | 
| 
      
 103 
     | 
    
         
            +
              MALIST occ;
         
     | 
| 
      
 104 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            #ifdef _sgraph_h_
         
     | 
| 
      
 107 
     | 
    
         
            +
              SGRAPH SG, SG2;
         
     | 
| 
      
 108 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            #ifdef _agraph_h_
         
     | 
| 
      
 111 
     | 
    
         
            +
              AGRAPH AG, AG2;
         
     | 
| 
      
 112 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            #ifdef _trsact_h_
         
     | 
| 
      
 115 
     | 
    
         
            +
              TRSACT TT, TT2;
         
     | 
| 
      
 116 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            #ifdef _seq_h_
         
     | 
| 
      
 119 
     | 
    
         
            +
              SEQ SS, SS2;
         
     | 
| 
      
 120 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
            #ifdef _fstar_h_
         
     | 
| 
      
 123 
     | 
    
         
            +
              FSTAR FS, FS2;
         
     | 
| 
      
 124 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            #ifdef _vec_h_
         
     | 
| 
      
 127 
     | 
    
         
            +
              MAT MM, MM2;
         
     | 
| 
      
 128 
     | 
    
         
            +
              SMAT SM, SM2;
         
     | 
| 
      
 129 
     | 
    
         
            +
              SETFAMILY FF, FF2;
         
     | 
| 
      
 130 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
            } PROBLEM;
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
            /*****  print filename information  ****/
         
     | 
| 
      
 136 
     | 
    
         
            +
            void PROBLEM_print (PROBLEM *P);
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            /*****  print usage of the program *****/
         
     | 
| 
      
 139 
     | 
    
         
            +
            void PROBLEM_error ();
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            /*****  read parameters given by command line  *****/
         
     | 
| 
      
 142 
     | 
    
         
            +
            void PROBLEM_read_param (int argc, char *argv[], PROBLEM *P);
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
            /*****  PROBLEM and ITEMSET initialization *****/
         
     | 
| 
      
 145 
     | 
    
         
            +
            /* all pointers are set to NULL, but don't touch filenames */
         
     | 
| 
      
 146 
     | 
    
         
            +
            void PROBLEM_init (PROBLEM *P);
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
            /*****  PROBLEM initialization: load the files given by filenames   ******/
         
     | 
| 
      
 149 
     | 
    
         
            +
            void PROBLEM_init2 (PROBLEM *P, int flag);
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
            /*****  allocate memory according to flag  *****/
         
     | 
| 
      
 152 
     | 
    
         
            +
            void PROBLEM_alloc (PROBLEM *PP, QUEUE_ID siz, QUEUE_ID siz2, size_t siz3, PERM *p, int f);
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
            /* termination of problem */
         
     | 
| 
      
 155 
     | 
    
         
            +
            void PROBLEM_end (PROBLEM *PP);
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,518 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /* Library of queue: spped priority implementation 
         
     | 
| 
      
 2 
     | 
    
         
            +
                        12/Apr/2001   by Takeaki Uno  e-mail:uno@nii.jp, 
         
     | 
| 
      
 3 
     | 
    
         
            +
                homepage:   http://research.nii.ac.jp/~uno/index.html  */
         
     | 
| 
      
 4 
     | 
    
         
            +
            /* This program is available for only academic use, basically.
         
     | 
| 
      
 5 
     | 
    
         
            +
               Anyone can modify this program, but he/she has to write down 
         
     | 
| 
      
 6 
     | 
    
         
            +
                the change of the modification on the top of the source code.
         
     | 
| 
      
 7 
     | 
    
         
            +
               Neither contact nor appointment to Takeaki Uno is needed.
         
     | 
| 
      
 8 
     | 
    
         
            +
               If one wants to re-distribute this code, do not forget to 
         
     | 
| 
      
 9 
     | 
    
         
            +
                refer the newest code, and show the link to homepage of 
         
     | 
| 
      
 10 
     | 
    
         
            +
                Takeaki Uno, to notify the news about the codes for the users.
         
     | 
| 
      
 11 
     | 
    
         
            +
               For the commercial use, please make a contact to Takeaki Uno. */
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            #ifndef _queue_c_
         
     | 
| 
      
 14 
     | 
    
         
            +
            #define _queue_c_
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            #include"queue.h"
         
     | 
| 
      
 18 
     | 
    
         
            +
            #include"stdlib2.c"
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            QSORT_TYPE(QUEUE_INT, QUEUE_INT)
         
     | 
| 
      
 21 
     | 
    
         
            +
            QSORT_TYPE(QUEUE_ID, QUEUE_ID)
         
     | 
| 
      
 22 
     | 
    
         
            +
            QUEUE INIT_QUEUE = {TYPE_QUEUE,NULL,0,0,0};
         
     | 
| 
      
 23 
     | 
    
         
            +
            QUEUE_INT *common_QUEUE_INTp;
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            /* initialization, not fill the memory by 0 */
         
     | 
| 
      
 26 
     | 
    
         
            +
            void QUEUE_alloc (QUEUE *Q, QUEUE_ID siz){
         
     | 
| 
      
 27 
     | 
    
         
            +
              *Q = INIT_QUEUE;
         
     | 
| 
      
 28 
     | 
    
         
            +
              Q->end = siz+1;
         
     | 
| 
      
 29 
     | 
    
         
            +
              malloc2 (Q->v, siz+1, "QUEUE_alloc: Q->v", EXIT);
         
     | 
| 
      
 30 
     | 
    
         
            +
            }
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            /* termination processing */
         
     | 
| 
      
 33 
     | 
    
         
            +
            void QUEUE_end (QUEUE *Q){
         
     | 
| 
      
 34 
     | 
    
         
            +
              free2 (Q->v);
         
     | 
| 
      
 35 
     | 
    
         
            +
              *Q = INIT_QUEUE;
         
     | 
| 
      
 36 
     | 
    
         
            +
            }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            /* tranpose the matrix ; counting/transpose/memory_allocate */
         
     | 
| 
      
 40 
     | 
    
         
            +
            void QUEUE_delivery(QUEUE *OQ, VEC_ID *c, QUEUE *jump, QUEUE *Q, QUEUE *occ, VEC_ID t, QUEUE_INT M){  VEC_ID i, e;
         
     | 
| 
      
 41 
     | 
    
         
            +
              QUEUE_INT *x;
         
     | 
| 
      
 42 
     | 
    
         
            +
              FLOOP(i, 0, occ? occ->t: t){
         
     | 
| 
      
 43 
     | 
    
         
            +
                e = occ? occ->v[i]: i;
         
     | 
| 
      
 44 
     | 
    
         
            +
                if ( c ){
         
     | 
| 
      
 45 
     | 
    
         
            +
                  if ( jump ){ MLOOP (x, Q[e].v, M){ if ( c[*x]==0 ) ARY_INS (*jump, *x); c[*x]++; }
         
     | 
| 
      
 46 
     | 
    
         
            +
                  } else { MLOOP (x, Q[e].v, M){ c[*x]++; }}
         
     | 
| 
      
 47 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 48 
     | 
    
         
            +
                  if ( jump ){ MLOOP (x, Q[e].v, M){ if ( OQ[*x].t==0 ) ARY_INS (*jump, *x); ARY_INS (OQ[*x], e); }
         
     | 
| 
      
 49 
     | 
    
         
            +
                  } else MLOOP (x, Q[e].v, M){ ARY_INS (OQ[*x], e); }
         
     | 
| 
      
 50 
     | 
    
         
            +
                }
         
     | 
| 
      
 51 
     | 
    
         
            +
              }
         
     | 
| 
      
 52 
     | 
    
         
            +
            }
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            /* sort a QUEUE with WEIGHT, with already allocated memory */
         
     | 
| 
      
 55 
     | 
    
         
            +
            void QUEUE_perm_WEIGHT (QUEUE *Q, WEIGHT *w, PERM *invperm, int flag){
         
     | 
| 
      
 56 
     | 
    
         
            +
              WEIGHT y;
         
     | 
| 
      
 57 
     | 
    
         
            +
              if ( w ){
         
     | 
| 
      
 58 
     | 
    
         
            +
                qsort_perm__QUEUE_INT (Q->v, Q->t, invperm, flag);
         
     | 
| 
      
 59 
     | 
    
         
            +
                ARY_INVPERMUTE_ (w, invperm, y, Q->t);
         
     | 
| 
      
 60 
     | 
    
         
            +
              }
         
     | 
| 
      
 61 
     | 
    
         
            +
              qsort_QUEUE_INT (Q->v, Q->t, flag);
         
     | 
| 
      
 62 
     | 
    
         
            +
            }
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            /* remove (or unify) the consecutive same ID's in a QUEUE (duplication delete, if sorted) */
         
     | 
| 
      
 65 
     | 
    
         
            +
            void QUEUE_rm_dup_WEIGHT (QUEUE *Q, WEIGHT *w){
         
     | 
| 
      
 66 
     | 
    
         
            +
              VEC_ID j, jj=0;
         
     | 
| 
      
 67 
     | 
    
         
            +
              if ( w ){
         
     | 
| 
      
 68 
     | 
    
         
            +
                FLOOP (j, 1, Q->t){
         
     | 
| 
      
 69 
     | 
    
         
            +
                  if ( Q->v[j-1] != Q->v[j] ){
         
     | 
| 
      
 70 
     | 
    
         
            +
                    Q->v[++jj] = Q->v[j];
         
     | 
| 
      
 71 
     | 
    
         
            +
                    w[jj] = w[j];
         
     | 
| 
      
 72 
     | 
    
         
            +
                  } else w[jj] += w[j];
         
     | 
| 
      
 73 
     | 
    
         
            +
                }
         
     | 
| 
      
 74 
     | 
    
         
            +
              } else FLOOP (j, 1, Q->t){
         
     | 
| 
      
 75 
     | 
    
         
            +
                if ( Q->v[j-1] != Q->v[j] ) Q->v[++jj] = Q->v[j];
         
     | 
| 
      
 76 
     | 
    
         
            +
              }
         
     | 
| 
      
 77 
     | 
    
         
            +
              if ( Q->t>0 ) Q->t = jj+1;
         
     | 
| 
      
 78 
     | 
    
         
            +
            }
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            /***********************************************************************/
         
     | 
| 
      
 81 
     | 
    
         
            +
            /* duplicate occ's in jump, ( copy occ's to allocated QUEUE array) */
         
     | 
| 
      
 82 
     | 
    
         
            +
            /* Q[i].end := original item, clear each original occ */
         
     | 
| 
      
 83 
     | 
    
         
            +
            /* buffer size is multiplied by u */
         
     | 
| 
      
 84 
     | 
    
         
            +
            /*******************************************************/
         
     | 
| 
      
 85 
     | 
    
         
            +
            void QUEUE_occ_dup (QUEUE *jump, QUEUE **QQ, QUEUE *Q, WEIGHT **ww, WEIGHT *w, WEIGHT **ppw, WEIGHT *pw, int u){
         
     | 
| 
      
 86 
     | 
    
         
            +
              QUEUE_ID i, l=QUEUE_LENGTH_(*jump);
         
     | 
| 
      
 87 
     | 
    
         
            +
              size_t cnt=0;
         
     | 
| 
      
 88 
     | 
    
         
            +
              QUEUE_INT e, *x;
         
     | 
| 
      
 89 
     | 
    
         
            +
              char *buf;
         
     | 
| 
      
 90 
     | 
    
         
            +
              int unit = sizeof(*Q) + (w?sizeof(*w):0) + (pw?sizeof(*pw):0);
         
     | 
| 
      
 91 
     | 
    
         
            +
             
         
     | 
| 
      
 92 
     | 
    
         
            +
              ENMAX (u, sizeof(*x));
         
     | 
| 
      
 93 
     | 
    
         
            +
              MQUE_FLOOP (*jump, x) cnt += Q[*x].t;
         
     | 
| 
      
 94 
     | 
    
         
            +
              if ( cnt == 0 ){ *QQ=NULL; return; }
         
     | 
| 
      
 95 
     | 
    
         
            +
              malloc2 (buf, l*unit + (cnt+l)*u, "QUEUE_occ_dup: buf", EXIT);
         
     | 
| 
      
 96 
     | 
    
         
            +
              *QQ = (QUEUE*)buf; buf += sizeof(*Q) *l;
         
     | 
| 
      
 97 
     | 
    
         
            +
              if ( w ){ *ww = (WEIGHT *)buf; buf += sizeof(*w)*l; }
         
     | 
| 
      
 98 
     | 
    
         
            +
              if ( pw ){ *ppw = (WEIGHT *)buf; buf += sizeof(*pw)*l; }
         
     | 
| 
      
 99 
     | 
    
         
            +
              ARY_FLOOP (*jump, i, e){
         
     | 
| 
      
 100 
     | 
    
         
            +
                (*QQ)[i].end = e;
         
     | 
| 
      
 101 
     | 
    
         
            +
                (*QQ)[i].v = (QUEUE_INT *)buf;
         
     | 
| 
      
 102 
     | 
    
         
            +
                (*QQ)[i].t = Q[e].t;
         
     | 
| 
      
 103 
     | 
    
         
            +
                memcpy (buf, Q[e].v, (Q[e].t+1)*u);
         
     | 
| 
      
 104 
     | 
    
         
            +
                buf += (Q[e].t+1) *u;
         
     | 
| 
      
 105 
     | 
    
         
            +
                if ( w ) (*ww)[i] = w[e];
         
     | 
| 
      
 106 
     | 
    
         
            +
                if ( pw ) (*ppw)[i] = pw[e];
         
     | 
| 
      
 107 
     | 
    
         
            +
              }
         
     | 
| 
      
 108 
     | 
    
         
            +
            }
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            /* return the position of the first element having value e. return -1 if no such element exists */
         
     | 
| 
      
 112 
     | 
    
         
            +
            LONG QUEUE_ele (QUEUE *Q, QUEUE_INT e){
         
     | 
| 
      
 113 
     | 
    
         
            +
              QUEUE_INT *x;
         
     | 
| 
      
 114 
     | 
    
         
            +
              MQUE_FLOOP (*Q, x)
         
     | 
| 
      
 115 
     | 
    
         
            +
                if ( *x == e ) return (x - Q->v);
         
     | 
| 
      
 116 
     | 
    
         
            +
              return (-1);
         
     | 
| 
      
 117 
     | 
    
         
            +
            }
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
            /* insert an element to the tail */
         
     | 
| 
      
 120 
     | 
    
         
            +
            void QUEUE_ins_ (QUEUE *Q, QUEUE_INT e){
         
     | 
| 
      
 121 
     | 
    
         
            +
              Q->v[Q->t] = e;
         
     | 
| 
      
 122 
     | 
    
         
            +
              Q->t++;
         
     | 
| 
      
 123 
     | 
    
         
            +
            }
         
     | 
| 
      
 124 
     | 
    
         
            +
            void QUEUE_ins (QUEUE *Q, QUEUE_INT e){
         
     | 
| 
      
 125 
     | 
    
         
            +
              Q->v[Q->t] = e;
         
     | 
| 
      
 126 
     | 
    
         
            +
              QUEUE_INCREMENT (*Q, Q->t);
         
     | 
| 
      
 127 
     | 
    
         
            +
              if (Q->s == Q->t ) error_num ("QUEUE_ins: overflow", Q->s, EXIT);
         
     | 
| 
      
 128 
     | 
    
         
            +
            }
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
            /* insert an element to the head */
         
     | 
| 
      
 131 
     | 
    
         
            +
            void QUEUE_ins_head_ (QUEUE *Q, QUEUE_INT e){
         
     | 
| 
      
 132 
     | 
    
         
            +
              Q->s--;
         
     | 
| 
      
 133 
     | 
    
         
            +
              Q->v[Q->s] = e;
         
     | 
| 
      
 134 
     | 
    
         
            +
            }
         
     | 
| 
      
 135 
     | 
    
         
            +
            void QUEUE_ins_head (QUEUE *Q, QUEUE_INT e){
         
     | 
| 
      
 136 
     | 
    
         
            +
              QUEUE_DECREMENT(*Q,Q->s);
         
     | 
| 
      
 137 
     | 
    
         
            +
              Q->v[Q->s] = e;
         
     | 
| 
      
 138 
     | 
    
         
            +
              if (Q->s == Q->t ) error_num ("QUEUE_ins_head: underflow", Q->s, EXIT);
         
     | 
| 
      
 139 
     | 
    
         
            +
            }
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            /* extract an element from the head, without checking underflow */
         
     | 
| 
      
 142 
     | 
    
         
            +
            QUEUE_INT QUEUE_ext_ (QUEUE *Q){
         
     | 
| 
      
 143 
     | 
    
         
            +
              (Q->s)++;
         
     | 
| 
      
 144 
     | 
    
         
            +
              return (Q->v[Q->s-1]);
         
     | 
| 
      
 145 
     | 
    
         
            +
            }
         
     | 
| 
      
 146 
     | 
    
         
            +
            QUEUE_INT QUEUE_ext (QUEUE *Q){
         
     | 
| 
      
 147 
     | 
    
         
            +
              QUEUE_INT e;
         
     | 
| 
      
 148 
     | 
    
         
            +
              if (Q->s == Q->t ) error_num ("QUEUE_ext: empty queue", Q->s, EXIT0);
         
     | 
| 
      
 149 
     | 
    
         
            +
              e = Q->v[Q->s];
         
     | 
| 
      
 150 
     | 
    
         
            +
              QUEUE_INCREMENT(*Q,Q->s);
         
     | 
| 
      
 151 
     | 
    
         
            +
              return ( e);
         
     | 
| 
      
 152 
     | 
    
         
            +
            }
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
            /* extract an element from the tail, without checking underflow */
         
     | 
| 
      
 155 
     | 
    
         
            +
            QUEUE_INT QUEUE_ext_tail_ (QUEUE *Q){
         
     | 
| 
      
 156 
     | 
    
         
            +
              (Q->t)--;
         
     | 
| 
      
 157 
     | 
    
         
            +
              return (Q->v[Q->t]);
         
     | 
| 
      
 158 
     | 
    
         
            +
            }
         
     | 
| 
      
 159 
     | 
    
         
            +
            QUEUE_INT QUEUE_ext_tail (QUEUE *Q){
         
     | 
| 
      
 160 
     | 
    
         
            +
              if ( Q->s == Q->t ) error_num ("QUEUE_ext_tail: empty queue", Q->s, EXIT0);
         
     | 
| 
      
 161 
     | 
    
         
            +
              QUEUE_DECREMENT(*Q,Q->t);
         
     | 
| 
      
 162 
     | 
    
         
            +
              return (Q->v[Q->t]);
         
     | 
| 
      
 163 
     | 
    
         
            +
            }
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
            /* remove the j-th element and replace it by the tail */
         
     | 
| 
      
 166 
     | 
    
         
            +
            void QUEUE_rm_ (QUEUE *Q, QUEUE_ID j){
         
     | 
| 
      
 167 
     | 
    
         
            +
              Q->t--;
         
     | 
| 
      
 168 
     | 
    
         
            +
              Q->v[j] = Q->v[Q->t];
         
     | 
| 
      
 169 
     | 
    
         
            +
            }
         
     | 
| 
      
 170 
     | 
    
         
            +
            void QUEUE_rm (QUEUE *Q, QUEUE_ID j){
         
     | 
| 
      
 171 
     | 
    
         
            +
              if ( Q->s <= Q->t ){
         
     | 
| 
      
 172 
     | 
    
         
            +
                if ( j < Q->s || j >= Q->t ) error ("QUEUE_rm: j is out of queue", EXIT);
         
     | 
| 
      
 173 
     | 
    
         
            +
              } else if ( j < Q->s && j >= Q->t ) error ("QUEUE_rm: j is out of queue", EXIT);
         
     | 
| 
      
 174 
     | 
    
         
            +
              QUEUE_DECREMENT(*Q,Q->t);
         
     | 
| 
      
 175 
     | 
    
         
            +
              Q->v[j] = Q->v[Q->t];
         
     | 
| 
      
 176 
     | 
    
         
            +
            }
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
            /* remove the j-th element and replace it by the head */
         
     | 
| 
      
 179 
     | 
    
         
            +
            void QUEUE_rm_head_ (QUEUE *Q, QUEUE_ID j){
         
     | 
| 
      
 180 
     | 
    
         
            +
              Q->v[j] = Q->v[Q->s];
         
     | 
| 
      
 181 
     | 
    
         
            +
              Q->s++;
         
     | 
| 
      
 182 
     | 
    
         
            +
            }
         
     | 
| 
      
 183 
     | 
    
         
            +
            void QUEUE_rm_head (QUEUE *Q, QUEUE_ID j){
         
     | 
| 
      
 184 
     | 
    
         
            +
              if ( Q->s <= Q->t ){
         
     | 
| 
      
 185 
     | 
    
         
            +
                if ( j < Q->s || j >= Q->t ) error ("QUEUE_rm: j is out of queue", EXIT);
         
     | 
| 
      
 186 
     | 
    
         
            +
              } else if ( j < Q->s && j >= Q->t ) error ("QUEUE_rm: j is out of queue", EXIT);
         
     | 
| 
      
 187 
     | 
    
         
            +
              Q->v[j] = Q->v[Q->s];
         
     | 
| 
      
 188 
     | 
    
         
            +
              QUEUE_INCREMENT(*Q,Q->s);
         
     | 
| 
      
 189 
     | 
    
         
            +
            }
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
            /* remove the j-th element and shift the following elements to fill the gap */
         
     | 
| 
      
 192 
     | 
    
         
            +
            int QUEUE_rm_ele_ (QUEUE *Q, QUEUE_INT e){
         
     | 
| 
      
 193 
     | 
    
         
            +
              QUEUE_ID i;
         
     | 
| 
      
 194 
     | 
    
         
            +
              QUEUE_F_LOOP (*Q, i){
         
     | 
| 
      
 195 
     | 
    
         
            +
                if ( Q->v[i] == e ){
         
     | 
| 
      
 196 
     | 
    
         
            +
                  memcpy ( &(Q->v[i]), &(Q->v[i+1]), (Q->t-i-1)*sizeof(QUEUE_INT));
         
     | 
| 
      
 197 
     | 
    
         
            +
                  Q->t--;
         
     | 
| 
      
 198 
     | 
    
         
            +
                  return (1);
         
     | 
| 
      
 199 
     | 
    
         
            +
                }
         
     | 
| 
      
 200 
     | 
    
         
            +
              }
         
     | 
| 
      
 201 
     | 
    
         
            +
              return (0);
         
     | 
| 
      
 202 
     | 
    
         
            +
            }  
         
     | 
| 
      
 203 
     | 
    
         
            +
            /* insert e to the position determined by the increasing order of elements */
         
     | 
| 
      
 204 
     | 
    
         
            +
            void QUEUE_ins_ele_ (QUEUE *Q, QUEUE_INT e){
         
     | 
| 
      
 205 
     | 
    
         
            +
              QUEUE_ID i;
         
     | 
| 
      
 206 
     | 
    
         
            +
              QUEUE_INT ee;
         
     | 
| 
      
 207 
     | 
    
         
            +
              QUEUE_BE_LOOP_ (*Q, i, ee){
         
     | 
| 
      
 208 
     | 
    
         
            +
                if ( ee<e ) break;
         
     | 
| 
      
 209 
     | 
    
         
            +
                Q->v[i+1] = ee;
         
     | 
| 
      
 210 
     | 
    
         
            +
              }
         
     | 
| 
      
 211 
     | 
    
         
            +
              Q->v[i+1] = e;
         
     | 
| 
      
 212 
     | 
    
         
            +
              Q->t++;
         
     | 
| 
      
 213 
     | 
    
         
            +
            }
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
            /* Append Q2 to the tail of Q1. Q2 will not be deleted */
         
     | 
| 
      
 216 
     | 
    
         
            +
            void QUEUE_concat_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 217 
     | 
    
         
            +
              memcpy ( &(Q1->v[Q1->t]), &(Q2->v[Q2->s]), (Q2->t-Q2->s)*sizeof(QUEUE_INT));
         
     | 
| 
      
 218 
     | 
    
         
            +
              Q1->t += Q2->t-Q2->s;
         
     | 
| 
      
 219 
     | 
    
         
            +
            }
         
     | 
| 
      
 220 
     | 
    
         
            +
            void QUEUE_concat (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 221 
     | 
    
         
            +
              QUEUE_ID e = Q2->s;
         
     | 
| 
      
 222 
     | 
    
         
            +
              while ( e != Q2->t){
         
     | 
| 
      
 223 
     | 
    
         
            +
                QUEUE_ins (Q1, Q2->v[e]);
         
     | 
| 
      
 224 
     | 
    
         
            +
                QUEUE_INCREMENT(*Q2,e);
         
     | 
| 
      
 225 
     | 
    
         
            +
              }
         
     | 
| 
      
 226 
     | 
    
         
            +
            }
         
     | 
| 
      
 227 
     | 
    
         
            +
            /* Append Q2 to the tail of Q1. Q2 will be deleted */
         
     | 
| 
      
 228 
     | 
    
         
            +
            void QUEUE_append_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 229 
     | 
    
         
            +
              QUEUE_concat_ (Q1, Q2);
         
     | 
| 
      
 230 
     | 
    
         
            +
              QUEUE_RMALL (*Q2);
         
     | 
| 
      
 231 
     | 
    
         
            +
            }
         
     | 
| 
      
 232 
     | 
    
         
            +
            void QUEUE_append (QUEUE *Q1, QUEUE *Q2){ // more improvement can be
         
     | 
| 
      
 233 
     | 
    
         
            +
              while ( Q2->s != Q2->t )
         
     | 
| 
      
 234 
     | 
    
         
            +
                  QUEUE_ins (Q1, QUEUE_ext(Q2));
         
     | 
| 
      
 235 
     | 
    
         
            +
            }
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
            /* Append from j to jj th elements to the tail of Q1. Q2 will not be deleted */
         
     | 
| 
      
 238 
     | 
    
         
            +
            void QUEUE_subconcat_ (QUEUE *Q1, QUEUE *Q2, QUEUE_ID j, QUEUE_ID jj){
         
     | 
| 
      
 239 
     | 
    
         
            +
              for ( ; j<=jj ; j++){
         
     | 
| 
      
 240 
     | 
    
         
            +
                Q1->v[Q1->t] = Q2->v[j];
         
     | 
| 
      
 241 
     | 
    
         
            +
                Q1->t++;
         
     | 
| 
      
 242 
     | 
    
         
            +
              }
         
     | 
| 
      
 243 
     | 
    
         
            +
            }
         
     | 
| 
      
 244 
     | 
    
         
            +
            void QUEUE_subconcat (QUEUE *Q1, QUEUE *Q2, QUEUE_ID j, QUEUE_ID jj){
         
     | 
| 
      
 245 
     | 
    
         
            +
              while (1){
         
     | 
| 
      
 246 
     | 
    
         
            +
                QUEUE_ins (Q1, Q2->v[j]);
         
     | 
| 
      
 247 
     | 
    
         
            +
                if ( j == jj ) break;
         
     | 
| 
      
 248 
     | 
    
         
            +
                QUEUE_INCREMENT(*Q2,j);
         
     | 
| 
      
 249 
     | 
    
         
            +
              } 
         
     | 
| 
      
 250 
     | 
    
         
            +
            }
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
            /* initialize Q1 by length of Q2, and copy Q2 to Q1 */
         
     | 
| 
      
 253 
     | 
    
         
            +
            void QUEUE_store_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 254 
     | 
    
         
            +
              QUEUE_alloc (Q1, QUEUE_LENGTH(*Q2));
         
     | 
| 
      
 255 
     | 
    
         
            +
              QUEUE_concat_ (Q1, Q2);
         
     | 
| 
      
 256 
     | 
    
         
            +
            }
         
     | 
| 
      
 257 
     | 
    
         
            +
            void QUEUE_store (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 258 
     | 
    
         
            +
              QUEUE_alloc (Q1, QUEUE_LENGTH(*Q2));
         
     | 
| 
      
 259 
     | 
    
         
            +
              QUEUE_concat (Q1, Q2);
         
     | 
| 
      
 260 
     | 
    
         
            +
            }
         
     | 
| 
      
 261 
     | 
    
         
            +
            /* copy Q2 to Q1 and delete Q2 */
         
     | 
| 
      
 262 
     | 
    
         
            +
            void QUEUE_restore_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 263 
     | 
    
         
            +
              QUEUE_RMALL (*Q1);
         
     | 
| 
      
 264 
     | 
    
         
            +
              QUEUE_concat_ (Q1, Q2);
         
     | 
| 
      
 265 
     | 
    
         
            +
              QUEUE_end (Q2);
         
     | 
| 
      
 266 
     | 
    
         
            +
            }
         
     | 
| 
      
 267 
     | 
    
         
            +
            void QUEUE_restore (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 268 
     | 
    
         
            +
              QUEUE_RMALL (*Q1);
         
     | 
| 
      
 269 
     | 
    
         
            +
              QUEUE_concat (Q1, Q2);
         
     | 
| 
      
 270 
     | 
    
         
            +
              QUEUE_end (Q2);
         
     | 
| 
      
 271 
     | 
    
         
            +
            }
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
            /* copy Q2 to Q1 */
         
     | 
| 
      
 274 
     | 
    
         
            +
            void QUEUE_cpy_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 275 
     | 
    
         
            +
              Q1->s = Q1->t = 0;
         
     | 
| 
      
 276 
     | 
    
         
            +
              QUEUE_concat_ (Q1, Q2);
         
     | 
| 
      
 277 
     | 
    
         
            +
            }
         
     | 
| 
      
 278 
     | 
    
         
            +
            void QUEUE_cpy (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 279 
     | 
    
         
            +
              QUEUE_RMALL (*Q1);
         
     | 
| 
      
 280 
     | 
    
         
            +
              QUEUE_concat (Q1, Q2);
         
     | 
| 
      
 281 
     | 
    
         
            +
            }
         
     | 
| 
      
 282 
     | 
    
         
            +
            /* copy l elements of Q2 starting from s2 to the s1th position of Q1.
         
     | 
| 
      
 283 
     | 
    
         
            +
               size of Q1 is not increasing */
         
     | 
| 
      
 284 
     | 
    
         
            +
            void QUEUE_subcpy_ (QUEUE *Q1, QUEUE_ID s1, QUEUE *Q2, QUEUE_ID s2, QUEUE_ID l){
         
     | 
| 
      
 285 
     | 
    
         
            +
              memcpy ( &(Q1->v[s1]), &(Q2->v[s2]), (l-s2)*sizeof(QUEUE_INT));
         
     | 
| 
      
 286 
     | 
    
         
            +
            }
         
     | 
| 
      
 287 
     | 
    
         
            +
            void QUEUE_subcpy (QUEUE *Q1, QUEUE_ID s1, QUEUE *Q2, QUEUE_ID s2, QUEUE_ID l){
         
     | 
| 
      
 288 
     | 
    
         
            +
              for ( ; s2!=l ; QUEUE_INCREMENT(*Q1,s1),QUEUE_INCREMENT(*Q2,s2) )
         
     | 
| 
      
 289 
     | 
    
         
            +
                  Q1->v[s1] = Q2->v[s2];
         
     | 
| 
      
 290 
     | 
    
         
            +
              Q1->v[s1] = Q2->v[s2];
         
     | 
| 
      
 291 
     | 
    
         
            +
            }
         
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
      
 293 
     | 
    
         
            +
            /* duplicate Q2 to Q1. The memory size will be the length of Q2 */
         
     | 
| 
      
 294 
     | 
    
         
            +
            QUEUE QUEUE_dup_ (QUEUE *Q){
         
     | 
| 
      
 295 
     | 
    
         
            +
              QUEUE QQ;
         
     | 
| 
      
 296 
     | 
    
         
            +
              QUEUE_alloc (&QQ, QUEUE_LENGTH_(*Q));
         
     | 
| 
      
 297 
     | 
    
         
            +
              QUEUE_cpy_ (&QQ, Q);
         
     | 
| 
      
 298 
     | 
    
         
            +
              return (QQ);
         
     | 
| 
      
 299 
     | 
    
         
            +
            }
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
            /* merge Q1 and Q2 by insert all elements of Q2 to Q1 with deleting duplications. Both Q1 and Q2 have to be sorted in increasing order */
         
     | 
| 
      
 302 
     | 
    
         
            +
            void QUEUE_merge_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 303 
     | 
    
         
            +
              QUEUE_ID i=Q1->t-1, j=Q2->t-1, t=i+j-Q2->s+1;
         
     | 
| 
      
 304 
     | 
    
         
            +
              QUEUE_INT ei, ej;
         
     | 
| 
      
 305 
     | 
    
         
            +
              if ( i+1 == Q1->s || j+1 == Q2->s ){
         
     | 
| 
      
 306 
     | 
    
         
            +
                QUEUE_concat_ (Q1, Q2);
         
     | 
| 
      
 307 
     | 
    
         
            +
                return;
         
     | 
| 
      
 308 
     | 
    
         
            +
              }
         
     | 
| 
      
 309 
     | 
    
         
            +
              Q1->t = t+1;
         
     | 
| 
      
 310 
     | 
    
         
            +
              ei = Q1->v[i];
         
     | 
| 
      
 311 
     | 
    
         
            +
              ej = Q2->v[j];
         
     | 
| 
      
 312 
     | 
    
         
            +
              while (1){
         
     | 
| 
      
 313 
     | 
    
         
            +
                if ( ei > ej ){
         
     | 
| 
      
 314 
     | 
    
         
            +
                  Q1->v[t] = ei;
         
     | 
| 
      
 315 
     | 
    
         
            +
                  if ( i == Q1->s ){
         
     | 
| 
      
 316 
     | 
    
         
            +
                    QUEUE_subcpy_ (Q1, Q1->s, Q2, Q2->s, j);
         
     | 
| 
      
 317 
     | 
    
         
            +
                    return;
         
     | 
| 
      
 318 
     | 
    
         
            +
                  }
         
     | 
| 
      
 319 
     | 
    
         
            +
                  i--;
         
     | 
| 
      
 320 
     | 
    
         
            +
                  ei = Q1->v[i];
         
     | 
| 
      
 321 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 322 
     | 
    
         
            +
                  Q1->v[t] = ej;
         
     | 
| 
      
 323 
     | 
    
         
            +
                  if ( j == Q2->s ) return;
         
     | 
| 
      
 324 
     | 
    
         
            +
                  j--;
         
     | 
| 
      
 325 
     | 
    
         
            +
                  ej = Q2->v[j];
         
     | 
| 
      
 326 
     | 
    
         
            +
                }
         
     | 
| 
      
 327 
     | 
    
         
            +
                t--;
         
     | 
| 
      
 328 
     | 
    
         
            +
              }
         
     | 
| 
      
 329 
     | 
    
         
            +
            }
         
     | 
| 
      
 330 
     | 
    
         
            +
            void QUEUE_merge (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 331 
     | 
    
         
            +
              QUEUE_ID i=Q1->t, j=Q2->t;
         
     | 
| 
      
 332 
     | 
    
         
            +
              QUEUE_INT ei, ej;
         
     | 
| 
      
 333 
     | 
    
         
            +
              QUEUE_ID t = (Q1->t + QUEUE_LENGTH(*Q2)-1) % Q1->end;
         
     | 
| 
      
 334 
     | 
    
         
            +
              if ( QUEUE_LENGTH(*Q1) + QUEUE_LENGTH(*Q2) >= Q1->end ){
         
     | 
| 
      
 335 
     | 
    
         
            +
                printf ("QUEUE_merge: overflow Q1->end="QUEUE_INTF", Q1length="QUEUE_INTF", Q2length="QUEUE_INTF"\n", Q1->end, QUEUE_LENGTH(*Q1), QUEUE_LENGTH(*Q2));
         
     | 
| 
      
 336 
     | 
    
         
            +
                exit (1);
         
     | 
| 
      
 337 
     | 
    
         
            +
              }
         
     | 
| 
      
 338 
     | 
    
         
            +
              if ( i == Q1->s || j == Q2->s ){
         
     | 
| 
      
 339 
     | 
    
         
            +
                QUEUE_concat (Q1, Q2);
         
     | 
| 
      
 340 
     | 
    
         
            +
                return;
         
     | 
| 
      
 341 
     | 
    
         
            +
              }
         
     | 
| 
      
 342 
     | 
    
         
            +
             
     | 
| 
      
 343 
     | 
    
         
            +
              Q1->t = t;
         
     | 
| 
      
 344 
     | 
    
         
            +
              QUEUE_DECREMENT(*Q1,i);
         
     | 
| 
      
 345 
     | 
    
         
            +
              QUEUE_DECREMENT(*Q2,j);
         
     | 
| 
      
 346 
     | 
    
         
            +
              ei = Q1->v[i];
         
     | 
| 
      
 347 
     | 
    
         
            +
              ej = Q2->v[j];
         
     | 
| 
      
 348 
     | 
    
         
            +
              while (1){
         
     | 
| 
      
 349 
     | 
    
         
            +
                if ( ei > ej ){
         
     | 
| 
      
 350 
     | 
    
         
            +
                  Q1->v[t] = ei;
         
     | 
| 
      
 351 
     | 
    
         
            +
                  if ( i == Q1->s ){
         
     | 
| 
      
 352 
     | 
    
         
            +
                    QUEUE_subcpy (Q1, Q1->s, Q2, Q2->s, (j+Q2->end-Q2->s)%Q2->end);
         
     | 
| 
      
 353 
     | 
    
         
            +
                    return;
         
     | 
| 
      
 354 
     | 
    
         
            +
                  }
         
     | 
| 
      
 355 
     | 
    
         
            +
                  QUEUE_DECREMENT(*Q1,i);
         
     | 
| 
      
 356 
     | 
    
         
            +
                  ei = Q1->v[i];
         
     | 
| 
      
 357 
     | 
    
         
            +
                } else {  
         
     | 
| 
      
 358 
     | 
    
         
            +
                  Q1->v[t] = ej;
         
     | 
| 
      
 359 
     | 
    
         
            +
                  if ( j == Q2->s ) return;
         
     | 
| 
      
 360 
     | 
    
         
            +
                  QUEUE_DECREMENT(*Q2,j);
         
     | 
| 
      
 361 
     | 
    
         
            +
                  ej = Q2->v[j];
         
     | 
| 
      
 362 
     | 
    
         
            +
                }
         
     | 
| 
      
 363 
     | 
    
         
            +
                QUEUE_DECREMENT(*Q1,t);
         
     | 
| 
      
 364 
     | 
    
         
            +
              }
         
     | 
| 
      
 365 
     | 
    
         
            +
            }
         
     | 
| 
      
 366 
     | 
    
         
            +
             
     | 
| 
      
 367 
     | 
    
         
            +
            /* delete all elements of Q1 included in Q2.
         
     | 
| 
      
 368 
     | 
    
         
            +
             both Q1 and Q2 have to be sorted in increasing order */
         
     | 
| 
      
 369 
     | 
    
         
            +
            void QUEUE_minus_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 370 
     | 
    
         
            +
              QUEUE_ID i=Q1->s, i2 = Q2->s, ii=Q1->s;
         
     | 
| 
      
 371 
     | 
    
         
            +
              while ( i != Q1->t && i2 != Q2->t){
         
     | 
| 
      
 372 
     | 
    
         
            +
                if (Q1->v[i] > Q2->v[i2] ) i2++;
         
     | 
| 
      
 373 
     | 
    
         
            +
                else {
         
     | 
| 
      
 374 
     | 
    
         
            +
                  if (Q1->v[i] < Q2->v[i2] ){
         
     | 
| 
      
 375 
     | 
    
         
            +
                    Q1->v[ii] = Q1->v[i];
         
     | 
| 
      
 376 
     | 
    
         
            +
                    ii++;
         
     | 
| 
      
 377 
     | 
    
         
            +
                  }
         
     | 
| 
      
 378 
     | 
    
         
            +
                  i++;
         
     | 
| 
      
 379 
     | 
    
         
            +
                }
         
     | 
| 
      
 380 
     | 
    
         
            +
              }
         
     | 
| 
      
 381 
     | 
    
         
            +
              while ( i != Q1->t ){
         
     | 
| 
      
 382 
     | 
    
         
            +
                Q1->v[ii] = Q1->v[i];
         
     | 
| 
      
 383 
     | 
    
         
            +
                i++;
         
     | 
| 
      
 384 
     | 
    
         
            +
                ii++;
         
     | 
| 
      
 385 
     | 
    
         
            +
              }
         
     | 
| 
      
 386 
     | 
    
         
            +
              Q1->t = ii;
         
     | 
| 
      
 387 
     | 
    
         
            +
            }
         
     | 
| 
      
 388 
     | 
    
         
            +
            void QUEUE_minus (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 389 
     | 
    
         
            +
              QUEUE_ID i=Q1->s, i2 = Q2->s, ii=Q1->s;
         
     | 
| 
      
 390 
     | 
    
         
            +
              while ( i != Q1->t && i2 != Q2->t ){
         
     | 
| 
      
 391 
     | 
    
         
            +
                if ( Q1->v[i] > Q2->v[i2] ) QUEUE_INCREMENT (*Q2, i2);
         
     | 
| 
      
 392 
     | 
    
         
            +
                else {
         
     | 
| 
      
 393 
     | 
    
         
            +
                  if ( Q1->v[i] < Q2->v[i2] ){
         
     | 
| 
      
 394 
     | 
    
         
            +
                    Q1->v[ii] = Q1->v[i];
         
     | 
| 
      
 395 
     | 
    
         
            +
                    QUEUE_INCREMENT (*Q1, ii);
         
     | 
| 
      
 396 
     | 
    
         
            +
                  }
         
     | 
| 
      
 397 
     | 
    
         
            +
                  QUEUE_INCREMENT (*Q1, i);
         
     | 
| 
      
 398 
     | 
    
         
            +
                }
         
     | 
| 
      
 399 
     | 
    
         
            +
              }
         
     | 
| 
      
 400 
     | 
    
         
            +
              while ( i != Q1->t ){
         
     | 
| 
      
 401 
     | 
    
         
            +
                Q1->v[ii] = Q1->v[i];
         
     | 
| 
      
 402 
     | 
    
         
            +
                QUEUE_INCREMENT (*Q1, i);
         
     | 
| 
      
 403 
     | 
    
         
            +
                QUEUE_INCREMENT (*Q1, ii);
         
     | 
| 
      
 404 
     | 
    
         
            +
              }
         
     | 
| 
      
 405 
     | 
    
         
            +
              Q1->t = ii;
         
     | 
| 
      
 406 
     | 
    
         
            +
            }
         
     | 
| 
      
 407 
     | 
    
         
            +
             
     | 
| 
      
 408 
     | 
    
         
            +
            /* Delete all elements of Q1 which are not included in Q2. 
         
     | 
| 
      
 409 
     | 
    
         
            +
             both Q1 and Q2 have to be sorted in increasing order */
         
     | 
| 
      
 410 
     | 
    
         
            +
            QUEUE_ID QUEUE_intsec_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 411 
     | 
    
         
            +
              QUEUE_ID i=Q1->s, i2 = Q2->s, c=0;
         
     | 
| 
      
 412 
     | 
    
         
            +
              while ( i != Q1->t ){
         
     | 
| 
      
 413 
     | 
    
         
            +
                if ( Q1->v[i] > Q2->v[i2] ){
         
     | 
| 
      
 414 
     | 
    
         
            +
                  if ( ++i2 == Q2->t ) break;
         
     | 
| 
      
 415 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 416 
     | 
    
         
            +
                  if ( Q1->v[i] == Q2->v[i2] ) c++;
         
     | 
| 
      
 417 
     | 
    
         
            +
                  i++;
         
     | 
| 
      
 418 
     | 
    
         
            +
                }
         
     | 
| 
      
 419 
     | 
    
         
            +
              }
         
     | 
| 
      
 420 
     | 
    
         
            +
              return (c);
         
     | 
| 
      
 421 
     | 
    
         
            +
            }
         
     | 
| 
      
 422 
     | 
    
         
            +
            void QUEUE_and_ (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 423 
     | 
    
         
            +
              QUEUE_ID i=Q1->s, i2 = Q2->s, ii=Q1->s;
         
     | 
| 
      
 424 
     | 
    
         
            +
              while ( i != Q1->t ){
         
     | 
| 
      
 425 
     | 
    
         
            +
                if ( Q1->v[i] > Q2->v[i2] ){
         
     | 
| 
      
 426 
     | 
    
         
            +
                  if ( ++i2 == Q2->t ) break;
         
     | 
| 
      
 427 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 428 
     | 
    
         
            +
                  if ( Q1->v[i] == Q2->v[i2] ) Q1->v[ii++] = Q1->v[i];
         
     | 
| 
      
 429 
     | 
    
         
            +
                  i++;
         
     | 
| 
      
 430 
     | 
    
         
            +
                }
         
     | 
| 
      
 431 
     | 
    
         
            +
              }
         
     | 
| 
      
 432 
     | 
    
         
            +
              Q1->t = ii;
         
     | 
| 
      
 433 
     | 
    
         
            +
            }
         
     | 
| 
      
 434 
     | 
    
         
            +
            void QUEUE_and (QUEUE *Q1, QUEUE *Q2){
         
     | 
| 
      
 435 
     | 
    
         
            +
              QUEUE_ID i=Q1->s, i2 = Q2->s, ii=Q1->s;
         
     | 
| 
      
 436 
     | 
    
         
            +
              while ( i != Q1->t && i2 != Q2->t){
         
     | 
| 
      
 437 
     | 
    
         
            +
                if ( Q1->v[i] > Q2->v[i2] ) QUEUE_INCREMENT (*Q2, i2);
         
     | 
| 
      
 438 
     | 
    
         
            +
                else {
         
     | 
| 
      
 439 
     | 
    
         
            +
                  if ( Q1->v[i] == Q2->v[i2] ){
         
     | 
| 
      
 440 
     | 
    
         
            +
                    Q1->v[ii] = Q1->v[i];
         
     | 
| 
      
 441 
     | 
    
         
            +
                    QUEUE_INCREMENT (*Q1, ii);
         
     | 
| 
      
 442 
     | 
    
         
            +
                  }
         
     | 
| 
      
 443 
     | 
    
         
            +
                  QUEUE_INCREMENT (*Q1, i);
         
     | 
| 
      
 444 
     | 
    
         
            +
                }
         
     | 
| 
      
 445 
     | 
    
         
            +
              }
         
     | 
| 
      
 446 
     | 
    
         
            +
              Q1->t = ii;
         
     | 
| 
      
 447 
     | 
    
         
            +
            }
         
     | 
| 
      
 448 
     | 
    
         
            +
             
     | 
| 
      
 449 
     | 
    
         
            +
            /* insertion sort */
         
     | 
| 
      
 450 
     | 
    
         
            +
            void QUEUE_sort (QUEUE *Q){
         
     | 
| 
      
 451 
     | 
    
         
            +
              QUEUE_ID i = Q->s, j, jj;
         
     | 
| 
      
 452 
     | 
    
         
            +
              QUEUE_INT e;
         
     | 
| 
      
 453 
     | 
    
         
            +
              if ( i== Q->t ) return;
         
     | 
| 
      
 454 
     | 
    
         
            +
              QUEUE_INCREMENT(*Q,i);
         
     | 
| 
      
 455 
     | 
    
         
            +
              for ( ; i!=Q->t ; QUEUE_INCREMENT(*Q,i) ){
         
     | 
| 
      
 456 
     | 
    
         
            +
                e=Q->v[i]; 
         
     | 
| 
      
 457 
     | 
    
         
            +
                j=i; 
         
     | 
| 
      
 458 
     | 
    
         
            +
                while (1){
         
     | 
| 
      
 459 
     | 
    
         
            +
                  jj = j;
         
     | 
| 
      
 460 
     | 
    
         
            +
                  QUEUE_DECREMENT(*Q,j);
         
     | 
| 
      
 461 
     | 
    
         
            +
                  if ( Q->v[j] <= e ) { Q->v[jj] = e; break; }
         
     | 
| 
      
 462 
     | 
    
         
            +
                  Q->v[jj] = Q->v[j];
         
     | 
| 
      
 463 
     | 
    
         
            +
                  if ( j == Q->s) { Q->v[j] = e; break; }
         
     | 
| 
      
 464 
     | 
    
         
            +
                }
         
     | 
| 
      
 465 
     | 
    
         
            +
              }
         
     | 
| 
      
 466 
     | 
    
         
            +
            }
         
     | 
| 
      
 467 
     | 
    
         
            +
             
     | 
| 
      
 468 
     | 
    
         
            +
             
     | 
| 
      
 469 
     | 
    
         
            +
            /* print a queue */
         
     | 
| 
      
 470 
     | 
    
         
            +
            void QUEUE_print (QUEUE *Q){
         
     | 
| 
      
 471 
     | 
    
         
            +
              QUEUE_ID i;
         
     | 
| 
      
 472 
     | 
    
         
            +
              for ( i=Q->s ; i!=Q->t ; ){
         
     | 
| 
      
 473 
     | 
    
         
            +
                printf (QUEUE_INTF" ", Q->v[i]);
         
     | 
| 
      
 474 
     | 
    
         
            +
                QUEUE_INCREMENT(*Q,i);
         
     | 
| 
      
 475 
     | 
    
         
            +
              }
         
     | 
| 
      
 476 
     | 
    
         
            +
              printf ("\n");
         
     | 
| 
      
 477 
     | 
    
         
            +
            }
         
     | 
| 
      
 478 
     | 
    
         
            +
            /* permutation version */
         
     | 
| 
      
 479 
     | 
    
         
            +
            void QUEUE_perm_print (QUEUE *Q, QUEUE_ID *q){
         
     | 
| 
      
 480 
     | 
    
         
            +
              QUEUE_ID i;
         
     | 
| 
      
 481 
     | 
    
         
            +
              for ( i=Q->s ; i!=Q->t ; ){
         
     | 
| 
      
 482 
     | 
    
         
            +
                printf (QUEUE_INTF" ", q[Q->v[i]]);
         
     | 
| 
      
 483 
     | 
    
         
            +
                QUEUE_INCREMENT(*Q,i);
         
     | 
| 
      
 484 
     | 
    
         
            +
              }
         
     | 
| 
      
 485 
     | 
    
         
            +
              printf ("\n");
         
     | 
| 
      
 486 
     | 
    
         
            +
            }
         
     | 
| 
      
 487 
     | 
    
         
            +
            void QUEUE_printn (QUEUE *Q){
         
     | 
| 
      
 488 
     | 
    
         
            +
              QUEUE_ID i;
         
     | 
| 
      
 489 
     | 
    
         
            +
              for ( i=Q->s ; i!=Q->t ; ){
         
     | 
| 
      
 490 
     | 
    
         
            +
                printf (QUEUE_INTF" ", Q->v[i]);
         
     | 
| 
      
 491 
     | 
    
         
            +
                QUEUE_INCREMENT(*Q,i);
         
     | 
| 
      
 492 
     | 
    
         
            +
              }
         
     | 
| 
      
 493 
     | 
    
         
            +
            }
         
     | 
| 
      
 494 
     | 
    
         
            +
            void QUEUE_perm_printn (QUEUE *Q, QUEUE_ID *q){
         
     | 
| 
      
 495 
     | 
    
         
            +
              QUEUE_ID i;
         
     | 
| 
      
 496 
     | 
    
         
            +
              for ( i=Q->s ; i!=Q->t ; ){
         
     | 
| 
      
 497 
     | 
    
         
            +
                printf (QUEUE_INTF" ",q[Q->v[i]]);
         
     | 
| 
      
 498 
     | 
    
         
            +
                QUEUE_INCREMENT(*Q,i);
         
     | 
| 
      
 499 
     | 
    
         
            +
              }
         
     | 
| 
      
 500 
     | 
    
         
            +
            }
         
     | 
| 
      
 501 
     | 
    
         
            +
            void QUEUE_print_ (QUEUE *Q){
         
     | 
| 
      
 502 
     | 
    
         
            +
              QUEUE_ID i;
         
     | 
| 
      
 503 
     | 
    
         
            +
              printf("s="QUEUE_IDF",t="QUEUE_INTF": ", Q->s, Q->t);
         
     | 
| 
      
 504 
     | 
    
         
            +
              for ( i=Q->s ; i!=Q->t ; ){
         
     | 
| 
      
 505 
     | 
    
         
            +
                printf (QUEUE_INTF" ",Q->v[i]);
         
     | 
| 
      
 506 
     | 
    
         
            +
                QUEUE_INCREMENT(*Q,i);
         
     | 
| 
      
 507 
     | 
    
         
            +
              }
         
     | 
| 
      
 508 
     | 
    
         
            +
              printf ("\n");
         
     | 
| 
      
 509 
     | 
    
         
            +
            }
         
     | 
| 
      
 510 
     | 
    
         
            +
             
     | 
| 
      
 511 
     | 
    
         
            +
            void QUEUE_print__ (QUEUE *Q){
         
     | 
| 
      
 512 
     | 
    
         
            +
              QUEUE_ID i;
         
     | 
| 
      
 513 
     | 
    
         
            +
              printf("s="QUEUE_IDF",t="QUEUE_IDF": ", Q->s, Q->t);
         
     | 
| 
      
 514 
     | 
    
         
            +
              for ( i=Q->s ; i!=Q->t ; i++ ) printf (QUEUE_INTF" ",Q->v[i]);
         
     | 
| 
      
 515 
     | 
    
         
            +
              printf ("\n");
         
     | 
| 
      
 516 
     | 
    
         
            +
            }
         
     | 
| 
      
 517 
     | 
    
         
            +
             
     | 
| 
      
 518 
     | 
    
         
            +
            #endif
         
     |