![]() |
|
|||
File indexing completed on 2025-07-01 08:45:37
0001 //----------------------------------*-C++-*----------------------------------// 0002 // Copyright 2021-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/LogicStack.hh 0007 //---------------------------------------------------------------------------// 0008 #pragma once 0009 0010 #include "corecel/Assert.hh" 0011 #include "corecel/Types.hh" 0012 0013 namespace celeritas 0014 { 0015 namespace detail 0016 { 0017 //---------------------------------------------------------------------------// 0018 /*! 0019 * Simple, fixed-max-size (no heap allocation) stack. 0020 * 0021 * This uses a bit field where the "top" of the stack is the least significant 0022 * bit. 0023 * 0024 * For a simple shape (the intersection of surfaces+senses), the max stack 0025 * depth is 1. For a combination of those, the stack depth is 2. This logic 0026 * stack can hold up to 32 entries (minimum size of size_type). 0027 * 0028 * The underlying code is highly optimized. For example, calling 'apply_and' 0029 * inside the 'evaluate' function (on GCC 5 with -O2) results in: \verbatim 0030 movl %eax, %ecx # stack, temp 0031 shrl %eax # D.44391 0032 andl $1, %ecx #, temp 0033 andl %ecx, %eax # temp, stack 0034 * \endverbatim 0035 * 0036 * Furthermore, and delightfully, if LogicStack is local to a function, and 0037 * assertions are off, all operations on size_ are optimized out completely! So 0038 * there's no penalty to adding that extra safety check. 0039 */ 0040 class LogicStack 0041 { 0042 public: 0043 //@{ 0044 //! Typedefs 0045 using value_type = bool; 0046 using size_type = celeritas::size_type; 0047 //@} 0048 0049 public: 0050 //! Default constructor 0051 CELER_FORCEINLINE_FUNCTION LogicStack() {} 0052 0053 //! Greatest number of boolean values allowed on the stack 0054 static CELER_CONSTEXPR_FUNCTION size_type max_stack_depth() 0055 { 0056 return sizeof(size_type) * 8; 0057 } 0058 0059 //// ACCESSORS //// 0060 0061 //! Number of elements on the stack 0062 CELER_FORCEINLINE_FUNCTION size_type size() const { return size_; } 0063 0064 // Whether any elements exist 0065 CELER_FORCEINLINE_FUNCTION bool empty() const; 0066 0067 // Access the top value of the stack 0068 CELER_FORCEINLINE_FUNCTION value_type top() const; 0069 0070 // Access a single bit (zero is deepest level of stack), used by ostream 0071 CELER_FORCEINLINE_FUNCTION value_type operator[](size_type index) const; 0072 0073 //// MUTATORS //// 0074 0075 // Push a boolean onto the stack 0076 CELER_FORCEINLINE_FUNCTION void push(value_type v); 0077 0078 // Pop a value off the stack 0079 CELER_FORCEINLINE_FUNCTION value_type pop(); 0080 0081 // Negate the value on the top of the stack 0082 CELER_FORCEINLINE_FUNCTION void apply_not(); 0083 0084 // Apply boolean 'and' to the top of the stack 0085 CELER_FORCEINLINE_FUNCTION void apply_and(); 0086 0087 // Apply boolean 'or' to the top of the stack 0088 CELER_FORCEINLINE_FUNCTION void apply_or(); 0089 0090 private: 0091 //! Get the least significant bit 0092 static CELER_CONSTEXPR_FUNCTION size_type lsb(size_type val) 0093 { 0094 return val & size_type(1); 0095 } 0096 0097 //! Shift right by one 0098 static CELER_CONSTEXPR_FUNCTION size_type shr(size_type val) 0099 { 0100 return val >> size_type(1); 0101 } 0102 0103 //! Shift left by one 0104 static CELER_CONSTEXPR_FUNCTION size_type shl(size_type val) 0105 { 0106 return val << size_type(1); 0107 } 0108 0109 private: 0110 //// DATA //// 0111 0112 size_type data_{0}; //!< Stack data 0113 size_type size_{0}; //!< Stack depth 0114 }; 0115 0116 //---------------------------------------------------------------------------// 0117 /*! 0118 * Whether the stack has any pushed values. 0119 */ 0120 CELER_FUNCTION bool LogicStack::empty() const 0121 { 0122 return size_ == size_type(0); 0123 } 0124 0125 //---------------------------------------------------------------------------// 0126 /*! 0127 * Access the top value of the stack. 0128 */ 0129 CELER_FUNCTION auto LogicStack::top() const -> value_type 0130 { 0131 CELER_EXPECT(!empty()); 0132 return LogicStack::lsb(data_); 0133 } 0134 0135 //---------------------------------------------------------------------------// 0136 /*! 0137 * Access a single bit (zero is deepest level of stack). 0138 */ 0139 CELER_FUNCTION auto LogicStack::operator[](size_type index) const -> value_type 0140 { 0141 CELER_EXPECT(index < size()); 0142 size_type shift = size() - index - size_type(1); 0143 return LogicStack::lsb(data_ >> shift); 0144 } 0145 0146 //---------------------------------------------------------------------------// 0147 /*! 0148 * Push a boolean onto the stack. 0149 */ 0150 CELER_FUNCTION void LogicStack::push(value_type v) 0151 { 0152 CELER_EXPECT(size() != max_stack_depth()); 0153 // Shift stack left and add least significant bit 0154 data_ = LogicStack::shl(data_) | LogicStack::lsb(v); 0155 // Size for DBC 0156 ++size_; 0157 } 0158 0159 //---------------------------------------------------------------------------// 0160 /*! 0161 * Pop a value off the stack. 0162 */ 0163 CELER_FUNCTION auto LogicStack::pop() -> value_type 0164 { 0165 CELER_EXPECT(!empty()); 0166 // Extract least significant bit 0167 value_type result = LogicStack::lsb(data_); 0168 // Shift right 0169 data_ = LogicStack::shr(data_); 0170 // Update size 0171 --size_; 0172 return result; 0173 } 0174 0175 //---------------------------------------------------------------------------// 0176 /*! 0177 * Negate the value on the top of the stack. 0178 */ 0179 CELER_FUNCTION void LogicStack::apply_not() 0180 { 0181 CELER_EXPECT(!empty()); 0182 data_ ^= size_type(1); 0183 } 0184 0185 //---------------------------------------------------------------------------// 0186 /*! 0187 * Apply boolean 'and' to the top of the stack. 0188 */ 0189 CELER_FUNCTION void LogicStack::apply_and() 0190 { 0191 CELER_EXPECT(size() >= size_type(2)); 0192 size_type temp = LogicStack::lsb(data_); 0193 data_ = LogicStack::shr(data_) & (temp | ~size_type(1)); 0194 --size_; 0195 } 0196 0197 //---------------------------------------------------------------------------// 0198 /*! 0199 * Apply boolean 'or' to the top of the stack. 0200 */ 0201 CELER_FUNCTION void LogicStack::apply_or() 0202 { 0203 CELER_EXPECT(size() >= size_type(2)); 0204 data_ = LogicStack::shr(data_) | LogicStack::lsb(data_); 0205 --size_; 0206 } 0207 0208 //---------------------------------------------------------------------------// 0209 } // namespace detail 0210 } // namespace celeritas
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |