tflite-micro/tensorflow/lite/micro/kernels/decode_test.cc
Esun Kim 183da3e302
Typo in code (#3447)
* Typo in code

* Format
2026-02-11 20:34:42 +00:00

247 lines
9.2 KiB
C++

/* Copyright 2025 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 <array>
#include <cstdint>
#include <initializer_list>
#include "tensorflow/lite/core/c/common.h"
#include "tensorflow/lite/micro/kernels/decode_state.h"
#include "tensorflow/lite/micro/kernels/decode_test_helpers.h"
#include "tensorflow/lite/micro/testing/micro_test_v2.h"
namespace {
//
// LUT test data
//
constexpr int kBitWidthLUT = 2;
constexpr int8_t kAncillaryDataLUT0[] = {1, 2, 3, 4};
constexpr int16_t kAncillaryDataLUT1[] = {5, 6, 7, 8};
constexpr uint8_t kDcmLUT0[tflite::DecodeState::kDcmSizeInBytes] = {
tflite::DecodeState::kDcmTypeLUT, // type: LUT
1, // DCM version: 1
0, // reserved
0, // reserved
1, // LUT version: 1
kBitWidthLUT, // Parameters: bit-width 2
std::size(kAncillaryDataLUT0), // channel stride
};
constexpr uint8_t kDcmLUT1[tflite::DecodeState::kDcmSizeInBytes] = {
tflite::DecodeState::kDcmTypeLUT, // type: LUT
1, // DCM version: 1
0, // reserved
0, // reserved
1, // LUT version: 1
kBitWidthLUT, // Parameters: bit-width 2
std::size(kAncillaryDataLUT1), // channel stride
};
// Align the tensor data the same as a Buffer in the TfLite schema.
// The encoded bitstring consists of fixed bit width groups (indices), each
// group representing an offset into the <value_table> (kAncillaryDataLUTx). The
// bitstring is in big-endian byte order with the most significant bit first. A
// bitstring is padded on the end, to the next byte boundary, with zero bits.
alignas(16) const uint8_t kEncodedLUT[] = {0x1B, 0xE4};
// Tensor shapes as TfLiteIntArray
constexpr int kOutputShapeLUT[] = {3, 1, 2, 4};
constexpr int kEncodedShapeLUT[] = {1, sizeof(kEncodedLUT)};
constexpr int8_t kExpectLUT0[] = {1, 2, 3, 4, 4, 3, 2, 1};
constexpr int16_t kExpectLUT1[] = {5, 6, 7, 8, 8, 7, 6, 5};
} // namespace
using tflite::testing::AncillaryData;
using tflite::testing::TensorInDatum;
using tflite::testing::TensorOutDatum;
TEST(DecodeTest, DecodeSingleTensorLUT) {
// Align the tensor data the same as a Buffer in the TfLite schema
alignas(16) int8_t output_data[std::size(kExpectLUT0)] = {};
alignas(16) const AncillaryData<int8_t, std::size(kAncillaryDataLUT0)>
kAncillaryData = {{kDcmLUT0}, {kAncillaryDataLUT0}};
constexpr int kAncillaryShapeLUT[] = {1, sizeof(kAncillaryData)};
const TfLiteIntArray* const encoded_dims =
tflite::testing::IntArrayFromInts(kEncodedShapeLUT);
static const TensorInDatum tid_encode = {
kEncodedLUT,
*encoded_dims,
};
static constexpr std::initializer_list<const TensorInDatum*> encodes = {
&tid_encode,
};
const TfLiteIntArray* const ancillary_dims =
tflite::testing::IntArrayFromInts(kAncillaryShapeLUT);
static const TensorInDatum tid_ancillary = {
&kAncillaryData,
*ancillary_dims,
};
static constexpr std::initializer_list<const TensorInDatum*> ancillaries = {
&tid_ancillary};
const TfLiteIntArray* const output_dims =
tflite::testing::IntArrayFromInts(kOutputShapeLUT);
constexpr int kOutputZeroPointsData[] = {0};
const TfLiteIntArray* const kOutputZeroPoints =
tflite::testing::IntArrayFromInts(kOutputZeroPointsData);
const TfLiteFloatArray kOutputScales = {kOutputZeroPoints->size};
static const TensorOutDatum tod = {
output_data, *output_dims, kTfLiteInt8, kOutputScales, *kOutputZeroPoints,
0, {},
};
static constexpr std::initializer_list<const TensorOutDatum*> outputs = {
&tod};
const std::initializer_list<const void*> expected = {kExpectLUT0};
tflite::testing::TestDecode<encodes.size() + ancillaries.size(),
outputs.size()>(
encodes, ancillaries, outputs, expected, tflite::Register_DECODE());
}
TEST(DecodeTest, DecodeTwoTensorsLUT) {
// Align the tensor data the same as a Buffer in the TfLite schema
alignas(16) int8_t output_data0[std::size(kExpectLUT0)] = {};
alignas(16) int16_t output_data1[std::size(kExpectLUT1)] = {};
alignas(16) const AncillaryData<int8_t, std::size(kAncillaryDataLUT0)>
kAncillaryData0 = {{kDcmLUT0}, {kAncillaryDataLUT0}};
alignas(16) const AncillaryData<int16_t, std::size(kAncillaryDataLUT1)>
kAncillaryData1 = {{kDcmLUT1}, {kAncillaryDataLUT1}};
constexpr int kAncillaryShapeLUT0[] = {1, sizeof(kAncillaryData0)};
constexpr int kAncillaryShapeLUT1[] = {1, sizeof(kAncillaryData1)};
const TfLiteIntArray* const encoded_dims =
tflite::testing::IntArrayFromInts(kEncodedShapeLUT);
static const TensorInDatum tid_encode0 = {
kEncodedLUT,
*encoded_dims,
};
static const TensorInDatum tid_encode1 = {
kEncodedLUT,
*encoded_dims,
};
static constexpr std::initializer_list<const TensorInDatum*> encodes = {
&tid_encode0, &tid_encode1};
const TfLiteIntArray* const ancillary_dims0 =
tflite::testing::IntArrayFromInts(kAncillaryShapeLUT0);
static const TensorInDatum tid_ancillary0 = {
&kAncillaryData0,
*ancillary_dims0,
};
const TfLiteIntArray* const ancillary_dims1 =
tflite::testing::IntArrayFromInts(kAncillaryShapeLUT1);
static const TensorInDatum tid_ancillary1 = {
&kAncillaryData1,
*ancillary_dims1,
};
static constexpr std::initializer_list<const TensorInDatum*> ancillaries = {
&tid_ancillary0, &tid_ancillary1};
const TfLiteIntArray* const output_dims =
tflite::testing::IntArrayFromInts(kOutputShapeLUT);
constexpr int kOutputZeroPointsData[] = {1, 0};
const TfLiteIntArray* const kOutputZeroPoints =
tflite::testing::IntArrayFromInts(kOutputZeroPointsData);
const TfLiteFloatArray kOutputScales = {kOutputZeroPoints->size};
static const TensorOutDatum tod0 = {
output_data0,
*output_dims,
kTfLiteInt8,
kOutputScales,
*kOutputZeroPoints,
0,
{},
};
static const TensorOutDatum tod1 = {
output_data1,
*output_dims,
kTfLiteInt16,
kOutputScales,
*kOutputZeroPoints,
0,
{},
};
static constexpr std::initializer_list<const TensorOutDatum*> outputs = {
&tod0, &tod1};
const std::initializer_list<const void*> expected = {kExpectLUT0,
kExpectLUT1};
tflite::testing::TestDecode<encodes.size() + ancillaries.size(),
outputs.size()>(
encodes, ancillaries, outputs, expected, tflite::Register_DECODE());
}
TEST(DecodeTest, DecodeWithAltDecompressionMemory) {
// Align the tensor data the same as a Buffer in the TfLite schema
alignas(16) int8_t output_data[std::size(kExpectLUT0)] = {};
alignas(16) const AncillaryData<int8_t, std::size(kAncillaryDataLUT0)>
kAncillaryData = {{kDcmLUT0}, {kAncillaryDataLUT0}};
constexpr int kAncillaryShapeLUT[] = {1, sizeof(kAncillaryData)};
const TfLiteIntArray* const encoded_dims =
tflite::testing::IntArrayFromInts(kEncodedShapeLUT);
static const TensorInDatum tid_encode = {
kEncodedLUT,
*encoded_dims,
};
static constexpr std::initializer_list<const TensorInDatum*> encodes = {
&tid_encode,
};
const TfLiteIntArray* const ancillary_dims =
tflite::testing::IntArrayFromInts(kAncillaryShapeLUT);
static const TensorInDatum tid_ancillary = {
&kAncillaryData,
*ancillary_dims,
};
static constexpr std::initializer_list<const TensorInDatum*> ancillaries = {
&tid_ancillary};
const TfLiteIntArray* const output_dims =
tflite::testing::IntArrayFromInts(kOutputShapeLUT);
constexpr int kOutputZeroPointsData[] = {0};
const TfLiteIntArray* const kOutputZeroPoints =
tflite::testing::IntArrayFromInts(kOutputZeroPointsData);
const TfLiteFloatArray kOutputScales = {kOutputZeroPoints->size};
static const TensorOutDatum tod = {
nullptr, // using alternate decompression memory
*output_dims, kTfLiteInt8, kOutputScales, *kOutputZeroPoints, 0, {},
};
static constexpr std::initializer_list<const TensorOutDatum*> outputs = {
&tod};
const std::initializer_list<const void*> expected = {kExpectLUT0};
std::initializer_list<tflite::MicroContext::AlternateMemoryRegion> amr = {
{output_data, sizeof(output_data)}};
tflite::testing::TestDecode<encodes.size() + ancillaries.size(),
outputs.size()>(
encodes, ancillaries, outputs, expected, tflite::Register_DECODE(), &amr);
}
TF_LITE_MICRO_TESTS_MAIN