///|
/// Batch sampling helpers used by exporters, benchmark harnesses, and
/// analysis tools. The series stores timestamps beside values so non-uniform
/// editorial edits remain observable.
pub struct ScalarSeries2 {
times : Array[Double]
values : Array[Double]
} derive(Debug)
///|
pub fn scalar_series2(
times : Array[Double],
values : Array[Double],
) -> ScalarSeries2 {
{ times: times.copy(), values: values.copy() }
}
///|
pub fn ScalarSeries2::times(self : ScalarSeries2) -> Array[Double] {
self.times.copy()
}
///|
pub fn ScalarSeries2::values(self : ScalarSeries2) -> Array[Double] {
self.values.copy()
}
///|
pub fn ScalarSeries2::length(self : ScalarSeries2) -> Int {
self.times.length().min(self.values.length())
}
///|
pub fn ScalarSeries2::duration(self : ScalarSeries2) -> Double {
if self.length() < 2 {
0.0
} else {
self.times[self.length() - 1] - self.times[0]
}
}
///|
pub fn ScalarSeries2::sample(self : ScalarSeries2, time : Double) -> Double {
let count = self.length()
if count == 0 {
return 0.0
}
if time <= self.times[0] {
return self.values[0]
}
if time >= self.times[count - 1] {
return self.values[count - 1]
}
for index in 0..<(count - 1) {
if time <= self.times[index + 1] {
let span = self.times[index + 1] - self.times[index]
let ratio = if span == 0.0 {
0.0
} else {
(time - self.times[index]) / span
}
return self.values[index] +
(self.values[index + 1] - self.values[index]) * ratio
}
}
self.values[count - 1]
}
///|
pub fn ScalarSeries2::derivatives(self : ScalarSeries2) -> Array[Double] {
let values : Array[Double] = []
let count = self.length()
for index in 0.. Double {
let mut area = 0.0
for index in 1.. (Double, Double) {
if self.length() == 0 {
return (0.0, 0.0)
}
let mut minimum = self.values[0]
let mut maximum = minimum
for index in 1.. ScalarSeries2 {
let actual = count.max(1)
let times : Array[Double] = []
let values : Array[Double] = []
let start = if self.length() == 0 { 0.0 } else { self.times[0] }
let end = if self.length() == 0 { 0.0 } else { self.times[self.length() - 1] }
for index in 0.. Double,
) -> ScalarSeries2 {
let values : Array[Double] = []
for value in self.values {
values.push(mapper(value))
}
scalar_series2(self.times, values)
}
///|
pub struct PointSeries2 {
times : Array[Double]
values : Array[Point2]
} derive(Debug)
///|
pub fn point_series2(
times : Array[Double],
values : Array[Point2],
) -> PointSeries2 {
{ times: times.copy(), values: values.copy() }
}
///|
pub fn PointSeries2::times(self : PointSeries2) -> Array[Double] {
self.times.copy()
}
///|
pub fn PointSeries2::values(self : PointSeries2) -> Array[Point2] {
self.values.copy()
}
///|
pub fn PointSeries2::sample(self : PointSeries2, time : Double) -> Point2 {
if self.values.length() == 0 {
return point2(x=0.0, y=0.0)
}
if time <= self.times[0] {
return self.values[0]
}
let last = self.values.length() - 1
if time >= self.times[last] {
return self.values[last]
}
for index in 0.. Array[Double] {
let values : Array[Double] = []
if self.values.length() == 0 {
return values
}
values.push(0.0)
for index in 1.. PointSeries2 {
let actual = count.max(1)
let times : Array[Double] = []
let values : Array[Point2] = []
let start = if self.times.length() == 0 { 0.0 } else { self.times[0] }
let end = if self.times.length() == 0 {
0.0
} else {
self.times[self.times.length() - 1]
}
for index in 0.. ColorSeries2 {
{ times: times.copy(), values: values.copy() }
}
///|
pub fn ColorSeries2::sample(self : ColorSeries2, time : Double) -> Rgba {
if self.values.length() == 0 {
return rgba(r=0.0, g=0.0, b=0.0, a=0.0)
}
if time <= self.times[0] {
return self.values[0]
}
let last = self.values.length() - 1
if time >= self.times[last] {
return self.values[last]
}
for index in 0.. ScalarSeries2 {
let actual = count.max(1)
let times : Array[Double] = []
let values : Array[Double] = []
for index in 0.. ScalarSeries2 {
let actual = count.max(1)
let times : Array[Double] = []
let values : Array[Double] = []
for index in 0..