//! # Numerical Multi-valued Functions in Complex Analysis
//!
//! This module provides numerical methods for handling multi-valued functions
//! in complex analysis, particularly focusing on finding roots of complex functions
//! using Newton's method.
use crate::numerical::complex_analysis::eval_complex_expr;
use crate::symbolic::core::Expr;
use num_complex::Complex;
use std::collections::HashMap;
/// Finds a root of a complex function `f(z) = 0` using Newton's method.
///
/// Newton's method is an iterative root-finding algorithm. For complex functions,
/// it uses the formula `z_{n+1} = z_n - f(z_n) / f'(z_n)`.
///
/// # Arguments
/// * `f` - The complex function as a symbolic expression.
/// * `f_prime` - The derivative of the function, `f'`.
/// * `start_point` - An initial guess for the root in the complex plane.
/// * `tolerance` - The desired precision of the root.
/// * `max_iter` - The maximum number of iterations.
///
/// # Returns
/// An `Option` containing the complex root if found, otherwise `None`.
pub fn newton_method_complex(
    f: &Expr,
    f_prime: &Expr,
    start_point: Complex<f64>,
    tolerance: f64,
    max_iter: usize,
) -> Option<Complex<f64>> {
    let mut z = start_point;
    let mut vars = HashMap::new();
    for _ in 0..max_iter {
        vars.insert("z".to_string(), z);
        let f_val = match eval_complex_expr(f, &vars) {
            Ok(val) => val,
            Err(_) => return None,
        };
        let f_prime_val = match eval_complex_expr(f_prime, &vars) {
            Ok(val) => val,
            Err(_) => return None,
        };
        if f_prime_val.norm_sqr() < 1e-12 {
            return None;
        }
        let delta = f_val / f_prime_val;
        z -= delta;
        if delta.norm() < tolerance {
            return Some(z);
        }
    }
    None
}
