Ejemplo n.º 1
0
        public static int GetSetBits(UnsafeBitSet *set, UnsafeArray *array)
        {
            Assert.Check(UnsafeArray.GetTypeHandle(array) == typeof(int).TypeHandle.Value);

            if (UnsafeArray.Length(array) < set->_sizeBits)
            {
                throw new InvalidOperationException(SET_ARRAY_LESS_CAPACITY);
            }

            var setCount    = 0;
            var bitOffset   = 0;
            var arrayBuffer = (int *)UnsafeArray.GetBuffer(array);

            for (var i = 0; i < set->_sizeBuckets; ++i)
            {
                var word64 = set->_bits[i];
                if (word64 == WORD_ZERO)
                {
                    // since we're skipping whole word, step up offset
                    bitOffset += WORD_SIZE_BITS;
                    continue;
                }

                var word32Count = 0;

NEXT_WORD32:
                var word32 = *((uint *)word64 + word32Count);
                if (word32 != 0)
                {
                    var word16Count = 0;

NEXT_WORD16:
                    var word16 = *((ushort *)word32 + word16Count);
                    if (word16 != 0)
                    {
                        var word8Count = 0;

NEXT_WORD8:
                        var word8 = *((byte *)word16 + word8Count);
                        if (word8 != 0)
                        {
                            if ((word8 & (1 << 0)) == 1 << 0)
                            {
                                arrayBuffer[setCount++] = (bitOffset + 0);
                            }
                            if ((word8 & (1 << 1)) == 1 << 1)
                            {
                                arrayBuffer[setCount++] = (bitOffset + 1);
                            }
                            if ((word8 & (1 << 2)) == 1 << 2)
                            {
                                arrayBuffer[setCount++] = (bitOffset + 2);
                            }
                            if ((word8 & (1 << 3)) == 1 << 3)
                            {
                                arrayBuffer[setCount++] = (bitOffset + 3);
                            }
                            if ((word8 & (1 << 4)) == 1 << 4)
                            {
                                arrayBuffer[setCount++] = (bitOffset + 4);
                            }
                            if ((word8 & (1 << 5)) == 1 << 5)
                            {
                                arrayBuffer[setCount++] = (bitOffset + 5);
                            }
                            if ((word8 & (1 << 6)) == 1 << 6)
                            {
                                arrayBuffer[setCount++] = (bitOffset + 6);
                            }
                            if ((word8 & (1 << 7)) == 1 << 7)
                            {
                                arrayBuffer[setCount++] = (bitOffset + 7);
                            }
                        }

                        // always step up bitoffset here
                        bitOffset += (WORD_SIZE_BITS / 8);

                        if (word8Count == 0)
                        {
                            ++word8Count;

                            // go back
                            goto NEXT_WORD8;
                        }
                    }
                    else
                    {
                        bitOffset += (WORD_SIZE_BITS / 4);
                    }

                    if (word16Count == 0)
                    {
                        ++word16Count;

                        // go back
                        goto NEXT_WORD16;
                    }
                }
                else
                {
                    bitOffset += (WORD_SIZE_BITS / 2);
                }

                if (word32Count == 0)
                {
                    ++word32Count;

                    // go back
                    goto NEXT_WORD32;
                }
            }

            return(setCount);
        }