mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Merged eigen/eigen into default
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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>() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
100
unsupported/test/cxx11_tensor_custom_index.cpp
Normal file
100
unsupported/test/cxx11_tensor_custom_index.cpp
Normal 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>();
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
273
unsupported/test/cxx11_tensor_fft.cpp
Normal file
273
unsupported/test/cxx11_tensor_fft.cpp
Normal 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>();
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
154
unsupported/test/cxx11_tensor_ifft.cpp
Normal file
154
unsupported/test/cxx11_tensor_ifft.cpp
Normal 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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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>());
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
*/
|
||||
|
||||
38
unsupported/test/cxx11_tensor_sugar.cpp
Normal file
38
unsupported/test/cxx11_tensor_sugar.cpp
Normal 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());
|
||||
}
|
||||
144
unsupported/test/cxx11_tensor_uint128.cpp
Normal file
144
unsupported/test/cxx11_tensor_uint128.cpp
Normal 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());
|
||||
}
|
||||
@@ -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>()) ));
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user