blob: 593b41419626f7cf7a84c2c2276b699cf5d8877a [file] [log] [blame]
// Copyright Fraunhofer-Gesellschaft zur Förderung der angewandten
// Forschung e.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#include <tuple>
#include "gmock/gmock.h"
#include "emitc/mhlo.h"
#include "emitc/types.h"
namespace {
using namespace emitc;
using ::testing::DoubleEq;
using ::testing::DoubleNear;
using ::testing::Eq;
using ::testing::FloatEq;
using ::testing::FloatNear;
using ::testing::Pointwise;
const float EPSILON = 5e-4;
// Unary elementwise ops
TEST(mhlo, abs) {
EXPECT_EQ(1, mhlo::abs(-1));
{
Tensor0D<int> x{-1};
Tensor0D<int> expected_result{1};
Tensor0D<int> result = mhlo::abs(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor1D<float, 2> x{-1.0f, -2.0f};
Tensor1D<float, 2> expected_result{1.0f, 2.0f};
Tensor1D<float, 2> result = mhlo::abs(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor2D<long, 2, 2> x{-2, -1, 0, 2};
Tensor2D<long, 2, 2> expected_result{2, 1, 0, 2};
Tensor2D<long, 2, 2> result = mhlo::abs(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor3D<int32_t, 2, 1, 2> x{-2, -1, 0, 2};
Tensor3D<int32_t, 2, 1, 2> expected_result{2, 1, 0, 2};
Tensor3D<int32_t, 2, 1, 2> result = mhlo::abs(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor4D<int, 2, 2, 1, 2> x{-2, -1, 0, 0, 3, -3, -2, 1};
Tensor4D<int, 2, 2, 1, 2> expected_result{2, 1, 0, 0, 3, 3, 2, 1};
Tensor4D<int, 2, 2, 1, 2> result = mhlo::abs(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
// TODO:: Test complex to real.
}
TEST(mhlo, ceil) {
EXPECT_EQ(1.0, mhlo::ceil(0.7));
{
Tensor0D<float> x{0.7f};
Tensor0D<float> expected_result{1.0f};
Tensor0D<float> result = mhlo::ceil(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor1D<float, 2> x{1.6f, 2.0f};
Tensor1D<float, 2> expected_result{2.0f, 2.0f};
Tensor1D<float, 2> result = mhlo::ceil(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor2D<double, 2, 2> x{2.1, 1.6, 0.0, 2.0};
Tensor2D<double, 2, 2> expected_result{3.0, 2.0, 0.0, 2.0};
Tensor2D<double, 2, 2> result = mhlo::ceil(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor3D<double, 2, 1, 2> x{2.1, 1.6, 0.0, 2.0};
Tensor3D<double, 2, 1, 2> expected_result{3.0, 2.0, 0.0, 2.0};
Tensor3D<double, 2, 1, 2> result = mhlo::ceil(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor4D<double, 1, 2, 1, 2> x{2.1, 1.6, 0.0, 2.0};
Tensor4D<double, 1, 2, 1, 2> expected_result{3.0, 2.0, 0.0, 2.0};
Tensor4D<double, 1, 2, 1, 2> result = mhlo::ceil(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
}
TEST(mhlo, convert) {
{
uint32_t x = 1;
uint64_t expected_result = 1;
uint64_t result = mhlo::convert<uint64_t>(x);
EXPECT_EQ(result, expected_result);
}
{
Tensor0D<uint32_t> x{1};
Tensor0D<size_t> expected_result{1};
Tensor0D<size_t> result = mhlo::convert<Tensor0D<size_t>>(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor1D<uint16_t, 2> x{1, 3};
Tensor1D<size_t, 2> expected_result{1, 3};
Tensor1D<size_t, 2> result = mhlo::convert<Tensor1D<size_t, 2>>(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor2D<float, 2, 2> x{1.0f, 2.0f, 4.0f, 8.0f};
Tensor2D<double, 2, 2> expected_result{1.0, 2.0, 4.0, 8.0};
Tensor2D<double, 2, 2> result = mhlo::convert<Tensor2D<double, 2, 2>>(x);
EXPECT_THAT(result, Pointwise(DoubleEq(), expected_result));
}
{
Tensor3D<float, 2, 1, 2> x{1.0f, 2.0f, 4.0f, 8.0f};
Tensor3D<double, 2, 1, 2> expected_result{1.0, 2.0, 4.0, 8.0};
Tensor3D<double, 2, 1, 2> result =
mhlo::convert<Tensor3D<double, 2, 1, 2>>(x);
EXPECT_THAT(result, Pointwise(DoubleEq(), expected_result));
}
{
Tensor4D<double, 2, 1, 2, 2> x{1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0};
Tensor4D<float, 2, 1, 2, 2> expected_result{1.0f, 2.0f, 4.0f, 8.0f,
16.0f, 32.0f, 64.0f, 128.0f};
Tensor4D<float, 2, 1, 2, 2> result =
mhlo::convert<Tensor4D<float, 2, 1, 2, 2>>(x);
EXPECT_THAT(result, Pointwise(FloatEq(), expected_result));
}
}
TEST(mhlo, cos) {
EXPECT_NEAR(1.0f, mhlo::cos(0.0f), EPSILON);
{
Tensor0D<float> x{M_PIf32};
Tensor0D<float> expected_result{-1.0f};
Tensor0D<float> result = mhlo::cos(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor1D<float, 2> x{M_PI_2f32, -M_PI_2f32};
Tensor1D<float, 2> expected_result{0.0f, 0.0f};
Tensor1D<float, 2> result = mhlo::cos(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor2D<double, 2, 2> x{2 * M_PIf32, 0.0f, -0.5f, 0.5f};
Tensor2D<double, 2, 2> expected_result{1.0f, 1.0f, 0.8775826f, 0.8775826f};
Tensor2D<double, 2, 2> result = mhlo::cos(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor3D<double, 2, 2, 1> x{2 * M_PIf32, 0.0f, -0.5f, 0.5f};
Tensor3D<double, 2, 2, 1> expected_result{1.0f, 1.0f, 0.8775826f,
0.8775826f};
Tensor3D<double, 2, 2, 1> result = mhlo::cos(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor4D<double, 1, 2, 1, 2> x{0.5f, 0.0f, -0.5f, 2 * M_PIf32};
Tensor4D<double, 1, 2, 1, 2> expected_result{0.8775826f, 1.0f, 0.8775826f,
1.0f};
Tensor4D<double, 1, 2, 1, 2> result = mhlo::cos(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
}
TEST(mhlo, exponential) {
EXPECT_NEAR(M_Ef32, mhlo::exponential(1.0f), EPSILON);
{
Tensor0D<float> x{0.0f};
Tensor0D<float> expected_result{1.0f};
Tensor0D<float> result = mhlo::exponential(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor1D<float, 2> x{M_LN2f32, M_LN10f32};
Tensor1D<float, 2> expected_result{2.0f, 10.0f};
Tensor1D<float, 2> result = mhlo::exponential(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor2D<double, 2, 2> x{1.0f, 2.0f, 3.0f, -1.0f};
Tensor2D<double, 2, 2> expected_result{2.718281f, 7.389056f, 20.085536f,
0.367879f};
Tensor2D<double, 2, 2> result = mhlo::exponential(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor3D<double, 2, 2, 2> x{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
Tensor3D<double, 2, 2, 2> expected_result{
1.0f, 2.718281f, 7.389056f, 20.085536f,
54.598150f, 148.413159f, 403.428793f, 1096.633158f};
Tensor3D<double, 2, 2, 2> result = mhlo::exponential(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor4D<double, 1, 2, 1, 2> x{-1.0f, -2.0f, -3.0f, 4.0f};
Tensor4D<double, 1, 2, 1, 2> expected_result{0.367879f, 0.135335f,
0.049787f, 54.598150f};
Tensor4D<double, 1, 2, 1, 2> result = mhlo::exponential(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
}
TEST(mhlo, exponential_minus_one) {
EXPECT_NEAR(M_Ef32 - 1, mhlo::exponential_minus_one(1.0f), EPSILON);
{
Tensor0D<float> x{0.0f};
Tensor0D<float> expected_result{0.0f};
Tensor0D<float> result = mhlo::exponential_minus_one(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor1D<float, 2> x{M_LN2f32, M_LN10f32};
Tensor1D<float, 2> expected_result{1.0f, 9.0f};
Tensor1D<float, 2> result = mhlo::exponential_minus_one(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor2D<double, 2, 2> x{-1.0f, 2.0f, 3.0f, 4.0f};
Tensor2D<double, 2, 2> expected_result{-0.632120f, 6.389056f, 19.085536f,
53.598150f};
Tensor2D<double, 2, 2> result = mhlo::exponential_minus_one(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor3D<double, 2, 2, 2> x{0.0f, 1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f, -7.0f};
Tensor3D<double, 2, 2, 2> expected_result{
0.0f, 1.718281f, 6.389056f, 19.085536f,
53.598150f, 147.413159f, 402.428793f, -0.9990881f};
Tensor3D<double, 2, 2, 2> result = mhlo::exponential_minus_one(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor4D<double, 1, 2, 1, 2> x{1.0f, 2.0f, 3.0f, -4.0f};
Tensor4D<double, 1, 2, 1, 2> expected_result{1.718281f, 6.389056f,
19.085536f, -0.981684f};
Tensor4D<double, 1, 2, 1, 2> result = mhlo::exponential_minus_one(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
}
TEST(mhlo, floor) {
EXPECT_EQ(0.0, mhlo::floor(0.7));
{
Tensor0D<float> x{0.7f};
Tensor0D<float> expected_result{0.0f};
Tensor0D<float> result = mhlo::floor(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor1D<float, 2> x{1.6f, 2.0f};
Tensor1D<float, 2> expected_result{1.0f, 2.0f};
Tensor1D<float, 2> result = mhlo::floor(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor2D<double, 2, 2> x{2.1, 1.6, 0.0, 2.0};
Tensor2D<double, 2, 2> expected_result{2.0, 1.0, 0.0, 2.0};
Tensor2D<double, 2, 2> result = mhlo::floor(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor3D<double, 2, 2, 2> x{2.1, 1.6, 0.0, -2.0, 3.2, 5.1, 6.9, 3.14};
Tensor3D<double, 2, 2, 2> expected_result{2.0, 1.0, 0.0, -2.0,
3.0, 5.0, 6.0, 3.0};
Tensor3D<double, 2, 2, 2> result = mhlo::floor(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor4D<double, 1, 2, 2, 2> x{2.1, 1.6, 0.0, 2.0, -3.2, 5.1, -6.9, 3.14};
Tensor4D<double, 1, 2, 2, 2> expected_result{2.0, 1.0, 0.0, 2.0,
-4.0, 5.0, -7.0, 3.0};
Tensor4D<double, 1, 2, 2, 2> result = mhlo::floor(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
}
TEST(mhlo, is_finite) {
EXPECT_EQ(true, mhlo::is_finite(0.0f));
{
Tensor0D<float> x{M_PIf32};
Tensor0D<bool> expected_result{true};
Tensor0D<bool> result = mhlo::is_finite(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor1D<float, 2> x{M_PI_2f32, INFINITY};
Tensor1D<bool, 2> expected_result{true, false};
Tensor1D<bool, 2> result = mhlo::is_finite(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor2D<float, 2, 2> x{INFINITY, -INFINITY, NAN, -0.0f};
Tensor2D<bool, 2, 2> expected_result{false, false, false, true};
Tensor2D<bool, 2, 2> result = mhlo::is_finite(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor3D<float, 2, 2, 1> x{INFINITY, -INFINITY, NAN, -0.0f};
Tensor3D<bool, 2, 2, 1> expected_result{false, false, false, true};
Tensor3D<bool, 2, 2, 1> result = mhlo::is_finite(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor4D<float, 2, 2, 1, 1> x{INFINITY, -INFINITY, NAN, -0.0f};
Tensor4D<bool, 2, 2, 1, 1> expected_result{false, false, false, true};
Tensor4D<bool, 2, 2, 1, 1> result = mhlo::is_finite(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
}
TEST(mhlo, log) {
EXPECT_NEAR(0.0f, mhlo::log(1.0f), EPSILON);
{
Tensor0D<float> x{M_Ef32};
Tensor0D<float> expected_result{1.0f};
Tensor0D<float> result = mhlo::log(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor1D<float, 2> x{M_Ef32 * M_Ef32, M_Ef32 * M_Ef32 * M_Ef32};
Tensor1D<float, 2> expected_result{2.0f, 3.0f};
Tensor1D<float, 2> result = mhlo::log(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor2D<float, 2, 2> x{1.0f, 2.0f, 3.0f, 4.0f};
Tensor2D<float, 2, 2> expected_result{0.0f, 0.693147f, 1.098612f,
1.386294f};
Tensor2D<float, 2, 2> result = mhlo::log(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor3D<float, 2, 2, 2> x{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
Tensor3D<float, 2, 2, 2> expected_result{0.0f, 0.693147f, 1.098612f,
1.386294f, 1.609437f, 1.791759f,
1.945910f, 2.079441f};
Tensor3D<float, 2, 2, 2> result = mhlo::log(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor4D<float, 2, 2, 2, 1> x{1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f};
Tensor4D<float, 2, 2, 2, 1> expected_result{0.0f, 0.693147f, 1.098612f,
1.386294f, 1.609437f, 1.791759f,
1.945910f, 2.079441f};
Tensor4D<float, 2, 2, 2, 1> result = mhlo::log(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
}
TEST(mhlo, log_plus_one) {
EXPECT_NEAR(0.693147f, mhlo::log_plus_one(1.0f), EPSILON);
{
Tensor0D<float> x{M_Ef32 - 1};
Tensor0D<float> expected_result{1.0f};
Tensor0D<float> result = mhlo::log_plus_one(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor1D<float, 2> x{M_Ef32 * M_Ef32, M_Ef32 * M_Ef32 * M_Ef32};
Tensor1D<float, 2> expected_result{2.126928f, 3.048587f};
Tensor1D<float, 2> result = mhlo::log_plus_one(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor2D<double, 2, 2> x{0.0, 1.0, 2.0, 3.0};
Tensor2D<double, 2, 2> expected_result{0.0, 0.693147, 1.098612, 1.386294};
Tensor2D<double, 2, 2> result = mhlo::log_plus_one(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
{
Tensor3D<double, 2, 2, 1> x{0.0, 1.0, 2.0, 3.0};
Tensor3D<double, 2, 2, 1> expected_result{0.0, 0.693147, 1.098612,
1.386294};
Tensor3D<double, 2, 2, 1> result = mhlo::log_plus_one(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
{
Tensor4D<double, 2, 2, 1, 2> x{0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0};
Tensor4D<double, 2, 2, 1, 2> expected_result{0.0, 0.693147, 1.098612,
1.386294, 1.609437, 1.791759,
1.945910, 2.079441};
Tensor4D<double, 2, 2, 1, 2> result = mhlo::log_plus_one(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
}
TEST(mhlo, negate) {
{
int x = -1;
int expected_result = 1;
int result = mhlo::negate(x);
EXPECT_EQ(expected_result, result);
}
{
Tensor0D<int> x{3};
Tensor0D<int> expected_result{-3};
Tensor0D<int> result = mhlo::negate(x);
EXPECT_THAT(expected_result, Pointwise(Eq(), result));
}
{
Tensor1D<float, 2> x{-1.3f, 2.4f};
Tensor1D<float, 2> expected_result{1.3f, -2.4f};
Tensor1D<float, 2> result = mhlo::negate(x);
EXPECT_THAT(expected_result, Pointwise(FloatNear(EPSILON), result));
}
{
Tensor2D<long, 2, 2> x{3, 1, -4, 0};
Tensor2D<long, 2, 2> expected_result{-3, -1, 4, 0};
Tensor2D<long, 2, 2> result = mhlo::negate(x);
EXPECT_THAT(expected_result, Pointwise(Eq(), result));
}
{
Tensor3D<double, 2, 1, 1> x{3.1415, -2.7183};
Tensor3D<double, 2, 1, 1> expected_result{-3.1415, 2.7183};
Tensor3D<double, 2, 1, 1> result = mhlo::negate(x);
EXPECT_THAT(expected_result, Pointwise(FloatNear(EPSILON), result));
}
{
Tensor4D<int64_t, 1, 2, 1, 2> x{9223372036854775807, -4,
-9223372036854775807, 4};
Tensor4D<int64_t, 1, 2, 1, 2> expected_result{-9223372036854775807, 4,
9223372036854775807, -4};
Tensor4D<int64_t, 1, 2, 1, 2> result = mhlo::negate(x);
EXPECT_THAT(expected_result, Pointwise(Eq(), result));
}
}
TEST(mhlo, round) {
EXPECT_EQ(1.0, mhlo::round(0.7));
EXPECT_EQ(0.0, mhlo::round(0.4));
{
Tensor0D<float> x{0.7f};
Tensor0D<float> expected_result{1.0f};
Tensor0D<float> result = mhlo::round(x);
EXPECT_THAT(expected_result, Pointwise(Eq(), result));
}
{
Tensor1D<float, 3> x{1.4f, -1.6f, 2.0f};
Tensor1D<float, 3> expected_result{1.0f, -2.0f, 2.0f};
Tensor1D<float, 3> result = mhlo::round(x);
EXPECT_THAT(expected_result, Pointwise(Eq(), result));
}
{
Tensor2D<double, 2, 2> x{-2.1, 1.6, 0.0, 2.0};
Tensor2D<double, 2, 2> expected_result{-2.0, 2.0, 0.0, 2.0};
Tensor2D<double, 2, 2> result = mhlo::round(x);
EXPECT_THAT(expected_result, Pointwise(Eq(), result));
}
{
Tensor3D<float, 2, 1, 2> x{2.1f, 1.6f, 0.0f, 2.0f};
Tensor3D<float, 2, 1, 2> expected_result{2.0f, 2.0f, 0.0f, 2.0f};
Tensor3D<float, 2, 1, 2> result = mhlo::round(x);
EXPECT_THAT(expected_result, Pointwise(Eq(), result));
}
{
Tensor4D<double, 2, 2, 1, 1> x{2.1, -3.2, 0.0, 2.0};
Tensor4D<double, 2, 2, 1, 1> expected_result{2.0, -3.0, 0.0, 2.0};
Tensor4D<double, 2, 2, 1, 1> result = mhlo::round(x);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
}
TEST(mhlo, sin) {
EXPECT_NEAR(0.0f, mhlo::sin(0.0f), EPSILON);
{
Tensor0D<float> x{M_PIf32};
Tensor0D<float> expected_result{0.0f};
Tensor0D<float> result = mhlo::sin(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor1D<float, 2> x{M_PI_2f32, -M_PI_2f32};
Tensor1D<float, 2> expected_result{1.0f, -1.0f};
Tensor1D<float, 2> result = mhlo::sin(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor2D<double, 2, 2> x{2 * M_PIf32, 0.0, -0.5, 0.5};
Tensor2D<double, 2, 2> expected_result{0.0, 0.0, -0.479426, 0.479426};
Tensor2D<double, 2, 2> result = mhlo::sin(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
{
Tensor3D<double, 1, 2, 2> x{2 * M_PIf32, 0.0, -0.5, 0.5};
Tensor3D<double, 1, 2, 2> expected_result{0.0, 0.0, -0.479426, 0.479426};
Tensor3D<double, 1, 2, 2> result = mhlo::sin(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
{
Tensor4D<double, 2, 1, 2, 1> x{2 * M_PIf32, 0.0, -0.5, 0.5};
Tensor4D<double, 2, 1, 2, 1> expected_result{0.0, 0.0, -0.479426, 0.479426};
Tensor4D<double, 2, 1, 2, 1> result = mhlo::sin(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
}
TEST(mhlo, sqrt) {
EXPECT_NEAR(3.0f, mhlo::sqrt(9.0f), EPSILON);
{
Tensor0D<float> x{4.0f};
Tensor0D<float> expected_result{2.0f};
Tensor0D<float> result = mhlo::sqrt(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor1D<float, 2> x{0.0f, 81.0f};
Tensor1D<float, 2> expected_result{0.0f, 9.0f};
Tensor1D<float, 2> result = mhlo::sqrt(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor2D<double, 2, 2> x{2.0, 3.0, 10.0, 1.0};
Tensor2D<double, 2, 2> expected_result{1.414213, 1.732050, 3.162277, 1.0};
Tensor2D<double, 2, 2> result = mhlo::sqrt(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
{
Tensor3D<double, 2, 1, 2> x{2.0, 3.0, 10.0, 1.0};
Tensor3D<double, 2, 1, 2> expected_result{1.414213, 1.732050, 3.162277,
1.0};
Tensor3D<double, 2, 1, 2> result = mhlo::sqrt(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
{
Tensor4D<double, 2, 2, 1, 2> x{2.0, 3.0, 10.0, 1.0, 18.0, 9.0, 5.0, 25.0};
Tensor4D<double, 2, 2, 1, 2> expected_result{
1.414213, 1.732050, 3.162277, 1.0, 4.242640, 3.0, 2.236067, 5.0};
Tensor4D<double, 2, 2, 1, 2> result = mhlo::sqrt(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
}
TEST(mhlo, tanh) {
EXPECT_NEAR(0.0f, mhlo::tanh(0.0f), EPSILON);
{
Tensor0D<float> x{0.0f};
Tensor0D<float> expected_result{0.0f};
Tensor0D<float> result = mhlo::tanh(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor1D<float, 2> x{0.0f, 1.0f};
Tensor1D<float, 2> expected_result{0.0f, 0.761594f};
Tensor1D<float, 2> result = mhlo::tanh(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor2D<double, 2, 2> x{0.0, 1.0, -1.0, 0.0};
Tensor2D<double, 2, 2> expected_result{0.0, 0.761594, -0.761594, 0.0};
Tensor2D<double, 2, 2> result = mhlo::tanh(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
{
Tensor3D<float, 1, 2, 2> x{0.0f, 1.0f, -1.0f, 0.0f};
Tensor3D<float, 1, 2, 2> expected_result{0.0f, 0.761594f, -0.761594f, 0.0f};
Tensor3D<float, 1, 2, 2> result = mhlo::tanh(x);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
Tensor4D<double, 3, 1, 1, 2> x{0.0, 1.0, -1.0, 0.0, M_PIf64, -M_2_PIf64};
Tensor4D<double, 3, 1, 1, 2> expected_result{0.0, 0.761594, -0.761594,
0.0, 0.996272, -0.562593};
Tensor4D<double, 3, 1, 1, 2> result = mhlo::tanh(x);
EXPECT_THAT(result, Pointwise(DoubleNear(EPSILON), expected_result));
}
}
// Binary elementwise ops
TEST(mhlo, add) {
EXPECT_EQ(2, mhlo::add(-1, 3));
Tensor0D<int> s0{-3};
Tensor0D<int> t0{8};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::add<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {5}));
Tensor1D<float, 2> s1{-1.3f, 2.4f};
Tensor1D<float, 2> t1{0.2f, -3.7f};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<float, 2> {
return mhlo::add<Tensor1D<float, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(FloatEq(), {-1.1f, -1.3f}));
Tensor2D<long, 2, 2> s2{3, 1, 4, 9};
Tensor2D<long, 2, 2> t2{-2, 8, 6, -10};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::add<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {1, 9, 10, -1}));
Tensor3D<int16_t, 2, 1, 2> s3{3, 1, 4, 9};
Tensor3D<int16_t, 2, 1, 2> t3{-2, 8, 6, -10};
auto lambda_3d = [&s3, &t3]() -> Tensor3D<int16_t, 2, 1, 2> {
return mhlo::add<Tensor3D<int16_t, 2, 1, 2>>(s3, t3);
};
EXPECT_THAT(lambda_3d(), Pointwise(Eq(), {1, 9, 10, -1}));
Tensor4D<int8_t, 2, 1, 2, 2> s4{3, 1, 4, 9, 10, 11, 0, 1};
Tensor4D<int8_t, 2, 1, 2, 2> t4{-2, 8, 6, -10, -10, 11, 1, 1};
auto lambda_4d = [&s4, &t4]() -> Tensor4D<int8_t, 2, 1, 2, 2> {
return mhlo::add<Tensor4D<int8_t, 2, 1, 2, 2>>(s4, t4);
};
EXPECT_THAT(lambda_4d(), Pointwise(Eq(), {1, 9, 10, -1, 0, 22, 1, 2}));
}
TEST(mhlo, atan2) {
EXPECT_NEAR(0.321751f, mhlo::atan2(1.0f, 3.0f), EPSILON);
Tensor0D<float> s0{1.0f};
Tensor0D<float> t0{3.0f};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<float> {
return mhlo::atan2<Tensor0D<float>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(FloatNear(EPSILON), {0.321751f}));
Tensor1D<float, 2> s1{1.0f, 0.5f};
Tensor1D<float, 2> t1{3.0f, -0.5f};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<float, 2> {
return mhlo::atan2<Tensor1D<float, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(),
Pointwise(FloatNear(EPSILON), {0.321751f, 2.35619f}));
Tensor2D<double, 2, 2> s2{1.0, 0.5, -0.5, 0.5};
Tensor2D<double, 2, 2> t2{3.0, -0.5, 0.5, 0.5};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<double, 2, 2> {
return mhlo::atan2<Tensor2D<double, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(FloatNear(EPSILON),
{0.321751, 2.35619, -0.785398, 0.785398}));
Tensor3D<double, 1, 2, 2> s3{1.0, 0.5, -0.5, 0.5};
Tensor3D<double, 1, 2, 2> t3{3.0, -0.5, 0.5, 0.5};
auto lambda_3d = [&s3, &t3]() -> Tensor3D<double, 1, 2, 2> {
return mhlo::atan2<Tensor3D<double, 1, 2, 2>>(s3, t3);
};
EXPECT_THAT(lambda_3d(), Pointwise(FloatNear(EPSILON),
{0.321751, 2.35619, -0.785398, 0.785398}));
Tensor4D<float, 1, 3, 1, 2> s4{1.0f, 0.5f, -0.5f, 0.5f, M_PIf32, 0.0f};
Tensor4D<float, 1, 3, 1, 2> t4{3.0f, -0.5f, 0.5f, 0.5f, 0.0f, -M_PIf32};
auto lambda_4d = [&s4, &t4]() -> Tensor4D<float, 1, 3, 1, 2> {
return mhlo::atan2<Tensor4D<float, 1, 3, 1, 2>>(s4, t4);
};
EXPECT_THAT(lambda_4d(),
Pointwise(FloatNear(EPSILON), {0.321751f, 2.35619f, -0.785398f,
0.785398f, 1.570796f, M_PIf32}));
}
TEST(mhlo, div) {
EXPECT_EQ(-3, mhlo::div(-3, 1));
EXPECT_EQ(-6.75, mhlo::div(27.0, -4.0));
EXPECT_EQ(-6, mhlo::div<int>(27.0, -4.0));
Tensor0D<int> s0{27};
Tensor0D<int> t0{-4};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::div<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {-6}));
Tensor1D<float, 2> s1{-1.3f, 2.4f};
Tensor1D<float, 2> t1{0.2f, -3.7f};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<float, 2> {
return mhlo::div<Tensor1D<float, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(FloatNear(EPSILON), {-6.5f, -0.6486f}));
Tensor2D<long, 2, 2> s2{3, 14, -31, -51};
Tensor2D<long, 2, 2> t2{-2, 2, 6, 7};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::div<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {-1, 7, -5, -7}));
Tensor3D<int8_t, 2, 2, 1> s3{3, 14, -31, -51};
Tensor3D<int8_t, 2, 2, 1> t3{-2, 2, 6, 7};
auto lambda_3d = [&s3, &t3]() -> Tensor3D<int8_t, 2, 2, 1> {
return mhlo::div<Tensor3D<int8_t, 2, 2, 1>>(s3, t3);
};
EXPECT_THAT(lambda_3d(), Pointwise(Eq(), {-1, 7, -5, -7}));
Tensor4D<int16_t, 2, 1, 3, 1> s4{3, 14, -31, -51, 16, -2};
Tensor4D<int16_t, 2, 1, 3, 1> t4{-2, 2, 6, 7, 8, -2};
auto lambda_4d = [&s4, &t4]() -> Tensor4D<int16_t, 2, 1, 3, 1> {
return mhlo::div<Tensor4D<int16_t, 2, 1, 3, 1>>(s4, t4);
};
EXPECT_THAT(lambda_4d(), Pointwise(Eq(), {-1, 7, -5, -7, 2, 1}));
}
TEST(mhlo, max) {
EXPECT_EQ(3, mhlo::max(-1, 3));
Tensor0D<int> s0{-3};
Tensor0D<int> t0{8};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::max<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {8}));
Tensor1D<float, 2> s1{-1.3f, 2.4f};
Tensor1D<float, 2> t1{0.2f, -3.7f};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<float, 2> {
return mhlo::max<Tensor1D<float, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(FloatEq(), {0.2f, 2.4f}));
Tensor2D<long, 2, 2> s2{3, 1, 4, 9};
Tensor2D<long, 2, 2> t2{-2, 8, 6, -10};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::max<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {3, 8, 6, 9}));
}
TEST(mhlo, min) {
EXPECT_EQ(-1, mhlo::min(-1, 3));
Tensor0D<int> s0{-3};
Tensor0D<int> t0{8};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::min<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {-3}));
Tensor1D<float, 2> s1{-1.3f, 2.4f};
Tensor1D<float, 2> t1{0.2f, -3.7f};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<float, 2> {
return mhlo::min<Tensor1D<float, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(FloatEq(), {-1.3f, -3.7f}));
Tensor2D<long, 2, 2> s2{3, 1, 4, 9};
Tensor2D<long, 2, 2> t2{-2, 8, 6, -10};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::min<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {-2, 1, 4, -10}));
}
TEST(mhlo, mul) {
EXPECT_EQ(-3, mhlo::mul(-1, 3));
Tensor0D<int> s0{-3};
Tensor0D<int> t0{8};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::mul<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {-24}));
Tensor1D<float, 2> s1{-1.3f, 2.4f};
Tensor1D<float, 2> t1{0.2f, -3.7f};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<float, 2> {
return mhlo::mul<Tensor1D<float, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(FloatEq(), {-0.26f, -8.88f}));
Tensor2D<long, 2, 2> s2{3, 1, 4, 9};
Tensor2D<long, 2, 2> t2{-2, 8, 6, -10};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::mul<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {-6, 8, 24, -90}));
}
TEST(mhlo, pow) {
EXPECT_EQ(9, mhlo::pow(3, 2));
Tensor0D<int> s0{2};
Tensor0D<int> t0{4};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::pow<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {16}));
Tensor1D<float, 2> s1{4.0f, 2.0f};
Tensor1D<float, 2> t1{0.5f, -2.0f};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<float, 2> {
return mhlo::pow<Tensor1D<float, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(FloatNear(EPSILON), {2.0f, 0.25f}));
Tensor2D<long, 2, 2> s2{3, 1, 4, 2};
Tensor2D<long, 2, 2> t2{0, -1, 3, -2};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::pow<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {1, 1, 64, 0}));
}
TEST(mhlo, shift_left) {
EXPECT_EQ(16u, mhlo::shift_left(2u, 3u));
Tensor0D<uint> s0{2};
Tensor0D<uint> t0{8};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<uint> {
return mhlo::shift_left<Tensor0D<uint>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {512}));
Tensor1D<uint8_t, 2> s1{3, 0};
Tensor1D<uint8_t, 2> t1{2, 3};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<uint8_t, 2> {
return mhlo::shift_left<Tensor1D<uint8_t, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(Eq(), {12, 0}));
Tensor2D<uint64_t, 2, 2> s2{0, 2, 5, 10};
Tensor2D<uint64_t, 2, 2> t2{0, 1, 3, 4};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<uint64_t, 2, 2> {
return mhlo::shift_left<Tensor2D<uint64_t, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {0, 4, 40, 160}));
}
TEST(mhlo, shift_right_logical) {
EXPECT_EQ(2u, mhlo::shift_right_logical(4u, 1u));
Tensor0D<uint> s0{6};
Tensor0D<uint> t0{2};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<uint> {
return mhlo::shift_right_logical<Tensor0D<uint>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {1}));
Tensor1D<uint8_t, 2> s1{17, 32};
Tensor1D<uint8_t, 2> t1{1, 3};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<uint8_t, 2> {
return mhlo::shift_right_logical<Tensor1D<uint8_t, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(Eq(), {8, 4}));
Tensor2D<uint64_t, 2, 2> s2{0, 2, 25, 10};
Tensor2D<uint64_t, 2, 2> t2{0, 1, 3, 2};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<uint64_t, 2, 2> {
return mhlo::shift_right_logical<Tensor2D<uint64_t, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {0, 1, 3, 2}));
}
TEST(mhlo, sub) {
EXPECT_EQ(-4, mhlo::sub(-1, 3));
Tensor0D<int> s0{-3};
Tensor0D<int> t0{8};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::sub<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {-11}));
Tensor1D<float, 2> s1{-1.3f, 2.4f};
Tensor1D<float, 2> t1{0.2f, -3.7f};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<float, 2> {
return mhlo::sub<Tensor1D<float, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(FloatEq(), {-1.5f, 6.1f}));
Tensor2D<long, 2, 2> s2{3, 1, 4, 9};
Tensor2D<long, 2, 2> t2{-2, 8, 6, -10};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::sub<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {5, -7, -2, 19}));
}
// Binary logical elementwise ops
TEST(mhlo, or) {
EXPECT_EQ(1, mhlo::logical_or(2, 3));
Tensor0D<int> s0{2};
Tensor0D<int> t0{8};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::logical_or<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {1}));
Tensor1D<int8_t, 2> s1{-1, 0};
Tensor1D<int8_t, 2> t1{0, 0};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<int8_t, 2> {
return mhlo::logical_or<Tensor1D<int8_t, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(Eq(), {1, 0}));
Tensor2D<long, 2, 2> s2{0, 2, 0, -1};
Tensor2D<long, 2, 2> t2{0, 0, -2, -2};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::logical_or<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {0, 1, 1, 1}));
}
TEST(mhlo, xor) {
EXPECT_EQ(1, mhlo::logical_xor(2, 3));
Tensor0D<int> s0{2};
Tensor0D<int> t0{8};
auto lambda_0d = [&s0, &t0]() -> Tensor0D<int> {
return mhlo::logical_xor<Tensor0D<int>>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {1}));
Tensor1D<int8_t, 2> s1{-1, 0};
Tensor1D<int8_t, 2> t1{0, 0};
auto lambda_1d = [&s1, &t1]() -> Tensor1D<int8_t, 2> {
return mhlo::logical_xor<Tensor1D<int8_t, 2>>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(Eq(), {1, 0}));
Tensor2D<long, 2, 2> s2{0, 2, 0, -1};
Tensor2D<long, 2, 2> t2{0, 0, -2, -2};
auto lambda_2d = [&s2, &t2]() -> Tensor2D<long, 2, 2> {
return mhlo::logical_xor<Tensor2D<long, 2, 2>>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {0, 1, 1, 1}));
}
// Tuple ops
TEST(mhlo, compare) {
auto lambda = []() { return mhlo::compare<int, std::less>(-1, 3); };
EXPECT_EQ(true, lambda());
Tensor0D<int> s0{-3};
Tensor0D<int> t0{-8};
auto lambda_0d = [&s0, &t0]() {
return mhlo::compare<Tensor0D<int>, std::less_equal>(s0, t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {false}));
Tensor1D<float, 2> s1{-1.3f, 2.4f};
Tensor1D<float, 2> t1{0.2f, 2.4f};
auto lambda_1d = [&s1, &t1]() {
return mhlo::compare<Tensor1D<float, 2>, std::equal_to>(s1, t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(Eq(), {false, true}));
Tensor2D<long, 2, 2> s2{3, 1, 4, 9};
Tensor2D<long, 2, 2> t2{-2, 1, 6, -10};
auto lambda_2d = [&s2, &t2]() {
return mhlo::compare<Tensor2D<long, 2, 2>, std::greater_equal>(s2, t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {true, true, false, true}));
Tensor3D<long, 2, 1, 2> s3{3, 1, 4, 9};
Tensor3D<long, 2, 1, 2> t3{-2, 1, 6, -10};
auto lambda_3d = [&s3, &t3]() {
return mhlo::compare<Tensor3D<long, 2, 1, 2>, std::greater_equal>(s3, t3);
};
EXPECT_THAT(lambda_3d(), Pointwise(Eq(), {true, true, false, true}));
Tensor4D<int, 2, 1, 2, 2> s4{3, 1, 4, 9, 10, 12, -4, 8};
Tensor4D<int, 2, 1, 2, 2> t4{-2, 1, 6, -10, 9, 13, 4, 10};
auto lambda_4d = [&s4, &t4]() {
return mhlo::compare<Tensor4D<int, 2, 1, 2, 2>, std::greater_equal>(s4, t4);
};
EXPECT_THAT(lambda_4d(), Pointwise(Eq(), {true, true, false, true, true,
false, false, false}));
}
// Slice ops
TEST(mhlo, slice) {
// Slice Tensor1D
Tensor1D<float, 5> s1{0.0f, 1.0f, 2.0f, 3.0f, 4.0f};
auto t1 =
mhlo::slice<Tensor1D<float, 2>, Tensor1D<float, 5>>(s1, {2}, {4}, {1});
EXPECT_THAT(t1, Pointwise(FloatEq(), {2.0f, 3.0f}));
auto t1_strided =
mhlo::slice<Tensor1D<float, 2>, Tensor1D<float, 5>>(s1, {1}, {4}, {2});
EXPECT_THAT(t1_strided, Pointwise(FloatEq(), {1.0f, 3.0f}));
// Slice Tensor2D
Tensor2D<float, 4, 3> s2{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f,
6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f};
auto t2 = mhlo::slice<Tensor2D<float, 2, 2>, Tensor2D<float, 4, 3>>(
s2, {2, 1}, {4, 3}, {1, 1});
EXPECT_THAT(t2, Pointwise(FloatEq(), {7.0f, 8.0f, 10.0f, 11.0f}));
auto t2_strided = mhlo::slice<Tensor2D<float, 2, 2>, Tensor2D<float, 4, 3>>(
s2, {1, 0}, {4, 3}, {2, 2});
EXPECT_THAT(t2_strided, Pointwise(FloatEq(), {3.0f, 5.0f, 9.0f, 11.0f}));
// Slice Tensor3D
Tensor3D<float, 4, 3, 2> s3{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f,
6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f,
12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f,
18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f};
auto t3 = mhlo::slice<Tensor3D<float, 2, 2, 2>, Tensor3D<float, 4, 3, 2>>(
s3, {2, 1, 0}, {4, 3, 2}, {1, 1, 1});
EXPECT_THAT(t3, Pointwise(FloatEq(), {14.0f, 15.0f, 16.0f, 17.0f, 20.0f,
21.0f, 22.0f, 23.0f}));
auto t3_strided =
mhlo::slice<Tensor3D<float, 2, 2, 1>, Tensor3D<float, 4, 3, 2>>(
s3, {0, 1, 0}, {4, 3, 2}, {2, 1, 2});
EXPECT_THAT(t3_strided, Pointwise(FloatEq(), {2.0f, 4.0f, 14.0f, 16.0f}));
auto t3_strided2 =
mhlo::slice<Tensor3D<float, 1, 2, 1>, Tensor3D<float, 4, 3, 2>>(
s3, {0, 1, 0}, {2, 3, 2}, {2, 1, 2});
EXPECT_THAT(t3_strided2, Pointwise(FloatEq(), {2.0f, 4.0f}));
// Slice Tensor4D
Tensor4D<float, 4, 3, 1, 2> s4{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f,
6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f,
12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f,
18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f};
auto t4 =
mhlo::slice<Tensor4D<float, 2, 2, 1, 2>, Tensor4D<float, 4, 3, 1, 2>>(
s4, {2, 1, 0, 0}, {4, 3, 1, 2}, {1, 1, 1, 1});
EXPECT_THAT(t4, Pointwise(FloatEq(), {14.0f, 15.0f, 16.0f, 17.0f, 20.0f,
21.0f, 22.0f, 23.0f}));
auto t4_2 =
mhlo::slice<Tensor4D<float, 4, 3, 1, 2>, Tensor4D<float, 4, 3, 1, 2>>(
s4, {0, 0, 0, 0}, {4, 3, 1, 2}, {1, 1, 1, 1});
EXPECT_THAT(t4_2, Pointwise(FloatEq(), s4));
auto t4_strided =
mhlo::slice<Tensor4D<float, 3, 2, 1, 1>, Tensor4D<float, 4, 3, 1, 2>>(
s4, {1, 0, 0, 0}, {4, 3, 1, 2}, {1, 2, 1, 2});
EXPECT_THAT(t4_strided,
Pointwise(FloatEq(), {6.0f, 10.0f, 12.0f, 16.0f, 18.0f, 22.0f}));
auto t4_strided_2 =
mhlo::slice<Tensor4D<float, 2, 1, 1, 1>, Tensor4D<float, 4, 3, 1, 2>>(
s4, {0, 2, 0, 0}, {4, 3, 1, 1}, {2, 1, 1, 1});
EXPECT_THAT(t4_strided_2, Pointwise(FloatEq(), {4.0f, 16.0f}));
}
TEST(mhlo, dynamic_slice) {
Tensor1D<float, 5> s1{0.0f, 1.0f, 2.0f, 3.0f, 4.0f};
auto t1 =
mhlo::dynamic_slice<Tensor1D<float, 2>, Tensor1D<float, 5>>(s1, {2}, {2});
EXPECT_THAT(t1, Pointwise(FloatEq(), {2.0f, 3.0f}));
Tensor2D<float, 4, 3> s2{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f,
6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f};
auto t2 = mhlo::dynamic_slice<Tensor2D<float, 2, 2>, Tensor2D<float, 4, 3>>(
s2, {2}, {1}, {2, 2});
EXPECT_THAT(t2, Pointwise(FloatEq(), {7.0f, 8.0f, 10.0f, 11.0f}));
}
TEST(mhlo, dynamic_update_slice) {
Tensor1D<float, 5> s1{0.0f, 1.0f, 2.0f, 3.0f, 4.0f};
Tensor1D<float, 2> u1{5.0f, 6.0f};
auto t1 = mhlo::dynamic_update_slice<Tensor1D<float, 2>, Tensor1D<float, 5>>(
s1, u1, {2});
EXPECT_THAT(t1, Pointwise(FloatEq(), {0.0f, 1.0f, 5.0f, 6.0f, 4.0f}));
Tensor2D<float, 4, 3> s2{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f,
6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f};
Tensor2D<float, 3, 2> u2{12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f};
auto t2 =
mhlo::dynamic_update_slice<Tensor2D<float, 3, 2>, Tensor2D<float, 4, 3>>(
s2, u2, {1}, {1});
EXPECT_THAT(t2,
Pointwise(FloatEq(), {0.0f, 1.0f, 2.0f, 3.0f, 12.0f, 13.0f, 6.0f,
14.0f, 15.0f, 9.0f, 16.0f, 17.0f}));
}
// Other ops
TEST(mhlo, batch_norm_inference) {
Tensor<float, 4, 2> input{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
Tensor<float, 4, 2> expected_result{-3.0f, 2.0f, 1.0f, 6.0f,
5.0f, 10.0f, 9.0f, 14.0f};
Tensor<float, 4, 2> result =
mhlo::batch_norm_inference<Tensor<float, 4, 2>, Tensor<float, 2>>(
input, {1.0f, 2.0f}, {1.0f, 2.0f}, {2.0f, 1.0f}, {0.249f, 0.999f},
0.001f, 1);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
TEST(mhlo, bitcast_convert) {
uint8_t a = 128;
int8_t b = -128;
EXPECT_EQ(b, mhlo::bitcast_convert<int8_t>(a));
Tensor0D<int16_t> t0{-1};
auto lambda_0d = [&t0]() {
return mhlo::bitcast_convert<Tensor0D<uint16_t>>(t0);
};
EXPECT_THAT(lambda_0d(), Pointwise(Eq(), {65535}));
Tensor1D<uint16_t, 2> t1{1, 2};
auto lambda_1d = [&t1]() {
return mhlo::bitcast_convert<Tensor1D<int16_t, 2>>(t1);
};
EXPECT_THAT(lambda_1d(), Pointwise(Eq(), {1, 2}));
Tensor2D<int8_t, 2, 2> t2{0, -4, 3, -12};
auto lambda_2d = [&t2]() {
return mhlo::bitcast_convert<Tensor2D<uint8_t, 2, 2>>(t2);
};
EXPECT_THAT(lambda_2d(), Pointwise(DoubleEq(), {0, 252, 3, 244}));
Tensor3D<int8_t, 2, 1, 2> t3{0, -4, 3, -12};
auto lambda_3d = [&t3]() {
return mhlo::bitcast_convert<Tensor3D<uint8_t, 2, 1, 2>>(t3);
};
EXPECT_THAT(lambda_3d(), Pointwise(DoubleEq(), {0, 252, 3, 244}));
Tensor4D<int8_t, 2, 1, 2, 2> t4{0, -4, 3, -12, -11, 0, 2, -4};
auto lambda_4d = [&t4]() {
return mhlo::bitcast_convert<Tensor4D<uint8_t, 2, 1, 2, 2>>(t4);
};
EXPECT_THAT(lambda_4d(),
Pointwise(DoubleEq(), {0, 252, 3, 244, 245, 0, 2, 252}));
}
TEST(mhlo, broadcast_in_dim) {
Tensor0D<int> t0{1};
Tensor1D<int64_t, 0> b0;
{ // 0D -> 1D
using Dest = Tensor1D<int, 4>;
Dest expected_result{1, 1, 1, 1};
Dest result = mhlo::broadcast_in_dim<Dest>(t0, b0);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{ // 0D -> 2D
using Dest = Tensor2D<int, 2, 3>;
Dest expected_result{1, 1, 1, 1, 1, 1};
Dest result = mhlo::broadcast_in_dim<Dest>(t0, b0);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
Tensor<int, 2> t1{1, 2};
{ // 1D -> 2D
using Dest = Tensor<int, 3, 2>;
Dest expected_result{1, 2, 1, 2, 1, 2};
Dest result = mhlo::broadcast_in_dim<Dest>(t1, {1});
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{ // 1D -> 2D
using Dest = Tensor<int, 2, 3>;
Dest expected_result{1, 1, 1, 2, 2, 2};
Dest result = mhlo::broadcast_in_dim<Dest>(t1, {0});
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
Tensor<int, 2, 3> t2{1, 2, 3, 4, 5, 6};
{ // 2D transpose
using Dest = Tensor<int, 3, 2>;
Dest expected_result{1, 4, 2, 5, 3, 6};
Dest result = mhlo::broadcast_in_dim<Dest>(t2, {1, 0});
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
Tensor2D<float, 1, 3> t3{1.1, 1.2, 1.3};
{ // 2D -> 3D
using Dest = Tensor3D<float, 1, 2, 3>;
Tensor1D<int64_t, 2> broadcast_dim{1, 2};
Dest result = mhlo::broadcast_in_dim<Dest>(t3, broadcast_dim);
Dest expected_result{1.1, 1.2, 1.3, 1.1, 1.2, 1.3};
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{ // 2D -> 3D + transpose
using Dest = Tensor3D<float, 1, 3, 2>;
Tensor1D<int64_t, 2> broadcast_dim{2, 1};
Dest result = mhlo::broadcast_in_dim<Dest>(t3, broadcast_dim);
Dest expected_result{1.1, 1.1, 1.2, 1.2, 1.3, 1.3};
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{ // 2D -> 4D
using Dest = Tensor4D<float, 1, 2, 2, 3>;
Tensor1D<int64_t, 2> broadcast_dim{2, 3};
Dest result = mhlo::broadcast_in_dim<Dest>(t3, broadcast_dim);
Dest expected_result{1.1, 1.2, 1.3, 1.1, 1.2, 1.3,
1.1, 1.2, 1.3, 1.1, 1.2, 1.3};
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
Tensor3D<float, 2, 2, 3> t4{1.1, 1.2, 1.3, 1.4, 1.5, 1.6,
2.1, 2.2, 2.3, 2.4, 2.5, 2.6};
{ // 3D -> 4D
using Dest = Tensor4D<float, 2, 2, 2, 3>;
Tensor1D<int64_t, 3> broadcast_dim{1, 2, 3};
Dest result = mhlo::broadcast_in_dim<Dest>(t4, broadcast_dim);
Dest expected_result{1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.1, 2.2,
2.3, 2.4, 2.5, 2.6, 1.1, 1.2, 1.3, 1.4,
1.5, 1.6, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6};
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
}
TEST(mhlo, clamp) {
Tensor<float, 2, 1> operand{-1.0f, 1.0f};
Tensor<float, 2, 1> min{0.0f, 0.0f};
Tensor<float, 2, 1> max{3.0f, 0.0f};
Tensor<float, 2, 1> expected_result{0.0, 0.0f};
Tensor<float, 2, 1> result = mhlo::clamp(min, operand, max);
EXPECT_THAT(result, Pointwise(FloatEq(), expected_result));
// broadcasting
Tensor<int32_t, 4, 2, 1> operand_b{0, 1, 2, 3, 4, 5, 6, 7};
Tensor<int32_t> min_b{2};
Tensor<int32_t> max_b{5};
Tensor<int32_t, 4, 2, 1> expected_result_b{2, 2, 2, 3, 4, 5, 5, 5};
Tensor<int32_t, 4, 2, 1> result_b = mhlo::clamp(min_b, operand_b, max_b);
EXPECT_THAT(result_b, Pointwise(Eq(), expected_result_b));
}
TEST(mhlo, concatenate) {
Tensor1D<int, 1> t1{1};
Tensor1D<int, 2> t2{2, 3};
Tensor1D<int, 3> t3{4, 5, 6};
auto lambda_1d_1 = [&t1]() -> Tensor1D<int, 1> {
return mhlo::concatenate<0, Tensor1D<int, 1>, Tensor1D<int, 1>>(t1);
};
EXPECT_THAT(lambda_1d_1(), Pointwise(Eq(), {1}));
auto lambda_1d_2 = [&t1, &t2]() -> Tensor1D<int, 3> {
return mhlo::concatenate<0, Tensor1D<int, 3>, Tensor1D<int, 1>,
Tensor1D<int, 2>>(t1, t2);
};
EXPECT_THAT(lambda_1d_2(), Pointwise(Eq(), {1, 2, 3}));
auto lambda_1d_3 = [&t1, &t2, &t3]() -> Tensor1D<int, 6> {
return mhlo::concatenate<0, Tensor1D<int, 6>, Tensor1D<int, 1>,
Tensor1D<int, 2>, Tensor1D<int, 3>>(t1, t2, t3);
};
EXPECT_THAT(lambda_1d_3(), Pointwise(Eq(), {1, 2, 3, 4, 5, 6}));
Tensor2D<float, 1, 2> t4{1.0f, 2.0f};
Tensor2D<float, 2, 2> t5{3.0f, 4.0f, 5.0f, 6.0f};
Tensor2D<float, 3, 2> t6{7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f};
auto lambda_2d_2_row = [&t4, &t5]() -> Tensor2D<float, 3, 2> {
return mhlo::concatenate<0, Tensor2D<float, 3, 2>, Tensor2D<float, 1, 2>,
Tensor2D<float, 2, 2>>(t4, t5);
};
EXPECT_THAT(lambda_2d_2_row(),
Pointwise(FloatEq(), {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}));
auto lambda_2d_2_col = [&t4, &t5]() -> Tensor2D<float, 2, 3> {
Tensor2D<float, 2, 1> t4_reshape = mhlo::reshape<Tensor2D<float, 2, 1>>(t4);
return mhlo::concatenate<1, Tensor2D<float, 2, 3>, Tensor2D<float, 2, 1>,
Tensor2D<float, 2, 2>>(t4_reshape, t5);
};
EXPECT_THAT(lambda_2d_2_col(),
Pointwise(FloatEq(), {1.0f, 3.0f, 4.0f, 2.0f, 5.0f, 6.0f}));
auto lambda_2d_3_row = [&t4, &t5, &t6]() -> Tensor2D<float, 6, 2> {
return mhlo::concatenate<0, Tensor2D<float, 6, 2>, Tensor2D<float, 1, 2>,
Tensor2D<float, 2, 2>, Tensor2D<float, 3, 2>>(
t4, t5, t6);
};
EXPECT_THAT(lambda_2d_3_row(),
Pointwise(FloatEq(), {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f,
8.0f, 9.0f, 10.0f, 11.0f, 12.0f}));
auto lambda_2d_3_col = [&t4, &t5, &t6]() -> Tensor2D<float, 2, 6> {
Tensor2D<float, 2, 1> t4_reshape = mhlo::reshape<Tensor2D<float, 2, 1>>(t4);
Tensor2D<float, 2, 3> t6_reshape = mhlo::reshape<Tensor2D<float, 2, 3>>(t6);
return mhlo::concatenate<1, Tensor2D<float, 2, 6>, Tensor2D<float, 2, 1>,
Tensor2D<float, 2, 2>, Tensor2D<float, 2, 3>>(
t4_reshape, t5, t6_reshape);
};
EXPECT_THAT(lambda_2d_3_col(),
Pointwise(FloatEq(), {1.0f, 3.0f, 4.0f, 7.0f, 8.0f, 9.0f, 2.0f,
5.0f, 6.0f, 10.0f, 11.0f, 12.0f}));
Tensor3D<float, 2, 2, 2> t7{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
Tensor3D<float, 2, 2, 2> t8{9.0f, 10.0f, 11.0f, 12.0f,
13.0f, 14.0f, 15.0f, 16.0f};
Tensor3D<float, 2, 2, 1> t9{9.0f, 10.0f, 11.0f, 12.0f};
auto lambda_3d_422 = [&t7, &t8]() -> Tensor3D<float, 4, 2, 2> {
return mhlo::concatenate<0, Tensor3D<float, 4, 2, 2>,
Tensor3D<float, 2, 2, 2>,
Tensor3D<float, 2, 2, 2>>(t7, t8);
};
EXPECT_THAT(lambda_3d_422(),
Pointwise(FloatEq(),
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f,
10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f}));
auto lambda_3d_242 = [&t7, &t8]() -> Tensor3D<float, 2, 4, 2> {
return mhlo::concatenate<1, Tensor3D<float, 2, 4, 2>,
Tensor3D<float, 2, 2, 2>,
Tensor3D<float, 2, 2, 2>>(t7, t8);
};
EXPECT_THAT(lambda_3d_242(),
Pointwise(FloatEq(),
{1.0f, 2.0f, 3.0f, 4.0f, 9.0f, 10.0f, 11.0f, 12.0f,
5.0f, 6.0f, 7.0f, 8.0f, 13.0f, 14.0f, 15.0f, 16.0f}));
auto lambda_3d_223 = [&t7, &t9]() -> Tensor3D<float, 2, 2, 3> {
return mhlo::concatenate<2, Tensor3D<float, 2, 2, 3>,
Tensor3D<float, 2, 2, 2>,
Tensor3D<float, 2, 2, 1>>(t7, t9);
};
EXPECT_THAT(lambda_3d_223(),
Pointwise(FloatEq(), {1.0f, 2.0f, 9.0f, 3.0f, 4.0f, 10.0f, 5.0f,
6.0f, 11.0f, 7.0f, 8.0f, 12.0f}));
Tensor4D<float, 2, 2, 2, 2> t10{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f,
7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f,
13.0f, 14.0f, 15.0f, 16.0f};
Tensor4D<float, 2, 2, 2, 2> t11{17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f,
23.0f, 24.0f, 25.0f, 26.0f, 27.0f, 28.0f,
29.0f, 30.0f, 31.0f, 32.0f};
Tensor4D<float, 2, 2, 1, 2> t12{33.0f, 34.0f, 35.0f, 36.0f,
37.0f, 38.0f, 39.0f, 40.0f};
auto lambda_4d_4222 = [&t10, &t11]() -> Tensor4D<float, 4, 2, 2, 2> {
return mhlo::concatenate<0, Tensor4D<float, 4, 2, 2, 2>,
Tensor4D<float, 2, 2, 2, 2>,
Tensor4D<float, 2, 2, 2, 2>>(t10, t11);
};
EXPECT_THAT(
lambda_4d_4222(),
Pointwise(FloatEq(),
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f,
17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f, 24.0f,
25.0f, 26.0f, 27.0f, 28.0f, 29.0f, 30.0f, 31.0f, 32.0f}));
auto lambda_4d_2422 = [&t10, &t11]() -> Tensor4D<float, 2, 4, 2, 2> {
return mhlo::concatenate<1, Tensor4D<float, 2, 4, 2, 2>,
Tensor4D<float, 2, 2, 2, 2>,
Tensor4D<float, 2, 2, 2, 2>>(t10, t11);
};
EXPECT_THAT(
lambda_4d_2422(),
Pointwise(FloatEq(),
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f, 24.0f,
9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f,
25.0f, 26.0f, 27.0f, 28.0f, 29.0f, 30.0f, 31.0f, 32.0f}));
auto lambda_4d_2242 = [&t10, &t11]() -> Tensor4D<float, 2, 2, 4, 2> {
return mhlo::concatenate<2, Tensor4D<float, 2, 2, 4, 2>,
Tensor4D<float, 2, 2, 2, 2>,
Tensor4D<float, 2, 2, 2, 2>>(t10, t11);
};
EXPECT_THAT(
lambda_4d_2242(),
Pointwise(FloatEq(),
{1.0f, 2.0f, 3.0f, 4.0f, 17.0f, 18.0f, 19.0f, 20.0f,
5.0f, 6.0f, 7.0f, 8.0f, 21.0f, 22.0f, 23.0f, 24.0f,
9.0f, 10.0f, 11.0f, 12.0f, 25.0f, 26.0f, 27.0f, 28.0f,
13.0f, 14.0f, 15.0f, 16.0f, 29.0f, 30.0f, 31.0f, 32.0f}));
auto lambda_4d_2224 = [&t10, &t11]() -> Tensor4D<float, 2, 2, 2, 4> {
return mhlo::concatenate<3, Tensor4D<float, 2, 2, 2, 4>,
Tensor4D<float, 2, 2, 2, 2>,
Tensor4D<float, 2, 2, 2, 2>>(t10, t11);
};
EXPECT_THAT(
lambda_4d_2224(),
Pointwise(FloatEq(),
{1.0f, 2.0f, 17.0f, 18.0f, 3.0f, 4.0f, 19.0f, 20.0f,
5.0f, 6.0f, 21.0f, 22.0f, 7.0f, 8.0f, 23.0f, 24.0f,
9.0f, 10.0f, 25.0f, 26.0f, 11.0f, 12.0f, 27.0f, 28.0f,
13.0f, 14.0f, 29.0f, 30.0f, 15.0f, 16.0f, 31.0f, 32.0f}));
auto lambda_4d_2232 = [&t10, &t12]() -> Tensor4D<float, 2, 2, 3, 2> {
return mhlo::concatenate<2, Tensor4D<float, 2, 2, 3, 2>,
Tensor4D<float, 2, 2, 2, 2>,
Tensor4D<float, 2, 2, 1, 2>>(t10, t12);
};
EXPECT_THAT(lambda_4d_2232(),
Pointwise(FloatEq(), {1.0f, 2.0f, 3.0f, 4.0f, 33.0f, 34.0f,
5.0f, 6.0f, 7.0f, 8.0f, 35.0f, 36.0f,
9.0f, 10.0f, 11.0f, 12.0f, 37.0f, 38.0f,
13.0f, 14.0f, 15.0f, 16.0f, 39.0f, 40.0f}));
}
TEST(mhlo, convolution) {
int64_t batch_group_count = 1;
int64_t input_batch_dimension = 0;
int64_t input_feature_dimension = 3;
Tensor1D<int64_t, 2> input_spatial_dimensions{1, 2};
int64_t kernel_input_feature_dimension = 2;
int64_t kernel_output_feature_dimension = 3;
Tensor1D<int64_t, 2> kernel_spatial_dimensions{0, 1};
int64_t output_batch_dimension = 0;
int64_t output_feature_dimension = 3;
Tensor1D<int64_t, 2> output_spatial_dimensions{1, 2};
int64_t feature_group_count = 1;
Tensor1D<int64_t, 2> rhs_dilation{1, 1};
Tensor1D<int64_t, 2> lhs_dilation{1, 1};
{
/// Adapted from
/// https://github.com/google/iree/blob/efd78a0b47a46457a644f43d98617d3e279b2a79/iree/test/e2e/xla_ops/convolution.mlir#L33
using InputType = Tensor4D<float, 1, 4, 5, 2>; // N H W C
using WeightType = Tensor4D<float, 3, 2, 2, 1>; // KH KW CIN COUT
using ResultType = Tensor4D<float, 1, 4, 5, 1>; // N H W C
InputType input{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40};
WeightType weights{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
ResultType expected_result{600, 736, 872, 1008, 476, 1310, 1466,
1622, 1778, 805, 2090, 2246, 2402, 2558,
1135, 1080, 1152, 1224, 1296, 524};
Tensor2D<int64_t, 2, 2> padding{1, 1, 0, 1}; // {pt, pb, pl, pr}
Tensor1D<int64_t, 2> window_strides{1, 1};
ResultType result = mhlo::convolution<ResultType, InputType, WeightType>(
input, weights, batch_group_count, input_batch_dimension,
input_feature_dimension, input_spatial_dimensions,
kernel_input_feature_dimension, kernel_output_feature_dimension,
kernel_spatial_dimensions, output_batch_dimension,
output_feature_dimension, output_spatial_dimensions,
feature_group_count, padding, lhs_dilation, rhs_dilation,
window_strides);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
{
// Strided convolution
using InputType = Tensor4D<float, 1, 4, 4, 1>; // N H W C
using WeightType = Tensor4D<float, 2, 2, 1, 1>; // KH KW CIN COUT
using ResultType = Tensor4D<float, 1, 2, 2, 1>; // N H W C
// clang-format off
InputType input{1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16};
WeightType weights{1, 2,
3, 4};
ResultType expected_result{44, 64,
124, 144};
// clang-format on
Tensor2D<int64_t, 2, 2> padding{0, 0, 0, 0}; // {pt, pb, pl, pr}
Tensor1D<int64_t, 2> window_strides{2, 2};
ResultType result = mhlo::convolution<ResultType, InputType, WeightType>(
input, weights, batch_group_count, input_batch_dimension,
input_feature_dimension, input_spatial_dimensions,
kernel_input_feature_dimension, kernel_output_feature_dimension,
kernel_spatial_dimensions, output_batch_dimension,
output_feature_dimension, output_spatial_dimensions,
feature_group_count, padding, lhs_dilation, rhs_dilation,
window_strides);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
}
TEST(mhlo, convolution_depthwise) {
using InputType = Tensor4D<float, 1, 4, 5, 2>;
using WeightType = Tensor4D<float, 2, 2, 1, 2>;
using ResultType = Tensor4D<float, 1, 3, 4, 2>;
InputType input{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40};
WeightType weights{1, 2, 3, 4, 5, 6, 7, 8};
ResultType expected_result{156, 204, 188, 244, 220, 284, 252, 324,
316, 404, 348, 444, 380, 484, 412, 524,
476, 604, 508, 644, 540, 684, 572, 724};
int64_t batch_group_count = 1;
int64_t input_batch_dimension = 0;
int64_t input_feature_dimension = 3;
Tensor1D<int64_t, 2> input_spatial_dimensions{1, 2};
int64_t kernel_input_feature_dimension = 2;
int64_t kernel_output_feature_dimension = 3;
Tensor1D<int64_t, 2> kernel_spatial_dimensions{0, 1};
int64_t output_batch_dimension = 0;
int64_t output_feature_dimension = 3;
Tensor1D<int64_t, 2> output_spatial_dimensions{1, 2};
int64_t feature_group_count = 2;
Tensor2D<int64_t, 2, 2> padding{0, 0, 0, 0};
Tensor1D<int64_t, 2> rhs_dilation{1, 1};
Tensor1D<int64_t, 2> lhs_dilation{1, 1};
Tensor1D<int64_t, 2> window_strides{1, 1};
ResultType result = mhlo::convolution<ResultType, InputType, WeightType>(
input, weights, batch_group_count, input_batch_dimension,
input_feature_dimension, input_spatial_dimensions,
kernel_input_feature_dimension, kernel_output_feature_dimension,
kernel_spatial_dimensions, output_batch_dimension,
output_feature_dimension, output_spatial_dimensions, feature_group_count,
padding, lhs_dilation, rhs_dilation, window_strides);
EXPECT_THAT(result, Pointwise(FloatNear(EPSILON), expected_result));
}
TEST(mhlo, DISABLED_convolution_grouped) {
// TODO implement test
}
TEST(mhlo, DISABLED_convolution_dilated) {
// TODO implement test
}
TEST(mhlo, dot) {
Tensor2D<int, 2, 2> a2{1, 0, 0, 1};
Tensor2D<int, 2, 2> b2{4, 1, 2, 2};
auto lambda_2d = [&a2, &b2]() -> Tensor2D<int, 2, 2> {
return mhlo::dot<Tensor2D<int, 2, 2>>(a2, b2);
};
EXPECT_THAT(lambda_2d(), Pointwise(Eq(), {4, 1, 2, 2}));
}
TEST(mhlo, reshape) {
Tensor0D<int> s0{-3};
auto t0 = mhlo::reshape<Tensor1D<int, 1>>(s0);
auto t0_1 = mhlo::reshape<Tensor2D<int, 1, 1>>(s0);
EXPECT_THAT(t0, Pointwise(Eq(), {-3}));
EXPECT_THAT(t0_1, Pointwise(Eq(), {-3}));
Tensor1D<float, 2> s1{-1.3f, 2.4f};
auto t1 = mhlo::reshape<Tensor2D<float, 1, 2>>(s1);
EXPECT_THAT(t1, Pointwise(FloatEq(), {-1.3f, 2.4f}));
Tensor2D<long, 2, 2> s2{3, 1, 4, 9};
auto t2 = mhlo::reshape<Tensor1D<long, 4>>(s2);
EXPECT_THAT(t2, Pointwise(Eq(), {3, 1, 4, 9}));
}
TEST(mhlo, pad) {
Tensor<int32_t, 2, 3> operand{1, 2, 3, 4, 5, 6};
Tensor<int32_t> value{0};
Tensor<int32_t, 3, 6> expected_result0{0, 1, 2, 3, 0, 0, 0, 4, 5,
6, 0, 0, 0, 0, 0, 0, 0, 0};
Tensor<int32_t, 3, 6> result0 =
mhlo::pad<Tensor<int32_t, 3, 6>>(operand, value, {0, 1}, {1, 2}, {0, 0});
EXPECT_THAT(result0, Pointwise(Eq(), expected_result0));
Tensor<int32_t, 3, 5> expected_result1{1, 0, 2, 0, 3, 0, 0, 0,
0, 0, 4, 0, 5, 0, 6};
Tensor<int32_t, 3, 5> result1 =
mhlo::pad<Tensor<int32_t, 3, 5>>(operand, value, {0, 0}, {0, 0}, {1, 1});
EXPECT_THAT(result1, Pointwise(Eq(), expected_result1));
Tensor<int32_t, 4, 8> expected_result2{0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 4, 0, 5, 0, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Tensor<int32_t, 4, 8> result2 =
mhlo::pad<Tensor<int32_t, 4, 8>>(operand, value, {0, 1}, {1, 2}, {1, 1});
EXPECT_THAT(result2, Pointwise(Eq(), expected_result2));
}
Tensor<int32_t> reduce_computation(Tensor<int32_t> a, Tensor<int32_t> b) {
Tensor<int32_t> v0 = mhlo::add(a, b);
return v0;
}
std::tuple<Tensor<int32_t>, Tensor<int32_t>>
reduce_computation_tuple(Tensor<int32_t> reduction_a, Tensor<int32_t> next_a,
Tensor<int32_t> reduction_b, Tensor<int32_t> next_b) {
Tensor<int32_t> v0 = mhlo::add(reduction_a, next_a);
Tensor<int32_t> v1 = mhlo::min(reduction_b, next_b);
return std::make_tuple(v0, v1);
}
TEST(mhlo, reduce) {
{
Tensor<int32_t, 2, 3> x{1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t, 3> expected_result{5, 7, 9};
Tensor<int32_t, 3> result = mhlo::reduce<Tensor<int32_t, 3>, 1>(
x, initValue, {0}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 2, 3> x{1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t, 2> expected_result{6, 15};
Tensor<int32_t, 2> result = mhlo::reduce<Tensor<int32_t, 2>, 1>(
x, initValue, {1}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 2, 3> x{1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t> expected_result{21};
Tensor<int32_t> result = mhlo::reduce<Tensor<int32_t>, 2>(
x, initValue, {0, 1}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 4, 2, 3> x{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t, 2, 3> expected_result{4, 8, 12, 16, 20, 24};
Tensor<int32_t, 2, 3> result = mhlo::reduce<Tensor<int32_t, 2, 3>, 1>(
x, initValue, {0}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 4, 2, 3> x{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t, 4, 3> expected_result{5, 7, 9, 5, 7, 9, 5, 7, 9, 5, 7, 9};
Tensor<int32_t, 4, 3> result = mhlo::reduce<Tensor<int32_t, 4, 3>, 1>(
x, initValue, {1}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 4, 2, 3> x{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t, 4, 2> expected_result{6, 15, 6, 15, 6, 15, 6, 15};
Tensor<int32_t, 4, 2> result = mhlo::reduce<Tensor<int32_t, 4, 2>, 1>(
x, initValue, {2}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 4, 2, 3> x{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t, 3> expected_result{20, 28, 36};
Tensor<int32_t, 3> result = mhlo::reduce<Tensor<int32_t, 3>, 2>(
x, initValue, {0, 1}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 4, 2, 3> x{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t, 2> expected_result{24, 60};
Tensor<int32_t, 2> result = mhlo::reduce<Tensor<int32_t, 2>, 2>(
x, initValue, {0, 2}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 4, 2, 3> x{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t, 4> expected_result{21, 21, 21, 21};
Tensor<int32_t, 4> result = mhlo::reduce<Tensor<int32_t, 4>, 2>(
x, initValue, {1, 2}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor<int32_t, 4, 2, 3> x{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue{0};
Tensor<int32_t> expected_result{84};
Tensor<int32_t> result = mhlo::reduce<Tensor<int32_t>, 3>(
x, initValue, {0, 1, 2}, reduce_computation);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
// 2 return values
{
Tensor<int32_t, 2, 3> x1{1, 2, 3, 4, 5, 6};
Tensor<int32_t, 2, 3> x2{1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue1{0};
Tensor<int32_t> initValue2{std::numeric_limits<int32_t>::max()};
std::tuple<Tensor<int32_t, 3>, Tensor<int32_t, 3>> expected_result{
{5, 7, 9}, {1, 2, 3}};
std::tuple<Tensor<int32_t, 3>, Tensor<int32_t, 3>> result =
mhlo::reduce<Tensor<int32_t, 3>, Tensor<int32_t, 3>, 1>(
x1, x2, initValue1, initValue2, {0}, reduce_computation_tuple);
EXPECT_THAT(std::get<0>(result),
Pointwise(Eq(), std::get<0>(expected_result)));
EXPECT_THAT(std::get<1>(result),
Pointwise(Eq(), std::get<1>(expected_result)));
}
{
Tensor<int32_t, 4, 2, 3> x1{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t, 4, 2, 3> x2{1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6,
1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Tensor<int32_t> initValue1{0};
Tensor<int32_t> initValue2{std::numeric_limits<int32_t>::max()};
std::tuple<Tensor<int32_t>, Tensor<int32_t>> expected_result{{84}, {1}};
std::tuple<Tensor<int32_t>, Tensor<int32_t>> result =
mhlo::reduce<Tensor<int32_t>, Tensor<int32_t>, 3>(
x1, x2, initValue1, initValue2, {0, 1, 2},
reduce_computation_tuple);
EXPECT_THAT(std::get<0>(result),
Pointwise(Eq(), std::get<0>(expected_result)));
EXPECT_THAT(std::get<1>(result),
Pointwise(Eq(), std::get<1>(expected_result)));
}
}
TEST(mhlo, reduce_window) {
Tensor<int32_t> c0{std::numeric_limits<int32_t>::min()};
Tensor<int32_t, 4, 8> t0{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32};
auto max = [](Tensor<int32_t> a, Tensor<int32_t> b) {
return mhlo::max(a, b);
};
Tensor<int32_t, 2, 4> expected_result0{10, 12, 14, 16, 26, 28, 30, 32};
Tensor<int32_t, 2, 4> result0 = mhlo::reduce_window<Tensor<int32_t, 2, 4>>(
t0, c0, {2, 2}, {2, 2}, {1, 1}, {1, 1}, {0, 0, 0, 0}, max);
EXPECT_THAT(result0, Pointwise(Eq(), expected_result0));
Tensor<int32_t, 3, 7> expected_result1{10, 11, 12, 13, 14, 15, 16,
18, 19, 20, 21, 22, 23, 24,
26, 27, 28, 29, 30, 31, 32};
Tensor<int32_t, 3, 7> result1 = mhlo::reduce_window<Tensor<int32_t, 3, 7>>(
t0, c0, {2, 2}, {1, 1}, {1, 1}, {1, 1}, {0, 0, 0, 0}, max);
EXPECT_THAT(result1, Pointwise(Eq(), expected_result1));
auto min = [](Tensor<float> a, Tensor<float> b) { return mhlo::min(a, b); };
Tensor<float> c1{std::numeric_limits<float>::max()};
Tensor<float, 5> t1{10000.0f, 1000.0f, 100.0f, 10.0f, 1.0f};
Tensor<float, 2> expected_result2{100.0f, 1.0f};
Tensor<float, 2> result2 = mhlo::reduce_window<Tensor<float, 2>>(
t1, c1, {3}, {2}, {1}, {1}, {0, 0}, min);
EXPECT_THAT(result2, Pointwise(Eq(), expected_result2));
Tensor<float, 3> expected_result3{1000.0f, 10.0f, 1.0f};
Tensor<float, 3> result3 = mhlo::reduce_window<Tensor<float, 3>>(
t1, c1, {3}, {2}, {1}, {1}, {1, 1}, min);
EXPECT_THAT(result3, Pointwise(Eq(), expected_result3));
}
TEST(mhlo, select) {
EXPECT_EQ(-1, mhlo::select(true, -1, 3));
EXPECT_EQ(3, mhlo::select(false, -1, 3));
{
Tensor0D<int> s{-3};
Tensor0D<int> t{8};
Tensor0D<bool> p{true};
Tensor0D<int> expected_result{-3};
Tensor0D<int> result = mhlo::select<Tensor0D<int>>(p, s, t);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor1D<float, 2> s{-1.3f, 2.4f};
Tensor1D<float, 2> t{0.2f, -3.7f};
Tensor1D<bool, 2> p{true, false};
Tensor1D<float, 2> expected_result{-1.3f, -3.7f};
Tensor1D<float, 2> result = mhlo::select<Tensor1D<float, 2>>(p, s, t);
EXPECT_THAT(result, Pointwise(FloatEq(), expected_result));
}
{
Tensor1D<float, 2> s{-1.3f, 2.4f};
Tensor1D<float, 2> t{0.2f, -3.7f};
Tensor0D<bool> p{true};
Tensor1D<float, 2> expected_result = s;
Tensor1D<float, 2> result = mhlo::select<Tensor1D<float, 2>>(p, s, t);
EXPECT_THAT(result, Pointwise(FloatEq(), expected_result));
}
{
Tensor2D<long, 2, 2> s{3, 1, 4, 9};
Tensor2D<long, 2, 2> t{-2, 8, 6, -10};
Tensor2D<bool, 2, 2> p{false, true, true, false};
Tensor2D<long, 2, 2> expected_result{-2, 1, 4, -10};
Tensor2D<long, 2, 2> result = mhlo::select<Tensor2D<long, 2, 2>>(p, s, t);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
{
Tensor2D<long, 2, 2> s{3, 1, 4, 9};
Tensor2D<long, 2, 2> t{-2, 8, 6, -10};
Tensor0D<bool> p{false};
Tensor2D<long, 2, 2> expected_result = t;
Tensor2D<long, 2, 2> result = mhlo::select<Tensor2D<long, 2, 2>>(p, s, t);
EXPECT_THAT(result, Pointwise(Eq(), expected_result));
}
}
} // namespace