use geo_nd::{Vector, Vector3D};
use std::marker::PhantomData;
struct Banana<V: Vector3D<f32>> {
p: PhantomData<V>,
}
impl<V2, V3, V4, V> Banana<V>
where
V2: Vector<f32, 2> + From<[f32; 2]>,
V3: Vector<f32, 3> + From<[f32; 3]>,
V4: Vector<f32, 4> + From<[f32; 4]>,
V: Vector3D<f32, Vec2 = V2, Vec3 = V3, Vec4 = V4>,
{
fn test_vecn_len_dist<T: Vector<f32, D>, const D: usize>(
zero: T,
ones: T,
v: T,
v_len2: f32,
v_o_dist2: f32,
) {
assert_eq!(zero.length(), 0., "Length of zero vector is 0");
assert_eq!(zero.length_sq(), 0., "Length^2 of zero vector is 0");
let v_len = v_len2.sqrt();
assert_eq!(v.length(), v_len, "Length of 3,4,12 vector is 13");
assert_eq!(v.length_sq(), v_len2, "Length^2 of 3,4,12 vector is 13");
assert_eq!(v.distance(&zero), v_len, "Separation is 13");
assert_eq!(v.distance_sq(&zero), v_len2, "Separation^2 is 13");
assert_eq!(
ones.length_sq(),
D as f32,
"Length^2 of ones vector is #dim"
);
assert_eq!((ones * 0.).length(), 0., "Length of ones*0 is 0");
assert_eq!((ones * 1.).length_sq(), D as f32, "Length of ones*1 is 13");
assert_eq!((ones / 1.).length_sq(), D as f32, "Length of ones/1 is 13");
assert_eq!(
(ones + zero).length_sq(),
D as f32,
"Length of ones + zero is 13"
);
assert_eq!(
(ones - zero).length_sq(),
D as f32,
"Length of ones + zero is 13"
);
assert_eq!((v * 0.).length(), 0., "Length of v*0 is 0");
assert_eq!((v * 1.).length(), v_len, "Length of v*1 is 13");
assert_eq!((v / 1.).length(), v_len, "Length of v/1 is 13");
assert_eq!((v + zero).length(), v_len, "Length of v + zero is 13");
assert_eq!((v - zero).length(), v_len, "Length of v + zero is 13");
assert_eq!((v * 2.).length(), 2. * v_len, "Length of v*2 is 26");
assert_eq!(
(v.distance_sq(&ones)),
v_o_dist2,
"Distance^2 of v-ones is 134"
);
assert_eq!(((-v) + zero).length(), v_len, "Length of (-v) + zero is 13");
assert_eq!(((-v) + v).length(), 0., "Length of (-v) + v is 0");
}
fn test_vecn_index<T: Vector<f32, D>, const D: usize>(
zero: T,
ones: T,
v: T,
n: usize,
vn: f32,
) {
assert_eq!(zero[n], 0., "zero has coordinate N of 0.");
assert_eq!(ones[n], 1., "ones has coordinate N of 1.");
assert_eq!(v[n], vn, "v has coordinate N of vn");
assert_eq!((v - zero)[n], vn, "v-zeros has coordinate N of vn");
assert_eq!((v - ones)[n], vn - 1., "v-ones has coordinate N of vn-1");
assert_eq!((v * 0.)[n], 0., "v*[0.] has coordinate N of 0");
assert_eq!((v * 1.)[n], vn, "v*[1.] has coordinate N of vn");
assert_eq!((v * 0.)[n], 0., "v*[0.] has coordinate N of 0");
assert_eq!((v * 1.)[n], vn, "v*[1.] has coordinate N of vn");
let mut d = v;
assert_eq!(d[n], vn);
d += ones;
assert_eq!(d[n], vn + 1.);
assert_eq!(d[n], vn + 1.);
d -= ones;
assert_eq!(d[n], vn);
d += d;
d *= 3.;
d -= v;
d /= 5.;
assert_eq!(d[n], vn);
}
fn test_vec4() {
let zero = V4::default();
let ones = [1.0, 1., 1., 1.].into();
let b = [3., 4., 12., 84.].into();
Self::test_vecn_len_dist(zero, ones, b, 85. * 85., 134. + 83. * 83.);
Self::test_vecn_index(zero, ones, b, 0, 3.);
Self::test_vecn_index(zero, ones, b, 1, 4.);
Self::test_vecn_index(zero, ones, b, 2, 12.);
Self::test_vecn_index(zero, ones, b, 3, 84.);
}
fn test_vec3() {
let zero = V3::default();
let ones = [1., 1., 1.].into();
let b = [3., 4., 12.].into();
Self::test_vecn_len_dist(zero, ones, b, 169., 134.);
Self::test_vecn_index(zero, ones, b, 0, 3.);
Self::test_vecn_index(zero, ones, b, 1, 4.);
Self::test_vecn_index(zero, ones, b, 2, 12.);
}
fn test_vec2() {
let zero = V2::default();
let ones = [1., 1.].into();
let b = [3., 4.].into();
Self::test_vecn_len_dist(zero, ones, b, 25., 13.);
Self::test_vecn_index(zero, ones, b, 0, 3.);
Self::test_vecn_index(zero, ones, b, 1, 4.);
}
}
#[test]
fn test_fslice() {
Banana::<f32>::test_vec2();
Banana::<f32>::test_vec3();
Banana::<f32>::test_vec4();
}