当前位置: 首页 > news >正文

【PhysUnits】15.9 引入P1后的右移运算(shr.rs) - 详解

一、源码

这段代码是用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
;
}
}

二、基本概念

  1. 类型定义:
  1. 核心trait:

三、实现逻辑

  1. Z0(零)的右移:
  1. P1(+1)的右移:
  1. N1(-1)的右移:
  1. B0(以0结尾的二进制数)的右移:
  1. B1(以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,并使用递归类型计算,实现了类型安全的右移操作。这种技术常用于嵌入式开发等需要编译期计算的场景。

http://www.hskmm.com/?act=detail&tid=26993

相关文章:

  • 10. 模型与视图
  • [KaibaMath]1004 关于f(x,y) = [x]+[y] - [x+y]的平移稳定性
  • Mac OS 问题与技巧
  • 《算法设计与分析》第一章学习记录
  • nestjs 和 nextjs 分别是做啥的
  • 定时收集TCM数据并生成Excel报表并上传
  • 2025.10 国庆集训模拟赛总结
  • 详细介绍:https和http有什么区别-http各个版本有什么区别
  • CF2150F Cycle Closing
  • Easysearch 字段隐身之谜:source_reuse 与 ignore_above 的陷阱解析
  • QOJ856 Cactus 广义串并联图
  • CF2152 订题
  • 静态路由
  • Kruskal 重构树学习笔记
  • GJ Round 2025赛季
  • ASP.NET Core 中读取 UserAgent 的正确姿势
  • vLLM推理加速指南:7个技巧让QPS提升30-60%
  • Git学习记录(二):代码patch
  • 2025年10月化妆品代工厂最新推荐排行榜:聚焦 OEM/ODM/ 网红爆款需求,精选优质企业助品牌高效合作
  • Exchange安全漏洞分析:ProxyOracle攻击链详解
  • 牛客 周赛111 20251008
  • 本人于2025上半学期编码需要遵守的规范(参考腾讯内部编码规范)
  • 10.8 CSP-JS 模拟赛 T5. xor
  • 防抖 解释
  • 从零到一搭建:vue3+vite7+antfu+stylelint+githooks,全流程配置,附带源码,集成css变量使用,下载即用
  • bat批处理脚本文件-获取当前时间的几种方法
  • 二分图最大权完美匹配 KM算法
  • 2025.10.8模拟赛
  • Python 中的排序排序函数及区别
  • RL | 速读 IJCAI 2025 的强化学习论文