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

8 比例缩放(scale.rs)

scale.rs代码是几何变换库euclid中典型的数据结构和方法的例子,用于处理二维和三维空间中的缩放变换。

一、scale.rs文件源码

//! A type-checked scaling factor between units.

use crate::num::One;

use crate::approxord::{max, min};
use crate::{Box2D, Box3D, Point2D, Point3D, Rect, Size2D, Vector2D};

use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::ops::{Add, Div, Mul, Sub};

#[cfg(feature = "bytemuck")]
use bytemuck::{Pod, Zeroable};
use num_traits::NumCast;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// A scaling factor between two different units of measurement.
///
/// This is effectively a type-safe float, intended to be used in combination with other types like
/// `length::Length` to enforce conversion between systems of measurement at compile time.
///
/// `Src` and `Dst` represent the units before and after multiplying a value by a `Scale`. They
/// may be types without values, such as empty enums.  For example:
///
/// ```rust
/// use euclid::Scale;
/// use euclid::Length;
/// enum Mm {};
/// enum Inch {};
///
/// let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
///
/// let one_foot: Length<f32, Inch> = Length::new(12.0);
/// let one_foot_in_mm: Length<f32, Mm> = one_foot * mm_per_inch;
/// ```
#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(bound(
        serialize = "T: serde::Serialize",
        deserialize = "T: serde::Deserialize<'de>"
    ))
)]
pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);

impl<T, Src, Dst> Scale<T, Src, Dst> {
    #[inline]
    pub const fn new(x: T) -> Self {
        Scale(x, PhantomData)
    }

    /// 创建标识比例(1.0)
    #[inline]
    pub fn identity() -> Self
    where T: One,{
        Scale::new(T::one())
    }

    /// Returns the given point transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, point2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_point(point2(42, -42)), point2(420, -420));
    /// ```
    #[inline]
    pub fn transform_point(self, point: Point2D<T, Src>) -> Point2D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Point2D::new(point.x * self.0, point.y * self.0)
    }

    /// Returns the given point transformed by this scale.
    #[inline]
    pub fn transform_point3d(self, point: Point3D<T, Src>) -> Point3D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Point3D::new(point.x * self.0, point.y * self.0, point.z * self.0)
    }

    /// Returns the given vector transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, vec2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_vector(vec2(42, -42)), vec2(420, -420));
    /// ```
    #[inline]
    pub fn transform_vector(self, vec: Vector2D<T, Src>) -> Vector2D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Vector2D::new(vec.x * self.0, vec.y * self.0)
    }

    /// Returns the given size transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, size2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_size(size2(42, -42)), size2(420, -420));
    /// ```
    #[inline]
    pub fn transform_size(self, size: Size2D<T, Src>) -> Size2D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Size2D::new(size.width * self.0, size.height * self.0)
    }

    /// Returns the given rect transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, rect};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_rect(&rect(1, 2, 42, -42)), rect(10, 20, 420, -420));
    /// ```
    #[inline]
    pub fn transform_rect(self, rect: &Rect<T, Src>) -> Rect<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Rect::new(
            self.transform_point(rect.origin),
            self.transform_size(rect.size),
        )
    }

    /// Returns the given box transformed by this scale.
    #[inline]
    pub fn transform_box2d(self, b: &Box2D<T, Src>) -> Box2D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Box2D {
            min: self.transform_point(b.min),
            max: self.transform_point(b.max),
        }
    }

    /// Returns the given box transformed by this scale.
    #[inline]
    pub fn transform_box3d(self, b: &Box3D<T, Src>) -> Box3D<T::Output, Dst>
    where T: Copy + Mul,{
        Box3D {
            min: self.transform_point3d(b.min),
            max: self.transform_point3d(b.max),
        }
    }

    /// Returns `true` if this scale has no effect.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// use euclid::num::One;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
    /// let mm_per_mm: Scale<f32, Mm, Mm> = Scale::new(1.0);
    ///
    /// assert_eq!(cm_per_mm.is_identity(), false);
    /// assert_eq!(mm_per_mm.is_identity(), true);
    /// assert_eq!(mm_per_mm, Scale::one());
    /// ```
    #[inline]
    pub fn is_identity(self) -> bool
    where T: PartialEq + One,{
        self.0 == T::one()
    }

    /// Returns the underlying scalar scale factor.
    #[inline]
    pub fn get(self) -> T {
        self.0
    }

    /// The inverse Scale (1.0 / self).
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let cm_per_mm: Scale<f32, Cm, Mm> = Scale::new(0.1);
    ///
    /// assert_eq!(cm_per_mm.inverse(), Scale::new(10.0));
    /// ```
    pub fn inverse(self) -> Scale<T::Output, Dst, Src>
    where
        T: One + Div,
    {
        let one: T = One::one();
        Scale::new(one / self.0)
    }
}

impl<T: PartialOrd, Src, Dst> Scale<T, Src, Dst> {
    #[inline]
    pub fn min(self, other: Self) -> Self {
        Self::new(min(self.0, other.0))
    }

    #[inline]
    pub fn max(self, other: Self) -> Self {
        Self::new(max(self.0, other.0))
    }

    /// Returns the point each component of which clamped by corresponding
    /// components of `start` and `end`.
    ///
    /// Shortcut for `self.max(start).min(end)`.
    #[inline]
    pub fn clamp(self, start: Self, end: Self) -> Self
    where
        T: Copy,
    {
        self.max(start).min(end)
    }
}

impl<T: NumCast, Src, Dst> Scale<T, Src, Dst> {
    /// Cast from one numeric representation to another, preserving the units.
    ///
    /// # Panics
    ///
    /// If the source value cannot be represented by the target type `NewT`, then
    /// method panics. Use `try_cast` if that must be case.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.cast::<f32>(), Scale::new(10.0));
    /// ```
    /// That conversion will panic, because `i32` not enough to store such big numbers:
    /// ```rust,should_panic
    /// use euclid::Scale;
    /// enum Mm {};// millimeter = 10^-2 meters
    /// enum Em {};// exameter   = 10^18 meters
    ///
    /// // Panics
    /// let to_em: Scale<i32, Mm, Em> = Scale::new(10e20).cast();
    /// ```
    #[inline]
    pub fn cast<NewT: NumCast>(self) -> Scale<NewT, Src, Dst> {
        self.try_cast().unwrap()
    }

    /// Fallible cast from one numeric representation to another, preserving the units.
    /// If the source value cannot be represented by the target type `NewT`, then `None`
    /// is returned.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    /// enum Em {};// Exameter = 10^18 meters
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    /// let to_em: Scale<f32, Mm, Em> = Scale::new(10e20);
    ///
    /// assert_eq!(to_mm.try_cast::<f32>(), Some(Scale::new(10.0)));
    /// // Integer to small to store that number
    /// assert_eq!(to_em.try_cast::<i32>(), None);
    /// ```
    pub fn try_cast<NewT: NumCast>(self) -> Option<Scale<NewT, Src, Dst>> {
        NumCast::from(self.0).map(Scale::new)
    }
}

#[cfg(feature = "arbitrary")]
impl<'a, T, Src, Dst> arbitrary::Arbitrary<'a> for Scale<T, Src, Dst>
where
    T: arbitrary::Arbitrary<'a>,
{
    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
        Ok(Scale::new(arbitrary::Arbitrary::arbitrary(u)?))
    }
}

#[cfg(feature = "bytemuck")]
unsafe impl<T: Zeroable, Src, Dst> Zeroable for Scale<T, Src, Dst> {}

#[cfg(feature = "bytemuck")]
unsafe impl<T: Pod, Src: 'static, Dst: 'static> Pod for Scale<T, Src, Dst> {}

// scale0 * scale1
// (A,B) * (B,C) = (A,C)
impl<T: Mul, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
    type Output = Scale<T::Output, A, C>;

    #[inline]
    fn mul(self, other: Scale<T, B, C>) -> Self::Output {
        Scale::new(self.0 * other.0)
    }
}

// scale0 + scale1
impl<T: Add, Src, Dst> Add for Scale<T, Src, Dst> {
    type Output = Scale<T::Output, Src, Dst>;

    #[inline]
    fn add(self, other: Scale<T, Src, Dst>) -> Self::Output {
        Scale::new(self.0 + other.0)
    }
}

// scale0 - scale1
impl<T: Sub, Src, Dst> Sub for Scale<T, Src, Dst> {
    type Output = Scale<T::Output, Src, Dst>;

    #[inline]
    fn sub(self, other: Scale<T, Src, Dst>) -> Self::Output {
        Scale::new(self.0 - other.0)
    }
}

// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
// https://github.com/rust-lang/rust/issues/26925

impl<T: PartialEq, Src, Dst> PartialEq for Scale<T, Src, Dst> {
    fn eq(&self, other: &Scale<T, Src, Dst>) -> bool {
        self.0 == other.0
    }
}

impl<T: Eq, Src, Dst> Eq for Scale<T, Src, Dst> {}

impl<T: PartialOrd, Src, Dst> PartialOrd for Scale<T, Src, Dst> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.0.partial_cmp(&other.0)
    }
}

impl<T: Ord, Src, Dst> Ord for Scale<T, Src, Dst> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.0.cmp(&other.0)
    }
}

impl<T: Clone, Src, Dst> Clone for Scale<T, Src, Dst> {
    fn clone(&self) -> Scale<T, Src, Dst> {
        Scale::new(self.0.clone())
    }
}

impl<T: Copy, Src, Dst> Copy for Scale<T, Src, Dst> {}

impl<T: fmt::Debug, Src, Dst> fmt::Debug for Scale<T, Src, Dst> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T: Default, Src, Dst> Default for Scale<T, Src, Dst> {
    fn default() -> Self {
        Self::new(T::default())
    }
}

impl<T: Hash, Src, Dst> Hash for Scale<T, Src, Dst> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

impl<T: One, Src, Dst> One for Scale<T, Src, Dst> {
    #[inline]
    fn one() -> Self {
        Scale::new(T::one())
    }
}

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

    enum Inch {}
    enum Cm {}
    enum Mm {}

    #[test]
    fn test_scale() {
        let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
        let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);

        let mm_per_cm: Scale<f32, Cm, Mm> = cm_per_mm.inverse();
        assert_eq!(mm_per_cm.get(), 10.0);

        let one: Scale<f32, Mm, Mm> = cm_per_mm * mm_per_cm;
        assert_eq!(one.get(), 1.0);

        let one: Scale<f32, Cm, Cm> = mm_per_cm * cm_per_mm;
        assert_eq!(one.get(), 1.0);

        let cm_per_inch: Scale<f32, Inch, Cm> = mm_per_inch * cm_per_mm;
        //  mm     cm     cm
        // ---- x ---- = ----
        // inch    mm    inch
        assert_eq!(cm_per_inch, Scale::new(2.54));

        let a: Scale<isize, Inch, Inch> = Scale::new(2);
        let b: Scale<isize, Inch, Inch> = Scale::new(3);
        assert_ne!(a, b);
        assert_eq!(a, a.clone());
        assert_eq!(a.clone() + b.clone(), Scale::new(5));
        assert_eq!(a - b, Scale::new(-1));

        // Clamp
        assert_eq!(Scale::identity().clamp(a, b), a);
        assert_eq!(Scale::new(5).clamp(a, b), b);
        let a = Scale::<f32, Inch, Inch>::new(2.0);
        let b = Scale::<f32, Inch, Inch>::new(3.0);
        let c = Scale::<f32, Inch, Inch>::new(2.5);
        assert_eq!(c.clamp(a, b), c);
    }
}

二、结构体定义

#[repr(C)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde",
    serde(bound(
        serialize = "T: serde::Serialize",
        deserialize = "T: serde::Deserialize<'de>"
    ))
)]
pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);

上面代码定义了一个使用Rust语言特性的泛型结构体Scale,这个结构体不仅使用了Rust的条件编译指令,还考虑了序列化/反序列化的能力,如果项目中启用了serde特性。下面是对这段代码的详细解释:

  1. #[repr( C )]:这个属性指定了结构体应该使用C语言的布局规则。这意味着结构体的内存布局将与C语言中的等效结构相匹配,这对于与C语言代码交互或与需要特定内存布局的系统API交互非常有用。
  2. #[cfg_attr(feature = “serde”, derive(Serialize, Deserialize))]:这是条件编译属性的一个示例。如果项目配置了serde特性(通常在Cargo.toml文件中通过features部分指定),那么将为这个结构体派生Serialize和Deserialize特性。这两个特性来自serde库,允许结构体实例被序列化为JSON、RON等格式或从这些格式反序列化。
  3. #[cfg_attr(… serde(bound(…)) )]:这部分进一步细化了serde特性的条件编译。它指定了当序列化或反序列化时,泛型参数T必须满足的条件。具体来说,如果正在序列化,T必须实现serde::Serialize;如果正在反序列化,T必须实现serde::Deserialize<'de>。这里,'de是一个生命周期参数,它是反序列化过程中使用的,表明反序列化操作与特定数据的生命周期相关联。
  4. pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);:这是Scale结构体的定义。它是一个泛型结构体,有三个类型参数:T、Src和Dst。结构体内部包含两个字段:
  • 第一个字段是公开的(pub T),意味着它可以被外部访问。
  • 第二个字段是PhantomData<(Src, Dst)>,它被标记为#[doc(hidden)],意味着在生成的文档中这个字段将被隐藏。PhantomData是一个特殊的类型,用于在类型系统中表达所有权、借用或生命周期,但不占用任何运行时空间。在这里,它用于表示Scale结构体与Src和Dst类型有关联,尽管这两个类型在运行时并不实际存储任何数据。
  1. 总结:这段代码定义了一个条件编译支持序列化/反序列化,同时遵循C语言内存布局规则的泛型结构体,用于在Rust代码中表示某种形式的缩放或转换操作,其中T代表缩放或转换的值类型,而Src和Dst则用于在类型系统中表达源和目标类型的信息。

三、对应方法

方法源码

impl<T, Src, Dst> Scale<T, Src, Dst> {
    #[inline]
    pub const fn new(x: T) -> Self {
        Scale(x, PhantomData)
    }

    /// 创建标识比例(1.0)
    #[inline]
    pub fn identity() -> Self
    where T: One,{
        Scale::new(T::one())
    }

    /// Returns the given point transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, point2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_point(point2(42, -42)), point2(420, -420));
    /// ```
    #[inline]
    pub fn transform_point(self, point: Point2D<T, Src>) -> Point2D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Point2D::new(point.x * self.0, point.y * self.0)
    }

    /// Returns the given point transformed by this scale.
    #[inline]
    pub fn transform_point3d(self, point: Point3D<T, Src>) -> Point3D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Point3D::new(point.x * self.0, point.y * self.0, point.z * self.0)
    }

    /// Returns the given vector transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, vec2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_vector(vec2(42, -42)), vec2(420, -420));
    /// ```
    #[inline]
    pub fn transform_vector(self, vec: Vector2D<T, Src>) -> Vector2D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Vector2D::new(vec.x * self.0, vec.y * self.0)
    }

    /// Returns the given size transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, size2};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_size(size2(42, -42)), size2(420, -420));
    /// ```
    #[inline]
    pub fn transform_size(self, size: Size2D<T, Src>) -> Size2D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Size2D::new(size.width * self.0, size.height * self.0)
    }

    /// Returns the given rect transformed by this scale.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::{Scale, rect};
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let to_mm: Scale<i32, Cm, Mm> = Scale::new(10);
    ///
    /// assert_eq!(to_mm.transform_rect(&rect(1, 2, 42, -42)), rect(10, 20, 420, -420));
    /// ```
    #[inline]
    pub fn transform_rect(self, rect: &Rect<T, Src>) -> Rect<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Rect::new(
            self.transform_point(rect.origin),
            self.transform_size(rect.size),
        )
    }

    /// Returns the given box transformed by this scale.
    #[inline]
    pub fn transform_box2d(self, b: &Box2D<T, Src>) -> Box2D<T::Output, Dst>
    where
        T: Copy + Mul,
    {
        Box2D {
            min: self.transform_point(b.min),
            max: self.transform_point(b.max),
        }
    }

    /// Returns the given box transformed by this scale.
    #[inline]
    pub fn transform_box3d(self, b: &Box3D<T, Src>) -> Box3D<T::Output, Dst>
    where T: Copy + Mul,{
        Box3D {
            min: self.transform_point3d(b.min),
            max: self.transform_point3d(b.max),
        }
    }

    /// Returns `true` if this scale has no effect.
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// use euclid::num::One;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
    /// let mm_per_mm: Scale<f32, Mm, Mm> = Scale::new(1.0);
    ///
    /// assert_eq!(cm_per_mm.is_identity(), false);
    /// assert_eq!(mm_per_mm.is_identity(), true);
    /// assert_eq!(mm_per_mm, Scale::one());
    /// ```
    #[inline]
    pub fn is_identity(self) -> bool
    where T: PartialEq + One,{
        self.0 == T::one()
    }

    /// Returns the underlying scalar scale factor.
    #[inline]
    pub fn get(self) -> T {
        self.0
    }

    /// The inverse Scale (1.0 / self).
    ///
    /// # Example
    ///
    /// ```rust
    /// use euclid::Scale;
    /// enum Mm {};
    /// enum Cm {};
    ///
    /// let cm_per_mm: Scale<f32, Cm, Mm> = Scale::new(0.1);
    ///
    /// assert_eq!(cm_per_mm.inverse(), Scale::new(10.0));
    /// ```
    pub fn inverse(self) -> Scale<T::Output, Dst, Src>
    where
        T: One + Div,
    {
        let one: T = One::one();
        Scale::new(one / self.0)
    }
}

2、new 方法:

这是一个常量函数,用于创建一个新的 Scale 实例。它接受一个类型为 T 的参数 x 作为缩放因子。

3、identity 方法:

用于创建一个表示没有缩放的 Scale 实例(即缩放因子为 1.0)。这需要 T 类型实现 One trait,该 trait 提供了一个获取类型中“1”的方法。

4、transform_point 方法:

用于将二维点(Point2D<T, Src>)根据缩放因子变换到新的单位系统(Dst)。这个方法要求 T 类型实现 Copy 和 Mul traits,以便可以复制和乘法操作。

5、transform_point3d 方法:

类似于 transform_point,但是用于三维点(Point3D<T, Src>)。

6、is_identity 方法:

检查当前的缩放因子是否为 1.0(即是否没有缩放)。这要求 T 类型实现 PartialEq 和 One traits。

7、get 方法:

返回缩放因子 x。

8、inverse 方法:

返回当前缩放的逆缩放,即将 1.0 / self.0 作为新的缩放因子。这要求 T 类型实现 One 和 Div traits。

9、min和max方法的实现:

min和max方法分别返回两个Scale实例之间较小或较大的那个。它们使用内部存储的值(self.0)来调用标准库中的min和max函数。

10、clamp方法的实现:

clamp方法将当前Scale实例的每个分量限制在start和end指定的范围内。这是通过先对start使用max方法,然后对end使用min方法来实现的,从而确保结果位于start和end之间。

11、NumCast trait相关的实现:

这部分代码被注释掉了,似乎原本打算为Scale实现一个与数值类型转换相关的功能,允许从一种数值表示转换到另一种,但具体的实现被省略了。

12、partial_cmp、cmp方法的实现:

  • partial_cmp方法提供了一个可选的比较结果,这在类型T只能部分排序时非常有用(例如,浮点数与NaN的比较)。
  • cmp方法提供了一个确定性的比较结果,要求T必须完全可排序(实现Ord trait)。

13、Clone、Copy trait的实现:

为Scale实现了Clone和Copy trait,这取决于T是否也实现了这些trait。如果T可以克隆或复制,那么Scale<T, Src, Dst>也可以。

14、Debug trait的实现:

为Scale实现了Debug trait,允许其实例使用{:?}格式化时打印调试信息。这依赖于T也实现了Debug trait。

15、Default trait的实现:

为Scale实现了Default trait,提供了一个默认构造函数,它依赖于T也实现了Default trait。

16、Hash trait的实现:

为Scale实现了Hash trait,允许其实例被哈希。这依赖于T也实现了Hash trait。

17、One trait的实现:

为Scale实现了One trait,提供了一个单位元素的构造函数(即值为1的Scale实例)。这依赖于T也实现了One trait。


http://www.kler.cn/a/528411.html

相关文章:

  • 17.2 图形绘制7
  • FIDL:Flutter与原生通讯的新姿势,不局限于基础数据类型
  • 网络工程师 (8)存储管理
  • 2025年大年初一篇,C#调用GPU并行计算推荐
  • Android --- CameraX讲解
  • C#面试常考随笔7:什么是匿名⽅法?还有Lambda表达式?
  • 我用Ai学Android Jetpack Compose之Row
  • .Net Web API 访问权限限定
  • JavaFX - 3D 形状
  • 如何使用 ChatBox AI 简化本地模型对话操作
  • ROS-激光雷达模块学习[粗]
  • 算法随笔_35: 每日温度
  • kamailio-ACC_JSON模块详解【后端语言go】
  • 数据结构(1)——算法时间复杂度与空间复杂度
  • 4. 劲舞团python解法——2024年省赛蓝桥杯真题
  • Kafka分区策略实现
  • 有没有个性化的UML图例
  • DevEco Studio的previewer一直转圈缓冲无法打开
  • 高性能消息队列Disruptor
  • 使用 Spring JDBC 进行数据库操作:深入解析 JdbcTemplate
  • dfs枚举问题
  • 【深度学习】softmax回归的从零开始实现
  • 想学习JAVA编程,请问应该如何去学习?
  • 深度学习之“线性代数”
  • DeepSeek超越ChatGPT的能力及部分核心原理
  • 算法【多重背包】