IterationPack_IterQuantityAccessContiguousDef.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
00005 //                  Copyright (2003) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 //
00029 // Definitions to template functions
00030 
00031 #ifndef ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H
00032 #define ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H
00033 
00034 #include <typeinfo>
00035 #include <algorithm>
00036 #include <iterator>
00037 
00038 #include "IterationPack_IterQuantityAccessContiguousDecl.hpp"
00039 #include "Teuchos_TestForException.hpp"
00040 
00041 namespace IterationPack {
00042 
00043 // Constructors/initializers
00044 
00045 template<class T_info>
00046 IterQuantityAccessContiguous<T_info>::IterQuantityAccessContiguous(
00047   int                              num_quantities
00048   ,const std::string&              name
00049   ,const abstract_factory_ptr_t&   abstract_factory
00050   )
00051   :num_quantities_(0)
00052   ,name_(name)
00053   ,abstract_factory_(abstract_factory)
00054   ,max_offset_(0)
00055 {
00056   resize( num_quantities );
00057 }
00058 
00059 template<class T_info>
00060 IterQuantityAccessContiguous<T_info>::~IterQuantityAccessContiguous() {
00061   release_mem();
00062 }
00063 
00064 template<class T_info>
00065 void IterQuantityAccessContiguous<T_info>::set_factory(
00066   const abstract_factory_ptr_t& abstract_factory
00067   )
00068 {
00069   release_mem();
00070   abstract_factory_ = abstract_factory;
00071   max_offset_ = std::numeric_limits<int>::min() + num_quantities_;  // uninitialized
00072   // ToDo: Don't wipe out storage, just reallocate new objects
00073   // as iteration quantities are updated.  This will take a little bit of
00074   // work and more overhead but it should be worth it in some types of
00075   // applications.
00076 }
00077 
00078 template<class T_info>
00079 void IterQuantityAccessContiguous<T_info>::resize( int num_quantities ) {
00080   TEST_FOR_EXCEPTION(
00081     num_quantities < 1, std::length_error
00082     ,"IterQuantityAccessContiguous::resize(num_quantities): Error, "
00083     "name = "<<name_<<", num_quantities = "<<num_quantities<<" must be greater than zero" );
00084   if( num_quantities_ != num_quantities )
00085     release_mem();
00086   num_quantities_ = num_quantities;
00087   max_offset_ = std::numeric_limits<int>::min() + num_quantities_; // uninitialized
00088 }
00089 
00090 // Overridden from IterQuantity
00091 
00092 template<class T_info>
00093 IterQuantity* IterQuantityAccessContiguous<T_info>::clone() const {
00094   return 0;
00095   // ToDo: replace above with the following when the copy
00096   // constructor is implemented.
00097   // return new IterQuantityAccessContiguous<T_info>(*this);
00098 }
00099 
00100 template<class T_info>
00101 const char* IterQuantityAccessContiguous<T_info>::name() const {
00102   return name_.c_str();
00103 }
00104 
00105 template<class T_info>
00106 bool IterQuantityAccessContiguous<T_info>::has_storage_k(int offset) const {
00107   return is_initialized()
00108     ? offset >= max_offset_ - num_quantities_ + 1
00109     : true;
00110 }
00111 
00112 template<class T_info>
00113 bool IterQuantityAccessContiguous<T_info>::updated_k(int offset) const {
00114   if( !is_initialized() )
00115     return false;
00116   if( ( offset > max_offset_ ) || ( offset < max_offset_ - num_quantities_ + 1 ) )
00117     return false;
00118   return updated_[max_offset_ - offset];
00119 }
00120 
00121 template<class T_info>
00122 int IterQuantityAccessContiguous<T_info>::last_updated() const {
00123   if( !is_initialized() )
00124     return base_t::NONE_UPDATED;
00125   // Find the last still set as updated.
00126   for(  int offset = max_offset_;
00127       offset >= max_offset_ - num_quantities_ + 1;
00128       --offset                    )
00129   {
00130     if( updated_[max_offset_ - offset] )
00131       return offset;
00132   }
00133   return base_t::NONE_UPDATED;
00134 }
00135 
00136 template<class T_info>
00137 void IterQuantityAccessContiguous<T_info>::set_not_updated_k(int offset) {
00138   this->assert_updated_k(offset);
00139   updated_[max_offset_ - offset] = false;
00140 }
00141 
00142 template<class T_info>
00143 void IterQuantityAccessContiguous<T_info>::set_all_not_updated() {
00144   if(!is_initialized()) return;
00145   std::fill( updated_.begin(), updated_.end(), false );
00146 }
00147 
00148 template<class T_info>
00149 bool IterQuantityAccessContiguous<T_info>::will_loose_mem(int offset, int set_offset) const {
00150   this->assert_updated_k(offset);
00151   return set_offset - max_offset_ > num_quantities_ - (max_offset_ - offset) - 1;
00152 }
00153 
00154 template<class T_info>
00155 void IterQuantityAccessContiguous<T_info>::next_iteration()
00156 {
00157   if( !is_initialized() ) return;
00158   --max_offset_;
00159 }
00160 
00161 template<class T_info>
00162 void IterQuantityAccessContiguous<T_info>::print_concrete_type( std::ostream& out ) const
00163 {
00164   const int last_updated = this->last_updated();
00165   if(last_updated != base_t::NONE_UPDATED)
00166     out << typeName(get_k(last_updated));
00167   else if( abstract_factory_.get() == NULL )
00168     out << "NULL";
00169   else
00170     out << typeName(*abstract_factory_->create());
00171 }
00172 
00173 // Overridden from IterQuantityAccess
00174 
00175 template<class T_info>
00176 T_info& IterQuantityAccessContiguous<T_info>::get_k(int offset) {
00177   this->assert_updated_k(offset);
00178   return *quantities_[max_offset_ - offset];
00179 }
00180 template<class T_info>
00181 const T_info& IterQuantityAccessContiguous<T_info>::get_k(int offset) const {
00182   this->assert_updated_k(offset);
00183   return *quantities_[max_offset_ - offset];
00184 }
00185 
00186 template<class T_info>
00187 T_info& IterQuantityAccessContiguous<T_info>::set_k(int offset) {
00188 
00189   lazy_initialization();
00190 
00191   this->assert_has_storage_k(offset); // assert that we are not trying to iterate backwards
00192 
00193   if(offset > max_offset_ + num_quantities_ - 1) {
00194     // There will be no back memory so you don't need to adjust the pointers
00195     max_offset_ = offset;
00196     std::fill(updated_.begin(), updated_.end(), false);
00197   }
00198   else {
00199     // Pointers may have to be rearranged
00200     if(offset > max_offset_) {
00201       // We need to rearrange quantities_ and updated_.
00202       int shifted = offset - max_offset_;
00203 
00204       // ///////////////////////////////////
00205       // Set the updated flags
00206 
00207       // Example: We are shifting from:
00208       //    [1, 0, -1, -2] to [ 3, 2, 1, 0 ]
00209 
00210       // Shift the flags for the memory that may be saved
00211       updated_t::iterator
00212         itr_updated_from        = updated_.begin(),
00213         itr_updated_from_end    = itr_updated_from + num_quantities_ - shifted,
00214         itr_updated_to          = itr_updated_from + shifted;
00215 
00216       std::copy(itr_updated_from, itr_updated_from_end, itr_updated_to);
00217 
00218       // make updated[] for the new quantities false
00219       std::fill_n( updated_.begin(), shifted, false );
00220 
00221       // /////////////////////////////////////
00222       // rotate the quantitiy pointer vector
00223 
00224       // example: [1, 0, -1, -2] => [3, 2, 1, 0] so reverse rotate 0 to the back.
00225 
00226       // Rotate the (num_quantities_ - shifted) pointer to the back and the
00227       // remainder back arround again.
00228 
00229 #if defined(_INTEL_CXX)
00230       typedef std::reverse_iterator<T_info**, T_info*, T_info*&
00231         , T_info**, ptrdiff_t>                  rev_t;
00232 #else
00233       typedef std::reverse_iterator<T_info**>           rev_t;
00234 #endif
00235 
00236       std::rotate(
00237           rev_t(&quantities_[0] + num_quantities_)
00238         , rev_t(&quantities_[0] + num_quantities_ - shifted)
00239         , rev_t(&quantities_[0])                              );
00240 
00241       max_offset_ = offset;
00242 
00243     }
00244     // else, no pointers need to be rearranged since we are not advancing the range
00245   }
00246 
00247   updated_[max_offset_ - offset] = true;
00248   return *quantities_[max_offset_ - offset];
00249 }
00250 
00251 template<class T_info>
00252 T_info& IterQuantityAccessContiguous<T_info>::set_k(int set_offset, int get_offset) {
00253   T_info& iq = this->get_k(get_offset);   // May throw exception
00254   return this->set_k(set_offset) = iq;    // ""
00255 }
00256 
00257 // Private member functions
00258 
00259 template<class T_info>
00260 bool IterQuantityAccessContiguous<T_info>::is_initialized() const {
00261   return store_.size() > 0;
00262 }
00263 
00264 template<class T_info>
00265 void IterQuantityAccessContiguous<T_info>::lazy_initialization() {
00266   if( !is_initialized() ) {
00267     TEST_FOR_EXCEPTION(
00268       abstract_factory_.get() == NULL, std::logic_error
00269       ,"IterQuantityAccessContiguous::lazy_initialization(): Error, "
00270       "iq_name = "<<name_<<" the abstract factory can not be NULL" );
00271     // Allocate storage
00272     updated_.resize(num_quantities_,false);
00273     store_.resize(num_quantities_);
00274     quantities_.resize(num_quantities_,NULL);
00275     // Set initial points to locations
00276     typename updated_t::iterator       itr_updated         = updated_.begin();
00277     typename store_t::iterator         itr_store           = store_.begin();
00278     typename quantities_t::iterator    itr_quantities      = quantities_.begin();
00279     for( ; itr_store != store_.end(); ++itr_updated, ++itr_store, ++itr_quantities )
00280     {
00281       *itr_updated     = false;
00282       *itr_store       = abstract_factory_->create();
00283       *itr_quantities  = itr_store->get();
00284     }
00285     max_offset_ = std::numeric_limits<int>::min() + num_quantities_ + 1;
00286   }
00287 }
00288 
00289 template<class T_info>
00290 void IterQuantityAccessContiguous<T_info>::release_mem() {
00291   updated_.resize(0);
00292   store_.resize(0);
00293   quantities_.resize(0);
00294 }
00295 
00296 } // end namespace IterationPack
00297 
00298 #endif  // ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H

Generated on Wed May 12 21:52:30 2010 for MOOCHO (Single Doxygen Collection) by  doxygen 1.4.7