#[cfg(test)]
mod tests {
extern crate test;
use std::cell::RefCell;
use std::process::Termination;
use std::rc::Rc;
use crate::{self as viffy, CacheAlignedArray, Serializable};
use crate::vector::ParameterVectorTrait;
use test::{Bencher, black_box};
#[test]
fn int_vector() {
{
let a = viffy::IntegerVector::from(5);
let b = viffy::IntegerVector::from(3);
let c = a + b;
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(c.get(i), 8);
}
}
{
let a = viffy::IntegerVector::from(5);
let b = viffy::IntegerVector::from(3);
let c = a - b;
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(c.get(i), 2);
}
}
{
let a = viffy::IntegerVector::from(5);
let b = viffy::IntegerVector::from(3);
let c = a * b;
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(c.get(i), 15);
}
}
{
let a = viffy::IntegerVector::from(5);
let b = viffy::IntegerVector::from(3);
let c = a / b;
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(c.get(i), 1);
}
}
}
#[test]
fn float_vector() {
{
let a = viffy::FloatVector::from(5.0f32);
let b = viffy::FloatVector::from(3.0f32);
let c = a + b;
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(c.get(i), 8.0f32);
}
}
{
let a = viffy::FloatVector::from(5.0f32);
let b = viffy::FloatVector::from(3.0f32);
let c = a - b;
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(c.get(i), 2.0f32);
}
}
{
let a = viffy::FloatVector::from(5.0f32);
let b = viffy::FloatVector::from(3.0f32);
let c = a * b;
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(c.get(i), 15.0f32);
}
}
{
let a = viffy::FloatVector::from(5.0f32);
let b = viffy::FloatVector::from(3.0f32);
let c = a / b;
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(c.get(i), 1.66666666667f32);
}
}
}
#[test]
fn cross_math_vector_ops() {
{
let a = viffy::math::Vector::<3>([1.0f32, 2.0f32, 3.0f32]);
let b = viffy::math::Vector::<3>([4.0f32, 5.0f32, 6.0f32]);
let c = a.cross(b);
assert_eq!(c, viffy::math::Vector::<3>([-3.0f32, 6.0f32, -3.0f32]));
}
}
#[test]
fn serializer_test() {
let mut buffer = vec![0u8; 4096];
{
let mut s = viffy::Serializer::new(&mut buffer, 0);
let tu8 = 20u8;
tu8.serialize(&mut s);
let tu16 = 3424u16;
tu16.serialize(&mut s);
let tu32 = 64738u32;
tu32.serialize(&mut s);
let tf32 = 0.543767f32;
tf32.serialize(&mut s);
}
{
let mut s = viffy::Serializer::new(&mut buffer, 0);
let mut tu8 = 0u8;
tu8.deserialize(&mut s);
assert_eq!(tu8, 20u8);
let mut tu16 = 0u16;
tu16.deserialize(&mut s);
assert_eq!(tu16, 3424u16);
let mut tu32 = 0u32;
tu32.deserialize(&mut s);
assert_eq!(tu32, 64738u32);
let mut tf32 = 0.0f32;
tf32.deserialize(&mut s);
assert_eq!(tf32, 0.543767f32);
}
}
#[test]
fn matrix_ops() {
let m = viffy::math::Matrix4x4::identity();
let v = viffy::math::Vector::<3>([1.0, 0.5, 0.25]);
let r = m.rotate(v, 0.0);
assert_eq!(r, viffy::math::Matrix4x4::identity());
let m1 = viffy::math::Matrix4x4([
[1.0, 0.0, 0.0, 1.0],
[0.0, 1.0, 0.0, 2.0],
[0.0, 0.0, 1.0, 3.0],
[0.0, 0.0, 0.0, 1.0],
]);
let m2 = viffy::math::Matrix4x4([
[2.0, 0.0, 0.0, 0.0],
[0.0, 2.0, 0.0, 0.0],
[0.0, 0.0, 2.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
]);
assert_eq!(m1 * m2, viffy::math::Matrix4x4([
[2.0, 0.0, 0.0, 1.0],
[0.0, 2.0, 0.0, 2.0],
[0.0, 0.0, 2.0, 3.0],
[0.0, 0.0, 0.0, 1.0],
]));
assert_eq!(viffy::math::Matrix4x4::identity() * viffy::math::Matrix4x4::identity(), viffy::math::Matrix4x4::identity());
let t1 = viffy::math::Matrix4x4([
[1.0, 0.0, 0.0, 1.0],
[0.0, 1.0, 0.0, 2.0],
[0.0, 0.0, 1.0, 3.0],
[0.0, 0.0, 0.0, 4.0],
]);
let t2 = viffy::math::Matrix4x4([
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[1.0, 2.0, 3.0, 4.0],
]);
assert_eq!(t1.transpose(), t2);
assert_eq!(t2.transpose(), t1);
assert_eq!(t2.transpose().transpose(), t2);
}
#[test]
fn matrix_lu_decomp() {
let m = viffy::math::Matrix4x4([
[2.0, 4.0, 3.0, 5.0],
[-4.0, -7.0, -5.0, -8.0],
[6.0, 8.0, 2.0, 9.0],
[4.0, 9.0, -2.0, 14.0],
]);
let (l, u) = m.lu_decomposition();
assert_eq!(l, viffy::math::Matrix4x4([
[1.0, 0.0, 0.0, 0.0],
[-2.0, 1.0, 0.0, 0.0],
[3.0, -4.0, 1.0, 0.0],
[2.0, 1.0, 3.0, 1.0],
]));
assert_eq!(u, viffy::math::Matrix4x4([
[2.0, 4.0, 3.0, 5.0],
[0.0, 1.0, 1.0, 2.0],
[0.0, 0.0, -3.0, 2.0],
[0.0, 0.0, 0.0, -4.0],
]));
let (l, u) = viffy::math::Matrix4x4([
[1.0, 2.0, 3.0, 0.0],
[4.0, 5.0, 6.0, 0.0],
[7.0, 8.0, 9.0, 0.0],
[0.0, 0.0, 0.0, 0.0],
]).lu_decomposition();
assert_eq!(l, viffy::math::Matrix4x4([
[1.0, 0.0, 0.0, 0.0],
[4.0, 1.0, 0.0, 0.0],
[7.0, 2.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
]));
assert_eq!(u, viffy::math::Matrix4x4([
[1.0, 2.0, 3.0, 0.0],
[0.0, -3.0, -6.0, 0.0],
[0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0],
]));
}
#[test]
fn matrix_lu_solver() {
let v = viffy::math::Matrix4x4([
[1.0, 2.0, 3.0, 0.0],
[4.0, 5.0, 6.0, 0.0],
[7.0, 8.0, 10.0, 0.0],
[0.0, 0.0, 0.0, 0.0],
]).solve_lu_vector3(viffy::math::Vector::<4>([3.0, 3.0, 4.0, 0.0]));
assert_eq!(v, viffy::math::Vector::<4>([-2.0, 1.0, 1.0, 0.0]));
}
#[test]
fn extract_and_insert() {
let mut a: viffy::IntegerVector = viffy::IntegerVector::from(10);
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(a[i], 10);
}
a[0] = 15;
assert_eq!(a[0], 15);
a[1] = 5;
assert_eq!(a[0], 15);
assert_eq!(a[1], 5);
for i in 2..viffy::VECTOR_SIZE {
assert_eq!(a[i], 10);
}
}
#[test]
fn compose_self() {
let a: viffy::IntegerVector = viffy::IntegerVector::from(10);
let b: viffy::IntegerVector = viffy::IntegerVector::from(5);
let c: viffy::IntegerVector = viffy::IntegerVector::from(0);
let d: viffy::IntegerVector = viffy::IntegerVector::from(0);
let r: viffy::IntegerVector = viffy::compose_vector((a, b, c, d), |(sa, sb, sc, sd)| {
assert_eq!(sa, 10);
assert_eq!(sb, 5);
assert_eq!(sc, 0);
assert_eq!(sd, 0);
(sa + sb + sc + sd) as i32
});
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(r.get(i), 15);
}
}
#[test]
fn contigous_properties() {
let mut a: viffy::ContigousIntegerVector = viffy::ContigousIntegerVector::from(0);
for i in 0..viffy::VECTOR_SIZE {
a[i] = (1 + i) as i32;
}
for i in 0..viffy::VECTOR_SIZE {
assert_eq!(a[i], (1 + i) as i32);
}
}
#[test]
fn fixed_bitmaps() {
let mut bmp = viffy::FixedBitmap::<16>::default();
bmp.set(0);
assert_eq!(bmp.get(0), true);
bmp.clear(0);
assert_eq!(bmp.get(0), false);
bmp.set(0);
assert_eq!(bmp.get(0), true);
bmp.clear(1);
assert_eq!(bmp.get(0), true);
}
const NORMAL_ARRAY_SIZE: usize = 0xff_ff;
const VIFFY_ARRAY_SIZE: usize = NORMAL_ARRAY_SIZE / viffy::VECTOR_SIZE;
#[inline(never)]
pub fn normal_access_1(
a: &CacheAlignedArray<i32, NORMAL_ARRAY_SIZE>,
b: &CacheAlignedArray<i32, NORMAL_ARRAY_SIZE>,
c: &mut CacheAlignedArray<i32, NORMAL_ARRAY_SIZE>
) {
for i in 0..c.len() {
black_box(a[i]);
black_box(b[i]);
}
for i in 0..a.len() {
unsafe {
*c.get_unchecked_mut(i) = *b.get_unchecked(*a.get_unchecked(i) as usize);
}
}
for i in 0..c.len() {
black_box(c[i]);
}
}
#[bench]
fn normal_access(b: &mut Bencher) -> impl Termination {
let mut a1 = CacheAlignedArray([0i32; NORMAL_ARRAY_SIZE]); let mut a2 = CacheAlignedArray([0i32; NORMAL_ARRAY_SIZE]); for i in 1..a2.len() {
a1[i] = i as i32;
a2[i] = (i as i32 * 52) + a2[i - 1];
}
let mut r1 = CacheAlignedArray([0i32; NORMAL_ARRAY_SIZE]);
b.iter(|| {
normal_access_1(&a1, &a2, &mut r1);
});
}
#[inline(never)]
pub fn viffy_access_1(
a: &CacheAlignedArray<viffy::ContigousIntegerVector, VIFFY_ARRAY_SIZE>,
b: &CacheAlignedArray<viffy::IntegerVector, VIFFY_ARRAY_SIZE>,
c: &mut CacheAlignedArray<viffy::IntegerVector, VIFFY_ARRAY_SIZE>
) {
for i in 0..c.len() {
black_box(a[i]);
black_box(b[i]);
}
for (index, icv) in a.0.iter().enumerate() {
icv.decompose_with(|id_value: i32| {
c[index].compose(|sub_index| {
unsafe {
(*b.get_unchecked(id_value as usize / 8))[sub_index]
}
});
});
}
for i in 0..c.len() {
black_box(c[i]);
}
}
#[bench]
fn viffy_access(b: &mut Bencher) -> impl Termination {
let mut a1 = CacheAlignedArray([viffy::ContigousIntegerVector::default(); VIFFY_ARRAY_SIZE]); let mut a2 = CacheAlignedArray([viffy::IntegerVector::default(); VIFFY_ARRAY_SIZE]); for i in 0..VIFFY_ARRAY_SIZE {
for j in 0..viffy::VECTOR_SIZE {
let index = (i * viffy::VECTOR_SIZE + j) as i32;
a1[i][j] = index;
if index >= 0 {
unsafe {
let prev = *(a2.as_ptr() as *const i32).add(index as usize);
a2[i][j] = (index * 52) + prev;
}
}
}
}
let mut r1 = CacheAlignedArray([viffy::IntegerVector::default(); VIFFY_ARRAY_SIZE]);
b.iter(|| {
viffy_access_1(&a1, &a2, &mut r1);
});
}
}