///|
fn pdf_fun_clamp(value : Double, low : Double, high : Double) -> Double {
if value < low {
low
} else if value > high {
high
} else {
value
}
}
///|
fn pdf_fun_interpolate(
value : Double,
source_min : Double,
source_max : Double,
target_min : Double,
target_max : Double,
) -> Double {
target_min +
(value - source_min) * ((target_max - target_min) / (source_max - source_min))
}
///|
fn pdf_fun_clamp_values(
values : ArrayView[Double],
range : ArrayView[Double],
) -> Array[Double] raise @core.PdfError {
if range.length() != values.length() * 2 {
raise BadFunctionEvaluation("range arity mismatch")
}
let output : Array[Double] = []
for index in 0.. Double {
@math.pow(2.0, bits_per_sample.to_double()) - 1.0
}
///|
fn PdfSampledFunction::encoded_inputs(
self : PdfSampledFunction,
function : PdfFunction,
clamped_inputs : ArrayView[Double],
) -> Array[Double] raise @core.PdfError {
if self.size.length() != clamped_inputs.length() ||
self.encode.length() != clamped_inputs.length() * 2 {
raise BadFunctionEvaluation("sampled input arity mismatch")
}
let output : Array[Double] = []
for index in 0.. Array[Double] raise @core.PdfError {
if self.size.length() != indices.length() {
raise BadFunctionEvaluation("sampled table arity mismatch")
}
let mut position = 0
let mut multiplier = 1
for index in 0.. self.samples.length() {
raise BadFunctionEvaluation("sampled table index out of range")
}
let values : Array[Double] = []
for index in 0.. Array[Double] raise @core.PdfError {
let range = match function.range {
Some(range) => range
None => raise BadFunctionEvaluation("sampled function missing range")
}
if range.length() % 2 != 0 ||
self.decode.length() != range.length() ||
self.decode.length() % 2 != 0 {
raise BadFunctionEvaluation("sampled output arity mismatch")
}
let output_count = range.length() / 2
let encoded = self.encoded_inputs(function, clamped_inputs)
let floors : Array[Int] = []
let ceilings : Array[Int] = []
for value in encoded {
floors.push(@math.floor(value).to_int())
ceilings.push(@math.ceil(value).to_int())
}
let floor_values = self.read_table(floors, output_count)
let ceiling_values = self.read_table(ceilings, output_count)
let max_sample = pdf_fun_max_sample(self.bits_per_sample)
let decoded : Array[Double] = []
for index in 0.. Array[Double] raise @core.PdfError {
if clamped_inputs.length() != 1 || function.domain.length() != 2 {
raise BadFunctionEvaluation("stitching function arity mismatch")
}
let input = clamped_inputs[0]
let points : Array[Double] = [function.domain[0]]
for bound in self.bounds {
points.push(bound)
}
points.push(function.domain[1])
let mut chosen = -1
for index in 0..= low && input < high) || input == high {
chosen = index
break
}
}
if chosen < 0 {
raise BadFunctionEvaluation("stitching function bounds mismatch")
}
let encoded = pdf_fun_interpolate(
input,
points[chosen],
points[chosen + 1],
self.stitch_encode[chosen * 2],
self.stitch_encode[chosen * 2 + 1],
)
self.functions[chosen].eval([encoded])
}
///|
fn PdfFunction::clamped_inputs(
self : PdfFunction,
inputs : ArrayView[Double],
) -> Array[Double] raise @core.PdfError {
if self.domain.length() != inputs.length() * 2 {
raise BadFunctionEvaluation("domain arity mismatch")
}
let output : Array[Double] = []
for index in 0.. Array[Double] raise @core.PdfError {
let clamped_inputs = self.clamped_inputs(inputs)
let output = match self.func {
PdfFunctionSampled(sampled) => sampled.eval_sampled(self, clamped_inputs)
PdfFunctionInterpolation({ c0, c1, n, }) => {
let values : Array[Double] = []
for input in clamped_inputs {
let factor = @math.pow(input, n)
for index in 0..
stitching.eval_stitching(self, clamped_inputs)
PdfFunctionCalculator(calculator) =>
calculator.eval_calculator(clamped_inputs)
}
match self.range {
Some(range) => pdf_fun_clamp_values(output, range)
None => output
}
}
///|
/// Compatibility wrapper for `PdfFunction::eval`.
pub fn pdf_eval_function(
function : PdfFunction,
inputs : ArrayView[Double],
) -> Array[Double] raise @core.PdfError {
function.eval(inputs)
}
///|
/// Print the function's diagnostic representation to standard output.
pub fn pdf_print_function(function : PdfFunction) -> Unit {
println(function.debug_string())
}