一、源码

这段代码是Rust类型级编程中用于标记非零类型的系统,它通过特质(trait)NonZero 和一系列实现来确保类型安全。未来将扩展到小数和浮点数以拓宽其表示范围。

use crate::sealed::Sealed;
use crate::number::{Bit, Unsigned, types::{B1, UInt}};

/// 标记特质,标识非零类型(除B0、U0、Z0外)
pub trait NonZero: Sealed {}

// B1(位1)是非零值
impl NonZero for B1 {}

// UInt<U, B> 只要存在即为非零
impl<U: Unsigned, B: Bit> NonZero for UInt<U, B> {}

// 正整数PInt要求底层无符号类型非零
impl<U: Unsigned + NonZero> NonZero for PInt<U> {}

// 负整数NInt要求底层无符号类型非零
impl<U: Unsigned + NonZero> NonZero for NInt<U> {}

二、代码解释

  1. 基本结构

use crate::sealed::Sealed;
use crate::number::{Bit, Unsigned, types::{B1, UInt}};
  • Sealed trait: 一个私有特质,防止下游crate实现这些特质,确保只有当前crate可以控制实现。

  • Bit: 表示二进制位(通常是B0或B1)。

  • Unsigned: 表示无符号整数类型(如U0, U1, U2等)。

  • UInt<U, B>: 无符号整数的类型级表示,其中U是高位部分,B是最低位(例如UInt<U1, B0>表示2)。

  1. NonZero trait

pub trait NonZero: Sealed {}

这是一个标记特质(marker trait),用于标识非零类型。它继承Sealed,确保只有当前crate可以实现它。
3. 具体实现
(a)B1(位1)是非零


impl NonZero for B1 {}

B1表示二进制位1,显然非零。
(b)UInt<U, B>(无符号整数)是非零


impl<U: Unsigned, B: Bit> NonZero for UInt<U, B> {}

UInt表示一个至少为1的正整数(例如UInt<U0, B1>是1),因此总是非零。
(c)正整数PInt要求底层无符号类型非零


impl<U: Unsigned + NonZero> NonZero for PInt<U> {}

PInt表示正整数(如PInt表示+1),它要求底层的无符号类型U必须非零(即U: NonZero)。
(d)负整数NInt要求底层无符号类型非零


impl<U: Unsigned + NonZero> NonZero for NInt<U> {}

NInt表示负整数(如NInt表示-1),同样要求底层无符号类型U非零。

三、扩展到小数和浮点数

当前系统仅支持整数(包括正负整数和无符号整数)。要支持小数和浮点数,我们需要扩展类型系统。

  1. 表示小数(定点数)

我们可以用定点数表示小数,例如:


// 示例:Qm.n 格式(m位整数部分,n位小数部分)
struct FixedPoint<I, F> {
    integer: I,   // 整数部分(带符号)
    fractional: F, // 小数部分(无符号)
}

要求:

  • 整数部分I可以是PInt、NInt或Z0(零)。

  • 小数部分F是一个无符号整数(表示小数位的值)。

实现NonZero:

  • 当整数部分非零(I: NonZero)时,整个数非零。

  • 如果整数部分为零,但小数部分非零(F: NonZero),那么整个数也非零。


impl<I, F> NonZero for FixedPoint<I, F>
where
    I: NonZero,  // 整数部分非零
    F: Unsigned + NonZero, // 或小数部分非零
{}
  1. 表示浮点数(IEEE754风格)

浮点数更复杂,但我们可以用类型参数表示符号、指数和尾数:


struct Float<S, E, M> {
    sign: S,      // 符号(B0表示正,B1表示负)
    exponent: E,  // 指数(有偏)
    mantissa: M,  // 尾数(隐含前导1)
}

非零条件:

  • 指数非全0(非规约数)或非全1(非无穷/NaN)。

  • 尾数非零(对于规约数)。

但类型级编程中,我们需要用类型表示这些状态。例如:


// 规约数(exponent非全0且非全1,mantissa任意)
impl<S, E, M> NonZero for Float<S, E, M>
where
    E: NotAllZeros + NotAllOnes, // 自定义特质,表示指数非全0且非全1
{}

// 非规约数(exponent全0,但mantissa非零)
impl<S, M> NonZero for Float<S, AllZeros, M>
where
    M: NonZero, // 尾数非零
{}
  1. 扩展范围

    小数(定点数):通过增加整数部分和小数部分的位数来扩展范围(例如FixedPoint<PInt, UInt<U5, B0>>表示整数部分10位,小数部分5位)。

    浮点数:通过增加指数和尾数的位数来扩展范围和精度(例如半精度、单精度、双精度)。

四、总结

  • 原代码通过NonZero特质标记非零整数类型(包括正负整数和无符号整数)。

  • 扩展到小数(定点数)时,需要同时检查整数部分和小数部分。

  • 扩展到浮点数时,需要根据指数和尾数的状态判断非零条件。

  • 通过增加位数(类型参数)可以拓宽表示范围和提高精度。

这种类型级编程常用于嵌入式系统、数值计算和高安全性领域,在编译期确保数值有效性(如避免除零错误)。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐