.. highlight:: c array and array_view ============================ array and array_view are the class for standard d-dimensional cuboid array and the corresponding view. Template parameters ---------------------------- * The class has four template parameters (same for array_view). .. code-block:: c array ============================ ========================== ======================================= Template parameter Access in the class Meaning ============================ ========================== ======================================= ValueType value_type The type of the element of the array Rank rank The rank of the array *[int]* IndexOrderTag indexmap_type The ordering in memory : can be Tag::C, Tag::Fortran or a permutation StorageTag storage_type The storage : Tag::shared_block or Tag::numpy ============================ ========================== ======================================= * Various IndexOrderTag are possible : ================= ==================================================================================================== IndexOrderTag Meaning ================= ==================================================================================================== Tag::C C-style order *[default]* Tag::Fortran Fortran-style order P - P is a permutation - Determined by a permutation P at compile time. Explain here the permutation, the convention. ================= ==================================================================================================== * Two possible storages : ================== ============================================================================ StorageTag Meaning ================== ============================================================================ Tag::shared_block a (shared_ptr on a) C++ block *[default]* Tag::numpy stored in a numpy array, in which case the array is also a numpy array and read numpy, be returned as numpy, sliced into a numpy, etc... ================== ============================================================================ .. _array_constructors: Constructors ----------------- Intentionally, array and array_view have only a few constructors : ========================================== =========================================================================================== Constructors of array Comments ========================================== =========================================================================================== array() - empty array of size 0 array(size_t, ...., size_t) - from the dimensions array(cuboid_domain const &) - a new array with the corresponding cuboid array(const array &) - copy construction array(const T & X) - Type T models the :ref:`HasImmutableArrayInterface` concept. - X must have the appropriate domain (checked at compile time). - Enabled iif has_immutable_array_interface::value == true. - Constructs a new array of domain X.domain() and fills it with evaluation of X. ========================================== =========================================================================================== ====================================================================== ======================================================================================= Constructors of array_view Comments ====================================================================== ======================================================================================= array_view(indexmap_type const & I, S_type const &) from a couple of indexmap I and storage of type S_type array_view(const T & X) T is any type such that X.indexmap() and X.storage(). Models ISP ... ====================================================================== ======================================================================================= array_view are typically constructed by slicing (Cf below). * Examples :: array A(10,2); array Af (2,2); //Higher dim, custom order : array > A0 (2,3,4); array > A1 (2,3,4); array > A2 (2,3,4); array A3 (2,3,4); array A4 (2,3,4); Access to data, domain, simple evaluation, ... -------------------------------------------------------- array, array_view, matrix, matrix_view, vector, vector_view model HasImmutableArrayInterface. Assignment & Copy -------------------- Every classes comes in two flavors: C and C_view (with C = array, matrix, vector, etc...). These two flavors differ in the way they handle their data in construction, copy construction, assignement. Basically, C owns its data, while C_view if only a view. array, matrix, vector ^^^^^^^^^^^^^^^^^^^^^^^^ They own their data. In many aspects, they are similar to like std::vector. * The data are contiguous in memory. * Constructors and copy constructors all create a new memory block. If needed, they make a *true* copy of the data. * The assignment operator may create a new Storage if size do not match. * As a result, /pointers to the data/ and reference to the storage are invalid after assignment. * They can be resized, again invalidating all references. array_view, matrix_view, vector_view ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ These classes do not own their data, but only present a view of them. * The data may not be contiguous in memory (e.g. if the view is the result of a slice). * Constructors only make another view of the data. * They *never* copy data, so they are quite quick. In particular, copy constructor makes shallow copy (i.e. return another view). * The assignement operator just copy data into the view. Behaviour is undefined if the size of the view is too small (define the macro ARRAY_CHECK for dynamical debugging checks). * Pointers to data taken from the views are still valid after assignement. * Views can be not be resized. .. warning:: **Memory management** Views carry a reference to the memory block they view, which guarantees that memory will not be dellocated before the destruction of the view. Indeed, the Storage types implement incorporated a reference counting mechanism, either using boost::shared_ptr for the C++ arrays, or using the python references for the numpy storage. The memory block will be dellocated when its array and all array_view pointing to it or to a portion of it will be destroyed, and only at that moment. Examples:: array *A = new array (Matrix(2,3)); // create an array A array_view B(*A); // making a view delete A; // A is gone... cout< array & operator=(const RHS & X); * RHS models HasImmutableArrayInterface. * array is first resized to have a domain X.domain(), and then filled with the evaluation of X (e.g. a copy if X is an array, computing the value if X is an expression). array_view, matrix_view, vector_view ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //.. cpp:function:: template array_view & operator=(const RHS & X); * RHS models HasImmutableArrayInterface [ or less ? : RHS can be evaluated in the domain_type::value_type, no domain needed.]. * Dimension of the view must match or behaviour is undefined. Iterators and interaction with STL containers and algorithms ---------------------------------------------------------------- STL compliant iterators, hence STL algorithms work... Examples:: array A (2,3); // first print the index generator for (array::indexmap_type::domain_type::generator it = A.indexmap().domain().begin(); !it.at_end(); ++it) cout<<" "<<*it<::iterator it = A.begin(); !it.at_end(); ++it) { *it =it.indices().get<0>() + 10 *it.indices().get<1>() ; } int u=0; for (array::iterator it = A.begin(); !it.at_end(); ++it,++u) { *it =u; } array A (2,3); std::vector > VV; VV.push_back(A); map > MAP; MAP["1"] = A; // Trying to put a vector in an array std::vector V (10); array B(V.size()), C(V.size()); for (unsigned int i =0; i<10; ++i) V[i] = 10+i; std::copy(V.begin(),V.end(),B.begin()); std::copy(B.begin(),B.end(),V.begin()); cout<<" Number of elements <25 : "<< std::count_if(B.begin(), B.end(),te)< A (2,3); array_view SL( A(range(0,2),0)); array_view SL2( A(1,range(0,2))); It is the standard way to produce a view. NB : * we use here the python convention: range(0,3) is 0:3, i.e. 0,1,2 NOT 0,1,2,3. * Todo : in fact we should wrap the range to python::slice for interoperability with python. Serialization ------------------------------------------------- * Boost.serialization * Boost.mpi Examples:: array A (2,2), B(2,2),C(2,2); boost::mpi::reduce (world, A,C, std::plus >(),0); * HDF5 (ALPS), eg. Examples:: array A (2,3),B,vc; array Af,Bf,vf; alps::hdf5::oarchive ar1("data.h5"); ar1 << alps::make_pvp("Tableau", A); ar1 << alps::make_pvp("Tableau2", Af); ar1 << alps::make_pvp("Tableau_view", A(range(),range(1,3))); alps::hdf5::iarchive ar2("data.h5"); ar2 >> alps::make_pvp("Tableau", B); ar2 >> alps::make_pvp("Tableau", Bf); ar2 >> alps::make_pvp("Tableau_view", vc); ar2 >> alps::make_pvp("TableauC",C); blas/lapack interface ------------------------------------------------- * matrix, vector and their views are interfaced with blas/lapack, via boost::numerics::bindings. * If needed (for a view), a temporary (and silent) copy is made to reorganize the data before calling blas/lapack (impl: cache class). Of course, performance is altered, but code is simple... Examples:: namespace blas = boost::numeric::bindings::blas; namespace lapack = boost::numeric::bindings::lapack; triqs_arrays::vector > V(5),V2(5); triqs_arrays::vector V3(2); triqs_arrays::matrix M1(2,2), M2(2,2), M3(2,2); blas::axpy(2.0,V,V2); blas::gemm(1.0,M1, M2, 1.0, M3); blas::ger(1.0,V3,V3,M2); // invert triqs_arrays::vector ipiv(2); lapack::getrf(M1, ipiv); lapack::getri(M1, ipiv); Transparent use of python arrays ------------------------------------------------- * If the storage is Tag::numpy, the memory block is allocated/viewed through the numpy interface. * One can mix arrays with any storage in expression (they have the same concepts). * boost python converters are enable for those arrays into numpy and their views [impl :broken for views]. Expression ------------------------------------------------- Simple expressions are made using boost.proto. Examples :: array A (2,2), B(2,2),C; C= A + 2*B; array D( A+ 2*B); // or even in C++0x : auto e = A + 2*B; // expression, purely formal array D(e); // really makes the computation cout<< e < A (2,2), B(2,2),C(2,2); C= A + 2*B; C= std::plus >()(A,B); C = A + Transpose(B); // Transpose(X) returns a lazy object that models HasImmutableArrayInterface. C = A + Transpose(B + B); // X can also be an expression... C = Transpose(B); // array F( 0.5 * A); // Type promotion is automatic // non square array R(2,3),Rt(3,2); cout<<" R = "<< array(Transpose(R)) <