Skip to main content

scirs2_stats/
error_recovery_system.rs

1//! Enhanced error handling and recovery system
2//!
3//! This module provides comprehensive error handling with intelligent recovery
4//! suggestions, detailed diagnostics, and context-aware error reporting.
5
6use crate::error::StatsError;
7use num_cpus;
8use std::collections::HashMap;
9use std::fmt;
10
11/// Enhanced error with recovery suggestions
12#[derive(Debug, Clone)]
13pub struct EnhancedStatsError {
14    /// Original error
15    pub error: StatsError,
16    /// Context information
17    pub context: ErrorContext,
18    /// Recovery suggestions
19    pub recovery_suggestions: Vec<RecoverySuggestion>,
20    /// Related documentation links
21    pub documentation_links: Vec<String>,
22    /// Example code snippets
23    pub example_snippets: Vec<CodeSnippet>,
24    /// Error severity
25    pub severity: ErrorSeverity,
26    /// Performance impact assessment
27    pub performance_impact: PerformanceImpact,
28}
29
30/// Error context information
31#[derive(Debug, Clone)]
32pub struct ErrorContext {
33    /// Function name where error occurred
34    pub function_name: String,
35    /// Module path
36    pub module_path: String,
37    /// Input data characteristics
38    pub data_characteristics: DataCharacteristics,
39    /// System information
40    pub system_info: SystemInfo,
41    /// Computation state
42    pub computation_state: ComputationState,
43}
44
45/// Data characteristics for error context
46#[derive(Debug, Clone)]
47pub struct DataCharacteristics {
48    /// Data size information
49    pub size_info: Option<SizeInfo>,
50    /// Data type information
51    pub type_info: String,
52    /// Data range information
53    pub range_info: Option<RangeInfo>,
54    /// Missing data information
55    pub missingdata_info: Option<MissingDataInfo>,
56    /// Data distribution characteristics
57    pub distribution_info: Option<DistributionInfo>,
58}
59
60/// Size information for arrays/matrices
61#[derive(Debug, Clone)]
62pub struct SizeInfo {
63    /// Number of elements
64    pub n_elements: usize,
65    /// Shape (for multidimensional arrays)
66    pub shape: Vec<usize>,
67    /// Memory usage estimate
68    pub memory_usage_mb: f64,
69}
70
71/// Range information for numerical data
72#[derive(Debug, Clone)]
73pub struct RangeInfo {
74    /// Minimum value
75    pub min: f64,
76    /// Maximum value
77    pub max: f64,
78    /// Has infinite values
79    pub has_infinite: bool,
80    /// Has NaN values
81    pub has_nan: bool,
82    /// Has zero values
83    pub has_zero: bool,
84}
85
86/// Missing data information
87#[derive(Debug, Clone)]
88pub struct MissingDataInfo {
89    /// Number of missing values
90    pub count: usize,
91    /// Percentage of missing values
92    pub percentage: f64,
93    /// Pattern of missingness
94    pub pattern: MissingPattern,
95}
96
97/// Missing data patterns
98#[derive(Debug, Clone, PartialEq)]
99pub enum MissingPattern {
100    /// Missing completely at random
101    MCAR,
102    /// Missing at random
103    MAR,
104    /// Missing not at random
105    MNAR,
106    /// Unknown pattern
107    Unknown,
108}
109
110/// Distribution characteristics
111#[derive(Debug, Clone)]
112pub struct DistributionInfo {
113    /// Estimated mean
114    pub mean: Option<f64>,
115    /// Estimated variance
116    pub variance: Option<f64>,
117    /// Estimated skewness
118    pub skewness: Option<f64>,
119    /// Estimated kurtosis
120    pub kurtosis: Option<f64>,
121    /// Suspected distribution family
122    pub suspected_family: Option<String>,
123}
124
125/// System information
126#[derive(Debug, Clone)]
127pub struct SystemInfo {
128    /// Available memory
129    pub available_memory_mb: Option<f64>,
130    /// Number of CPU cores
131    pub cpu_cores: Option<usize>,
132    /// SIMD capabilities
133    pub simd_capabilities: Vec<String>,
134    /// Parallel processing availability
135    pub parallel_available: bool,
136}
137
138/// Computation state
139#[derive(Debug, Clone)]
140pub struct ComputationState {
141    /// Algorithm being used
142    pub algorithm: String,
143    /// Iteration number (if iterative)
144    pub iteration: Option<usize>,
145    /// Convergence status
146    pub convergence_status: Option<ConvergenceStatus>,
147    /// Current tolerance
148    pub current_tolerance: Option<f64>,
149    /// Intermediate results
150    pub intermediate_results: HashMap<String, f64>,
151}
152
153/// Convergence status
154#[derive(Debug, Clone, PartialEq)]
155pub enum ConvergenceStatus {
156    /// Not started
157    NotStarted,
158    /// In progress
159    InProgress,
160    /// Converged successfully
161    Converged,
162    /// Failed to converge
163    FailedToConverge,
164    /// Diverged
165    Diverged,
166}
167
168/// Recovery suggestion with specific actions
169#[derive(Debug, Clone)]
170pub struct RecoverySuggestion {
171    /// Suggestion type
172    pub suggestion_type: SuggestionType,
173    /// Description of the suggestion
174    pub description: String,
175    /// Specific action to take
176    pub action: RecoveryAction,
177    /// Expected outcome
178    pub expected_outcome: String,
179    /// Confidence level (0.0 to 1.0)
180    pub confidence: f64,
181    /// Prerequisites for this suggestion
182    pub prerequisites: Vec<String>,
183}
184
185/// Types of recovery suggestions
186#[derive(Debug, Clone, PartialEq)]
187pub enum SuggestionType {
188    /// Change algorithm parameters
189    ParameterAdjustment,
190    /// Switch to different algorithm
191    AlgorithmChange,
192    /// Preprocess data
193    DataPreprocessing,
194    /// Increase computational resources
195    ResourceIncrease,
196    /// Use approximation method
197    Approximation,
198    /// Check input validation
199    InputValidation,
200    /// Memory optimization
201    MemoryOptimization,
202    /// Numerical stability improvement
203    NumericalStability,
204}
205
206/// Specific recovery actions
207#[derive(Debug, Clone)]
208pub enum RecoveryAction {
209    /// Adjust parameter to specific value
210    AdjustParameter {
211        parameter_name: String,
212        current_value: String,
213        suggested_value: String,
214        explanation: String,
215    },
216    /// Change algorithm
217    ChangeAlgorithm {
218        current_algorithm: String,
219        suggested_algorithm: String,
220        reasons: Vec<String>,
221    },
222    /// Preprocess data
223    PreprocessData {
224        preprocessing_steps: Vec<PreprocessingStep>,
225    },
226    /// Scale computation
227    ScaleComputation {
228        current_approach: String,
229        suggested_approach: String,
230        expected_improvement: String,
231    },
232    /// Validate inputs
233    ValidateInputs {
234        validation_checks: Vec<ValidationCheck>,
235    },
236    /// Simple data preprocessing (without detailed steps)
237    SimplePreprocessData,
238    /// Simple input validation (without detailed checks)
239    SimpleValidateInputs,
240    /// Adjust tolerance for convergence
241    AdjustTolerance { new_tolerance: f64 },
242    /// Increase maximum iterations
243    IncreaseIterations { factor: f64 },
244    /// Switch to different algorithm
245    SwitchAlgorithm { new_algorithm: String },
246    /// Enable parallel processing
247    EnableParallelProcessing { num_threads: usize },
248    /// Use chunked processing for large data
249    UseChunkedProcessing { chunksize: usize },
250    /// Apply regularization
251    ApplyRegularization { regularization_strength: f64 },
252    /// Reduce precision for speed
253    ReducePrecision { new_precision: String },
254    /// Use approximation methods
255    UseApproximation { approximation_method: String },
256}
257
258/// Data preprocessing steps
259#[derive(Debug, Clone)]
260pub struct PreprocessingStep {
261    /// Step name
262    pub name: String,
263    /// Description
264    pub description: String,
265    /// Code example
266    pub code_example: String,
267    /// Expected impact
268    pub expected_impact: String,
269}
270
271/// Input validation checks
272#[derive(Debug, Clone)]
273pub struct ValidationCheck {
274    /// Check name
275    pub name: String,
276    /// Condition to check
277    pub condition: String,
278    /// How to fix if failed
279    pub fix_suggestion: String,
280}
281
282/// Code snippet for examples
283#[derive(Debug, Clone)]
284pub struct CodeSnippet {
285    /// Title of the snippet
286    pub title: String,
287    /// Code content
288    pub code: String,
289    /// Language (usually "rust")
290    pub language: String,
291    /// Description
292    pub description: String,
293}
294
295/// Error severity levels
296#[derive(Debug, Clone, PartialEq, PartialOrd)]
297pub enum ErrorSeverity {
298    /// Low severity - operation can often continue
299    Low,
300    /// Medium severity - may impact results
301    Medium,
302    /// High severity - computation cannot proceed
303    High,
304    /// Critical severity - system-level issue
305    Critical,
306}
307
308/// Performance impact assessment
309#[derive(Debug, Clone)]
310pub struct PerformanceImpact {
311    /// Expected memory usage change
312    pub memory_impact: ImpactLevel,
313    /// Expected computation time change
314    pub time_impact: ImpactLevel,
315    /// Expected accuracy impact
316    pub accuracy_impact: ImpactLevel,
317    /// Scalability concerns
318    pub scalability_impact: ImpactLevel,
319}
320
321/// Impact levels for performance assessment
322#[derive(Debug, Clone, PartialEq)]
323pub enum ImpactLevel {
324    /// No significant impact
325    None,
326    /// Minor impact
327    Minor,
328    /// Moderate impact
329    Moderate,
330    /// Major impact
331    Major,
332    /// Severe impact
333    Severe,
334}
335
336/// Enhanced error handling system
337pub struct ErrorRecoverySystem {
338    /// Error history
339    error_history: Vec<EnhancedStatsError>,
340    /// Recovery success rates
341    #[allow(dead_code)]
342    recovery_success_rates: HashMap<String, f64>,
343    /// System configuration
344    config: ErrorRecoveryConfig,
345}
346
347/// Configuration for error recovery system
348#[derive(Debug, Clone)]
349pub struct ErrorRecoveryConfig {
350    /// Maximum number of errors to keep in history
351    pub max_historysize: usize,
352    /// Enable detailed diagnostics
353    pub detailed_diagnostics: bool,
354    /// Enable automatic recovery suggestions
355    pub auto_suggestions: bool,
356    /// Include performance analysis
357    pub performance_analysis: bool,
358    /// Include code examples
359    pub include_examples: bool,
360}
361
362impl Default for ErrorRecoveryConfig {
363    fn default() -> Self {
364        Self {
365            max_historysize: 100,
366            detailed_diagnostics: true,
367            auto_suggestions: true,
368            performance_analysis: true,
369            include_examples: true,
370        }
371    }
372}
373
374impl ErrorRecoverySystem {
375    /// Create new error recovery system
376    pub fn new(config: ErrorRecoveryConfig) -> Self {
377        Self {
378            error_history: Vec::new(),
379            recovery_success_rates: HashMap::new(),
380            config,
381        }
382    }
383
384    /// Enhance a basic error with context and recovery suggestions
385    pub fn enhance_error(
386        &mut self,
387        error: StatsError,
388        function_name: &str,
389        module_path: &str,
390    ) -> EnhancedStatsError {
391        let context = self.build_error_context(function_name, module_path, &error);
392        let recovery_suggestions = self.generate_recovery_suggestions(&error, &context);
393        let documentation_links = self.generate_documentation_links(&error);
394        let example_snippets = if self.config.include_examples {
395            self.generate_example_snippets(&error, &recovery_suggestions)
396        } else {
397            Vec::new()
398        };
399        let severity = self.assess_error_severity(&error, &context);
400        let performance_impact = if self.config.performance_analysis {
401            self.assess_performance_impact(&error, &context)
402        } else {
403            PerformanceImpact {
404                memory_impact: ImpactLevel::None,
405                time_impact: ImpactLevel::None,
406                accuracy_impact: ImpactLevel::None,
407                scalability_impact: ImpactLevel::None,
408            }
409        };
410
411        let enhanced_error = EnhancedStatsError {
412            error,
413            context,
414            recovery_suggestions,
415            documentation_links,
416            example_snippets,
417            severity,
418            performance_impact,
419        };
420
421        // Add to history
422        self.error_history.push(enhanced_error.clone());
423        if self.error_history.len() > self.config.max_historysize {
424            self.error_history.drain(0..1);
425        }
426
427        enhanced_error
428    }
429
430    /// Build error context
431    fn build_error_context(
432        &self,
433        function_name: &str,
434        module_path: &str,
435        error: &StatsError,
436    ) -> ErrorContext {
437        let data_characteristics = self.inferdata_characteristics(error);
438        let system_info = self.gather_system_info();
439        let computation_state = self.infer_computation_state(error, function_name);
440
441        ErrorContext {
442            function_name: function_name.to_string(),
443            module_path: module_path.to_string(),
444            data_characteristics,
445            system_info,
446            computation_state,
447        }
448    }
449
450    /// Infer data characteristics from error
451    fn inferdata_characteristics(&self, error: &StatsError) -> DataCharacteristics {
452        // This would analyze the _error to infer data properties
453        DataCharacteristics {
454            size_info: None,
455            type_info: "unknown".to_string(),
456            range_info: None,
457            missingdata_info: None,
458            distribution_info: None,
459        }
460    }
461
462    /// Gather system information
463    fn gather_system_info(&self) -> SystemInfo {
464        SystemInfo {
465            available_memory_mb: self.get_available_memory(),
466            cpu_cores: Some(num_cpus::get()),
467            simd_capabilities: self.detect_simd_capabilities(),
468            parallel_available: true,
469        }
470    }
471
472    /// Get available memory (simplified)
473    fn get_available_memory(&self) -> Option<f64> {
474        // This would use system APIs to get actual memory info
475        None
476    }
477
478    /// Detect SIMD capabilities
479    fn detect_simd_capabilities(&self) -> Vec<String> {
480        let mut capabilities = Vec::new();
481
482        #[cfg(target_arch = "x86_64")]
483        {
484            if std::arch::is_x86_feature_detected!("sse") {
485                capabilities.push("SSE".to_string());
486            }
487            if std::arch::is_x86_feature_detected!("sse2") {
488                capabilities.push("SSE2".to_string());
489            }
490            if std::arch::is_x86_feature_detected!("avx") {
491                capabilities.push("AVX".to_string());
492            }
493            if std::arch::is_x86_feature_detected!("avx2") {
494                capabilities.push("AVX2".to_string());
495            }
496        }
497
498        capabilities
499    }
500
501    /// Infer computation state
502    fn infer_computation_state(&self, error: &StatsError, functionname: &str) -> ComputationState {
503        ComputationState {
504            algorithm: functionname.to_string(),
505            iteration: None,
506            convergence_status: None,
507            current_tolerance: None,
508            intermediate_results: HashMap::new(),
509        }
510    }
511
512    /// Generate recovery suggestions based on error type
513    fn generate_recovery_suggestions(
514        &self,
515        error: &StatsError,
516        context: &ErrorContext,
517    ) -> Vec<RecoverySuggestion> {
518        let mut suggestions = Vec::new();
519
520        match error {
521            StatsError::InvalidArgument(msg) => {
522                suggestions.extend(self.generate_invalid_argument_suggestions(msg, context));
523            }
524            StatsError::DimensionMismatch(msg) => {
525                suggestions.extend(self.generate_dimension_mismatch_suggestions(msg, context));
526            }
527            StatsError::ComputationError(msg) => {
528                suggestions.extend(self.generate_computation_error_suggestions(msg, context));
529            }
530            StatsError::ConvergenceError(msg) => {
531                suggestions.extend(self.generate_convergence_error_suggestions(msg, context));
532            }
533            _ => {
534                suggestions.push(RecoverySuggestion {
535                    suggestion_type: SuggestionType::InputValidation,
536                    description: "Check input data and parameters".to_string(),
537                    action: RecoveryAction::ValidateInputs {
538                        validation_checks: vec![ValidationCheck {
539                            name: "Data finite check".to_string(),
540                            condition: "All values are finite (not NaN or infinite)".to_string(),
541                            fix_suggestion: "Remove or replace NaN/infinite values".to_string(),
542                        }],
543                    },
544                    expected_outcome: "Eliminate invalid input data".to_string(),
545                    confidence: 0.7,
546                    prerequisites: vec![],
547                });
548            }
549        }
550
551        suggestions
552    }
553
554    /// Generate suggestions for invalid argument errors
555    fn generate_invalid_argument_suggestions(
556        &self,
557        msg: &str,
558        _context: &ErrorContext,
559    ) -> Vec<RecoverySuggestion> {
560        vec![RecoverySuggestion {
561            suggestion_type: SuggestionType::InputValidation,
562            description: "Validate input parameters before calling the function".to_string(),
563            action: RecoveryAction::ValidateInputs {
564                validation_checks: vec![ValidationCheck {
565                    name: "Parameter bounds check".to_string(),
566                    condition: "Parameters are within valid ranges".to_string(),
567                    fix_suggestion: "Adjust parameters to valid ranges".to_string(),
568                }],
569            },
570            expected_outcome: "Function executes successfully with valid inputs".to_string(),
571            confidence: 0.9,
572            prerequisites: vec!["Input data available".to_string()],
573        }]
574    }
575
576    /// Generate suggestions for dimension mismatch errors
577    fn generate_dimension_mismatch_suggestions(
578        &self,
579        msg: &str,
580        _context: &ErrorContext,
581    ) -> Vec<RecoverySuggestion> {
582        vec![RecoverySuggestion {
583            suggestion_type: SuggestionType::DataPreprocessing,
584            description: "Reshape or transpose arrays to match expected dimensions".to_string(),
585            action: RecoveryAction::PreprocessData {
586                preprocessing_steps: vec![PreprocessingStep {
587                    name: "Array reshape".to_string(),
588                    description: "Reshape arrays to compatible dimensions".to_string(),
589                    code_example: "array.intoshape((new_rows, new_cols))".to_string(),
590                    expected_impact: "Arrays will have compatible dimensions".to_string(),
591                }],
592            },
593            expected_outcome: "Arrays have compatible dimensions for the operation".to_string(),
594            confidence: 0.85,
595            prerequisites: vec!["Data can be reshaped without loss".to_string()],
596        }]
597    }
598
599    /// Generate suggestions for computation errors
600    fn generate_computation_error_suggestions(
601        &self,
602        msg: &str,
603        context: &ErrorContext,
604    ) -> Vec<RecoverySuggestion> {
605        let mut suggestions = Vec::new();
606
607        if msg.contains("singular") || msg.contains("invert") {
608            suggestions.push(RecoverySuggestion {
609                suggestion_type: SuggestionType::NumericalStability,
610                description: "Add regularization to improve numerical stability".to_string(),
611                action: RecoveryAction::AdjustParameter {
612                    parameter_name: "regularization".to_string(),
613                    current_value: "0.0".to_string(),
614                    suggested_value: "1e-6".to_string(),
615                    explanation: "Small regularization prevents singular matrices".to_string(),
616                },
617                expected_outcome: "Matrix inversion becomes numerically stable".to_string(),
618                confidence: 0.8,
619                prerequisites: vec!["Matrix inversion required".to_string()],
620            });
621        }
622
623        if msg.contains("memory") || msg.contains("allocation") {
624            suggestions.push(RecoverySuggestion {
625                suggestion_type: SuggestionType::MemoryOptimization,
626                description: "Use chunked processing to reduce memory usage".to_string(),
627                action: RecoveryAction::ScaleComputation {
628                    current_approach: "Process entire dataset at once".to_string(),
629                    suggested_approach: "Process data in smaller chunks".to_string(),
630                    expected_improvement: "Reduced memory usage".to_string(),
631                },
632                expected_outcome: "Computation succeeds with available memory".to_string(),
633                confidence: 0.75,
634                prerequisites: vec!["Data can be processed in chunks".to_string()],
635            });
636        }
637
638        suggestions
639    }
640
641    /// Generate suggestions for convergence errors
642    fn generate_convergence_error_suggestions(
643        &self,
644        msg: &str,
645        _context: &ErrorContext,
646    ) -> Vec<RecoverySuggestion> {
647        vec![RecoverySuggestion {
648            suggestion_type: SuggestionType::ParameterAdjustment,
649            description: "Increase maximum iterations or relax tolerance".to_string(),
650            action: RecoveryAction::AdjustParameter {
651                parameter_name: "max_iterations".to_string(),
652                current_value: "unknown".to_string(),
653                suggested_value: "increased value".to_string(),
654                explanation: "More iterations allow algorithm to converge".to_string(),
655            },
656            expected_outcome: "Algorithm converges within the iteration limit".to_string(),
657            confidence: 0.7,
658            prerequisites: vec!["Algorithm is potentially convergent".to_string()],
659        }]
660    }
661
662    /// Generate documentation links
663    fn generate_documentation_links(&self, error: &StatsError) -> Vec<String> {
664        let mut links = Vec::new();
665
666        match error {
667            StatsError::InvalidArgument(_) => {
668                links.push(
669                    "https://docs.rs/scirs2-stats/latest/scirs2_stats/index.html#input-validation"
670                        .to_string(),
671                );
672            }
673            StatsError::DimensionMismatch(_) => {
674                links.push(
675                    "https://docs.rs/scirs2-stats/latest/scirs2_stats/index.html#array-operations"
676                        .to_string(),
677                );
678            }
679            StatsError::ComputationError(_) => {
680                links.push("https://docs.rs/scirs2-stats/latest/scirs2_stats/index.html#numerical-stability".to_string());
681            }
682            _ => {
683                links.push(
684                    "https://docs.rs/scirs2-stats/latest/scirs2_stats/index.html".to_string(),
685                );
686            }
687        }
688
689        links
690    }
691
692    /// Generate example code snippets
693    fn generate_example_snippets(
694        &self,
695        error: &StatsError,
696        suggestions: &[RecoverySuggestion],
697    ) -> Vec<CodeSnippet> {
698        let mut snippets = Vec::new();
699
700        if !suggestions.is_empty() {
701            match &suggestions[0].action {
702                RecoveryAction::AdjustParameter {
703                    parameter_name,
704                    suggested_value,
705                    ..
706                } => {
707                    snippets.push(CodeSnippet {
708                        title: format!("Adjust {} parameter", parameter_name),
709                        code: format!(
710                            "// Set {} to {}\nlet {} = {};\n// Then retry the operation",
711                            parameter_name, suggested_value, parameter_name, suggested_value
712                        ),
713                        language: "rust".to_string(),
714                        description: "Parameter adjustment example".to_string(),
715                    });
716                }
717                RecoveryAction::PreprocessData {
718                    preprocessing_steps,
719                } => {
720                    if !preprocessing_steps.is_empty() {
721                        snippets.push(CodeSnippet {
722                            title: "Data preprocessing".to_string(),
723                            code: preprocessing_steps[0].code_example.clone(),
724                            language: "rust".to_string(),
725                            description: preprocessing_steps[0].description.clone(),
726                        });
727                    }
728                }
729                _ => {}
730            }
731        }
732
733        snippets
734    }
735
736    /// Assess error severity
737    fn assess_error_severity(&self, error: &StatsError, context: &ErrorContext) -> ErrorSeverity {
738        match error {
739            StatsError::InvalidArgument(_) => ErrorSeverity::Medium,
740            StatsError::DimensionMismatch(_) => ErrorSeverity::Medium,
741            StatsError::ComputationError(_) => ErrorSeverity::High,
742            StatsError::ConvergenceError(_) => ErrorSeverity::Medium,
743            _ => ErrorSeverity::Low,
744        }
745    }
746
747    /// Assess performance impact
748    fn assess_performance_impact(
749        &self,
750        error: &StatsError,
751        context: &ErrorContext,
752    ) -> PerformanceImpact {
753        match error {
754            StatsError::ComputationError(msg) if msg.contains("memory") => PerformanceImpact {
755                memory_impact: ImpactLevel::Major,
756                time_impact: ImpactLevel::Moderate,
757                accuracy_impact: ImpactLevel::None,
758                scalability_impact: ImpactLevel::Major,
759            },
760            StatsError::ConvergenceError(_) => PerformanceImpact {
761                memory_impact: ImpactLevel::Minor,
762                time_impact: ImpactLevel::Major,
763                accuracy_impact: ImpactLevel::Moderate,
764                scalability_impact: ImpactLevel::Moderate,
765            },
766            _ => PerformanceImpact {
767                memory_impact: ImpactLevel::None,
768                time_impact: ImpactLevel::Minor,
769                accuracy_impact: ImpactLevel::Minor,
770                scalability_impact: ImpactLevel::None,
771            },
772        }
773    }
774
775    /// Get error history
776    pub fn error_history(&self) -> &[EnhancedStatsError] {
777        &self.error_history
778    }
779
780    /// Generate comprehensive error report
781    pub fn generate_error_report(&self, enhancederror: &EnhancedStatsError) -> String {
782        let mut report = String::new();
783
784        report.push_str("# Error Report\n\n");
785        report.push_str(&format!("**Error:** {}\n\n", enhancederror.error));
786        report.push_str(&format!("**Severity:** {:?}\n\n", enhancederror.severity));
787        report.push_str(&format!(
788            "**Function:** {}\n",
789            enhancederror.context.function_name
790        ));
791        report.push_str(&format!(
792            "**Module:** {}\n\n",
793            enhancederror.context.module_path
794        ));
795
796        report.push_str("## Recovery Suggestions\n\n");
797        for (i, suggestion) in enhancederror.recovery_suggestions.iter().enumerate() {
798            report.push_str(&format!(
799                "{}. **{}** (Confidence: {:.0}%)\n",
800                i + 1,
801                suggestion.description,
802                suggestion.confidence * 100.0
803            ));
804            report.push_str(&format!("   - {}\n", suggestion.expected_outcome));
805        }
806
807        if !enhancederror.example_snippets.is_empty() {
808            report.push_str("\n## Example Code\n\n");
809            for snippet in &enhancederror.example_snippets {
810                report.push_str(&format!("### {}\n\n", snippet.title));
811                report.push_str(&format!(
812                    "```{}\n{}\n```\n\n",
813                    snippet.language, snippet.code
814                ));
815            }
816        }
817
818        if !enhancederror.documentation_links.is_empty() {
819            report.push_str("## Documentation\n\n");
820            for link in &enhancederror.documentation_links {
821                report.push_str(&format!("- [Documentation]({})\n", link));
822            }
823        }
824
825        report
826    }
827}
828
829impl fmt::Display for EnhancedStatsError {
830    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
831        write!(f, "{}", self.error)?;
832
833        if !self.recovery_suggestions.is_empty() {
834            write!(f, "\n\nSuggestions:")?;
835            for suggestion in &self.recovery_suggestions {
836                write!(f, "\n  - {}", suggestion.description)?;
837            }
838        }
839
840        Ok(())
841    }
842}
843
844/// Global error recovery system instance
845static mut GLOBAL_ERROR_RECOVERY: Option<ErrorRecoverySystem> = None;
846static mut ERROR_RECOVERY_INITIALIZED: bool = false;
847
848/// Initialize global error recovery system
849#[allow(dead_code)]
850pub fn initialize_error_recovery(config: Option<ErrorRecoveryConfig>) {
851    unsafe {
852        if !ERROR_RECOVERY_INITIALIZED {
853            GLOBAL_ERROR_RECOVERY = Some(ErrorRecoverySystem::new(config.unwrap_or_default()));
854            ERROR_RECOVERY_INITIALIZED = true;
855        }
856    }
857}
858
859/// Enhance error with recovery suggestions (global function)
860#[allow(dead_code)]
861pub fn enhance_error_with_recovery(
862    error: StatsError,
863    function_name: &str,
864    module_path: &str,
865) -> EnhancedStatsError {
866    unsafe {
867        if !ERROR_RECOVERY_INITIALIZED {
868            initialize_error_recovery(None);
869        }
870
871        if let Some(ref mut system) = GLOBAL_ERROR_RECOVERY {
872            system.enhance_error(error, function_name, module_path)
873        } else {
874            // Fallback if system not available
875            EnhancedStatsError {
876                error,
877                context: ErrorContext {
878                    function_name: function_name.to_string(),
879                    module_path: module_path.to_string(),
880                    data_characteristics: DataCharacteristics {
881                        size_info: None,
882                        type_info: "unknown".to_string(),
883                        range_info: None,
884                        missingdata_info: None,
885                        distribution_info: None,
886                    },
887                    system_info: SystemInfo {
888                        available_memory_mb: None,
889                        cpu_cores: Some(num_cpus::get()),
890                        simd_capabilities: vec![],
891                        parallel_available: true,
892                    },
893                    computation_state: ComputationState {
894                        algorithm: function_name.to_string(),
895                        iteration: None,
896                        convergence_status: None,
897                        current_tolerance: None,
898                        intermediate_results: HashMap::new(),
899                    },
900                },
901                recovery_suggestions: vec![],
902                documentation_links: vec![],
903                example_snippets: vec![],
904                severity: ErrorSeverity::Medium,
905                performance_impact: PerformanceImpact {
906                    memory_impact: ImpactLevel::None,
907                    time_impact: ImpactLevel::None,
908                    accuracy_impact: ImpactLevel::None,
909                    scalability_impact: ImpactLevel::None,
910                },
911            }
912        }
913    }
914}
915
916/// Convenience macro for enhanced error handling
917#[macro_export]
918macro_rules! enhanced_error {
919    ($error:expr) => {
920        enhance_error_with_recovery($error, function_name!(), module_path!())
921    };
922}