Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-13 10:48:05

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/orangeinp/detail/NodeReplacer.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <iostream>
0010 #include <ostream>
0011 #include <variant>
0012 #include <vector>
0013 
0014 namespace celeritas
0015 {
0016 namespace orangeinp
0017 {
0018 namespace detail
0019 {
0020 //---------------------------------------------------------------------------//
0021 /*!
0022  * Add a node ID and its "replaced" value.
0023  *
0024  * This implementation detail of the CSG simplify algorithm updates the
0025  * dependent logical state from a single node.
0026  *
0027  * \return whether a change to the state took place
0028  */
0029 class NodeReplacer
0030 {
0031   public:
0032     enum NodeRepl
0033     {
0034         unvisited,
0035         unknown,
0036         known_false,
0037         known_true
0038     };
0039 
0040     //!@{
0041     //! \name Type aliases
0042     using VecRepl = std::vector<NodeRepl>;
0043     //!@}
0044 
0045   public:
0046     // Construct with pointers to the state and the node being replaced
0047     inline NodeReplacer(VecRepl* state, NodeId n);
0048 
0049     // Simplify node types that reference other nodes
0050     inline bool operator()(Aliased const& n);
0051     inline bool operator()(Negated const& n);
0052     inline bool operator()(Joined const& n);
0053 
0054     // Check that replacement matches our stored boolean
0055     inline bool operator()(True const&);
0056     inline bool operator()(False const&);
0057 
0058     // Literals don't propagate information
0059     inline bool operator()(Surface const&) { return {}; }
0060 
0061   private:
0062     VecRepl* state_;
0063     NodeRepl repl_;
0064 
0065     // Update the given node to the replacement value
0066     inline bool update(NodeId n, NodeRepl repl);
0067 };
0068 
0069 //---------------------------------------------------------------------------//
0070 // INLINE DEFINITIONS
0071 //---------------------------------------------------------------------------//
0072 /*!
0073  * Construct with pointer to the state and the replacement value.
0074  *
0075  * For now the replacement must be a boolean.
0076  */
0077 NodeReplacer::NodeReplacer(VecRepl* state, NodeId n) : state_{state}
0078 {
0079     CELER_EXPECT(state_);
0080     repl_ = (*state_)[n.unchecked_get()];
0081 }
0082 
0083 //---------------------------------------------------------------------------//
0084 /*!
0085  * Check that the replacement node matches this state.
0086  */
0087 bool NodeReplacer::operator()(True const&)
0088 {
0089     CELER_ASSERT(repl_ == NodeRepl::known_true);
0090     return false;
0091 }
0092 
0093 //---------------------------------------------------------------------------//
0094 /*!
0095  * Check that the replacement node matches this state.
0096  */
0097 bool NodeReplacer::operator()(False const&)
0098 {
0099     CELER_ASSERT(repl_ == NodeRepl::known_false);
0100     return false;
0101 }
0102 
0103 //---------------------------------------------------------------------------//
0104 /*!
0105  * Replace the target of an aliased node.
0106  *
0107  * Aliasing a node implies the alias has the same value.
0108  */
0109 bool NodeReplacer::operator()(Aliased const& n)
0110 {
0111     return this->update(n.node, repl_);
0112 }
0113 
0114 //---------------------------------------------------------------------------//
0115 /*!
0116  * Update the target of a negated node.
0117  *
0118  * Negating a node implies its child has the opposite value.
0119  */
0120 bool NodeReplacer::operator()(Negated const& n)
0121 {
0122     NodeRepl repl = [r = repl_] {
0123         switch (r)
0124         {
0125             case NodeRepl::known_false:
0126                 return NodeRepl::known_true;
0127             case NodeRepl::known_true:
0128                 return NodeRepl::known_false;
0129             default:
0130                 return r;
0131         }
0132     }();
0133 
0134     return this->update(n.node, repl);
0135 }
0136 
0137 //---------------------------------------------------------------------------//
0138 /*!
0139  * Some 'join' operations imply requirements for the daughters.
0140  *
0141  * If this node is "true" and it uses an "and" operation, all daughters must be
0142  * true. Likewise, "false" with "or" implies all daughters are false.
0143  */
0144 bool NodeReplacer::operator()(Joined const& n)
0145 {
0146     NodeRepl repl = repl_;
0147     if ((repl == NodeRepl::known_true && n.op == op_or)
0148         || (repl == NodeRepl::known_false && n.op == op_and))
0149     {
0150         // ... but with this combination we can't prove
0151         // anything about the children
0152         repl = NodeRepl::unknown;
0153     }
0154 
0155     bool updated{false};
0156     for (NodeId d : n.nodes)
0157     {
0158         // NOTE: don't write as "updated || this->update(...)" dude to short
0159         // circuit logic
0160         bool daughter_updated = this->update(d, repl);
0161         updated = updated || daughter_updated;
0162     }
0163     return updated;
0164 }
0165 
0166 //---------------------------------------------------------------------------//
0167 /*!
0168  * Update the given node to the replacement value.
0169  */
0170 bool NodeReplacer::update(NodeId n, NodeRepl repl)
0171 {
0172     CELER_EXPECT(n < state_->size());
0173     NodeRepl& dest = (*state_)[n.unchecked_get()];
0174     CELER_VALIDATE(
0175         !(dest == NodeRepl::known_true && repl == NodeRepl::known_false)
0176             && !(dest == NodeRepl::known_false && repl == NodeRepl::known_true),
0177         << "encountered logical contradiction in CSG operation");
0178     if (dest < repl)
0179     {
0180         dest = repl;
0181         return true;
0182     }
0183     return false;
0184 }
0185 
0186 //---------------------------------------------------------------------------//
0187 }  // namespace detail
0188 }  // namespace orangeinp
0189 }  // namespace celeritas