public static Range <int> EqualRange <TElement, TValue>( [NotNull, ItemNotNull, InstantHandle] this IList <TElement> list, TValue value, int startIndex, int endIndex) where TElement : IComparable <TValue> { Code.NotNull(list, nameof(list)); ValidateIndicesRange(startIndex, endIndex, list.Count); var upperBoundStartIndex = startIndex; var upperBoundEndIndex = endIndex; // the loop locates the lower bound at the same time restricting the range for upper bound search while (startIndex < endIndex) { var median = startIndex + (endIndex - startIndex) / 2; var compareResult = list[median].CompareTo(value); if (compareResult < 0) { startIndex = median + 1; upperBoundStartIndex = startIndex; } else if (compareResult == 0) { endIndex = median; upperBoundStartIndex = endIndex + 1; } else { endIndex = median; upperBoundEndIndex = endIndex; } } return(Range.Create(startIndex, UpperBoundCore(list, value, upperBoundStartIndex, upperBoundEndIndex))); }
public static Range <int> EqualRange( [NotNull, InstantHandle] this IList <float> list, float value, int startIndex, int endIndex) { Code.NotNull(list, nameof(list)); ValidateIndicesRange(startIndex, endIndex, list.Count); var upperBoundStartIndex = startIndex; var upperBoundEndIndex = endIndex; // the loop locates the lower bound at the same time restricting the range for upper bound search while (startIndex < endIndex) { var median = startIndex + (endIndex - startIndex) / 2; if (list[median] < value) { startIndex = median + 1; upperBoundStartIndex = startIndex; } else if (list[median] == value) { endIndex = median; upperBoundStartIndex = endIndex + 1; } else { endIndex = median; upperBoundEndIndex = endIndex; } } return(Range.Create(startIndex, UpperBoundCore(list, value, upperBoundStartIndex, upperBoundEndIndex))); }
public static void TestRangeToString() { int?value1 = 1; int?empty = null; var key = "Hello!"; AreEqual(Range <int> .Empty.ToString(), "∅"); AreEqual(Range <int> .Infinite.ToString(), "(-∞..+∞)"); AreEqual(Range.Create(1, 1).ToString(), "[1..1]"); AreEqual(Range.Create(1, 2).ToString(), "[1..2]"); AreEqual(Range.CreateExclusive(1, 2).ToString(), "(1..2)"); AreEqual(Range.CreateExclusiveFrom(1, 2).ToString(), "(1..2]"); AreEqual(Range.CreateExclusiveTo(1, 2).ToString(), "[1..2)"); AreEqual(Range.CreateExclusive(value1, empty).ToString("000"), "(001..+∞)"); AreEqual(Range.Create(RangeBoundaryFrom <int> .Empty, RangeBoundaryTo <int> .Empty, key).ToString(), "'Hello!':∅"); AreEqual(Range.Create(empty, empty, key).ToString(), "'Hello!':(-∞..+∞)"); AreEqual(Range.Create(empty, empty, (string)null).ToString(), "'':(-∞..+∞)"); AreEqual(Range.Create(1, 1, key).ToString(), "'Hello!':[1..1]"); AreEqual(Range.Create(1, 2, key).ToString(), "'Hello!':[1..2]"); AreEqual(Range.CreateExclusive(1, 2, key).ToString(), "'Hello!':(1..2)"); AreEqual(Range.CreateExclusiveFrom(1, 2, key).ToString(), "'Hello!':(1..2]"); AreEqual(Range.CreateExclusiveTo(1, 2, key).ToString(), "'Hello!':[1..2)"); AreEqual(Range.CreateExclusive(value1, empty, 3).ToString("000"), "'3':(001..+∞)"); var cultureRu = CultureInfo.GetCultureInfo("ru-RU"); var cultureEn = CultureInfo.GetCultureInfo("en-US"); AreEqual(Range.Create(1.5, 2.5, 1.1).ToString("000.000", cultureRu), "'1,1':[001,500..002,500]"); AreEqual(Range.Create(1.5, 2.5, 1.1).ToString("000.000", cultureEn), "'1.1':[001.500..002.500]"); AreEqual(Range.Create(1.5, 2.5, (string)null).ToString(null, cultureRu), "'':[1,5..2,5]"); AreEqual(Range.Create(1.5, 2.5, (string)null).ToString(null, cultureEn), "'':[1.5..2.5]"); }
public static void TestRangeAdjust() { var emptyFrom = RangeBoundaryFrom <double> .Empty; var emptyTo = RangeBoundaryTo <double> .Empty; var range = Range.Create(1.0, 2.0); AreEqual(range.Adjust(double.NegativeInfinity), 1); AreEqual(range.Adjust(0), 1); AreEqual(range.Adjust(1), 1); AreEqual(range.Adjust(1.5), 1.5); AreEqual(range.Adjust(2), 2); AreEqual(range.Adjust(3), 2); AreEqual(range.Adjust(double.PositiveInfinity), 2); range = Range.Create(double.NegativeInfinity, double.PositiveInfinity); AreEqual(range.Adjust(double.NegativeInfinity), double.NegativeInfinity); AreEqual(range.Adjust(0), 0); AreEqual(range.Adjust(double.PositiveInfinity), double.PositiveInfinity); range = Range.Create(emptyFrom, emptyTo); Throws <ArgumentException>(() => range.Adjust(double.NegativeInfinity)); Throws <ArgumentException>(() => range.Adjust(1)); Throws <ArgumentException>(() => range.Adjust(double.PositiveInfinity)); range = Range.CreateExclusive(1.0, 2.0); Throws <ArgumentException>(() => range.Adjust(double.NegativeInfinity)); Throws <ArgumentException>(() => range.Adjust(1.5)); Throws <ArgumentException>(() => range.Adjust(double.PositiveInfinity)); }
public static void TestRangeMakeInclusiveExclusive() { var range = Range.Create(1, 2); AreEqual(range, range.MakeInclusive(i => i - 1, i => i + 1)); range = Range.CreateExclusive(1, 2); AreEqual(Range.Create(0, 3), range.MakeInclusive(i => i - 1, i => i + 1)); range = Range.CreateExclusiveTo(1, 2); AreEqual(Range.Create(1, 3), range.MakeInclusive(i => i - 1, i => i + 1)); range = Range.CreateExclusive(1, 2); AreEqual(range, range.MakeExclusive(i => i - 1, i => i + 1)); range = Range.Create(1, 2); AreEqual(Range.CreateExclusive(0, 3), range.MakeExclusive(i => i - 1, i => i + 1)); range = Range.CreateExclusiveFrom(1, 2); AreEqual(Range.CreateExclusive(1, 3), range.MakeExclusive(i => i - 1, i => i + 1)); range = Range.CreateExclusive(2, 3); IsTrue(range.MakeInclusive(i => i + 1, i => i - 1).IsEmpty); range = Range.Create(2, 3); IsTrue(range.MakeExclusive(i => i + 1, i => i - 1).IsEmpty); range = Range.CreateExclusive(2, 3); IsTrue(range.MakeInclusive(i => i + 1, i => i - 1).IsEmpty); range = Range.Create(2, 3); IsTrue(range.MakeExclusive(i => i + 1, i => i - 1).IsEmpty); var range2 = Range.CreateExclusive(1, double.PositiveInfinity); IsTrue(range2.MakeInclusive(i => double.NegativeInfinity, i => i + 1).IsInfinite); range2 = Range.Create(double.NegativeInfinity, 2); IsTrue(range2.MakeExclusive(i => i + 1, i => double.PositiveInfinity).IsInfinite); range2 = Range.Create(double.NegativeInfinity, double.PositiveInfinity); AreEqual(range2, range2.MakeInclusive(i => i - 1, i => i + 1)); }
public static void TestRangeProperties() { int?value1 = 1; int?value2 = 2; int?empty = null; var key = "Hello!"; var a = new Range <int?>(); Throws <InvalidOperationException>(() => a.FromValue.ToString()); Throws <InvalidOperationException>(() => a.ToValue.ToString()); AreEqual(a.From.Kind, RangeBoundaryFromKind.Empty); AreEqual(a.To.Kind, RangeBoundaryToKind.Empty); IsTrue(a.IsEmpty); IsFalse(a.IsNotEmpty); IsFalse(a.IsInfinite); IsFalse(a.IsSinglePoint); a = Range <int?> .Infinite; Throws <InvalidOperationException>(() => a.FromValue.ToString()); Throws <InvalidOperationException>(() => a.ToValue.ToString()); AreEqual(a.From.Kind, RangeBoundaryFromKind.Infinite); AreEqual(a.To.Kind, RangeBoundaryToKind.Infinite); IsFalse(a.IsEmpty); IsTrue(a.IsNotEmpty); IsTrue(a.IsInfinite); IsFalse(a.IsSinglePoint); a = Range.CreateExclusiveTo(empty, value2); Throws <InvalidOperationException>(() => a.FromValue.ToString()); AreEqual(a.ToValue, value2); AreEqual(a.From.Kind, RangeBoundaryFromKind.Infinite); AreEqual(a.To.Kind, RangeBoundaryToKind.Exclusive); IsFalse(a.IsEmpty); IsTrue(a.IsNotEmpty); IsFalse(a.IsInfinite); IsFalse(a.IsSinglePoint); a = Range.Create(value1, value2); AreEqual(a.FromValue, value1); AreEqual(a.ToValue, value2); AreEqual(a.From.Kind, RangeBoundaryFromKind.Inclusive); AreEqual(a.To.Kind, RangeBoundaryToKind.Inclusive); IsFalse(a.IsEmpty); IsTrue(a.IsNotEmpty); IsFalse(a.IsInfinite); IsFalse(a.IsSinglePoint); var b = Range.Create(value1, value1, key); AreEqual(b.FromValue, value1); AreEqual(b.ToValue, value1); AreEqual(b.Key, key); AreEqual(b.From.Kind, RangeBoundaryFromKind.Inclusive); AreEqual(b.To.Kind, RangeBoundaryToKind.Inclusive); IsFalse(b.IsEmpty); IsTrue(b.IsNotEmpty); IsFalse(b.IsInfinite); IsTrue(b.IsSinglePoint); }
public static void TestRangeEquality() { int?value1 = 1; int?value2 = 2; int?empty = null; var key = "Hello!"; var key2 = "Hello2!"; var eFrom = new RangeBoundaryFrom <int?>(); var eTo = new RangeBoundaryTo <int?>(); AreEqual(Range <int?> .Empty, Range.Create(eFrom, eTo)); AreEqual(Range <int?> .Infinite, Range.Create(empty, empty)); AreNotEqual(Range <double?> .Infinite, Range.Create(empty, empty)); AreEqual( Range.CreateExclusiveFrom(value1, value2).From, Range.BoundaryFromExclusive(value1)); AreEqual( Range.CreateExclusiveFrom(value1, value2).To, Range.BoundaryTo(value2)); AreNotEqual( Range.CreateExclusiveFrom(value1, value2), Range.Create(value1, value2)); IsTrue(Range.Create(value1, value2) == Range.Create <int?>(1, 2)); IsTrue(Range.Create(value1, value2) != Range.Create(value1, 1)); IsTrue(Range.Create(value1, value2, key) == Range.Create <int?, string>(1, 2, key)); IsTrue(Range.Create(value1, value2, key) != Range.Create <int?, string>(1, 2, key2)); IsTrue(Range.Create(value1, value2, key) != Range.Create <int?, string>(1, 1, key)); }
public static CompositeRange <T, TKey> ToCompositeRange <T, TKey>( this IEnumerable <TKey> source, [InstantHandle] Func <TKey, T> fromValueSelector, [InstantHandle] Func <TKey, T> toValueSelector) where TKey : notnull => source .Select(s => Range.Create(fromValueSelector(s), toValueSelector(s), s)) .ToCompositeRange();
/// <summary>Converts sequence of elements to the composite range.</summary> /// <typeparam name="TSource">The type of the values in original collection.</typeparam> /// <typeparam name="T">The type of the range values.</typeparam> /// <typeparam name="TKey">The type of the range key</typeparam> /// <param name="source">Original collection.</param> /// <param name="fromValueSelector">Callback to obtain a value for the From boundary.</param> /// <param name="toValueSelector">Callback to obtain a value for the To boundary.</param> /// <param name="keySelector">Callback to obtain a value for the range key.</param> /// <returns>A new composite range with keys filled from the original collection.</returns> public static CompositeRange <T, TKey> ToCompositeRange <TSource, T, TKey>( [NotNull] this IEnumerable <TSource> source, [NotNull, InstantHandle] Func <TSource, T> fromValueSelector, [NotNull, InstantHandle] Func <TSource, T> toValueSelector, [NotNull, InstantHandle] Func <TSource, TKey> keySelector) => source .Select(s => Range.Create(fromValueSelector(s), toValueSelector(s), keySelector(s))) .ToCompositeRange();
public static void TestRangeContainsRange2() { double?empty = null; double?value1 = 1; double?value2 = 2; var emptyFrom = RangeBoundaryFrom <double?> .Empty; var emptyTo = RangeBoundaryTo <double?> .Empty; var range = Range.Create(value1, value2); IsTrue(range.Contains(1, 2)); IsFalse(range.Contains(1, null)); IsFalse(range.Contains(null, null)); IsFalse(range.Contains(double.NegativeInfinity, double.PositiveInfinity)); Throws <ArgumentException>(() => range.Contains(2, 1)); Throws <ArgumentException>(() => range.Contains(double.PositiveInfinity, double.NegativeInfinity)); IsTrue(range.Contains(1.5, 1.5)); IsTrue(range.Contains(1.5, 2)); IsFalse(range.Contains(0, 3)); IsFalse(range.Contains(0, 1.5)); IsFalse(range.Contains(1.5, 3)); IsFalse(range.Contains(3, 4)); range = Range.Create(emptyFrom, emptyTo); IsTrue(range.Contains(range)); IsFalse(range.Contains(1, 2)); IsTrue(range.Contains(Range.Create(emptyFrom, emptyTo, _rangeKey2))); IsFalse(range.Contains(1, null)); IsTrue(range.Contains(Range <double?> .Empty)); IsFalse(range.Contains(Range <double?> .Infinite)); IsFalse(range.Contains(null, null)); IsFalse(range.Contains(double.NegativeInfinity, double.PositiveInfinity)); Throws <ArgumentException>( () => range.Contains(2, 1)); Throws <ArgumentException>( () => range.Contains(double.PositiveInfinity, double.NegativeInfinity)); range = Range.CreateExclusive(empty, empty); IsTrue(range.Contains(range)); IsTrue(range.Contains(Range.CreateExclusive(empty, empty, _rangeKey2))); IsTrue(range.Contains(1, 2)); IsTrue(range.Contains(1, null)); IsFalse(range.Contains(Range <double?> .Empty)); IsTrue(range.Contains(Range <double?> .Infinite)); IsTrue(range.Contains(null, null)); IsTrue(range.Contains(double.NegativeInfinity, double.PositiveInfinity)); Throws <ArgumentException>( () => range.Contains(2, 1)); Throws <ArgumentException>( () => range.Contains(double.PositiveInfinity, double.NegativeInfinity)); range = Range.CreateExclusive(value1, value2); IsTrue(range.Contains(Range.CreateExclusive(value1, value2, _rangeKey2))); IsFalse(range.Contains(1, 2)); IsTrue(range.Contains(1.5, 1.5)); IsFalse(range.Contains(1.5, 2)); IsFalse(range.Contains(3, 4)); }
public static void TestRangeContains() { double?empty = null; double?value1 = 1; double?value2 = 2; var emptyFrom = RangeBoundaryFrom <double?> .Empty; var emptyTo = RangeBoundaryTo <double?> .Empty; var range = Range.Create(value1, value2); IsFalse(range.Contains(null)); IsFalse(range.Contains(double.NegativeInfinity)); IsFalse(range.Contains(double.PositiveInfinity)); IsFalse(range.Contains(RangeBoundaryFrom <double?> .Empty)); IsFalse(range.Contains(RangeBoundaryTo <double?> .Empty)); IsFalse(range.Contains(0)); IsTrue(range.Contains(1)); IsTrue(range.Contains(1.5)); IsTrue(range.Contains(2)); IsFalse(range.Contains(3)); range = Range.Create(emptyFrom, emptyTo); IsFalse(range.Contains(null)); IsFalse(range.Contains(double.NegativeInfinity)); IsFalse(range.Contains(double.PositiveInfinity)); IsTrue(range.Contains(RangeBoundaryFrom <double?> .Empty)); IsTrue(range.Contains(RangeBoundaryTo <double?> .Empty)); IsFalse(range.Contains(0)); range = Range.CreateExclusive(empty, empty); IsTrue(range.Contains(null)); IsTrue(range.Contains(double.NegativeInfinity)); IsTrue(range.Contains(double.PositiveInfinity)); IsFalse(range.Contains(RangeBoundaryFrom <double?> .Empty)); IsFalse(range.Contains(RangeBoundaryTo <double?> .Empty)); IsTrue(range.Contains(0)); range = Range.CreateExclusive(value1, value2); IsFalse(range.Contains(1)); IsTrue(range.Contains(1.5)); IsFalse(range.Contains(2)); range = Range.CreateExclusive(value1, value2); IsFalse(range.Contains(Range.BoundaryFrom <double?>(1))); IsFalse(range.Contains(Range.BoundaryTo <double?>(2))); IsTrue(range.Contains(Range.BoundaryFromExclusive <double?>(1))); IsTrue(range.Contains(Range.BoundaryFromExclusive <double?>(1.5))); IsFalse(range.Contains(Range.BoundaryFromExclusive <double?>(2))); IsFalse(range.Contains(Range.BoundaryToExclusive <double?>(1))); IsTrue(range.Contains(Range.BoundaryToExclusive <double?>(1.5))); IsTrue(range.Contains(Range.BoundaryToExclusive <double?>(2))); Throws <ArgumentException>( () => range.Contains(Range.BoundaryFrom <double?>(double.PositiveInfinity))); Throws <ArgumentException>( () => range.Contains(Range.BoundaryTo <double?>(double.NegativeInfinity))); }
public static void TestRangeWithKey() { var range = Range.Create(1, 2); AreEqual(range.WithKey(_rangeKey2), Range.Create(1, 2, _rangeKey2)); AreEqual(range.WithKey(_rangeKey2).WithoutKey(), new Range <int>(1, 2)); var toInf = (double?)double.PositiveInfinity; var range2 = Range.CreateExclusive(1, toInf); AreEqual(range2.WithKey(_rangeKey2).Key, _rangeKey2); }
public void CompareTo() { Assert.AreEqual(-1, Range.StartsWith(1).CompareTo(Range.StartsWith(1, false))); Assert.AreEqual(0, Range.StartsWith(1).CompareTo(Range.StartsWith(1))); Assert.AreEqual(0, Range.StartsWith(1, false).CompareTo(Range.StartsWith(1, false))); Assert.AreEqual(1, Range.StartsWith(1, false).CompareTo(Range.StartsWith(1, true))); Assert.AreEqual(0, Range.Create(1, 3, true).CompareTo(Range.Create(1, 3, true))); Assert.AreEqual(0, Range.Create(1, 3, false).CompareTo(Range.Create(1, 3, false))); Assert.AreEqual(1, Range.Create(1, 3, true, true).CompareTo(Range.Create(1, 3, true, false))); Assert.AreEqual(-1, Range.Create(1, 3, true, false).CompareTo(Range.Create(1, 3, true, true))); }
public static Range <T> ParseRange <T>(string value, Func <string, T> parseValueCallback) { if (value == RangeInternal.EmptyString) { return(Range <T> .Empty); } var boundaries = value.Split(new[] { RangeInternal.SeparatorString }, 2, StringSplitOptions.None); return(Range.Create( ParseBoundaryFromCore(boundaries[0], parseValueCallback), ParseBoundaryToCore(boundaries[1], parseValueCallback))); }
public static void TestKeyedRangeUnion() { double value1 = 1; double value2 = 2; var emptyFrom = RangeBoundaryFrom <double> .Empty; var emptyTo = RangeBoundaryTo <double> .Empty; var emptyRange = Range.Create(emptyFrom, emptyTo, RangeKey); var infiniteRange = Range.Create(double.NegativeInfinity, double.PositiveInfinity, RangeKey); var range = Range.Create(value1, value2, RangeKey); AreEqual(range.Union(range), range); AreEqual(range.Union(1, 2), range); AreEqual(range.Union(1.5, 1.5), range); AreEqual(range.Union(0, 3), Range.Create(0.0, 3.0, RangeKey)); AreEqual(range.Union(1.5, 3), Range.Create(1.0, 3.0, RangeKey)); AreEqual(range.Union(0, 1.5), Range.Create(0.0, 2.0, RangeKey)); AreEqual(range.Union(3, 4), Range.Create(1.0, 4.0, RangeKey)); AreEqual(range.Union(-2, -1), Range.Create(-2.0, 2.0, RangeKey)); AreEqual(range.Union(emptyRange), range); AreEqual(emptyRange.Union(range), range); AreEqual(range.Union(infiniteRange), infiniteRange); AreEqual(infiniteRange.Union(range), infiniteRange); AreEqual(emptyRange.Union(infiniteRange), infiniteRange); AreEqual(infiniteRange.Union(emptyRange), infiniteRange); range = Range.CreateExclusive(value1, value2, RangeKey); AreEqual(range.Union(range), range); AreEqual(range.Union(1, 2), Range.Create(1.0, 2.0, RangeKey)); AreEqual(range.Union(1.5, 1.5), range); AreEqual(range.Union(0, 3), Range.Create(0.0, 3.0, RangeKey)); AreEqual(range.Union(1.5, 3), Range.CreateExclusiveFrom(1.0, 3.0, RangeKey)); AreEqual(range.Union(0, 1.5), Range.CreateExclusiveTo(0.0, 2.0, RangeKey)); AreEqual(range.Union(3, 4), Range.CreateExclusiveFrom(1.0, 4.0, RangeKey)); AreEqual(range.Union(-2, -1), Range.CreateExclusiveTo(-2.0, 2.0, RangeKey)); AreEqual(range.Union(emptyRange), range); AreEqual(emptyRange.Union(range), range); AreEqual(range.Union(infiniteRange), infiniteRange); AreEqual(infiniteRange.Union(range), infiniteRange); AreEqual(emptyRange.Union(infiniteRange), infiniteRange); AreEqual(infiniteRange.Union(emptyRange), infiniteRange); Throws <ArgumentException>( () => range.Union(2, 1)); Throws <ArgumentException>( () => range.Union(double.PositiveInfinity, double.NegativeInfinity)); Throws <ArgumentException>( () => range.Union(2, double.NegativeInfinity)); Throws <ArgumentException>( () => range.Union(double.PositiveInfinity, 1)); }
public static void TestRangeIntersection() { double value1 = 1; double value2 = 2; var emptyFrom = RangeBoundaryFrom <double> .Empty; var emptyTo = RangeBoundaryTo <double> .Empty; var emptyRange = Range.Create(emptyFrom, emptyTo); var infiniteRange = Range.Create(double.NegativeInfinity, double.PositiveInfinity); var range = Range.Create(value1, value2); AreEqual(range.Intersect(range), range); AreEqual(range.Intersect(1, 2), range); AreEqual(range.Intersect(1.5, 1.5), Range.Create(1.5, 1.5)); AreEqual(range.Intersect(0, 3), range); AreEqual(range.Intersect(1.5, 3), Range.Create(1.5, 2.0)); AreEqual(range.Intersect(0, 1.5), Range.Create(1.0, 1.5)); AreEqual(range.Intersect(3, 4), emptyRange); AreEqual(range.Intersect(-2, -1), emptyRange); AreEqual(range.Intersect(emptyRange), emptyRange); AreEqual(emptyRange.Intersect(range), emptyRange); AreEqual(range.Intersect(infiniteRange), range); AreEqual(infiniteRange.Intersect(range), range); AreEqual(emptyRange.Intersect(infiniteRange), emptyRange); AreEqual(infiniteRange.Intersect(emptyRange), emptyRange); range = Range.CreateExclusive(value1, value2); AreEqual(range.Intersect(range), range); AreEqual(range.Intersect(1, 2), range); AreEqual(range.Intersect(1.5, 1.5), Range.Create(1.5, 1.5)); AreEqual(range.Intersect(0, 3), range); AreEqual(range.Intersect(1.5, 3), Range.CreateExclusiveTo(1.5, 2.0)); AreEqual(range.Intersect(0, 1.5), Range.CreateExclusiveFrom(1.0, 1.5)); AreEqual(range.Intersect(3, 4), emptyRange); AreEqual(range.Intersect(-2, -1), emptyRange); AreEqual(range.Intersect(emptyRange), emptyRange); AreEqual(emptyRange.Intersect(range), emptyRange); AreEqual(range.Intersect(infiniteRange), range); AreEqual(infiniteRange.Intersect(range), range); AreEqual(emptyRange.Intersect(infiniteRange), emptyRange); AreEqual(infiniteRange.Intersect(emptyRange), emptyRange); Throws <ArgumentException>( () => range.Intersect(2, 1)); Throws <ArgumentException>( () => range.Intersect(double.PositiveInfinity, double.NegativeInfinity)); Throws <ArgumentException>( () => range.Intersect(2, double.NegativeInfinity)); Throws <ArgumentException>( () => range.Intersect(double.PositiveInfinity, 1)); }
public void Exclude() { CheckExclude(Range.EndsWith(5, true), Range.Create(2, 3, true, true), "..(2)", "(3)..5"); CheckExclude(Range.EndsWith(5, true), Range.Create(2, 5, true, false), "..(2)", "5"); CheckExclude(Range.EndsWith(5, true), Range.Create(2, 5, true, true), "..(2)"); CheckExclude(Range.EndsWith(5, false), Range.Create(2, 5, true, true), "..(2)"); CheckExclude(Range.EndsWith(5, false), Range.Create(2, 5, true, false), "..(2)"); CheckExclude(Range.Create(0, 5, true, true), Range.Create(2, 5, true, true), "0..(2)"); CheckExclude(Range.Create(0, 5, true, true), Range.Create(2, 10, true, true), "0..(2)"); CheckExclude(Range.Create(0, 5, true, true), Range.StartsWith(2, true), "0..(2)"); CheckExclude(Range.Create(0, 5, true, true), Range.StartsWith(5, false), "0..5"); CheckExclude(Range.Create(0, 5, true, true), Range.StartsWith(5, true), "0..(5)"); }
/// <summary>Creates instance of <seealso cref="CompositeRange{T}"/>.</summary> /// <param name="ranges">Contained ranges.</param> /// <param name="skipsArgHandling">Stub argument to mark unsafe (no validation) constructor overload.</param> internal CompositeRange([NotNull] IEnumerable <Range <T, TKey> > ranges, UnsafeOverload skipsArgHandling) { Code.NotNull(ranges, nameof(ranges)); #pragma warning disable 618 // ok by design. bool rangesReady = skipsArgHandling == UnsafeOverload.NoEmptyRangesAlreadySortedAndMerged; var tempRanges = rangesReady || skipsArgHandling == UnsafeOverload.NoEmptyRanges ? ranges.ToArray() : ranges.Where(r => r.IsNotEmpty).ToArray(); #pragma warning restore 618 if (tempRanges.Length == 0) { _ranges = _emptyRanges; _hasRangesToMerge = false; _containingRange = _emptyRangeNoKey; return; } if (tempRanges.Length == 1 || rangesReady) { _ranges = tempRanges.AsReadOnly(); _hasRangesToMerge = false; _containingRange = Range.Create(tempRanges[0].From, tempRanges[tempRanges.Length - 1].To); return; } #pragma warning disable 618 // ok by design. if (skipsArgHandling != UnsafeOverload.RangesAlreadySorted) #pragma warning restore 618 { Array.Sort(tempRanges, _rangeComparer); } bool hasRangesToMerge = false; var maxToBoundary = tempRanges[0].To; for (int i = 1; i < tempRanges.Length; i++) { var range = tempRanges[i]; // TODO: check for keyed range. hasRangesToMerge = hasRangesToMerge || IsContinuationFor(maxToBoundary, range); maxToBoundary = Range.Max(maxToBoundary, range.To); } _ranges = tempRanges.AsReadOnly(); _hasRangesToMerge = hasRangesToMerge; _containingRange = Range.Create(tempRanges[0].From, maxToBoundary); }
public static void TestKeyedRangeKeyFlow() { int?value1 = 1; int?empty = null; var key = "Hello!"; var range = Range.Create(value1, empty).WithKey("A"); AreEqual(range.ToString(CultureInfo.InvariantCulture), "'A':[1..+∞)"); AreNotEqual(range.Key, key); var prevRange = range.WithKey(key); range = prevRange; AreEqual(range.ToString(CultureInfo.InvariantCulture), "'Hello!':[1..+∞)"); AreEqual(range.Key, key); AreEqual(range, prevRange); range = range.Intersect(1, 2); AreEqual(range.ToString(CultureInfo.InvariantCulture), "'Hello!':[1..2]"); AreEqual(range.Key, key); AreNotEqual(range, prevRange); range = range.Union(4, 8); AreEqual(range.ToString(CultureInfo.InvariantCulture), "'Hello!':[1..8]"); AreEqual(range.Key, key); AreNotEqual(range, prevRange); range = range.Intersect(10, 20); AreEqual(range.ToString(CultureInfo.InvariantCulture), "'Hello!':∅"); AreEqual(range.Key, key); AreNotEqual(range, prevRange); range = range.Union(null, null); AreEqual(range.ToString(CultureInfo.InvariantCulture), "'Hello!':(-∞..+∞)"); AreEqual(range.Key, key); AreNotEqual(range, prevRange); range = range.TrimFrom(1); AreEqual(range.ToString(CultureInfo.InvariantCulture), "'Hello!':[1..+∞)"); AreEqual(range.Key, key); AreEqual(range, prevRange); range = Range.Create(value1, value1) .WithKey("B") .Intersect(range); AreEqual(range.ToString(CultureInfo.InvariantCulture), "'B':[1..1]"); AreNotEqual(range.Key, key); AreNotEqual(range, prevRange); }
public void Invert() { var list = Range.Create(20, 30).ToRangeList().Add(Range.Create(11, 12, false, true)); CheckList(list, "[(11)..12, 20..30]"); var invertedList = list.Invert(); CheckList(invertedList, "[..11, (12)..(20), (30)..]"); var invertedAgain = invertedList.Invert(); CheckList(invertedAgain, "[(11)..12, 20..30]"); Assert.AreEqual(list, invertedAgain); }
public void Contains() { var range = Range.Create(0, 2); Assert.IsTrue(range.Contains(0)); Assert.IsTrue(range.Contains(1)); Assert.IsTrue(range.Contains(2)); range = Range.Create(0, 2, false); Assert.IsFalse(range.Contains(0)); Assert.IsTrue(range.Contains(1)); Assert.IsFalse(range.Contains(2)); Assert.IsFalse(Range.Empty <int>().Contains(10)); }
public static void TestRangesCore(CompositeRange <int, string> ranges) { var tree = new IntervalTree <int, string>(ranges); for (var i = ranges.ContainingRange.FromValue; i <= ranges.ContainingRange.ToValue; i++) { var overlapRange = Range.Create(i, i); AssertSameOverlap(ranges, tree, overlapRange); overlapRange = Range.Create(i - 1, i + 1); AssertSameOverlap(ranges, tree, overlapRange); overlapRange = Range.Create(i - 2, i + 2); AssertSameOverlap(ranges, tree, overlapRange); overlapRange = Range.Create(i - 10, i); AssertSameOverlap(ranges, tree, overlapRange); } }
/// <summary> /// Converts sequence of elements to the composite range using only From boundary. /// The To boundary value is taken from the next item in sequence (+∞ for the last item in sequence) /// </summary> /// <typeparam name="TSource">The type of the values in original collection.</typeparam> /// <typeparam name="T">The type of the range values.</typeparam> /// <typeparam name="TKey">The type of the range key</typeparam> /// <param name="source">Original collection.</param> /// <param name="fromValueSelector">Callback to obtain a value for the From boundary.</param> /// <param name="keySelector">Callback to obtain a value for the range key.</param> /// <returns>A new composite range with keys filled from the original collection.</returns> public static CompositeRange <T, TKey> ToCompositeRangeFrom <TSource, T, TKey>( [NotNull] this IEnumerable <TSource> source, [NotNull, InstantHandle] Func <TSource, T> fromValueSelector, [NotNull, InstantHandle] Func <TSource, TKey> keySelector) { var keyAndFromBoundary = source .Select(s => (From: Range.BoundaryFrom(fromValueSelector(s)), Key: keySelector(s))) .OrderBy(s => s.From) .ToArray(); if (keyAndFromBoundary.Length == 0) { return(CompositeRange <T, TKey> .Empty); } // logic is following: // foreach item in sequence // if same boundary as before - add to pending // else add all (pending to current) ranges. Store current as pending. var prevBoundary = RangeBoundaryFrom <T> .Empty; var prevKeys = new List <TKey>(); var ranges = new List <Range <T, TKey> >(); foreach (var fromWithKey in keyAndFromBoundary) { if (prevBoundary != fromWithKey.From) { foreach (var prevKey in prevKeys) { ranges.Add(Range.Create(prevBoundary, fromWithKey.From.GetComplementation(), prevKey)); } prevKeys.Clear(); prevBoundary = fromWithKey.From; } prevKeys.Add(fromWithKey.Key); } foreach (var prevKey in prevKeys) { ranges.Add(Range.Create(prevBoundary, RangeBoundaryTo <T> .PositiveInfinity, prevKey)); } return(ranges.ToCompositeRange()); }
public static void TestRangeTrimTo() { double?empty = null; double?value1 = 1; double?value2 = 2; var emptyFrom = RangeBoundaryFrom <double?> .Empty; var emptyTo = RangeBoundaryTo <double?> .Empty; var emptyRange = Range.Create(emptyFrom, emptyTo); var range = Range.Create(value1, value2); AreEqual(range.TrimTo(null), range); AreEqual(range.TrimTo(double.PositiveInfinity), range); Throws <ArgumentException>(() => range.TrimTo(double.NegativeInfinity)); AreEqual(range.TrimTo(RangeBoundaryTo <double?> .Empty), emptyRange); AreEqual(range.TrimTo(0), emptyRange); AreEqual(range.TrimTo(1), Range.Create(value1, 1)); AreEqual(range.TrimTo(1.5), Range.Create(value1, 1.5)); AreEqual(range.TrimTo(2), range); AreEqual(range.TrimTo(3), range); range = Range.Create(emptyFrom, emptyTo); AreEqual(range.TrimTo(null), range); AreEqual(range.TrimTo(double.PositiveInfinity), range); Throws <ArgumentException>(() => range.TrimTo(double.NegativeInfinity)); AreEqual(range.TrimTo(RangeBoundaryTo <double?> .Empty), range); AreEqual(range.TrimTo(0), range); range = Range.CreateExclusive(empty, empty); AreEqual(range.TrimTo(null), range); AreEqual(range.TrimTo(double.PositiveInfinity), range); Throws <ArgumentException>(() => range.TrimTo(double.NegativeInfinity)); AreEqual(range.TrimTo(RangeBoundaryTo <double?> .Empty), emptyRange); AreEqual(range.TrimTo(0), Range.Create(empty, 0)); range = Range.CreateExclusive(value1, value2); AreEqual(range.TrimTo(2), range); AreEqual(range.TrimTo(1.5), Range.CreateExclusiveFrom(value1, 1.5)); AreEqual(range.TrimTo(1), emptyRange); range = Range.CreateExclusive(value1, value2); AreEqual(range.TrimTo(Range.BoundaryTo <double?>(2)), range); AreEqual(range.TrimTo(Range.BoundaryTo <double?>(1.5)), Range.CreateExclusiveFrom(value1, 1.5)); AreEqual(range.TrimTo(Range.BoundaryTo <double?>(1)), emptyRange); }
public static void TestKeyedRangeTrimFrom() { double?empty = null; double?value1 = 1; double?value2 = 2; var emptyFrom = RangeBoundaryFrom <double?> .Empty; var emptyTo = RangeBoundaryTo <double?> .Empty; var emptyRange = Range.Create(emptyFrom, emptyTo, _rangeKey); var range = Range.Create(value1, value2, _rangeKey); AreEqual(range.TrimFrom(null), range); AreEqual(range.TrimFrom(double.NegativeInfinity), range); Throws <ArgumentException>(() => range.TrimFrom(double.PositiveInfinity)); AreEqual(range.TrimFrom(RangeBoundaryFrom <double?> .Empty), emptyRange); AreEqual(range.TrimFrom(0), range); AreEqual(range.TrimFrom(1), range); AreEqual(range.TrimFrom(1.5), Range.Create(1.5, value2, _rangeKey)); AreEqual(range.TrimFrom(2), Range.Create(2, value2, _rangeKey)); AreEqual(range.TrimFrom(3), emptyRange); range = Range.Create(emptyFrom, emptyTo, _rangeKey); AreEqual(range.TrimFrom(null), range); AreEqual(range.TrimFrom(double.NegativeInfinity), range); Throws <ArgumentException>(() => range.TrimFrom(double.PositiveInfinity)); AreEqual(range.TrimFrom(RangeBoundaryFrom <double?> .Empty), range); AreEqual(range.TrimFrom(0), range); range = Range.CreateExclusive(empty, empty, _rangeKey); AreEqual(range.TrimFrom(null), range); AreEqual(range.TrimFrom(double.NegativeInfinity), range); Throws <ArgumentException>(() => range.TrimFrom(double.PositiveInfinity)); AreEqual(range.TrimFrom(RangeBoundaryFrom <double?> .Empty), emptyRange); AreEqual(range.TrimFrom(0), Range.Create(0, empty, _rangeKey)); range = Range.CreateExclusive(value1, value2, _rangeKey); AreEqual(range.TrimFrom(1), range); AreEqual(range.TrimFrom(1.5), Range.CreateExclusiveTo(1.5, value2, _rangeKey)); AreEqual(range.TrimFrom(2), emptyRange); range = Range.CreateExclusive(value1, value2, _rangeKey); AreEqual(range.TrimFrom(Range.BoundaryFrom <double?>(1)), range); AreEqual(range.TrimFrom(Range.BoundaryFrom <double?>(1.5)), Range.CreateExclusiveTo(1.5, value2, _rangeKey)); AreEqual(range.TrimFrom(Range.BoundaryFrom <double?>(2)), emptyRange); }
public static void TestKeyedRangeExtendTo() { double?empty = null; double?value1 = 1; double?value2 = 2; var emptyFrom = RangeBoundaryFrom <double?> .Empty; var emptyTo = RangeBoundaryTo <double?> .Empty; var range = Range.Create(value1, value2, RangeKey); AreEqual(range.ExtendTo(null), Range.Create(value1, empty, RangeKey)); AreEqual(range.ExtendTo(double.PositiveInfinity), Range.Create(value1, empty, RangeKey)); Throws <ArgumentException>(() => range.ExtendTo(double.NegativeInfinity)); AreEqual(range.ExtendTo(RangeBoundaryTo <double?> .Empty), range); AreEqual(range.ExtendTo(0), range); AreEqual(range.ExtendTo(1), range); AreEqual(range.ExtendTo(1.5), range); AreEqual(range.ExtendTo(2), range); AreEqual(range.ExtendTo(3), Range.Create(value1, 3, RangeKey)); range = Range.Create(emptyFrom, emptyTo, RangeKey); AreEqual(range.ExtendTo(null), range); AreEqual(range.ExtendTo(double.PositiveInfinity), range); Throws <ArgumentException>(() => range.ExtendTo(double.NegativeInfinity)); AreEqual(range.ExtendTo(RangeBoundaryTo <double?> .Empty), range); AreEqual(range.ExtendTo(0), range); range = Range.CreateExclusive(empty, empty, RangeKey); AreEqual(range.ExtendTo(null), range); AreEqual(range.ExtendTo(double.PositiveInfinity), range); Throws <ArgumentException>(() => range.ExtendTo(double.NegativeInfinity)); AreEqual(range.ExtendTo(RangeBoundaryTo <double?> .Empty), range); AreEqual(range.ExtendTo(0), range); range = Range.CreateExclusive(value1, value2, RangeKey); AreEqual(range.ExtendTo(1), range); AreEqual(range.ExtendTo(1.5), range); AreEqual(range.ExtendTo(2), Range.CreateExclusiveFrom(value1, 2, RangeKey)); range = Range.CreateExclusive(value1, value2, RangeKey); AreEqual(range.ExtendTo(Range.BoundaryTo <double?>(2)), Range.CreateExclusiveFrom(value1, 2, RangeKey)); AreEqual(range.ExtendTo(Range.BoundaryToExclusive <double?>(2)), range); AreEqual(range.ExtendTo(Range.BoundaryToExclusive <double?>(3)), Range.CreateExclusive(value1, 3, RangeKey)); }
public static CompositeRange <T, TKey> ToCompositeRangeTo <TSource, T, TKey>( this IEnumerable <TSource> source, [InstantHandle] Func <TSource, T> toValueSelector, [InstantHandle] Func <TSource, TKey> keySelector) where TKey : notnull { var keyAndToBoundary = source .Select(s => (Key: keySelector(s), To: Range.BoundaryTo(toValueSelector(s)))) .OrderBy(s => s.To) .ToArray(); if (keyAndToBoundary.Length == 0) { return(CompositeRange <T, TKey> .Empty); } // logic is following: // foreach item in sequence // if To is same as before - add same range with new key // else add range (old.To..To, key) and. var prevRange = Range <T, TKey> .Empty; var ranges = new List <Range <T, TKey> >(); foreach (var(key, to) in keyAndToBoundary) { if (prevRange.IsEmpty) { prevRange = Range.Create(RangeBoundaryFrom <T> .NegativeInfinity, to, key); } else if (prevRange.To == to) { prevRange = prevRange.WithKey(key); } else { prevRange = Range.Create(prevRange.To.GetComplementation(), to, key); } ranges.Add(prevRange); } return(ranges.ToCompositeRange()); }
private static CompositeRange <T> GetComplementationCore <T, TCompositeRange>( TCompositeRange compositeRange) where TCompositeRange : ICompositeRange <T> { if (compositeRange.IsEmpty) { return(CompositeRange <T> .Infinite); } var result = new List <Range <T> >(); if (compositeRange.ContainingRange.From.HasValue) { result.Add( Range.Create( RangeBoundaryFrom <T> .NegativeInfinity, compositeRange.ContainingRange.From.GetComplementation())); } var previousRange = Range <T> .Empty; foreach (var range in compositeRange.GetMergedRanges()) { if (previousRange.IsNotEmpty) { result.Add( Range.Create( previousRange.To.GetComplementation(), range.From.GetComplementation())); } previousRange = range; } if (compositeRange.ContainingRange.To.HasValue) { result.Add( Range.Create( compositeRange.ContainingRange.To.GetComplementation(), RangeBoundaryTo <T> .PositiveInfinity)); } return(new CompositeRange <T>(result, UnsafeOverload.NoEmptyRangesAlreadySortedAndMerged)); }
public static void TestRangeWithValue() { var range = Range.Create(1, 2); AreEqual(Range.Create(0, 3), range.WithValues(i => i - 1, i => i + 1)); range = Range.CreateExclusiveFrom(1, 2); AreEqual(Range.CreateExclusiveFrom(0, 3), range.WithValues(i => i - 1, i => i + 1)); range = Range.CreateExclusive(1, 2); AreEqual(Range.CreateExclusive(2, 3), range.WithValues(i => i + 1)); var toInf = (double?)double.PositiveInfinity; var range2 = Range.CreateExclusive(1, toInf); IsTrue(range2.WithValues(i => (double?)null).IsInfinite); range2 = Range.Create(double.NegativeInfinity, toInf); AreEqual(range2, range2.WithValues(i => i - 1, i => i + 1)); }
public CompositeRange <T> GetComplementation() { if (IsEmpty) { // ReSharper disable once ArrangeStaticMemberQualifier // Used for codegen return(CompositeRange <T> .Infinite); } var result = new List <Range <T> >(); if (ContainingRange.From.HasValue) { result.Add( Range.Create( RangeBoundaryFrom <T> .NegativeInfinity, ContainingRange.From.GetComplementation())); } var previousRange = Range <T> .Empty; foreach (var range in GetMergedRanges()) { if (previousRange.IsNotEmpty) { result.Add( Range.Create( previousRange.To.GetComplementation(), range.From.GetComplementation())); } previousRange = range; } if (ContainingRange.To.HasValue) { result.Add( Range.Create( ContainingRange.To.GetComplementation(), RangeBoundaryTo <T> .PositiveInfinity)); } return(new CompositeRange <T>(result, UnsafeOverload.NoEmptyRangesAlreadySortedAndMerged)); }