Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:05:55

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