// -*- c++ -*- /* * Copyright (c) 2010-2012, Jim Bosch * All rights reserved. * * ndarray is distributed under a simple BSD-like license; * see the LICENSE file that should be present in the root * of the source distribution, or alternately available at: * https://github.com/ndarray/ndarray */ #include "ndarray.h" #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE ndarray #include "boost/test/unit_test.hpp" BOOST_AUTO_TEST_CASE(sizes) { std::cerr << "sizeof(int): " << sizeof(int) << "\n"; std::cerr << "sizeof(double*): " << sizeof(double*) << "\n"; std::cerr << "sizeof(shared_ptr): " << sizeof(boost::shared_ptr) << "\n"; std::cerr << "sizeof(Core): " << sizeof(ndarray::detail::Core<1>) << "\n"; std::cerr << "sizeof(Core): " << sizeof(ndarray::detail::Core<2>) << "\n"; std::cerr << "sizeof(Core): " << sizeof(ndarray::detail::Core<3>) << "\n"; } BOOST_AUTO_TEST_CASE(vectors) { ndarray::Vector a = ndarray::makeVector(5,6,7); BOOST_CHECK_EQUAL(a[0],5); BOOST_CHECK_EQUAL(a[1],6); BOOST_CHECK_EQUAL(a[2],7); ndarray::Vector b(a); BOOST_CHECK_EQUAL(a,b); ndarray::Vector c(a); BOOST_CHECK_EQUAL(c[0],5.0); BOOST_CHECK_EQUAL(c[1],6.0); BOOST_CHECK_EQUAL(c[2],7.0); ndarray::Vector d(5.0); BOOST_CHECK_EQUAL(d[0],5.0); BOOST_CHECK_EQUAL(d[1],5.0); BOOST_CHECK_EQUAL(d[2],5.0); ndarray::Vector e; ndarray::Vector f = ndarray::concatenate(a, e); BOOST_CHECK_EQUAL(a, f); e = a.last<0>(); // make sure we can default-construct whether or not T is a number ndarray::Vector,2> g; BOOST_CHECK_EQUAL(g, ndarray::makeVector(boost::shared_ptr(), boost::shared_ptr())); ndarray::Vector h; BOOST_CHECK_EQUAL(h, ndarray::makeVector(0, 0, 0)); } BOOST_AUTO_TEST_CASE(cores) { typedef ndarray::detail::Core<3> Core; ndarray::Vector shape = ndarray::makeVector(4,3,2); ndarray::Vector strides = ndarray::makeVector(6,2,1); Core::Ptr core = Core::create(shape, strides); BOOST_CHECK_EQUAL(core->getRC(),1); Core::Ptr copy = core; BOOST_CHECK_EQUAL(core->getRC(),2); copy.reset(); BOOST_CHECK_EQUAL(core->getRC(),1); } BOOST_AUTO_TEST_CASE(allocation) { ndarray::Vector shape = ndarray::makeVector(5,6,7); ndarray::Array a = ndarray::allocate(shape); BOOST_CHECK_EQUAL(a.getShape(), shape); ndarray::Array b = ndarray::allocate(shape); BOOST_CHECK_EQUAL(b.getShape(), shape); BOOST_CHECK_EQUAL(b.getSize<0>(), shape[0]); BOOST_CHECK_EQUAL(b.getSize<1>(), shape[1]); BOOST_CHECK_EQUAL(b.getSize<2>(), shape[2]); BOOST_CHECK_EQUAL(b.getStride<0>(), 6*7); BOOST_CHECK_EQUAL(b.getStride<1>(), 7); BOOST_CHECK_EQUAL(b.getStride<2>(), 1); BOOST_CHECK_EQUAL(b.getStrides(), ndarray::makeVector(6*7 ,7, 1)); ndarray::Array c = ndarray::allocate(5,6,7); BOOST_CHECK_EQUAL(c.getShape(), shape); BOOST_CHECK_EQUAL(c.getSize<0>(), shape[0]); BOOST_CHECK_EQUAL(c.getSize<1>(), shape[1]); BOOST_CHECK_EQUAL(c.getSize<2>(), shape[2]); BOOST_CHECK_EQUAL(c.getStride<0>(), 1); BOOST_CHECK_EQUAL(c.getStride<1>(), 5); BOOST_CHECK_EQUAL(c.getStride<2>(), 5*6); BOOST_CHECK_EQUAL(c.getStrides(), ndarray::makeVector(1, 5, 5*6)); ndarray::Array d(shape); BOOST_CHECK_EQUAL(d.getShape(), shape); BOOST_CHECK_EQUAL(d.getStrides(), a.getStrides()); ndarray::Array e(shape); BOOST_CHECK_EQUAL(e.getShape(), shape); BOOST_CHECK_EQUAL(e.getStrides(), c.getStrides()); ndarray::Vector shape2(shape); ndarray::Array f(shape2); BOOST_CHECK_EQUAL(f.getShape(), shape); BOOST_CHECK_EQUAL(f.getStrides(), a.getStrides()); ndarray::Array g(shape2); BOOST_CHECK_EQUAL(g.getShape(), shape); BOOST_CHECK_EQUAL(g.getStrides(), c.getStrides()); } BOOST_AUTO_TEST_CASE(external) { double data[3*4*2] = {0}; ndarray::Vector shape = ndarray::makeVector(3,4,2); ndarray::Vector strides = ndarray::makeVector(8,2,1); ndarray::Array a = ndarray::external(data,shape,strides); BOOST_CHECK_EQUAL(a.getData(), data); BOOST_CHECK_EQUAL(a.getShape(), shape); BOOST_CHECK_EQUAL(a.getStrides(), strides); } BOOST_AUTO_TEST_CASE(conversion) { double data[3*4*2] = {0}; ndarray::Vector shape = ndarray::makeVector(3,4,2); ndarray::Vector strides = ndarray::makeVector(8,2,1); ndarray::Array a = ndarray::external(data,shape,strides); ndarray::Array b = a; } BOOST_AUTO_TEST_CASE(shallow) { double data[3*4*2] = {0}; ndarray::Vector shape = ndarray::makeVector(3,4,2); ndarray::Vector strides = ndarray::makeVector(8,2,1); ndarray::Array a = ndarray::external(data,shape,strides); ndarray::Array b = ndarray::external(data,shape,strides); BOOST_CHECK(a == b); BOOST_CHECK(a[2].shallow() == b[2].shallow()); BOOST_CHECK(a[0][1].shallow() == b[0][1].shallow()); BOOST_CHECK(a[0][1].shallow() != b[1][2].shallow()); ndarray::Array c; c = a; BOOST_CHECK_EQUAL(a.getData(), c.getData()); BOOST_CHECK_EQUAL(a.getShape(), c.getShape()); BOOST_CHECK_EQUAL(a.getStrides(), c.getStrides()); BOOST_CHECK(a.shallow() == c.shallow()); ndarray::Array d = c[1]; BOOST_CHECK_EQUAL(d.getData(), c[1].getData()); BOOST_CHECK_EQUAL(d.getShape(), c[1].getShape()); BOOST_CHECK_EQUAL(d.getStrides(), c[1].getStrides()); BOOST_CHECK(d.shallow() == c[1].shallow()); } BOOST_AUTO_TEST_CASE(casts) { double data[3*4*2] = {0}; ndarray::Vector shape = ndarray::makeVector(3,4,2); ndarray::Vector strides = ndarray::makeVector(8,2,1); ndarray::Array a = ndarray::external(data,shape,strides); ndarray::Array b = ndarray::static_dimension_cast<2>(a); BOOST_CHECK(a == b); ndarray::Array c = ndarray::const_array_cast(a); BOOST_CHECK(a == c); ndarray::Array d = ndarray::dynamic_dimension_cast<3>(a); BOOST_CHECK(a == d); ndarray::Array e = d[ndarray::view()(0,4,2)()]; ndarray::Array f = ndarray::dynamic_dimension_cast<3>(e); BOOST_CHECK(f.empty()); } BOOST_AUTO_TEST_CASE(complex) { std::complex data[3*4*2] = { std::complex(0.0,0.0) }; ndarray::Vector shape = ndarray::makeVector(3,4,2); ndarray::Vector strides = ndarray::makeVector(8,2,1); ndarray::Array,3,3> a = ndarray::external(data,shape,strides); ndarray::Array re(getReal(a)); ndarray::Array im(getImag(a)); a[1][2][0] = std::complex(4.5,1.2); BOOST_CHECK(re[1][2][0] == 4.5); BOOST_CHECK(im[1][2][0] == 1.2); } BOOST_AUTO_TEST_CASE(indexing) { double data[3*4*2] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, }; ndarray::Vector a_shape = ndarray::makeVector(4,3,2); ndarray::Vector a_strides = ndarray::makeVector(6,2,1); ndarray::Array a = ndarray::external(data, a_shape, a_strides); BOOST_CHECK(a.front().shallow() == a[0].shallow()); BOOST_CHECK(a.back().shallow() == a[a_shape[0]-1].shallow()); ndarray::Size n = 0; for (ndarray::Size i=0; i b_shape = ndarray::makeVector(8,3); ndarray::Vector b_strides = ndarray::makeVector(1,8); ndarray::Array b = ndarray::external(data, b_shape, b_strides); for (ndarray::Size i=0; i c_shape = ndarray::makeVector(4,3); ndarray::Vector c_strides = ndarray::makeVector(1,8); ndarray::Array c = ndarray::external(data, c_shape, c_strides); for (ndarray::Size i=0; i a_shape = ndarray::makeVector(4,3,2); ndarray::Vector a_strides = ndarray::makeVector(6,2,1); ndarray::Array a = ndarray::external(data, a_shape, a_strides); ndarray::Array::Iterator ai_iter = a.begin(); ndarray::Array::Iterator const ai_end = a.end(); for (int i=0; ai_iter != ai_end; ++i, ++ai_iter) { ndarray::Array::Reference::Iterator aj_iter = ai_iter->begin(); ndarray::Array::Reference::Iterator const aj_end = ai_iter->end(); for (int j=0; aj_iter != aj_end; ++j, ++aj_iter) { ndarray::Array::Reference::Reference::Iterator ak_iter = aj_iter->begin(); ndarray::Array::Reference::Reference::Iterator const ak_end = aj_iter->end(); for (int k=0; ak_iter != ak_end; ++k, ++ak_iter) { BOOST_CHECK_EQUAL(a[i][j][k], *ak_iter); } } } ndarray::Vector b_shape = ndarray::makeVector(4,3); ndarray::Vector b_strides = ndarray::makeVector(1,8); ndarray::Array b = ndarray::external(data, b_shape, b_strides); ndarray::Array::Iterator bi_iter = b.begin(); ndarray::Array::Iterator const bi_end = b.end(); for (int i=0; bi_iter != bi_end; ++i, ++bi_iter) { ndarray::Array::Reference::Iterator bj_iter = bi_iter->begin(); ndarray::Array::Reference::Iterator const bj_end = bi_iter->end(); for (int j=0; bj_iter != bj_end; ++j, ++bj_iter) { BOOST_CHECK_EQUAL(b[i][j], *bj_iter); } } } BOOST_AUTO_TEST_CASE(views) { ndarray::Vector shape = ndarray::makeVector(4,3,2); ndarray::Array a = ndarray::allocate(shape); BOOST_CHECK(a == a[ndarray::view()()].shallow()); BOOST_CHECK(a == a[ndarray::view()].shallow()); BOOST_CHECK(a[1].shallow() == a[ndarray::view(1)].shallow()); BOOST_CHECK(a[1][2].shallow() == a[ndarray::view(1)(2)].shallow()); BOOST_CHECK(a != a[ndarray::view(0,3)].shallow()); ndarray::Array b = a[ndarray::view()(1,3)(0)]; BOOST_CHECK(b.getShape() == ndarray::makeVector(4,2)); BOOST_CHECK(b.getStrides() == ndarray::makeVector(6,2)); BOOST_CHECK(b.getData() == a.getData() + 2); ndarray::Array c = b[ndarray::view(0,4,2)()]; BOOST_CHECK(c.getShape() == ndarray::makeVector(2,2)); BOOST_CHECK(c.getStrides() == ndarray::makeVector(12,2)); BOOST_CHECK(c.getData() == b.getData()); } #ifndef GCC_45 BOOST_AUTO_TEST_CASE(predicates) { double data1[3*4*2] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, }; double data2[3*4*2] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, }; ndarray::Vector shape = ndarray::makeVector(4,3,2); ndarray::Vector strides = ndarray::makeVector(6,2,1); ndarray::Array a = ndarray::external(data1, shape, strides); ndarray::Array b = ndarray::allocate(shape); ndarray::Array c = ndarray::allocate(shape); ndarray::Array d = ndarray::external(data2,shape,strides); b.deep() = equal(a, 3.0); c.deep() = logical_not(b); BOOST_CHECK(a != d); BOOST_CHECK(all(equal(a, d))); BOOST_CHECK(ndarray::any(equal(a, d))); d[3][1][0] = 5.0; BOOST_CHECK(!ndarray::all(equal(a, d))); BOOST_CHECK(ndarray::any(equal(a, d))); BOOST_CHECK(ndarray::any(not_equal(a, d))); d.deep() = -5.0; BOOST_CHECK(!ndarray::all(equal(a, d))); BOOST_CHECK(ndarray::all(not_equal(a, d))); BOOST_CHECK(ndarray::all(greater(a, d))); BOOST_CHECK(!ndarray::any(equal(a, d))); for (int i=0; i shape = ndarray::makeVector(4,3,2); ndarray::Vector strides = ndarray::makeVector(6,2,1); ndarray::Array a = ndarray::external(data,shape,strides); ndarray::Array b = ndarray::allocate(ndarray::concatenate(shape, 3)); ndarray::Array c = ndarray::allocate(shape); c.deep() = a + 1.2; b.deep() = a + 1.2; BOOST_CHECK(ndarray::allclose(c, b)); b.deep() += 1E-9; BOOST_CHECK(ndarray::allclose(c, b, 1E-8)); BOOST_CHECK(!ndarray::allclose(c, b, 1E-10)); } BOOST_AUTO_TEST_CASE(binary_ops) { float data[3*4*2] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, }; ndarray::Vector shape = ndarray::makeVector(4,3,2); ndarray::Vector strides = ndarray::makeVector(6,2,1); ndarray::Array a = ndarray::external(data,shape,strides); ndarray::Array b = ndarray::allocate(shape); ndarray::Array c = ndarray::allocate(shape); c.deep() = 0.0; double q = 1.2; b.deep() = a + q; c.deep() -= (a * b - q); for (int i=0; i shape3 = ndarray::makeVector(3,4,2); ndarray::Vector strides3 = ndarray::makeVector(8,2,1); ndarray::Vector shape2 = ndarray::makeVector(3,4); ndarray::Vector strides2 = ndarray::makeVector(4,1); ndarray::Array a3 = ndarray::external(data3,shape3,strides3); ndarray::Array a32 = ndarray::external(data32,shape3,strides3); ndarray::Array a2 = ndarray::external(data2,shape2,strides2); ndarray::Array b3 = ndarray::copy(a3); ndarray::Array b32 = ndarray::copy(a32); ndarray::Array b2 = ndarray::copy(a2); ndarray::Array c3 = ndarray::allocate(shape3); ndarray::Array c32 = ndarray::allocate(shape3); c3.deep() = 0.0; c3.deep() -= 2.0 * b2; c32.deep() = 0.0; c32.deep() -= 2.0 * b32; BOOST_CHECK(all(equal(c3, c32))); c3.deep() += b2; c32.deep() += b32; BOOST_CHECK(all(equal(c3, c32))); } #endif BOOST_AUTO_TEST_CASE(assignment) { double data[3*4*2] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, }; ndarray::Vector shape = ndarray::makeVector(3,4,2); ndarray::Vector strides = ndarray::makeVector(8,2,1); ndarray::Array a = ndarray::external(data,shape,strides); ndarray::Array b = ndarray::allocate(shape); b.deep() = a; ndarray::Array c = ndarray::allocate(shape); ndarray::Array d = c; c.deep() = a; BOOST_CHECK(a.shallow() != b.shallow()); BOOST_CHECK(a.shallow() != c.shallow()); int n = 0; for (int i=0; i shape = ndarray::makeVector(3,4,2); ndarray::Vector strides = ndarray::makeVector(8,2,1); ndarray::Array a = ndarray::external(data,shape,strides); ndarray::Array b = a.transpose(); ndarray::Array c = a.transpose(ndarray::makeVector(1,0,2)); for (int i=0; i a1 = a[ndarray::view(0)()()]; ndarray::Array b1 = b[ndarray::view()()(0)]; BOOST_CHECK(b1.transpose().shallow() == a1.shallow()); BOOST_CHECK(a1.transpose().shallow() == b1.shallow()); } { ndarray::Array a1 = a[ndarray::view(1,3)()()]; ndarray::Array b1 = b[ndarray::view()()(1,3)]; BOOST_CHECK(b1.transpose().shallow() == a1.shallow()); BOOST_CHECK(a1.transpose().shallow() == b1.shallow()); } { ndarray::Array a1 = a[ndarray::view(0,3,2)()()]; ndarray::Array b1 = b[ndarray::view()()(0,3,2)]; BOOST_CHECK(b1.transpose().shallow() == a1.shallow()); BOOST_CHECK(a1.transpose().shallow() == b1.shallow()); } { ndarray::Array a1 = a[ndarray::view()(1,3)()]; ndarray::Array b1 = b[ndarray::view()(1,3)()]; BOOST_CHECK(b1.transpose().shallow() == a1.shallow()); BOOST_CHECK(a1.transpose().shallow() == b1.shallow()); } { ndarray::Array a1 = a[ndarray::view()(0,4,2)()]; ndarray::Array b1 = b[ndarray::view()(0,4,2)()]; BOOST_CHECK(b1.transpose().shallow() == a1.shallow()); BOOST_CHECK(a1.transpose().shallow() == b1.shallow()); } { ndarray::Array a1 = a[0][0]; ndarray::Array b1 = a1; ndarray::Array c1 = b1; } } BOOST_AUTO_TEST_CASE(flatten) { double data[3*4*2] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, }; ndarray::Vector a_shape = ndarray::makeVector(4,3,2); ndarray::Vector a_strides = ndarray::makeVector(6,2,1); ndarray::Array a = ndarray::external(data,a_shape,a_strides); ndarray::Array b = ndarray::flatten<2>(a); ndarray::Array b_check = ndarray::external( data, ndarray::makeVector(4,6), ndarray::makeVector(6,1) ); BOOST_CHECK(b.shallow() == b_check.shallow()); ndarray::Array c = ndarray::flatten<1>(a); ndarray::Array c_check = ndarray::external( data, ndarray::makeVector(24), ndarray::makeVector(1) ); } BOOST_AUTO_TEST_CASE(unique) { ndarray::Array a = ndarray::allocate(5,4); BOOST_CHECK(a.isUnique()); ndarray::Array b(a); BOOST_CHECK(!a.isUnique()); BOOST_CHECK(!b.isUnique()); a = ndarray::Array(); BOOST_CHECK(b.isUnique()); ndarray::Array c = b[ndarray::view(1,4)(1,3)]; BOOST_CHECK(!c.isUnique()); BOOST_CHECK(!b.isUnique()); b = ndarray::Array(); BOOST_CHECK(c.isUnique()); ndarray::Array d = ndarray::allocate(6,3); d.swap(c); BOOST_CHECK(c.isUnique()); BOOST_CHECK(d.isUnique()); } BOOST_AUTO_TEST_CASE(ticket1720) { ndarray::Array a = ndarray::allocate(5,4); a.deep() = 0; ndarray::Array b = ndarray::allocate(5,4); b.deep() = 1; a[0] = b[1]; BOOST_CHECK_EQUAL(a[0][0], 1); ndarray::Array c(b); a[1] = c[1]; BOOST_CHECK_EQUAL(a[1][0], 1); } BOOST_AUTO_TEST_CASE(zeroSize) { ndarray::Array a = ndarray::allocate(0); BOOST_CHECK(!a.getData()); BOOST_CHECK_EQUAL(a.getSize<0>(), 0); ndarray::Array b = ndarray::allocate(0, 5); BOOST_CHECK(!b.getData()); BOOST_CHECK_EQUAL(b.getSize<0>(), 0); BOOST_CHECK_EQUAL(b.getSize<1>(), 5); ndarray::Array c = ndarray::allocate(5, 0); BOOST_CHECK(!c.getData()); BOOST_CHECK_EQUAL(c.getSize<0>(), 5); BOOST_CHECK_EQUAL(c.getSize<1>(), 0); } BOOST_AUTO_TEST_CASE(manager) { ndarray::Array a = ndarray::allocate(5); ndarray::Array b = ndarray::external(a.getData(), a.getShape(), a.getStrides(), a.getManager()); BOOST_CHECK_EQUAL(a.getManager(), b.getManager()); // no extra indirection in makeManager } BOOST_AUTO_TEST_CASE(issue3) { ndarray::Array a1(5); ndarray::Array r1(5); BOOST_CHECK_EQUAL(a1.getSize<0>(), 5); BOOST_CHECK_EQUAL(r1.getSize<0>(), 5); ndarray::Array a2(5); ndarray::ArrayRef r2(5); ndarray::Array b2(5, 4); ndarray::ArrayRef s2(5, 4); BOOST_CHECK_EQUAL(a2.getSize<0>(), 5); BOOST_CHECK_EQUAL(a2.getSize<1>(), 1); BOOST_CHECK_EQUAL(r2.getSize<0>(), 5); BOOST_CHECK_EQUAL(r2.getSize<1>(), 1); BOOST_CHECK_EQUAL(b2.getSize<0>(), 5); BOOST_CHECK_EQUAL(b2.getSize<1>(), 4); BOOST_CHECK_EQUAL(s2.getSize<0>(), 5); BOOST_CHECK_EQUAL(s2.getSize<1>(), 4); ndarray::Array a5(5); ndarray::ArrayRef r5(5); ndarray::Array b5(5, 4, 3, 2); ndarray::ArrayRef s5(5, 4, 3, 2); BOOST_CHECK_EQUAL(a5.getSize<0>(), 5); BOOST_CHECK_EQUAL(a5.getSize<1>(), 1); BOOST_CHECK_EQUAL(a5.getSize<2>(), 1); BOOST_CHECK_EQUAL(a5.getSize<3>(), 1); BOOST_CHECK_EQUAL(a5.getSize<4>(), 1); BOOST_CHECK_EQUAL(r5.getSize<0>(), 5); BOOST_CHECK_EQUAL(r5.getSize<1>(), 1); BOOST_CHECK_EQUAL(r5.getSize<2>(), 1); BOOST_CHECK_EQUAL(r5.getSize<3>(), 1); BOOST_CHECK_EQUAL(r5.getSize<4>(), 1); BOOST_CHECK_EQUAL(b5.getSize<0>(), 5); BOOST_CHECK_EQUAL(b5.getSize<1>(), 4); BOOST_CHECK_EQUAL(b5.getSize<2>(), 3); BOOST_CHECK_EQUAL(b5.getSize<3>(), 2); BOOST_CHECK_EQUAL(b5.getSize<4>(), 1); BOOST_CHECK_EQUAL(s5.getSize<0>(), 5); BOOST_CHECK_EQUAL(s5.getSize<1>(), 4); BOOST_CHECK_EQUAL(s5.getSize<2>(), 3); BOOST_CHECK_EQUAL(s5.getSize<3>(), 2); BOOST_CHECK_EQUAL(s5.getSize<4>(), 1); }