IterationPack: General framework for building iterative algorithms Version of the Day
IterationPack_IterQuantityAccessContiguousDef.hpp
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 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 
00038 // 
00039 // ***********************************************************************
00040 // @HEADER
00041 //
00042 // Definitions to template functions
00043 
00044 #ifndef ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H
00045 #define ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H
00046 
00047 #include <typeinfo>
00048 #include <algorithm>
00049 #include <iterator>
00050 
00051 #include "IterationPack_IterQuantityAccessContiguousDecl.hpp"
00052 #include "Teuchos_Assert.hpp"
00053 
00054 namespace IterationPack {
00055 
00056 // Constructors/initializers
00057 
00058 template<class T_info>
00059 IterQuantityAccessContiguous<T_info>::IterQuantityAccessContiguous(
00060   int                              num_quantities
00061   ,const std::string&              name
00062   ,const abstract_factory_ptr_t&   abstract_factory
00063   )
00064   :num_quantities_(0)
00065   ,name_(name)
00066   ,abstract_factory_(abstract_factory)
00067   ,max_offset_(0)
00068 {
00069   resize( num_quantities );
00070 }
00071 
00072 template<class T_info>
00073 IterQuantityAccessContiguous<T_info>::~IterQuantityAccessContiguous() {
00074   release_mem();
00075 }
00076 
00077 template<class T_info>
00078 void IterQuantityAccessContiguous<T_info>::set_factory(
00079   const abstract_factory_ptr_t& abstract_factory
00080   )
00081 {
00082   release_mem();
00083   abstract_factory_ = abstract_factory;
00084   max_offset_ = std::numeric_limits<int>::min() + num_quantities_;  // uninitialized
00085   // ToDo: Don't wipe out storage, just reallocate new objects
00086   // as iteration quantities are updated.  This will take a little bit of
00087   // work and more overhead but it should be worth it in some types of
00088   // applications.
00089 }
00090 
00091 template<class T_info>
00092 void IterQuantityAccessContiguous<T_info>::resize( int num_quantities ) {
00093   TEUCHOS_TEST_FOR_EXCEPTION(
00094     num_quantities < 1, std::length_error
00095     ,"IterQuantityAccessContiguous::resize(num_quantities): Error, "
00096     "name = "<<name_<<", num_quantities = "<<num_quantities<<" must be greater than zero" );
00097   if( num_quantities_ != num_quantities )
00098     release_mem();
00099   num_quantities_ = num_quantities;
00100   max_offset_ = std::numeric_limits<int>::min() + num_quantities_; // uninitialized
00101 }
00102 
00103 // Overridden from IterQuantity
00104 
00105 template<class T_info>
00106 IterQuantity* IterQuantityAccessContiguous<T_info>::clone() const {
00107   return 0;
00108   // ToDo: replace above with the following when the copy
00109   // constructor is implemented.
00110   // return new IterQuantityAccessContiguous<T_info>(*this);
00111 }
00112 
00113 template<class T_info>
00114 const char* IterQuantityAccessContiguous<T_info>::name() const {
00115   return name_.c_str();
00116 }
00117 
00118 template<class T_info>
00119 bool IterQuantityAccessContiguous<T_info>::has_storage_k(int offset) const {
00120   return is_initialized()
00121     ? offset >= max_offset_ - num_quantities_ + 1
00122     : true;
00123 }
00124 
00125 template<class T_info>
00126 bool IterQuantityAccessContiguous<T_info>::updated_k(int offset) const {
00127   if( !is_initialized() )
00128     return false;
00129   if( ( offset > max_offset_ ) || ( offset < max_offset_ - num_quantities_ + 1 ) )
00130     return false;
00131   return updated_[max_offset_ - offset];
00132 }
00133 
00134 template<class T_info>
00135 int IterQuantityAccessContiguous<T_info>::last_updated() const {
00136   if( !is_initialized() )
00137     return base_t::NONE_UPDATED;
00138   // Find the last still set as updated.
00139   for(  int offset = max_offset_;
00140       offset >= max_offset_ - num_quantities_ + 1;
00141       --offset                    )
00142   {
00143     if( updated_[max_offset_ - offset] )
00144       return offset;
00145   }
00146   return base_t::NONE_UPDATED;
00147 }
00148 
00149 template<class T_info>
00150 void IterQuantityAccessContiguous<T_info>::set_not_updated_k(int offset) {
00151   this->assert_updated_k(offset);
00152   updated_[max_offset_ - offset] = false;
00153 }
00154 
00155 template<class T_info>
00156 void IterQuantityAccessContiguous<T_info>::set_all_not_updated() {
00157   if(!is_initialized()) return;
00158   std::fill( updated_.begin(), updated_.end(), false );
00159 }
00160 
00161 template<class T_info>
00162 bool IterQuantityAccessContiguous<T_info>::will_loose_mem(int offset, int set_offset) const {
00163   this->assert_updated_k(offset);
00164   return set_offset - max_offset_ > num_quantities_ - (max_offset_ - offset) - 1;
00165 }
00166 
00167 template<class T_info>
00168 void IterQuantityAccessContiguous<T_info>::next_iteration()
00169 {
00170   if( !is_initialized() ) return;
00171   --max_offset_;
00172 }
00173 
00174 template<class T_info>
00175 void IterQuantityAccessContiguous<T_info>::print_concrete_type( std::ostream& out ) const
00176 {
00177   const int last_updated = this->last_updated();
00178   if(last_updated != base_t::NONE_UPDATED)
00179     out << typeName(get_k(last_updated));
00180   else if( abstract_factory_.get() == NULL )
00181     out << "NULL";
00182   else
00183     out << typeName(*abstract_factory_->create());
00184 }
00185 
00186 // Overridden from IterQuantityAccess
00187 
00188 template<class T_info>
00189 T_info& IterQuantityAccessContiguous<T_info>::get_k(int offset) {
00190   this->assert_updated_k(offset);
00191   return *quantities_[max_offset_ - offset];
00192 }
00193 template<class T_info>
00194 const T_info& IterQuantityAccessContiguous<T_info>::get_k(int offset) const {
00195   this->assert_updated_k(offset);
00196   return *quantities_[max_offset_ - offset];
00197 }
00198 
00199 template<class T_info>
00200 T_info& IterQuantityAccessContiguous<T_info>::set_k(int offset) {
00201 
00202   lazy_initialization();
00203 
00204   this->assert_has_storage_k(offset); // assert that we are not trying to iterate backwards
00205 
00206   if(offset > max_offset_ + num_quantities_ - 1) {
00207     // There will be no back memory so you don't need to adjust the pointers
00208     max_offset_ = offset;
00209     std::fill(updated_.begin(), updated_.end(), false);
00210   }
00211   else {
00212     // Pointers may have to be rearranged
00213     if(offset > max_offset_) {
00214       // We need to rearrange quantities_ and updated_.
00215       int shifted = offset - max_offset_;
00216 
00217       // ///////////////////////////////////
00218       // Set the updated flags
00219 
00220       // Example: We are shifting from:
00221       //    [1, 0, -1, -2] to [ 3, 2, 1, 0 ]
00222 
00223       // Shift the flags for the memory that may be saved
00224       updated_t::iterator
00225         itr_updated_from        = updated_.begin(),
00226         itr_updated_from_end    = itr_updated_from + num_quantities_ - shifted,
00227         itr_updated_to          = itr_updated_from + shifted;
00228 
00229       std::copy(itr_updated_from, itr_updated_from_end, itr_updated_to);
00230 
00231       // make updated[] for the new quantities false
00232       std::fill_n( updated_.begin(), shifted, false );
00233 
00234       // /////////////////////////////////////
00235       // rotate the quantitiy pointer vector
00236 
00237       // example: [1, 0, -1, -2] => [3, 2, 1, 0] so reverse rotate 0 to the back.
00238 
00239       // Rotate the (num_quantities_ - shifted) pointer to the back and the
00240       // remainder back arround again.
00241 
00242 #if defined(_INTEL_CXX)
00243       typedef std::reverse_iterator<T_info**, T_info*, T_info*&
00244         , T_info**, ptrdiff_t>                  rev_t;
00245 #else
00246       typedef std::reverse_iterator<T_info**>           rev_t;
00247 #endif
00248 
00249       std::rotate(
00250           rev_t(&quantities_[0] + num_quantities_)
00251         , rev_t(&quantities_[0] + num_quantities_ - shifted)
00252         , rev_t(&quantities_[0])                              );
00253 
00254       max_offset_ = offset;
00255 
00256     }
00257     // else, no pointers need to be rearranged since we are not advancing the range
00258   }
00259 
00260   updated_[max_offset_ - offset] = true;
00261   return *quantities_[max_offset_ - offset];
00262 }
00263 
00264 template<class T_info>
00265 T_info& IterQuantityAccessContiguous<T_info>::set_k(int set_offset, int get_offset) {
00266   T_info& iq = this->get_k(get_offset);   // May throw exception
00267   return this->set_k(set_offset) = iq;    // ""
00268 }
00269 
00270 // Private member functions
00271 
00272 template<class T_info>
00273 bool IterQuantityAccessContiguous<T_info>::is_initialized() const {
00274   return store_.size() > 0;
00275 }
00276 
00277 template<class T_info>
00278 void IterQuantityAccessContiguous<T_info>::lazy_initialization() {
00279   if( !is_initialized() ) {
00280     TEUCHOS_TEST_FOR_EXCEPTION(
00281       abstract_factory_.get() == NULL, std::logic_error
00282       ,"IterQuantityAccessContiguous::lazy_initialization(): Error, "
00283       "iq_name = "<<name_<<" the abstract factory can not be NULL" );
00284     // Allocate storage
00285     updated_.resize(num_quantities_,false);
00286     store_.resize(num_quantities_);
00287     quantities_.resize(num_quantities_,NULL);
00288     // Set initial points to locations
00289     typename updated_t::iterator       itr_updated         = updated_.begin();
00290     typename store_t::iterator         itr_store           = store_.begin();
00291     typename quantities_t::iterator    itr_quantities      = quantities_.begin();
00292     for( ; itr_store != store_.end(); ++itr_updated, ++itr_store, ++itr_quantities )
00293     {
00294       *itr_updated     = false;
00295       *itr_store       = abstract_factory_->create();
00296       *itr_quantities  = itr_store->get();
00297     }
00298     max_offset_ = std::numeric_limits<int>::min() + num_quantities_ + 1;
00299   }
00300 }
00301 
00302 template<class T_info>
00303 void IterQuantityAccessContiguous<T_info>::release_mem() {
00304   updated_.resize(0);
00305   store_.resize(0);
00306   quantities_.resize(0);
00307 }
00308 
00309 } // end namespace IterationPack
00310 
00311 #endif  // ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends