mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-24 21:10:33 +05:00
Range(obj) does respect index type now. If obj has a function Range it
calls the function
This commit is contained in:
parent
d9897fce99
commit
6c71982951
@ -59,6 +59,26 @@ namespace ngcore
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// Type trait to check if a class implements a 'range_type Range()' function
|
||||||
|
template<typename T>
|
||||||
|
struct has_Range
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template<typename T2>
|
||||||
|
static constexpr auto check(T2*) ->
|
||||||
|
std::enable_if<std::declval<T2>().Range(), std::true_type> { std::true_type(); }
|
||||||
|
template<typename>
|
||||||
|
static constexpr std::false_type check(...);
|
||||||
|
using type = decltype(check<T>(nullptr)); // NOLINT
|
||||||
|
public:
|
||||||
|
NGCORE_API static constexpr bool value = type::value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool has_range = detail::has_Range<T>::value;
|
||||||
|
|
||||||
template <typename AO>
|
template <typename AO>
|
||||||
class AOWrapperIterator
|
class AOWrapperIterator
|
||||||
@ -210,7 +230,7 @@ namespace ngcore
|
|||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr size_t IndexBASE () { return 0; }
|
constexpr T IndexBASE () { return T(0); }
|
||||||
|
|
||||||
|
|
||||||
template <class T, class IndexType = size_t> class FlatArray;
|
template <class T, class IndexType = size_t> class FlatArray;
|
||||||
@ -293,6 +313,11 @@ namespace ngcore
|
|||||||
return T_Range<T>(a,b);
|
return T_Range<T>(a,b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
NETGEN_INLINE auto Range (const T& ao)
|
||||||
|
-> typename std::enable_if<has_range<T>, decltype(std::declval<T>().Range())>::type
|
||||||
|
{ return ao.Range(); }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
NETGEN_INLINE T_Range<T> Range_impl (T n, std::true_type)
|
NETGEN_INLINE T_Range<T> Range_impl (T n, std::true_type)
|
||||||
{
|
{
|
||||||
@ -301,13 +326,15 @@ namespace ngcore
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
NETGEN_INLINE auto Range_impl (const T & ao, std::false_type)
|
NETGEN_INLINE auto Range_impl (const T & ao, std::false_type)
|
||||||
-> T_Range<decltype(ao.Size())>
|
-> T_Range<index_type<T>>
|
||||||
{
|
{
|
||||||
return T_Range<decltype(ao.Size())> (0, ao.Size());
|
return T_Range<index_type<T>> (IndexBASE<index_type<T>>(),
|
||||||
|
IndexBASE<index_type<T>>() + index_type<T>(ao.Size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto Range(const T & x) -> decltype(Range_impl(x, std::is_integral<T>())) {
|
auto Range(const T & x)
|
||||||
|
-> typename std::enable_if<!has_range<T>, decltype(Range_impl(x, std::is_integral<T>()))>::type {
|
||||||
return Range_impl(x, std::is_integral<T>());
|
return Range_impl(x, std::is_integral<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +429,7 @@ namespace ngcore
|
|||||||
class FlatArray : public BaseArrayObject<FlatArray<T,IndexType> >
|
class FlatArray : public BaseArrayObject<FlatArray<T,IndexType> >
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
static constexpr size_t BASE = IndexBASE<IndexType>();
|
static constexpr IndexType BASE = IndexBASE<IndexType>();
|
||||||
/// the size
|
/// the size
|
||||||
size_t size;
|
size_t size;
|
||||||
/// the data
|
/// the data
|
||||||
@ -500,9 +527,9 @@ namespace ngcore
|
|||||||
return data[i-BASE];
|
return data[i-BASE];
|
||||||
}
|
}
|
||||||
|
|
||||||
NETGEN_INLINE T_Range<size_t> Range () const
|
NETGEN_INLINE T_Range<index_type> Range () const
|
||||||
{
|
{
|
||||||
return T_Range<size_t> (BASE, Size()+BASE);
|
return T_Range<index_type> (BASE, size+BASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
NETGEN_INLINE const CArray<T> Addr (size_t pos) const
|
NETGEN_INLINE const CArray<T> Addr (size_t pos) const
|
||||||
|
@ -126,6 +126,26 @@ namespace ngcore
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct IndexTypeHelper
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template<typename T2>
|
||||||
|
static constexpr auto check(T2* t) -> typename T2::index_type { return *t; }
|
||||||
|
static constexpr auto check(...) -> decltype(std::declval<T>().Size())
|
||||||
|
{ return decltype(std::declval<T>().Size())(); }
|
||||||
|
public:
|
||||||
|
using type = decltype(check((T*) nullptr)); // NOLINT
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// Get index type of object. If object has a typedef index_type this type is returned
|
||||||
|
// else decltype(obj.Size()) is returned.
|
||||||
|
template<typename T>
|
||||||
|
using index_type = typename detail::IndexTypeHelper<T>::type;
|
||||||
} // namespace ngcore
|
} // namespace ngcore
|
||||||
|
|
||||||
#endif // NETGEN_CORE_UTILS_HPP
|
#endif // NETGEN_CORE_UTILS_HPP
|
||||||
|
@ -84,6 +84,7 @@ namespace netgen
|
|||||||
T * data;
|
T * data;
|
||||||
public:
|
public:
|
||||||
typedef T TELEM;
|
typedef T TELEM;
|
||||||
|
using index_type = TIND;
|
||||||
|
|
||||||
/// provide size and memory
|
/// provide size and memory
|
||||||
NgFlatArray (size_t asize, T * adata)
|
NgFlatArray (size_t asize, T * adata)
|
||||||
|
@ -162,7 +162,7 @@ namespace netgen
|
|||||||
PointIndex & operator= (const PointIndex&) = default;
|
PointIndex & operator= (const PointIndex&) = default;
|
||||||
PointIndex & operator= (PointIndex&&) = default;
|
PointIndex & operator= (PointIndex&&) = default;
|
||||||
|
|
||||||
PointIndex (int ai) : i(ai)
|
constexpr PointIndex (int ai) : i(ai)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (ai < PointIndex::BASE)
|
if (ai < PointIndex::BASE)
|
||||||
@ -172,7 +172,7 @@ namespace netgen
|
|||||||
}
|
}
|
||||||
constexpr PointIndex (t_invalid inv) : i(PointIndex::BASE-1) { ; }
|
constexpr PointIndex (t_invalid inv) : i(PointIndex::BASE-1) { ; }
|
||||||
// PointIndex & operator= (const PointIndex &ai) { i = ai.i; return *this; }
|
// PointIndex & operator= (const PointIndex &ai) { i = ai.i; return *this; }
|
||||||
operator int () const { return i; }
|
constexpr operator int () const { return i; }
|
||||||
PointIndex operator++ (int) { PointIndex hi(*this); i++; return hi; }
|
PointIndex operator++ (int) { PointIndex hi(*this); i++; return hi; }
|
||||||
PointIndex operator-- (int) { PointIndex hi(*this); i--; return hi; }
|
PointIndex operator-- (int) { PointIndex hi(*this); i--; return hi; }
|
||||||
PointIndex operator++ () { i++; return *this; }
|
PointIndex operator++ () { i++; return *this; }
|
||||||
@ -180,9 +180,9 @@ namespace netgen
|
|||||||
void Invalidate() { i = PointIndex::BASE-1; }
|
void Invalidate() { i = PointIndex::BASE-1; }
|
||||||
bool IsValid() const { return i != PointIndex::BASE-1; }
|
bool IsValid() const { return i != PointIndex::BASE-1; }
|
||||||
#ifdef BASE0
|
#ifdef BASE0
|
||||||
enum { BASE = 0 };
|
static constexpr size_t BASE = 0;
|
||||||
#else
|
#else
|
||||||
enum { BASE = 1 };
|
static constexpr size_t BASE = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void DoArchive (Archive & ar) { ar & i; }
|
void DoArchive (Archive & ar) { ar & i; }
|
||||||
@ -193,7 +193,7 @@ namespace netgen
|
|||||||
namespace ngcore
|
namespace ngcore
|
||||||
{
|
{
|
||||||
template<>
|
template<>
|
||||||
constexpr size_t IndexBASE<netgen::PointIndex> () { return netgen::PointIndex::BASE; }
|
constexpr netgen::PointIndex IndexBASE<netgen::PointIndex> () { return netgen::PointIndex(netgen::PointIndex::BASE); }
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace netgen
|
namespace netgen
|
||||||
@ -255,14 +255,14 @@ namespace netgen
|
|||||||
int i;
|
int i;
|
||||||
public:
|
public:
|
||||||
SurfaceElementIndex () = default;
|
SurfaceElementIndex () = default;
|
||||||
SurfaceElementIndex (int ai) : i(ai) { ; }
|
constexpr SurfaceElementIndex (int ai) : i(ai) { ; }
|
||||||
/*
|
/*
|
||||||
SurfaceElementIndex & operator= (const SurfaceElementIndex & ai)
|
SurfaceElementIndex & operator= (const SurfaceElementIndex & ai)
|
||||||
{ i = ai.i; return *this; }
|
{ i = ai.i; return *this; }
|
||||||
*/
|
*/
|
||||||
SurfaceElementIndex & operator= (const SurfaceElementIndex & ai) = default;
|
SurfaceElementIndex & operator= (const SurfaceElementIndex & ai) = default;
|
||||||
SurfaceElementIndex & operator= (int ai) { i = ai; return *this; }
|
SurfaceElementIndex & operator= (int ai) { i = ai; return *this; }
|
||||||
operator int () const { return i; }
|
constexpr operator int () const { return i; }
|
||||||
SurfaceElementIndex operator++ (int) { SurfaceElementIndex hi(*this); i++; return hi; }
|
SurfaceElementIndex operator++ (int) { SurfaceElementIndex hi(*this); i++; return hi; }
|
||||||
SurfaceElementIndex operator-- (int) { SurfaceElementIndex hi(*this); i--; return hi; }
|
SurfaceElementIndex operator-- (int) { SurfaceElementIndex hi(*this); i--; return hi; }
|
||||||
SurfaceElementIndex & operator++ () { ++i; return *this; }
|
SurfaceElementIndex & operator++ () { ++i; return *this; }
|
||||||
|
@ -26,6 +26,7 @@ macro(add_unit_test name sources)
|
|||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
add_unit_test(archive archive.cpp)
|
add_unit_test(archive archive.cpp)
|
||||||
|
add_unit_test(array array.cpp)
|
||||||
add_unit_test(symboltable symboltable.cpp)
|
add_unit_test(symboltable symboltable.cpp)
|
||||||
add_unit_test(utils utils.cpp)
|
add_unit_test(utils utils.cpp)
|
||||||
add_unit_test(version version.cpp)
|
add_unit_test(version version.cpp)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include <array.hpp>
|
#include <core/array.hpp>
|
||||||
using namespace ngcore;
|
using namespace ngcore;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
#include "meshing.hpp"
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Array")
|
TEST_CASE("Array")
|
||||||
{
|
{
|
||||||
@ -15,13 +17,14 @@ TEST_CASE("Array")
|
|||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
Array<double> a_initlst = { 1., 2., 3.};
|
Array<double> a_initlst = { 1., 2., 3.};
|
||||||
CHECK(a_initlst[1] == 2.);
|
CHECK(a_initlst[1] == 2.);
|
||||||
CHECK(a_initlst.size() == 3);
|
CHECK(a_initlst.Size() == 3);
|
||||||
FlatArray fa_a = a_initlst;
|
FlatArray fa_a = a_initlst;
|
||||||
CHECK(typeid(fa_a) == typeid(FlatArray<double>));
|
CHECK(typeid(fa_a) == typeid(FlatArray<double>));
|
||||||
CHECK(fa_a.size() == 3);
|
CHECK(fa_a.Size() == 3);
|
||||||
CHECK(a.Last() == 3.);
|
CHECK(fa_a.Last() == 3.);
|
||||||
a.DeleteLast();
|
a_initlst.DeleteLast();
|
||||||
CHECK(a.Last() == 2. && a.Size() == 2);
|
CHECK(a_initlst.Last() == 2.);
|
||||||
|
CHECK(a_initlst.Size() == 2);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
CHECK_THROWS_AS(fa_a[5], RangeException);
|
CHECK_THROWS_AS(fa_a[5], RangeException);
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
@ -34,4 +37,25 @@ TEST_CASE("Array")
|
|||||||
CHECK(val == 2);
|
CHECK(val == 2);
|
||||||
}
|
}
|
||||||
CHECK(count == 4);
|
CHECK(count == 4);
|
||||||
|
|
||||||
|
// range tests
|
||||||
|
CHECK(typeid(array.Range()) == typeid(T_Range<size_t>));
|
||||||
|
Array<int, int> intarray;
|
||||||
|
CHECK(typeid(intarray.Range()) == typeid(T_Range<int>));
|
||||||
|
CHECK(typeid(Range(intarray)) == typeid(T_Range<int>));
|
||||||
|
int i = 0;
|
||||||
|
for(auto j : Range(b))
|
||||||
|
CHECK(j == i++);
|
||||||
|
i = 0;
|
||||||
|
for(auto j : b.Range())
|
||||||
|
CHECK(j == i++);
|
||||||
|
|
||||||
|
// pointindex is still 1 based
|
||||||
|
Array<double, netgen::PointIndex> piarray(2);
|
||||||
|
i = 1;
|
||||||
|
for(auto j : Range(piarray))
|
||||||
|
CHECK(j == i++);
|
||||||
|
i = 1;
|
||||||
|
for(auto j : piarray.Range())
|
||||||
|
CHECK(j == i++);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user