设计样条函子的更合理方法?

问题描述 投票:0回答:1

我对样条数据结构做了以下定义:

#[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]
    }
}

请注意,为了使示例方法采用引用而不是可变引用,我需要进行绝对可怕的黑客攻击。这当然会让整个数据结构变得不健全。

黑客攻击的原因:

  • 我需要在样条上计算大量微分运算符,这些运算符是通用定义的,将这些运算符定义为采用 FnMut 而不是 Fn 会导致大量多余的克隆,这是有问题的。

  • 我需要它很快,我不希望来自互斥体甚至原子布尔检查的开销。

  • UnsafeCell 不可克隆。

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

pointers rust unsafe type-safety
1个回答
0
投票

last_t_index
变为
Cell<usize>
。它提供内部可变性,具有
Clone
能力,并且没有运行时开销。它通过要求
.get()
.set()
方法 copy 来实现此目的,但对于
usize
来说,这是无关紧要的。

© www.soinside.com 2019 - 2024. All rights reserved.