Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
amdis
amdis-core
Commits
989b5b7c
Commit
989b5b7c
authored
Aug 28, 2019
by
Praetorius, Simon
Browse files
added backport of transformedRangeView from dune-2.7 git branch
parent
10aab891
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/amdis/utility/CMakeLists.txt
View file @
989b5b7c
...
...
@@ -3,6 +3,7 @@ install(FILES
LocalBasisCache.hpp
LocalToGlobalAdapter.hpp
MacroGridFactory.hpp
MappedRangeView.hpp
QuadratureFactory.hpp
Twist.hpp
UniqueBorderPartition.hpp
...
...
src/amdis/utility/MappedRangeView.hpp
0 → 100644
View file @
989b5b7c
#pragma once
#include <iterator>
#include <type_traits>
#include <amdis/common/TypeTraits.hpp>
namespace
AMDiS
{
// NOTE: this is a backport of the dune-common TransformedRangeView with added size() function.
namespace
Impl
{
// Helper class to mimic a pointer for proxy objects.
// This is needed to implement operator-> on an iterator
// using proxy-values. It stores the proxy value but
// provides operator-> like a pointer.
template
<
class
ProxyType
>
class
PointerProxy
{
public:
PointerProxy
(
ProxyType
&&
p
)
:
p_
(
p
)
{}
ProxyType
*
operator
->
()
{
return
&
p_
;
}
ProxyType
p_
;
};
// An iterator transforming a wrapped iterator using
// an unary function. It inherits the iterator-category
// of the underlying iterator.
template
<
class
I
,
class
F
,
class
C
=
typename
std
::
iterator_traits
<
I
>
::
iterator_category
>
class
MappedRangeIterator
;
template
<
class
I
,
class
F
>
class
MappedRangeIterator
<
I
,
F
,
std
::
forward_iterator_tag
>
{
public:
using
iterator_category
=
std
::
forward_iterator_tag
;
using
reference
=
decltype
(
std
::
declval
<
F
>
()(
*
(
std
::
declval
<
I
>
())));
using
value_type
=
std
::
decay_t
<
reference
>
;
using
pointer
=
PointerProxy
<
value_type
>
;
// If we later want to allow standalone MappedRangeIterators,
// we could customize the FunctionPointer to be a default-constructible,
// copy-assignable type storing a function but acting like a pointer
// to function.
using
FunctionPointer
=
const
F
*
;
constexpr
MappedRangeIterator
(
const
I
&
it
,
FunctionPointer
f
)
noexcept
:
it_
(
it
)
,
f_
(
f
)
{}
// Explicitly initialize members. Using a plain
//
// constexpr MappedRangeIterator() noexcept {}
//
// would default-initialize the members while
//
// constexpr MappedRangeIterator() noexcept : it_(), f_() {}
//
// leads to value-initialization. This is a case where
// both are really different. If it_ is a raw pointer (i.e. POD)
// then default-initialization leaves it uninitialized while
// value-initialization zero-initializes it.
constexpr
MappedRangeIterator
()
noexcept
:
it_
()
,
f_
()
{}
// Dereferencing returns a value created by the function
constexpr
reference
operator
*
()
const
noexcept
{
return
(
*
f_
)(
*
it_
);
}
// Dereferencing returns a value created by the function
pointer
operator
->
()
const
noexcept
{
return
(
*
f_
)(
*
it_
);
}
constexpr
MappedRangeIterator
&
operator
=
(
MappedRangeIterator
const
&
)
=
default
;
constexpr
bool
operator
==
(
const
MappedRangeIterator
&
other
)
const
noexcept
{
return
(
it_
==
other
.
it_
);
}
constexpr
bool
operator
!=
(
const
MappedRangeIterator
&
other
)
const
noexcept
{
return
(
it_
!=
other
.
it_
);
}
MappedRangeIterator
&
operator
++
()
noexcept
{
++
it_
;
return
*
this
;
}
MappedRangeIterator
operator
++
(
int
)
noexcept
{
MappedRangeIterator
copy
(
*
this
);
++
(
*
this
);
return
copy
;
}
protected:
I
it_
;
FunctionPointer
f_
;
};
template
<
class
I
,
class
F
>
class
MappedRangeIterator
<
I
,
F
,
std
::
bidirectional_iterator_tag
>
:
public
MappedRangeIterator
<
I
,
F
,
std
::
forward_iterator_tag
>
{
protected:
using
Base
=
MappedRangeIterator
<
I
,
F
,
std
::
forward_iterator_tag
>
;
using
Base
::
it_
;
using
Base
::
f_
;
public:
using
iterator_category
=
std
::
bidirectional_iterator_tag
;
using
reference
=
typename
Base
::
reference
;
using
value_type
=
typename
Base
::
value_type
;
using
pointer
=
typename
Base
::
pointer
;
using
FunctionPointer
=
typename
Base
::
FunctionPointer
;
// inheriting constructor
using
Base
::
Base
;
// Member functions of the forward_iterator that need
// to be redefined because the base class methods return a
// forward_iterator.
constexpr
MappedRangeIterator
&
operator
=
(
MappedRangeIterator
const
&
)
=
default
;
MappedRangeIterator
&
operator
++
()
noexcept
{
++
it_
;
return
*
this
;
}
MappedRangeIterator
operator
++
(
int
)
noexcept
{
MappedRangeIterator
copy
(
*
this
);
++
(
*
this
);
return
copy
;
}
// Additional member functions of bidirectional_iterator
MappedRangeIterator
&
operator
--
()
noexcept
{
--
(
this
->
it_
);
return
*
this
;
}
MappedRangeIterator
operator
--
(
int
)
noexcept
{
MappedRangeIterator
copy
(
*
this
);
--
(
*
this
);
return
copy
;
}
};
template
<
class
I
,
class
F
>
class
MappedRangeIterator
<
I
,
F
,
std
::
random_access_iterator_tag
>
:
public
MappedRangeIterator
<
I
,
F
,
std
::
bidirectional_iterator_tag
>
{
protected:
using
Base
=
MappedRangeIterator
<
I
,
F
,
std
::
bidirectional_iterator_tag
>
;
using
Base
::
it_
;
using
Base
::
f_
;
public:
using
iterator_category
=
std
::
random_access_iterator_tag
;
using
reference
=
typename
Base
::
reference
;
using
value_type
=
typename
Base
::
value_type
;
using
pointer
=
typename
Base
::
pointer
;
using
difference_type
=
typename
std
::
iterator_traits
<
I
>::
difference_type
;
using
FunctionPointer
=
typename
Base
::
FunctionPointer
;
// inheriting constructor
using
Base
::
Base
;
// Member functions of the forward_iterator that need
// to be redefined because the base class methods return a
// forward_iterator.
constexpr
MappedRangeIterator
&
operator
=
(
MappedRangeIterator
const
&
)
=
default
;
MappedRangeIterator
&
operator
++
()
noexcept
{
++
it_
;
return
*
this
;
}
MappedRangeIterator
operator
++
(
int
)
noexcept
{
MappedRangeIterator
copy
(
*
this
);
++
(
*
this
);
return
copy
;
}
// Member functions of the bidirectional_iterator that need
// to be redefined because the base class methods return a
// bidirectional_iterator.
MappedRangeIterator
&
operator
--
()
noexcept
{
--
(
this
->
it_
);
return
*
this
;
}
MappedRangeIterator
operator
--
(
int
)
noexcept
{
MappedRangeIterator
copy
(
*
this
);
--
(
*
this
);
return
copy
;
}
// Additional member functions of random_access_iterator
MappedRangeIterator
&
operator
+=
(
difference_type
n
)
noexcept
{
it_
+=
n
;
return
*
this
;
}
MappedRangeIterator
&
operator
-=
(
difference_type
n
)
noexcept
{
it_
-=
n
;
return
*
this
;
}
bool
operator
<
(
const
MappedRangeIterator
&
other
)
noexcept
{
return
it_
<
other
.
it_
;
}
bool
operator
<=
(
const
MappedRangeIterator
&
other
)
noexcept
{
return
it_
<=
other
.
it_
;
}
bool
operator
>
(
const
MappedRangeIterator
&
other
)
noexcept
{
return
it_
>
other
.
it_
;
}
bool
operator
>=
(
const
MappedRangeIterator
&
other
)
noexcept
{
return
it_
>=
other
.
it_
;
}
reference
operator
[](
difference_type
n
)
noexcept
{
return
(
*
f_
)(
*
(
it_
+
n
));
}
friend
MappedRangeIterator
operator
+
(
const
MappedRangeIterator
&
it
,
difference_type
n
)
noexcept
{
return
MappedRangeIterator
(
it
.
it_
+
n
,
it
.
f_
);
}
friend
MappedRangeIterator
operator
+
(
difference_type
n
,
const
MappedRangeIterator
&
it
)
noexcept
{
return
MappedRangeIterator
(
n
+
it
.
it_
,
it
.
f_
);
}
friend
MappedRangeIterator
operator
-
(
const
MappedRangeIterator
&
it
,
difference_type
n
)
noexcept
{
return
MappedRangeIterator
(
it
.
it_
-
n
,
it
.
f_
);
}
friend
difference_type
operator
-
(
const
MappedRangeIterator
&
first
,
const
MappedRangeIterator
&
second
)
noexcept
{
return
first
.
it_
-
second
.
it_
;
}
};
}
// namespace Impl
/**
* \brief A range transforming the values of another range on-the-fly
*
* This behaves like a range providing `begin()` and `end()`.
* The iterators over this range internally iterate over
* the wrapped range. When dereferencing the iterator,
* the value is transformed on-the-fly using a given
* transformation function leaving the underlying range
* unchanged.
*
* The transformation may either return temorary values
* or l-value references. In the former case the range behaves
* like a proxy-container. In the latter case it forwards these
* references allowing, e.g., to sort a subset of some container
* by applying a transformation to an index-range for those values.
*
* The iterators of the MappedRangeView have the same
* iterator_category as the ones of the wrapped container.
*
* If range is given as r-value, then the returned MappedRangeView
* stores it by value, if range is given as (const) l-value, then the
* MappedRangeView stores it by (const) reference.
*
* If R is a value type, then the MappedRangeView stores the wrapped range by value,
* if R is a reference type, then the MappedRangeView stores the wrapped range by reference.
*
* \tparam R Underlying range.
* \tparam F Unary function used to transform the values in the underlying range.
**/
template
<
class
R
,
class
F
>
class
MappedRangeView
{
using
RawConstIterator
=
TYPEOF
(
std
::
declval
<
const
R
>
().
begin
());
using
RawIterator
=
TYPEOF
(
std
::
declval
<
R
>
().
begin
());
public:
/**
* \brief Iterator type
*
* This inherits the iterator_category of the iterators
* of the underlying range.
*/
using
const_iterator
=
Impl
::
MappedRangeIterator
<
RawConstIterator
,
F
>
;
using
iterator
=
Impl
::
MappedRangeIterator
<
RawIterator
,
F
>
;
/**
* \brief Construct from range and function
*/
template
<
class
RR
>
constexpr
MappedRangeView
(
RR
&&
rawRange
,
F
const
&
f
)
noexcept
:
rawRange_
(
FWD
(
rawRange
))
,
f_
(
f
)
{}
/**
* \brief Obtain a iterator to the first element
*
* The life time of the returned iterator is bound to
* the life time of the range since it only contains a
* pointer to the transformation function stored
* in the range.
*/
constexpr
const_iterator
begin
()
const
noexcept
{
return
const_iterator
(
rawRange_
.
begin
(),
&
f_
);
}
constexpr
iterator
begin
()
noexcept
{
return
iterator
(
rawRange_
.
begin
(),
&
f_
);
}
/**
* \brief Return the number of elements in the range, if availble.
*
* Note, this function is only availble if the underlying raw range
* knows its size and provides a function `size()`.
*/
template
<
class
RR
=
R
,
class
=
decltype
(
std
::
declval
<
RR
>().
size
())
>
constexpr
auto
size
()
const
noexcept
{
return
rawRange_
.
size
();
}
/// Provide element access for random-accessible ranges
template
<
class
RR
=
R
,
class
=
decltype
(
std
::
declval
<
RR
>().
operator
[](
std
::
size_t
(
0
)))
>
decltype
(
auto
)
operator
[](
std
::
size_t
i
)
const
{
return
f_
(
rawRange_
[
i
]);
}
/**
* \brief Checks whether the range is empty
*/
constexpr
bool
empty
()
const
noexcept
{
return
rawRange_
.
begin
()
==
rawRange_
.
end
();
}
/**
* \brief Obtain a iterator past the last element
*
* The life time of the returned iterator is bound to
* the life time of the range since it only contains a
* pointer to the transformation function stored
* in the range.
*/
constexpr
const_iterator
end
()
const
noexcept
{
return
const_iterator
(
rawRange_
.
end
(),
&
f_
);
}
constexpr
iterator
end
()
noexcept
{
return
iterator
(
rawRange_
.
end
(),
&
f_
);
}
private:
R
rawRange_
;
F
f_
;
};
/**
* \brief Create a MappedRangeView
*
* \param range The range the transform
* \param f Unary function that should the applied to the entries of the range.
*
* This behaves like a range providing `begin()` and `end()`.
* The iterators over this range internally iterate over
* the wrapped range. When dereferencing the iterator,
* the value is transformed on-the-fly using a given
* transformation function leaving the underlying range
* unchanged.
*
* The transformation may either return temporary values
* or l-value references. In the former case the range behaves
* like a proxy-container. In the latter case it forwards these
* references allowing, e.g., to sort a subset of some container
* by applying a transformation to an index-range for those values.
*
* The iterators of the MappedRangeView have the same
* iterator_category as the ones of the wrapped container.
*
* If range is an r-value, then the MappedRangeView stores it by value,
* if range is an l-value, then the MappedRangeView stores it by reference.
**/
template
<
class
R
,
class
F
>
auto
mappedRangeView
(
R
&&
range
,
F
const
&
f
)
{
return
MappedRangeView
<
R
,
F
>
(
FWD
(
range
),
f
);
}
template
<
class
Iter
,
class
F
>
auto
mappedIterator
(
Iter
it
,
F
const
*
f
)
{
using
iterator
=
Impl
::
MappedRangeIterator
<
Iter
,
F
>
;
return
iterator
(
it
,
f
);
}
template
<
class
ConstIter
,
class
F
>
auto
mappedConstIterator
(
ConstIter
it
,
F
const
*
f
)
{
using
const_iterator
=
Impl
::
MappedRangeIterator
<
ConstIter
,
F
>
;
return
const_iterator
(
it
,
f
);
}
}
// end namespace AMDiS
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment