MOOCHO (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IterationPack_IterQuantityAccessContiguousDef.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
5 // Copyright (2003) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 //
42 // Definitions to template functions
43 
44 #ifndef ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H
45 #define ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H
46 
47 #include <typeinfo>
48 #include <algorithm>
49 #include <iterator>
50 
52 #include "Teuchos_Assert.hpp"
53 
54 namespace IterationPack {
55 
56 // Constructors/initializers
57 
58 template<class T_info>
60  int num_quantities
61  ,const std::string& name
62  ,const abstract_factory_ptr_t& abstract_factory
63  )
64  :num_quantities_(0)
65  ,name_(name)
66  ,abstract_factory_(abstract_factory)
67  ,max_offset_(0)
68 {
69  resize( num_quantities );
70 }
71 
72 template<class T_info>
74  release_mem();
75 }
76 
77 template<class T_info>
79  const abstract_factory_ptr_t& abstract_factory
80  )
81 {
82  release_mem();
83  abstract_factory_ = abstract_factory;
84  max_offset_ = std::numeric_limits<int>::min() + num_quantities_; // uninitialized
85  // ToDo: Don't wipe out storage, just reallocate new objects
86  // as iteration quantities are updated. This will take a little bit of
87  // work and more overhead but it should be worth it in some types of
88  // applications.
89 }
90 
91 template<class T_info>
94  num_quantities < 1, std::length_error
95  ,"IterQuantityAccessContiguous::resize(num_quantities): Error, "
96  "name = "<<name_<<", num_quantities = "<<num_quantities<<" must be greater than zero" );
97  if( num_quantities_ != num_quantities )
98  release_mem();
99  num_quantities_ = num_quantities;
100  max_offset_ = std::numeric_limits<int>::min() + num_quantities_; // uninitialized
101 }
102 
103 // Overridden from IterQuantity
104 
105 template<class T_info>
107  return 0;
108  // ToDo: replace above with the following when the copy
109  // constructor is implemented.
110  // return new IterQuantityAccessContiguous<T_info>(*this);
111 }
112 
113 template<class T_info>
115  return name_.c_str();
116 }
117 
118 template<class T_info>
120  return is_initialized()
121  ? offset >= max_offset_ - num_quantities_ + 1
122  : true;
123 }
124 
125 template<class T_info>
127  if( !is_initialized() )
128  return false;
129  if( ( offset > max_offset_ ) || ( offset < max_offset_ - num_quantities_ + 1 ) )
130  return false;
131  return updated_[max_offset_ - offset];
132 }
133 
134 template<class T_info>
136  if( !is_initialized() )
137  return base_t::NONE_UPDATED;
138  // Find the last still set as updated.
139  for( int offset = max_offset_;
140  offset >= max_offset_ - num_quantities_ + 1;
141  --offset )
142  {
143  if( updated_[max_offset_ - offset] )
144  return offset;
145  }
146  return base_t::NONE_UPDATED;
147 }
148 
149 template<class T_info>
151  this->assert_updated_k(offset);
152  updated_[max_offset_ - offset] = false;
153 }
154 
155 template<class T_info>
157  if(!is_initialized()) return;
158  std::fill( updated_.begin(), updated_.end(), false );
159 }
160 
161 template<class T_info>
162 bool IterQuantityAccessContiguous<T_info>::will_loose_mem(int offset, int set_offset) const {
163  this->assert_updated_k(offset);
164  return set_offset - max_offset_ > num_quantities_ - (max_offset_ - offset) - 1;
165 }
166 
167 template<class T_info>
169 {
170  if( !is_initialized() ) return;
171  --max_offset_;
172 }
173 
174 template<class T_info>
176 {
177  const int last_updated = this->last_updated();
178  if(last_updated != base_t::NONE_UPDATED)
179  out << typeName(get_k(last_updated));
180  else if( abstract_factory_.get() == NULL )
181  out << "NULL";
182  else
183  out << typeName(*abstract_factory_->create());
184 }
185 
186 // Overridden from IterQuantityAccess
187 
188 template<class T_info>
190  this->assert_updated_k(offset);
191  return *quantities_[max_offset_ - offset];
192 }
193 template<class T_info>
194 const T_info& IterQuantityAccessContiguous<T_info>::get_k(int offset) const {
195  this->assert_updated_k(offset);
196  return *quantities_[max_offset_ - offset];
197 }
198 
199 template<class T_info>
201 
202  lazy_initialization();
203 
204  this->assert_has_storage_k(offset); // assert that we are not trying to iterate backwards
205 
206  if(offset > max_offset_ + num_quantities_ - 1) {
207  // There will be no back memory so you don't need to adjust the pointers
208  max_offset_ = offset;
209  std::fill(updated_.begin(), updated_.end(), false);
210  }
211  else {
212  // Pointers may have to be rearranged
213  if(offset > max_offset_) {
214  // We need to rearrange quantities_ and updated_.
215  int shifted = offset - max_offset_;
216 
217  // ///////////////////////////////////
218  // Set the updated flags
219 
220  // Example: We are shifting from:
221  // [1, 0, -1, -2] to [ 3, 2, 1, 0 ]
222 
223  // Shift the flags for the memory that may be saved
224  updated_t::iterator
225  itr_updated_from = updated_.begin(),
226  itr_updated_from_end = itr_updated_from + num_quantities_ - shifted,
227  itr_updated_to = itr_updated_from + shifted;
228 
229  std::copy(itr_updated_from, itr_updated_from_end, itr_updated_to);
230 
231  // make updated[] for the new quantities false
232  std::fill_n( updated_.begin(), shifted, false );
233 
234  // /////////////////////////////////////
235  // rotate the quantitiy pointer vector
236 
237  // example: [1, 0, -1, -2] => [3, 2, 1, 0] so reverse rotate 0 to the back.
238 
239  // Rotate the (num_quantities_ - shifted) pointer to the back and the
240  // remainder back arround again.
241 
242 #if defined(_INTEL_CXX)
243  typedef std::reverse_iterator<T_info**, T_info*, T_info*&
244  , T_info**, ptrdiff_t> rev_t;
245 #else
246  typedef std::reverse_iterator<T_info**> rev_t;
247 #endif
248 
249  std::rotate(
250  rev_t(&quantities_[0] + num_quantities_)
251  , rev_t(&quantities_[0] + num_quantities_ - shifted)
252  , rev_t(&quantities_[0]) );
253 
254  max_offset_ = offset;
255 
256  }
257  // else, no pointers need to be rearranged since we are not advancing the range
258  }
259 
260  updated_[max_offset_ - offset] = true;
261  return *quantities_[max_offset_ - offset];
262 }
263 
264 template<class T_info>
265 T_info& IterQuantityAccessContiguous<T_info>::set_k(int set_offset, int get_offset) {
266  T_info& iq = this->get_k(get_offset); // May throw exception
267  return this->set_k(set_offset) = iq; // ""
268 }
269 
270 // Private member functions
271 
272 template<class T_info>
274  return store_.size() > 0;
275 }
276 
277 template<class T_info>
279  if( !is_initialized() ) {
281  abstract_factory_.get() == NULL, std::logic_error
282  ,"IterQuantityAccessContiguous::lazy_initialization(): Error, "
283  "iq_name = "<<name_<<" the abstract factory can not be NULL" );
284  // Allocate storage
285  updated_.resize(num_quantities_,false);
286  store_.resize(num_quantities_);
287  quantities_.resize(num_quantities_,NULL);
288  // Set initial points to locations
289  typename updated_t::iterator itr_updated = updated_.begin();
290  typename store_t::iterator itr_store = store_.begin();
291  typename quantities_t::iterator itr_quantities = quantities_.begin();
292  for( ; itr_store != store_.end(); ++itr_updated, ++itr_store, ++itr_quantities )
293  {
294  *itr_updated = false;
295  *itr_store = abstract_factory_->create();
296  *itr_quantities = itr_store->get();
297  }
298  max_offset_ = std::numeric_limits<int>::min() + num_quantities_ + 1;
299  }
300 }
301 
302 template<class T_info>
304  updated_.resize(0);
305  store_.resize(0);
306  quantities_.resize(0);
307 }
308 
309 } // end namespace IterationPack
310 
311 #endif // ITER_QUANITY_ACCESS_CONTINUOUS_DEF_H
void resize(int num_quantities)
Resize the number of contiguous storage locations.
std::string typeName(const T &t)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void set_factory(const abstract_factory_ptr_t &abstract_factory)
Set the abstract factory to use to allocate storate.
Iterface for information about Iteration Quantities.
void copy(const f_int &N, const f_dbl_prec *X, const f_int &INCX, f_dbl_prec *Y, const f_int &INCY)
std::ostream * out