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