yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
1f99c2086
master
1#include "slang-uint-set.h" 2 3namespace Slang 4{ 5 6Index UIntSet ::getLSBZero () 7{ 8uint64_t offset = 0 ; 9for (Element & element :this -> m_buffer ) 10 { 11// Flip all bits so bitscanForward can find a 0 bit 12Element flippedElement = ~element ; 13 14// continue if we don't have 0 bits 15if (flippedElement == 0 ) 16 { 17offset += sizeof (Element )* 8 ; 18continue ; 19 } 20 21// Get LSBZero of current Block, add with offset 22return bitscanForward (flippedElement )+ offset ; 23 } 24return offset ; 25} 26 27UIntSet & UIntSet ::operator= (UIntSet && other ) 28{ 29m_buffer = _Move (other .m_buffer ); 30return * this ; 31} 32 33UIntSet & UIntSet ::operator= (const UIntSet & other ) 34{ 35m_buffer = other .m_buffer ; 36return * this ; 37} 38 39HashCode UIntSet ::getHashCode ()const 40{ 41int rs = 0 ; 42for (auto val :m_buffer ) 43rs ^=val ; 44return rs ; 45} 46 47void UIntSet ::resizeAndClear (UInt val ) 48{ 49// TODO(JS): This could be faster in that if the resize is larger the additional area is cleared 50// twice 51resize (val ); 52clear (); 53} 54 55void UIntSet ::setAll () 56{ 57 ::memset (m_buffer .getBuffer (),-1 ,m_buffer .getCount ()* sizeof (Element )); 58} 59 60void UIntSet ::resize (UInt size ) 61{ 62const Index newCount = Index ((size + kElementMask ) >>kElementShift ); 63resizeBackingBufferDirectly (newCount ); 64} 65 66void UIntSet ::clear () 67{ 68 ::memset (m_buffer .getBuffer (),0 ,m_buffer .getCount ()* sizeof (Element )); 69} 70 71bool UIntSet ::isEmpty ()const 72{ 73return _areAllZero (m_buffer .getBuffer (),m_buffer .getCount ()); 74} 75 76void UIntSet ::clearAndDeallocate () 77{ 78m_buffer .clearAndDeallocate (); 79} 80 81void UIntSet ::unionWith (const UIntSet & set ) 82{ 83const Index minCount = Math ::Min (set .m_buffer .getCount (),m_buffer .getCount ()); 84for (Index i = 0 ;i < minCount ;i ++ ) 85 { 86m_buffer [i ] |=set .m_buffer [i ]; 87 } 88 89if (set .m_buffer .getCount ()> m_buffer .getCount ()) 90m_buffer .addRange ( 91set .m_buffer .getBuffer ()+ m_buffer .getCount (), 92set .m_buffer .getCount ()- m_buffer .getCount ()); 93} 94 95bool UIntSet ::operator== (const UIntSet & set )const 96{ 97const Index aCount = m_buffer .getCount (); 98const auto aElems = m_buffer .getBuffer (); 99 100const Index bCount = set .m_buffer .getCount (); 101const auto bElems = set .m_buffer .getBuffer (); 102 103const Index minCount = Math ::Min (aCount ,bCount ); 104 105return ::memcmp (aElems ,bElems ,minCount * sizeof (Element ))== 0 && 106_areAllZero (aElems + minCount ,aCount - minCount )&& 107_areAllZero (bElems + minCount ,bCount - minCount ); 108} 109 110void UIntSet ::intersectWith (const UIntSet & set ) 111{ 112if (set .m_buffer .getCount ()< m_buffer .getCount ()) 113 ::memset ( 114m_buffer .getBuffer ()+ set .m_buffer .getCount (), 1150 , 116 (m_buffer .getCount ()- set .m_buffer .getCount ())* sizeof (Element )); 117 118const Index minCount = Math ::Min (set .m_buffer .getCount (),m_buffer .getCount ()); 119for (Index i = 0 ;i < minCount ;i ++ ) 120 { 121m_buffer [i ] &=set .m_buffer [i ]; 122 } 123} 124 125void UIntSet ::subtractWith (const UIntSet & set ) 126{ 127const Index minCount = Math ::Min (this -> m_buffer .getCount (),set .m_buffer .getCount ()); 128for (Index i = 0 ;i < minCount ;i ++ ) 129 { 130this -> m_buffer [i ]= this -> m_buffer [i ]& (~set .m_buffer [i ]); 131 } 132} 133 134/* static */ void UIntSet ::calcUnion (UIntSet & outRs ,const UIntSet & set1 ,const UIntSet & set2 ) 135{ 136outRs .resizeBackingBufferDirectly ( 137Math ::Max (set1 .m_buffer .getCount (),set2 .m_buffer .getCount ())); 138outRs .clear (); 139for (Index i = 0 ;i < set1 .m_buffer .getCount ();i ++ ) 140outRs .m_buffer [i ] |=set1 .m_buffer [i ]; 141for (Index i = 0 ;i < set2 .m_buffer .getCount ();i ++ ) 142outRs .m_buffer [i ] |=set2 .m_buffer [i ]; 143} 144 145/* static */ void UIntSet ::calcIntersection ( 146UIntSet & outRs , 147const UIntSet & set1 , 148const UIntSet & set2 ) 149{ 150const Index minCount = Math ::Min (set1 .m_buffer .getCount (),set2 .m_buffer .getCount ()); 151outRs .resizeBackingBufferDirectly (minCount ); 152 153for (Index i = 0 ;i < minCount ;i ++ ) 154outRs .m_buffer [i ]= set1 .m_buffer [i ]& set2 .m_buffer [i ]; 155} 156 157/* static */ void UIntSet ::calcSubtract (UIntSet & outRs ,const UIntSet & set1 ,const UIntSet & set2 ) 158{ 159const auto set1Count = set1 .m_buffer .getCount (); 160const auto set2Count = set2 .m_buffer .getCount (); 161 162outRs .resizeBackingBufferDirectly (set1Count ); 163 164for (Index i = 0 ;i < set1Count ;i ++ ) 165 { 166if (i < set2Count ) 167 { 168outRs .m_buffer [i ]= set1 .m_buffer [i ]& (~set2 .m_buffer [i ]); 169 } 170else 171 { 172// If `set2` is smaller, copy the remaining values from `set1` 173outRs .m_buffer [i ]= set1 .m_buffer [i ]; 174 } 175 } 176} 177 178/* static */ bool UIntSet ::hasIntersection (const UIntSet & set1 ,const UIntSet & set2 ) 179{ 180const Index minCount = Math ::Min (set1 .m_buffer .getCount (),set2 .m_buffer .getCount ()); 181for (Index i = 0 ;i < minCount ;i ++ ) 182 { 183if (set1 .m_buffer [i ]& set2 .m_buffer [i ]) 184return true; 185 } 186return false; 187} 188 189Index UIntSet ::countElements ()const 190{ 191// TODO: This can be made faster using SIMD intrinsics to count set bits. 192uint64_t tmp ; 193constexpr Index loopSize = 194 ((sizeof (Element ) /sizeof (tmp ))!= 0 ) ?sizeof (Element ) /sizeof (tmp ) :1 ; 195Index count = 0 ; 196for (auto index = 0 ;index < this -> m_buffer .getCount ();index ++ ) 197 { 198for (auto i = 0 ;i < loopSize ;i ++ ) 199 { 200tmp = m_buffer [index ] >> (sizeof (tmp )* i ); 201tmp = tmp - ((tmp >>1 )& 0x5555555555555555 ); 202tmp = (tmp & 0x3333333333333333 )+ ((tmp >>2 )& 0x3333333333333333 ); 203count += ((tmp + (tmp >>4 )& 0xF0F0F0F0F0F0F0F )* 0x101010101010101 ) >>56 ; 204 } 205 } 206return count ; 207} 208 209}// namespace Slang