Files
tensorflow--tensorflow/tensorflow/lite/kernels/pad_test.cc
T
wehub-resource-sync 8a852e4b4e
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s
chore: import upstream snapshot with attribution
2026-07-13 12:14:16 +08:00

1722 lines
62 KiB
C++

/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
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
http://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.
==============================================================================*/
#include <cstdint>
#include <initializer_list>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "flatbuffers/flatbuffers.h" // from @flatbuffers
#include "tensorflow/lite/core/interpreter.h"
#include "tensorflow/lite/kernels/test_util.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/types/half.h"
namespace tflite {
namespace {
using ::testing::ElementsAreArray;
using ::testing::Matcher;
template <typename RegularInputOutput, typename PaddingIntegerType>
class PadOpModel : public SingleOpModel {
public:
void SetInput(std::initializer_list<RegularInputOutput> data) {
PopulateTensor<RegularInputOutput>(input_, data);
}
template <typename QuantizedInputOutput>
void SetQuantizedInput(std::initializer_list<float> data) {
QuantizeAndPopulate<QuantizedInputOutput>(input_, data);
}
template <typename QuantizedInputOutput>
void SetQuantizedPadValue(float data) {
QuantizeAndPopulate<QuantizedInputOutput>(constant_values_, {data});
}
void SetPaddings(std::initializer_list<PaddingIntegerType> paddings) {
PopulateTensor<PaddingIntegerType>(paddings_, paddings);
}
std::vector<RegularInputOutput> GetOutput() {
return ExtractVector<RegularInputOutput>(output_);
}
std::vector<int> GetOutputShape() { return GetTensorShape(output_); }
template <typename QuantizedInputOutput>
std::vector<float> GetDequantizedOutput() {
return Dequantize<QuantizedInputOutput>(
ExtractVector<QuantizedInputOutput>(output_), GetScale(output_),
GetZeroPoint(output_));
}
protected:
int input_;
int output_;
int paddings_;
int constant_values_;
};
// Tests case where paddings is a const tensor. Type T1 is the dtype. Type T2 is
// the padding dtype.
template <typename T1, typename T2>
class PadV2OpConstModel : public PadOpModel<T1, T2> {
public:
PadV2OpConstModel(const TensorData& input,
std::initializer_list<int> paddings_shape,
std::initializer_list<T2> paddings, T1 constant_values,
const TensorData& output) {
this->input_ = this->AddInput(input);
this->paddings_ =
this->AddConstInput(GetTensorType<T2>(), paddings, paddings_shape);
this->constant_values_ =
this->AddConstInput(GetTensorType<T1>(), {constant_values}, {1});
this->output_ = this->AddOutput(output);
this->SetBuiltinOp(BuiltinOperator_PADV2, BuiltinOptions_PadV2Options,
CreatePadV2Options(this->builder_).Union());
this->BuildInterpreter({input.shape});
}
PadV2OpConstModel(const TensorData& input,
std::initializer_list<int> paddings_shape,
std::initializer_list<T2> paddings,
const TensorData& constant_values,
const TensorData& output) {
this->input_ = this->AddInput(input);
this->paddings_ =
this->AddConstInput(GetTensorType<T2>(), paddings, paddings_shape);
this->constant_values_ = this->AddInput(constant_values);
this->output_ = this->AddOutput(output);
this->SetBuiltinOp(BuiltinOperator_PADV2, BuiltinOptions_PadV2Options,
CreatePadV2Options(this->builder_).Union());
this->BuildInterpreter({input.shape});
}
};
// Tests case where paddings is a const tensor. Type T is the padding dtype.
//
// Example usage is as follows:
// PadOpDynamicModel m(input_shape, paddings_shape, paddings_data);
// m.SetInput(input_data);
// m.Invoke();
template <typename T>
class PadOpConstModel : public PadOpModel<float, T> {
public:
PadOpConstModel(const TensorData& input,
std::initializer_list<int> paddings_shape,
std::initializer_list<T> paddings, const TensorData& output) {
this->input_ = this->AddInput(input);
this->paddings_ =
this->AddConstInput(GetTensorType<T>(), paddings, paddings_shape);
this->constant_values_ = this->AddNullInput();
this->output_ = this->AddOutput(output);
this->SetBuiltinOp(BuiltinOperator_PAD, BuiltinOptions_PadOptions,
CreatePadOptions(this->builder_).Union());
this->BuildInterpreter({input.shape});
}
};
// Test case where paddings is a non-const tensor.
template <typename RegularInputOutput, typename PaddingIntegerType>
class PadV2OpDynamicModel
: public PadOpModel<RegularInputOutput, PaddingIntegerType> {
public:
PadV2OpDynamicModel(const TensorData& input,
std::initializer_list<int> paddings_shape,
RegularInputOutput constant_values,
const TensorData& output) {
this->input_ = this->AddInput(input);
this->paddings_ = this->AddInput(GetTensorType<PaddingIntegerType>());
this->constant_values_ = this->AddConstInput(
GetTensorType<RegularInputOutput>(), {constant_values}, {1});
this->output_ = this->AddOutput(output);
this->SetBuiltinOp(BuiltinOperator_PADV2, BuiltinOptions_PadV2Options,
CreatePadV2Options(this->builder_).Union());
this->BuildInterpreter({input.shape, paddings_shape});
}
PadV2OpDynamicModel(const TensorData& input,
std::initializer_list<int> paddings_shape,
const TensorData& constant_values,
const TensorData& output) {
this->input_ = this->AddInput(input);
this->paddings_ = this->AddInput(GetTensorType<PaddingIntegerType>());
this->constant_values_ = this->AddInput(constant_values);
this->output_ = this->AddOutput(output);
this->SetBuiltinOp(BuiltinOperator_PADV2, BuiltinOptions_PadV2Options,
CreatePadV2Options(this->builder_).Union());
this->BuildInterpreter({input.shape, paddings_shape});
}
};
// Test case where paddings is a non-const tensor.
//
// Example usage is as follows:
// PadOpDynamicModel m(input_shape, paddings_shape);
// m.SetInput(input_data);
// m.SetPaddings(paddings_data);
// m.Invoke();
template <typename T>
class PadOpDynamicModel : public PadOpModel<float, T> {
public:
PadOpDynamicModel(const TensorData& input,
std::initializer_list<int> paddings_shape,
const TensorData& output) {
this->input_ = this->AddInput(input);
this->paddings_ = this->AddInput(GetTensorType<T>());
this->constant_values_ = this->AddNullInput();
this->output_ = this->AddOutput(output);
this->SetBuiltinOp(BuiltinOperator_PAD, BuiltinOptions_PadOptions,
CreatePadOptions(this->builder_).Union());
this->BuildInterpreter({input.shape, paddings_shape});
}
};
class PadOpTest : public ::testing::Test {};
#if GTEST_HAS_DEATH_TEST
template <typename padding_integer_type>
void TooFewDimensions() {
EXPECT_DEATH(PadOpConstModel<padding_integer_type>(
{TensorType_FLOAT32, {1, 2, 3, 4, 5, 6, 7, 8, 9}}, {9, 2},
{1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9},
{TensorType_FLOAT32}),
"dims <= reference_ops::PadKernelMaxDimensionCount()");
}
TEST_F(PadOpTest, Int32PaddingTooFewDimensions) { TooFewDimensions<int32_t>(); }
TEST_F(PadOpTest, Int64PaddingTooFewDimensions) { TooFewDimensions<int64_t>(); }
TEST_F(PadOpTest, Int8PaddingTooFewDimensions) { TooFewDimensions<int8_t>(); }
TEST_F(PadOpTest, Int16PaddingTooFewDimensions) { TooFewDimensions<int16_t>(); }
template <typename padding_integer_type>
void UnequalDimensions() {
EXPECT_DEATH(PadOpConstModel<padding_integer_type>(
{TensorType_FLOAT32, {1, 1, 2, 1}}, {3, 2},
{1, 1, 2, 2, 3, 3}, {TensorType_FLOAT32}),
"3 != 4");
}
TEST_F(PadOpTest, Int32PaddingUnequalDimensions) {
UnequalDimensions<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingUnequalDimensions) {
UnequalDimensions<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingUnequalDimensions) { UnequalDimensions<int8_t>(); }
TEST_F(PadOpTest, Int16PaddingUnequalDimensions) {
UnequalDimensions<int16_t>();
}
template <typename padding_integer_type>
void InvalidPadValue() {
EXPECT_DEATH(PadOpConstModel<int32_t>({TensorType_FLOAT32, {1, 1, 2, 1}},
{4, 2}, {0, 0, 1, -1, 2, -1, 0, 0},
{TensorType_FLOAT32}),
"Pad value has to be greater than equal to 0.");
}
TEST_F(PadOpTest, Int32PaddingInvalidPadValue) { InvalidPadValue<int32_t>(); }
TEST_F(PadOpTest, Int64PaddingInvalidPadValue) { InvalidPadValue<int64_t>(); }
TEST_F(PadOpTest, Int8PaddingInvalidPadValue) { InvalidPadValue<int8_t>(); }
TEST_F(PadOpTest, Int16PaddingInvalidPadValue) { InvalidPadValue<int16_t>(); }
TEST_F(PadOpTest, Int64PaddingOverflow) {
EXPECT_DEATH(PadOpConstModel<int64_t>(
{TensorType_FLOAT32, {1, 1, 2, 1}}, {4, 2},
{std::numeric_limits<int64_t>::min(), 0, 1, -1, 2, -1, 0, 0},
{TensorType_FLOAT32}),
"INT64 padding overflow. Only support value between INT32_MIN "
"and INT32_MAX.");
EXPECT_DEATH(PadOpConstModel<int64_t>(
{TensorType_FLOAT32, {1, 1, 2, 1}}, {4, 2},
{0, 0, 1, -1, 2, -1, std::numeric_limits<int64_t>::max(), 0},
{TensorType_FLOAT32}),
"INT64 padding overflow. Only support value between INT32_MIN "
"and INT32_MAX.");
}
#endif
template <typename padding_integer_type>
void SimpleConstTest() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadOpConstModel<padding_integer_type> m({TensorType_FLOAT32, {1, 2, 2, 1}},
{4, 2}, {1, 1, 0, 0, 1, 1, 0, 0},
{TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray({0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0,
0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({3, 2, 4, 1}));
}
TEST_F(PadOpTest, Int32PaddingSimpleConstTest) { SimpleConstTest<int32_t>(); }
TEST_F(PadOpTest, Int64PaddingSimpleConstTest) { SimpleConstTest<int64_t>(); }
TEST_F(PadOpTest, Int8PaddingSimpleConstTest) { SimpleConstTest<int8_t>(); }
TEST_F(PadOpTest, Int16PaddingSimpleConstTest) { SimpleConstTest<int16_t>(); }
template <typename padding_integer_type>
void SimpleConstImageStyleTest() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadOpConstModel<padding_integer_type> m({TensorType_FLOAT32, {1, 2, 2, 1}},
{4, 2}, {0, 0, 1, 1, 1, 1, 0, 0},
{TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4,
0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadOpTest, Int32PaddingSimpleConstImageStyleTest) {
SimpleConstImageStyleTest<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingSimpleConstImageStyleTest) {
SimpleConstImageStyleTest<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingSimpleConstImageStyleTest) {
SimpleConstImageStyleTest<int8_t>();
}
TEST_F(PadOpTest, Int16PaddingSimpleConstImageStyleTest) {
SimpleConstImageStyleTest<int16_t>();
}
// Optimized versions may choose to handle zero-sized images differently.
template <typename padding_integer_type>
void ZeroHeightConstImageStyleTest() {
PadOpConstModel<padding_integer_type> m({TensorType_FLOAT32, {1, 0, 2, 1}},
{4, 2}, {0, 0, 1, 1, 1, 1, 0, 0},
{TensorType_FLOAT32});
// Nothing to SetInput().
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 2, 4, 1}));
}
TEST_F(PadOpTest, Int32PaddingZeroHeightConstImageStyleTest) {
ZeroHeightConstImageStyleTest<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingZeroHeightConstImageStyleTest) {
ZeroHeightConstImageStyleTest<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingZeroHeightConstImageStyleTest) {
ZeroHeightConstImageStyleTest<int8_t>();
}
TEST_F(PadOpTest, Int16PaddingZeroHeightConstImageStyleTest) {
ZeroHeightConstImageStyleTest<int16_t>();
}
// Optimized versions may choose to handle zero-sized images differently.
template <typename padding_integer_type>
void ZeroWidthConstImageStyleTest() {
PadOpConstModel<padding_integer_type> m({TensorType_FLOAT32, {1, 2, 0, 1}},
{4, 2}, {0, 0, 1, 1, 1, 1, 0, 0},
{TensorType_FLOAT32});
// Nothing to SetInput().
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 2, 1}));
}
TEST_F(PadOpTest, Int32PaddingZeroWidthConstImageStyleTest) {
ZeroWidthConstImageStyleTest<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingZeroWidthConstImageStyleTest) {
ZeroWidthConstImageStyleTest<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingZeroWidthConstImageStyleTest) {
ZeroWidthConstImageStyleTest<int8_t>();
}
TEST_F(PadOpTest, Int16PaddingZeroWidthConstImageStyleTest) {
ZeroWidthConstImageStyleTest<int16_t>();
}
template <typename padding_integer_type>
void SimpleConst1DTest() {
PadOpConstModel<padding_integer_type> m({TensorType_FLOAT32, {2}}, {1, 2},
{1, 2}, {TensorType_FLOAT32});
m.SetInput({2, 3});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 2, 3, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({5}));
}
TEST_F(PadOpTest, Int32PaddingSimpleConst1DTest) {
SimpleConst1DTest<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingSimpleConst1DTest) {
SimpleConst1DTest<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingSimpleConst1DTest) { SimpleConst1DTest<int8_t>(); }
TEST_F(PadOpTest, Int16PaddingSimpleConst1DTest) {
SimpleConst1DTest<int16_t>();
}
template <typename padding_integer_type>
void SimpleConst1DDim0Test() {
if (SingleOpModel::GetForceUseNnapi()) {
return;
}
PadOpConstModel<int32_t> m({TensorType_FLOAT32, {0}}, {1, 2}, {1, 2},
{TensorType_FLOAT32});
// NumElements(input) = 0, so there is no input data.
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({3}));
}
TEST_F(PadOpTest, Int32PaddingSimpleConst1DDim0Test) {
SimpleConst1DDim0Test<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingSimpleConst1DDim0Test) {
SimpleConst1DDim0Test<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingSimpleConst1DDim0Test) {
SimpleConst1DDim0Test<int8_t>();
}
TEST_F(PadOpTest, Int16PaddingSimpleConst1DDim0Test) {
SimpleConst1DDim0Test<int16_t>();
}
template <typename padding_integer_type>
void SimpleDynamicTest() {
PadOpDynamicModel<padding_integer_type> m({TensorType_FLOAT32, {1, 2, 2, 1}},
{4, 2}, {TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4,
0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadOpTest, Int32PaddingSimpleDynamicTest) {
SimpleDynamicTest<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingSimpleDynamicTest) {
SimpleDynamicTest<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingSimpleDynamicTest) { SimpleDynamicTest<int8_t>(); }
TEST_F(PadOpTest, Int16PaddingSimpleDynamicTest) {
SimpleDynamicTest<int16_t>();
}
template <typename padding_integer_type>
void DynamicUnequalDimensions() {
if (SingleOpModel::GetForceUseNnapi()) {
return;
}
PadOpDynamicModel<padding_integer_type> m({TensorType_FLOAT32, {}}, {3, 2},
{TensorType_FLOAT32});
// Skip invoking m.SetInput() since the method doesn't work with dynamic
// shapes.
m.SetPaddings({0, 0, 1, 1, 1, 1});
ASSERT_NE(m.Invoke(), kTfLiteOk) << "Unequal dimensions.";
}
TEST_F(PadOpTest, Int32PaddingDynamicUnequalDimensions) {
DynamicUnequalDimensions<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingDynamicUnequalDimensions) {
DynamicUnequalDimensions<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingDynamicUnequalDimensions) {
DynamicUnequalDimensions<int8_t>();
}
TEST_F(PadOpTest, Int16PaddingDynamicUnequalDimensions) {
DynamicUnequalDimensions<int16_t>();
}
template <typename padding_integer_type>
void AdvancedConstTestV2() {
PadOpConstModel<padding_integer_type> m({TensorType_FLOAT32, {1, 2, 3, 1}},
{4, 2}, {1, 0, 0, 2, 0, 3, 0, 0},
{TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4, 5, 6});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(
m.GetOutput(),
ElementsAreArray({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5,
6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 4, 6, 1}));
}
TEST_F(PadOpTest, Int32PaddingAdvancedConstTest) {
AdvancedConstTestV2<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingAdvancedConstTest) {
AdvancedConstTestV2<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingAdvancedConstTest) {
AdvancedConstTestV2<int8_t>();
}
TEST_F(PadOpTest, Int16PaddingAdvancedConstTest) {
AdvancedConstTestV2<int16_t>();
}
template <typename padding_integer_type>
void AdvancedConstImageStyleTest() {
PadOpConstModel<int32_t> m({TensorType_FLOAT32, {1, 2, 3, 1}}, {4, 2},
{0, 0, 0, 2, 1, 3, 0, 0}, {TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4, 5, 6});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray({0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(PadOpTest, Int32PaddingAdvancedConstImageStyleTest) {
AdvancedConstImageStyleTest<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingAdvancedConstImageStyleTest) {
AdvancedConstImageStyleTest<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingAdvancedConstImageStyleTest) {
AdvancedConstImageStyleTest<int8_t>();
}
TEST_F(PadOpTest, Int16PaddingAdvancedConstImageStyleTest) {
AdvancedConstImageStyleTest<int16_t>();
}
template <typename padding_integer_type>
void AdvancedDynamicTest() {
PadOpDynamicModel<padding_integer_type> m({TensorType_FLOAT32, {1, 2, 3, 1}},
{4, 2}, {TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4, 5, 6});
m.SetPaddings({0, 0, 0, 2, 1, 3, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray({0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(PadOpTest, Int32PaddingAdvancedDynamicTest) {
AdvancedDynamicTest<int32_t>();
}
TEST_F(PadOpTest, Int64PaddingAdvancedDynamicTest) {
AdvancedDynamicTest<int64_t>();
}
TEST_F(PadOpTest, Int8PaddingAdvancedDynamicTest) {
AdvancedDynamicTest<int8_t>();
}
TEST_F(PadOpTest, Int16PaddingAdvancedDynamicTest) {
AdvancedDynamicTest<int16_t>();
}
std::vector<Matcher<float>> DequantizedArrayNear(
const std::vector<float>& values, const float min, const float max) {
const float quantization_tolerance = (max - min) / 255.0;
return ArrayFloatNear(values, quantization_tolerance);
}
class QuantizedPadOpTest : public ::testing::Test {};
#if GTEST_HAS_DEATH_TEST
template <typename integer_type, TensorType tensor_dtype>
void ZeroNotInQuantizationRange() {
// The test_util and actual quantization code currently ensure that the range
// must include zero, but if that ever changes, this test will catch it.
EXPECT_DEATH(PadOpConstModel<int32_t> m(
{tensor_dtype, {1, 2, 2, 1}, 1.0, 2.0}, {4, 2},
{0, 0, 1, 1, 1, 1, 0, 0}, {tensor_dtype, {}, 1.0, 2.0}),
".*Check failed: f_min <= 0.*");
}
TEST_F(QuantizedPadOpTest, UInt8ZeroNotInQuantizationRange) {
ZeroNotInQuantizationRange<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadOpTest, Int8ZeroNotInQuantizationRange) {
ZeroNotInQuantizationRange<int8_t, TensorType_INT8>();
}
TEST_F(QuantizedPadOpTest, Int16ZeroNotInQuantizationRange) {
ZeroNotInQuantizationRange<int16_t, TensorType_INT16>();
}
#endif
template <typename integer_type, TensorType tensor_dtype>
void SimpleConstTest() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
const float kMin = -1.f;
const float kMax = tensor_dtype == TensorType_INT16 ? 32767.f / 32768.f : 1.f;
PadOpConstModel<int32_t> m({tensor_dtype, {1, 2, 2, 1}, kMin, kMax}, {4, 2},
{0, 0, 1, 1, 1, 1, 0, 0},
{tensor_dtype, {}, kMin, kMax});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{0, 0, 0, 0, 0, -0.8, 0.2, 0, 0, 0.9, 0.7, 0, 0, 0, 0, 0},
kMin, kMax)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(QuantizedPadOpTest, UInt8SimpleConstTest) {
SimpleConstTest<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadOpTest, Int8SimpleConstTest) {
SimpleConstTest<int8_t, TensorType_INT8>();
}
TEST_F(QuantizedPadOpTest, Int16SimpleConstTest) {
SimpleConstTest<int16_t, TensorType_INT16>();
}
template <typename integer_type, TensorType tensor_dtype>
void SimpleDynamicTest() {
const float kMin = -1.f;
const float kMax = tensor_dtype == TensorType_INT16 ? 32767.f / 32768.f : 1.f;
PadOpDynamicModel<int32_t> m({tensor_dtype, {1, 2, 2, 1}, kMin, kMax}, {4, 2},
{tensor_dtype, {}, kMin, kMax});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7});
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{0, 0, 0, 0, 0, -0.8, 0.2, 0, 0, 0.9, 0.7, 0, 0, 0, 0, 0},
kMin, kMax)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(QuantizedPadOpTest, UInt8SimpleDynamicTest) {
SimpleDynamicTest<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadOpTest, Int8SimpleDynamicTest) {
SimpleDynamicTest<int8_t, TensorType_INT8>();
}
TEST_F(QuantizedPadOpTest, Int16SimpleDynamicTest) {
SimpleDynamicTest<int16_t, TensorType_INT16>();
}
template <typename integer_type, TensorType tensor_dtype>
void AdvancedConstTest() {
const float kMin = -1.f;
const float kMax = tensor_dtype == TensorType_INT16 ? 32767.f / 32768.f : 1.f;
PadOpConstModel<int32_t> m({tensor_dtype, {1, 2, 3, 1}, kMin, kMax}, {4, 2},
{0, 0, 0, 2, 1, 3, 0, 0},
{tensor_dtype, {}, kMin, kMax});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{0, -0.8, 0.2, 0.9, 0, 0, 0, 0, 0.7, 0.1, -0.3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
kMin, kMax)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(QuantizedPadOpTest, UInt8AdvancedConstTest) {
AdvancedConstTest<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadOpTest, Int8AdvancedConstTest) {
AdvancedConstTest<int8_t, TensorType_INT8>();
}
TEST_F(QuantizedPadOpTest, Int16AdvancedConstTest) {
AdvancedConstTest<int16_t, TensorType_INT16>();
}
template <typename integer_type, TensorType tensor_dtype>
void AdvancedDynamicTest() {
const float kMin = -1.f;
const float kMax = tensor_dtype == TensorType_INT16 ? 32767.f / 32768.f : 1.f;
PadOpDynamicModel<int32_t> m({tensor_dtype, {1, 2, 3, 1}, kMin, kMax}, {4, 2},
{tensor_dtype, {}, kMin, kMax});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3});
m.SetPaddings({0, 0, 0, 2, 1, 3, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{0, -0.8, 0.2, 0.9, 0, 0, 0, 0, 0.7, 0.1, -0.3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
kMin, kMax)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(QuantizedPadOpTest, UInt8AdvancedDynamicTest) {
AdvancedDynamicTest<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadOpTest, Int8AdvancedDynamicTest) {
AdvancedDynamicTest<int8_t, TensorType_INT8>();
}
TEST_F(QuantizedPadOpTest, Int16AdvancedDynamicTest) {
AdvancedDynamicTest<int16_t, TensorType_INT16>();
}
class PadV2OpTest : public ::testing::Test {};
#if GTEST_HAS_DEATH_TEST
template <typename padding_integer_type>
void TooManyDimensions() {
typedef PadV2OpConstModel<float, padding_integer_type> f;
EXPECT_DEATH(f({TensorType_FLOAT32, {1, 2, 3, 4, 5, 6, 7, 8, 9}}, {9, 2},
{1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}, 0.0,
{TensorType_FLOAT32}),
"dims <= reference_ops::PadKernelMaxDimensionCount()");
}
TEST_F(PadV2OpTest, Int32PaddingTooManyDimensions) {
TooManyDimensions<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingTooManyDimensions) {
TooManyDimensions<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingTooManyDimensions) {
TooManyDimensions<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingTooManyDimensions) {
TooManyDimensions<int16_t>();
}
template <typename padding_integer_type>
void UnequalDimensionsV2() {
typedef PadV2OpConstModel<float, padding_integer_type> f;
EXPECT_DEATH(f({TensorType_FLOAT32, {1, 1, 2, 1}}, {3, 2}, {1, 1, 2, 2, 3, 3},
0.0, {TensorType_FLOAT32}),
"3 != 4");
}
TEST_F(PadV2OpTest, Int32PaddingUnequalDimensions) {
UnequalDimensionsV2<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingUnequalDimensions) {
UnequalDimensionsV2<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingUnequalDimensions) {
UnequalDimensionsV2<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingUnequalDimensions) {
UnequalDimensionsV2<int16_t>();
}
template <typename padding_integer_type>
void InvalidPadValueV2() {
typedef PadV2OpConstModel<float, padding_integer_type> f;
EXPECT_DEATH(f({TensorType_FLOAT32, {1, 1, 2, 1}}, {4, 2},
{0, 0, 1, -1, 2, -1, 0, 0}, 0.0, {TensorType_FLOAT32}),
"Pad value has to be greater than equal to 0.");
}
TEST_F(PadV2OpTest, Int32PaddingInvalidPadValue) {
InvalidPadValueV2<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingInvalidPadValue) {
InvalidPadValueV2<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingInvalidPadValue) { InvalidPadValueV2<int8_t>(); }
TEST_F(PadV2OpTest, Int16PaddingInvalidPadValue) {
InvalidPadValueV2<int16_t>();
}
TEST_F(PadV2OpTest, Int64PaddingOverflow) {
EXPECT_DEATH(PadOpConstModel<int64_t>(
{TensorType_FLOAT32, {1, 1, 2, 1}}, {4, 2},
{std::numeric_limits<int64_t>::min(), 0, 1, -1, 2, -1, 0, 0},
{TensorType_FLOAT32}),
"INT64 padding overflow. Only support value between INT32_MIN "
"and INT32_MAX.");
}
TEST_F(PadV2OpTest, UnsupportedPaddingType) {
EXPECT_DEATH(
PadOpConstModel<float>({TensorType_FLOAT32, {1, 1, 2, 1}}, {4, 2},
{0, 0, 1, 1, 2, 1, 0, 0}, {TensorType_FLOAT32}),
"Padding type FLOAT32 is currently not supported by Pad.");
}
#endif
template <typename padding_integer_type>
void SimpleConstTestUint8() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadV2OpConstModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0}, 0.0,
{TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4,
0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleConstTestUint8) {
SimpleConstTestUint8<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleConstTestUint8) {
SimpleConstTestUint8<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleConstTestUint8) {
SimpleConstTestUint8<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleConstTestUint8) {
SimpleConstTestUint8<int16_t>();
}
template <typename padding_integer_type>
void SimpleConstTestInt8() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadV2OpConstModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0}, 0.0,
{TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4,
0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleConstTestInt8) {
SimpleConstTestInt8<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleConstTestInt8) {
SimpleConstTestInt8<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleConstTestInt8) {
SimpleConstTestInt8<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleConstTestInt8) {
SimpleConstTestInt8<int16_t>();
}
template <typename padding_integer_type>
void SimpleConstFloat32ValuedTestUint8() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadV2OpConstModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0}, 5,
{TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 5, 5, 5, 1, 2, 5, 5, 3, 4,
5, 5, 5, 5, 5}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleConstFloat32ValuedTestUint8) {
SimpleConstFloat32ValuedTestUint8<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleConstFloat32ValuedTestUint8) {
SimpleConstFloat32ValuedTestUint8<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleConstFloat32ValuedTestUint8) {
SimpleConstFloat32ValuedTestUint8<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleConstFloat32ValuedTestUint8) {
SimpleConstFloat32ValuedTestUint8<int16_t>();
}
template <typename padding_integer_type>
void SimpleConstFloat32ValuedTestInt8() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadV2OpConstModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0}, 5,
{TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 5, 5, 5, 1, 2, 5, 5, 3, 4,
5, 5, 5, 5, 5}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleConstFloat32ValuedTestInt8) {
SimpleConstFloat32ValuedTestInt8<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleConstFloat32ValuedTestInt8) {
SimpleConstFloat32ValuedTestInt8<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleConstFloat32ValuedTestInt8) {
SimpleConstFloat32ValuedTestInt8<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleConstFloat32ValuedTestInt8) {
SimpleConstFloat32ValuedTestInt8<int16_t>();
}
template <typename padding_integer_type>
void SimpleConstFloat16ValuedTest() {
PadV2OpConstModel<half, padding_integer_type> m(
{TensorType_FLOAT16, {1, 2, 2, 1}}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0},
half{4.0f}, {TensorType_FLOAT16});
m.SetInput({half{1.5f}, half{2.5f}, half{3.5f}, half{4.5f}});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray(ArrayFloatNear(
{half{4}, half{4}, half{4}, half{4}, half{4}, half{1.5f},
half{2.5f}, half{4}, half{4}, half{3.5f}, half{4.5f},
half{4}, half{4}, half{4}, half{4}, half{4}})));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleConstFloat16) {
SimpleConstFloat16ValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleConstFloat16) {
SimpleConstFloat16ValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleConstFloat16) {
SimpleConstFloat16ValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleConstFloat16) {
SimpleConstFloat16ValuedTest<int16_t>();
}
template <typename padding_integer_type>
void SimpleConstBFloat16ValuedTest() {
PadV2OpConstModel<Eigen::bfloat16, padding_integer_type> m(
{TensorType_BFLOAT16, {1, 2, 2, 1}}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0},
Eigen::bfloat16{6.0f}, {TensorType_BFLOAT16});
m.SetInput({Eigen::bfloat16{1.0f}, Eigen::bfloat16{2.0f},
Eigen::bfloat16{3.0f}, Eigen::bfloat16{4.0}});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({6, 6, 6, 6, 6, 1, 2, 6, 6, 3, 4,
6, 6, 6, 6, 6}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleConstBFloat16) {
SimpleConstBFloat16ValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleConstBFloat16) {
SimpleConstBFloat16ValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleConstBFloat16) {
SimpleConstBFloat16ValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleConstBFloat16) {
SimpleConstBFloat16ValuedTest<int16_t>();
}
template <typename padding_integer_type>
void SimpleConstBoolValuedTest() {
PadV2OpConstModel<bool, padding_integer_type> m(
{TensorType_BOOL, {1, 2, 2, 1}}, {4, 2},
{false, false, true, true, true, true, false, false}, true,
{TensorType_BOOL});
m.SetInput({true, true, false, false});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(
m.GetOutput(),
ElementsAreArray({true, true, true, true, true, true, true, true, true,
false, false, true, true, true, true, true}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleConstBool) {
SimpleConstBoolValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleConstBool) {
SimpleConstBoolValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleConstBool) {
SimpleConstBoolValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleConstBool) {
SimpleConstBoolValuedTest<int16_t>();
}
template <typename padding_integer_type>
void Simple4DConstFloat32ValuedTest() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadV2OpConstModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 1, 2, 1}}, {4, 2}, {0, 1, 0, 0, 0, 0, 0, 1}, 5,
{TensorType_FLOAT32});
m.SetInput({3, 3});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({3, 5, 3, 5, 5, 5, 5, 5}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 2, 2}));
}
TEST_F(PadV2OpTest, Int32PaddingSimple4DConstFloat32ValuedTest) {
Simple4DConstFloat32ValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimple4DConstFloat32ValuedTest) {
Simple4DConstFloat32ValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimple4DConstFloat32ValuedTest) {
Simple4DConstFloat32ValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimple4DConstFloat32ValuedTest) {
Simple4DConstFloat32ValuedTest<int16_t>();
}
template <typename padding_integer_type>
void Simple4DConstFloat16ValuedTest() {
PadV2OpConstModel<half, padding_integer_type> m(
{TensorType_FLOAT16, {1, 1, 2, 1}}, {4, 2}, {0, 1, 0, 0, 0, 0, 0, 1},
half{7.0f}, {TensorType_FLOAT16});
m.SetInput({half{3.0f}, half{6.0f}});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray(ArrayFloatNear(
{half{3.0f}, half{7.0f}, half{6.0f}, half{7.0f}, half{7.0f},
half{7.0f}, half{7.0f}, half{7.0f}})));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 2, 2}));
}
TEST_F(PadV2OpTest, Int32PaddingSimple4DConstFloat16ValuedTest) {
Simple4DConstFloat16ValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimple4DConstFloat16ValuedTest) {
Simple4DConstFloat16ValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimple4DConstFloat16ValuedTest) {
Simple4DConstFloat16ValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimple4DConstFloat16ValuedTest) {
Simple4DConstFloat16ValuedTest<int16_t>();
}
template <typename padding_integer_type>
void Simple4DConstBFloat16ValuedTest() {
PadV2OpConstModel<Eigen::bfloat16, padding_integer_type> m(
{TensorType_BFLOAT16, {1, 1, 2, 1}}, {4, 2}, {0, 1, 0, 0, 0, 0, 0, 1},
Eigen::bfloat16{5.0}, {TensorType_BFLOAT16});
m.SetInput({Eigen::bfloat16{3.2f}, Eigen::bfloat16{6.4f}});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(
m.GetOutput(),
ElementsAreArray(ArrayFloatNear(
{Eigen::bfloat16{3.2f}, Eigen::bfloat16{5.0f}, Eigen::bfloat16{6.4f},
Eigen::bfloat16{5.0f}, Eigen::bfloat16{5.0f}, Eigen::bfloat16{5.0f},
Eigen::bfloat16{5.0f}, Eigen::bfloat16{5.0f}})));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 2, 2}));
}
TEST_F(PadV2OpTest, Int32PaddingSimple4DConstBFloat16ValuedTest) {
Simple4DConstBFloat16ValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimple4DConstBFloat16ValuedTest) {
Simple4DConstBFloat16ValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimple4DConstBFloat16ValuedTest) {
Simple4DConstBFloat16ValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimple4DConstBFloat16ValuedTest) {
Simple4DConstBFloat16ValuedTest<int16_t>();
}
template <typename padding_integer_type>
void SimpleConstInt32ValuedTest() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadV2OpConstModel<int32_t, padding_integer_type> m(
{TensorType_INT32, {1, 2, 2, 1}}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0}, 5,
{TensorType_INT32});
m.SetInput({1, 2, 3, 4});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 5, 5, 5, 1, 2, 5, 5, 3, 4,
5, 5, 5, 5, 5}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleConstInt32ValuedTest) {
SimpleConstInt32ValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleConstInt32ValuedTest) {
SimpleConstInt32ValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleConstInt32ValuedTest) {
SimpleConstInt32ValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleConstInt32ValuedTest) {
SimpleConstInt32ValuedTest<int16_t>();
}
template <typename padding_integer_type>
void SimpleDynamicTestV2() {
PadV2OpDynamicModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, 0.0, {TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({0, 0, 0, 0, 0, 1, 2, 0, 0, 3, 4,
0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleDynamicTest) {
SimpleDynamicTestV2<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleDynamicTest) {
SimpleDynamicTestV2<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleDynamicTest) {
SimpleDynamicTestV2<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleDynamicTest) {
SimpleDynamicTestV2<int16_t>();
}
template <typename padding_integer_type>
void SimpleDynamicTestV2Float16() {
PadV2OpDynamicModel<half, padding_integer_type> m(
{TensorType_FLOAT16, {1, 2, 2, 1}}, {4, 2}, half{0.0f},
{TensorType_FLOAT16});
m.SetInput({half{1.0f}, half{2.0f}, half{3.0f}, half{4.0f}});
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray(ArrayFloatNear(
{half{0.0f}, half{0.0f}, half{0.0f}, half{0.0f}, half{0.0f},
half{1.0f}, half{2.0f}, half{0.0f}, half{0.0f}, half{3.0f},
half{4.0f}, half{0.0f}, half{0.0f}, half{0.0f}, half{0.0f},
half{0.0f}})));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleDynamicTestFloat16) {
SimpleDynamicTestV2Float16<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleDynamicTestFloat16) {
SimpleDynamicTestV2Float16<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleDynamicTestFloat16) {
SimpleDynamicTestV2Float16<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleDynamicTestFloat16) {
SimpleDynamicTestV2Float16<int16_t>();
}
template <typename padding_integer_type>
void SimpleDynamicTestV2BFloat16() {
PadV2OpDynamicModel<Eigen::bfloat16, padding_integer_type> m(
{TensorType_BFLOAT16, {1, 2, 2, 1}}, {4, 2}, Eigen::bfloat16{2.0},
{TensorType_BFLOAT16});
m.SetInput({Eigen::bfloat16{5.0f}, Eigen::bfloat16{6.0f},
Eigen::bfloat16{7.0f}, Eigen::bfloat16{8.0f}});
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({2, 2, 2, 2, 2, 5, 6, 2, 2, 7, 8,
2, 2, 2, 2, 2}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleDynamicTestBFloat16) {
SimpleDynamicTestV2BFloat16<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleDynamicTestBFloat16) {
SimpleDynamicTestV2BFloat16<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleDynamicTestBFloat16) {
SimpleDynamicTestV2BFloat16<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleDynamicTestBFloat16) {
SimpleDynamicTestV2BFloat16<int16_t>();
}
template <typename padding_integer_type>
void SimpleDynamicTestBoolV2() {
PadV2OpDynamicModel<bool, padding_integer_type> m(
{TensorType_BOOL, {1, 2, 2, 1}}, {4, 2}, false, {TensorType_BOOL});
m.SetInput({true, false, true, false});
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray({false, false, false, false, false, true, false,
false, false, true, false, false, false, false,
false, false}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleDynamicTestBoolV2) {
SimpleDynamicTestBoolV2<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleDynamicTestBoolV2) {
SimpleDynamicTestBoolV2<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleDynamicTestBoolV2) {
SimpleDynamicTestBoolV2<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleDynamicTestBoolV2) {
SimpleDynamicTestBoolV2<int16_t>();
}
template <typename padding_integer_type>
void PadV2OpDynamicUnequalDimensions() {
if (SingleOpModel::GetForceUseNnapi()) {
return;
}
PadV2OpDynamicModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {}}, {4, 2}, 0.0, {TensorType_FLOAT32});
// Skip invoking m.SetInput() since the method doesn't work with dynamic
// shapes.
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_NE(m.Invoke(), kTfLiteOk) << "Unequal dimensions";
}
TEST_F(PadV2OpTest, Int32PaddingDynamicUnequalDimensions) {
PadV2OpDynamicUnequalDimensions<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingDynamicUnequalDimensions) {
PadV2OpDynamicUnequalDimensions<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingDynamicUnequalDimensions) {
PadV2OpDynamicUnequalDimensions<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingDynamicUnequalDimensions) {
PadV2OpDynamicUnequalDimensions<int16_t>();
}
template <typename padding_integer_type>
void SimpleDynamicValuedTest() {
PadV2OpDynamicModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 2, 1}}, {4, 2}, 5, {TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 5, 5, 5, 1, 2, 5, 5, 3, 4,
5, 5, 5, 5, 5}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleDynamicValuedTest) {
SimpleDynamicValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleDynamicValuedTest) {
SimpleDynamicValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleDynamicValuedTest) {
SimpleDynamicValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleDynamicValuedTest) {
SimpleDynamicValuedTest<int16_t>();
}
template <typename padding_integer_type>
void SimpleTensorWithDim0Test() {
PadV2OpDynamicModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 2, 0}}, {4, 2}, 5, {TensorType_FLOAT32});
// NumElements(input) = 0, so there is no input data.
m.SetPaddings({0, 0, 1, 1, 0, 0, 1, 1});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 2, 2}));
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
// Since NumElements(output) = 0 in this case, there is no data.
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 0}));
}
TEST_F(PadV2OpTest, Int32PaddingSimpleTensorWithDim0Test) {
SimpleTensorWithDim0Test<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimpleTensorWithDim0Test) {
SimpleTensorWithDim0Test<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimpleTensorWithDim0Test) {
SimpleTensorWithDim0Test<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimpleTensorWithDim0Test) {
SimpleTensorWithDim0Test<int16_t>();
}
template <typename padding_integer_type>
void Simple5DConstFloat32ValuedTest() {
PadV2OpConstModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 1, 2, 1, 1}}, {5, 2},
{0, 1, 0, 0, 1, 1, 0, 0, 0, 1}, 5, {TensorType_FLOAT32});
m.SetInput({3, 3});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({2, 1, 4, 1, 2}));
EXPECT_THAT(m.GetOutput(), ElementsAreArray({5, 5, 3, 5, 3, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5}));
}
TEST_F(PadV2OpTest, Int32PaddingSimple5DConstFloat32ValuedTest) {
Simple5DConstFloat32ValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimple5DConstFloat32ValuedTest) {
Simple5DConstFloat32ValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimple5DConstFloat32ValuedTest) {
Simple5DConstFloat32ValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimple5DConstFloat32ValuedTest) {
Simple5DConstFloat32ValuedTest<int16_t>();
}
template <typename padding_integer_type>
void Simple5DConstInt32ValuedTest() {
PadV2OpConstModel<int32_t, padding_integer_type> m(
{TensorType_INT32, {1, 2, 2, 1, 1}}, {5, 2},
{0, 0, 1, 1, 1, 1, 0, 0, 1, 1}, 5, {TensorType_INT32});
m.SetInput({1, 2, 3, 4});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1, 3}));
EXPECT_THAT(
m.GetOutput(),
ElementsAreArray({5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}));
}
TEST_F(PadV2OpTest, Int32PaddingSimple5DConstInt32ValuedTest) {
Simple5DConstInt32ValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimple5DConstInt32ValuedTest) {
Simple5DConstInt32ValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimple5DConstInt32ValuedTest) {
Simple5DConstInt32ValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimple5DConstInt32ValuedTest) {
Simple5DConstInt32ValuedTest<int16_t>();
}
template <typename padding_integer_type>
void Simple5DDynamicValuedTest() {
PadV2OpDynamicModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 2, 1, 1}}, {5, 2}, 5, {TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4});
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0, 1, 1});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1, 3}));
EXPECT_THAT(
m.GetOutput(),
ElementsAreArray({5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}));
}
TEST_F(PadV2OpTest, Int32PaddingSimple5DDynamicValuedTest) {
Simple5DDynamicValuedTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingSimple5DDynamicValuedTest) {
Simple5DDynamicValuedTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingSimple5DDynamicValuedTest) {
Simple5DDynamicValuedTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingSimple5DDynamicValuedTest) {
Simple5DDynamicValuedTest<int16_t>();
}
template <typename padding_integer_type>
void AdvancedConstTest() {
PadV2OpConstModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 3, 1}}, {4, 2}, {0, 0, 0, 2, 1, 3, 0, 0}, 0,
{TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4, 5, 6});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray({0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingAdvancedConstTest) {
AdvancedConstTest<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingAdvancedConstTest) {
AdvancedConstTest<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingAdvancedConstTest) {
AdvancedConstTest<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingAdvancedConstTest) {
AdvancedConstTest<int16_t>();
}
template <typename padding_integer_type>
void AdvancedDynamicTestV2() {
PadV2OpDynamicModel<float, padding_integer_type> m(
{TensorType_FLOAT32, {1, 2, 3, 1}}, {4, 2}, 0, {TensorType_FLOAT32});
m.SetInput({1, 2, 3, 4, 5, 6});
m.SetPaddings({0, 0, 0, 2, 1, 3, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.GetOutput(),
ElementsAreArray({0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(PadV2OpTest, Int32PaddingAdvancedDynamicTest) {
AdvancedDynamicTestV2<int32_t>();
}
TEST_F(PadV2OpTest, Int64PaddingAdvancedDynamicTest) {
AdvancedDynamicTestV2<int64_t>();
}
TEST_F(PadV2OpTest, Int8PaddingAdvancedDynamicTest) {
AdvancedDynamicTestV2<int8_t>();
}
TEST_F(PadV2OpTest, Int16PaddingAdvancedDynamicTest) {
AdvancedDynamicTestV2<int16_t>();
}
class QuantizedPadV2OpTest : public ::testing::Test {
protected:
std::vector<Matcher<float>> DequantizedArrayNear(
const std::vector<float>& values, const float min, const float max) {
const float quantization_tolerance = (max - min) / 255.0;
return ArrayFloatNear(values, quantization_tolerance);
}
};
#if GTEST_HAS_DEATH_TEST
template <TensorType tensor_dtype>
void ZeroNotInQuantizationRangeV2() {
// The test_util and actual quantization code currently ensure that the range
// must include zero, but if that ever changes, this test will catch it.
typedef PadV2OpConstModel<float, int32_t> f;
EXPECT_DEATH(f({tensor_dtype, {1, 2, 2, 1}, 1.0, 2.0}, {4, 2},
{0, 0, 1, 1, 1, 1, 0, 0}, 0, {tensor_dtype, {}, 1.0, 2.0}),
".*Check failed: f_min <= 0.*");
}
TEST_F(QuantizedPadV2OpTest, UInt8ZeroNotInQuantizationRange) {
ZeroNotInQuantizationRangeV2<TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8ZeroNotInQuantizationRange) {
ZeroNotInQuantizationRangeV2<TensorType_INT8>();
}
#endif
template <typename integer_type, TensorType tensor_dtype>
void SimpleConstTestV2() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadV2OpConstModel<integer_type, int32_t> m(
{tensor_dtype, {1, 2, 2, 1}, -1.0, 1.0}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0},
{tensor_dtype, {1}, -1.0, 1.0}, {tensor_dtype, {}, -1.0, 1.0});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7});
m.template SetQuantizedPadValue<integer_type>(0);
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{0, 0, 0, 0, 0, -0.8, 0.2, 0, 0, 0.9, 0.7, 0, 0, 0, 0, 0},
-1.0, 1.0)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(QuantizedPadV2OpTest, UInt8SimpleConstTest) {
SimpleConstTestV2<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8SimpleConstTest) {
SimpleConstTestV2<int8_t, TensorType_INT8>();
}
template <typename integer_type, TensorType tensor_dtype>
void SimpleDynamicTestV2() {
PadV2OpDynamicModel<integer_type, int32_t> m(
{tensor_dtype, {1, 2, 2, 1}, -1.0, 1.0}, {4, 2},
{tensor_dtype, {1}, -1.0, 1.0}, {tensor_dtype, {}, -1.0, 1.0});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7});
m.template SetQuantizedPadValue<integer_type>(0);
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{0, 0, 0, 0, 0, -0.8, 0.2, 0, 0, 0.9, 0.7, 0, 0, 0, 0, 0},
-1.0, 1.0)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(QuantizedPadV2OpTest, UInt8SimpleDynamicTest) {
SimpleDynamicTestV2<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8SimpleDynamicTest) {
SimpleDynamicTestV2<int8_t, TensorType_INT8>();
}
template <typename integer_type, TensorType tensor_dtype>
void AdvancedConstTestV2() {
PadV2OpConstModel<integer_type, int32_t> m(
{tensor_dtype, {1, 2, 3, 1}, -1.0, 1.0}, {4, 2}, {0, 0, 0, 2, 1, 3, 0, 0},
{tensor_dtype, {1}, -1.0, 1.0}, {tensor_dtype, {}, -1.0, 1.0});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3});
m.template SetQuantizedPadValue<integer_type>(0);
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{0, -0.8, 0.2, 0.9, 0, 0, 0, 0, 0.7, 0.1, -0.3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
-1.0, 1.0)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(QuantizedPadV2OpTest, UInt8AdvancedConstTest) {
AdvancedConstTestV2<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8AdvancedConstTest) {
AdvancedConstTestV2<int8_t, TensorType_INT8>();
}
template <typename integer_type, TensorType tensor_dtype>
void AdvancedDynamicTestV2() {
PadV2OpDynamicModel<integer_type, int32_t> m(
{tensor_dtype, {1, 2, 3, 1}, -1.0, 1.0}, {4, 2},
{tensor_dtype, {1}, -1.0, 1.0}, {tensor_dtype, {}, -1.0, 1.0});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3});
m.template SetQuantizedPadValue<integer_type>(0);
m.SetPaddings({0, 0, 0, 2, 1, 3, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{0, -0.8, 0.2, 0.9, 0, 0, 0, 0, 0.7, 0.1, -0.3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
-1.0, 1.0)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(QuantizedPadV2OpTest, UInt8AdvancedDynamicTest) {
AdvancedDynamicTestV2<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8AdvancedDynamicTest) {
AdvancedDynamicTestV2<int8_t, TensorType_INT8>();
}
template <typename integer_type, TensorType tensor_dtype>
void SimpleConstValuedTest() {
// Padding is represented as four 2-D lists representing above padding and
// below padding (i.e. {{0, 0}, {1, 1}, {1, 1}, {0, 0}}).
PadV2OpConstModel<integer_type, int32_t> m(
{tensor_dtype, {1, 2, 2, 1}, -1.0, 1.0}, {4, 2}, {0, 0, 1, 1, 1, 1, 0, 0},
{tensor_dtype, {1}, -1.0, 1.0}, {tensor_dtype, {}, -1.0, 1.0});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7});
m.template SetQuantizedPadValue<integer_type>(-0.5);
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{-0.5, -0.5, -0.5, -0.5, -0.5, -0.8, 0.2, -0.5, -0.5, 0.9,
0.7, -0.5, -0.5, -0.5, -0.5, -0.5},
-1.0, 1.0)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(QuantizedPadV2OpTest, UInt8SimpleConstValuedTest) {
SimpleConstValuedTest<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8SimpleConstValuedTest) {
SimpleConstValuedTest<int8_t, TensorType_INT8>();
}
template <typename integer_type, TensorType tensor_dtype>
void SimpleDynamicValuedTest() {
PadV2OpDynamicModel<integer_type, int32_t> m(
{tensor_dtype, {1, 2, 2, 1}, -1.0, 1.0}, {4, 2},
{tensor_dtype, {1}, -1.0, 1.0}, {tensor_dtype, {}, -1.0, 1.0});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7});
m.template SetQuantizedPadValue<integer_type>(-0.5);
m.SetPaddings({0, 0, 1, 1, 1, 1, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{-0.5, -0.5, -0.5, -0.5, -0.5, -0.8, 0.2, -0.5, -0.5, 0.9,
0.7, -0.5, -0.5, -0.5, -0.5, -0.5},
-1.0, 1.0)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 4, 1}));
}
TEST_F(QuantizedPadV2OpTest, UInt8SimpleDynamicValuedTest) {
SimpleDynamicValuedTest<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8SimpleDynamicValuedTest) {
SimpleDynamicValuedTest<int8_t, TensorType_INT8>();
}
template <typename integer_type, TensorType tensor_dtype>
void AdvancedConstValuedTest() {
PadV2OpConstModel<integer_type, int32_t> m(
{tensor_dtype, {1, 2, 3, 1}, -1.0, 1.0}, {4, 2}, {0, 0, 0, 2, 1, 3, 0, 0},
{tensor_dtype, {1}, -1.0, 1.0}, {tensor_dtype, {}, -1.0, 1.0});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3});
m.template SetQuantizedPadValue<integer_type>(-0.5);
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{-0.5, -0.8, 0.2, 0.9, -0.5, -0.5, -0.5, -0.5, 0.7, 0.1,
-0.3, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5},
-1.0, 1.0)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(QuantizedPadV2OpTest, UInt8AdvancedConstValuedTest) {
AdvancedConstValuedTest<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8AdvancedConstValuedTest) {
AdvancedConstValuedTest<int8_t, TensorType_INT8>();
}
template <typename integer_type, TensorType tensor_dtype>
void AdvancedDynamicValuedTest() {
PadV2OpDynamicModel<integer_type, int32_t> m(
{tensor_dtype, {1, 2, 3, 1}, -1.0, 1.0}, {4, 2},
{tensor_dtype, {1}, -1.0, 1.0}, {tensor_dtype, {}, -1.0, 1.0});
m.template SetQuantizedInput<integer_type>({-0.8, 0.2, 0.9, 0.7, 0.1, -0.3});
m.template SetQuantizedPadValue<integer_type>(-0.5);
m.SetPaddings({0, 0, 0, 2, 1, 3, 0, 0});
ASSERT_EQ(m.Invoke(), kTfLiteOk);
EXPECT_THAT(m.template GetDequantizedOutput<integer_type>(),
ElementsAreArray(DequantizedArrayNear(
{-0.5, -0.8, 0.2, 0.9, -0.5, -0.5, -0.5, -0.5, 0.7, 0.1,
-0.3, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5,
-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5},
-1.0, 1.0)));
EXPECT_THAT(m.GetOutputShape(), ElementsAreArray({1, 4, 7, 1}));
}
TEST_F(QuantizedPadV2OpTest, UInt8AdvancedDynamicValuedTest) {
AdvancedDynamicValuedTest<uint8_t, TensorType_UINT8>();
}
TEST_F(QuantizedPadV2OpTest, Int8AdvancedDynamicValuedTest) {
AdvancedDynamicValuedTest<int8_t, TensorType_INT8>();
}
} // namespace
} // namespace tflite