-
Notifications
You must be signed in to change notification settings - Fork 11
Rework expressions framework, with some improvements #439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
41dcd54
Add a base class for expressions
bartgol 651ba98
Make existing expressions inherit from the base class
bartgol 65bbc9a
Beef up expressions unit testing
bartgol fc37881
Upgrade (and rename) CmpExpression to support logical and/or
bartgol d33d2aa
Fix missing pfor for rank-4 expression evaluation
bartgol 9732417
Fix ekat_test_config.h
bartgol File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| #ifndef EKAT_EXPRESSION_BASE_HPP | ||
| #define EKAT_EXPRESSION_BASE_HPP | ||
|
|
||
| #include "ekat_expression_traits.hpp" | ||
|
|
||
| #include <Kokkos_Core.hpp> | ||
|
|
||
| namespace ekat { | ||
|
|
||
| // A base class for expressions | ||
| template<typename Derived> | ||
| class ExpressionBase { | ||
| public: | ||
| using expression_tag = void; // Add tag to be used for SFINAE and meta-utils | ||
|
|
||
| ExpressionBase () { | ||
| static_assert(is_expr_v<Derived>, | ||
| "Template arg is NOT an expression. Ensure Derived inherits from ExpressionBase."); | ||
| } | ||
|
|
||
| Derived& cast () { return *static_cast<Derived*>(this); } | ||
| const Derived& cast () const { return *static_cast<const Derived*>(this); } | ||
|
|
||
| ExpressionBase<Derived>& as_base () { return *this; } | ||
| const ExpressionBase<Derived>& as_base () const { return *this; } | ||
|
|
||
| static constexpr int rank() { return Derived::rank(); } | ||
|
|
||
| int extent (int i) const { return cast().extent(i); } | ||
|
|
||
| template<typename... Args> | ||
| KOKKOS_INLINE_FUNCTION | ||
| auto eval (Args... args) const | ||
| { | ||
| return cast().eval(args...); | ||
| } | ||
| }; | ||
|
|
||
| } // namespace ekat | ||
|
|
||
| #endif // EKAT_EXPRESSION_BASE_HPP |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| #ifndef EKAT_EXPRESSION_BINARY_PREDICATE_HPP | ||
| #define EKAT_EXPRESSION_BINARY_PREDICATE_HPP | ||
|
|
||
| #include "ekat_expression_base.hpp" | ||
|
|
||
| namespace ekat { | ||
|
|
||
| enum class BinaryPredicateOp : int { | ||
| EQ, // == | ||
| NE, // != | ||
| GT, // > | ||
| GE, // >= | ||
| LT, // < | ||
| LE, // <= | ||
| AND, // logical and | ||
| OR // logical or | ||
| }; | ||
|
|
||
| template<typename ELeft, typename ERight, BinaryPredicateOp Op> | ||
| class BinaryPredicateExpression : public ExpressionBase<BinaryPredicateExpression<ELeft,ERight,Op>> { | ||
| public: | ||
|
bartgol marked this conversation as resolved.
|
||
| static constexpr bool expr_l = is_expr_v<ELeft>; | ||
| static constexpr bool expr_r = is_expr_v<ERight>; | ||
|
|
||
| using return_left_t = eval_return_t<ELeft>; | ||
| using return_right_t = eval_return_t<ERight>; | ||
| // The return type is a logical-like, but same for all Op's, so just use one | ||
| using return_type = decltype(std::declval<return_left_t>()==std::declval<return_right_t>()); | ||
|
|
||
| // Don't create an expression from builtin types, just compare them! | ||
| static_assert(expr_l or expr_r, | ||
| "[BinaryPredicateExpression] At least one between ELeft and ERight must be an Expression type.\n"); | ||
|
|
||
| BinaryPredicateExpression (const ELeft& left, | ||
| const ERight& right) | ||
| : m_left(left) | ||
| , m_right(right) | ||
| { | ||
| // Nothing to do here | ||
| } | ||
|
|
||
| static constexpr int rank() { | ||
| if constexpr (expr_l) { | ||
| if constexpr (expr_r) { | ||
| static_assert(ELeft::rank()==ERight::rank(), | ||
| "[BinaryPredicateExpression] Error! ELeft and ERight are Expression types of different rank.\n"); | ||
| } | ||
| return ELeft::rank(); | ||
| } else if constexpr (expr_r) { | ||
| return ERight::rank(); | ||
| } else { | ||
| return 0; | ||
| } | ||
| } | ||
|
|
||
| int extent (int i) const { | ||
| if constexpr (expr_l) | ||
| return m_left.extent(i); | ||
| else | ||
| return m_right.extent(i); | ||
| } | ||
|
|
||
| template<typename... Args> | ||
| KOKKOS_INLINE_FUNCTION | ||
| return_type eval(Args... args) const { | ||
| if constexpr (expr_l) { | ||
| if constexpr (expr_r) | ||
| return eval_impl(m_left.eval(args...), m_right.eval(args...)); | ||
| else | ||
| return eval_impl(m_left.eval(args...), m_right); | ||
| } else if constexpr (expr_r) { | ||
| return eval_impl(m_left, m_right.eval(args...)); | ||
| } else { | ||
| return eval_impl(m_left, m_right); | ||
| } | ||
| } | ||
|
|
||
| protected: | ||
|
|
||
| template<typename... Args> | ||
| KOKKOS_INLINE_FUNCTION | ||
| return_type eval_impl(const return_left_t& l, const return_right_t& r) const { | ||
| if constexpr (Op==BinaryPredicateOp::EQ) | ||
| return l==r; | ||
| else if constexpr (Op==BinaryPredicateOp::NE) | ||
| return l!=r; | ||
| else if constexpr (Op==BinaryPredicateOp::GT) | ||
| return l>r; | ||
| else if constexpr (Op==BinaryPredicateOp::GE) | ||
| return l>=r; | ||
| else if constexpr (Op==BinaryPredicateOp::LT) | ||
| return l<r; | ||
| else if constexpr (Op==BinaryPredicateOp::LE) | ||
| return l<=r; | ||
| else if constexpr (Op==BinaryPredicateOp::AND) | ||
| return l and r; | ||
| else | ||
| return l or r; | ||
| } | ||
|
|
||
| ELeft m_left; | ||
| ERight m_right; | ||
| }; | ||
|
|
||
| // Overload comparison operators | ||
| #define EKAT_GEN_BIN_PREDICATE_EXPR(OP,ENUM) \ | ||
| template<typename T1, typename T2, \ | ||
| typename = std::enable_if_t<is_any_expr_v<T1,T2>>> \ | ||
| KOKKOS_INLINE_FUNCTION \ | ||
| auto operator OP (const T1& l, const T2& r) \ | ||
| { \ | ||
| using ret_t = BinaryPredicateExpression<get_expr_node_t<T1>, \ | ||
| get_expr_node_t<T2>, \ | ||
| BinaryPredicateOp::ENUM>; \ | ||
| \ | ||
| return ret_t(get_expr_node(l),get_expr_node(r)); \ | ||
| } | ||
|
|
||
| EKAT_GEN_BIN_PREDICATE_EXPR(==,EQ); | ||
| EKAT_GEN_BIN_PREDICATE_EXPR(!=,NE); | ||
| EKAT_GEN_BIN_PREDICATE_EXPR(> ,GT); | ||
| EKAT_GEN_BIN_PREDICATE_EXPR(>=,GE); | ||
| EKAT_GEN_BIN_PREDICATE_EXPR(< ,LT); | ||
| EKAT_GEN_BIN_PREDICATE_EXPR(<=,LE); | ||
| EKAT_GEN_BIN_PREDICATE_EXPR(&&,AND); | ||
| EKAT_GEN_BIN_PREDICATE_EXPR(||,OR); | ||
|
|
||
| #undef EKAT_GEN_BIN_PREDICATE_EXPR | ||
|
|
||
| } // namespace ekat | ||
|
|
||
| #endif // EKAT_EXPRESSION_BINARY_PREDICATE_HPP | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.