internal static ParallelQuery <int> MakeJoin(bool orderPreserved) { int[] a = Enumerable.Range(0, 100).ToArray(); ParallelQuery <int> ipe = a.AsParallel(); if (orderPreserved) { ipe = ipe.AsOrdered(); } return(ipe.Join(a.AsParallel(), i => i, i => i, (i, j) => i)); }
public static void Join(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; int seen = 0; foreach (var p in leftQuery.Join(rightQuery, x => x * KeyFactor, y => y, (x, y) => KeyValuePair.Create(x, y))) { Assert.Equal(seen++, p.Key); Assert.Equal(p.Key * KeyFactor, p.Value); } Assert.Equal(Math.Min(leftCount, (rightCount + (KeyFactor - 1)) / KeyFactor), seen); }
public static void Join_Unordered(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; IntegerRangeSet seen = new IntegerRangeSet(0, Math.Min(leftCount, (rightCount + (KeyFactor - 1)) / KeyFactor)); foreach (var p in leftQuery.Join(rightQuery, x => x * KeyFactor, y => y, (x, y) => KeyValuePair.Create(x, y))) { Assert.Equal(p.Key * KeyFactor, p.Value); seen.Add(p.Key); } seen.AssertComplete(); }
public static void Join_Multiple(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; int seen = 0; Assert.All(leftQuery.Join(rightQuery, x => x, y => y / KeyFactor, (x, y) => KeyValuePair.Create(x, y)), p => { Assert.Equal(p.Key, p.Value / KeyFactor); Assert.Equal(seen++, p.Value); }); Assert.Equal(Math.Min(leftCount * KeyFactor, rightCount), seen); }
public static void Join_InnerJoin_Ordered(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; ParallelQuery <int> middleQuery = ParallelEnumerable.Range(0, leftCount).AsOrdered(); int seen = 0; Assert.All(leftQuery.Join(middleQuery.Join(rightQuery, x => x * KeyFactor / 2, y => y, (x, y) => KeyValuePair.Create(x, y)), z => z * 2, p => p.Key, (x, p) => KeyValuePair.Create(x, p)), pOuter => { KeyValuePair <int, int> pInner = pOuter.Value; Assert.Equal(seen++, pOuter.Key); Assert.Equal(pOuter.Key * 2, pInner.Key); Assert.Equal(pOuter.Key * KeyFactor, pInner.Value); }); Assert.Equal(Math.Min((leftCount + 1) / 2, (rightCount + (KeyFactor - 1)) / KeyFactor), seen); }
public static void Join_Unordered_Multiple(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; IntegerRangeSet seenOuter = new IntegerRangeSet(0, Math.Min(leftCount, (rightCount + (KeyFactor - 1)) / KeyFactor)); IntegerRangeSet seenInner = new IntegerRangeSet(0, Math.Min(leftCount * KeyFactor, rightCount)); Assert.All(leftQuery.Join(rightQuery, x => x, y => y / KeyFactor, (x, y) => KeyValuePair.Create(x, y)), p => { Assert.Equal(p.Key, p.Value / KeyFactor); seenInner.Add(p.Value); if (p.Value % KeyFactor == 0) { seenOuter.Add(p.Key); } }); seenOuter.AssertComplete(); seenInner.AssertComplete(); }
// Join doesn't always return items from the right ordered. See Issue #1155 public static void Join_Multiple(Labeled <ParallelQuery <int> > left, int leftCount, Labeled <ParallelQuery <int> > right, int rightCount) { ParallelQuery <int> leftQuery = left.Item; ParallelQuery <int> rightQuery = right.Item; int seenOuter = 0; int previousOuter = -1; IntegerRangeSet seenInner = new IntegerRangeSet(0, 0); Assert.All(leftQuery.Join(rightQuery, x => x, y => y / KeyFactor, (x, y) => KeyValuePair.Create(x, y)), p => { if (p.Key != previousOuter) { Assert.Equal(seenOuter++, p.Key); seenInner.AssertComplete(); seenInner = new IntegerRangeSet(p.Key * KeyFactor, Math.Min(rightCount - p.Key * KeyFactor, KeyFactor)); previousOuter = p.Key; } seenInner.Add(p.Value); Assert.Equal(p.Key, p.Value / KeyFactor); }); Assert.Equal(Math.Min(leftCount, (rightCount + (KeyFactor - 1)) / KeyFactor), seenOuter); seenInner.AssertComplete(); }
private static void RunAllTests( TestTracker result, ParallelQuery <int> q, bool orderPreserved, string leftOpName, bool leftOrderDefined) { LogTestRun(leftOpName, "All1", orderPreserved); result.MustEqual( q.All(i => i > 100), q.ToArray().Any(i => i > 100)); LogTestRun(leftOpName, "All2", orderPreserved); result.MustEqual( q.All(i => i == 75), q.ToArray().All(i => i == 75)); LogTestRun(leftOpName, "Any1", orderPreserved); result.MustEqual( q.Any(i => i > 100), q.ToArray().Any(i => i > 100)); LogTestRun(leftOpName, "Any2", orderPreserved); result.MustEqual( q.Any(i => i == 75), q.ToArray().Any(i => i == 75)); LogTestRun(leftOpName, "Concat", orderPreserved); result.MustSequenceEqual( q.Concat(q).Concat(new int[] { 1, 2, 3 }.AsParallel()), q.Reverse().Reverse().ToArray().Concat(q.Reverse().Reverse()).Concat(new int[] { 1, 2, 3 }), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "DefaultIfEmpty", orderPreserved); result.MustSequenceEqual( q.DefaultIfEmpty(), q.ToArray().DefaultIfEmpty(), orderPreserved && leftOrderDefined); LogTestRun(leftOpName, "ElementAt", orderPreserved); IEnumerable <int> q2 = q.ToArray(); int count1 = q.Count(), count2 = q2.Count(); List <int> list1 = new List <int>(); List <int> list2 = new List <int>(); for (int i = 0; i < count1; i++) { list1.Add(q.ElementAt(i)); } for (int i = 0; i < count2; i++) { list2.Add(q2.ElementAt(i)); } result.MustSequenceEqual(list1, list2, leftOrderDefined); LogTestRun(leftOpName, "Except", orderPreserved); result.MustSequenceEqual( q.Except(Enumerable.Range(90, 50).AsParallel()), q.ToArray().Except(Enumerable.Range(90, 50)), false); LogTestRun(leftOpName, "First", orderPreserved); CheckFirstOrLast( result, q.First(), q.ToArray().First(), leftOrderDefined); LogTestRun(leftOpName, "GroupBy", orderPreserved); result.MustGroupByEqual( q.GroupBy(i => i % 5, (i, e) => new Pair <int, IEnumerable <int> >(i, e)), q.ToArray().GroupBy(i => i % 5, (i, e) => new Pair <int, IEnumerable <int> >(i, e))); LogTestRun(leftOpName, "GroupJoin", orderPreserved); result.MustSequenceEqual( q.GroupJoin(q, i => i, i => i, (i, e) => e.FirstOrDefault()), q.ToArray().GroupJoin(q.ToArray(), i => i, i => i, (i, e) => e.FirstOrDefault()), false); LogTestRun(leftOpName, "Intersect", orderPreserved); result.MustSequenceEqual( q.Intersect(Enumerable.Range(90, 50).AsParallel()), q.ToArray().Intersect(Enumerable.Range(90, 50)), false); LogTestRun(leftOpName, "Join1", orderPreserved); result.MustSequenceEqual( q.Join((new int[] { 1, 1, 2, 3, 3 }).AsParallel(), i => i, i => i, (i, j) => i + j), q.ToArray().Join(new int[] { 1, 1, 2, 3, 3 }, i => i, i => i, (i, j) => i + j), false); LogTestRun(leftOpName, "Join2", orderPreserved); result.MustSequenceEqual( q.Join((new int[] { 1, 1, 100, 3, 3 }).AsParallel(), i => new String('a', i), i => new String('a', i), (i, j) => i + j), q.ToArray().Join(new int[] { 1, 1, 100, 3, 3 }, i => new String('a', i), i => new String('a', i), (i, j) => i + j), false); LogTestRun(leftOpName, "Last", orderPreserved); CheckFirstOrLast( result, q.Last(), q.ToArray().Last(), leftOrderDefined); LogTestRun(leftOpName, "Min", orderPreserved); CheckFirstOrLast( result, q.Min(), q.ToArray().Min(), leftOrderDefined); LogTestRun(leftOpName, "Max", orderPreserved); CheckFirstOrLast( result, q.Min(), q.ToArray().Min(), leftOrderDefined); LogTestRun(leftOpName, "OrderBy-ThenBy", orderPreserved); result.MustSequenceEqual( q.Concat(q).OrderBy(i => i % 5).ThenBy(i => - i), q.ToArray().Concat(q).OrderBy(i => i % 5).ThenBy(i => - i), true); LogTestRun(leftOpName, "OrderByDescending-ThenByDescending", orderPreserved); result.MustSequenceEqual( q.Concat(q).OrderByDescending(i => i % 5).ThenByDescending(i => - i), q.ToArray().Concat(q).OrderByDescending(i => i % 5).ThenByDescending(i => - i), true); LogTestRun(leftOpName, "Reverse", orderPreserved); result.MustSequenceEqual( q.Concat(q).Reverse(), q.ToArray().Concat(q).Reverse(), orderPreserved && leftOrderDefined); LogTestRun(leftOpName, "Select", orderPreserved); result.MustSequenceEqual( q.Select(i => 5 * i - 17), q.ToArray().Select(i => 5 * i - 17), orderPreserved && leftOrderDefined); LogTestRun(leftOpName, "SelectMany", orderPreserved); result.MustSequenceEqual( q.SelectMany(i => new int[] { 1, 2, 3 }, (i, j) => i + 100 * j), q.ToArray().SelectMany(i => new int[] { 1, 2, 3 }, (i, j) => i + 100 * j), false); LogTestRun(leftOpName, "SequenceEqual", orderPreserved); if (orderPreserved && leftOrderDefined) { result.MustEqual(q.SequenceEqual(q), true); } else { // We don't check the return value as it can be either true or false q.SequenceEqual(q); } LogTestRun(leftOpName, "Skip", orderPreserved); CheckTakeSkip( result, q.Skip(10), q.ToArray().Skip(10), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "SkipWhile", orderPreserved); CheckTakeSkip( result, q.SkipWhile(i => i < 30), q.ToArray().SkipWhile(i => i < 30), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "SkipWhileIndexed", orderPreserved); CheckTakeSkip( result, q.SkipWhile((i, j) => j < 30), q.ToArray().SkipWhile((i, j) => j < 30), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "Take", orderPreserved); CheckTakeSkip( result, q.Take(10), q.ToArray().Take(10), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "TakeWhile", orderPreserved); CheckTakeSkip( result, q.TakeWhile(i => i < 30), q.ToArray().TakeWhile(i => i < 30), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "TakeWhileIndexed", orderPreserved); CheckTakeSkip( result, q.TakeWhile((i, j) => j < 30), q.ToArray().TakeWhile((i, j) => j < 30), leftOrderDefined && orderPreserved); LogTestRun(leftOpName, "Union", orderPreserved); result.MustSequenceEqual( q.Union(Enumerable.Range(90, 50).AsParallel()), q.ToArray().Union(Enumerable.Range(90, 50)), false); LogTestRun(leftOpName, "Where", orderPreserved); result.MustSequenceEqual( q.Where(i => i < 20 || i > 80), q.ToArray().Where(i => i < 20 || i > 80), orderPreserved && leftOrderDefined); LogTestRun(leftOpName, "Zip", orderPreserved); IEnumerable <KeyValuePair <int, int> > zipQ = q.Zip(q, (i, j) => new KeyValuePair <int, int>(i, j)); result.MustSequenceEqual( zipQ.Select(p => p.Key), q.Reverse().Reverse().ToArray(), orderPreserved && leftOrderDefined); result.MustSequenceEqual( zipQ.Select(p => p.Value), q.Reverse().Reverse().ToArray(), orderPreserved && leftOrderDefined); }
private static void RunOrderByComposedWithJoinJoin(int outerSize, int innerSize, bool descending) { // Generate data in the reverse order in which it'll be sorted. DataDistributionType type = descending ? DataDistributionType.AlreadyAscending : DataDistributionType.AlreadyDescending; int[] left = CreateOrderByInput(outerSize, type); int[] right = CreateOrderByInput(innerSize, type); int min = outerSize >= innerSize ? innerSize : outerSize; int[] middle = new int[min]; if (descending) { for (int i = middle.Length; i > 0; i--) { middle[i - 1] = i; } } else { for (int i = 0; i < middle.Length; i++) { middle[i] = i; } } Func <int, int> identityKeySelector = delegate(int x) { return(x); }; // Create the sort object. ParallelQuery <int> sortedLeft; if (descending) { sortedLeft = left.AsParallel().OrderByDescending <int, int>(identityKeySelector); } else { sortedLeft = left.AsParallel().OrderBy <int, int>(identityKeySelector); } // and now the join... ParallelQuery <Pair <int, int> > innerJoin = sortedLeft.Join <int, int, int, Pair <int, int> >( right.AsParallel(), identityKeySelector, identityKeySelector, delegate(int x, int y) { return(new Pair <int, int>(x, y)); }); ParallelQuery <int> outerJoin = innerJoin.Join <Pair <int, int>, int, int, int>( middle.AsParallel(), delegate(Pair <int, int> p) { return(p.First); }, identityKeySelector, delegate(Pair <int, int> x, int y) { return(x.First); }); // Ensure pairs are of equal values, and that they are in ascending or descending order. int cnt = 0; int? last = null; string method = string.Format("RunOrderByComposedWithJoinJoin(outerSize = {0}, innerSize = {1}, descending = {2})", outerSize, innerSize, descending); foreach (int p in outerJoin) { cnt++; if (!((last == null || ((last.Value <= p && !descending) || (last.Value >= p && descending))))) { Assert.True(false, string.Format(method + " > *ERROR: sort order not correct: last = {0}, curr = {1}", last.Value, p)); } last = p; } }
private static void RunThenByComposedWithJoinJoin(int outerSize, int innerSize, bool descending) { // Generate data in the reverse order in which it'll be sorted. DataDistributionType type = descending ? DataDistributionType.AlreadyAscending : DataDistributionType.AlreadyDescending; int[] leftPartOne = CreateOrderByInput(outerSize, type); int[] leftPartTwo = CreateOrderByInput(outerSize, DataDistributionType.Random); Pair <int, int>[] left = new Pair <int, int> [outerSize]; for (int i = 0; i < outerSize; i++) { left[i] = new Pair <int, int>(leftPartOne[i] / 1024, leftPartTwo[i]); } int[] right = CreateOrderByInput(innerSize, type); int minValue = outerSize >= innerSize ? innerSize : outerSize; int[] middle = new int[minValue]; if (descending) { for (int i = middle.Length; i > 0; i--) { middle[i - 1] = i; } } else { for (int i = 0; i < middle.Length; i++) { middle[i] = i; } } Func <int, int> identityKeySelector = delegate(int x) { return(x); }; // Create the sort object. ParallelQuery <Pair <int, int> > sortedLeft; if (descending) { sortedLeft = left.AsParallel() .OrderByDescending <Pair <int, int>, int>(delegate(Pair <int, int> p) { return(p.First); }) .ThenByDescending <Pair <int, int>, int>(delegate(Pair <int, int> p) { return(p.Second); }); } else { sortedLeft = left.AsParallel() .OrderBy <Pair <int, int>, int>(delegate(Pair <int, int> p) { return(p.First); }) .ThenBy <Pair <int, int>, int>(delegate(Pair <int, int> p) { return(p.Second); }); } // and now the join... ParallelQuery <Pair <int, int> > innerJoin = sortedLeft.Join <Pair <int, int>, int, int, Pair <int, int> >( right.AsParallel(), delegate(Pair <int, int> p) { return(p.First); }, identityKeySelector, delegate(Pair <int, int> x, int y) { return(x); }); ParallelQuery <Pair <int, int> > outerJoin = innerJoin.Join <Pair <int, int>, int, int, Pair <int, int> >( middle.AsParallel(), delegate(Pair <int, int> p) { return(p.First); }, identityKeySelector, delegate(Pair <int, int> x, int y) { return(x); }); //Assert.True(false, string.Format(" > Invoking join of {0} outer elems with {1} inner elems", left.Length, right.Length)); // Ensure pairs are of equal values, and that they are in ascending or descending order. int cnt = 0, secondaryCnt = 0; Pair <int, int>?last = null; string methodName = string.Format("RunThenByComposedWithJoinJoin(outerSize = {0}, innerSize = {1}, descending = {2})", outerSize, innerSize, descending); foreach (Pair <int, int> p in outerJoin) { cnt++; if (!((last == null || ((last.Value.First <= p.First && !descending) || (last.Value.First >= p.First && descending))))) { Assert.True(false, string.Format(methodName + " > *ERROR: outer sort order not correct: last = {0}, curr = {1}", last.Value.First, p.First)); break; } if (last != null && last.Value.First == p.First) { secondaryCnt++; } if (!((last == null || (last.Value.First != p.First) || ((last.Value.Second <= p.Second && !descending) || (last.Value.Second >= p.Second && descending))))) { Assert.True(false, string.Format(methodName + " > *ERROR: inner sort order not correct: last = {0}, curr = {1}", last.Value.Second, p.Second)); } last = p; } }
public static ParallelQuery <TOuter> Join <TOuter, TInner, TKey>(this ParallelQuery <TOuter> outer, ParallelQuery <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector) { ParallelQuery <TOuter> results = outer.Join(inner, outerKeySelector, innerKeySelector, (x, y) => x); return(results); }