tpl_dynArray.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef TPL_DYNARRAY_H
00045 # define TPL_DYNARRAY_H
00046 
00047 # include <string>
00048 # include <cmath>
00049 # include <aleph.H>
00050 
00051 using namespace std;
00052 
00053 # ifdef DEBUG
00054 # include <math.h>
00055 # endif /* DEBUG */
00056 
00057 using namespace Aleph;
00058 
00059 namespace Aleph {
00060 
00112     template <typename T>
00113 class DynArray
00114 {
00115 
00116 private:
00117 
00118   static const size_t Default_Pow_Dir;  /* 16   */
00119   static const size_t Default_Pow_Seg;  /* 64   */
00120   static const size_t Default_Pow_Block; /* 4096 */
00121   static const size_t Max_Bits_Allowed; 
00122   static const size_t Max_Dim_Allowed;
00123   static const size_t Max_Pow_Block;
00124   mutable size_t pow_dir;
00125   mutable size_t pow_seg;
00126   mutable size_t pow_block;
00127   mutable size_t seg_plus_block_pow;
00128   mutable size_t mask_seg_plus_block;
00129   mutable size_t dir_size;    // = 2^pow_dir
00130   mutable size_t seg_size;    // = 2^pow_seg
00131   mutable size_t block_size;  // = 2^pow_block
00132   mutable size_t max_dim;   // 2^(pow_dir + pow_seg + pow_block) - 1
00133   static size_t two_raised(const size_t & n)
00134   {
00135     if (n >= Max_Bits_Allowed)
00136       throw std::overflow_error ("number of bits exceeds de maximun allowed");
00137 
00138     I((1 << n) == (int) pow((float) 2.0, (float) n)); 
00139 
00140     return 1 << n;
00141   }
00142   size_t mask_seg;
00143   size_t mask_block;
00144   size_t index_in_dir(const size_t & i) const
00145   {
00146 
00147     I( (pow_block + pow_seg) == seg_plus_block_pow );
00148     I( seg_size * block_size == two_raised(seg_plus_block_pow) );
00149     I( i >> seg_plus_block_pow == i/(seg_size*block_size) );
00150 
00151     return i >> seg_plus_block_pow;
00152   }
00153 
00154   size_t modulus_from_index_in_dir(const size_t & i) const
00155   {
00156 
00157     I( mask_seg_plus_block == seg_size*block_size - 1 );
00158     I( (i & mask_seg_plus_block) == i%(seg_size*block_size) );
00159 
00160     return (i & mask_seg_plus_block);
00161   }
00162 
00163   size_t index_in_seg(const size_t & i) const
00164   {
00165 
00166     I( two_raised(pow_block) == block_size );
00167     I( (modulus_from_index_in_dir(i) >> pow_block) == 
00168             (i%(seg_size*block_size))/block_size );
00169 
00170     return modulus_from_index_in_dir(i) >> pow_block;
00171   }
00172     
00173   size_t index_in_block(const size_t & i) const
00174   {
00175 
00176     I( mask_block == block_size - 1 );
00177     I( (modulus_from_index_in_dir(i) & mask_block) == 
00178             ((i%(seg_size*block_size))%block_size) );
00179 
00180     return modulus_from_index_in_dir(i) & mask_block;
00181   }
00182   size_t current_dim;  
00183   size_t num_segs;   
00184   size_t num_blocks;
00185   T *** dir;
00186   void fill_dir_to_null()
00187   {
00188 
00189     I(dir != NULL);
00190 
00191     for (size_t i = 0; i < dir_size; ++i)
00192       dir[i] = NULL;
00193   }
00194 
00195   void fill_seg_to_null(T ** seg)
00196   {
00197 
00198     I(seg != NULL);
00199 
00200     for (size_t i = 0; i < seg_size; ++i)
00201       seg[i] = NULL;
00202   }
00203   void allocate_dir()
00204   {
00205 
00206     try
00207       {
00208 
00209         dir = new T ** [dir_size]; 
00210         fill_dir_to_null();
00211 
00212       }
00213     catch (...) 
00214       { 
00215         dir = NULL; 
00216         throw;
00217       }
00218 
00219   }
00220 
00221   void allocate_segment(T **& seg)
00222   {
00223 
00224     I(seg == NULL);
00225 
00226     seg = new T* [seg_size];
00227     fill_seg_to_null(seg);
00228     ++num_segs;
00229   }
00230   T default_initial_value;
00231 
00232   T * default_initial_value_ptr;
00233   void allocate_block(T *& block)
00234   {
00235 
00236     I(block == NULL);
00237 
00238     block = new T [block_size];
00239     ++num_blocks;
00240 
00241     if (default_initial_value_ptr == NULL)
00242       return;
00243 
00244     for (size_t i = 0; i < block_size; ++i)
00245       block[i] = default_initial_value;
00246   }
00247   void release_segment(T **& seg)
00248   {
00249 
00250     I(seg != NULL);
00251 
00252     delete [] seg;
00253     seg = NULL;
00254     --num_segs;
00255   }
00256 
00257   void release_block(T *& block)
00258   {
00259 
00260     I(block != NULL);
00261 
00262     delete [] block;
00263     block = NULL;
00264     --num_blocks;
00265   }
00266   void release_blocks_and_segment(T ** & seg)
00267   {
00268 
00269     I(seg != NULL);
00270 
00271     for(size_t i = 0; i < seg_size ; ++i)
00272       if (seg[i] != NULL) 
00273         release_block(seg[i]);
00274     
00275     release_segment(seg);
00276   }
00277 
00278   void release_all_segments_and_blocks()
00279   {
00280     for(size_t i = 0; i < dir_size ; ++i)
00281       if (dir[i] != NULL)
00282         release_blocks_and_segment(dir[i]); 
00283 
00284     current_dim = 0;
00285   }
00286 
00287   void release_dir()
00288   {
00289     release_all_segments_and_blocks();
00290 
00291     delete [] dir; 
00292     dir = NULL;
00293     current_dim = 0;
00294   }
00295   static size_t next2Pow(const size_t & number) 
00296   {
00297     return static_cast<size_t>(ceil(log(static_cast<float>(number))/log(2.0)));
00298   }
00299   size_t divide_by_block_size(const size_t & number) const
00300   {
00301 
00302     I(number/block_size == number >> pow_block);
00303 
00304     return number >> pow_block;
00305   }
00306 
00307   size_t modulus_by_block_size(const size_t & number) const
00308   {
00309 
00310     I((number%block_size) == (number & mask_block));
00311 
00312     return number & mask_block;
00313   }
00314 
00315   void advance_block_index(size_t &       block_index, 
00316                            size_t &       seg_index, 
00317                            const size_t & len) const
00318   {
00319     if (block_index + len < block_size)
00320       {
00321         block_index += len;
00322         return;
00323       }
00324 
00325     seg_index += divide_by_block_size(len);
00326     block_index = modulus_by_block_size(len); 
00327   }
00328   class Proxy
00329   {
00330     size_t index;
00331     size_t pos_in_dir;
00332     size_t pos_in_seg;
00333     size_t pos_in_block;
00334     T**&         ref_seg;
00335     T*           block;
00336     DynArray&    array;
00337 
00338   public:
00339 
00340     Proxy(DynArray<T>& _array, const size_t & i)
00341       : index       ( i                            ),
00342         pos_in_dir  ( _array.index_in_dir(index)   ),
00343         pos_in_seg  ( _array.index_in_seg(index)   ),
00344         pos_in_block( _array.index_in_block(index) ),
00345         ref_seg     ( _array.dir[pos_in_dir]       ),
00346         block       ( NULL                         ),
00347         array       ( _array                       )
00348     {
00349       if (ref_seg != NULL)
00350         block = ref_seg[pos_in_seg]; // ya existe un bloque para la entrada i
00351     }
00352     operator T & () 
00353     {
00354 
00355       if (block == NULL)
00356         throw std::invalid_argument("accessed entry has not been still written");
00357 
00358       return block[pos_in_block];
00359     }
00360     T * operator -> ()
00361     {
00362       bool seg_was_allocated_in_current_call = false;
00363 
00364       if (ref_seg == NULL) // hay segmento?
00365       {     // No ==> apartarlo!
00366         array.allocate_segment(ref_seg);
00367         seg_was_allocated_in_current_call = true; 
00368       }
00369       if (block == NULL) // test if block is allocated
00370         {
00371 
00372         try // tratar apartar bloque
00373           {
00374 
00375             array.allocate_block(block);
00376             ref_seg[pos_in_seg] = block;
00377 
00378             I(array.dir[pos_in_dir] == ref_seg); 
00379           }
00380         catch (...) // Ocurre una falla en el apartado del bloque
00381           {
00382             if (seg_was_allocated_in_current_call)
00383               array.release_segment(ref_seg);
00384 
00385             throw;
00386           }
00387 
00388         }
00389 
00390       if (index >= array.current_dim)
00391         array.current_dim = index + 1; 
00392 
00393       return &block[pos_in_block]; 
00394     }
00395     Proxy & operator = (const T & data)
00396     {
00397       bool seg_was_allocated_in_current_call = false;
00398 
00399       if (ref_seg == NULL) // hay segmento?
00400       {     // No ==> apartarlo!
00401         array.allocate_segment(ref_seg);
00402         seg_was_allocated_in_current_call = true; 
00403       }
00404       if (block == NULL) // test if block is allocated
00405         {
00406 
00407         try // tratar apartar bloque
00408           {
00409 
00410             array.allocate_block(block);
00411             ref_seg[pos_in_seg] = block;
00412 
00413             I(array.dir[pos_in_dir] == ref_seg); 
00414           }
00415         catch (...) // Ocurre una falla en el apartado del bloque
00416           {
00417             if (seg_was_allocated_in_current_call)
00418               array.release_segment(ref_seg);
00419 
00420             throw;
00421           }
00422 
00423         }
00424       if (index >= array.current_dim)
00425         array.current_dim = index + 1; 
00426 
00427       block[pos_in_block] = data;
00428 
00429       return *this;
00430     }
00431 
00432     Proxy & operator = (const Proxy & proxy)
00433     {
00434       if (proxy.block == NULL) // ¿operando derecho puede leer?
00435         throw std::invalid_argument("right entry has not been still written");
00436 
00437       if (&proxy == this)
00438         return *this;
00439 
00440 
00441       bool seg_was_allocated_in_current_call = false;
00442 
00443       if (ref_seg == NULL) // hay segmento?
00444       {     // No ==> apartarlo!
00445         array.allocate_segment(ref_seg);
00446         seg_was_allocated_in_current_call = true; 
00447       }
00448       if (block == NULL) // test if block is allocated
00449         {
00450 
00451         try // tratar apartar bloque
00452           {
00453 
00454             array.allocate_block(block);
00455             ref_seg[pos_in_seg] = block;
00456 
00457             I(array.dir[pos_in_dir] == ref_seg); 
00458           }
00459         catch (...) // Ocurre una falla en el apartado del bloque
00460           {
00461             if (seg_was_allocated_in_current_call)
00462               array.release_segment(ref_seg);
00463 
00464             throw;
00465           }
00466 
00467         }
00468       if (index >= array.current_dim)
00469         array.current_dim = index + 1; 
00470 
00471       block[pos_in_block] = proxy.block[proxy.pos_in_block];
00472 
00473       return *this;
00474     }
00475   };
00476 
00477 public:
00478 
00480   const size_t & get_dir_size() const { return dir_size; }
00482   const size_t & get_seg_size() const { return seg_size; }
00484   const size_t & get_block_size() const { return block_size; } 
00486   const size_t & size() const { return current_dim; }
00488   const size_t & max_size() const { return max_dim; }
00490   const size_t & get_num_blocks() const { return num_blocks; }
00501   void set_default_initial_value(const T & value)
00502   {
00503     default_initial_value     = value;
00504     default_initial_value_ptr = &default_initial_value;
00505   }
00525   DynArray(const size_t & _pow_dir, 
00526            const size_t & _pow_seg,
00527            const size_t & _pow_block)
00528     throw (std::exception, std::bad_alloc, 
00529            std::length_error, std::overflow_error) 
00530     : pow_dir             ( _pow_dir                                 ),
00531       pow_seg             ( _pow_seg                                 ),
00532       pow_block           ( _pow_block                               ),
00533       seg_plus_block_pow  ( _pow_seg + _pow_block                    ),
00534       mask_seg_plus_block ( two_raised(seg_plus_block_pow) - 1       ),
00535       dir_size            ( two_raised(pow_dir)                      ), 
00536       seg_size            ( two_raised(pow_seg)                      ), 
00537       block_size          ( two_raised(pow_block)                    ), 
00538       max_dim             ( two_raised(seg_plus_block_pow + pow_dir) ), 
00539       mask_seg            ( seg_size - 1                             ),
00540       mask_block          ( block_size - 1                           ),
00541       current_dim         ( 0                                        ),
00542       num_segs            ( 0                                        ),
00543       num_blocks          ( 0                                        ),
00544       default_initial_value_ptr (NULL)
00545   {
00546     I(Max_Dim_Allowed > 0);
00547 
00548     if (max_dim > Max_Dim_Allowed)
00549       throw std::length_error ("Dimension too large"); 
00550 
00551     allocate_dir();
00552   }
00572   DynArray(const size_t & dim = 10000) 
00573 
00574     throw (std::exception, std::bad_alloc, 
00575            std::length_error, std::overflow_error) 
00576 
00577     : pow_dir             ( Default_Pow_Dir                          ),
00578       pow_seg             ( Default_Pow_Seg                          ),
00579         pow_block       (std::min(std::max(next2Pow(dim/8), Default_Pow_Block), 
00580                                   Max_Pow_Block)
00581                          ), 
00582       seg_plus_block_pow  ( pow_seg + pow_block                      ),
00583       mask_seg_plus_block ( two_raised(seg_plus_block_pow) - 1       ),
00584       dir_size            ( two_raised(pow_dir)                      ), 
00585       seg_size            ( two_raised(pow_seg)                      ), 
00586       block_size          ( two_raised(pow_block)                    ), 
00587       max_dim             ( two_raised(seg_plus_block_pow + pow_dir) ),
00588       mask_seg            ( seg_size - 1                             ),
00589       mask_block          ( block_size - 1                           ),
00590       current_dim         ( 0                                        ),
00591       num_segs            ( 0                                        ),
00592       num_blocks          ( 0                                        ),
00593       default_initial_value_ptr (NULL)
00594   {
00595 
00596     I(Max_Dim_Allowed > 0);
00597 
00598     if (max_dim > Max_Dim_Allowed)
00599       throw std::length_error ("Dimension too large"); 
00600 
00601     allocate_dir();
00602   }
00604   ~DynArray() 
00605   { 
00606     I(dir != NULL);
00607 
00608     release_dir();
00609   }
00621   void copy_array(const DynArray<T> & src_array)
00622   {
00623     for (int i = 0; i < src_array.current_dim; ++i)
00624       if (src_array.exist(i))
00625         (*this)[i] = src_array.access(i);
00626   }
00636   DynArray(const DynArray<T> & array) 
00637       throw (std::exception, std::bad_alloc)
00638     : pow_dir                   (array.pow_dir),
00639       pow_seg                   (array.pow_seg),
00640       pow_block                 (array.pow_block),
00641       seg_plus_block_pow        (array.seg_plus_block_pow),
00642       mask_seg_plus_block       (array.mask_seg_plus_block),
00643       dir_size                  (array.dir_size),
00644       seg_size                  (array.seg_size),
00645       block_size                (array.block_size),
00646       max_dim                   (array.max_dim),
00647       mask_seg                  (array.mask_seg),
00648       mask_block                (array.mask_block),
00649       current_dim               (0),
00650       num_segs                  (0),
00651       num_blocks                (0),
00652       default_initial_value_ptr (NULL)
00653   {
00654     allocate_dir();
00655     copy_array(array);
00656   }
00657 
00665   DynArray<T> & operator = (const DynArray<T> & array) 
00666     throw (std::exception, std::bad_alloc)
00667   {
00668     if (this == &array)
00669       return *this;
00670 
00671     copy_array(array);
00672     
00673     if (array.current_dim < current_dim)
00674       cut(array.current_dim);
00675 
00676     current_dim = array.current_dim;
00677 
00678     return *this;
00679   }
00690   void swap(DynArray<T> & array)
00691   {
00692     Aleph::swap(dir, array.dir);
00693     Aleph::swap(pow_dir,  array.pow_dir);
00694     Aleph::swap(pow_seg, array.pow_seg);
00695     Aleph::swap(pow_block, array.pow_block);
00696     Aleph::swap(seg_plus_block_pow, array.seg_plus_block_pow);
00697     Aleph::swap(mask_seg_plus_block, array.mask_seg_plus_block);
00698     Aleph::swap(dir_size, array.dir_size);
00699     Aleph::swap(seg_size, array.seg_size);
00700     Aleph::swap(block_size, array.block_size);
00701     Aleph::swap(mask_seg, array.mask_seg);
00702     Aleph::swap(mask_block, array.mask_block);
00703     Aleph::swap(max_dim, array.max_dim);
00704     Aleph::swap(current_dim, array.current_dim);
00705     Aleph::swap(num_segs, array.num_segs);
00706     Aleph::swap(num_blocks, array.num_blocks);
00707   }
00727   T & access(const size_t & i) 
00728   {
00729 
00730     I(dir[index_in_dir(i)] != NULL);
00731     I(dir[index_in_dir(i)][index_in_seg(i)] != NULL);
00732 
00733     return dir[index_in_dir(i)][index_in_seg(i)][index_in_block(i)];
00734   }
00735 
00755   const T & access(const size_t & i) const
00756   {
00757     I(dir[index_in_dir(i)] != NULL);
00758     I(dir[index_in_dir(i)][index_in_seg(i)] != NULL);
00759 
00760     return dir[index_in_dir(i)][index_in_seg(i)][index_in_block(i)];
00761   }
00762 
00777   bool exist(const size_t & i) const 
00778 
00779     throw (std::exception, std::out_of_range)
00780 
00781   {
00782 
00783     if (i >= max_dim)
00784       throw std::out_of_range ("index out of maximun range");
00785 
00786     const size_t pos_in_dir = index_in_dir(i);
00787        
00788 
00789     I(pos_in_dir < dir_size);
00790 
00791     if (dir[pos_in_dir] == NULL)
00792       return false;
00793 
00794     const size_t pos_in_seg = index_in_seg(i);
00795        
00796 
00797     I(pos_in_seg < seg_size);
00798 
00799     if (dir[pos_in_dir][pos_in_seg] == NULL) 
00800       return false;
00801 
00802     return true;
00803   }  
00804   T * test(const size_t & i)
00805   {
00806     const size_t pos_in_dir = index_in_dir(i);
00807        
00808     if (dir[pos_in_dir] == NULL)
00809       return NULL;
00810 
00811     const size_t pos_in_seg = index_in_seg(i);
00812        
00813     if (dir[pos_in_dir][pos_in_seg] == NULL) 
00814       return NULL;
00815 
00816     return &dir[index_in_dir(i)][index_in_seg(i)][index_in_block(i)];
00817   }
00829   T & touch(const size_t & i) 
00830 
00831     throw (std::exception, std::bad_alloc, std::out_of_range)
00832 
00833   {
00834 
00835     if (i >= max_dim)
00836       throw std::out_of_range ("index out of maximun range");
00837 
00838     const size_t pos_in_dir = index_in_dir(i);
00839 
00840     if (dir[pos_in_dir] == NULL)
00841       allocate_segment(dir[pos_in_dir]);
00842 
00843     const size_t pos_in_seg = index_in_seg(i);
00844 
00845     if (dir[pos_in_dir][pos_in_seg] == NULL)
00846 
00847       {
00848         try
00849           {
00850 
00851             allocate_block(dir[pos_in_dir][pos_in_seg]);
00852 
00853           }
00854         catch (...)
00855           {
00856             release_segment(dir[pos_in_dir]);
00857             throw;
00858           }
00859       }
00860 
00861     if (i >= current_dim)
00862       current_dim = i + 1;
00863 
00864     return dir[pos_in_dir][pos_in_seg][index_in_block(i)];
00865   }
00881   void reserve(const size_t & l, const size_t & r) 
00882 
00883     throw (std::exception, std::bad_alloc, std::domain_error, std::length_error) 
00884 
00885   {
00886 
00887     if (l > r)
00888       throw std::domain_error("invalid range");
00889 
00890     if (r >= max_dim)
00891       throw std::length_error ("dimension too large"); 
00892 
00893     const size_t first_seg = index_in_dir(l);
00894     const size_t last_seg  = index_in_dir(r);
00895 
00896     const size_t first_block = index_in_seg(l);
00897     const size_t last_block  = index_in_seg(r);
00898 
00899 
00900     try
00901       {
00902 
00903         for (size_t seg_idx = first_seg; seg_idx <= last_seg; ++seg_idx)
00904           {
00905             if (dir[seg_idx] == NULL)
00906               allocate_segment(dir[seg_idx]);
00907 
00908             size_t block_idx = (seg_idx == first_seg) ? first_block : 0;
00909 
00910             const size_t final_block = 
00911               (seg_idx == last_seg) ? last_block : seg_size - 1;
00912 
00913             while (block_idx <= final_block)
00914               {
00915                 if (dir[seg_idx][block_idx] == NULL)
00916                   allocate_block(dir[seg_idx][block_idx]);
00917 
00918                 ++block_idx; 
00919               }
00920           } // end for (...) 
00921 
00922         if (r + 1 > current_dim)
00923           current_dim = r + 1;
00924 
00925       }
00926     catch (...)
00927       {
00928         if (r + 1 > current_dim)
00929           current_dim = r + 1;
00930         throw;
00931       }
00932 
00933   }
00947   void cut(const size_t & new_dim = 0) 
00948 
00949     throw (std::exception, std::domain_error) 
00950 
00951   {
00952 
00953     if (new_dim > current_dim)
00954       throw std::domain_error("new dimension is greater that current dimension");
00955 
00956     if (new_dim == 0) 
00957       {
00958         release_all_segments_and_blocks();
00959         current_dim = 0;
00960         return;
00961       }
00962 
00963     const size_t old_dim = current_dim; // guarda antigua dimensión
00964 
00965         // índices cotas de bloques
00966     const int idx_first_seg   = index_in_dir(old_dim - 1);
00967     const int idx_first_block = index_in_seg(old_dim - 1);
00968     
00969         // índices cotas de segmentos
00970     const int idx_last_seg   = index_in_dir(new_dim - 1);
00971     const int idx_last_block = index_in_seg(new_dim - 1);    
00972     
00973         // recorre descendentemente los segmentos 
00974     for (int idx_seg = index_in_dir(old_dim - 1); idx_seg >= idx_last_seg; 
00975          --idx_seg)
00976       {
00977         if (dir[idx_seg] == NULL) // ¿hay un segmento?
00978           continue; // no ==> avance al siguiente
00979             
00980             // primer bloque a liberar 
00981         int idx_block = idx_seg == idx_first_seg ? idx_first_block : seg_size - 1;
00982             // Libera descendentemente los bloques reservados del segmento
00983         while ( (idx_seg > idx_last_seg and idx_block >= 0) or
00984                 (idx_seg == idx_last_seg and idx_block > idx_last_block) )
00985         {
00986           if (dir[idx_seg][idx_block] != NULL) // ¿Hay un bloque aquí?
00987             release_block(dir[idx_seg][idx_block]);
00988           --idx_block; 
00989         }
00990         if (idx_block < 0)
00991           release_segment(dir[idx_seg]);
00992       }
00993 
00994     I(dir[idx_last_seg] != NULL and dir[idx_last_seg][idx_last_block] != NULL);
00995 
00996 
00997     current_dim = new_dim; // actualiza nueva dimensión
00998   }
00999 
01000   Proxy operator [] (const size_t & i) const
01001     throw (std::exception, std::bad_alloc, std::length_error, 
01002            std::invalid_argument) 
01003   {
01004     if (i >= max_dim)
01005       throw std::out_of_range ("index out of maximun range");
01006 
01007     return Proxy (const_cast<DynArray<T>&>(*this), i);
01008   }
01009 
01010   Proxy operator [] (const size_t & i) 
01011 
01012     throw (std::exception, std::length_error, 
01013            std::invalid_argument, std::bad_alloc)
01014 
01015   {
01016 
01017     if (i >= max_dim)
01018       throw std::out_of_range ("index out of maximun range");
01019 
01020     return Proxy (const_cast<DynArray<T>&>(*this), i);
01021   }
01022 };
01023 
01024 template <typename T> const size_t DynArray<T>::Default_Pow_Dir   = 4;  /* 16   */
01025 template <typename T> const size_t DynArray<T>::Default_Pow_Seg   = 6;  /* 64   */
01026 template <typename T> const size_t DynArray<T>::Default_Pow_Block = 12; /* 4096 */
01027 template <typename T> const size_t DynArray<T>::Max_Bits_Allowed  = 8 * sizeof(size_t); 
01028 template <typename T> const size_t DynArray<T>::Max_Dim_Allowed   = 2*1024*1024*1024ul;
01029 
01030 template <typename T> const size_t DynArray<T>::Max_Pow_Block =
01031 (Max_Bits_Allowed - Default_Pow_Dir  - Default_Pow_Seg  - 1);
01032 
01033 } // end namespace Aleph
01034 
01035 # endif /* TPL_DYNARRAY_H */
01036 

Leandro R. León