Skip to content

Commit 3891767

Browse files
authored
Merge pull request #240 from thelfer/236-allow-assign-algorithm-to-work-on-temporary-views
Fix Issue #236
2 parents bae30f1 + 9196f07 commit 3891767

6 files changed

Lines changed: 109 additions & 26 deletions

File tree

docs/web/release-notes-3.2.md

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,17 +227,56 @@ This following code now generates a view rather than an evaluator:
227227
auto v = f.view() | as_array<2>;
228228
~~~~
229229

230-
In comparison, to achieve the same behaviour in Version 3.1, creation of
231-
an intermediate variable was required, as follows:
230+
> By comparison, to achieve the same behaviour in Version 3.1, creation of
231+
> an intermediate variable was required, as follows:
232+
>
233+
> ~~~~{.cxx}
234+
> // creating an array view in Version 3.1:
235+
> auto f_view = f.view();
236+
> auto v = f_view | as_array<2>;
237+
> ~~~~
238+
239+
## Temporary views can be used in "assignement" `operator|` and `assign` function
240+
241+
In Version 3.1, "assignement" `operator|` and `assign` function did not
242+
accept temporaries.
243+
244+
This behaviour has been changed in Version 3.2 which allows a more
245+
direct code:
246+
247+
~~~~{.cxx}
248+
f2 | as_scalar | (f | as_scalar); // "assignement" operator|
249+
~~~~
250+
251+
or equivalently:
232252

233253
~~~~{.cxx}
234-
// creating an array view in Version 3.1:
235-
auto f_view = f.view();
236-
auto v = f_view | as_array<2>;
254+
assign(ctx, f | as_scalar, f2 | as_scalar);
237255
~~~~
238256

257+
> By comparison, Version 3.1 would have forced to store the view resulting
258+
> from `f | as_scalar` into a temporary as follows:
259+
>
260+
> ~~~~{.cxx}
261+
> auto tmp = f | as_scalar;
262+
> assign(ctx, tmp, f2 | as_scalar);
263+
> ~~~~
264+
239265
# Issues fixed
240266
267+
## Issue 236: [mgis-function] Allow "assignement" operator | and `assign` algorithm to work on temporary views
268+
269+
270+
For more details, see <https://github.com/thelfer/MFrontGenericInterfaceSupport/issues/236>
271+
272+
## Issue #233: [cmake] Add a build-tests target
273+
274+
For more details, see <https://github.com/thelfer/MFrontGenericInterfaceSupport/issues/233>
275+
276+
## 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
277+
278+
For more details, see <https://github.com/thelfer/MFrontGenericInterfaceSupport/issues/232>
279+
241280
## 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
242281
243282
For more details, see <https://github.com/thelfer/MFrontGenericInterfaceSupport/issues/227>

include/MGIS/Function/Algorithms.hxx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,18 @@ namespace mgis::function {
124124
* \param[in] e: right hand side
125125
*/
126126
template <ExecutionPolicyConceptConcept ExecutionPolicy,
127-
typename FunctionType,
127+
ViewableFunctionArgumentConcept FunctionType,
128128
EvaluatorConcept EvaluatorType>
129129
[[nodiscard]] constexpr bool assign(AbstractErrorHandler&,
130-
FunctionType&,
130+
FunctionType&&,
131131
const ExecutionPolicy,
132132
const EvaluatorType) //
133133
requires(
134-
(internals::isEvaluatorAssignableToFunction<EvaluatorType, FunctionType>)&&(
135-
(LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
136-
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>)));
134+
(internals::isEvaluatorAssignableToFunction<
135+
EvaluatorType,
136+
std::decay_t<FunctionType>>)&& //
137+
((LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
138+
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>)));
137139
/*!
138140
* \brief assign the evaluator to a function
139141
* \param[in] ctx: execution context
@@ -160,12 +162,15 @@ namespace mgis::function {
160162
* \param[in] lhs: left hand side
161163
* \param[in] e: right hand side
162164
*/
163-
template <typename FunctionType, EvaluatorConcept EvaluatorType>
165+
template <ViewableFunctionArgumentConcept FunctionType,
166+
EvaluatorConcept EvaluatorType>
164167
[[nodiscard]] constexpr bool assign(AbstractErrorHandler&,
165-
FunctionType&,
168+
FunctionType&&,
166169
const EvaluatorType) //
167170
requires(
168-
(internals::isEvaluatorAssignableToFunction<EvaluatorType, FunctionType>)&& //
171+
(internals::isEvaluatorAssignableToFunction<
172+
EvaluatorType,
173+
std::decay_t<FunctionType>>)&& //
169174
((LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
170175
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>)));
171176
/*!

include/MGIS/Function/Algorithms.ixx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,14 +556,16 @@ namespace mgis::function {
556556
#ifdef MGIS_HAS_STL_PARALLEL_ALGORITHMS
557557

558558
template <ExecutionPolicyConceptConcept ExecutionPolicy,
559-
typename FunctionType,
559+
ViewableFunctionArgumentConcept FunctionType,
560560
EvaluatorConcept EvaluatorType>
561561
constexpr bool assign(AbstractErrorHandler& ctx,
562-
FunctionType& f,
562+
FunctionType&& f,
563563
const ExecutionPolicy policy,
564564
const EvaluatorType e) //
565565
requires(
566-
(internals::isEvaluatorAssignableToFunction<EvaluatorType, FunctionType>)&& //
566+
(internals::isEvaluatorAssignableToFunction<
567+
EvaluatorType,
568+
std::decay_t<FunctionType>>)&& //
567569
((LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
568570
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>))) {
569571
if (!areEquivalent(getSpace(f), getSpace(e))) {
@@ -587,12 +589,15 @@ namespace mgis::function {
587589

588590
#endif /* MGIS_HAS_STL_PARALLEL_ALGORITHMS */
589591

590-
template <typename FunctionType, EvaluatorConcept EvaluatorType>
592+
template <ViewableFunctionArgumentConcept FunctionType,
593+
EvaluatorConcept EvaluatorType>
591594
constexpr bool assign(AbstractErrorHandler& ctx,
592-
FunctionType& f,
595+
FunctionType&& f,
593596
const EvaluatorType e) //
594597
requires(
595-
(internals::isEvaluatorAssignableToFunction<EvaluatorType, FunctionType>)&& //
598+
(internals::isEvaluatorAssignableToFunction<
599+
EvaluatorType,
600+
std::decay_t<FunctionType>>)&& //
596601
((LinearElementSpaceConcept<evaluator_space<EvaluatorType>>) ||
597602
(LinearQuadratureSpaceConcept<evaluator_space<EvaluatorType>>))) {
598603
if (!areEquivalent(getSpace(f), getSpace(e))) {

include/MGIS/Function/FunctionConcept.hxx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,10 +458,11 @@ namespace mgis::function {
458458
* \param[in] e: evaluator
459459
* \param[in] f: function
460460
*/
461-
template <EvaluatorConcept EvaluatorType, FunctionConcept FunctionType>
462-
[[nodiscard]] bool operator|(EvaluatorType, FunctionType&) requires(
461+
template <EvaluatorConcept EvaluatorType,
462+
ViewableFunctionArgumentConcept FunctionType>
463+
[[nodiscard]] bool operator|(EvaluatorType, FunctionType&&) requires(
463464
std::same_as<evaluator_space<EvaluatorType>,
464-
function_space<FunctionType>>);
465+
function_space<std::decay_t<FunctionType>>>);
465466
#endif
466467

467468
} // end of namespace mgis::function

include/MGIS/Function/FunctionConcept.ixx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,18 @@ namespace mgis::function::internals {
3737

3838
namespace mgis::function {
3939

40-
template <EvaluatorConcept EvaluatorType, FunctionConcept FunctionType>
41-
bool operator|(EvaluatorType e, FunctionType& f) requires(
40+
template <EvaluatorConcept EvaluatorType,
41+
ViewableFunctionArgumentConcept FunctionType>
42+
bool operator|(EvaluatorType e, FunctionType&& f) requires(
4243
std::same_as<evaluator_space<EvaluatorType>,
43-
function_space<FunctionType>>) {
44+
function_space<std::decay_t<FunctionType>>>) {
4445
Context ctx;
45-
return assign(ctx, f, e);
46+
if constexpr (LightweightFunctionConcept<std::decay_t<FunctionType>>) {
47+
auto tmp = f; // always make a copy to allow using rvalues
48+
return assign(ctx, tmp, e);
49+
} else {
50+
return assign(ctx, f, e);
51+
}
4652
} // end of operator |
4753

4854
} // end of namespace mgis::function

tests/FunctionTest.cxx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#endif
1111

1212
#include <cmath>
13+
#include <tuple>
1314
#include <memory>
1415
#include <cstdlib>
1516
#include <iostream>
@@ -233,6 +234,7 @@ struct FunctionTest final : public tfel::tests::TestCase {
233234
this->test11();
234235
this->test12();
235236
this->test13();
237+
this->test14();
236238
return this->result;
237239
}
238240

@@ -766,6 +768,31 @@ struct FunctionTest final : public tfel::tests::TestCase {
766768
TFEL_TESTS_STATIC_ASSERT(check_value(values[3], 3));
767769
#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */
768770
} // end of test13
771+
void test14() {
772+
#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS
773+
using namespace mgis;
774+
using namespace mgis::function;
775+
auto check_value = [](const real& a, const real b) constexpr->bool {
776+
constexpr auto eps = real{1e-12};
777+
auto local_abs = [](const real r) { return r > 0 ? r : -r; };
778+
return local_abs(a - b) < eps;
779+
};
780+
auto ctx = Context{};
781+
auto space = BasicLinearSpace{2};
782+
auto f = Function<BasicLinearSpace>{space, 1};
783+
auto f2 = Function<BasicLinearSpace>{space, 1};
784+
auto f3 = Function<BasicLinearSpace>{space, 1};
785+
std::tie(f(0)[0], f(1)[0]) = std::tuple{5, 12};
786+
const auto ok = f | as_scalar | (f2 | as_scalar);
787+
const auto ok2 = assign(ctx, f3 | as_scalar, f | as_scalar);
788+
TFEL_TESTS_ASSERT(ok);
789+
TFEL_TESTS_ASSERT(ok2);
790+
TFEL_TESTS_ASSERT(check_value(f2(0)[0], 5));
791+
TFEL_TESTS_ASSERT(check_value(f2(1)[0], 12));
792+
TFEL_TESTS_ASSERT(check_value(f3(0)[0], 5));
793+
TFEL_TESTS_ASSERT(check_value(f3(1)[0], 12));
794+
#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */
795+
}
769796
};
770797

771798
TFEL_TESTS_GENERATE_PROXY(FunctionTest, "FunctionTest");

0 commit comments

Comments
 (0)