#![deny(rustdoc::broken_intra_doc_links)]

use crate::{
    ACos, ACosH, ASin, ASinH, ATan, ATan2, ATanH, Abs, Arg, Arithmetic, ComplexScalar,
    ComplexScalarConstructors, ComplexScalarGetParts, ComplexScalarMutateParts,
    ComplexScalarSetParts, Conjugate, Constants, Cos, CosH, Exp, FpChecks, FpScalar,
    HyperbolicFunctions, Ln, Log2, Log10, LogarithmFunctions, Max, Min, MulAddRef, NegAssign,
    NeumaierAddable, Pow, PowIntExponent, RealNative64StrictFinite,
    RealNative64StrictFiniteInDebug, RealScalar, Reciprocal, Sin, SinH, Sqrt, Tan, TanH,
    TrigonometricFunctions,
    functions::{
        ACosComplexErrors, ACosHErrors, ACosHInputErrors, ACosRealErrors, ACosRealInputErrors,
        ASinComplexErrors, ASinHErrors, ASinRealErrors, ASinRealInputErrors, ATan2Errors,
        ATan2InputErrors, ATanComplexErrors, ATanComplexInputErrors, ATanHErrors, ATanHInputErrors,
        ATanRealErrors, AbsComplexErrors, AbsRealErrors, ArgErrors, ArgInputErrors, Clamp,
        Classify, CosErrors, CosHErrors, ExpErrors, ExpM1, Hypot, Ln1p, LogarithmComplexErrors,
        LogarithmComplexInputErrors, LogarithmRealErrors, LogarithmRealInputErrors,
        PowComplexBaseRealExponentErrors, PowComplexBaseRealExponentInputErrors,
        PowIntExponentErrors, PowIntExponentInputErrors, PowRealBaseRealExponentErrors,
        PowRealBaseRealExponentInputErrors, ReciprocalErrors, ReciprocalInputErrors, Rounding,
        Sign, SinErrors, SinHErrors, SqrtComplexErrors, SqrtRealErrors, SqrtRealInputErrors,
        TanComplexErrors, TanHComplexErrors, TanHComplexInputErrors, TanHRealErrors, TanRealErrors,
        TanRealInputErrors, TotalCmp,
    },
    kernels::{NumKernel, RawComplexTrait, RawRealTrait, RawScalarTrait},
    neumaier_compensated_sum::NeumaierSum,
    scalar_kind,
    validation::{
        ErrorsTryFromf64, ValidationPolicyComplex, ValidationPolicyReal, capture_backtrace,
    },
};
use bytemuck::CheckedBitPattern;
use derive_more::with_trait::{AsRef, Debug, Display, LowerExp};
use duplicate::duplicate_item;
use num::{One, Zero};
use paste::paste;
use rand::{
    Rng,
    distr::{Distribution, StandardUniform},
};
use serde::{Deserialize, Serialize};
use std::{
    cmp::Ordering,
    iter::Sum,
    marker::PhantomData,
    num::FpCategory,
    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use try_create::{IntoInner, New, TryNew, TryNewValidated, ValidationPolicy};

// --- MACRO HELPER 1: For the binary operations like: Add, Sub, Mul, Div ---
// Generates the 4 implementations (T op T, &T op T, T op &T, &T op &T)
macro_rules! __impl_validated_arithmetic_op {
    (
        $StructName:ident, $PolicyType:ident, $trait_name:ident, $method_name:ident, $msg:literal,
        // This is an optional block of code that can be used to perform pre-checks before the operation like division by zero
        // e.g., `debug_assert!(!rhs.is_zero(), "Division by zero!");`
        {$($pre_check:tt)*}
    ) => {
        // T op T
        impl<K: NumKernel> $trait_name<$StructName<K>> for $StructName<K> {
            type Output = Self;
            #[inline(always)]
            fn $method_name(self, rhs: Self) -> Self::Output {
                let _ = $($pre_check)*(&rhs);
                Self::try_new_validated(self.value.$method_name(rhs.value)).expect($msg)
            }
        }
        // &T op T
        impl<'a, K: NumKernel> $trait_name<$StructName<K>> for &'a $StructName<K> {
            type Output = $StructName<K>;
            #[inline(always)]
            fn $method_name(self, rhs: $StructName<K>) -> Self::Output {
                let _ = $($pre_check)*(&rhs);
                $StructName::<K>::try_new_validated(self.value.clone().$method_name(rhs.value)).expect($msg)
            }
        }
        // T op &T
        impl<'a, K: NumKernel> $trait_name<&'a $StructName<K>> for $StructName<K> {
            type Output = Self;
            #[inline(always)]
            fn $method_name(self, rhs: &'a Self) -> Self::Output {
                let _ = $($pre_check)*(rhs);
                Self::try_new_validated(self.value.$method_name(&rhs.value)).expect($msg)
            }
        }
        // &T op &T
        impl<'a, K: NumKernel> $trait_name<&'a $StructName<K>> for &'a $StructName<K> {
            type Output = $StructName<K>;
            #[inline(always)]
            fn $method_name(self, rhs: &'a $StructName<K>) -> Self::Output {
                let _ = $($pre_check)*(rhs);
                $StructName::<K>::try_new_validated(self.value.clone().$method_name(&rhs.value)).expect($msg)
            }
        }
    };
}

// --- MACRO HELPER 2: For the assignment operations like: AddAssign, SubAssign, etc. ---
// Generates the 2 implementations (T op= T, T op= &T)
macro_rules! __impl_validated_arithmetic_op_assign {
    (
        $StructName:ident, $PolicyType:ident, $trait_name:ident, $method_name:ident, $msg:literal,
        {$($pre_check:tt)*}
    ) => {
        // T op= T
        impl<K: NumKernel> $trait_name<$StructName<K>> for $StructName<K> {
            #[inline(always)]
            fn $method_name(&mut self, rhs: Self) {
                let _ = $($pre_check)*(&rhs);
                self.value.$method_name(rhs.value);
                let _ = K::$PolicyType::validate_ref(&self.value).expect($msg);
            }
        }
        // T op= &T
        impl<'a, K: NumKernel> $trait_name<&'a $StructName<K>> for $StructName<K> {
            #[inline(always)]
            fn $method_name(&mut self, rhs: &'a Self) {
                let _ = $($pre_check)*(rhs);
                self.value.$method_name(&rhs.value);
                let _ = K::$PolicyType::validate_ref(&self.value).expect($msg);
            }
        }
    };
}

// --- MACRO HELPER 3: For both op and assignment op ---
macro_rules! __impl_validated_arithmetic_op_and_op_assign {
    (
        $StructName:ident, $PolicyType:ident, $trait_name:ident, $method_name:ident, $msg:literal,
        {$($pre_check:tt)*}
    ) => {
        paste! {
            // First, implement the binary operation
            __impl_validated_arithmetic_op!(
                $StructName,
                $PolicyType,
                $trait_name,
                $method_name,
                $msg,
                {$($pre_check)*}
            );
            // Then, implement the assignment operation (we use the crate "paste" to generate the correct trait and method names)
            __impl_validated_arithmetic_op_assign!(
                $StructName,
                $PolicyType,
                [<$trait_name Assign>], // attach the string "Assign" at the end of the $trait_name
                [<$method_name _assign>], // attach the string "_assign" at the end of the $method_name
                $msg,
                {$($pre_check)*}
            );
        }
    };
}

/// A macro to define a validated numeric struct (`RealValidated` or `ComplexValidated`)
/// and implement a host of standard traits for it.
///
/// This macro is the cornerstone of the validated type system. It generates:
/// 1.  The struct definition itself (e.g., `pub struct RealValidated<K>`).
/// 2.  Core trait impls: `IntoInner`, `Clone`, `PartialEq`, `Zero`, `One`, `FpChecks`.
/// 3.  Constructor impls: `TryNewValidated`, `TryNew`, `New` (with debug-only checks).
/// 4.  Arithmetic impls: `Add`, `Sub`, `Mul`, `Div` and their `*Assign` variants
///     for all four reference combinations (T op T, &T op T, etc.).
/// 5.  `Neg`, `NegAssign`, and `MulAddRef` implementations.
/// 6.  `Sum` implementation using a compensated Neumaier summation algorithm for accuracy.
macro_rules! define_validated_struct {
    (
        // The name of the struct to define (e.g., RealValidated)
        $StructName:ident,
        // The associated policy type on NumKernel (e.g., RealPolicy)
        $PolicyType:ident,
        // The type of the value inside the struct (e.g., RawReal or RawComplex)
        $RawType:ident,
        // The documentation string for the struct
        $doc:literal,
        // The string to use in the `Display` and `LowerExp` attributes
        $display_string:literal
    ) => {
        #[doc = $doc]
        #[repr(transparent)]
        #[derive(AsRef, Debug, Display, LowerExp, Serialize, Deserialize)]
        #[display($display_string, value)]
        #[lower_exp($display_string, value)]
        pub struct $StructName<K: NumKernel> {
            #[as_ref]
            pub(crate) value: K::$RawType,

            pub(crate) _phantom: PhantomData<K>,
        }

        //------------------------------------------------------------------
        // Conditional Copy implementation is defined outside the macro
        // (see the end of this file) because it requires different bounds
        // for RealValidated (K::RawReal: Copy) vs ComplexValidated (K::RawComplex: Copy).
        //------------------------------------------------------------------

        impl<K: NumKernel> IntoInner for $StructName<K> {
            type InnerType = K::$RawType;
            //type InnerType = <<K as NumKernel>::$PolicyType as ValidationPolicy>::Value;

            #[inline(always)]
            fn into_inner(self) -> Self::InnerType {
                self.value
            }
        }
        impl<K: NumKernel> Clone for $StructName<K> {
            #[inline(always)]
            fn clone(&self) -> Self {
                Self {
                    value: self.value.clone(),
                    _phantom: PhantomData,
                }
            }
        }
        impl<K: NumKernel> PartialEq for $StructName<K> {
            #[inline(always)]
            fn eq(&self, other: &Self) -> bool {
                self.value.eq(&other.value)
            }
        }
        impl<K: NumKernel> TryNewValidated for $StructName<K> {
            type Policy = K::$PolicyType;

            #[inline(always)]
            fn try_new_validated(value: Self::InnerType) -> Result<Self, Self::Error> {
                let value = Self::Policy::validate(value)?;
                Ok(Self {
                    value,
                    _phantom: PhantomData,
                })
            }
        }
        impl<K: NumKernel> TryNew for $StructName<K> {
            type Error = <<K as NumKernel>::$PolicyType as ValidationPolicy>::Error;

            #[inline(always)]
            fn try_new(value: Self::InnerType) -> Result<Self, Self::Error> {
                Self::try_new_validated(value)
            }
        }
        impl<K: NumKernel> New for $StructName<K> {
            #[inline(always)]
            fn new(value: Self::InnerType) -> Self {
                #[cfg(debug_assertions)]
                {
                    Self::try_new_validated(value)
                        .expect("Error calling try_new_validated() inside new() in debug mode")
                }
                #[cfg(not(debug_assertions))]
                {
                    Self {
                        value,
                        _phantom: PhantomData,
                    }
                }
            }
        }
        impl<K: NumKernel> Zero for $StructName<K> {
            #[inline(always)]
            fn zero() -> Self {
                Self {
                    value: <Self as IntoInner>::InnerType::raw_zero(
                        <K as NumKernel>::$PolicyType::PRECISION,
                    ),
                    _phantom: PhantomData,
                }
            }

            #[inline(always)]
            fn is_zero(&self) -> bool {
                self.value.is_zero()
            }
        }
        impl<K: NumKernel> One for $StructName<K> {
            #[inline(always)]
            fn one() -> Self {
                Self {
                    value: <Self as IntoInner>::InnerType::raw_one(
                        <K as NumKernel>::$PolicyType::PRECISION,
                    ),
                    _phantom: PhantomData,
                }
            }
        }
        impl<K: NumKernel> FpChecks for $StructName<K> {
            /// Returns `true` if `self` is neither infinite nor NaN.
            #[inline(always)]
            fn is_finite(&self) -> bool {
                self.value.is_finite()
            }

            /// Returns `true` if `self` is positive infinity or negative infinity, and `false` otherwise.
            #[inline(always)]
            fn is_infinite(&self) -> bool {
                self.value.is_infinite()
            }

            /// Returns `true` if `self` is NaN.
            #[inline(always)]
            fn is_nan(&self) -> bool {
                self.value.is_nan()
            }

            /// Returns `true` if `self` is *normal* (i.e. neither zero, infinite, subnormal, or NaN).
            #[inline(always)]
            fn is_normal(&self) -> bool {
                self.value.is_normal()
            }
        }
        impl<K: NumKernel> NeumaierAddable for $StructName<K> {
            fn neumaier_compensated_sum(value: Self, sum: &mut Self, compensation: &mut Self) {
                NeumaierAddable::neumaier_compensated_sum(
                    value.value,
                    &mut sum.value,
                    &mut compensation.value,
                );
                let _ = K::$PolicyType::validate_ref(&sum.value)
                    .expect("Neumaier compensated sum failed validation for sum");
                let _ = K::$PolicyType::validate_ref(&compensation.value)
                    .expect("Neumaier compensated sum failed validation for compensation");
            }
        }
        impl<K: NumKernel> Sum for $StructName<K> {
            fn sum<I>(iter: I) -> Self
            where
                I: Iterator<Item = Self>,
            {
                // Using Neumaier's algorithm for compensated summation.
                // This algorithm helps to reduce the numerical error in the sum of floating-point numbers.
                // It maintains a running sum and a compensation term to account for small errors.
                NeumaierSum::new_sequential(iter).sum()
            }
        }

        // --- Implementations of the core traits for arithmetic operations, delegated to the Macro Helpers ---
        __impl_validated_arithmetic_op_and_op_assign!(
            $StructName,
            $PolicyType,
            Add,
            add,
            "Addition failed validation",
            {}
        );

        __impl_validated_arithmetic_op_and_op_assign!(
            $StructName,
            $PolicyType,
            Sub,
            sub,
            "Subtraction failed validation",
            {}
        );

        __impl_validated_arithmetic_op_and_op_assign!(
            $StructName,
            $PolicyType,
            Mul,
            mul,
            "Multiplication failed validation",
            {}
        );

        __impl_validated_arithmetic_op_and_op_assign!(
            $StructName,
            $PolicyType,
            Div,
            div,
            "Division failed validation",
            {} //{debug_assert!(!rhs.is_zero(), "Division by zero!");}
        );

        // --- Implementation of Neg ---
        impl<K: NumKernel> Neg for $StructName<K> {
            type Output = Self;
            #[inline(always)]
            fn neg(self) -> Self::Output {
                // Negation of a valid number is assumed to be valid (e.g., finite -> finite)
                Self {
                    value: -self.value,
                    _phantom: PhantomData,
                }
            }
        }
        impl<K: NumKernel> NegAssign for $StructName<K> {
            /// Performs the negation of `self`.
            #[inline(always)]
            fn neg_assign(&mut self) {
                self.value.neg_assign();
            }
        }

        // --- Implementation of MulAddRef ---
        impl<K: NumKernel> MulAddRef for $StructName<K> {
            /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
            ///
            /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
            #[inline(always)]
            fn mul_add_ref(self, b: &Self, c: &Self) -> Self {
                Self::try_new_validated(self.value.unchecked_mul_add(&b.value, &c.value))
                    .expect("MulAddRef failed validation")
            }
        }
    };
}

//----------------------------------------------------------------------------------
// Now, use the macro to generate everything for the RealValidated struct
define_validated_struct!(
    RealValidated,
    RealPolicy,
    RawReal,
    "A validated real number that is guaranteed to conform to a specific [`NumKernel`].",
    "RealValidated({})"
);

impl<K: NumKernel> PartialOrd for RealValidated<K> {
    #[inline(always)]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.value.partial_cmp(&other.value)
    }
}

impl<K: NumKernel> PartialEq<f64> for RealValidated<K> {
    #[inline(always)]
    fn eq(&self, other: &f64) -> bool {
        self.value.eq(other)
    }
}

impl<K: NumKernel> PartialOrd<f64> for RealValidated<K> {
    #[inline(always)]
    fn partial_cmp(&self, other: &f64) -> Option<Ordering> {
        self.value.partial_cmp(other)
    }
}

impl<K: NumKernel> Sqrt for RealValidated<K> {
    type Error = SqrtRealErrors<<<Self as TryNewValidated>::Policy as ValidationPolicy>::Value>;

    #[inline(always)]
    fn try_sqrt(self) -> Result<Self, Self::Error> {
        let value = self.value;
        if value < 0.0 {
            Err(SqrtRealInputErrors::NegativeValue {
                value,
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new_validated(value.unchecked_sqrt())
                .map_err(|e| SqrtRealErrors::Output { source: e })
        }
    }

    #[inline(always)]
    fn sqrt(self) -> Self {
        self.try_sqrt().expect(
            "Error raised by the function Sqrt::try_sqrt() inside the function Sqrt::sqrt()",
        )
    }
}

impl<K: NumKernel> Sign for RealValidated<K> {
    /// Returns `true` if the value is negative, −0 or NaN with a negative sign.
    #[inline(always)]
    fn kernel_is_sign_negative(&self) -> bool {
        self.value.kernel_is_sign_negative()
    }

    /// Returns `true` if the value is positive, +0 or NaN with a positive sign.
    #[inline(always)]
    fn kernel_is_sign_positive(&self) -> bool {
        self.value.kernel_is_sign_positive()
    }

    /// Returns a number with the magnitude of `self` and the sign of `sign`.
    #[inline(always)]
    fn kernel_copysign(self, sign: &Self) -> Self {
        Self {
            value: self.value.kernel_copysign(&sign.value),
            _phantom: PhantomData,
        }
    }

    /// Returns the signum of the number.
    #[inline(always)]
    fn kernel_signum(self) -> Self {
        Self {
            value: self.value.kernel_signum(),
            _phantom: PhantomData,
        }
    }
}

impl<K: NumKernel> Rounding for RealValidated<K> {
    /// Returns the smallest integer greater than or equal to `self`.
    #[inline(always)]
    fn kernel_ceil(self) -> Self {
        Self::try_new_validated(self.value.kernel_ceil()).expect(
            "Error raised by RealValidated::try_new_validated() inside the function Rounding::kernel_ceil()",
        )
    }

    /// Returns the largest integer smaller than or equal to `self`.
    #[inline(always)]
    fn kernel_floor(self) -> Self {
        Self::try_new_validated(self.value.kernel_floor()).expect(
            "Error raised by RealValidated::try_new_validated() inside the function Rounding::kernel_floor()",
        )
    }

    /// Returns the fractional part of `self`.
    #[inline(always)]
    fn kernel_fract(self) -> Self {
        Self::try_new_validated(self.value.kernel_fract()).expect(
            "Error raised by RealValidated::try_new_validated() inside the function Rounding::kernel_fract()",
        )
    }

    /// Rounds `self` to the nearest integer, rounding half-way cases away from zero.
    #[inline(always)]
    fn kernel_round(self) -> Self {
        Self::try_new_validated(self.value.kernel_round()).expect(
            "Error raised by RealValidated::try_new_validated() inside the function Rounding::kernel_round()",
        )
    }

    /// Returns the nearest integer to a number. Rounds half-way cases to the number with an even least significant digit.
    ///
    /// This function always returns the precise result.
    ///
    /// # Examples
    /// ```
    /// use num_valid::{
    ///     functions::Rounding,
    ///     RealNative64StrictFinite,
    /// };
    /// use try_create::TryNew;
    ///
    /// let f = RealNative64StrictFinite::try_new(3.3).unwrap();
    /// let g = RealNative64StrictFinite::try_new(-3.3).unwrap();
    /// let h = RealNative64StrictFinite::try_new(3.5).unwrap();
    /// let i = RealNative64StrictFinite::try_new(-4.5).unwrap();
    ///
    /// assert_eq!(f.kernel_round_ties_even(), RealNative64StrictFinite::try_new(3.).unwrap());
    /// assert_eq!(g.kernel_round_ties_even(), RealNative64StrictFinite::try_new(-3.).unwrap());
    /// assert_eq!(h.kernel_round_ties_even(), RealNative64StrictFinite::try_new(4.).unwrap());
    /// assert_eq!(i.kernel_round_ties_even(), RealNative64StrictFinite::try_new(-4.).unwrap());
    /// ```
    #[inline(always)]
    fn kernel_round_ties_even(self) -> Self {
        Self::try_new_validated(self.value.kernel_round_ties_even()).expect(
            "Error raised by RealValidated::try_new_validated() inside the function Rounding::kernel_round_ties_even()",
        )
    }

    /// Returns the integer part of `self`. This means that non-integer numbers are always truncated towards zero.
    ///    
    /// # Examples
    /// ```
    /// use num_valid::{
    ///     functions::Rounding,
    ///     RealNative64StrictFinite,
    /// };
    /// use try_create::TryNew;
    ///
    /// let f = RealNative64StrictFinite::try_new(3.7).unwrap();
    /// let g = RealNative64StrictFinite::try_new(3.).unwrap();
    /// let h = RealNative64StrictFinite::try_new(-3.7).unwrap();
    ///
    /// assert_eq!(f.kernel_trunc(), RealNative64StrictFinite::try_new(3.).unwrap());
    /// assert_eq!(g.kernel_trunc(), RealNative64StrictFinite::try_new(3.).unwrap());
    /// assert_eq!(h.kernel_trunc(), RealNative64StrictFinite::try_new(-3.).unwrap());
    /// ```
    #[inline(always)]
    fn kernel_trunc(self) -> Self {
        Self::try_new_validated(self.value.kernel_trunc()).expect(
            "Error raised by RealValidated::try_new_validated() inside the function Rounding::kernel_trunc()",
        )
    }
}

impl<K: NumKernel> RealValidated<K> {
    /// Creates a new `RealValidated` instance from a raw value using the provided factory function.
    ///
    /// # Arguments
    /// * `raw_factory` - A function that takes a precision and returns a raw real value.
    /// * `err_msg` - A static error message to use if validation fails.
    ///
    /// # Returns
    /// A `RealValidated<K>` instance if the raw value is valid, otherwise it panics with the provided error message.
    #[inline(always)]
    fn from_raw_factory<F: Fn(u32) -> K::RawReal>(raw_factory: F, err_msg: &'static str) -> Self {
        // This is a (private) factory function that creates a RealValidated instance from a raw value.
        // It uses the raw_factory function to get the raw value based on the precision defined in
        // the policy, and then attempts to create a RealValidated instance with that value.
        let raw_value = raw_factory(<K::RealPolicy as ValidationPolicyReal>::PRECISION);

        Self::try_new_validated(raw_value).expect(err_msg)
    }
}

impl<K: NumKernel> Constants for RealValidated<K> {
    #[duplicate_item(
        func           raw_func;
        [pi]           [raw_pi];
        [two_pi]       [raw_two_pi];
        [pi_div_2]     [raw_pi_div_2];
        [one_div_2]    [raw_one_div_2];
        [two]          [raw_two];
        [max_finite]   [raw_max_finite];
        [min_finite]   [raw_min_finite];
        [epsilon]      [raw_epsilon];
        [negative_one] [raw_negative_one];
        [ln_2]         [raw_ln_2];
        [ln_10]        [raw_ln_10];
        [log2_e]       [raw_log2_e];
        [log10_e]      [raw_log10_e];
        [e]            [raw_e];
        [log2_10]      [raw_log2_10];
        [log10_2]      [raw_log10_2];
    )]
    #[inline(always)]
    fn func() -> Self {
        // Use `paste` to generate the error message dynamically.
        // This creates a compile-time string like:
        // "Error raised by RealValidated::try_new_validated() inside RealValidated::pi()"
        paste::paste! {
            Self::from_raw_factory(
                K::RawReal::raw_func,
                concat!("Error raised by RealValidated::try_new_validated() inside RealValidated::", stringify!([<func>]), "()"))
        }
    }
}

//----------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
// Now, use the macro to generate everything for the ComplexValidated struct
define_validated_struct!(
    ComplexValidated,
    ComplexPolicy,
    RawComplex,
    "A validated complex number that is guaranteed to conform to a specific [`NumKernel`].",
    "ComplexValidated({})"
);

impl<K: NumKernel> Conjugate for ComplexValidated<K> {
    #[inline(always)]
    fn conjugate(self) -> Self {
        Self {
            value: self.value.conjugate(),
            _phantom: PhantomData,
        }
    }
}

impl<K: NumKernel> Sqrt for ComplexValidated<K> {
    type Error = SqrtComplexErrors<<<Self as TryNewValidated>::Policy as ValidationPolicy>::Value>;

    #[inline(always)]
    fn try_sqrt(self) -> Result<Self, Self::Error> {
        Self::try_new_validated(self.value.unchecked_sqrt())
            .map_err(|e| SqrtComplexErrors::Output { source: e })
    }

    #[inline(always)]
    fn sqrt(self) -> Self {
        self.try_sqrt().expect(
            "Error raised by the function Sqrt::try_sqrt() inside the function Sqrt::sqrt()",
        )
    }
}

//----------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
impl<K: NumKernel> Arithmetic for RealValidated<K> {}
impl<K: NumKernel> Arithmetic for ComplexValidated<K> {}
//----------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
// --- MACRO HELPER: For mixed operations Complex op Real ---
macro_rules! __impl_complex_real_arithmetic {
    (
        $op_trait:ident, $op_method:ident,
        $assign_trait:ident, $assign_method:ident,
        $msg:literal,
        {$($pre_check:tt)*}
    ) => {
        // --- Implementation of mixed arithmetic operations (Complex op Real) ---
        // Complex op Real
        impl<K: NumKernel> $op_trait<RealValidated<K>> for ComplexValidated<K>
        where
            // Bound: The raw complex type must support the operation with the raw real type
            <K::ComplexPolicy as ValidationPolicy>::Value: $op_trait<<K::RealPolicy as ValidationPolicy>::Value, Output = <K::ComplexPolicy as ValidationPolicy>::Value>,
        {
            type Output = ComplexValidated<K>;
            #[inline(always)]
            fn $op_method(self, rhs: RealValidated<K>) -> Self::Output {
                let _ = $($pre_check)*(rhs);
                Self::try_new_validated(self.value.$op_method(rhs.value)).expect($msg)
            }
        }
        // Complex op &Real
        impl<'a, K: NumKernel> $op_trait<&'a RealValidated<K>> for ComplexValidated<K>
        where
             <K::ComplexPolicy as ValidationPolicy>::Value: $op_trait<&'a <K::RealPolicy as ValidationPolicy>::Value, Output = <K::ComplexPolicy as ValidationPolicy>::Value>,
        {
            type Output = ComplexValidated<K>;
            #[inline(always)]
            fn $op_method(self, rhs: &'a RealValidated<K>) -> Self::Output {
                let _ = $($pre_check)*(rhs);
                ComplexValidated::<K>::try_new_validated(self.value.$op_method(&rhs.value)).expect($msg)
            }
        }
        /*
        // &Complex op &Real
        impl<'a, K: NumKernel> $op_trait<&'a RealValidated<K>> for &'a ComplexValidated<K>
        where
             <K::ComplexPolicy as ValidationPolicy>::Value: $op_trait<&'a <K::RealPolicy as ValidationPolicy>::Value, Output = <K::ComplexPolicy as ValidationPolicy>::Value>,
        {
            type Output = ComplexValidated<K>;
            #[inline(always)]
            fn $op_method(self, rhs: &'a RealValidated<K>) -> Self::Output {
                $($pre_check)*(rhs);
                ComplexValidated::<K>::try_new_validated(self.value.clone().$op_method(rhs.as_ref())).expect($msg)
            }
        }
        */

        // --- Implementazione dell'operazione di assegnamento (es. Complex *= Real) ---
        // Complex op= Real
        impl<K: NumKernel> $assign_trait<RealValidated<K>> for ComplexValidated<K>
        where
            // Bound: Il tipo complesso grezzo deve supportare l'operazione di assegnamento con il tipo reale grezzo
            <K::ComplexPolicy as ValidationPolicy>::Value: $assign_trait<<K::RealPolicy as ValidationPolicy>::Value>,
        {
            #[inline(always)]
            fn $assign_method(&mut self, rhs: RealValidated<K>) {
                let _ = $($pre_check)*(rhs);
                self.value.$assign_method(rhs.value);
                let _ = K::ComplexPolicy::validate_ref(&self.value).expect(concat!($msg, " (assign)"));
            }
        }
        // Complex op= &Real
        impl<'a, K: NumKernel> $assign_trait<&'a RealValidated<K>> for ComplexValidated<K>
        where
            <K::ComplexPolicy as ValidationPolicy>::Value: $assign_trait<&'a <K::RealPolicy as ValidationPolicy>::Value>,
        {
            #[inline(always)]
            fn $assign_method(&mut self, rhs: &'a RealValidated<K>) {
                let _ = $($pre_check)*(rhs);
                self.value.$assign_method(&rhs.value);
                let _ = K::ComplexPolicy::validate_ref(&self.value).expect(concat!($msg, " (assign)"));
            }
        }
    };
}

// --- MACRO HELPER: For mixed operations Real op Complex ---
macro_rules! __impl_real_complex_arithmetic {
    (
        $op_trait:ident, $op_method:ident,
        $assign_trait:ident, $assign_method:ident,
        $msg:literal,
        {$($pre_check:tt)*}
    ) => {
        // --- Implementation of mixed arithmetic operations (Real op Complex) ---
        // Real op Complex
        impl<K: NumKernel> $op_trait<ComplexValidated<K>> for RealValidated<K>
        where
            // Bound: The raw real type must support the operation with the raw complex type
            <K::RealPolicy as ValidationPolicy>::Value: $op_trait<<K::ComplexPolicy as ValidationPolicy>::Value, Output = <K::ComplexPolicy as ValidationPolicy>::Value>,
        {
            type Output = ComplexValidated<K>;
            #[inline(always)]
            fn $op_method(self, rhs: ComplexValidated<K>) -> Self::Output {
                let _ = $($pre_check)*(rhs);
                Self::Output::try_new_validated(self.value.$op_method(rhs.value)).expect($msg)
            }
        }
        // &Real op Complex
        impl<'a, K: NumKernel> $op_trait<ComplexValidated<K>> for &'a RealValidated<K>
        where
            // Bound: The raw real type must support the operation with the raw complex type
            <K::RealPolicy as ValidationPolicy>::Value: $op_trait<<K::ComplexPolicy as ValidationPolicy>::Value, Output = <K::ComplexPolicy as ValidationPolicy>::Value>,
        {
            type Output = ComplexValidated<K>;
            #[inline(always)]
            fn $op_method(self, rhs: ComplexValidated<K>) -> Self::Output {
                let _ = $($pre_check)*(rhs);
                Self::Output::try_new_validated(self.value.clone().$op_method(rhs.value)).expect($msg)
            }
        }
    };
}
//----------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
// --- Implementation of mixed arithmetic operations (Complex op Real) ---
//----------------------------------------------------------------------------------
__impl_complex_real_arithmetic!(
    Add,
    add,
    AddAssign,
    add_assign,
    "Complex + Real failed validation",
    {}
);
__impl_complex_real_arithmetic!(
    Sub,
    sub,
    SubAssign,
    sub_assign,
    "Complex - Real failed validation",
    {}
);
__impl_complex_real_arithmetic!(
    Mul,
    mul,
    MulAssign,
    mul_assign,
    "Complex * Real failed validation",
    {}
);
__impl_complex_real_arithmetic!(
    Div,
    div,
    DivAssign,
    div_assign,
    "Complex / Real failed validation",
    {} //{debug_assert!(!rhs.is_zero(), "Division of complex by zero real!");}
);

//----------------------------------------------------------------------------------
// --- Implementation of mixed arithmetic operations (Real op Complex) ---
//----------------------------------------------------------------------------------
__impl_real_complex_arithmetic!(
    Mul,
    mul,
    MulAssign,
    mul_assign,
    "Real * Complex failed validation",
    {}
);
//----------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
// --- Implementation of the Abs trait ---
#[duplicate_item(
    T E;
    [RealValidated]    [AbsRealErrors<<K::RealPolicy as ValidationPolicy>::Value>];
    [ComplexValidated] [AbsComplexErrors<<K::ComplexPolicy as ValidationPolicy>::Value>];
)]
impl<K: NumKernel> Abs for T<K> {
    type Output = RealValidated<K>;
    type Error = E;

    #[inline(always)]
    fn try_abs(self) -> Result<Self::Output, Self::Error> {
        Self::Output::try_new_validated(self.value.unchecked_abs())
            .map_err(|e| Self::Error::Output { source: e })
    }

    /// Returns the *absolute value* of `self`.
    #[inline(always)]
    fn abs(self) -> Self::Output {
        self.try_abs()
            .expect("Error raised by the function Abs::try_abs() inside the function Abs::abs()")
    }
}

//----------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
// --- Implementation of the Reciprocal trait ---
#[duplicate_item(
    T;
    [RealValidated];
    [ComplexValidated];
)]
impl<K: NumKernel> Reciprocal for T<K> {
    type Error = ReciprocalErrors<<<Self as TryNewValidated>::Policy as ValidationPolicy>::Value>;

    #[inline(always)]
    fn try_reciprocal(self) -> Result<Self, Self::Error> {
        if self.value.is_zero() {
            Err(ReciprocalInputErrors::DivisionByZero {
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new_validated(self.value.unchecked_reciprocal())
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    #[inline(always)]
    fn reciprocal(self) -> Self {
        self.try_reciprocal().expect("Error raised by the function Reciprocal::try_reciprocal() inside the function Reciprocal::reciprocal()")
    }
}
//------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
//impl<K: NumKernel> FpScalar for RealValidated<K> {}
//impl<K: NumKernel> FpScalar for ComplexValidated<K> {}
//----------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
/// Macro to implement a unary operation for a type that can be validated.
/// This macro generates an implementation of a trait for a type, providing methods to try the operation
/// and to perform the operation directly, handling errors appropriately.
///
/// The macro takes the trait name, the method names for trying and performing the operation,
/// the error type, and the type itself as parameters.
/// The `try_method` returns a `Result` with the type or an error, while the `method` returns the type directly,
/// panicking if an error occurs.
/// This is useful for types that require validation before performing operations, such as `rug::Float` or `rug::Complex`.
///
/// Note: this macro does not perform any check on the validity of the domain of the operation.
/// It is the responsibility of the caller to ensure that the input is valid for the operation.
macro_rules! impl_validated_unary_op {
    ($Trait:ident, $method:ident, $Err:ident, $StructName:ty) => {
        paste! {
            impl<K: NumKernel> $Trait for $StructName<K> {
                type Error = $Err<<<Self as TryNewValidated>::Policy as ValidationPolicy>::Value>;

                #[inline(always)]
                fn [<try_ $method>](self) -> Result<Self, Self::Error> {
                    Self::try_new_validated(self.value.[<unchecked_ $method>]())
                        .map_err(|e| Self::Error::Output { source: e })
                }

                #[inline(always)]
                fn $method(self) -> Self {
                    self.[<try_ $method>]().expect(concat!(
                        "Error raised by the function ",
                        stringify!($Trait),
                        "::",
                        stringify!($try_method),
                        "()",
                        " in the function ",
                        stringify!($Trait),
                        "::",
                        stringify!($method),
                        "()"
                    ))
                }
            }
        }
    };
}

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(Exp, exp, ExpErrors, RealValidated);
impl_validated_unary_op!(Exp, exp, ExpErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(Sin, sin, SinErrors, RealValidated);
impl_validated_unary_op!(Sin, sin, SinErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(Cos, cos, CosErrors, RealValidated);
impl_validated_unary_op!(Cos, cos, CosErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(SinH, sinh, SinHErrors, RealValidated);
impl_validated_unary_op!(SinH, sinh, SinHErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(ASinH, asinh, ASinHErrors, RealValidated);
impl_validated_unary_op!(ASinH, asinh, ASinHErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(CosH, cosh, CosHErrors, RealValidated);
impl_validated_unary_op!(CosH, cosh, CosHErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(ATan, atan, ATanRealErrors, RealValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(TanH, tanh, TanHRealErrors, RealValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(ASin, asin, ASinComplexErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(ACos, acos, ACosComplexErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl_validated_unary_op!(Tan, tan, TanComplexErrors, ComplexValidated);
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl<K: NumKernel> ATan2 for RealValidated<K> {
    type Error = ATan2Errors<K::RawReal>;

    fn try_atan2(self, denominator: &Self) -> Result<Self, Self::Error> {
        let numerator = self.value;
        let denominator = &denominator.value;
        if RawScalarTrait::is_zero(&numerator) && RawScalarTrait::is_zero(denominator) {
            Err(ATan2InputErrors::ZeroOverZero {
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new_validated(numerator.unchecked_atan2(denominator))
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    fn atan2(self, denominator: &Self) -> Self {
        self.try_atan2(denominator).expect(
            "Error raised by the function ATan2::try_atan2() inside the function ATan2::atan2()",
        )
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
#[duplicate_item(
    T                  Trait  try_func   func   unchecked_func   E                   ErrIn                    value_is_a_pole;
    [RealValidated]    [Tan]  [try_tan]  [tan]  [unchecked_tan]  [TanRealErrors]     [TanRealInputErrors]     [self.value.clone().unchecked_cos().is_zero()];
    [ComplexValidated] [ATan] [try_atan] [atan] [unchecked_atan] [ATanComplexErrors] [ATanComplexInputErrors] [*self.value.raw_real_part() == 0. && (*self.value.raw_imag_part() == 1. || *self.value.raw_imag_part() == -1.)]
)]
impl<K: NumKernel> Trait for T<K> {
    type Error = E<<<Self as TryNewValidated>::Policy as ValidationPolicy>::Value>;

    #[inline(always)]
    fn try_func(self) -> Result<Self, Self::Error> {
        if value_is_a_pole {
            Err(ErrIn::ArgumentIsPole {
                value: self.value,
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new_validated(self.value.unchecked_func())
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    #[inline(always)]
    fn func(self) -> Self {
        self.try_func().unwrap()
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
#[duplicate_item(
    T                  Trait   try_func    func    unchecked_func    E                   ErrIn                    value_is_not_in_domain;
    [RealValidated]    [ACosH] [try_acosh] [acosh] [unchecked_acosh] [ACosHErrors]       [ACosHInputErrors]       [self.value < 1.];
    [ComplexValidated] [ACosH] [try_acosh] [acosh] [unchecked_acosh] [ACosHErrors]       [ACosHInputErrors]       [self.value.raw_imag_part() == &0. && self.value.raw_real_part() < &1.];
    [RealValidated]    [ATanH] [try_atanh] [atanh] [unchecked_atanh] [ATanHErrors]       [ATanHInputErrors]       [self.value <= -1. || self.value >= 1.];
    [ComplexValidated] [ATanH] [try_atanh] [atanh] [unchecked_atanh] [ATanHErrors]       [ATanHInputErrors]       [self.value.raw_imag_part() == &0. && (self.value.raw_real_part() <= &-1. || self.value.raw_real_part() >= &1.)];
    [ComplexValidated] [TanH]  [try_tanh]  [tanh]  [unchecked_tanh]  [TanHComplexErrors] [TanHComplexInputErrors] [RawScalarTrait::is_zero(&self.value.clone().unchecked_cosh())];
    [RealValidated]    [ASin]  [try_asin]  [asin]  [unchecked_asin]  [ASinRealErrors]    [ASinRealInputErrors]    [self.value < -1.0 || self.value > 1.0];
    [RealValidated]    [ACos]  [try_acos]  [acos]  [unchecked_acos]  [ACosRealErrors]    [ACosRealInputErrors]    [self.value < -1.0 || self.value > 1.0];
)]
impl<K: NumKernel> Trait for T<K> {
    type Error = E<<<Self as TryNewValidated>::Policy as ValidationPolicy>::Value>;

    #[inline(always)]
    fn try_func(self) -> Result<Self, Self::Error> {
        if value_is_not_in_domain {
            Err(ErrIn::OutOfDomain {
                value: self.value,
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new_validated(self.value.unchecked_func())
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    #[inline(always)]
    fn func(self) -> Self {
        self.try_func().unwrap()
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
/// Implement the [`ComplexScalarConstructors`] trait for the [`ComplexValidated`] type.
impl<K: NumKernel> ComplexScalarConstructors for ComplexValidated<K> {
    type RawComplex = K::RawComplex;

    fn try_new_complex(
        real_part: K::RawReal,
        imag_part: K::RawReal,
    ) -> Result<Self, <Self::RawComplex as RawScalarTrait>::ValidationErrors> {
        let complex = K::RawComplex::new_unchecked_raw_complex(real_part, imag_part);
        Self::try_new_validated(complex)
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
/// Implement the [`ComplexScalarGetParts`] trait for the [`ComplexValidated`] type.
impl<K: NumKernel> ComplexScalarGetParts for ComplexValidated<K> {
    /// Get the real part of the complex number.
    #[inline(always)]
    fn real_part(&self) -> RealValidated<K> {
        RealValidated {
            value: self.value.raw_real_part().clone(),
            _phantom: PhantomData,
        }
    }

    /// Get the imaginary part of the complex number.
    #[inline(always)]
    fn imag_part(&self) -> RealValidated<K> {
        RealValidated {
            value: self.value.raw_imag_part().clone(),
            _phantom: PhantomData,
        }
    }

    #[inline(always)]
    fn raw_real_part(&self) -> &K::RawReal {
        self.value.raw_real_part()
    }

    #[inline(always)]
    fn raw_imag_part(&self) -> &K::RawReal {
        self.value.raw_imag_part()
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
/// Implement the [`ComplexScalarSetParts`] trait for the [`ComplexValidated`] type.
impl<K: NumKernel> ComplexScalarSetParts for ComplexValidated<K> {
    /// Set the value of the real part.
    #[inline(always)]
    fn set_real_part(&mut self, real_part: RealValidated<K>) {
        *self.value.mut_raw_real_part() = real_part.value;
    }

    /// Set the value of the imaginary part.
    #[inline(always)]
    fn set_imaginary_part(&mut self, imag_part: RealValidated<K>) {
        *self.value.mut_raw_imag_part() = imag_part.value;
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
/// Implement the [`ComplexScalarMutateParts`] trait for the [`ComplexValidated`] type.
impl<K: NumKernel> ComplexScalarMutateParts for ComplexValidated<K> {
    /// Add the value of the the real coefficient `c` to real part of `self`.
    #[inline(always)]
    fn add_to_real_part(&mut self, c: &RealValidated<K>) {
        let real_part = self.value.mut_raw_real_part();
        *real_part += &c.value;
        K::RealPolicy::validate_ref(real_part)
            .expect("Error raised by validate_ref() inside ComplexValidated::add_to_real_part()");
    }

    /// Add the value of the the real coefficient `c` to imaginary part of `self`.
    #[inline(always)]
    fn add_to_imaginary_part(&mut self, c: &RealValidated<K>) {
        let imag_part = self.value.mut_raw_imag_part();
        *imag_part += &c.value;
        K::RealPolicy::validate_ref(imag_part).expect(
            "Error raised by validate_ref() inside ComplexValidated::add_to_imaginary_part()",
        );
    }

    /// Multiply the value of the real part by the real coefficient `c`.
    #[inline(always)]
    fn multiply_real_part(&mut self, c: &RealValidated<K>) {
        let real_part = self.value.mut_raw_real_part();
        *real_part *= &c.value;
        K::RealPolicy::validate_ref(real_part)
            .expect("Error raised by validate_ref() inside ComplexValidated::multiply_real_part()");
    }

    /// Multiply the value of the imaginary part by the real coefficient `c`.
    #[inline(always)]
    fn multiply_imaginary_part(&mut self, c: &RealValidated<K>) {
        let imag_part = self.value.mut_raw_imag_part();
        *imag_part *= &c.value;
        K::RealPolicy::validate_ref(imag_part).expect(
            "Error raised by validate_ref() inside ComplexValidated::multiply_imaginary_part()",
        );
    }
}

//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl<K: NumKernel> Arg for ComplexValidated<K> {
    type Output = RealValidated<K>;
    type Error = ArgErrors<K::RawComplex>;

    #[inline(always)]
    fn try_arg(self) -> Result<Self::Output, Self::Error> {
        if RawScalarTrait::is_zero(&self.value) {
            Err(ArgInputErrors::Zero {
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::Output::try_new_validated(self.value.unchecked_arg())
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    #[inline(always)]
    fn arg(self) -> RealValidated<K> {
        self.try_arg()
            .expect("Error calling ComplexValidated::try_arg() inside ComplexValidated::arg()")
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
#[duplicate_item(
    trait_name try_func    func    unchecked_func;
    [Ln]       [try_ln]    [ln]    [unchecked_ln];
    [Log10]    [try_log10] [log10] [unchecked_log10];
    [Log2]     [try_log2]  [log2]  [unchecked_log2];
)]
impl<K: NumKernel> trait_name for RealValidated<K> {
    type Error =
        LogarithmRealErrors<<<Self as TryNewValidated>::Policy as ValidationPolicy>::Value>;

    #[inline(always)]
    fn try_func(self) -> Result<Self, Self::Error> {
        if self.value < 0.0 {
            Err(LogarithmRealInputErrors::NegativeArgument {
                value: self.value,
                backtrace: capture_backtrace(),
            }
            .into())
        } else if self.value == 0. {
            Err(LogarithmRealInputErrors::ZeroArgument {
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new_validated(self.value.unchecked_func())
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    #[inline(always)]
    fn func(self) -> Self {
        self.try_func().unwrap()
    }
}

#[duplicate_item(
    trait_name try_func    func    unchecked_func;
    [Ln]       [try_ln]    [ln]    [unchecked_ln];
    [Log10]    [try_log10] [log10] [unchecked_log10];
    [Log2]     [try_log2]  [log2]  [unchecked_log2];
)]
impl<K: NumKernel> trait_name for ComplexValidated<K> {
    type Error =
        LogarithmComplexErrors<<<Self as TryNewValidated>::Policy as ValidationPolicy>::Value>;

    #[inline(always)]
    fn try_func(self) -> Result<Self, Self::Error> {
        if RawScalarTrait::is_zero(&self.value) {
            Err(LogarithmComplexInputErrors::ZeroArgument {
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new_validated(self.value.unchecked_func())
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    #[inline(always)]
    fn func(self) -> Self {
        self.try_func().unwrap()
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl<K: NumKernel> Pow<&RealValidated<K>> for RealValidated<K> {
    type Error = PowRealBaseRealExponentErrors<K::RawReal>;

    #[inline(always)]
    fn try_pow(self, exponent: &Self) -> Result<Self, Self::Error> {
        if self.value < 0.0 {
            Err(PowRealBaseRealExponentInputErrors::NegativeBase {
                base: self.value,
                exponent: exponent.value.clone(),
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new(self.value.unchecked_pow_exponent_real(&exponent.value))
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    /// Raises th number `self` to the power `exponent`.
    #[inline(always)]
    fn pow(self, exponent: &Self) -> Self {
        self.try_pow(exponent)
            .expect("Error raised by the function Pow::try_pow() in the function Pow::pow()!")
    }
}

impl<K: NumKernel> Pow<&RealValidated<K>> for ComplexValidated<K> {
    type Error = PowComplexBaseRealExponentErrors<K::RawComplex>;

    #[inline(always)]
    fn try_pow(self, exponent: &RealValidated<K>) -> Result<Self, Self::Error> {
        if self.is_zero() {
            if *exponent < 0.0 {
                Err(
                    PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent {
                        exponent: exponent.value.clone(),
                        backtrace: capture_backtrace(),
                    }
                    .into(),
                )
            } else if *exponent == 0.0 {
                Ok(Self::one())
            } else {
                Ok(Self::zero())
            }
        } else {
            Self::try_new_validated(self.value.unchecked_pow_exponent_real(&exponent.value))
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    /// Raises th number `self` to the power `exponent`.
    #[inline(always)]
    fn pow(self, exponent: &RealValidated<K>) -> Self {
        self.try_pow(exponent)
            .expect("Error raised by the function Pow::try_pow() in the function Pow::pow()!")
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
#[duplicate_item(
    T exponent_type unchecked_func;
    duplicate!{
        [struct_name; [RealValidated]; [ComplexValidated]]
        [struct_name] [i8]    [unchecked_pow_exponent_i8];
        [struct_name] [i16]   [unchecked_pow_exponent_i16];
        [struct_name] [i32]   [unchecked_pow_exponent_i32];
        [struct_name] [i64]   [unchecked_pow_exponent_i64];
        [struct_name] [i128]  [unchecked_pow_exponent_i128];
        [struct_name] [isize] [unchecked_pow_exponent_isize];
    }
)]
impl<K: NumKernel> Pow<exponent_type> for T<K> {
    type Error = PowIntExponentErrors<
        <<Self as TryNewValidated>::Policy as ValidationPolicy>::Value,
        exponent_type,
    >;

    fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
        if RawScalarTrait::is_zero(&self.value) && exponent < 0 {
            Err(PowIntExponentInputErrors::ZeroBaseNegativeExponent {
                exponent,
                backtrace: capture_backtrace(),
            }
            .into())
        } else {
            Self::try_new_validated(self.value.unchecked_func(&exponent))
                .map_err(|e| Self::Error::Output { source: e })
        }
    }

    /// Raises th number `self` to the power `exponent`.
    #[inline(always)]
    fn pow(self, exponent: exponent_type) -> Self {
        self.try_pow(exponent)
            .expect("Error raised by the function Pow::try_pow() in the function Pow::pow()!")
    }
}

#[duplicate_item(
    T exponent_type unchecked_func;
    duplicate!{
        [struct_name; [RealValidated]; [ComplexValidated]]
        [struct_name] [u8]    [unchecked_pow_exponent_u8];
        [struct_name] [u16]   [unchecked_pow_exponent_u16];
        [struct_name] [u32]   [unchecked_pow_exponent_u32];
        [struct_name] [u64]   [unchecked_pow_exponent_u64];
        [struct_name] [u128]  [unchecked_pow_exponent_u128];
        [struct_name] [usize] [unchecked_pow_exponent_usize];
    }
)]
impl<K: NumKernel> Pow<exponent_type> for T<K> {
    type Error = PowIntExponentErrors<
        <<Self as TryNewValidated>::Policy as ValidationPolicy>::Value,
        exponent_type,
    >;

    fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
        Self::try_new_validated(self.value.unchecked_func(&exponent))
            .map_err(|e| Self::Error::Output { source: e })
    }

    /// Raises th number `self` to the power `exponent`.
    #[inline(always)]
    fn pow(self, exponent: exponent_type) -> Self {
        self.try_pow(exponent)
            .expect("Error raised by the function Pow::try_pow() in the function Pow::pow()!")
    }
}

impl<K: NumKernel> PowIntExponent for RealValidated<K> {
    type RawType = K::RawReal;
}

impl<K: NumKernel> PowIntExponent for ComplexValidated<K> {
    type RawType = K::RawComplex;
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl<K: NumKernel> Max for RealValidated<K> {}
impl<K: NumKernel> Min for RealValidated<K> {}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl<K: NumKernel> Clamp for RealValidated<K> {
    /// Clamps the value within the specified bounds.
    #[inline(always)]
    fn clamp(self, min: &Self, max: &Self) -> Self {
        Self::try_new_validated(self.value.raw_clamp(&min.value, &max.value)).expect(
            "Error raised by RealValidated::try_new_validated() inside RealValidated::clamp()",
        )
    }
}

impl<K: NumKernel> Classify for RealValidated<K> {
    /// Returns the floating point category of the number. If only one property is going to be tested,
    /// it is generally faster to use the specific predicate instead.
    /// ```
    /// use num_valid::{
    ///     functions::Classify,
    ///     kernels::native64_validated::RealNative64StrictFinite,
    /// };
    /// use std::num::FpCategory;
    /// use try_create::TryNew;
    ///
    /// let num = RealNative64StrictFinite::try_new(12.4).unwrap();
    ///
    /// assert_eq!(num.classify(), FpCategory::Normal);
    /// ```
    #[inline(always)]
    fn classify(&self) -> FpCategory {
        self.value.raw_classify()
    }
}

impl<K: NumKernel> ExpM1 for RealValidated<K> {
    /// Returns `e^(self) - 1`` in a way that is accurate even if the number is close to zero.
    #[inline(always)]
    fn exp_m1(self) -> Self {
        Self::try_new_validated(self.value.unchecked_exp_m1()).expect(
            "Error raised by RealValidated::try_new_validated() inside RealValidated::exp_m1()",
        )
    }
}

impl<K: NumKernel> Ln1p for RealValidated<K> {
    /// Returns `ln(1. + self)` (natural logarithm) more accurately than if the operations were performed separately.
    #[inline(always)]
    fn ln_1p(self) -> Self {
        Self::try_new_validated(self.value.unchecked_ln_1p()).expect(
            "Error raised by RealValidated::try_new_validated() inside RealValidated::ln_1p()",
        )
    }
}

impl<K: NumKernel> Hypot for RealValidated<K> {
    /// Compute the distance between the origin and a point (`self`, `other`) on the Euclidean plane.
    /// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `self.abs()` and `other.abs()`.
    #[inline(always)]
    fn hypot(self, other: &Self) -> Self {
        Self::try_new_validated(self.value.unchecked_hypot(&other.value)).expect(
            "Error raised by RealValidated::try_new_validated() inside RealValidated::hypot()",
        )
    }
}

impl<K: NumKernel> TotalCmp for RealValidated<K> {
    #[inline(always)]
    fn total_cmp(&self, other: &Self) -> Ordering {
        self.value.raw_total_cmp(&other.value)
    }
}

impl<K: NumKernel> RealScalar for RealValidated<K> {
    type RawReal = K::RawReal;

    /// Multiplies two products and adds them in one fused operation, rounding to the nearest with only one rounding error.
    /// `a.kernel_mul_add_mul_mut(&b, &c, &d)` produces a result like `&a * &b + &c * &d`, but stores the result in `a` using its precision.
    #[inline(always)]
    fn kernel_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
        self.value
            .unchecked_mul_add_mul_mut(&mul.value, &add_mul1.value, &add_mul2.value);
    }

    /// Multiplies two products and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
    /// `a.kernel_mul_sub_mul_mut(&b, &c, &d)` produces a result like `&a * &b - &c * &d`, but stores the result in `a` using its precision.
    #[inline(always)]
    fn kernel_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
        self.value
            .unchecked_mul_sub_mul_mut(&mul.value, &sub_mul1.value, &sub_mul2.value);
    }

    /// Try to build a [`RealValidated`] instance from a [`f64`].
    /// The returned value is `Ok` if the input `value` is valid w.r.t. the [`ValidationPolicy`] `V`,
    /// otherwise the returned value is `ErrorsTryFromf64`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_valid::{RealNative64StrictFinite, RealScalar};
    ///
    /// // Valid value
    /// let x = RealNative64StrictFinite::try_from_f64(3.14).unwrap();
    /// assert_eq!(x.as_ref(), &3.14);
    ///
    /// // Invalid value (NaN)
    /// assert!(RealNative64StrictFinite::try_from_f64(f64::NAN).is_err());
    /// ```
    #[inline(always)]
    fn try_from_f64(value: f64) -> Result<Self, ErrorsTryFromf64<K::RawReal>> {
        let v_as_raw_real = K::RawReal::try_new_raw_real_from_f64::<K::RealPolicy>(value)?;
        Ok(Self {
            value: v_as_raw_real,
            _phantom: PhantomData,
        })
    }

    /// Build a [`RealValidated`] instance from a [`f64`].
    ///
    /// This is a convenience method that panics if the value is invalid.
    /// Use [`try_from_f64`](Self::try_from_f64) for error handling without panics.
    ///
    /// # Panics
    ///
    /// Panics if the input value fails validation (e.g., NaN, infinity, or subnormal for strict policies).
    ///
    /// # Examples
    ///
    /// ```
    /// use num_valid::{RealNative64StrictFinite, RealScalar};
    ///
    /// // Valid constant - no need for unwrap()
    /// let pi = RealNative64StrictFinite::from_f64(std::f64::consts::PI);
    /// assert_eq!(pi.as_ref(), &std::f64::consts::PI);
    ///
    /// let e = RealNative64StrictFinite::from_f64(std::f64::consts::E);
    /// assert_eq!(e.as_ref(), &std::f64::consts::E);
    /// ```
    ///
    /// ```should_panic
    /// use num_valid::{RealNative64StrictFinite, RealScalar};
    ///
    /// // This will panic because NaN is invalid
    /// let invalid = RealNative64StrictFinite::from_f64(f64::NAN);
    /// ```
    #[inline(always)]
    fn from_f64(value: f64) -> Self {
        Self::try_from_f64(value).expect(
            "RealScalar::from_f64() failed: invalid f64 value (NaN, infinity, or subnormal)",
        )
    }
}
//------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
#[duplicate_item(
    trait_name T;
    duplicate!{[
        trait_name_nested; [TrigonometricFunctions]; [HyperbolicFunctions]; [LogarithmFunctions];
        ]
        [trait_name_nested] [RealValidated<K>];
        [trait_name_nested] [ComplexValidated<K>];
    }
)]
impl<K: NumKernel> trait_name for T {}
//----------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl<K: NumKernel> FpScalar for RealValidated<K> {
    type Kind = scalar_kind::Real;
    type RealType = RealValidated<K>;

    /// Returns a reference to the underlying raw real value.
    fn as_raw_ref(&self) -> &Self::InnerType {
        &self.value
    }
}

impl<K: NumKernel> FpScalar for ComplexValidated<K> {
    type Kind = scalar_kind::Complex;
    type RealType = RealValidated<K>;

    /// Returns a reference to the underlying raw complex value.
    fn as_raw_ref(&self) -> &Self::InnerType {
        &self.value
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
impl<K: NumKernel> ComplexScalar for ComplexValidated<K> {
    fn into_parts(self) -> (Self::RealType, Self::RealType) {
        let real_part = self.value.raw_real_part().clone();
        let imag_part = self.value.raw_imag_part().clone();
        (RealValidated::new(real_part), RealValidated::new(imag_part))
    }
}
//------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
/// Implement the [`Distribution`] trait for [`RealValidated`] type
/// using the `StandardUniform` distribution.
impl<K: NumKernel> Distribution<RealValidated<K>> for StandardUniform {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> RealValidated<K> {
        RealValidated::try_from_f64(rng.random::<f64>())
            .expect("Error raised by RealValidated::try_from_f64() inside Distribution::sample()")
    }
}

/// Implement the [`Distribution`] trait for [`ComplexValidated`] type
/// using the `StandardUniform` distribution.
impl<K: NumKernel> Distribution<ComplexValidated<K>> for StandardUniform {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> ComplexValidated<K> {
        let real_part = rng.random::<RealValidated<K>>();
        let imag_part = rng.random::<RealValidated<K>>();
        ComplexValidated::<K>::new_complex(real_part, imag_part)
    }
}
//----------------------------------------------------------------------------------

//----------------------------------------------------------------------------------
// Conditional Copy implementations for validated types.
//
// These implementations are only available when the underlying raw type
// (`K::RawReal` for real, `K::RawComplex` for complex) implements `Copy`.
// This enables zero-cost pass-by-value semantics for types like
// `RealNative64StrictFinite` (backed by `f64`) and `ComplexNative64StrictFinite`
// (backed by `Complex<f64>`) while correctly requiring `Clone` for non-`Copy`
// types like `rug::Float` and `rug::Complex`.
//
// # Example
//
// ```rust
// use num_valid::RealNative64StrictFinite;
// use try_create::TryNew;
//
// let x = RealNative64StrictFinite::try_new(3.14).unwrap();
// let y = x; // Copy, not move!
// let z = x; // x is still valid because it was copied
// assert_eq!(x, y);
// assert_eq!(x, z);
// ```
impl<K: NumKernel> Copy for RealValidated<K> where K::RawReal: Copy {}
impl<K: NumKernel> Copy for ComplexValidated<K> where K::RawComplex: Copy {}
//----------------------------------------------------------------------------------

#[duplicate_item(
    T;
    [RealNative64StrictFinite];
    [RealNative64StrictFiniteInDebug];
)]
unsafe impl CheckedBitPattern for T {
    type Bits = u64;

    fn is_valid_bit_pattern(bits: &Self::Bits) -> bool {
        let value = f64::from_bits(*bits);
        <Self as TryNewValidated>::Policy::validate_ref(&value).is_ok()
    }
}

#[duplicate_item(
    T;
    [RealNative64StrictFinite];
    [RealNative64StrictFiniteInDebug];
)]
unsafe impl bytemuck::NoUninit for T {}
//----------------------------------------------------------------------------------
