123 lines
3.5 KiB
C++
123 lines
3.5 KiB
C++
// Copyright (c) 2018-2019 Cem Bassoy
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See
|
|
// accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// The authors gratefully acknowledge the support of
|
|
// Fraunhofer and Google in producing this work
|
|
// which started as a Google Summer of Code project.
|
|
//
|
|
// And we acknowledge the support from all contributors.
|
|
|
|
|
|
#include <iostream>
|
|
#include <algorithm>
|
|
#include <boost/numeric/ublas/tensor.hpp>
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include "utility.hpp"
|
|
|
|
BOOST_AUTO_TEST_SUITE ( test_einstein_notation, * boost::unit_test::depends_on("test_multi_index") )
|
|
|
|
|
|
using test_types = zip<int,long,float,double,std::complex<float>>::with_t<boost::numeric::ublas::first_order, boost::numeric::ublas::last_order>;
|
|
|
|
//using test_types = zip<int>::with_t<boost::numeric::ublas::first_order>;
|
|
|
|
BOOST_AUTO_TEST_CASE_TEMPLATE( test_einstein_multiplication, value, test_types )
|
|
{
|
|
using namespace boost::numeric::ublas;
|
|
using value_type = typename value::first_type;
|
|
using layout_type = typename value::second_type;
|
|
using tensor_type = tensor<value_type,layout_type>;
|
|
using namespace boost::numeric::ublas::index;
|
|
|
|
{
|
|
auto A = tensor_type{5,3};
|
|
auto B = tensor_type{3,4};
|
|
// auto C = tensor_type{4,5,6};
|
|
|
|
for(auto j = 0u; j < A.extents().at(1); ++j)
|
|
for(auto i = 0u; i < A.extents().at(0); ++i)
|
|
A.at( i,j ) = value_type(i+1);
|
|
|
|
for(auto j = 0u; j < B.extents().at(1); ++j)
|
|
for(auto i = 0u; i < B.extents().at(0); ++i)
|
|
B.at( i,j ) = value_type(i+1);
|
|
|
|
|
|
|
|
auto AB = A(_,_e) * B(_e,_);
|
|
|
|
// std::cout << "A = " << A << std::endl;
|
|
// std::cout << "B = " << B << std::endl;
|
|
// std::cout << "AB = " << AB << std::endl;
|
|
|
|
for(auto j = 0u; j < AB.extents().at(1); ++j)
|
|
for(auto i = 0u; i < AB.extents().at(0); ++i)
|
|
BOOST_CHECK_EQUAL( AB.at( i,j ) , value_type(A.at( i,0 ) * ( B.extents().at(0) * (B.extents().at(0)+1) / 2 )) );
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
auto A = tensor_type{4,5,3};
|
|
auto B = tensor_type{3,4,2};
|
|
|
|
for(auto k = 0u; k < A.extents().at(2); ++k)
|
|
for(auto j = 0u; j < A.extents().at(1); ++j)
|
|
for(auto i = 0u; i < A.extents().at(0); ++i)
|
|
A.at( i,j,k ) = value_type(i+1);
|
|
|
|
for(auto k = 0u; k < B.extents().at(2); ++k)
|
|
for(auto j = 0u; j < B.extents().at(1); ++j)
|
|
for(auto i = 0u; i < B.extents().at(0); ++i)
|
|
B.at( i,j,k ) = value_type(i+1);
|
|
|
|
auto AB = A(_d,_,_f) * B(_f,_d,_);
|
|
|
|
// std::cout << "A = " << A << std::endl;
|
|
// std::cout << "B = " << B << std::endl;
|
|
// std::cout << "AB = " << AB << std::endl;
|
|
// n*(n+1)/2;
|
|
auto const nf = ( B.extents().at(0) * (B.extents().at(0)+1) / 2 );
|
|
auto const nd = ( A.extents().at(0) * (A.extents().at(0)+1) / 2 );
|
|
|
|
for(auto j = 0u; j < AB.extents().at(1); ++j)
|
|
for(auto i = 0u; i < AB.extents().at(0); ++i)
|
|
BOOST_CHECK_EQUAL( AB.at( i,j ) , value_type(nf * nd) );
|
|
|
|
}
|
|
|
|
|
|
{
|
|
auto A = tensor_type{4,3};
|
|
auto B = tensor_type{3,4,2};
|
|
|
|
for(auto j = 0u; j < A.extents().at(1); ++j)
|
|
for(auto i = 0u; i < A.extents().at(0); ++i)
|
|
A.at( i,j ) = value_type(i+1);
|
|
|
|
for(auto k = 0u; k < B.extents().at(2); ++k)
|
|
for(auto j = 0u; j < B.extents().at(1); ++j)
|
|
for(auto i = 0u; i < B.extents().at(0); ++i)
|
|
B.at( i,j,k ) = value_type(i+1);
|
|
|
|
auto AB = A(_d,_f) * B(_f,_d,_);
|
|
|
|
// n*(n+1)/2;
|
|
auto const nf = ( B.extents().at(0) * (B.extents().at(0)+1) / 2 );
|
|
auto const nd = ( A.extents().at(0) * (A.extents().at(0)+1) / 2 );
|
|
|
|
for(auto i = 0u; i < AB.extents().at(0); ++i)
|
|
BOOST_CHECK_EQUAL ( AB.at( i ) , value_type(nf * nd) );
|
|
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|
|
|