private ulong?NextLabelRelativeToBase(LinkedListNode <OrderingNode> record) { var next = record.GetNextCircular(); if (next == BaseRecord) { return(null); // return M } else { return(LabelRelativeToBase(next)); } }
private void InsertAfter(T newElement, LinkedListNode <OrderingNode> afterNode) { if (newElement == null) { throw new ArgumentNullException("newElement", "Collection does not support null entries."); } // Find the starting point for our possible relabeling. //afterNode can't currently be null - as long as BaseRecord exists. ++Insertions; ulong j = 1UL; LinkedListNode <OrderingNode> current = afterNode.GetNextCircular(); ///string debugInfo1 = $"Comparing labels relative to {afterNode.Value.Label}"; //string debugInfo2 = ""; while (LabelDistance(afterNode, current) != null && LabelDistance(afterNode, current).Value <= j * j) { //debugInfo2 += $"Label diff {LabelDistance(afterNode, current).Value} <= {j}*{j} ({j * j})\r\n"; ++j; current = current.GetNextCircular(); } // NEXT: //status: just changed this finalLabel to handle the M case. //next is to correct the handling of the finalLabel.Value * k / j part. //this can be done easily,I think, because ulong_max fits into decimal. // ulong?finalLabel = LabelDistance(afterNode, current); Relabelings += (int)(j - 1); // Now, relabel (j-1) records: current = afterNode.GetNextCircular(); for (ulong k = 1UL; k < j; ++k) { ulong relabel; if (finalLabel == null) { //relabel = GetPortionOfM((double)k) unchecked { relabel = (GetFractionOfM(k, j) + afterNode.Value.Label); } } else { unchecked { //relabel = MOD_M(finalLabel.Value * k / j + afterNode.Value.Label); relabel = (GetFraction(finalLabel.Value, k, j) + afterNode.Value.Label); } } //string debugInfo3 = $"Relabeling {current.Value.Label} to {relabel}"; current.Value.Label = relabel; current = current.GetNextCircular(); } // Insert the new element: const ulong halfM = 1UL << 63; // 2^63, half of 2^64 //const ulong halfM = M / 2; //todo, replace after testing ulong newLabelRelativeToBase; if (NextLabelRelativeToBase(afterNode) == null) { // Averaging with M, so use halfM: newLabelRelativeToBase = (LabelRelativeToBase(afterNode) / 2UL) + halfM; } else { // Carefully avoid off-by-one errors here... newLabelRelativeToBase = (NextLabelRelativeToBase(afterNode).Value - LabelRelativeToBase(afterNode)) / 2UL + LabelRelativeToBase(afterNode); } ulong newLabel; unchecked { newLabel = (newLabelRelativeToBase + BaseRecord.Value.Label); } var newNode = new LinkedListNode <OrderingNode>(new OrderingNode(newElement, newLabel)); list.AddAfter(afterNode, newNode); dict[newElement] = newNode; // If afterNode is null, we're inserting at the start of the list, and startLabel will be 0: //ulong startLabel = afterNode?.Value.Label ?? 0L; }