blob: 5854ab8b0e06d05ba1e86f8f1d49c2a854a30d36 [file] [edit]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#define EIGEN_USE_SYCL
#define EIGEN_TEST_NO_LONGDOUBLE
#include "main.h"
#include <Eigen/Geometry>
template <typename Scalar>
void sycl_scalar_math(sycl::queue& queue) {
constexpr int kOutputs = 38;
std::vector<Scalar> result(4 * kOutputs);
{
sycl::buffer<Scalar, 1> buffer(result.data(), sycl::range<1>(result.size()));
queue.submit([&](sycl::handler& handler) {
auto output = buffer.template get_access<sycl::access::mode::write>(handler);
handler.parallel_for(sycl::range<1>(4), [=](sycl::id<1> id) {
const Scalar x = Scalar(id[0] + 1) / Scalar(4);
const int offset = int(id[0]) * kOutputs;
output[offset + 0] = internal::psin(x);
output[offset + 1] = internal::pcos(x);
output[offset + 2] = internal::ptan(x);
output[offset + 3] = internal::pasin(x);
output[offset + 4] = internal::pacos(x);
output[offset + 5] = internal::patan(x);
output[offset + 6] = internal::psinh(x);
output[offset + 7] = internal::pcosh(x);
output[offset + 8] = internal::ptanh(x);
output[offset + 9] = internal::pasinh(x);
output[offset + 10] = internal::pacosh(x + Scalar(1));
output[offset + 11] = internal::patanh(x / Scalar(2));
output[offset + 12] = numext::log(x);
output[offset + 13] = numext::log2(x);
output[offset + 14] = numext::log10(x);
output[offset + 15] = numext::exp(x);
output[offset + 16] = Array<Scalar, 1, 1>::Constant(x).pow(Scalar(1.5))(0);
output[offset + 17] = numext::cbrt(x);
output[offset + 18] = numext::sqrt(x);
output[offset + 19] = numext::hypot(x, Scalar(2));
output[offset + 20] = numext::atan2(x, Scalar(2));
output[offset + 21] = numext::copysign(x, Scalar(-1));
output[offset + 22] = numext::rint(x + Scalar(0.25));
const Matrix<Scalar, 3, 1> vector(Scalar(1), x, x / Scalar(2));
output[offset + 23] = vector.template lpNorm<3>();
output[offset + 24] = vector.norm();
const Quaternion<Scalar> rotation(AngleAxis<Scalar>(x, Matrix<Scalar, 3, 1>::UnitZ()));
output[offset + 25] = rotation.angularDistance(Quaternion<Scalar>::Identity());
output[offset + 26] =
rotation.slerp(Scalar(0.5), Quaternion<Scalar>::Identity()).angularDistance(Quaternion<Scalar>::Identity());
output[offset + 27] = Rotation2D<Scalar>(x).toRotationMatrix()(0, 1);
JacobiRotation<Scalar> jacobi;
jacobi.makeJacobi(Scalar(2), x, Scalar(3));
output[offset + 28] = numext::abs2(jacobi.c()) + numext::abs2(jacobi.s());
output[offset + 29] = Rotation2D<Scalar>(Rotation2D<Scalar>(x).toRotationMatrix()).angle();
output[offset + 30] = numext::copysign(Scalar(0), Scalar(-1));
output[offset + 31] = numext::atan2(Scalar(-0.0), Scalar(-1));
output[offset + 32] = Scalar(float(numext::tanh(half(float(x)))));
output[offset + 33] = Scalar(float(numext::tanh(bfloat16(float(x)))));
output[offset + 34] = Scalar(float(numext::sqrt(half(float(x)))));
output[offset + 35] = Scalar(float(numext::sqrt(bfloat16(float(x)))));
output[offset + 36] = Scalar(float(numext::log2(half(float(x)))));
output[offset + 37] = Scalar(float(numext::log2(bfloat16(float(x)))));
});
});
queue.wait_and_throw();
}
for (int i = 0; i < 4; ++i) {
const Scalar x = Scalar(i + 1) / Scalar(4);
const Scalar expected[] = {std::sin(x),
std::cos(x),
std::tan(x),
std::asin(x),
std::acos(x),
std::atan(x),
std::sinh(x),
std::cosh(x),
std::tanh(x),
std::asinh(x),
std::acosh(x + Scalar(1)),
std::atanh(x / Scalar(2)),
std::log(x),
std::log2(x),
std::log10(x),
std::exp(x),
std::pow(x, Scalar(1.5)),
std::cbrt(x),
std::sqrt(x),
std::hypot(x, Scalar(2)),
std::atan2(x, Scalar(2)),
-x,
std::rint(x + Scalar(0.25)),
std::pow(Scalar(1) + x * x * x * Scalar(1.125), Scalar(1) / Scalar(3)),
std::sqrt(Scalar(1) + x * x * Scalar(1.25)),
x,
x / Scalar(2),
-std::sin(x),
Scalar(1),
x};
// Each composed rotation/norm uses O(10) operations and a few elementary functions.
for (int j = 0; j < 30; ++j) {
const Scalar tolerance =
Scalar(128) * NumTraits<Scalar>::epsilon() * (std::max)(Scalar(1), std::abs(expected[j]));
VERIFY(std::abs(result[i * kOutputs + j] - expected[j]) <= tolerance);
}
VERIFY_IS_EQUAL(result[i * kOutputs + 30], Scalar(0));
VERIFY((numext::signbit)(result[i * kOutputs + 30]));
VERIFY(result[i * kOutputs + 31] < Scalar(0));
VERIFY(std::abs(result[i * kOutputs + 31] + Scalar(EIGEN_PI)) <= Scalar(4) * NumTraits<Scalar>::epsilon());
VERIFY_IS_EQUAL(result[i * kOutputs + 32], Scalar(float(half(std::tanh(float(x))))));
VERIFY_IS_EQUAL(result[i * kOutputs + 33], Scalar(float(bfloat16(std::tanh(float(x))))));
VERIFY_IS_EQUAL(result[i * kOutputs + 34], Scalar(float(half(std::sqrt(float(x))))));
VERIFY_IS_EQUAL(result[i * kOutputs + 35], Scalar(float(bfloat16(std::sqrt(float(x))))));
VERIFY_IS_EQUAL(result[i * kOutputs + 36], Scalar(float(half(std::log2(float(x))))));
VERIFY_IS_EQUAL(result[i * kOutputs + 37], Scalar(float(bfloat16(std::log2(float(x))))));
}
}
EIGEN_DECLARE_TEST(sycl_math) {
sycl::queue queue;
CALL_SUBTEST(sycl_scalar_math<float>(queue));
if (queue.get_device().has(sycl::aspect::fp64)) CALL_SUBTEST(sycl_scalar_math<double>(queue));
}