mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 13:53:40 +01:00
arrays : add ConstView to fix const correctness
- A()(0) = 1 will not work any more if A is const, as it should be. - Introduced the notion of const_view, simply done by a flag (flag 0, for easy debug) - changed the slice of ISP to use it (only on C++11 compliant compiler) - Move BoundCheck Flags to 5.
This commit is contained in:
parent
fc2a620eae
commit
552c440238
41
test/triqs/arrays/const_view.cpp
Normal file
41
test/triqs/arrays/const_view.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* 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 "./common.hpp"
|
||||||
|
#include "./src/array.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace triqs::arrays;
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
const array<long,1> A = {1,2,3,4};
|
||||||
|
|
||||||
|
std::cerr << A.opt_flags<<std::endl;
|
||||||
|
std::cerr << A().opt_flags<<std::endl;
|
||||||
|
|
||||||
|
// None of this should compile
|
||||||
|
//A(0) = 2;
|
||||||
|
//A()(0) = 2;
|
||||||
|
//A(range(0,2))(0) = 10;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
78
test/triqs/arrays/temp_slice.cpp
Normal file
78
test/triqs/arrays/temp_slice.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* 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 "./common.hpp"
|
||||||
|
#include "./src/array.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace triqs::arrays;
|
||||||
|
|
||||||
|
auto bad (array<long,1> const & a) DECL_AND_RETURN (a(range(0,3)));
|
||||||
|
|
||||||
|
auto bad2 (array<long,1> const & a) DECL_AND_RETURN (a(0));
|
||||||
|
|
||||||
|
array_view<long,1> good(array<long,1> const & a) {return a(range(0,3));}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
array<long,1> A = {1,2,3,4};
|
||||||
|
|
||||||
|
std::cerr<<"A is "<<A<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto r = A(range(0,3));
|
||||||
|
TEST_ASSERT(r.storage().is_weak);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto r = array<long,1> {1,2,3,4} (range(0,3));
|
||||||
|
TEST_ASSERT(!r.storage().is_weak);
|
||||||
|
std::cerr << r << r.storage().is_weak << std::endl ;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto r = array<long,1> {1,2,3,4} (range(0,3))();
|
||||||
|
std::cerr << r << r.storage().is_weak << std::endl ;
|
||||||
|
TEST_ASSERT(!r.storage().is_weak);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto r = good ( { 1,2,3,4} );
|
||||||
|
std::cerr << " good "<< r << r.storage().is_weak << std::endl ;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto & r = bad2 ( { 1,2,3,4} );
|
||||||
|
std::cerr << " bad2 " << r << std::endl ;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto r = bad ( { 1,2,3,4} );
|
||||||
|
std::cerr << " bad " << r << r.storage().is_weak << std::endl ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (std::exception & e) { std::cout << e.what()<<std::endl;}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -55,13 +55,14 @@ namespace boost { namespace serialization { class access;}}
|
|||||||
|
|
||||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||||
#define TRIQS_ARRAYS_CHECK_IM_STORAGE_COMPAT
|
#define TRIQS_ARRAYS_CHECK_IM_STORAGE_COMPAT
|
||||||
|
#define TRIQS_ARRAYS_CHECK_WEAK_REFS
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define TRIQS_ARRAYS_DEBUG_CHECK(Cond,Error)
|
#define TRIQS_ARRAYS_DEBUG_CHECK(Cond,Error)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// In particular, gcc 4.6, 4.7 do not have "rvalue for *this", which forbid the implementation
|
// In particular, gcc 4.6, 4.7 do not have "rvalue for *this", which forbid the implementation
|
||||||
// of weak references. In that we, we will revert to strong view instead.
|
// of weak references. In that case, we will revert to strong view instead.
|
||||||
#ifdef TRIQS_COMPILER_IS_OBSOLETE
|
#ifdef TRIQS_COMPILER_IS_OBSOLETE
|
||||||
#define TRIQS_ARRAYS_SLICE_DEFAUT_IS_SHARED
|
#define TRIQS_ARRAYS_SLICE_DEFAUT_IS_SHARED
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,18 +27,18 @@ namespace triqs { namespace arrays {
|
|||||||
|
|
||||||
// Flags is a 64 bit unsigned int.
|
// Flags is a 64 bit unsigned int.
|
||||||
// 0 is the default option.
|
// 0 is the default option.
|
||||||
// Meaning of the bits :
|
// Meaning of the bits :
|
||||||
// 0 -> Boundcheck
|
// 0 -> Const
|
||||||
// 1,2 -> Predefined order :
|
// 1,2 -> Predefined order :
|
||||||
// 0 : None, 1 : C, 2 : Fortran
|
// 0 : None, 1 : C, 2 : Fortran
|
||||||
// 3,4 -> Init
|
// 3 -> Init the array
|
||||||
// 0 : Noinit, 1 : NanInit, 2 : DefaultInit
|
// 5 -> Boundcheck
|
||||||
|
|
||||||
constexpr ull_t BoundCheck = 1ull << 0;
|
constexpr ull_t ConstView = 1ull << 0;
|
||||||
constexpr ull_t TraversalOrderC = 1ull << 1;
|
constexpr ull_t TraversalOrderC = 1ull << 1;
|
||||||
constexpr ull_t TraversalOrderFortran = 1ull << 2;
|
constexpr ull_t TraversalOrderFortran = 1ull << 2;
|
||||||
//constexpr ull_t NanInit = 1ull << 3;
|
constexpr ull_t DefaultInit = 1ull << 3;
|
||||||
constexpr ull_t DefaultInit = 1ull << 4;
|
constexpr ull_t BoundCheck = 1ull << 5;
|
||||||
|
|
||||||
#define BOUND_CHECK triqs::arrays::BoundCheck
|
#define BOUND_CHECK triqs::arrays::BoundCheck
|
||||||
#define TRAVERSAL_ORDER_C triqs::arrays::TraversalOrderC
|
#define TRAVERSAL_ORDER_C triqs::arrays::TraversalOrderC
|
||||||
@ -55,10 +55,12 @@ namespace triqs { namespace arrays {
|
|||||||
constexpr ull_t get(ull_t f, ull_t a) { return ((f & (1ull<<a)) >> a);}
|
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);}
|
constexpr ull_t get2(ull_t f, ull_t a) { return ((f & ((1ull<<a) + (1ull<< (a+1ull)))) >> a);}
|
||||||
|
|
||||||
|
constexpr bool is_const (ull_t f) { return get (f,0) !=0;}
|
||||||
|
|
||||||
#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||||
constexpr bool bound_check (ull_t f) { return true;}
|
constexpr bool bound_check (ull_t f) { return true;}
|
||||||
#else
|
#else
|
||||||
constexpr bool bound_check (ull_t f) { return get (f, 0)!=0;}
|
constexpr bool bound_check (ull_t f) { return get (f, 5)!=0;}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr bool traversal_order_c (ull_t f) { return get (f,1ull)!=0ull;}
|
constexpr bool traversal_order_c (ull_t f) { return get (f,1ull)!=0ull;}
|
||||||
@ -66,13 +68,11 @@ namespace triqs { namespace arrays {
|
|||||||
|
|
||||||
template< ull_t F> struct bound_check_trait { static constexpr bool value = bound_check(F); };
|
template< ull_t F> struct bound_check_trait { static constexpr bool value = bound_check(F); };
|
||||||
|
|
||||||
constexpr ull_t init_mode (ull_t f) { return get2 (f,3);}
|
constexpr ull_t init_mode (ull_t f) { return get (f,3);}
|
||||||
constexpr bool check_init_mode (ull_t f) { return get2 (f,3)!=3ull;}
|
|
||||||
|
|
||||||
template<ull_t F> struct init_tag1;
|
template<ull_t F> struct init_tag1;
|
||||||
template<> struct init_tag1<0> { typedef Tag::no_init type;};
|
template<> struct init_tag1<0> { typedef Tag::no_init type;};
|
||||||
//template<> struct init_tag1<1> { typedef Tag::nan_inf_init type;};
|
template<> struct init_tag1<1> { typedef Tag::default_init type;};
|
||||||
template<> struct init_tag1<2> { typedef Tag::default_init type;};
|
|
||||||
|
|
||||||
// for the init_tag, we pass the *whole* option flag.
|
// 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> struct init_tag : init_tag1 < init_mode(F)> {};
|
||||||
@ -81,21 +81,21 @@ namespace triqs { namespace arrays {
|
|||||||
static constexpr bool bc = bound_check(F);
|
static constexpr bool bc = bound_check(F);
|
||||||
static constexpr bool is_c = traversal_order_c(F);
|
static constexpr bool is_c = traversal_order_c(F);
|
||||||
static constexpr bool is_f = traversal_order_fortran(F);
|
static constexpr bool is_f = traversal_order_fortran(F);
|
||||||
static constexpr bool inm = check_init_mode(F);
|
|
||||||
static_assert ( (!( is_c && is_f)), "You asked C and Fortran traversal order at the same time...");
|
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 ...");
|
static_assert ( (!( (is_c || is_f) && To )), "You asked C or Fortran traversal order and gave a traversal order ...");
|
||||||
static_assert ( (inm), "You asked nan and default init at the same time...");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define TRIQS_FLAGS_GET(f,a) ((f & (1ull<<a)) >> a)
|
#define TRIQS_FLAGS_GET(f,a) ((f & (1ull<<a)) >> a)
|
||||||
#define TRIQS_FLAGS_GET2(f,a) ((f & ((1ull<<a) + (1ull<< (a+1ull)))) >> a)
|
#define TRIQS_FLAGS_GET2(f,a) ((f & ((1ull<<a) + (1ull<< (a+1ull)))) >> a)
|
||||||
|
|
||||||
|
constexpr bool is_const (ull_t f) { return false;} // non const view on icc
|
||||||
|
|
||||||
#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||||
template< ull_t F> struct bound_check_trait { static constexpr bool value = true;};
|
template< ull_t F> struct bound_check_trait { static constexpr bool value = true;};
|
||||||
#else
|
#else
|
||||||
template< ull_t F> struct bound_check_trait { static constexpr bool value = TRIQS_FLAGS_GET (F, 0)!=0; };
|
template< ull_t F> struct bound_check_trait { static constexpr bool value = TRIQS_FLAGS_GET (F, 5)!=0; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template< ull_t F> struct traversal_order_c { static constexpr bool value = TRIQS_FLAGS_GET(F,1) !=0; };
|
template< ull_t F> struct traversal_order_c { static constexpr bool value = TRIQS_FLAGS_GET(F,1) !=0; };
|
||||||
@ -105,8 +105,7 @@ namespace triqs { namespace arrays {
|
|||||||
|
|
||||||
template<ull_t F> struct init_tag1;
|
template<ull_t F> struct init_tag1;
|
||||||
template<> struct init_tag1<0> { typedef Tag::no_init type;};
|
template<> struct init_tag1<0> { typedef Tag::no_init type;};
|
||||||
//template<> struct init_tag1<1> { typedef Tag::nan_inf_init type;};
|
template<> struct init_tag1<1> { typedef Tag::default_init type;};
|
||||||
template<> struct init_tag1<2> { typedef Tag::default_init type;};
|
|
||||||
template<ull_t F> struct init_tag : init_tag1 < init_mode_tr<F>::value > {};
|
template<ull_t F> struct init_tag : init_tag1 < init_mode_tr<F>::value > {};
|
||||||
|
|
||||||
template<ull_t F, ull_t To> struct assert_make_sense { };// no check on icc
|
template<ull_t F, ull_t To> struct assert_make_sense { };// no check on icc
|
||||||
|
@ -52,6 +52,7 @@ namespace triqs { namespace arrays {
|
|||||||
typedef StorageType storage_type;
|
typedef StorageType storage_type;
|
||||||
typedef IndexMapType indexmap_type;
|
typedef IndexMapType indexmap_type;
|
||||||
static constexpr unsigned int rank = IndexMapType::domain_type::rank;
|
static constexpr unsigned int rank = IndexMapType::domain_type::rank;
|
||||||
|
static constexpr ull_t opt_flags = OptionFlags;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
indexmap_type indexmap_;
|
indexmap_type indexmap_;
|
||||||
@ -188,7 +189,7 @@ namespace triqs { namespace arrays {
|
|||||||
// Evaluation and slices
|
// Evaluation and slices
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
(!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0)
|
(!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank==0) && !flags::is_const(OptionFlags)
|
||||||
, value_type &>::type
|
, value_type &>::type
|
||||||
operator()(Args const & ... args) { return storage_[indexmap_(args...)]; }
|
operator()(Args const & ... args) { return storage_[indexmap_(args...)]; }
|
||||||
|
|
||||||
@ -203,7 +204,8 @@ namespace triqs { namespace arrays {
|
|||||||
//typedef typename std::conditional<is_const, typename std::add_const<value_type>::type, value_type>::type V2;
|
//typedef typename std::conditional<is_const, typename std::add_const<value_type>::type, value_type>::type V2;
|
||||||
typedef value_type V2;
|
typedef value_type V2;
|
||||||
static_assert(IM2::domain_type::rank !=0, "Internal error");
|
static_assert(IM2::domain_type::rank !=0, "Internal error");
|
||||||
typedef typename ISPViewType<V2,IM2::domain_type::rank, OptionFlags, IM2::traversal_order_in_template, ViewTag, ForceBorrowed || StorageType::is_weak >::type type;
|
static constexpr ull_t optmodif = (is_const ? ConstView : 0ull);
|
||||||
|
typedef typename ISPViewType<V2,IM2::domain_type::rank, OptionFlags|optmodif, IM2::traversal_order_in_template, ViewTag, ForceBorrowed || StorageType::is_weak >::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// change here only for debug
|
// change here only for debug
|
||||||
@ -211,7 +213,7 @@ namespace triqs { namespace arrays {
|
|||||||
#ifndef TRIQS_ARRAYS_SLICE_DEFAUT_IS_SHARED
|
#ifndef TRIQS_ARRAYS_SLICE_DEFAUT_IS_SHARED
|
||||||
template<typename... Args> // non const version
|
template<typename... Args> // non const version
|
||||||
typename boost::lazy_enable_if_c<
|
typename boost::lazy_enable_if_c<
|
||||||
(!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank!=0)
|
(!clef::is_any_lazy<Args...>::value) && (indexmaps::slicer<indexmap_type,Args...>::r_type::domain_type::rank!=0) && !flags::is_const(OptionFlags)
|
||||||
, result_of_call_as_view<false,true,Args...>
|
, result_of_call_as_view<false,true,Args...>
|
||||||
>::type // enable_if
|
>::type // enable_if
|
||||||
operator()(Args const & ... args) & {
|
operator()(Args const & ... args) & {
|
||||||
@ -236,8 +238,7 @@ namespace triqs { namespace arrays {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent to make_view
|
/// Equivalent to make_view
|
||||||
//typename ISPViewType<typename std::add_const<value_type>::type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag >::type
|
typename ISPViewType<value_type,domain_type::rank, OptionFlags | ConstView, TraversalOrder, ViewTag, true >::type
|
||||||
typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag, true >::type
|
|
||||||
operator()() const & { return *this; }
|
operator()() const & { return *this; }
|
||||||
|
|
||||||
typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag, true >::type
|
typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag, true >::type
|
||||||
|
@ -21,13 +21,16 @@
|
|||||||
#ifndef TRIQS_COMPILER_DETAILS_H
|
#ifndef TRIQS_COMPILER_DETAILS_H
|
||||||
#define TRIQS_COMPILER_DETAILS_H
|
#define TRIQS_COMPILER_DETAILS_H
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#if defined __GNUC__ || defined __clang__
|
||||||
#define restrict __restrict__
|
#define restrict __restrict__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined __GNUC__ && ! defined __clang__
|
||||||
#define GCC_VERSION (__GNUC__ * 10000 \
|
#define GCC_VERSION (__GNUC__ * 10000 \
|
||||||
+ __GNUC_MINOR__ * 100 \
|
+ __GNUC_MINOR__ * 100 \
|
||||||
+ __GNUC_PATCHLEVEL__)
|
+ __GNUC_PATCHLEVEL__)
|
||||||
#if GCC_VERSION < 40801
|
#if GCC_VERSION < 40801
|
||||||
|
#warning "gcc compiler" GCC_VERSION
|
||||||
#define TRIQS_COMPILER_IS_OBSOLETE
|
#define TRIQS_COMPILER_IS_OBSOLETE
|
||||||
// we still accept gcc 4.6 and 4.7, but only the 4.8.1 and higher is a compliant c++11
|
// we still accept gcc 4.6 and 4.7, but only the 4.8.1 and higher is a compliant c++11
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user