///|
/// Validation policies for production sample tables.
pub struct SampleValidationPolicy2 {
tolerance : Double
endpoint_tolerance : Double
maximum_gap : Double
require_monotonic_time : Bool
} derive(Debug)
///|
pub fn sample_validation_policy2() -> SampleValidationPolicy2 {
{
tolerance: 0.000001,
endpoint_tolerance: 0.000001,
maximum_gap: 0.1,
require_monotonic_time: true,
}
}
///|
pub fn SampleValidationPolicy2::with_tolerance(
self : SampleValidationPolicy2,
value : Double,
) -> SampleValidationPolicy2 {
{
tolerance: value.max(0.000000000001),
endpoint_tolerance: self.endpoint_tolerance,
maximum_gap: self.maximum_gap,
require_monotonic_time: self.require_monotonic_time,
}
}
///|
pub fn SampleValidationPolicy2::with_gap(
self : SampleValidationPolicy2,
value : Double,
) -> SampleValidationPolicy2 {
{
tolerance: self.tolerance,
endpoint_tolerance: self.endpoint_tolerance,
maximum_gap: value.max(0.0),
require_monotonic_time: self.require_monotonic_time,
}
}
///|
pub fn SampleValidationPolicy2::with_monotonic_time(
self : SampleValidationPolicy2,
value : Bool,
) -> SampleValidationPolicy2 {
{
tolerance: self.tolerance,
endpoint_tolerance: self.endpoint_tolerance,
maximum_gap: self.maximum_gap,
require_monotonic_time: value,
}
}
///|
pub fn SampleValidationPolicy2::tolerance(
self : SampleValidationPolicy2,
) -> Double {
self.tolerance
}
///|
pub fn SampleValidationPolicy2::endpoint_tolerance(
self : SampleValidationPolicy2,
) -> Double {
self.endpoint_tolerance
}
///|
pub fn SampleValidationPolicy2::maximum_gap(
self : SampleValidationPolicy2,
) -> Double {
self.maximum_gap
}
///|
pub fn validate_sample_times2(
name : String,
times : Array[Double],
policy : SampleValidationPolicy2,
) -> DiagnosticReport2 {
let report = diagnostic_report2(name).with_measurements(
times.length(),
if times.length() == 0 {
0.0
} else {
times[times.length() - 1] - times[0]
},
)
for index in 0.. 0 {
let gap = times[index] - times[index - 1]
if policy.require_monotonic_time && gap <= 0.0 {
report.add(
diagnostic_issue(
ErrorDiagnostic,
EndpointMismatchDiagnostic,
"sample times are not increasing",
index,
gap,
0.0,
),
)
}
if gap > policy.maximum_gap {
report.add(
diagnostic_issue(
WarningDiagnostic,
SamplingErrorDiagnostic,
"sample time gap exceeds policy",
index,
gap,
policy.maximum_gap,
),
)
}
}
}
report
}
///|
pub fn validate_sample_values2(
name : String,
values : Array[Double],
policy : SampleValidationPolicy2,
) -> DiagnosticReport2 {
let report = inspect_scalar_values(name, values, policy.tolerance)
if values.length() >= 2 &&
(values[0] - values[values.length() - 1]).abs() <= policy.endpoint_tolerance {
report.add(
diagnostic_issue(
InfoDiagnostic,
EndpointMismatchDiagnostic,
"sample table closes on the same endpoint",
0,
values[0],
values[values.length() - 1],
),
)
}
report
}
///|
pub fn validate_lut2(
name : String,
table : CurveLookupTable,
curve : Curve,
policy : SampleValidationPolicy2,
) -> DiagnosticReport2 {
let report = diagnostic_report2(name).with_measurements(table.samples(), 1.0)
if table.samples() < 2 {
report.add(
diagnostic_issue(
ErrorDiagnostic,
EmptyInputDiagnostic,
"lookup table has fewer than two samples",
0,
table.samples().to_double(),
2.0,
),
)
return report
}
if !table.monotonic() {
report.add(
diagnostic_issue(
WarningDiagnostic,
SamplingErrorDiagnostic,
"lookup table is non-monotonic",
0,
0.0,
0.0,
),
)
}
let error = table.error(curve, table.samples() * 2)
if error > policy.tolerance {
report.add(
diagnostic_issue(
WarningDiagnostic,
SamplingErrorDiagnostic,
"lookup table error exceeds tolerance",
0,
error,
policy.tolerance,
),
)
}
report
}
///|
pub struct ValidationBundle2 {
reports : Array[DiagnosticReport2]
summary : DiagnosticSummary2
} derive(Debug)
///|
pub fn validation_bundle2(
reports : Array[DiagnosticReport2],
) -> ValidationBundle2 {
{ reports: reports.copy(), summary: summarize_diagnostics(reports) }
}
///|
pub fn ValidationBundle2::reports(
self : ValidationBundle2,
) -> Array[DiagnosticReport2] {
self.reports.copy()
}
///|
pub fn ValidationBundle2::summary(
self : ValidationBundle2,
) -> DiagnosticSummary2 {
self.summary
}
///|
pub fn ValidationBundle2::passed(self : ValidationBundle2) -> Bool {
self.summary.passed()
}