【unitrix】 4.19 类型级二进制数减法实现解析(sub.rs)

一、源码

这段代码实现了一个类型级别的数值系统,支持多种数字类型(整数、定点数、变量)之间的减法运算。它使用了 Rust 的类型系统特性(traits 和关联类型)在编译期完成数值计算。



//小数、浮点数与Var 的混合计算未实现

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

// ==================== 带借位减法 Trait ====================
/// 带借位减法运算
/// Subtraction with borrow operation
///
/// 表示 a - b - 1 的运算 (相当于 a - (b + 1))
/// Represents the operation of a - b - 1 (equivalent to a - (b + 1))
/// 说明:有借位表示有低位数,本位 NonZero
pub trait SubWithBorrow<Rhs> {
    type Output;
}

// ==================== 带借位减法实现 ====================

// ========== 带借位P1 - NonZero ==========
 // P1 - I - 1 = -I
impl<I:NonZero + Neg> SubWithBorrow<I> for P1 {
    type Output = I::Output;
}

// ========== 带借位N1 - NonZero ==========
// N1 - I - 1 = !I-1 (即N1+(!I+1)-1)
impl<I: NonZero + Not<Output: Sub1>> SubWithBorrow<I> for N1{
    type Output = <I::Output as Sub1>::Output;
}

// ========== 带借位B0 - NonZero ==========
// B0 - P1 -1=B0
impl<H: NonZero + Sub1<Output: IfB0>> SubWithBorrow<P1> for B0<H>{
    type Output = <H::Output as IfB0>::Output;
}

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

// B0

- B0

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

- B1

-1 = B0 impl<H1: NonZero + SubWithBorrow<H2, Output: IfB0>, H2: NonZero> SubWithBorrow<B1<H2>> for B0<H1>{ type Output = <H1::Output as IfB0>::Output; } // ========== 带借位B1 - NonZero ========== // B1 - P1 - 1 = B1 impl<H: NonZero + Sub1<Output: IfB1>> SubWithBorrow<P1> for B1<H>{ type Output = <H::Output as IfB1>::Output; } // B1 - N1 -1 = B1 impl<H: NonZero> SubWithBorrow<N1> for B1<H> { type Output = Self; } // B1

- B0

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

- B1

- 1 = B1 impl<H1: NonZero + SubWithBorrow<H2, Output: IfB1>, H2: NonZero> SubWithBorrow<B1<H2>> for B1<H1>{ type Output = <H1::Output as IfB1>::Output; } // ==================== 标准减法实现 (Sub trait) ==================== // ==================== Z0 - All ==================== // Z0 - I = -I impl<I: TypedInt + Neg> Sub<I> for Z0 { type Output = I::Output; #[inline(always)] fn sub(self, i: I) -> Self::Output { -i } } // Z0 - FixedPoint impl<I: TypedInt, F: Unsigned> Sub<FixedPoint<I, F>> for Z0 where FixedPoint<I, F>: Neg, { type Output = <FixedPoint<I, F> as Neg>::Output; #[inline(always)] fn sub(self, rhs: FixedPoint<I, F>) -> Self::Output { -rhs } } // Z0 - Var impl<T: Primitive + Neg> Sub<Var<T>> for Z0 { type Output = Var<T>; #[inline(always)] fn sub(self, rhs: Var<T>) -> Self::Output { -rhs } } // ========== P1 - All ========== // P1 - I = -(I-1) impl<I: TypedInt + Sub1<Output: Neg<Output: Default>>> Sub<I> for P1{ type Output = <I::Output as Neg>::Output; #[inline(always)] fn sub(self, _: I) -> Self::Output { Default::default() } } // P1 - FixedPoint impl<I: TypedInt, F: Unsigned> Sub<FixedPoint<I, F>> for P1 where P1: Sub<I>, { type Output = FixedPoint< <P1 as Sub<I>>::Output, F>; #[inline(always)] fn sub(self, _: FixedPoint<I, F>) -> Self::Output { Default::default() } } // P1 - Var impl<T: Primitive> Sub<Var<T>> for P1 where Var<T>: From<P1>, { type Output = Var<T>; #[inline(always)] fn sub(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(self) - rhs } } // ========== N1 - All ========== // N1 - I = N1 + (!I + 1)= !I impl<I: TypedInt + Not<Output: Default>> Sub<I> for N1{ type Output = I::Output; #[inline(always)] fn sub(self, _: I) -> Self::Output { Default::default() } } // N1 - FixedPoint=(-FixedPoint) - 1 impl<I: TypedInt, F: Unsigned> Sub<FixedPoint<I, F>> for N1 where FixedPoint<I, F>: Neg<Output: Sub1>, { type Output = < <FixedPoint<I, F> as Neg>::Output as Sub1 >::Output; #[inline(always)] fn sub(self, _: FixedPoint<I, F>) -> Self::Output { Default::default() } } // N1 - Var impl<T: Primitive> Sub<Var<T>> for N1 where Var<T>: From<N1> + Sub, { type Output = <Var<T> as Sub>::Output; #[inline(always)] fn sub(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(self) - rhs } } // ========== B0 - All ========== // B0 - Z0 impl<H: NonZero> Sub<Z0> for B0<H> { type Output = Self; #[inline(always)] fn sub(self, _: Z0) -> Self::Output { self } } // B0 - P1=B0 -1 impl<H: NonZero> Sub<P1> for B0<H> where B0<H>:Sub1, { type Output = <B0<H> as Sub1>::Output; #[inline(always)] fn sub(self, _: P1) -> Self::Output { Default::default() } } // B0 - N1 =B0 + 1 impl<H: NonZero> Sub<N1> for B0<H> where B0<H>:Add1, { type Output = <B0<H> as Add1>::Output; #[inline(always)] fn sub(self, _: N1) -> Self::Output { Default::default() } } // B0

- B0

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

- B1

= B1 impl<H1: NonZero + SubWithBorrow<H2, Output: IfB1>, H2: NonZero> Sub<B1<H2>> for B0<H1>{ type Output = <H1::Output as IfB1>::Output; #[inline(always)] fn sub(self, _: B1<H2>) -> Self::Output { Default::default() } } // B0 - FixedPoint= B0 + (- FixedPoint) impl<H: NonZero, I: TypedInt, F: Unsigned> Sub<FixedPoint<I, F>> for B0<H> where FixedPoint<I, F>: Neg, Self: Sub< <FixedPoint<I, F> as Neg>::Output, Output: Default >, { type Output = < Self as Sub< <FixedPoint<I, F> as Neg>::Output> >::Output; #[inline(always)] fn sub(self, _: FixedPoint<I, F>) -> Self::Output { Default::default() } } // B0 - Var impl<T: Primitive, H: NonZero> Sub<Var<T>> for B0<H> where Var<T>: From<B0<H>>, { type Output = <Var<T> as Sub>::Output; #[inline(always)] fn sub(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(self) - rhs } } // ========== B1 - All ========== // B1-Z0 impl<H: NonZero> Sub<Z0> for B1<H> { type Output = Self; #[inline(always)] fn sub(self, _: Z0) -> Self::Output { self } } // B1 - P1 = B1 - 1 impl<H: NonZero> Sub<P1> for B1<H> where B1<H>: Sub1, { type Output = <B1<H> as Sub1>::Output; #[inline(always)] fn sub(self, _: P1) -> Self::Output { Default::default() } } // B1 - N1 = B1 + 1 impl<H: NonZero + Add1> Sub<N1> for B1<H> where B1<H>: Add1, { type Output = <B1<H> as Add1>::Output; #[inline(always)] fn sub(self, _: N1) -> Self::Output { Default::default() } } // B1

- B0

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

- B1

= B0 impl<H1: NonZero + Sub<H2,Output: IfB0>, H2: NonZero> Sub<B1<H2>> for B1<H1>{ type Output = <H1::Output as IfB0>::Output; #[inline(always)] fn sub(self, _: B1<H2>) -> Self::Output { Default::default() } } // B1 - FixedPoint = B1 + (-FixedPoint) impl<H: NonZero, I: TypedInt, F: Unsigned> Sub<FixedPoint<I, F>> for B1<H> where FixedPoint<I, F>: Neg, Self: Sub< <FixedPoint<I, F> as Neg>::Output, Output: Default >, { type Output = <Self as Sub< <FixedPoint<I, F> as Neg>::Output > >::Output; #[inline(always)] fn sub(self, _: FixedPoint<I, F>) -> Self::Output { Default::default() } } // B1 - Var impl<T: Primitive, H: NonZero> Sub<Var<T>> for B1<H> where Var<T>: From<B1<H>>, { type Output = <Var<T> as Sub>::Output; #[inline(always)] fn sub(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(self) - rhs } } // ==================== FixedPoint - All ==================== // FixedPoint -I2 impl<I: TypedInt + Sub<I2>, F: Unsigned, I2: TypedInt> Sub<I2> for FixedPoint<I, F>{ type Output = FixedPoint< <I as Sub<I2>>::Output, F>; #[inline(always)] fn sub(self, _: I2) -> Self::Output { Default::default() } } // FixedPoint - FixedPoint=FixedPoint + (-FixedPoint) impl<I1: TypedInt, F1: Unsigned, I2: TypedInt, F2: Unsigned> Sub<FixedPoint<I2, F2>> for FixedPoint<I1, F1> where FixedPoint<I2, F2>: Neg, Self: Add<<FixedPoint<I2, F2> as Neg>::Output> { type Output = < Self as Add<<FixedPoint<I2, F2> as Neg>::Output> >::Output; #[inline(always)] fn sub(self, rhs: FixedPoint<I2, F2>) -> Self::Output { self + (-rhs) } } // FixedPoint -Var impl<T: Primitive, I: TypedInt, F: Unsigned> Sub<Var<T>> for FixedPoint<I, F> where Var<T>: Sub + From<Self>, { type Output = <Var<T> as Sub>::Output; #[inline(always)] fn sub(self, rhs: Var<T>) -> Self::Output { Var::<T>::from(self) - rhs } } // ==================== Var - All ==================== // Var - I impl<T: Primitive, I: TypedInt> Sub<I> for Var<T> where Var<T>: From<I> + Sub, { type Output = <Var<T> as Sub>::Output; #[inline(always)] fn sub(self, rhs: I) -> Self::Output { self - Var::<T>::from(rhs) } } // Var - FixedPoint,需要完善 FixedPoint => Var impl<T: Primitive, I: TypedInt, F: Unsigned> Sub<FixedPoint<I, F>> for Var<T> where Self: From<FixedPoint<I, F>>, { type Output = <Self as Sub>::Output; #[inline(always)] fn sub(self, rhs: FixedPoint<I, F>) -> Self::Output { self - Var::<T>::from(rhs) } } /// 实现 Var 与 Var 的减法运算 /// 用法: V - V impl<T: Primitive> Sub for Var<T> { type Output = Self; fn sub(self, b: Self) -> Self::Output { Var(self.0 - b.0) // 内部值相减后包装为新 Var } } #[cfg(test)] mod tests { use crate::number::*; // ==================== 标准减法测试 ==================== #[test] fn test_z0_sub() { // Z0 - I assert_eq!(Z0 - P1, N1); assert_eq!(Z0 - N1, P1); assert_eq!(Z0 - B0::<P1>::default(), B0::<N1>::default()); // Z0 - FixedPoint assert_eq!( Z0 - FixedPoint::<P1, B0<B0<P1>>>::default(), FixedPoint::< B0<N1>, B1<B1<P1>> >::default() ); // Z0 - Var let var = Var(5i32); assert_eq!(Z0 - var, Var(-5i32)); } #[test] fn test_p1_sub() { // P1 - I assert_eq!(P1 - P1, Z0); assert_eq!(P1 - N1, B0::<P1>::default()); assert_eq!(P1 - B0::<P1>::default(), N1); // P1 - FixedPoint assert_eq!( P1 - FixedPoint::<P1, B0<B0<B0<P1>>>>::default(), FixedPoint::<Z0, B0<B0<B0<P1>>>>::default() ); // P1 - Var let var = Var(2i32); assert_eq!(P1 - var, Var(-1i32)); } #[test] fn test_n1_sub() { // N1 - I assert_eq!(N1 - P1, B0::<N1>::default()); assert_eq!(N1 - N1, Z0); assert_eq!(N1 - B0::<P1>::default(), B1::<B0<N1>>::default()); // N1 - FixedPoint assert_eq!( N1 - FixedPoint::<P1, B0<B0<B0<P1>>>>::default(), FixedPoint::<B0<N1>, B1<B1<B1<P1>>>>::default() ); // N1 - Var let var = Var(3i32); assert_eq!(N1 - var, Var(-4i32)); } #[test] fn test_b0_sub() { // B0 - I assert_eq!(B0::<P1>::default() - Z0, B0::<P1>::default()); assert_eq!(B0::<P1>::default() - P1, B0::<Z0>::default()); assert_eq!(B0::<P1>::default() - N1, B1::<P1>::default()); assert_eq!(B0::<B0<P1>>::default() - B0::<P1>::default(), B0::<P1>::default()); assert_eq!(B0::<B0<P1>>::default() - B1::<P1>::default(), P1); // B0 - FixedPoint assert_eq!( B0::<P1>::default() - FixedPoint::<P1, B0<B0<B0<P1>>>>::default(), FixedPoint::<B0::<Z0>, B0<B0<B0<P1>>>>::default() ); // B0 - Var let var = Var(3i32); assert_eq!(B0::<P1>::default() - var, Var(-3i32)); } #[test] fn test_b1_sub() { // B1 - I assert_eq!(B1::<P1>::default() - Z0, B1::<P1>::default()); assert_eq!(B1::<P1>::default() - P1, P1); assert_eq!(B1::<P1>::default() - N1, B0::<B0<P1>>::default()); assert_eq!(B1::<B0<P1>>::default() - B0::<P1>::default(), B1::<P1>::default()); assert_eq!(B1::<B0<P1>>::default() - B1::<P1>::default(), B0::<P1>::default()); // B1 - FixedPoint assert_eq!( B1::<P1>::default() - FixedPoint::<P1, B0<B0<P1>>>::default(), FixedPoint::<B1::<Z0>, B0<B0<P1>>>::default() ); // B1 - Var let var = Var(2i32); assert_eq!(B1::<P1>::default() - var, Var(-1i32)); } #[test] fn test_fixed_point_sub() { // FixedPoint - I assert_eq!( FixedPoint::<B0<P1>, B0<B0<B0<P1>>>>::default() - P1, FixedPoint::<P1, B0<B0<B0<P1>>>>::default() ); // FixedPoint - FixedPoint let fp1 = FixedPoint::<P1, B0<B0<B0<P1>>>>::default(); let fp2 = FixedPoint::<P1, B0<B0<B0<P1>>>>::default(); assert_eq!(fp1 - fp2, FixedPoint::<Z0, Z0>::default()); // FixedPoint - Var let var = Var(1i32); assert_eq!( FixedPoint::<P1, B0<B0<B0<P1>>>>::default() - var, Var(0i32) ); } #[test] fn test_var_sub() { // Var - I let var = Var(5i32); assert_eq!(var - P1, Var(4i32)); // Var - FixedPoint let fp = FixedPoint::<P1, B0<B0<B0<P1>>>>::default(); assert_eq!(Var(3i32) - fp, Var(2i32)); // Var - Var let var1 = Var(5i32); let var2 = Var(3i32); assert_eq!(var1 - var2, Var(2i32)); } }

二、主要组成部分

  1. 核心 Traits 和类型
  • SubWithBorrow: 带借位的减法 trait,表示 a - b - 1 的运算

  • Sub: 标准减法 trait 的实现

  • 数字类型:

    • Z0: 表示零

    • P1: 表示 +1

    • N1: 表示 -1

    • B0, B1: 二进制数表示(H 是高位)

    • FixedPoint: 定点数(I 是整数部分,F 是小数部分)

    • Var: 运行时变量(T 是基本类型如 i32)

  1. 带借位减法实现 (SubWithBorrow)

处理各种类型组合的带借位减法(a - b - 1):

  • P1 - NonZero: 结果为 -I

  • N1 - NonZero: 结果为 !I - 1

  • B0 与各种类型的减法

  • B1 与各种类型的减法

  1. 标准减法实现 (Sub)

为各种类型组合实现标准减法:

  • Z0 - All: 零减任何数等于其相反数

  • P1 - All: +1 减其他数

  • N1 - All: -1 减其他数

  • B0 - All: 二进制数 0… 减其他数

  • B1 - All: 二进制数 1… 减其他数

  • FixedPoint - All: 定点数减法

  • Var - All: 运行时变量减法

  1. 测试模块

包含对各种减法情况的测试,验证实现的正确性。

三、设计特点

  • 类型安全计算: 所有运算都在类型系统层面完成,保证编译期类型安全

  • 零成本抽象: 运行时没有额外开销

  • 组合式设计: 通过 traits 和关联类型组合各种运算

  • 扩展性: 可以方便地添加新的数字类型和运算

四、使用示例


// 编译期计算
let _ = Z0 - P1;  // 结果为 N1 (-1)
let _ = B0<P1> - B1<P1>;  // 二进制数运算

// 运行时变量计算
let var = Var(5i32);
let result = var - P1;  // 结果为 Var(4i32)

这段代码展示了 Rust 类型系统的强大能力,能够在编译期完成复杂的数值计算和类型转换,同时保持类型安全和零成本抽象。

你可能感兴趣的:(我的unitrix库,rust)