【unitrix】 4.18 类型级二进制数加法实现解析(add.rs)

一、源码

这段代码实现了一个类型级别的二进制数加法系统,包括基本加法、带进位加法以及与其他数值类型的混合运算。

rust 复制代码
//! Type-level binary number addition implementation
//!
//! 本模块提供类型级别的二进制数加法运算,包括:
//! This module provides type-level binary number addition operations, including:
//! - 基本加法 (Basic addition)
//! - 带进位加法 (Addition with carry)
//! - 结果标准化处理 (Result standardization)
//! - 含类型级整数、小数与Var桥接的基本类型混合加法 (Mixed addition with typed integers, fixed-point and Var)

use core::ops::Add;
use crate::number::{
    Z0, P1, N1, B0, B1, FixedPoint, Float, Var,
    NonZero, Primitive, TypedInt, Unsigned, 
    Add1, Sub1, IfB0, IfB1, Shl1, Shr1
};

// ==================== Addition With Carry ====================

/// 带进位加法运算 (a + b + 1)
/// Addition with carry operation (a + b + 1)
/// 分Z0、P1、N1、B0、B1分别考虑。其中Z0在小数中使用
pub trait AddWithCarry<Rhs> {
    type Output;
}

// ----- Z0 + All -----
// Z0 + I + 1=I + 1
impl<I: TypedInt + Add1> AddWithCarry<I> for Z0 {
    type Output = I::Output;
}

// ----- P1 + All -----
// P1 + Z0 + 1 = 2
impl AddWithCarry<Z0> for P1 {
    type Output = B0<P1>;
}

// P1 + P1 + 1 = 3
impl AddWithCarry<P1> for P1 {
    type Output = B1<P1>;
}

// P1 + N1 + 1 = 1
impl AddWithCarry<N1> for P1 {
    type Output = P1;
}

// P1 + B0<H> +1 =B0<H+1>
impl<H: NonZero + Add1<Output: IfB0>> AddWithCarry<B0<H>> for P1 {
    type Output = <H::Output as IfB0>::Output;
}

// P1 + B1<H> +1 =B1<H+1>
impl<H: NonZero + Add1<Output: IfB1>> AddWithCarry<B1<H>> for P1 {
    type Output = <H::Output as IfB1>::Output;
}

// ----- N1 + All -----
// N1 + I + 1 = I
impl<I: TypedInt> AddWithCarry<I> for N1 {
    type Output = I;
}

// ----- B0 + All -----
// B0<H> + Z0 + 1 =B1<H>
impl<H: NonZero + IfB1> AddWithCarry<Z0> for B0<H> {
    type Output = <H as IfB1>::Output;
}

// B0<H> + P1 + 1 =B0<H+1>
impl<H: NonZero + Add1<Output: IfB0>> AddWithCarry<P1> for B0<H> {
    type Output = <H::Output as IfB0>::Output;
}

// B0<H> + N1 + 1 =B0<H>
impl<H: NonZero> AddWithCarry<N1> for B0<H> {
    type Output = Self;
}

// B0<H1> + B0<H2> + 1= B1<H1+H2>
impl<H1: NonZero + Add<H2, Output: IfB1>, H2: NonZero> AddWithCarry<B0<H2>> for B0<H1> {
    type Output = <H1::Output as IfB1>::Output;
}

// B0<H1> + B1<H2> + 1= B0<H1+H2+1>
impl<H1: NonZero + AddWithCarry<H2, Output: IfB0>, H2: NonZero> AddWithCarry<B1<H2>> for B0<H1> {
    type Output = <H1::Output as IfB0>::Output;
}

// ----- B1 + All -----
// B1<H> + Z0 + 1 = B0<H+1>
impl<H: NonZero + Add1<Output: IfB0>> AddWithCarry<Z0> for B1<H> {
    type Output = <H::Output as IfB0>::Output;
}

// B1<H> + P1 + 1 = B1<H+1>
impl<H: NonZero + Add1<Output: IfB1>> AddWithCarry<P1> for B1<H> {
    type Output = <H::Output as IfB1>::Output;
}

// B1<H> + N1 + 1 = B1<H>
impl<H: NonZero + Add1> AddWithCarry<N1> for B1<H> {
    type Output = Self;
}

// B1<H1> + B0<H2> + 1 = B0<H1+H2+1>
impl<H1: NonZero + AddWithCarry<H2, Output: IfB0>, H2: NonZero> AddWithCarry<B0<H2>> for B1<H1> {
    type Output = <H1::Output as IfB0>::Output;
}

// B1<H1> + B1<H2> + 1 = B1<H1+H2+1>
impl<H1: NonZero + AddWithCarry<H2, Output: IfB1>, H2: NonZero> AddWithCarry<B1<H2>> for B1<H1> {
    type Output = <H1::Output as IfB1>::Output;
}

// ==================== Operator Overloading ====================

// ----- Z0 + All -----
// Z0 + I = I
impl<I: TypedInt> Add<I> for Z0 {
    type Output = I;
    #[inline(always)]
    fn add(self, rhs: I) -> Self::Output { rhs }
}

// Z0 + FixedPoint = FixedPoint
impl<I: TypedInt, F: Unsigned> Add<FixedPoint<I, F>> for Z0 {
    type Output = FixedPoint<I, F>;
    #[inline(always)]
    fn add(self, rhs: FixedPoint<I, F>) -> Self::Output { rhs }
}

// Z0 + Float = Float
impl<S, E> Add<Float<S, E>> for Z0 {
    type Output = Float<S, E>;
    #[inline(always)]
    fn add(self, rhs: Float<S, E>) -> Self::Output { rhs }
}

// Z0 + Var<T> =  Var<T>
impl<T: Primitive> Add<Var<T>> for Z0 {
    type Output = Var<T>;
    #[inline(always)]
    fn add(self, rhs: Var<T>) -> Self::Output { rhs }
}

// ----- P1 + All -----
// P1 + I = I + 1
impl<I: TypedInt + Add1> Add<I> for P1 {
    type Output = I::Output;
    #[inline(always)]
    fn add(self, _: I) -> Self::Output { Default::default() }
}

// P1 + FixedPoint
impl<I: TypedInt + Add1, F: Unsigned> Add<FixedPoint<I, F>> for P1 {
    type Output = FixedPoint<<I as Add1>::Output, F>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I, F>) -> Self::Output { Default::default() }
}

// P1 + Var<T>
impl<T: Primitive> Add<Var<T>> for P1
where 
    Var<T>: Add + From<Self>,
{
    type Output = <Var<T> as Add>::Output;
    #[inline(always)]
    fn add(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(Self) + rhs }
}

// ----- N1 + All -----
// N1 + I = I + 1
impl<I: TypedInt + Sub1> Add<I> for N1 {
    type Output = I::Output;
    #[inline(always)]
    fn add(self, _: I) -> Self::Output { Default::default() }
}

// N1 + FixedPoint = FixedPoint - 1
impl<I: TypedInt + Sub1, F: Unsigned> Add<FixedPoint<I, F>> for N1{
    type Output = FixedPoint<<I as Sub1>::Output, F>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I, F>) -> Self::Output { Default::default() }
}

// N1 + Var<T>
impl<T: Primitive> Add<Var<T>> for N1
where 
    Var<T>: Add + From<Self>,
{
    type Output = <Var<T> as Add>::Output;
    #[inline(always)]
    fn add(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(self) + rhs }
}

// ----- B0 + All -----
// B0<H> + Z0 = B0<H>
impl<H: NonZero> Add<Z0> for B0<H> {
    type Output = Self;
    #[inline(always)]
    fn add(self, _: Z0) -> Self::Output { self }
}

// B0<H> + P1 = B0<H> + 1
impl<H: NonZero> Add<P1> for B0<H>
where 
    B0<H>: Add1,
{
    type Output = <B0<H> as Add1>::Output;
    #[inline(always)]
    fn add(self, _: P1) -> Self::Output { Default::default() }
}

// B0<H> + N1 = B0<H> - 1
impl<H: NonZero> Add<N1> for B0<H>
where
    B0<H>: Sub1,
{
    type Output = <B0<H> as Sub1>::Output;
    #[inline(always)]
    fn add(self, _: N1) -> Self::Output { Default::default() }
}

// B0<H1> + B0<H2> = B0<H1+H2>
impl<H1: NonZero + Add<H2, Output: IfB0>, H2: NonZero> Add<B0<H2>> for B0<H1> {
    type Output = <H1::Output as IfB0>::Output;
    #[inline(always)]
    fn add(self, _: B0<H2>) -> Self::Output { Default::default() }
}

// B0<H1> + B1<H2> = B1<H1+H2>
impl<H1: NonZero + Add<H2, Output: IfB1>, H2: NonZero> Add<B1<H2>> for B0<H1> {
    type Output = <H1::Output as IfB1>::Output;
    #[inline(always)]
    fn add(self, _: B1<H2>) -> Self::Output { Default::default() }
}

// B0<H> + FixedPoint<I, F> = FixedPoint<I + B0<H>, F>
impl<H: NonZero, I: TypedInt + Add<Self>, F: Unsigned> Add<FixedPoint<I, F>> for B0<H>{
    type Output = FixedPoint<<I as Add<Self>>::Output, F>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I, F>) -> Self::Output { Default::default() }
}

// B0<H> + Var<T>
impl< H: NonZero, T: Primitive> Add<Var<T>> for B0<H>
where 
    Var<T>: Add + From<Self>,
{
    type Output = <Var<T> as Add>::Output;
    #[inline(always)]
    fn add(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(self) + rhs }
}

// ----- B1 + All -----
// B1<H> + Z0 = B1<H>
impl<H: NonZero> Add<Z0> for B1<H> {
    type Output = Self;
    #[inline(always)]
    fn add(self, _: Z0) -> Self::Output { self }
}

// B1<H> + P1 = B1<H> + 1
impl<H: NonZero> Add<P1> for B1<H>
where
    B1<H>: Add1,
{
    type Output = <B1<H> as Add1>::Output;
    #[inline(always)]
    fn add(self, _: P1) -> Self::Output { Default::default() }
}

// B1<H> + N1 = B1<H> - 1
impl<H: NonZero> Add<N1> for B1<H>
where 
    B1<H>: Sub1,
{
    type Output = <B1<H> as Sub1>::Output;
    #[inline(always)]
    fn add(self, _: N1) -> Self::Output { Default::default() }
}

// B1<H1> + B0<H2> = B1<H1+H2>
impl<H1: NonZero + Add<H2, Output: IfB1>, H2: NonZero> Add<B0<H2>> for B1<H1> {
    type Output = <H1::Output as IfB1>::Output;
    #[inline(always)]
    fn add(self, _: B0<H2>) -> Self::Output { Default::default() }
}

// B1<H1> + B1<H2> = B0<H1+H2+1>
impl<H1: NonZero + AddWithCarry<H2, Output: IfB0>, H2: NonZero> Add<B1<H2>> for B1<H1> {
    type Output = <H1::Output as IfB0>::Output;
    #[inline(always)]
    fn add(self, _: B1<H2>) -> Self::Output { Default::default() }
}

// B1<H> + FixedPoint<I, F> = FixedPoint<I + B1<H>, F>
impl< H: NonZero, I: TypedInt + Add<Self>, F: Unsigned> Add<FixedPoint<I, F>> for B1<H>{
    type Output = FixedPoint<<I as Add<Self>>::Output, F>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I, F>) -> Self::Output { Default::default() }
}

// B1<H> + Var<T>
impl<T: Primitive, H: NonZero> Add<Var<T>> for B1<H>
where 
    Var<T>: Add + From<Self>,
{
    type Output = <Var<T> as Add>::Output;
    #[inline(always)]
    fn add(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(self) + rhs }
}

// ----- FixedPoint + All -----
// FixedPoint<I, F> + I2 = FixedPoint<I + I2, F>
impl<I: TypedInt + Add<I2>, F: Unsigned, I2: TypedInt> Add<I2> for FixedPoint<I, F>{
    type Output = FixedPoint<<I as Add<I2>>::Output, F>;
    #[inline(always)]
    fn add(self, _: I2) -> Self::Output { Default::default() }
}

// FixedPoint<I1, F1> + FixedPoint<I2, F2>,F1为Z0、P1、B0、B1时分别计算
// F1=Z0时...
impl<I1: TypedInt + Add<I2>,I2: TypedInt, F2: Unsigned> Add<FixedPoint<I2, F2>> for FixedPoint<I1, Z0>{
    type Output = FixedPoint<<I1 as Add<I2>>::Output, F2>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, F2>) -> Self::Output { Default::default() }
}

// F1=P1时...
// F2=Z0
impl<I1: TypedInt + Add<I2>,I2: TypedInt> Add<FixedPoint<I2, Z0>> for FixedPoint<I1, P1>{
    type Output = FixedPoint<I1::Output, P1>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, Z0>) -> Self::Output { Default::default() }
}
// F2=P1
impl<I1: TypedInt + AddWithCarry<I2>,I2: TypedInt> Add<FixedPoint<I2, P1>> for FixedPoint<I1, P1>{
    type Output = FixedPoint<I1::Output, Z0>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, P1>) -> Self::Output { Default::default() }
}
// F2=B0<L>
impl<I1: TypedInt + Add<I2>,I2: TypedInt, L: Unsigned + NonZero> Add<FixedPoint<I2, B0<L>>> for FixedPoint<I1, P1>{
    type Output = FixedPoint<I1::Output, B1<L>>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, B0<L>>) -> Self::Output { Default::default() }
}

// F2=B1<L>
impl<I1: TypedInt + AddWithCarry<I2>,I2: TypedInt, L: Unsigned + NonZero> Add<FixedPoint<I2, B1<L>>> for FixedPoint<I1, P1>{
    type Output = FixedPoint<I1::Output, B0<L>>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, B1<L>>) -> Self::Output { Default::default() }
}

// F1=B0<L>时...
// F2=Z0
impl<I1: TypedInt + Add<I2>,I2: TypedInt, L: Unsigned + NonZero> Add<FixedPoint<I2, Z0>> for FixedPoint<I1, B0<L>>{
    type Output = FixedPoint<I1::Output, B0<L>>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, Z0>) -> Self::Output { Default::default() }
}
// F2=P1
impl<I1: TypedInt + Add<I2>,I2: TypedInt, L: Unsigned + NonZero> Add<FixedPoint<I2, P1>> for FixedPoint<I1, B0<L>>{
    type Output = FixedPoint<I1::Output, B1<L>>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, P1>) -> Self::Output { Default::default() }
}
// F2=B0<L>
impl<I1: TypedInt + IfB0, I2: TypedInt + IfB0, L1: Unsigned + NonZero, L2: Unsigned + NonZero> Add<FixedPoint<I2, B0<L2>>> for FixedPoint<I1, B0<L1>>
where
    FixedPoint<I1::Output, L1>: Add<FixedPoint<I2::Output, L2>>,
    <FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output: Shr1,
    <<FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output as Shr1>::Output: Default,
{
    type Output = <<FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output as Shr1>::Output;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, B0<L2>>) -> Self::Output { Default::default() }
}

// F2=B1<L>
impl<I1: TypedInt + IfB0, I2: TypedInt + IfB1, L1: Unsigned + NonZero, L2: Unsigned + NonZero> Add<FixedPoint<I2, B1<L2>>> for FixedPoint<I1, B0<L1>>
where
    FixedPoint<I1::Output, L1>: Add<FixedPoint<I2::Output, L2>>,
    <FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output: Shr1,
    <<FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output as Shr1>::Output: Default,
{
    type Output = <<FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output as Shr1>::Output;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, B1<L2>>) -> Self::Output { Default::default() }
}

// F1=B1<L>时...
// F2=Z0
impl<I1: TypedInt + Add<I2>, I2: TypedInt, L: Unsigned + NonZero> Add<FixedPoint<I2, Z0>> for FixedPoint<I1, B1<L>>{
    type Output = FixedPoint<I1::Output, B1<L>>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, Z0>) -> Self::Output { Default::default() }
}
// F2=P1
impl<I1: TypedInt + AddWithCarry<I2>, I2: TypedInt, L: Unsigned + NonZero> Add<FixedPoint<I2, P1>> for FixedPoint<I1, B1<L>>{
    type Output = FixedPoint<I1::Output, B0<L>>;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, P1>) -> Self::Output { Default::default() }
}
// F2=B0<L>
impl<I1: TypedInt + IfB1, I2: TypedInt + IfB0, L1: Unsigned + NonZero, L2: Unsigned + NonZero> Add<FixedPoint<I2, B0<L2>>> for FixedPoint<I1, B1<L1>>
where
    FixedPoint<I1::Output, L1>: Add<FixedPoint<I2::Output, L2>>,
    <FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output: Shr1,
    <<FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output as Shr1>::Output: Default,
{
    type Output = <<FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output as Shr1>::Output;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, B0<L2>>) -> Self::Output { Default::default() }
}

// F2=B1<L>
impl<I1: TypedInt + IfB1, I2: TypedInt + IfB1, L1: Unsigned + NonZero, L2: Unsigned + NonZero> Add<FixedPoint<I2, B1<L2>>> for FixedPoint<I1, B1<L1>>
where
    FixedPoint<I1::Output, L1>:  Add<FixedPoint<I2::Output, L2>>,
    <FixedPoint<I1::Output, L1> as  Add<FixedPoint<I2::Output, L2>>>::Output: Shr1,
    <<FixedPoint<I1::Output, L1> as  Add<FixedPoint<I2::Output, L2>>>::Output as Shr1>::Output: Default,
{
    type Output = <<FixedPoint<I1::Output, L1> as Add<FixedPoint<I2::Output, L2>>>::Output as Shr1>::Output;
    #[inline(always)]
    fn add(self, _: FixedPoint<I2, B1<L2>>) -> Self::Output { Default::default() }
}

// ----- Var<T> Operations -----
impl<T: Primitive, I: TypedInt> Add<I> for Var<T>
where 
    Var<T>: From<I> + Add,
{
    type Output = <Var<T> as Add>::Output;
    fn add(self, rhs: I) -> Self::Output { self + Var::<T>::from(rhs)}
}
//?????
impl<T: Primitive> Add for Var<T> {
    type Output = Self;
    #[inline(always)]
    fn add(self, rhs: Self) -> Self::Output { Var(self.0 + rhs.0) }
}

#[cfg(test)]
mod tests {
    use crate::number::*;

    #[test]
    fn test_z0_addition() {
        assert_eq!(Z0 + Z0, Z0);
        assert_eq!(Z0 + P1, P1);
        assert_eq!(Z0 + N1, N1);
        assert_eq!(Z0 + B0::<P1>::default(), B0::<P1>::default());
        assert_eq!(Z0 + B1::<P1>::default(), B1::<P1>::default());
    }

    #[test]
    fn test_p1_addition() {
        assert_eq!(P1 + Z0, P1);
        assert_eq!(P1 + P1, B0::<P1>::default());
        assert_eq!(P1 + N1, Z0);
        assert_eq!(P1 + B0::<P1>::default(), B1::<P1>::default());
        assert_eq!(P1 + B1::<P1>::default(), B0::<B0::<P1>>::default());
    }

    #[test]
    fn test_n1_addition() {
        assert_eq!(N1 + Z0, N1);
        assert_eq!(N1 + P1, Z0);
        assert_eq!(N1 + N1, B0::<N1>::default());
        assert_eq!(N1 + B0::<P1>::default(), P1);
        assert_eq!(N1 + B1::<P1>::default(), B0::<P1>::default());
    }

    #[test]
    fn test_b0_addition() {
        let b0_p1 = B0::<P1>::default();
        let b1_p1 = B1::<P1>::default();
        
        assert_eq!(b0_p1 + Z0, b0_p1);
        assert_eq!(b0_p1 + P1, B1::<P1>::default());
        assert_eq!(b0_p1 + N1, P1);
        assert_eq!(b0_p1 + b0_p1, B0::<B0::<P1>>::default());
        assert_eq!(b0_p1 + b1_p1, B1::<B0::<P1>>::default());
    }

    #[test]
    fn test_b1_addition() {
        let b1_p1 = B1::<P1>::default();
        let b0_p1 = B0::<P1>::default();
        
        assert_eq!(b1_p1 + Z0, b1_p1);
        assert_eq!(b1_p1 + P1, B0::<B0::<P1>>::default());
        assert_eq!(b1_p1 + N1, B0::<P1>::default());
        assert_eq!(b1_p1 + b0_p1, B1::<B0::<P1>>::default());
        assert_eq!(b1_p1 + b1_p1, B0::<B1::<P1>>::default());
    }

    #[test]
    fn test_fixed_point_addition() {
        let fp = FixedPoint::<P1, P1>::default();
        
        assert_eq!(Z0 + fp, fp);
        assert_eq!(P1 + fp, FixedPoint::<B0::<P1>, P1>::default());
        assert_eq!(N1 + fp, FixedPoint::<Z0, P1>::default());
    }

    #[test]
    fn test_var_addition() {
        let var1 = Var::<i32>::from(1);
        let var2 = Var::<i32>::from(2);
        
        assert_eq!(Z0 + var1.clone(), var1);
        assert_eq!(P1 + var1.clone(), Var::from(2));
        assert_eq!(N1 + var1.clone(), Var::from(0));
        assert_eq!(var1 + var2, Var::from(3));
    }

    #[test]
    fn test_add_with_carry() {
        assert_eq!(<P1 as AddWithCarry<P1>>::Output::default(), B1::<P1>::default());
        assert_eq!(<P1 as AddWithCarry<N1>>::Output::default(), P1::default());
        assert_eq!(<B0::<P1> as AddWithCarry<B1::<P1>>>::Output::default(), B0::<B1::<P1>>::default());
        assert_eq!(<B1::<P1> as AddWithCarry<B0::<P1>>>::Output::default(), B0::<B1::<P1>>::default());
    }

        #[test]
    fn test_nested_binary_addition() {
        let b0_b1_p1 = B0::<B1::<P1>>::default();
        let b1_b0_p1 = B1::<B0::<P1>>::default();
        
        assert_eq!(b0_b1_p1 + b0_b1_p1, B0::<B0::<B1::<P1>>>::default());
        assert_eq!(b1_b0_p1 + b1_b0_p1, B0::<B1::<B0::<P1>>>::default());
        assert_eq!(b0_b1_p1 + b1_b0_p1, B1::<B1::<B0::<P1>>>::default());
    }

    #[test]
    fn test_deeply_nested_addition() {
        let b0_b0_b1_p1 = B0::<B0::<B1::<P1>>>::default();
        let b1_b1_b0_p1 = B1::<B1::<B0::<P1>>>::default();
        
        assert_eq!(b0_b0_b1_p1 + b1_b1_b0_p1, B1::<B1<B1<B0<P1>>>>::default());
    }

    #[test]
    fn test_fixed_point_precision_combinations() {
        // Different fractional precisions
        let fp1 = FixedPoint::<P1, B0::<P1>>::default();
        let fp2 = FixedPoint::<P1, B1::<P1>>::default();
        
        assert_eq!(fp1 + fp2, FixedPoint::<B1::<P1>, Z0>::default());
        
        // Larger integer parts
        let fp3 = FixedPoint::<B0::<B1::<P1>>, P1>::default();
        let fp4 = FixedPoint::<B1::<B0::<P1>>, P1>::default();
        assert_eq!(fp3 + fp4, FixedPoint::<B0<B0<B1<P1>>>, Z0>::default());
    }

    #[test]
    fn test_var_mixed_operations() {
        // Test with different primitive types
        let var_i32 = Var::<i32>::from(5);
        let var_f64 = Var::<f64>::from(3.5);
        
        assert_eq!(var_i32 + P1, Var::<i32>::from(6));
        assert_eq!(var_f64 + N1, Var::<f64>::from(2.5));
        
        // Test with larger values
        let big_var = Var::<i64>::from(i64::MAX - 1);
        assert_eq!(big_var + P1, Var::<i64>::from(i64::MAX));
    }

    #[test]
    fn test_edge_cases() {
        // Maximum nested binary number
        type MaxNested = B1::<B1::<B1::<B1::<P1>>>>;
        let max_val = MaxNested::default();
        assert_eq!(max_val + Z0, max_val);
        
        // Minimum value tests
        let min_fp = FixedPoint::<N1, Z0>::default();
        assert_eq!(min_fp + P1, FixedPoint::<Z0, Z0>::default());
    }

    #[test]
    fn test_add_with_carry_edge_cases() {
        // Test carry propagation
        assert_eq!(
            <B1::<B1::<P1>> as AddWithCarry<B1::<B1::<P1>>>>::Output::default(),
            B1::<B1::<B1::<P1>>>::default()
        );
        
        // Test with maximum values
        type MaxCarry = B1::<B1::<B1::<P1>>>;
        assert_eq!(
            <MaxCarry as AddWithCarry<MaxCarry>>::Output::default(),
            B1::<B1::<B1::<B1::<P1>>>>::default()
        );
    }

    #[test]
    fn test_fixed_point_overflow() {
        // Test behavior when integer part would overflow
        let max_fp = FixedPoint::<B1::<B1::<P1>>, Z0>::default();
        let one = FixedPoint::<P1, Z0>::default();
        assert_eq!(max_fp + one, FixedPoint::<B0::<B0::<B0::<P1>>>, Z0>::default());
    }
}

二、核心概念

  1. 类型表示
  • Z0: 表示零

  • P1: 表示+1

  • N1: 表示-1

  • B0: 表示二进制数0后跟更高位H

  • B1: 表示二进制数1后跟更高位H

  1. 主要特性
  • AddWithCarry: 带进位加法特征(a + b + 1)

  • Add: 标准加法特征(a + b)

三、带进位加法实现

AddWithCarry trait 定义了所有可能的带进位加法组合:

  1. Z0 + 任何类型:
  • 结果等于另一个数加1 (I + 1)
  1. P1 + 各种类型:
  • P1 + Z0 + 1 = 2 (表示为B0)

  • P1 + P1 + 1 = 3 (表示为B1)

  • P1 + N1 + 1 = 1 (P1)

  • 与B0/B1的组合会产生进位传播

  1. N1 + 任何类型:
  • 结果等于另一个数本身(因为-1 + 0 +1 = 0)
  1. B0/B1 + 各种类型:
  • 处理二进制数的进位传播

  • 根据输入类型的不同产生不同的输出类型

四、标准加法实现

标准加法通过Rust的Add trait实现,覆盖了所有类型组合:

  1. 基本类型加法:
  • Z0 + I = I (零加任何数等于该数)

  • P1 + I = I + 1

  • N1 + I = I - 1

  1. 二进制数加法:
  • B0 + B0 = B0<H1+H2>

  • B0 + B1 = B1<H1+H2>

  • B1 + B1 = B0<H1+H2+1> (产生进位)

  1. 定点数加法:
  • 处理整数部分和小数部分的不同组合

  • 根据小数部分的类型(P1/Z0/B0/B1)进行不同的计算

  1. 变量类型(Var)加法:
  • 支持与各种类型相加

  • 最终转换为运行时计算

五、定点数加法细节

定点数加法(FixedPoint<I, F>)是最复杂的部分,需要同时处理:

  1. 整数部分(I)的加法

  2. 小数部分(F)的加法

  3. 不同小数精度的处理:

  • Z0: 无小数

  • P1: 0.5

  • B0: 0.xxx形式

  • B1: 0.1xxx形式

对于不同小数精度的组合,代码中实现了专门的加法规则,确保结果正确。

六、测试用例

测试覆盖了:

  • 基本类型加法

  • 二进制数加法(包括嵌套情况)

  • 定点数加法

  • 变量类型加法

  • 边界情况(最大值、最小值)

  • 进位传播

七、设计亮点

  1. 类型安全: 所有运算在编译期确定,无运行时开销

  2. 扩展性: 可以轻松添加新的数值类型

  3. 组合性: 支持不同类型之间的混合运算

  4. 精确控制: 特别是定点数运算可以精确控制小数精度

这个实现展示了Rust类型系统的强大能力,通过类型级编程实现了复杂的数值运算系统。

相关推荐
KENYCHEN奉孝7 小时前
Rust征服字节跳动:高并发服务器实战
服务器·开发语言·rust
明天好,会的14 小时前
跨平台ZeroMQ:在Rust中使用zmq库的完整指南
开发语言·后端·rust
寻月隐君19 小时前
Rust 网络编程实战:用 Tokio 手写一个迷你 TCP 反向代理 (minginx)
后端·rust·github
芳草萋萋鹦鹉洲哦1 天前
【vue3+tauri+rust】如何实现下载文件mac+windows
windows·macos·rust
寻月隐君1 天前
Rust 异步编程实践:从 Tokio 基础到阻塞任务处理模式
后端·rust·github
萧曵 丶2 天前
Rust 中的返回类型
开发语言·后端·rust
浪裡遊2 天前
Sass详解:功能特性、常用方法与最佳实践
开发语言·前端·javascript·css·vue.js·rust·sass
受之以蒙2 天前
Rust & WASM 之 wasm-bindgen 基础:让 Rust 与 JavaScript 无缝对话
前端·笔记·rust
Elixin2 天前
第一章:环境搭建
rust