Skip to content

Commit 6b0719f

Browse files
Curve analysis derivatives - give memory to function
We preallocate memory then pass it to functions to compute the derivatives directly. We do this because it's usually better practice not to allocate memory often and instead offer control over the user where the memory comes from.
1 parent b3474a0 commit 6b0719f

File tree

2 files changed

+166
-29
lines changed

2 files changed

+166
-29
lines changed

lib/rust/mmscenegraph/src/math/curve_analysis.rs

Lines changed: 116 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -88,29 +88,128 @@ fn calc_derivative(
8888
Ok(())
8989
}
9090

91-
/// Calculate derivatives (velocity, acceleration, jerk) from time and
92-
/// height data.
91+
/// Allocate vectors for 1st order derivatives.
92+
pub fn allocate_derivatives_order_1(num: usize) -> Result<Vec<Real>> {
93+
let velocity = vec![0.0; num];
94+
Ok(velocity)
95+
}
96+
97+
/// Allocate vectors for 2nd order derivatives.
98+
pub fn allocate_derivatives_order_2(
99+
num: usize,
100+
) -> Result<(Vec<Real>, Vec<Real>)> {
101+
let velocity = vec![0.0; num];
102+
let acceleration = vec![0.0; num];
103+
Ok((velocity, acceleration))
104+
}
105+
106+
/// Allocate vectors for 3rd order derivatives.
107+
pub fn allocate_derivatives_order_3(
108+
num: usize,
109+
) -> Result<(Vec<Real>, Vec<Real>, Vec<Real>)> {
110+
let velocity = vec![0.0; num];
111+
let acceleration = vec![0.0; num];
112+
let jerk = vec![0.0; num];
113+
Ok((velocity, acceleration, jerk))
114+
}
115+
116+
/// Calculate 1st order derivatives (velocity) from time and value
117+
/// data.
93118
///
94-
/// Returns vectors of the same length as input by using forward,
95-
/// central, and backward differences
96-
pub fn calculate_derivatives(
119+
/// Returns vectors of the same length as input by using finite
120+
/// differences.
121+
pub fn calculate_derivatives_order_1(
97122
times: &[Real],
98-
heights: &[Real],
99-
) -> Result<(Vec<Real>, Vec<Real>, Vec<Real>)> {
100-
let n = heights.len();
123+
values: &[Real],
124+
out_velocity: &mut [Real],
125+
) -> Result<()> {
126+
// Verify slice lengths match
127+
if times.len() != values.len() || times.len() != out_velocity.len() {
128+
bail!("Input and output slices must have equal length; times.len()={} values.len()={} out_velocity.len()={}",
129+
times.len(),
130+
values.len(),
131+
out_velocity.len())
132+
}
133+
134+
let n = values.len();
101135
if n < 4 {
102136
bail!("Need at least 4 points for derivative analysis");
103137
}
104138

105-
// TODO: Should these vectors be given to this function to be
106-
// allocated?
107-
let mut velocity = vec![0.0; n];
108-
let mut acceleration = vec![0.0; n];
109-
let mut jerk = vec![0.0; n];
139+
calc_derivative(times, values, out_velocity)?;
110140

111-
calc_derivative(times, heights, &mut velocity)?;
112-
calc_derivative(times, &velocity, &mut acceleration)?;
113-
calc_derivative(times, &acceleration, &mut jerk)?;
141+
Ok(())
142+
}
114143

115-
Ok((velocity, acceleration, jerk))
144+
/// Calculate 2nd order derivatives (velocity and acceleration) from
145+
/// time and value data.
146+
///
147+
/// Returns vectors of the same length as input by using finite
148+
/// differences.
149+
pub fn calculate_derivatives_order_2(
150+
times: &[Real],
151+
values: &[Real],
152+
out_velocity: &mut [Real],
153+
out_acceleration: &mut [Real],
154+
) -> Result<()> {
155+
// Verify slice lengths match
156+
if times.len() != values.len()
157+
|| times.len() != out_velocity.len()
158+
|| times.len() != out_acceleration.len()
159+
{
160+
bail!("Input and output slices must have equal length; times.len()={} values.len()={} out_velocity.len()={} out_acceleration.len()={}",
161+
times.len(),
162+
values.len(),
163+
out_velocity.len(),
164+
out_acceleration.len(),
165+
)
166+
}
167+
168+
let n = values.len();
169+
if n < 4 {
170+
bail!("Need at least 4 points for derivative analysis");
171+
}
172+
173+
calc_derivative(times, values, out_velocity)?;
174+
calc_derivative(times, &out_velocity, out_acceleration)?;
175+
176+
Ok(())
177+
}
178+
179+
/// Calculate 3rd order derivatives (velocity, acceleration, and jerk)
180+
/// from time and value data.
181+
///
182+
/// Returns vectors of the same length as input by using finite
183+
/// differences.
184+
pub fn calculate_derivatives_order_3(
185+
times: &[Real],
186+
values: &[Real],
187+
out_velocity: &mut [Real],
188+
out_acceleration: &mut [Real],
189+
out_jerk: &mut [Real],
190+
) -> Result<()> {
191+
// Verify slice lengths match
192+
if times.len() != values.len()
193+
|| times.len() != out_velocity.len()
194+
|| times.len() != out_acceleration.len()
195+
|| times.len() != out_jerk.len()
196+
{
197+
bail!("Input and output slices must have equal length; times.len()={} values.len()={} out_velocity.len()={} out_acceleration.len()={} out_jerk.len()={}",
198+
times.len(),
199+
values.len(),
200+
out_velocity.len(),
201+
out_acceleration.len(),
202+
out_jerk.len());
203+
}
204+
205+
let n = values.len();
206+
if n < 4 {
207+
bail!("Need at least 4 points for derivative analysis");
208+
}
209+
210+
calc_derivative(times, values, out_velocity)?;
211+
calc_derivative(times, out_velocity, out_acceleration)?;
212+
calc_derivative(times, out_acceleration, out_jerk)?;
213+
214+
Ok(())
116215
}

lib/rust/mmscenegraph/tests/curve_analysis_derivatives.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,24 @@ mod common;
2323
use anyhow::Result;
2424
use approx::assert_relative_eq;
2525

26-
use mmscenegraph_rust::math::curve_analysis::calculate_derivatives;
26+
use mmscenegraph_rust::math::curve_analysis::allocate_derivatives_order_3;
27+
use mmscenegraph_rust::math::curve_analysis::calculate_derivatives_order_3;
2728

2829
fn print_arrays(velocity: &[f64], acceleration: &[f64], jerk: &[f64]) {
29-
println!("Found {} velocity:", velocity.len());
30+
println!("Velocity (1st order derivative) count {} :", velocity.len());
3031
for (i, v) in velocity.iter().enumerate() {
3132
println!("i={i} v={v}");
3233
}
3334

34-
println!("Found {} acceleration:", acceleration.len());
35+
println!(
36+
"Acceleration (2nd order derivative) count {} :",
37+
acceleration.len()
38+
);
3539
for (i, v) in acceleration.iter().enumerate() {
3640
println!("i={i} v={v}");
3741
}
3842

39-
println!("Found {} jerk:", jerk.len());
43+
println!("Jerk (3rd order derivative) count {} :", jerk.len());
4044
for (i, v) in jerk.iter().enumerate() {
4145
println!("i={i} v={v}");
4246
}
@@ -48,8 +52,18 @@ fn calculate_derivatives1() -> Result<()> {
4852
let times = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0];
4953
let heights = vec![1.0, 1.1, 1.2, 1.3, 1.4, 1.5];
5054

51-
let (velocity, acceleration, jerk) =
52-
calculate_derivatives(&times, &heights)?;
55+
// let (velocity, acceleration, jerk) =
56+
// calculate_derivatives(&times, &heights)?;
57+
58+
let (mut velocity, mut acceleration, mut jerk) =
59+
allocate_derivatives_order_3(times.len())?;
60+
calculate_derivatives_order_3(
61+
&times,
62+
&heights,
63+
&mut velocity,
64+
&mut acceleration,
65+
&mut jerk,
66+
)?;
5367

5468
print_arrays(&velocity, &acceleration, &jerk);
5569

@@ -87,8 +101,18 @@ fn calculate_derivatives2() -> Result<()> {
87101
let times = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0];
88102
let heights = vec![-1.0, -1.1, -1.2, -1.3, -1.4, -1.5];
89103

90-
let (velocity, acceleration, jerk) =
91-
calculate_derivatives(&times, &heights)?;
104+
// let (velocity, acceleration, jerk) =
105+
// calculate_derivatives(&times, &heights)?;
106+
107+
let (mut velocity, mut acceleration, mut jerk) =
108+
allocate_derivatives_order_3(times.len())?;
109+
calculate_derivatives_order_3(
110+
&times,
111+
&heights,
112+
&mut velocity,
113+
&mut acceleration,
114+
&mut jerk,
115+
)?;
92116

93117
print_arrays(&velocity, &acceleration, &jerk);
94118

@@ -126,8 +150,15 @@ fn calculate_derivatives3() -> Result<()> {
126150
let times = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0];
127151
let heights = vec![1.0, 1.1, 1.25, 1.5, 2.0, 4.0];
128152

129-
let (velocity, acceleration, jerk) =
130-
calculate_derivatives(&times, &heights)?;
153+
let (mut velocity, mut acceleration, mut jerk) =
154+
allocate_derivatives_order_3(times.len())?;
155+
calculate_derivatives_order_3(
156+
&times,
157+
&heights,
158+
&mut velocity,
159+
&mut acceleration,
160+
&mut jerk,
161+
)?;
131162

132163
print_arrays(&velocity, &acceleration, &jerk);
133164

@@ -150,8 +181,15 @@ fn calculate_derivatives4() -> Result<()> {
150181
let times = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
151182
let heights = vec![0.0, 1.0, 4.0, 9.0, 16.0, 25.0, 36.0]; // f(x) = x^2
152183

153-
let (velocity, acceleration, jerk) =
154-
calculate_derivatives(&times, &heights)?;
184+
let (mut velocity, mut acceleration, mut jerk) =
185+
allocate_derivatives_order_3(times.len())?;
186+
calculate_derivatives_order_3(
187+
&times,
188+
&heights,
189+
&mut velocity,
190+
&mut acceleration,
191+
&mut jerk,
192+
)?;
155193

156194
print_arrays(&velocity, &acceleration, &jerk);
157195

0 commit comments

Comments
 (0)