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

【学Rust写CAD】16 0、1、-1代数单位元(algebraic_units.rs)

前文曾经叙述的常量类(Const)包含了本程序的功能,但它目前必须在夜版rust下编译。考虑2D CAD使用需要相对简单,过渡期采用本程序。待rust稳定版可以实现常量类或有3D需求时改用常量类。

源码

//algebraic_units.rs 代数单位元
use std::ops::{Add, Mul, Neg};

/// 零元素 (加法单位元)
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Zero;

/// 单位元 (乘法单位元)
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct One;

/// 负单位元 (乘法逆元)
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct DecOne;

// ========== Zero 的实现 ==========

// Zero + T = T
impl<T> Add<T> for Zero {
    type Output = T;
    fn add(self, rhs: T) -> T {
        rhs
    }
}

// Zero * Zero = Zero
impl Mul for Zero {
    type Output = Zero;
    fn mul(self, _: Self) -> Self {
        Zero
    }
}

// Zero * T = Zero
impl<T> Mul<T> for Zero {
    type Output = Zero;
    fn mul(self, _: T) -> Self {
        Zero
    }
}

// T * Zero = Zero
impl<T> Mul<Zero> for T {
    type Output = Zero;
    fn mul(self, _: Zero) -> Zero {
        Zero
    }
}

// ========== One 的实现 ==========

// One * One = One
impl Mul for One {
    type Output = One;
    fn mul(self, _: Self) -> Self {
        One
    }
}

// One * T = T
impl<T> Mul<T> for One {
    type Output = T;
    fn mul(self, rhs: T) -> T {
        rhs
    }
}

// T * One = T
impl<T> Mul<One> for T {
    type Output = T;
    fn mul(self, _: One) -> T {
        self
    }
}

// One + T = T + 1 (需要 T 支持 Add<i32>)
impl<T: Add<i32, Output = T>> Add<T> for One {
    type Output = T;
    fn add(self, rhs: T) -> T {
        rhs + 1
    }
}

// ========== DecOne 的实现 ==========

// DecOne * DecOne = One
impl Mul for DecOne {
    type Output = One;
    fn mul(self, _: Self) -> One {
        One
    }
}

// DecOne * T = -T (需要 T 支持 Neg)
impl<T: Neg<Output = T>> Mul<T> for DecOne {
    type Output = T;
    fn mul(self, rhs: T) -> T {
        -rhs
    }
}

// T * DecOne = -T (需要 T 支持 Neg)
impl<T: Neg<Output = T>> Mul<DecOne> for T {
    type Output = T;
    fn mul(self, _: DecOne) -> T {
        -self
    }
}

// DecOne + T = T - 1 (需要 T 支持 Sub<i32>)
impl<T: Sub<i32, Output = T>> Add<T> for DecOne {
    type Output = T;
    fn add(self, rhs: T) -> T {
        rhs - 1
    }
}

// ========== 其他组合运算 ==========

// One * DecOne = DecOne
impl Mul<DecOne> for One {
    type Output = DecOne;
    fn mul(self, rhs: DecOne) -> DecOne {
        rhs
    }
}

// DecOne * One = DecOne
impl Mul<One> for DecOne {
    type Output = DecOne;
    fn mul(self, _: One) -> DecOne {
        self
    }
}

// Zero * DecOne = Zero (已由 Zero 的通用实现覆盖)
// DecOne * Zero = Zero (已由 Zero 的通用实现覆盖)

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_zero_operations() {
        let z = Zero;

        // 加法测试
        assert_eq!(z + 5, 5);       // 0 + 5 = 5
        assert_eq!(z + (-3), -3);  // 0 + (-3) = -3
        assert_eq!(z + "hello", "hello"); // 0 + 非数字类型

        // 乘法测试
        assert_eq!(z * z, z);       // 0 * 0 = 0
        assert_eq!(z * 10, z);      // 0 * 10 = 0
        assert_eq!(10 * z, z);      // 10 * 0 = 0
        assert_eq!(z * One, z);     // 0 * 1 = 0
        assert_eq!(One * z, z);     // 1 * 0 = 0
        assert_eq!(z * DecOne, z);  // 0 * -1 = 0
        assert_eq!(DecOne * z, z);  // -1 * 0 = 0
    }

    #[test]
    fn test_one_operations() {
        let o = One;

        // 乘法测试
        assert_eq!(o * o, o);       // 1 * 1 = 1
        assert_eq!(o * 7, 7);       // 1 * 7 = 7
        assert_eq!(7 * o, 7);       // 7 * 1 = 7
        assert_eq!(o * DecOne, DecOne); // 1 * -1 = -1
        assert_eq!(DecOne * o, DecOne); // -1 * 1 = -1

        // 加法测试
        assert_eq!(o + 3, 4);       // 1 + 3 = 4
        assert_eq!(o + (-2), -1);   // 1 + (-2) = -1
    }

    #[test]
    fn test_dec_one_operations() {
        let d = DecOne;

        // 乘法测试
        assert_eq!(d * d, One);     // -1 * -1 = 1
        assert_eq!(d * 4, -4);      // -1 * 4 = -4
        assert_eq!(4 * d, -4);      // 4 * -1 = -4
        assert_eq!(d * One, d);     // -1 * 1 = -1
        assert_eq!(One * d, d);     // 1 * -1 = -1

        // 加法测试
        assert_eq!(d + 5, 4);       // -1 + 5 = 4
        assert_eq!(d + (-3), -4);   // -1 + (-3) = -4
    }

    #[test]
    fn test_mixed_operations() {
        // 混合类型运算
        assert_eq!(One * (DecOne * 3), -3); // 1 * (-1 * 3) = -3
        assert_eq!((Zero + One) * DecOne, DecOne); // (0 + 1) * -1 = -1
        assert_eq!(DecOne * (One + 1), -2); // -1 * (1 + 1) = -2
    }

    #[test]
    fn test_commutative_law() {
        // 验证交换律
        let a = 5;
        assert_eq!(a * One, One * a);
        assert_eq!(a * DecOne, DecOne * a);
        assert_eq!(a * Zero, Zero * a);
    }

    #[test]
    fn test_associative_law() {
        // 验证结合律 (注意:加法实现不满足严格结合律)
        assert_eq!((One * DecOne) * DecOne, One * (DecOne * DecOne)); // (-1) * -1 = 1
    }

    #[test]
    fn test_distributive_law() {
        // 验证分配律 (a + b) * c = a*c + b*c
        let a = 2;
        let b = 3;
        let c = DecOne;
        assert_eq!((a + b) * c, a * c + b * c); // 5 * -1 = -2 + -3
    }
}

代码分析

这段代码定义了几个表示数学概念的单元类型(Zero、One、DecOne)并实现了它们的运算规则。下面将详细解释:

  1. 类型定义
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Zero;  // 表示加法单位元(0)
#[derive(Clone, Debug, Default, PartialEq, Eq)] 
pub struct One;   // 表示乘法单位元(1)
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct DecOne; // 表示乘法逆元(-1)
  1. Zero 的实现
    实现了加法单位元的性质:
  • Zero + T = T:任何数加0等于它本身

  • Zero * T = Zero:任何数乘0等于0

  • T * Zero = Zero:乘法交换律

  1. One 的实现
    实现了乘法单位元的性质:
  • One * T = T:任何数乘1等于它本身

  • T * One = T:乘法交换律

  • One + T = T + 1:特殊的加法实现(需要T支持加整数)

  1. DecOne 的实现
    实现了乘法逆元的性质:
  • DecOne * DecOne = One:-1 * -1 = 1

  • DecOne * T = -T:任何数乘-1等于它的负数

  • T * DecOne = -T:乘法交换律

  • DecOne + T = T - 1:特殊的加法实现(需要T支持减整数)

  1. 其他组合运算
    处理了这些类型之间的交互运算,如:
  • One * DecOne = DecOne

  • DecOne * One = DecOne

  1. 测试部分
    包含详尽的测试用例验证:
  • 基本运算的正确性

  • 混合运算的正确性

  • 数学定律(交换律、结合律、分配律)的验证

关键点

  1. 这些类型都是零大小的单元类型,仅用作标记

  2. 通过Rust的trait系统实现了运算符重载

  3. 实现了数学中单位元的抽象概念:

  • Zero是加法的单位元

  • One是乘法的单位元

  • DecOne是乘法的逆元

  1. 泛型实现使得这些运算可以适用于多种类型

这种实现方式在代数系统、线性代数库或符号计算中很有用,可以优雅地表示数学概念而不引入运行时开销。

相关文章:

  • Redis:概念与常用命令
  • mysql-分区和性能
  • Java项目生成接口文档的方案
  • Linux环境上传本地文件安装mysql
  • MySQL(数据表创建)
  • 【持续集成和持续部署】
  • H5DS编辑器教程——H5页面触发动画实战指南
  • 视频网站服务器网络连接不稳定该如何解决?
  • Python大数据处理 基本的编程方法
  • 《Oracle服务进程精准管控指南:23c/11g双版本内存优化实战》 ——附自动化脚本开发全攻略
  • Linux C语言获取elf文件符号信息
  • NVIDIA cuOpt:GPU加速优化AI微服务详解
  • 红宝书第十八讲:详解JavaScript的async/await与错误处理
  • 浅谈数据结构
  • 蓝桥杯 数三角
  • 阿里OSS使用指南!
  • 论文阅读笔记——ST-4DGS,WideRange4D
  • 【day24】逻辑分析与流程梳理:电子门票核销成功率巡检
  • 【数据分享】2000—2024年我国乡镇的逐年归一化植被指数(NDVI)数据(年最大值/Shp/Excel格式)
  • FFmpeg —— 实时绘制音频波形图(附源码)
  • 新华时评:任凭风云变幻,中俄关系从容前行
  • 习近平离京赴莫斯科对俄罗斯进行国事访问并出席纪念苏联伟大卫国战争胜利80周年庆典
  • 黄仁勋:中国AI市场将达500亿美元,美国企业若无法参与是巨大损失
  • 李云泽:将加快出台与房地产发展新模式相适配的系列融资制度
  • 俄乌交换205名被俘人员,俄方人员已抵达白俄罗斯
  • 重温经典|中国首部剪纸动画片《猪八戒吃瓜》创作始末