26 template <
bool is_const = false>
27 class const_noconst_iterator;
32 using iterator = const_noconst_iterator<false>;
50 T &
at(
unsigned int j) {
return _data.at(j); }
77 unsigned int stride(
unsigned int j)
const;
82 void dataStore(std::ostream & stream,
void * context);
83 void dataLoad(std::istream & stream,
void * context);
127 template <
bool is_const>
131 typedef typename std::conditional<is_const, const MultiIndex<T> &,
MultiIndex<T> &>::type
135 : _multi_index(multi_index), _flat_index(position),
_shape(multi_index.
size())
137 _multi_index.findIndexVector(position, _indices);
149 _multi_index.findIndexVector(_flat_index, _indices);
161 for (
unsigned int j = 0; j < _indices.size(); ++j)
163 _indices[_indices.size() - j - 1] =
164 (_indices[_indices.size() - j - 1] + 1) %
_shape[_indices.size() - j - 1];
165 if (_indices[_indices.size() - j - 1] != 0)
177 for (
unsigned int j = 0; j < _indices.size(); ++j)
179 _indices[_indices.size() - j - 1] =
180 (_indices[_indices.size() - j - 1] + 1) %
_shape[_indices.size() - j - 1];
181 if (_indices[_indices.size() - j - 1] != 0)
192 for (
unsigned int j = 0; j < _indices.size(); ++j)
194 if (_indices[_indices.size() - j - 1] == 0)
195 _indices[_indices.size() - j - 1] =
_shape[_indices.size() - j - 1] - 1;
198 --_indices[_indices.size() - j - 1];
211 for (
unsigned int j = 0; j < _indices.size(); ++j)
213 if (_indices[_indices.size() - j - 1] == 0)
214 _indices[_indices.size() - j - 1] =
_shape[_indices.size() - j - 1] - 1;
217 --_indices[_indices.size() - j - 1];
234 return std::pair<const size_type &, T &>(_indices, _multi_index._data[_flat_index]);
236 std::pair<const size_type &, const T &>
operator*()
const 238 return std::pair<const size_type &, const T &>(_indices, _multi_index._data[_flat_index]);
252 _data.resize(_nentries);
260 if (data.size() != _nentries)
261 mooseError(
"shape and data arguments' sizes are inconsistent.");
269 return _data[flatIndex(indices)];
276 return _data[flatIndex(indices)];
285 return slice(
dim, ind);
293 if (dimension.size() != index.size())
294 mooseError(
"dimension and index must have the same size.");
295 if (dimension.size() > _dim - 1)
296 mooseError(
"The result of slice must be at least of dimension 1.");
299 for (
unsigned int d = 0; d < dimension.size(); ++d)
301 if (dimension[d] >= _dim)
302 mooseError(
"dimension is set to ", dimension[d],
" which is larger than _dim ", _dim);
303 if (index[d] >= _shape[dimension[d]])
309 _shape[dimension[d]]);
315 for (
unsigned int j = 0; j < _dim; ++j)
316 if (std::find(dimension.begin(), dimension.end(), j) == dimension.end())
317 new_shape.push_back(_shape[j]);
322 for (
unsigned int n = 0; n < _nentries; ++n)
325 findIndexVector(n, indices);
327 for (
unsigned int d = 0; d < dimension.size(); ++d)
328 if (indices[dimension[d]] != index[d])
336 (*it).second = _data[n];
347 if (shape.size() != _shape.size())
348 mooseError(
"resize cannot change the dimensionality of MultiIndex.");
353 std::vector<T> old_data = _data;
359 _data.assign(_nentries, T(0));
360 for (
unsigned int j = 0; j < _nentries; ++j)
363 findIndexVector(j, indices);
366 bool existed_in_old =
true;
367 for (
unsigned int d = 0; d < _dim; ++d)
368 if (indices[d] >= old_shape[d])
370 existed_in_old =
false;
377 unsigned int old_j = 0;
378 for (
unsigned int d = 0; d < _dim; ++d)
379 old_j += indices[d] * old_stride[d];
382 _data[j] = old_data[old_j];
391 mooseAssert(j < _dim,
"Dimension is" << _dim <<
", stride(j) called with j = " << j);
400 _data.assign(_nentries,
value);
417 _dim = _shape.size();
418 _nentries = _data.size();
419 buildAccumulatedShape();
427 for (
unsigned int d = 0; d < _dim; ++d)
429 unsigned int i = flat_index / _stride[d];
431 flat_index -= i * _stride[d];
442 _stride.resize(_dim);
443 for (
unsigned int d = 0; d < _dim; ++d)
446 for (
unsigned int j = d + 1; j < _dim; ++j)
456 if (shape.size() == 0)
469 for (
unsigned int d = 0; d < _dim; ++d)
470 _nentries *= _shape[d];
472 buildAccumulatedShape();
479 mooseAssert(indices.size() == _dim,
480 "Indices vector has wrong size. size=" << indices.size() <<
" vs. dim=" << _dim);
482 for (
unsigned int j = 0; j < indices.size(); ++j)
483 if (indices[j] >= _shape[j])
484 mooseError(
"Indices vector at entry ", j,
" is ", indices[j],
" vs. shape ", _shape[j]);
489 unsigned int index = 0;
490 for (
unsigned int d = 0; d < _dim; ++d)
491 index += indices[d] * _stride[d];
iterator begin()
iterators for begin and end of this container
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
unsigned int nEntries() const
total number of values stored in the container
const_noconst_iterator< true > const_iterator
const_noconst_iterator(reference_type multi_index, unsigned int position)
const T & operator[](unsigned int j) const
std::conditional< is_const, const MultiIndex< T > &, MultiIndex< T > & >::type reference_type
T & operator()(const size_type &indices)
element access operators
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
void dataLoad(std::istream &stream, MultiIndex< T > &mi, void *context)
reference_type _multi_index
std::vector< T > _data
the data unrolled into a vector
unsigned int _dim
the number of dimensions TODO: get rid of this -> _shape.size()
unsigned int dim() const
dimension of the container
unsigned int _nentries
the number of entries TODO: get rid of this -> _data.size()
void resize(const size_type &shape)
Resize container. Must keep dimensionality constant.
const_noconst_iterator< false > iterator
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
MultiIndex container iterator.
const size_type & size() const
container size as dim dimensional vector
MultiIndex(const size_type &shape)
construct zero initialized container of a given shape
void reshape(const size_type &shape)
change the container shape and reset meta data
std::pair< const size_type &, const T & > operator*() const
const_iterator begin() const
const size_type & stride() const
reference_type getMultiIndexObject() const
const_iterator end() const
std::vector< unsigned int > size_type
const_noconst_iterator & operator++()
const_noconst_iterator & operator--(int)
const_noconst_iterator & operator=(const const_noconst_iterator &other)
void findIndexVector(unsigned int flat_index, size_type &indices) const
given a flat index computes the vector of indices i0, i1, i2, ...
void buildAccumulatedShape()
build accumulated shape vector for flat index calculation
const_noconst_iterator & operator++(int)
void assign(const size_type &shape, T value)
Reshape container arbitrarily and initialize with value.
std::pair< const size_type &, T & > operator*()
dereferencing operator
unsigned int flatIndex(const size_type &indices) const
compute the flat index for a size_type index
void dataStore(std::ostream &stream, MultiIndex< T > &mi, void *context)
const_noconst_iterator & operator--()
MultiIndex< T > slice(unsigned int dimension, unsigned int index) const
accesses a slice of the multi index object
bool operator!=(const const_noconst_iterator &other) const
T & operator[](unsigned int j)
direct data access via bracket operator
unsigned int flatIndex() const
bool operator==(const const_noconst_iterator &other) const
to be equal both iterators must hold a reference to the same MultiIndexObject and be at the same _fla...
std::vector< T > getRawData() const
get the raw data vector
void dataLoad(std::istream &stream, void *context)
size_type _shape
the size along each index
T value_type
container related types and categories
size_type _stride
stride for each index, e.g. if you know {i, j, k} -> flat_index, {i, j + 1, k} = flat_index + stride[...
Implements a container class for multi-indexed objects with an arbitrary number of indices...
void dataStore(std::ostream &stream, void *context)
Implement loadHelper and storeHelper for easier data (de)serialization.