use crate::error::StatsError;
use num_cpus;
use std::collections::HashMap;
use std::fmt;
#[derive(Debug, Clone)]
pub struct EnhancedStatsError {
pub error: StatsError,
pub context: ErrorContext,
pub recovery_suggestions: Vec<RecoverySuggestion>,
pub documentation_links: Vec<String>,
pub example_snippets: Vec<CodeSnippet>,
pub severity: ErrorSeverity,
pub performance_impact: PerformanceImpact,
}
#[derive(Debug, Clone)]
pub struct ErrorContext {
pub function_name: String,
pub module_path: String,
pub data_characteristics: DataCharacteristics,
pub system_info: SystemInfo,
pub computation_state: ComputationState,
}
#[derive(Debug, Clone)]
pub struct DataCharacteristics {
pub size_info: Option<SizeInfo>,
pub type_info: String,
pub range_info: Option<RangeInfo>,
pub missingdata_info: Option<MissingDataInfo>,
pub distribution_info: Option<DistributionInfo>,
}
#[derive(Debug, Clone)]
pub struct SizeInfo {
pub n_elements: usize,
pub shape: Vec<usize>,
pub memory_usage_mb: f64,
}
#[derive(Debug, Clone)]
pub struct RangeInfo {
pub min: f64,
pub max: f64,
pub has_infinite: bool,
pub has_nan: bool,
pub has_zero: bool,
}
#[derive(Debug, Clone)]
pub struct MissingDataInfo {
pub count: usize,
pub percentage: f64,
pub pattern: MissingPattern,
}
#[derive(Debug, Clone, PartialEq)]
pub enum MissingPattern {
MCAR,
MAR,
MNAR,
Unknown,
}
#[derive(Debug, Clone)]
pub struct DistributionInfo {
pub mean: Option<f64>,
pub variance: Option<f64>,
pub skewness: Option<f64>,
pub kurtosis: Option<f64>,
pub suspected_family: Option<String>,
}
#[derive(Debug, Clone)]
pub struct SystemInfo {
pub available_memory_mb: Option<f64>,
pub cpu_cores: Option<usize>,
pub simd_capabilities: Vec<String>,
pub parallel_available: bool,
}
#[derive(Debug, Clone)]
pub struct ComputationState {
pub algorithm: String,
pub iteration: Option<usize>,
pub convergence_status: Option<ConvergenceStatus>,
pub current_tolerance: Option<f64>,
pub intermediate_results: HashMap<String, f64>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ConvergenceStatus {
NotStarted,
InProgress,
Converged,
FailedToConverge,
Diverged,
}
#[derive(Debug, Clone)]
pub struct RecoverySuggestion {
pub suggestion_type: SuggestionType,
pub description: String,
pub action: RecoveryAction,
pub expected_outcome: String,
pub confidence: f64,
pub prerequisites: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum SuggestionType {
ParameterAdjustment,
AlgorithmChange,
DataPreprocessing,
ResourceIncrease,
Approximation,
InputValidation,
MemoryOptimization,
NumericalStability,
}
#[derive(Debug, Clone)]
pub enum RecoveryAction {
AdjustParameter {
parameter_name: String,
current_value: String,
suggested_value: String,
explanation: String,
},
ChangeAlgorithm {
current_algorithm: String,
suggested_algorithm: String,
reasons: Vec<String>,
},
PreprocessData {
preprocessing_steps: Vec<PreprocessingStep>,
},
ScaleComputation {
current_approach: String,
suggested_approach: String,
expected_improvement: String,
},
ValidateInputs {
validation_checks: Vec<ValidationCheck>,
},
SimplePreprocessData,
SimpleValidateInputs,
AdjustTolerance { new_tolerance: f64 },
IncreaseIterations { factor: f64 },
SwitchAlgorithm { new_algorithm: String },
EnableParallelProcessing { num_threads: usize },
UseChunkedProcessing { chunksize: usize },
ApplyRegularization { regularization_strength: f64 },
ReducePrecision { new_precision: String },
UseApproximation { approximation_method: String },
}
#[derive(Debug, Clone)]
pub struct PreprocessingStep {
pub name: String,
pub description: String,
pub code_example: String,
pub expected_impact: String,
}
#[derive(Debug, Clone)]
pub struct ValidationCheck {
pub name: String,
pub condition: String,
pub fix_suggestion: String,
}
#[derive(Debug, Clone)]
pub struct CodeSnippet {
pub title: String,
pub code: String,
pub language: String,
pub description: String,
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ErrorSeverity {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone)]
pub struct PerformanceImpact {
pub memory_impact: ImpactLevel,
pub time_impact: ImpactLevel,
pub accuracy_impact: ImpactLevel,
pub scalability_impact: ImpactLevel,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ImpactLevel {
None,
Minor,
Moderate,
Major,
Severe,
}
pub struct ErrorRecoverySystem {
error_history: Vec<EnhancedStatsError>,
#[allow(dead_code)]
recovery_success_rates: HashMap<String, f64>,
config: ErrorRecoveryConfig,
}
#[derive(Debug, Clone)]
pub struct ErrorRecoveryConfig {
pub max_historysize: usize,
pub detailed_diagnostics: bool,
pub auto_suggestions: bool,
pub performance_analysis: bool,
pub include_examples: bool,
}
impl Default for ErrorRecoveryConfig {
fn default() -> Self {
Self {
max_historysize: 100,
detailed_diagnostics: true,
auto_suggestions: true,
performance_analysis: true,
include_examples: true,
}
}
}
impl ErrorRecoverySystem {
pub fn new(config: ErrorRecoveryConfig) -> Self {
Self {
error_history: Vec::new(),
recovery_success_rates: HashMap::new(),
config,
}
}
pub fn enhance_error(
&mut self,
error: StatsError,
function_name: &str,
module_path: &str,
) -> EnhancedStatsError {
let context = self.build_error_context(function_name, module_path, &error);
let recovery_suggestions = self.generate_recovery_suggestions(&error, &context);
let documentation_links = self.generate_documentation_links(&error);
let example_snippets = if self.config.include_examples {
self.generate_example_snippets(&error, &recovery_suggestions)
} else {
Vec::new()
};
let severity = self.assess_error_severity(&error, &context);
let performance_impact = if self.config.performance_analysis {
self.assess_performance_impact(&error, &context)
} else {
PerformanceImpact {
memory_impact: ImpactLevel::None,
time_impact: ImpactLevel::None,
accuracy_impact: ImpactLevel::None,
scalability_impact: ImpactLevel::None,
}
};
let enhanced_error = EnhancedStatsError {
error,
context,
recovery_suggestions,
documentation_links,
example_snippets,
severity,
performance_impact,
};
self.error_history.push(enhanced_error.clone());
if self.error_history.len() > self.config.max_historysize {
self.error_history.drain(0..1);
}
enhanced_error
}
fn build_error_context(
&self,
function_name: &str,
module_path: &str,
error: &StatsError,
) -> ErrorContext {
let data_characteristics = self.inferdata_characteristics(error);
let system_info = self.gather_system_info();
let computation_state = self.infer_computation_state(error, function_name);
ErrorContext {
function_name: function_name.to_string(),
module_path: module_path.to_string(),
data_characteristics,
system_info,
computation_state,
}
}
fn inferdata_characteristics(&self, error: &StatsError) -> DataCharacteristics {
DataCharacteristics {
size_info: None,
type_info: "unknown".to_string(),
range_info: None,
missingdata_info: None,
distribution_info: None,
}
}
fn gather_system_info(&self) -> SystemInfo {
SystemInfo {
available_memory_mb: self.get_available_memory(),
cpu_cores: Some(num_cpus::get()),
simd_capabilities: self.detect_simd_capabilities(),
parallel_available: true,
}
}
fn get_available_memory(&self) -> Option<f64> {
None
}
fn detect_simd_capabilities(&self) -> Vec<String> {
let mut capabilities = Vec::new();
#[cfg(target_arch = "x86_64")]
{
if std::arch::is_x86_feature_detected!("sse") {
capabilities.push("SSE".to_string());
}
if std::arch::is_x86_feature_detected!("sse2") {
capabilities.push("SSE2".to_string());
}
if std::arch::is_x86_feature_detected!("avx") {
capabilities.push("AVX".to_string());
}
if std::arch::is_x86_feature_detected!("avx2") {
capabilities.push("AVX2".to_string());
}
}
capabilities
}
fn infer_computation_state(&self, error: &StatsError, functionname: &str) -> ComputationState {
ComputationState {
algorithm: functionname.to_string(),
iteration: None,
convergence_status: None,
current_tolerance: None,
intermediate_results: HashMap::new(),
}
}
fn generate_recovery_suggestions(
&self,
error: &StatsError,
context: &ErrorContext,
) -> Vec<RecoverySuggestion> {
let mut suggestions = Vec::new();
match error {
StatsError::InvalidArgument(msg) => {
suggestions.extend(self.generate_invalid_argument_suggestions(msg, context));
}
StatsError::DimensionMismatch(msg) => {
suggestions.extend(self.generate_dimension_mismatch_suggestions(msg, context));
}
StatsError::ComputationError(msg) => {
suggestions.extend(self.generate_computation_error_suggestions(msg, context));
}
StatsError::ConvergenceError(msg) => {
suggestions.extend(self.generate_convergence_error_suggestions(msg, context));
}
_ => {
suggestions.push(RecoverySuggestion {
suggestion_type: SuggestionType::InputValidation,
description: "Check input data and parameters".to_string(),
action: RecoveryAction::ValidateInputs {
validation_checks: vec![ValidationCheck {
name: "Data finite check".to_string(),
condition: "All values are finite (not NaN or infinite)".to_string(),
fix_suggestion: "Remove or replace NaN/infinite values".to_string(),
}],
},
expected_outcome: "Eliminate invalid input data".to_string(),
confidence: 0.7,
prerequisites: vec![],
});
}
}
suggestions
}
fn generate_invalid_argument_suggestions(
&self,
msg: &str,
_context: &ErrorContext,
) -> Vec<RecoverySuggestion> {
vec![RecoverySuggestion {
suggestion_type: SuggestionType::InputValidation,
description: "Validate input parameters before calling the function".to_string(),
action: RecoveryAction::ValidateInputs {
validation_checks: vec![ValidationCheck {
name: "Parameter bounds check".to_string(),
condition: "Parameters are within valid ranges".to_string(),
fix_suggestion: "Adjust parameters to valid ranges".to_string(),
}],
},
expected_outcome: "Function executes successfully with valid inputs".to_string(),
confidence: 0.9,
prerequisites: vec!["Input data available".to_string()],
}]
}
fn generate_dimension_mismatch_suggestions(
&self,
msg: &str,
_context: &ErrorContext,
) -> Vec<RecoverySuggestion> {
vec![RecoverySuggestion {
suggestion_type: SuggestionType::DataPreprocessing,
description: "Reshape or transpose arrays to match expected dimensions".to_string(),
action: RecoveryAction::PreprocessData {
preprocessing_steps: vec![PreprocessingStep {
name: "Array reshape".to_string(),
description: "Reshape arrays to compatible dimensions".to_string(),
code_example: "array.intoshape((new_rows, new_cols))".to_string(),
expected_impact: "Arrays will have compatible dimensions".to_string(),
}],
},
expected_outcome: "Arrays have compatible dimensions for the operation".to_string(),
confidence: 0.85,
prerequisites: vec!["Data can be reshaped without loss".to_string()],
}]
}
fn generate_computation_error_suggestions(
&self,
msg: &str,
context: &ErrorContext,
) -> Vec<RecoverySuggestion> {
let mut suggestions = Vec::new();
if msg.contains("singular") || msg.contains("invert") {
suggestions.push(RecoverySuggestion {
suggestion_type: SuggestionType::NumericalStability,
description: "Add regularization to improve numerical stability".to_string(),
action: RecoveryAction::AdjustParameter {
parameter_name: "regularization".to_string(),
current_value: "0.0".to_string(),
suggested_value: "1e-6".to_string(),
explanation: "Small regularization prevents singular matrices".to_string(),
},
expected_outcome: "Matrix inversion becomes numerically stable".to_string(),
confidence: 0.8,
prerequisites: vec!["Matrix inversion required".to_string()],
});
}
if msg.contains("memory") || msg.contains("allocation") {
suggestions.push(RecoverySuggestion {
suggestion_type: SuggestionType::MemoryOptimization,
description: "Use chunked processing to reduce memory usage".to_string(),
action: RecoveryAction::ScaleComputation {
current_approach: "Process entire dataset at once".to_string(),
suggested_approach: "Process data in smaller chunks".to_string(),
expected_improvement: "Reduced memory usage".to_string(),
},
expected_outcome: "Computation succeeds with available memory".to_string(),
confidence: 0.75,
prerequisites: vec!["Data can be processed in chunks".to_string()],
});
}
suggestions
}
fn generate_convergence_error_suggestions(
&self,
msg: &str,
_context: &ErrorContext,
) -> Vec<RecoverySuggestion> {
vec![RecoverySuggestion {
suggestion_type: SuggestionType::ParameterAdjustment,
description: "Increase maximum iterations or relax tolerance".to_string(),
action: RecoveryAction::AdjustParameter {
parameter_name: "max_iterations".to_string(),
current_value: "unknown".to_string(),
suggested_value: "increased value".to_string(),
explanation: "More iterations allow algorithm to converge".to_string(),
},
expected_outcome: "Algorithm converges within the iteration limit".to_string(),
confidence: 0.7,
prerequisites: vec!["Algorithm is potentially convergent".to_string()],
}]
}
fn generate_documentation_links(&self, error: &StatsError) -> Vec<String> {
let mut links = Vec::new();
match error {
StatsError::InvalidArgument(_) => {
links.push(
"https://docs.rs/scirs2-stats/latest/scirs2_stats/index.html#input-validation"
.to_string(),
);
}
StatsError::DimensionMismatch(_) => {
links.push(
"https://docs.rs/scirs2-stats/latest/scirs2_stats/index.html#array-operations"
.to_string(),
);
}
StatsError::ComputationError(_) => {
links.push("https://docs.rs/scirs2-stats/latest/scirs2_stats/index.html#numerical-stability".to_string());
}
_ => {
links.push(
"https://docs.rs/scirs2-stats/latest/scirs2_stats/index.html".to_string(),
);
}
}
links
}
fn generate_example_snippets(
&self,
error: &StatsError,
suggestions: &[RecoverySuggestion],
) -> Vec<CodeSnippet> {
let mut snippets = Vec::new();
if !suggestions.is_empty() {
match &suggestions[0].action {
RecoveryAction::AdjustParameter {
parameter_name,
suggested_value,
..
} => {
snippets.push(CodeSnippet {
title: format!("Adjust {} parameter", parameter_name),
code: format!(
"// Set {} to {}\nlet {} = {};\n// Then retry the operation",
parameter_name, suggested_value, parameter_name, suggested_value
),
language: "rust".to_string(),
description: "Parameter adjustment example".to_string(),
});
}
RecoveryAction::PreprocessData {
preprocessing_steps,
} => {
if !preprocessing_steps.is_empty() {
snippets.push(CodeSnippet {
title: "Data preprocessing".to_string(),
code: preprocessing_steps[0].code_example.clone(),
language: "rust".to_string(),
description: preprocessing_steps[0].description.clone(),
});
}
}
_ => {}
}
}
snippets
}
fn assess_error_severity(&self, error: &StatsError, context: &ErrorContext) -> ErrorSeverity {
match error {
StatsError::InvalidArgument(_) => ErrorSeverity::Medium,
StatsError::DimensionMismatch(_) => ErrorSeverity::Medium,
StatsError::ComputationError(_) => ErrorSeverity::High,
StatsError::ConvergenceError(_) => ErrorSeverity::Medium,
_ => ErrorSeverity::Low,
}
}
fn assess_performance_impact(
&self,
error: &StatsError,
context: &ErrorContext,
) -> PerformanceImpact {
match error {
StatsError::ComputationError(msg) if msg.contains("memory") => PerformanceImpact {
memory_impact: ImpactLevel::Major,
time_impact: ImpactLevel::Moderate,
accuracy_impact: ImpactLevel::None,
scalability_impact: ImpactLevel::Major,
},
StatsError::ConvergenceError(_) => PerformanceImpact {
memory_impact: ImpactLevel::Minor,
time_impact: ImpactLevel::Major,
accuracy_impact: ImpactLevel::Moderate,
scalability_impact: ImpactLevel::Moderate,
},
_ => PerformanceImpact {
memory_impact: ImpactLevel::None,
time_impact: ImpactLevel::Minor,
accuracy_impact: ImpactLevel::Minor,
scalability_impact: ImpactLevel::None,
},
}
}
pub fn error_history(&self) -> &[EnhancedStatsError] {
&self.error_history
}
pub fn generate_error_report(&self, enhancederror: &EnhancedStatsError) -> String {
let mut report = String::new();
report.push_str("# Error Report\n\n");
report.push_str(&format!("**Error:** {}\n\n", enhancederror.error));
report.push_str(&format!("**Severity:** {:?}\n\n", enhancederror.severity));
report.push_str(&format!(
"**Function:** {}\n",
enhancederror.context.function_name
));
report.push_str(&format!(
"**Module:** {}\n\n",
enhancederror.context.module_path
));
report.push_str("## Recovery Suggestions\n\n");
for (i, suggestion) in enhancederror.recovery_suggestions.iter().enumerate() {
report.push_str(&format!(
"{}. **{}** (Confidence: {:.0}%)\n",
i + 1,
suggestion.description,
suggestion.confidence * 100.0
));
report.push_str(&format!(" - {}\n", suggestion.expected_outcome));
}
if !enhancederror.example_snippets.is_empty() {
report.push_str("\n## Example Code\n\n");
for snippet in &enhancederror.example_snippets {
report.push_str(&format!("### {}\n\n", snippet.title));
report.push_str(&format!(
"```{}\n{}\n```\n\n",
snippet.language, snippet.code
));
}
}
if !enhancederror.documentation_links.is_empty() {
report.push_str("## Documentation\n\n");
for link in &enhancederror.documentation_links {
report.push_str(&format!("- [Documentation]({})\n", link));
}
}
report
}
}
impl fmt::Display for EnhancedStatsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.error)?;
if !self.recovery_suggestions.is_empty() {
write!(f, "\n\nSuggestions:")?;
for suggestion in &self.recovery_suggestions {
write!(f, "\n - {}", suggestion.description)?;
}
}
Ok(())
}
}
static mut GLOBAL_ERROR_RECOVERY: Option<ErrorRecoverySystem> = None;
static mut ERROR_RECOVERY_INITIALIZED: bool = false;
#[allow(dead_code)]
pub fn initialize_error_recovery(config: Option<ErrorRecoveryConfig>) {
unsafe {
if !ERROR_RECOVERY_INITIALIZED {
GLOBAL_ERROR_RECOVERY = Some(ErrorRecoverySystem::new(config.unwrap_or_default()));
ERROR_RECOVERY_INITIALIZED = true;
}
}
}
#[allow(dead_code)]
pub fn enhance_error_with_recovery(
error: StatsError,
function_name: &str,
module_path: &str,
) -> EnhancedStatsError {
unsafe {
if !ERROR_RECOVERY_INITIALIZED {
initialize_error_recovery(None);
}
if let Some(ref mut system) = GLOBAL_ERROR_RECOVERY {
system.enhance_error(error, function_name, module_path)
} else {
EnhancedStatsError {
error,
context: ErrorContext {
function_name: function_name.to_string(),
module_path: module_path.to_string(),
data_characteristics: DataCharacteristics {
size_info: None,
type_info: "unknown".to_string(),
range_info: None,
missingdata_info: None,
distribution_info: None,
},
system_info: SystemInfo {
available_memory_mb: None,
cpu_cores: Some(num_cpus::get()),
simd_capabilities: vec![],
parallel_available: true,
},
computation_state: ComputationState {
algorithm: function_name.to_string(),
iteration: None,
convergence_status: None,
current_tolerance: None,
intermediate_results: HashMap::new(),
},
},
recovery_suggestions: vec![],
documentation_links: vec![],
example_snippets: vec![],
severity: ErrorSeverity::Medium,
performance_impact: PerformanceImpact {
memory_impact: ImpactLevel::None,
time_impact: ImpactLevel::None,
accuracy_impact: ImpactLevel::None,
scalability_impact: ImpactLevel::None,
},
}
}
}
}
#[macro_export]
macro_rules! enhanced_error {
($error:expr) => {
enhance_error_with_recovery($error, function_name!(), module_path!())
};
}