📄 indirect.h
字号:
/*************************************************************************** * blitz/array/indirect.h Array indirection * * Copyright (C) 1997-2001 Todd Veldhuizen <tveldhui@oonumerics.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Suggestions: blitz-dev@oonumerics.org * Bugs: blitz-bugs@oonumerics.org * * For more information, please see the Blitz++ Home Page: * http://oonumerics.org/blitz/ * ****************************************************************************/#ifndef BZ_ARRAY_INDIRECT_H#define BZ_ARRAY_INDIRECT_H#include <blitz/array/asexpr.h>#include <blitz/array/cartesian.h>BZ_NAMESPACE(blitz)template<typename T_array, typename T_index>class IndirectArray {public: IndirectArray(T_array& array, T_index& index) : array_(array), index_(index) { } template<typename T_expr> void operator=(T_expr expr);protected: T_array& array_; T_index& index_;};// Forward declarationstemplate<typename T_array, typename T_arrayiter, typename T_subdomain, typename T_expr>inline void applyOverSubdomain(const T_array& array, T_arrayiter& arrayIter, T_subdomain subdomain, T_expr expr);template<typename T_array, typename T_arrayiter, int N_rank, typename T_expr>inline void applyOverSubdomain(const T_array& array, T_arrayiter& arrayIter, RectDomain<N_rank> subdomain, T_expr expr);template<typename T_array, typename T_index> template<typename T_rhs>void IndirectArray<T_array, T_index>::operator=(T_rhs rhs){ typedef _bz_typename asExpr<T_rhs>::T_expr T_expr; T_expr expr(rhs); _bz_typename T_array::T_iterator arrayIter(array_); _bz_typename T_index::iterator iter = index_.begin(), end = index_.end(); for (; iter != end; ++iter) { _bz_typename T_index::value_type subdomain = *iter; applyOverSubdomain(array_, arrayIter, subdomain, expr); }}template<typename T_array, typename T_arrayiter, typename T_subdomain, typename T_expr>inline void applyOverSubdomain(const T_array& BZ_DEBUG_PARAM(array), T_arrayiter& arrayIter, T_subdomain subdomain, T_expr expr){ BZPRECHECK(array.isInRange(subdomain), "In indirection using an STL container of TinyVector<int," << array.rank() << ">, one of the" << endl << "positions is out of" " range: " << endl << subdomain << endl << "Array lower bounds: " << array.lbound() << endl << "Array upper bounds: " << array.ubound() << endl) arrayIter.moveTo(subdomain); expr.moveTo(subdomain); *const_cast<_bz_typename T_arrayiter::T_numtype*>(arrayIter.data()) = *expr;}// Specialization for RectDomain<N>template<typename T_array, typename T_arrayiter, int N_rank, typename T_expr>inline void applyOverSubdomain(const T_array& BZ_DEBUG_PARAM(array), T_arrayiter& arrayIter, RectDomain<N_rank> subdomain, T_expr expr){ typedef _bz_typename T_array::T_numtype T_numtype; // Assume that the RectDomain<N_rank> is a 1-D strip. // Find the dimension in which the strip is oriented. This // variable is static so that we cache the value; likely to be // the same for all strips within a container. static int stripDim = 0; if (subdomain.lbound(stripDim) == subdomain.ubound(stripDim)) { // Cached value was wrong, find the correct value of stripDim for (stripDim=0; stripDim < N_rank; ++stripDim) if (subdomain.lbound(stripDim) != subdomain.ubound(stripDim)) break; // Handle case where the strip is just a single point if (stripDim == N_rank) stripDim = 0; }#ifdef BZ_DEBUG // Check that this is in fact a 1D strip for (int i=0; i < N_rank; ++i) if ((i != stripDim) && (subdomain.lbound(i) != subdomain.ubound(i))) BZPRECHECK(0, "In indirection using an STL container of RectDomain<" << N_rank << ">, one of" << endl << "the RectDomain objects was not" " a one-dimensional strip:" << endl << "RectDomain<" << N_rank << ">::lbound() = " << subdomain.lbound() << endl << "RectDomain<" << N_rank << ">::ubound() = " << subdomain.ubound())#endif // Check that the start and end position are in range BZPRECHECK(array.isInRange(subdomain.lbound()), "In indirection using an STL container of RectDomain<" << N_rank << ">, one of" << endl << "the RectDomain objects has a" " lbound which is out of range:" << endl << subdomain.lbound() << endl << "Array lower bounds: " << array.lbound() << endl << "Array upper bounds: " << array.ubound() << endl) BZPRECHECK(array.isInRange(subdomain.ubound()), "In indirection using an STL container of RectDomain<" << N_rank << ">, one of" << endl << "the RectDomain objects has a" " ubound which is out of range:" << endl << subdomain.lbound() << endl << "Array lower bounds: " << array.lbound() << endl << "Array upper bounds: " << array.ubound() << endl) // Position at the beginning of the strip arrayIter.moveTo(subdomain.lbound()); expr.moveTo(subdomain.lbound()); // Loop through the strip#ifdef BZ_USE_FAST_READ_ARRAY_EXPR bool useUnitStride = arrayIter.isUnitStride(stripDim) && expr.isUnitStride(stripDim); int lbound = subdomain.lbound(stripDim); int ubound = subdomain.ubound(stripDim); if (useUnitStride) { T_numtype* restrict data = const_cast<T_numtype*>(arrayIter.data()); int length = ubound - lbound + 1; for (int i=0; i < length; ++i) *data++ = expr.fastRead(i); } else {#endif arrayIter.loadStride(stripDim); expr.loadStride(stripDim); for (int i=lbound; i <= ubound; ++i) { *const_cast<_bz_typename T_arrayiter::T_numtype*>(arrayIter.data()) = *expr; expr.advance(); arrayIter.advance(); }#ifdef BZ_USE_FAST_READ_ARRAY_EXPR }#endif}// Global functions for cartesian product of index setstemplate<typename T_container>CartesianProduct<TinyVector<int,2>,T_container,2>indexSet(const T_container& container0, const T_container& container1){ return CartesianProduct<TinyVector<int,2>,T_container,2>( const_cast<T_container&>(container0), const_cast<T_container&>(container1));}template<typename T_container>CartesianProduct<TinyVector<int,3>,T_container,3>indexSet(const T_container& container0, const T_container& container1, const T_container& container2){ return CartesianProduct<TinyVector<int,3>,T_container,3>( const_cast<T_container&>(container0), const_cast<T_container&>(container1), const_cast<T_container&>(container2));}template<typename T_container>CartesianProduct<TinyVector<int,4>,T_container,4>indexSet(const T_container& container0, const T_container& container1, const T_container& container2, const T_container& container3){ return CartesianProduct<TinyVector<int,4>,T_container,4>( const_cast<T_container&>(container0), const_cast<T_container&>(container1), const_cast<T_container&>(container2), const_cast<T_container&>(container3));}template<typename T_container>CartesianProduct<TinyVector<int,5>,T_container,5>indexSet(const T_container& container0, const T_container& container1, const T_container& container2, const T_container& container3, const T_container& container4){ return CartesianProduct<TinyVector<int,5>,T_container,5>( const_cast<T_container&>(container0), const_cast<T_container&>(container1), const_cast<T_container&>(container2), const_cast<T_container&>(container3), const_cast<T_container&>(container4));}template<typename T_container>CartesianProduct<TinyVector<int,6>,T_container,6>indexSet(const T_container& container0, const T_container& container1, const T_container& container2, const T_container& container3, const T_container& container4, const T_container& container5){ return CartesianProduct<TinyVector<int,6>,T_container,6>( const_cast<T_container&>(container0), const_cast<T_container&>(container1), const_cast<T_container&>(container2), const_cast<T_container&>(container3), const_cast<T_container&>(container4), const_cast<T_container&>(container5));}template<typename T_container>CartesianProduct<TinyVector<int,7>,T_container,7>indexSet(const T_container& container0, const T_container& container1, const T_container& container2, const T_container& container3, const T_container& container4, const T_container& container5, const T_container& container6){ return CartesianProduct<TinyVector<int,7>,T_container,7>( const_cast<T_container&>(container0), const_cast<T_container&>(container1), const_cast<T_container&>(container2), const_cast<T_container&>(container3), const_cast<T_container&>(container4), const_cast<T_container&>(container5), const_cast<T_container&>(container6));}template<typename T_container>CartesianProduct<TinyVector<int,8>,T_container,8>indexSet(const T_container& container0, const T_container& container1, const T_container& container2, const T_container& container3, const T_container& container4, const T_container& container5, const T_container& container6, const T_container& container7){ return CartesianProduct<TinyVector<int,8>,T_container,8>( const_cast<T_container&>(container0), const_cast<T_container&>(container1), const_cast<T_container&>(container2), const_cast<T_container&>(container3), const_cast<T_container&>(container4), const_cast<T_container&>(container5), const_cast<T_container&>(container6), const_cast<T_container&>(container7));}template<typename T_container>CartesianProduct<TinyVector<int,9>,T_container,9>indexSet(const T_container& container0, const T_container& container1, const T_container& container2, const T_container& container3, const T_container& container4, const T_container& container5, const T_container& container6, const T_container& container7, const T_container& container8){ return CartesianProduct<TinyVector<int,9>,T_container,9>( const_cast<T_container&>(container0), const_cast<T_container&>(container1), const_cast<T_container&>(container2), const_cast<T_container&>(container3), const_cast<T_container&>(container4), const_cast<T_container&>(container5), const_cast<T_container&>(container6), const_cast<T_container&>(container7), const_cast<T_container&>(container8));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -