Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:17:13

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file orange/univ/detail/InfixEvaluator.hh
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  * Evaluate an explicit infix logical expression applied to a vector of senses.
0022  *
0023  * Explicit infix notation explicitly spells out the intersection operator,
0024  * i.e., \c logic::land wehereas implicit infix notation omits it.
0025  *
0026  * These two expressions are equivalent:
0027  * Implicit notation: A(BC | DE)
0028  * Explicit notation: A&((B&C) | (D&E))
0029  */
0030 class InfixEvaluator
0031 {
0032   public:
0033     //@{
0034     //! \name Type aliases
0035     using SpanConstLogic = LdgSpan<logic_int const>;
0036     //@}
0037 
0038   public:
0039     // Construct with a view to some logic definition
0040     explicit CELER_FORCEINLINE_FUNCTION InfixEvaluator(SpanConstLogic logic);
0041 
0042     // Evaluate a logical expression, substituting bools from the vector
0043     template<class F>
0044     inline CELER_FUNCTION bool operator()(F&& eval_sense) const;
0045 
0046   private:
0047     // Short-circuit evaluation of the second operand
0048     inline CELER_FUNCTION size_type short_circuit(size_type i) const;
0049 
0050     //// DATA ////
0051 
0052     SpanConstLogic logic_;
0053 };
0054 
0055 //---------------------------------------------------------------------------//
0056 /*!
0057  * Construct with a view to some logic definition.
0058  */
0059 CELER_FUNCTION InfixEvaluator::InfixEvaluator(SpanConstLogic logic)
0060     : logic_(logic)
0061 {
0062     CELER_EXPECT(!logic_.empty());
0063 }
0064 
0065 //---------------------------------------------------------------------------//
0066 /*!
0067  * Evaluate a logical expression, substituting bools from the vector.
0068  *
0069  * The functor eval_sense takes as argument a \c celeritas::FaceId present in
0070  * the logic expression passed to the constructor and returns a boolean value
0071  * matching \c celeritas::Sense
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             // negation of a sub-expression is not supported
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  * Short-circuit evaluation of the second operand.
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 }  // namespace detail
0145 }  // namespace celeritas