Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions docs/web/release-notes-3.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,17 +227,56 @@ This following code now generates a view rather than an evaluator:
auto v = f.view() | as_array<2>;
~~~~

In comparison, to achieve the same behaviour in Version 3.1, creation of
an intermediate variable was required, as follows:
> By comparison, to achieve the same behaviour in Version 3.1, creation of
> an intermediate variable was required, as follows:
>
> ~~~~{.cxx}
> // creating an array view in Version 3.1:
> auto f_view = f.view();
> auto v = f_view | as_array<2>;
> ~~~~

## Temporary views can be used in "assignement" `operator|` and `assign` function

In Version 3.1, "assignement" `operator|` and `assign` function did not
accept temporaries.

This behaviour has been changed in Version 3.2 which allows a more
direct code:

~~~~{.cxx}
f2 | as_scalar | (f | as_scalar); // "assignement" operator|
~~~~

or equivalently:

~~~~{.cxx}
// creating an array view in Version 3.1:
auto f_view = f.view();
auto v = f_view | as_array<2>;
assign(ctx, f | as_scalar, f2 | as_scalar);
~~~~

> By comparison, Version 3.1 would have forced to store the view resulting
> from `f | as_scalar` into a temporary as follows:
>
> ~~~~{.cxx}
> auto tmp = f | as_scalar;
> assign(ctx, tmp, f2 | as_scalar);
> ~~~~

# Issues fixed

## Issue 236: [mgis-function] Allow "assignement" operator | and `assign` algorithm to work on temporary views

For more details, see <https://github.com/thelfer/MFrontGenericInterfaceSupport/issues/236>

## Issue #233: [cmake] Add a build-tests target

For more details, see <https://github.com/thelfer/MFrontGenericInterfaceSupport/issues/233>

## Issue 232: [mgis-function] add more constraint on the `assign` algorithm to detect if values of the function can be assigned to the values of the evaluator

For more details, see <https://github.com/thelfer/MFrontGenericInterfaceSupport/issues/232>

## Issue 227: [mgis-function] allow modifiers and views to take lightweigh functions views by copy, i.e. alleviate restrictions that views and modifiers can't operate on temporaries

For more details, see <https://github.com/thelfer/MFrontGenericInterfaceSupport/issues/227>
Expand Down
21 changes: 13 additions & 8 deletions include/MGIS/Function/Algorithms.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,18 @@ namespace mgis::function {
* \param[in] e: right hand side
*/
template <ExecutionPolicyConceptConcept ExecutionPolicy,
typename FunctionType,
ViewableFunctionArgumentConcept FunctionType,
EvaluatorConcept EvaluatorType>
[[nodiscard]] constexpr bool assign(AbstractErrorHandler&,
FunctionType&,
FunctionType&&,
const ExecutionPolicy,
const EvaluatorType) //
requires(
(internals::isEvaluatorAssignableToFunction<EvaluatorType, FunctionType>)&&(
(LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>)));
(internals::isEvaluatorAssignableToFunction<
EvaluatorType,
std::decay_t<FunctionType>>)&& //
((LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>)));
/*!
* \brief assign the evaluator to a function
* \param[in] ctx: execution context
Expand All @@ -160,12 +162,15 @@ namespace mgis::function {
* \param[in] lhs: left hand side
* \param[in] e: right hand side
*/
template <typename FunctionType, EvaluatorConcept EvaluatorType>
template <ViewableFunctionArgumentConcept FunctionType,
EvaluatorConcept EvaluatorType>
[[nodiscard]] constexpr bool assign(AbstractErrorHandler&,
FunctionType&,
FunctionType&&,
const EvaluatorType) //
requires(
(internals::isEvaluatorAssignableToFunction<EvaluatorType, FunctionType>)&& //
(internals::isEvaluatorAssignableToFunction<
EvaluatorType,
std::decay_t<FunctionType>>)&& //
((LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>)));
/*!
Expand Down
17 changes: 11 additions & 6 deletions include/MGIS/Function/Algorithms.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -556,14 +556,16 @@ namespace mgis::function {
#ifdef MGIS_HAS_STL_PARALLEL_ALGORITHMS

template <ExecutionPolicyConceptConcept ExecutionPolicy,
typename FunctionType,
ViewableFunctionArgumentConcept FunctionType,
EvaluatorConcept EvaluatorType>
constexpr bool assign(AbstractErrorHandler& ctx,
FunctionType& f,
FunctionType&& f,
const ExecutionPolicy policy,
const EvaluatorType e) //
requires(
(internals::isEvaluatorAssignableToFunction<EvaluatorType, FunctionType>)&& //
(internals::isEvaluatorAssignableToFunction<
EvaluatorType,
std::decay_t<FunctionType>>)&& //
((LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>))) {
if (!areEquivalent(getSpace(f), getSpace(e))) {
Expand All @@ -587,12 +589,15 @@ namespace mgis::function {

#endif /* MGIS_HAS_STL_PARALLEL_ALGORITHMS */

template <typename FunctionType, EvaluatorConcept EvaluatorType>
template <ViewableFunctionArgumentConcept FunctionType,
EvaluatorConcept EvaluatorType>
constexpr bool assign(AbstractErrorHandler& ctx,
FunctionType& f,
FunctionType&& f,
const EvaluatorType e) //
requires(
(internals::isEvaluatorAssignableToFunction<EvaluatorType, FunctionType>)&& //
(internals::isEvaluatorAssignableToFunction<
EvaluatorType,
std::decay_t<FunctionType>>)&& //
((LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>))) {
if (!areEquivalent(getSpace(f), getSpace(e))) {
Expand Down
7 changes: 4 additions & 3 deletions include/MGIS/Function/FunctionConcept.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -458,10 +458,11 @@ namespace mgis::function {
* \param[in] e: evaluator
* \param[in] f: function
*/
template <EvaluatorConcept EvaluatorType, FunctionConcept FunctionType>
[[nodiscard]] bool operator|(EvaluatorType, FunctionType&) requires(
template <EvaluatorConcept EvaluatorType,
ViewableFunctionArgumentConcept FunctionType>
[[nodiscard]] bool operator|(EvaluatorType, FunctionType&&) requires(
std::same_as<evaluator_space<EvaluatorType>,
function_space<FunctionType>>);
function_space<std::decay_t<FunctionType>>>);
#endif

} // end of namespace mgis::function
Expand Down
14 changes: 10 additions & 4 deletions include/MGIS/Function/FunctionConcept.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,18 @@ namespace mgis::function::internals {

namespace mgis::function {

template <EvaluatorConcept EvaluatorType, FunctionConcept FunctionType>
bool operator|(EvaluatorType e, FunctionType& f) requires(
template <EvaluatorConcept EvaluatorType,
ViewableFunctionArgumentConcept FunctionType>
bool operator|(EvaluatorType e, FunctionType&& f) requires(
std::same_as<evaluator_space<EvaluatorType>,
function_space<FunctionType>>) {
function_space<std::decay_t<FunctionType>>>) {
Context ctx;
return assign(ctx, f, e);
if constexpr (LightweightFunctionConcept<std::decay_t<FunctionType>>) {
auto tmp = f; // always make a copy to allow using rvalues
return assign(ctx, tmp, e);
} else {
return assign(ctx, f, e);
}
} // end of operator |

} // end of namespace mgis::function
Expand Down
27 changes: 27 additions & 0 deletions tests/FunctionTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#endif

#include <cmath>
#include <tuple>
#include <memory>
#include <cstdlib>
#include <iostream>
Expand Down Expand Up @@ -233,6 +234,7 @@ struct FunctionTest final : public tfel::tests::TestCase {
this->test11();
this->test12();
this->test13();
this->test14();
return this->result;
}

Expand Down Expand Up @@ -766,6 +768,31 @@ struct FunctionTest final : public tfel::tests::TestCase {
TFEL_TESTS_STATIC_ASSERT(check_value(values[3], 3));
#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */
} // end of test13
void test14() {
#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS
using namespace mgis;
using namespace mgis::function;
auto check_value = [](const real& a, const real b) constexpr->bool {
constexpr auto eps = real{1e-12};
auto local_abs = [](const real r) { return r > 0 ? r : -r; };
return local_abs(a - b) < eps;
};
auto ctx = Context{};
auto space = BasicLinearSpace{2};
auto f = Function<BasicLinearSpace>{space, 1};
auto f2 = Function<BasicLinearSpace>{space, 1};
auto f3 = Function<BasicLinearSpace>{space, 1};
std::tie(f(0)[0], f(1)[0]) = std::tuple{5, 12};
const auto ok = f | as_scalar | (f2 | as_scalar);
const auto ok2 = assign(ctx, f3 | as_scalar, f | as_scalar);
TFEL_TESTS_ASSERT(ok);
TFEL_TESTS_ASSERT(ok2);
TFEL_TESTS_ASSERT(check_value(f2(0)[0], 5));
TFEL_TESTS_ASSERT(check_value(f2(1)[0], 12));
TFEL_TESTS_ASSERT(check_value(f3(0)[0], 5));
TFEL_TESTS_ASSERT(check_value(f3(1)[0], 12));
#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */
}
};

TFEL_TESTS_GENERATE_PROXY(FunctionTest, "FunctionTest");
Expand Down
Loading