mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 05:43: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_CHECK_IM_STORAGE_COMPAT
|
||||
#define TRIQS_ARRAYS_CHECK_WEAK_REFS
|
||||
|
||||
#else
|
||||
#define TRIQS_ARRAYS_DEBUG_CHECK(Cond,Error)
|
||||
#endif
|
||||
|
||||
// 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
|
||||
#define TRIQS_ARRAYS_SLICE_DEFAUT_IS_SHARED
|
||||
#endif
|
||||
|
@ -27,18 +27,18 @@ namespace triqs { namespace arrays {
|
||||
|
||||
// Flags is a 64 bit unsigned int.
|
||||
// 0 is the default option.
|
||||
// Meaning of the bits :
|
||||
// 0 -> Boundcheck
|
||||
// Meaning of the bits :
|
||||
// 0 -> Const
|
||||
// 1,2 -> Predefined order :
|
||||
// 0 : None, 1 : C, 2 : Fortran
|
||||
// 3,4 -> Init
|
||||
// 0 : Noinit, 1 : NanInit, 2 : DefaultInit
|
||||
// 3 -> Init the array
|
||||
// 5 -> Boundcheck
|
||||
|
||||
constexpr ull_t BoundCheck = 1ull << 0;
|
||||
constexpr ull_t TraversalOrderC = 1ull << 1;
|
||||
constexpr ull_t TraversalOrderFortran = 1ull << 2;
|
||||
//constexpr ull_t NanInit = 1ull << 3;
|
||||
constexpr ull_t DefaultInit = 1ull << 4;
|
||||
constexpr ull_t ConstView = 1ull << 0;
|
||||
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
|
||||
@ -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 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
|
||||
constexpr bool bound_check (ull_t f) { return true;}
|
||||
#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
|
||||
|
||||
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); };
|
||||
|
||||
constexpr ull_t init_mode (ull_t f) { return get2 (f,3);}
|
||||
constexpr bool check_init_mode (ull_t f) { return get2 (f,3)!=3ull;}
|
||||
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::nan_inf_init type;};
|
||||
template<> struct init_tag1<2> { typedef Tag::default_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)> {};
|
||||
@ -81,21 +81,21 @@ namespace triqs { namespace arrays {
|
||||
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 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) && 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
|
||||
|
||||
#define TRIQS_FLAGS_GET(f,a) ((f & (1ull<<a)) >> 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
|
||||
template< ull_t F> struct bound_check_trait { static constexpr bool value = true;};
|
||||
#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
|
||||
|
||||
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<> struct init_tag1<0> { typedef Tag::no_init type;};
|
||||
//template<> struct init_tag1<1> { typedef Tag::nan_inf_init type;};
|
||||
template<> struct init_tag1<2> { typedef Tag::default_init type;};
|
||||
template<> struct init_tag1<1> { typedef Tag::default_init type;};
|
||||
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
|
||||
|
@ -52,6 +52,7 @@ namespace triqs { namespace arrays {
|
||||
typedef StorageType storage_type;
|
||||
typedef IndexMapType indexmap_type;
|
||||
static constexpr unsigned int rank = IndexMapType::domain_type::rank;
|
||||
static constexpr ull_t opt_flags = OptionFlags;
|
||||
protected:
|
||||
|
||||
indexmap_type indexmap_;
|
||||
@ -188,7 +189,7 @@ namespace triqs { namespace arrays {
|
||||
// Evaluation and slices
|
||||
template<typename... Args>
|
||||
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
|
||||
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 value_type V2;
|
||||
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
|
||||
@ -211,7 +213,7 @@ namespace triqs { namespace arrays {
|
||||
#ifndef TRIQS_ARRAYS_SLICE_DEFAUT_IS_SHARED
|
||||
template<typename... Args> // non const version
|
||||
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...>
|
||||
>::type // enable_if
|
||||
operator()(Args const & ... args) & {
|
||||
@ -236,8 +238,7 @@ namespace triqs { namespace arrays {
|
||||
}
|
||||
|
||||
/// 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, TraversalOrder, ViewTag, true >::type
|
||||
typename ISPViewType<value_type,domain_type::rank, OptionFlags | ConstView, TraversalOrder, ViewTag, true >::type
|
||||
operator()() const & { return *this; }
|
||||
|
||||
typename ISPViewType<value_type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag, true >::type
|
||||
|
@ -21,13 +21,16 @@
|
||||
#ifndef TRIQS_COMPILER_DETAILS_H
|
||||
#define TRIQS_COMPILER_DETAILS_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined __GNUC__ || defined __clang__
|
||||
#define restrict __restrict__
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__ && ! defined __clang__
|
||||
#define GCC_VERSION (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNUC_PATCHLEVEL__)
|
||||
#if GCC_VERSION < 40801
|
||||
#warning "gcc compiler" GCC_VERSION
|
||||
#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
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user