马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、源码
这段代码是用Rust实现的类型级右移运算(>>),属于类型级编程的范畴。它通过类型体系来体现和操纵二进制数,并在编译期完成计算。
- use super::basic::{Z0, P1, N1, B0, B1, NonZero, NonOne, Unsigned};
- use super::sub1::Sub1;
- use core::ops::Shr;
- // ==================== Right Shift Operation (>>) ====================
- // ==================== 右移运算(>>) ====================
- // Z0 >> U
- // Zero right shifted by any unsigned number is still zero
- // 零右移任何无符号数仍然是零
- impl<R: Unsigned> Shr<R> for Z0 {
- type Output = Z0;
- fn shr(self, _: R) -> Self::Output {
- Z0 // 0 >> n = 0
- }
- }
- // 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::new()
- }
- }
- // N1 >> U
- // Negative one right shifted by any unsigned number remains negative one
- // (due to sign extension in two's complement)
- // 负一右移任何无符号数仍然是负一(由于二进制补码中的符号扩展)
- impl<R: Unsigned> Shr<R> for N1 {
- type Output = Self;
- fn shr(self, _: R) -> 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 one becomes its head
- // 以0结尾的二进制数右移一位变为其头部
- impl<H: NonZero> Shr<P1> for B0<H> {
- type Output = H;
- fn shr(self, _: P1) -> Self::Output {
- H::default()
- }
- }
- // Binary number ending with 0 right shifted by more than one
- // Recursively shifts right by one until the shift amount is zero
- // 以0结尾的二进制数右移多于一位
- // 递归地右移一位直到移位量为零
- impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shr<R> for B0<H>
- where
- H: Shr<<R as Sub1>::Output>
- {
- type Output = <H as Shr<R::Output>>::Output;
- fn shr(self, r: R) -> Self::Output {
- (self>>P1)>>r.sub1()
- }
- }
- // 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 one becomes its head
- // 以1结尾的二进制数右移一位变为其头部
- impl<H: NonZero> Shr<P1> for B1<H> {
- type Output = H;
- fn shr(self, _: P1) -> Self::Output {
- H::default()
- }
- }
- // 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 (B0 prefix)
- // 以1结尾的二进制数右移多于一位
- // 递归地右移一位直到移位量为零,并保持符号位(B0前缀)
- impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shr<R> for B1<H>
- where
- H: Shr<<R as Sub1>::Output>
- {
- type Output = <H as Shr<R::Output>>::Output;
- fn shr(self, r: R) -> Self::Output {
- (self>>P1)>>(r.sub1())
- }
- }
- // Test cases
- #[cfg(test)]
- mod tests {
- use super::*;
-
- #[test]
- fn test_shr() {
- // Test Z0
- let _: Z0 = Z0 >> Z0;
- let _: Z0 = Z0 >> P1;
-
- // Test P1
- let _: P1 = P1 >> Z0;
- let _: Z0 = P1 >> P1;
-
- // Test N1
- let _: N1 = N1 >> Z0;
- let _: N1 = N1 >> P1;
-
- // Test B0
- let b0: B0<P1> = B0::new();
- let _: B0<P1> = b0 >> Z0;
- let _: P1 = b0 >> P1;
-
- // Test B1
- let b1: B1<P1> = B1::new();
- let _: B1<P1> = b1 >> Z0;
- let _: P1 = b1 >> P1;
- }
- }
复制代码 二、根本概念
- Z0:体现数字0
- P1:体现+1
- N1:体现-1
- B0:体现以0末端的二进制数(如B0体现二进制10,即十进制2)
- B1:体现以1末端的二进制数(如B1体现二进制11,即十进制3)
- NonZero、NonOne、Unsigned:这些是标记trait,用于束缚类型参数
- Shr:Rust的右移运算符trait,这里为差别类型实现了该trait
三、实现逻辑
- 右移0位:保持稳定
- 右移非零位:变为0(因为正数的右移会补0)
- 右移任何位数都保持稳定(因为负数的右移在补码体现中会进行符号扩展)
- 右移0位:保持稳定
- 右移1位:去掉最后一位0,变成头部H
- 右移多位:递归地右移1位直到完成
递归实现
对于多位右移操纵,代码使用了递归的方式:
- impl<H: NonZero, R: Unsigned + NonZero + NonOne + Sub1> Shr<R> for B0<H>
- where
- H: Shr<<R as Sub1>::Output>
- {
- type Output = <H as Shr<R::Output>>::Output;
- fn shr(self, r: R) -> Self::Output {
- (self>>P1)>>r.sub1()
- }
- }
复制代码 这里的意思是:要计算B0 >> R,先右移1位变成H,然后对剩下的R-1位继续右移。
测试用例
测试了各种情况:
- 零的右移
- +1的右移
- -1的右移
- 以0末端的二进制数的右移
- 以1末端的二进制数的右移
四、总结
这段代码展示了怎样使用Rust的类型体系在编译期完成右移运算。通过为差别类型实现Shr trait,并使用递归类型计算,实现了类型安全的右移操纵。这种技术常用于嵌入式开辟等需要编译期计算的场景。
|