<commit_before>#![feature(test)]

extern crate test;
extern crate variable_size_byte_writer;

use test::Bencher;
use variable_size_byte_writer::*;

#[bench]
fn write_59bits_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let mut target = std::io::Cursor::new(vec![]);

    let bits = test::black_box(59);
    bench.iter(|| writer.write(&mut target, 0x7A25555_ABABFFFF, bits));
}

#[bench]
fn write_59bits_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let _res = std::fs::create_dir("benches/temp");
    let mut file = std::fs::File::create("benches/temp/write_64_file.temp").unwrap();

    let bits = test::black_box(59);
    bench.iter(|| writer.write(&mut file, 0x7A25555_ABABFFFF, bits));
    std::fs::remove_file("benches/temp/write_64_file.temp").unwrap();
}

#[bench]
fn write_21bits_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let mut target = std::io::Cursor::new(vec![]);

    let bits = test::black_box(21);
    bench.iter(|| writer.write_32(&mut target, 0x7_F1F0, bits));
}

#[bench]
fn write_21bits_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let _res = std::fs::create_dir("benches/temp");
    let mut file = std::fs::File::create("benches/temp/write_32_file.temp").unwrap();

    let bits = test::black_box(21);
    bench.iter(|| writer.write(&mut file, 0x7_F1F0, bits));
    std::fs::remove_file("benches/temp/write_32_file.temp").unwrap();
}

#[bench]
fn write_7bits_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let mut target = std::io::Cursor::new(vec![]);

    let bits = test::black_box(7);
    bench.iter(|| writer.write_8(&mut target, 0x1A, bits));
}

#[bench]
fn write_7bits_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let _res = std::fs::create_dir("benches/temp");
    let mut file = std::fs::File::create("benches/temp/write_8_file.temp").unwrap();
    let bits = test::black_box(7);
    bench.iter(|| writer.write_8(&mut file, 0x1A, bits));
    std::fs::remove_file("benches/temp/write_8_file.temp").unwrap();
}<commit_msg>fixed benches<commit_after>#![feature(test)]

extern crate test;
extern crate variable_size_byte_writer;

use test::Bencher;
use variable_size_byte_writer::*;

#[bench]
fn write_59bits_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let mut target = std::io::Cursor::new(vec![]);

    let bits = test::black_box(59);
    bench.iter(|| writer.write(&mut target, 0x7A25555_ABABFFFF, bits));
}

#[bench]
fn write_59bits_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let _res = std::fs::create_dir("benches/temp");
    let mut file = std::fs::File::create("benches/temp/write_64_file.temp").unwrap();

    let bits = test::black_box(59);
    bench.iter(|| writer.write(&mut file, 0x7A25555_ABABFFFF, bits));

    std::fs::remove_file("benches/temp/write_64_file.temp").unwrap();
}

#[bench]
fn write_21bits_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let mut target = std::io::Cursor::new(vec![]);

    let bits = test::black_box(21);
    bench.iter(|| writer.write(&mut target, 0x7_F1F0, bits));
}

#[bench]
fn write_21bits_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let _res = std::fs::create_dir("benches/temp");
    let mut file = std::fs::File::create("benches/temp/write_32_file.temp").unwrap();

    let bits = test::black_box(21);
    bench.iter(|| writer.write(&mut file, 0x7_F1F0, bits));

    std::fs::remove_file("benches/temp/write_32_file.temp").unwrap();
}

#[bench]
fn write_7bits_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let mut target = std::io::Cursor::new(vec![]);

    let bits = test::black_box(7);
    bench.iter(|| writer.write(&mut target, 0x1A, bits));
}

#[bench]
fn write_7bits_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new();
    let _res = std::fs::create_dir("benches/temp");

    let mut file = std::fs::File::create("benches/temp/write_8_file.temp").unwrap();
    let bits = test::black_box(7);
    bench.iter(|| writer.write(&mut file, 0x1A, bits));

    std::fs::remove_file("benches/temp/write_8_file.temp").unwrap();
}<|endoftext|>


<commit_before>#![feature(phase)]
#![allow(uppercase_variables)]

#[phase(plugin, link)] extern crate itertools;
extern crate test;
extern crate ndarray;

use ndarray::{Array, S, Si};
use ndarray::{arr0, arr1, arr2};

#[test]
fn test_matmul_rcarray()
{
    let mut A: Array<uint, (uint, uint)> = Array::zeros((2u, 3u));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let mut B: Array<uint, (uint, uint)> = Array::zeros((3u, 4u));
    for (i, elt) in B.iter_mut().enumerate() {
        *elt = i;
    }

    let c = A.mat_mul(&B);
    println!("A = \n{}", A);
    println!("B = \n{}", B);
    println!("A x B = \n{}", c);
    unsafe {
        let result = Array::from_vec_dim((2u, 4u), vec![20u, 23, 26, 29, 56, 68, 80, 92]);
        assert_eq!(c.shape(), result.shape());
        assert!(c.iter().zip(result.iter()).all(|(a,b)| a == b));
        assert!(c == result);
    }
}

#[test]
fn test_slice()
{
    let mut A: Array<uint, (uint, uint)> = Array::zeros((3u, 4u));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let vi = A.slice([Si(1, None, 1), Si(0, None, 2)]);
    assert_eq!(vi.shape(), &[2u, 2u]);
    let vi = A.slice([S, S]);
    assert_eq!(vi.shape(), A.shape());
    assert!(vi.iter().zip(A.iter()).all(|(a, b)| a == b));
}

#[test]
fn test_index()
{
    let mut A: Array<uint, (uint, uint)> = Array::zeros((2u, 3u));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    for ((i, j), x) in iproduct!(range(0,2u), range(0,3u)).zip(A.iter()) {
        assert_eq!(*x, A[(i, j)]);
    }

    let vi = A.slice([Si(1, None, 1), Si(0, None, 2)]);
    let mut it = vi.iter();
    for (i, j) in iproduct!(range(0, 1u), range(0, 2u)) {
        let x = it.next().unwrap();
        assert_eq!(*x, vi[(i, j)]);
    }
    assert!(it.next().is_none());
}

#[test]
fn test_add()
{
    let mut A: Array<uint, (uint, uint)> = Array::zeros((2u, 2u));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let B = A.clone();
    A.iadd(&B);
    assert_eq!(A[(0,0)], 0u);
    assert_eq!(A[(0,1)], 2u);
    assert_eq!(A[(1,0)], 4u);
    assert_eq!(A[(1,1)], 6u);
}

#[test]
fn test_multidim()
{
    let mut mat = Array::zeros(2u*3*4*5*6).reshape((2u,3u,4u,5u,6u));
    mat[(0,0,0,0,0)] = 22u8;
    {
        for (i, elt) in mat.iter_mut().enumerate() {
            *elt = i as u8;
        }
    }
    //println!("shape={}, strides={}", mat.shape(), mat.strides);
    assert_eq!(mat.shape(), &[2u,3,4,5,6]);
}

/*
array([[[ 7,  6],
        [ 5,  4],
        [ 3,  2],
        [ 1,  0]],

       [[15, 14],
        [13, 12],
        [11, 10],
        [ 9,  8]]])
*/
#[test]
fn test_negative_stride_rcarray()
{
    let mut mat = Array::zeros((2u, 4u, 2u));
    mat[(0, 0, 0)] = 1.0f32;
    for (i, elt) in mat.iter_mut().enumerate() {
        *elt = i as f32;
    }

    {
        let vi = mat.slice([S, Si(0, None, -1), Si(0, None, -1)]);
        assert_eq!(vi.shape(), &[2,4,2]);
        // Test against sequential iterator
        let seq = [7f32,6., 5.,4.,3.,2.,1.,0.,15.,14.,13., 12.,11.,  10.,   9.,   8.];
        for (a, b) in vi.clone().iter().zip(seq.iter()) {
            assert_eq!(*a, *b);
        }
    }
    {
        let vi = mat.slice([S, Si(0, None, -5), S]);
        let seq = [6_f32, 7., 14., 15.];
        for (a, b) in vi.iter().zip(seq.iter()) {
            assert_eq!(*a, *b);
        }
    }
}

#[test]
fn test_cow()
{
    let mut mat = Array::<int, _>::zeros((2u,2u));
    mat[(0, 0)] = 1;
    let n = mat.clone();
    mat[(0, 1)] = 2;
    mat[(1, 0)] = 3;
    mat[(1, 1)] = 4;
    assert_eq!(mat[(0,0)], 1);
    assert_eq!(mat[(0,1)], 2);
    assert_eq!(n[(0,0)], 1);
    assert_eq!(n[(0,1)], 0);
    let mut rev = mat.reshape(4u).slice([Si(0, None, -1)]);
    assert_eq!(rev[0], 4);
    assert_eq!(rev[1], 3);
    assert_eq!(rev[2], 2);
    assert_eq!(rev[3], 1);
    let before = rev.clone();
    // mutation
    rev[0] = 5;
    assert_eq!(rev[0], 5);
    assert_eq!(rev[1], 3);
    assert_eq!(rev[2], 2);
    assert_eq!(rev[3], 1);
    assert_eq!(before[0], 4);
    assert_eq!(before[1], 3);
    assert_eq!(before[2], 2);
    assert_eq!(before[3], 1);
}

#[test]
fn test_sub()
{
    let mat = Array::from_iter(range(0.0f32, 16.0)).reshape((2u, 4u, 2u));
    let s1 = mat.subview(0,0);
    let s2 = mat.subview(0,1);
    assert_eq!(s1.shape(), &[4, 2]);
    assert_eq!(s2.shape(), &[4, 2]);
    let n = Array::from_iter(range(8.0f32, 16.0)).reshape((4u,2u));
    assert_eq!(n, s2);
    let m = Array::from_vec(vec![2f32, 3., 10., 11.]).reshape((2u, 2u));
    assert_eq!(m, mat.subview(1, 1));
}

#[test]
fn diag()
{
    let d = arr2::<f32>([[1., 2., 3.0f32]]).diag();
    assert_eq!(d.shape(), &[1]);
    let d = arr2::<f32>([[1., 2., 3.0f32], [0., 0., 0.]]).diag();
    assert_eq!(d.shape(), &[2]);
    let d = arr2::<f32>([]).diag();
    assert_eq!(d.shape(), &[0]);
    let d = Array::<f32, _>::zeros(()).diag();
    assert_eq!(d.shape(), &[1]);
}

#[test]
fn swapaxes()
{
    let mut a = arr2::<f32>([[1., 2.], [3., 4.0f32]]);
    let     b = arr2::<f32>([[1., 3.], [2., 4.0f32]]);
    assert!(a != b);
    a.swap_axes(0, 1);
    assert_eq!(a, b);
    a.swap_axes(1, 1);
    assert_eq!(a, b);
    assert_eq!(a.raw_data(), &[1., 2., 3., 4.]);
    assert_eq!(b.raw_data(), &[1., 3., 2., 4.]);
}

#[test]
fn standard_layout()
{
    let mut a = arr2::<f32>([[1., 2.], [3., 4.0]]);
    assert!(a.is_standard_layout());
    a.swap_axes(0, 1);
    assert!(!a.is_standard_layout());
    a.swap_axes(0, 1);
    assert!(a.is_standard_layout());
    let x1 = a.subview(0, 0);
    assert!(x1.is_standard_layout());
    let x2 = a.subview(1, 0);
    assert!(!x2.is_standard_layout());
}

#[test]
fn assign()
{
    let mut a = arr2::<f32>([[1., 2.], [3., 4.]]);
    let     b = arr2::<f32>([[1., 3.], [2., 4.]]);
    a.assign(&b);
    assert_eq!(a, b);

    /* Test broadcasting */
    a.assign(&Array::zeros(1u));
    assert_eq!(a, Array::zeros((2u, 2u)));
}

#[test]
fn dyn_dimension()
{
    let a = arr2::<f32>([[1., 2.], [3., 4.0]]).reshape(vec![2u, 2]);
    assert_eq!(a - a, Array::zeros(vec![2u,2u]));

    let mut dim = Vec::from_elem(1024, 1u);
    dim.as_mut_slice()[16] = 4;
    dim.as_mut_slice()[17] = 3;
    let z = Array::<f32, Vec<uint>>::zeros(dim.clone());
    assert_eq!(z.shape(), dim.as_slice());
}

#[test]
fn sum_mean()
{
    let a = arr2::<f32>([[1., 2.], [3., 4.]]);
    assert_eq!(a.sum(0), arr1([4., 6.]));
    assert_eq!(a.sum(1), arr1([3., 7.]));
    assert_eq!(a.mean(0), arr1([2., 3.]));
    assert_eq!(a.mean(1), arr1([1.5, 3.5]));
    assert_eq!(a.sum(1).sum(0), arr0(10.));
}

#[test]
fn iter_size_hint()
{
    let mut a = arr2::<f32>([[1., 2.], [3., 4.]]);
    {
        let mut it = a.iter();
        assert_eq!(it.size_hint(), (4, Some(4)));
        it.next();
        assert_eq!(it.size_hint().val0(), 3);
        it.next();
        assert_eq!(it.size_hint().val0(), 2);
        it.next();
        assert_eq!(it.size_hint().val0(), 1);
        it.next();
        assert_eq!(it.size_hint().val0(), 0);
        assert!(it.next().is_none());
        assert_eq!(it.size_hint().val0(), 0);
    }

    a.swap_axes(0, 1);
    {
        let mut it = a.iter();
        assert_eq!(it.size_hint(), (4, Some(4)));
        it.next();
        assert_eq!(it.size_hint().val0(), 3);
        it.next();
        assert_eq!(it.size_hint().val0(), 2);
        it.next();
        assert_eq!(it.size_hint().val0(), 1);
        it.next();
        assert_eq!(it.size_hint().val0(), 0);
        assert!(it.next().is_none());
        assert_eq!(it.size_hint().val0(), 0);
    }
}

#[test]
fn zero_axes()
{
    let a = arr1::<f32>([]);
    for elt in a.iter() {
        assert!(false);
    }
    println!("{}", a);
    let b = arr2::<f32>([[], [], [], []]);
    println!("{}\n{}", b.shape(), b);

    // we can even get a subarray of b
    let bsub = b.subview(0, 2);
    assert_eq!(bsub.dim(), 0);
}
<commit_msg>Port tests/array.rs<commit_after>#![feature(phase)]
#![allow(uppercase_variables)]

#[phase(plugin, link)] extern crate itertools;
extern crate test;
extern crate ndarray;

use ndarray::{Array, S, Si};
use ndarray::{arr0, arr1, arr2};
use ndarray::{d1, d2, d3, Ix};

#[test]
fn test_matmul_rcarray()
{
    let mut A = Array::<uint, _>::zeros(d2(2, 3));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let mut B = Array::<uint, _>::zeros(d2(3, 4));
    for (i, elt) in B.iter_mut().enumerate() {
        *elt = i;
    }

    let c = A.mat_mul(&B);
    println!("A = \n{}", A);
    println!("B = \n{}", B);
    println!("A x B = \n{}", c);
    unsafe {
        let result = Array::from_vec_dim(d2(2, 4), vec![20u, 23, 26, 29, 56, 68, 80, 92]);
        assert_eq!(c.shape(), result.shape());
        assert!(c.iter().zip(result.iter()).all(|(a,b)| a == b));
        assert!(c == result);
    }
}

#[test]
fn test_slice()
{
    let mut A = Array::<uint, _>::zeros(d2(3, 4));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let vi = A.slice([Si(1, None, 1), Si(0, None, 2)]);
    assert_eq!(vi.shape(), &[2, 2]);
    let vi = A.slice([S, S]);
    assert_eq!(vi.shape(), A.shape());
    assert!(vi.iter().zip(A.iter()).all(|(a, b)| a == b));
}

#[test]
fn test_index()
{
    let mut A = Array::<uint, _>::zeros(d2(2, 3));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    for ((i, j), x) in iproduct!(range::<Ix>(0,2), range::<Ix>(0,3)).zip(A.iter()) {
        assert_eq!(*x, A[(i, j)]);
    }

    let vi = A.slice([Si(1, None, 1), Si(0, None, 2)]);
    let mut it = vi.iter();
    for (i, j) in iproduct!(range::<Ix>(0, 1), range::<Ix>(0, 2)) {
        let x = it.next().unwrap();
        assert_eq!(*x, vi[(i, j)]);
    }
    assert!(it.next().is_none());
}

#[test]
fn test_add()
{
    let mut A = Array::<uint, _>::zeros(d2(2, 2));
    for (i, elt) in A.iter_mut().enumerate() {
        *elt = i;
    }

    let B = A.clone();
    A.iadd(&B);
    assert_eq!(A[(0,0)], 0u);
    assert_eq!(A[(0,1)], 2u);
    assert_eq!(A[(1,0)], 4u);
    assert_eq!(A[(1,1)], 6u);
}

#[test]
fn test_multidim()
{
    let mut mat = Array::zeros(2u32*3*4*5*6).reshape((2u32,3u32,4u32,5u32,6u32));
    mat[(0,0,0,0,0)] = 22u8;
    {
        for (i, elt) in mat.iter_mut().enumerate() {
            *elt = i as u8;
        }
    }
    //println!("shape={}, strides={}", mat.shape(), mat.strides);
    assert_eq!(mat.shape(), &[2u32,3,4,5,6]);
}

/*
array([[[ 7,  6],
        [ 5,  4],
        [ 3,  2],
        [ 1,  0]],

       [[15, 14],
        [13, 12],
        [11, 10],
        [ 9,  8]]])
*/
#[test]
fn test_negative_stride_rcarray()
{
    let mut mat = Array::zeros(d3(2, 4, 2));
    mat[(0, 0, 0)] = 1.0f32;
    for (i, elt) in mat.iter_mut().enumerate() {
        *elt = i as f32;
    }

    {
        let vi = mat.slice([S, Si(0, None, -1), Si(0, None, -1)]);
        assert_eq!(vi.shape(), &[2,4,2]);
        // Test against sequential iterator
        let seq = [7f32,6., 5.,4.,3.,2.,1.,0.,15.,14.,13., 12.,11.,  10.,   9.,   8.];
        for (a, b) in vi.clone().iter().zip(seq.iter()) {
            assert_eq!(*a, *b);
        }
    }
    {
        let vi = mat.slice([S, Si(0, None, -5), S]);
        let seq = [6_f32, 7., 14., 15.];
        for (a, b) in vi.iter().zip(seq.iter()) {
            assert_eq!(*a, *b);
        }
    }
}

#[test]
fn test_cow()
{
    let mut mat = Array::<int, _>::zeros(d2(2,2));
    mat[(0, 0)] = 1;
    let n = mat.clone();
    mat[(0, 1)] = 2;
    mat[(1, 0)] = 3;
    mat[(1, 1)] = 4;
    assert_eq!(mat[(0,0)], 1);
    assert_eq!(mat[(0,1)], 2);
    assert_eq!(n[(0,0)], 1);
    assert_eq!(n[(0,1)], 0);
    let mut rev = mat.reshape(d1(4)).slice([Si(0, None, -1)]);
    assert_eq!(rev[0], 4);
    assert_eq!(rev[1], 3);
    assert_eq!(rev[2], 2);
    assert_eq!(rev[3], 1);
    let before = rev.clone();
    // mutation
    rev[0] = 5;
    assert_eq!(rev[0], 5);
    assert_eq!(rev[1], 3);
    assert_eq!(rev[2], 2);
    assert_eq!(rev[3], 1);
    assert_eq!(before[0], 4);
    assert_eq!(before[1], 3);
    assert_eq!(before[2], 2);
    assert_eq!(before[3], 1);
}

#[test]
fn test_sub()
{
    let mat = Array::from_iter(range(0.0f32, 16.0)).reshape(d3(2, 4, 2));
    let s1 = mat.subview(0,0);
    let s2 = mat.subview(0,1);
    assert_eq!(s1.shape(), &[4, 2]);
    assert_eq!(s2.shape(), &[4, 2]);
    let n = Array::from_iter(range(8.0f32, 16.0)).reshape(d2(4,2));
    assert_eq!(n, s2);
    let m = Array::from_vec(vec![2f32, 3., 10., 11.]).reshape(d2(2, 2));
    assert_eq!(m, mat.subview(1, 1));
}

#[test]
fn diag()
{
    let d = arr2::<f32>([[1., 2., 3.0f32]]).diag();
    assert_eq!(d.shape(), &[1]);
    let d = arr2::<f32>([[1., 2., 3.0f32], [0., 0., 0.]]).diag();
    assert_eq!(d.shape(), &[2]);
    let d = arr2::<f32>([]).diag();
    assert_eq!(d.shape(), &[0]);
    let d = Array::<f32, _>::zeros(()).diag();
    assert_eq!(d.shape(), &[1]);
}

#[test]
fn swapaxes()
{
    let mut a = arr2::<f32>([[1., 2.], [3., 4.0f32]]);
    let     b = arr2::<f32>([[1., 3.], [2., 4.0f32]]);
    assert!(a != b);
    a.swap_axes(0, 1);
    assert_eq!(a, b);
    a.swap_axes(1, 1);
    assert_eq!(a, b);
    assert_eq!(a.raw_data(), &[1., 2., 3., 4.]);
    assert_eq!(b.raw_data(), &[1., 3., 2., 4.]);
}

#[test]
fn standard_layout()
{
    let mut a = arr2::<f32>([[1., 2.], [3., 4.0]]);
    assert!(a.is_standard_layout());
    a.swap_axes(0, 1);
    assert!(!a.is_standard_layout());
    a.swap_axes(0, 1);
    assert!(a.is_standard_layout());
    let x1 = a.subview(0, 0);
    assert!(x1.is_standard_layout());
    let x2 = a.subview(1, 0);
    assert!(!x2.is_standard_layout());
}

#[test]
fn assign()
{
    let mut a = arr2::<f32>([[1., 2.], [3., 4.]]);
    let     b = arr2::<f32>([[1., 3.], [2., 4.]]);
    a.assign(&b);
    assert_eq!(a, b);

    /* Test broadcasting */
    a.assign(&Array::zeros(d1(1)));
    assert_eq!(a, Array::zeros(d2(2, 2)));
}

#[test]
fn dyn_dimension()
{
    let a = arr2::<f32>([[1., 2.], [3., 4.0]]).reshape(vec![2u32, 2]);
    assert_eq!(a - a, Array::zeros(vec![2u32, 2]));

    let mut dim = Vec::from_elem(1024, 1 as Ix);
    dim.as_mut_slice()[16] = 4;
    dim.as_mut_slice()[17] = 3;
    let z = Array::<f32, _>::zeros(dim.clone());
    assert_eq!(z.shape(), dim.as_slice());
}

#[test]
fn sum_mean()
{
    let a = arr2::<f32>([[1., 2.], [3., 4.]]);
    assert_eq!(a.sum(0), arr1([4., 6.]));
    assert_eq!(a.sum(1), arr1([3., 7.]));
    assert_eq!(a.mean(0), arr1([2., 3.]));
    assert_eq!(a.mean(1), arr1([1.5, 3.5]));
    assert_eq!(a.sum(1).sum(0), arr0(10.));
}

#[test]
fn iter_size_hint()
{
    let mut a = arr2::<f32>([[1., 2.], [3., 4.]]);
    {
        let mut it = a.iter();
        assert_eq!(it.size_hint(), (4, Some(4)));
        it.next();
        assert_eq!(it.size_hint().val0(), 3);
        it.next();
        assert_eq!(it.size_hint().val0(), 2);
        it.next();
        assert_eq!(it.size_hint().val0(), 1);
        it.next();
        assert_eq!(it.size_hint().val0(), 0);
        assert!(it.next().is_none());
        assert_eq!(it.size_hint().val0(), 0);
    }

    a.swap_axes(0, 1);
    {
        let mut it = a.iter();
        assert_eq!(it.size_hint(), (4, Some(4)));
        it.next();
        assert_eq!(it.size_hint().val0(), 3);
        it.next();
        assert_eq!(it.size_hint().val0(), 2);
        it.next();
        assert_eq!(it.size_hint().val0(), 1);
        it.next();
        assert_eq!(it.size_hint().val0(), 0);
        assert!(it.next().is_none());
        assert_eq!(it.size_hint().val0(), 0);
    }
}

#[test]
fn zero_axes()
{
    let a = arr1::<f32>([]);
    for elt in a.iter() {
        assert!(false);
    }
    println!("{}", a);
    let b = arr2::<f32>([[], [], [], []]);
    println!("{}\n{}", b.shape(), b);

    // we can even get a subarray of b
    let bsub = b.subview(0, 2);
    assert_eq!(bsub.dim(), 0);
}
<|endoftext|>


<commit_before>use tokio_core::io::EasyBuf;

use protocol::Response;

#[test]
fn test_response_get_from_easybuf() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x00,
        0x04, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x09,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0xde, 0xad, 0xbe, 0xef,
        0x57, 0x6f, 0x72, 0x6c,
        0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);

    assert_eq!(response.extras().unwrap(), [0xde, 0xad, 0xbe, 0xef]);
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"World");
}

#[test]
fn test_response_getk_from_easybuf() {
    // I dunno why, but memcached doc have a mistake here,
    // it says that instead of `0x0e` body length byte
    // there should be a `0x09` which is wrong.
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x05,
        0x04, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x0e,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0xde, 0xad, 0xbe, 0xef,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f, 0x57, 0x6f, 0x72,
        0x6c, 0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);

    assert_eq!(response.extras().unwrap(), [0xde, 0xad, 0xbe, 0xef]);
    assert_eq!(response.key().unwrap(), b"Hello");
    assert_eq!(response.value().unwrap(), b"World");

}<commit_msg>Response parsing tests<commit_after>use tokio_core::io::EasyBuf;

use protocol::Response;

#[test]
fn test_response_get_from_easybuf() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x00,
        0x04, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x09,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0xde, 0xad, 0xbe, 0xef,
        0x57, 0x6f, 0x72, 0x6c,
        0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);

    assert_eq!(response.extras().unwrap(), [0xde, 0xad, 0xbe, 0xef]);
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"World");
}

#[test]
fn test_response_getk_from_easybuf() {
    // I dunno why, but memcached doc have a mistake here,
    // it says that instead of `0x0e` "total body length" byte
    // there should be a `0x09` which is looks totally wrong.
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x05,
        0x04, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x0e,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0xde, 0xad, 0xbe, 0xef,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f, 0x57, 0x6f, 0x72,
        0x6c, 0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);

    assert_eq!(response.extras().unwrap(), [0xde, 0xad, 0xbe, 0xef]);
    assert_eq!(response.key().unwrap(), b"Hello");
    assert_eq!(response.value().unwrap(), b"World");
}

#[test]
fn test_response_cas() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x02, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x02);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert_eq!(*response.cas(), 0x0000000000000001);

    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert!(response.value().is_none());
}

#[test]
fn test_response_incr_not_exists() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x05, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x05);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert_eq!(*response.cas(), 0x0000000000000005);

    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}

#[test]
fn test_response_version() {
    /*
    Byte/     0       |       1       |       2       |       3       |
        /              |               |               |               |
       |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
       +---------------+---------------+---------------+---------------+
      0| 0x81          | 0x0b          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
      4| 0x00          | 0x00          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
      8| 0x00          | 0x00          | 0x00          | 0x05          |
       +---------------+---------------+---------------+---------------+
     12| 0x00          | 0x00          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
     16| 0x00          | 0x00          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
     20| 0x00          | 0x00          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
     24| 0x31 ('1')    | 0x2e ('.')    | 0x33 ('3')    | 0x2e ('.')    |
       +---------------+---------------+---------------+---------------+
     28| 0x31 ('1')    |
       +---------------+
       Total 29 bytes (24 byte header, 5 byte body)

   Field        (offset) (value)
   Magic        (0)    : 0x81
   Opcode       (1)    : 0x0b
   Key length   (2,3)  : 0x0000
   Extra length (4)    : 0x00
   Data type    (5)    : 0x00
   Status       (6,7)  : 0x0000
   Total body   (8-11) : 0x00000005
   Opaque       (12-15): 0x00000000
   CAS          (16-23): 0x0000000000000000
   Extras              : None
   Key                 : None
   Value               : Textual string "1.3.1"
    */
    let mut buf = EasyBuf::from(vec![
        0x81, 0x0b, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x31, 0x2e, 0x33, 0x2e,
        0x31,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x0b);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"1.3.1");
}

#[test]
fn test_response_error_not_found() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x09,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x4e, 0x6f, 0x74, 0x20,
        0x66, 0x6f, 0x75, 0x6e,
        0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0001);
    assert_eq!(*response.data_type(), 0x00);
    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"Not found");
}<|endoftext|>


<commit_before>use proto::metapb;
use super::engine::Mutator;
use super::keys;
use raftserver::{Result, other};

// How do we organize the route meta key to determine the region a key belongs to?
//
// We use 2 hash (meta1, meta2) to route the key.
// Meta1 is always located in region1 and can't be split. Meta2 can be split into
// different regions.
// For a given key, first we find in meta1 to know which meta2 has this key,
// then find in meta2 and know where the really data region is.
//
// The region route meta key for a region is encoded with a meta prefix + region end key.
// E,g, if a data region key range is ["123", "999"), the relevant meta2 key is
//  meta2 prefix + "999"
// Why using the end key but not start key? We use seek in RocksDB to search the key, if we have
// 2 regions ["111", "222"), ["222", "333") and encode the key with start key, the layout may be:
//  \x00\x03"111" -> region 2
//  \x00\x03"222" -> region 3
// If we want to find key "123", using seek we may get `\x00\x03"222"`, but not `\x00\x03"111"`,
// (Rocksdb seeks the key >= given key), so we must move back to get the correct region.

trait RouteMetaAction <T: Mutator>{
    fn handle(&self, w: &T, key: &[u8], region: &metapb::Region) -> Result<()>;
}

struct PutRouteMetaAction;

impl<T: Mutator> RouteMetaAction<T> for PutRouteMetaAction {
    fn handle(&self, w: &T, key: &[u8], region: &metapb::Region) -> Result<()> {
        try!(w.put_msg(key, region));
        Ok(())
    }
}

struct DeleteRouteMetaAction;

impl<T: Mutator> RouteMetaAction<T> for DeleteRouteMetaAction {
    fn handle(&self, w: &T, key: &[u8], _: &metapb::Region) -> Result<()> {
        try!(w.delete(key));
        Ok(())
    }
}

fn put_route_meta<T: Mutator>(w: &T, key: &[u8], region: &metapb::Region) -> Result<()> {
    try!(w.put_msg(key, region));
    Ok(())
}

fn del_route_meta<T: Mutator>(w: &T, key: &[u8], _: &metapb::Region) -> Result<()> {
    try!(w.delete(key));
    Ok(())
}

pub fn split_region_route<T: Mutator>(w: &T,
                                      left: &metapb::Region,
                                      right: &metapb::Region)
                                      -> Result<()> {
    try!(handle_region_route(w, left, PutRouteMetaAction));
    try!(handle_region_route(w, right, PutRouteMetaAction));
    Ok(())
}

pub fn update_region_route<T: Mutator>(w: &T, region: &metapb::Region) -> Result<()> {
    try!(handle_region_route(w, region, PutRouteMetaAction));
    Ok(())
}

fn handle_region_route<T: Mutator, F: RouteMetaAction<T>>(w: &T,
                                                          region: &metapb::Region,
                                                          action: F)
                                                          -> Result<()> {
    let start_key = region.get_start_key();
    let end_key = region.get_end_key();

    // We can't split meta1.
    if end_key.starts_with(keys::META1_PREFIX_KEY) ||
       start_key.starts_with(keys::META1_PREFIX_KEY) {
        return Err(other("meta1 route can't be split"));
    }

    // If regions end_key ends with a meta2 prefix, updates relevant meta1.
    if end_key.starts_with(keys::META2_PREFIX_KEY) {
        try!(action.handle(w, &keys::region_route_meta_key(end_key), region));
    } else {
        // The regions ends with a normal data key, updates relevant meta2.
        try!(action.handle(w, &vec![keys::META2_PREFIX_KEY, end_key].concat(), region));

        // The regions start_key starts with MIN_KEY or meta2 prefix, updates meta1 KEY_MAX.
        if start_key == keys::MIN_KEY || start_key.starts_with(keys::META2_PREFIX_KEY) {
            try!(action.handle(w,
                               &vec![keys::META1_PREFIX_KEY, keys::MAX_KEY].concat(),
                               region));
        }
    }

    Ok(())
}

// Checks whether the key to split the route is valid or not.
pub fn validate_route_meta_split_key(key: &[u8]) -> bool {
    // TODO: should we consider META2_MAX_KEY as invalid key?
    if key == keys::META2_MAX_KEY {
        return false;
    }

    // Meta1 can't be split.
    if key >= keys::MIN_KEY && key < keys::META2_PREFIX_KEY {
        return false;
    }

    return true;

}
<commit_msg>raftserver: update region route meta doc.<commit_after>use proto::metapb;
use super::engine::Mutator;
use super::keys;
use raftserver::{Result, other};

// How do we organize the route meta key to determine the region a key belongs to?
//
// We use 2 hash (meta1, meta2) to route the key.
// Meta1 is always located in region1 and can't be split. Meta2 can be split into
// different regions.
// For a given key, first we find in meta1 to know which meta2 has this key,
// then find in meta2 and know where the really data region is.
//
// The region route meta key for a region is encoded with a meta prefix + region end key.
// E,g, if a data region key range is ["123", "999"), the relevant meta2 key is
//  meta2 prefix + "999"
// Why using the end key but not start key? We use seek in RocksDB to search the key, if we have
// 2 regions ["111", "222"), ["222", "333") and encode the key with start key, the layout may be:
//  \x00\x03"111" -> region 2
//  \x00\x03"222" -> region 3
// If we want to find key "123", using seek we may get `\x00\x03"222"`, but not `\x00\x03"111"`,
// (Rocksdb seeks the key >= given key), so we must move back to get the correct region.
//
// So for a key like "123", the route flow is:
//  1, find meta2 region using key \x00\0x02"123" in meta1.
//  2, find data region using key \x00\x03"123" in meta2.
//  3, find data using key "123".
//
// Client should cache all region route meta so that it can send the commands to the relevant region
// directly and correctly. If the request key is not in the region, clients should re-flesh the cache
// from placement driver first then re-send again.

trait RouteMetaAction <T: Mutator>{
    fn handle(&self, w: &T, key: &[u8], region: &metapb::Region) -> Result<()>;
}

struct PutRouteMetaAction;

impl<T: Mutator> RouteMetaAction<T> for PutRouteMetaAction {
    fn handle(&self, w: &T, key: &[u8], region: &metapb::Region) -> Result<()> {
        try!(w.put_msg(key, region));
        Ok(())
    }
}

struct DeleteRouteMetaAction;

impl<T: Mutator> RouteMetaAction<T> for DeleteRouteMetaAction {
    fn handle(&self, w: &T, key: &[u8], _: &metapb::Region) -> Result<()> {
        try!(w.delete(key));
        Ok(())
    }
}

fn put_route_meta<T: Mutator>(w: &T, key: &[u8], region: &metapb::Region) -> Result<()> {
    try!(w.put_msg(key, region));
    Ok(())
}

fn del_route_meta<T: Mutator>(w: &T, key: &[u8], _: &metapb::Region) -> Result<()> {
    try!(w.delete(key));
    Ok(())
}

pub fn split_region_route<T: Mutator>(w: &T,
                                      left: &metapb::Region,
                                      right: &metapb::Region)
                                      -> Result<()> {
    try!(handle_region_route(w, left, PutRouteMetaAction));
    try!(handle_region_route(w, right, PutRouteMetaAction));
    Ok(())
}

pub fn update_region_route<T: Mutator>(w: &T, region: &metapb::Region) -> Result<()> {
    try!(handle_region_route(w, region, PutRouteMetaAction));
    Ok(())
}

fn handle_region_route<T: Mutator, F: RouteMetaAction<T>>(w: &T,
                                                          region: &metapb::Region,
                                                          action: F)
                                                          -> Result<()> {
    let start_key = region.get_start_key();
    let end_key = region.get_end_key();

    // We can't split meta1.
    if end_key.starts_with(keys::META1_PREFIX_KEY) ||
       start_key.starts_with(keys::META1_PREFIX_KEY) {
        return Err(other("meta1 route can't be split"));
    }

    // If regions end_key ends with a meta2 prefix, updates relevant meta1.
    if end_key.starts_with(keys::META2_PREFIX_KEY) {
        try!(action.handle(w, &keys::region_route_meta_key(end_key), region));
    } else {
        // The regions ends with a normal data key, updates relevant meta2.
        try!(action.handle(w, &vec![keys::META2_PREFIX_KEY, end_key].concat(), region));

        // The regions start_key starts with MIN_KEY or meta2 prefix, updates meta1 KEY_MAX.
        if start_key == keys::MIN_KEY || start_key.starts_with(keys::META2_PREFIX_KEY) {
            try!(action.handle(w,
                               &vec![keys::META1_PREFIX_KEY, keys::MAX_KEY].concat(),
                               region));
        }
    }

    Ok(())
}

// Checks whether the key to split the route is valid or not.
pub fn validate_route_meta_split_key(key: &[u8]) -> bool {
    // TODO: should we consider META2_MAX_KEY as invalid key?
    if key == keys::META2_MAX_KEY {
        return false;
    }

    // Meta1 can't be split.
    if key >= keys::MIN_KEY && key < keys::META2_PREFIX_KEY {
        return false;
    }

    return true;

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate macros;
extern crate rustc_serialize;
extern crate byteorder;

use std::net::{TcpListener, TcpStream};

rpc_service!(my_server:
    hello(String) -> String;
    add((i32, i32)) -> i32;
);

use my_server::*;

impl Service for () {
    fn hello(&self, s: String) -> String {
        format!("Hello, {}", s)
    }

    fn add(&self, (x, y): (i32, i32)) -> i32 {
        x + y
    }
}

fn main() {
    println!("Starting");
    let listener = TcpListener::bind("127.0.0.1:9000").unwrap();
    std::thread::spawn(|| {
        let server = Server::new(());
        println!("Server running");
        server.serve(listener);
    });
    let mut client = Client(TcpStream::connect("127.0.0.1:9000").unwrap());
    println!("Client running");
    println!("add((1, 2)) => {}", client.add((1, 2)).unwrap());
    println!("hello(\"adam\") => {:?}", client.hello("Adam".into()));
}
<commit_msg>main to use a struct Foo<commit_after>#[macro_use]
extern crate macros;
extern crate rustc_serialize;
extern crate byteorder;

use std::net::{TcpListener, TcpStream};

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Foo {
    message: String
}

rpc_service!(my_server:
    hello(::Foo) -> ::Foo;
    add((i32, i32)) -> i32;
);

use my_server::*;

impl Service for () {
    fn hello(&self, s: Foo) -> Foo {
        Foo{message: format!("Hello, {}", &s.message)}
    }

    fn add(&self, (x, y): (i32, i32)) -> i32 {
        x + y
    }
}

fn main() {
    println!("Starting");
    let listener = TcpListener::bind("127.0.0.1:9000").unwrap();
    std::thread::spawn(|| {
        let server = Server::new(());
        println!("Server running");
        server.serve(listener);
    });
    let mut client = Client(TcpStream::connect("127.0.0.1:9000").unwrap());
    println!("Client running");
    println!("add((1, 2)) => {}", client.add((1, 2)).unwrap());
    println!("hello(\"adam\") => {:?}", client.hello(Foo{message: "Adam".into()}));
}
<|endoftext|>


<commit_before>use autograd::{Function, FuncIntf, FuncDelegate, Variable, VarId, FIWrap};
use tensor::{RefTensorList, RefTensorKindList, TensorList, TensorKindList, OptTensorKindList};

#[builder(pattern="owned")]
#[derive(Builder, Clone)]
pub struct NLLLossArgs {
    #[builder(default="false")]
    pub size_average: bool,
    #[builder(default="None")]
    pub weight: Option<VarId>,
}

impl Default for NLLLossArgs {
    fn default() -> Self {
        NLLLossArgsBuilder::default().build().unwrap()
    }
}

impl_func_args!(NLLLoss, NLLLossArgs);

impl FuncIntf for NLLLoss {
    fn forward(&mut self, input: &mut TensorKindList) -> TensorKindList {
        unimplemented!();
    }
    fn backward(&mut self, input: &mut OptTensorKindList) -> OptTensorKindList {
        unimplemented!();
    }
}
<commit_msg>remove unneeded file for loss<commit_after><|endoftext|>


<commit_before>
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

use primes;

pub mod util;
use util::t_log;

const MAX_SIZE: usize = 300;
const HEURISTIC_LIMIT: u64 = 14;

pub struct Chunk {
    pub low: u64,
    pub high: u64,
}

pub struct FactorialWorker {
    mutex_table: Mutex<HashMap<u64,[u64; MAX_SIZE]>>,
    mutex_factorization_worker: Mutex<FactorizationWorker>,
}

impl FactorialWorker {
    pub fn new() -> FactorialWorker {
        t_log("FactorialWorker constructor");
        FactorialWorker {
            mutex_table: Mutex::new(HashMap::new()),
            mutex_factorization_worker: Mutex::new(FactorizationWorker::new()),
        }
    }

    fn get_factorial(&mut self, n: u64) -> [u64;  MAX_SIZE] {
        let mut table = self.mutex_table.lock().unwrap();
        if table.contains_key(&n) {
            // println!("TRACER cache hit!");
            *table.get(&n).unwrap()
        } else {
            let result = self.compute_factorial(n);
            table.insert(n, result);
            result
        }
    }

    fn compute_factorial(&self, n: u64) -> [u64;  MAX_SIZE] {
        let mut result: [u64; MAX_SIZE] = [0; MAX_SIZE];
        let mut factorization_worker = self.mutex_factorization_worker.lock().unwrap();
        for i in 0..n+1 {
            let factor = factorization_worker.get_factorization(i);
            for j in 0..MAX_SIZE {
                result[j] += factor[j];
            }
        }
        result
    }
}

struct FactorizationWorker {
    mutex: Mutex<HashMap<u64,[u64; MAX_SIZE]>>,
}

impl FactorizationWorker {
    fn new() -> FactorizationWorker {
        t_log("FactorizationWorker constructor");
        FactorizationWorker {
            mutex: Mutex::new(HashMap::new()),
        }
    }

    fn get_factorization(&mut self, n: u64) -> [u64;  MAX_SIZE] {
        let mut table = self.mutex.lock().unwrap();
        if table.contains_key(&n) {
            // println!("TRACER cache hit!");
            *table.get(&n).unwrap()
        } else {
            let result = self.compute_factorization(n);
            table.insert(n, result);
            result
        }
    }

    fn compute_factorization(&self, n: u64) -> [u64;  MAX_SIZE] {
       let mut result: [u64; MAX_SIZE] = [0; MAX_SIZE];
       let factors = primes::factors(n);
       for i in factors {
           // println!("TRACER g_f i {}", i);
           result[i as usize] += 1;
       }
       result
    }
}

fn my_compare(a: &[u64; MAX_SIZE], b: &[u64; MAX_SIZE], c: &[u64; MAX_SIZE]) -> bool {
    let mut result = true;

    for i in 0..MAX_SIZE {
        if a[i] + b[i] != c[i] {
            result = false;
            return result;
        }
    }

    result
}

fn my_log(a: &[u64; MAX_SIZE]) {
    let mut s = String::new();

    for i in 0..MAX_SIZE {
        if a[i] > 0 {
            s.push_str(&format!("{}^{} ", i, a[i]));
        }
    }

    t_log(&format!("\nTRACER {}\n", s));
}

#[allow(dead_code)]
fn my_log_triplet(a: &[u64; MAX_SIZE], b: &[u64; MAX_SIZE], c: &[u64; MAX_SIZE]) {
    my_log(a);
    my_log(b);
    my_log(c);
}

fn do_stop_early(a_factorial: &[u64; MAX_SIZE], b_factorial: &[u64; MAX_SIZE],
                    c_factorial: &[u64; MAX_SIZE], c: u64) -> bool {
    let mut result = false;

    if c < HEURISTIC_LIMIT {
        let a_number = get_number(a_factorial);
        let b_number = get_number(b_factorial);
        let c_number = get_number(c_factorial);
        // println!("TRACER is_greater_than {} {} {}", a_number, b_number, c_number);
        result = (a_number * b_number) > c_number
    }
    result
}

// TODO: handle the inevitable overflow panic
fn get_number(n: &[u64; MAX_SIZE]) -> u64 {
    let mut result: u64 = 1;

    // my_log(n);
    for i in 0..MAX_SIZE {
        if n[i] > 0 {
            let value = i as u64;
            result *= u64::pow(value, n[i] as u32);
        }
    }

    result
}

pub fn find_factors(chunk: &Chunk, factorial_worker_mutex: &Arc<Mutex<FactorialWorker>>) {
    let c_low = chunk.low;
    let c_high = chunk.high;
    let check_frequency = 10;
    let mut count = 1;

    for c in c_low..c_high {
        let mut factorial_worker = factorial_worker_mutex.lock().unwrap();

        for a in 1..c {
            for b in a..c {
                let a_factorial = factorial_worker.get_factorial(a);
                let b_factorial = factorial_worker.get_factorial(b);
                let c_factorial = factorial_worker.get_factorial(c);
                let do_check = count % check_frequency == 0;
                if do_check && do_stop_early(&a_factorial, &b_factorial, &c_factorial, c) {
                    // println!("TRACER early eject :: {}! x {}! > {}!", a, b, c);
                    break;
                } else {
                    if my_compare(&a_factorial, &b_factorial, &c_factorial) {
                        t_log(&format!("TRACER HIT :: {}! x {}! = {}!", a, b, c));
                    }
                }
                count += 1;
            }
        }
    }

    t_log(&format!("TRACER COMPLETE {} {}", c_low, c_high));
}

#[allow(unused_imports)]
mod tests {
    use super::*;

    #[test]
    fn test_get_number() {
        let mut factorial_worker = FactorialWorker::new();
        let n = 4;
        let n_factorial = factorial_worker.get_factorial(n);

        // test
        let result = get_number(&n_factorial);

        assert_eq!(result, 24);
    }

    #[test]
    fn test_do_stop_early_sanity() {
        let mut factorial_worker = FactorialWorker::new();
        let a_factorial = factorial_worker.get_factorial(6);
        let b_factorial = factorial_worker.get_factorial(7);
        let c: u64 = 10;
        let c_factorial = factorial_worker.get_factorial(c);

        // test
        let result = do_stop_early(&a_factorial, &b_factorial, &c_factorial, c);

        assert_eq!(result, false);
    }

    #[test]
    fn test_do_stop_early_yes() {
        let mut factorial_worker = FactorialWorker::new();
        let a_factorial = factorial_worker.get_factorial(4);
        let b_factorial = factorial_worker.get_factorial(5);
        let c: u64 = 6;
        let c_factorial = factorial_worker.get_factorial(c);

        // test
        let result = do_stop_early(&a_factorial, &b_factorial, &c_factorial, c);

        assert_eq!(result, true);
    }

    #[test]
    fn test_do_stop_early_overflow_check() {
        let mut factorial_worker = FactorialWorker::new();
        let a_factorial = factorial_worker.get_factorial(9);
        let b_factorial = factorial_worker.get_factorial(11);
        let c: u64 = 14;
        let c_factorial = factorial_worker.get_factorial(c);

        // test
        let result = do_stop_early(&a_factorial, &b_factorial, &c_factorial, c);

        assert_eq!(result, false);
    }

    #[test]
    fn test_compute_factorization() {
        let factorization_worker = FactorizationWorker::new();
        let n = 120;

        // test
        let result = factorization_worker.compute_factorization(n);

        assert_eq!(result[2], 3);
        assert_eq!(result[3], 1);
        assert_eq!(result[5], 1);
    }

    #[test]
    fn test_get_factorization() {
        let mut factorization_worker = FactorizationWorker::new();
        let n = 120;

        factorization_worker.get_factorization(n);

        // test
        let result = factorization_worker.get_factorization(n);

        assert_eq!(result[2], 3);
        assert_eq!(result[3], 1);
        assert_eq!(result[5], 1);
    }

    #[test]
    fn test_compute_factorial() {
        let factorial_worker = FactorialWorker::new();
        let n = 5;

        // test
        let result = factorial_worker.compute_factorial(n);

        assert_eq!(result[2], 3);
        assert_eq!(result[3], 1);
        assert_eq!(result[5], 1);
    }

    #[test]
    fn test_get_factorial() {
        let mut factorial_worker = FactorialWorker::new();
        let n = 5;

        factorial_worker.get_factorial(n);

        // test
        let result = factorial_worker.get_factorial(n);

        assert_eq!(result[2], 3);
        assert_eq!(result[3], 1);
        assert_eq!(result[5], 1);
    }
}
<commit_msg>incremental change, though i think the locks are much too coarse re: granularity<commit_after>
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

use primes;

pub mod util;
use util::t_log;

const MAX_SIZE: usize = 300;
const HEURISTIC_LIMIT: u64 = 14;

pub struct Chunk {
    pub low: u64,
    pub high: u64,
}

pub struct FactorialWorker {
    mutex_table: Mutex<HashMap<u64,[u64; MAX_SIZE]>>,
    mutex_factorization_worker: Mutex<FactorizationWorker>,
}

impl FactorialWorker {
    pub fn new() -> FactorialWorker {
        t_log("FactorialWorker constructor");
        FactorialWorker {
            mutex_table: Mutex::new(HashMap::new()),
            mutex_factorization_worker: Mutex::new(FactorizationWorker::new()),
        }
    }

    fn get_factorial(&mut self, n: u64) -> [u64;  MAX_SIZE] {
        let mut table = self.mutex_table.lock().unwrap();
        if table.contains_key(&n) {
            // println!("TRACER cache hit!");
            *table.get(&n).unwrap()
        } else {
            let result = self.compute_factorial(n);
            table.insert(n, result);
            result
        }
    }

    fn compute_factorial(&self, n: u64) -> [u64;  MAX_SIZE] {
        let mut result: [u64; MAX_SIZE] = [0; MAX_SIZE];
        let mut factorization_worker = self.mutex_factorization_worker.lock().unwrap();
        for i in 0..n+1 {
            let factor = factorization_worker.get_factorization(i);
            for j in 0..MAX_SIZE {
                result[j] += factor[j];
            }
        }
        result
    }
}

struct FactorizationWorker {
    table: HashMap<u64,[u64; MAX_SIZE]>,
}

impl FactorizationWorker {
    fn new() -> FactorizationWorker {
        t_log("FactorizationWorker constructor");
        FactorizationWorker {
            table: HashMap::new(),
        }
    }

    fn get_factorization(&mut self, n: u64) -> [u64;  MAX_SIZE] {
        if self.table.contains_key(&n) {
            *self.table.get(&n).unwrap()
        } else {
            let result = self.compute_factorization(n);
            self.table.insert(n, result);
            result
        }
    }

    fn compute_factorization(&self, n: u64) -> [u64;  MAX_SIZE] {
       let mut result: [u64; MAX_SIZE] = [0; MAX_SIZE];
       let factors = primes::factors(n);
       for i in factors {
           // println!("TRACER g_f i {}", i);
           result[i as usize] += 1;
       }
       result
    }
}

fn my_compare(a: &[u64; MAX_SIZE], b: &[u64; MAX_SIZE], c: &[u64; MAX_SIZE]) -> bool {
    let mut result = true;

    for i in 0..MAX_SIZE {
        if a[i] + b[i] != c[i] {
            result = false;
            return result;
        }
    }

    result
}

fn my_log(a: &[u64; MAX_SIZE]) {
    let mut s = String::new();

    for i in 0..MAX_SIZE {
        if a[i] > 0 {
            s.push_str(&format!("{}^{} ", i, a[i]));
        }
    }

    t_log(&format!("\nTRACER {}\n", s));
}

#[allow(dead_code)]
fn my_log_triplet(a: &[u64; MAX_SIZE], b: &[u64; MAX_SIZE], c: &[u64; MAX_SIZE]) {
    my_log(a);
    my_log(b);
    my_log(c);
}

fn do_stop_early(a_factorial: &[u64; MAX_SIZE], b_factorial: &[u64; MAX_SIZE],
                    c_factorial: &[u64; MAX_SIZE], c: u64) -> bool {
    let mut result = false;

    if c < HEURISTIC_LIMIT {
        let a_number = get_number(a_factorial);
        let b_number = get_number(b_factorial);
        let c_number = get_number(c_factorial);
        // println!("TRACER is_greater_than {} {} {}", a_number, b_number, c_number);
        result = (a_number * b_number) > c_number
    }
    result
}

// TODO: handle the inevitable overflow panic
fn get_number(n: &[u64; MAX_SIZE]) -> u64 {
    let mut result: u64 = 1;

    // my_log(n);
    for i in 0..MAX_SIZE {
        if n[i] > 0 {
            let value = i as u64;
            result *= u64::pow(value, n[i] as u32);
        }
    }

    result
}

pub fn find_factors(chunk: &Chunk, factorial_worker_mutex: &Arc<Mutex<FactorialWorker>>) {
    let c_low = chunk.low;
    let c_high = chunk.high;
    let check_frequency = 10;
    let mut count = 1;

    for c in c_low..c_high {
        for a in 1..c {
            for b in a..c {
                let mut factorial_worker = factorial_worker_mutex.lock().unwrap();
                let a_factorial = factorial_worker.get_factorial(a);
                let b_factorial = factorial_worker.get_factorial(b);
                let c_factorial = factorial_worker.get_factorial(c);
                let do_check = count % check_frequency == 0;
                if do_check && do_stop_early(&a_factorial, &b_factorial, &c_factorial, c) {
                    // println!("TRACER early eject :: {}! x {}! > {}!", a, b, c);
                    break;
                } else {
                    if my_compare(&a_factorial, &b_factorial, &c_factorial) {
                        t_log(&format!("TRACER HIT :: {}! x {}! = {}!", a, b, c));
                    }
                }
                count += 1;
            }
        }
    }

    t_log(&format!("TRACER COMPLETE {} {}", c_low, c_high));
}

#[allow(unused_imports)]
mod tests {
    use super::*;

    #[test]
    fn test_get_number() {
        let mut factorial_worker = FactorialWorker::new();
        let n = 4;
        let n_factorial = factorial_worker.get_factorial(n);

        // test
        let result = get_number(&n_factorial);

        assert_eq!(result, 24);
    }

    #[test]
    fn test_do_stop_early_sanity() {
        let mut factorial_worker = FactorialWorker::new();
        let a_factorial = factorial_worker.get_factorial(6);
        let b_factorial = factorial_worker.get_factorial(7);
        let c: u64 = 10;
        let c_factorial = factorial_worker.get_factorial(c);

        // test
        let result = do_stop_early(&a_factorial, &b_factorial, &c_factorial, c);

        assert_eq!(result, false);
    }

    #[test]
    fn test_do_stop_early_yes() {
        let mut factorial_worker = FactorialWorker::new();
        let a_factorial = factorial_worker.get_factorial(4);
        let b_factorial = factorial_worker.get_factorial(5);
        let c: u64 = 6;
        let c_factorial = factorial_worker.get_factorial(c);

        // test
        let result = do_stop_early(&a_factorial, &b_factorial, &c_factorial, c);

        assert_eq!(result, true);
    }

    #[test]
    fn test_do_stop_early_overflow_check() {
        let mut factorial_worker = FactorialWorker::new();
        let a_factorial = factorial_worker.get_factorial(9);
        let b_factorial = factorial_worker.get_factorial(11);
        let c: u64 = 14;
        let c_factorial = factorial_worker.get_factorial(c);

        // test
        let result = do_stop_early(&a_factorial, &b_factorial, &c_factorial, c);

        assert_eq!(result, false);
    }

    #[test]
    fn test_compute_factorization() {
        let factorization_worker = FactorizationWorker::new();
        let n = 120;

        // test
        let result = factorization_worker.compute_factorization(n);

        assert_eq!(result[2], 3);
        assert_eq!(result[3], 1);
        assert_eq!(result[5], 1);
    }

    #[test]
    fn test_get_factorization() {
        let mut factorization_worker = FactorizationWorker::new();
        let n = 120;

        factorization_worker.get_factorization(n);

        // test
        let result = factorization_worker.get_factorization(n);

        assert_eq!(result[2], 3);
        assert_eq!(result[3], 1);
        assert_eq!(result[5], 1);
    }

    #[test]
    fn test_compute_factorial() {
        let factorial_worker = FactorialWorker::new();
        let n = 5;

        // test
        let result = factorial_worker.compute_factorial(n);

        assert_eq!(result[2], 3);
        assert_eq!(result[3], 1);
        assert_eq!(result[5], 1);
    }

    #[test]
    fn test_get_factorial() {
        let mut factorial_worker = FactorialWorker::new();
        let n = 5;

        factorial_worker.get_factorial(n);

        // test
        let result = factorial_worker.get_factorial(n);

        assert_eq!(result[2], 3);
        assert_eq!(result[3], 1);
        assert_eq!(result[5], 1);
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
use borrow_check::nll::region_infer::TypeTest;
use borrow_check::nll::type_check::Locations;
use borrow_check::nll::universal_regions::UniversalRegions;
use rustc::infer::canonical::QueryRegionConstraint;
use rustc::infer::outlives::env::RegionBoundPairs;
use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
use rustc::infer::region_constraints::{GenericKind, VerifyBound};
use rustc::infer::{self, SubregionOrigin};
use rustc::mir::ConstraintCategory;
use rustc::ty::subst::UnpackedKind;
use rustc::ty::{self, TyCtxt};
use syntax_pos::DUMMY_SP;

crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
    universal_regions: &'a UniversalRegions<'tcx>,
    region_bound_pairs: &'a RegionBoundPairs<'tcx>,
    implicit_region_bound: Option<ty::Region<'tcx>>,
    param_env: ty::ParamEnv<'tcx>,
    locations: Locations,
    category: ConstraintCategory,
    outlives_constraints: &'a mut ConstraintSet,
    type_tests: &'a mut Vec<TypeTest<'tcx>>,
}

impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
    crate fn new(
        tcx: TyCtxt<'a, 'gcx, 'tcx>,
        universal_regions: &'a UniversalRegions<'tcx>,
        region_bound_pairs: &'a RegionBoundPairs<'tcx>,
        implicit_region_bound: Option<ty::Region<'tcx>>,
        param_env: ty::ParamEnv<'tcx>,
        locations: Locations,
        category: ConstraintCategory,
        outlives_constraints: &'a mut ConstraintSet,
        type_tests: &'a mut Vec<TypeTest<'tcx>>,
    ) -> Self {
        Self {
            tcx,
            universal_regions,
            region_bound_pairs,
            implicit_region_bound,
            param_env,
            locations,
            category,
            outlives_constraints,
            type_tests,
        }
    }

    pub(super) fn convert_all(&mut self, query_constraints: &[QueryRegionConstraint<'tcx>]) {
        for query_constraint in query_constraints {
            self.convert(query_constraint);
        }
    }

    pub(super) fn convert(&mut self, query_constraint: &QueryRegionConstraint<'tcx>) {
        debug!("generate: constraints at: {:#?}", self.locations);

        // Extract out various useful fields we'll need below.
        let ConstraintConversion {
            tcx,
            region_bound_pairs,
            implicit_region_bound,
            param_env,
            ..
        } = *self;

        // At the moment, we never generate any "higher-ranked"
        // region constraints like `for<'a> 'a: 'b`. At some point
        // when we move to universes, we will, and this assertion
        // will start to fail.
        let ty::OutlivesPredicate(k1, r2) =
            query_constraint.no_late_bound_regions().unwrap_or_else(|| {
                bug!(
                    "query_constraint {:?} contained bound regions",
                    query_constraint,
                );
            });

        match k1.unpack() {
            UnpackedKind::Lifetime(r1) => {
                let r1_vid = self.to_region_vid(r1);
                let r2_vid = self.to_region_vid(r2);
                self.add_outlives(r1_vid, r2_vid);
            }

            UnpackedKind::Type(t1) => {
                // we don't actually use this for anything, but
                // the `TypeOutlives` code needs an origin.
                let origin = infer::RelateParamBound(DUMMY_SP, t1);

                TypeOutlives::new(
                    &mut *self,
                    tcx,
                    region_bound_pairs,
                    implicit_region_bound,
                    param_env,
                ).type_must_outlive(origin, t1, r2);
            }
        }
    }

    fn verify_to_type_test(
        &self,
        generic_kind: GenericKind<'tcx>,
        region: ty::Region<'tcx>,
        verify_bound: VerifyBound<'tcx>,
    ) -> TypeTest<'tcx> {
        let lower_bound = self.to_region_vid(region);

        TypeTest {
            generic_kind,
            lower_bound,
            locations: self.locations,
            verify_bound,
        }
    }

    fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
        self.universal_regions.to_region_vid(r)
    }

    fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
        self.outlives_constraints.push(OutlivesConstraint {
            locations: self.locations,
            category: self.category,
            sub,
            sup,
        });
    }

    fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
        self.type_tests.push(type_test);
    }
}

impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx>
    for &'a mut ConstraintConversion<'b, 'gcx, 'tcx>
{
    fn push_sub_region_constraint(
        &mut self,
        _origin: SubregionOrigin<'tcx>,
        a: ty::Region<'tcx>,
        b: ty::Region<'tcx>,
    ) {
        let b = self.universal_regions.to_region_vid(b);
        let a = self.universal_regions.to_region_vid(a);
        self.add_outlives(b, a);
    }

    fn push_verify(
        &mut self,
        _origin: SubregionOrigin<'tcx>,
        kind: GenericKind<'tcx>,
        a: ty::Region<'tcx>,
        bound: VerifyBound<'tcx>,
    ) {
        let type_test = self.verify_to_type_test(kind, a, bound);
        self.add_type_test(type_test);
    }
}
<commit_msg>add useful debug log<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
use borrow_check::nll::region_infer::TypeTest;
use borrow_check::nll::type_check::Locations;
use borrow_check::nll::universal_regions::UniversalRegions;
use rustc::infer::canonical::QueryRegionConstraint;
use rustc::infer::outlives::env::RegionBoundPairs;
use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
use rustc::infer::region_constraints::{GenericKind, VerifyBound};
use rustc::infer::{self, SubregionOrigin};
use rustc::mir::ConstraintCategory;
use rustc::ty::subst::UnpackedKind;
use rustc::ty::{self, TyCtxt};
use syntax_pos::DUMMY_SP;

crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
    universal_regions: &'a UniversalRegions<'tcx>,
    region_bound_pairs: &'a RegionBoundPairs<'tcx>,
    implicit_region_bound: Option<ty::Region<'tcx>>,
    param_env: ty::ParamEnv<'tcx>,
    locations: Locations,
    category: ConstraintCategory,
    outlives_constraints: &'a mut ConstraintSet,
    type_tests: &'a mut Vec<TypeTest<'tcx>>,
}

impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
    crate fn new(
        tcx: TyCtxt<'a, 'gcx, 'tcx>,
        universal_regions: &'a UniversalRegions<'tcx>,
        region_bound_pairs: &'a RegionBoundPairs<'tcx>,
        implicit_region_bound: Option<ty::Region<'tcx>>,
        param_env: ty::ParamEnv<'tcx>,
        locations: Locations,
        category: ConstraintCategory,
        outlives_constraints: &'a mut ConstraintSet,
        type_tests: &'a mut Vec<TypeTest<'tcx>>,
    ) -> Self {
        Self {
            tcx,
            universal_regions,
            region_bound_pairs,
            implicit_region_bound,
            param_env,
            locations,
            category,
            outlives_constraints,
            type_tests,
        }
    }

    pub(super) fn convert_all(&mut self, query_constraints: &[QueryRegionConstraint<'tcx>]) {
        for query_constraint in query_constraints {
            self.convert(query_constraint);
        }
    }

    pub(super) fn convert(&mut self, query_constraint: &QueryRegionConstraint<'tcx>) {
        debug!("generate: constraints at: {:#?}", self.locations);

        // Extract out various useful fields we'll need below.
        let ConstraintConversion {
            tcx,
            region_bound_pairs,
            implicit_region_bound,
            param_env,
            ..
        } = *self;

        // At the moment, we never generate any "higher-ranked"
        // region constraints like `for<'a> 'a: 'b`. At some point
        // when we move to universes, we will, and this assertion
        // will start to fail.
        let ty::OutlivesPredicate(k1, r2) =
            query_constraint.no_late_bound_regions().unwrap_or_else(|| {
                bug!(
                    "query_constraint {:?} contained bound regions",
                    query_constraint,
                );
            });

        match k1.unpack() {
            UnpackedKind::Lifetime(r1) => {
                let r1_vid = self.to_region_vid(r1);
                let r2_vid = self.to_region_vid(r2);
                self.add_outlives(r1_vid, r2_vid);
            }

            UnpackedKind::Type(t1) => {
                // we don't actually use this for anything, but
                // the `TypeOutlives` code needs an origin.
                let origin = infer::RelateParamBound(DUMMY_SP, t1);

                TypeOutlives::new(
                    &mut *self,
                    tcx,
                    region_bound_pairs,
                    implicit_region_bound,
                    param_env,
                ).type_must_outlive(origin, t1, r2);
            }
        }
    }

    fn verify_to_type_test(
        &self,
        generic_kind: GenericKind<'tcx>,
        region: ty::Region<'tcx>,
        verify_bound: VerifyBound<'tcx>,
    ) -> TypeTest<'tcx> {
        let lower_bound = self.to_region_vid(region);

        TypeTest {
            generic_kind,
            lower_bound,
            locations: self.locations,
            verify_bound,
        }
    }

    fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
        self.universal_regions.to_region_vid(r)
    }

    fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
        self.outlives_constraints.push(OutlivesConstraint {
            locations: self.locations,
            category: self.category,
            sub,
            sup,
        });
    }

    fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
        debug!("add_type_test(type_test={:?})", type_test);
        self.type_tests.push(type_test);
    }
}

impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx>
    for &'a mut ConstraintConversion<'b, 'gcx, 'tcx>
{
    fn push_sub_region_constraint(
        &mut self,
        _origin: SubregionOrigin<'tcx>,
        a: ty::Region<'tcx>,
        b: ty::Region<'tcx>,
    ) {
        let b = self.universal_regions.to_region_vid(b);
        let a = self.universal_regions.to_region_vid(a);
        self.add_outlives(b, a);
    }

    fn push_verify(
        &mut self,
        _origin: SubregionOrigin<'tcx>,
        kind: GenericKind<'tcx>,
        a: ty::Region<'tcx>,
        bound: VerifyBound<'tcx>,
    ) {
        let type_test = self.verify_to_type_test(kind, a, bound);
        self.add_type_test(type_test);
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
    html_root_url = "https://rust-random.github.io/rand/"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![allow(
    clippy::excessive_precision,
    clippy::float_cmp,
    clippy::unreadable_literal
)]
#![allow(clippy::neg_cmp_op_on_partial_ord)] // suggested fix too verbose
#![no_std]
#![cfg_attr(doc_cfg, feature(doc_cfg))]

//! Generating random samples from probability distributions.
//!
//! ## Re-exports
//!
//! This crate is a super-set of the [`rand::distributions`] module. See the
//! [`rand::distributions`] module documentation for an overview of the core
//! [`Distribution`] trait and implementations.
//!
//! The following are re-exported:
//!
//! - The [`Distribution`] trait and [`DistIter`] helper type
//! - The [`Standard`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`],
//! [`Open01`], [`Bernoulli`], and [`WeightedIndex`] distributions
//!
//! ## Distributions
//!
//! This crate provides the following probability distributions:
//!
//! - Related to real-valued quantities that grow linearly
//!   (e.g. errors, offsets):
//!   - [`Normal`] distribution, and [`StandardNormal`] as a primitive
//!   - [`Cauchy`] distribution
//! - Related to Bernoulli trials (yes/no events, with a given probability):
//!   - [`Binomial`] distribution
//! - Related to positive real-valued quantities that grow exponentially
//!   (e.g. prices, incomes, populations):
//!   - [`LogNormal`] distribution
//! - Related to the occurrence of independent events at a given rate:
//!   - [`Pareto`] distribution
//!   - [`Poisson`] distribution
//!   - [`Exp`]onential distribution, and [`Exp1`] as a primitive
//!   - [`Weibull`] distribution
//! - Gamma and derived distributions:
//!   - [`Gamma`] distribution
//!   - [`ChiSquared`] distribution
//!   - [`StudentT`] distribution
//!   - [`FisherF`] distribution
//! - Triangular distribution:
//!   - [`Beta`] distribution
//!   - [`Triangular`] distribution
//! - Multivariate probability distributions
//!   - [`Dirichlet`] distribution
//!   - [`UnitSphere`] distribution
//!   - [`UnitBall`] distribution
//!   - [`UnitCircle`] distribution
//!   - [`UnitDisc`] distribution
//! - Alternative implementation for weighted index sampling
//!   - [`WeightedAliasIndex`] distribution
//! - Misc. distributions
//!   - [`InverseGaussian`] distribution
//!   - [`NormalInverseGaussian`] distribution

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "std")]
extern crate std;

pub use rand::distributions::{
    uniform, Alphanumeric, Bernoulli, BernoulliError, DistIter, Distribution, Open01, OpenClosed01,
    Standard, Uniform,
};

pub use self::binomial::{Binomial, Error as BinomialError};
pub use self::cauchy::{Cauchy, Error as CauchyError};
#[cfg(feature = "alloc")]
pub use self::dirichlet::{Dirichlet, Error as DirichletError};
pub use self::exponential::{Error as ExpError, Exp, Exp1};
pub use self::gamma::{
    Beta, BetaError, ChiSquared, ChiSquaredError, Error as GammaError, FisherF, FisherFError,
    Gamma, StudentT,
};
pub use self::geometric::{Error as GeoError, Geo};
pub use self::hypergeometric::{Error as HyperGeoError, Hypergeometric};
pub use self::inverse_gaussian::{InverseGaussian, Error as InverseGaussianError};
pub use self::normal::{Error as NormalError, LogNormal, Normal, StandardNormal};
pub use self::normal_inverse_gaussian::{NormalInverseGaussian, Error as NormalInverseGaussianError};
pub use self::pareto::{Error as ParetoError, Pareto};
pub use self::pert::{Pert, PertError};
pub use self::poisson::{Error as PoissonError, Poisson};
pub use self::triangular::{Triangular, TriangularError};
pub use self::unit_ball::UnitBall;
pub use self::unit_circle::UnitCircle;
pub use self::unit_disc::UnitDisc;
pub use self::unit_sphere::UnitSphere;
pub use self::weibull::{Error as WeibullError, Weibull};
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub use rand::distributions::{WeightedError, WeightedIndex};
#[cfg(feature = "alloc")]
pub use weighted_alias::WeightedAliasIndex;

pub use num_traits;

#[cfg(test)]
#[macro_use]
mod test {
    // Notes on testing
    //
    // Testing random number distributions correctly is hard. The following
    // testing is desired:
    //
    // - Construction: test initialisation with a few valid parameter sets.
    // - Erroneous usage: test that incorrect usage generates an error.
    // - Vector: test that usage with fixed inputs (including RNG) generates a
    //   fixed output sequence on all platforms.
    // - Correctness at fixed points (optional): using a specific mock RNG,
    //   check that specific values are sampled (e.g. end-points and median of
    //   distribution).
    // - Correctness of PDF (extra): generate a histogram of samples within a
    //   certain range, and check this approximates the PDF. These tests are
    //   expected to be expensive, and should be behind a feature-gate.
    //
    // TODO: Vector and correctness tests are largely absent so far.
    // NOTE: Some distributions have tests checking only that samples can be
    // generated. This is redundant with vector and correctness tests.

    /// Construct a deterministic RNG with the given seed
    pub fn rng(seed: u64) -> impl rand::RngCore {
        // For tests, we want a statistically good, fast, reproducible RNG.
        // PCG32 will do fine, and will be easy to embed if we ever need to.
        const INC: u64 = 11634580027462260723;
        rand_pcg::Pcg32::new(seed, INC)
    }

    /// Assert that two numbers are almost equal to each other.
    ///
    /// On panic, this macro will print the values of the expressions with their
    /// debug representations.
    macro_rules! assert_almost_eq {
        ($a:expr, $b:expr, $prec:expr) => {
            let diff = ($a - $b).abs();
            if diff > $prec {
                panic!(
                    "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \
                     (left: `{}`, right: `{}`)",
                    diff, $prec, $a, $b
                );
            }
        };
    }
}

#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub mod weighted_alias;

mod binomial;
mod cauchy;
mod dirichlet;
mod exponential;
mod gamma;
mod geometric;
mod hypergeometric;
mod inverse_gaussian;
mod normal;
mod normal_inverse_gaussian;
mod pareto;
mod pert;
mod poisson;
mod triangular;
mod unit_ball;
mod unit_circle;
mod unit_disc;
mod unit_sphere;
mod utils;
mod weibull;
mod ziggurat_tables;

<commit_msg>Update crate documentation<commit_after>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
    html_root_url = "https://rust-random.github.io/rand/"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![allow(
    clippy::excessive_precision,
    clippy::float_cmp,
    clippy::unreadable_literal
)]
#![allow(clippy::neg_cmp_op_on_partial_ord)] // suggested fix too verbose
#![no_std]
#![cfg_attr(doc_cfg, feature(doc_cfg))]

//! Generating random samples from probability distributions.
//!
//! ## Re-exports
//!
//! This crate is a super-set of the [`rand::distributions`] module. See the
//! [`rand::distributions`] module documentation for an overview of the core
//! [`Distribution`] trait and implementations.
//!
//! The following are re-exported:
//!
//! - The [`Distribution`] trait and [`DistIter`] helper type
//! - The [`Standard`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`],
//! [`Open01`], [`Bernoulli`], and [`WeightedIndex`] distributions
//!
//! ## Distributions
//!
//! This crate provides the following probability distributions:
//!
//! - Related to real-valued quantities that grow linearly
//!   (e.g. errors, offsets):
//!   - [`Normal`] distribution, and [`StandardNormal`] as a primitive
//!   - [`Cauchy`] distribution
//! - Related to Bernoulli trials (yes/no events, with a given probability):
//!   - [`Binomial`] distribution
//!   - [`Geo`]metric distribution
//! - Related to positive real-valued quantities that grow exponentially
//!   (e.g. prices, incomes, populations):
//!   - [`LogNormal`] distribution
//! - Related to the occurrence of independent events at a given rate:
//!   - [`Pareto`] distribution
//!   - [`Poisson`] distribution
//!   - [`Exp`]onential distribution, and [`Exp1`] as a primitive
//!   - [`Weibull`] distribution
//! - Gamma and derived distributions:
//!   - [`Gamma`] distribution
//!   - [`ChiSquared`] distribution
//!   - [`StudentT`] distribution
//!   - [`FisherF`] distribution
//! - Triangular distribution:
//!   - [`Beta`] distribution
//!   - [`Triangular`] distribution
//! - Multivariate probability distributions
//!   - [`Dirichlet`] distribution
//!   - [`UnitSphere`] distribution
//!   - [`UnitBall`] distribution
//!   - [`UnitCircle`] distribution
//!   - [`UnitDisc`] distribution
//! - Alternative implementation for weighted index sampling
//!   - [`WeightedAliasIndex`] distribution
//! - Misc. distributions
//!   - [`InverseGaussian`] distribution
//!   - [`NormalInverseGaussian`] distribution
//!   - [`Hypergeometric`] distribution

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "std")]
extern crate std;

pub use rand::distributions::{
    uniform, Alphanumeric, Bernoulli, BernoulliError, DistIter, Distribution, Open01, OpenClosed01,
    Standard, Uniform,
};

pub use self::binomial::{Binomial, Error as BinomialError};
pub use self::cauchy::{Cauchy, Error as CauchyError};
#[cfg(feature = "alloc")]
pub use self::dirichlet::{Dirichlet, Error as DirichletError};
pub use self::exponential::{Error as ExpError, Exp, Exp1};
pub use self::gamma::{
    Beta, BetaError, ChiSquared, ChiSquaredError, Error as GammaError, FisherF, FisherFError,
    Gamma, StudentT,
};
pub use self::geometric::{Error as GeoError, Geo};
pub use self::hypergeometric::{Error as HyperGeoError, Hypergeometric};
pub use self::inverse_gaussian::{InverseGaussian, Error as InverseGaussianError};
pub use self::normal::{Error as NormalError, LogNormal, Normal, StandardNormal};
pub use self::normal_inverse_gaussian::{NormalInverseGaussian, Error as NormalInverseGaussianError};
pub use self::pareto::{Error as ParetoError, Pareto};
pub use self::pert::{Pert, PertError};
pub use self::poisson::{Error as PoissonError, Poisson};
pub use self::triangular::{Triangular, TriangularError};
pub use self::unit_ball::UnitBall;
pub use self::unit_circle::UnitCircle;
pub use self::unit_disc::UnitDisc;
pub use self::unit_sphere::UnitSphere;
pub use self::weibull::{Error as WeibullError, Weibull};
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub use rand::distributions::{WeightedError, WeightedIndex};
#[cfg(feature = "alloc")]
pub use weighted_alias::WeightedAliasIndex;

pub use num_traits;

#[cfg(test)]
#[macro_use]
mod test {
    // Notes on testing
    //
    // Testing random number distributions correctly is hard. The following
    // testing is desired:
    //
    // - Construction: test initialisation with a few valid parameter sets.
    // - Erroneous usage: test that incorrect usage generates an error.
    // - Vector: test that usage with fixed inputs (including RNG) generates a
    //   fixed output sequence on all platforms.
    // - Correctness at fixed points (optional): using a specific mock RNG,
    //   check that specific values are sampled (e.g. end-points and median of
    //   distribution).
    // - Correctness of PDF (extra): generate a histogram of samples within a
    //   certain range, and check this approximates the PDF. These tests are
    //   expected to be expensive, and should be behind a feature-gate.
    //
    // TODO: Vector and correctness tests are largely absent so far.
    // NOTE: Some distributions have tests checking only that samples can be
    // generated. This is redundant with vector and correctness tests.

    /// Construct a deterministic RNG with the given seed
    pub fn rng(seed: u64) -> impl rand::RngCore {
        // For tests, we want a statistically good, fast, reproducible RNG.
        // PCG32 will do fine, and will be easy to embed if we ever need to.
        const INC: u64 = 11634580027462260723;
        rand_pcg::Pcg32::new(seed, INC)
    }

    /// Assert that two numbers are almost equal to each other.
    ///
    /// On panic, this macro will print the values of the expressions with their
    /// debug representations.
    macro_rules! assert_almost_eq {
        ($a:expr, $b:expr, $prec:expr) => {
            let diff = ($a - $b).abs();
            if diff > $prec {
                panic!(
                    "assertion failed: `abs(left - right) = {:.1e} < {:e}`, \
                     (left: `{}`, right: `{}`)",
                    diff, $prec, $a, $b
                );
            }
        };
    }
}

#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub mod weighted_alias;

mod binomial;
mod cauchy;
mod dirichlet;
mod exponential;
mod gamma;
mod geometric;
mod hypergeometric;
mod inverse_gaussian;
mod normal;
mod normal_inverse_gaussian;
mod pareto;
mod pert;
mod poisson;
mod triangular;
mod unit_ball;
mod unit_circle;
mod unit_disc;
mod unit_sphere;
mod utils;
mod weibull;
mod ziggurat_tables;

<|endoftext|>


<commit_before>
extern crate "rustc-serialize" as serialize;
extern crate jsonway;

use jsonway::{JsonWay};

#[deriving(Show)]
enum Side {
    Light,
    Dark
}

struct Jedi {
    name: String,
    side: Side
}

fn jedi_array() -> Vec<Jedi> {
    vec![
        Jedi { name: "Saes Rrogon".to_string(), side: Side::Dark },
        Jedi { name: "Qui-Gon Jinn".to_string(), side: Side::Light },
        Jedi { name: "Obi-Wan Kenobi".to_string(), side: Side::Light }
    ]
}

#[test]
fn simple_array_of_objects() {
    let jedi_array = jedi_array();

    let json = JsonWay::array(|json| {
        json.objects(&mut jedi_array.iter(), |jedi, json| {
            match jedi.side {
                Side::Light => {
                    json.set("name".to_string(), jedi.name.to_string());
                    json.set("side".to_string(), jedi.side.to_string());
                },
                Side::Dark => json.skip()
            }
        })
    }).unwrap();

    let array = json.as_array().unwrap();

    assert_eq!(array.len(), 2);
}

#[test]
fn simple_array_of_arrays() {
    let jedi_array = jedi_array();

    let json = JsonWay::array(|json| {
        json.objects(&mut jedi_array.iter(), |jedi, json| {
            match jedi.side {
                Side::Light => {
                    json.set("name".to_string(), jedi.name.to_string());
                    json.set("side".to_string(), jedi.side.to_string());
                },
                Side::Dark => json.skip()
            }
        })
    }).unwrap();

    let array = json.as_array().unwrap();

    assert_eq!(array.len(), 2);
}<commit_msg>refactor: rename `deriving` to `derive`<commit_after>
extern crate "rustc-serialize" as serialize;
extern crate jsonway;

use jsonway::{JsonWay};

#[derive(Show)]
enum Side {
    Light,
    Dark
}

struct Jedi {
    name: String,
    side: Side
}

fn jedi_array() -> Vec<Jedi> {
    vec![
        Jedi { name: "Saes Rrogon".to_string(), side: Side::Dark },
        Jedi { name: "Qui-Gon Jinn".to_string(), side: Side::Light },
        Jedi { name: "Obi-Wan Kenobi".to_string(), side: Side::Light }
    ]
}

#[test]
fn simple_array_of_objects() {
    let jedi_array = jedi_array();

    let json = JsonWay::array(|json| {
        json.objects(&mut jedi_array.iter(), |jedi, json| {
            match jedi.side {
                Side::Light => {
                    json.set("name".to_string(), jedi.name.to_string());
                    json.set("side".to_string(), jedi.side.to_string());
                },
                Side::Dark => json.skip()
            }
        })
    }).unwrap();

    let array = json.as_array().unwrap();

    assert_eq!(array.len(), 2);
}

#[test]
fn simple_array_of_arrays() {
    let jedi_array = jedi_array();

    let json = JsonWay::array(|json| {
        json.objects(&mut jedi_array.iter(), |jedi, json| {
            match jedi.side {
                Side::Light => {
                    json.set("name".to_string(), jedi.name.to_string());
                    json.set("side".to_string(), jedi.side.to_string());
                },
                Side::Dark => json.skip()
            }
        })
    }).unwrap();

    let array = json.as_array().unwrap();

    assert_eq!(array.len(), 2);
}<|endoftext|>


<commit_before>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");

            if cpp_compat {
                command.arg("--cpp-compat");
            }
        }
    }

    if let Some(style) = style {
        command.arg("--style");
        command.arg(match style {
            Style::Both => "both",
            Style::Tag => "tag",
            Style::Type => "type",
        });
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(cbindgen_output: &Path, language: Language) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let mut object = cbindgen_output.to_path_buf();
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-c").arg(cbindgen_output);
    command.arg("-o").arg(&object);
    command.arg("-Wall");
    command.arg("-Werror");
    // `swift_name` is not recognzied by gcc.
    command.arg("-Wno-attributes");
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        // inline variables are are a c++17 extension
        command.arg("-std=c++17");
    }

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let mut output = Path::new(&crate_dir).join("tests").join("expectations");
    if let Some(style) = style {
        match style {
            Style::Both => {
                output.push("both");
            }
            Style::Tag => {
                output.push("tag");
            }
            Style::Type => {}
        }
    }

    let ext = match language {
        Language::Cxx => "cpp",
        Language::C => {
            if cpp_compat {
                "compat.c"
            } else {
                "c"
            }
        }
    };

    output.push(format!("{}.{}", name, ext));

    run_cbindgen(cbindgen_path, path, &output, language, cpp_compat, style);
    compile(&output, language);

    if language == Language::C && cpp_compat {
        compile(&output, Language::Cxx)
    }
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    for style in &[Style::Type, Style::Tag, Style::Both] {
        for cpp_compat in &[true, false] {
            run_compile_test(
                cbindgen_path,
                name,
                &test,
                Language::C,
                *cpp_compat,
                Some(*style),
            );
        }
    }
    run_compile_test(
        cbindgen_path,
        name,
        &test,
        Language::Cxx,
        /* cpp_compat = */ false,
        None,
    );
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<commit_msg>tests: Provide style definition to the C / C++ tests.<commit_after>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn style_str(style: Style) -> &'static str {
    match style {
        Style::Both => "both",
        Style::Tag => "tag",
        Style::Type => "type",
    }
}

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");

            if cpp_compat {
                command.arg("--cpp-compat");
            }
        }
    }

    if let Some(style) = style {
        command.arg("--style").arg(style_str(style));
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(cbindgen_output: &Path, language: Language, style: Option<Style>) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let mut object = cbindgen_output.to_path_buf();
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-c").arg(cbindgen_output);
    command.arg("-o").arg(&object);
    command.arg("-Wall");
    command.arg("-Werror");
    // `swift_name` is not recognzied by gcc.
    command.arg("-Wno-attributes");
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        // inline variables are are a c++17 extension
        command.arg("-std=c++17");
    }

    if let Some(style) = style {
        command.arg("-D");
        command.arg(format!(
            "CBINDGEN_STYLE_{}",
            style_str(style).to_uppercase()
        ));
    }

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    language: Language,
    cpp_compat: bool,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let mut output = Path::new(&crate_dir).join("tests").join("expectations");
    if let Some(style) = style {
        match style {
            Style::Both => {
                output.push("both");
            }
            Style::Tag => {
                output.push("tag");
            }
            Style::Type => {}
        }
    }

    let ext = match language {
        Language::Cxx => "cpp",
        Language::C => {
            if cpp_compat {
                "compat.c"
            } else {
                "c"
            }
        }
    };

    output.push(format!("{}.{}", name, ext));

    run_cbindgen(cbindgen_path, path, &output, language, cpp_compat, style);
    compile(&output, language, style);

    if language == Language::C && cpp_compat {
        compile(&output, Language::Cxx, style)
    }
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    for style in &[Style::Type, Style::Tag, Style::Both] {
        for cpp_compat in &[true, false] {
            run_compile_test(
                cbindgen_path,
                name,
                &test,
                Language::C,
                *cpp_compat,
                Some(*style),
            );
        }
    }
    run_compile_test(
        cbindgen_path,
        name,
        &test,
        Language::Cxx,
        /* cpp_compat = */ false,
        None,
    );
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<|endoftext|>