///|
fn rebuild(
log : Log,
curves : Array[Curve],
rows : Array[Array[Double?]],
) -> Log raise WellError {
make_log(
curves,
rows,
headers=log.headers,
parameters=log.parameters,
other=log.other,
null_value=log.null_value,
version_headers=log.version_headers,
extra_sections=log.extra_sections,
)
}
///|
/// Return an ascending owned copy, never sorting arbitrary invalid depth reversals.
pub fn ascending(log : Log) -> Log raise WellError {
validate(log)
let rows : Array[Array[Double?]] = []
let n = log.rows.length()
let reverse = n > 1 && log.rows[0][0].unwrap() > log.rows[n - 1][0].unwrap()
for i in 0.. Log raise WellError {
validate(log)
if !finite(low) || !finite(high) || low > high {
fail("invalid depth window")
}
let rows : Array[Array[Double?]] = []
for row in log.rows {
let d = row[0].unwrap()
if d >= low && d <= high {
rows.push(row)
}
}
rebuild(log, log.curves, rows)
}
///|
/// Select curves in requested order; depth remains mandatory and first.
pub fn select(log : Log, names : Array[String]) -> Log raise WellError {
validate(log)
let indices = [0]
let curves = [log.curves[0]]
for name in names {
let index = curve_index(log, name)
if index == 0 {
continue
}
if indices.contains(index) {
fail("duplicate selected curve: " + name)
}
indices.push(index)
curves.push(log.curves[index])
}
let rows = log.rows.map(row => indices.map(i => row[i]))
rebuild(log, curves, rows)
}
///|
/// Construct a finite ascending uniform grid, explicitly bounded before allocation.
pub fn depth_grid(
start : Double,
stop : Double,
step : Double,
limit? : Int = 100000,
) -> Array[Double] raise WellError {
if !finite(start) ||
!finite(stop) ||
!finite(step) ||
step <= 0.0 ||
stop < start {
fail("grid requires finite ascending endpoints and positive step")
}
if limit < 1 || limit > 1000000 {
fail("grid limit must be 1..1000000")
}
let span = stop - start
if !finite(span) || span / step >= limit.to_double() {
fail("grid exceeds sample budget")
}
let grid : Array[Double] = []
for i in 0.. stop {
break
}
if grid.length() > 0 && d <= grid[grid.length() - 1] {
fail("grid step below floating point resolution")
}
grid.push(d)
if d == stop {
break
}
}
grid
}