1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations 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 
24 namespace tflite {
25 namespace ops {
26 namespace builtin {
27 namespace local_response_norm {
28 
29 // This file has two implementation of LocalResponseNorm.
30 enum KernelType {
31   kReference,
32   kGenericOptimized,
33 };
34 
35 constexpr int kInputTensor = 0;
36 constexpr int kOutputTensor = 0;
37 
Prepare(TfLiteContext * context,TfLiteNode * node)38 TfLiteStatus 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 
62 template <KernelType kernel_type>
Eval(TfLiteContext * context,TfLiteNode * node)63 TfLiteStatus 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     context->ReportError(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 
Register_LOCAL_RESPONSE_NORM_REF()101 TfLiteRegistration* 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 
Register_LOCAL_RESPONSE_NORM_GENERIC_OPT()108 TfLiteRegistration* 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 
Register_LOCAL_RESPONSE_NORMALIZATION()115 TfLiteRegistration* Register_LOCAL_RESPONSE_NORMALIZATION() {
116   return Register_LOCAL_RESPONSE_NORM_GENERIC_OPT();
117 }
118 
119 }  // namespace builtin
120 }  // namespace ops
121 }  // namespace tflite
122