3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-25 13:53:40 +01:00

[arrays] Important changes in implementation.

- Simplify group_indices
  - Only for C ordered, remove complex compile time.
  - Could be generalized to non C ordered, but no need.
- Fix slice for custom orders.
- Generalize the group_indices for the custom order.
- Add c_ordered_transposed_view (useful ?)
- Improve slice, special for ellipsis (quicker).
- Simplify TraversalOrder
- Assignement. Specialize one case for speed.
- use FORCEINLINE in foreach, according to speed test for clang
- add one speed test
- Modify iterators for better speed.
- along the lines decided for the foreach
- update doc.
This commit is contained in:
Olivier Parcollet 2014-09-07 14:34:10 +02:00
parent d1c8a9a46e
commit 47cb8a03f7
57 changed files with 1855 additions and 1549 deletions

View File

@ -2,7 +2,7 @@
using namespace triqs::arrays; using namespace triqs::arrays;
int main() { int main() {
array<long, 2> A(2, 2); array<long, 2> A(2, 2);
matrix<long, 2> M(2, 2); matrix<long> M(2, 2);
// M + A; // --> ERROR. Rejected by the compiler. // M + A; // --> ERROR. Rejected by the compiler.
M + make_matrix_view(A); //--> OK. M + make_matrix_view(A); //--> OK.
} }

View File

@ -17,17 +17,17 @@ int main() {
// a vector of double // a vector of double
vector<double> V(10); vector<double> V(10);
// arrays with custom TraversalOrder // arrays with custom memory layout
// C-style // C-style
array<long, 3, 0, permutation(2, 1, 0)> A0(2, 3, 4); array<long, 3> A0(2, 3, 4);
array<long, 3, 0> A0b; // same type but empty array<long, 3> A0b; // same type but empty
// Fortran-style // Fortran-style
array<long, 3, TRAVERSAL_ORDER_FORTRAN> A4(2, 3, 4); array<long, 3> A4(2, 3, 4, FORTRAN_LAYOUT);
array<long, 3, 0, permutation(0, 1, 2)> A1b; // same type but empty array<long, 3> A1b(FORTRAN_LAYOUT); // same type but empty
// custom : (i,j,k) : index j is fastest, then k, then i // custom : (i,j,k) : index j is fastest, then k, then i
array<long, 3, 0, permutation(1, 0, 2)> A2(2, 3, 4); array<long, 3> A2(2, 3, 4, triqs::arrays::make_memory_layout(1, 0, 2));
} }

View File

@ -7,15 +7,9 @@ array, matrix & vector
.. code-block:: c .. code-block:: c
template <typename ValueType, int Rank, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class array; template <typename ValueType, int Rank, typename TraversalOrder=void> class array;
template <typename ValueType, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class matrix; template <typename ValueType, typename TraversalOrder=void> class matrix;
template <typename ValueType, ull_t OptionsFlags=0> class vector; template <typename ValueType> class vector;
where triqs::ull_t is the type defined by :
.. code-block:: c
typedef unsigned long long ull_t;
* The library provides three basic containers: * The library provides three basic containers:
@ -41,9 +35,8 @@ Template parameters
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+ +-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
| Rank | int | rank | The rank of the array | | Rank | int | rank | The rank of the array |
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+ +-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
| :ref:`OptionsFlags<arr_templ_par_opt>` | ull_t | opt_flags | Compile time options | | :ref:`TraversalOrder<arr_templ_par_to>` | ull_t | | Traversal Order for loops and |
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+ | | | | iterators |
| :ref:`TraversalOrder<arr_templ_par_to>` | ull_t | | Traversal Order for all loops |
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+ +-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
NB: Rank is only present for array, since matrix have rank 2 and vector rank 1. NB: Rank is only present for array, since matrix have rank 2 and vector rank 1.

View File

@ -4,7 +4,7 @@ int main() {
array<double, 2> A(2, 3); array<double, 2> A(2, 3);
A.resize(make_shape(5, 5)); A.resize(make_shape(5, 5));
matrix<double, 2> M; matrix<double> M;
M.resize(3, 3); M.resize(3, 3);
vector<double> V; vector<double> V;

View File

@ -7,14 +7,14 @@ operator <<
**Synopsis**:: **Synopsis**::
template <typename ValueType, int Rank, ull_t OptionsFlags=0, ull_t TraversalOrder=0> template <typename ValueType, int Rank, typename TraversalOrder=void>
std::ostream & operator << (std::ostream & out, array_view<ValueType,Rank,OptionsFlags,TraversalOrder> const &); std::ostream & operator << (std::ostream & out, array_view<ValueType,Rank,TraversalOrder> const &);
template <typename ValueType, ull_t OptionsFlags=0, ull_t TraversalOrder=0> template <typename ValueType, typename TraversalOrder=void>
std::ostream & operator << (std::ostream & out, matrix_view<ValueType,OptionsFlags,TraversalOrder> const &); std::ostream & operator << (std::ostream & out, matrix_view<ValueType,TraversalOrder> const &);
template <typename ValueType, ull_t OptionsFlags=0> template <typename ValueType>
std::ostream & operator << (std::ostream & out, vector_view<ValueType,OptionsFlags> const &); std::ostream & operator << (std::ostream & out, vector_view<ValueType> const &);
Prints the view (or the container since the view is trivially build from the container) Prints the view (or the container since the view is trivially build from the container)
to the stream out. to the stream out.

View File

@ -1,51 +1,41 @@
Template parameters of the containers and views Template parameters of the containers and views
====================================================== ======================================================
.. _arr_templ_par_opt:
OptionFlags
----------------------------
* OptionFlags is a series of flags determining various options at compile time.
The possible flags are accessible via a constexpr ull_t in triqs::arrays or a macro:
======================== =======================================
Macro constexpr equivalent
======================== =======================================
BOUND_CHECK triqs::arrays::BoundCheck
TRAVERSAL_ORDER_C triqs::arrays::TraversalOrderC
TRAVERSAL_ORDER_FORTRAN triqs::arrays::TraversalOrderFortran
DEFAULT_INIT triqs::arrays::DefaultInit
======================== =======================================
Defaults can be modified with the macros:
* `TRIQS_ARRAYS_ENFORCE_BOUNDCHECK` : enforce BoundCheck by default (slows down codes ! Use only for debugging purposes).
.. _arr_templ_par_to: .. _arr_templ_par_to:
TraversalOrder TraversalOrder
---------------------------- ----------------------------
* TraversalOrder is a coding of the optimal ordering of indices, given by a permutation * TraversalOrder is a type encoding of the optimal traversal in memory.
evaluated at **compile time**. Default is void, corresponding to as regular C-style ordering (slowest index first).
The traversal of the arrays (iterators, foreach loop) will be written and optimised for this
* The traversal of the arrays (iterators, foreach loop) will be written and optimised for this
order. order.
The default (0) is understood as regular C-style ordering (slowest index first). * It is indeed sometimes necessary to know *at compile time* the traversal order to generate
an optimal code. The default (C-style) is sufficient is most cases, but not always...
Note that an array can use any index ordering in memory, and that decision is take at run time * More explanations here...
(this is necessary for interfacing with python numpy arrays, see below).
The code will be correct for any order, but optimised for the TraversalOrder.
For a few very specials operations (e.g. regrouping of indices), the indices ordering in memory and TraversalOrder * Note that this notion is completely independent of the real memory layout of the array,
must coincide. This will be explicitely said below. By default, it is not necessary (but can be suboptimal). which is a runtime parameter.
The permutation P encodes the position of the index: P[0] is the fastest index, P[rank - 1] the slowest index The code will be correct for any order, but may be faster for the TraversalOrder.
(see examples below).
TraversalOrder is not present for vector since there is only one possibility in 1d.
* TraversalOrder is not present for vector since there is only one possibility in 1d.
* TODO : document the various possibility beyond C style.
+--------------------------+------------------------------------------------------------+
| TraversalOrder | Meaning |
+==========================+============================================================+
| void | C style traversal (lowest index first). |
+--------------------------+------------------------------------------------------------+
| _traversal_fortran | Fortran style traversal (last index first) |
+--------------------------+------------------------------------------------------------+
| _traversal_dynamical | Traverse in the order specified by the memory layout |
+--------------------------+------------------------------------------------------------+
| _traversal_custom<2,1,0> | Traverse in the order specified by the permutation (2,1,0) |
+--------------------------+------------------------------------------------------------+

View File

@ -34,7 +34,7 @@ Constructors of array_const_view
--------------------------------------- ---------------------------------------
+------------------------------------------------------------------------+---------------------------------------------------------------------------------------+ +------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
| Constructors of array_const_view<T,R,OptionsFlags, TraversalOrder> | Comments | | Constructors of array_const_view<T,R,TraversalOrder> | Comments |
+========================================================================+=======================================================================================+ +========================================================================+=======================================================================================+
| array_const_view(array_const_view const &) | Create a new view, viewing the same data. Does **not** copy data. (copy constructor) | | array_const_view(array_const_view const &) | Create a new view, viewing the same data. Does **not** copy data. (copy constructor) |
+------------------------------------------------------------------------+---------------------------------------------------------------------------------------+ +------------------------------------------------------------------------+---------------------------------------------------------------------------------------+

View File

@ -9,20 +9,13 @@ Views
.. code-block:: c .. code-block:: c
template <typename ValueType, int Rank, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class array_view; template <typename ValueType, int Rank, typename TraversalOrder=void> class array_view;
template <typename ValueType, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class matrix_view; template <typename ValueType, typename TraversalOrder=void> class matrix_view;
template <typename ValueType, ull_t OptionsFlags=0> class vector_view; template <typename ValueType> class vector_view;
template <typename ValueType, int Rank, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class array_const_view; template <typename ValueType, int Rank, typename TraversalOrder=void> class array_const_view;
template <typename ValueType, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class matrix_const_view; template <typename ValueType, typename TraversalOrder=void> class matrix_const_view;
template <typename ValueType, ull_t OptionsFlags=0> class vector_const_view; template <typename ValueType> class vector_const_view;
where triqs::ull_t is the type defined by :
.. code-block:: c
typedef unsigned long long ull_t;
* The view types of X (= array, matrix, vector) are called X_view, and X_const_view, with the same template parameters as the regular type. * The view types of X (= array, matrix, vector) are called X_view, and X_const_view, with the same template parameters as the regular type.
@ -65,8 +58,6 @@ Template parameters
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+ +-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
| Rank | int | rank | The rank of the array | | Rank | int | rank | The rank of the array |
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+ +-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
| :ref:`OptionsFlags<arr_templ_par_opt>` | ull_t | opt_flags | Compile time options |
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
| :ref:`TraversalOrder<arr_templ_par_to>` | ull_t | | Traversal Order for all loops | | :ref:`TraversalOrder<arr_templ_par_to>` | ull_t | | Traversal Order for all loops |
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+ +-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+

View File

@ -16,9 +16,8 @@ several advantages:
* it is more compact, less error prone (one does not need to specify the bounds in the loop). * it is more compact, less error prone (one does not need to specify the bounds in the loop).
* the library orders the for loop in the most efficient way to traverse the memory. * The library orders the loops in way specified by the template parameters TraversalOrder (by default, the standard C order),
Hence if one change the TraversalOrder for some arrays, there is no need to change the for loop to obtain the most efficient way to traverse the memory.
ordering to obtain a better performance, just recompile...
* it is easier to write generic code for array of several dimensions. * it is easier to write generic code for array of several dimensions.
@ -26,7 +25,7 @@ foreach
------------ ------------
The *foreach* function call a given function *f* successively on the indices of an array *A*, The *foreach* function call a given function *f* successively on the indices of an array *A*,
in the order specified by the TraversalOrder flag of the array. in the order specified by the TraversalOrder of the array.
* Synopsis:: * Synopsis::
@ -44,7 +43,7 @@ in the order specified by the TraversalOrder flag of the array.
for (i,j,k...) F(i,j,k...) for (i,j,k...) F(i,j,k...)
* The for loop are automatically organised to optimize the traversal order of A * The for loop are automatically organised to optimize the traversal order of A
using the TraversalOrder flag of the array. using the TraversalOrder of the array.
* As a result this is always equally or more optimized than a manually written loop. * As a result this is always equally or more optimized than a manually written loop.
@ -80,7 +79,7 @@ Synopsis::
for (i,j,k...) A(i,j,k...) = F(i,j,k...) for (i,j,k...) A(i,j,k...) = F(i,j,k...)
* The for loop are automatically organised to optimize the traversal order of A * The for loop are automatically organised to optimize the traversal order of A
using the TraversalOrder flag of the array. using the TraversalOrder of the array.
.. triqs_example:: ./foreach_1.cpp .. triqs_example:: ./foreach_1.cpp
.. note:: .. note::

View File

@ -6,7 +6,7 @@ void f(array_view<long,3> A) {
std::cout << " A(range(),range(),0) = "<< A(range(),range(),0) <<std::endl; std::cout << " A(range(),range(),0) = "<< A(range(),range(),0) <<std::endl;
std::cout << " A(range(),range(),1) = "<< A(range(),range(),1) <<std::endl; std::cout << " A(range(),range(),1) = "<< A(range(),range(),1) <<std::endl;
std::cout << " memory_layout (permutation of indices) = "<< A.indexmap().memory_indices_layout() << std::endl; std::cout << " memory_layout (permutation of indices) = "<< A.indexmap().get_memory_layout() << std::endl;
std::cout << " strides = "<< A.indexmap().strides() <<std::endl; std::cout << " strides = "<< A.indexmap().strides() <<std::endl;
std::cout << " is_contiguous = "<< A.indexmap().is_contiguous() <<std::endl; std::cout << " is_contiguous = "<< A.indexmap().is_contiguous() <<std::endl;

View File

@ -37,7 +37,7 @@ struct plain_for_no_ptr_const {
struct assign_to_const { struct assign_to_const {
void operator()() { void operator()() {
triqs::arrays::array<double,2,TRAVERSAL_ORDER_FORTRAN> A (N1,N2,FORTRAN_LAYOUT); triqs::arrays::array<double,2> A (N1,N2,FORTRAN_LAYOUT);
auto V = make_view(A); auto V = make_view(A);
for (int u =0; u<5000; ++u) for (int u =0; u<5000; ++u)
//make_view(A) = 1867; //make_view(A) = 1867;
@ -58,8 +58,8 @@ struct plain_for_no_ptr {
//typedef double value_type; //typedef double value_type;
//typedef triqs::arrays::matrix<double>::indexmap_type::domain_type::index_value_type index_value_type; //typedef triqs::arrays::matrix<double>::indexmap_type::domain_type::index_value_type index_value_type;
struct F { struct F {
triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > & a; triqs::arrays::matrix<double> & a;
F(triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > & a_): a(a_){} F(triqs::arrays::matrix<double> & a_): a(a_){}
//void operator()(value_type & p, index_value_type const & key) const { p=key[0]*10 + key[1] ;} //void operator()(value_type & p, index_value_type const & key) const { p=key[0]*10 + key[1] ;}
//void operator()(value_type & p, value_type const & x0, value_type const & x1) const { p=x0*10 + x1 ;} //void operator()(value_type & p, value_type const & x0, value_type const & x1) const { p=x0*10 + x1 ;}
template<typename X0, typename X1> void operator()( X0 const & x0, X1 const & x1) const { a(x0,x1) =x0*10 + x1 ;} template<typename X0, typename X1> void operator()( X0 const & x0, X1 const & x1) const { a(x0,x1) =x0*10 + x1 ;}
@ -67,7 +67,7 @@ struct F {
struct with_foreach { struct with_foreach {
void operator()() { void operator()() {
triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > A (N1,N2,FORTRAN_LAYOUT); triqs::arrays::matrix<double> A (N1,N2,FORTRAN_LAYOUT);
// triqs::arrays::indexmaps:: // triqs::arrays::indexmaps::
for (int u =0; u<3000; ++u) foreach(A,F(A)); for (int u =0; u<3000; ++u) foreach(A,F(A));
// for (int u =0; u<5000; ++u) make_view(A) = 1867; // for (int u =0; u<5000; ++u) make_view(A) = 1867;

160
test/speed/array3.cpp Normal file
View File

@ -0,0 +1,160 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by O. Parcollet
*
* TRIQS 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 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include <triqs/arrays.hpp>
#include <triqs/arrays/linalg/det_and_inverse.hpp>
using namespace triqs::arrays;
using namespace triqs::clef;
using namespace triqs;
const int N1 = 500, N2 = 300, Nu = 20;
struct simple_loop {
void operator()() {
array<double, 3> A(N1, N1, N1);
for (int u = 0; u < Nu; ++u)
for (int i = 0; i < N1; ++i)
for (int j = 0; j < N1; ++j)
for (int k = 0; k < N1; ++k) A(i, j, k) = i - j + u * k;
}
};
struct with_clef {
void operator()() {
array<double, 3> A(N1, N1, N1);
placeholder<0> i_;
placeholder<1> j_;
placeholder<2> k_;
for (int u = 0; u < Nu; ++u)
A(i_,j_,k_) << i_ - j_ + u * k_;
}
};
struct with_clef_custom_order {
void operator()() {
array<double, 3> A(N1, N1, N1, make_memory_layout(1,0,2));
//array<double, 3> A(N1, N1, N1, make_memory_layout(1,2,0));
placeholder<0> i_;
placeholder<1> j_;
placeholder<2> k_;
for (int u = 0; u < Nu; ++u)
A(i_,j_,k_) << i_ - j_ + u * k_;
}
};
struct loop_2 {
void operator()() {
long ind[3];
long Ns[3] = {N1, N1, N1};
array<double, 3> A(N1, N1, N1);
auto l = [&A](int i, int j, int k) { A(i, j, k) = i - j + 2 * k; };
for (int u = 0; u < Nu; ++u)
for (ind[0] = 0; ind[0] < Ns[0]; ++ind[0])
for (ind[1] = 0; ind[1] < Ns[0]; ++ind[1])
for (ind[2] = 0; ind[2] < Ns[0]; ++ind[2]) l(ind[0], ind[1], ind[2]);
}
};
struct loop_reorder {
void operator()() {
int p[3];
for (int u = 0; u<3; ++u) p[u] = (u+2)%3; // = {2, 0, 1};
//int p[] = {0,1,2};
long ind[3];
long Ns[3] = {N1, N1, N1};
array<double, 3> A(N1, N1, N1);
auto l = [&A](int i, int j, int k) { A(i, j, k) = i - j + 2 * k; };
for (int u = 0; u < Nu; ++u)
for (ind[0] = 0; ind[0] < Ns[0]; ++ind[0])
for (ind[1] = 0; ind[1] < Ns[1]; ++ind[1])
for (ind[2] = 0; ind[2] < Ns[2]; ++ind[2])
l(ind[p[1]], ind[p[2]], ind[p[0]]);
// l(ind[p[0]], ind[p[1]], ind[p[2]]);
}
};
struct loop_reorder2 {
void operator()() {
//int p[] = {2, 0, 1};
int p[] = {0,1,2};
int ind[3];
int Ns[3] = {N1, N1, N1};
array<double, 3> A(N1, N1, N1);
auto l = [&A](int i, int j, int k) { A(i, j, k) = i - j + 2 * k; };
for (int u = 0; u < Nu; ++u)
for (ind[p[0]] = 0; ind[p[0]] < Ns[p[0]]; ++ind[p[0]])
for (ind[p[1]] = 0; ind[p[1]] < Ns[p[1]]; ++ind[p[1]])
for (ind[p[2]] = 0; ind[p[2]] < Ns[p[2]]; ++ind[p[2]]) l(ind[0], ind[1], ind[2]);
}
};
// a very bad idea ... 15 x slower...
struct iter2 {
void operator()() {
array<double, 3> A(N1, N1, N1);
auto l = [&A](int i, int j, int k) { A(i, j, k) = i - j + 2 * k; };
long m = N1 * N1 * N1;
long N11 = N1 * N1;
for (int u = 0; u < Nu; ++u)
for (long ind = 0; ind < m; ++ind) {
l(ind % N1, (ind / N1) % N1, (ind / N11) % N1);
}
}
};
struct iter {
void operator()() {
array<double, 3> A(N1, N1, N1);
auto l = [&A](int i, int j, int k) { A(i, j, k) = i - j + 2 * k; };
for (int u = 0; u < Nu; ++u)
for (auto it = A.begin(); it; ++it) {
l(it.indices()[0], it.indices()[1], it.indices()[2]);
}
}
};
#include "./speed_tester.hpp"
int main() {
const int l = 5;
speed_tester<simple_loop>(l);
speed_tester<with_clef>(l);
speed_tester<with_clef_custom_order>(l);
speed_tester<loop_2>(l);
speed_tester<loop_reorder>(l);
speed_tester<loop_reorder2>(l);
speed_tester<iter>(l);
//speed_tester<iter2>(l);
return 0;
}

View File

@ -41,7 +41,7 @@ struct plain {
struct lazy { struct lazy {
void operator()() { void operator()() {
tql::placeholder<0> i_; tql::placeholder<1> j_; tql::placeholder<0> i_; tql::placeholder<1> j_;
triqs::arrays::array<double,2,TRAVERSAL_ORDER_FORTRAN> A (N1,N2,FORTRAN_LAYOUT); triqs::arrays::array<double,2> A (N1,N2,FORTRAN_LAYOUT);
for (int u =0; u<5000; ++u) for (int u =0; u<5000; ++u)
A(i_,j_) << i_+ 2*j_; A(i_,j_) << i_+ 2*j_;
} }
@ -49,7 +49,7 @@ struct lazy {
struct foreach_lambda { struct foreach_lambda {
void operator()() { void operator()() {
triqs::arrays::array<double,2,TRAVERSAL_ORDER_FORTRAN> A (N1,N2,FORTRAN_LAYOUT); triqs::arrays::array<double,2> A (N1,N2,FORTRAN_LAYOUT);
for (int u =0; u<5000; ++u) for (int u =0; u<5000; ++u)
//assign_foreach(A, [](size_t i, size_t j) { return i + 2.0*j;}); //assign_foreach(A, [](size_t i, size_t j) { return i + 2.0*j;});
assign_foreach(A, [](long i, long j) { return i + 2.0*j;}); assign_foreach(A, [](long i, long j) { return i + 2.0*j;});

View File

@ -37,7 +37,7 @@ struct plain_for_no_ptr_const {
struct assign_to_const { struct assign_to_const {
void operator()() { void operator()() {
triqs::arrays::array<double,2,TRAVERSAL_ORDER_FORTRAN> A (N1,N2,FORTRAN_LAYOUT); triqs::arrays::array<double,2> A (N1,N2,FORTRAN_LAYOUT);
auto V = make_view(A); auto V = make_view(A);
for (int u =0; u<2500000; ++u) for (int u =0; u<2500000; ++u)
//make_view(A) = 1867; //make_view(A) = 1867;
@ -58,8 +58,8 @@ struct plain_for_no_ptr {
//typedef double value_type; //typedef double value_type;
//typedef triqs::arrays::matrix<double>::indexmap_type::domain_type::index_value_type index_value_type; //typedef triqs::arrays::matrix<double>::indexmap_type::domain_type::index_value_type index_value_type;
struct F { struct F {
triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > & a; triqs::arrays::matrix<double> & a;
F(triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > & a_): a(a_){} F(triqs::arrays::matrix<double> & a_): a(a_){}
//void operator()(value_type & p, index_value_type const & key) const { p=key[0]*10 + key[1] ;} //void operator()(value_type & p, index_value_type const & key) const { p=key[0]*10 + key[1] ;}
//void operator()(value_type & p, value_type const & x0, value_type const & x1) const { p=x0*10 + x1 ;} //void operator()(value_type & p, value_type const & x0, value_type const & x1) const { p=x0*10 + x1 ;}
template<typename X0, typename X1> void operator()( X0 const & x0, X1 const & x1) const { a(x0,x1) =x0*10 + x1 ;} template<typename X0, typename X1> void operator()( X0 const & x0, X1 const & x1) const { a(x0,x1) =x0*10 + x1 ;}
@ -67,7 +67,7 @@ struct F {
struct with_foreach { struct with_foreach {
void operator()() { void operator()() {
triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > A (N1,N2,FORTRAN_LAYOUT); triqs::arrays::matrix<double> A (N1,N2,FORTRAN_LAYOUT);
// triqs::arrays::indexmaps:: // triqs::arrays::indexmaps::
for (int u =0; u<2500000; ++u) foreach(A,F(A)); for (int u =0; u<2500000; ++u) foreach(A,F(A));
// for (int u =0; u<5000; ++u) make_view(A) = 1867; // for (int u =0; u<5000; ++u) make_view(A) = 1867;

View File

@ -1,4 +1,4 @@
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK //#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
//#define TRIQS_ARRAYS_CHECK_WEAK_REFS //#define TRIQS_ARRAYS_CHECK_WEAK_REFS

View File

@ -31,10 +31,10 @@ int main(int argc, char **argv) {
array<long,2, BoundCheck > A (2,3); array<long,2> A (2,3);
array<long,2 > B (2,3); array<long,2 > B (2,3);
array<long,1 > C(2); array<long,1 > C(2);
array<long,2, BoundCheck > Af (2,3, FORTRAN_LAYOUT); array<long,2> Af (2,3, FORTRAN_LAYOUT);
try { try {

View File

@ -0,0 +1,36 @@
#include "./common.hpp"
using namespace triqs::arrays;
using namespace triqs::clef;
template <typename... T> void test(T... x) {
placeholder<0> i_;
placeholder<1> j_;
placeholder<2> k_;
placeholder<3> l_;
array<int, 4> a(1, 2, 3, 4, make_memory_layout(x...));
a(i_, j_, k_, l_) << i_ + 10 * j_ + 100 * k_ + 1000 * l_;
TEST_ERR(a);
auto v = c_ordered_transposed_view(a());
TEST(a.shape());
TEST(a.indexmap().get_memory_layout());
TEST(v.shape());
TEST(v.indexmap().get_memory_layout());
std::cerr << "----------------" << std::endl;
}
int main() {
try {
test(0, 1, 2, 3);
test(1, 0, 2, 3);
test(2, 0, 3, 1);
}
catch (std::exception const& e) {
std::cerr << e.what() << std::endl;
}
}

View File

@ -27,6 +27,7 @@
#include <iostream> #include <iostream>
#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> "<< (X) <<std::endl; #define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> "<< (X) <<std::endl;
#define TEST_ERR(X) std::cerr << BOOST_PP_STRINGIZE((X)) << " ---> "<< (X) <<std::endl;
#define TEST_ASSERT(X) if(!bool(X)) { std::stringstream fs; fs<< "Failed Assertion line "<< __LINE__<< " of file "<< __FILE__<<" :\n"<<BOOST_PP_STRINGIZE((X)); std::cout << fs.str()<< std::endl ; TRIQS_RUNTIME_ERROR<< fs.str();} #define TEST_ASSERT(X) if(!bool(X)) { std::stringstream fs; fs<< "Failed Assertion line "<< __LINE__<< " of file "<< __FILE__<<" :\n"<<BOOST_PP_STRINGIZE((X)); std::cout << fs.str()<< std::endl ; TRIQS_RUNTIME_ERROR<< fs.str();}

View File

@ -25,7 +25,7 @@
using namespace triqs::arrays; using namespace triqs::arrays;
template <typename U, ull_t opt, ull_t to, bool B> void f(array_view<U, 2, opt, to, B, true> const &a) { template <typename U, typename To, bool B> void f(array_view<U, 2, To, B, true> const &a) {
std::cout << a << std::endl; std::cout << a << std::endl;
} }

View File

@ -21,6 +21,7 @@
#include "./common.hpp" #include "./common.hpp"
#include <triqs/arrays/array.hpp> #include <triqs/arrays/array.hpp>
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
#include <triqs/arrays/matrix.hpp> #include <triqs/arrays/matrix.hpp>
#include <iostream> #include <iostream>
#include <triqs/arrays/asserts.hpp> #include <triqs/arrays/asserts.hpp>

View File

@ -31,7 +31,7 @@ int main(int argc, char **argv) {
A(i_,j_) << i_ + 2*j_ ; A(i_,j_) << i_ + 2*j_ ;
std::cout << "A = "<<A << std::endl; std::cout << "A = "<<A << std::endl;
tqa::array<double,2,TRAVERSAL_ORDER_FORTRAN> B(2,2); tqa::array<double,2> B(2,2);
B(i_,j_) << i_ + 2*j_ ; B(i_,j_) << i_ + 2*j_ ;
std::cout << "B = "<<B << std::endl; std::cout << "B = "<<B << std::endl;
} }

View File

@ -1,64 +1,94 @@
#include "./common.hpp" #include "./common.hpp"
#include <triqs/arrays/indexmaps/cuboid/group_indices.hpp> #include <triqs/arrays.hpp>
#include <triqs/arrays/matrix.hpp>
#include <triqs/arrays/asserts.hpp>
namespace tqa=triqs::arrays; using namespace triqs::arrays;
namespace tql=triqs::clef; using namespace triqs::clef;
using tqa::m_index; int main() {
template<triqs::ull_t FLAG> void test() { try {
placeholder<0> i_;
placeholder<1> j_;
placeholder<2> k_;
placeholder<3> l_;
tql::placeholder<0> i_; { // a simple test
tql::placeholder<1> j_; array<int, 4> A(2, 2, 2, 2);
tql::placeholder<2> k_; A(i_, j_, k_, l_) << i_ + 10 * j_ + 100 * k_ + 1000 * l_;
tql::placeholder<3> l_; TEST_ERR(A);
TEST_ERR(group_indices_view(A, {0,1}, {2,3}));
}
{ // a simple test // more complex : inversing a tensor product of matrices...
tqa::array<int,4,FLAG> A(2,2,2,2); matrix<double> B(2, 2), C(3, 3), Binv, Cinv;
A(i_,j_,k_,l_) << i_ + 10*j_ + 100*k_ + 1000*l_; C(i_, j_) << 1.7 / (3.4 * i_ - 2.3 * j_ + 1);
TEST(A); B(i_, j_) << 2 * i_ + j_;
TEST( group_indices(A, m_index<0,1>(), m_index<2,3>())); TEST_ERR(B);
TEST_ERR(C);
Binv = inverse(B);
Cinv = inverse(C);
TEST_ERR(Binv);
TEST_ERR(Cinv);
std::cerr << " --- (1) ---"<< std::endl;
{
array<double, 4> A(2, 3, 2, 3);
A(i_, j_, k_, l_) << B(i_, k_) * C(j_, l_);
TEST_ERR(A);
auto M = make_matrix_view(group_indices_view(A, {0, 1}, {2, 3}));
M = inverse(M);
// checking
array<double, 4> R(A.shape());
R(i_, j_, k_, l_) << Binv(i_, k_) * Cinv(j_, l_);
TEST_ERR(R);
TEST_ERR(A);
assert_all_close(R, A, 5.e-15);
}
std::cerr << " --- (2) ---"<< std::endl;
{
array<double, 4> A(2, 3, 2, 3, make_memory_layout(1, 0, 3, 2));
A(i_, j_, k_, l_) << B(i_, k_) * C(j_, l_);
TEST_ERR(A);
auto M = make_matrix_view(group_indices_view(A, {0, 1}, {2, 3}));
M = inverse(M);
// checking
array<double, 4> R(A.shape());
R(i_, j_, k_, l_) << Binv(i_, k_) * Cinv(j_, l_);
TEST_ERR(R);
TEST_ERR(A);
assert_all_close(R, A, 5.e-15);
}
std::cerr << " --- (3) ---"<< std::endl;
{
array<double, 4> A(2, 2, 3, 3, make_memory_layout(0, 2, 1, 3));
A(i_, k_, j_, l_) << B(i_, k_) * C(j_, l_);
TEST_ERR(A);
auto M = make_matrix_view(group_indices_view(A, {0, 2}, {1, 3}));
M = inverse(M);
// checking
array<double, 4> R(A.shape());
R(i_, k_, j_, l_) << Binv(i_, k_) * Cinv(j_, l_);
TEST_ERR(R);
TEST_ERR(A);
assert_all_close(R, A, 5.e-15);
}
} }
catch (std::exception const& e) {
{ // more complex : inversing a tensor product of matrices... std::cerr << e.what() << std::endl;
tqa::matrix<double,FLAG> B(2,2), C(3,3), Binv, Cinv;
C(i_,j_) << 1.7 /( 3.4*i_ - 2.3*j_ + 1) ;
B(i_,j_) << 2*i_ + j_;
TEST(B); TEST(C);
Binv = inverse(B);
Cinv = inverse(C);
TEST(Binv); TEST(Cinv);
tqa::array<double,4,FLAG> A(2,3,2,3);
A(i_,j_,k_,l_) << B(i_,k_) * C(j_,l_);
TEST(A);
tqa::matrix_view<double,FLAG> M = group_indices (A, m_index<0,1>() , m_index<2,3>() );
M = inverse(M);
// checking
tqa::array<double,4,FLAG> R(A.shape());
R(i_,j_,k_,l_) << Binv(i_,k_) * Cinv(j_,l_);
TEST(R);
TEST(A);
assert_all_close(R,A,5.e-15);
//TEST(make_array(R-A));
//TEST( max(abs(R-A)));
} }
} }
int main () {
test<TRAVERSAL_ORDER_FORTRAN>();
test<TRAVERSAL_ORDER_C>();
// template dans le namespace clef pour ADL et enable sur le concept de A ...
// an alternative syntax ?
//auto V = group_indices( A(i_,j_,k_,l_), var(i_,j_), var(k_,l_));
// match A(...), deduce the int of hte ph, and make a finder for a ph in it
// finder<Expr>::find<i>::value --> m_index<...>
}

View File

@ -1,46 +0,0 @@
(A) ---> [0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111 ]
(group_indices(A, m_index<0,1>(), m_index<2,3>())) --->
[[0,100,1000,1100]
[1,101,1001,1101]
[10,110,1010,1110]
[11,111,1011,1111]]
(B) --->
[[0,1]
[2,3]]
(C) --->
[[1.7,-1.30769,-0.472222]
[0.386364,0.809524,-8.5]
[0.217949,0.309091,0.53125]]
(Binv) --->
[[-1.5,0.5]
[1,0]]
(Cinv) --->
[[0.386252,0.0693273,1.45257]
[-0.259977,0.1271,1.80251]
[-0.00720283,-0.102391,0.237694]]
(A) ---> [0 3.4 0 0.772727 0 0.435897 1.7 5.1 0.386364 1.15909 0.217949 0.653846 0 -2.61538 0 1.61905 0 0.618182 -1.30769 -3.92308 0.809524 2.42857 0.309091 0.927273 0 -0.944444 0 -17 0 1.0625 -0.472222 -1.41667 -8.5 -25.5 0.53125 1.59375 ]
(R) ---> [-0.579378 0.386252 0.389966 -0.259977 0.0108043 -0.00720283 0.193126 0 -0.129989 0 -0.00360142 0 -0.103991 0.0693273 -0.19065 0.1271 0.153587 -0.102391 0.0346636 0 0.06355 0 -0.0511955 0 -2.17886 1.45257 -2.70376 1.80251 -0.35654 0.237694 0.726286 0 0.901255 0 0.118847 0 ]
(A) ---> [-0.579378 0.386252 0.389966 -0.259977 0.0108043 -0.00720283 0.193126 0 -0.129989 0 -0.00360142 0 -0.103991 0.0693273 -0.19065 0.1271 0.153587 -0.102391 0.0346636 0 0.06355 0 -0.0511955 0 -2.17886 1.45257 -2.70376 1.80251 -0.35654 0.237694 0.726286 0 0.901255 0 0.118847 0 ]
(A) ---> [0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111 ]
(group_indices(A, m_index<0,1>(), m_index<2,3>())) --->
[[0,1000,100,1100]
[10,1010,110,1110]
[1,1001,101,1101]
[11,1011,111,1111]]
(B) --->
[[0,1]
[2,3]]
(C) --->
[[1.7,-1.30769,-0.472222]
[0.386364,0.809524,-8.5]
[0.217949,0.309091,0.53125]]
(Binv) --->
[[-1.5,0.5]
[1,0]]
(Cinv) --->
[[0.386252,0.0693273,1.45257]
[-0.259977,0.1271,1.80251]
[-0.00720283,-0.102391,0.237694]]
(A) ---> [0 3.4 0 0.772727 0 0.435897 1.7 5.1 0.386364 1.15909 0.217949 0.653846 0 -2.61538 0 1.61905 0 0.618182 -1.30769 -3.92308 0.809524 2.42857 0.309091 0.927273 0 -0.944444 0 -17 0 1.0625 -0.472222 -1.41667 -8.5 -25.5 0.53125 1.59375 ]
(R) ---> [-0.579378 0.386252 0.389966 -0.259977 0.0108043 -0.00720283 0.193126 0 -0.129989 0 -0.00360142 0 -0.103991 0.0693273 -0.19065 0.1271 0.153587 -0.102391 0.0346636 0 0.06355 0 -0.0511955 0 -2.17886 1.45257 -2.70376 1.80251 -0.35654 0.237694 0.726286 0 0.901255 0 0.118847 0 ]
(A) ---> [-0.579378 0.386252 0.389966 -0.259977 0.0108043 -0.00720283 0.193126 0 -0.129989 0 -0.00360142 0 -0.103991 0.0693273 -0.19065 0.1271 0.153587 -0.102391 0.0346636 0 0.06355 0 -0.0511955 0 -2.17886 1.45257 -2.70376 1.80251 -0.35654 0.237694 0.726286 0 0.901255 0 0.118847 0 ]

View File

@ -65,7 +65,7 @@ int main(int argc, char **argv) {
std::cout<<" F order : traversal"<<std::endl; std::cout<<" F order : traversal"<<std::endl;
array<long,2,TRAVERSAL_ORDER_FORTRAN> Af (2,3); array<long,2,_traversal_fortran> Af (2,3, FORTRAN_LAYOUT);
for (auto it = Af.begin(); it; ++it) { for (auto it = Af.begin(); it; ++it) {
*it =it.indices()[0] + 10 *it.indices()[1] ; *it =it.indices()[0] + 10 *it.indices()[1] ;

View File

@ -24,38 +24,18 @@
namespace triqs { namespace arrays { namespace triqs { namespace arrays {
/* template <typename V, int R, ull_t Opt, ull_t To, typename ... I>
array_view<V, sizeof...(I), Opt> reinterpret_array_view (array<V,R,Opt,To> const & a, I ... index) {
//static int constexpr rank = sizeof...(I);
typedef array_view<V, sizeof...(I), Opt, indexmaps::mem_layout::c_order(rank)> return_t;
//typedef array_view<V, rank, Opt, indexmaps::mem_layout::c_order(rank)> return_t;
return return_t { make_shape(index...), a.storage() };
//return return_t (typename return_t::indexmap_type (mini_vector<size_t,rank>(index...)) , a.storage());
}
*/
template <typename V, int R, ull_t Opt, ull_t To, typename ... I> template <typename V, int R, typename To, typename... I>
array_view<V, sizeof...(I), Opt> reinterpret (array<V,R,Opt,To> const & a, I ... index) { array_view<V, sizeof...(I)> reinterpret(array<V, R, To> const &a, I... index) {
return { {make_shape(index...)}, a.storage() }; return { {make_shape(index...)}, a.storage() };
} }
// wrong for views // wrong for views
template <typename V, int R, ull_t Opt, ull_t To, bool B, typename ... I> template <typename V, int R, bool B, typename To, typename ... I>
array_view<V, sizeof...(I), Opt,indexmaps::mem_layout::c_order(sizeof...(I))> reinterpret_array_view (array_view<V,R,Opt,To,B> const & a, I ... index) { array_view<V, sizeof...(I)> reinterpret_array_view (array_view<V,R,To,B> const & a, I ... index) {
if (!has_contiguous_data(a)) TRIQS_RUNTIME_ERROR << "reinterpretation failure : data of the view are not contiguous"; if (!has_contiguous_data(a)) TRIQS_RUNTIME_ERROR << "reinterpretation failure : data of the view are not contiguous";
return { {make_shape(index...)}, a.storage() }; return { {make_shape(index...)}, a.storage() };
} }
/*
template <typename V, int R, ull_t Opt, ull_t To, typename ... I>
array_view<V, sizeof...(I), Opt,indexmaps::mem_layout::c_order(sizeof...(I))> reinterpret_array_view_c (matrix<V,Opt,To> const & a, I ... index) {
return { {make_shape(index...)}, a.storage() };
}
template <typename V, int R, ull_t Opt, ull_t To, typename ... I>
array_view<V, sizeof...(I), Opt,indexmaps::mem_layout::c_order(sizeof...(I))> reinterpret_array_view_c (vector<V,Opt> const & a, I ... index) {
return { {make_shape(index...)}, a.storage() };
}
*/
}} }}

View File

@ -20,96 +20,81 @@
******************************************************************************/ ******************************************************************************/
#include "./common.hpp" #include "./common.hpp"
#include <iostream> #include <iostream>
#include <triqs/arrays/impl/common.hpp> #include <triqs/arrays.hpp>
#include <triqs/arrays/indexmaps/range.hpp>
#include <triqs/arrays/indexmaps/permutation.hpp>
#include <triqs/arrays/indexmaps/cuboid/slice_traversal_order.hpp>
using namespace triqs::arrays; using namespace triqs::arrays;
using namespace triqs::arrays::permutations; using namespace triqs::arrays::indexmaps;
template<ull F> struct P { template <typename ML1, typename ML2, typename... Args> void test(ML1 ml1, ML2 ml2, Args... x) {
static constexpr ull value = F;
friend std::ostream & operator <<( std::ostream & out, P const & s) { cuboid::map<ML2::rank> m(ml2);
//out << "Permutation of size " << permutations::size(s.value) << " : "<< std::hex; slicer<cuboid::map<ML2::rank>, Args...> S;
out << std::hex; auto m2 = S.invoke(m, x...);
s.print(out, std::integral_constant<ull,0>()); std::cout << m.get_memory_layout() << std::endl;
return out << std::dec; std::cout << m2.get_memory_layout() << std::endl;
if (m2.get_memory_layout() != ml1) {
std::cout << "error " << m2.get_memory_layout() << " " << ml1 << std::endl;
exit(1);
} }
std::cout << "----------------------" << std::endl;
template<ull c> void print( std::ostream & out, std::integral_constant<ull,c>) const { out << apply(this->value,c); print(out, std::integral_constant<ull,c+1>());}
void print( std::ostream & out, std::integral_constant<ull,size(F)>) const {}
};
template<ull R, ull p, typename... Args > void test() {
typedef indexmaps::cuboid::slicing_TO_order::sliced_memory_order<p,Args...> S1;
constexpr auto s1 = S1::value;
//std::cout << " sliced "<< std::hex<< S1::value << " " <<std::endl ;
std::cout << P<p>() << std::endl;
std::cout << P<s1>() << std::endl;
//std::cout << "mashk "<< std::hex<<S1::mask_t::value<< std::endl;
if ( R != s1) {std::cout << "error "<< std::hex<< R<< " "<< s1<<std::endl ; exit(1);}//TRIQS_RUNTIME_ERROR<<" failed";
std::cout << "----------------------"<< std::endl ;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
std::cout << " C order " << std::endl;
test(make_memory_layout(0, 1), make_memory_layout(0, 1, 2, 3), 0, range(), 0, range());
test(make_memory_layout(0, 1, 2), make_memory_layout(0, 1, 2, 3), range(), range(), 0, range());
test(make_memory_layout(0, 1, 2, 3), make_memory_layout(0, 1, 2, 3), range(), range(), range(), range());
test(make_memory_layout(), make_memory_layout(0, 1, 2, 3), 0, 0, 0, 0);
std::cout << " F order " << std::endl;
test(make_memory_layout(1, 0), make_memory_layout(3, 2, 1, 0), 0, range(), 0, range());
test(make_memory_layout(2, 1, 0), make_memory_layout(3, 2, 1, 0), 0, range(), range(), range());
test(make_memory_layout(2, 1, 0), make_memory_layout(3, 2, 1, 0), range(), 0, range(), range());
test(make_memory_layout(2, 1, 0), make_memory_layout(3, 2, 1, 0), range(), range(), 0, range());
test(make_memory_layout(2, 1, 0), make_memory_layout(3, 2, 1, 0), range(), range(), range(), 0);
test(make_memory_layout(3, 2, 1, 0), make_memory_layout(3, 2, 1, 0), range(), range(), range(), range());
test(make_memory_layout(), make_memory_layout(3, 2, 1, 0), 0, 0, 0, 0);
std::cout << " F order " << std::endl ; test(make_memory_layout(0), make_memory_layout(0, 1), 0, range());
test< permutation(0,1) ,permutation(0,1,2,3), int, range,int, range>();
test< permutation(0,1,2) ,permutation(0,1,2,3), range, range,int, range>();
test< permutations::identity(4) ,permutation(0,1,2,3), range, range, range, range>();
//test< permutation(0,1,2,3) ,permutation(0,1,2,3), range, range, range, range>();
test< 0 ,permutation(0,1,2,3), int, int, int, int> ();
std::cout << " c order " << std::endl ; std::cout << " custom order " << std::endl;
test< permutation(1,0) ,permutation(3,2,1,0), int, range,int, range>(); test(make_memory_layout(1, 0), make_memory_layout(0, 3, 1, 2), 0, range(), 0, range());
test< permutation(2,1,0) ,permutation(3,2,1,0), int, range, range, range>(); test(make_memory_layout(2, 0, 1), make_memory_layout(0, 3, 1, 2), 0, range(), range(), range());
test< permutation(2,1,0) ,permutation(3,2,1,0), range,int, range, range>(); test(make_memory_layout(0, 2, 1), make_memory_layout(0, 3, 1, 2), range(), 0, range(), range());
test< permutation(2,1,0) ,permutation(3,2,1,0), range, range,int, range>(); test(make_memory_layout(0, 2, 1), make_memory_layout(0, 3, 1, 2), range(), range(), 0, range());
test< permutation(2,1,0) ,permutation(3,2,1,0), range, range, range, int>(); test(make_memory_layout(0, 1, 2), make_memory_layout(0, 3, 1, 2), range(), range(), range(), 0);
test< permutation(3,2,1,0) ,permutation(3,2,1,0), range, range, range, range>(); test(make_memory_layout(0, 3, 1, 2), make_memory_layout(0, 3, 1, 2), range(), range(), range(), range());
test< 0 ,permutation(3,2,1,0), int, int, int, int> (); test(make_memory_layout(), make_memory_layout(0, 3, 1, 2), 0, 0, 0, 0);
test< permutation(0), permutation(0,1), int, range>(); std::cout << " ----------- custom order ------------- " << std::endl;
std::cout << " custom order " << std::endl ; std::cout << " ---- 0 0 " << std::endl;
test< permutation(1,0) ,permutation(0,3,1,2), int, range,int, range>(); test(make_memory_layout(2, 0, 3, 1), make_memory_layout(2, 0, 3, 1), range(), range(), range(), range());
test< permutation(2,0,1) ,permutation(0,3,1,2), int, range, range, range>();
test< permutation(0,2,1) ,permutation(0,3,1,2), range,int, range, range>();
test< permutation(0,2,1) ,permutation(0,3,1,2), range, range,int, range>();
test< permutation(0,1,2) ,permutation(0,3,1,2), range, range, range, int>();
test< permutation(0,3,1,2) ,permutation(0,3,1,2), range, range, range, range>();
test< 0 ,permutation(0,3,1,2), int, int, int, int> ();
std::cout << " ----------- custom order ------------- " << std::endl ; std::cout << " ---- 1 0 " << std::endl;
test(make_memory_layout(1, 2, 0), make_memory_layout(2, 0, 3, 1), 0, range(), range(), range());
test(make_memory_layout(1, 0, 2), make_memory_layout(2, 0, 3, 1), range(), 0, range(), range());
test(make_memory_layout(0, 2, 1), make_memory_layout(2, 0, 3, 1), range(), range(), 0, range());
test(make_memory_layout(2, 0, 1), make_memory_layout(2, 0, 3, 1), range(), range(), range(), 0);
std::cout << " ---- 0 int "<< std::endl ; std::cout << " ---- 2 0 " << std::endl;
test< permutation(2,0,3,1) ,permutation(2,0,3,1), range, range, range, range>(); test(make_memory_layout(0, 1), make_memory_layout(2, 0, 3, 1), 0, 0, range(), range());
test(make_memory_layout(1, 0), make_memory_layout(2, 0, 3, 1), 0, range(), 0, range());
test(make_memory_layout(1, 0), make_memory_layout(2, 0, 3, 1), 0, range(), range(), 0);
test(make_memory_layout(0, 1), make_memory_layout(2, 0, 3, 1), range(), 0, 0, range());
test(make_memory_layout(1, 0), make_memory_layout(2, 0, 3, 1), range(), 0, range(), 0);
test(make_memory_layout(0, 1), make_memory_layout(2, 0, 3, 1), range(), range(), 0, 0);
std::cout << " ---- 1 int "<< std::endl ; std::cout << " ---- 3 0 " << std::endl;
test< permutation(1,2,0) ,permutation(2,0,3,1), int, range, range, range>(); test(make_memory_layout(0), make_memory_layout(2, 0, 3, 1), range(), 0, 0, 0);
test< permutation(1,0,2) ,permutation(2,0,3,1), range,int, range, range>(); test(make_memory_layout(0), make_memory_layout(2, 0, 3, 1), 0, range(), 0, 0);
test< permutation(0,2,1) ,permutation(2,0,3,1), range, range,int, range>(); test(make_memory_layout(0), make_memory_layout(2, 0, 3, 1), 0, 0, range(), 0);
test< permutation(2,0,1) ,permutation(2,0,3,1), range, range, range, int>(); test(make_memory_layout(0), make_memory_layout(2, 0, 3, 1), 0, 0, 0, range());
std::cout << " ---- 2 int "<< std::endl ;
test< permutation(0,1) ,permutation(2,0,3,1), int, int, range, range>();
test< permutation(1,0) ,permutation(2,0,3,1), int, range,int, range>();
test< permutation(1,0) ,permutation(2,0,3,1), int, range,range, int>();
test< permutation(0,1) ,permutation(2,0,3,1), range,int, int, range>();
test< permutation(1,0) ,permutation(2,0,3,1), range,int, range, int>();
test< permutation(0,1) ,permutation(2,0,3,1), range, range,int, int>();
std::cout << " ---- 3 int "<< std::endl ;
test< permutation(0) ,permutation(2,0,3,1), range, int, int, int>();
test< permutation(0) ,permutation(2,0,3,1), int,range, int, int>();
test< permutation(0) ,permutation(2,0,3,1), int, int,range, int>();
test< permutation(0) ,permutation(2,0,3,1), int, int, int, range>();
std::cout << " ---- 4 int "<< std::endl ;
test< 0 ,permutation(2,0,3,1), int, int, int, int> ();
std::cout << " OK "<< std::endl ;
std::cout << " ---- 4 0 " << std::endl;
test(make_memory_layout(), make_memory_layout(2, 0, 3, 1), 0, 0, 0, 0);
std::cout << " OK " << std::endl;
} }

View File

@ -24,67 +24,61 @@
#include <triqs/arrays/array.hpp> #include <triqs/arrays/array.hpp>
#include <iostream> #include <iostream>
using std::cout; using std::endl; using std::cout;
using std::endl;
using namespace triqs::arrays; using namespace triqs::arrays;
/// ///
template<typename IM, typename A> template <typename IM, typename A> void print_in_indexmap_order(std::ostream &out, IM const &im, A const &a) {
void print_in_indexmap_order (std::ostream & out, IM const & im, A const & a) { out << "[";
out<<"[";
//for (typename IM::iterator it(im); it; ++it) out<<a[it.indices()]<<" ";
for (typename IM::iterator it(im); it; ++it) { for (typename IM::iterator it(im); it; ++it) {
auto i = it.indices(); auto i = it.indices();
out<< a(i[0],i[1],i[2])<<" "; out << a(i[0], i[1], i[2]) << " ";
} }
out<<"]"; out << "]";
} }
template<class AA> template <class AA> void f(AA &A) {
void f(AA & A) {
for (int i =0; i<2; ++i) for (int i = 0; i < 2; ++i)
for (int j=0; j<3; ++j) for (int j = 0; j < 3; ++j)
for (int k=0; k<4; ++k) for (int k = 0; k < 4; ++k) A(i, j, k) = 100 * (i + 1) + 10 * (j + 1) + (k + 1);
A(i,j,k) = 100*(i+1)+ 10*(j+1) + (k+1);
print_in_indexmap_order(std::cout,A.indexmap(),A);std::cout<<std::endl; print_in_indexmap_order(std::cout, A.indexmap(), A);
std::cout << std::endl;
std::cout<< A(0,range(), range())<<std::endl; std::cout << A(0, range(), range()) << std::endl;
std::cout<< A(1,range(), range())<<std::endl; std::cout << A(1, range(), range()) << std::endl;
std::cout<< A(range(), 0, range())<<std::endl; std::cout << A(range(), 0, range()) << std::endl;
std::cout<< A(range(), range(),1)<<std::endl; std::cout << A(range(), range(), 1) << std::endl;
std::cout<< A(range(), 0,1)<<std::endl; std::cout << A(range(), 0, 1) << std::endl;
std::cout<<"-------------------------------------------------- "<<std::endl; std::cout << "-------------------------------------------------- " << std::endl;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
try { try {
//array<long, 3, Option::options<Option::memory_order <2,1,0> > > A0 (2,3,4);
//array<long, 3, Option::options<Option::memory_order <0,1,2> > > A1 (2,3,4);
//array<long, 3, Option::options<Option::memory_order <1,0,2> > > A2 (2,3,4);
// permutation in triqs::arrays // permutation in triqs::arrays
array<long, 3, 0, permutation(2,1,0)> A0 (2,3,4); array<long, 3> A0(2, 3, 4);
array<long, 3, 0, permutation(0,1,2)> A1 (2,3,4); array<long, 3, _traversal_dynamical> A1(2, 3, 4, make_memory_layout(2, 1, 0));
array<long, 3, 0, permutation(1,0,2)> A2 (2,3,4); array<long, 3, _traversal_dynamical> A2(2, 3, 4, make_memory_layout(2, 0, 1));
array<long, 3> A3 (2,3,4); array<long, 3> A3(2, 3, 4, make_memory_layout(0, 1, 2));
array<long, 3, TRAVERSAL_ORDER_FORTRAN> A4 (2,3,4,FORTRAN_LAYOUT); array<long, 3, _traversal_fortran> A4(2, 3, 4, FORTRAN_LAYOUT);
f(A0); f(A0);
f(A1); f(A1);
f(A2); f(A2);
f(A3); f(A3);
f(A4); f(A4);
} }
catch (const char * ERR) { catch (const char *ERR) {
std::cout<<"Error is "<<ERR<<std::endl; std::cout << "Error is " << ERR << std::endl;
} }
return 0; return 0;
} }

View File

@ -134,14 +134,14 @@ int main(int argc, char **argv) {
std::cerr << " " << res << std::endl ; std::cerr << " " << res << std::endl ;
} }
{ // to mini_vector /* { // to mini_vector
auto t = std::make_tuple(1,2,3.4); auto t = std::make_tuple(1,2,3.4);
auto m = triqs::utility::tuple_to_mini_vector<double>(t); auto m = triqs::utility::tuple_to_mini_vector<double>(t);
std::cout << m<< std::endl ; std::cout << m<< std::endl ;
} }
*/
{ // filter { // filter
std::cout << " ----- filter ----"<< std::endl ; std::cout << " ----- filter ----"<< std::endl ;
auto t= std::make_tuple(0,1,2,3,4,"=5"); auto t= std::make_tuple(0,1,2,3,4,"=5");

View File

@ -40,8 +40,8 @@ int main(int argc, char **argv) {
check<array<int,1>> (); check<array<int,1>> ();
check<array_view<int,1>>(); check<array_view<int,1>>();
check<matrix<int,1>>(); check<matrix<int>>();
check<matrix_view<int,1>>(); check<matrix_view<int>>();
return 0; return 0;
} }

View File

@ -21,6 +21,8 @@
#ifndef TRIQS_ARRAYS_ALL_H #ifndef TRIQS_ARRAYS_ALL_H
#define TRIQS_ARRAYS_ALL_H #define TRIQS_ARRAYS_ALL_H
#define TRIQS_ARRAYS_INCLUDED
// The basic classes // The basic classes
#include <triqs/arrays/array.hpp> #include <triqs/arrays/array.hpp>
#include <triqs/arrays/matrix.hpp> #include <triqs/arrays/matrix.hpp>
@ -36,6 +38,9 @@
// HDF5 interface // HDF5 interface
#include <triqs/arrays/h5/simple_read_write.hpp> #include <triqs/arrays/h5/simple_read_write.hpp>
// Regrouping indices
#include <triqs/arrays/group_indices.hpp>
// Linear algebra ?? Keep here ? // Linear algebra ?? Keep here ?
//#include <triqs/arrays/linalg/det_and_inverse.hpp> //#include <triqs/arrays/linalg/det_and_inverse.hpp>

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011-2013 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -18,43 +18,43 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_ARRAY_H #pragma once
#define TRIQS_ARRAYS_ARRAY_H
#include <triqs/utility/first_include.hpp> #include <triqs/utility/first_include.hpp>
#include "indexmaps/cuboid/map.hpp" #include "indexmaps/cuboid/map.hpp"
#include "indexmaps/cuboid/slice.hpp" #include "indexmaps/cuboid/slice.hpp"
#include "impl/indexmap_storage_pair.hpp" #include "impl/indexmap_storage_pair.hpp"
#include "impl/assignment.hpp" #include "impl/assignment.hpp"
#include "impl/flags.hpp"
namespace triqs { namespace arrays { namespace triqs { namespace arrays {
template <typename ValueType, int Rank, ull_t Opt=0, ull_t TraversalOrder= 0, bool Borrowed=false, bool IsConst=false > class array_view; template <typename ValueType, int Rank, typename TraversalOrder= void, bool Borrowed = false, bool IsConst = false> class array_view;
template <typename ValueType, int Rank, ull_t Opt=0, ull_t TraversalOrder= 0> class array; template <typename ValueType, int Rank, typename TraversalOrder= void> class array;
// ---------------------- array_view -------------------------------- // ---------------------- array_view --------------------------------
#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<Rank,Opt,TraversalOrder>, \ #define IMPL_TYPE \
storages::shared_block<ValueType, Borrowed>, Opt, TraversalOrder, IsConst, true, Tag::array_view > indexmap_storage_pair<indexmaps::cuboid::map<Rank,TraversalOrder>, storages::shared_block<ValueType, Borrowed>, TraversalOrder, IsConst, true, \
Tag::array_view>
template <typename ValueType, int Rank, ull_t Opt, ull_t TraversalOrder, bool Borrowed, bool IsConst> template <typename ValueType, int Rank, typename TraversalOrder, bool Borrowed, bool IsConst>
class array_view: Tag::array_view, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE { class array_view: Tag::array_view, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE {
static_assert( Rank>0, " Rank must be >0"); static_assert( Rank>0, " Rank must be >0");
public: public:
typedef typename IMPL_TYPE::indexmap_type indexmap_type; using indexmap_type = typename IMPL_TYPE::indexmap_type;
typedef typename IMPL_TYPE::storage_type storage_type; using storage_type = typename IMPL_TYPE::storage_type;
typedef array <ValueType,Rank,Opt,TraversalOrder> regular_type; using regular_type = array<ValueType, Rank, TraversalOrder>;
typedef array_view<ValueType,Rank,Opt,TraversalOrder> view_type; using view_type = array_view<ValueType, Rank, TraversalOrder>;
typedef array_view<ValueType, Rank, Opt, TraversalOrder, false, true> const_view_type; using const_view_type = array_view<ValueType, Rank, TraversalOrder, false, true>;
typedef array_view<ValueType,Rank,Opt,TraversalOrder,true> weak_view_type; using weak_view_type = array_view<ValueType, Rank, TraversalOrder, true>;
/// Build from an IndexMap and a storage /// Build from an IndexMap and a storage
template <typename S> array_view(indexmap_type const& Ind, S const& Mem) : IMPL_TYPE(Ind, Mem) {} template <typename S> array_view(indexmap_type const& Ind, S const& Mem) : IMPL_TYPE(Ind, Mem) {}
/// Copy constructor /// Copy constructor
array_view(array_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {} array_view(array_view const& X) : IMPL_TYPE(X.indexmap(), X.storage()) {}
/// Build from anything that has an indexmap and a storage compatible with this class /// Build from anything that has an indexmap and a storage compatible with this class
template<typename ISP> array_view(const ISP & X): IMPL_TYPE(X.indexmap(),X.storage()) { template <typename ISP> array_view(const ISP& X) : IMPL_TYPE(X.indexmap(), X.storage()) {
// to be activated // to be activated
static_assert(IsConst || (!ISP::is_const), "Cannot construct a non const view from a const one !"); static_assert(IsConst || (!ISP::is_const), "Cannot construct a non const view from a const one !");
} }
@ -79,7 +79,7 @@ namespace triqs { namespace arrays {
} }
// rebind the other view, iif this is const, and the other is not. // rebind the other view, iif this is const, and the other is not.
template <bool C = IsConst> ENABLE_IFC(C) rebind(array_view<ValueType, Rank, Opt, TraversalOrder, Borrowed, !IsConst> const& X) { template <typename To, bool C = IsConst> ENABLE_IFC(C) rebind(array_view<ValueType, Rank, To, Borrowed, !IsConst> const& X) {
this->indexmap_ = X.indexmap_; this->indexmap_ = X.indexmap_;
this->storage_ = X.storage_; this->storage_ = X.storage_;
} }
@ -96,45 +96,52 @@ namespace triqs { namespace arrays {
// to forbid serialization of views... // to forbid serialization of views...
//template<class Archive> void serialize(Archive & ar, const unsigned int version) = delete; //template<class Archive> void serialize(Archive & ar, const unsigned int version) = delete;
template <typename... INT> friend array_view transposed_view(array_view const& a, INT... is) { template <typename... INT> friend view_type transposed_view(array_view const& a, INT... is) {
return array_view{transpose(a.indexmap_, is...), a.storage_}; return transposed_view(a, mini_vector<int, Rank>{is...});
}
friend view_type transposed_view(array_view const& a, mini_vector<int, Rank> const& perm) {
return {transpose(a.indexmap_, perm), a.storage_};
}
friend view_type c_ordered_transposed_view(array_view const& a) {
return transposed_view(a, a.indexmap().get_memory_layout().get_memory_positions());
} }
}; };
#undef IMPL_TYPE #undef IMPL_TYPE
template <typename ValueType, int Rank, ull_t Opt=0, ull_t TraversalOrder=0, bool Borrowed=false> template <typename ValueType, int Rank, typename TraversalOrder = void, bool Borrowed = false>
using array_const_view = array_view<ValueType, Rank, Opt, TraversalOrder, Borrowed, true>; using array_const_view = array_view<ValueType, Rank, TraversalOrder, Borrowed, true>;
//------------------------------- array --------------------------------------------------- //------------------------------- array ---------------------------------------------------
#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<Rank,Opt,TraversalOrder>, \ #define IMPL_TYPE \
storages::shared_block<ValueType>, Opt, TraversalOrder, false, false, Tag::array_view > indexmap_storage_pair<indexmaps::cuboid::map<Rank,TraversalOrder>, storages::shared_block<ValueType>, TraversalOrder, false, false, Tag::array_view>
template <typename ValueType, int Rank, ull_t Opt, ull_t TraversalOrder> template <typename ValueType, int Rank, typename TraversalOrder>
class array: Tag::array, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE { class array : Tag::array, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE {
public: public:
typedef typename IMPL_TYPE::value_type value_type; using value_type = typename IMPL_TYPE::value_type;
typedef typename IMPL_TYPE::storage_type storage_type; using storage_type = typename IMPL_TYPE::storage_type;
typedef typename IMPL_TYPE::indexmap_type indexmap_type; using indexmap_type = typename IMPL_TYPE::indexmap_type;
typedef array<ValueType, Rank, Opt, TraversalOrder> regular_type; using regular_type = array<ValueType, Rank, TraversalOrder>;
typedef array_view<ValueType, Rank, Opt, TraversalOrder> view_type; using view_type = array_view<ValueType, Rank, TraversalOrder>;
typedef array_view<ValueType, Rank, Opt, TraversalOrder, false, true> const_view_type; using const_view_type = array_view<ValueType, Rank, TraversalOrder, false, true>;
typedef array_view<ValueType, Rank, Opt, TraversalOrder, true> weak_view_type; using weak_view_type = array_view<ValueType, Rank, TraversalOrder, true>;
/// Empty array. /// Empty array.
explicit array(memory_layout<Rank> ml = memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order)) :IMPL_TYPE(ml){} explicit array(memory_layout<Rank> ml = memory_layout<Rank>{}) : IMPL_TYPE(ml) {}
/// From a domain /// From a domain
explicit array( typename indexmap_type::domain_type const & dom, memory_layout<Rank> ml = memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order)): explicit array(typename indexmap_type::domain_type const& dom, memory_layout<Rank> ml = memory_layout<Rank>{})
IMPL_TYPE(indexmap_type(dom,ml)){} : IMPL_TYPE(indexmap_type(dom, ml)) {}
#ifdef TRIQS_DOXYGEN #ifdef TRIQS_DOXYGEN
/// Construction from the dimensions. NB : the number of parameters must be exactly rank (checked at compile time). /// Construction from the dimensions. NB : the number of parameters must be exactly rank (checked at compile time).
array (size_t I_1, .... , size_t I_rank); array (size_t I_1, .... , size_t I_rank);
#else #else
#define IMPL(z, NN, unused) \ #define IMPL(z, NN, unused) \
explicit array (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), size_t I_),memory_layout<Rank> ml = memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order)): \ explicit array (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), size_t I_),memory_layout<Rank> ml = memory_layout<Rank>{}): \
IMPL_TYPE(indexmap_type(mini_vector<size_t,BOOST_PP_INC(NN)>(BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), I_)),ml)) {\ IMPL_TYPE(indexmap_type(mini_vector<size_t,BOOST_PP_INC(NN)>(BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), I_)),ml)) {\
static_assert(IMPL_TYPE::rank-1==NN,"array : incorrect number of variables in constructor");} static_assert(IMPL_TYPE::rank-1==NN,"array : incorrect number of variables in constructor");}
BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil) BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil)
@ -148,9 +155,8 @@ namespace triqs { namespace arrays {
explicit array(array && X) { this->swap_me(X); } explicit array(array && X) { this->swap_me(X); }
// from a temporary storage and an indexmap. Used for reshaping a temporary array // from a temporary storage and an indexmap. Used for reshaping a temporary array
explicit array(typename indexmap_type::domain_type const & dom, storage_type && sto, explicit array(typename indexmap_type::domain_type const& dom, storage_type&& sto, memory_layout<Rank> ml = memory_layout<Rank>{})
memory_layout<Rank> ml = memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order)): : IMPL_TYPE(indexmap_type(dom, ml), std::move(sto)) {}
IMPL_TYPE(indexmap_type(dom,ml), std::move(sto)){}
/** /**
* Build a new array from X.domain() and fill it with by evaluating X. X can be : * Build a new array from X.domain() and fill it with by evaluating X. X can be :
@ -158,8 +164,10 @@ namespace triqs { namespace arrays {
* - a expression : e.g. array<int> A = B+ 2*C; * - a expression : e.g. array<int> A = B+ 2*C;
*/ */
template <typename T> template <typename T>
array(const T & X, TYPE_ENABLE_IF(memory_layout<Rank>, ImmutableCuboidArray<T>) ml = memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order)): array(const T& X, TYPE_ENABLE_IF(memory_layout<Rank>, ImmutableCuboidArray<T>) ml = memory_layout<Rank>{})
IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); } : IMPL_TYPE(indexmap_type(X.domain(), ml)) {
triqs_arrays_assign_delegation(*this, X);
}
#ifdef TRIQS_WITH_PYTHON_SUPPORT #ifdef TRIQS_WITH_PYTHON_SUPPORT
///Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy. ///Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy.
@ -169,14 +177,14 @@ namespace triqs { namespace arrays {
// build from a init_list // build from a init_list
template<typename T, int R=Rank> template<typename T, int R=Rank>
array(std::initializer_list<T> const & l, typename std::enable_if<R==1>::type * dummy =0): array(std::initializer_list<T> const & l, typename std::enable_if<R==1>::type * dummy =0):
IMPL_TYPE(indexmap_type(mini_vector<size_t,1>(l.size()),memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order))) { IMPL_TYPE(indexmap_type(mini_vector<size_t,1>(l.size()),memory_layout<Rank>())) {
size_t i=0; size_t i=0;
for (auto const & x : l) (*this)(i++) = x; for (auto const & x : l) (*this)(i++) = x;
} }
template<typename T, int R=Rank> template<typename T, int R=Rank>
array (std::initializer_list<std::initializer_list<T>> const & l, typename std::enable_if<R==2>::type * dummy =0): array (std::initializer_list<std::initializer_list<T>> const & l, typename std::enable_if<R==2>::type * dummy =0):
IMPL_TYPE(memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order)) { IMPL_TYPE(memory_layout<Rank>()) {
size_t i=0,j=0; int s=-1; size_t i=0,j=0; int s=-1;
for (auto const & l1 : l) { if (s==-1) s= l1.size(); else if (s != l1.size()) TRIQS_RUNTIME_ERROR << "initializer list not rectangular !";} for (auto const & l1 : l) { if (s==-1) s= l1.size(); else if (s != l1.size()) TRIQS_RUNTIME_ERROR << "initializer list not rectangular !";}
IMPL_TYPE::resize(typename IMPL_TYPE::domain_type (mini_vector<size_t,2>(l.size(),s))); IMPL_TYPE::resize(typename IMPL_TYPE::domain_type (mini_vector<size_t,2>(l.size(),s)));
@ -217,10 +225,10 @@ namespace triqs { namespace arrays {
TRIQS_DEFINE_COMPOUND_OPERATORS(array); TRIQS_DEFINE_COMPOUND_OPERATORS(array);
template <typename... INT> friend const_view_type transposed_view(array const& a, INT... is) { template <typename... INT> friend const_view_type transposed_view(array const& a, INT... is) {
return view_type{transpose(a.indexmap_, is...), a.storage_}; return transposed_view(a(), is...);
}; };
template <typename... INT> friend view_type transposed_view(array& a, INT... is) { template <typename... INT> friend view_type transposed_view(array& a, INT... is) {
return view_type{transpose(a.indexmap_, is...), a.storage_}; return transposed_view(a(), is...);
}; };
};//array class };//array class
@ -230,19 +238,18 @@ namespace triqs { namespace arrays {
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// how to build the view type .... // how to build the view type ....
template < class V, int R, ull_t Opt, ull_t TraversalOrder, bool Borrowed, bool IsConst > template <class V, int R, typename TraversalOrder, bool Borrowed, bool IsConst>
struct ISPViewType< V, R, Opt, TraversalOrder,Tag::array_view, Borrowed,IsConst> { typedef array_view<V,R,Opt,TraversalOrder, Borrowed,IsConst> type; }; struct ISPViewType<V, R, TraversalOrder, Tag::array_view, Borrowed, IsConst> {
using type = array_view<V, R, TraversalOrder, Borrowed, IsConst>;
};
}}//namespace triqs::arrays }}//namespace triqs::arrays
// The std::swap is WRONG for a view because of the copy/move semantics of view. // The std::swap is WRONG for a view because of the copy/move semantics of view.
// Use swap instead (the correct one, found by ADL). // Use swap instead (the correct one, found by ADL).
namespace std { namespace std {
template <typename V, int R, triqs::ull_t Opt, triqs::ull_t To, bool B1, bool B2, bool C1, bool C2> template <typename V, typename To1, typename To2, int R, bool B1, bool B2, bool C1, bool C2>
void swap( triqs::arrays::array_view<V,R,Opt,To,B1,C1> & a , triqs::arrays::array_view<V,R,Opt,To,B2,C2> & b)= delete; void swap(triqs::arrays::array_view<V, R, To1, B1, C1>& a, triqs::arrays::array_view<V, R, To2, B2, C2>& b) = delete;
} }
#include "./expression_template/array_algebra.hpp" #include "./expression_template/array_algebra.hpp"
#endif

View File

@ -132,8 +132,8 @@ namespace triqs { namespace arrays { namespace blas {
// to allow gemm (alpha, a, b, beta, M(..., ...)) i.e. a temporary view, which is not matched by previos templates // to allow gemm (alpha, a, b, beta, M(..., ...)) i.e. a temporary view, which is not matched by previos templates
// which require an lvalue. This is the only version which takes an && as last argument // which require an lvalue. This is the only version which takes an && as last argument
// indeed, in the routine, c is a *lvalue*, since it has a name, and hence we call *other* overload of the function // indeed, in the routine, c is a *lvalue*, since it has a name, and hence we call *other* overload of the function
template<typename A, typename MT1, typename MT2, typename B, typename V, ull_t Opt, ull_t To, bool W> template<typename A, typename MT1, typename MT2, typename B, typename V, typename To, bool W>
void gemm (A alpha, MT1 const & a, MT2 const & b, B beta, matrix_view<V,Opt,To,W> && c) { gemm(alpha,a,b,beta,c);} void gemm (A alpha, MT1 const & a, MT2 const & b, B beta, matrix_view<V,To,W> && c) { gemm(alpha,a,b,beta,c);}
}}}// namespace }}}// namespace

View File

@ -98,8 +98,8 @@ namespace triqs { namespace arrays { namespace blas {
// to allow gem (alpha, a, b, beta, M(..., ...)) i.e. a temporary view, which is not matched by previos templates // to allow gem (alpha, a, b, beta, M(..., ...)) i.e. a temporary view, which is not matched by previos templates
// which require an lvalue. // which require an lvalue.
template<typename A, typename MT, typename VT, typename B, typename V, ull_t Opt, bool W> template<typename A, typename MT, typename VT, typename B, typename V, bool W>
void gemv (A alpha, MT const & a, VT const & b, B beta, vector_view<V,Opt,W> && c) { gemv(alpha,a,b,beta,c);} void gemv (A alpha, MT const & a, VT const & b, B beta, vector_view<V,W> && c) { gemv(alpha,a,b,beta,c);}
}}}// namespace }}}// namespace

View File

@ -74,8 +74,8 @@ namespace triqs { namespace arrays { namespace blas {
// to allow ger (alpha, x,y, M(..., ...)) i.e. a temporary view, which is not matched by previos templates // to allow ger (alpha, x,y, M(..., ...)) i.e. a temporary view, which is not matched by previos templates
// which require an lvalue // which require an lvalue
template< typename A, typename VTX, typename VTY, typename V, ull_t Opt, ull_t To, bool W> template< typename A, typename VTX, typename VTY, typename V, typename To, bool W>
void ger (A alpha, VTX const & x, VTY const & y, matrix_view<V,Opt,To,W> && r) { ger(alpha,x,y,r);} void ger (A alpha, VTX const & x, VTY const & y, matrix_view<V,To,W> && r) { ger(alpha,x,y,r);}
}}}// namespace }}}// namespace
#endif #endif

View File

@ -64,7 +64,7 @@ namespace arrays {
exposed_view_type view2() const { return view1(bool_constant<is_amv_value_or_view_class<DataType>::value>()); } exposed_view_type view2() const { return view1(bool_constant<is_amv_value_or_view_class<DataType>::value>()); }
bool need_copy_dynamic(DataType const& x, std::false_type) const { return false; } bool need_copy_dynamic(DataType const& x, std::false_type) const { return false; }
bool need_copy_dynamic(DataType const& x, std::true_type) const { return (x.indexmap().memory_indices_layout() != ml); } bool need_copy_dynamic(DataType const& x, std::true_type) const { return (x.indexmap().get_memory_layout() != ml); }
void back_update(std::true_type) {} void back_update(std::true_type) {}
void back_update(std::false_type) { void back_update(std::false_type) {
@ -98,12 +98,12 @@ namespace arrays {
template <typename DataType> using const_cache = cache_impl<DataType, true>; template <typename DataType> using const_cache = cache_impl<DataType, true>;
template <typename D> template <typename D>
const_cache<D> make_const_cache(D const& x, memory_layout<D::domain_type::rank> ml = memory_layout<D::domain_type::rank>{'C'}) { const_cache<D> make_const_cache(D const& x, memory_layout<D::domain_type::rank> ml = memory_layout<D::domain_type::rank>{}) {
return {x, ml}; return {x, ml};
} }
template <typename D> template <typename D>
cache<D> make_cache(D const& x, memory_layout<D::domain_type::rank> ml = memory_layout<D::domain_type::rank>{'C'}) { cache<D> make_cache(D const& x, memory_layout<D::domain_type::rank> ml = memory_layout<D::domain_type::rank>{}) {
return {x, ml}; return {x, ml};
} }
} }

View File

@ -0,0 +1,77 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2014 by O. Parcollet
*
* TRIQS 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 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include <triqs/arrays/array.hpp>
#include <algorithm>
namespace triqs {
namespace arrays {
/**
* Regroup indices for a C array
* Usage : group_indices_view(A, {0,1}, {2,3})
* Precondition :
* - every indices is listed in the {...} exactly once.
* - the indices in one group are consecutive in memory.
* Routine is not extra-fast, since it does check the preconditions
*/
template <typename A, typename ...U>
array_view<typename A::value_type, sizeof...(U)> group_indices_view(A const& a, std::initializer_list<U>... args) {
auto indices_groups = std::vector<std::vector<int>>{std::vector<int>(args)...};
static const int Rf = sizeof...(U);
if (Rf != indices_groups.size())
TRIQS_RUNTIME_ERROR << "Return rank is " << Rf << " but " << indices_groups.size() << " indices are given";
/// First check indices are contiguous in memory
auto mem_pos = a.indexmap().get_memory_layout().get_memory_positions();
for (auto const& gr : indices_groups) {
auto gr2 = std::vector<int>(gr.size());
for (int i = 0; i < int(gr.size()); ++i) gr2[i] = mem_pos[gr[i]];
if (*std::max_element(begin(gr2), end(gr2)) - *std::min_element(begin(gr2), end(gr2)) + 1 != gr2.size())
TRIQS_RUNTIME_ERROR << "Indices not contiguous in memory";
}
/// Now compute the new lengths and strides.
mini_vector<size_t, Rf> l;
mini_vector<std::ptrdiff_t, Rf> s;
auto la = a.indexmap().lengths();
l = 1;
s = a.num_elements(); // init : superior to all strides, so a good start for the min ...
for (int i = 0; i < Rf; ++i) {
for (auto ind : indices_groups[i]) {
if (la[ind] == -1) TRIQS_RUNTIME_ERROR << "Index "<< ind << "given multiple times";
l[i] *= la [ind];
la[ind] = -1;
s[i] = std::min(s[i], a.indexmap().strides()[ind]);
}
}
/// Check all indices have been used
for (int i = 0; i < la.size(); ++i)
if (la[i] != -1) TRIQS_RUNTIME_ERROR << "Grouping incomplete : index " << i << " is to taken into account";
/// Return the new view (indexmap, storage)
return {{l, s, 0}, a.storage()};
}
}
}

View File

@ -114,9 +114,19 @@ namespace triqs { namespace arrays {
TRIQS_REJECT_MATRIX_COMPOUND_MUL_DIV_NON_SCALAR; TRIQS_REJECT_MATRIX_COMPOUND_MUL_DIV_NON_SCALAR;
typedef typename LHS::value_type value_type; typedef typename LHS::value_type value_type;
LHS & lhs; const RHS & rhs; LHS & lhs; const RHS & rhs;
impl(LHS & lhs_, const RHS & rhs_): lhs(lhs_), rhs(rhs_) {} //, p(*(lhs_.data_start())) {} impl(LHS & lhs_, const RHS & rhs_): lhs(lhs_), rhs(rhs_) {}
template<typename ... Args> void operator()(Args const & ... args) const { _ops_<value_type, typename RHS::value_type, OP>::invoke(lhs(args...),rhs(args...));} template<typename ... Args> void operator()(Args const & ... args) const { _ops_<value_type, typename RHS::value_type, OP>::invoke(lhs(args...),rhs(args...));}
void invoke() { foreach(lhs,*this); } FORCEINLINE void invoke() { foreach(lhs,*this); }
};
// help compiler : in the most common case, less things to inline..
template<typename LHS, typename RHS>
struct impl<LHS,RHS,'E', ENABLE_IFC( ImmutableCuboidArray<RHS>::value && (!is_scalar_for<RHS,LHS>::value) && (!is_isp<RHS,LHS>::value)&& (!is_special<LHS,RHS>::value)) > {
TRIQS_REJECT_ASSIGN_TO_CONST;
typedef typename LHS::value_type value_type;
LHS & lhs; const RHS & rhs;
impl(LHS & lhs_, const RHS & rhs_): lhs(lhs_), rhs(rhs_) {}
FORCEINLINE void invoke() { assign_foreach(lhs, rhs); }
}; };
// ----------------- assignment for scalar RHS, except some matrix case -------------------------------------------------- // ----------------- assignment for scalar RHS, except some matrix case --------------------------------------------------

View File

@ -1,87 +0,0 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2013 by O. Parcollet
*
* TRIQS 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 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_ARRAYS_FLAGS_H
#define TRIQS_ARRAYS_FLAGS_H
#include "../indexmaps/permutation.hpp"
namespace triqs { namespace arrays {
typedef unsigned long long ull_t;
namespace Tag {struct no_init {}; struct default_init {};}
// Flags is a 64 bit unsigned int.
// 0 is the default option.
// Meaning of the bits :
// 0 -> Const
// 1,2 -> Predefined order :
// 0 : None, 1 : C, 2 : Fortran
// 3 -> Init the array
// 5 -> Boundcheck
constexpr ull_t TraversalOrderC = 1ull << 1;
constexpr ull_t TraversalOrderFortran = 1ull << 2;
constexpr ull_t DefaultInit = 1ull << 3;
constexpr ull_t BoundCheck = 1ull << 5;
#define BOUND_CHECK triqs::arrays::BoundCheck
#define TRAVERSAL_ORDER_C triqs::arrays::TraversalOrderC
#define TRAVERSAL_ORDER_FORTRAN triqs::arrays::TraversalOrderFortran
#define DEFAULT_INIT triqs::arrays::DefaultInit
// NB : flags MUST be insensitive to slicing ...
// i.e. when I slice, the flags does not change.
namespace flags {
constexpr ull_t get(ull_t f, ull_t a) { return ((f & (1ull<<a)) >> a);}
constexpr ull_t get2(ull_t f, ull_t a) { return ((f & ((1ull<<a) + (1ull<< (a+1ull)))) >> a);}
#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
constexpr bool bound_check (ull_t f) { return true;}
#else
constexpr bool bound_check (ull_t f) { return get (f, 5)!=0;}
#endif
constexpr bool traversal_order_c (ull_t f) { return get (f,1ull)!=0ull;}
constexpr bool traversal_order_fortran (ull_t f) { return get (f,2ull)!=0ull;}
template< ull_t F> struct bound_check_trait { static constexpr bool value = bound_check(F); };
constexpr ull_t init_mode (ull_t f) { return get (f,3);}
template<ull_t F> struct init_tag1;
template<> struct init_tag1<0> { typedef Tag::no_init type;};
template<> struct init_tag1<1> { typedef Tag::default_init type;};
// for the init_tag, we pass the *whole* option flag.
template<ull_t F> struct init_tag : init_tag1 < init_mode(F)> {};
template<ull_t F, ull_t To> struct assert_make_sense {
static constexpr bool bc = bound_check(F);
static constexpr bool is_c = traversal_order_c(F);
static constexpr bool is_f = traversal_order_fortran(F);
static_assert ( (!( is_c && is_f)), "You asked C and Fortran traversal order at the same time...");
static_assert ( (!( (is_c || is_f) && To )), "You asked C or Fortran traversal order and gave a traversal order ...");
};
}
}}//namespace triqs::arrays
#endif

View File

@ -18,12 +18,11 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAY_IMPL_INDEX_STORAGE_PAIR_H #pragma once
#define TRIQS_ARRAY_IMPL_INDEX_STORAGE_PAIR_H
#include "./common.hpp" #include "./common.hpp"
#include "./flags.hpp"
#include "../storages/shared_block.hpp" #include "../storages/shared_block.hpp"
#include "./assignment.hpp" #include "./assignment.hpp"
#include "./print.hpp"
#include "../indexmaps/cuboid/foreach.hpp" #include "../indexmaps/cuboid/foreach.hpp"
#include "triqs/utility/exceptions.hpp" #include "triqs/utility/exceptions.hpp"
#include "triqs/utility/typeid_name.hpp" #include "triqs/utility/typeid_name.hpp"
@ -36,7 +35,7 @@
namespace triqs { namespace arrays { namespace triqs { namespace arrays {
template<typename A> auto get_shape (A const & x) DECL_AND_RETURN(x.domain().lengths()); template<typename A> AUTO_DECL get_shape (A const & x) RETURN(x.domain().lengths());
template<typename A> size_t first_dim (A const & x) { return x.domain().lengths()[0];} template<typename A> size_t first_dim (A const & x) { return x.domain().lengths()[0];}
template<typename A> size_t second_dim (A const & x) { return x.domain().lengths()[1];} template<typename A> size_t second_dim (A const & x) { return x.domain().lengths()[1];}
@ -45,23 +44,25 @@ namespace triqs { namespace arrays {
template<typename A> size_t fifth_dim (A const & x) { return x.domain().lengths()[4];} template<typename A> size_t fifth_dim (A const & x) { return x.domain().lengths()[4];}
template<typename A> size_t sixth_dim (A const & x) { return x.domain().lengths()[5];} template<typename A> size_t sixth_dim (A const & x) { return x.domain().lengths()[5];}
template<typename A> size_t seventh_dim (A const & x) { return x.domain().lengths()[6];} template<typename A> size_t seventh_dim (A const & x) { return x.domain().lengths()[6];}
template<typename A> size_t eighth_dim (A const & x) { return x.domain().lengths()[7];}
template<typename A> size_t ninth_dim (A const & x) { return x.domain().lengths()[8];}
template <bool Const, typename IndexMapIterator, typename StorageType > class iterator_adapter; template <bool Const, typename IndexMapIterator, typename StorageType > class iterator_adapter;
template <class V, int R, ull_t OptionFlags, ull_t TraversalOrder, class ViewTag, bool Borrowed, bool IsConst> struct ISPViewType; template <class V, int R, typename TraversalOrder, class ViewTag, bool Borrowed, bool IsConst> struct ISPViewType;
template <typename IndexMapType, typename StorageType, ull_t OptionFlags, ull_t TraversalOrder, bool IsConst, bool IsView, typename ViewTag> template <typename IndexMapType, typename StorageType, typename TraversalOrder, bool IsConst, bool IsView, typename ViewTag>
class indexmap_storage_pair : Tag::indexmap_storage_pair, TRIQS_CONCEPT_TAG_NAME(MutableCuboidArray) { class indexmap_storage_pair : Tag::indexmap_storage_pair, TRIQS_CONCEPT_TAG_NAME(MutableCuboidArray) {
public : public :
typedef typename StorageType::value_type value_type; using value_type=typename StorageType::value_type ;
static_assert(std::is_constructible<value_type>::value, "array/array_view and const operate only on values"); static_assert(std::is_constructible<value_type>::value, "array/array_view and const operate only on values");
static_assert(!std::is_const<value_type>::value, "no const type"); static_assert(!std::is_const<value_type>::value, "no const type");
typedef StorageType storage_type; using storage_type=StorageType ;
typedef IndexMapType indexmap_type; using indexmap_type=IndexMapType ;
static constexpr unsigned int rank = IndexMapType::domain_type::rank; using traversal_order_t = typename _get_traversal_order_t<TraversalOrder>::type;
static constexpr ull_t opt_flags = OptionFlags; using traversal_order_arg = TraversalOrder;
static constexpr ull_t traversal_order = TraversalOrder; static constexpr int rank = IndexMapType::domain_type::rank;
static constexpr bool is_const = IsConst; static constexpr bool is_const = IsConst;
protected: protected:
@ -72,30 +73,25 @@ namespace triqs { namespace arrays {
// ------------------------------- constructors -------------------------------------------- // ------------------------------- constructors --------------------------------------------
indexmap_storage_pair() {} indexmap_storage_pair() {}
indexmap_storage_pair (indexmap_type const & IM, storage_type const & ST): indexmap_(IM),storage_(ST) {deleg(IM,ST);}
indexmap_storage_pair (indexmap_type && IM, storage_type && ST) : indexmap_(std::move(IM)),storage_(std::move(ST)){deleg(IM,ST);}
indexmap_storage_pair (indexmap_type const & IM, storage_type && ST) : indexmap_(IM),storage_(std::move(ST)) {deleg(IM,ST);}
/// The storage is allocated from the size of IM. indexmap_storage_pair(indexmap_type IM, storage_type ST) : indexmap_(std::move(IM)), storage_(std::move(ST)) {
indexmap_storage_pair (const indexmap_type & IM): indexmap_(IM),storage_(){
this->storage_ = StorageType(this->indexmap_.domain().number_of_elements(), typename flags::init_tag<OptionFlags>::type() );
}
private :
void deleg (const indexmap_type & IM, const storage_type & ST) {
//std::cerr << " construct ISP && ST "<< storage_type::is_weak<< std::endl;
#ifdef TRIQS_ARRAYS_CHECK_IM_STORAGE_COMPAT #ifdef TRIQS_ARRAYS_CHECK_IM_STORAGE_COMPAT
if (ST.size() != IM.domain().number_of_elements()) if (ST.size() != IM.domain().number_of_elements())
TRIQS_RUNTIME_ERROR<<"index_storage_pair construction : storage and indices are not compatible"; TRIQS_RUNTIME_ERROR<<"index_storage_pair construction : storage and indices are not compatible";
#endif #endif
} }
public: /// The storage is allocated from the size of IM.
/// Shallow copy indexmap_storage_pair(const indexmap_type &IM) : indexmap_(IM), storage_() {
indexmap_storage_pair(const indexmap_storage_pair & X):indexmap_(X.indexmap()),storage_(X.storage_){} storage_ = StorageType(indexmap_.domain().number_of_elements());
indexmap_storage_pair(indexmap_storage_pair && X):indexmap_(std::move(X.indexmap())),storage_(std::move(X.storage_)){} }
protected:
public:
// Shallow copy
indexmap_storage_pair(indexmap_storage_pair const &X) = default;
indexmap_storage_pair(indexmap_storage_pair &&X) = default;
protected:
#ifdef TRIQS_WITH_PYTHON_SUPPORT #ifdef TRIQS_WITH_PYTHON_SUPPORT
indexmap_storage_pair (PyObject * X, bool enforce_copy, const char * name ) { indexmap_storage_pair (PyObject * X, bool enforce_copy, const char * name ) {
try { try {
@ -109,11 +105,9 @@ namespace triqs { namespace arrays {
// linker search for IndexMapType::domain_type::rank in triqs.so // linker search for IndexMapType::domain_type::rank in triqs.so
// and cannot resolve it ??? // and cannot resolve it ???
//<<"\n rank = "<< IndexMapType::domain_type::rank//this->rank //<<"\n rank = "<< IndexMapType::domain_type::rank//this->rank
<<"\n OptionFlags = "<< OptionFlags
<<"\nfrom the python object \n"<< numpy_interface::object_to_string(X) <<"\nfrom the python object \n"<< numpy_interface::object_to_string(X)
<<"\nThe error was :\n "<<s.what(); <<"\nThe error was :\n "<<s.what();
} }
//std::cerr << " Leave IPS ref count = "<< X->ob_refcnt << std::endl;
} }
#endif #endif
// ------------------------------- swap -------------------------------------------- // ------------------------------- swap --------------------------------------------
@ -156,10 +150,10 @@ namespace triqs { namespace arrays {
value_type const * restrict data_start() const { return &storage_[indexmap_.start_shift()];} value_type const * restrict data_start() const { return &storage_[indexmap_.start_shift()];}
value_type * restrict data_start() { return &storage_[indexmap_.start_shift()];} value_type * restrict data_start() { return &storage_[indexmap_.start_shift()];}
typedef typename indexmap_type::domain_type domain_type; using domain_type=typename indexmap_type::domain_type ;
domain_type const & domain() const { return indexmap_.domain();} domain_type const & domain() const { return indexmap_.domain();}
typedef typename domain_type::index_value_type shape_type; using shape_type=typename domain_type::index_value_type ;
shape_type const & shape() const { return domain().lengths();} shape_type const & shape() const { return domain().lengths();}
size_t shape(size_t i) const { return domain().lengths()[i];} size_t shape(size_t i) const { return domain().lengths()[i];}
@ -171,27 +165,27 @@ namespace triqs { namespace arrays {
// ------------------------------- operator () -------------------------------------------- // ------------------------------- operator () --------------------------------------------
typedef typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag,false, IsConst >::type view_type; using view_type = typename ISPViewType<value_type, domain_type::rank, TraversalOrder, ViewTag, false, IsConst>::type;
typedef typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag,true , IsConst>::type weak_view_type; using weak_view_type = typename ISPViewType<value_type, domain_type::rank, TraversalOrder, ViewTag, true, IsConst>::type;
// Evaluation and slices // Evaluation and slices
template<typename... Args> template<typename... Args>
typename std::enable_if< std14::enable_if_t<
(!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0) && (!IsConst) (!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0) && (!IsConst)
, value_type &>::type , value_type &>
operator()(Args const & ... args) & { return storage_[indexmap_(args...)]; } operator()(Args const & ... args) & { return storage_[indexmap_(args...)]; }
template<typename... Args> template<typename... Args>
typename std::enable_if< std14::enable_if_t<
(!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0) (!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0)
, value_type const &>::type , value_type const &>
operator()(Args const & ... args) const & { return storage_[indexmap_(args...)]; } operator()(Args const & ... args) const & { return storage_[indexmap_(args...)]; }
// && : return a & iif it is a non const view // && : return a & iif it is a non const view
template<typename... Args> template<typename... Args>
typename std::enable_if< std14::enable_if_t<
(!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0) && (!IsConst&&IsView) (!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0) && (!IsConst&&IsView)
, value_type &>::type , value_type &>
operator()(Args const & ... args) && { operator()(Args const & ... args) && {
// add here a security check in case it is a view, unique. For a regular type, move the result... // add here a security check in case it is a view, unique. For a regular type, move the result...
#ifdef TRIQS_ARRAYS_DEBUG #ifdef TRIQS_ARRAYS_DEBUG
@ -202,17 +196,18 @@ namespace triqs { namespace arrays {
// && return a value if this is not a view (regular class) or it is a const_view // && return a value if this is not a view (regular class) or it is a const_view
template<typename... Args> template<typename... Args>
typename std::enable_if< std14::enable_if_t<
(!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0) && (!(!IsConst&&IsView)) (!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0) && (!(!IsConst&&IsView))
, value_type>::type , value_type>
operator()(Args const & ... args) && { return storage_[indexmap_(args...)]; } operator()(Args const & ... args) && { return storage_[indexmap_(args...)]; }
template<bool is_const, bool ForceBorrowed, typename ... Args> struct result_of_call_as_view { template<bool is_const, bool ForceBorrowed, typename ... Args> struct result_of_call_as_view {
typedef typename indexmaps::slicer<indexmap_type,Args...>::r_type IM2; using IM2=typename indexmaps::slicer<indexmap_type,Args...>::r_type ;
//typedef typename std::conditional<is_const, typename std::add_const<value_type>::type, value_type>::type V2; //using V2=typename std::conditional<is_const, typename std::add_const<value_type>::type, value_type>::type ;
typedef value_type V2; using V2=value_type ;
static_assert(IM2::domain_type::rank !=0, "Internal error"); static_assert(IM2::domain_type::rank !=0, "Internal error");
typedef typename ISPViewType<V2,IM2::domain_type::rank, OptionFlags, IM2::traversal_order_in_template, ViewTag, ForceBorrowed || StorageType::is_weak, is_const >::type type; typedef typename ISPViewType < V2, IM2::domain_type::rank, typename IM2::traversal_order_in_template, ViewTag,
ForceBorrowed || StorageType::is_weak, is_const > ::type type;
}; };
template<typename... Args> // non const version template<typename... Args> // non const version
@ -243,13 +238,13 @@ namespace triqs { namespace arrays {
} }
/// Equivalent to make_view /// Equivalent to make_view
typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag, true, true >::type typename ISPViewType<value_type,domain_type::rank, TraversalOrder, ViewTag, true, true >::type
operator()() const & { return *this; } operator()() const & { return *this; }
typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag, true, IsConst >::type typename ISPViewType<value_type,domain_type::rank, TraversalOrder, ViewTag, true, IsConst >::type
operator()() & { return *this; } operator()() & { return *this; }
typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag, StorageType::is_weak,IsConst >::type typename ISPViewType<value_type,domain_type::rank, TraversalOrder, ViewTag, StorageType::is_weak,IsConst >::type
operator()() && { return *this; } operator()() && { return *this; }
// Interaction with the CLEF library : calling with any clef expression as argument build a new clef expression // Interaction with the CLEF library : calling with any clef expression as argument build a new clef expression
@ -297,8 +292,8 @@ namespace triqs { namespace arrays {
// template<typename Fnt> friend void triqs_clef_auto_assign (indexmap_storage_pair & x, Fnt f) { assign_foreach(x,f);} // template<typename Fnt> friend void triqs_clef_auto_assign (indexmap_storage_pair & x, Fnt f) { assign_foreach(x,f);}
// ------------------------------- Iterators -------------------------------------------- // ------------------------------- Iterators --------------------------------------------
typedef iterator_adapter<true,typename IndexMapType::iterator, StorageType> const_iterator; using const_iterator=iterator_adapter<true,typename IndexMapType::iterator, StorageType> ;
typedef iterator_adapter<false,typename IndexMapType::iterator, StorageType> iterator; using iterator=iterator_adapter<false,typename IndexMapType::iterator, StorageType> ;
const_iterator begin() const {return const_iterator(indexmap(),storage(),false);} const_iterator begin() const {return const_iterator(indexmap(),storage(),false);}
const_iterator end() const {return const_iterator(indexmap(),storage(),true);} const_iterator end() const {return const_iterator(indexmap(),storage(),true);}
const_iterator cbegin() const {return const_iterator(indexmap(),storage(),false);} const_iterator cbegin() const {return const_iterator(indexmap(),storage(),false);}
@ -311,11 +306,11 @@ namespace triqs { namespace arrays {
// ------------------------------- resize -------------------------------------------- // ------------------------------- resize --------------------------------------------
// //
void resize (domain_type const & d) { void resize (domain_type const & d) {
this->indexmap_ = IndexMapType(d,this->indexmap_.memory_indices_layout()); indexmap_ = IndexMapType(d,indexmap_.get_memory_layout());
// build a new one with the lengths of IND BUT THE SAME layout ! // build a new one with the lengths of IND BUT THE SAME layout !
// optimisation. Construct a storage only if the new index is not compatible (size mismatch). // optimisation. Construct a storage only if the new index is not compatible (size mismatch).
if (this->storage_.size() != this->indexmap_.domain().number_of_elements()) if (storage_.size() != indexmap_.domain().number_of_elements())
this->storage_ = StorageType(this->indexmap_.domain().number_of_elements(), typename flags::init_tag<OptionFlags>::type() ); storage_ = StorageType(indexmap_.domain().number_of_elements());
} }
template<typename Xtype> template<typename Xtype>
@ -332,11 +327,10 @@ namespace triqs { namespace arrays {
// pretty print of the array // pretty print of the array
friend std::ostream & operator << (std::ostream & out, const indexmap_storage_pair & A) { friend std::ostream & operator << (std::ostream & out, const indexmap_storage_pair & A) {
if (A.storage().size()==0) out<<"empty "; if (A.storage().size()==0) out<<"empty ";
else indexmaps::pretty_print(out,A); else pretty_print(out,A);
return out; return out;
} }
};// end class };// end class
}}//namespace triqs::arrays }}//namespace triqs::arrays
#endif

View File

@ -0,0 +1,77 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by O. Parcollet
*
* TRIQS 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 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include <triqs/utility/first_include.hpp>
namespace triqs {
namespace arrays {
/// ------------ Pretty Printing : specializing the default behaviour for d=1,2 -------------------------
namespace PrettyPrint_details {
template <int R, typename A> struct print_impl {
std::ostream &out;
A const &a;
print_impl(std::ostream &out_, A const &a_) : out(out_), a(a_) {}
template <typename A0, typename... Args> void operator()(A0 const &a0, Args const &... args) const {
out << a(a0, args...) << " ";
}
void print() const {
out << "[";
// indexmaps::cuboid::foreach<permutations::identity(A::domain_type::rank)>(a.domain(),
// std::cref(*this)); // foreach(a, std::cref(*this));
indexmaps::cuboid::foreach_impl(_traversal_fortran{}, a.domain(), FORTRAN_LAYOUT, *this);
// foreach(a, *this);
out << "]";
}
};
template <typename A> struct print_impl<1, A> {
std::ostream &out;
A const &a;
print_impl(std::ostream &out_, A const &a_) : out(out_), a(a_) {}
void print() const {
auto d = a.indexmap().domain();
out << "[";
for (size_t i = 0; i < d.lengths()[0]; ++i) out << (i > 0 ? "," : "") << a(i);
out << "]";
}
};
template <typename A> struct print_impl<2, A> {
std::ostream &out;
A const &a;
print_impl(std::ostream &out_, A const &a_) : out(out_), a(a_) {}
void print() const {
auto d = a.indexmap().domain();
out << "\n[";
for (size_t i = 0; i < d.lengths()[0]; ++i) {
out << (i == 0 ? "[" : " [");
for (size_t j = 0; j < d.lengths()[1]; ++j) out << (j > 0 ? "," : "") << a(i, j);
out << "]" << (i == d.lengths()[0] - 1 ? "" : "\n");
}
out << "]";
}
};
}
template <typename A> void pretty_print(std::ostream &out, A const &a) {
PrettyPrint_details::print_impl<A::domain_type::rank, A>(out, a).print();
}
}
}

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011-2013 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -18,180 +18,132 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_DOMAIN_H #pragma once
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_DOMAIN_H
#include "../common.hpp" #include "../common.hpp"
#include "../range.hpp" #include "../range.hpp"
#include "./mem_layout.hpp" #include "./mem_layout.hpp"
#include "../permutation.hpp"
#include <triqs/utility/mini_vector.hpp> #include <triqs/utility/mini_vector.hpp>
#include "../../impl/exceptions.hpp" #include "../../impl/exceptions.hpp"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid { namespace triqs {
using namespace triqs::arrays::permutations; namespace arrays {
namespace indexmaps {
namespace cuboid {
using namespace triqs::arrays::permutations;
/// Standard hyper_rectangular domain for arrays /// Standard hyper_rectangular domain for arrays
template<int Rank> template <int Rank> class domain_t {
class domain_t { using n_uple = mini_vector<size_t, Rank>;
typedef mini_vector<size_t,Rank> n_uple; n_uple lengths_;
n_uple lengths_; friend class boost::serialization::access;
friend class boost::serialization::access; template <class Archive> void serialize(Archive &ar, const unsigned int version) {
template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & TRIQS_MAKE_NVP("dimensions",lengths_);} ar &TRIQS_MAKE_NVP("dimensions", lengths_);
public : }
static constexpr unsigned int rank = Rank;
typedef n_uple index_value_type;
domain_t () =default; public:
domain_t (const domain_t & C) = default; static constexpr unsigned int rank = Rank;
domain_t (domain_t && C) = default; using index_value_type = n_uple;
domain_t & operator =( domain_t const &) = default;
domain_t & operator =( domain_t && x)= default;
domain_t (n_uple lengths):lengths_(std::move(lengths)) {} domain_t() = default;
domain_t (mini_vector<int,Rank> const & lengths):lengths_(lengths) {} domain_t(const domain_t &C) = default;
domain_t (std::vector<std::size_t> const & l):lengths_() { domain_t(domain_t &&C) = default;
if (!(l.size()==Rank)) TRIQS_RUNTIME_ERROR << "cuboid domain_t construction : vector size incorrect : got "<<l.size() <<" while expected "<< Rank; domain_t &operator=(domain_t const &) = default;
lengths_ = n_uple(l); domain_t &operator=(domain_t &&x) = default;
}
template <typename ... T> domain_t(size_t i0, T... t): lengths_(i0, t...){}
size_t number_of_elements() const { return lengths_.product_of_elements();} domain_t(n_uple lengths) : lengths_(std::move(lengths)) {}
bool operator==(domain_t const & X) const { return this->lengths_ == X.lengths_;} domain_t(mini_vector<int, Rank> const &lengths) : lengths_(lengths) {}
bool operator!=(domain_t const & X) const { return !(*this==X);} domain_t(std::vector<std::size_t> const &l) : lengths_() {
n_uple const & lengths() const & { return lengths_;} if (!(l.size() == Rank))
n_uple lengths() && { return lengths_;} TRIQS_RUNTIME_ERROR << "cuboid domain_t construction : vector size incorrect : got " << l.size() << " while expected "
/** Generates the value of the indices of a cuboid_domain. */ << Rank;
static constexpr ull_t iteration_order_default = permutations::identity(Rank); lengths_ = n_uple(l);
template <ull_t IterationOrder= iteration_order_default > }
class gal_generator { template <typename... T> domain_t(size_t i0, T... t) : lengths_(i0, t...) {}
typedef index_value_type indices_type;
const domain_t * dom; size_t number_of_elements() const { return lengths_.product_of_elements(); }
bool operator==(domain_t const &X) const { return this->lengths_ == X.lengths_; }
bool operator!=(domain_t const &X) const { return !(*this == X); }
n_uple const &lengths() const &{ return lengths_; }
n_uple lengths() && { return lengths_; }
/** Generates the value of the indices of a cuboid_domain. */
static constexpr ull_t iteration_order_default = permutations::identity(Rank);
template <ull_t IterationOrder = iteration_order_default> class gal_generator {
using indices_type = index_value_type;
const domain_t *dom;
indices_type indices_tuple; indices_type indices_tuple;
bool atend; bool atend;
public: public:
gal_generator (const domain_t & P, bool atEnd=false): dom(&P), atend(atEnd) {} gal_generator(const domain_t &P, bool atEnd = false) : dom(&P), atend(atEnd) {}
bool operator==(const gal_generator & IT2) const { assert((IT2.dom == dom)); return ((IT2.atend==atend) );} bool operator==(const gal_generator &IT2) const {
bool operator!=(const gal_generator & IT2) const { return (!operator==(IT2));} assert((IT2.dom == dom));
indices_type const & operator *() const { return indices_tuple;} return ((IT2.atend == atend));
explicit operator bool () const { return !atend;}
gal_generator & operator++(){ assert(!atend); atend = advance_impl(std::integral_constant<int,0>()); return *this;}
private:
template<int r> bool advance_impl(std::integral_constant<int,r>) {
constexpr int p = permutations::apply(IterationOrder, r);
if (indices_tuple[p] < dom->lengths()[p]-1) { ++(indices_tuple[p]); return false;}
indices_tuple[p] = 0;
return advance_impl(std::integral_constant<int,r+1>());
} }
bool advance_impl(std::integral_constant<int,rank>) { return true;} bool operator!=(const gal_generator &IT2) const { return (!operator==(IT2)); }
indices_type const &operator*() const { return indices_tuple; }
explicit operator bool() const { return !atend; }
gal_generator &operator++() {
assert(!atend);
atend = advance_impl(std::integral_constant<int, 0>());
return *this;
}
private:
template <int r> bool advance_impl(std::integral_constant<int, r>) {
constexpr int p = permutations::apply(IterationOrder, r);
if (indices_tuple[p] < dom->lengths()[p] - 1) {
++(indices_tuple[p]);
return false;
}
indices_tuple[p] = 0;
return advance_impl(std::integral_constant<int, r + 1>());
}
bool advance_impl(std::integral_constant<int, rank>) { return true; }
}; };
typedef gal_generator<> generator; using generator = gal_generator<>;
generator begin() const { return generator(*this,false);} generator begin() const { return generator(*this, false); }
generator end() const { return generator(*this,true);} generator end() const { return generator(*this, true); }
/* End of generator */ /* End of generator */
// Check that key in in the domain // Check that key in in the domain
template<class KeyType> void assert_key_in_domain(KeyType const & key) const { template <class KeyType> void assert_key_in_domain(KeyType const &key) const {
std::stringstream fs; std::stringstream fs;
bool res = key_check_impl(std::integral_constant<int,0>(), key,this->lengths_,fs); bool res = key_check_impl(std::integral_constant<int, 0>(), key, this->lengths_, fs);
if (!res) TRIQS_ARRAYS_KEY_ERROR << " key out of domain \n" <<fs.str() ; if (!res) TRIQS_ARRAYS_KEY_ERROR << " key out of domain \n" << fs.str();
}
template<int r,class KeyType>
bool key_check_impl (std::integral_constant<int,r>, KeyType const & key, n_uple const & L, std::stringstream & fs ) const {
//bool cond = ( ( size_t(key[r]) < L[r]));
bool cond = ( ( size_t(std::get<r>(key)) < L[r]));
//if (!cond) fs << "key ["<<r<<"] = "<< key[r] <<" is not within [0,"<<L[r]<<"[\n";
if (!cond) fs << "key ["<<r<<"] = "<< std::get<r>(key) <<" is not within [0,"<<L[r]<<"[\n";
return key_check_impl(std::integral_constant<int,r+1>(), key,L,fs) && cond;
} }
template<class KeyType> bool key_check_impl (std::integral_constant<int,rank>, KeyType const &, n_uple const &, std::stringstream &) const { return true;} template <int r, class KeyType>
bool key_check_impl(std::integral_constant<int, r>, KeyType const &key, n_uple const &L, std::stringstream &fs) const {
// Check that key in in the domain : variadic form. No need for speed optimisation here, it is just for debug bool cond = ((size_t(std::get<r>(key)) < L[r]));
template<typename ... Args> void assert_key_in_domain_v (Args const & ... args) const { assert_key_in_domain( std::make_tuple(args...));} if (!cond) fs << "key [" << r << "] = " << std::get<r>(key) << " is not within [0," << L[r] << "[\n";
return key_check_impl(std::integral_constant<int, r + 1>(), key, L, fs) && cond;
friend std::ostream & operator<<(std::ostream & out, domain_t const & x){return out<<"Cuboid of rank "<<x.rank<<" and dimensions "<<x.lengths();} }
template <class KeyType>
}; bool key_check_impl(std::integral_constant<int, rank>, KeyType const &, n_uple const &, std::stringstream &) const {
return true;
// ------------------------- foreach -----------------------------------------------------
//typedef size_t foreach_int_type;
typedef std::ptrdiff_t foreach_int_type;
// better to be signed here : 1) on some machine/compiler, it is a lot faster !
// When used with clef auto assign, e.g. A(i_,j_) = i -2*j, one needs signed arithmetics
#define AUX0(z,P,NNN) constexpr int p##P = mem_layout::memory_rank_to_index(TraversalOrder,NNN-P);
#define AUX1(z,P,unused) for (t[p##P]=0; t[p##P]< l[p##P]; ++t[p##P])
//#define AUX1(z,P,unused) for (foreach_int_type x##P=0; x##P< dom.lengths()[p##P]; ++x##P)
#define AUX3(z,p,unused) BOOST_PP_COMMA_IF(p) t[p]
#define IMPL(z, RR, unused) \
template<ull_t TraversalOrder, typename FntType> void foreach(domain_t<RR> const & dom, FntType F) {\
BOOST_PP_REPEAT(RR,AUX0,BOOST_PP_DEC(RR))\
mini_vector<foreach_int_type,RR> t;\
const mini_vector<foreach_int_type,RR> l(dom.lengths());\
BOOST_PP_REPEAT(RR,AUX1,nil){ F(BOOST_PP_REPEAT(RR,AUX3,nil)); }}
BOOST_PP_REPEAT_FROM_TO(1,ARRAY_NRANK_MAX , IMPL, nil);
#undef IMPL
#undef AUX0
#undef AUX1
#undef AUX3
}
/// ------------ Pretty Printing : specializing the default behaviour for d=1,2 -------------------------
namespace PrettyPrint_details {
template<int R, typename A>
struct print_impl {
std::ostream & out; A const & a;
print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){}
template<typename A0, typename ... Args> void operator()(A0 const & a0, Args const & ... args) const { out << a(a0,args...)<< " ";}
void print() const { out<<"[";
indexmaps::cuboid::foreach<permutations::identity(A::domain_type::rank)> (a.domain(), std::cref(*this)); //foreach(a, std::cref(*this));
out<<"]"; }
};
template<typename A>
struct print_impl <1,A> {
std::ostream & out; A const & a;
print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){}
void print() const {
auto d = a.indexmap().domain();
out<<"["; for (size_t i=0; i< d.lengths()[0]; ++i) out<<(i>0 ? ",": "")<<a(i); out<<"]";}
};
template<typename A>
struct print_impl <2,A> {
std::ostream & out; A const & a;
print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){}
void print() const {
auto d = a.indexmap().domain();
out<<"\n[";
for (size_t i=0; i< d.lengths()[0]; ++i) {
out<<(i==0 ? "[" : " [");
for (size_t j=0; j< d.lengths()[1]; ++j) out<<(j>0 ? ",": "")<<a(i,j);
out<<"]"<<(i==d.lengths()[0]-1 ? "" : "\n");
} }
out<<"]";
}
};
// Check that key in in the domain : variadic form. No need for speed optimisation here, it is just for debug
template <typename... Args> void assert_key_in_domain_v(Args const &... args) const {
assert_key_in_domain(std::make_tuple(args...));
}
friend std::ostream &operator<<(std::ostream &out, domain_t const &x) {
return out << "Cuboid of rank " << x.rank << " and dimensions " << x.lengths();
}
};
}
}
template <typename... U> indexmaps::cuboid::domain_t<sizeof...(U)> make_cuboid_domain(U... u) {
return {size_t(u)...};
}
using matrix_shape_t = indexmaps::cuboid::domain_t<2>;
using vector_shape_t = indexmaps::cuboid::domain_t<1>;
} }
template<typename A>
void pretty_print (std::ostream & out, A const & a ) { PrettyPrint_details::print_impl<A::domain_type::rank,A>(out,a).print();}
} }
template<typename ... U>
indexmaps::cuboid::domain_t<sizeof...(U)> make_cuboid_domain(U ... u) { return {size_t(u)...};}
//cuboid_array_domain<sizeof...(U)> make_cuboid_domain(U ... u) { return {u...};}
typedef indexmaps::cuboid::domain_t<2> matrix_shape_t;
typedef indexmaps::cuboid::domain_t<1> vector_shape_t;
}}
#endif

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -18,30 +18,125 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_FOREACH_H #pragma once
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_FOREACH_H
#include "./map.hpp" #include "./map.hpp"
#include "./mem_layout.hpp"
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
namespace triqs { namespace arrays { namespace triqs {
namespace arrays {
template<typename A, typename Enable = void> struct get_traversal_order : indexmaps::mem_layout::fortran_order_tr<A::domain_type::rank>{}; #define FORCEINLINE __inline__ __attribute__((always_inline))
//template<typename A, typename Enable = void> struct get_traversal_order : indexmaps::mem_layout::c_order_tr<A::domain_type::rank>{};
template<typename A> struct get_traversal_order<A,typename A::indexmap_type::has_traversal_order_tag> : std::integral_constant<ull_t, A::indexmap_type::traversal_order>{};
// ------------------------- foreach -----------------------------------------------------
namespace indexmaps {
namespace cuboid {
// using foreach_int_type=size_t ;
using foreach_int_type = std::ptrdiff_t;
// better to be signed here : 1) on some machine/compiler, it is a lot faster !
// When used with clef auto assign, e.g. A(i_,j_) = i -2*j, one needs signed arithmetics
#define AUX_FOR(X) for (ind[X] = 0; ind[X] < l[X]; ++ind[X])
#define AUX_C(z, P, unused) for (foreach_int_type i##P = 0; i##P < l[P]; ++i##P)
#define AUX_F(z, P, RANK) AUX_FOR(RANK - P)
#define AUX_Dynamical(z, P, unused) AUX_FOR(ml[P])
#define AUX_Custom1(z, P, NNN) constexpr int p##P = permutations::apply(traversal_order_perm, P);
#define AUX_Custom2(z, P, unused) AUX_FOR(p##P)
#define AUX3(z, p, unused) BOOST_PP_COMMA_IF(p) ind[p]
#define AUX3C(z, p, unused) BOOST_PP_COMMA_IF(p) i##p
#define IMPL(z, RR, unused) \
template <typename FntType> \
FORCEINLINE void foreach_impl(_traversal_c, domain_t<RR> const& dom, memory_layout<RR> const& ml, FntType F) { \
const mini_vector<foreach_int_type, RR> l(dom.lengths()); \
BOOST_PP_REPEAT(RR, AUX_C, nil) { F(BOOST_PP_REPEAT(RR, AUX3C, nil)); } \
} \
template <typename FntType> \
FORCEINLINE void foreach_impl(_traversal_fortran, domain_t<RR> const& dom, memory_layout<RR> ml, FntType F) { \
foreach_int_type ind[RR]; \
const mini_vector<foreach_int_type, RR> l(dom.lengths()); \
BOOST_PP_REPEAT(RR, AUX_F, BOOST_PP_DEC(RR)) { F(BOOST_PP_REPEAT(RR, AUX3, nil)); } \
} \
template <typename FntType> \
FORCEINLINE void foreach_impl(_traversal_dynamical, domain_t<RR> const& dom, memory_layout<RR> ml, FntType F) { \
foreach_int_type ind[RR]; \
const mini_vector<foreach_int_type, RR> l(dom.lengths()); \
BOOST_PP_REPEAT(RR, AUX_Dynamical, nil) { F(BOOST_PP_REPEAT(RR, AUX3, nil)); } \
} \
template <typename FntType, int... Is> \
FORCEINLINE void foreach_impl(_traversal_custom<Is...>, domain_t<RR> const& dom, memory_layout<RR> ml, FntType F) { \
constexpr ull_t traversal_order_perm = permutations::permutation(Is...); \
BOOST_PP_REPEAT(RR, AUX_Custom1, BOOST_PP_DEC(RR)); \
foreach_int_type ind[RR]; \
const mini_vector<foreach_int_type, RR> l(dom.lengths()); \
BOOST_PP_REPEAT(RR, AUX_Custom2, nil) { F(BOOST_PP_REPEAT(RR, AUX3, nil)); } \
}
BOOST_PP_REPEAT_FROM_TO(1, ARRAY_NRANK_MAX, IMPL, nil);
#undef IMPL
#undef AUX_C
#undef AUX_F
#undef AUX_FOR
#undef AUX_Dynamical
#undef AUX_Custom
#undef AUX_Custom1
#undef AUX3
#undef AUX3C
}
}
/// Get the traversal order
template <typename A, typename Enable = void> struct _get_traversal_order {
using traversal_order_t = _traversal_c;
static memory_layout<A::domain_type::rank> invoke(A const& a) {
return memory_layout<A::domain_type::rank>{};
}
};
template <typename A> struct _get_traversal_order<A, typename A::indexmap_type::has_traversal_order_tag> {
using traversal_order_t = typename A::traversal_order_t;
static memory_layout<A::domain_type::rank> invoke(A const& a) { return a.indexmap().get_memory_layout(); }
};
/// --------------- FOREACH ------------------------
template <typename T, typename Function> template <typename T, typename Function>
typename std::enable_if<ImmutableCuboidArray<T>::value >::type FORCEINLINE std14::enable_if_t<ImmutableCuboidArray<T>::value> foreach(T const& x, Function const& F) {
foreach (T const & x, Function const & F) { indexmaps::cuboid::foreach<get_traversal_order<T>::value> (x.domain(), F); } using S = _get_traversal_order<T>;
#ifndef TRIQS_ARRAYS_FOREACH_C_OR_DYNAMICAL
template <typename T, typename Function> indexmaps::cuboid::foreach_impl(typename S::traversal_order_t{}, x.domain(), S::invoke(x), F);
struct assign_foreach_adapter { #else
T& x; Function const & f; if (ml.is_c()) {
assign_foreach_adapter( T& x_, Function const & ff): x(x_), f(ff){} indexmaps::cuboid::foreach_impl(_traversal_c{}, x.domain(), S::invoke(x), F);
template<typename ... Args> void operator()(Args const & ... args) const { x(args...) = f(args...);} } else {
}; indexmaps::cuboid::foreach_impl(_traversal_dynamical{}, x.domain(), S::invoke(x), F);
}
template <typename T, typename Function>
typename std::enable_if<MutableCuboidArray<T>::value >::type
assign_foreach (T & x, Function const & F) { indexmaps::cuboid::foreach<get_traversal_order<T>::value> (x.domain(),assign_foreach_adapter<T,Function>(x,F)); }
}}//namespace
#endif #endif
}
/// --------------- ASSIGN FOREACH ------------------------
#ifndef TRIQS_C11
template <typename T, typename Function>
std14::enable_if_t<MutableCuboidArray<T>::value> assign_foreach(T& x, Function const& f) {
using S = _get_traversal_order<T>;
indexmaps::cuboid::foreach_impl(typename S::traversal_order_t{}, x.domain(), S::invoke(x),
[&x, &f](auto const&... args) { x(args...) = f(args...); });
}
#else
template <typename T, typename Function> struct assign_foreach_adapter {
T& x;
Function const& f;
assign_foreach_adapter(T& x_, Function const& ff) : x(x_), f(ff) {}
template <typename... Args> void operator()(Args const&... args) const { x(args...) = f(args...); }
};
template <typename T, typename Function>
std14::enable_if_t<MutableCuboidArray<T>::value> assign_foreach(T& x, Function const& F) {
using S = _get_traversal_order<T>;
indexmaps::cuboid::foreach_impl(typename S::traversal_order_t{}, x.domain(), S::invoke(x),
assign_foreach_adapter<T, Function>(x, F));
}
#endif
}
} // namespace

View File

@ -1,107 +0,0 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2013 by O. Parcollet
*
* TRIQS 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 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_GROUP_INDICES_H
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_GROUP_INDICES_H
#include <triqs/arrays/array.hpp>
namespace triqs { namespace arrays {
// a variadic push_back into a vector.
template<typename V> void vector_push_back_v(V & v){}
template<typename V, typename T0, typename ... T> void vector_push_back_v(V & v, T0 && t0, T && ... t){ v.push_back(std::forward<T0>(t0)); vector_push_back_v(v,t...);}
// a list of compile time int...
template<int... Is> struct m_index{};
template<int I0, int... Is> struct m_index<I0,Is...> {static constexpr int head = I0; };
template<int... Is> std::vector<int> m_index_to_vector( m_index<Is...>) { std::vector<int> v; vector_push_back_v(v,Is...); return v;}
// a trait to get the min, max of a m_index
template<typename CTL> struct get_min_max;
template<int I0, int I1, int ... Is> struct get_min_max<m_index<I0, I1, Is...>> {
typedef get_min_max<m_index<I1,Is...>> r;
static constexpr int min = (I0 < r::min ? I0 : r::min); static constexpr int max = (I0 > r::max ? I0 : r::max);
};
template<int I0> struct get_min_max<m_index<I0>> { static constexpr int min = I0; static constexpr int max = I0; };
// given a m_index of indices, a metafunction to map to their position into memory
template<ull_t ML, typename CTL> struct index_group_to_mem_pos_list;
template<ull_t ML,int ... Is> struct index_group_to_mem_pos_list<ML,m_index<Is...>> {
typedef m_index < indexmaps::mem_layout::index_to_memory_rank(ML,Is)...> type;
static_assert( get_min_max<type>::max - get_min_max<type>::min + 1 == sizeof...(Is), "Indices not contiguous in memory");
};
#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS
// count the number of Is strictly smaller than C
constexpr int count_pos(int C){ return 0;}
template<typename ... T> constexpr int count_pos(int C, int i, T... t){ return (i<C ? 1 : 0) + count_pos(C, t...);}
// a metafunction to map this counting on a list
template<int ... Is> struct count_pos_list { typedef m_index< count_pos(Is, Is...)...> type; };
#else
template<int C, typename CTL> struct count_pos;
template<int C, int I0, int ... Is> struct count_pos<C,m_index<I0,Is...>> : std::integral_constant<int, count_pos<C,m_index<Is...>>::value + (I0<C ? 1 : 0)> {};
template<int C> struct count_pos<C,m_index<>> : std::integral_constant<int,0>{};
template<int ... Is> struct count_pos_list { typedef m_index<Is...> tmp; typedef m_index< count_pos<Is, tmp>::value...> type; };
#endif
// a simple foreach
template<typename Callee, typename T0, typename ... T> void for_each (Callee & C, T0 const & t0, T const & ... t ) { C(t0); for_each(C, t...);}
template<typename Callee> void for_each (Callee & C){}
// make a permutation out of a m_index
template<typename CTL> struct to_permu;
template<int ... Is> struct to_permu<m_index<Is...>> { static constexpr ull_t value = permutations::permutation(Is...);};
// the main class
template<typename A, typename ... MIndex> struct group_indices_impl {
static constexpr int new_dim = sizeof...(MIndex);
typedef typename count_pos_list< index_group_to_mem_pos_list<A::indexmap_type::traversal_order,MIndex>::type::head ...>::type new_memory_pos;
static constexpr ull_t traversal_layout = to_permu<new_memory_pos>::value;
typedef array_view<typename A::value_type, new_dim,0,traversal_layout > type;
static type invoke(A const & a) {
if (a.indexmap().memory_indices_layout_ull() != a.indexmap().traversal_order)
TRIQS_RUNTIME_ERROR << "Grouping indices is only possible for arrays when the memory_layout is the same as the traversal order \n"
<< "But here your memory_layout is "<< a.indexmap().memory_indices_layout() << " while the traversal order is "<< a.indexmap().traversal_order_indices_layout();
std::vector< std::vector<int> > Indices;
vector_push_back_v(Indices, m_index_to_vector(MIndex())...);
mini_vector<size_t, type::rank> l;
mini_vector<std::ptrdiff_t, type::rank> s;
for (size_t u=0; u<type::rank; ++u) {l[u]=1; s[u]=0;}
size_t i =0;
for (auto & m_index : Indices) {
bool first = true;
for (auto & ind : m_index) {
l[i] *= a.indexmap().lengths()[ind];
s[i] = (first ? a.indexmap().strides()[ind]: std::min(s[i], a.indexmap().strides()[ind]));
first = false;
}
++i;
}
//std::cerr << "strides "<< s << std::endl ;
typename type::indexmap_type im(l,s,0);
return type(im,a.storage());
}
};
template<typename A, typename ... MIndex >
typename group_indices_impl<A,MIndex... >::type group_indices(A const & a, MIndex... ) { return group_indices_impl<A,MIndex...>::invoke(a);}
}}//namespace triqs::arrays
#endif

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -18,50 +18,49 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_MAP_H #pragma once
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_MAP_H
#include "./domain.hpp" #include "./domain.hpp"
#include "./mem_layout.hpp" #include "./mem_layout.hpp"
#include "../../impl/flags.hpp"
#include <vector> #include <vector>
#include <boost/iterator/iterator_facade.hpp> #include <boost/iterator/iterator_facade.hpp>
namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid { namespace triqs { namespace arrays {
template< bool BC, class D, class K> struct _chk; struct _traversal_c {};
template< class D, class K> struct _chk<true, D, K> { static void invoke (D const & d, K const & k) {d.assert_key_in_domain(k);} }; struct _traversal_fortran {};
template< class D, class K> struct _chk<false, D, K> { static void invoke (D const & d, K const & k) {} }; struct _traversal_dynamical {};
template <int... Is> struct _traversal_custom {};
template< bool BC, class D, class ... K> struct _chk_v; template <typename T> struct _get_traversal_order_t {
template< class D, class ... K> struct _chk_v<true, D, K...> { static void invoke (D const & d, K const & ... k) {d.assert_key_in_domain_v(k...);} }; using type = T;
template< class D, class ... K> struct _chk_v<false, D, K...> { static void invoke (D const & d, K const & ... k) {} }; };
template <> struct _get_traversal_order_t<void> {
using type = _traversal_c;
};
template<int Rank> ull_t memory_layout_from_strides(mini_vector<std::ptrdiff_t, Rank> const & strides) { constexpr ull_t _get_traversal_order_permutation(int R, _traversal_c) { return permutations::identity(R); }
int c[Rank]; for (size_t i=0; i<Rank; ++i) c[i]=0; constexpr ull_t _get_traversal_order_permutation(int R, _traversal_fortran) { return permutations::ridentity(R); }
for (size_t i=0; i<Rank; ++i) template <int... Is> constexpr ull_t _get_traversal_order_permutation(int R,_traversal_custom<Is...>) {
for (size_t j=i+1; j<Rank; ++j) static_assert(sizeof...(Is) == R, " Rank mismatch");
if (strides[i] > strides[j]) c[i]++; else c[j]++; return permutations::permutation(Is...);
// we computed the map : index -> memory_rank, which is the inverse map, cf mem_layout
return permutations::inverse(permutations::permutation_from_array(c, Rank));
} }
namespace indexmaps { namespace cuboid {
/** Standard hyper_rectangular arrays, implementing the IndexMap concept. /** Standard hyper_rectangular arrays, implementing the IndexMap concept.
*/ */
template<int Rank, ull_t OptionsFlags, ull_t TraversalOrder > template <int Rank, typename TraversalOrder=void> class map {
class map {
public : public :
static constexpr bool CheckBounds = flags::bound_check_trait<OptionsFlags>::value; static const int rank = Rank;
static constexpr ull_t traversal_order_in_template = TraversalOrder; using lengths_type=mini_vector<size_t,rank> ;
static constexpr ull_t traversal_order = indexmaps::mem_layout::get_traversal_order<Rank, OptionsFlags, TraversalOrder>::value; using strides_type=mini_vector<std::ptrdiff_t, rank> ;
typedef void has_traversal_order_tag; using domain_type = domain_t<Rank>;
static const unsigned int rank = Rank; using traversal_order_in_template = TraversalOrder;
typedef mini_vector<size_t,rank> lengths_type; using has_traversal_order_tag = void;
typedef mini_vector<std::ptrdiff_t, rank> strides_type; domain_type const& domain() const { return mydomain; }
typedef domain_t<Rank> domain_type;
domain_type const & domain() const { return mydomain;}
// semi-regular type // semi-regular type
map (): start_shift_(0), memory_order_(memory_layout<Rank>(traversal_order)) {} map (): start_shift_(0), memory_order_() {}
map (map const & C) = default; map (map const & C) = default;
map (map && C) = default; map (map && C) = default;
map & operator = (map const & m) = default; map & operator = (map const & m) = default;
@ -69,8 +68,8 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
// basic construction // basic construction
map(memory_layout<Rank> const & ml):mydomain(), start_shift_(0), memory_order_(ml) {} map(memory_layout<Rank> const & ml):mydomain(), start_shift_(0), memory_order_(ml) {}
map(domain_type const & C): mydomain(C), start_shift_(0), memory_order_(traversal_order) {compute_stride_compact();} map(domain_type const & C): mydomain(C), start_shift_(0), memory_order_() {compute_stride_compact();}
map(domain_type const & C, memory_layout<Rank> ml): mydomain(C), start_shift_(0), memory_order_(ml) {compute_stride_compact();} map(domain_type const & C, memory_layout<Rank> ml): mydomain(C), start_shift_(0), memory_order_(std::move(ml)) {compute_stride_compact();}
/// Construction from the length, the stride, start_shift /// Construction from the length, the stride, start_shift
map(lengths_type Lengths, strides_type strides, std::ptrdiff_t start_shift ): map(lengths_type Lengths, strides_type strides, std::ptrdiff_t start_shift ):
@ -81,30 +80,45 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
map(lengths_type Lengths, strides_type strides, std::ptrdiff_t start_shift, memory_layout<Rank> const & ml ): map(lengths_type Lengths, strides_type strides, std::ptrdiff_t start_shift, memory_layout<Rank> const & ml ):
mydomain(std::move(Lengths)), strides_(std::move(strides)), start_shift_(start_shift), memory_order_ (ml) {} mydomain(std::move(Lengths)), strides_(std::move(strides)), start_shift_(start_shift), memory_order_ (ml) {}
/// Construction from another map with the same order (used in grouping indices) /// Construction from another map with the same order
template<ull_t Opt2, ull_t To2> map (map<Rank,Opt2,To2> const & C): template <typename To2>
mydomain(C.domain()), strides_(C.strides()), start_shift_(C.start_shift()), memory_order_ (C.memory_indices_layout()) {} map(map<Rank, To2> const& C)
: mydomain(C.domain()), strides_(C.strides()), start_shift_(C.start_shift()), memory_order_(C.get_memory_layout()) {}
template <typename To2> map& operator=(map<Rank, To2> const& m) {
*this = map{m};
}
// transposition // transposition
template <typename... INT> friend map transpose(map const& m, INT... is) { friend map transpose(map const& m, mini_vector<int, Rank> const & perm) {
return map{{m.domain().lengths()[is]...}, {m.strides_[is]...}, m.start_shift_, transpose(m.memory_order_, is...)}; lengths_type l;
strides_type s;
for (int u = 0; u < Rank; ++u) {
l[perm[u]] = m.domain().lengths()[u];
s[perm[u]] = m.strides_[u];
}
return map{l, s, m.start_shift_, transpose(m.memory_order_, perm)};
} }
/// Returns the shift in position of the element key. /// Returns the shift in position of the element key.
template <typename KeyType> template <typename KeyType> size_t operator[](KeyType const& key) const {
size_t operator[] (KeyType const & key ) const { #ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
_chk<CheckBounds, domain_type, KeyType>::invoke (this->domain(),key); this->domain().assert_key_in_domain(key);
return start_shift_ + dot_product(key,this->strides()); #endif
return start_shift_ + dot_product(key, this->strides());
} }
friend std::ostream & operator << (std::ostream & out, const map & P) { friend std::ostream & operator << (std::ostream & out, const map & P) {
return out <<" ordering = {"<<P.memory_indices_layout()<<"}"<<std::endl return out <<" ordering = {"<<P.get_memory_layout()<<"}"<<std::endl
<<" Lengths : "<<P.lengths() << std::endl <<" Lengths : "<<P.lengths() << std::endl
<<" Stride : "<<P.strides_ << std::endl; <<" Stride : "<<P.strides_ << std::endl;
} }
/// TODO: replace by a tuple call....
template<typename ... Args> size_t operator()(Args const & ... args) const { template<typename ... Args> size_t operator()(Args const & ... args) const {
_chk_v<CheckBounds, domain_type, Args...>::invoke (this->domain(),args...); #ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
this->domain().assert_key_in_domain_v(args...);
#endif
return start_shift_ + _call_impl<0>(args...); return start_shift_ + _call_impl<0>(args...);
} }
private : private :
@ -115,19 +129,17 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
/// ///
bool is_contiguous() const { bool is_contiguous() const {
const size_t last_index = mem_layout::memory_rank_to_index(memory_order_.value, rank-1); int slowest_index = memory_order_[0];
return (strides()[last_index] * this->lengths()[last_index] == mydomain.number_of_elements()); return (strides()[slowest_index] * this->lengths()[slowest_index] == mydomain.number_of_elements());
} }
size_t start_shift() const { return start_shift_;} size_t start_shift() const { return start_shift_;}
lengths_type const & lengths() const { return mydomain.lengths();} lengths_type const & lengths() const { return mydomain.lengths();}
strides_type const & strides() const { return this->strides_;} strides_type const & strides() const { return this->strides_;}
memory_layout<Rank> const & memory_indices_layout() const { return memory_order_;} memory_layout<Rank> const & get_memory_layout() const { return memory_order_;}
memory_layout<Rank> traversal_order_indices_layout() const { return memory_layout<Rank>(traversal_order);} bool memory_layout_is_c() const { return get_memory_layout().is_c();}
ull_t memory_indices_layout_ull() const { return memory_order_.value;} bool memory_layout_is_fortran() const { return get_memory_layout().is_fortran();}
bool memory_layout_is_c() const { return memory_indices_layout().value == mem_layout::c_order(Rank);}
bool memory_layout_is_fortran() const { return memory_indices_layout().value == mem_layout::fortran_order(Rank);}
private : private :
domain_type mydomain; domain_type mydomain;
@ -143,19 +155,30 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
ar & TRIQS_MAKE_NVP("start_shift",start_shift_); ar & TRIQS_MAKE_NVP("start_shift",start_shift_);
} }
// for construction // for construction
// TODO : use tupletools
void compute_stride_compact() { void compute_stride_compact() {
size_t str = 1; size_t str = 1;
csc_impl(memory_order_.value, str, std::integral_constant<int,rank>()); csc_impl(memory_order_, str, std::integral_constant<int,rank>());
assert(this->domain().number_of_elements()==str); assert(this->domain().number_of_elements()==str);
} }
template<int v> // call for indices fastest (rank -1) to slowest (0)
void csc_impl(ull_t order, size_t & str, std::integral_constant<int,v>) { template <int v> void csc_impl(memory_layout<Rank> const& ml, size_t& str, std::integral_constant<int, v>) {
size_t u = mem_layout::memory_rank_to_index(order, rank-v); // size_t u = mem_layout::memory_rank_to_index(order, rank-v);
this->strides_[u] = str; int u = ml[v - 1];
str *= this->lengths() [u]; this->strides_[u] = str;
csc_impl(order, str, std::integral_constant<int,v-1>()); str *= this->lengths()[u];
} csc_impl(ml, str, std::integral_constant<int, v - 1>());
void csc_impl(ull_t order,size_t & str, std::integral_constant<int,0>) {} }
void csc_impl(memory_layout<Rank> const&, size_t&, std::integral_constant<int, 0>) {}
// iterator helper impl.
static constexpr int __iter_get_p(int p, map const * im, _traversal_c) { return p;}
static constexpr int __iter_get_p(int p, map const* im, _traversal_fortran) { return Rank - p - 1; }
static int __iter_get_p(int p, map const* im, _traversal_dynamical) { return im->get_memory_layout()[p]; }
template <int... Is> static constexpr int __iter_get_p(int p, map const* im, _traversal_custom<Is...>) {
return permutations::apply(_get_traversal_order_permutation(Rank, _traversal_custom<Is...>{}),
p);
}
public: public:
@ -166,9 +189,9 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
*/ */
class iterator : public boost::iterator_facade< iterator, const std::ptrdiff_t, boost::forward_traversal_tag > { class iterator : public boost::iterator_facade< iterator, const std::ptrdiff_t, boost::forward_traversal_tag > {
public: public:
typedef map indexmap_type; using indexmap_type=map ;
typedef typename domain_type::index_value_type indices_type; using indices_type=typename domain_type::index_value_type ;
typedef const std::ptrdiff_t return_type; using return_type=const std::ptrdiff_t ;
iterator (): im(NULL), pos(0),atend(true) {} iterator (): im(NULL), pos(0),atend(true) {}
iterator (const map & P, bool atEnd=false, ull_t iteration_order=0): iterator (const map & P, bool atEnd=false, ull_t iteration_order=0):
im(&P), pos(im->start_shift()),atend(atEnd) {} im(&P), pos(im->start_shift()),atend(atEnd) {}
@ -178,7 +201,7 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
friend class boost::iterator_core_access; friend class boost::iterator_core_access;
void increment(){ inc_ind_impl (std::integral_constant<int,Rank>()); } void increment(){ inc_ind_impl (std::integral_constant<int,Rank>()); }
template<int v> inline void inc_ind_impl(std::integral_constant<int,v>) { template<int v> inline void inc_ind_impl(std::integral_constant<int,v>) {
constexpr size_t p = mem_layout::memory_rank_to_index(traversal_order, rank-v); int p = __iter_get_p(v - 1, im, typename _get_traversal_order_t<TraversalOrder>::type{});
#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK #ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
if (atend) TRIQS_RUNTIME_ERROR << "Iterator in cuboid cannot be pushed after end !"; if (atend) TRIQS_RUNTIME_ERROR << "Iterator in cuboid cannot be pushed after end !";
#endif #endif
@ -198,18 +221,17 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
}; //------------- end class --------------------- }; //------------- end class ---------------------
}//namespace cuboid }//namespace cuboid
template<int R1, int R2, ull_t OptFlags1, ull_t OptFlags2, ull_t To1, ull_t To2> template <int R1, int R2, typename To1, typename To2>
bool compatible_for_assignment (const cuboid::map<R1,OptFlags1,To1> & X1, const cuboid::map<R2,OptFlags2,To2> & X2) { return X1.lengths() == X2.lengths();} bool compatible_for_assignment(const cuboid::map<R1, To1>& X1, const cuboid::map<R2, To2>& X2) {
return X1.lengths() == X2.lengths();
}
template<int R1, int R2, ull_t OptFlags1, ull_t OptFlags2, ull_t To1, ull_t To2> template <int R1, int R2, typename To1, typename To2>
bool raw_copy_possible (const cuboid::map<R1,OptFlags1,To1> & X1,const cuboid::map<R2,OptFlags2,To2> & X2) { bool raw_copy_possible(const cuboid::map<R1, To1>& X1, const cuboid::map<R2, To2>& X2) {
return ( (X1.memory_indices_layout() == X2.memory_indices_layout()) return ( (X1.get_memory_layout() == X2.get_memory_layout())
&& X1.is_contiguous() && X2.is_contiguous() && X1.is_contiguous() && X2.is_contiguous()
&& (X1.domain().number_of_elements()==X2.domain().number_of_elements())); && (X1.domain().number_of_elements()==X2.domain().number_of_elements()));
} }
}}}//namespace triqs::arrays::indexmaps }}}//namespace triqs::arrays::indexmaps
#endif

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2012 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -18,93 +18,110 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_INDEXMAP_MEMORY_LAYOUT_H #pragma once
#define TRIQS_ARRAYS_INDEXMAP_MEMORY_LAYOUT_H namespace triqs {
#include "../permutation.hpp" namespace arrays {
#include "../../impl/flags.hpp"
namespace triqs { namespace arrays { struct __mem_layout_fortran_order {};
struct __mem_layout_c_order {};
#define C_LAYOUT (triqs::arrays::__mem_layout_c_order())
#define FORTRAN_LAYOUT (triqs::arrays::__mem_layout_fortran_order())
namespace indexmaps { namespace mem_layout { enum class memory_order_type {
/* The storage order is given by a permutation P stored in a ull_t (unsigned long long) as in permutations::.. C,
* P[0] : the fastest index, Fortran,
* P[RANK-1] : the slowest index Custom
* Example : };
* 012 : Fortran, the first index is the fastest
* 210: C the last index is the fastest
* 120 : storage (i,j,k) is : index j is fastest, then k, then i
*
* index_to_memory_rank : i ---> r : to the index (0,1, ... etc), associates the rank in memory
* e.g. r=0 : fastest index, r = RANK-1 : the slowest
* memory_rank_to_index : the inverse mapping : r---> i :
* 0-> the fastest index, etc..
*
* All these computations can be done *at compile time* (constexpr)
*/
constexpr int memory_rank_to_index(ull_t p, int r) { return permutations::apply(p, r);} /* The storage order is given by a permutation P
constexpr int index_to_memory_rank(ull_t p, int r) { return permutations::apply(permutations::inverse(p), r);} * P[0] : the slowest index,
* P[Rank-1] : the fastest index
* Example :
* 210 : Fortran, the first index is the fastest
* 012 : C the last index is the fastest
* 120 : storage (i,j,k) is : index j is slowest, then k, then i
*/
template <int Rank> class memory_layout {
constexpr bool is_fortran (ull_t p){ return p == permutations::identity(permutations::size(p));} memory_order_type order = memory_order_type::C;
constexpr bool is_c (ull_t p){ return p == permutations::ridentity(permutations::size(p));} mini_vector<int, Rank> p = utility::no_init_tag{};
constexpr ull_t fortran_order (int n){ return permutations::identity(n);} public:
constexpr ull_t c_order (int n){ return permutations::ridentity(n);} static const int rank = Rank;
template<int n> struct fortran_order_tr { static constexpr ull_t value = permutations::identity(n);}; explicit memory_layout() {
template<int n> struct c_order_tr { static constexpr ull_t value = permutations::ridentity(n);}; for (int u = 0; u < Rank; ++u) p[u] = u;
// From the flag in the template definition to the real traversal_order
// 0 -> C order
// 1 -> Fortran Order
// Any other number interpreted as a permutation ?
constexpr ull_t _get_traversal_order (int rank, ull_t fl, ull_t to) { return (flags::traversal_order_c(fl) ? c_order(rank) :
(flags::traversal_order_fortran(fl) ? fortran_order(rank) : (to==0 ? c_order(rank) : to )));}
template< int rank, ull_t fl, ull_t to> struct get_traversal_order { static constexpr ull_t value = _get_traversal_order (rank,fl,to); };
}}
struct memory_layout_fortran {};
struct memory_layout_c {};
#define FORTRAN_LAYOUT (triqs::arrays::memory_layout_fortran())
#define C_LAYOUT (triqs::arrays::memory_layout_fortran())
// stores the layout == order of the indices in memory
// wrapped into a little type to make constructor unambigous.
template<int Rank>
struct memory_layout {
ull_t value;
explicit memory_layout (ull_t v) : value(v) {assert((permutations::size(v)==Rank));}
explicit memory_layout (char ml='C') {
assert( (ml=='C') || (ml == 'F'));
value = (ml=='F' ? indexmaps::mem_layout::fortran_order(Rank) : indexmaps::mem_layout::c_order(Rank));
}
memory_layout (memory_layout_fortran) { value = indexmaps::mem_layout::fortran_order(Rank); }
memory_layout (memory_layout_c) { value = indexmaps::mem_layout::c_order(Rank); }
template<typename ... INT>
explicit memory_layout(int i0, int i1, INT ... in) : value (permutations::permutation(i0,i1,in...)){
static_assert( sizeof...(in)==Rank-2, "Error");
}
memory_layout (const memory_layout & C) = default;
memory_layout (memory_layout && C) = default;
memory_layout & operator =( memory_layout const &) = default;
memory_layout & operator =( memory_layout && x) = default;
bool operator ==( memory_layout const & ml) const { return value == ml.value;}
bool operator !=( memory_layout const & ml) const { return value != ml.value;}
friend std::ostream &operator<<(std::ostream &out, memory_layout const &s) {
permutations::print(out, s.value);
return out;
}
};
template <int R, typename... INT> memory_layout<R> transpose(memory_layout<R> ml, INT... is) {
static_assert(sizeof...(INT)==R, "!");
return memory_layout<R>{permutations::compose(ml.value, permutations::inverse(permutations::permutation(is...)))};
} }
}}//namespace triqs::arrays
#endif memory_layout(__mem_layout_fortran_order) {
order = memory_order_type::Fortran;
for (int u = 0; u < Rank; ++u) p[u] = Rank - u - 1;
}
memory_layout(__mem_layout_c_order) : memory_layout() {}
// internal use only : no check , we KNOW the order is not C or Fortran
template <typename T> explicit memory_layout(mini_vector<T, Rank> v, bool) : p(std::move(v)) {
order = memory_order_type::Custom;
}
// For the user : we find out whether it is C or Fortran
template <typename T> explicit memory_layout(mini_vector<T, Rank> v) : p(std::move(v)) {
bool c = true, f = true;
for (int u = 0; u < Rank; ++u) {
c = c && (v[u] == u);
f = f && (v[u] == Rank - u - 1);
}
if (c) return;
order = (f ? memory_order_type::Fortran : memory_order_type::Custom);
}
template <typename... INT>
explicit memory_layout(int i0, INT... in)
: memory_layout(mini_vector<int, sizeof...(INT) + 1>{i0, in...}) {}
bool operator==(memory_layout const &ml) const { return p == ml.p; }
bool operator!=(memory_layout const &ml) const { return !operator==(ml); }
int operator[](int u) const { return p[u]; }
bool is_c() const { return order == memory_order_type::C; }
bool is_fortran() const { return order == memory_order_type::Fortran; }
mini_vector<int, Rank> get_memory_positions() const {
auto r = mini_vector<int, Rank>(utility::no_init_tag{});
for (int u = 0; u < Rank; ++u) r[p[u]] = u;
return r;
}
mini_vector<int, Rank> get_indices_in_order() const { return p; }
friend std::ostream &operator<<(std::ostream &out, memory_layout const &s) { return out << s.p; }
};
// ------------------------- functions -------------------------------------
/// Make a memory_layout from the indices
template <typename... T> memory_layout<sizeof...(T)> make_memory_layout(T... x) { return memory_layout<sizeof...(T)>(x...); }
/// Make a memory_layout from the strides
template <int Rank> memory_layout<Rank> memory_layout_from_strides(mini_vector<std::ptrdiff_t, Rank> const &strides) {
mini_vector<int, Rank> c; // rely on init to 0 by default of mini_vector
for (int i = 0; i < Rank; ++i)
for (int j = i + 1; j < Rank; ++j)
if (strides[i] > strides[j])
c[i]++;
else
c[j]++;
// we computed the map : index -> memory_rank, which is the inverse map, cf mem_layout
return memory_layout<Rank>{c};
}
/// Apply a permutation to the indices
template <int R> memory_layout<R> transpose(memory_layout<R> const &ml, mini_vector<int, R> const &perm) {
mini_vector<int, R> res;
for (int u = 0; u < R; ++u) res[u] = perm[ml[u]];
return memory_layout<R>{res};
}
}
} // namespace triqs::arrays

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -18,98 +18,118 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_SLICE_H #pragma once
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_SLICE_H
#include <triqs/utility/count_type_occurrence.hpp> #include <triqs/utility/count_type_occurrence.hpp>
#include "./slice_traversal_order.hpp" namespace triqs {
namespace triqs { namespace arrays { namespace indexmaps { namespace arrays {
namespace cuboid_details { namespace indexmaps {
#define LISILOSO l_type const * li, s_type const * si, l_type * lo, s_type * so namespace cuboid_details {
typedef size_t l_type; #define LISILOSO l_type const* li, s_type const* si, l_type* lo, s_type* so, int* imap
typedef std::ptrdiff_t s_type; using l_type = size_t;
using s_type = std::ptrdiff_t;
template <bool BC> inline void _check_BC ( int N, int ind, size_t B, int ind_min =0) { } inline void _check_BC(int N, int ind, size_t B, int ind_min = 0) {
template <> inline void _check_BC<true> (int N, int ind, size_t B, int ind_min) { #ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
if (!((ind >= ind_min) && (ind < int(B)))) TRIQS_ARRAYS_KEY_ERROR << " index "<<N<<" is out of domain: \n " << ind <<" is not within [0,"<< B <<"[\n"; if (!((ind >= ind_min) && (ind < int(B))))
} TRIQS_ARRAYS_KEY_ERROR << " index " << N << " is out of domain: \n " << ind << " is not within [0," << B << "[\n";
#endif
}
struct slice_calc { // group in a struct to avoid declaration order issue with the cross call of templates... struct slice_calc { // group in a struct to avoid declaration order issue with the cross call of templates...
template<int N, int P, bool BoundCheck> template <int N, int P> static void one_step(LISILOSO, std::ptrdiff_t& offset, size_t R) {
static void one_step(LISILOSO, std::ptrdiff_t& offset, size_t R){ _check_BC(N, R, li[N]);
_check_BC <BoundCheck> (N, R, li[N]); offset += R * si[N];
offset += R*si[N]; imap[N] = -1;
} }
template<int N, int P, bool BoundCheck> template <int N, int P> static void one_step(LISILOSO, std::ptrdiff_t& offset, range R) {
static void one_step(LISILOSO, std::ptrdiff_t& offset, range R){ _check_BC(N, R.first(), li[N]);
_check_BC<BoundCheck> (N, R.first(),li[N]); lo[P] = ((R.last() == -1 ? li[N] : R.last()) - R.first() + R.step() - 1) / R.step(); // python behaviour
lo[P] = ((R.last()==-1 ? li[N] : R.last()) - R.first() + R.step()-1 )/R.step(); // python behaviour _check_BC(N, R.first() + (lo[P] != 0 ? (lo[P] - 1) : 0) * R.step(), li[N], -1);
_check_BC<BoundCheck> (N, R.first() + (lo[P]!=0 ? (lo[P]-1) : 0)*R.step() ,li[N], -1); so[P] = si[N] * R.step();
so[P] = si[N] * R.step();
offset += R.first() * si[N]; offset += R.first() * si[N];
imap[N] = P;
} }
template<int N, int P, bool BoundCheck, int EllipsisLength, typename Arg0, typename... Args> // ellipsis is a total range, we can simplify the computation in that case...
static typename std::enable_if<((EllipsisLength==1) || (!std::is_base_of<ellipsis, Arg0 >::type::value)), void>::type template <int N, int P> static void one_step(LISILOSO, std::ptrdiff_t& offset, ellipsis) {
invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) { _check_BC(N, 0, li[N]);
constexpr bool dP = (std::is_base_of<range,Arg0>::type::value ? 1 : 0); // Arg0 is range or ellipsis lo[P] = li[N];
one_step<N,P,BoundCheck>(li,si,lo,so,offset, arg0); _check_BC(N, (lo[P] != 0 ? (lo[P] - 1) : 0), li[N], -1);
invoke<N+1,P+dP,BoundCheck,EllipsisLength>(li,si,lo,so, offset, args...); so[P] = si[N];
imap[N] = P;
} }
template<int N, int P, bool BoundCheck, int EllipsisLength, typename Arg0, typename... Args> template <int N, int P, int EllipsisLength, typename Arg0, typename... Args>
static typename std::enable_if<((EllipsisLength==0) && std::is_base_of<ellipsis, Arg0 >::type::value), void>::type static std14::enable_if_t<((EllipsisLength == 1) || (!std::is_base_of<ellipsis, Arg0>::type::value)), void>
invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) { invoke(LISILOSO, s_type& offset, Arg0 const& arg0, Args const&... args) {
invoke<N,P,BoundCheck,EllipsisLength>(li,si,lo,so, offset, args...); constexpr bool dP = (std::is_base_of<range, Arg0>::type::value ? 1 : 0); // Arg0 is range or ellipsis
one_step<N, P>(li, si, lo, so, imap, offset, arg0);
invoke<N + 1, P + dP, EllipsisLength>(li, si, lo, so, imap, offset, args...);
} }
template<int N, int P, bool BoundCheck, int EllipsisLength, typename Arg0, typename... Args> template <int N, int P, int EllipsisLength, typename Arg0, typename... Args>
static typename std::enable_if<((EllipsisLength>1) && std::is_base_of<ellipsis, Arg0 >::type::value), void>::type static std14::enable_if_t<((EllipsisLength == 0) && std::is_base_of<ellipsis, Arg0>::type::value), void>
invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) { invoke(LISILOSO, s_type& offset, Arg0 const& arg0, Args const&... args) {
//constexpr int dP = 1;//(std::is_base_of<range,Arg0>::type::value ? 1 : 0); // Arg0 is range or ellipsis invoke<N, P, EllipsisLength>(li, si, lo, so, imap, offset, args...);
one_step<N,P,BoundCheck>(li,si,lo,so,offset, arg0);
invoke<N+1,P+1,BoundCheck,EllipsisLength-1>(li,si,lo,so, offset, arg0, args...);
} }
template<int N, int P, bool BoundCheck, int EllipsisLength> static void invoke(LISILOSO, s_type & offset ) {} template <int N, int P, int EllipsisLength, typename Arg0, typename... Args>
}; static std14::enable_if_t<((EllipsisLength > 1) && std::is_base_of<ellipsis, Arg0>::type::value), void>
invoke(LISILOSO, s_type& offset, Arg0 const& arg0, Args const&... args) {
one_step<N, P>(li, si, lo, so, imap, offset, arg0);
invoke<N + 1, P + 1, EllipsisLength - 1>(li, si, lo, so, imap, offset, arg0, args...);
}
template <int N, int P, int EllipsisLength> static void invoke(LISILOSO, s_type& offset) {}
};
#undef LISILOSO #undef LISILOSO
}//namespace cuboid_details } // namespace cuboid_details
// special case of no argument : // special case of no argument :
template<int R, ull_t Opt, ull_t To> struct slicer < cuboid::map<R, Opt,To> > { typedef cuboid::map < R, Opt,To > r_type; }; template <int R,typename To> struct slicer<cuboid::map<R, To>> {
using r_type = cuboid::map<R, To>;
// general case
template<int R, ull_t Opt, ull_t To, typename... Args> struct slicer < cuboid::map<R, Opt,To>, Args...> {
static const unsigned int len = sizeof...(Args);
static constexpr bool has_ellipsis = (count_type_occurrence<ellipsis,Args...>::value>0);
static_assert((count_type_occurrence<ellipsis,Args...>::value < 2), "Only one ellipsis is permitted");
static_assert((len>=R || has_ellipsis), "Too few arguments in slice");
static_assert((len<=R+(has_ellipsis ?1:0)), "Too many arguments in slice"); // + one to allow an empty ellipsis
typedef cuboid::map<R,Opt,To> im_t;
static constexpr int Rf = R - count_type_occurrence_not<range,Args...>::value;
static constexpr ull_t To_i = im_t::traversal_order;
// compute a new traversal order, only if there is no ellipsis
// the computation with ellipsis is not yet implemented...
static constexpr ull_t Tof = (has_ellipsis ? 0 : cuboid::slicing_TO_order::sliced_memory_order<To_i,Args...>::value);
typedef cuboid::map < Rf , Opt, Tof> r_type;
#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS
static_assert(( (has_ellipsis) || (permutations::size(Tof) == Rf)), "Mismatch between Rank and the TraversalOrder");
#endif
static r_type invoke (im_t const & X, Args ... args) {
typename r_type::lengths_type newlengths;
typename r_type::strides_type newstrides;
std::ptrdiff_t newstart= X.start_shift();
constexpr int EllipsisLength = R -len+1;
cuboid_details::slice_calc::invoke<0,0,flags::bound_check_trait<Opt>::value,EllipsisLength>(&X.lengths()[0],&X.strides()[0],&newlengths[0],&newstrides[0],newstart, args...);
return r_type(std::move(newlengths),std::move(newstrides),newstart);// use move construction ?
}; };
};
}}}//namespaces triqs::arrays::indexmaps // general case
#endif template <int R, typename To, typename... Args> struct slicer<cuboid::map<R, To>, Args...> {
static const unsigned int len = sizeof...(Args);
static constexpr bool has_ellipsis = (count_type_occurrence<ellipsis, Args...>::value > 0);
static_assert((count_type_occurrence<ellipsis, Args...>::value < 2), "Only one ellipsis is permitted");
static_assert((len >= R || has_ellipsis), "Too few arguments in slice");
static_assert((len <= R + (has_ellipsis ? 1 : 0)), "Too many arguments in slice"); // + one to allow an empty ellipsis
using im_t = cuboid::map<R, To>;
static constexpr int Rf = R - count_type_occurrence_not<range, Args...>::value;
// TO DO : compute the new traversal order using the same routine, constexpr, if needed ?
// Af the moment, using simply the C traversal order.
using Tof = void; //_traversal_c;
using r_type = cuboid::map<Rf, Tof>;
static r_type invoke(im_t const& X, Args... args) {
typename r_type::lengths_type newlengths;
typename r_type::strides_type newstrides;
std::ptrdiff_t newstart = X.start_shift();
constexpr int EllipsisLength = R - len + 1;
mini_vector<int, R> imap(utility::no_init_tag{});
cuboid_details::slice_calc::invoke<0, 0, EllipsisLength>(&X.lengths()[0], &X.strides()[0], &newlengths[0], &newstrides[0],
imap.ptr(), newstart, args...);
if (X.get_memory_layout().is_c()) return r_type(std::move(newlengths), std::move(newstrides), newstart, memory_layout<Rf>{});
if (X.get_memory_layout().is_fortran()) return r_type(std::move(newlengths), std::move(newstrides), newstart, memory_layout<Rf>{FORTRAN_LAYOUT});
// Compute the new memory index order
mini_vector<int, Rf> p(utility::no_init_tag{});
for (int i = 0, j = 0; j < R; ++j) {
auto k = imap[X.get_memory_layout()[j]];
if (k != -1) p[i++] = k;
}
return r_type(std::move(newlengths), std::move(newstrides), newstart, memory_layout<Rf>{p, bool()});
};
};
}
}
} // namespaces triqs::arrays::indexmaps

View File

@ -1,48 +0,0 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2012 by O. Parcollet
*
* TRIQS 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 3 of the License, or (at your option) any later
* version.
*
* TRIQS 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.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_ARRAYS_INDEXMAP_STORAGE_ORDER_H
#define TRIQS_ARRAYS_INDEXMAP_STORAGE_ORDER_H
#include "./mem_layout.hpp"
namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid { namespace slicing_TO_order {
template <typename... SliceArgs> struct _impl{
static constexpr int n_range_ellipsis=0;
static constexpr ull_t mask(ull_t mo, int P, int c) { return 0;}
static constexpr ull_t smo (ull_t mo, ull_t ma, int P, int c) { return 0;}
};
template <typename A0, typename... SliceArgs> struct _impl< A0,SliceArgs...> {
typedef _impl<SliceArgs...> next_t;
static constexpr bool is_range = std::is_base_of<range, A0>::value; // range and ellipsis (derived from range)
static constexpr int n_range_ellipsis= next_t::n_range_ellipsis + is_range;
static constexpr ull_t mask(ull_t mo, int P=0, int c=0) { return ((is_range ? P+1 : 0) << (4*c)) + next_t::mask(mo,P + is_range,c+1);}
static constexpr ull_t r2 (ull_t mo, ull_t ma, int c) { return (ma >> (4*(permutations::apply(mo,c)))) & 0xF; }
static constexpr ull_t aux (ull_t mo,ull_t ma,ull_t r,int P,int c) { return (r!=0? ( (r-1) << (4*P)) : 0) + next_t::smo(mo,ma,P+(r!=0), c+1); }
static constexpr ull_t smo (ull_t mo, ull_t ma, int P=0, int c=0) { return aux(mo,ma,r2(mo,ma,c),P,c); }
};
template<typename ... Args>
constexpr ull_t sliced_memory_order1(ull_t mo) { return _impl<Args...>::n_range_ellipsis + 0x10*_impl<Args...>::smo(mo, _impl<Args...>::mask(mo));}
template<typename ... Args>
constexpr ull_t sliced_memory_order2(ull_t mo) { return (mem_layout::is_c (mo) ? c_order(_impl<Args...>::n_range_ellipsis) :
( mem_layout::is_fortran(mo) ? fortran_order(_impl<Args...>::n_range_ellipsis) : sliced_memory_order1<Args...>(mo) ));
}
template<ull_t mo, typename ... Args> struct sliced_memory_order { static constexpr ull_t value = sliced_memory_order1<Args...>(mo); };
}}}}}//namespace triqs::arrays
#endif

View File

@ -175,7 +175,7 @@ namespace arrays {
ENABLE_IF(is_matrix_or_view<typename std::remove_reference<A>::type>) ENABLE_IF(is_matrix_or_view<typename std::remove_reference<A>::type>)
triqs_arrays_assign_delegation(MT &lhs, inverse_lazy<A> const &rhs) { triqs_arrays_assign_delegation(MT &lhs, inverse_lazy<A> const &rhs) {
static_assert(is_matrix_or_view<MT>::value, "Can only assign an inverse matrix to a matrix or a matrix_view"); static_assert(is_matrix_or_view<MT>::value, "Can only assign an inverse matrix to a matrix or a matrix_view");
bool M_eq_inverse_M = ((lhs.indexmap().memory_indices_layout() == rhs.input().indexmap().memory_indices_layout()) && bool M_eq_inverse_M = ((lhs.indexmap().get_memory_layout() == rhs.input().indexmap().get_memory_layout()) &&
(lhs.data_start() == rhs.input().data_start()) && (has_contiguous_data(lhs))); (lhs.data_start() == rhs.input().data_start()) && (has_contiguous_data(lhs)));
if (!M_eq_inverse_M) { if (!M_eq_inverse_M) {
lhs = rhs(); lhs = rhs();

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -18,236 +18,257 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAYS_MATRIX_H #pragma once
#define TRIQS_ARRAYS_MATRIX_H
#include "indexmaps/cuboid/map.hpp" #include "indexmaps/cuboid/map.hpp"
#include "indexmaps/cuboid/slice.hpp" #include "indexmaps/cuboid/slice.hpp"
#include "impl/indexmap_storage_pair.hpp" #include "impl/indexmap_storage_pair.hpp"
#include "impl/assignment.hpp" #include "impl/assignment.hpp"
#include "vector.hpp" #include "vector.hpp"
namespace triqs { namespace arrays { namespace triqs {
namespace arrays {
template <typename ValueType, ull_t Opt=0, ull_t TraversalOrder= 0, bool Borrowed = false, bool IsConst=false> class matrix_view; template <typename ValueType, typename TraversalOrder = void, bool Borrowed = false, bool IsConst = false> class matrix_view;
template <typename ValueType, ull_t Opt=0, ull_t TraversalOrder= 0> class matrix; template <typename ValueType, typename TraversalOrder = void> class matrix;
// ---------------------- matrix -------------------------------- // ---------------------- matrix --------------------------------
// //
#define _IMPL_MATRIX_COMMON \ #define _IMPL_MATRIX_COMMON \
bool is_square() const { return this->shape()[0] == this->shape()[1];}\ bool is_square() const { return this->shape()[0] == this->shape()[1]; } \
\ \
view_type transpose() const {\ view_type transpose() const { \
typename indexmap_type::lengths_type l; l[0] = this->indexmap().lengths()[1];l[1] = this->indexmap().lengths()[0];\ typename indexmap_type::lengths_type l; \
typename indexmap_type::strides_type s; s[0] = this->indexmap().strides()[1];s[1] = this->indexmap().strides()[0];\ l[0] = this->indexmap().lengths()[1]; \
return view_type( indexmap_type(l,s, this->indexmap().start_shift()), this->storage());\ l[1] = this->indexmap().lengths()[0]; \
}\ typename indexmap_type::strides_type s; \
bool memory_layout_is_c() const { return this->indexmap().strides()[0] >= this->indexmap().strides()[1]; } \ s[0] = this->indexmap().strides()[1]; \
s[1] = this->indexmap().strides()[0]; \
return view_type(indexmap_type(l, s, this->indexmap().start_shift()), this->storage()); \
} \
bool memory_layout_is_c() const { return this->indexmap().strides()[0] >= this->indexmap().strides()[1]; } \
bool memory_layout_is_fortran() const { return this->indexmap().strides()[0] < this->indexmap().strides()[1]; } bool memory_layout_is_fortran() const { return this->indexmap().strides()[0] < this->indexmap().strides()[1]; }
#define IMPL_TYPE indexmap_storage_pair < indexmaps::cuboid::map<2,Opt,TraversalOrder>, \ #define IMPL_TYPE \
storages::shared_block<ValueType,Borrowed>, Opt, TraversalOrder, IsConst, true, Tag::matrix_view > indexmap_storage_pair<indexmaps::cuboid::map<2,TraversalOrder>, storages::shared_block<ValueType, Borrowed>, TraversalOrder, IsConst, true, \
Tag::matrix_view>
template <typename ValueType, ull_t Opt, ull_t TraversalOrder, bool Borrowed, bool IsConst> template <typename ValueType, typename TraversalOrder, bool Borrowed, bool IsConst>
class matrix_view : Tag::matrix_view, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE { class matrix_view : Tag::matrix_view, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE {
public : public:
typedef matrix <ValueType,Opt,TraversalOrder> regular_type; using regular_type = matrix<ValueType, TraversalOrder>;
typedef matrix_view<ValueType,Opt,TraversalOrder> view_type; using view_type = matrix_view<ValueType, TraversalOrder>;
typedef matrix_view<ValueType, Opt, TraversalOrder, false, true> const_view_type; using const_view_type = matrix_view<ValueType, TraversalOrder, false, true>;
typedef matrix_view<ValueType,Opt,TraversalOrder,true> weak_view_type; using weak_view_type = matrix_view<ValueType, TraversalOrder, true>;
using indexmap_type = typename IMPL_TYPE::indexmap_type;
using storage_type = typename IMPL_TYPE::storage_type;
typedef typename IMPL_TYPE::indexmap_type indexmap_type; /// Build from an IndexMap and a storage
typedef typename IMPL_TYPE::storage_type storage_type; template <typename S> matrix_view(typename IMPL_TYPE::indexmap_type const& Ind, S const& Mem) : IMPL_TYPE(Ind, Mem) {}
/// Build from an IndexMap and a storage /// Build from anything that has an indexmap and a storage compatible with this class
template<typename S> matrix_view (typename IMPL_TYPE::indexmap_type const & Ind,S const & Mem): IMPL_TYPE(Ind, Mem) {} template <typename ISP> matrix_view(const ISP& X) : IMPL_TYPE(X.indexmap(), X.storage()) {}
/// Build from anything that has an indexmap and a storage compatible with this class
template<typename ISP> matrix_view(const ISP & X): IMPL_TYPE(X.indexmap(),X.storage()) {}
#ifdef TRIQS_WITH_PYTHON_SUPPORT #ifdef TRIQS_WITH_PYTHON_SUPPORT
/// Build from a numpy.array : throws if X is not a numpy.array /// Build from a numpy.array : throws if X is not a numpy.array
explicit matrix_view (PyObject * X): IMPL_TYPE(X, false, "matrix_view "){} explicit matrix_view(PyObject* X) : IMPL_TYPE(X, false, "matrix_view ") {}
#endif #endif
/// Copy construction /// Copy construction
matrix_view( matrix_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {} matrix_view(matrix_view const& X) : IMPL_TYPE(X.indexmap(), X.storage()) {}
matrix_view () = delete; matrix_view() = delete;
// Move // Move
matrix_view(matrix_view && X) { this->swap_me(X); } matrix_view(matrix_view&& X) { this->swap_me(X); }
/// Swap /// Swap
friend void swap( matrix_view & A, matrix_view & B) { A.swap_me(B);} friend void swap(matrix_view& A, matrix_view& B) { A.swap_me(B); }
/// Rebind the view /// Rebind the view
void rebind(matrix_view const& X) { void rebind(matrix_view const& X) {
this->indexmap_ = X.indexmap_; this->indexmap_ = X.indexmap_;
this->storage_ = X.storage_; this->storage_ = X.storage_;
} }
// rebind the other view, iif this is const, and the other is not. // rebind the other view, iif this is const, and the other is not.
template <bool C = IsConst> ENABLE_IFC(C) rebind(matrix_view<ValueType, Opt, TraversalOrder, Borrowed, !IsConst> const& X) { template <typename To2, bool C = IsConst> ENABLE_IFC(C) rebind(matrix_view<ValueType, To2, Borrowed, !IsConst> const& X) {
this->indexmap_ = X.indexmap_; this->indexmap_ = X.indexmap_;
this->storage_ = X.storage_; this->storage_ = X.storage_;
} }
/** Assignement. The size of the array MUST match exactly. */ /** Assignement. The size of the array MUST match exactly. */
template<typename RHS> matrix_view & operator=(const RHS & X) {triqs_arrays_assign_delegation(*this,X); return *this; } template <typename RHS> matrix_view& operator=(const RHS& X) {
triqs_arrays_assign_delegation(*this, X);
return *this;
}
matrix_view & operator=(matrix_view const & X) {triqs_arrays_assign_delegation(*this,X); return *this; }//cf array_view class comment matrix_view& operator=(matrix_view const& X) {
triqs_arrays_assign_delegation(*this, X);
return *this;
} // cf array_view class comment
// Move assignment not defined : will use the copy = since view must copy data // Move assignment not defined : will use the copy = since view must copy data
TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view); TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view);
_IMPL_MATRIX_COMMON; _IMPL_MATRIX_COMMON;
}; };
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// this traits is used by indexmap_storage_pair, when slicing to find the correct view type. // this traits is used by indexmap_storage_pair, when slicing to find the correct view type.
template < class V, int R, ull_t OptionFlags, ull_t To, bool Borrowed, bool IsConst> template <class V, int R, typename TraversalOrder, bool Borrowed, bool IsConst>
struct ISPViewType< V, R, OptionFlags, To, Tag::matrix_view, Borrowed,IsConst> { struct ISPViewType<V, R, TraversalOrder, Tag::matrix_view, Borrowed, IsConst> : std::conditional<R == 1, vector_view<V, Borrowed, IsConst>,
typedef typename std::conditional<R == 1, vector_view<V, OptionFlags, Borrowed, IsConst>, matrix_view<V, TraversalOrder, Borrowed, IsConst>> {};
matrix_view<V, OptionFlags, To, Borrowed, IsConst>>::type type;
};
#undef IMPL_TYPE #undef IMPL_TYPE
template <typename ValueType, ull_t Opt = 0, ull_t TraversalOrder = 0, bool Borrowed = false> template <typename ValueType, typename TraversalOrder = void, bool Borrowed = false>
using matrix_const_view = matrix_view<ValueType, Opt, TraversalOrder, Borrowed, true>; using matrix_const_view = matrix_view<ValueType, TraversalOrder, Borrowed, true>;
// ---------------------- matrix -------------------------------- // ---------------------- matrix --------------------------------
#define IMPL_TYPE indexmap_storage_pair < indexmaps::cuboid::map<2,Opt,TraversalOrder>, \ #define IMPL_TYPE \
storages::shared_block<ValueType>, Opt, TraversalOrder, false, false, Tag::matrix_view > indexmap_storage_pair<indexmaps::cuboid::map<2, TraversalOrder>, storages::shared_block<ValueType>, TraversalOrder, false, \
false, Tag::matrix_view>
template <typename ValueType, ull_t Opt, ull_t TraversalOrder > template <typename ValueType, typename TraversalOrder>
class matrix: Tag::matrix, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE { class matrix : Tag::matrix, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE {
public : public:
typedef typename IMPL_TYPE::value_type value_type; using value_type = typename IMPL_TYPE::value_type;
typedef typename IMPL_TYPE::storage_type storage_type; using storage_type = typename IMPL_TYPE::storage_type;
typedef typename IMPL_TYPE::indexmap_type indexmap_type; using indexmap_type = typename IMPL_TYPE::indexmap_type;
typedef matrix <ValueType,Opt,TraversalOrder> regular_type; using regular_type = matrix<ValueType, TraversalOrder>;
typedef matrix_view<ValueType,Opt,TraversalOrder> view_type; using view_type = matrix_view<ValueType, TraversalOrder>;
typedef matrix_view<ValueType, Opt, TraversalOrder, false, true> const_view_type; using const_view_type = matrix_view<ValueType, TraversalOrder, false, true>;
typedef matrix_view<ValueType,Opt,TraversalOrder,true> weak_view_type; using weak_view_type = matrix_view<ValueType, TraversalOrder, true>;
/// Empty matrix. /// Empty matrix.
matrix(memory_layout<2> ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order) ): IMPL_TYPE(indexmap_type(ml)) {} matrix(memory_layout<2> ml = memory_layout<2>{}) : IMPL_TYPE(indexmap_type(ml)) {}
/// Move /// Move
explicit matrix(matrix && X) { this->swap_me(X); } explicit matrix(matrix&& X) { this->swap_me(X); }
/// ///
matrix(size_t dim1, size_t dim2, memory_layout<2> ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order) ) : matrix(size_t dim1, size_t dim2, memory_layout<2> ml = memory_layout<2>{})
IMPL_TYPE(indexmap_type(mini_vector<size_t,2>(dim1,dim2),ml)) {} : IMPL_TYPE(indexmap_type(mini_vector<size_t, 2>(dim1, dim2), ml)) {}
/// ///
matrix(mini_vector<size_t,2> const & sha, memory_layout<2> ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order)) : matrix(mini_vector<size_t, 2> const& sha, memory_layout<2> ml = memory_layout<2>{}) : IMPL_TYPE(indexmap_type(sha, ml)) {}
IMPL_TYPE(indexmap_type(sha,ml)) {}
/** Makes a true (deep) copy of the data. */ /** Makes a true (deep) copy of the data. */
matrix(const matrix & X): IMPL_TYPE(X.indexmap(),X.storage().clone()) {} matrix(const matrix& X) : IMPL_TYPE(X.indexmap(), X.storage().clone()) {}
/// Build a new matrix from X.domain() and fill it with by evaluating X. X can be : /// Build a new matrix from X.domain() and fill it with by evaluating X. X can be :
template <typename T> template <typename T>
matrix(const T & X, TYPE_ENABLE_IF(memory_layout<2>, ImmutableCuboidArray<T>) ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order)): matrix(const T& X, TYPE_ENABLE_IF(memory_layout<2>, ImmutableCuboidArray<T>) ml = memory_layout<2>{})
IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); } : IMPL_TYPE(indexmap_type(X.domain(), ml)) {
triqs_arrays_assign_delegation(*this, X);
}
#ifdef TRIQS_WITH_PYTHON_SUPPORT #ifdef TRIQS_WITH_PYTHON_SUPPORT
///Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy. /// Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy.
explicit matrix (PyObject * X): IMPL_TYPE(X, true, "matrix "){} explicit matrix(PyObject* X) : IMPL_TYPE(X, true, "matrix ") {}
#endif #endif
// build from a init_list // build from a init_list
template<typename T> template <typename T> matrix(std::initializer_list<std::initializer_list<T>> const& l) : IMPL_TYPE(memory_layout<2>()) {
matrix (std::initializer_list<std::initializer_list<T>> const & l): size_t i = 0, j = 0;
IMPL_TYPE(memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order)) { int s = -1;
size_t i=0,j=0; int s=-1; for (auto const& l1 : l) {
for (auto const & l1 : l) { if (s==-1) s= l1.size(); else if (s != l1.size()) TRIQS_RUNTIME_ERROR << "initializer list not rectangular !";} if (s == -1)
IMPL_TYPE::resize(typename IMPL_TYPE::domain_type (mini_vector<size_t,2>(l.size(),s))); s = l1.size();
for (auto const & l1 : l) { else if (s != l1.size())
for (auto const & x : l1) { (*this)(i,j++) = x;} TRIQS_RUNTIME_ERROR << "initializer list not rectangular !";
j=0; ++i; }
} IMPL_TYPE::resize(typename IMPL_TYPE::domain_type(mini_vector<size_t, 2>(l.size(), s)));
} for (auto const& l1 : l) {
for (auto const& x : l1) {
(*this)(i, j++) = x;
}
j = 0;
++i;
}
}
/** /**
* Resizes the matrix. NB : all references to the storage is invalidated. * Resizes the matrix. NB : all references to the storage is invalidated.
* Does not initialize the matrix by default * Does not initialize the matrix by default
*/ */
matrix & resize (size_t n1, size_t n2) { IMPL_TYPE::resize(typename IMPL_TYPE::domain_type (mini_vector<size_t,2>(n1,n2))); return *this;} matrix& resize(size_t n1, size_t n2) {
IMPL_TYPE::resize(typename IMPL_TYPE::domain_type(mini_vector<size_t, 2>(n1, n2)));
return *this;
}
/** /**
* Resizes the matrix. NB : all references to the storage is invalidated. * Resizes the matrix. NB : all references to the storage is invalidated.
* Does not initialize the matrix by default * Does not initialize the matrix by default
*/ */
matrix & resize (const indexmaps::cuboid::domain_t<IMPL_TYPE::rank> & l) { IMPL_TYPE::resize(l); return *this; } matrix& resize(const indexmaps::cuboid::domain_t<IMPL_TYPE::rank>& l) {
IMPL_TYPE::resize(l);
return *this;
}
/// Assignement resizes the matrix. All references to the storage are therefore invalidated. /// Assignement resizes the matrix. All references to the storage are therefore invalidated.
matrix & operator=(const matrix & X) { IMPL_TYPE::resize_and_clone_data(X); return *this; } matrix& operator=(const matrix& X) {
IMPL_TYPE::resize_and_clone_data(X);
return *this;
}
/// Move assignment /// Move assignment
matrix & operator=(matrix && X) { this->swap_me(X); return *this;} matrix& operator=(matrix&& X) {
this->swap_me(X);
return *this;
}
/// Swap /// Swap
friend void swap( matrix & A, matrix & B) { A.swap_me(B);} friend void swap(matrix& A, matrix& B) { A.swap_me(B); }
/** /**
* Assignement resizes the matrix. All references to the storage are therefore invalidated. * Assignement resizes the matrix. All references to the storage are therefore invalidated.
* NB : to avoid that, do make_view(A) = X instead of A = X * NB : to avoid that, do make_view(A) = X instead of A = X
*/ */
template<typename RHS> template <typename RHS> matrix& operator=(const RHS& X) {
matrix & operator=(const RHS & X) { static_assert(ImmutableCuboidArray<RHS>::value, "Assignment : RHS not supported");
static_assert( ImmutableCuboidArray<RHS>::value, "Assignment : RHS not supported"); IMPL_TYPE::resize(X.domain());
IMPL_TYPE::resize(X.domain()); triqs_arrays_assign_delegation(*this, X);
triqs_arrays_assign_delegation(*this,X); return *this;
return *this; }
}
TRIQS_DEFINE_COMPOUND_OPERATORS(matrix); TRIQS_DEFINE_COMPOUND_OPERATORS(matrix);
_IMPL_MATRIX_COMMON; _IMPL_MATRIX_COMMON;
};//matrix class }; // matrix class
#undef _IMPL_MATRIX_COMMON #undef _IMPL_MATRIX_COMMON
#undef IMPL_TYPE #undef IMPL_TYPE
template<typename V> template <typename V> matrix<V> make_unit_matrix(int dim) {
matrix <V> make_unit_matrix(int dim) {
matrix<V> r(dim, dim); matrix<V> r(dim, dim);
r() = 1; r() = 1;
return r; return r;
} }
template<typename ArrayType> template <typename ArrayType>
matrix_view<typename ArrayType::value_type, ArrayType::opt_flags, ArrayType::traversal_order, true> matrix_view<typename ArrayType::value_type, typename ArrayType::traversal_order_t, true> make_matrix_view(ArrayType const& a) {
make_matrix_view(ArrayType const & a) { static_assert(ArrayType::rank == 2, "make_matrix_view only works for array of rank 2");
static_assert(ArrayType::rank ==2, "make_matrix_view only works for array of rank 2"); return a;
return a; }
}
template<typename ArrayType> template <typename ArrayType> matrix<typename ArrayType::value_type> make_matrix(ArrayType const& a) {
matrix<typename ArrayType::value_type> static_assert(ArrayType::domain_type::rank == 2, "make_matrix only works for array of rank 2");
make_matrix(ArrayType const & a) { return a;
static_assert(ArrayType::domain_type::rank ==2, "make_matrix only works for array of rank 2"); }
return a;
}
template <typename M> template <typename M> TYPE_ENABLE_IF(typename M::value_type, ImmutableMatrix<M>) trace(M const& m) {
TYPE_ENABLE_IF(typename M::value_type, ImmutableMatrix<M>) trace(M const &m) { auto r = typename M::value_type{};
auto r = typename M::value_type{}; if (first_dim(m) != second_dim(m)) TRIQS_RUNTIME_ERROR << " Trace of a non square matrix";
if (first_dim(m) != second_dim(m)) auto d = first_dim(m);
TRIQS_RUNTIME_ERROR << " Trace of a non square matrix"; for (int i = 0; i < d; ++i) r += m(i, i);
auto d = first_dim(m); return r;
for (int i = 0; i < d; ++i) }
r += m(i, i); }
return r; } // namespace triqs::arrays
}
}}//namespace triqs::arrays
// The std::swap is WRONG for a view because of the copy/move semantics of view. // The std::swap is WRONG for a view because of the copy/move semantics of view.
// Use swap instead (the correct one, found by ADL). // Use swap instead (the correct one, found by ADL).
namespace std { namespace std {
template <typename V, triqs::ull_t Opt, triqs::ull_t To, bool B1, bool B2, bool C1, bool C2> template <typename V, typename To1, typename To2, bool B1, bool B2, bool C1, bool C2>
void swap( triqs::arrays::matrix_view<V,Opt,To,B1,C1> & a , triqs::arrays::matrix_view<V,Opt,To,B2,C2> & b)= delete; void swap(triqs::arrays::matrix_view<V, To1, B1, C1>& a, triqs::arrays::matrix_view<V, To2, B2, C2>& b) = delete;
} }
#include "./expression_template/matrix_algebra.hpp" #include "./expression_template/matrix_algebra.hpp"
#endif

View File

@ -44,6 +44,7 @@ namespace arrays {
long n; long n;
typedef typename A_t::value_type value_type; typedef typename A_t::value_type value_type;
using traversal_order_t = typename A_t::traversal_order_t;
typedef indexmaps::slicer<typename A_t::indexmap_type, long, ellipsis> slicer_t; typedef indexmaps::slicer<typename A_t::indexmap_type, long, ellipsis> slicer_t;
typedef typename slicer_t::r_type indexmap_type; typedef typename slicer_t::r_type indexmap_type;
typedef typename indexmap_type::domain_type domain_type; typedef typename indexmap_type::domain_type domain_type;
@ -98,6 +99,7 @@ namespace arrays {
long n; long n;
typedef typename A_t::value_type value_type; typedef typename A_t::value_type value_type;
using traversal_order_t = typename A_t::traversal_order_t;
typedef indexmaps::slicer<typename A_t::indexmap_type, long, ellipsis> slicer_t; typedef indexmaps::slicer<typename A_t::indexmap_type, long, ellipsis> slicer_t;
typedef typename slicer_t::r_type indexmap_type; typedef typename slicer_t::r_type indexmap_type;
typedef typename indexmap_type::domain_type domain_type; typedef typename indexmap_type::domain_type domain_type;

View File

@ -20,7 +20,6 @@
******************************************************************************/ ******************************************************************************/
#include "../impl/common.hpp" #include "../impl/common.hpp"
#include "../impl/traits.hpp" #include "../impl/traits.hpp"
#include "../impl/flags.hpp"
#include "../../utility/mini_vector.hpp" #include "../../utility/mini_vector.hpp"
#include "./numpy_extractor.hpp" #include "./numpy_extractor.hpp"
#ifdef TRIQS_WITH_PYTHON_SUPPORT #ifdef TRIQS_WITH_PYTHON_SUPPORT

View File

@ -49,12 +49,12 @@ namespace triqs { namespace arrays { namespace storages {
static constexpr bool is_weak = Weak; static constexpr bool is_weak = Weak;
/// Construct a new block of memory of given size /// Construct a new block of memory of given size
explicit shared_block(size_t size, Tag::no_init) { construct_delegate(size); } explicit shared_block(size_t size) { construct_delegate(size); }
explicit shared_block(size_t size, Tag::default_init) {// C++11 : delegate to previous constructor when gcc 4.6 support is out. //explicit shared_block(size_t size, Tag::default_init) {// C++11 : delegate to previous constructor when gcc 4.6 support is out.
construct_delegate(size); // construct_delegate(size);
const auto s = this->size(); for (size_t u=0; u<s; ++u) data_[u] = ValueType(); // const auto s = this->size(); for (size_t u=0; u<s; ++u) data_[u] = ValueType();
} // }
#ifdef TRIQS_WITH_PYTHON_SUPPORT #ifdef TRIQS_WITH_PYTHON_SUPPORT
explicit shared_block(PyObject * arr, bool weak): sptr(new mem_block<ValueType>(arr,weak)) { data_ = sptr->p; s= sptr->size(); } explicit shared_block(PyObject * arr, bool weak): sptr(new mem_block<ValueType>(arr,weak)) { data_ = sptr->p; s= sptr->size(); }

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -18,197 +18,214 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>. * TRIQS. If not, see <http://www.gnu.org/licenses/>.
* *
******************************************************************************/ ******************************************************************************/
#ifndef TRIQS_ARRAY_VECTOR_H #pragma once
#define TRIQS_ARRAY_VECTOR_H
#include "indexmaps/cuboid/map.hpp" #include "indexmaps/cuboid/map.hpp"
#include "indexmaps/cuboid/slice.hpp" #include "indexmaps/cuboid/slice.hpp"
#include "impl/indexmap_storage_pair.hpp" #include "impl/indexmap_storage_pair.hpp"
#include "impl/assignment.hpp" #include "impl/assignment.hpp"
#include "impl/flags.hpp"
#include <algorithm> #include <algorithm>
namespace triqs { namespace arrays { namespace triqs {
namespace arrays {
template <typename ValueType, ull_t Opt=0, bool Borrowed =false, bool IsConst=false> class vector_view; template <typename ValueType, bool Borrowed = false, bool IsConst = false> class vector_view;
template <typename ValueType, ull_t Opt=0> class vector; template <typename ValueType> class vector;
// ---------------------- vector_view -------------------------------- // ---------------------- vector_view --------------------------------
#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<1,Opt,0> , storages::shared_block<ValueType,Borrowed>, Opt, 0, IsConst, true, Tag::vector_view > #define IMPL_TYPE \
indexmap_storage_pair<indexmaps::cuboid::map<1>, storages::shared_block<ValueType, Borrowed>, void, IsConst, true, \
Tag::vector_view>
/** */ /** */
template <typename ValueType, ull_t Opt, bool Borrowed, bool IsConst> template <typename ValueType, bool Borrowed, bool IsConst>
class vector_view : Tag::vector_view, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE { class vector_view : Tag::vector_view, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE {
public : public:
typedef vector <ValueType,Opt> regular_type; using regular_type = vector<ValueType>;
typedef vector_view<ValueType,Opt,false> view_type; using view_type = vector_view<ValueType, false>;
typedef vector_view<ValueType, Opt, false, true> const_view_type; using const_view_type = vector_view<ValueType, false, true>;
typedef vector_view<ValueType,Opt,true> weak_view_type; using weak_view_type = vector_view<ValueType, true>;
using indexmap_type = typename IMPL_TYPE::indexmap_type;
using storage_type = typename IMPL_TYPE::storage_type;
typedef typename IMPL_TYPE::indexmap_type indexmap_type; /// Build from an IndexMap and a storage
typedef typename IMPL_TYPE::storage_type storage_type; template <typename S> vector_view(indexmaps::cuboid::map<1> const& Ind, S const& Mem) : IMPL_TYPE(Ind, Mem) {}
/// Build from an IndexMap and a storage /// Build from anything that has an indexmap and a storage compatible with this class
template<typename S, ull_t Opt2, ull_t To2> vector_view (indexmaps::cuboid::map<1, Opt2,To2> const & Ind,S const & Mem): IMPL_TYPE(Ind, Mem) {} template <typename ISP> vector_view(const ISP& X) : IMPL_TYPE(X.indexmap(), X.storage()) {}
/// Build from anything that has an indexmap and a storage compatible with this class
template<typename ISP>
vector_view(const ISP & X): IMPL_TYPE(X.indexmap(),X.storage()) {}
#ifdef TRIQS_WITH_PYTHON_SUPPORT #ifdef TRIQS_WITH_PYTHON_SUPPORT
/// Build from a numpy.array : throws if X is not a numpy.array /// Build from a numpy.array : throws if X is not a numpy.array
explicit vector_view (PyObject * X): IMPL_TYPE(X, false, "vector_view "){} explicit vector_view(PyObject* X) : IMPL_TYPE(X, false, "vector_view ") {}
#endif #endif
/// Copy construction /// Copy construction
vector_view(vector_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {} vector_view(vector_view const& X) : IMPL_TYPE(X.indexmap(), X.storage()) {}
vector_view () = delete; vector_view() = delete;
// Move // Move
vector_view(vector_view && X) { this->swap_me(X);} vector_view(vector_view&& X) { this->swap_me(X); }
/// Swap /// Swap
friend void swap( vector_view & A, vector_view & B) { A.swap_me(B);} friend void swap(vector_view& A, vector_view& B) { A.swap_me(B); }
/// Rebind the view /// Rebind the view
void rebind(vector_view const& X) { void rebind(vector_view const& X) {
this->indexmap_ = X.indexmap_; this->indexmap_ = X.indexmap_;
this->storage_ = X.storage_; this->storage_ = X.storage_;
} }
// rebind the other view, iif this is const, and the other is not. // rebind the other view, iif this is const, and the other is not.
template <bool C = IsConst> ENABLE_IFC(C) rebind(vector_view<ValueType, Opt, Borrowed, !IsConst> const& X) { template <bool C = IsConst> ENABLE_IFC(C) rebind(vector_view<ValueType, Borrowed, !IsConst> const& X) {
this->indexmap_ = X.indexmap_; this->indexmap_ = X.indexmap_;
this->storage_ = X.storage_; this->storage_ = X.storage_;
} }
/** Assignment. The size of the array MUST match exactly. */ /** Assignment. The size of the array MUST match exactly. */
template<typename RHS> vector_view & operator=(const RHS & X) { triqs_arrays_assign_delegation(*this,X); return *this; } template <typename RHS> vector_view& operator=(const RHS& X) {
triqs_arrays_assign_delegation(*this, X);
return *this;
}
vector_view & operator=(vector_view const & X) {triqs_arrays_assign_delegation(*this,X); return *this; }//cf array_view class comment vector_view& operator=(vector_view const& X) {
triqs_arrays_assign_delegation(*this, X);
return *this;
} // cf array_view class comment
// Move assignment not defined : will use the copy = since view must copy data // Move assignment not defined : will use the copy = since view must copy data
size_t size() const { return this->shape()[0];} size_t size() const { return this->shape()[0]; }
std::ptrdiff_t stride() const { return this->indexmap().strides()[0]; }
std::ptrdiff_t stride() const { return this->indexmap().strides()[0];} TRIQS_DEFINE_COMPOUND_OPERATORS(vector_view);
TRIQS_DEFINE_COMPOUND_OPERATORS(vector_view); // to make interface similar to std::vector : forward [] to ()
template <typename Arg> auto operator[](Arg&& arg) const DECL_AND_RETURN((*this)(std::forward<Arg>(arg)));
// to make interface similar to std::vector : forward [] to () template <typename Arg> auto operator[](Arg&& arg)DECL_AND_RETURN((*this)(std::forward<Arg>(arg)));
template<typename Arg> auto operator[](Arg && arg) const DECL_AND_RETURN((*this)(std::forward<Arg>(arg))); };
template<typename Arg> auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward<Arg>(arg)));
};
#undef IMPL_TYPE #undef IMPL_TYPE
template < class V, int R, ull_t OptionFlags, ull_t To, bool Borrowed, bool IsConst> template <class V, int R, bool Borrowed, bool IsConst>
struct ISPViewType< V, R,OptionFlags,To, Tag::vector_view, Borrowed, IsConst> { typedef vector_view<V,OptionFlags,Borrowed,IsConst> type; }; struct ISPViewType<V, R, void, Tag::vector_view, Borrowed, IsConst> {
using type = vector_view<V, Borrowed, IsConst>;
};
template <typename ValueType, ull_t Opt = 0, bool Borrowed = false> template <typename ValueType, bool Borrowed = false> using vector_const_view = vector_view<ValueType, Borrowed, true>;
using vector_const_view = vector_view<ValueType, Opt, Borrowed, true>;
// ---------------------- vector-------------------------------- // ---------------------- vector--------------------------------
#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<1,Opt,0> , storages::shared_block<ValueType>, Opt, 0, false, false,Tag::vector_view > #define IMPL_TYPE \
indexmap_storage_pair<indexmaps::cuboid::map<1>, storages::shared_block<ValueType>, void, false, false, Tag::vector_view>
template <typename ValueType, ull_t Opt> template <typename ValueType> class vector : Tag::vector, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE {
class vector: Tag::vector, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE { public:
public : using value_type = typename IMPL_TYPE::value_type;
typedef typename IMPL_TYPE::value_type value_type; using storage_type = typename IMPL_TYPE::storage_type;
typedef typename IMPL_TYPE::storage_type storage_type; using indexmap_type = typename IMPL_TYPE::indexmap_type;
typedef typename IMPL_TYPE::indexmap_type indexmap_type; using regular_type = vector<ValueType>;
typedef vector<ValueType, Opt> regular_type; using view_type = vector_view<ValueType>;
typedef vector_view<ValueType, Opt> view_type; using const_view_type = vector_view<ValueType, false, true>;
typedef vector_view<ValueType, Opt, false, true> const_view_type; using weak_view_type = vector_view<ValueType, true>;
typedef vector_view<ValueType, Opt, true> weak_view_type;
/// Empty vector. /// Empty vector.
vector(){} vector() {}
// Move // Move
explicit vector(vector && X) { this->swap_me(X); } explicit vector(vector&& X) { this->swap_me(X); }
/// ///
vector(size_t dim):IMPL_TYPE(indexmap_type(mini_vector<size_t,1>(dim))) {} vector(size_t dim) : IMPL_TYPE(indexmap_type(mini_vector<size_t, 1>(dim))) {}
/// to mimic std vector /// to mimic std vector
template<typename Arg> template <typename Arg> vector(size_t dim, Arg&& arg) : IMPL_TYPE(indexmap_type(mini_vector<size_t, 1>(dim))) {
vector(size_t dim, Arg && arg):IMPL_TYPE(indexmap_type(mini_vector<size_t,1>(dim))) { (*this)() = std::forward<Arg>(arg);} (*this)() = std::forward<Arg>(arg);
}
/** Makes a true (deep) copy of the data. */ /** Makes a true (deep) copy of the data. */
vector(const vector & X): IMPL_TYPE(X.indexmap(),X.storage().clone()) {} vector(const vector& X) : IMPL_TYPE(X.indexmap(), X.storage().clone()) {}
/** /**
* Build a new vector from X.domain() and fill it with by evaluating X. X can be : * Build a new vector from X.domain() and fill it with by evaluating X. X can be :
* - another type of array, array_view, matrix,.... (any <IndexMap, Storage> pair) * - another type of array, array_view, matrix,.... (any <IndexMap, Storage> pair)
* - a expression : e.g. array<int, IndexOrder::C<1> > A( B+ 2*C); * - a expression : e.g. array<int, IndexOrder::C<1> > A( B+ 2*C);
* - ml : useless directly, since there only one ml, but used in generic code it maintains the same constructor as array, matrix * - ml : useless directly, since there only one ml, but used in generic code it maintains the same constructor as array,
*/ * matrix
template <typename T> */
//vector(const T & X, typename boost::enable_if< ImmutableCuboidArray<T> >::type *dummy =0): template <typename T>
vector(const T & X, TYPE_ENABLE_IF(memory_layout<1>, ImmutableCuboidArray<T>) ml = memory_layout<1>(IMPL_TYPE::indexmap_type::traversal_order)): // vector(const T & X, std14::enable_if_t< ImmutableCuboidArray<T> ::value> *dummy =0):
IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); } vector(const T& X, TYPE_ENABLE_IF(memory_layout<1>, ImmutableCuboidArray<T>) ml = memory_layout<1>{})
: IMPL_TYPE(indexmap_type(X.domain(), ml)) {
triqs_arrays_assign_delegation(*this, X);
}
#ifdef TRIQS_WITH_PYTHON_SUPPORT #ifdef TRIQS_WITH_PYTHON_SUPPORT
///Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy. /// Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy.
explicit vector (PyObject * X): IMPL_TYPE(X, true, "vector "){} explicit vector(PyObject* X) : IMPL_TYPE(X, true, "vector ") {}
#endif #endif
// build from a init_list // build from a init_list
template<typename T> template <typename T>
vector(std::initializer_list<T> const & l): vector(std::initializer_list<T> const& l)
IMPL_TYPE(indexmap_type(mini_vector<size_t,1>(l.size()),memory_layout<1>(IMPL_TYPE::indexmap_type::traversal_order))) { : IMPL_TYPE(indexmap_type(mini_vector<size_t, 1>(l.size()), memory_layout<1>{})) {
size_t i=0; size_t i = 0;
for (auto const & x : l) (*this)(i++) = x; for (auto const& x : l) (*this)(i++) = x;
} }
/** /**
* Resizes the vector. NB : all references to the storage is invalidated. * Resizes the vector. NB : all references to the storage is invalidated.
* Does not initialize the vector by default: to resize and init, do resize(IND).init() * Does not initialize the vector by default: to resize and init, do resize(IND).init()
*/ */
vector & resize (size_t L) { IMPL_TYPE::resize(typename IMPL_TYPE::domain_type(mini_vector<size_t,1>(L))); return *this; } vector& resize(size_t L) {
IMPL_TYPE::resize(typename IMPL_TYPE::domain_type(mini_vector<size_t, 1>(L)));
return *this;
}
/** /**
* Resizes the vector. NB : all references to the storage is invalidated. * Resizes the vector. NB : all references to the storage is invalidated.
* Does not initialize the vector by default: to resize and init, do resize(IND).init() * Does not initialize the vector by default: to resize and init, do resize(IND).init()
*/ */
vector & resize (const indexmaps::cuboid::domain_t<IMPL_TYPE::rank> & l) { IMPL_TYPE::resize(l); return *this; } vector& resize(const indexmaps::cuboid::domain_t<IMPL_TYPE::rank>& l) {
IMPL_TYPE::resize(l);
return *this;
}
/// Assignement resizes the vector. All references to the storage are therefore invalidated. /// Assignement resizes the vector. All references to the storage are therefore invalidated.
vector & operator=(const vector & X) { IMPL_TYPE::resize_and_clone_data(X); return *this; } vector& operator=(const vector& X) {
IMPL_TYPE::resize_and_clone_data(X);
return *this;
}
/** /**
* Assignement resizes the vector. All references to the storage are therefore invalidated. * Assignement resizes the vector. All references to the storage are therefore invalidated.
* NB : to avoid that, do make_view(A) = X instead of A = X * NB : to avoid that, do make_view(A) = X instead of A = X
*/ */
template<typename RHS> template <typename RHS> vector& operator=(const RHS& X) {
vector & operator=(const RHS & X) { static_assert(ImmutableCuboidArray<RHS>::value, "Assignment : RHS not supported");
static_assert( ImmutableCuboidArray<RHS>::value, "Assignment : RHS not supported"); IMPL_TYPE::resize(X.domain());
IMPL_TYPE::resize(X.domain()); triqs_arrays_assign_delegation(*this, X);
triqs_arrays_assign_delegation(*this,X); return *this;
return *this; }
}
/// Move assignment /// Move assignment
vector & operator=(vector && X) { this->swap_me(X); return *this;} vector& operator=(vector&& X) {
this->swap_me(X);
return *this;
}
/// Swap friend void swap(vector& A, vector& B) { A.swap_me(B); }
friend void swap( vector & A, vector & B) { A.swap_me(B);}
/// size_t size() const { return this->shape()[0]; }
size_t size() const { return this->shape()[0];} std::ptrdiff_t stride() const { return this->indexmap().strides()[0]; }
/// TRIQS_DEFINE_COMPOUND_OPERATORS(vector);
std::ptrdiff_t stride() const { return this->indexmap().strides()[0];}
TRIQS_DEFINE_COMPOUND_OPERATORS(vector); // to make interface similar to std::vector : forward [] to ()
template <typename Arg> auto operator[](Arg&& arg) const DECL_AND_RETURN((*this)(std::forward<Arg>(arg)));
template <typename Arg> auto operator[](Arg&& arg)DECL_AND_RETURN((*this)(std::forward<Arg>(arg)));
// to make interface similar to std::vector : forward [] to () }; // vector class
template<typename Arg> auto operator[](Arg && arg) const DECL_AND_RETURN((*this)(std::forward<Arg>(arg))); }
template<typename Arg> auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward<Arg>(arg))); } // namespace triqs::arrays
};//vector class
}}//namespace triqs::arrays
#undef IMPL_TYPE #undef IMPL_TYPE
@ -216,10 +233,11 @@ namespace triqs { namespace arrays {
#include "./blas_lapack/copy.hpp" #include "./blas_lapack/copy.hpp"
#include "./blas_lapack/swap.hpp" #include "./blas_lapack/swap.hpp"
#include "./blas_lapack/axpy.hpp" #include "./blas_lapack/axpy.hpp"
namespace triqs { namespace arrays { namespace triqs {
namespace arrays {
// norm2 squared // norm2 squared
template <typename V> typename std::enable_if<ImmutableVector<V>::value, typename V::value_type>::type norm2_sqr(V const& a) { template <typename V> std14::enable_if_t<ImmutableVector<V>::value, typename V::value_type> norm2_sqr(V const& a) {
int dim = a.size(); int dim = a.size();
auto r = typename V::value_type{}; auto r = typename V::value_type{};
for (int i = 0; i < dim; ++i) r += a(i) * a(i); for (int i = 0; i < dim; ++i) r += a(i) * a(i);
@ -227,101 +245,109 @@ namespace triqs { namespace arrays {
} }
// norm2 // norm2
template <typename V> typename std::enable_if<ImmutableVector<V>::value, typename V::value_type>::type norm2(V const& a) { template <typename V> std14::enable_if_t<ImmutableVector<V>::value, typename V::value_type> norm2(V const& a) {
using std::sqrt; using std::sqrt;
return sqrt(norm2(a)); return sqrt(norm2(a));
} }
// lexicographical comparison operators // lexicographical comparison operators
template<typename V1, typename V2> template <typename V1, typename V2>
typename std::enable_if< ImmutableVector<V1>::value && ImmutableVector<V2>::value , bool>::type std14::enable_if_t<ImmutableVector<V1>::value&& ImmutableVector<V2>::value, bool> operator<(V1 const& a, V2 const& b) {
operator < (V1 const & a, V2 const & b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());} return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
}
template<typename V1, typename V2> template <typename V1, typename V2>
typename std::enable_if< ImmutableVector<V1>::value && ImmutableVector<V2>::value , bool>::type std14::enable_if_t<ImmutableVector<V1>::value&& ImmutableVector<V2>::value, bool> operator>(V1 const& a, V2 const& b) {
operator > (V1 const & a, V2 const & b) { return (b<a); } return (b < a);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_vector_or_view <RHS > >::type std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_assign_delegation(vector<T>& lhs, RHS const& rhs) {
triqs_arrays_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs) { blas::copy(rhs,lhs); } blas::copy(rhs, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_vector_or_view <RHS > >::type std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_compound_assign_delegation(vector<T>& lhs, RHS const& rhs,
triqs_arrays_compound_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs, char_<'A'>) { char_<'A'>) {
T a = 1.0; blas::axpy(a,rhs,lhs); T a = 1.0;
} blas::axpy(a, rhs, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_vector_or_view <RHS > >::type std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_compound_assign_delegation(vector<T>& lhs, RHS const& rhs,
triqs_arrays_compound_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs, char_<'S'>) { char_<'S'>) {
T a = -1.0; blas::axpy(a,rhs,lhs); T a = -1.0;
} blas::axpy(a, rhs, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_scalar_for<RHS,vector<T,Opt> > >::type std14::enable_if_t<is_scalar_for<RHS, vector<T>>::value> triqs_arrays_compound_assign_delegation(vector<T>& lhs, RHS const& rhs,
triqs_arrays_compound_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs, char_<'M'>) { char_<'M'>) {
T a = rhs; blas::scal(a,lhs); T a = rhs;
} blas::scal(a, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_scalar_for<RHS,vector<T,Opt> > >::type std14::enable_if_t<is_scalar_for<RHS, vector<T>>::value> triqs_arrays_compound_assign_delegation(vector<T>& lhs, RHS const& rhs,
triqs_arrays_compound_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs, char_<'D'>) { char_<'D'>) {
T a = 1/rhs; blas::scal(a,lhs); T a = 1 / rhs;
} blas::scal(a, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_vector_or_view <RHS > >::type std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_assign_delegation(vector_view<T>& lhs, RHS const& rhs) {
triqs_arrays_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs) { blas::copy(rhs,lhs); } blas::copy(rhs, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_vector_or_view <RHS > >::type std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_compound_assign_delegation(vector_view<T>& lhs, RHS const& rhs,
triqs_arrays_compound_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs, char_<'A'>) { char_<'A'>) {
T a = 1.0; blas::axpy(a,rhs,lhs); T a = 1.0;
} blas::axpy(a, rhs, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_vector_or_view <RHS > >::type std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_compound_assign_delegation(vector_view<T>& lhs, RHS const& rhs,
triqs_arrays_compound_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs, char_<'S'>) { char_<'S'>) {
T a = -1.0; blas::axpy(a,rhs,lhs); T a = -1.0;
} blas::axpy(a, rhs, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_scalar_for<RHS,vector_view<T,Opt> > >::type std14::enable_if_t<is_scalar_for<RHS, vector_view<T>>::value>
triqs_arrays_compound_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs, char_<'M'>) { triqs_arrays_compound_assign_delegation(vector_view<T>& lhs, RHS const& rhs, char_<'M'>) {
T a = rhs; blas::scal(a,lhs); T a = rhs;
} blas::scal(a, lhs);
}
template<typename RHS, typename T, ull_t Opt> template <typename RHS, typename T>
typename boost::enable_if< is_scalar_for<RHS,vector_view<T,Opt> > >::type std14::enable_if_t<is_scalar_for<RHS, vector_view<T>>::value>
triqs_arrays_compound_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs, char_<'D'>) { triqs_arrays_compound_assign_delegation(vector_view<T>& lhs, RHS const& rhs, char_<'D'>) {
T a = 1/rhs; blas::scal(a,lhs); T a = 1 / rhs;
} blas::scal(a, lhs);
}
template<typename T, ull_t Opt, bool Borrowed> template <typename T, bool Borrowed>
void triqs_arrays_assign_delegation(vector_view<T,Opt,Borrowed> & av, std::vector<T> const& vec) { void triqs_arrays_assign_delegation(vector_view<T, Borrowed>& av, std::vector<T> const& vec) {
std::size_t size = vec.size(); std::size_t size = vec.size();
for(std::size_t n = 0; n < size; ++n) av(n) = vec[n]; for (std::size_t n = 0; n < size; ++n) av(n) = vec[n];
} }
// swapping 2 vector // swapping 2 vector
template <typename V, ull_t S1, ull_t S2, bool B1, bool B2> template <typename V, bool B1, bool B2, bool B3, bool B4> void deep_swap(vector_view<V, B1, B2> x, vector_view<V, B3, B4> y) {
void deep_swap(vector_view <V,S1,B1> x, vector_view<V,S2,B2> y) { blas::swap(x, y);
blas::swap(x,y); }
}
template <typename V, ull_t S1, ull_t S2> template <typename V> void deep_swap(vector<V>& x, vector<V>& y) { blas::swap(x, y); }
void deep_swap(vector <V,S1> & x, vector<V,S2> & y) { blas::swap(x,y);} }
}
}}
// The std::swap is WRONG for a view because of the copy/move semantics of view. // The std::swap is WRONG for a view because of the copy/move semantics of view.
// Use swap instead (the correct one, found by ADL). // Use swap instead (the correct one, found by ADL).
namespace std { namespace std {
template <typename V, triqs::ull_t S, bool B1, bool B2, bool C1, bool C2> template <typename V, bool B1, bool B2, bool C1, bool C2>
void swap(triqs::arrays::vector_view<V, S, B1, C1>& a, triqs::arrays::vector_view<V, S, B2,C2>& b) = delete; void swap(triqs::arrays::vector_view<V, B1, C1>& a, triqs::arrays::vector_view<V, B2, C2>& b) = delete;
} }
#include "./expression_template/vector_algebra.hpp" #include "./expression_template/vector_algebra.hpp"
#endif

View File

@ -25,7 +25,7 @@
#include <triqs/arrays.hpp> #include <triqs/arrays.hpp>
#include "../arrays/matrix_tensor_proxy.hpp" #include "../arrays/matrix_tensor_proxy.hpp"
#define TRIQS_GF_DATA_PROXIES_WITH_SIMPLE_VIEWS //#define TRIQS_GF_DATA_PROXIES_WITH_SIMPLE_VIEWS
namespace triqs { namespace gfs { namespace triqs { namespace gfs {
@ -51,12 +51,12 @@ namespace triqs { namespace gfs {
#ifdef TRIQS_GF_DATA_PROXIES_WITH_SIMPLE_VIEWS #ifdef TRIQS_GF_DATA_PROXIES_WITH_SIMPLE_VIEWS
template <typename S> auto operator()(S& data, long i) const DECL_AND_RETURN(data(i, arrays::ellipsis())); template <typename S> auto operator()(S& data, long i) const DECL_AND_RETURN(data(i, arrays::ellipsis()));
#else #else
auto operator()(B::storage_t& data, long i) const DECL_AND_RETURN(arrays::make_tensor_proxy(data, i)); auto operator()(typename B::storage_t& data, long i) const DECL_AND_RETURN(arrays::make_tensor_proxy(data, i));
auto operator()(B::storage_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i)); auto operator()(typename B::storage_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i));
auto operator()(B::storage_view_t& data, long i) const DECL_AND_RETURN(arrays::make_tensor_proxy(data, i)); auto operator()(typename B::storage_view_t& data, long i) const DECL_AND_RETURN(arrays::make_tensor_proxy(data, i));
auto operator()(B::storage_view_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i)); auto operator()(typename B::storage_view_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i));
auto operator()(B::storage_const_view_t& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i)); auto operator()(typename B::storage_const_view_t& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i));
auto operator()(B::storage_const_view_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i)); auto operator()(typename B::storage_const_view_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i));
#endif #endif
}; };
@ -68,12 +68,12 @@ namespace triqs { namespace gfs {
template <typename S> auto operator()(S & data, long i) const RETURN(make_matrix_view(data(i, arrays::ellipsis()))); template <typename S> auto operator()(S & data, long i) const RETURN(make_matrix_view(data(i, arrays::ellipsis())));
#else #else
/// The data access /// The data access
auto operator()(B::storage_t& data, long i) const DECL_AND_RETURN(arrays::make_matrix_proxy(data, i)); auto operator()(typename B::storage_t& data, long i) const DECL_AND_RETURN(arrays::make_matrix_proxy(data, i));
auto operator()(B::storage_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i)); auto operator()(typename B::storage_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i));
auto operator()(B::storage_view_t& data, long i) const DECL_AND_RETURN(arrays::make_matrix_proxy(data, i)); auto operator()(typename B::storage_view_t& data, long i) const DECL_AND_RETURN(arrays::make_matrix_proxy(data, i));
auto operator()(B::storage_view_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i)); auto operator()(typename B::storage_view_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i));
auto operator()(B::storage_const_view_t& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i)); auto operator()(typename B::storage_const_view_t& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i));
auto operator()(B::storage_const_view_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i)); auto operator()(typename B::storage_const_view_t const& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i));
#endif #endif
}; };

View File

@ -2,7 +2,7 @@
* *
* TRIQS: a Toolbox for Research in Interacting Quantum Systems * TRIQS: a Toolbox for Research in Interacting Quantum Systems
* *
* Copyright (C) 2011 by O. Parcollet * Copyright (C) 2011-2014 by O. Parcollet
* *
* TRIQS is free software: you can redistribute it and/or modify it under the * TRIQS 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 * terms of the GNU General Public License as published by the Free Software
@ -22,13 +22,14 @@
#define TRIQS_ARRAYS_MINI_VECTOR_H #define TRIQS_ARRAYS_MINI_VECTOR_H
#include "./first_include.hpp" #include "./first_include.hpp"
#include <iostream> #include <iostream>
#include "./macros.hpp"
#include "./c14.hpp"
#include "./compiler_details.hpp" #include "./compiler_details.hpp"
#include "./exceptions.hpp" #include "./exceptions.hpp"
#include <boost/serialization/utility.hpp> #include <boost/serialization/utility.hpp>
#include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_params.hpp>
#include <vector> #include <vector>
#include <triqs/utility/tuple_tools.hpp>
#define TRIQS_MINI_VECTOR_NRANK_MAX 10 #define TRIQS_MINI_VECTOR_NRANK_MAX 10
@ -36,6 +37,8 @@
//#define TRIQS_MAKE_NVP(NAME,X) boost::serialization::make_nvp(NAME,X) //#define TRIQS_MAKE_NVP(NAME,X) boost::serialization::make_nvp(NAME,X)
namespace triqs { namespace utility { namespace triqs { namespace utility {
struct no_init_tag{};
template <typename T, int Rank> template <typename T, int Rank>
class mini_vector { class mini_vector {
T _data[(Rank!=0 ? Rank : 1)]; T _data[(Rank!=0 ? Rank : 1)];
@ -48,14 +51,104 @@ namespace triqs { namespace utility {
mini_vector(){init();} mini_vector(){init();}
#define AUX(z,p,unused) _data[p] = x_##p; mini_vector(no_init_tag){}
#define IMPL(z, NN, unused) \
mini_vector (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), T x_)){ \ mini_vector(T x_0) {
static_assert(Rank-1==NN,"mini_vector : incorrect number of variables in constructor");\ static_assert(Rank == 1, "mini_vector : incorrect number of variables in constructor");
BOOST_PP_REPEAT(BOOST_PP_INC(NN),AUX,nil) } _data[0] = x_0;
BOOST_PP_REPEAT(TRIQS_MINI_VECTOR_NRANK_MAX , IMPL, nil); }
#undef IMPL mini_vector(T x_0, T x_1) {
#undef AUX static_assert(Rank == 2, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
}
mini_vector(T x_0, T x_1, T x_2) {
static_assert(Rank == 3, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
_data[2] = x_2;
}
mini_vector(T x_0, T x_1, T x_2, T x_3) {
static_assert(Rank == 4, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
_data[2] = x_2;
_data[3] = x_3;
}
mini_vector(T x_0, T x_1, T x_2, T x_3, T x_4) {
static_assert(Rank == 5, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
_data[2] = x_2;
_data[3] = x_3;
_data[4] = x_4;
}
mini_vector(T x_0, T x_1, T x_2, T x_3, T x_4, T x_5) {
static_assert(Rank == 6, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
_data[2] = x_2;
_data[3] = x_3;
_data[4] = x_4;
_data[5] = x_5;
}
mini_vector(T x_0, T x_1, T x_2, T x_3, T x_4, T x_5, T x_6) {
static_assert(Rank == 7, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
_data[2] = x_2;
_data[3] = x_3;
_data[4] = x_4;
_data[5] = x_5;
_data[6] = x_6;
}
mini_vector(T x_0, T x_1, T x_2, T x_3, T x_4, T x_5, T x_6, T x_7) {
static_assert(Rank == 8, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
_data[2] = x_2;
_data[3] = x_3;
_data[4] = x_4;
_data[5] = x_5;
_data[6] = x_6;
_data[7] = x_7;
}
mini_vector(T x_0, T x_1, T x_2, T x_3, T x_4, T x_5, T x_6, T x_7, T x_8) {
static_assert(Rank == 9, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
_data[2] = x_2;
_data[3] = x_3;
_data[4] = x_4;
_data[5] = x_5;
_data[6] = x_6;
_data[7] = x_7;
_data[8] = x_8;
}
mini_vector(T x_0, T x_1, T x_2, T x_3, T x_4, T x_5, T x_6, T x_7, T x_8, T x_9) {
static_assert(Rank == 10, "mini_vector : incorrect number of variables in constructor");
_data[0] = x_0;
_data[1] = x_1;
_data[2] = x_2;
_data[3] = x_3;
_data[4] = x_4;
_data[5] = x_5;
_data[6] = x_6;
_data[7] = x_7;
_data[8] = x_8;
_data[9] = x_9;
};
/*
#define AUX(z,p,unused) _data[p] = x_##p;
#define IMPL(z, NN, unused) \
mini_vector (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), T x_)){ \
static_assert(Rank-1==NN,"mini_vector : incorrect number of variables in constructor");\
BOOST_PP_REPEAT(BOOST_PP_INC(NN),AUX,nil) }
BOOST_PP_REPEAT(TRIQS_MINI_VECTOR_NRANK_MAX , IMPL, nil);
#undef IMPL
#undef AUX
*/
mini_vector(const mini_vector & x){ *this = x; } mini_vector(const mini_vector & x){ *this = x; }
mini_vector(mini_vector && x){ *this = std::move(x); } mini_vector(mini_vector && x){ *this = std::move(x); }
@ -78,6 +171,11 @@ namespace triqs { namespace utility {
template<typename T2> template<typename T2>
mini_vector & operator=(const mini_vector<T2,Rank> & x){ for (int i=0;i<Rank; ++i) _data[i] = x[i]; return *this;} mini_vector & operator=(const mini_vector<T2,Rank> & x){ for (int i=0;i<Rank; ++i) _data[i] = x[i]; return *this;}
mini_vector &operator=(T x) {
for (int i = 0; i < Rank; ++i) _data[i] = x;
return *this;
}
T & operator[](size_t i) { return _data[i];} T & operator[](size_t i) { return _data[i];}
const T & operator[](size_t i) const { return _data[i];} const T & operator[](size_t i) const { return _data[i];}
@ -130,9 +228,15 @@ namespace triqs { namespace utility {
template <typename T> class mini_vector<T, 0> { template <typename T> class mini_vector<T, 0> {
T _data[1]; T _data[1];
public: public:
mini_vector(){}
mini_vector(no_init_tag){}
T & operator[](size_t i) { return _data[i];} T & operator[](size_t i) { return _data[i];}
const T & operator[](size_t i) const { return _data[i];} const T & operator[](size_t i) const { return _data[i];}
}; T * restrict ptr() { return _data;}
const T * restrict ptr() const { return _data;}
friend std::ostream & operator << ( std::ostream & out, mini_vector const & v ) {return out<<"[]";}
};
// ------------- Comparison -------------------------------------- // ------------- Comparison --------------------------------------
@ -161,13 +265,13 @@ namespace triqs { namespace utility {
return res; return res;
} }
#ifndef TRIQS_C11 //#ifndef TRIQS_C11
// ------------- transform a tuple into a minivector -------------------------------------- // // ------------- transform a tuple into a minivector --------------------------------------
//
template <typename T, typename TU> mini_vector<T, std::tuple_size<TU>::value> tuple_to_mini_vector(TU const &t) { // template <typename T, typename TU> mini_vector<T, std::tuple_size<TU>::value> tuple_to_mini_vector(TU const &t) {
return tuple::apply_construct_parenthesis<mini_vector<T, std::tuple_size<TU>::value>>(t); // return tuple::apply_construct_parenthesis<mini_vector<T, std::tuple_size<TU>::value>>(t);
} // }
#endif //#endif
}}//namespace triqs::arrays }}//namespace triqs::arrays
@ -175,6 +279,8 @@ namespace std { // overload std::get to work with it
template <int i, typename T, int R> AUTO_DECL get(triqs::utility::mini_vector<T, R> &v) RETURN(v[i]); template <int i, typename T, int R> AUTO_DECL get(triqs::utility::mini_vector<T, R> &v) RETURN(v[i]);
template <int i, typename T, int R> AUTO_DECL get(triqs::utility::mini_vector<T, R> const &v) RETURN(v[i]); template <int i, typename T, int R> AUTO_DECL get(triqs::utility::mini_vector<T, R> const &v) RETURN(v[i]);
template<typename T, int R> struct tuple_size<triqs::utility::mini_vector<T, R>>: std::integral_constant<size_t,R>{};
} }
#endif #endif

View File

@ -154,11 +154,14 @@ namespace triqs { namespace mpi {
template<typename A> struct mpi_impl<A,ENABLE_IFC(!mpi_datatype<typename A::value_type>::ok && arrays::is_amv_value_or_view_class<A>::value)> : boost_mpi_impl<A>{}; template<typename A> struct mpi_impl<A,ENABLE_IFC(!mpi_datatype<typename A::value_type>::ok && arrays::is_amv_value_or_view_class<A>::value)> : boost_mpi_impl<A>{};
// overload for views rvalues (created on the fly) // overload for views rvalues (created on the fly)
template <typename V, int R, ull_t Opt, ull_t To, bool W> template <typename V, int R, typename To, bool W> void reduce_in_place(communicator _c, arrays::array_view<V, R, To, W>&& a, int root = 0) {
void reduce_in_place( communicator _c, arrays::array_view<V,R,Opt,To, W> && a, int root =0) { reduce_in_place(_c,a,root);} reduce_in_place(_c, a, root);
}
template <typename A, typename V, int R, ull_t Opt, ull_t To, bool W> template <typename A, typename V, int R, typename To, bool W>
void reduce( communicator _c, A const & a, arrays::array_view<V,R,Opt,To, W> && b, int root =0) { reduce(_c,a,b,root);} void reduce(communicator _c, A const& a, arrays::array_view<V, R, To, W>&& b, int root = 0) {
reduce(_c, a, b, root);
}
// to be implemented : scatter, gather for arrays // to be implemented : scatter, gather for arrays

View File

@ -23,6 +23,7 @@
#include "./c14.hpp" #include "./c14.hpp"
#include <tuple> #include <tuple>
#include <ostream> #include <ostream>
#include "./mini_vector.hpp"
// adding to the std lib the reversed lazy tuple... // adding to the std lib the reversed lazy tuple...
// overloading & specializing only the functions needed here. // overloading & specializing only the functions needed here.