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