Hi everyone. I've got an issue I can't seem to find a solution for online. I'm writing an application that has a configuration file which a user will edit to control what the application outputs to disk.
The program is a heavy number cruncher that uses 3D arrays (from ndarray
) of type f64
at the moment, but I want to extend this to also compute arrays of Complex64
from num_complex
. Since this will instantly double my memory requirement (as a complex value is essentially (f64, f64)), I'd much prefer that I didn't use just the real part of the type for all real-only calculations, so thus implementing a generic set of functions is a requirement.
This part has taken me some time, but now I have a MWE of this functionality:
fn sample_operation<F: ComplexFloat>(w: &Array3<F>) -> F {
w.into_iter().map(|&el| el.conj() * el).fold(F::zero(), |acc, v| acc + v)
}
can be called with both real and complex types:
let comp = Array3::<Complex64>::from_elem((10,10,10), Complex64::new(1., 2.));
let real = Array3::<f64>::from_elem((10,10,10), 2.);
let comp_ans = sample_operation(&comp); //Returns complex of size 16
let real_ans = sample_operation(&real); //Returns real of size 8
The issue I have now is I want the user to be able to choose the type in the configuration file. More specifically, I have a PotentialType
enum that is deserialised from the input, and some of the underlying potentials should emit only reals, and some complex. So what I'd really like is something along the lines of this:
fn get_potential<F: ComplexFloat>(potential_type: &PotentialType) -> Result<F, Error> {
match potential_type {
Real => Ok(12.0),
Complex => Ok(Complex64::new(12.0, 1.0)),
}
}
which obviously gives me expected type parameter, found f64/Complex64 errors as the return types are not generic here.
Is there any way I can set, at runtime, the type of a variable from a function like this? Or is there a way I can refactor/rethink this method to allow the generic types to do their job?