27 ReadOnlySpan<int> columns,
28 ReadOnlySpan<double> prefixDemand,
29 ReadOnlySpan<double> slope,
30 ReadOnlySpan<double> intercept,
41 throw new ArgumentException(
42 "At least one predecessor column is required.",
46 var requiredWorkspace = checked((2 * rowCount) + 2);
48 if (workspace.Length < requiredWorkspace)
50 throw new ArgumentException(
51 $
"SMAWK workspace must contain at least {requiredWorkspace} entries.",
67 private static void Search(
71 ReadOnlySpan<int> columns,
72 ReadOnlySpan<double> prefixDemand,
73 ReadOnlySpan<double> slope,
74 ReadOnlySpan<double> intercept,
85 for (var columnPosition = 0;
86 columnPosition < columns.Length;
89 var column = columns[columnPosition];
91 while (reducedCount > 0)
93 var comparisonRowPosition = reducedCount - 1;
95 if (comparisonRowPosition >= rowCount)
102 (comparisonRowPosition * rowStep);
105 workspace[reducedCount - 1];
107 if (!IsStrictlyBetter(
121 if (reducedCount < rowCount)
123 workspace[reducedCount] = column;
129 workspace[..reducedCount];
131 var oddRowCount = rowCount / 2;
137 checked(rowStep * 2),
144 workspace[reducedCount..]);
147 var lowerPosition = 0;
149 for (var rowPosition = 0;
150 rowPosition < rowCount;
155 (rowPosition * rowStep);
160 argMin[row - rowStep];
162 while (lowerPosition < reducedCount &&
163 reducedColumns[lowerPosition] != lowerColumn)
168 if (lowerPosition >= reducedCount)
170 throw new InvalidOperationException(
171 "SMAWK lower-bound column was not found.");
175 var upperPosition = reducedCount - 1;
177 if (rowPosition + 1 < rowCount)
179 var upperRow = row + rowStep;
180 var upperColumn = argMin[upperRow];
182 upperPosition = lowerPosition;
184 while (upperPosition < reducedCount &&
185 reducedColumns[upperPosition] != upperColumn)
190 if (upperPosition >= reducedCount)
192 throw new InvalidOperationException(
193 "SMAWK upper-bound column was not found.");
197 var bestPosition = lowerPosition;
199 for (var position = lowerPosition + 1;
200 position <= upperPosition;
203 if (IsStrictlyBetter(
205 reducedColumns[position],
206 reducedColumns[bestPosition],
211 bestPosition = position;
215 argMin[row] = reducedColumns[bestPosition];
217 if (rowPosition + 1 < rowCount)
219 lowerPosition = upperPosition;
224 private static bool IsStrictlyBetter(
228 ReadOnlySpan<double> prefixDemand,
229 ReadOnlySpan<double> slope,
230 ReadOnlySpan<double> intercept)
248 return candidate < current;
254 ReadOnlySpan<double> prefixDemand,
255 ReadOnlySpan<double> slope,
256 ReadOnlySpan<double> intercept)
266 if (!
double.IsFinite(product) ||
267 !
double.IsFinite(value))
269 throw new ArithmeticException(
270 "Numerical overflow while evaluating an Aggarwal-Park Monge-matrix entry.");