一、源码
这段代码实现了类型级别的右移运算(>>),包括对整数和定点数的支持。
/*类型级别的右移运算实现* 编制人: $ource* 修改版次:0版完成版* 本版次创建时间: 2025年6月27日* 最后修改时间: 2025年7月2日 Sub1修改* 待完善问题:无*/
use core::ops::{Shl, Shr};use crate::number::{Z0, P1, N1, B0, B1, Var, FixedPoint,TypedInt, NonZero, Primitive, PrimitiveInt, Unsigned,IfB0, IfB1, Sub1,
};// ==================== Right Shift Operation (>>) ====================
// ==================== 右移运算(>>) ====================// ==================== Z0 >> All ====================
// Zero right shifted by any amount is still zero
// 零右移任何位数仍然是零
impl<R: Unsigned> Shr<R> for Z0 {type Output = Z0;fn shr(self, _: R) -> Self::Output {Z0}
}// Zero right shifted by a variable amount is still zero
// 零右移可变位数仍然是零
impl<T: Primitive> Shr<Var<T>> for Z0 {type Output = Z0;fn shr(self, _: Var<T>) -> Self::Output {Z0}
}// ==================== P1 >> U ====================
// Positive one right shifted by zero is itself
// 正一右移零位是其本身
impl Shr<Z0> for P1 {type Output = Self;fn shr(self, _: Z0) -> Self::Output {self}
}// Positive one right shifted by any non-zero unsigned number becomes zero
// 正一右移任何非零无符号数变为零
impl<R: Unsigned + NonZero> Shr<R> for P1 {type Output = Z0;fn shr(self, _: R) -> Self::Output {Z0}
}impl<T: PrimitiveInt> Shr<Var<T>> for P1
where Var<T>: From<P1> + Shr<Output=Var<T>>
{type Output = Var<T>;fn shr(self, rhs: Var<T>) -> Self::Output {Var::<T>::from(self) >> rhs}
}// ==================== N1 >> U ====================
// Negative one right shifted by any unsigned number remains negative one
// (due to sign extension in two's complement arithmetic right shift)
// 负一右移任何无符号数仍然是负一(由于二进制补码算术右移中的符号扩展)
impl<R: Unsigned> Shr<R> for N1 {type Output = Self;fn shr(self, _: R) -> Self::Output {self}
}impl<T: PrimitiveInt> Shr<Var<T>> for N1 {type Output = Self;fn shr(self, _: Var<T>) -> Self::Output {self}
}// ==================== B0 >> U ====================
// Binary number ending with 0 right shifted by zero is itself
// 以0结尾的二进制数右移零位是其本身
impl<H: NonZero> Shr<Z0> for B0<H> {type Output = Self;fn shr(self, _: Z0) -> Self::Output {self}
}// Binary number ending with 0 right shifted by more than one
// Recursively shifts right by one until the shift amount is zero
// (equivalent to dropping the least significant bit and shifting the rest)
// 以0结尾的二进制数右移多于一位
// 递归地右移一位直到移位量为零(相当于丢弃最低有效位并右移其余位)
impl<H: NonZero + Default + Shr<<R as Sub1>::Output, Output:Default>, R: Unsigned + NonZero + Sub1> Shr<R> for B0<H>{type Output = < H as Shr< <R as Sub1>::Output > >::Output;fn shr(self, _: R) -> Self::Output {Default::default()}
}impl<H: NonZero, T: PrimitiveInt> Shr<Var<T>> for B0<H>
where Var<T>: From<B0<H>> + Shr<Output=Var<T>>,
{type Output = Var<T>;fn shr(self, rhs: Var<T>) -> Self::Output {Var::<T>::from(self) >> rhs}
}// ==================== B1 >> U ====================
// Binary number ending with 1 right shifted by zero is itself
// 以1结尾的二进制数右移零位是其本身
impl<H: NonZero> Shr<Z0> for B1<H> {type Output = Self;fn shr(self, _: Z0) -> Self::Output {self}
}// Binary number ending with 1 right shifted by more than one
// Recursively shifts right by one until the shift amount is zero,
// and maintains the sign bit
// 以1结尾的二进制数右移多于一位
// 递归地右移一位直到移位量为零,并保持符号位
impl<H: NonZero + Default + Shr<<R as Sub1>::Output, Output: Default>, R: Unsigned + NonZero + Sub1> Shr<R> for B1<H>{type Output = < H as Shr< <R as Sub1>::Output > >::Output;fn shr(self, _: R) -> Self::Output {Default::default()}
}impl<H: NonZero, T: PrimitiveInt> Shr<Var<T>> for B1<H>
where Var<T>: From<B1<H>> + Shr<Output=Var<T>>,
{type Output = Var<T>;fn shr(self, rhs: Var<T>) -> Self::Output {Var::<T>::from(self) >> rhs}
}// ==================== FixedPoint<IntPart, FracPart> >> All ====================
// ==================== 定点数右移实现 ====================// Fixed-point number right shift by zero - no change
// 定点数右移零位 - 无变化
impl<IntPart, FracPart> Shr<Z0> for FixedPoint<IntPart, FracPart> {type Output = Self;fn shr(self, _: Z0) -> Self::Output {self}
}// Fixed-point with zero integer part right shift
// Shifting affects only the fractional part
// 整数部分为零的定点数右移
// 移位仅影响小数部分
impl<FracPart: TypedInt + Shl<R>, R: Unsigned + NonZero> Shr<R> for FixedPoint<Z0, FracPart> { //FracPart是反向存储的type Output = FixedPoint<Z0, <FracPart as Shl<R>>::Output>;fn shr(self, _: R) -> Self::Output {FixedPoint::new()}
}// Fixed-point with positive one integer part right shift
// Shifting moves bits from integer to fractional part
// 整数部分为正一的定点数右移
// 移位将位从整数部分移动到小数部分
impl<FracPart: TypedInt + IfB1, R: Unsigned + NonZero + Sub1> Shr<R> for FixedPoint<P1, FracPart>
whereFixedPoint< Z0, <FracPart as IfB1>::Output > : Shr<<R as Sub1>::Output, Output: Default>,
{type Output = < FixedPoint< Z0, <FracPart as IfB1>::Output > as Shr<<R as Sub1>::Output> >::Output;fn shr(self, _: R) -> Self::Output {Default::default()}
}// Fixed-point with negative one integer part right shift
// Arithmetic right shift preserves the sign bit
// 整数部分为负一的定点数右移
// 算术右移保留符号位
impl<FracPart: IfB1, R> Shr<R> for FixedPoint<N1, FracPart>
whereR: Unsigned + NonZero + Sub1,<FracPart as IfB1>::Output : Shr<<R as Sub1>::Output>, // 递归条件
{type Output = FixedPoint<N1, <<FracPart as IfB1>::Output as Shr<<R as Sub1>::Output> >::Output>;fn shr(self, _: R) -> Self::Output {FixedPoint::new()}
}// Fixed-point with binary integer part ending with 0 right shift
// 整数部分以0结尾的二进制定点数右移
impl<H:NonZero, FracPart: IfB0, R: Unsigned + NonZero + Sub1> Shr<R> for FixedPoint<B0<H>, FracPart>
whereFixedPoint<H,<FracPart as IfB0>::Output>: Shr<<R as Sub1>::Output, Output: Default>, // 递归条件
{type Output = < FixedPoint<H,<FracPart as IfB0>::Output> as Shr<<R as Sub1>::Output> >::Output;fn shr(self, _: R) -> Self::Output {// 递归处理:先移1位,再移n-1位Default::default()}
}// Fixed-point with binary integer part ending with 1 right shift
// 整数部分以1结尾的二进制定点数右移
impl<H:NonZero, FracPart: IfB1, R: Unsigned + NonZero + Sub1> Shr<R> for FixedPoint<B1<H>, FracPart>
whereFixedPoint<H,<FracPart as IfB1>::Output>: Shr<<R as Sub1>::Output, Output: Default>, // 递归条件
{type Output = < FixedPoint<H,<FracPart as IfB1>::Output> as Shr<<R as Sub1>::Output> >::Output;fn shr(self, _: R) -> Self::Output {// 递归处理:先移1位,再移n-1位Default::default()}
}// ==================== Var >> All ====================
impl<T: PrimitiveInt, R: Unsigned> Shr<R> for Var<T>
whereVar<T>: From<R> + Shr,
{type Output = <Var<T> as Shr>::Output;fn shr(self, rhs: R) -> Self::Output {self >> Var::<T>::from(rhs)}
}impl<T: PrimitiveInt + Shr<Output = T>> Shr<Var<T>> for Var<T>{type Output = Var<T>;fn shr(self, rhs: Var<T>) -> Self::Output {Var(self.0 >> rhs.0)}
}/* 右移一位特质实现* 编制人: $ource* 创建时间: 2023年7月4日*//// 定义右移一位的特质
pub trait Shr1 {type Output;fn shr1(self) -> Self::Output;
}// ==================== Z0 Shr1 ====================
// 零右移一位仍然是零
impl Shr1 for Z0 {type Output = Z0;fn shr1(self) -> Self::Output {Z0}
}// ==================== P1 Shr1 ====================
// 正一右移一位变为零
impl Shr1 for P1 {type Output = Z0;fn shr1(self) -> Self::Output {Z0}
}// ==================== N1 Shr1 ====================
// 负一右移一位仍然是负一(算术右移保留符号位)
impl Shr1 for N1 {type Output = N1;fn shr1(self) -> Self::Output {self}
}// ==================== B0 Shr1 ====================
// 以0结尾的二进制数右移一位相当于去掉最低位
impl<H: NonZero> Shr1 for B0<H> {type Output = H;fn shr1(self) -> Self::Output {H::default()}
}// ==================== B1 Shr1 ====================
// 以1结尾的二进制数右移一位相当于去掉最低位
impl<H: NonZero> Shr1 for B1<H> {type Output = H;fn shr1(self) -> Self::Output {H::default()}
}// ==================== FixedPoint Shr1 ====================
// 定点数右移一位实现// 整数部分为零的定点数右移一位
impl<FracPart: TypedInt + IfB0> Shr1 for FixedPoint<Z0, FracPart> {type Output = FixedPoint<Z0, <FracPart as IfB0>::Output>;fn shr1(self) -> Self::Output {FixedPoint::new()}
}// 整数部分为正一的定点数右移一位
impl<FracPart: TypedInt + IfB1> Shr1 for FixedPoint<P1, FracPart> {type Output = FixedPoint<Z0, <FracPart as IfB1>::Output>;fn shr1(self) -> Self::Output {FixedPoint::new()}
}// 整数部分为负一的定点数右移一位
impl<FracPart: IfB1> Shr1 for FixedPoint<N1, FracPart> {type Output = FixedPoint<N1, <FracPart as IfB1>::Output>;fn shr1(self) -> Self::Output {FixedPoint::new()}
}// 整数部分以0结尾的定点数右移一位
impl<H: NonZero, FracPart: IfB0> Shr1 for FixedPoint<B0<H>, FracPart> {type Output = FixedPoint<H, <FracPart as IfB0>::Output>;fn shr1(self) -> Self::Output {FixedPoint::new()}
}// 整数部分以1结尾的定点数右移一位
impl<H: NonZero, FracPart: IfB1> Shr1 for FixedPoint<B1<H>, FracPart> {type Output = FixedPoint<H, <FracPart as IfB1>::Output>;fn shr1(self) -> Self::Output {FixedPoint::new()}
}#[cfg(test)]
mod tests {use crate::number::*;// ==================== Z0 右移测试 ====================#[test]fn test_z0_shr() {let z0 = Z0;// Z0 >> U0 = Z0assert_eq!(z0 >> Z0, Z0);// Z0 >> U1 = Z0assert_eq!(z0 >> P1, Z0);// Z0 >> U5 = Z0assert_eq!(z0 >> B1::<B0<P1>>::new(), Z0);// Z0 >> Var = Z0let var = Var(5_i32);assert_eq!(z0 >> var, Z0);}// ==================== P1 右移测试 ====================#[test]fn test_p1_shr() {let p1 = P1;// P1 >> U0 = P1assert_eq!(p1 >> Z0, P1);// P1 >> U1 = Z0assert_eq!(p1 >> P1, Z0);// P1 >> U2 = Z0assert_eq!(p1 >> B0::<P1>::new(), Z0);// P1 >> Varlet var1 = Var(0_i32);assert_eq!(p1 >> var1, Var::<i32>::from(P1));let var2 = Var::<i32>::from(1);assert_eq!(p1 >> var2, Var::<i32>::from(Z0));}// ==================== N1 右移测试 ====================#[test]fn test_n1_shr() {let n1 = N1;// N1 >> U0 = N1assert_eq!(n1 >> Z0, N1);// N1 >> U1 = N1 (算术右移保留符号位)assert_eq!(n1 >> P1, N1);// N1 >> U5 = N1assert_eq!(n1 >> B1::<B0<P1>>::new(), N1);// N1 >> Varlet var = Var::<i32>::from(3);assert_eq!(n1 >> var, N1);}// ==================== B0 右移测试 ====================#[test]fn test_b0_shr() {let b0p1 = B0::<P1>::new();// B0<P1> >> U0 = B0<P1>assert_eq!(b0p1 >> Z0, b0p1);// B0<P1> >> U1 = P1assert_eq!(b0p1 >> P1, P1);// B0<P1> >> U2 = Z0 (P1 >> U1 = Z0)assert_eq!(b0p1 >> B0::<P1>::new(), Z0);// B0<P1> >> Varlet var1 = Var::<i32>::from(0);assert_eq!(b0p1 >> var1, Var::from(b0p1));let var2 = Var::<i32>::from(1);assert_eq!(b0p1 >> var2, Var::from(P1::new()));}// ==================== B1 右移测试 ====================#[test]fn test_b1_shr() {type B1P1 = B1<P1>;let b1p1 = B1P1::new();// B1<P1> >> U0 = B1<P1>assert_eq!(b1p1 >> Z0, b1p1);// B1<P1> >> U1 = P1assert_eq!(b1p1 >> P1, P1);// B1<P1> >> U2 = Z0 (P1 >> U1 = Z0)assert_eq!(b1p1 >> B0::<P1>::new(), Z0);// B1<P1> >> Varlet var1 = Var::<i32>::from(0);assert_eq!(b1p1 >> var1, Var::from(b1p1));let var2 = Var::<i32>::from(1);assert_eq!(b1p1 >> var2, Var::from(P1::new()));}// ==================== 定点数右移测试 ====================#[test]fn test_fixed_point_shr() {// 整数部分为0的定点数右移type FP1 = FixedPoint<Z0, B1<P1>>;let fp1 = FP1::new();// FP1 >> U0 = FP1assert_eq!(fp1 >> Z0, fp1);// FP1 >> U1 = FixedPoint<Z0, U3 << U1>// 注意:FracPart是反向存储的,左移实际上是增加小数位数// 这里需要根据实际实现调整断言// 整数部分为P1的定点数右移type FP2 = FixedPoint<P1, B1<P1>>;let fp2 = FP2::new();// FP2 >> U0 = FP2assert_eq!(fp2 >> Z0, fp2);// FP2 >> U1 = FixedPoint<Z0, ...>// 需要根据实际实现调整断言// 整数部分为N1的定点数右移type FP3 = FixedPoint<N1, B1<P1>>;let fp3 = FP3::new();// FP3 >> U1 = FP3 (算术右移保留符号位)assert_eq!(fp3 >> P1, FixedPoint::< N1, B1<B1<P1>> >::new());}// ==================== Var 右移测试 ====================#[test]fn test_var_shr() {// Var >> Unsignedlet var1 = Var::<i32>::from(8);assert_eq!(var1 >> P1, Var::from(4));assert_eq!(var1 >> B0::<P1>::new(), Var::from(2));assert_eq!(var1 >> B1::<P1>::new(), Var::from(1));// Var >> Varlet var2 = Var::<i32>::from(16);let shift = Var::<i32>::from(2);assert_eq!(var2 >> shift, Var::from(4));// 负数算术右移let var3 = Var::<i32>::from(-8);assert_eq!(var3 >> P1, Var::from(-4));assert_eq!(var3 >> B0::<P1>::new(), Var::from(-2));}#[test]fn test_shr1() {// 测试Z0assert_eq!(Z0.shr1(), Z0);// 测试P1assert_eq!(P1.shr1(), Z0);// 测试N1assert_eq!(N1.shr1(), N1);// 测试B0let b0 = B0::<P1>::new();assert_eq!(b0.shr1(), P1);// 测试B1let b1 = B1::<P1>::new();assert_eq!(b1.shr1(), P1);// 测试FixedPointlet fp1 = FixedPoint::<P1, B1<P1>>::new();assert_eq!(fp1.shr1(), FixedPoint::<Z0, B1<B1<P1>>>::new());let fp2 = FixedPoint::<B0<P1>, B1<P1>>::new();assert_eq!(fp2.shr1(), FixedPoint::<P1, B0<B1<P1>>>::new());}
}
二、基本概念
- 类型级别编程
-
使用Rust的类型系统在编译期进行计算
-
通过特质(trait)和泛型实现类型之间的运算
- 数字表示
-
Z0: 表示数字0
-
P1: 表示正1
-
N1: 表示负1
-
B0, B1: 二进制表示的数字,B0表示最低位为0,B1表示最低位为1
三、核心实现
- 零的右移 (Z0)
impl<R: Unsigned> Shr<R> for Z0 {type Output = Z0;fn shr(self, _: R) -> Self::Output { Z0 }
}
- 任何数右移0仍然是0
- 正一的右移 (P1)
impl Shr<Z0> for P1 {type Output = Self;fn shr(self, _: Z0) -> Self::Output { self }
}impl<R: Unsigned + NonZero> Shr<R> for P1 {type Output = Z0;fn shr(self, _: R) -> Self::Output { Z0 }
}
-
右移0位保持不变
-
右移任何非零位数变为0
- 负一的右移 (N1)
impl<R: Unsigned> Shr<R> for N1 {type Output = Self;fn shr(self, _: R) -> Self::Output { self }
}
- 算术右移保留符号位,所以总是保持-1
- 二进制数的右移 (B0, B1)
impl<H: NonZero + Default + Shr<<R as Sub1>::Output, Output:Default>, R: Unsigned + NonZero + Sub1> Shr<R> for B0<H>{type Output = <H as Shr<<R as Sub1>::Output>>::Output;fn shr(self, _: R) -> Self::Output { Default::default() }
}
-
递归实现:右移n位 = 右移1位后再右移(n-1)位
-
B0>右移1位等于H(去掉最低位的0)
-
B1>右移1位等于H(去掉最低位的1)
四、定点数右移
定点数表示为FixedPoint<IntPart, FracPart>,其中:
-
IntPart: 整数部分类型
-
FracPart: 小数部分类型(反向存储)
实现要点
impl<FracPart: TypedInt + Shl<R>, R: Unsigned + NonZero> Shr<R> for FixedPoint<Z0, FracPart> {type Output = FixedPoint<Z0, <FracPart as Shl<R>>::Output>;fn shr(self, _: R) -> Self::Output { FixedPoint::new() }
}
-
整数部分为0时,右移只影响小数部分
-
小数部分是反向存储的,所以右移实际上是左移小数部分
impl<FracPart: TypedInt + IfB1, R: Unsigned + NonZero + Sub1> Shr<R> for FixedPoint<P1, FracPart>
whereFixedPoint<Z0, <FracPart as IfB1>::Output>: Shr<<R as Sub1>::Output, Output: Default>,
{type Output = <FixedPoint<Z0, <FracPart as IfB1>::Output> as Shr<<R as Sub1>::Output>>::Output;fn shr(self, _: R) -> Self::Output { Default::default() }
}
- 整数部分为1时,右移会将整数部分的1移到小数部分
五、变量右移 (Var)
impl<T: PrimitiveInt + Shr<Output = T>> Shr<Var<T>> for Var<T>{type Output = Var<T>;fn shr(self, rhs: Var<T>) -> Self::Output { Var(self.0 >> rhs.0) }
}
-
运行时实际的右移操作
-
支持变量移位量
六、右移一位特质 (Shr1)
单独实现了Shr1特质来优化右移一位的操作,避免递归调用。
七、测试用例
代码包含了全面的测试用例,验证了:
-
各种数字类型的右移行为
-
定点数的右移行为
-
变量移位
-
边界情况处理
八、总结
这段代码展示了如何在Rust类型系统中实现复杂的算术运算,特点包括:
-
编译期计算
-
支持任意位数移位
-
正确处理算术右移的符号扩展
-
支持定点数的小数部分处理
-
提供运行时变量移位支持
这种类型级别的实现可以用于需要编译期计算和验证的场景,如嵌入式系统、金融计算等对精度和性能要求高的领域。