|
IterationPack: General framework for building iterative algorithms
Version of the Day
|
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
1.7.6.1