private static int BiLayerCrossCount(IEnumerable<CrossCounterPair> pairs, int firstLayerVertexCount, int secondLayerVertexCount) { if (pairs == null) return 0; //radix sort of the pair, order by First asc, Second asc #region Sort by Second ASC var radixBySecond = new List<CrossCounterPair>[secondLayerVertexCount]; List<CrossCounterPair> r; int pairCount = 0; foreach (var pair in pairs) { //get the radix where the pair should be inserted r = radixBySecond[pair.Second]; if (r == null) { r = new List<CrossCounterPair>(); radixBySecond[pair.Second] = r; } r.Add(pair); pairCount++; } #endregion #region Sort By First ASC var radixByFirst = new List<CrossCounterPair>[firstLayerVertexCount]; foreach (var list in radixBySecond) { if (list == null) continue; foreach (var pair in list) { //get the radix where the pair should be inserted r = radixByFirst[pair.First]; if (r == null) { r = new List<CrossCounterPair>(); radixByFirst[pair.First] = r; } r.Add(pair); } } #endregion // // Build the accumulator tree // int firstIndex = 1; while (firstIndex < pairCount) firstIndex *= 2; int treeSize = 2 * firstIndex - 1; firstIndex -= 1; CrossCounterTreeNode[] tree = new CrossCounterTreeNode[treeSize]; for (int i = 0; i < treeSize; i++) tree[i] = new CrossCounterTreeNode(); // // Count the crossings // int crossCount = 0; int index; foreach (var list in radixByFirst) { if (list == null) continue; foreach (var pair in list) { index = pair.Second + firstIndex; tree[index].Accumulator += pair.Weight; switch (pair.Markable) { case false: tree[index].InnerSegmentMarker = true; break; case true: tree[index].NonInnerSegmentQueue.Enqueue(pair); break; default: break; } while (index > 0) { if (index % 2 > 0) { crossCount += tree[index + 1].Accumulator * pair.Weight; switch (pair.Markable) { case false: var queue = tree[index + 1].NonInnerSegmentQueue; while (queue.Count > 0) { queue.Dequeue().Marked = true; } break; case true: if (tree[index+1].InnerSegmentMarker) { pair.Marked = true; } break; default: break; } } index = (index - 1) / 2; tree[index].Accumulator += pair.Weight; switch (pair.Markable) { case false: tree[index].InnerSegmentMarker = true; break; case true: tree[index].NonInnerSegmentQueue.Enqueue(pair); break; default: break; } } } } return crossCount; }
private static int BiLayerCrossCount(IEnumerable <CrossCounterPair> pairs, int firstLayerVertexCount, int secondLayerVertexCount, CancellationToken cancellationToken) { if (pairs == null) { return(0); } //radix sort of the pair, order by First asc, Second asc #region Sort by Second ASC var radixBySecond = new List <CrossCounterPair> [secondLayerVertexCount]; List <CrossCounterPair> r; int pairCount = 0; foreach (var pair in pairs) { //get the radix where the pair should be inserted r = radixBySecond[pair.Second]; if (r == null) { r = new List <CrossCounterPair>(); radixBySecond[pair.Second] = r; } r.Add(pair); pairCount = Math.Max(pairCount, pair.Second); } pairCount += 1; #endregion #region Sort By First ASC var radixByFirst = new List <CrossCounterPair> [firstLayerVertexCount]; foreach (var list in radixBySecond) { if (list == null) { continue; } foreach (var pair in list) { cancellationToken.ThrowIfCancellationRequested(); //get the radix where the pair should be inserted r = radixByFirst[pair.First]; if (r == null) { r = new List <CrossCounterPair>(); radixByFirst[pair.First] = r; } r.Add(pair); } } #endregion // // Build the accumulator tree // int firstIndex = 1; while (firstIndex < pairCount) { firstIndex *= 2; } int treeSize = 2 * firstIndex - 1; firstIndex -= 1; CrossCounterTreeNode[] tree = new CrossCounterTreeNode[treeSize]; for (int i = 0; i < treeSize; i++) { tree[i] = new CrossCounterTreeNode(); } // // Count the crossings // int crossCount = 0; int index; foreach (var list in radixByFirst) { if (list == null) { continue; } foreach (var pair in list) { index = pair.Second + firstIndex; tree[index].Accumulator += pair.Weight; switch (pair.Type) { case EdgeTypes.InnerSegment: tree[index].InnerSegmentMarker = true; break; case EdgeTypes.NonInnerSegment: tree[index].NonInnerSegmentQueue.Enqueue(pair.NonInnerSegment); break; default: break; } while (index > 0) { cancellationToken.ThrowIfCancellationRequested(); if (index % 2 > 0) { crossCount += tree[index + 1].Accumulator * pair.Weight; switch (pair.Type) { case EdgeTypes.InnerSegment: var queue = tree[index + 1].NonInnerSegmentQueue; while (queue.Count > 0) { queue.Dequeue().Marked = true; } break; case EdgeTypes.NonInnerSegment: if (tree[index + 1].InnerSegmentMarker) { pair.NonInnerSegment.Marked = true; } break; default: break; } } index = (index - 1) / 2; tree[index].Accumulator += pair.Weight; switch (pair.Type) { case EdgeTypes.InnerSegment: tree[index].InnerSegmentMarker = true; break; case EdgeTypes.NonInnerSegment: tree[index].NonInnerSegmentQueue.Enqueue(pair.NonInnerSegment); break; default: break; } } } } return(crossCount); }
private int BiLayerCrossCount( [CanBeNull, ItemNotNull] IEnumerable <CrossCounterPair> pairs, int firstLayerVertexCount, int secondLayerVertexCount) { if (pairs is null) { return(0); } // Radix sort of the pairs, order by First asc, Second asc #region Sort by Second ASC var radixBySecond = new List <CrossCounterPair> [secondLayerVertexCount]; List <CrossCounterPair> r; int pairCount = 0; foreach (CrossCounterPair pair in pairs) { // Get the radix where the pair should be inserted r = radixBySecond[pair.Second]; if (r is null) { r = new List <CrossCounterPair>(); radixBySecond[pair.Second] = r; } r.Add(pair); pairCount = Math.Max(pairCount, pair.Second); } ++pairCount; #endregion #region Sort By First ASC var radixByFirst = new List <CrossCounterPair> [firstLayerVertexCount]; foreach (List <CrossCounterPair> list in radixBySecond) { if (list is null) { continue; } foreach (CrossCounterPair pair in list) { ThrowIfCancellationRequested(); // Get the radix where the pair should be inserted r = radixByFirst[pair.First]; if (r is null) { r = new List <CrossCounterPair>(); radixByFirst[pair.First] = r; } r.Add(pair); } } #endregion // Build the accumulator tree int firstIndex = 1; while (firstIndex < pairCount) { firstIndex *= 2; } int treeSize = 2 * firstIndex - 1; --firstIndex; var tree = new CrossCounterTreeNode[treeSize]; for (int i = 0; i < treeSize; ++i) { tree[i] = new CrossCounterTreeNode(); } // Count the crossings int crossCount = 0; foreach (List <CrossCounterPair> list in radixByFirst) { if (list is null) { continue; } foreach (CrossCounterPair pair in list) { int index = pair.Second + firstIndex; tree[index].Accumulator += pair.Weight; switch (pair.Type) { case EdgeTypes.InnerSegment: tree[index].InnerSegmentMarker = true; break; case EdgeTypes.NonInnerSegment: tree[index].NonInnerSegmentQueue.Enqueue(pair.NonInnerSegment); break; } while (index > 0) { ThrowIfCancellationRequested(); if (index % 2 > 0) { crossCount += tree[index + 1].Accumulator * pair.Weight; switch (pair.Type) { case EdgeTypes.InnerSegment: Queue <SugiEdge> queue = tree[index + 1].NonInnerSegmentQueue; while (queue.Count > 0) { queue.Dequeue().Marked = true; } break; case EdgeTypes.NonInnerSegment: if (tree[index + 1].InnerSegmentMarker) { pair.NonInnerSegment.Marked = true; } break; } } index = (index - 1) / 2; tree[index].Accumulator += pair.Weight; switch (pair.Type) { case EdgeTypes.InnerSegment: tree[index].InnerSegmentMarker = true; break; case EdgeTypes.NonInnerSegment: tree[index].NonInnerSegmentQueue.Enqueue(pair.NonInnerSegment); break; } } } } return(crossCount); }