using System; using System.Collections.Generic; using System.Collections.ObjectModel; namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.Comparison; /// 一个方法的固定五次计时样本和确定性结论。 public sealed class SmoothingTimingSummary { /// 创建一个只接受五个已测量样本的计时汇总。 public SmoothingTimingSummary( IReadOnlyList measuredElapsedMilliseconds, bool isDeterministic, string diagnostic) { if (measuredElapsedMilliseconds == null || measuredElapsedMilliseconds.Count != 5) throw new ArgumentException("计时汇总必须包含五个已测量样本。", nameof(measuredElapsedMilliseconds)); var copy = new List(measuredElapsedMilliseconds.Count); for (int index = 0; index < measuredElapsedMilliseconds.Count; index++) { double value = measuredElapsedMilliseconds[index]; if (double.IsNaN(value) || double.IsInfinity(value) || value < 0d) throw new ArgumentOutOfRangeException(nameof(measuredElapsedMilliseconds), "计时样本必须为有限非负数。"); copy.Add(value); } MeasuredElapsedMilliseconds = new ReadOnlyCollection(copy); MedianElapsedMilliseconds = Median(copy); IsDeterministic = isDeterministic; Diagnostic = diagnostic ?? string.Empty; } /// 不含预热执行的五个实测耗时,单位 ms。 public IReadOnlyList MeasuredElapsedMilliseconds { get; } /// 五个实测耗时的稳定中位数,单位 ms。 public double MedianElapsedMilliseconds { get; } /// 五次输出是否具有相同的状态和稳定几何摘要。 public bool IsDeterministic { get; } /// 非确定性或测量失败的稳定诊断说明。 public string Diagnostic { get; } /// 从五次测量结果中生成计时汇总,并拒绝状态或几何不稳定的输出。 public static SmoothingTimingSummary FromMeasurements( IReadOnlyList measuredElapsedMilliseconds, IReadOnlyList measuredResults) { if (measuredResults == null || measuredResults.Count != 5) throw new ArgumentException("确定性检查必须包含五个测量结果。", nameof(measuredResults)); for (int index = 0; index < measuredResults.Count; index++) { if (measuredResults[index] == null) throw new ArgumentException("确定性检查不能包含空测量结果。", nameof(measuredResults)); } PathSmoothingResult canonical = measuredResults[0]; string canonicalDigest = StableGeometryDigest.Compute(canonical); for (int index = 1; index < measuredResults.Count; index++) { PathSmoothingResult measured = measuredResults[index]; string digest = StableGeometryDigest.Compute(measured); if (measured.Status != canonical.Status || measured.Path.Count != canonical.Path.Count || measured.Segments.Count != canonical.Segments.Count || !string.Equals(digest, canonicalDigest, StringComparison.Ordinal)) { return new SmoothingTimingSummary( measuredElapsedMilliseconds, false, "五次测量的状态、点数、分段数或稳定几何摘要不一致。"); } } return new SmoothingTimingSummary(measuredElapsedMilliseconds, true, string.Empty); } internal static double Median(IReadOnlyList values) { var sorted = new double[values.Count]; for (int index = 0; index < values.Count; index++) sorted[index] = values[index]; Array.Sort(sorted); int middle = sorted.Length / 2; return sorted.Length % 2 == 1 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2d; } }