File indexing completed on 2025-01-30 10:17:13
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include "corecel/Assert.hh"
0011 #include "corecel/cont/Span.hh"
0012 #include "corecel/data/LdgIterator.hh"
0013 #include "orange/OrangeTypes.hh"
0014
0015 namespace celeritas
0016 {
0017 namespace detail
0018 {
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 class InfixEvaluator
0031 {
0032 public:
0033
0034
0035 using SpanConstLogic = LdgSpan<logic_int const>;
0036
0037
0038 public:
0039
0040 explicit CELER_FORCEINLINE_FUNCTION InfixEvaluator(SpanConstLogic logic);
0041
0042
0043 template<class F>
0044 inline CELER_FUNCTION bool operator()(F&& eval_sense) const;
0045
0046 private:
0047
0048 inline CELER_FUNCTION size_type short_circuit(size_type i) const;
0049
0050
0051
0052 SpanConstLogic logic_;
0053 };
0054
0055
0056
0057
0058
0059 CELER_FUNCTION InfixEvaluator::InfixEvaluator(SpanConstLogic logic)
0060 : logic_(logic)
0061 {
0062 CELER_EXPECT(!logic_.empty());
0063 }
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 template<class F>
0074 CELER_FUNCTION bool InfixEvaluator::operator()(F&& eval_sense) const
0075 {
0076 bool result{true};
0077
0078 int par_depth{0};
0079 size_type i{0};
0080 while (i < logic_.size())
0081 {
0082 if (logic_int const lgc{logic_[i]}; !logic::is_operator_token(lgc))
0083 {
0084 result = eval_sense(FaceId{lgc});
0085 }
0086 else if ((lgc == logic::lor && result)
0087 || (lgc == logic::land && !result))
0088 {
0089 if (par_depth == 0)
0090 {
0091 break;
0092 }
0093 --par_depth;
0094 i = this->short_circuit(i);
0095 }
0096 else if (lgc == logic::ltrue)
0097 {
0098 result = true;
0099 }
0100 else if (lgc == logic::lopen)
0101 {
0102 ++par_depth;
0103 }
0104 else if (lgc == logic::lclose)
0105 {
0106 CELER_ASSERT(par_depth > 0);
0107 --par_depth;
0108 }
0109 else if (lgc == logic::lnot)
0110 {
0111
0112 CELER_ASSUME(i + 1 < logic_.size());
0113 CELER_EXPECT(!logic::is_operator_token(logic_[i + 1]));
0114 result = !eval_sense(FaceId{logic_[++i]});
0115 }
0116 ++i;
0117 }
0118 return result;
0119 }
0120
0121
0122
0123
0124
0125 CELER_FUNCTION size_type InfixEvaluator::short_circuit(size_type i) const
0126 {
0127 int par_depth{1};
0128 while (par_depth > 0)
0129 {
0130 CELER_ASSUME(i + 1 < logic_.size());
0131 if (logic_int lgc = logic_[++i]; lgc == logic::lopen)
0132 {
0133 ++par_depth;
0134 }
0135 else if (lgc == logic::lclose)
0136 {
0137 --par_depth;
0138 }
0139 }
0140 return i;
0141 }
0142
0143
0144 }
0145 }