quantrs2_sim/mixed_precision_impl/
mod.rs1pub mod analysis;
9pub mod config;
10pub mod simulator;
11pub mod state_vector;
12
13pub use analysis::{AnalysisSummary, PerformanceMetrics, PrecisionAnalysis, PrecisionAnalyzer};
15pub use config::{
16 AdaptiveStrategy, MixedPrecisionConfig, MixedPrecisionContext, PrecisionLevel, QuantumPrecision,
17};
18pub use simulator::{MixedPrecisionSimulator, MixedPrecisionStats};
19pub use state_vector::MixedPrecisionStateVector;
20
21use crate::error::Result;
22
23#[allow(clippy::missing_const_for_fn)] pub fn initialize() -> Result<()> {
26 #[cfg(feature = "advanced_math")]
28 {
29 let _context = MixedPrecisionContext::new(AdaptiveStrategy::ErrorBased(1e-6));
31 let _ = _context; }
33
34 Ok(())
35}
36
37pub const fn is_available() -> bool {
39 cfg!(feature = "advanced_math")
40}
41
42pub fn get_supported_precisions() -> Vec<QuantumPrecision> {
44 vec![
45 QuantumPrecision::Half,
46 QuantumPrecision::Single,
47 QuantumPrecision::Double,
48 QuantumPrecision::Adaptive,
49 ]
50}
51
52pub const fn default_accuracy_config() -> MixedPrecisionConfig {
54 MixedPrecisionConfig::for_accuracy()
55}
56
57pub const fn default_performance_config() -> MixedPrecisionConfig {
59 MixedPrecisionConfig::for_performance()
60}
61
62pub fn default_balanced_config() -> MixedPrecisionConfig {
64 MixedPrecisionConfig::balanced()
65}
66
67pub fn validate_config(config: &MixedPrecisionConfig) -> Result<()> {
69 config.validate()
70}
71
72pub fn estimate_memory_usage(config: &MixedPrecisionConfig, num_qubits: usize) -> usize {
74 config.estimate_memory_usage(num_qubits)
75}
76
77pub fn calculate_memory_savings(config: &MixedPrecisionConfig, num_qubits: usize) -> f64 {
79 simulator::utils::memory_savings(config, num_qubits)
80}
81
82pub fn get_performance_factor(precision: QuantumPrecision) -> f64 {
84 simulator::utils::performance_improvement_factor(precision)
85}
86
87pub fn benchmark_precisions() -> Result<analysis::PrecisionAnalysis> {
89 let mut analyzer = PrecisionAnalyzer::new();
90 Ok(analyzer.analyze_for_tolerance(1e-6))
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use scirs2_core::ndarray::Array1;
97 use scirs2_core::Complex64;
98
99 #[test]
100 fn test_precision_initialization() {
101 let result = initialize();
102 assert!(result.is_ok());
103 }
104
105 #[test]
106 fn test_supported_precisions() {
107 let precisions = get_supported_precisions();
108 assert_eq!(precisions.len(), 4);
109 assert!(precisions.contains(&QuantumPrecision::Half));
110 assert!(precisions.contains(&QuantumPrecision::Single));
111 assert!(precisions.contains(&QuantumPrecision::Double));
112 assert!(precisions.contains(&QuantumPrecision::Adaptive));
113 }
114
115 #[test]
116 fn test_config_creation() {
117 let accuracy_config = default_accuracy_config();
118 assert_eq!(
119 accuracy_config.state_vector_precision,
120 QuantumPrecision::Double
121 );
122
123 let performance_config = default_performance_config();
124 assert_eq!(
125 performance_config.state_vector_precision,
126 QuantumPrecision::Half
127 );
128
129 let balanced_config = default_balanced_config();
130 assert_eq!(
131 balanced_config.state_vector_precision,
132 QuantumPrecision::Single
133 );
134 }
135
136 #[test]
137 fn test_config_validation() {
138 let config = MixedPrecisionConfig::default();
139 assert!(validate_config(&config).is_ok());
140
141 let mut invalid_config = config;
142 invalid_config.error_tolerance = -1.0;
143 assert!(validate_config(&invalid_config).is_err());
144 }
145
146 #[test]
147 fn test_memory_estimation() {
148 let config = MixedPrecisionConfig::default();
149 let memory_4q = estimate_memory_usage(&config, 4);
150 let memory_8q = estimate_memory_usage(&config, 8);
151
152 assert!(memory_8q > memory_4q * 10);
154 }
155
156 #[test]
157 fn test_precision_properties() {
158 assert_eq!(QuantumPrecision::Half.memory_factor(), 0.25);
159 assert_eq!(QuantumPrecision::Single.memory_factor(), 0.5);
160 assert_eq!(QuantumPrecision::Double.memory_factor(), 1.0);
161
162 assert!(QuantumPrecision::Half.typical_error() > QuantumPrecision::Single.typical_error());
163 assert!(
164 QuantumPrecision::Single.typical_error() > QuantumPrecision::Double.typical_error()
165 );
166 }
167
168 #[test]
169 fn test_precision_transitions() {
170 assert_eq!(
171 QuantumPrecision::Half.higher_precision(),
172 Some(QuantumPrecision::Single)
173 );
174 assert_eq!(
175 QuantumPrecision::Single.higher_precision(),
176 Some(QuantumPrecision::Double)
177 );
178 assert_eq!(QuantumPrecision::Double.higher_precision(), None);
179
180 assert_eq!(
181 QuantumPrecision::Double.lower_precision(),
182 Some(QuantumPrecision::Single)
183 );
184 assert_eq!(
185 QuantumPrecision::Single.lower_precision(),
186 Some(QuantumPrecision::Half)
187 );
188 assert_eq!(QuantumPrecision::Half.lower_precision(), None);
189 }
190
191 #[test]
192 fn test_state_vector_creation() {
193 let state = MixedPrecisionStateVector::new(4, QuantumPrecision::Single);
194 assert_eq!(state.len(), 4);
195 assert_eq!(state.precision(), QuantumPrecision::Single);
196
197 let basis_state =
198 MixedPrecisionStateVector::computational_basis(2, QuantumPrecision::Double);
199 assert_eq!(basis_state.len(), 4);
200 assert_eq!(basis_state.precision(), QuantumPrecision::Double);
201 }
202
203 #[test]
204 fn test_state_vector_operations() {
205 let mut state = MixedPrecisionStateVector::new(4, QuantumPrecision::Single);
206
207 let amplitude = Complex64::new(0.5, 0.3);
209 assert!(state.set_amplitude(0, amplitude).is_ok());
210
211 let retrieved_amplitude = state.amplitude(0).unwrap();
213 assert!((retrieved_amplitude.re - amplitude.re).abs() < 1e-6);
214 assert!((retrieved_amplitude.im - amplitude.im).abs() < 1e-6);
215
216 let prob = state.probability(0).unwrap();
218 assert!((prob - amplitude.norm_sqr()).abs() < 1e-6);
219 }
220
221 #[test]
222 fn test_precision_conversion() {
223 let state_single = MixedPrecisionStateVector::new(4, QuantumPrecision::Single);
224 let state_double = state_single.to_precision(QuantumPrecision::Double);
225
226 assert!(state_double.is_ok());
227 let converted = state_double.unwrap();
228 assert_eq!(converted.precision(), QuantumPrecision::Double);
229 assert_eq!(converted.len(), 4);
230 }
231
232 #[test]
233 fn test_simulator_creation() {
234 let config = MixedPrecisionConfig::default();
235 let simulator = MixedPrecisionSimulator::new(2, config);
236
237 assert!(simulator.is_ok());
238 let sim = simulator.unwrap();
239 assert!(sim.get_state().is_some());
240 }
241
242 #[test]
243 fn test_performance_metrics() {
244 let metrics = PerformanceMetrics::new(100.0, 1024, 10.0, 5.0);
245 assert_eq!(metrics.execution_time_ms, 100.0);
246 assert_eq!(metrics.memory_usage_bytes, 1024);
247 assert_eq!(metrics.throughput_ops_per_sec, 10.0);
248 assert_eq!(metrics.energy_efficiency, 5.0);
249
250 let score = metrics.performance_score();
251 assert!((0.0..=1.0).contains(&score));
252 }
253
254 #[test]
255 fn test_precision_analysis() {
256 let mut analysis = PrecisionAnalysis::new();
257 analysis.add_recommendation("test_op".to_string(), QuantumPrecision::Single);
258 analysis.add_error_estimate(QuantumPrecision::Single, 1e-6);
259
260 let metrics = PerformanceMetrics::new(50.0, 512, 20.0, 10.0);
261 analysis.add_performance_metrics(QuantumPrecision::Single, metrics);
262
263 analysis.calculate_quality_score();
264
265 assert_eq!(
266 analysis.get_best_precision("test_op"),
267 Some(QuantumPrecision::Single)
268 );
269 assert!(analysis.quality_score > 0.0);
270 }
271
272 #[test]
273 fn test_analyzer() {
274 let mut analyzer = PrecisionAnalyzer::new();
275 let result = analyzer.analyze_for_tolerance(1e-6);
276 assert!(!result.error_estimates.is_empty());
277 assert!(!result.performance_metrics.is_empty());
278 }
279}