mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 05:43: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:
parent
d1c8a9a46e
commit
47cb8a03f7
@ -2,7 +2,7 @@
|
||||
using namespace triqs::arrays;
|
||||
int main() {
|
||||
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 + make_matrix_view(A); //--> OK.
|
||||
}
|
||||
|
@ -17,17 +17,17 @@ int main() {
|
||||
// a vector of double
|
||||
vector<double> V(10);
|
||||
|
||||
// arrays with custom TraversalOrder
|
||||
// arrays with custom memory layout
|
||||
|
||||
// C-style
|
||||
array<long, 3, 0, permutation(2, 1, 0)> A0(2, 3, 4);
|
||||
array<long, 3, 0> A0b; // same type but empty
|
||||
array<long, 3> A0(2, 3, 4);
|
||||
array<long, 3> A0b; // same type but empty
|
||||
|
||||
// Fortran-style
|
||||
array<long, 3, TRAVERSAL_ORDER_FORTRAN> A4(2, 3, 4);
|
||||
array<long, 3, 0, permutation(0, 1, 2)> A1b; // same type but empty
|
||||
array<long, 3> A4(2, 3, 4, FORTRAN_LAYOUT);
|
||||
array<long, 3> A1b(FORTRAN_LAYOUT); // same type but empty
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
@ -7,15 +7,9 @@ array, matrix & vector
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
template <typename ValueType, int Rank, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class array;
|
||||
template <typename ValueType, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class matrix;
|
||||
template <typename ValueType, ull_t OptionsFlags=0> class vector;
|
||||
|
||||
where triqs::ull_t is the type defined by :
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
typedef unsigned long long ull_t;
|
||||
template <typename ValueType, int Rank, typename TraversalOrder=void> class array;
|
||||
template <typename ValueType, typename TraversalOrder=void> class matrix;
|
||||
template <typename ValueType> class vector;
|
||||
|
||||
|
||||
* The library provides three basic containers:
|
||||
@ -41,9 +35,8 @@ Template parameters
|
||||
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
|
||||
| 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 loops and |
|
||||
| | | | iterators |
|
||||
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
|
||||
|
||||
NB: Rank is only present for array, since matrix have rank 2 and vector rank 1.
|
||||
|
@ -4,7 +4,7 @@ int main() {
|
||||
array<double, 2> A(2, 3);
|
||||
A.resize(make_shape(5, 5));
|
||||
|
||||
matrix<double, 2> M;
|
||||
matrix<double> M;
|
||||
M.resize(3, 3);
|
||||
|
||||
vector<double> V;
|
||||
|
@ -7,14 +7,14 @@ operator <<
|
||||
|
||||
**Synopsis**::
|
||||
|
||||
template <typename ValueType, int Rank, ull_t OptionsFlags=0, ull_t TraversalOrder=0>
|
||||
std::ostream & operator << (std::ostream & out, array_view<ValueType,Rank,OptionsFlags,TraversalOrder> const &);
|
||||
template <typename ValueType, int Rank, typename TraversalOrder=void>
|
||||
std::ostream & operator << (std::ostream & out, array_view<ValueType,Rank,TraversalOrder> const &);
|
||||
|
||||
template <typename ValueType, ull_t OptionsFlags=0, ull_t TraversalOrder=0>
|
||||
std::ostream & operator << (std::ostream & out, matrix_view<ValueType,OptionsFlags,TraversalOrder> const &);
|
||||
template <typename ValueType, typename TraversalOrder=void>
|
||||
std::ostream & operator << (std::ostream & out, matrix_view<ValueType,TraversalOrder> const &);
|
||||
|
||||
template <typename ValueType, ull_t OptionsFlags=0>
|
||||
std::ostream & operator << (std::ostream & out, vector_view<ValueType,OptionsFlags> const &);
|
||||
template <typename ValueType>
|
||||
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)
|
||||
to the stream out.
|
||||
|
@ -1,51 +1,41 @@
|
||||
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:
|
||||
|
||||
TraversalOrder
|
||||
----------------------------
|
||||
|
||||
* TraversalOrder is a coding of the optimal ordering of indices, given by a permutation
|
||||
evaluated at **compile time**.
|
||||
The traversal of the arrays (iterators, foreach loop) will be written and optimised for this
|
||||
* TraversalOrder is a type encoding of the optimal traversal in memory.
|
||||
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
|
||||
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
|
||||
(this is necessary for interfacing with python numpy arrays, see below).
|
||||
The code will be correct for any order, but optimised for the TraversalOrder.
|
||||
* More explanations here...
|
||||
|
||||
For a few very specials operations (e.g. regrouping of indices), the indices ordering in memory and TraversalOrder
|
||||
must coincide. This will be explicitely said below. By default, it is not necessary (but can be suboptimal).
|
||||
* Note that this notion is completely independent of the real memory layout of the array,
|
||||
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
|
||||
(see examples below).
|
||||
|
||||
TraversalOrder is not present for vector since there is only one possibility in 1d.
|
||||
The code will be correct for any order, but may be faster for the TraversalOrder.
|
||||
|
||||
* 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) |
|
||||
+--------------------------+------------------------------------------------------------+
|
||||
|
||||
|
||||
|
@ -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) |
|
||||
+------------------------------------------------------------------------+---------------------------------------------------------------------------------------+
|
||||
|
@ -9,20 +9,13 @@ Views
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
template <typename ValueType, int Rank, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class array_view;
|
||||
template <typename ValueType, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class matrix_view;
|
||||
template <typename ValueType, ull_t OptionsFlags=0> class vector_view;
|
||||
template <typename ValueType, int Rank, typename TraversalOrder=void> class array_view;
|
||||
template <typename ValueType, typename TraversalOrder=void> class matrix_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, ull_t OptionsFlags=0, ull_t TraversalOrder=0> class matrix_const_view;
|
||||
template <typename ValueType, ull_t OptionsFlags=0> class vector_const_view;
|
||||
|
||||
|
||||
where triqs::ull_t is the type defined by :
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
typedef unsigned long long ull_t;
|
||||
template <typename ValueType, int Rank, typename TraversalOrder=void> class array_const_view;
|
||||
template <typename ValueType, typename TraversalOrder=void> class matrix_const_view;
|
||||
template <typename ValueType> class vector_const_view;
|
||||
|
||||
* 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 |
|
||||
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
|
||||
| :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 |
|
||||
+-----------------------------------------+-------------------------------+-------------------------------+--------------------------------------+
|
||||
|
||||
|
@ -16,9 +16,8 @@ several advantages:
|
||||
|
||||
* 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.
|
||||
Hence if one change the TraversalOrder for some arrays, there is no need to change the for loop
|
||||
ordering to obtain a better performance, just recompile...
|
||||
* The library orders the loops in way specified by the template parameters TraversalOrder (by default, the standard C order),
|
||||
to obtain the most efficient way to traverse the memory.
|
||||
|
||||
* 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*,
|
||||
in the order specified by the TraversalOrder flag of the array.
|
||||
in the order specified by the TraversalOrder of the array.
|
||||
|
||||
* Synopsis::
|
||||
|
||||
@ -44,7 +43,7 @@ in the order specified by the TraversalOrder flag of the array.
|
||||
for (i,j,k...) F(i,j,k...)
|
||||
|
||||
* 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.
|
||||
|
||||
@ -80,7 +79,7 @@ Synopsis::
|
||||
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
|
||||
using the TraversalOrder flag of the array.
|
||||
using the TraversalOrder of the array.
|
||||
|
||||
.. triqs_example:: ./foreach_1.cpp
|
||||
.. note::
|
||||
|
@ -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(),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 << " is_contiguous = "<< A.indexmap().is_contiguous() <<std::endl;
|
||||
|
||||
|
@ -37,7 +37,7 @@ struct plain_for_no_ptr_const {
|
||||
|
||||
struct assign_to_const {
|
||||
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);
|
||||
for (int u =0; u<5000; ++u)
|
||||
//make_view(A) = 1867;
|
||||
@ -58,8 +58,8 @@ struct plain_for_no_ptr {
|
||||
//typedef double value_type;
|
||||
//typedef triqs::arrays::matrix<double>::indexmap_type::domain_type::index_value_type index_value_type;
|
||||
struct F {
|
||||
triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > & a;
|
||||
F(triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > & a_): a(a_){}
|
||||
triqs::arrays::matrix<double> & 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, 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 ;}
|
||||
@ -67,7 +67,7 @@ struct F {
|
||||
|
||||
struct with_foreach {
|
||||
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::
|
||||
for (int u =0; u<3000; ++u) foreach(A,F(A));
|
||||
// for (int u =0; u<5000; ++u) make_view(A) = 1867;
|
||||
|
160
test/speed/array3.cpp
Normal file
160
test/speed/array3.cpp
Normal 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;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ struct plain {
|
||||
struct lazy {
|
||||
void operator()() {
|
||||
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)
|
||||
A(i_,j_) << i_+ 2*j_;
|
||||
}
|
||||
@ -49,7 +49,7 @@ struct lazy {
|
||||
|
||||
struct foreach_lambda {
|
||||
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)
|
||||
//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;});
|
||||
|
@ -37,7 +37,7 @@ struct plain_for_no_ptr_const {
|
||||
|
||||
struct assign_to_const {
|
||||
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);
|
||||
for (int u =0; u<2500000; ++u)
|
||||
//make_view(A) = 1867;
|
||||
@ -58,8 +58,8 @@ struct plain_for_no_ptr {
|
||||
//typedef double value_type;
|
||||
//typedef triqs::arrays::matrix<double>::indexmap_type::domain_type::index_value_type index_value_type;
|
||||
struct F {
|
||||
triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > & a;
|
||||
F(triqs::arrays::matrix<double,TRAVERSAL_ORDER_FORTRAN > & a_): a(a_){}
|
||||
triqs::arrays::matrix<double> & 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, 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 ;}
|
||||
@ -67,7 +67,7 @@ struct F {
|
||||
|
||||
struct with_foreach {
|
||||
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::
|
||||
for (int u =0; u<2500000; ++u) foreach(A,F(A));
|
||||
// for (int u =0; u<5000; ++u) make_view(A) = 1867;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
//#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
|
||||
//#define TRIQS_ARRAYS_CHECK_WEAK_REFS
|
||||
|
||||
|
@ -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,1 > C(2);
|
||||
array<long,2, BoundCheck > Af (2,3, FORTRAN_LAYOUT);
|
||||
array<long,2> Af (2,3, FORTRAN_LAYOUT);
|
||||
|
||||
try {
|
||||
|
||||
|
36
test/triqs/arrays/c_ordered_transposed_view.cpp
Normal file
36
test/triqs/arrays/c_ordered_transposed_view.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#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();}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "./common.hpp"
|
||||
#include <triqs/arrays/array.hpp>
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
#include <triqs/arrays/matrix.hpp>
|
||||
#include <iostream>
|
||||
#include <triqs/arrays/asserts.hpp>
|
||||
|
@ -31,7 +31,7 @@ int main(int argc, char **argv) {
|
||||
A(i_,j_) << i_ + 2*j_ ;
|
||||
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_ ;
|
||||
std::cout << "B = "<<B << std::endl;
|
||||
}
|
||||
|
@ -1,64 +1,94 @@
|
||||
#include "./common.hpp"
|
||||
#include <triqs/arrays/indexmaps/cuboid/group_indices.hpp>
|
||||
#include <triqs/arrays/matrix.hpp>
|
||||
#include <triqs/arrays/asserts.hpp>
|
||||
#include <triqs/arrays.hpp>
|
||||
|
||||
namespace tqa=triqs::arrays;
|
||||
namespace tql=triqs::clef;
|
||||
using namespace triqs::arrays;
|
||||
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_;
|
||||
tql::placeholder<1> j_;
|
||||
tql::placeholder<2> k_;
|
||||
tql::placeholder<3> l_;
|
||||
{ // a simple test
|
||||
array<int, 4> A(2, 2, 2, 2);
|
||||
A(i_, j_, k_, l_) << i_ + 10 * j_ + 100 * k_ + 1000 * l_;
|
||||
TEST_ERR(A);
|
||||
TEST_ERR(group_indices_view(A, {0,1}, {2,3}));
|
||||
}
|
||||
|
||||
{ // a simple test
|
||||
tqa::array<int,4,FLAG> A(2,2,2,2);
|
||||
A(i_,j_,k_,l_) << i_ + 10*j_ + 100*k_ + 1000*l_;
|
||||
TEST(A);
|
||||
TEST( group_indices(A, m_index<0,1>(), m_index<2,3>()));
|
||||
// more complex : inversing a tensor product of matrices...
|
||||
matrix<double> 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_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);
|
||||
}
|
||||
}
|
||||
|
||||
{ // more complex : inversing a tensor product of matrices...
|
||||
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)));
|
||||
catch (std::exception const& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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<...>
|
||||
}
|
||||
|
@ -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 ]
|
@ -65,7 +65,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
|
||||
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) {
|
||||
*it =it.indices()[0] + 10 *it.indices()[1] ;
|
||||
|
@ -24,38 +24,18 @@
|
||||
|
||||
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>
|
||||
array_view<V, sizeof...(I), Opt> reinterpret (array<V,R,Opt,To> const & a, I ... index) {
|
||||
template <typename V, int R, typename To, typename... I>
|
||||
array_view<V, sizeof...(I)> reinterpret(array<V, R, To> const &a, I... index) {
|
||||
return { {make_shape(index...)}, a.storage() };
|
||||
}
|
||||
|
||||
// wrong for views
|
||||
template <typename V, int R, ull_t Opt, ull_t To, bool B, 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) {
|
||||
template <typename V, int R, bool B, typename To, typename ... I>
|
||||
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";
|
||||
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() };
|
||||
}
|
||||
*/
|
||||
|
||||
}}
|
||||
|
||||
|
@ -20,96 +20,81 @@
|
||||
******************************************************************************/
|
||||
#include "./common.hpp"
|
||||
#include <iostream>
|
||||
#include <triqs/arrays/impl/common.hpp>
|
||||
#include <triqs/arrays/indexmaps/range.hpp>
|
||||
#include <triqs/arrays/indexmaps/permutation.hpp>
|
||||
#include <triqs/arrays/indexmaps/cuboid/slice_traversal_order.hpp>
|
||||
#include <triqs/arrays.hpp>
|
||||
|
||||
using namespace triqs::arrays;
|
||||
using namespace triqs::arrays::permutations;
|
||||
using namespace triqs::arrays::indexmaps;
|
||||
|
||||
template<ull F> struct P {
|
||||
static constexpr ull value = F;
|
||||
friend std::ostream & operator <<( std::ostream & out, P const & s) {
|
||||
//out << "Permutation of size " << permutations::size(s.value) << " : "<< std::hex;
|
||||
out << std::hex;
|
||||
s.print(out, std::integral_constant<ull,0>());
|
||||
return out << std::dec;
|
||||
template <typename ML1, typename ML2, typename... Args> void test(ML1 ml1, ML2 ml2, Args... x) {
|
||||
|
||||
cuboid::map<ML2::rank> m(ml2);
|
||||
slicer<cuboid::map<ML2::rank>, Args...> S;
|
||||
auto m2 = S.invoke(m, x...);
|
||||
std::cout << m.get_memory_layout() << std::endl;
|
||||
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);
|
||||
}
|
||||
|
||||
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 ;
|
||||
std::cout << "----------------------" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
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< 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> ();
|
||||
test(make_memory_layout(0), make_memory_layout(0, 1), 0, range());
|
||||
|
||||
std::cout << " c order " << std::endl ;
|
||||
test< permutation(1,0) ,permutation(3,2,1,0), int, range,int, range>();
|
||||
test< permutation(2,1,0) ,permutation(3,2,1,0), int, range, range, range>();
|
||||
test< permutation(2,1,0) ,permutation(3,2,1,0), range,int, range, range>();
|
||||
test< permutation(2,1,0) ,permutation(3,2,1,0), range, range,int, range>();
|
||||
test< permutation(2,1,0) ,permutation(3,2,1,0), range, range, range, int>();
|
||||
test< permutation(3,2,1,0) ,permutation(3,2,1,0), range, range, range, range>();
|
||||
test< 0 ,permutation(3,2,1,0), int, int, int, int> ();
|
||||
std::cout << " custom order " << std::endl;
|
||||
test(make_memory_layout(1, 0), make_memory_layout(0, 3, 1, 2), 0, range(), 0, range());
|
||||
test(make_memory_layout(2, 0, 1), make_memory_layout(0, 3, 1, 2), 0, range(), range(), range());
|
||||
test(make_memory_layout(0, 2, 1), make_memory_layout(0, 3, 1, 2), range(), 0, range(), range());
|
||||
test(make_memory_layout(0, 2, 1), make_memory_layout(0, 3, 1, 2), range(), range(), 0, range());
|
||||
test(make_memory_layout(0, 1, 2), make_memory_layout(0, 3, 1, 2), range(), range(), range(), 0);
|
||||
test(make_memory_layout(0, 3, 1, 2), make_memory_layout(0, 3, 1, 2), range(), range(), range(), range());
|
||||
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 ;
|
||||
test< permutation(1,0) ,permutation(0,3,1,2), int, range,int, 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 << " ---- 0 0 " << std::endl;
|
||||
test(make_memory_layout(2, 0, 3, 1), make_memory_layout(2, 0, 3, 1), range(), range(), range(), range());
|
||||
|
||||
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 ;
|
||||
test< permutation(2,0,3,1) ,permutation(2,0,3,1), range, range, range, range>();
|
||||
std::cout << " ---- 2 0 " << std::endl;
|
||||
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 ;
|
||||
test< permutation(1,2,0) ,permutation(2,0,3,1), int, range, range, range>();
|
||||
test< permutation(1,0,2) ,permutation(2,0,3,1), range,int, range, range>();
|
||||
test< permutation(0,2,1) ,permutation(2,0,3,1), range, range,int, range>();
|
||||
test< permutation(2,0,1) ,permutation(2,0,3,1), range, range, range, int>();
|
||||
|
||||
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 << " ---- 3 0 " << std::endl;
|
||||
test(make_memory_layout(0), make_memory_layout(2, 0, 3, 1), range(), 0, 0, 0);
|
||||
test(make_memory_layout(0), make_memory_layout(2, 0, 3, 1), 0, range(), 0, 0);
|
||||
test(make_memory_layout(0), make_memory_layout(2, 0, 3, 1), 0, 0, range(), 0);
|
||||
test(make_memory_layout(0), make_memory_layout(2, 0, 3, 1), 0, 0, 0, range());
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -24,67 +24,61 @@
|
||||
#include <triqs/arrays/array.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using std::cout; using std::endl;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using namespace triqs::arrays;
|
||||
|
||||
///
|
||||
template<typename IM, typename A>
|
||||
void print_in_indexmap_order (std::ostream & out, IM const & im, A const & a) {
|
||||
out<<"[";
|
||||
//for (typename IM::iterator it(im); it; ++it) out<<a[it.indices()]<<" ";
|
||||
template <typename IM, typename A> void print_in_indexmap_order(std::ostream &out, IM const &im, A const &a) {
|
||||
out << "[";
|
||||
for (typename IM::iterator it(im); it; ++it) {
|
||||
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>
|
||||
void f(AA & A) {
|
||||
template <class AA> void f(AA &A) {
|
||||
|
||||
for (int i =0; i<2; ++i)
|
||||
for (int j=0; j<3; ++j)
|
||||
for (int k=0; k<4; ++k)
|
||||
A(i,j,k) = 100*(i+1)+ 10*(j+1) + (k+1);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
for (int k = 0; k < 4; ++k) 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(1,range(), range())<<std::endl;
|
||||
std::cout<< A(range(), 0, range())<<std::endl;
|
||||
std::cout<< A(range(), range(),1)<<std::endl;
|
||||
std::cout<< A(range(), 0,1)<<std::endl;
|
||||
std::cout<<"-------------------------------------------------- "<<std::endl;
|
||||
std::cout << A(0, range(), range()) << std::endl;
|
||||
std::cout << A(1, range(), range()) << std::endl;
|
||||
std::cout << A(range(), 0, range()) << std::endl;
|
||||
std::cout << A(range(), range(), 1) << std::endl;
|
||||
std::cout << A(range(), 0, 1) << std::endl;
|
||||
std::cout << "-------------------------------------------------- " << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
|
||||
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
|
||||
array<long, 3, 0, permutation(2,1,0)> A0 (2,3,4);
|
||||
array<long, 3, 0, permutation(0,1,2)> A1 (2,3,4);
|
||||
array<long, 3, 0, permutation(1,0,2)> A2 (2,3,4);
|
||||
array<long, 3> A3 (2,3,4);
|
||||
array<long, 3, TRAVERSAL_ORDER_FORTRAN> A4 (2,3,4,FORTRAN_LAYOUT);
|
||||
// permutation in triqs::arrays
|
||||
array<long, 3> A0(2, 3, 4);
|
||||
array<long, 3, _traversal_dynamical> A1(2, 3, 4, make_memory_layout(2, 1, 0));
|
||||
array<long, 3, _traversal_dynamical> A2(2, 3, 4, make_memory_layout(2, 0, 1));
|
||||
array<long, 3> A3(2, 3, 4, make_memory_layout(0, 1, 2));
|
||||
array<long, 3, _traversal_fortran> A4(2, 3, 4, FORTRAN_LAYOUT);
|
||||
|
||||
f(A0);
|
||||
f(A1);
|
||||
f(A2);
|
||||
f(A3);
|
||||
f(A4);
|
||||
f(A0);
|
||||
f(A1);
|
||||
f(A2);
|
||||
f(A3);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -134,14 +134,14 @@ int main(int argc, char **argv) {
|
||||
std::cerr << " " << res << std::endl ;
|
||||
}
|
||||
|
||||
{ // to mini_vector
|
||||
/* { // to mini_vector
|
||||
|
||||
auto t = std::make_tuple(1,2,3.4);
|
||||
auto m = triqs::utility::tuple_to_mini_vector<double>(t);
|
||||
std::cout << m<< std::endl ;
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
{ // filter
|
||||
std::cout << " ----- filter ----"<< std::endl ;
|
||||
auto t= std::make_tuple(0,1,2,3,4,"=5");
|
||||
|
@ -40,8 +40,8 @@ int main(int argc, char **argv) {
|
||||
|
||||
check<array<int,1>> ();
|
||||
check<array_view<int,1>>();
|
||||
check<matrix<int,1>>();
|
||||
check<matrix_view<int,1>>();
|
||||
check<matrix<int>>();
|
||||
check<matrix_view<int>>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@
|
||||
#ifndef TRIQS_ARRAYS_ALL_H
|
||||
#define TRIQS_ARRAYS_ALL_H
|
||||
|
||||
#define TRIQS_ARRAYS_INCLUDED
|
||||
|
||||
// The basic classes
|
||||
#include <triqs/arrays/array.hpp>
|
||||
#include <triqs/arrays/matrix.hpp>
|
||||
@ -36,6 +38,9 @@
|
||||
// HDF5 interface
|
||||
#include <triqs/arrays/h5/simple_read_write.hpp>
|
||||
|
||||
// Regrouping indices
|
||||
#include <triqs/arrays/group_indices.hpp>
|
||||
|
||||
// Linear algebra ?? Keep here ?
|
||||
//#include <triqs/arrays/linalg/det_and_inverse.hpp>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAYS_ARRAY_H
|
||||
#define TRIQS_ARRAYS_ARRAY_H
|
||||
#pragma once
|
||||
#include <triqs/utility/first_include.hpp>
|
||||
#include "indexmaps/cuboid/map.hpp"
|
||||
#include "indexmaps/cuboid/slice.hpp"
|
||||
#include "impl/indexmap_storage_pair.hpp"
|
||||
#include "impl/assignment.hpp"
|
||||
#include "impl/flags.hpp"
|
||||
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, ull_t Opt=0, ull_t TraversalOrder= 0> class array;
|
||||
template <typename ValueType, int Rank, typename TraversalOrder= void, bool Borrowed = false, bool IsConst = false> class array_view;
|
||||
template <typename ValueType, int Rank, typename TraversalOrder= void> class array;
|
||||
|
||||
// ---------------------- array_view --------------------------------
|
||||
|
||||
#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<Rank,Opt,TraversalOrder>, \
|
||||
storages::shared_block<ValueType, Borrowed>, Opt, TraversalOrder, IsConst, true, Tag::array_view >
|
||||
#define IMPL_TYPE \
|
||||
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 {
|
||||
static_assert( Rank>0, " Rank must be >0");
|
||||
|
||||
public:
|
||||
typedef typename IMPL_TYPE::indexmap_type indexmap_type;
|
||||
typedef typename IMPL_TYPE::storage_type storage_type;
|
||||
typedef array <ValueType,Rank,Opt,TraversalOrder> regular_type;
|
||||
typedef array_view<ValueType,Rank,Opt,TraversalOrder> view_type;
|
||||
typedef array_view<ValueType, Rank, Opt, TraversalOrder, false, true> const_view_type;
|
||||
typedef array_view<ValueType,Rank,Opt,TraversalOrder,true> weak_view_type;
|
||||
using indexmap_type = typename IMPL_TYPE::indexmap_type;
|
||||
using storage_type = typename IMPL_TYPE::storage_type;
|
||||
using regular_type = array<ValueType, Rank, TraversalOrder>;
|
||||
using view_type = array_view<ValueType, Rank, TraversalOrder>;
|
||||
using const_view_type = array_view<ValueType, Rank, TraversalOrder, false, true>;
|
||||
using weak_view_type = array_view<ValueType, Rank, TraversalOrder, true>;
|
||||
|
||||
/// Build from an IndexMap and a storage
|
||||
template <typename S> array_view(indexmap_type const& Ind, S const& Mem) : IMPL_TYPE(Ind, Mem) {}
|
||||
|
||||
/// 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
|
||||
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
|
||||
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.
|
||||
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->storage_ = X.storage_;
|
||||
}
|
||||
@ -96,45 +96,52 @@ namespace triqs { namespace arrays {
|
||||
// to forbid serialization of views...
|
||||
//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) {
|
||||
return array_view{transpose(a.indexmap_, is...), a.storage_};
|
||||
template <typename... INT> friend view_type transposed_view(array_view const& a, INT... is) {
|
||||
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
|
||||
|
||||
template <typename ValueType, int Rank, ull_t Opt=0, ull_t TraversalOrder=0, bool Borrowed=false>
|
||||
using array_const_view = array_view<ValueType, Rank, Opt, TraversalOrder, Borrowed, true>;
|
||||
template <typename ValueType, int Rank, typename TraversalOrder = void, bool Borrowed = false>
|
||||
using array_const_view = array_view<ValueType, Rank, TraversalOrder, Borrowed, true>;
|
||||
|
||||
//------------------------------- array ---------------------------------------------------
|
||||
|
||||
#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<Rank,Opt,TraversalOrder>, \
|
||||
storages::shared_block<ValueType>, Opt, TraversalOrder, false, false, Tag::array_view >
|
||||
#define IMPL_TYPE \
|
||||
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>
|
||||
class array: Tag::array, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE {
|
||||
public:
|
||||
typedef typename IMPL_TYPE::value_type value_type;
|
||||
typedef typename IMPL_TYPE::storage_type storage_type;
|
||||
typedef typename IMPL_TYPE::indexmap_type indexmap_type;
|
||||
typedef array<ValueType, Rank, Opt, TraversalOrder> regular_type;
|
||||
typedef array_view<ValueType, Rank, Opt, TraversalOrder> view_type;
|
||||
typedef array_view<ValueType, Rank, Opt, TraversalOrder, false, true> const_view_type;
|
||||
typedef array_view<ValueType, Rank, Opt, TraversalOrder, true> weak_view_type;
|
||||
template <typename ValueType, int Rank, typename TraversalOrder>
|
||||
class array : Tag::array, TRIQS_CONCEPT_TAG_NAME(MutableArray), public IMPL_TYPE {
|
||||
public:
|
||||
using value_type = typename IMPL_TYPE::value_type;
|
||||
using storage_type = typename IMPL_TYPE::storage_type;
|
||||
using indexmap_type = typename IMPL_TYPE::indexmap_type;
|
||||
using regular_type = array<ValueType, Rank, TraversalOrder>;
|
||||
using view_type = array_view<ValueType, Rank, TraversalOrder>;
|
||||
using const_view_type = array_view<ValueType, Rank, TraversalOrder, false, true>;
|
||||
using weak_view_type = array_view<ValueType, Rank, TraversalOrder, true>;
|
||||
|
||||
/// Empty array.
|
||||
explicit array(memory_layout<Rank> ml = memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order)) :IMPL_TYPE(ml){}
|
||||
/// Empty array.
|
||||
explicit array(memory_layout<Rank> ml = memory_layout<Rank>{}) : IMPL_TYPE(ml) {}
|
||||
|
||||
/// 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)):
|
||||
IMPL_TYPE(indexmap_type(dom,ml)){}
|
||||
/// From a domain
|
||||
explicit array(typename indexmap_type::domain_type const& dom, memory_layout<Rank> ml = memory_layout<Rank>{})
|
||||
: IMPL_TYPE(indexmap_type(dom, ml)) {}
|
||||
|
||||
#ifdef TRIQS_DOXYGEN
|
||||
/// 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);
|
||||
#else
|
||||
#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)) {\
|
||||
static_assert(IMPL_TYPE::rank-1==NN,"array : incorrect number of variables in constructor");}
|
||||
BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil)
|
||||
@ -148,9 +155,8 @@ namespace triqs { namespace arrays {
|
||||
explicit array(array && X) { this->swap_me(X); }
|
||||
|
||||
// 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,
|
||||
memory_layout<Rank> ml = memory_layout<Rank>(IMPL_TYPE::indexmap_type::traversal_order)):
|
||||
IMPL_TYPE(indexmap_type(dom,ml), std::move(sto)){}
|
||||
explicit array(typename indexmap_type::domain_type const& dom, storage_type&& sto, memory_layout<Rank> ml = memory_layout<Rank>{})
|
||||
: 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 :
|
||||
@ -158,8 +164,10 @@ namespace triqs { namespace arrays {
|
||||
* - a expression : e.g. array<int> A = B+ 2*C;
|
||||
*/
|
||||
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)):
|
||||
IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); }
|
||||
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);
|
||||
}
|
||||
|
||||
#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.
|
||||
@ -169,14 +177,14 @@ namespace triqs { namespace arrays {
|
||||
// build from a init_list
|
||||
template<typename T, int R=Rank>
|
||||
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;
|
||||
for (auto const & x : l) (*this)(i++) = x;
|
||||
}
|
||||
|
||||
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):
|
||||
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;
|
||||
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)));
|
||||
@ -217,10 +225,10 @@ namespace triqs { namespace arrays {
|
||||
TRIQS_DEFINE_COMPOUND_OPERATORS(array);
|
||||
|
||||
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) {
|
||||
return view_type{transpose(a.indexmap_, is...), a.storage_};
|
||||
return transposed_view(a(), is...);
|
||||
};
|
||||
|
||||
};//array class
|
||||
@ -230,19 +238,18 @@ namespace triqs { namespace arrays {
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// how to build the view type ....
|
||||
template < class V, int R, ull_t Opt, ull_t 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; };
|
||||
|
||||
template <class V, int R, typename TraversalOrder, bool Borrowed, bool IsConst>
|
||||
struct ISPViewType<V, R, TraversalOrder, Tag::array_view, Borrowed, IsConst> {
|
||||
using type = array_view<V, R, TraversalOrder, Borrowed, IsConst>;
|
||||
};
|
||||
}}//namespace triqs::arrays
|
||||
|
||||
// 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).
|
||||
namespace std {
|
||||
template <typename V, int R, triqs::ull_t Opt, triqs::ull_t To, 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;
|
||||
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, To1, B1, C1>& a, triqs::arrays::array_view<V, R, To2, B2, C2>& b) = delete;
|
||||
}
|
||||
|
||||
#include "./expression_template/array_algebra.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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
|
||||
// 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
|
||||
template<typename A, typename MT1, typename MT2, typename B, typename V, ull_t Opt, ull_t 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);}
|
||||
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,To,W> && c) { gemm(alpha,a,b,beta,c);}
|
||||
|
||||
}}}// namespace
|
||||
|
||||
|
@ -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
|
||||
// which require an lvalue.
|
||||
template<typename A, typename MT, typename VT, typename B, typename V, ull_t Opt, 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);}
|
||||
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,W> && c) { gemv(alpha,a,b,beta,c);}
|
||||
|
||||
}}}// namespace
|
||||
|
||||
|
@ -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
|
||||
// which require an lvalue
|
||||
template< typename A, typename VTX, typename VTY, typename V, ull_t Opt, ull_t 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);}
|
||||
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,To,W> && r) { ger(alpha,x,y,r);}
|
||||
|
||||
}}}// namespace
|
||||
#endif
|
||||
|
@ -64,7 +64,7 @@ namespace arrays {
|
||||
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::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::false_type) {
|
||||
@ -98,12 +98,12 @@ namespace arrays {
|
||||
template <typename DataType> using const_cache = cache_impl<DataType, true>;
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
}
|
||||
|
77
triqs/arrays/group_indices.hpp
Normal file
77
triqs/arrays/group_indices.hpp
Normal 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()};
|
||||
}
|
||||
}
|
||||
}
|
@ -114,9 +114,19 @@ namespace triqs { namespace arrays {
|
||||
TRIQS_REJECT_MATRIX_COMPOUND_MUL_DIV_NON_SCALAR;
|
||||
typedef typename LHS::value_type value_type;
|
||||
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...));}
|
||||
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 --------------------------------------------------
|
||||
|
@ -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
|
@ -18,12 +18,11 @@
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAY_IMPL_INDEX_STORAGE_PAIR_H
|
||||
#define TRIQS_ARRAY_IMPL_INDEX_STORAGE_PAIR_H
|
||||
#pragma once
|
||||
#include "./common.hpp"
|
||||
#include "./flags.hpp"
|
||||
#include "../storages/shared_block.hpp"
|
||||
#include "./assignment.hpp"
|
||||
#include "./print.hpp"
|
||||
#include "../indexmaps/cuboid/foreach.hpp"
|
||||
#include "triqs/utility/exceptions.hpp"
|
||||
#include "triqs/utility/typeid_name.hpp"
|
||||
@ -36,7 +35,7 @@
|
||||
|
||||
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 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 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 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 <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) {
|
||||
|
||||
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_const<value_type>::value, "no const type");
|
||||
typedef StorageType storage_type;
|
||||
typedef IndexMapType indexmap_type;
|
||||
static constexpr unsigned int rank = IndexMapType::domain_type::rank;
|
||||
static constexpr ull_t opt_flags = OptionFlags;
|
||||
static constexpr ull_t traversal_order = TraversalOrder;
|
||||
using storage_type=StorageType ;
|
||||
using indexmap_type=IndexMapType ;
|
||||
using traversal_order_t = typename _get_traversal_order_t<TraversalOrder>::type;
|
||||
using traversal_order_arg = TraversalOrder;
|
||||
static constexpr int rank = IndexMapType::domain_type::rank;
|
||||
static constexpr bool is_const = IsConst;
|
||||
|
||||
protected:
|
||||
@ -72,30 +73,25 @@ namespace triqs { namespace arrays {
|
||||
// ------------------------------- constructors --------------------------------------------
|
||||
|
||||
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 (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;
|
||||
indexmap_storage_pair(indexmap_type IM, storage_type ST) : indexmap_(std::move(IM)), storage_(std::move(ST)) {
|
||||
#ifdef TRIQS_ARRAYS_CHECK_IM_STORAGE_COMPAT
|
||||
if (ST.size() != IM.domain().number_of_elements())
|
||||
TRIQS_RUNTIME_ERROR<<"index_storage_pair construction : storage and indices are not compatible";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/// Shallow copy
|
||||
indexmap_storage_pair(const indexmap_storage_pair & X):indexmap_(X.indexmap()),storage_(X.storage_){}
|
||||
indexmap_storage_pair(indexmap_storage_pair && X):indexmap_(std::move(X.indexmap())),storage_(std::move(X.storage_)){}
|
||||
protected:
|
||||
/// The storage is allocated from the size of IM.
|
||||
indexmap_storage_pair(const indexmap_type &IM) : indexmap_(IM), storage_() {
|
||||
storage_ = StorageType(indexmap_.domain().number_of_elements());
|
||||
}
|
||||
|
||||
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
|
||||
indexmap_storage_pair (PyObject * X, bool enforce_copy, const char * name ) {
|
||||
try {
|
||||
@ -109,11 +105,9 @@ namespace triqs { namespace arrays {
|
||||
// linker search for IndexMapType::domain_type::rank in triqs.so
|
||||
// and cannot resolve it ???
|
||||
//<<"\n rank = "<< IndexMapType::domain_type::rank//this->rank
|
||||
<<"\n OptionFlags = "<< OptionFlags
|
||||
<<"\nfrom the python object \n"<< numpy_interface::object_to_string(X)
|
||||
<<"\nThe error was :\n "<<s.what();
|
||||
}
|
||||
//std::cerr << " Leave IPS ref count = "<< X->ob_refcnt << std::endl;
|
||||
}
|
||||
#endif
|
||||
// ------------------------------- swap --------------------------------------------
|
||||
@ -156,10 +150,10 @@ namespace triqs { namespace arrays {
|
||||
value_type const * restrict data_start() const { 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();}
|
||||
|
||||
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();}
|
||||
|
||||
size_t shape(size_t i) const { return domain().lengths()[i];}
|
||||
@ -171,27 +165,27 @@ namespace triqs { namespace arrays {
|
||||
|
||||
// ------------------------------- operator () --------------------------------------------
|
||||
|
||||
typedef typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag,false, IsConst >::type view_type;
|
||||
typedef typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag,true , IsConst>::type weak_view_type;
|
||||
using view_type = typename ISPViewType<value_type, domain_type::rank, TraversalOrder, ViewTag, false, IsConst>::type;
|
||||
using weak_view_type = typename ISPViewType<value_type, domain_type::rank, TraversalOrder, ViewTag, true, IsConst>::type;
|
||||
|
||||
// Evaluation and slices
|
||||
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)
|
||||
, value_type &>::type
|
||||
, value_type &>
|
||||
operator()(Args const & ... args) & { return storage_[indexmap_(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)
|
||||
, value_type const &>::type
|
||||
, value_type const &>
|
||||
operator()(Args const & ... args) const & { return storage_[indexmap_(args...)]; }
|
||||
|
||||
// && : return a & iif it is a non const view
|
||||
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)
|
||||
, value_type &>::type
|
||||
, value_type &>
|
||||
operator()(Args const & ... args) && {
|
||||
// add here a security check in case it is a view, unique. For a regular type, move the result...
|
||||
#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
|
||||
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))
|
||||
, value_type>::type
|
||||
, value_type>
|
||||
operator()(Args const & ... args) && { return storage_[indexmap_(args...)]; }
|
||||
|
||||
template<bool is_const, bool ForceBorrowed, typename ... Args> struct result_of_call_as_view {
|
||||
typedef typename indexmaps::slicer<indexmap_type,Args...>::r_type IM2;
|
||||
//typedef typename std::conditional<is_const, typename std::add_const<value_type>::type, value_type>::type V2;
|
||||
typedef value_type V2;
|
||||
using IM2=typename indexmaps::slicer<indexmap_type,Args...>::r_type ;
|
||||
//using V2=typename std::conditional<is_const, typename std::add_const<value_type>::type, value_type>::type ;
|
||||
using V2=value_type ;
|
||||
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
|
||||
@ -243,13 +238,13 @@ namespace triqs { namespace arrays {
|
||||
}
|
||||
|
||||
/// 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; }
|
||||
|
||||
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; }
|
||||
|
||||
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; }
|
||||
|
||||
// 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);}
|
||||
|
||||
// ------------------------------- Iterators --------------------------------------------
|
||||
typedef iterator_adapter<true,typename IndexMapType::iterator, StorageType> const_iterator;
|
||||
typedef iterator_adapter<false,typename IndexMapType::iterator, StorageType> iterator;
|
||||
using const_iterator=iterator_adapter<true,typename IndexMapType::iterator, StorageType> ;
|
||||
using iterator=iterator_adapter<false,typename IndexMapType::iterator, StorageType> ;
|
||||
const_iterator begin() const {return const_iterator(indexmap(),storage(),false);}
|
||||
const_iterator end() const {return const_iterator(indexmap(),storage(),true);}
|
||||
const_iterator cbegin() const {return const_iterator(indexmap(),storage(),false);}
|
||||
@ -311,11 +306,11 @@ namespace triqs { namespace arrays {
|
||||
// ------------------------------- resize --------------------------------------------
|
||||
//
|
||||
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 !
|
||||
// optimisation. Construct a storage only if the new index is not compatible (size mismatch).
|
||||
if (this->storage_.size() != this->indexmap_.domain().number_of_elements())
|
||||
this->storage_ = StorageType(this->indexmap_.domain().number_of_elements(), typename flags::init_tag<OptionFlags>::type() );
|
||||
if (storage_.size() != indexmap_.domain().number_of_elements())
|
||||
storage_ = StorageType(indexmap_.domain().number_of_elements());
|
||||
}
|
||||
|
||||
template<typename Xtype>
|
||||
@ -332,11 +327,10 @@ namespace triqs { namespace arrays {
|
||||
// pretty print of the array
|
||||
friend std::ostream & operator << (std::ostream & out, const indexmap_storage_pair & A) {
|
||||
if (A.storage().size()==0) out<<"empty ";
|
||||
else indexmaps::pretty_print(out,A);
|
||||
else pretty_print(out,A);
|
||||
return out;
|
||||
}
|
||||
};// end class
|
||||
|
||||
}}//namespace triqs::arrays
|
||||
#endif
|
||||
|
||||
|
77
triqs/arrays/impl/print.hpp
Normal file
77
triqs/arrays/impl/print.hpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_DOMAIN_H
|
||||
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_DOMAIN_H
|
||||
#pragma once
|
||||
#include "../common.hpp"
|
||||
#include "../range.hpp"
|
||||
#include "./mem_layout.hpp"
|
||||
#include "../permutation.hpp"
|
||||
#include <triqs/utility/mini_vector.hpp>
|
||||
#include "../../impl/exceptions.hpp"
|
||||
#include <iostream>
|
||||
#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 {
|
||||
using namespace triqs::arrays::permutations;
|
||||
namespace triqs {
|
||||
namespace arrays {
|
||||
namespace indexmaps {
|
||||
namespace cuboid {
|
||||
using namespace triqs::arrays::permutations;
|
||||
|
||||
/// Standard hyper_rectangular domain for arrays
|
||||
template<int Rank>
|
||||
class domain_t {
|
||||
typedef mini_vector<size_t,Rank> n_uple;
|
||||
n_uple lengths_;
|
||||
friend class boost::serialization::access;
|
||||
template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & TRIQS_MAKE_NVP("dimensions",lengths_);}
|
||||
public :
|
||||
static constexpr unsigned int rank = Rank;
|
||||
typedef n_uple index_value_type;
|
||||
/// Standard hyper_rectangular domain for arrays
|
||||
template <int Rank> class domain_t {
|
||||
using n_uple = mini_vector<size_t, Rank>;
|
||||
n_uple lengths_;
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive> void serialize(Archive &ar, const unsigned int version) {
|
||||
ar &TRIQS_MAKE_NVP("dimensions", lengths_);
|
||||
}
|
||||
|
||||
domain_t () =default;
|
||||
domain_t (const domain_t & C) = default;
|
||||
domain_t (domain_t && C) = default;
|
||||
domain_t & operator =( domain_t const &) = default;
|
||||
domain_t & operator =( domain_t && x)= default;
|
||||
public:
|
||||
static constexpr unsigned int rank = Rank;
|
||||
using index_value_type = n_uple;
|
||||
|
||||
domain_t (n_uple lengths):lengths_(std::move(lengths)) {}
|
||||
domain_t (mini_vector<int,Rank> const & lengths):lengths_(lengths) {}
|
||||
domain_t (std::vector<std::size_t> const & l):lengths_() {
|
||||
if (!(l.size()==Rank)) TRIQS_RUNTIME_ERROR << "cuboid domain_t construction : vector size incorrect : got "<<l.size() <<" while expected "<< Rank;
|
||||
lengths_ = n_uple(l);
|
||||
}
|
||||
template <typename ... T> domain_t(size_t i0, T... t): lengths_(i0, t...){}
|
||||
domain_t() = default;
|
||||
domain_t(const domain_t &C) = default;
|
||||
domain_t(domain_t &&C) = default;
|
||||
domain_t &operator=(domain_t const &) = default;
|
||||
domain_t &operator=(domain_t &&x) = default;
|
||||
|
||||
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 {
|
||||
typedef index_value_type indices_type;
|
||||
const domain_t * dom;
|
||||
domain_t(n_uple lengths) : lengths_(std::move(lengths)) {}
|
||||
domain_t(mini_vector<int, Rank> const &lengths) : lengths_(lengths) {}
|
||||
domain_t(std::vector<std::size_t> const &l) : lengths_() {
|
||||
if (!(l.size() == Rank))
|
||||
TRIQS_RUNTIME_ERROR << "cuboid domain_t construction : vector size incorrect : got " << l.size() << " while expected "
|
||||
<< Rank;
|
||||
lengths_ = n_uple(l);
|
||||
}
|
||||
template <typename... T> domain_t(size_t i0, T... t) : lengths_(i0, t...) {}
|
||||
|
||||
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;
|
||||
bool atend;
|
||||
|
||||
public:
|
||||
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 { 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>());
|
||||
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 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 end() const { return generator(*this,true);}
|
||||
/* End of generator */
|
||||
generator begin() const { return generator(*this, false); }
|
||||
generator end() const { return generator(*this, true); }
|
||||
/* End of generator */
|
||||
|
||||
// Check that key in in the domain
|
||||
template<class KeyType> void assert_key_in_domain(KeyType const & key) const {
|
||||
std::stringstream 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() ;
|
||||
}
|
||||
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;
|
||||
// Check that key in in the domain
|
||||
template <class KeyType> void assert_key_in_domain(KeyType const &key) const {
|
||||
std::stringstream 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();
|
||||
}
|
||||
template<class KeyType> bool key_check_impl (std::integral_constant<int,rank>, KeyType const &, n_uple const &, std::stringstream &) const { return true;}
|
||||
|
||||
// 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();}
|
||||
|
||||
};
|
||||
|
||||
// ------------------------- 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");
|
||||
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(std::get<r>(key)) < L[r]));
|
||||
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;
|
||||
}
|
||||
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
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_FOREACH_H
|
||||
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_FOREACH_H
|
||||
#pragma once
|
||||
#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>{};
|
||||
//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>{};
|
||||
#define FORCEINLINE __inline__ __attribute__((always_inline))
|
||||
|
||||
// ------------------------- 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>
|
||||
typename std::enable_if<ImmutableCuboidArray<T>::value >::type
|
||||
foreach (T const & x, Function const & F) { indexmaps::cuboid::foreach<get_traversal_order<T>::value> (x.domain(), F); }
|
||||
|
||||
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>
|
||||
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
|
||||
FORCEINLINE std14::enable_if_t<ImmutableCuboidArray<T>::value> foreach(T const& x, Function const& F) {
|
||||
using S = _get_traversal_order<T>;
|
||||
#ifndef TRIQS_ARRAYS_FOREACH_C_OR_DYNAMICAL
|
||||
indexmaps::cuboid::foreach_impl(typename S::traversal_order_t{}, x.domain(), S::invoke(x), F);
|
||||
#else
|
||||
if (ml.is_c()) {
|
||||
indexmaps::cuboid::foreach_impl(_traversal_c{}, x.domain(), S::invoke(x), F);
|
||||
} else {
|
||||
indexmaps::cuboid::foreach_impl(_traversal_dynamical{}, x.domain(), S::invoke(x), F);
|
||||
}
|
||||
#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
|
||||
|
@ -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
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_MAP_H
|
||||
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_MAP_H
|
||||
#pragma once
|
||||
#include "./domain.hpp"
|
||||
#include "./mem_layout.hpp"
|
||||
#include "../../impl/flags.hpp"
|
||||
#include <vector>
|
||||
#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;
|
||||
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);} };
|
||||
template< class D, class K> struct _chk<false, D, K> { static void invoke (D const & d, K const & k) {} };
|
||||
struct _traversal_c {};
|
||||
struct _traversal_fortran {};
|
||||
struct _traversal_dynamical {};
|
||||
template <int... Is> struct _traversal_custom {};
|
||||
|
||||
template< bool BC, class D, class ... K> struct _chk_v;
|
||||
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...);} };
|
||||
template< class D, class ... K> struct _chk_v<false, D, K...> { static void invoke (D const & d, K const & ... k) {} };
|
||||
template <typename T> struct _get_traversal_order_t {
|
||||
using type = T;
|
||||
};
|
||||
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) {
|
||||
int c[Rank]; for (size_t i=0; i<Rank; ++i) c[i]=0;
|
||||
for (size_t i=0; i<Rank; ++i)
|
||||
for (size_t 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 permutations::inverse(permutations::permutation_from_array(c, Rank));
|
||||
constexpr ull_t _get_traversal_order_permutation(int R, _traversal_c) { return permutations::identity(R); }
|
||||
constexpr ull_t _get_traversal_order_permutation(int R, _traversal_fortran) { return permutations::ridentity(R); }
|
||||
template <int... Is> constexpr ull_t _get_traversal_order_permutation(int R,_traversal_custom<Is...>) {
|
||||
static_assert(sizeof...(Is) == R, " Rank mismatch");
|
||||
return permutations::permutation(Is...);
|
||||
}
|
||||
|
||||
namespace indexmaps { namespace cuboid {
|
||||
|
||||
/** Standard hyper_rectangular arrays, implementing the IndexMap concept.
|
||||
*/
|
||||
template<int Rank, ull_t OptionsFlags, ull_t TraversalOrder >
|
||||
class map {
|
||||
template <int Rank, typename TraversalOrder=void> class map {
|
||||
public :
|
||||
static constexpr bool CheckBounds = flags::bound_check_trait<OptionsFlags>::value;
|
||||
static constexpr ull_t traversal_order_in_template = TraversalOrder;
|
||||
static constexpr ull_t traversal_order = indexmaps::mem_layout::get_traversal_order<Rank, OptionsFlags, TraversalOrder>::value;
|
||||
typedef void has_traversal_order_tag;
|
||||
static const unsigned int rank = Rank;
|
||||
typedef mini_vector<size_t,rank> lengths_type;
|
||||
typedef mini_vector<std::ptrdiff_t, rank> strides_type;
|
||||
typedef domain_t<Rank> domain_type;
|
||||
domain_type const & domain() const { return mydomain;}
|
||||
static const int rank = Rank;
|
||||
using lengths_type=mini_vector<size_t,rank> ;
|
||||
using strides_type=mini_vector<std::ptrdiff_t, rank> ;
|
||||
using domain_type = domain_t<Rank>;
|
||||
using traversal_order_in_template = TraversalOrder;
|
||||
using has_traversal_order_tag = void;
|
||||
domain_type const& domain() const { return mydomain; }
|
||||
|
||||
// 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 && C) = default;
|
||||
map & operator = (map const & m) = default;
|
||||
@ -69,8 +68,8 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
|
||||
|
||||
// basic construction
|
||||
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, memory_layout<Rank> ml): mydomain(C), start_shift_(0), memory_order_(ml) {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_(std::move(ml)) {compute_stride_compact();}
|
||||
|
||||
/// Construction from the length, the stride, 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 ):
|
||||
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)
|
||||
template<ull_t Opt2, ull_t To2> map (map<Rank,Opt2,To2> const & C):
|
||||
mydomain(C.domain()), strides_(C.strides()), start_shift_(C.start_shift()), memory_order_ (C.memory_indices_layout()) {}
|
||||
/// Construction from another map with the same order
|
||||
template <typename To2>
|
||||
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
|
||||
template <typename... INT> friend map transpose(map const& m, INT... is) {
|
||||
return map{{m.domain().lengths()[is]...}, {m.strides_[is]...}, m.start_shift_, transpose(m.memory_order_, is...)};
|
||||
friend map transpose(map const& m, mini_vector<int, Rank> const & perm) {
|
||||
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.
|
||||
template <typename KeyType>
|
||||
size_t operator[] (KeyType const & key ) const {
|
||||
_chk<CheckBounds, domain_type, KeyType>::invoke (this->domain(),key);
|
||||
return start_shift_ + dot_product(key,this->strides());
|
||||
template <typename KeyType> size_t operator[](KeyType const& key) const {
|
||||
#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
this->domain().assert_key_in_domain(key);
|
||||
#endif
|
||||
return start_shift_ + dot_product(key, this->strides());
|
||||
}
|
||||
|
||||
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
|
||||
<<" Stride : "<<P.strides_ << std::endl;
|
||||
}
|
||||
|
||||
/// TODO: replace by a tuple call....
|
||||
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...);
|
||||
}
|
||||
private :
|
||||
@ -115,19 +129,17 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
|
||||
|
||||
///
|
||||
bool is_contiguous() const {
|
||||
const size_t last_index = mem_layout::memory_rank_to_index(memory_order_.value, rank-1);
|
||||
return (strides()[last_index] * this->lengths()[last_index] == mydomain.number_of_elements());
|
||||
int slowest_index = memory_order_[0];
|
||||
return (strides()[slowest_index] * this->lengths()[slowest_index] == mydomain.number_of_elements());
|
||||
}
|
||||
|
||||
size_t start_shift() const { return start_shift_;}
|
||||
lengths_type const & lengths() const { return mydomain.lengths();}
|
||||
strides_type const & strides() const { return this->strides_;}
|
||||
|
||||
memory_layout<Rank> const & memory_indices_layout() const { return memory_order_;}
|
||||
memory_layout<Rank> traversal_order_indices_layout() const { return memory_layout<Rank>(traversal_order);}
|
||||
ull_t memory_indices_layout_ull() const { return memory_order_.value;}
|
||||
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);}
|
||||
memory_layout<Rank> const & get_memory_layout() const { return memory_order_;}
|
||||
bool memory_layout_is_c() const { return get_memory_layout().is_c();}
|
||||
bool memory_layout_is_fortran() const { return get_memory_layout().is_fortran();}
|
||||
|
||||
private :
|
||||
domain_type mydomain;
|
||||
@ -143,19 +155,30 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
|
||||
ar & TRIQS_MAKE_NVP("start_shift",start_shift_);
|
||||
}
|
||||
// for construction
|
||||
// TODO : use tupletools
|
||||
void compute_stride_compact() {
|
||||
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);
|
||||
}
|
||||
template<int v>
|
||||
void csc_impl(ull_t order, size_t & str, std::integral_constant<int,v>) {
|
||||
size_t u = mem_layout::memory_rank_to_index(order, rank-v);
|
||||
this->strides_[u] = str;
|
||||
str *= this->lengths() [u];
|
||||
csc_impl(order, str, std::integral_constant<int,v-1>());
|
||||
}
|
||||
void csc_impl(ull_t order,size_t & str, std::integral_constant<int,0>) {}
|
||||
// call for indices fastest (rank -1) to slowest (0)
|
||||
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);
|
||||
int u = ml[v - 1];
|
||||
this->strides_[u] = str;
|
||||
str *= this->lengths()[u];
|
||||
csc_impl(ml, str, std::integral_constant<int, v - 1>());
|
||||
}
|
||||
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:
|
||||
|
||||
@ -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 > {
|
||||
public:
|
||||
typedef map indexmap_type;
|
||||
typedef typename domain_type::index_value_type indices_type;
|
||||
typedef const std::ptrdiff_t return_type;
|
||||
using indexmap_type=map ;
|
||||
using indices_type=typename domain_type::index_value_type ;
|
||||
using return_type=const std::ptrdiff_t ;
|
||||
iterator (): im(NULL), pos(0),atend(true) {}
|
||||
iterator (const map & P, bool atEnd=false, ull_t iteration_order=0):
|
||||
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;
|
||||
void increment(){ inc_ind_impl (std::integral_constant<int,Rank>()); }
|
||||
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
|
||||
if (atend) TRIQS_RUNTIME_ERROR << "Iterator in cuboid cannot be pushed after end !";
|
||||
#endif
|
||||
@ -198,18 +221,17 @@ namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
|
||||
|
||||
}; //------------- end class ---------------------
|
||||
|
||||
|
||||
|
||||
}//namespace cuboid
|
||||
|
||||
template<int R1, int R2, ull_t OptFlags1, ull_t OptFlags2, ull_t To1, ull_t To2>
|
||||
bool compatible_for_assignment (const cuboid::map<R1,OptFlags1,To1> & X1, const cuboid::map<R2,OptFlags2,To2> & X2) { return X1.lengths() == X2.lengths();}
|
||||
template <int R1, int R2, typename To1, typename To2>
|
||||
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>
|
||||
bool raw_copy_possible (const cuboid::map<R1,OptFlags1,To1> & X1,const cuboid::map<R2,OptFlags2,To2> & X2) {
|
||||
return ( (X1.memory_indices_layout() == X2.memory_indices_layout())
|
||||
template <int R1, int R2, typename To1, typename To2>
|
||||
bool raw_copy_possible(const cuboid::map<R1, To1>& X1, const cuboid::map<R2, To2>& X2) {
|
||||
return ( (X1.get_memory_layout() == X2.get_memory_layout())
|
||||
&& X1.is_contiguous() && X2.is_contiguous()
|
||||
&& (X1.domain().number_of_elements()==X2.domain().number_of_elements()));
|
||||
}
|
||||
}}}//namespace triqs::arrays::indexmaps
|
||||
#endif
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAYS_INDEXMAP_MEMORY_LAYOUT_H
|
||||
#define TRIQS_ARRAYS_INDEXMAP_MEMORY_LAYOUT_H
|
||||
#include "../permutation.hpp"
|
||||
#include "../../impl/flags.hpp"
|
||||
#pragma once
|
||||
namespace triqs {
|
||||
namespace arrays {
|
||||
|
||||
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 {
|
||||
/* The storage order is given by a permutation P stored in a ull_t (unsigned long long) as in permutations::..
|
||||
* P[0] : the fastest index,
|
||||
* P[RANK-1] : the slowest index
|
||||
* 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)
|
||||
*/
|
||||
enum class memory_order_type {
|
||||
C,
|
||||
Fortran,
|
||||
Custom
|
||||
};
|
||||
|
||||
constexpr int memory_rank_to_index(ull_t p, int r) { return permutations::apply(p, r);}
|
||||
constexpr int index_to_memory_rank(ull_t p, int r) { return permutations::apply(permutations::inverse(p), r);}
|
||||
/* The storage order is given by a permutation P
|
||||
* 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));}
|
||||
constexpr bool is_c (ull_t p){ return p == permutations::ridentity(permutations::size(p));}
|
||||
memory_order_type order = memory_order_type::C;
|
||||
mini_vector<int, Rank> p = utility::no_init_tag{};
|
||||
|
||||
constexpr ull_t fortran_order (int n){ return permutations::identity(n);}
|
||||
constexpr ull_t c_order (int n){ return permutations::ridentity(n);}
|
||||
public:
|
||||
static const int rank = Rank;
|
||||
|
||||
template<int n> struct fortran_order_tr { static constexpr ull_t value = permutations::identity(n);};
|
||||
template<int n> struct c_order_tr { static constexpr ull_t value = permutations::ridentity(n);};
|
||||
|
||||
// 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...)))};
|
||||
explicit memory_layout() {
|
||||
for (int u = 0; u < Rank; ++u) p[u] = u;
|
||||
}
|
||||
}}//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
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_SLICE_H
|
||||
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_SLICE_H
|
||||
#pragma once
|
||||
#include <triqs/utility/count_type_occurrence.hpp>
|
||||
#include "./slice_traversal_order.hpp"
|
||||
namespace triqs { namespace arrays { namespace indexmaps {
|
||||
namespace cuboid_details {
|
||||
#define LISILOSO l_type const * li, s_type const * si, l_type * lo, s_type * so
|
||||
typedef size_t l_type;
|
||||
typedef std::ptrdiff_t s_type;
|
||||
namespace triqs {
|
||||
namespace arrays {
|
||||
namespace indexmaps {
|
||||
namespace cuboid_details {
|
||||
#define LISILOSO l_type const* li, s_type const* si, l_type* lo, s_type* so, int* imap
|
||||
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) { }
|
||||
template <> inline void _check_BC<true> (int N, int ind, size_t B, int ind_min) {
|
||||
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";
|
||||
}
|
||||
inline void _check_BC(int N, int ind, size_t B, int ind_min = 0) {
|
||||
#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";
|
||||
#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>
|
||||
static void one_step(LISILOSO, std::ptrdiff_t& offset, size_t R){
|
||||
_check_BC <BoundCheck> (N, R, li[N]);
|
||||
offset += R*si[N];
|
||||
template <int N, int P> static void one_step(LISILOSO, std::ptrdiff_t& offset, size_t R) {
|
||||
_check_BC(N, R, li[N]);
|
||||
offset += R * si[N];
|
||||
imap[N] = -1;
|
||||
}
|
||||
|
||||
template<int N, int P, bool BoundCheck>
|
||||
static void one_step(LISILOSO, std::ptrdiff_t& offset, range R){
|
||||
_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
|
||||
_check_BC<BoundCheck> (N, R.first() + (lo[P]!=0 ? (lo[P]-1) : 0)*R.step() ,li[N], -1);
|
||||
so[P] = si[N] * R.step();
|
||||
template <int N, int P> static void one_step(LISILOSO, std::ptrdiff_t& offset, range R) {
|
||||
_check_BC(N, R.first(), li[N]);
|
||||
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);
|
||||
so[P] = si[N] * R.step();
|
||||
offset += R.first() * si[N];
|
||||
imap[N] = P;
|
||||
}
|
||||
|
||||
template<int N, int P, bool BoundCheck, int EllipsisLength, typename Arg0, typename... Args>
|
||||
static typename std::enable_if<((EllipsisLength==1) || (!std::is_base_of<ellipsis, Arg0 >::type::value)), void>::type
|
||||
invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) {
|
||||
constexpr bool dP = (std::is_base_of<range,Arg0>::type::value ? 1 : 0); // Arg0 is range or ellipsis
|
||||
one_step<N,P,BoundCheck>(li,si,lo,so,offset, arg0);
|
||||
invoke<N+1,P+dP,BoundCheck,EllipsisLength>(li,si,lo,so, offset, args...);
|
||||
// ellipsis is a total range, we can simplify the computation in that case...
|
||||
template <int N, int P> static void one_step(LISILOSO, std::ptrdiff_t& offset, ellipsis) {
|
||||
_check_BC(N, 0, li[N]);
|
||||
lo[P] = li[N];
|
||||
_check_BC(N, (lo[P] != 0 ? (lo[P] - 1) : 0), li[N], -1);
|
||||
so[P] = si[N];
|
||||
imap[N] = P;
|
||||
}
|
||||
|
||||
template<int N, int P, bool BoundCheck, int EllipsisLength, typename Arg0, typename... Args>
|
||||
static typename std::enable_if<((EllipsisLength==0) && std::is_base_of<ellipsis, Arg0 >::type::value), void>::type
|
||||
invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) {
|
||||
invoke<N,P,BoundCheck,EllipsisLength>(li,si,lo,so, offset, args...);
|
||||
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) {
|
||||
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>
|
||||
static typename std::enable_if<((EllipsisLength>1) && std::is_base_of<ellipsis, Arg0 >::type::value), void>::type
|
||||
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
|
||||
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, int EllipsisLength, typename Arg0, typename... Args>
|
||||
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<N, P, EllipsisLength>(li, si, lo, so, imap, offset, 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
|
||||
}//namespace cuboid_details
|
||||
} // namespace cuboid_details
|
||||
|
||||
// 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; };
|
||||
|
||||
// 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 ?
|
||||
// special case of no argument :
|
||||
template <int R,typename To> struct slicer<cuboid::map<R, To>> {
|
||||
using r_type = cuboid::map<R, To>;
|
||||
};
|
||||
};
|
||||
}}}//namespaces triqs::arrays::indexmaps
|
||||
#endif
|
||||
|
||||
// general case
|
||||
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
|
||||
|
@ -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
|
@ -175,7 +175,7 @@ namespace arrays {
|
||||
ENABLE_IF(is_matrix_or_view<typename std::remove_reference<A>::type>)
|
||||
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");
|
||||
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)));
|
||||
if (!M_eq_inverse_M) {
|
||||
lhs = rhs();
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAYS_MATRIX_H
|
||||
#define TRIQS_ARRAYS_MATRIX_H
|
||||
#pragma once
|
||||
#include "indexmaps/cuboid/map.hpp"
|
||||
#include "indexmaps/cuboid/slice.hpp"
|
||||
#include "impl/indexmap_storage_pair.hpp"
|
||||
#include "impl/assignment.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, ull_t Opt=0, ull_t TraversalOrder= 0> class matrix;
|
||||
template <typename ValueType, typename TraversalOrder = void, bool Borrowed = false, bool IsConst = false> class matrix_view;
|
||||
template <typename ValueType, typename TraversalOrder = void> class matrix;
|
||||
|
||||
// ---------------------- matrix --------------------------------
|
||||
//
|
||||
#define _IMPL_MATRIX_COMMON \
|
||||
bool is_square() const { return this->shape()[0] == this->shape()[1];}\
|
||||
\
|
||||
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::strides_type s; 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]; } \
|
||||
// ---------------------- matrix --------------------------------
|
||||
//
|
||||
#define _IMPL_MATRIX_COMMON \
|
||||
bool is_square() const { return this->shape()[0] == this->shape()[1]; } \
|
||||
\
|
||||
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::strides_type s; \
|
||||
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]; }
|
||||
|
||||
#define IMPL_TYPE indexmap_storage_pair < indexmaps::cuboid::map<2,Opt,TraversalOrder>, \
|
||||
storages::shared_block<ValueType,Borrowed>, Opt, TraversalOrder, IsConst, true, Tag::matrix_view >
|
||||
#define IMPL_TYPE \
|
||||
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>
|
||||
class matrix_view : Tag::matrix_view, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE {
|
||||
public :
|
||||
typedef matrix <ValueType,Opt,TraversalOrder> regular_type;
|
||||
typedef matrix_view<ValueType,Opt,TraversalOrder> view_type;
|
||||
typedef matrix_view<ValueType, Opt, TraversalOrder, false, true> const_view_type;
|
||||
typedef matrix_view<ValueType,Opt,TraversalOrder,true> weak_view_type;
|
||||
template <typename ValueType, typename TraversalOrder, bool Borrowed, bool IsConst>
|
||||
class matrix_view : Tag::matrix_view, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE {
|
||||
public:
|
||||
using regular_type = matrix<ValueType, TraversalOrder>;
|
||||
using view_type = matrix_view<ValueType, TraversalOrder>;
|
||||
using const_view_type = matrix_view<ValueType, TraversalOrder, false, true>;
|
||||
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;
|
||||
typedef typename IMPL_TYPE::storage_type storage_type;
|
||||
/// Build from an IndexMap and a storage
|
||||
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
|
||||
template<typename S> matrix_view (typename IMPL_TYPE::indexmap_type const & Ind,S const & Mem): IMPL_TYPE(Ind, Mem) {}
|
||||
|
||||
/// 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()) {}
|
||||
/// 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
|
||||
/// Build from a numpy.array : throws if X is not a numpy.array
|
||||
explicit matrix_view (PyObject * X): IMPL_TYPE(X, false, "matrix_view "){}
|
||||
/// Build from a numpy.array : throws if X is not a numpy.array
|
||||
explicit matrix_view(PyObject* X) : IMPL_TYPE(X, false, "matrix_view ") {}
|
||||
#endif
|
||||
|
||||
/// Copy construction
|
||||
matrix_view( matrix_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {}
|
||||
/// Copy construction
|
||||
matrix_view(matrix_view const& X) : IMPL_TYPE(X.indexmap(), X.storage()) {}
|
||||
|
||||
matrix_view () = delete;
|
||||
matrix_view() = delete;
|
||||
|
||||
// Move
|
||||
matrix_view(matrix_view && X) { this->swap_me(X); }
|
||||
// Move
|
||||
matrix_view(matrix_view&& X) { this->swap_me(X); }
|
||||
|
||||
/// Swap
|
||||
friend void swap( matrix_view & A, matrix_view & B) { A.swap_me(B);}
|
||||
/// Swap
|
||||
friend void swap(matrix_view& A, matrix_view& B) { A.swap_me(B); }
|
||||
|
||||
/// Rebind the view
|
||||
void rebind(matrix_view const& X) {
|
||||
this->indexmap_ = X.indexmap_;
|
||||
this->storage_ = X.storage_;
|
||||
}
|
||||
/// Rebind the view
|
||||
void rebind(matrix_view const& X) {
|
||||
this->indexmap_ = X.indexmap_;
|
||||
this->storage_ = X.storage_;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
this->indexmap_ = X.indexmap_;
|
||||
this->storage_ = X.storage_;
|
||||
}
|
||||
// rebind the other view, iif this is const, and the other is not.
|
||||
template <typename To2, bool C = IsConst> ENABLE_IFC(C) rebind(matrix_view<ValueType, To2, Borrowed, !IsConst> const& X) {
|
||||
this->indexmap_ = X.indexmap_;
|
||||
this->storage_ = X.storage_;
|
||||
}
|
||||
|
||||
/** 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; }
|
||||
/** 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;
|
||||
}
|
||||
|
||||
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);
|
||||
_IMPL_MATRIX_COMMON;
|
||||
};
|
||||
TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view);
|
||||
_IMPL_MATRIX_COMMON;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// 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>
|
||||
struct ISPViewType< V, R, OptionFlags, To, Tag::matrix_view, Borrowed,IsConst> {
|
||||
typedef typename std::conditional<R == 1, vector_view<V, OptionFlags, Borrowed, IsConst>,
|
||||
matrix_view<V, OptionFlags, To, Borrowed, IsConst>>::type type;
|
||||
};
|
||||
template <class V, int R, typename TraversalOrder, bool Borrowed, bool IsConst>
|
||||
struct ISPViewType<V, R, TraversalOrder, Tag::matrix_view, Borrowed, IsConst> : std::conditional<R == 1, vector_view<V, Borrowed, IsConst>,
|
||||
matrix_view<V, TraversalOrder, Borrowed, IsConst>> {};
|
||||
#undef IMPL_TYPE
|
||||
|
||||
template <typename ValueType, ull_t Opt = 0, ull_t TraversalOrder = 0, bool Borrowed = false>
|
||||
using matrix_const_view = matrix_view<ValueType, Opt, TraversalOrder, Borrowed, true>;
|
||||
template <typename ValueType, typename TraversalOrder = void, bool Borrowed = false>
|
||||
using matrix_const_view = matrix_view<ValueType, TraversalOrder, Borrowed, true>;
|
||||
|
||||
// ---------------------- matrix --------------------------------
|
||||
#define IMPL_TYPE indexmap_storage_pair < indexmaps::cuboid::map<2,Opt,TraversalOrder>, \
|
||||
storages::shared_block<ValueType>, Opt, TraversalOrder, false, false, Tag::matrix_view >
|
||||
// ---------------------- matrix --------------------------------
|
||||
#define IMPL_TYPE \
|
||||
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 >
|
||||
class matrix: Tag::matrix, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE {
|
||||
public :
|
||||
typedef typename IMPL_TYPE::value_type value_type;
|
||||
typedef typename IMPL_TYPE::storage_type storage_type;
|
||||
typedef typename IMPL_TYPE::indexmap_type indexmap_type;
|
||||
typedef matrix <ValueType,Opt,TraversalOrder> regular_type;
|
||||
typedef matrix_view<ValueType,Opt,TraversalOrder> view_type;
|
||||
typedef matrix_view<ValueType, Opt, TraversalOrder, false, true> const_view_type;
|
||||
typedef matrix_view<ValueType,Opt,TraversalOrder,true> weak_view_type;
|
||||
template <typename ValueType, typename TraversalOrder>
|
||||
class matrix : Tag::matrix, TRIQS_CONCEPT_TAG_NAME(MutableMatrix), public IMPL_TYPE {
|
||||
public:
|
||||
using value_type = typename IMPL_TYPE::value_type;
|
||||
using storage_type = typename IMPL_TYPE::storage_type;
|
||||
using indexmap_type = typename IMPL_TYPE::indexmap_type;
|
||||
using regular_type = matrix<ValueType, TraversalOrder>;
|
||||
using view_type = matrix_view<ValueType, TraversalOrder>;
|
||||
using const_view_type = matrix_view<ValueType, TraversalOrder, false, true>;
|
||||
using weak_view_type = matrix_view<ValueType, TraversalOrder, true>;
|
||||
|
||||
/// Empty matrix.
|
||||
matrix(memory_layout<2> ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order) ): IMPL_TYPE(indexmap_type(ml)) {}
|
||||
/// Empty matrix.
|
||||
matrix(memory_layout<2> ml = memory_layout<2>{}) : IMPL_TYPE(indexmap_type(ml)) {}
|
||||
|
||||
/// Move
|
||||
explicit matrix(matrix && X) { this->swap_me(X); }
|
||||
/// Move
|
||||
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) ) :
|
||||
IMPL_TYPE(indexmap_type(mini_vector<size_t,2>(dim1,dim2),ml)) {}
|
||||
///
|
||||
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)) {}
|
||||
|
||||
///
|
||||
matrix(mini_vector<size_t,2> const & sha, memory_layout<2> ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order)) :
|
||||
IMPL_TYPE(indexmap_type(sha,ml)) {}
|
||||
///
|
||||
matrix(mini_vector<size_t, 2> const& sha, memory_layout<2> ml = memory_layout<2>{}) : IMPL_TYPE(indexmap_type(sha, ml)) {}
|
||||
|
||||
/** Makes a true (deep) copy of the data. */
|
||||
matrix(const matrix & X): IMPL_TYPE(X.indexmap(),X.storage().clone()) {}
|
||||
/** Makes a true (deep) copy of the data. */
|
||||
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 :
|
||||
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)):
|
||||
IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); }
|
||||
/// Build a new matrix from X.domain() and fill it with by evaluating X. X can be :
|
||||
template <typename T>
|
||||
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);
|
||||
}
|
||||
|
||||
#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.
|
||||
explicit matrix (PyObject * X): IMPL_TYPE(X, true, "matrix "){}
|
||||
/// 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 ") {}
|
||||
#endif
|
||||
|
||||
// build from a init_list
|
||||
template<typename T>
|
||||
matrix (std::initializer_list<std::initializer_list<T>> const & l):
|
||||
IMPL_TYPE(memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order)) {
|
||||
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 !";}
|
||||
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;
|
||||
}
|
||||
}
|
||||
// build from a init_list
|
||||
template <typename T> matrix(std::initializer_list<std::initializer_list<T>> const& l) : IMPL_TYPE(memory_layout<2>()) {
|
||||
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 !";
|
||||
}
|
||||
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.
|
||||
* 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;}
|
||||
/**
|
||||
* Resizes the matrix. NB : all references to the storage is invalidated.
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the matrix. NB : all references to the storage is invalidated.
|
||||
* Does not initialize the matrix by default
|
||||
*/
|
||||
matrix & resize (const indexmaps::cuboid::domain_t<IMPL_TYPE::rank> & l) { IMPL_TYPE::resize(l); return *this; }
|
||||
/**
|
||||
* Resizes the matrix. NB : all references to the storage is invalidated.
|
||||
* Does not initialize the matrix by default
|
||||
*/
|
||||
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.
|
||||
matrix & operator=(const matrix & X) { IMPL_TYPE::resize_and_clone_data(X); return *this; }
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// Move assignment
|
||||
matrix & operator=(matrix && X) { this->swap_me(X); return *this;}
|
||||
/// Move assignment
|
||||
matrix& operator=(matrix&& X) {
|
||||
this->swap_me(X);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Swap
|
||||
friend void swap( matrix & A, matrix & B) { A.swap_me(B);}
|
||||
/// Swap
|
||||
friend void swap(matrix& A, matrix& B) { A.swap_me(B); }
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
template<typename RHS>
|
||||
matrix & operator=(const RHS & X) {
|
||||
static_assert( ImmutableCuboidArray<RHS>::value, "Assignment : RHS not supported");
|
||||
IMPL_TYPE::resize(X.domain());
|
||||
triqs_arrays_assign_delegation(*this,X);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
template <typename RHS> matrix& operator=(const RHS& X) {
|
||||
static_assert(ImmutableCuboidArray<RHS>::value, "Assignment : RHS not supported");
|
||||
IMPL_TYPE::resize(X.domain());
|
||||
triqs_arrays_assign_delegation(*this, X);
|
||||
return *this;
|
||||
}
|
||||
|
||||
TRIQS_DEFINE_COMPOUND_OPERATORS(matrix);
|
||||
_IMPL_MATRIX_COMMON;
|
||||
};//matrix class
|
||||
TRIQS_DEFINE_COMPOUND_OPERATORS(matrix);
|
||||
_IMPL_MATRIX_COMMON;
|
||||
}; // matrix class
|
||||
#undef _IMPL_MATRIX_COMMON
|
||||
#undef IMPL_TYPE
|
||||
|
||||
|
||||
template<typename V>
|
||||
matrix <V> make_unit_matrix(int dim) {
|
||||
template <typename V> matrix<V> make_unit_matrix(int dim) {
|
||||
matrix<V> r(dim, dim);
|
||||
r() = 1;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
matrix_view<typename ArrayType::value_type, ArrayType::opt_flags, ArrayType::traversal_order, true>
|
||||
make_matrix_view(ArrayType const & a) {
|
||||
static_assert(ArrayType::rank ==2, "make_matrix_view only works for array of rank 2");
|
||||
return a;
|
||||
}
|
||||
template <typename ArrayType>
|
||||
matrix_view<typename ArrayType::value_type, typename ArrayType::traversal_order_t, true> make_matrix_view(ArrayType const& a) {
|
||||
static_assert(ArrayType::rank == 2, "make_matrix_view only works for array of rank 2");
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
matrix<typename ArrayType::value_type>
|
||||
make_matrix(ArrayType const & a) {
|
||||
static_assert(ArrayType::domain_type::rank ==2, "make_matrix only works for array of rank 2");
|
||||
return a;
|
||||
}
|
||||
template <typename ArrayType> matrix<typename ArrayType::value_type> make_matrix(ArrayType const& a) {
|
||||
static_assert(ArrayType::domain_type::rank == 2, "make_matrix only works for array of rank 2");
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
TYPE_ENABLE_IF(typename M::value_type, ImmutableMatrix<M>) trace(M const &m) {
|
||||
auto r = typename M::value_type{};
|
||||
if (first_dim(m) != second_dim(m))
|
||||
TRIQS_RUNTIME_ERROR << " Trace of a non square matrix";
|
||||
auto d = first_dim(m);
|
||||
for (int i = 0; i < d; ++i)
|
||||
r += m(i, i);
|
||||
return r;
|
||||
}
|
||||
}}//namespace triqs::arrays
|
||||
template <typename M> TYPE_ENABLE_IF(typename M::value_type, ImmutableMatrix<M>) trace(M const& m) {
|
||||
auto r = typename M::value_type{};
|
||||
if (first_dim(m) != second_dim(m)) TRIQS_RUNTIME_ERROR << " Trace of a non square matrix";
|
||||
auto d = first_dim(m);
|
||||
for (int i = 0; i < d; ++i) r += m(i, i);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
} // namespace triqs::arrays
|
||||
|
||||
// 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).
|
||||
namespace std {
|
||||
template <typename V, triqs::ull_t Opt, triqs::ull_t To, 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;
|
||||
template <typename V, typename To1, typename To2, bool B1, bool B2, bool C1, bool C2>
|
||||
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"
|
||||
#endif
|
||||
|
||||
|
@ -44,6 +44,7 @@ namespace arrays {
|
||||
long n;
|
||||
|
||||
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 typename slicer_t::r_type indexmap_type;
|
||||
typedef typename indexmap_type::domain_type domain_type;
|
||||
@ -98,6 +99,7 @@ namespace arrays {
|
||||
long n;
|
||||
|
||||
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 typename slicer_t::r_type indexmap_type;
|
||||
typedef typename indexmap_type::domain_type domain_type;
|
||||
|
@ -20,7 +20,6 @@
|
||||
******************************************************************************/
|
||||
#include "../impl/common.hpp"
|
||||
#include "../impl/traits.hpp"
|
||||
#include "../impl/flags.hpp"
|
||||
#include "../../utility/mini_vector.hpp"
|
||||
#include "./numpy_extractor.hpp"
|
||||
#ifdef TRIQS_WITH_PYTHON_SUPPORT
|
||||
|
@ -49,12 +49,12 @@ namespace triqs { namespace arrays { namespace storages {
|
||||
static constexpr bool is_weak = Weak;
|
||||
|
||||
/// 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.
|
||||
construct_delegate(size);
|
||||
const auto s = this->size(); for (size_t u=0; u<s; ++u) data_[u] = ValueType();
|
||||
}
|
||||
//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);
|
||||
// const auto s = this->size(); for (size_t u=0; u<s; ++u) data_[u] = ValueType();
|
||||
// }
|
||||
|
||||
#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(); }
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAY_VECTOR_H
|
||||
#define TRIQS_ARRAY_VECTOR_H
|
||||
#pragma once
|
||||
#include "indexmaps/cuboid/map.hpp"
|
||||
#include "indexmaps/cuboid/slice.hpp"
|
||||
#include "impl/indexmap_storage_pair.hpp"
|
||||
#include "impl/assignment.hpp"
|
||||
#include "impl/flags.hpp"
|
||||
#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, ull_t Opt=0> class vector;
|
||||
template <typename ValueType, bool Borrowed = false, bool IsConst = false> class vector_view;
|
||||
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>
|
||||
class vector_view : Tag::vector_view, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE {
|
||||
public :
|
||||
typedef vector <ValueType,Opt> regular_type;
|
||||
typedef vector_view<ValueType,Opt,false> view_type;
|
||||
typedef vector_view<ValueType, Opt, false, true> const_view_type;
|
||||
typedef vector_view<ValueType,Opt,true> weak_view_type;
|
||||
template <typename ValueType, bool Borrowed, bool IsConst>
|
||||
class vector_view : Tag::vector_view, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE {
|
||||
public:
|
||||
using regular_type = vector<ValueType>;
|
||||
using view_type = vector_view<ValueType, false>;
|
||||
using const_view_type = vector_view<ValueType, false, true>;
|
||||
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;
|
||||
typedef typename IMPL_TYPE::storage_type storage_type;
|
||||
/// Build from an IndexMap and a storage
|
||||
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
|
||||
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) {}
|
||||
|
||||
/// 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()) {}
|
||||
/// 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
|
||||
/// Build from a numpy.array : throws if X is not a numpy.array
|
||||
explicit vector_view (PyObject * X): IMPL_TYPE(X, false, "vector_view "){}
|
||||
/// Build from a numpy.array : throws if X is not a numpy.array
|
||||
explicit vector_view(PyObject* X) : IMPL_TYPE(X, false, "vector_view ") {}
|
||||
#endif
|
||||
|
||||
/// Copy construction
|
||||
vector_view(vector_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {}
|
||||
/// Copy construction
|
||||
vector_view(vector_view const& X) : IMPL_TYPE(X.indexmap(), X.storage()) {}
|
||||
|
||||
vector_view () = delete;
|
||||
vector_view() = delete;
|
||||
|
||||
// Move
|
||||
vector_view(vector_view && X) { this->swap_me(X);}
|
||||
// Move
|
||||
vector_view(vector_view&& X) { this->swap_me(X); }
|
||||
|
||||
/// Swap
|
||||
friend void swap( vector_view & A, vector_view & B) { A.swap_me(B);}
|
||||
/// Swap
|
||||
friend void swap(vector_view& A, vector_view& B) { A.swap_me(B); }
|
||||
|
||||
/// Rebind the view
|
||||
void rebind(vector_view const& X) {
|
||||
this->indexmap_ = X.indexmap_;
|
||||
this->storage_ = X.storage_;
|
||||
}
|
||||
/// Rebind the view
|
||||
void rebind(vector_view const& X) {
|
||||
this->indexmap_ = X.indexmap_;
|
||||
this->storage_ = X.storage_;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
this->indexmap_ = X.indexmap_;
|
||||
this->storage_ = X.storage_;
|
||||
}
|
||||
// rebind the other view, iif this is const, and the other is not.
|
||||
template <bool C = IsConst> ENABLE_IFC(C) rebind(vector_view<ValueType, Borrowed, !IsConst> const& X) {
|
||||
this->indexmap_ = X.indexmap_;
|
||||
this->storage_ = X.storage_;
|
||||
}
|
||||
|
||||
/** 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; }
|
||||
/** 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;
|
||||
}
|
||||
|
||||
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)));
|
||||
template<typename Arg> auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward<Arg>(arg)));
|
||||
};
|
||||
// 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)));
|
||||
};
|
||||
#undef IMPL_TYPE
|
||||
|
||||
template < class V, int R, ull_t OptionFlags, ull_t To, bool Borrowed, bool IsConst>
|
||||
struct ISPViewType< V, R,OptionFlags,To, Tag::vector_view, Borrowed, IsConst> { typedef vector_view<V,OptionFlags,Borrowed,IsConst> type; };
|
||||
template <class V, int R, bool Borrowed, bool IsConst>
|
||||
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>
|
||||
using vector_const_view = vector_view<ValueType, Opt, Borrowed, true>;
|
||||
template <typename ValueType, bool Borrowed = false> using vector_const_view = vector_view<ValueType, Borrowed, true>;
|
||||
|
||||
// ---------------------- vector--------------------------------
|
||||
#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<1,Opt,0> , storages::shared_block<ValueType>, Opt, 0, false, false,Tag::vector_view >
|
||||
// ---------------------- vector--------------------------------
|
||||
#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>
|
||||
class vector: Tag::vector, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE {
|
||||
public :
|
||||
typedef typename IMPL_TYPE::value_type value_type;
|
||||
typedef typename IMPL_TYPE::storage_type storage_type;
|
||||
typedef typename IMPL_TYPE::indexmap_type indexmap_type;
|
||||
typedef vector<ValueType, Opt> regular_type;
|
||||
typedef vector_view<ValueType, Opt> view_type;
|
||||
typedef vector_view<ValueType, Opt, false, true> const_view_type;
|
||||
typedef vector_view<ValueType, Opt, true> weak_view_type;
|
||||
template <typename ValueType> class vector : Tag::vector, TRIQS_CONCEPT_TAG_NAME(MutableVector), public IMPL_TYPE {
|
||||
public:
|
||||
using value_type = typename IMPL_TYPE::value_type;
|
||||
using storage_type = typename IMPL_TYPE::storage_type;
|
||||
using indexmap_type = typename IMPL_TYPE::indexmap_type;
|
||||
using regular_type = vector<ValueType>;
|
||||
using view_type = vector_view<ValueType>;
|
||||
using const_view_type = vector_view<ValueType, false, true>;
|
||||
using weak_view_type = vector_view<ValueType, true>;
|
||||
|
||||
/// Empty vector.
|
||||
vector(){}
|
||||
/// Empty vector.
|
||||
vector() {}
|
||||
|
||||
// Move
|
||||
explicit vector(vector && X) { this->swap_me(X); }
|
||||
// Move
|
||||
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
|
||||
template<typename Arg>
|
||||
vector(size_t dim, Arg && arg):IMPL_TYPE(indexmap_type(mini_vector<size_t,1>(dim))) { (*this)() = std::forward<Arg>(arg);}
|
||||
/// to mimic std vector
|
||||
template <typename Arg> vector(size_t dim, Arg&& arg) : IMPL_TYPE(indexmap_type(mini_vector<size_t, 1>(dim))) {
|
||||
(*this)() = std::forward<Arg>(arg);
|
||||
}
|
||||
|
||||
/** Makes a true (deep) copy of the data. */
|
||||
vector(const vector & X): IMPL_TYPE(X.indexmap(),X.storage().clone()) {}
|
||||
/** Makes a true (deep) copy of the data. */
|
||||
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 :
|
||||
* - another type of array, array_view, matrix,.... (any <IndexMap, Storage> pair)
|
||||
* - 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
|
||||
*/
|
||||
template <typename T>
|
||||
//vector(const T & X, typename boost::enable_if< ImmutableCuboidArray<T> >::type *dummy =0):
|
||||
vector(const T & X, TYPE_ENABLE_IF(memory_layout<1>, ImmutableCuboidArray<T>) ml = memory_layout<1>(IMPL_TYPE::indexmap_type::traversal_order)):
|
||||
IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); }
|
||||
/**
|
||||
* 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)
|
||||
* - 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
|
||||
*/
|
||||
template <typename T>
|
||||
// vector(const T & X, std14::enable_if_t< ImmutableCuboidArray<T> ::value> *dummy =0):
|
||||
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
|
||||
///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 "){}
|
||||
/// 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 ") {}
|
||||
#endif
|
||||
|
||||
// build from a init_list
|
||||
template<typename T>
|
||||
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))) {
|
||||
size_t i=0;
|
||||
for (auto const & x : l) (*this)(i++) = x;
|
||||
}
|
||||
// build from a init_list
|
||||
template <typename T>
|
||||
vector(std::initializer_list<T> const& l)
|
||||
: IMPL_TYPE(indexmap_type(mini_vector<size_t, 1>(l.size()), memory_layout<1>{})) {
|
||||
size_t i = 0;
|
||||
for (auto const& x : l) (*this)(i++) = x;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
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.
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
vector & resize (const indexmaps::cuboid::domain_t<IMPL_TYPE::rank> & l) { IMPL_TYPE::resize(l); return *this; }
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
* NB : to avoid that, do make_view(A) = X instead of A = X
|
||||
*/
|
||||
template<typename RHS>
|
||||
vector & operator=(const RHS & X) {
|
||||
static_assert( ImmutableCuboidArray<RHS>::value, "Assignment : RHS not supported");
|
||||
IMPL_TYPE::resize(X.domain());
|
||||
triqs_arrays_assign_delegation(*this,X);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
template <typename RHS> vector& operator=(const RHS& X) {
|
||||
static_assert(ImmutableCuboidArray<RHS>::value, "Assignment : RHS not supported");
|
||||
IMPL_TYPE::resize(X.domain());
|
||||
triqs_arrays_assign_delegation(*this, X);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Move assignment
|
||||
vector & operator=(vector && X) { this->swap_me(X); return *this;}
|
||||
/// Move assignment
|
||||
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]; }
|
||||
|
||||
///
|
||||
std::ptrdiff_t stride() const { return this->indexmap().strides()[0];}
|
||||
TRIQS_DEFINE_COMPOUND_OPERATORS(vector);
|
||||
|
||||
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 ()
|
||||
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)));
|
||||
|
||||
};//vector class
|
||||
}}//namespace triqs::arrays
|
||||
}; // vector class
|
||||
}
|
||||
} // namespace triqs::arrays
|
||||
|
||||
#undef IMPL_TYPE
|
||||
|
||||
@ -216,10 +233,11 @@ namespace triqs { namespace arrays {
|
||||
#include "./blas_lapack/copy.hpp"
|
||||
#include "./blas_lapack/swap.hpp"
|
||||
#include "./blas_lapack/axpy.hpp"
|
||||
namespace triqs { namespace arrays {
|
||||
namespace triqs {
|
||||
namespace arrays {
|
||||
|
||||
// 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();
|
||||
auto r = typename V::value_type{};
|
||||
for (int i = 0; i < dim; ++i) r += a(i) * a(i);
|
||||
@ -227,101 +245,109 @@ namespace triqs { namespace arrays {
|
||||
}
|
||||
|
||||
// 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;
|
||||
return sqrt(norm2(a));
|
||||
}
|
||||
|
||||
// lexicographical comparison operators
|
||||
template<typename V1, typename V2>
|
||||
typename std::enable_if< ImmutableVector<V1>::value && ImmutableVector<V2>::value , bool>::type
|
||||
operator < (V1 const & a, V2 const & b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());}
|
||||
template <typename V1, typename V2>
|
||||
std14::enable_if_t<ImmutableVector<V1>::value&& ImmutableVector<V2>::value, bool> operator<(V1 const& a, V2 const& b) {
|
||||
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
|
||||
}
|
||||
|
||||
template<typename V1, typename V2>
|
||||
typename std::enable_if< ImmutableVector<V1>::value && ImmutableVector<V2>::value , bool>::type
|
||||
operator > (V1 const & a, V2 const & b) { return (b<a); }
|
||||
template <typename V1, typename V2>
|
||||
std14::enable_if_t<ImmutableVector<V1>::value&& ImmutableVector<V2>::value, bool> operator>(V1 const& a, V2 const& b) {
|
||||
return (b < a);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_vector_or_view <RHS > >::type
|
||||
triqs_arrays_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs) { blas::copy(rhs,lhs); }
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_assign_delegation(vector<T>& lhs, RHS const& rhs) {
|
||||
blas::copy(rhs, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_vector_or_view <RHS > >::type
|
||||
triqs_arrays_compound_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs, char_<'A'>) {
|
||||
T a = 1.0; blas::axpy(a,rhs,lhs);
|
||||
}
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_compound_assign_delegation(vector<T>& lhs, RHS const& rhs,
|
||||
char_<'A'>) {
|
||||
T a = 1.0;
|
||||
blas::axpy(a, rhs, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_vector_or_view <RHS > >::type
|
||||
triqs_arrays_compound_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs, char_<'S'>) {
|
||||
T a = -1.0; blas::axpy(a,rhs,lhs);
|
||||
}
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_compound_assign_delegation(vector<T>& lhs, RHS const& rhs,
|
||||
char_<'S'>) {
|
||||
T a = -1.0;
|
||||
blas::axpy(a, rhs, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_scalar_for<RHS,vector<T,Opt> > >::type
|
||||
triqs_arrays_compound_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs, char_<'M'>) {
|
||||
T a = rhs; blas::scal(a,lhs);
|
||||
}
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_scalar_for<RHS, vector<T>>::value> triqs_arrays_compound_assign_delegation(vector<T>& lhs, RHS const& rhs,
|
||||
char_<'M'>) {
|
||||
T a = rhs;
|
||||
blas::scal(a, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_scalar_for<RHS,vector<T,Opt> > >::type
|
||||
triqs_arrays_compound_assign_delegation (vector<T,Opt> & lhs, RHS const & rhs, char_<'D'>) {
|
||||
T a = 1/rhs; blas::scal(a,lhs);
|
||||
}
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_scalar_for<RHS, vector<T>>::value> triqs_arrays_compound_assign_delegation(vector<T>& lhs, RHS const& rhs,
|
||||
char_<'D'>) {
|
||||
T a = 1 / rhs;
|
||||
blas::scal(a, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_vector_or_view <RHS > >::type
|
||||
triqs_arrays_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs) { blas::copy(rhs,lhs); }
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_assign_delegation(vector_view<T>& lhs, RHS const& rhs) {
|
||||
blas::copy(rhs, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_vector_or_view <RHS > >::type
|
||||
triqs_arrays_compound_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs, char_<'A'>) {
|
||||
T a = 1.0; blas::axpy(a,rhs,lhs);
|
||||
}
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_compound_assign_delegation(vector_view<T>& lhs, RHS const& rhs,
|
||||
char_<'A'>) {
|
||||
T a = 1.0;
|
||||
blas::axpy(a, rhs, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_vector_or_view <RHS > >::type
|
||||
triqs_arrays_compound_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs, char_<'S'>) {
|
||||
T a = -1.0; blas::axpy(a,rhs,lhs);
|
||||
}
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_vector_or_view<RHS>::value> triqs_arrays_compound_assign_delegation(vector_view<T>& lhs, RHS const& rhs,
|
||||
char_<'S'>) {
|
||||
T a = -1.0;
|
||||
blas::axpy(a, rhs, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_scalar_for<RHS,vector_view<T,Opt> > >::type
|
||||
triqs_arrays_compound_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs, char_<'M'>) {
|
||||
T a = rhs; blas::scal(a,lhs);
|
||||
}
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_scalar_for<RHS, vector_view<T>>::value>
|
||||
triqs_arrays_compound_assign_delegation(vector_view<T>& lhs, RHS const& rhs, char_<'M'>) {
|
||||
T a = rhs;
|
||||
blas::scal(a, lhs);
|
||||
}
|
||||
|
||||
template<typename RHS, typename T, ull_t Opt>
|
||||
typename boost::enable_if< is_scalar_for<RHS,vector_view<T,Opt> > >::type
|
||||
triqs_arrays_compound_assign_delegation (vector_view<T,Opt> & lhs, RHS const & rhs, char_<'D'>) {
|
||||
T a = 1/rhs; blas::scal(a,lhs);
|
||||
}
|
||||
template <typename RHS, typename T>
|
||||
std14::enable_if_t<is_scalar_for<RHS, vector_view<T>>::value>
|
||||
triqs_arrays_compound_assign_delegation(vector_view<T>& lhs, RHS const& rhs, char_<'D'>) {
|
||||
T a = 1 / rhs;
|
||||
blas::scal(a, lhs);
|
||||
}
|
||||
|
||||
template<typename T, ull_t Opt, bool Borrowed>
|
||||
void triqs_arrays_assign_delegation(vector_view<T,Opt,Borrowed> & av, std::vector<T> const& vec) {
|
||||
std::size_t size = vec.size();
|
||||
for(std::size_t n = 0; n < size; ++n) av(n) = vec[n];
|
||||
}
|
||||
template <typename T, bool Borrowed>
|
||||
void triqs_arrays_assign_delegation(vector_view<T, Borrowed>& av, std::vector<T> const& vec) {
|
||||
std::size_t size = vec.size();
|
||||
for (std::size_t n = 0; n < size; ++n) av(n) = vec[n];
|
||||
}
|
||||
|
||||
// swapping 2 vector
|
||||
template <typename V, ull_t S1, ull_t S2, bool B1, bool B2>
|
||||
void deep_swap(vector_view <V,S1,B1> x, vector_view<V,S2,B2> y) {
|
||||
blas::swap(x,y);
|
||||
}
|
||||
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) {
|
||||
blas::swap(x, y);
|
||||
}
|
||||
|
||||
template <typename V, ull_t S1, ull_t S2>
|
||||
void deep_swap(vector <V,S1> & x, vector<V,S2> & y) { blas::swap(x,y);}
|
||||
|
||||
}}
|
||||
template <typename V> void deep_swap(vector<V>& x, vector<V>& y) { blas::swap(x, y); }
|
||||
}
|
||||
}
|
||||
|
||||
// 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).
|
||||
namespace std {
|
||||
template <typename V, triqs::ull_t S, 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;
|
||||
template <typename V, bool B1, bool B2, bool C1, bool C2>
|
||||
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"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <triqs/arrays.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 {
|
||||
|
||||
@ -51,12 +51,12 @@ namespace triqs { namespace gfs {
|
||||
#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()));
|
||||
#else
|
||||
auto operator()(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()(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()(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_t& data, long i) const DECL_AND_RETURN(arrays::make_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()(typename B::storage_view_t& data, long i) const DECL_AND_RETURN(arrays::make_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()(typename 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 const& data, long i) const DECL_AND_RETURN(arrays::make_const_tensor_proxy(data, i));
|
||||
#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())));
|
||||
#else
|
||||
/// The data access
|
||||
auto operator()(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()(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()(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_t& data, long i) const DECL_AND_RETURN(arrays::make_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()(typename B::storage_view_t& data, long i) const DECL_AND_RETURN(arrays::make_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()(typename 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 const& data, long i) const DECL_AND_RETURN(arrays::make_const_matrix_proxy(data, i));
|
||||
#endif
|
||||
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* 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
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
@ -22,13 +22,14 @@
|
||||
#define TRIQS_ARRAYS_MINI_VECTOR_H
|
||||
#include "./first_include.hpp"
|
||||
#include <iostream>
|
||||
#include "./macros.hpp"
|
||||
#include "./c14.hpp"
|
||||
#include "./compiler_details.hpp"
|
||||
#include "./exceptions.hpp"
|
||||
#include <boost/serialization/utility.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <vector>
|
||||
#include <triqs/utility/tuple_tools.hpp>
|
||||
|
||||
#define TRIQS_MINI_VECTOR_NRANK_MAX 10
|
||||
|
||||
@ -36,6 +37,8 @@
|
||||
//#define TRIQS_MAKE_NVP(NAME,X) boost::serialization::make_nvp(NAME,X)
|
||||
namespace triqs { namespace utility {
|
||||
|
||||
struct no_init_tag{};
|
||||
|
||||
template <typename T, int Rank>
|
||||
class mini_vector {
|
||||
T _data[(Rank!=0 ? Rank : 1)];
|
||||
@ -48,14 +51,104 @@ namespace triqs { namespace utility {
|
||||
|
||||
mini_vector(){init();}
|
||||
|
||||
#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(no_init_tag){}
|
||||
|
||||
mini_vector(T x_0) {
|
||||
static_assert(Rank == 1, "mini_vector : incorrect number of variables in constructor");
|
||||
_data[0] = x_0;
|
||||
}
|
||||
mini_vector(T x_0, T x_1) {
|
||||
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(mini_vector && x){ *this = std::move(x); }
|
||||
@ -78,6 +171,11 @@ namespace triqs { namespace utility {
|
||||
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=(T x) {
|
||||
for (int i = 0; i < Rank; ++i) _data[i] = x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T & operator[](size_t i) { 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> {
|
||||
T _data[1];
|
||||
public:
|
||||
mini_vector(){}
|
||||
mini_vector(no_init_tag){}
|
||||
|
||||
T & operator[](size_t i) { 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 --------------------------------------
|
||||
|
||||
@ -161,13 +265,13 @@ namespace triqs { namespace utility {
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef TRIQS_C11
|
||||
// ------------- 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) {
|
||||
return tuple::apply_construct_parenthesis<mini_vector<T, std::tuple_size<TU>::value>>(t);
|
||||
}
|
||||
#endif
|
||||
//#ifndef TRIQS_C11
|
||||
// // ------------- 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) {
|
||||
// return tuple::apply_construct_parenthesis<mini_vector<T, std::tuple_size<TU>::value>>(t);
|
||||
// }
|
||||
//#endif
|
||||
|
||||
}}//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> 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
|
||||
|
@ -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>{};
|
||||
|
||||
// overload for views rvalues (created on the fly)
|
||||
template <typename V, int R, ull_t Opt, ull_t To, bool W>
|
||||
void reduce_in_place( communicator _c, arrays::array_view<V,R,Opt,To, W> && a, int root =0) { reduce_in_place(_c,a,root);}
|
||||
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) {
|
||||
reduce_in_place(_c, a, root);
|
||||
}
|
||||
|
||||
template <typename A, typename V, int R, ull_t Opt, ull_t 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);}
|
||||
template <typename A, typename V, int R, typename To, bool W>
|
||||
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
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "./c14.hpp"
|
||||
#include <tuple>
|
||||
#include <ostream>
|
||||
#include "./mini_vector.hpp"
|
||||
|
||||
// adding to the std lib the reversed lazy tuple...
|
||||
// overloading & specializing only the functions needed here.
|
||||
|
Loading…
Reference in New Issue
Block a user