g3 0.1.4

Neat library for computer graphics based on geometric algebra
Documentation
#![feature(portable_simd)]
#[cfg(test)]
mod tests {
  use g3::*;

  const EPSILON: f32 = 0.02;
  fn approx_eq(result: [f32; 4], expected: [f32; 4]) {
    assert_eq!(result.len(), expected.len());
    for (i, a) in result.iter().enumerate() {
      let b = expected[i];
      assert!((a - b).abs() < EPSILON, "{:?} ≉ {:?}, at index {:}", result, expected, i);
    }
  }

  #[test] fn rotor_log_exp() {
    let r = rotor(pi * 0.5, 0.3, -3.0, 1.0);
    let b = r.log();
    let s = b.exp();
    assert!(r.approx_eq(s, EPSILON));
  }

  #[test] fn rotor_sqrt() {
    let r = rotor(pi/2.0, 0.3, -3.0, 1.0);
    let s = r.sqrt();
    let n = s * s;
    assert!(r.approx_eq(n, EPSILON));
  }

  #[test] fn motor_exp_log_sqrt() {
    let r = rotor(pi/2.0, 0.3, -3.0, 1.0);
    let t = translator(12.0, -2.0, 0.4, 1.0);
    let m1 = r * t;
    let l = m1.log();
    let m2 = l.exp();
    assert!(m1.approx_eq(m2, EPSILON));
    let m3 = m1.sqrt() * m1.sqrt();
    assert!(m1.approx_eq(m3, EPSILON));
  }

  #[test] fn motor_slerp() {
    // Construct a motor from a translator and rotor
    let r = rotor(pi/2.0, 0.3, -3.0, 1.0);
    let t = translator(12.0, -2.0, 0.4, 1.0);
    let m1 = r * t;
    let l = m1.log();
    // Divide the motor action into three equal steps
    let step = l / 3.0;
    let m_step = step.exp();
    let m2 = m_step * m_step * m_step;
    assert!(m1.approx_eq(m2, EPSILON));
  }

  #[test] fn motor_blend() {
    let r1 = rotor(pi/2.0, 0.0, 0.0, 1.0);
    let t1 = translator(1.0, 0.0, 0.0, 1.0);
    let m1 = r1 * t1;

    let r2 = rotor(pi/2.0, 0.3, -3.0, 1.0);
    let t2 = translator(12.0, -2.0, 0.4, 1.0);
    let m2 = r2 * t2;

    let motion = m2 * m1.reverse();
    let step = motion.log() / 4.0;
    let motor_step = step.exp();

    // Applying motor_step 0 times to m1 is m1.
    // Applying motor_step 4 times to m1 is m2 * ~m1;
    let r = motor_step * motor_step * motor_step * motor_step * m1;
    assert!(r.approx_eq(m2, EPSILON));
  }

  #[test] fn translator_motor_log() {
    let t = translator(1.0, 1.0, 2.0, 3.0);
    t.log();
    let m:Motor = t.into();
    let l = m.log();
    approx_eq([l.e01(), l.e02(), l.e03(), 0.0], [m.e01(), m.e02(), m.e03(), 0.0]);
  }

  #[test] fn ideal_motor_step() {
    let r1 = rotor(0.0, 0.0, 0.0, 1.0);
    let t1 = translator(1.0, 0.0, 0.0, 1.0);
    let m1 = r1 * t1;
    let step = m1.log() / 4.0;
    let motor_step = step.exp();
    // Applying motor_step 4 times should recover the translator t1 (embedded) in m1
    let m3 = motor_step * motor_step * motor_step * motor_step;
    assert!(m3.approx_eq(m1, EPSILON));
  }
}