use std::{array, collections::HashMap};
use nalgebra::{SMatrix, SVector};
use num::complex::Complex64;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use crate::{
amplitudes::{AmplitudeID, Parameter, ParameterMap},
LadduError, LadduResult,
};
fn is_glob_selector(selector: &str) -> bool {
selector.contains('*') || selector.contains('?')
}
fn glob_matches(pattern: &str, text: &str) -> bool {
let pattern = pattern.chars().collect::<Vec<_>>();
let text = text.chars().collect::<Vec<_>>();
let mut table = vec![vec![false; text.len() + 1]; pattern.len() + 1];
table[0][0] = true;
for pattern_idx in 1..=pattern.len() {
if pattern[pattern_idx - 1] == '*' {
table[pattern_idx][0] = table[pattern_idx - 1][0];
}
}
for pattern_idx in 1..=pattern.len() {
for text_idx in 1..=text.len() {
table[pattern_idx][text_idx] = match pattern[pattern_idx - 1] {
'*' => table[pattern_idx - 1][text_idx] || table[pattern_idx][text_idx - 1],
'?' => table[pattern_idx - 1][text_idx - 1],
character => {
character == text[text_idx - 1] && table[pattern_idx - 1][text_idx - 1]
}
};
}
}
table[pattern.len()][text.len()]
}
#[derive(Debug)]
pub struct Parameters {
values: Vec<f64>,
n_free: usize,
storage_to_assembled: Vec<usize>,
}
impl Parameters {
pub fn new(values: Vec<f64>, n_free: usize, storage_to_assembled: Vec<usize>) -> Self {
Self {
values,
n_free,
storage_to_assembled,
}
}
pub fn values(&self) -> &[f64] {
&self.values
}
pub fn with_values(&self, values: Vec<f64>) -> Self {
Self {
values,
n_free: self.n_free,
storage_to_assembled: self.storage_to_assembled.clone(),
}
}
pub fn get(&self, pid: ParameterID) -> f64 {
self.assembled_index(pid)
.and_then(|index| self.values.get(index))
.copied()
.unwrap_or(f64::NAN)
}
pub fn assembled_index(&self, pid: ParameterID) -> Option<usize> {
self.storage_index(pid)
.and_then(|index| self.storage_to_assembled.get(index).copied())
}
pub fn free_index(&self, pid: ParameterID) -> Option<usize> {
let index = self.assembled_index(pid)?;
(index < self.n_free).then_some(index)
}
fn storage_index(&self, pid: ParameterID) -> Option<usize> {
match pid {
ParameterID::Parameter(index) | ParameterID::Constant(index) => Some(index),
ParameterID::Uninit => None,
}
}
pub fn len(&self) -> usize {
self.n_free
}
pub fn is_empty(&self) -> bool {
self.n_free == 0
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Resources {
amplitudes: HashMap<String, AmplitudeID>,
pub active: Vec<bool>,
#[serde(default)]
active_indices: Vec<usize>,
pub parameter_map: ParameterMap,
pub caches: Vec<Cache>,
scalar_cache_names: HashMap<String, usize>,
complex_scalar_cache_names: HashMap<String, usize>,
vector_cache_names: HashMap<String, usize>,
complex_vector_cache_names: HashMap<String, usize>,
matrix_cache_names: HashMap<String, usize>,
complex_matrix_cache_names: HashMap<String, usize>,
cache_size: usize,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Cache(Vec<f64>);
impl Cache {
fn new(cache_size: usize) -> Self {
Self(vec![0.0; cache_size])
}
pub fn store_scalar(&mut self, sid: ScalarID, value: f64) {
self.0[sid.0] = value;
}
pub fn store_complex_scalar(&mut self, csid: ComplexScalarID, value: Complex64) {
self.0[csid.0] = value.re;
self.0[csid.1] = value.im;
}
pub fn store_vector<const R: usize>(&mut self, vid: VectorID<R>, value: SVector<f64, R>) {
vid.0
.into_iter()
.enumerate()
.for_each(|(vi, i)| self.0[i] = value[vi]);
}
pub fn store_complex_vector<const R: usize>(
&mut self,
cvid: ComplexVectorID<R>,
value: SVector<Complex64, R>,
) {
cvid.0
.into_iter()
.enumerate()
.for_each(|(vi, i)| self.0[i] = value[vi].re);
cvid.1
.into_iter()
.enumerate()
.for_each(|(vi, i)| self.0[i] = value[vi].im);
}
pub fn store_matrix<const R: usize, const C: usize>(
&mut self,
mid: MatrixID<R, C>,
value: SMatrix<f64, R, C>,
) {
mid.0.into_iter().enumerate().for_each(|(vi, row)| {
row.into_iter()
.enumerate()
.for_each(|(vj, k)| self.0[k] = value[(vi, vj)])
});
}
pub fn store_complex_matrix<const R: usize, const C: usize>(
&mut self,
cmid: ComplexMatrixID<R, C>,
value: SMatrix<Complex64, R, C>,
) {
cmid.0.into_iter().enumerate().for_each(|(vi, row)| {
row.into_iter()
.enumerate()
.for_each(|(vj, k)| self.0[k] = value[(vi, vj)].re)
});
cmid.1.into_iter().enumerate().for_each(|(vi, row)| {
row.into_iter()
.enumerate()
.for_each(|(vj, k)| self.0[k] = value[(vi, vj)].im)
});
}
pub fn get_scalar(&self, sid: ScalarID) -> f64 {
self.0[sid.0]
}
pub fn get_complex_scalar(&self, csid: ComplexScalarID) -> Complex64 {
Complex64::new(self.0[csid.0], self.0[csid.1])
}
pub fn get_vector<const R: usize>(&self, vid: VectorID<R>) -> SVector<f64, R> {
SVector::from_fn(|i, _| self.0[vid.0[i]])
}
pub fn get_complex_vector<const R: usize>(
&self,
cvid: ComplexVectorID<R>,
) -> SVector<Complex64, R> {
SVector::from_fn(|i, _| Complex64::new(self.0[cvid.0[i]], self.0[cvid.1[i]]))
}
pub fn get_matrix<const R: usize, const C: usize>(
&self,
mid: MatrixID<R, C>,
) -> SMatrix<f64, R, C> {
SMatrix::from_fn(|i, j| self.0[mid.0[i][j]])
}
pub fn get_complex_matrix<const R: usize, const C: usize>(
&self,
cmid: ComplexMatrixID<R, C>,
) -> SMatrix<Complex64, R, C> {
SMatrix::from_fn(|i, j| Complex64::new(self.0[cmid.0[i][j]], self.0[cmid.1[i][j]]))
}
}
#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize)]
pub enum ParameterID {
Parameter(usize),
Constant(usize),
#[default]
Uninit,
}
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)]
pub struct ScalarID(usize);
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)]
pub struct ComplexScalarID(usize, usize);
#[serde_as]
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct VectorID<const R: usize>(#[serde_as(as = "[_; R]")] [usize; R]);
impl<const R: usize> Default for VectorID<R> {
fn default() -> Self {
Self([0; R])
}
}
#[serde_as]
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct ComplexVectorID<const R: usize>(
#[serde_as(as = "[_; R]")] [usize; R],
#[serde_as(as = "[_; R]")] [usize; R],
);
impl<const R: usize> Default for ComplexVectorID<R> {
fn default() -> Self {
Self([0; R], [0; R])
}
}
#[serde_as]
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct MatrixID<const R: usize, const C: usize>(
#[serde_as(as = "[[_; C]; R]")] [[usize; C]; R],
);
impl<const R: usize, const C: usize> Default for MatrixID<R, C> {
fn default() -> Self {
Self([[0; C]; R])
}
}
#[serde_as]
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct ComplexMatrixID<const R: usize, const C: usize>(
#[serde_as(as = "[[_; C]; R]")] [[usize; C]; R],
#[serde_as(as = "[[_; C]; R]")] [[usize; C]; R],
);
impl<const R: usize, const C: usize> Default for ComplexMatrixID<R, C> {
fn default() -> Self {
Self([[0; C]; R], [[0; C]; R])
}
}
impl Resources {
pub fn rename_parameter(&mut self, old: &str, new: &str) -> LadduResult<()> {
self.parameter_map.rename_parameter(old, new)
}
pub fn rename_parameters(&mut self, mapping: &HashMap<String, String>) -> LadduResult<()> {
self.parameter_map.rename_parameters(mapping)
}
pub fn free_parameter(&self, name: &str) -> LadduResult<()> {
self.parameter_map.free_parameter(name)
}
pub fn fix_parameter(&self, name: &str, value: f64) -> LadduResult<()> {
self.parameter_map.fix_parameter(name, value)
}
pub fn free_parameter_names(&self) -> Vec<String> {
self.parameter_map.free().names()
}
pub fn fixed_parameter_names(&self) -> Vec<String> {
self.parameter_map.fixed().names()
}
pub fn parameter_names(&self) -> Vec<String> {
self.free_parameter_names()
.into_iter()
.chain(self.fixed_parameter_names())
.collect()
}
pub fn n_free_parameters(&self) -> usize {
self.parameter_map.free().len()
}
pub fn n_fixed_parameters(&self) -> usize {
self.parameter_map.fixed().len()
}
pub fn n_parameters(&self) -> usize {
self.n_free_parameters() + self.n_fixed_parameters()
}
fn rebuild_active_indices(&mut self) {
self.active_indices.clear();
self.active_indices.extend(
self.active
.iter()
.enumerate()
.filter_map(|(idx, &is_active)| if is_active { Some(idx) } else { None }),
);
}
pub(crate) fn refresh_active_indices(&mut self) {
self.rebuild_active_indices();
}
pub fn active_indices(&self) -> &[usize] {
&self.active_indices
}
fn selector_indices(&self, selector: &str) -> Vec<usize> {
if is_glob_selector(selector) {
self.amplitudes
.iter()
.filter_map(|(name, amplitude)| {
if glob_matches(selector, name) {
Some(amplitude.1)
} else {
None
}
})
.collect()
} else {
self.amplitudes
.get(selector)
.map(|amplitude| vec![amplitude.1])
.unwrap_or_default()
}
}
fn set_activation_state_by_selector(
&mut self,
selector: &str,
active: bool,
strict: bool,
) -> LadduResult<bool> {
let indices = self.selector_indices(selector);
if indices.is_empty() {
if strict {
return Err(LadduError::AmplitudeNotFoundError {
name: selector.to_string(),
});
}
return Ok(false);
}
let mut changed = false;
for idx in indices {
if self.active[idx] != active {
self.active[idx] = active;
changed = true;
}
}
Ok(changed)
}
fn selector_indices_many<T: AsRef<str>>(
&self,
selectors: &[T],
strict: bool,
) -> LadduResult<Vec<usize>> {
let mut indices = Vec::new();
for selector in selectors {
let selector_ref = selector.as_ref();
let selector_indices = self.selector_indices(selector_ref);
if selector_indices.is_empty() && strict {
return Err(LadduError::AmplitudeNotFoundError {
name: selector_ref.to_string(),
});
}
indices.extend(selector_indices);
}
indices.sort_unstable();
indices.dedup();
Ok(indices)
}
fn isolate_indices(&mut self, indices: &[usize]) {
let mut changed = false;
for (idx, active) in self.active.iter_mut().enumerate() {
let next_active = indices.binary_search(&idx).is_ok();
if *active != next_active {
*active = next_active;
changed = true;
}
}
if changed {
self.rebuild_active_indices();
}
}
pub fn activate<T: AsRef<str>>(&mut self, name: T) {
if self
.set_activation_state_by_selector(name.as_ref(), true, false)
.unwrap_or(false)
{
self.rebuild_active_indices();
}
}
pub fn activate_many<T: AsRef<str>>(&mut self, names: &[T]) {
let mut changed = false;
for name in names {
if self
.set_activation_state_by_selector(name.as_ref(), true, false)
.unwrap_or(false)
{
changed = true;
}
}
if changed {
self.rebuild_active_indices();
}
}
pub fn activate_strict<T: AsRef<str>>(&mut self, name: T) -> LadduResult<()> {
if self.set_activation_state_by_selector(name.as_ref(), true, true)? {
self.rebuild_active_indices();
}
Ok(())
}
pub fn activate_many_strict<T: AsRef<str>>(&mut self, names: &[T]) -> LadduResult<()> {
let mut changed = false;
for name in names {
if self.set_activation_state_by_selector(name.as_ref(), true, true)? {
changed = true;
}
}
if changed {
self.rebuild_active_indices();
}
Ok(())
}
pub fn activate_all(&mut self) {
let mut changed = false;
for active in self.active.iter_mut() {
if !*active {
*active = true;
changed = true;
}
}
if changed {
self.rebuild_active_indices();
}
}
pub fn deactivate<T: AsRef<str>>(&mut self, name: T) {
if self
.set_activation_state_by_selector(name.as_ref(), false, false)
.unwrap_or(false)
{
self.rebuild_active_indices();
}
}
pub fn deactivate_many<T: AsRef<str>>(&mut self, names: &[T]) {
let mut changed = false;
for name in names {
if self
.set_activation_state_by_selector(name.as_ref(), false, false)
.unwrap_or(false)
{
changed = true;
}
}
if changed {
self.rebuild_active_indices();
}
}
pub fn deactivate_strict<T: AsRef<str>>(&mut self, name: T) -> LadduResult<()> {
if self.set_activation_state_by_selector(name.as_ref(), false, true)? {
self.rebuild_active_indices();
}
Ok(())
}
pub fn deactivate_many_strict<T: AsRef<str>>(&mut self, names: &[T]) -> LadduResult<()> {
let mut changed = false;
for name in names {
if self.set_activation_state_by_selector(name.as_ref(), false, true)? {
changed = true;
}
}
if changed {
self.rebuild_active_indices();
}
Ok(())
}
pub fn deactivate_all(&mut self) {
let mut changed = false;
for active in self.active.iter_mut() {
if *active {
*active = false;
changed = true;
}
}
if changed {
self.rebuild_active_indices();
}
}
pub fn isolate<T: AsRef<str>>(&mut self, name: T) {
let indices = self.selector_indices(name.as_ref());
if !indices.is_empty() || !is_glob_selector(name.as_ref()) {
self.isolate_indices(&indices);
}
}
pub fn isolate_strict<T: AsRef<str>>(&mut self, name: T) -> LadduResult<()> {
let indices = self.selector_indices_many(&[name], true)?;
self.isolate_indices(&indices);
Ok(())
}
pub fn isolate_many<T: AsRef<str>>(&mut self, names: &[T]) {
if let Ok(indices) = self.selector_indices_many(names, false) {
if !indices.is_empty() || names.iter().any(|name| !is_glob_selector(name.as_ref())) {
self.isolate_indices(&indices);
}
}
}
pub fn isolate_many_strict<T: AsRef<str>>(&mut self, names: &[T]) -> LadduResult<()> {
let indices = self.selector_indices_many(names, true)?;
self.isolate_indices(&indices);
Ok(())
}
pub fn register_amplitude(&mut self, name: &str) -> LadduResult<AmplitudeID> {
if self.amplitudes.contains_key(name) {
return Err(LadduError::RegistrationError {
name: name.to_string(),
});
}
let next_id = AmplitudeID(name.to_string(), self.amplitudes.len());
self.amplitudes.insert(name.to_string(), next_id.clone());
self.active.push(true);
self.rebuild_active_indices();
Ok(next_id)
}
pub fn amplitude_id(&self, name: &str) -> Option<AmplitudeID> {
self.amplitudes.get(name).cloned()
}
pub fn register_parameter(&mut self, p: &Parameter) -> LadduResult<ParameterID> {
self.parameter_map.register_parameter(p)
}
pub(crate) fn reserve_cache(&mut self, num_events: usize) {
self.caches = vec![Cache::new(self.cache_size); num_events]
}
pub fn register_scalar(&mut self, name: Option<&str>) -> ScalarID {
let first_index = if let Some(name) = name {
*self
.scalar_cache_names
.entry(name.to_string())
.or_insert_with(|| {
self.cache_size += 1;
self.cache_size - 1
})
} else {
self.cache_size += 1;
self.cache_size - 1
};
ScalarID(first_index)
}
pub fn register_complex_scalar(&mut self, name: Option<&str>) -> ComplexScalarID {
let first_index = if let Some(name) = name {
*self
.complex_scalar_cache_names
.entry(name.to_string())
.or_insert_with(|| {
self.cache_size += 2;
self.cache_size - 2
})
} else {
self.cache_size += 2;
self.cache_size - 2
};
ComplexScalarID(first_index, first_index + 1)
}
pub fn register_vector<const R: usize>(&mut self, name: Option<&str>) -> VectorID<R> {
let first_index = if let Some(name) = name {
*self
.vector_cache_names
.entry(name.to_string())
.or_insert_with(|| {
self.cache_size += R;
self.cache_size - R
})
} else {
self.cache_size += R;
self.cache_size - R
};
VectorID(array::from_fn(|i| first_index + i))
}
pub fn register_complex_vector<const R: usize>(
&mut self,
name: Option<&str>,
) -> ComplexVectorID<R> {
let first_index = if let Some(name) = name {
*self
.complex_vector_cache_names
.entry(name.to_string())
.or_insert_with(|| {
self.cache_size += R * 2;
self.cache_size - (R * 2)
})
} else {
self.cache_size += R * 2;
self.cache_size - (R * 2)
};
ComplexVectorID(
array::from_fn(|i| first_index + i),
array::from_fn(|i| (first_index + R) + i),
)
}
pub fn register_matrix<const R: usize, const C: usize>(
&mut self,
name: Option<&str>,
) -> MatrixID<R, C> {
let first_index = if let Some(name) = name {
*self
.matrix_cache_names
.entry(name.to_string())
.or_insert_with(|| {
self.cache_size += R * C;
self.cache_size - (R * C)
})
} else {
self.cache_size += R * C;
self.cache_size - (R * C)
};
MatrixID(array::from_fn(|i| {
array::from_fn(|j| first_index + i * C + j)
}))
}
pub fn register_complex_matrix<const R: usize, const C: usize>(
&mut self,
name: Option<&str>,
) -> ComplexMatrixID<R, C> {
let first_index = if let Some(name) = name {
*self
.complex_matrix_cache_names
.entry(name.to_string())
.or_insert_with(|| {
self.cache_size += 2 * R * C;
self.cache_size - (2 * R * C)
})
} else {
self.cache_size += 2 * R * C;
self.cache_size - (2 * R * C)
};
ComplexMatrixID(
array::from_fn(|i| array::from_fn(|j| first_index + i * C + j)),
array::from_fn(|i| array::from_fn(|j| (first_index + R * C) + i * C + j)),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use nalgebra::{Matrix2, Vector2};
use num::complex::Complex64;
#[test]
fn test_parameters() {
let parameters = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let params = Parameters::new(parameters, 3, vec![0, 1, 2, 3, 4, 5]);
assert_eq!(params.get(ParameterID::Parameter(0)), 1.0);
assert_eq!(params.get(ParameterID::Parameter(1)), 2.0);
assert_eq!(params.get(ParameterID::Parameter(2)), 3.0);
assert_eq!(params.get(ParameterID::Constant(3)), 4.0);
assert_eq!(params.get(ParameterID::Constant(4)), 5.0);
assert_eq!(params.get(ParameterID::Constant(5)), 6.0);
assert_eq!(params.free_index(ParameterID::Parameter(0)), Some(0));
assert_eq!(params.free_index(ParameterID::Constant(3)), None);
assert_eq!(params.len(), 3);
}
#[test]
fn test_uninit_parameter_returns_nan() {
let parameters = vec![1.0, 1.0];
let params = Parameters::new(parameters, 1, vec![0, 1]);
assert!(params.get(ParameterID::Uninit).is_nan());
assert!(params.get(ParameterID::Parameter(3)).is_nan());
assert!(params.get(ParameterID::Constant(3)).is_nan());
}
#[test]
fn test_resources_amplitude_management() {
let mut resources = Resources::default();
let amp1 = resources.register_amplitude("amp1").unwrap();
let amp2 = resources.register_amplitude("amp2").unwrap();
assert!(resources.active[amp1.1]);
assert!(resources.active[amp2.1]);
resources.deactivate_strict("amp1").unwrap();
assert!(!resources.active[amp1.1]);
assert!(resources.active[amp2.1]);
resources.activate_strict("amp1").unwrap();
assert!(resources.active[amp1.1]);
resources.deactivate_all();
assert!(!resources.active[amp1.1]);
assert!(!resources.active[amp2.1]);
resources.activate_all();
assert!(resources.active[amp1.1]);
assert!(resources.active[amp2.1]);
resources.isolate_strict("amp1").unwrap();
assert!(resources.active[amp1.1]);
assert!(!resources.active[amp2.1]);
}
#[test]
fn test_resources_amplitude_glob_management() {
let mut resources = Resources::default();
let signal_s = resources.register_amplitude("signal.s").unwrap();
let signal_d = resources.register_amplitude("signal.d").unwrap();
let background = resources.register_amplitude("background").unwrap();
resources.deactivate_strict("signal.*").unwrap();
assert!(!resources.active[signal_s.1]);
assert!(!resources.active[signal_d.1]);
assert!(resources.active[background.1]);
resources.activate_strict("signal.?").unwrap();
assert!(resources.active[signal_s.1]);
assert!(resources.active[signal_d.1]);
assert!(resources.active[background.1]);
resources.isolate_strict("signal.*").unwrap();
assert!(resources.active[signal_s.1]);
assert!(resources.active[signal_d.1]);
assert!(!resources.active[background.1]);
resources.activate_all();
resources
.isolate_many_strict(&["signal.s", "back*"])
.unwrap();
assert!(resources.active[signal_s.1]);
assert!(!resources.active[signal_d.1]);
assert!(resources.active[background.1]);
assert!(resources.activate_strict("missing*").is_err());
assert!(resources.deactivate_strict("missing?").is_err());
assert!(resources.isolate_strict("missing*").is_err());
}
#[test]
fn test_resources_non_strict_zero_match_glob_is_noop() {
let mut resources = Resources::default();
let signal = resources.register_amplitude("signal").unwrap();
let background = resources.register_amplitude("background").unwrap();
resources.deactivate("missing*");
assert!(resources.active[signal.1]);
assert!(resources.active[background.1]);
resources.isolate("missing*");
assert!(resources.active[signal.1]);
assert!(resources.active[background.1]);
}
#[test]
fn test_resources_parameter_registration() {
let mut resources = Resources::default();
let param1 = resources
.register_parameter(&Parameter::new("param1"))
.unwrap();
let const1 = resources
.register_parameter(&Parameter::new_fixed("const1", 1.0))
.unwrap();
match param1 {
ParameterID::Parameter(idx) => assert_eq!(idx, 0),
_ => panic!("Expected Parameter variant"),
}
match const1 {
ParameterID::Constant(idx) => assert_eq!(idx, 1),
_ => panic!("Expected Constant variant"),
}
}
#[test]
fn test_cache_scalar_operations() {
let mut resources = Resources::default();
let scalar1 = resources.register_scalar(Some("test_scalar"));
let scalar2 = resources.register_scalar(None);
let scalar3 = resources.register_scalar(Some("test_scalar"));
resources.reserve_cache(1);
let cache = &mut resources.caches[0];
cache.store_scalar(scalar1, 1.0);
cache.store_scalar(scalar2, 2.0);
assert_eq!(cache.get_scalar(scalar1), 1.0);
assert_eq!(cache.get_scalar(scalar2), 2.0);
assert_eq!(cache.get_scalar(scalar3), 1.0);
}
#[test]
fn test_cache_complex_operations() {
let mut resources = Resources::default();
let complex1 = resources.register_complex_scalar(Some("test_complex"));
let complex2 = resources.register_complex_scalar(None);
let complex3 = resources.register_complex_scalar(Some("test_complex"));
resources.reserve_cache(1);
let cache = &mut resources.caches[0];
let value1 = Complex64::new(1.0, 2.0);
let value2 = Complex64::new(3.0, 4.0);
cache.store_complex_scalar(complex1, value1);
cache.store_complex_scalar(complex2, value2);
assert_eq!(cache.get_complex_scalar(complex1), value1);
assert_eq!(cache.get_complex_scalar(complex2), value2);
assert_eq!(cache.get_complex_scalar(complex3), value1);
}
#[test]
fn test_cache_vector_operations() {
let mut resources = Resources::default();
let vector_id1: VectorID<2> = resources.register_vector(Some("test_vector"));
let vector_id2: VectorID<2> = resources.register_vector(None);
let vector_id3: VectorID<2> = resources.register_vector(Some("test_vector"));
resources.reserve_cache(1);
let cache = &mut resources.caches[0];
let value1 = Vector2::new(1.0, 2.0);
let value2 = Vector2::new(3.0, 4.0);
cache.store_vector(vector_id1, value1);
cache.store_vector(vector_id2, value2);
assert_eq!(cache.get_vector(vector_id1), value1);
assert_eq!(cache.get_vector(vector_id2), value2);
assert_eq!(cache.get_vector(vector_id3), value1);
}
#[test]
fn test_cache_complex_vector_operations() {
let mut resources = Resources::default();
let complex_vector_id1: ComplexVectorID<2> =
resources.register_complex_vector(Some("test_complex_vector"));
let complex_vector_id2: ComplexVectorID<2> = resources.register_complex_vector(None);
let complex_vector_id3: ComplexVectorID<2> =
resources.register_complex_vector(Some("test_complex_vector"));
resources.reserve_cache(1);
let cache = &mut resources.caches[0];
let value1 = Vector2::new(Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0));
let value2 = Vector2::new(Complex64::new(5.0, 6.0), Complex64::new(7.0, 8.0));
cache.store_complex_vector(complex_vector_id1, value1);
cache.store_complex_vector(complex_vector_id2, value2);
assert_eq!(cache.get_complex_vector(complex_vector_id1), value1);
assert_eq!(cache.get_complex_vector(complex_vector_id2), value2);
assert_eq!(cache.get_complex_vector(complex_vector_id3), value1);
}
#[test]
fn test_cache_matrix_operations() {
let mut resources = Resources::default();
let matrix_id1: MatrixID<2, 2> = resources.register_matrix(Some("test_matrix"));
let matrix_id2: MatrixID<2, 2> = resources.register_matrix(None);
let matrix_id3: MatrixID<2, 2> = resources.register_matrix(Some("test_matrix"));
resources.reserve_cache(1);
let cache = &mut resources.caches[0];
let value1 = Matrix2::new(1.0, 2.0, 3.0, 4.0);
let value2 = Matrix2::new(5.0, 6.0, 7.0, 8.0);
cache.store_matrix(matrix_id1, value1);
cache.store_matrix(matrix_id2, value2);
assert_eq!(cache.get_matrix(matrix_id1), value1);
assert_eq!(cache.get_matrix(matrix_id2), value2);
assert_eq!(cache.get_matrix(matrix_id3), value1);
}
#[test]
fn test_cache_complex_matrix_operations() {
let mut resources = Resources::default();
let complex_matrix_id1: ComplexMatrixID<2, 2> =
resources.register_complex_matrix(Some("test_complex_matrix"));
let complex_matrix_id2: ComplexMatrixID<2, 2> = resources.register_complex_matrix(None);
let complex_matrix_id3: ComplexMatrixID<2, 2> =
resources.register_complex_matrix(Some("test_complex_matrix"));
resources.reserve_cache(1);
let cache = &mut resources.caches[0];
let value1 = Matrix2::new(
Complex64::new(1.0, 2.0),
Complex64::new(3.0, 4.0),
Complex64::new(5.0, 6.0),
Complex64::new(7.0, 8.0),
);
let value2 = Matrix2::new(
Complex64::new(9.0, 10.0),
Complex64::new(11.0, 12.0),
Complex64::new(13.0, 14.0),
Complex64::new(15.0, 16.0),
);
cache.store_complex_matrix(complex_matrix_id1, value1);
cache.store_complex_matrix(complex_matrix_id2, value2);
assert_eq!(cache.get_complex_matrix(complex_matrix_id1), value1);
assert_eq!(cache.get_complex_matrix(complex_matrix_id2), value2);
assert_eq!(cache.get_complex_matrix(complex_matrix_id3), value1);
}
#[test]
fn test_uninit_parameter_registration() {
let mut resources = Resources::default();
let result = resources.register_parameter(&Parameter::default());
assert!(result.is_err());
}
#[test]
fn test_duplicate_named_amplitude_registration_error() {
let mut resources = Resources::default();
assert!(resources.register_amplitude("test_amp").is_ok());
assert!(resources.register_amplitude("test_amp").is_err());
}
}