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) { } }
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)); }
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>()); }
internal PartialSumsData(int maxSum) { FoundData = new HashSet <int>(); Datas = new BestSumsData(); Minuniques = int.MaxValue; SumsCount = -1; Created = 0; Sums = null; Storage = new BitArrayStorage(maxSum); }
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); }
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 } }
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); } }
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)); }
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"); }
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); }
internal PreSumsData(bool _) { BitArray = null; Uniques = int.MaxValue; }
internal PreSumsData(BitArraySlim bits, int uniqs) { BitArray = bits; Uniques = uniqs; }
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; } } }
private static void CreateAllSums(int number, BitArraySlim currSums, PartialSumsData data) { data.Sums = CreatePartialSums(new int[] { number }, currSums, data); data.SumsCount = BoolArrayTrueCount(data.Sums); }
internal void Push(BitArraySlim arr) { Arrays.Push(arr); }