/// <summary> /// Unions the current range set with the given range set. /// </summary> public void Union(SelectableRangeSet unionTo) { List <SelectableRange> inputSet = unionTo.rangeSet; int inSz = inputSet.Count; int n = 0; while (n < inSz) { SelectableRange inRange = (SelectableRange)inputSet[n]; int sz = rangeSet.Count; List <SelectableRange> i = rangeSet.GetRange(0, rangeSet.Count); int j = 0; while (j < i.Count) { SelectableRange range = i[j]; if (RangeIntersectedBy(inRange, range)) { i.RemoveAt(j); inRange = ChangeRangeSizeToEncompass(inRange, range); } j++; } // Insert into sorted position RangePosition startPoint = inRange.StartPosition; DataObject start = inRange.Start; RangePosition endPoint = inRange.EndPosition; DataObject end = inRange.End; if (start == SelectableRange.FirstInSet) { rangeSet.Insert(0, inRange); } else { DataObject startCell = start; i = rangeSet.GetRange(0, rangeSet.Count); j = 0; while (j < i.Count) { SelectableRange range = i[j]; DataObject curStart = range.Start; if (curStart != SelectableRange.FirstInSet) { if (curStart.CompareTo(startCell) > 0) { i[j] = i[j - 1]; break; } } j++; } i.Add(inRange); } n++; } }
/// <inheritdoc/> public override bool Equals(object ob) { SelectableRange destRange = (SelectableRange)ob; return(Start.ValuesEqual(destRange.Start) && End.ValuesEqual(destRange.End) && StartPosition == destRange.StartPosition && EndPosition == destRange.EndPosition); }
/// <summary> /// Alters the first range so it encompasses the second range. /// </summary> /// <remarks> /// This assumes that range1 intersects range2. /// </remarks> private static SelectableRange ChangeRangeSizeToEncompass(SelectableRange range1, SelectableRange range2) { RangePosition startPosition1 = range1.StartPosition; DataObject start1 = range1.Start; RangePosition endPosition1 = range1.EndPosition; DataObject end1 = range1.End; RangePosition startPosition2 = range2.StartPosition; DataObject start2 = range2.Start; RangePosition endPosition2 = range2.EndPosition; DataObject end2 = range2.End; if (start1 != SelectableRange.FirstInSet) { if (start2 != SelectableRange.FirstInSet) { DataObject cell = start1; int c = cell.CompareTo(start2); if (c > 0 || c == 0 && startPosition1 == RangePosition.AfterLastValue && startPosition2 == RangePosition.FirstValue) { start1 = start2; startPosition1 = startPosition2; } } else { start1 = start2; startPosition1 = startPosition2; } } if (end1 != SelectableRange.LastInSet) { if (end2 != SelectableRange.LastInSet) { DataObject cell = end1; int c = cell.CompareTo(end2); if (c < 0 || c == 0 && endPosition1 == RangePosition.BeforeFirstValue && endPosition2 == RangePosition.LastValue) { end1 = end2; endPosition1 = endPosition2; } } else { end1 = end2; endPosition1 = endPosition2; } } return(new SelectableRange(startPosition1, start1, endPosition1, end1)); }
/// <summary> /// Set up a range. /// </summary> /// <param name="i"></param> /// <param name="range"></param> private void SetupRange(int i, SelectableRange range) { DataObject l = range.Start; RangePosition lf = range.StartPosition; DataObject u = range.End; RangePosition uf = range.EndPosition; // Handle lower first if (l == SelectableRange.FirstInSet && lf == RangePosition.FirstValue) { // Special case no lower check lowerFlags[i] = NoCheck; } else { if (lf == RangePosition.FirstValue) { lowerFlags[i] = CheckLesserEqualOrGreaterEqual; // >= } else if (lf == RangePosition.AfterLastValue) { lowerFlags[i] = CheckLesserOrGreater; // > } else { throw new ApplicationException("Incorrect lower flag."); } lowerCells[i] = ResolveCell(l); } // Now handle upper if (u == SelectableRange.LastInSet && uf == RangePosition.LastValue) { // Special case no upper check upperFlags[i] = NoCheck; } else { if (uf == RangePosition.LastValue) { upperFlags[i] = CheckLesserEqualOrGreaterEqual; // <= } else if (uf == RangePosition.BeforeFirstValue) { upperFlags[i] = CheckLesserOrGreater; // < } else { throw new ApplicationException("Incorrect upper flag."); } upperCells[i] = ResolveCell(u); } }
/// <summary> /// Returns the range as an array of SelectableRange or an empty array /// if there is no range. /// </summary> /// <returns></returns> public SelectableRange[] ToArray() { int sz = rangeSet.Count; SelectableRange[] ranges = new SelectableRange[sz]; for (int i = 0; i < sz; ++i) { ranges[i] = rangeSet[i]; } return(ranges); }
/// <inheritdoc/> public override IList <long> SelectRange(SelectableRange range) { long setSize = Table.RowCount; // If no items in the set return an empty set if (setSize == 0) { return(new List <long>(0)); } return(SelectRange(new SelectableRange[] { range })); }
/// <summary> /// Returns true if the two SelectableRange ranges intersect. /// </summary> private static bool RangeIntersectedBy(SelectableRange range1, SelectableRange range2) { RangePosition startFlag1 = range1.StartPosition; DataObject start1 = range1.Start; RangePosition endFlag1 = range1.EndPosition; DataObject end1 = range1.End; RangePosition startFlag2 = range2.StartPosition; DataObject start2 = range2.Start; RangePosition endFlag2 = range2.EndPosition; DataObject end2 = range2.End; DataObject startCell1 = start1 == SelectableRange.FirstInSet ? null : start1; DataObject endCell1 = end1 == SelectableRange.LastInSet ? null : end1; DataObject startCell2 = start2 == SelectableRange.FirstInSet ? null : start2; DataObject endCell2 = end2 == SelectableRange.LastInSet ? null : end2; bool intersect1 = false; if (startCell1 != null && endCell2 != null) { int c = startCell1.CompareTo(endCell2); if (c < 0 || (c == 0 && (startFlag1 == RangePosition.FirstValue || endFlag2 == RangePosition.LastValue))) { intersect1 = true; } } else { intersect1 = true; } bool intersect2 = false; if (startCell2 != null && endCell1 != null) { int c = startCell2.CompareTo(endCell1); if (c < 0 || (c == 0 && (startFlag2 == RangePosition.FirstValue || endFlag1 == RangePosition.LastValue))) { intersect2 = true; } } else { intersect2 = true; } return(intersect1 && intersect2); }
/// <summary> /// Intersects this range with the given Operator and value constant. /// </summary> /// <example> /// For example, if a range is <c>'a' -> [END]</c> and the given /// operator is '<=' and the value is 'z' the result range is 'a' -> 'z'. /// </example> public void Intersect(Operator op, DataObject val) { lock (this) { int sz = rangeSet.Count; List <SelectableRange> i = rangeSet.GetRange(0, sz); if (op.IsEquivalent(Operator.NotEqual) || op.IsEquivalent(Operator.IsNot)) { bool nullCheck = op.IsEquivalent(Operator.NotEqual); int j = 0; while (j < sz) { SelectableRange range = i[j]; SelectableRange leftRange = IntersectRange(range, Operator.Smaller, val, nullCheck); SelectableRange rightRange = IntersectRange(range, Operator.Greater, val, nullCheck); i.RemoveAt(j); if (leftRange != null) { i.Add(leftRange); } if (rightRange != null) { i.Add(rightRange); } j++; } rangeSet = new List <SelectableRange>(i); } else { bool nullCheck = !op.IsEquivalent(Operator.Is); int j = 0; while (j < sz) { SelectableRange range = i[j]; range = IntersectRange(range, op, val, nullCheck); if (range == null) { i.RemoveAt(j); } else { i[j] = range; } j++; } rangeSet = new List <SelectableRange>(i); } } }
/// <inheritdoc/> public override IList <long> SelectRange(SelectableRange range) { // If no items in the set return an empty set if (SetSize == 0) { return(new List <long>(0)); } IList <long> list = AddRange(range, null); if (list == null) { return(new List <long>(0)); } return(list); }
/// <summary> /// Adds a range from this set to the given list of integers. /// </summary> /// <param name="range">The instance of <see cref="SelectableRange"/> /// used to identify the indexes of nodes to add to the given list.</param> /// <param name="list">The list of integers where to add the selected range /// of indexes.</param> /// <remarks> /// IntegerList may be null if a list has not yet been allocated for /// the range. /// </remarks> /// <returns> /// Returns the given <paramref name="list"/> integrated with the range /// of values identified by the given <pramref name="range"/> selector. /// </returns> private IList <long> AddRange(SelectableRange range, IList <long> list) { // Select the range specified. RangePosition startFlag = range.StartPosition; DataObject start = range.Start; RangePosition endFlag = range.EndPosition; DataObject end = range.End; long r1 = PositionOfRangePoint(startFlag, start); long r2 = PositionOfRangePoint(endFlag, end); if (r2 < r1) { return(list); } // Add the range to the set return(AddRangeToSet(r1, r2, list)); }
/// <inheritdoc/> public override IList<long> SelectRange(SelectableRange range) { // If no items in the set return an empty set if (SetSize == 0) return new List<long>(0); IList<long> list = AddRange(range, null); if (list == null) return new List<long>(0); return list; }
/// <summary> /// Set up a range. /// </summary> /// <param name="i"></param> /// <param name="range"></param> private void SetupRange(int i, SelectableRange range) { DataObject l = range.Start; RangePosition lf = range.StartPosition; DataObject u = range.End; RangePosition uf = range.EndPosition; // Handle lower first if (l == SelectableRange.FirstInSet && lf == RangePosition.FirstValue) { // Special case no lower check lowerFlags[i] = NoCheck; } else { if (lf == RangePosition.FirstValue) { lowerFlags[i] = CheckLesserEqualOrGreaterEqual; // >= } else if (lf == RangePosition.AfterLastValue) { lowerFlags[i] = CheckLesserOrGreater; // > } else { throw new ApplicationException("Incorrect lower flag."); } lowerCells[i] = ResolveCell(l); } // Now handle upper if (u == SelectableRange.LastInSet && uf == RangePosition.LastValue) { // Special case no upper check upperFlags[i] = NoCheck; } else { if (uf == RangePosition.LastValue) { upperFlags[i] = CheckLesserEqualOrGreaterEqual; // <= } else if (uf == RangePosition.BeforeFirstValue) { upperFlags[i] = CheckLesserOrGreater; // < } else { throw new ApplicationException("Incorrect upper flag."); } upperCells[i] = ResolveCell(u); } }
/// <summary> /// Constructs the checker. /// </summary> /// <param name="scheme"></param> /// <param name="ranges"></param> public RangeChecker(BlindSearch scheme, SelectableRange[] ranges) { this.scheme = scheme; int size = ranges.Length; lowerFlags = new byte[size]; upperFlags = new byte[size]; lowerCells = new DataObject[size]; upperCells = new DataObject[size]; for (int i = 0; i < ranges.Length; ++i) { SetupRange(i, ranges[i]); } }
/// <inheritdoc/> public override IList<long> SelectRange(SelectableRange[] ranges) { long setSize = Table.RowCount; // If no items in the set return an empty set if (setSize == 0) return new List<long>(0); RangeChecker checker = new RangeChecker(this, ranges); return checker.Resolve(); }
/// <inheritdoc/> public override IList<long> SelectRange(SelectableRange range) { long setSize = Table.RowCount; // If no items in the set return an empty set if (setSize == 0) return new List<long>(0); return SelectRange(new SelectableRange[] { range }); }
/// <summary> /// Intersects the given SelectableRange object with the given operator and /// value constraint. /// </summary> /// <remarks> /// <b>Note</b>: This does not work with the <c><></c> operator /// which must be handled another way. /// </remarks> private static SelectableRange IntersectRange(SelectableRange range, Operator op, DataObject val, bool nullCheck) { DataObject start = range.Start; RangePosition startPosition = range.StartPosition; DataObject end = range.End; RangePosition endPosition = range.EndPosition; bool inclusive = op.IsEquivalent(Operator.Is) || op.IsEquivalent(Operator.Equal) || op.IsEquivalent(Operator.GreaterOrEqual) || op.IsEquivalent(Operator.SmallerOrEqual); if (op.IsEquivalent(Operator.Is) || op.IsEquivalent(Operator.Equal) || op.IsEquivalent(Operator.Greater) || op.IsEquivalent(Operator.GreaterOrEqual)) { // With this operator, NULL values must return null. if (nullCheck && val.IsNull) { return(null); } if (start == SelectableRange.FirstInSet) { start = val; startPosition = inclusive ? RangePosition.FirstValue : RangePosition.AfterLastValue; } else { int c = val.CompareTo(start); if ((c == 0 && startPosition == RangePosition.FirstValue) || c > 0) { start = val; startPosition = inclusive ? RangePosition.FirstValue : RangePosition.AfterLastValue; } } } if (op.IsEquivalent(Operator.Is) || op.IsEquivalent(Operator.Equal) || op.IsEquivalent(Operator.Smaller) || op.IsEquivalent(Operator.SmallerOrEqual)) { // With this operator, NULL values must return null. if (nullCheck && val.IsNull) { return(null); } // If start is first in set, then we have to change it to after NULL if (nullCheck && start == SelectableRange.FirstInSet) { start = DataObject.Null; startPosition = RangePosition.AfterLastValue; } if (end == SelectableRange.LastInSet) { end = val; endPosition = inclusive ? RangePosition.LastValue : RangePosition.BeforeFirstValue; } else { int c = val.CompareTo(end); if ((c == 0 && endPosition == RangePosition.LastValue) || c < 0) { end = val; endPosition = inclusive ? RangePosition.LastValue : RangePosition.BeforeFirstValue; } } } // If start and end are not null types (if either are, then it means it // is a placeholder value meaning start or end of set). if (start != SelectableRange.FirstInSet && end != SelectableRange.LastInSet) { // If start is higher than end, return null int c = start.CompareTo(end); if ((c == 0 && (startPosition == RangePosition.AfterLastValue || endPosition == RangePosition.BeforeFirstValue)) || c > 0) { return(null); } } // The new intersected range return(new SelectableRange(startPosition, start, endPosition, end)); }
/// <summary> /// Alters the first range so it encompasses the second range. /// </summary> /// <remarks> /// This assumes that range1 intersects range2. /// </remarks> private static SelectableRange ChangeRangeSizeToEncompass(SelectableRange range1, SelectableRange range2) { RangePosition startPosition1 = range1.StartPosition; DataObject start1 = range1.Start; RangePosition endPosition1 = range1.EndPosition; DataObject end1 = range1.End; RangePosition startPosition2 = range2.StartPosition; DataObject start2 = range2.Start; RangePosition endPosition2 = range2.EndPosition; DataObject end2 = range2.End; if (start1 != SelectableRange.FirstInSet) { if (start2 != SelectableRange.FirstInSet) { DataObject cell = start1; int c = cell.CompareTo(start2); if (c > 0 || c == 0 && startPosition1 == RangePosition.AfterLastValue && startPosition2 == RangePosition.FirstValue) { start1 = start2; startPosition1 = startPosition2; } } else { start1 = start2; startPosition1 = startPosition2; } } if (end1 != SelectableRange.LastInSet) { if (end2 != SelectableRange.LastInSet) { DataObject cell = end1; int c = cell.CompareTo(end2); if (c < 0 || c == 0 && endPosition1 == RangePosition.BeforeFirstValue && endPosition2 == RangePosition.LastValue) { end1 = end2; endPosition1 = endPosition2; } } else { end1 = end2; endPosition1 = endPosition2; } } return new SelectableRange(startPosition1, start1, endPosition1, end1); }
/// <summary> /// Intersects the given SelectableRange object with the given operator and /// value constraint. /// </summary> /// <remarks> /// <b>Note</b>: This does not work with the <c><></c> operator /// which must be handled another way. /// </remarks> private static SelectableRange IntersectRange(SelectableRange range, Operator op, DataObject val, bool nullCheck) { DataObject start = range.Start; RangePosition startPosition = range.StartPosition; DataObject end = range.End; RangePosition endPosition = range.EndPosition; bool inclusive = op.IsEquivalent(Operator.Is) || op.IsEquivalent(Operator.Equal) || op.IsEquivalent(Operator.GreaterOrEqual) || op.IsEquivalent(Operator.SmallerOrEqual); if (op.IsEquivalent(Operator.Is) || op.IsEquivalent(Operator.Equal) || op.IsEquivalent(Operator.Greater) || op.IsEquivalent(Operator.GreaterOrEqual)) { // With this operator, NULL values must return null. if (nullCheck && val.IsNull) { return null; } if (start == SelectableRange.FirstInSet) { start = val; startPosition = inclusive ? RangePosition.FirstValue : RangePosition.AfterLastValue; } else { int c = val.CompareTo(start); if ((c == 0 && startPosition == RangePosition.FirstValue) || c > 0) { start = val; startPosition = inclusive ? RangePosition.FirstValue : RangePosition.AfterLastValue; } } } if (op.IsEquivalent(Operator.Is) || op.IsEquivalent(Operator.Equal) || op.IsEquivalent(Operator.Smaller) || op.IsEquivalent(Operator.SmallerOrEqual)) { // With this operator, NULL values must return null. if (nullCheck && val.IsNull) { return null; } // If start is first in set, then we have to change it to after NULL if (nullCheck && start == SelectableRange.FirstInSet) { start = DataObject.Null; startPosition = RangePosition.AfterLastValue; } if (end == SelectableRange.LastInSet) { end = val; endPosition = inclusive ? RangePosition.LastValue : RangePosition.BeforeFirstValue; } else { int c = val.CompareTo(end); if ((c == 0 && endPosition == RangePosition.LastValue) || c < 0) { end = val; endPosition = inclusive ? RangePosition.LastValue : RangePosition.BeforeFirstValue; } } } // If start and end are not null types (if either are, then it means it // is a placeholder value meaning start or end of set). if (start != SelectableRange.FirstInSet && end != SelectableRange.LastInSet) { // If start is higher than end, return null int c = start.CompareTo(end); if ((c == 0 && (startPosition == RangePosition.AfterLastValue || endPosition == RangePosition.BeforeFirstValue)) || c > 0) { return null; } } // The new intersected range return new SelectableRange(startPosition, start, endPosition, end); }
/// <summary> /// Returns the range as an array of SelectableRange or an empty array /// if there is no range. /// </summary> /// <returns></returns> public SelectableRange[] ToArray() { int sz = rangeSet.Count; SelectableRange[] ranges = new SelectableRange[sz]; for (int i = 0; i < sz; ++i) { ranges[i] = rangeSet[i]; } return ranges; }
/// <inheritdoc/> public override IList<long> SelectRange(SelectableRange[] ranges) { // If no items in the set return an empty set if (SetSize == 0) return new List<long>(0); IList<long> list = null; foreach (SelectableRange range in ranges) { list = AddRange(range, list); } if (list == null) return new List<long>(0); return list; }
/// <summary> /// Returns true if the two SelectableRange ranges intersect. /// </summary> private static bool RangeIntersectedBy(SelectableRange range1, SelectableRange range2) { RangePosition startFlag1 = range1.StartPosition; DataObject start1 = range1.Start; RangePosition endFlag1 = range1.EndPosition; DataObject end1 = range1.End; RangePosition startFlag2 = range2.StartPosition; DataObject start2 = range2.Start; RangePosition endFlag2 = range2.EndPosition; DataObject end2 = range2.End; DataObject startCell1 = start1 == SelectableRange.FirstInSet ? null : start1; DataObject endCell1 = end1 == SelectableRange.LastInSet ? null : end1; DataObject startCell2 = start2 == SelectableRange.FirstInSet ? null : start2; DataObject endCell2 = end2 == SelectableRange.LastInSet ? null : end2; bool intersect1 = false; if (startCell1 != null && endCell2 != null) { int c = startCell1.CompareTo(endCell2); if (c < 0 || (c == 0 && (startFlag1 == RangePosition.FirstValue || endFlag2 == RangePosition.LastValue))) { intersect1 = true; } } else { intersect1 = true; } bool intersect2 = false; if (startCell2 != null && endCell1 != null) { int c = startCell2.CompareTo(endCell1); if (c < 0 || (c == 0 && (startFlag2 == RangePosition.FirstValue || endFlag1 == RangePosition.LastValue))) { intersect2 = true; } } else { intersect2 = true; } return (intersect1 && intersect2); }
/// <summary> /// Adds a range from this set to the given list of integers. /// </summary> /// <param name="range">The instance of <see cref="SelectableRange"/> /// used to identify the indexes of nodes to add to the given list.</param> /// <param name="list">The list of integers where to add the selected range /// of indexes.</param> /// <remarks> /// IntegerList may be null if a list has not yet been allocated for /// the range. /// </remarks> /// <returns> /// Returns the given <paramref name="list"/> integrated with the range /// of values identified by the given <pramref name="range"/> selector. /// </returns> private IList<long> AddRange(SelectableRange range, IList<long> list) { // Select the range specified. RangePosition startFlag = range.StartPosition; DataObject start = range.Start; RangePosition endFlag = range.EndPosition; DataObject end = range.End; long r1 = PositionOfRangePoint(startFlag, start); long r2 = PositionOfRangePoint(endFlag, end); if (r2 < r1) return list; // Add the range to the set return AddRangeToSet(r1, r2, list); }
/// <summary> /// Selects the given range of values from this index. /// </summary> /// <param name="range"></param> /// <remarks> /// The <see cref="SelectableRange"/> must contain a /// <see cref="SelectableRange.Start"/> value that compares <= to /// the <see cref="SelectableRange.End"/> value. /// <para> /// This must guarentee that the returned set is sorted from lowest to /// highest value. /// </para> /// </remarks> /// <returns></returns> public abstract IList <long> SelectRange(SelectableRange range);