/// <summary> /// Creates a RLEBitset from a BitArray. /// </summary> /// <param name="bits">a BitArray</param> /// <returns>an RLEBitset</returns> public static IBitset CreateFrom(BitArray bits) { RLEBitset rtnVal = new RLEBitset(); rtnVal._Length = bits.Length; Run currRun = new Run(); for (int i = 0; i < bits.Count; i++) { if (bits.Get(i) == true) { currRun.StartIndex = i; currRun.EndIndex = i; for (int j = i + 1; j < bits.Count; j++) { if (bits.Get(j)) { currRun.EndIndex = j; } else { break; } } i = currRun.EndIndex; //move the counter to the end of the run we just found rtnVal._RunArray.Add(currRun); currRun = new Run(); } } return rtnVal; }
/// <summary> /// Creates a RLEBitset from a BitArray. /// </summary> /// <param name="bits">a BitArray</param> /// <returns>an RLEBitset</returns> public static IBitset CreateFrom(BitArray bits) { RLEBitset rtnVal = new RLEBitset(); rtnVal._Length = bits.Length; Run currRun = new Run(); for (int i = 0; i < bits.Count; i++) { if (bits.Get(i) == true) { currRun.StartIndex = i; currRun.EndIndex = i; for (int j = i + 1; j < bits.Count; j++) { if (bits.Get(j)) { currRun.EndIndex = j; } else { break; } } i = currRun.EndIndex; //move the counter to the end of the run we just found rtnVal._RunArray.Add(currRun); currRun = new Run(); } } return(rtnVal); }
/// <summary> /// Performs the set difference, defined as the set in A and not in B. /// </summary> /// <param name="otherSet">the other IBitset</param> /// <returns>The set difference of this set and the other.</returns> public IBitset Difference(IBitset otherSet) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset - errors if cannot cast IBitset rtnVal = And(otherRLESet.Not()); return(rtnVal); }
/// <summary> /// Determines if the other IBitset is equal to this one. /// </summary> /// <param name="otherSet">the other IBitset</param> /// <returns>a boolean</returns> public override bool Equals(object otherSet) { bool rtnVal = false; if ((otherSet is RLEBitset)) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset - errors if cannot cast if (this._Length == otherRLESet._Length && this._RunArray.Count == otherRLESet._RunArray.Count) { if (this._RunArray.Count == 0) { rtnVal = true; } for (int i = 0; i < this._RunArray.Count; i++) { if (this._RunArray[i].StartIndex == otherRLESet._RunArray[i].StartIndex && this._RunArray[i].EndIndex == otherRLESet._RunArray[i].EndIndex) { rtnVal = true; } else { rtnVal = false; break; } } } } return(rtnVal); }
/// <summary> /// Creates a RLEBitset from an array of indices and a capacity value. /// Each value in the input array represents the position (i.e. index) of a 1. /// The capity represents the length of the uncompressed data. /// </summary> /// <param name="indices">an array of integers representing the positions of 1's</param> /// <param name="capacity">the length of the uncompressed array</param> /// <returns></returns> public static IBitset CreateFrom(int[] indices, int capacity) { RLEBitset rtnVal = new RLEBitset(); rtnVal.length = capacity; if (indices.Length > 0) { Array.Sort(indices); // sort the input array first. if (indices.Last() > capacity) // capacity must be larger than highest index value in input array. { throw new ArgumentException("capacity cannot be less than max index value"); } Run currRun = new Run(); currRun.StartIndex = indices.FirstOrDefault(); for (int i = 0; i < indices.Length - 1; i++) { if (indices[i + 1] - indices[i] > 1) { currRun.EndIndex = indices[i]; rtnVal.runArray.Add(currRun); currRun = new Run(); currRun.StartIndex = indices[i + 1]; } } currRun.EndIndex = indices.LastOrDefault(); rtnVal.runArray.Add(currRun); } return rtnVal; }
/// <summary> /// Creates a RLEBitset from an array of indices and a capacity value. /// Each value in the input array represents the position (i.e. index) of a 1. /// The capity represents the length of the uncompressed data. /// </summary> /// <param name="indices">an array of integers representing the positions of 1's</param> /// <param name="capacity">the length of the uncompressed array</param> /// <returns></returns> public static IBitset CreateFrom(int[] indices, int capacity) { RLEBitset rtnVal = new RLEBitset(); rtnVal._Length = capacity; if (indices.Length > 0) { Array.Sort(indices); // sort the input array first. if (indices.Last() > capacity) // capacity must be larger than highest index value in input array. { throw new ArgumentException("capacity cannot be less than max index value"); } Run currRun = new Run(); currRun.StartIndex = indices.FirstOrDefault(); for (int i = 0; i < indices.Length - 1; i++) { if (indices[i + 1] - indices[i] > 1) { currRun.EndIndex = indices[i]; rtnVal._RunArray.Add(currRun); currRun = new Run(); currRun.StartIndex = indices[i + 1]; } } currRun.EndIndex = indices.LastOrDefault(); rtnVal._RunArray.Add(currRun); } return(rtnVal); }
/// <summary> /// Returns a deep copy of this RLEBitset. /// </summary> public IBitset Clone() { RLEBitset rtnVal = new RLEBitset(); Run[] tempRuns = new Run[runArray.Count]; runArray.CopyTo(tempRuns); rtnVal.runArray = tempRuns.ToList(); rtnVal.length = length; return(rtnVal); }
/// <summary> /// Returns a deep copy of this RLEBitset. /// </summary> public IBitset Clone() { RLEBitset rtnVal = new RLEBitset(); Run[] tempRuns = new Run[this._RunArray.Count]; this._RunArray.CopyTo(tempRuns); rtnVal._RunArray = tempRuns.ToList(); rtnVal._Length = this._Length; return(rtnVal); }
/// <summary> /// Creates a RLEBitset from an array of indices. /// Each value in the input array represents the position (i.e. index) of a 1. /// </summary> /// <param name="indices">an array of integers representing the positions of 1's</param> /// <returns>an RLEBitset</returns> public static IBitset CreateFrom(int[] indices) { int capacity = 0; if (indices.Length > 0) { capacity = indices.Max() + 1; } return(RLEBitset.CreateFrom(indices, capacity)); }
private void mergeOtherRun(RLEBitset other, ref Run current, ref int nextThisIndex, ref int nextOtherIndex) { Run next = other._RunArray[nextOtherIndex]; nextOtherIndex++; if (!merge(ref current, ref next, true, nextThisIndex - 1)) { //no merge, so a new interval has been inserted nextThisIndex++; } }
/// <summary> /// For indices in the range [start, end] add the index to the set if /// the value is true, otherwise remove it. /// </summary> /// <param name="start">the index to start from (inclusive)</param> /// <param name="end">the index to stop at (exclusive)</param> public void Set(int start, int end, bool value) { RLEBitset other = new RLEBitset(); other.runArray.Add(new Run(start, end - 1)); if (value) { OrWith(other); } else { DifferenceWith(other); } }
/// <summary> /// Sets the bit at a specific position in the IBitset to the specified value. /// </summary> /// <param name="index">The zero-based index of the bit to set.</param> /// <param name="value">The Boolean value to assign to the bit.</param> public void Set(int index, bool value) { int[] tmpIndices = { index }; IBitset other = RLEBitset.CreateFrom(tmpIndices, this.length); if (value) { OrWith(other); } else { DifferenceWith(other); } }
/// <summary> /// Sets all bits in the given range to the specified value. /// </summary> /// <param name="startIndex">The zero-based start position of the range.</param> /// <param name="count">The number of bits in the range.</param> /// <param name="value">The Boolean value to assign to the bits.</param> public void SetRange(int startIndex, int count, bool value) { RLEBitset other = new RLEBitset(); other.runArray.Add(new Run(startIndex, startIndex + count - 1)); if (value) { OrWith(other); } else { DifferenceWith(other); } }
/// <summary> /// Helper function for Or operations. /// Adds the given run to the run-array by. Either: /// a) merges it with the previous run if overlap with previous in array /// b) adds it as next run if no overlap with previous in array /// </summary> /// <param name="currRLE">the RLE to be modified</param> /// <param name="runToAdd">the Run to add</param> private void AddRunToRLE(ref RLEBitset currRLE, Run runToAdd) { Run currRun = new Run(); if (TryCreateUnion(currRLE.runArray.LastOrDefault(), runToAdd, ref currRun) && currRLE.runArray.Count > 0) { //there is overlap with the previous run in run-array so we merge this run with the previous in the array. int tmpIndx = currRLE.runArray.Count - 1; currRLE.runArray[tmpIndx] = currRun; } else { //no overlap with previous run in run-array, so we add the overlapping run as is. currRLE.runArray.Add(runToAdd); } }
/// <summary> /// Read a binary serialization of a RLE bitset, as written by the Serialize method. /// </summary> /// <param name="stream">The stream to read from.</param> /// <returns>The bitset deserialized from the stream.</returns> public static RLEBitset Deserialize(Stream stream) { RLEBitset bitset = new RLEBitset(); //We don't care about the encoding, but we have to specify something to be able to set the stream as leave open. using (BinaryReader reader = new BinaryReader(stream.WrapAsNonClosingStream(), Encoding.Default)) { bitset.length = reader.ReadInt32(); while (stream.Position < stream.Length - 1) { Run currRun = new Run(); currRun.StartIndex = reader.ReadInt32(); currRun.EndIndex = reader.ReadInt32(); bitset.runArray.Add(currRun); } } return(bitset); }
/// <summary> /// Inverts all the values in the current IBitset, /// so that elements set to true are changed to false, and elements set to false are changed to true. /// </summary> /// <returns>a new IBitset with inverted values</returns> public IBitset Not() { RLEBitset rtnVal = new RLEBitset(); rtnVal._Length = this._Length; if (_RunArray.Count > 0) { Run currRun = new Run(); // handle first run if needed. if (_RunArray[0].StartIndex > 0) { currRun.StartIndex = 0; currRun.EndIndex = _RunArray[0].StartIndex - 1; rtnVal._RunArray.Add(currRun); currRun = new Run(); } // handle the middle runs. currRun.StartIndex = _RunArray[0].EndIndex + 1; for (int i = 0; i < _RunArray.Count - 1; i++) { currRun.EndIndex = _RunArray[i + 1].StartIndex - 1; rtnVal._RunArray.Add(currRun); currRun = new Run(); currRun.StartIndex = _RunArray[i + 1].EndIndex + 1; } // handle the last run. if (_Length > currRun.StartIndex) { currRun.EndIndex = _Length - 1; rtnVal._RunArray.Add(currRun); } } else { rtnVal._RunArray.Add(new Run(0, _Length - 1)); } return(rtnVal); }
public IBitset And(IBitset otherSet) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset - errors if cannot cast RLEBitset rtnVal = new RLEBitset(); // instantiate the return value rtnVal._Length = this._Length; List <Run> runsA = this._RunArray; List <Run> runsB = otherRLESet._RunArray; int i = 0; int j = 0; while (i < runsA.Count && j < runsB.Count) { // check for overlap of the runs. Run currRun = new Run(); if (tryCreateIntersection(runsA[i], runsB[j], ref currRun)) { rtnVal._RunArray.Add(currRun); } // iterate the counters appropriately to compare the next set of runs for overlap. if (runsA[i].EndIndex > runsB[j].EndIndex + 1) { j++; } else if (runsA[i].EndIndex < runsB[j].EndIndex - 1) { i++; } else { i++; j++; } } return(rtnVal); }
/// <summary> /// Inverts all the values in the current IBitset, /// so that elements set to true are changed to false, and elements set to false are changed to true. /// </summary> /// <returns>a new IBitset with inverted values</returns> public IBitset Not() { RLEBitset rtnVal = new RLEBitset(); rtnVal._Length = this._Length; if (_RunArray.Count > 0) { Run currRun = new Run(); // handle first run if needed. if (_RunArray[0].StartIndex > 0) { currRun.StartIndex = 0; currRun.EndIndex = _RunArray[0].StartIndex - 1; rtnVal._RunArray.Add(currRun); currRun = new Run(); } // handle the middle runs. currRun.StartIndex = _RunArray[0].EndIndex + 1; for (int i = 0; i < _RunArray.Count - 1; i++) { currRun.EndIndex = _RunArray[i + 1].StartIndex - 1; rtnVal._RunArray.Add(currRun); currRun = new Run(); currRun.StartIndex = _RunArray[i + 1].EndIndex + 1; } // handle the last run. if (_Length > currRun.StartIndex) { currRun.EndIndex = _Length - 1; rtnVal._RunArray.Add(currRun); } } else { rtnVal._RunArray.Add(new Run(0, _Length - 1)); } return rtnVal; }
/// <summary> /// Performs the set difference, defined as the set in A and not in B. /// </summary> /// <param name="otherSet">the other IBitset</param> public void DifferenceWith(IBitset otherSet) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset - errors if cannot cast AndWith(otherRLESet.Not()); }
public IBitset And(IBitset otherSet) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset - errors if cannot cast RLEBitset rtnVal = new RLEBitset(); // instantiate the return value rtnVal._Length = this._Length; List<Run> runsA = this._RunArray; List<Run> runsB = otherRLESet._RunArray; int i = 0; int j = 0; while (i < runsA.Count && j < runsB.Count) { // check for overlap of the runs. Run currRun = new Run(); if (tryCreateIntersection(runsA[i], runsB[j], ref currRun)) { rtnVal._RunArray.Add(currRun); } // iterate the counters appropriately to compare the next set of runs for overlap. if (runsA[i].EndIndex > runsB[j].EndIndex + 1) { j++; } else if (runsA[i].EndIndex < runsB[j].EndIndex - 1) { i++; } else { i++; j++; } } return rtnVal; }
public void OrWith(IBitset otherSet) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset - errors if cannot cast Run current = new Run(); int nextThisIndex, nextOtherIndex; if (this._RunArray.Count == 0) { this._RunArray = new List <Run>(otherRLESet._RunArray); this._Length = otherRLESet._Length; nextThisIndex = this._RunArray.Count; //this stops the loops nextOtherIndex = this._RunArray.Count; } else if (otherRLESet._RunArray.Count == 0) { nextThisIndex = this._RunArray.Count; //this stops the loops nextOtherIndex = this._RunArray.Count; } else if (this._RunArray[0].StartIndex <= otherRLESet._RunArray[0].StartIndex) { current = this._RunArray[0]; nextThisIndex = 1; nextOtherIndex = 0; } else if (tryCreateUnion(this._RunArray[0], otherRLESet._RunArray[0], ref current)) { //first two sets overlap this._RunArray[0] = current; nextThisIndex = 1; nextOtherIndex = 1; } else { this._RunArray.Insert(0, otherRLESet._RunArray[0]); nextThisIndex = 1; nextOtherIndex = 1; } while ((nextThisIndex < this._RunArray.Count) && (nextOtherIndex < otherRLESet._RunArray.Count)) { if (this._RunArray[nextThisIndex].StartIndex > otherRLESet._RunArray[nextOtherIndex].StartIndex) { mergeOtherRun(otherRLESet, ref current, ref nextThisIndex, ref nextOtherIndex); } else { mergeExistingRun(ref current, ref nextThisIndex); } } if (nextThisIndex < this._RunArray.Count) { //we finished the other, finish this one while (nextThisIndex < this._RunArray.Count) { mergeExistingRun(ref current, ref nextThisIndex); } } else { //we finished this one, finish the other while (nextOtherIndex < otherRLESet._RunArray.Count) { int lastNextIndex = this._RunArray.Count; mergeOtherRun(otherRLESet, ref current, ref lastNextIndex, ref nextOtherIndex); } } }
/// <summary> /// Returns a deep copy of this RLEBitset. /// </summary> public IBitset Clone() { RLEBitset rtnVal = new RLEBitset(); Run[] tempRuns = new Run[this._RunArray.Count]; this._RunArray.CopyTo(tempRuns); rtnVal._RunArray = tempRuns.ToList(); rtnVal._Length = this._Length; return rtnVal; }
/// <summary> /// Intersects an IBitset with another IBitset, modifying the first IBitset rather /// than creating a new IBitset /// </summary> /// <param name="otherSet">the other IBitset</param> /// <returns>void</returns> public void AndWith(IBitset otherSet) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset List <Run> runsA = this._RunArray; List <Run> runsB = otherRLESet._RunArray; int i = 0; int j = 0; while (i < runsA.Count && j < runsB.Count) { int x = runsA[i].StartIndex; int y = runsA[i].EndIndex; int w = runsB[j].StartIndex; int z = runsB[j].EndIndex; if (x < w) { if (y < w) { runsA.RemoveAt(i); } else // (y >= w) { // crops the current run in runsA from the left to align with // the start of the current run in runsB Run ithRun = runsA[i]; ithRun.StartIndex = w; runsA[i] = ithRun; var what = this._RunArray[i]; if (y <= z) { i++; } else // (y > z ) { // splits the run from runsA into two runs Run newRun = new Run(z + 1, y); Run newRun2 = runsA[i]; newRun2.EndIndex = z; runsA[i] = newRun2; runsA.Insert(i + 1, newRun); i++; j++; } } } else // (x >= w) { if (y <= z) { i++; } else // (y > z) { if (x <= z) { // splits the run from runsA into two runs Run newRun = new Run(z + 1, y); Run newRun2 = runsA[i]; newRun2.EndIndex = z; runsA[i] = newRun2; runsA.Insert(i + 1, newRun); i++; j++; } else { j++; } } } } //this truncates runsA if we've considered all of the runs in runsB this._RunArray = this._RunArray.Take(i).ToList(); }
public IBitset Or(IBitset otherSet) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset - errors if cannot cast RLEBitset rtnVal = new RLEBitset(); // instantiate the return value rtnVal.length = (this.length > otherRLESet.length) ? this.length : otherRLESet.length; List<Run> runsA = this.runArray; List<Run> runsB = otherRLESet.runArray; int i = 0; int j = 0; while (i < runsA.Count && j < runsB.Count) { Run currRun = new Run(); if (TryCreateUnion(runsA[i], runsB[j], ref currRun)) { //there is an overlap //now compare the overlapping run you created to the previous run you added to see if they should be merged AddRunToRLE(ref rtnVal, currRun); //now move the counters. if (runsA[i].EndIndex < runsB[j].EndIndex) { i++; } else if (runsA[i].EndIndex > runsB[j].EndIndex) { j++; } else { i++; j++; } } else { //no overlap, so let's just add lower run and step that counter. if (runsA[i].StartIndex < runsB[j].StartIndex) { AddRunToRLE(ref rtnVal, runsA[i]); i++; } else { AddRunToRLE(ref rtnVal, runsB[j]); j++; } } } //account for remaining runs in one of our sets. int remCounter = 0; List<Run> remRuns = new List<Run>(); if (i < runsA.Count) { remCounter = i; remRuns = runsA; } else if (j < runsB.Count) { remCounter = j; remRuns = runsB; } while (remCounter < remRuns.Count) { AddRunToRLE(ref rtnVal, remRuns[remCounter]); remCounter++; } return rtnVal; }
public IBitset Or(IBitset otherSet) { RLEBitset otherRLESet = (RLEBitset)otherSet; // cast to an RLEBitset - errors if cannot cast RLEBitset rtnVal = new RLEBitset(); // instantiate the return value rtnVal.length = (this.length > otherRLESet.length) ? this.length : otherRLESet.length; List <Run> runsA = this.runArray; List <Run> runsB = otherRLESet.runArray; int i = 0; int j = 0; while (i < runsA.Count && j < runsB.Count) { Run currRun = new Run(); if (TryCreateUnion(runsA[i], runsB[j], ref currRun)) { //there is an overlap //now compare the overlapping run you created to the previous run you added to see if they should be merged AddRunToRLE(ref rtnVal, currRun); //now move the counters. if (runsA[i].EndIndex < runsB[j].EndIndex) { i++; } else if (runsA[i].EndIndex > runsB[j].EndIndex) { j++; } else { i++; j++; } } else { //no overlap, so let's just add lower run and step that counter. if (runsA[i].StartIndex < runsB[j].StartIndex) { AddRunToRLE(ref rtnVal, runsA[i]); i++; } else { AddRunToRLE(ref rtnVal, runsB[j]); j++; } } } //account for remaining runs in one of our sets. int remCounter = 0; List <Run> remRuns = new List <Run>(); if (i < runsA.Count) { remCounter = i; remRuns = runsA; } else if (j < runsB.Count) { remCounter = j; remRuns = runsB; } while (remCounter < remRuns.Count) { AddRunToRLE(ref rtnVal, remRuns[remCounter]); remCounter++; } return(rtnVal); }
/// <summary> /// Read a binary serialization of a RLE bitset, as written by the Serialize method. /// </summary> /// <param name="stream">The stream to read from.</param> /// <returns>The bitset deserialized from the stream.</returns> public static RLEBitset Deserialize(Stream stream) { RLEBitset bitset = new RLEBitset(); //We don't care about the encoding, but we have to specify something to be able to set the stream as leave open. using (BinaryReader reader = new BinaryReader(stream, Encoding.Default, true)) { bitset.length = reader.ReadInt32(); while (stream.Position < stream.Length - 1) { Run currRun = new Run(); currRun.StartIndex = reader.ReadInt32(); currRun.EndIndex = reader.ReadInt32(); bitset.runArray.Add(currRun); } } return bitset; }