Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:24:49

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