我对样条线数据 struct 做了以下定义:

#[derive(Clone, Debug)]
pub struct BSpline
{
    knots: Vec<f32>,
    control_points: Vec<Vec3>,
    /// Internal helper variable. Used to optimize repetetitive samplings on close
    /// $t$ values.
    last_t_index: usize,
    order: usize,
}

impl BSpline
{
    pub fn sample(&self, t: f32) -> Vec3
    {
        debug_assert!(self.control_points.len() >= self.order);

        let t = f32::clamp(t, self.knots[0], *self.knots.last().unwrap());

        let mut t_index = self.last_t_index;
        while !(t >= self.knots[t_index] && t <= self.knots[t_index + 1])
        {
            t_index = (t_index + 1) % self.knots.len();
        }

        // TODO(low): find a better way than this hack.
        let ptr = &self.last_t_index as *const usize as *mut usize;
        unsafe {
            ptr.write(usize::min(t_index, self.order - 1));
        };
        // Create the cache to compute the pyramid of intermediate evaluations.
        let order = self.order;
        let degree = order - 1;
        let mut evaluation = Vec::new();

        for i in 0..order
        {
            evaluation.push(self.control_points[t_index - degree + i]);
        }

        for l in 0..degree
        {
            for j in ((l + 1)..=degree).rev()
            {
                let alpha = (t - self.knots[t_index - degree + j])
                    / (self.knots[t_index - l + j] - self.knots[t_index - degree + j]);
                evaluation[j] = (1.0 - alpha) * evaluation[j - 1] + alpha * evaluation[j];
            }
        }

        evaluation[degree]
    }
}

请注意,为了使示例方法接受引用而不是可变引用,我需要做一个非常糟糕的修改.这当然会使整个数据 struct 变得不合理.

黑客攻击的原因:

  • 我需要在样条线上计算许多一般定义的微分运算符,将这些运算符定义为取FnMut而不是Fn会导致大量多余的克隆,这是有问题的.

  • 我需要速度快,我不想要来自互斥锁的开销,甚至不想来自原子布尔判断.

  • UnsafeCells不可克隆.

该代码仅用于单线程代码,在这种情况下应该可以正常工作,但这仍然是一个危险信号.我能做些什么来改善它吗?

推荐答案

last_t_index变成Cell<usize>.它提供了内部可变性,是Clone可用的,并且没有运行时开销.它通过要求.get().set()方法copy赋值来实现这一点,但对于usize来说这并不重要.

Rust相关问答推荐

展开枚举变量并返回所属值或引用

默认特征实现中的生命周期问题

AXUM一路由多个不包括URL的参数类型

我们能确定Rust会优化掉Clone()吗?如果它会立即掉落?

为什么Deref类特征不构成?

关于使用平面图功能的borrow 判断器的问题

解析程序无法在Cargo 发布中 Select 依赖版本

从 rust 函数返回 &HashMap

如何处理闭包中的生命周期以及作为参数和返回类型的闭包?

如何在 Rust 中打印 let-else 语句中的错误?

`use` 和 `crate` 关键字在 Rust 项目中效果不佳

闭包返回类型的生命周期规范

不安全块不返回预期值

如何在 Rust 中将 Vec> 转换为 Vec>?

一个函数调用会产生双重borrow 错误,而另一个则不会

如何在 Rust Polars 中可靠地连接 LazyFrames

只有一个字符被读入作为词法分析器的输入

为什么分配对变量的引用使我无法返回它

如何在宏中的多个参数上编写嵌套循环?

如何从 Rust 应用程序连接到 Docker 容器中的 SurrealDB?