一、源码
这段代码是用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,用于约束类型参数
- 核心trait:
- Shr:Rust的右移运算符trait,这里为不同类型实现了该trait
三、实现逻辑
- Z0(零)的右移:
任何数右移0位保持不变
0右移任何位数仍然是0
- P1(+1)的右移:
右移0位:保持不变
右移非零位:变为0(因为正数的右移会补0)
- N1(-1)的右移:
- 右移任何位数都保持不变(因为负数的右移在补码表示中会进行符号扩展)
- B0(以0结尾的二进制数)的右移:
右移0位:保持不变
右移1位:去掉最后一位0,变成头部H
右移多位:递归地右移1位直到完成
- B1(以1结尾的二进制数)的右移:
- 类似B0,但会保持符号位
递归实现
对于多位右移操作,代码使用了递归的方式:
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,并使用递归类型计算,实现了类型安全的右移操作。这种技术常用于嵌入式开发等需要编译期计算的场景。