|
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 // 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
1.7.4