Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 09:03:18

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file orange/univ/detail/InfixEvaluator.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Assert.hh"
0010 #include "corecel/cont/Span.hh"
0011 #include "corecel/data/LdgIterator.hh"
0012 #include "orange/OrangeTypes.hh"
0013 
0014 namespace celeritas
0015 {
0016 namespace detail
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Evaluate an explicit infix logical expression applied to a vector of senses.
0021  *
0022  * Explicit infix notation explicitly spells out the intersection operator,
0023  * i.e., \c logic::land wehereas implicit infix notation omits it.
0024  *
0025  * These two expressions are equivalent:
0026  * Implicit notation: A(BC | DE)
0027  * Explicit notation: A&((B&C) | (D&E))
0028  */
0029 class InfixEvaluator
0030 {
0031   public:
0032     //@{
0033     //! \name Type aliases
0034     using SpanConstLogic = LdgSpan<logic_int const>;
0035     //@}
0036 
0037   public:
0038     // Construct with a view to some logic definition
0039     explicit CELER_FORCEINLINE_FUNCTION InfixEvaluator(SpanConstLogic logic);
0040 
0041     // Evaluate a logical expression, substituting bools from the vector
0042     template<class F>
0043     inline CELER_FUNCTION bool operator()(F&& eval_sense) const;
0044 
0045   private:
0046     // Short-circuit evaluation of the second operand
0047     inline CELER_FUNCTION size_type short_circuit(size_type i) const;
0048 
0049     //// DATA ////
0050 
0051     SpanConstLogic logic_;
0052 };
0053 
0054 //---------------------------------------------------------------------------//
0055 /*!
0056  * Construct with a view to some logic definition.
0057  */
0058 CELER_FUNCTION InfixEvaluator::InfixEvaluator(SpanConstLogic logic)
0059     : logic_(logic)
0060 {
0061     CELER_EXPECT(!logic_.empty());
0062 }
0063 
0064 //---------------------------------------------------------------------------//
0065 /*!
0066  * Evaluate a logical expression, substituting bools from the vector.
0067  *
0068  * The functor eval_sense takes as argument a \c celeritas::FaceId present in
0069  * the logic expression passed to the constructor and returns a boolean value
0070  * matching \c celeritas::Sense
0071  */
0072 template<class F>
0073 CELER_FUNCTION bool InfixEvaluator::operator()(F&& eval_sense) const
0074 {
0075     bool result{true};
0076 
0077     int par_depth{0};
0078     size_type i{0};
0079     while (i < logic_.size())
0080     {
0081         if (logic_int const lgc{logic_[i]}; !logic::is_operator_token(lgc))
0082         {
0083             result = static_cast<bool>(eval_sense(FaceId{lgc}));
0084         }
0085         else if ((lgc == logic::lor && result)
0086                  || (lgc == logic::land && !result))
0087         {
0088             if (par_depth == 0)
0089             {
0090                 break;
0091             }
0092             --par_depth;
0093             i = this->short_circuit(i);
0094         }
0095         else if (lgc == logic::ltrue)
0096         {
0097             result = true;
0098         }
0099         else if (lgc == logic::lopen)
0100         {
0101             ++par_depth;
0102         }
0103         else if (lgc == logic::lclose)
0104         {
0105             CELER_ASSERT(par_depth > 0);
0106             --par_depth;
0107         }
0108         else if (lgc == logic::lnot)
0109         {
0110             // negation of a sub-expression is not supported
0111             CELER_ASSUME(i + 1 < logic_.size());
0112             CELER_EXPECT(!logic::is_operator_token(logic_[i + 1]));
0113             result = !static_cast<bool>(eval_sense(FaceId{logic_[++i]}));
0114         }
0115         ++i;
0116     }
0117     return result;
0118 }
0119 
0120 //---------------------------------------------------------------------------//
0121 /*!
0122  * Short-circuit evaluation of the second operand.
0123  */
0124 CELER_FUNCTION size_type InfixEvaluator::short_circuit(size_type i) const
0125 {
0126     int par_depth{1};
0127     while (par_depth > 0)
0128     {
0129         CELER_ASSUME(i + 1 < logic_.size());
0130         if (logic_int lgc = logic_[++i]; lgc == logic::lopen)
0131         {
0132             ++par_depth;
0133         }
0134         else if (lgc == logic::lclose)
0135         {
0136             --par_depth;
0137         }
0138     }
0139     return i;
0140 }
0141 
0142 //---------------------------------------------------------------------------//
0143 }  // namespace detail
0144 }  // namespace celeritas