Merged eigen/eigen into default

This commit is contained in:
Tal Hadad
2015-12-20 12:50:07 +02:00
296 changed files with 10487 additions and 4148 deletions

View File

@@ -49,11 +49,11 @@ ei_add_test(EulerAngles)
find_package(MPFR 2.3.0)
find_package(GMP)
if(MPFR_FOUND)
if(MPFR_FOUND AND EIGEN_COMPILER_SUPPORT_CXX11)
include_directories(${MPFR_INCLUDES} ./mpreal)
ei_add_property(EIGEN_TESTED_BACKENDS "MPFR C++, ")
set(EIGEN_MPFR_TEST_LIBRARIES ${MPFR_LIBRARIES} ${GMP_LIBRARIES})
ei_add_test(mpreal_support "" "${EIGEN_MPFR_TEST_LIBRARIES}" )
ei_add_test(mpreal_support "-std=c++11" "${EIGEN_MPFR_TEST_LIBRARIES}" )
else()
ei_add_property(EIGEN_MISSING_BACKENDS "MPFR C++, ")
endif()
@@ -93,7 +93,6 @@ endif()
ei_add_test(polynomialsolver)
ei_add_test(polynomialutils)
ei_add_test(splines)
ei_add_test(incomplete_cholesky)
ei_add_test(gmres)
ei_add_test(minres)
ei_add_test(levenberg_marquardt)
@@ -120,6 +119,7 @@ if(EIGEN_TEST_CXX11)
ei_add_test(cxx11_tensor_of_const_values "-std=c++0x")
ei_add_test(cxx11_tensor_of_complex "-std=c++0x")
ei_add_test(cxx11_tensor_of_strings "-std=c++0x")
ei_add_test(cxx11_tensor_uint128 "-std=c++0x")
ei_add_test(cxx11_tensor_intdiv "-std=c++0x")
ei_add_test(cxx11_tensor_lvalue "-std=c++0x")
ei_add_test(cxx11_tensor_map "-std=c++0x")
@@ -145,6 +145,10 @@ if(EIGEN_TEST_CXX11)
ei_add_test(cxx11_tensor_io "-std=c++0x")
ei_add_test(cxx11_tensor_generator "-std=c++0x")
ei_add_test(cxx11_tensor_custom_op "-std=c++0x")
ei_add_test(cxx11_tensor_custom_index "-std=c++0x")
ei_add_test(cxx11_tensor_sugar "-std=c++0x")
ei_add_test(cxx11_tensor_fft "-std=c++0x")
ei_add_test(cxx11_tensor_ifft "-std=c++0x")
# These tests needs nvcc
# ei_add_test(cxx11_tensor_device "-std=c++0x")

View File

@@ -129,6 +129,7 @@ template<typename Func> void forward_jacobian(const Func& f)
// TODO also check actual derivatives!
template <int>
void test_autodiff_scalar()
{
Vector2f p = Vector2f::Random();
@@ -140,6 +141,7 @@ void test_autodiff_scalar()
}
// TODO also check actual derivatives!
template <int>
void test_autodiff_vector()
{
Vector2f p = Vector2f::Random();
@@ -153,6 +155,7 @@ void test_autodiff_vector()
VERIFY_IS_APPROX(res.value(), foo(p));
}
template <int>
void test_autodiff_jacobian()
{
CALL_SUBTEST(( forward_jacobian(TestFunc1<double,2,2>()) ));
@@ -162,12 +165,56 @@ void test_autodiff_jacobian()
CALL_SUBTEST(( forward_jacobian(TestFunc1<double>(3,3)) ));
}
template <int>
void test_autodiff_hessian()
{
typedef AutoDiffScalar<VectorXd> AD;
typedef Matrix<AD,Eigen::Dynamic,1> VectorAD;
typedef AutoDiffScalar<VectorAD> ADD;
typedef Matrix<ADD,Eigen::Dynamic,1> VectorADD;
VectorADD x(2);
double s1 = internal::random<double>(), s2 = internal::random<double>(), s3 = internal::random<double>(), s4 = internal::random<double>();
x(0).value()=s1;
x(1).value()=s2;
//set unit vectors for the derivative directions (partial derivatives of the input vector)
x(0).derivatives().resize(2);
x(0).derivatives().setZero();
x(0).derivatives()(0)= 1;
x(1).derivatives().resize(2);
x(1).derivatives().setZero();
x(1).derivatives()(1)=1;
//repeat partial derivatives for the inner AutoDiffScalar
x(0).value().derivatives() = VectorXd::Unit(2,0);
x(1).value().derivatives() = VectorXd::Unit(2,1);
//set the hessian matrix to zero
for(int idx=0; idx<2; idx++) {
x(0).derivatives()(idx).derivatives() = VectorXd::Zero(2);
x(1).derivatives()(idx).derivatives() = VectorXd::Zero(2);
}
ADD y = sin(AD(s3)*x(0) + AD(s4)*x(1));
VERIFY_IS_APPROX(y.value().derivatives()(0), y.derivatives()(0).value());
VERIFY_IS_APPROX(y.value().derivatives()(1), y.derivatives()(1).value());
VERIFY_IS_APPROX(y.value().derivatives()(0), s3*std::cos(s1*s3+s2*s4));
VERIFY_IS_APPROX(y.value().derivatives()(1), s4*std::cos(s1*s3+s2*s4));
VERIFY_IS_APPROX(y.derivatives()(0).derivatives(), -std::sin(s1*s3+s2*s4)*Vector2d(s3*s3,s4*s3));
VERIFY_IS_APPROX(y.derivatives()(1).derivatives(), -std::sin(s1*s3+s2*s4)*Vector2d(s3*s4,s4*s4));
}
void test_autodiff()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( test_autodiff_scalar() );
CALL_SUBTEST_2( test_autodiff_vector() );
CALL_SUBTEST_3( test_autodiff_jacobian() );
CALL_SUBTEST_1( test_autodiff_scalar<1>() );
CALL_SUBTEST_2( test_autodiff_vector<1>() );
CALL_SUBTEST_3( test_autodiff_jacobian<1>() );
CALL_SUBTEST_4( test_autodiff_hessian<1>() );
}
}

View File

@@ -61,14 +61,14 @@ static void test_argmax_tuple_reducer()
Tensor<Tuple<DenseIndex, float>, 4, DataLayout> index_tuples(2,3,5,7);
index_tuples = tensor.index_tuples();
Tensor<Tuple<DenseIndex, float>, 1, DataLayout> reduced(1);
Tensor<Tuple<DenseIndex, float>, 0, DataLayout> reduced;
DimensionList<DenseIndex, 4> dims;
reduced = index_tuples.reduce(
dims, internal::ArgMaxTupleReducer<Tuple<DenseIndex, float>>());
Tensor<float, 1, DataLayout> maxi = tensor.maximum();
Tensor<float, 0, DataLayout> maxi = tensor.maximum();
VERIFY_IS_EQUAL(maxi(0), reduced(0).second);
VERIFY_IS_EQUAL(maxi(), reduced(0).second);
array<DenseIndex, 3> reduce_dims;
for (int d = 0; d < 3; ++d) reduce_dims[d] = d;
@@ -93,14 +93,14 @@ static void test_argmin_tuple_reducer()
Tensor<Tuple<DenseIndex, float>, 4, DataLayout> index_tuples(2,3,5,7);
index_tuples = tensor.index_tuples();
Tensor<Tuple<DenseIndex, float>, 1, DataLayout> reduced(1);
Tensor<Tuple<DenseIndex, float>, 0, DataLayout> reduced;
DimensionList<DenseIndex, 4> dims;
reduced = index_tuples.reduce(
dims, internal::ArgMinTupleReducer<Tuple<DenseIndex, float>>());
Tensor<float, 1, DataLayout> mini = tensor.minimum();
Tensor<float, 0, DataLayout> mini = tensor.minimum();
VERIFY_IS_EQUAL(mini(0), reduced(0).second);
VERIFY_IS_EQUAL(mini(), reduced(0).second);
array<DenseIndex, 3> reduce_dims;
for (int d = 0; d < 3; ++d) reduce_dims[d] = d;
@@ -123,7 +123,7 @@ static void test_simple_argmax()
tensor = (tensor + tensor.constant(0.5)).log();
tensor(0,0,0,0) = 10.0;
Tensor<DenseIndex, 1, DataLayout> tensor_argmax(1);
Tensor<DenseIndex, 0, DataLayout> tensor_argmax;
tensor_argmax = tensor.argmax();
@@ -144,7 +144,7 @@ static void test_simple_argmin()
tensor = (tensor + tensor.constant(0.5)).log();
tensor(0,0,0,0) = -10.0;
Tensor<DenseIndex, 1, DataLayout> tensor_argmin(1);
Tensor<DenseIndex, 0, DataLayout> tensor_argmin;
tensor_argmin = tensor.argmin();

View File

@@ -29,8 +29,8 @@ static void test_1d()
int row_major[6];
memset(col_major, 0, 6*sizeof(int));
memset(row_major, 0, 6*sizeof(int));
TensorMap<Tensor<int, 1>> vec3(col_major, 6);
TensorMap<Tensor<int, 1, RowMajor>> vec4(row_major, 6);
TensorMap<Tensor<int, 1> > vec3(col_major, 6);
TensorMap<Tensor<int, 1, RowMajor> > vec4(row_major, 6);
vec3 = vec1;
vec4 = vec2;
@@ -92,8 +92,8 @@ static void test_2d()
int row_major[6];
memset(col_major, 0, 6*sizeof(int));
memset(row_major, 0, 6*sizeof(int));
TensorMap<Tensor<int, 2>> mat3(row_major, 2, 3);
TensorMap<Tensor<int, 2, RowMajor>> mat4(col_major, 2, 3);
TensorMap<Tensor<int, 2> > mat3(row_major, 2, 3);
TensorMap<Tensor<int, 2, RowMajor> > mat4(col_major, 2, 3);
mat3 = mat1;
mat4 = mat2;
@@ -152,8 +152,8 @@ static void test_3d()
int row_major[2*3*7];
memset(col_major, 0, 2*3*7*sizeof(int));
memset(row_major, 0, 2*3*7*sizeof(int));
TensorMap<Tensor<int, 3>> mat3(col_major, 2, 3, 7);
TensorMap<Tensor<int, 3, RowMajor>> mat4(row_major, 2, 3, 7);
TensorMap<Tensor<int, 3> > mat3(col_major, 2, 3, 7);
TensorMap<Tensor<int, 3, RowMajor> > mat4(row_major, 2, 3, 7);
mat3 = mat1;
mat4 = mat2;

View File

@@ -24,12 +24,12 @@ static void test_simple_cast()
cplextensor.setRandom();
chartensor = ftensor.cast<char>();
cplextensor = ftensor.cast<std::complex<float>>();
cplextensor = ftensor.cast<std::complex<float> >();
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 30; ++j) {
VERIFY_IS_EQUAL(chartensor(i,j), static_cast<char>(ftensor(i,j)));
VERIFY_IS_EQUAL(cplextensor(i,j), static_cast<std::complex<float>>(ftensor(i,j)));
VERIFY_IS_EQUAL(cplextensor(i,j), static_cast<std::complex<float> >(ftensor(i,j)));
}
}
}

View File

@@ -507,6 +507,115 @@ static void test_cuda_convolution_3d()
}
}
template <typename Scalar>
void test_cuda_lgamma(const Scalar stddev)
{
Tensor<Scalar, 2> in(72,97);
in.setRandom();
in *= in.constant(stddev);
Tensor<Scalar, 2> out(72,97);
out.setZero();
std::size_t bytes = in.size() * sizeof(Scalar);
Scalar* d_in;
Scalar* d_out;
cudaMalloc((void**)(&d_in), bytes);
cudaMalloc((void**)(&d_out), bytes);
cudaMemcpy(d_in, in.data(), bytes, cudaMemcpyHostToDevice);
Eigen::CudaStreamDevice stream;
Eigen::GpuDevice gpu_device(&stream);
Eigen::TensorMap<Eigen::Tensor<Scalar, 2> > gpu_in(d_in, 72, 97);
Eigen::TensorMap<Eigen::Tensor<Scalar, 2> > gpu_out(d_out, 72, 97);
gpu_out.device(gpu_device) = gpu_in.lgamma();
assert(cudaMemcpyAsync(out.data(), d_out, bytes, cudaMemcpyDeviceToHost, gpu_device.stream()) == cudaSuccess);
assert(cudaStreamSynchronize(gpu_device.stream()) == cudaSuccess);
for (int i = 0; i < 72; ++i) {
for (int j = 0; j < 97; ++j) {
VERIFY_IS_APPROX(out(i,j), (std::lgamma)(in(i,j)));
}
}
}
template <typename Scalar>
void test_cuda_erf(const Scalar stddev)
{
Tensor<Scalar, 2> in(72,97);
in.setRandom();
in *= in.constant(stddev);
Tensor<Scalar, 2> out(72,97);
out.setZero();
std::size_t bytes = in.size() * sizeof(Scalar);
Scalar* d_in;
Scalar* d_out;
cudaMalloc((void**)(&d_in), bytes);
cudaMalloc((void**)(&d_out), bytes);
cudaMemcpy(d_in, in.data(), bytes, cudaMemcpyHostToDevice);
Eigen::CudaStreamDevice stream;
Eigen::GpuDevice gpu_device(&stream);
Eigen::TensorMap<Eigen::Tensor<Scalar, 2> > gpu_in(d_in, 72, 97);
Eigen::TensorMap<Eigen::Tensor<Scalar, 2> > gpu_out(d_out, 72, 97);
gpu_out.device(gpu_device) = gpu_in.erf();
assert(cudaMemcpyAsync(out.data(), d_out, bytes, cudaMemcpyDeviceToHost, gpu_device.stream()) == cudaSuccess);
assert(cudaStreamSynchronize(gpu_device.stream()) == cudaSuccess);
for (int i = 0; i < 72; ++i) {
for (int j = 0; j < 97; ++j) {
VERIFY_IS_APPROX(out(i,j), (std::erf)(in(i,j)));
}
}
}
template <typename Scalar>
void test_cuda_erfc(const Scalar stddev)
{
Tensor<Scalar, 2> in(72,97);
in.setRandom();
in *= in.constant(stddev);
Tensor<Scalar, 2> out(72,97);
out.setZero();
std::size_t bytes = in.size() * sizeof(Scalar);
Scalar* d_in;
Scalar* d_out;
cudaMalloc((void**)(&d_in), bytes);
cudaMalloc((void**)(&d_out), bytes);
cudaMemcpy(d_in, in.data(), bytes, cudaMemcpyHostToDevice);
Eigen::CudaStreamDevice stream;
Eigen::GpuDevice gpu_device(&stream);
Eigen::TensorMap<Eigen::Tensor<Scalar, 2> > gpu_in(d_in, 72, 97);
Eigen::TensorMap<Eigen::Tensor<Scalar, 2> > gpu_out(d_out, 72, 97);
gpu_out.device(gpu_device) = gpu_in.erfc();
assert(cudaMemcpyAsync(out.data(), d_out, bytes, cudaMemcpyDeviceToHost, gpu_device.stream()) == cudaSuccess);
assert(cudaStreamSynchronize(gpu_device.stream()) == cudaSuccess);
for (int i = 0; i < 72; ++i) {
for (int j = 0; j < 97; ++j) {
VERIFY_IS_APPROX(out(i,j), (std::erfc)(in(i,j)));
}
}
}
void test_cxx11_tensor_cuda()
{
CALL_SUBTEST(test_cuda_elementwise_small());
@@ -522,4 +631,34 @@ void test_cxx11_tensor_cuda()
CALL_SUBTEST(test_cuda_convolution_2d<RowMajor>());
CALL_SUBTEST(test_cuda_convolution_3d<ColMajor>());
CALL_SUBTEST(test_cuda_convolution_3d<RowMajor>());
CALL_SUBTEST(test_cuda_lgamma<float>(1.0f));
CALL_SUBTEST(test_cuda_lgamma<float>(100.0f));
CALL_SUBTEST(test_cuda_lgamma<float>(0.01f));
CALL_SUBTEST(test_cuda_lgamma<float>(0.001f));
CALL_SUBTEST(test_cuda_erf<float>(1.0f));
CALL_SUBTEST(test_cuda_erf<float>(100.0f));
CALL_SUBTEST(test_cuda_erf<float>(0.01f));
CALL_SUBTEST(test_cuda_erf<float>(0.001f));
CALL_SUBTEST(test_cuda_erfc<float>(1.0f));
// CALL_SUBTEST(test_cuda_erfc<float>(100.0f));
CALL_SUBTEST(test_cuda_erfc<float>(5.0f)); // CUDA erfc lacks precision for large inputs
CALL_SUBTEST(test_cuda_erfc<float>(0.01f));
CALL_SUBTEST(test_cuda_erfc<float>(0.001f));
CALL_SUBTEST(test_cuda_tanh<double>(1.0));
CALL_SUBTEST(test_cuda_tanh<double>(100.0));
CALL_SUBTEST(test_cuda_tanh<double>(0.01));
CALL_SUBTEST(test_cuda_tanh<double>(0.001));
CALL_SUBTEST(test_cuda_lgamma<double>(1.0));
CALL_SUBTEST(test_cuda_lgamma<double>(100.0));
CALL_SUBTEST(test_cuda_lgamma<double>(0.01));
CALL_SUBTEST(test_cuda_lgamma<double>(0.001));
CALL_SUBTEST(test_cuda_erf<double>(1.0));
CALL_SUBTEST(test_cuda_erf<double>(100.0));
CALL_SUBTEST(test_cuda_erf<double>(0.01));
CALL_SUBTEST(test_cuda_erf<double>(0.001));
CALL_SUBTEST(test_cuda_erfc<double>(1.0));
// CALL_SUBTEST(test_cuda_erfc<double>(100.0));
CALL_SUBTEST(test_cuda_erfc<double>(5.0)); // CUDA erfc lacks precision for large inputs
CALL_SUBTEST(test_cuda_erfc<double>(0.01));
CALL_SUBTEST(test_cuda_erfc<double>(0.001));
}

View File

@@ -0,0 +1,100 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2015 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "main.h"
#include <limits>
#include <map>
#include <Eigen/Dense>
#include <Eigen/CXX11/Tensor>
using Eigen::Tensor;
template <int DataLayout>
static void test_map_as_index()
{
#ifdef EIGEN_HAS_SFINAE
Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7);
tensor.setRandom();
using NormalIndex = DSizes<ptrdiff_t, 4>;
using CustomIndex = std::map<ptrdiff_t, ptrdiff_t>;
CustomIndex coeffC;
coeffC[0] = 1;
coeffC[1] = 2;
coeffC[2] = 4;
coeffC[3] = 1;
NormalIndex coeff(1,2,4,1);
VERIFY_IS_EQUAL(tensor.coeff(coeffC), tensor.coeff(coeff));
VERIFY_IS_EQUAL(tensor.coeffRef(coeffC), tensor.coeffRef(coeff));
#endif
}
template <int DataLayout>
static void test_matrix_as_index()
{
#ifdef EIGEN_HAS_SFINAE
Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7);
tensor.setRandom();
using NormalIndex = DSizes<ptrdiff_t, 4>;
using CustomIndex = Matrix<unsigned int, 4, 1>;
CustomIndex coeffC(1,2,4,1);
NormalIndex coeff(1,2,4,1);
VERIFY_IS_EQUAL(tensor.coeff(coeffC), tensor.coeff(coeff));
VERIFY_IS_EQUAL(tensor.coeffRef(coeffC), tensor.coeffRef(coeff));
#endif
}
template <int DataLayout>
static void test_varlist_as_index()
{
#ifdef EIGEN_HAS_SFINAE
Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7);
tensor.setRandom();
DSizes<ptrdiff_t, 4> coeff(1,2,4,1);
VERIFY_IS_EQUAL(tensor.coeff({1,2,4,1}), tensor.coeff(coeff));
VERIFY_IS_EQUAL(tensor.coeffRef({1,2,4,1}), tensor.coeffRef(coeff));
#endif
}
template <int DataLayout>
static void test_sizes_as_index()
{
#ifdef EIGEN_HAS_SFINAE
Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7);
tensor.setRandom();
DSizes<ptrdiff_t, 4> coeff(1,2,4,1);
Sizes<1,2,4,1> coeffC;
VERIFY_IS_EQUAL(tensor.coeff(coeffC), tensor.coeff(coeff));
VERIFY_IS_EQUAL(tensor.coeffRef(coeffC), tensor.coeffRef(coeff));
#endif
}
void test_cxx11_tensor_custom_index() {
test_map_as_index<ColMajor>();
test_map_as_index<RowMajor>();
test_matrix_as_index<ColMajor>();
test_matrix_as_index<RowMajor>();
test_varlist_as_index<ColMajor>();
test_varlist_as_index<RowMajor>();
test_sizes_as_index<ColMajor>();
test_sizes_as_index<RowMajor>();
}

View File

@@ -25,7 +25,9 @@ struct InsertZeros {
template <typename Output, typename Device>
void eval(const Tensor<float, 2>& input, Output& output, const Device& device) const
{
array<DenseIndex, 2> strides{{2, 2}};
array<DenseIndex, 2> strides;
strides[0] = 2;
strides[1] = 2;
output.stride(strides).device(device) = input;
Eigen::DSizes<DenseIndex, 2> offsets(1,1);
@@ -70,7 +72,8 @@ struct BatchMatMul {
Output& output, const Device& device) const
{
typedef Tensor<float, 3>::DimensionPair DimPair;
array<DimPair, 1> dims({{DimPair(1, 0)}});
array<DimPair, 1> dims;
dims[0] = DimPair(1, 0);
for (int i = 0; i < output.dimension(2); ++i) {
output.template chip<2>(i).device(device) = input1.chip<2>(i).contract(input2.chip<2>(i), dims);
}
@@ -88,9 +91,10 @@ static void test_custom_binary_op()
Tensor<float, 3> result = tensor1.customOp(tensor2, BatchMatMul());
for (int i = 0; i < 5; ++i) {
typedef Tensor<float, 3>::DimensionPair DimPair;
array<DimPair, 1> dims({{DimPair(1, 0)}});
array<DimPair, 1> dims;
dims[0] = DimPair(1, 0);
Tensor<float, 2> reference = tensor1.chip<2>(i).contract(tensor2.chip<2>(i), dims);
TensorRef<Tensor<float, 2>> val = result.chip<2>(i);
TensorRef<Tensor<float, 2> > val = result.chip<2>(i);
for (int j = 0; j < 2; ++j) {
for (int k = 0; k < 7; ++k) {
VERIFY_IS_APPROX(val(j, k), reference(j, k));

View File

@@ -0,0 +1,273 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Jianwei Cui <thucjw@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "main.h"
#include <Eigen/CXX11/Tensor>
using Eigen::Tensor;
template <int DataLayout>
static void test_fft_2D_golden() {
Tensor<float, 2, DataLayout, long> input(2, 3);
input(0, 0) = 1;
input(0, 1) = 2;
input(0, 2) = 3;
input(1, 0) = 4;
input(1, 1) = 5;
input(1, 2) = 6;
array<int, 2> fft;
fft[0] = 0;
fft[1] = 1;
Tensor<std::complex<float>, 2, DataLayout, long> output = input.template fft<Eigen::BothParts, Eigen::FFT_FORWARD>(fft);
std::complex<float> output_golden[6]; // in ColMajor order
output_golden[0] = std::complex<float>(21, 0);
output_golden[1] = std::complex<float>(-9, 0);
output_golden[2] = std::complex<float>(-3, 1.73205);
output_golden[3] = std::complex<float>( 0, 0);
output_golden[4] = std::complex<float>(-3, -1.73205);
output_golden[5] = std::complex<float>(0 ,0);
std::complex<float> c_offset = std::complex<float>(1.0, 1.0);
if (DataLayout == ColMajor) {
VERIFY_IS_APPROX(output(0) + c_offset, output_golden[0] + c_offset);
VERIFY_IS_APPROX(output(1) + c_offset, output_golden[1] + c_offset);
VERIFY_IS_APPROX(output(2) + c_offset, output_golden[2] + c_offset);
VERIFY_IS_APPROX(output(3) + c_offset, output_golden[3] + c_offset);
VERIFY_IS_APPROX(output(4) + c_offset, output_golden[4] + c_offset);
VERIFY_IS_APPROX(output(5) + c_offset, output_golden[5] + c_offset);
}
else {
VERIFY_IS_APPROX(output(0)+ c_offset, output_golden[0]+ c_offset);
VERIFY_IS_APPROX(output(1)+ c_offset, output_golden[2]+ c_offset);
VERIFY_IS_APPROX(output(2)+ c_offset, output_golden[4]+ c_offset);
VERIFY_IS_APPROX(output(3)+ c_offset, output_golden[1]+ c_offset);
VERIFY_IS_APPROX(output(4)+ c_offset, output_golden[3]+ c_offset);
VERIFY_IS_APPROX(output(5)+ c_offset, output_golden[5]+ c_offset);
}
}
static void test_fft_complex_input_golden() {
Tensor<std::complex<float>, 1, ColMajor, long> input(5);
input(0) = std::complex<float>(1, 1);
input(1) = std::complex<float>(2, 2);
input(2) = std::complex<float>(3, 3);
input(3) = std::complex<float>(4, 4);
input(4) = std::complex<float>(5, 5);
array<int, 1> fft;
fft[0] = 0;
Tensor<std::complex<float>, 1, ColMajor, long> forward_output_both_parts = input.fft<BothParts, FFT_FORWARD>(fft);
Tensor<std::complex<float>, 1, ColMajor, long> reverse_output_both_parts = input.fft<BothParts, FFT_REVERSE>(fft);
Tensor<float, 1, ColMajor, long> forward_output_real_part = input.fft<RealPart, FFT_FORWARD>(fft);
Tensor<float, 1, ColMajor, long> reverse_output_real_part = input.fft<RealPart, FFT_REVERSE>(fft);
Tensor<float, 1, ColMajor, long> forward_output_imag_part = input.fft<ImagPart, FFT_FORWARD>(fft);
Tensor<float, 1, ColMajor, long> reverse_output_imag_part = input.fft<ImagPart, FFT_REVERSE>(fft);
VERIFY_IS_EQUAL(forward_output_both_parts.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(reverse_output_both_parts.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(forward_output_real_part.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(reverse_output_real_part.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(forward_output_imag_part.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(reverse_output_imag_part.dimension(0), input.dimension(0));
std::complex<float> forward_golden_result[5];
std::complex<float> reverse_golden_result[5];
forward_golden_result[0] = std::complex<float>(15.000000000000000,+15.000000000000000);
forward_golden_result[1] = std::complex<float>(-5.940954801177935, +0.940954801177934);
forward_golden_result[2] = std::complex<float>(-3.312299240582266, -1.687700759417735);
forward_golden_result[3] = std::complex<float>(-1.687700759417735, -3.312299240582266);
forward_golden_result[4] = std::complex<float>( 0.940954801177934, -5.940954801177935);
reverse_golden_result[0] = std::complex<float>( 3.000000000000000, + 3.000000000000000);
reverse_golden_result[1] = std::complex<float>( 0.188190960235587, - 1.188190960235587);
reverse_golden_result[2] = std::complex<float>(-0.337540151883547, - 0.662459848116453);
reverse_golden_result[3] = std::complex<float>(-0.662459848116453, - 0.337540151883547);
reverse_golden_result[4] = std::complex<float>(-1.188190960235587, + 0.188190960235587);
for(int i = 0; i < 5; ++i) {
VERIFY_IS_APPROX(forward_output_both_parts(i), forward_golden_result[i]);
VERIFY_IS_APPROX(forward_output_real_part(i), forward_golden_result[i].real());
VERIFY_IS_APPROX(forward_output_imag_part(i), forward_golden_result[i].imag());
}
for(int i = 0; i < 5; ++i) {
VERIFY_IS_APPROX(reverse_output_both_parts(i), reverse_golden_result[i]);
VERIFY_IS_APPROX(reverse_output_real_part(i), reverse_golden_result[i].real());
VERIFY_IS_APPROX(reverse_output_imag_part(i), reverse_golden_result[i].imag());
}
}
static void test_fft_real_input_golden() {
Tensor<float, 1, ColMajor, long> input(5);
input(0) = 1.0;
input(1) = 2.0;
input(2) = 3.0;
input(3) = 4.0;
input(4) = 5.0;
array<int, 1> fft;
fft[0] = 0;
Tensor<std::complex<float>, 1, ColMajor, long> forward_output_both_parts = input.fft<BothParts, FFT_FORWARD>(fft);
Tensor<std::complex<float>, 1, ColMajor, long> reverse_output_both_parts = input.fft<BothParts, FFT_REVERSE>(fft);
Tensor<float, 1, ColMajor, long> forward_output_real_part = input.fft<RealPart, FFT_FORWARD>(fft);
Tensor<float, 1, ColMajor, long> reverse_output_real_part = input.fft<RealPart, FFT_REVERSE>(fft);
Tensor<float, 1, ColMajor, long> forward_output_imag_part = input.fft<ImagPart, FFT_FORWARD>(fft);
Tensor<float, 1, ColMajor, long> reverse_output_imag_part = input.fft<ImagPart, FFT_REVERSE>(fft);
VERIFY_IS_EQUAL(forward_output_both_parts.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(reverse_output_both_parts.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(forward_output_real_part.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(reverse_output_real_part.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(forward_output_imag_part.dimension(0), input.dimension(0));
VERIFY_IS_EQUAL(reverse_output_imag_part.dimension(0), input.dimension(0));
std::complex<float> forward_golden_result[5];
std::complex<float> reverse_golden_result[5];
forward_golden_result[0] = std::complex<float>( 15, 0);
forward_golden_result[1] = std::complex<float>(-2.5, +3.44095480117793);
forward_golden_result[2] = std::complex<float>(-2.5, +0.81229924058227);
forward_golden_result[3] = std::complex<float>(-2.5, -0.81229924058227);
forward_golden_result[4] = std::complex<float>(-2.5, -3.44095480117793);
reverse_golden_result[0] = std::complex<float>( 3.0, 0);
reverse_golden_result[1] = std::complex<float>(-0.5, -0.688190960235587);
reverse_golden_result[2] = std::complex<float>(-0.5, -0.162459848116453);
reverse_golden_result[3] = std::complex<float>(-0.5, +0.162459848116453);
reverse_golden_result[4] = std::complex<float>(-0.5, +0.688190960235587);
std::complex<float> c_offset(1.0, 1.0);
float r_offset = 1.0;
for(int i = 0; i < 5; ++i) {
VERIFY_IS_APPROX(forward_output_both_parts(i) + c_offset, forward_golden_result[i] + c_offset);
VERIFY_IS_APPROX(forward_output_real_part(i) + r_offset, forward_golden_result[i].real() + r_offset);
VERIFY_IS_APPROX(forward_output_imag_part(i) + r_offset, forward_golden_result[i].imag() + r_offset);
}
for(int i = 0; i < 5; ++i) {
VERIFY_IS_APPROX(reverse_output_both_parts(i) + c_offset, reverse_golden_result[i] + c_offset);
VERIFY_IS_APPROX(reverse_output_real_part(i) + r_offset, reverse_golden_result[i].real() + r_offset);
VERIFY_IS_APPROX(reverse_output_imag_part(i) + r_offset, reverse_golden_result[i].imag() + r_offset);
}
}
template <int DataLayout, typename RealScalar, bool isComplexInput, int FFTResultType, int FFTDirection, int TensorRank>
static void test_fft_real_input_energy() {
Eigen::DSizes<long, TensorRank> dimensions;
int total_size = 1;
for (int i = 0; i < TensorRank; ++i) {
dimensions[i] = rand() % 20 + 1;
total_size *= dimensions[i];
}
const DSizes<long, TensorRank> arr = dimensions;
typedef typename internal::conditional<isComplexInput == true, std::complex<RealScalar>, RealScalar>::type InputScalar;
Tensor<InputScalar, TensorRank, DataLayout, long> input;
input.resize(arr);
input.setRandom();
array<int, TensorRank> fft;
for (int i = 0; i < TensorRank; ++i) {
fft[i] = i;
}
typedef typename internal::conditional<FFTResultType == Eigen::BothParts, std::complex<RealScalar>, RealScalar>::type OutputScalar;
Tensor<OutputScalar, TensorRank, DataLayout> output;
output = input.template fft<FFTResultType, FFTDirection>(fft);
for (int i = 0; i < TensorRank; ++i) {
VERIFY_IS_EQUAL(output.dimension(i), input.dimension(i));
}
float energy_original = 0.0;
float energy_after_fft = 0.0;
for (int i = 0; i < total_size; ++i) {
energy_original += pow(std::abs(input(i)), 2);
}
for (int i = 0; i < total_size; ++i) {
energy_after_fft += pow(std::abs(output(i)), 2);
}
if(FFTDirection == FFT_FORWARD) {
VERIFY_IS_APPROX(energy_original, energy_after_fft / total_size);
}
else {
VERIFY_IS_APPROX(energy_original, energy_after_fft * total_size);
}
}
void test_cxx11_tensor_fft() {
test_fft_complex_input_golden();
test_fft_real_input_golden();
test_fft_2D_golden<ColMajor>();
test_fft_2D_golden<RowMajor>();
test_fft_real_input_energy<ColMajor, float, true, Eigen::BothParts, FFT_FORWARD, 1>();
test_fft_real_input_energy<ColMajor, double, true, Eigen::BothParts, FFT_FORWARD, 1>();
test_fft_real_input_energy<ColMajor, float, false, Eigen::BothParts, FFT_FORWARD, 1>();
test_fft_real_input_energy<ColMajor, double, false, Eigen::BothParts, FFT_FORWARD, 1>();
test_fft_real_input_energy<ColMajor, float, true, Eigen::BothParts, FFT_FORWARD, 2>();
test_fft_real_input_energy<ColMajor, double, true, Eigen::BothParts, FFT_FORWARD, 2>();
test_fft_real_input_energy<ColMajor, float, false, Eigen::BothParts, FFT_FORWARD, 2>();
test_fft_real_input_energy<ColMajor, double, false, Eigen::BothParts, FFT_FORWARD, 2>();
test_fft_real_input_energy<ColMajor, float, true, Eigen::BothParts, FFT_FORWARD, 3>();
test_fft_real_input_energy<ColMajor, double, true, Eigen::BothParts, FFT_FORWARD, 3>();
test_fft_real_input_energy<ColMajor, float, false, Eigen::BothParts, FFT_FORWARD, 3>();
test_fft_real_input_energy<ColMajor, double, false, Eigen::BothParts, FFT_FORWARD, 3>();
test_fft_real_input_energy<ColMajor, float, true, Eigen::BothParts, FFT_FORWARD, 4>();
test_fft_real_input_energy<ColMajor, double, true, Eigen::BothParts, FFT_FORWARD, 4>();
test_fft_real_input_energy<ColMajor, float, false, Eigen::BothParts, FFT_FORWARD, 4>();
test_fft_real_input_energy<ColMajor, double, false, Eigen::BothParts, FFT_FORWARD, 4>();
test_fft_real_input_energy<RowMajor, float, true, Eigen::BothParts, FFT_FORWARD, 1>();
test_fft_real_input_energy<RowMajor, double, true, Eigen::BothParts, FFT_FORWARD, 1>();
test_fft_real_input_energy<RowMajor, float, false, Eigen::BothParts, FFT_FORWARD, 1>();
test_fft_real_input_energy<RowMajor, double, false, Eigen::BothParts, FFT_FORWARD, 1>();
test_fft_real_input_energy<RowMajor, float, true, Eigen::BothParts, FFT_FORWARD, 2>();
test_fft_real_input_energy<RowMajor, double, true, Eigen::BothParts, FFT_FORWARD, 2>();
test_fft_real_input_energy<RowMajor, float, false, Eigen::BothParts, FFT_FORWARD, 2>();
test_fft_real_input_energy<RowMajor, double, false, Eigen::BothParts, FFT_FORWARD, 2>();
test_fft_real_input_energy<RowMajor, float, true, Eigen::BothParts, FFT_FORWARD, 3>();
test_fft_real_input_energy<RowMajor, double, true, Eigen::BothParts, FFT_FORWARD, 3>();
test_fft_real_input_energy<RowMajor, float, false, Eigen::BothParts, FFT_FORWARD, 3>();
test_fft_real_input_energy<RowMajor, double, false, Eigen::BothParts, FFT_FORWARD, 3>();
test_fft_real_input_energy<RowMajor, float, true, Eigen::BothParts, FFT_FORWARD, 4>();
test_fft_real_input_energy<RowMajor, double, true, Eigen::BothParts, FFT_FORWARD, 4>();
test_fft_real_input_energy<RowMajor, float, false, Eigen::BothParts, FFT_FORWARD, 4>();
test_fft_real_input_energy<RowMajor, double, false, Eigen::BothParts, FFT_FORWARD, 4>();
}

View File

@@ -15,6 +15,33 @@ using Eigen::Tensor;
using Eigen::RowMajor;
static void test_0d()
{
TensorFixedSize<float, Sizes<> > scalar1;
TensorFixedSize<float, Sizes<>, RowMajor> scalar2;
VERIFY_IS_EQUAL(scalar1.rank(), 0);
scalar1() = 7.0;
scalar2() = 13.0;
// Test against shallow copy.
TensorFixedSize<float, Sizes<> > copy = scalar1;
VERIFY_IS_NOT_EQUAL(scalar1.data(), copy.data());
VERIFY_IS_APPROX(scalar1(), copy());
copy = scalar1;
VERIFY_IS_NOT_EQUAL(scalar1.data(), copy.data());
VERIFY_IS_APPROX(scalar1(), copy());
TensorFixedSize<float, Sizes<> > scalar3 = scalar1.sqrt();
TensorFixedSize<float, Sizes<>, RowMajor> scalar4 = scalar2.sqrt();
VERIFY_IS_EQUAL(scalar3.rank(), 0);
VERIFY_IS_APPROX(scalar3(), sqrtf(7.0));
VERIFY_IS_APPROX(scalar4(), sqrtf(13.0));
scalar3 = scalar1 + scalar2;
VERIFY_IS_APPROX(scalar3(), 7.0f + 13.0f);
}
static void test_1d()
{
TensorFixedSize<float, Sizes<6> > vec1;
@@ -223,6 +250,7 @@ static void test_array()
void test_cxx11_tensor_fixed_size()
{
CALL_SUBTEST(test_0d());
CALL_SUBTEST(test_1d());
CALL_SUBTEST(test_tensor_map());
CALL_SUBTEST(test_2d());

View File

@@ -0,0 +1,154 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Jianwei Cui <thucjw@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "main.h"
#include <complex>
#include <cmath>
#include <Eigen/CXX11/Tensor>
using Eigen::Tensor;
template <int DataLayout>
static void test_1D_fft_ifft_invariant(int sequence_length) {
Tensor<double, 1, DataLayout> tensor(sequence_length);
tensor.setRandom();
array<int, 1> fft;
fft[0] = 0;
Tensor<std::complex<double>, 1, DataLayout> tensor_after_fft;
Tensor<std::complex<double>, 1, DataLayout> tensor_after_fft_ifft;
tensor_after_fft = tensor.template fft<Eigen::BothParts, Eigen::FFT_FORWARD>(fft);
tensor_after_fft_ifft = tensor_after_fft.template fft<Eigen::BothParts, Eigen::FFT_REVERSE>(fft);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(0), sequence_length);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(0), sequence_length);
for (int i = 0; i < sequence_length; ++i) {
VERIFY_IS_APPROX(static_cast<float>(tensor(i)), static_cast<float>(std::real(tensor_after_fft_ifft(i))));
}
}
template <int DataLayout>
static void test_2D_fft_ifft_invariant(int dim0, int dim1) {
Tensor<double, 2, DataLayout> tensor(dim0, dim1);
tensor.setRandom();
array<int, 2> fft;
fft[0] = 0;
fft[1] = 1;
Tensor<std::complex<double>, 2, DataLayout> tensor_after_fft;
Tensor<std::complex<double>, 2, DataLayout> tensor_after_fft_ifft;
tensor_after_fft = tensor.template fft<Eigen::BothParts, Eigen::FFT_FORWARD>(fft);
tensor_after_fft_ifft = tensor_after_fft.template fft<Eigen::BothParts, Eigen::FFT_REVERSE>(fft);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(0), dim0);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(1), dim1);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(0), dim0);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(1), dim1);
for (int i = 0; i < dim0; ++i) {
for (int j = 0; j < dim1; ++j) {
//std::cout << "[" << i << "][" << j << "]" << " Original data: " << tensor(i,j) << " Transformed data:" << tensor_after_fft_ifft(i,j) << std::endl;
VERIFY_IS_APPROX(static_cast<float>(tensor(i,j)), static_cast<float>(std::real(tensor_after_fft_ifft(i,j))));
}
}
}
template <int DataLayout>
static void test_3D_fft_ifft_invariant(int dim0, int dim1, int dim2) {
Tensor<double, 3, DataLayout> tensor(dim0, dim1, dim2);
tensor.setRandom();
array<int, 3> fft;
fft[0] = 0;
fft[1] = 1;
fft[2] = 2;
Tensor<std::complex<double>, 3, DataLayout> tensor_after_fft;
Tensor<std::complex<double>, 3, DataLayout> tensor_after_fft_ifft;
tensor_after_fft = tensor.template fft<Eigen::BothParts, Eigen::FFT_FORWARD>(fft);
tensor_after_fft_ifft = tensor_after_fft.template fft<Eigen::BothParts, Eigen::FFT_REVERSE>(fft);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(0), dim0);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(1), dim1);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(2), dim2);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(0), dim0);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(1), dim1);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(2), dim2);
for (int i = 0; i < dim0; ++i) {
for (int j = 0; j < dim1; ++j) {
for (int k = 0; k < dim2; ++k) {
VERIFY_IS_APPROX(static_cast<float>(tensor(i,j,k)), static_cast<float>(std::real(tensor_after_fft_ifft(i,j,k))));
}
}
}
}
template <int DataLayout>
static void test_sub_fft_ifft_invariant(int dim0, int dim1, int dim2, int dim3) {
Tensor<double, 4, DataLayout> tensor(dim0, dim1, dim2, dim3);
tensor.setRandom();
array<int, 2> fft;
fft[0] = 2;
fft[1] = 0;
Tensor<std::complex<double>, 4, DataLayout> tensor_after_fft;
Tensor<double, 4, DataLayout> tensor_after_fft_ifft;
tensor_after_fft = tensor.template fft<Eigen::BothParts, Eigen::FFT_FORWARD>(fft);
tensor_after_fft_ifft = tensor_after_fft.template fft<Eigen::RealPart, Eigen::FFT_REVERSE>(fft);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(0), dim0);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(1), dim1);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(2), dim2);
VERIFY_IS_EQUAL(tensor_after_fft.dimension(3), dim3);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(0), dim0);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(1), dim1);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(2), dim2);
VERIFY_IS_EQUAL(tensor_after_fft_ifft.dimension(3), dim3);
for (int i = 0; i < dim0; ++i) {
for (int j = 0; j < dim1; ++j) {
for (int k = 0; k < dim2; ++k) {
for (int l = 0; l < dim3; ++l) {
VERIFY_IS_APPROX(static_cast<float>(tensor(i,j,k,l)), static_cast<float>(tensor_after_fft_ifft(i,j,k,l)));
}
}
}
}
}
void test_cxx11_tensor_ifft() {
CALL_SUBTEST(test_1D_fft_ifft_invariant<ColMajor>(4));
CALL_SUBTEST(test_1D_fft_ifft_invariant<ColMajor>(16));
CALL_SUBTEST(test_1D_fft_ifft_invariant<ColMajor>(32));
CALL_SUBTEST(test_1D_fft_ifft_invariant<ColMajor>(1024*1024));
CALL_SUBTEST(test_2D_fft_ifft_invariant<ColMajor>(4,4));
CALL_SUBTEST(test_2D_fft_ifft_invariant<ColMajor>(8,16));
CALL_SUBTEST(test_2D_fft_ifft_invariant<ColMajor>(16,32));
CALL_SUBTEST(test_2D_fft_ifft_invariant<ColMajor>(1024,1024));
CALL_SUBTEST(test_3D_fft_ifft_invariant<ColMajor>(4,4,4));
CALL_SUBTEST(test_3D_fft_ifft_invariant<ColMajor>(8,16,32));
CALL_SUBTEST(test_3D_fft_ifft_invariant<ColMajor>(16,4,8));
CALL_SUBTEST(test_3D_fft_ifft_invariant<ColMajor>(256,256,256));
CALL_SUBTEST(test_sub_fft_ifft_invariant<ColMajor>(4,4,4,4));
CALL_SUBTEST(test_sub_fft_ifft_invariant<ColMajor>(8,16,32,64));
CALL_SUBTEST(test_sub_fft_ifft_invariant<ColMajor>(16,4,8,12));
CALL_SUBTEST(test_sub_fft_ifft_invariant<ColMajor>(64,64,64,64));
}

View File

@@ -58,11 +58,11 @@ static void test_type2index_list()
typedef Eigen::IndexList<Eigen::type2index<0>, Eigen::type2index<1>, Eigen::type2index<2>, Eigen::type2index<3>, Eigen::type2index<4>> Dims4;
#if 0
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims0>()() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims1>()() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims2>()() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims3>()() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims4>()() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims0>() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims1>() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims2>() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims3>() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<Dims4>() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
#endif
EIGEN_STATIC_ASSERT((internal::are_inner_most_dims<Dims0, 1, ColMajor>::value == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
@@ -142,7 +142,7 @@ static void test_type2index_list()
}
const Dims4 reduction_axis4;
Tensor<float, 1> result4 = tensor.sum(reduction_axis4);
Tensor<float, 0> result4 = tensor.sum(reduction_axis4);
float expected = 0.0f;
for (int m = 0; m < 11; ++m) {
for (int l = 0; l < 7; ++l) {
@@ -155,7 +155,7 @@ static void test_type2index_list()
}
}
}
VERIFY_IS_APPROX(result4(0), expected);
VERIFY_IS_APPROX(result4(), expected);
}
@@ -216,29 +216,29 @@ static void test_mixed_index_list()
reduction_indices.set(3, 3);
EIGEN_STATIC_ASSERT((internal::array_get<0>(reduction_indices) == 0), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::array_get<2>(reduction_indices) == 2), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_known_statically<ReductionIndices>()(0) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_known_statically<ReductionIndices>()(2) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionIndices>()(0, 0) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionIndices>()(2, 2) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_known_statically<ReductionIndices>(0) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_known_statically<ReductionIndices>(2) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionIndices>(0, 0) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionIndices>(2, 2) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
#if 0
EIGEN_STATIC_ASSERT((internal::all_indices_known_statically<ReductionIndices>()() == false), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<ReductionIndices>()() == false), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::all_indices_known_statically<ReductionIndices>() == false), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<ReductionIndices>() == false), YOU_MADE_A_PROGRAMMING_MISTAKE);
#endif
typedef IndexList<type2index<0>, type2index<1>, type2index<2>, type2index<3>> ReductionList;
ReductionList reduction_list;
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionList>()(0, 0) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionList>()(1, 1) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionList>()(2, 2) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionList>()(3, 3) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionList>(0, 0) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionList>(1, 1) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionList>(2, 2) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::index_statically_eq<ReductionList>(3, 3) == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
#if 0
EIGEN_STATIC_ASSERT((internal::all_indices_known_statically<ReductionList>()() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<ReductionList>()() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::all_indices_known_statically<ReductionList>() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::indices_statically_known_to_increase<ReductionList>() == true), YOU_MADE_A_PROGRAMMING_MISTAKE);
#endif
Tensor<float, 1> result1 = tensor.sum(reduction_axis);
Tensor<float, 1> result2 = tensor.sum(reduction_indices);
Tensor<float, 1> result3 = tensor.sum(reduction_list);
Tensor<float, 0> result1 = tensor.sum(reduction_axis);
Tensor<float, 0> result2 = tensor.sum(reduction_indices);
Tensor<float, 0> result3 = tensor.sum(reduction_list);
float expected = 0.0f;
for (int i = 0; i < 2; ++i) {
@@ -250,9 +250,9 @@ static void test_mixed_index_list()
}
}
}
VERIFY_IS_APPROX(result1(0), expected);
VERIFY_IS_APPROX(result2(0), expected);
VERIFY_IS_APPROX(result3(0), expected);
VERIFY_IS_APPROX(result1(), expected);
VERIFY_IS_APPROX(result2(), expected);
VERIFY_IS_APPROX(result3(), expected);
}

View File

@@ -14,8 +14,29 @@
void test_signed_32bit()
{
// Divide by one
const Eigen::internal::TensorIntDivisor<int32_t, false> div_by_one(1);
for (int32_t j = 0; j < 25000; ++j) {
const int32_t fast_div = j / div_by_one;
const int32_t slow_div = j / 1;
VERIFY_IS_EQUAL(fast_div, slow_div);
}
// Standard divide by 2 or more
for (int32_t i = 2; i < 25000; ++i) {
const Eigen::internal::TensorIntDivisor<int32_t> div(i);
const Eigen::internal::TensorIntDivisor<int32_t, false> div(i);
for (int32_t j = 0; j < 25000; ++j) {
const int32_t fast_div = j / div;
const int32_t slow_div = j / i;
VERIFY_IS_EQUAL(fast_div, slow_div);
}
}
// Optimized divide by 2 or more
for (int32_t i = 2; i < 25000; ++i) {
const Eigen::internal::TensorIntDivisor<int32_t, true> div(i);
for (int32_t j = 0; j < 25000; ++j) {
const int32_t fast_div = j / div;
@@ -42,7 +63,7 @@ void test_unsigned_32bit()
void test_signed_64bit()
{
for (int64_t i = 2; i < 25000; ++i) {
for (int64_t i = 1; i < 25000; ++i) {
const Eigen::internal::TensorIntDivisor<int64_t> div(i);
for (int64_t j = 0; j < 25000; ++j) {
@@ -56,7 +77,7 @@ void test_signed_64bit()
void test_unsigned_64bit()
{
for (uint64_t i = 2; i < 25000; ++i) {
for (uint64_t i = 1; i < 25000; ++i) {
const Eigen::internal::TensorIntDivisor<uint64_t> div(i);
for (uint64_t j = 0; j < 25000; ++j) {
@@ -95,8 +116,7 @@ void test_powers_64bit() {
if (start_num < 0)
start_num = 0;
for (int64_t num = start_num; num < end_num; num++) {
Eigen::internal::TensorIntDivisor<int64_t> divider =
Eigen::internal::TensorIntDivisor<int64_t>(div);
Eigen::internal::TensorIntDivisor<int64_t> divider(div);
int64_t result = num/div;
int64_t result_op = divider.divide(num);
VERIFY_IS_EQUAL(result_op, result);
@@ -109,8 +129,7 @@ void test_specific() {
// A particular combination that was previously failing
int64_t div = 209715200;
int64_t num = 3238002688;
Eigen::internal::TensorIntDivisor<int64_t> divider =
Eigen::internal::TensorIntDivisor<int64_t>(div);
Eigen::internal::TensorIntDivisor<int64_t> divider(div);
int64_t result = num/div;
int64_t result_op = divider.divide(num);
VERIFY_IS_EQUAL(result, result_op);

View File

@@ -14,6 +14,24 @@
using Eigen::Tensor;
using Eigen::RowMajor;
static void test_0d()
{
Tensor<int, 0> scalar1;
Tensor<int, 0, RowMajor> scalar2;
TensorMap<Tensor<const int, 0>> scalar3(scalar1.data());
TensorMap<Tensor<const int, 0, RowMajor>> scalar4(scalar2.data());
scalar1() = 7;
scalar2() = 13;
VERIFY_IS_EQUAL(scalar1.rank(), 0);
VERIFY_IS_EQUAL(scalar1.size(), 1);
VERIFY_IS_EQUAL(scalar3(), 7);
VERIFY_IS_EQUAL(scalar4(), 13);
}
static void test_1d()
{
Tensor<int, 1> vec1(6);
@@ -139,9 +157,117 @@ static void test_3d()
}
static void test_from_tensor()
{
Tensor<int, 3> mat1(2,3,7);
Tensor<int, 3, RowMajor> mat2(2,3,7);
int val = 0;
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 7; ++k) {
mat1(i,j,k) = val;
mat2(i,j,k) = val;
val++;
}
}
}
TensorMap<Tensor<int, 3>> mat3(mat1);
TensorMap<Tensor<int, 3, RowMajor>> mat4(mat2);
VERIFY_IS_EQUAL(mat3.rank(), 3);
VERIFY_IS_EQUAL(mat3.size(), 2*3*7);
VERIFY_IS_EQUAL(mat3.dimension(0), 2);
VERIFY_IS_EQUAL(mat3.dimension(1), 3);
VERIFY_IS_EQUAL(mat3.dimension(2), 7);
VERIFY_IS_EQUAL(mat4.rank(), 3);
VERIFY_IS_EQUAL(mat4.size(), 2*3*7);
VERIFY_IS_EQUAL(mat4.dimension(0), 2);
VERIFY_IS_EQUAL(mat4.dimension(1), 3);
VERIFY_IS_EQUAL(mat4.dimension(2), 7);
val = 0;
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 7; ++k) {
VERIFY_IS_EQUAL(mat3(i,j,k), val);
VERIFY_IS_EQUAL(mat4(i,j,k), val);
val++;
}
}
}
TensorFixedSize<int, Sizes<2,3,7>> mat5;
val = 0;
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 7; ++k) {
mat5(i,j,k) = val;
val++;
}
}
}
TensorMap<TensorFixedSize<int, Sizes<2,3,7>>> mat6(mat5);
VERIFY_IS_EQUAL(mat6.rank(), 3);
VERIFY_IS_EQUAL(mat6.size(), 2*3*7);
VERIFY_IS_EQUAL(mat6.dimension(0), 2);
VERIFY_IS_EQUAL(mat6.dimension(1), 3);
VERIFY_IS_EQUAL(mat6.dimension(2), 7);
val = 0;
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 7; ++k) {
VERIFY_IS_EQUAL(mat6(i,j,k), val);
val++;
}
}
}
}
static int f(const TensorMap<Tensor<int, 3> >& tensor) {
// Size<0> empty;
EIGEN_STATIC_ASSERT((internal::array_size<Sizes<>>::value == 0), YOU_MADE_A_PROGRAMMING_MISTAKE);
EIGEN_STATIC_ASSERT((internal::array_size<DSizes<int, 0>>::value == 0), YOU_MADE_A_PROGRAMMING_MISTAKE);
Tensor<int, 0> result = tensor.sum();
return result();
}
static void test_casting()
{
Tensor<int, 3> tensor(2,3,7);
int val = 0;
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 7; ++k) {
tensor(i,j,k) = val;
val++;
}
}
}
TensorMap<Tensor<int, 3>> map(tensor);
int sum1 = f(map);
int sum2 = f(tensor);
VERIFY_IS_EQUAL(sum1, sum2);
VERIFY_IS_EQUAL(sum1, 861);
}
void test_cxx11_tensor_map()
{
CALL_SUBTEST(test_0d());
CALL_SUBTEST(test_1d());
CALL_SUBTEST(test_2d());
CALL_SUBTEST(test_3d());
CALL_SUBTEST(test_from_tensor());
CALL_SUBTEST(test_casting());
}

View File

@@ -13,6 +13,45 @@
using Eigen::Tensor;
template <int DataLayout>
static void test_trivial_reductions() {
{
Tensor<float, 0, DataLayout> tensor;
tensor.setRandom();
array<ptrdiff_t, 0> reduction_axis;
Tensor<float, 0, DataLayout> result = tensor.sum(reduction_axis);
VERIFY_IS_EQUAL(result(), tensor());
}
{
Tensor<float, 1, DataLayout> tensor(7);
tensor.setRandom();
array<ptrdiff_t, 0> reduction_axis;
Tensor<float, 1, DataLayout> result = tensor.sum(reduction_axis);
VERIFY_IS_EQUAL(result.dimension(0), 7);
for (int i = 0; i < 7; ++i) {
VERIFY_IS_EQUAL(result(i), tensor(i));
}
}
{
Tensor<float, 2, DataLayout> tensor(2, 3);
tensor.setRandom();
array<ptrdiff_t, 0> reduction_axis;
Tensor<float, 2, DataLayout> result = tensor.sum(reduction_axis);
VERIFY_IS_EQUAL(result.dimension(0), 2);
VERIFY_IS_EQUAL(result.dimension(1), 3);
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
VERIFY_IS_EQUAL(result(i, j), tensor(i, j));
}
}
}
}
template <int DataLayout>
static void test_simple_reductions() {
Tensor<float, 4, DataLayout> tensor(2, 3, 5, 7);
@@ -37,18 +76,18 @@ static void test_simple_reductions() {
}
{
Tensor<float, 1, DataLayout> sum1 = tensor.sum();
VERIFY_IS_EQUAL(sum1.dimension(0), 1);
Tensor<float, 0, DataLayout> sum1 = tensor.sum();
VERIFY_IS_EQUAL(sum1.rank(), 0);
array<ptrdiff_t, 4> reduction_axis4;
reduction_axis4[0] = 0;
reduction_axis4[1] = 1;
reduction_axis4[2] = 2;
reduction_axis4[3] = 3;
Tensor<float, 1, DataLayout> sum2 = tensor.sum(reduction_axis4);
VERIFY_IS_EQUAL(sum2.dimension(0), 1);
Tensor<float, 0, DataLayout> sum2 = tensor.sum(reduction_axis4);
VERIFY_IS_EQUAL(sum2.rank(), 0);
VERIFY_IS_APPROX(sum1(0), sum2(0));
VERIFY_IS_APPROX(sum1(), sum2());
}
reduction_axis2[0] = 0;
@@ -69,18 +108,18 @@ static void test_simple_reductions() {
}
{
Tensor<float, 1, DataLayout> prod1 = tensor.prod();
VERIFY_IS_EQUAL(prod1.dimension(0), 1);
Tensor<float, 0, DataLayout> prod1 = tensor.prod();
VERIFY_IS_EQUAL(prod1.rank(), 0);
array<ptrdiff_t, 4> reduction_axis4;
reduction_axis4[0] = 0;
reduction_axis4[1] = 1;
reduction_axis4[2] = 2;
reduction_axis4[3] = 3;
Tensor<float, 1, DataLayout> prod2 = tensor.prod(reduction_axis4);
VERIFY_IS_EQUAL(prod2.dimension(0), 1);
Tensor<float, 0, DataLayout> prod2 = tensor.prod(reduction_axis4);
VERIFY_IS_EQUAL(prod2.rank(), 0);
VERIFY_IS_APPROX(prod1(0), prod2(0));
VERIFY_IS_APPROX(prod1(), prod2());
}
reduction_axis2[0] = 0;
@@ -101,18 +140,18 @@ static void test_simple_reductions() {
}
{
Tensor<float, 1, DataLayout> max1 = tensor.maximum();
VERIFY_IS_EQUAL(max1.dimension(0), 1);
Tensor<float, 0, DataLayout> max1 = tensor.maximum();
VERIFY_IS_EQUAL(max1.rank(), 0);
array<ptrdiff_t, 4> reduction_axis4;
reduction_axis4[0] = 0;
reduction_axis4[1] = 1;
reduction_axis4[2] = 2;
reduction_axis4[3] = 3;
Tensor<float, 1, DataLayout> max2 = tensor.maximum(reduction_axis4);
VERIFY_IS_EQUAL(max2.dimension(0), 1);
Tensor<float, 0, DataLayout> max2 = tensor.maximum(reduction_axis4);
VERIFY_IS_EQUAL(max2.rank(), 0);
VERIFY_IS_APPROX(max1(0), max2(0));
VERIFY_IS_APPROX(max1(), max2());
}
reduction_axis2[0] = 0;
@@ -133,18 +172,18 @@ static void test_simple_reductions() {
}
{
Tensor<float, 1, DataLayout> min1 = tensor.minimum();
VERIFY_IS_EQUAL(min1.dimension(0), 1);
Tensor<float, 0, DataLayout> min1 = tensor.minimum();
VERIFY_IS_EQUAL(min1.rank(), 0);
array<ptrdiff_t, 4> reduction_axis4;
reduction_axis4[0] = 0;
reduction_axis4[1] = 1;
reduction_axis4[2] = 2;
reduction_axis4[3] = 3;
Tensor<float, 1, DataLayout> min2 = tensor.minimum(reduction_axis4);
VERIFY_IS_EQUAL(min2.dimension(0), 1);
Tensor<float, 0, DataLayout> min2 = tensor.minimum(reduction_axis4);
VERIFY_IS_EQUAL(min2.rank(), 0);
VERIFY_IS_APPROX(min1(0), min2(0));
VERIFY_IS_APPROX(min1(), min2());
}
reduction_axis2[0] = 0;
@@ -167,18 +206,35 @@ static void test_simple_reductions() {
}
{
Tensor<float, 1, DataLayout> mean1 = tensor.mean();
VERIFY_IS_EQUAL(mean1.dimension(0), 1);
Tensor<float, 0, DataLayout> mean1 = tensor.mean();
VERIFY_IS_EQUAL(mean1.rank(), 0);
array<ptrdiff_t, 4> reduction_axis4;
reduction_axis4[0] = 0;
reduction_axis4[1] = 1;
reduction_axis4[2] = 2;
reduction_axis4[3] = 3;
Tensor<float, 1, DataLayout> mean2 = tensor.mean(reduction_axis4);
VERIFY_IS_EQUAL(mean2.dimension(0), 1);
Tensor<float, 0, DataLayout> mean2 = tensor.mean(reduction_axis4);
VERIFY_IS_EQUAL(mean2.rank(), 0);
VERIFY_IS_APPROX(mean1(0), mean2(0));
VERIFY_IS_APPROX(mean1(), mean2());
}
{
Tensor<int, 1> ints(10);
std::iota(ints.data(), ints.data() + ints.dimension(0), 0);
TensorFixedSize<bool, Sizes<> > all;
all = ints.all();
VERIFY(!all());
all = (ints >= ints.constant(0)).all();
VERIFY(all());
TensorFixedSize<bool, Sizes<> > any;
any = (ints > ints.constant(10)).any();
VERIFY(!any());
any = (ints < ints.constant(1)).any();
VERIFY(any());
}
}
@@ -190,8 +246,8 @@ static void test_full_reductions() {
reduction_axis[0] = 0;
reduction_axis[1] = 1;
Tensor<float, 1, DataLayout> result = tensor.sum(reduction_axis);
VERIFY_IS_EQUAL(result.dimension(0), 1);
Tensor<float, 0, DataLayout> result = tensor.sum(reduction_axis);
VERIFY_IS_EQUAL(result.rank(), 0);
float sum = 0.0f;
for (int i = 0; i < 2; ++i) {
@@ -202,7 +258,7 @@ static void test_full_reductions() {
VERIFY_IS_APPROX(result(0), sum);
result = tensor.square().sum(reduction_axis).sqrt();
VERIFY_IS_EQUAL(result.dimension(0), 1);
VERIFY_IS_EQUAL(result.rank(), 0);
sum = 0.0f;
for (int i = 0; i < 2; ++i) {
@@ -210,7 +266,7 @@ static void test_full_reductions() {
sum += tensor(i, j) * tensor(i, j);
}
}
VERIFY_IS_APPROX(result(0), sqrtf(sum));
VERIFY_IS_APPROX(result(), sqrtf(sum));
}
struct UserReducer {
@@ -401,6 +457,8 @@ static void test_reduce_middle_dims() {
}
void test_cxx11_tensor_reduction() {
CALL_SUBTEST(test_trivial_reductions<ColMajor>());
CALL_SUBTEST(test_trivial_reductions<RowMajor>());
CALL_SUBTEST(test_simple_reductions<ColMajor>());
CALL_SUBTEST(test_simple_reductions<RowMajor>());
CALL_SUBTEST(test_full_reductions<ColMajor>());

View File

@@ -28,7 +28,7 @@ static void test_full_reductions() {
Tensor<float, 2, DataLayout> in(num_rows, num_cols);
in.setRandom();
Tensor<float, 1, DataLayout> full_redux(1);
Tensor<float, 0, DataLayout> full_redux;
full_redux = in.sum();
std::size_t in_bytes = in.size() * sizeof(float);
@@ -38,16 +38,16 @@ static void test_full_reductions() {
gpu_device.memcpyHostToDevice(gpu_in_ptr, in.data(), in_bytes);
TensorMap<Tensor<float, 2, DataLayout> > in_gpu(gpu_in_ptr, num_rows, num_cols);
TensorMap<Tensor<float, 1, DataLayout> > out_gpu(gpu_out_ptr, 1);
TensorMap<Tensor<float, 0, DataLayout> > out_gpu(gpu_out_ptr);
out_gpu.device(gpu_device) = in_gpu.sum();
Tensor<float, 1, DataLayout> full_redux_gpu(1);
Tensor<float, 0, DataLayout> full_redux_gpu;
gpu_device.memcpyDeviceToHost(full_redux_gpu.data(), gpu_out_ptr, out_bytes);
gpu_device.synchronize();
// Check that the CPU and GPU reductions return the same result.
VERIFY_IS_APPROX(full_redux(0), full_redux_gpu(0));
VERIFY_IS_APPROX(full_redux(), full_redux_gpu());
}
void test_cxx11_tensor_reduction_cuda() {

View File

@@ -114,10 +114,18 @@ static void test_expr_reverse(bool LValue)
Tensor<float, 4, DataLayout> result(2,3,5,7);
array<ptrdiff_t, 4> src_slice_dim{{2,3,1,7}};
array<ptrdiff_t, 4> src_slice_start{{0,0,0,0}};
array<ptrdiff_t, 4> dst_slice_dim{{2,3,1,7}};
array<ptrdiff_t, 4> dst_slice_start{{0,0,0,0}};
array<ptrdiff_t, 4> src_slice_dim;
src_slice_dim[0] = 2;
src_slice_dim[1] = 3;
src_slice_dim[2] = 1;
src_slice_dim[3] = 7;
array<ptrdiff_t, 4> src_slice_start;
src_slice_start[0] = 0;
src_slice_start[1] = 0;
src_slice_start[2] = 0;
src_slice_start[3] = 0;
array<ptrdiff_t, 4> dst_slice_dim = src_slice_dim;
array<ptrdiff_t, 4> dst_slice_start = src_slice_start;
for (int i = 0; i < 5; ++i) {
if (LValue) {

View File

@@ -14,6 +14,35 @@
using Eigen::Tensor;
using Eigen::RowMajor;
static void test_0d()
{
Tensor<int, 0> scalar1;
Tensor<int, 0, RowMajor> scalar2;
Tensor<int, 0> scalar3;
Tensor<int, 0, RowMajor> scalar4;
scalar3.resize();
scalar4.resize();
scalar1() = 7;
scalar2() = 13;
scalar3.setValues(17);
scalar4.setZero();
VERIFY_IS_EQUAL(scalar1.rank(), 0);
VERIFY_IS_EQUAL(scalar1.size(), 1);
VERIFY_IS_EQUAL(scalar1(), 7);
VERIFY_IS_EQUAL(scalar2(), 13);
VERIFY_IS_EQUAL(scalar3(), 17);
VERIFY_IS_EQUAL(scalar4(), 0);
Tensor<int, 0> scalar5(scalar1);
VERIFY_IS_EQUAL(scalar5(), 7);
VERIFY_IS_EQUAL(scalar5.data()[0], 7);
}
static void test_1d()
{
Tensor<int, 1> vec1(6);
@@ -287,13 +316,10 @@ static void test_resize()
void test_cxx11_tensor_simple()
{
CALL_SUBTEST(test_0d());
CALL_SUBTEST(test_1d());
CALL_SUBTEST(test_2d());
CALL_SUBTEST(test_3d());
CALL_SUBTEST(test_simple_assign());
CALL_SUBTEST(test_resize());
}
/*
* kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
*/

View File

@@ -0,0 +1,38 @@
#include "main.h"
#include <Eigen/CXX11/Tensor>
using Eigen::Tensor;
using Eigen::RowMajor;
static void test_comparison_sugar() {
// we already trust comparisons between tensors, we're simply checking that
// the sugared versions are doing the same thing
Tensor<int, 3> t(6, 7, 5);
t.setRandom();
// make sure we have at least one value == 0
t(0,0,0) = 0;
Tensor<bool,0> b;
#define TEST_TENSOR_EQUAL(e1, e2) \
b = ((e1) == (e2)).all(); \
VERIFY(b())
#define TEST_OP(op) TEST_TENSOR_EQUAL(t op 0, t op t.constant(0))
TEST_OP(==);
TEST_OP(!=);
TEST_OP(<=);
TEST_OP(>=);
TEST_OP(<);
TEST_OP(>);
#undef TEST_OP
#undef TEST_TENSOR_EQUAL
}
void test_cxx11_tensor_sugar()
{
CALL_SUBTEST(test_comparison_sugar());
}

View File

@@ -0,0 +1,144 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2015 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "main.h"
#include <Eigen/CXX11/Tensor>
using Eigen::internal::TensorUInt128;
using Eigen::internal::static_val;
void VERIFY_EQUAL(TensorUInt128<uint64_t, uint64_t> actual, __uint128_t expected) {
bool matchl = actual.lower() == static_cast<uint64_t>(expected);
bool matchh = actual.upper() == static_cast<uint64_t>(expected >> 64);
if (!matchl || !matchh) {
const char* testname = g_test_stack.back().c_str();
std::cerr << "Test " << testname << " failed in " << __FILE__
<< " (" << __LINE__ << ")"
<< std::endl;
abort();
}
}
void test_add() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i1 = 0; i1 < 100; ++i1) {
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
TensorUInt128<uint64_t, uint64_t> i(i1, i2);
__uint128_t a = (static_cast<__uint128_t>(i1) << 64) + static_cast<__uint128_t>(i2);
for (uint64_t j1 = 0; j1 < 100; ++j1) {
for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
TensorUInt128<uint64_t, uint64_t> j(j1, j2);
__uint128_t b = (static_cast<__uint128_t>(j1) << 64) + static_cast<__uint128_t>(j2);
TensorUInt128<uint64_t, uint64_t> actual = i + j;
__uint128_t expected = a + b;
VERIFY_EQUAL(actual, expected);
}
}
}
}
}
void test_sub() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i1 = 0; i1 < 100; ++i1) {
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
TensorUInt128<uint64_t, uint64_t> i(i1, i2);
__uint128_t a = (static_cast<__uint128_t>(i1) << 64) + static_cast<__uint128_t>(i2);
for (uint64_t j1 = 0; j1 < 100; ++j1) {
for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
TensorUInt128<uint64_t, uint64_t> j(j1, j2);
__uint128_t b = (static_cast<__uint128_t>(j1) << 64) + static_cast<__uint128_t>(j2);
TensorUInt128<uint64_t, uint64_t> actual = i - j;
__uint128_t expected = a - b;
VERIFY_EQUAL(actual, expected);
}
}
}
}
}
void test_mul() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i1 = 0; i1 < 100; ++i1) {
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
TensorUInt128<uint64_t, uint64_t> i(i1, i2);
__uint128_t a = (static_cast<__uint128_t>(i1) << 64) + static_cast<__uint128_t>(i2);
for (uint64_t j1 = 0; j1 < 100; ++j1) {
for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
TensorUInt128<uint64_t, uint64_t> j(j1, j2);
__uint128_t b = (static_cast<__uint128_t>(j1) << 64) + static_cast<__uint128_t>(j2);
TensorUInt128<uint64_t, uint64_t> actual = i * j;
__uint128_t expected = a * b;
VERIFY_EQUAL(actual, expected);
}
}
}
}
}
void test_div() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i1 = 0; i1 < 100; ++i1) {
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
TensorUInt128<uint64_t, uint64_t> i(i1, i2);
__uint128_t a = (static_cast<__uint128_t>(i1) << 64) + static_cast<__uint128_t>(i2);
for (uint64_t j1 = 0; j1 < 100; ++j1) {
for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
TensorUInt128<uint64_t, uint64_t> j(j1, j2);
__uint128_t b = (static_cast<__uint128_t>(j1) << 64) + static_cast<__uint128_t>(j2);
TensorUInt128<uint64_t, uint64_t> actual = i / j;
__uint128_t expected = a / b;
VERIFY_EQUAL(actual, expected);
}
}
}
}
}
void test_misc1() {
uint64_t incr = internal::random<uint64_t>(1, 9999999999);
for (uint64_t i2 = 1; i2 < 100 * incr; i2 += incr) {
TensorUInt128<static_val<0>, uint64_t> i(0, i2);
__uint128_t a = static_cast<__uint128_t>(i2);
for (uint64_t j2 = 1; j2 < 100 * incr; j2 += incr) {
TensorUInt128<static_val<0>, uint64_t> j(0, j2);
__uint128_t b = static_cast<__uint128_t>(j2);
uint64_t actual = (i * j).upper();
uint64_t expected = (a * b) >> 64;
VERIFY_IS_EQUAL(actual, expected);
}
}
}
void test_misc2() {
int64_t incr = internal::random<int64_t>(1, 100);
for (int64_t log_div = 0; log_div < 63; ++log_div) {
for (int64_t divider = 1; divider <= 1000000 * incr; divider += incr) {
uint64_t expected = (static_cast<__uint128_t>(1) << (64+log_div)) / static_cast<__uint128_t>(divider) - (static_cast<__uint128_t>(1) << 64) + 1;
uint64_t shift = 1ULL << log_div;
TensorUInt128<uint64_t, uint64_t> result = (TensorUInt128<uint64_t, static_val<0> >(shift, 0) / TensorUInt128<static_val<0>, uint64_t>(divider) - TensorUInt128<static_val<1>, static_val<0> >(1, 0) + TensorUInt128<static_val<0>, static_val<1> >(1));
uint64_t actual = static_cast<uint64_t>(result);
VERIFY_EQUAL(actual, expected);
}
}
}
void test_cxx11_tensor_uint128()
{
CALL_SUBTEST_1(test_add());
CALL_SUBTEST_2(test_sub());
CALL_SUBTEST_3(test_mul());
CALL_SUBTEST_4(test_div());
CALL_SUBTEST_5(test_misc1());
CALL_SUBTEST_6(test_misc2());
}

View File

@@ -13,8 +13,6 @@
#define NUMBER_DIRECTIONS 16
#include <unsupported/Eigen/AdolcForward>
int adtl::ADOLC_numDir;
template<typename Vector>
EIGEN_DONT_INLINE typename Vector::Scalar foo(const Vector& p)
{
@@ -123,7 +121,7 @@ template<typename Func> void adolc_forward_jacobian(const Func& f)
void test_forward_adolc()
{
adtl::ADOLC_numDir = NUMBER_DIRECTIONS;
adtl::setNumDir(NUMBER_DIRECTIONS);
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST(( adolc_forward_jacobian(TestFunc1<double,2,2>()) ));

View File

@@ -1,35 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// #define EIGEN_DONT_VECTORIZE
// #define EIGEN_MAX_ALIGN_BYTES 0
#include "sparse_solver.h"
#include <Eigen/IterativeLinearSolvers>
#include <unsupported/Eigen/IterativeSolvers>
template<typename T, typename I> void test_incomplete_cholesky_T()
{
typedef SparseMatrix<T,0,I> SparseMatrixType;
ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, AMDOrdering<I> > > cg_illt_lower_amd;
ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, NaturalOrdering<I> > > cg_illt_lower_nat;
ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, AMDOrdering<I> > > cg_illt_upper_amd;
ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, AMDOrdering<I> > > cg_illt_upper_nat;
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_lower_amd) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_lower_nat) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_upper_amd) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_upper_nat) );
}
void test_incomplete_cholesky()
{
CALL_SUBTEST_1(( test_incomplete_cholesky_T<double,int>() ));
CALL_SUBTEST_2(( test_incomplete_cholesky_T<std::complex<double>, int>() ));
CALL_SUBTEST_3(( test_incomplete_cholesky_T<double,long int>() ));
}

File diff suppressed because it is too large Load Diff