예제 #1
0
        public void BitArrayFactory_Constructor_Validation()
        {
            try
            {
                _ = new BitArraySlim <ByteArray1>(-1);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }

            try
            {
                _ = new BitArraySlim <ByteArray1>(9);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }

            _ = new BitArraySlim <ByteArrayGinormous>(255);

            try
            {
                // Small bit array restricts the max size of the underlying
                // byte array so it can save space by only using a byte for
                // the field it uses to store the size
                _ = new BitArraySlim <ByteArrayGinormous>(256);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }
        }
예제 #2
0
        private static PreSumsData FinishCreateSumsData(int number, BitArraySlim currSums, int currSumsCount, PartialSumsData data)
        {
            if (data.SumsCount != -1)
            {
                int uniqueSums = data.SumsCount - currSumsCount;
                return(new PreSumsData(currSums, uniqueSums));
            }

            if (data.SumsCount == -1)
            {
                CreateAllSums(number, currSums, data);
                data.SumsCount = BoolArrayTrueCount(data.Sums);
            }

            int uniques = 0;

            for (int i = 0; i < currSums.Length; i++)
            {
                if (currSums[i] == 1)
                {
                    int newSum = i + number;
                    if (newSum >= currSums.Length)
                    {
                        uniques++;
                    }
                    else if (currSums[newSum] == 0)
                    {
                        uniques++;
                    }
                }
            }

            return(new PreSumsData(currSums, uniques));
        }
예제 #3
0
            internal void CopyToAndClearRest(BitArraySlim copyTo)
            {
                int copyLength = GetCurrentArrayLength();
                int fillLength = copyTo.GetCurrentArrayLength() - copyLength;

                Array.Copy(Bytes, copyTo.Bytes, copyLength);

                Array.Fill(copyTo.Bytes, 0ul, copyLength, fillLength + GetSizeDiff <Vector256 <byte>, ulong>());
            }
예제 #4
0
 internal PartialSumsData(int maxSum)
 {
     FoundData  = new HashSet <int>();
     Datas      = new BestSumsData();
     Minuniques = int.MaxValue;
     SumsCount  = -1;
     Created    = 0;
     Sums       = null;
     Storage    = new BitArrayStorage(maxSum);
 }
예제 #5
0
        private static int BoolArrayTrueCount(BitArraySlim array)
        {
            int trueCount    = 0;
            int elementCount = array.GetCurrentArrayLength();

            for (int i = 0; i < elementCount; i++)
            {
                trueCount += BitOperations.PopCount(array.Bytes[i]);
            }

            return(trueCount);
        }
예제 #6
0
        private static bool CreateAllSumsDatas(Span <int> numbers, BitArraySlim currSums, PartialSumsData data)
        {
            if (numbers.Length > 1)
            {
                int        midPoint   = numbers.Length / 2;
                Span <int> firstPart  = numbers.Slice(0, midPoint);
                Span <int> secondPart = numbers.Slice(midPoint);

                BitArraySlim secondPartSums = CreatePartialSums(secondPart, currSums, data);
                if (!CreateAllSumsDatas(firstPart, secondPartSums, data))
                {
                    data.Storage.Push(secondPartSums);
                }

                BitArraySlim firstPartSums = CreatePartialSums(firstPart, currSums, data);
                if (!CreateAllSumsDatas(secondPart, firstPartSums, data))
                {
                    data.Storage.Push(firstPartSums);
                }
            }
            else
            {
                data.Created++;

                int actualSumCount = BoolArrayTrueCount(currSums);
                if (data.SumsCount - actualSumCount > data.Minuniques)
                {
                    return(false);
                }

                int number = numbers[0];
                if (!data.FoundData.Contains(number))
                {
                    BestSumsData newData = new BestSumsData(number, FinishCreateSumsData(number, currSums, actualSumCount, data));
                    data.Minuniques = Math.Min(data.Minuniques, data.Datas.Data.Uniques);

                    if (newData.Data.Uniques < data.Datas.Data.Uniques ||
                        (newData.Data.Uniques == data.Datas.Data.Uniques &&
                         newData.Number < data.Datas.Number))
                    {
                        if (data.Datas.Data.BitArray != null)
                        {
                            data.Storage.Push(data.Datas.Data.BitArray);
                        }
                        data.Datas = newData;
                        return(true);
                    }
                }
            }

            return(false);
        }
        // http://imysql.com/mysql-internal-manual/com-stmt-execute.html
        public static void WriteExecuteStatement(ref PacketWriter writer, int statementId, object[] parameters) // Can I avoid boxing? array allocation?
        {
            /*
             *  1              [17] COM_STMT_EXECUTE
             *  4              stmt-id
             *  1              flags
             *  4              iteration-count
             *  if num-params > 0:
             *  n              NULL-bitmap, length: (num-params+7)/8
             *  1              new-params-bound-flag
             *      if new-params-bound-flag == 1:
             *      n              type of each parameter, length: num-params * 2
             *      n              value of each parameter
             */

            writer.WriteByte((byte)CommandId.ExecuteStatement);
            writer.WriteInt32(statementId);

            writer.WriteByte((byte)ExecuteStatementFlags.ReadOnly); // flags
            writer.WriteInt32(1);                                   // The iteration-count is always 1


            if (parameters.Length > 0)
            {
                var nullMap = new BitArraySlim(parameters.Length);

                var nullMapLength    = (parameters.Length + 7) / 8;
                var nullBitMapOffset = writer.CurrentOffset; // save and after use
                writer.Skip(nullMapLength);

                for (int i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i] == null)
                    {
                        nullMap[i] = true;
                        continue;
                    }

                    nullMap[i] = false;

                    // TODO:write parameter type

                    MySqlParameterWriter.Write(ref writer, parameters[i]);
                }

                var offset = writer.CurrentOffset;
                writer.Seek(nullBitMapOffset); // ready for null-map position
                nullMap.WriteTo(ref writer);

                writer.Seek(offset); // return to end
            }
        }
예제 #8
0
 internal BitArraySlim Pop(int length)
 {
     if (Arrays.Count == 0)
     {
         return(new BitArraySlim(length, MaxSum + 1));
     }
     else
     {
         BitArraySlim arr = Arrays.Pop();
         arr.Reuse(length);
         return(arr);
     }
 }
예제 #9
0
        public static (int number, int newNumber) Solve(int[] numbers)
        {
            Array.Sort(numbers);

            int maxSum = 0;

            for (int i = 0; i < numbers.Length; i++)
            {
                maxSum += numbers[i];
            }

            PartialSumsData data = new PartialSumsData(maxSum);

            BitArraySlim currSums = new BitArraySlim(1);

            currSums.ForceSet(0, 1);


            CreateAllSumsDatas(numbers, currSums, data);

            return(CreateCollisionAvoidanceArray(data.Sums, data.Datas, data));
        }
예제 #10
0
        private static (int number, int newNumber) CreateCollisionAvoidanceArray(BitArraySlim sums, BestSumsData bestData, PartialSumsData data)
        {
            SumsData sumData = bestData.Data.ToSumsData(bestData.Number, data.SumsCount);

            foreach (var unique in sumData.Uniques)
            {
                sums.ForceSet(unique, 0);
            }

            for (int i = 1; i <= sums.Length;)
            {
                bool foundObstacle = false;
                foreach (var newSum in sumData.NewSums)
                {
                    int overlapIndex = newSum - (bestData.Number - i);
                    int offset       = 0;
                    while (overlapIndex + offset < sums.Length && sums[overlapIndex + offset] == 1)
                    {
                        offset++;
                    }

                    i += offset;
                    if (offset > 0)
                    {
                        foundObstacle = true;
                        break;
                    }
                }

                if (!foundObstacle)
                {
                    return(bestData.Number, i);
                }
            }

            throw new Exception("impossible!.... i thought");
        }
예제 #11
0
        private static BitArraySlim CreatePartialSums(Span <int> numbers, BitArraySlim currSums, PartialSumsData data)
        {
            int maxSum = currSums.Length;

            for (int i = 0; i < numbers.Length; i++)
            {
                maxSum += numbers[i];
            }

            BitArraySlim newSums = data.Storage.Pop(maxSum);

            currSums.CopyToAndClearRest(newSums);


            int prevMaxSum = currSums.Length - 1;

            for (int i = 0; i < numbers.Length; i++)
            {
                CreateSumsVectorized(prevMaxSum, numbers[i], newSums);
                prevMaxSum += numbers[i];
            }

            return(newSums);
        }
예제 #12
0
 internal PreSumsData(bool _)
 {
     BitArray = null;
     Uniques  = int.MaxValue;
 }
예제 #13
0
 internal PreSumsData(BitArraySlim bits, int uniqs)
 {
     BitArray = bits;
     Uniques  = uniqs;
 }
예제 #14
0
        private static unsafe void CreateSumsVectorized(int z, int number, BitArraySlim newSums)
        {
            BitArrayIndices numberOffset = new BitArrayIndices(number);

            int length = ((z + number) / BitCount <ulong>());

            fixed(ulong *arr = newSums.Bytes)
            {
                ulong *lastPtr = arr + length;
                ulong *currPtr = lastPtr - numberOffset.ByteIndex;

                int sizeFromUint;

                if (Avx2.IsSupported)
                {
                    sizeFromUint = GetSizeDiff <Vector256 <ulong>, ulong>();
                }
                else if (Sse2.IsSupported)
                {
                    sizeFromUint = GetSizeDiff <Vector128 <ulong>, ulong>();
                }
                else
                {
                    sizeFromUint = GetSizeDiff <ulong, ulong>();
                }

                int iterations = length - numberOffset.ByteIndex;
                int rest       = (sizeFromUint - (iterations % sizeFromUint)) % sizeFromUint;

                iterations += rest;
                lastPtr    += rest;
                currPtr    += rest;

                if (numberOffset.BitIndex % BitCount <byte>() == 0)
                {
                    int offset = numberOffset.BitIndex / BitCount <byte>();
                    lastPtr = (ulong *)(((byte *)lastPtr) + offset);

                    for (int i = 0; i <= iterations; i += sizeFromUint)
                    {
                        if (Avx2.IsSupported)
                        {
                            moveSumsNoShift256bit(lastPtr - i, currPtr - i);
                        }
                        else if (Sse2.IsSupported)
                        {
                            moveSumsNoShift128bit(lastPtr - i, currPtr - i);
                        }
                        else
                        {
                            moveSumsNoShift64bit(lastPtr - i, currPtr - i);
                        }
                    }
                }
                else
                {
                    for (int i = -1; i <= iterations - 1; i += sizeFromUint)
                    {
                        if (Avx2.IsSupported)
                        {
                            moveSumsWithShift256bit(lastPtr - i, currPtr - i, numberOffset.BitIndex);
                        }
                        else if (Sse2.IsSupported)
                        {
                            moveSumsWithShift128bit(lastPtr - i, currPtr - i, numberOffset.BitIndex);
                        }
                        else
                        {
                            moveSumsWithShift64bit(lastPtr - i, currPtr - i, numberOffset.BitIndex);
                        }
                    }

                    ulong affter = currPtr[-iterations] << numberOffset.BitIndex;
                    lastPtr[-iterations] |= affter;
                }
            }
        }
예제 #15
0
 private static void CreateAllSums(int number, BitArraySlim currSums, PartialSumsData data)
 {
     data.Sums      = CreatePartialSums(new int[] { number }, currSums, data);
     data.SumsCount = BoolArrayTrueCount(data.Sums);
 }
예제 #16
0
 internal void Push(BitArraySlim arr)
 {
     Arrays.Push(arr);
 }