1/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15#include "tensorflow/lite/c/builtin_op_data.h"
16#include "tensorflow/lite/c/common.h"
17#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h"
18#include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
19#include "tensorflow/lite/kernels/internal/tensor.h"
20#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
21#include "tensorflow/lite/kernels/internal/types.h"
22#include "tensorflow/lite/kernels/kernel_util.h"
23
24namespace tflite {
25namespace ops {
26namespace builtin {
27namespace local_response_norm {
28
29// This file has two implementation of LocalResponseNorm.
30enum KernelType {
31 kReference,
32 kGenericOptimized,
33};
34
35constexpr int kInputTensor = 0;
36constexpr int kOutputTensor = 0;
37
38TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
39 TF_LITE_ENSURE_EQ(context, NumInputs(node), 1);
40 TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);
41
42 const TfLiteTensor* input;
43 TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, kInputTensor, &input));
44 TfLiteTensor* output;
45 TF_LITE_ENSURE_OK(context,
46 GetOutputSafe(context, node, kOutputTensor, &output));
47
48 TF_LITE_ENSURE_EQ(context, NumDimensions(input), 4);
49
50 TF_LITE_ENSURE_TYPES_EQ(context, output->type, kTfLiteFloat32);
51 TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type);
52
53 TfLiteIntArray* output_size = TfLiteIntArrayCreate(4);
54 output_size->data[0] = input->dims->data[0];
55 output_size->data[1] = input->dims->data[1];
56 output_size->data[2] = input->dims->data[2];
57 output_size->data[3] = input->dims->data[3];
58
59 return context->ResizeTensor(context, output, output_size);
60}
61
62template <KernelType kernel_type>
63TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
64 auto* params =
65 reinterpret_cast<TfLiteLocalResponseNormParams*>(node->builtin_data);
66
67 const TfLiteTensor* input;
68 TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, kInputTensor, &input));
69 TfLiteTensor* output;
70 TF_LITE_ENSURE_OK(context,
71 GetOutputSafe(context, node, kOutputTensor, &output));
72
73 if (output->type == kTfLiteFloat32) {
74#define TF_LITE_LOCAL_RESPONSE_NORM(type) \
75 tflite::LocalResponseNormalizationParams op_params; \
76 op_params.range = params->radius; \
77 op_params.bias = params->bias; \
78 op_params.alpha = params->alpha; \
79 op_params.beta = params->beta; \
80 type::LocalResponseNormalization( \
81 op_params, GetTensorShape(input), GetTensorData<float>(input), \
82 GetTensorShape(output), GetTensorData<float>(output))
83 if (kernel_type == kReference) {
84 TF_LITE_LOCAL_RESPONSE_NORM(reference_ops);
85 }
86 if (kernel_type == kGenericOptimized) {
87 TF_LITE_LOCAL_RESPONSE_NORM(optimized_ops);
88 }
89#undef TF_LITE_LOCAL_RESPONSE_NORM
90 } else {
91 TF_LITE_KERNEL_LOG(context, "Output type is %d, requires float.",
92 output->type);
93 return kTfLiteError;
94 }
95
96 return kTfLiteOk;
97}
98
99} // namespace local_response_norm
100
101TfLiteRegistration* Register_LOCAL_RESPONSE_NORM_REF() {
102 static TfLiteRegistration r = {
103 nullptr, nullptr, local_response_norm::Prepare,
104 local_response_norm::Eval<local_response_norm::kReference>};
105 return &r;
106}
107
108TfLiteRegistration* Register_LOCAL_RESPONSE_NORM_GENERIC_OPT() {
109 static TfLiteRegistration r = {
110 nullptr, nullptr, local_response_norm::Prepare,
111 local_response_norm::Eval<local_response_norm::kGenericOptimized>};
112 return &r;
113}
114
115TfLiteRegistration* Register_LOCAL_RESPONSE_NORMALIZATION() {
116 return Register_LOCAL_RESPONSE_NORM_GENERIC_OPT();
117}
118
119} // namespace builtin
120} // namespace ops
121} // namespace tflite
122