Rustb 0.7.0

A package for calculating band, angle state, linear and nonlinear conductivities based on tight-binding models
//! Generic trait definitions for numeric type flexibility and hopping parameter conversions.
use crate::SpinDirection;
use crate::TbError;
use crate::model::Dimension;
use num_complex::Complex64;
use num_traits::identities::Zero;

pub trait ToFloat {
    fn to_float(self) -> f64;
}
impl ToFloat for usize {
    fn to_float(self) -> f64 {
        self as f64
    }
}

impl ToFloat for isize {
    fn to_float(self) -> f64 {
        self as f64
    }
}

impl ToFloat for f32 {
    fn to_float(self) -> f64 {
        self as f64
    }
}

impl ToFloat for f64 {
    fn to_float(self) -> f64 {
        self
    }
}

pub trait UseFloat: Copy + Clone + Zero + std::fmt::Display + PartialOrd {
    fn from<T: ToFloat>(n: T) -> Self;
}
impl UseFloat for f32 {
    fn from<T: ToFloat>(n: T) -> Self {
        n.to_float() as f32
    }
}

impl UseFloat for f64 {
    fn from<T: ToFloat>(n: T) -> Self {
        n.to_float()
    }
}

//这里的trait是为了让set_hop 可以同时满足 f64 和 Complex64 的
pub trait HopUse: Copy + Clone + Zero {
    fn to_complex(&self) -> Complex64;
}
impl HopUse for f64 {
    fn to_complex(&self) -> Complex64 {
        Complex64::new(*self, 0.0)
    }
}

impl HopUse for Complex64 {
    fn to_complex(&self) -> Complex64 {
        *self
    }
}

// Conversion from integer types to Option<SpinDirection>.
// Note: we cannot impl From<usize> for Option<SpinDirection> due to orphan rules
// (both From and Option are foreign). Use SpinDirection::from_usize() instead.
impl SpinDirection {
    /// Convert a `usize` (0=I, 1=X, 2=Y, 3=Z) to `Option<SpinDirection>`.
    /// Returns `None` for spin index 0 (identity), `Some(SpinDirection::X/Y/Z)` for 1/2/3.
    ///
    /// # Panics
    ///
    /// Panics for indices outside 0..=3. Prefer [`SpinDirection::try_from_index`]
    /// for a non-panicking conversion.
    pub fn from_index(index: usize) -> Option<SpinDirection> {
        match Self::try_from_index(index) {
            Ok(value) => value,
            Err(error) => panic!("{error}"),
        }
    }

    /// Fallible conversion from a `usize` spin index.
    ///
    /// `0` maps to `Ok(None)` (identity), `1..=3` map to
    /// `Ok(Some(SpinDirection::X/Y/Z))`, and anything else returns
    /// [`TbError::InvalidSpinValue`].
    pub fn try_from_index(index: usize) -> crate::error::Result<Option<SpinDirection>> {
        match index {
            0 => Ok(None),
            1 => Ok(Some(SpinDirection::X)),
            2 => Ok(Some(SpinDirection::Y)),
            3 => Ok(Some(SpinDirection::Z)),
            _ => Err(TbError::InvalidSpinValue {
                spin: index,
                supported: vec![0, 1, 2, 3],
            }),
        }
    }
}

impl From<Dimension> for usize {
    fn from(d: Dimension) -> Self {
        d as usize
    }
}

impl TryFrom<usize> for Dimension {
    type Error = TbError;

    fn try_from(value: usize) -> Result<Self, Self::Error> {
        match value {
            1 => Ok(Dimension::one),
            2 => Ok(Dimension::two),
            3 => Ok(Dimension::three),
            _ => Err(TbError::InvalidDimension {
                dim: value,
                supported: vec![1, 2, 3],
            }),
        }
    }
}