|
phdMesh Version of the Day
|
00001 /*------------------------------------------------------------------------*/ 00002 /* phdMesh : Parallel Heterogneous Dynamic unstructured Mesh */ 00003 /* Copyright (2007) Sandia Corporation */ 00004 /* */ 00005 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */ 00006 /* license for use of this work by or on behalf of the U.S. Government. */ 00007 /* */ 00008 /* This library is free software; you can redistribute it and/or modify */ 00009 /* it under the terms of the GNU Lesser General Public License as */ 00010 /* published by the Free Software Foundation; either version 2.1 of the */ 00011 /* License, or (at your option) any later version. */ 00012 /* */ 00013 /* This library is distributed in the hope that it will be useful, */ 00014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 00015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ 00016 /* Lesser General Public License for more details. */ 00017 /* */ 00018 /* You should have received a copy of the GNU Lesser General Public */ 00019 /* License along with this library; if not, write to the Free Software */ 00020 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ 00021 /* USA */ 00022 /*------------------------------------------------------------------------*/ 00028 #ifndef pddgeom_OctTree_hpp 00029 #define pddgeom_OctTree_hpp 00030 00031 #include <limits> 00032 #include <iosfwd> 00033 #include <util/Basics.hpp> 00034 #include <util/SimpleArrayOps.hpp> 00035 00036 namespace phdmesh { 00037 00038 class OctTreeKey ; 00039 00040 } 00041 00042 namespace std { 00043 00044 ostream & operator << ( ostream & , const phdmesh::OctTreeKey & ); 00045 00046 } 00047 00048 namespace phdmesh { 00049 00050 class OctTreeKey { 00051 public: 00052 typedef unsigned value_type ; 00053 enum { MaxDepth = 16 }; 00054 enum { MaskIndex = 0x0f }; 00055 enum { BitsPerIndex = 4 }; 00056 enum { BitsPerWord = std::numeric_limits<value_type>::digits }; 00057 enum { IndexPerWord = BitsPerWord / BitsPerIndex }; 00058 enum { NWord = MaxDepth / IndexPerWord }; 00059 enum { OKBits = StaticAssert< 0 == BitsPerWord % BitsPerIndex >::OK }; 00060 enum { OKWord = StaticAssert< 0 == MaxDepth % IndexPerWord >::OK }; 00061 private: 00062 value_type m_value[ NWord ]; 00063 public: 00064 00065 OctTreeKey() 00066 { Copy<NWord>( m_value , 0u ); } 00067 00068 OctTreeKey( const OctTreeKey & k ) 00069 { Copy<NWord>( m_value , k.m_value ); } 00070 00071 OctTreeKey & operator = ( const OctTreeKey & k ) 00072 { Copy<NWord>( m_value , k.m_value ); return *this ; } 00073 00074 bool operator == ( const OctTreeKey & k ) const 00075 { return Equal<NWord>( m_value , k.m_value ); } 00076 00077 bool operator != ( const OctTreeKey & k ) const 00078 { return Equal<NWord>( m_value , k.m_value ); } 00079 00080 bool operator < ( const OctTreeKey & k ) const 00081 { return Less<NWord>( m_value , k.m_value ); } 00082 00084 unsigned depth() const ; 00085 00089 template<unsigned Depth> unsigned index() const ; 00090 00092 unsigned index( const unsigned Depth ) const ; 00093 00095 template<unsigned D> OctTreeKey & clear_index() ; 00096 00098 OctTreeKey & clear_index( const unsigned Depth ); 00099 00101 template<unsigned D> OctTreeKey & set_index( const unsigned ); 00102 00104 OctTreeKey & set_index( const unsigned Depth , const unsigned ); 00105 00107 OctTreeKey & clear(); 00108 00110 OctTreeKey & set_maximum(); 00111 00113 const value_type * value() const { return m_value ; } 00114 00116 OctTreeKey & set_value( const value_type * ); 00117 00119 bool intersect( const OctTreeKey & k ) const ; 00120 00121 private: 00122 void throw_depth( const unsigned ) const ; 00123 void throw_index( const unsigned , const unsigned ) const ; 00124 }; 00125 00126 //---------------------------------------------------------------------- 00127 00130 OctTreeKey hsfc3d( const unsigned Depth , const unsigned * const coord ); 00131 00132 //---------------------------------------------------------------------- 00133 //---------------------------------------------------------------------- 00134 00135 template<unsigned Depth> struct OctTreeSize ; 00136 00137 template<> 00138 struct OctTreeSize<0> 00139 { enum { value = 1 }; }; 00140 00141 template<unsigned Depth> 00142 struct OctTreeSize 00143 { 00144 enum { MaxDepth = 10 , N = Depth }; // Size representable by an unsigned int 00145 00146 enum { OK = StaticAssert< N <= MaxDepth >::OK }; 00147 00148 enum { value = 1 + 8 * OctTreeSize<Depth-1>::value }; 00149 }; 00150 00151 unsigned oct_tree_size( const unsigned Depth ); 00152 00154 unsigned oct_tree_offset( const unsigned Depth , const OctTreeKey & ); 00155 00156 template<unsigned Depth> 00157 inline 00158 unsigned oct_tree_offset( const OctTreeKey & k ) 00159 { return oct_tree_offset( Depth , k ); } 00160 00161 } 00162 00163 //---------------------------------------------------------------------- 00164 //---------------------------------------------------------------------- 00165 00166 namespace phdmesh { 00167 00168 template<unsigned Depth> 00169 inline 00170 unsigned OctTreeKey::index() const 00171 { 00172 enum { OK = StaticAssert< 0 < Depth && Depth <= MaxDepth >::OK }; 00173 enum { which = ( Depth - 1 ) / IndexPerWord }; 00174 enum { shift = BitsPerWord - BitsPerIndex * ( Depth % IndexPerWord ) }; 00175 00176 return ( m_value[ which ] >> shift ) & MaskIndex ; 00177 } 00178 00179 template<unsigned Depth> 00180 inline 00181 OctTreeKey & OctTreeKey::clear_index() 00182 { 00183 enum { OK = StaticAssert< 0 < Depth && Depth <= MaxDepth >::OK }; 00184 enum { which = ( Depth - 1 ) / IndexPerWord }; 00185 enum { shift = BitsPerWord - BitsPerIndex * ( Depth % IndexPerWord ) }; 00186 00187 const value_type m = MaskIndex ; 00188 00189 m_value[ which ] &= ~( m << shift ); 00190 00191 return *this ; 00192 } 00193 00194 template<unsigned Depth> 00195 inline 00196 OctTreeKey & OctTreeKey::set_index( const unsigned Index ) 00197 { 00198 enum { OK = StaticAssert< 0 < Depth && Depth <= MaxDepth >::OK }; 00199 enum { which = ( Depth - 1 ) / IndexPerWord }; 00200 enum { shift = BitsPerWord - BitsPerIndex * ( Depth % IndexPerWord ) }; 00201 00202 if ( 8 < Index ) { throw_index( Depth , Index ); } 00203 00204 const value_type m = MaskIndex ; 00205 00206 ( m_value[which] &= ~( m << shift ) ) |= Index << shift ; 00207 00208 return *this ; 00209 } 00210 00211 } 00212 00213 #endif 00214
1.7.4