ONE - On-device Neural Engine
Loading...
Searching...
No Matches
Comparison.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef __NNFW_CKER_COMPARISON_H__
19#define __NNFW_CKER_COMPARISON_H__
20
21#include "cker/Shape.h"
22#include "cker/Types.h"
23#include "cker/Utils.h"
24
25namespace nnfw
26{
27namespace cker
28{
29
30template <typename T> inline bool EqualFn(T lhs, T rhs) { return lhs == rhs; }
31template <typename T> inline bool NotEqualFn(T lhs, T rhs) { return lhs != rhs; }
32template <typename T> inline bool GreaterFn(T lhs, T rhs) { return lhs > rhs; }
33template <typename T> inline bool GreaterEqualFn(T lhs, T rhs) { return lhs >= rhs; }
34template <typename T> inline bool LessFn(T lhs, T rhs) { return lhs < rhs; }
35template <typename T> inline bool LessEqualFn(T lhs, T rhs) { return lhs <= rhs; }
36
37template <typename T> using ComparisonFn = bool (*)(T, T);
38
39template <typename T, ComparisonFn<T> F>
40inline void ComparisonImpl(const Shape &input1_shape, const T *input1_data,
41 const Shape &input2_shape, const T *input2_data,
42 const Shape &output_shape, bool *output_data)
43{
44 const int64_t flatsize = // number of data....
45 MatchingFlatSize(input1_shape, input2_shape, output_shape);
46 for (int64_t i = 0; i < flatsize; ++i)
47 {
48 output_data[i] = F(input1_data[i], input2_data[i]);
49 }
50}
51
52template <ComparisonFn<float> F>
53inline void Comparison(const Shape &input1_shape, const float *input1_data,
54 const Shape &input2_shape, const float *input2_data,
55 const Shape &output_shape, bool *output_data)
56{
57 ComparisonImpl<float, F>(input1_shape, input1_data, input2_shape, input2_data, output_shape,
58 output_data);
59}
60
61template <typename T, ComparisonFn<int32_t> F>
62inline void ComparisonWithScaling(ComparisonParams &params, const Shape &input1_shape,
63 const T *input1_data, const Shape &input2_shape,
64 const T *input2_data, const Shape &output_shape,
65 bool *output_data)
66{
67 int left_shift = params.left_shift;
68 int32_t input1_offset = params.input1_offset;
69 int32_t input1_multiplier = params.input1_multiplier;
70 int input1_shift = params.input1_shift;
71 int32_t input2_offset = params.input2_offset;
72 int32_t input2_multiplier = params.input2_multiplier;
73 int input2_shift = params.input2_shift;
74 const int64_t flatsize = MatchingFlatSize(input1_shape, input2_shape, output_shape);
75 for (int64_t i = 0; i < flatsize; ++i)
76 {
77 const int32_t input1_val = input1_offset + input1_data[i];
78 const int32_t input2_val = input2_offset + input2_data[i];
79 const int32_t shifted_input1_val = input1_val * (1 << left_shift);
80 const int32_t shifted_input2_val = input2_val * (1 << left_shift);
81 const int32_t scaled_input1_val = MultiplyByQuantizedMultiplierSmallerThanOneExp(
82 shifted_input1_val, input1_multiplier, input1_shift);
83 const int32_t scaled_input2_val = MultiplyByQuantizedMultiplierSmallerThanOneExp(
84 shifted_input2_val, input2_multiplier, input2_shift);
85 output_data[i] = F(scaled_input1_val, scaled_input2_val);
86 }
87}
88
89template <typename T, ComparisonFn<T> F>
90inline void
91BroadcastComparison4DSlowImpl(const Shape &unextended_input1_shape, const T *input1_data,
92 const Shape &unextended_input2_shape, const T *input2_data,
93 const Shape &unextended_output_shape, bool *output_data)
94{
95 assert(unextended_input1_shape.DimensionsCount() <= 4);
96 assert(unextended_input2_shape.DimensionsCount() <= 4);
97 assert(unextended_output_shape.DimensionsCount() <= 4);
98 const Shape output_shape = Shape::ExtendedShape(4, unextended_output_shape);
99
102 NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, unextended_input2_shape, &desc1,
103 &desc2);
104
105 for (int b = 0; b < output_shape.Dims(0); ++b)
106 {
107 for (int y = 0; y < output_shape.Dims(1); ++y)
108 {
109 for (int x = 0; x < output_shape.Dims(2); ++x)
110 {
111 for (int c = 0; c < output_shape.Dims(3); ++c)
112 {
113 output_data[Offset(output_shape, b, y, x, c)] =
114 F(input1_data[SubscriptToIndex(desc1, b, y, x, c)],
115 input2_data[SubscriptToIndex(desc2, b, y, x, c)]);
116 }
117 }
118 }
119 }
120}
121
122template <typename T, ComparisonFn<T> F>
123inline void BroadcastComparison4DSlow(const Shape &input1_shape, const T *input1_data,
124 const Shape &input2_shape, const T *input2_data,
125 const Shape &output_shape, bool *output_data)
126{
127 BroadcastComparison4DSlowImpl<T, F>(input1_shape, input1_data, input2_shape, input2_data,
128 output_shape, output_data);
129}
130
131template <typename T, ComparisonFn<int32_t> F>
133 const Shape &input1_shape, const T *input1_data,
134 const Shape &input2_shape, const T *input2_data,
135 const Shape &output_shape, bool *output_data)
136{
137 assert(input1_shape.DimensionsCount() <= 4);
138 assert(input2_shape.DimensionsCount() <= 4);
139 assert(output_shape.DimensionsCount() <= 4);
140
141 int left_shift = params.left_shift;
142 int32_t input1_offset = params.input1_offset;
143 int32_t input1_multiplier = params.input1_multiplier;
144 int input1_shift = params.input1_shift;
145 int32_t input2_offset = params.input2_offset;
146 int32_t input2_multiplier = params.input2_multiplier;
147 int input2_shift = params.input2_shift;
148
151 NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
152
153 for (int b = 0; b < output_shape.Dims(0); ++b)
154 {
155 for (int y = 0; y < output_shape.Dims(1); ++y)
156 {
157 for (int x = 0; x < output_shape.Dims(2); ++x)
158 {
159 for (int c = 0; c < output_shape.Dims(3); ++c)
160 {
161 const int32_t input1_val =
162 input1_offset + input1_data[SubscriptToIndex(desc1, b, y, x, c)];
163 const int32_t input2_val =
164 input2_offset + input2_data[SubscriptToIndex(desc2, b, y, x, c)];
165 const int32_t shifted_input1_val = input1_val * (1 << left_shift);
166 const int32_t shifted_input2_val = input2_val * (1 << left_shift);
167 const int32_t scaled_input1_val = MultiplyByQuantizedMultiplierSmallerThanOneExp(
168 shifted_input1_val, input1_multiplier, input1_shift);
169 const int32_t scaled_input2_val = MultiplyByQuantizedMultiplierSmallerThanOneExp(
170 shifted_input2_val, input2_multiplier, input2_shift);
171 output_data[Offset(output_shape, b, y, x, c)] = F(scaled_input1_val, scaled_input2_val);
172 }
173 }
174 }
175 }
176}
177
178#define TFLITE_COMPARISON_OP(name) \
179 template <typename T> \
180 inline void name(const Shape &input1_shape, const T *input1_data, const Shape &input2_shape, \
181 const T *input2_data, const Shape &output_shape, bool *output_data) \
182 { \
183 Comparison<name##Fn>(input1_shape, input1_data, input2_shape, input2_data, output_shape, \
184 output_data); \
185 } \
186 template <typename T> \
187 inline void name##NoScaling(const Shape &input1_shape, const T *input1_data, \
188 const Shape &input2_shape, const T *input2_data, \
189 const Shape &output_shape, bool *output_data) \
190 { \
191 ComparisonImpl<T, name##Fn>(input1_shape, input1_data, input2_shape, input2_data, \
192 output_shape, output_data); \
193 } \
194 template <typename T> \
195 inline void name##WithScaling( \
196 ComparisonParams &params, const Shape &input1_shape, const T *input1_data, \
197 const Shape &input2_shape, const T *input2_data, const Shape &output_shape, bool *output_data) \
198 { \
199 ComparisonWithScaling<T, name##Fn>(params, input1_shape, input1_data, input2_shape, \
200 input2_data, output_shape, output_data); \
201 } \
202 template <typename T> \
203 inline void Broadcast4DSlow##name##NoScaling(const Shape &input1_shape, const T *input1_data, \
204 const Shape &input2_shape, const T *input2_data, \
205 const Shape &output_shape, bool *output_data) \
206 { \
207 BroadcastComparison4DSlowImpl<T, name##Fn>(input1_shape, input1_data, input2_shape, \
208 input2_data, output_shape, output_data); \
209 } \
210 template <typename T> \
211 inline void Broadcast4DSlow##name(const Shape &input1_shape, const T *input1_data, \
212 const Shape &input2_shape, const T *input2_data, \
213 const Shape &output_shape, bool *output_data) \
214 { \
215 BroadcastComparison4DSlow<T, name##Fn>(input1_shape, input1_data, input2_shape, input2_data, \
216 output_shape, output_data); \
217 } \
218 template <typename T> \
219 inline void Broadcast4DSlow##name##WithScaling( \
220 ComparisonParams &params, const Shape &input1_shape, const T *input1_data, \
221 const Shape &input2_shape, const T *input2_data, const Shape &output_shape, bool *output_data) \
222 { \
223 BroadcastComparison4DSlowWithScaling<T, name##Fn>( \
224 params, input1_shape, input1_data, input2_shape, input2_data, output_shape, output_data); \
225 }
226
233#undef TFLITE_COMPARISON_OP
234
235} // namespace cker
236} // namespace nnfw
237
238#endif
int32_t DimensionsCount() const
Definition Shape.h:91
#define TFLITE_COMPARISON_OP(name)
Definition Comparison.h:178
NdArrayDesc< 4 > desc1
const luci_interpreter::RuntimeShape output_shape
NdArrayDesc< 4 > desc2
void Comparison(const Shape &input1_shape, const float *input1_data, const Shape &input2_shape, const float *input2_data, const Shape &output_shape, bool *output_data)
Definition Comparison.h:53
bool LessFn(T lhs, T rhs)
Definition Comparison.h:34
bool EqualFn(T lhs, T rhs)
Definition Comparison.h:30
void BroadcastComparison4DSlowWithScaling(ComparisonParams &params, const Shape &input1_shape, const T *input1_data, const Shape &input2_shape, const T *input2_data, const Shape &output_shape, bool *output_data)
Definition Comparison.h:132
int Offset(const Shape &shape, int i0, int i1, int i2, int i3)
Definition Shape.h:237
bool(*)(T, T) ComparisonFn
Definition Comparison.h:37
void NdArrayDescsForElementwiseBroadcast(const Shape &input0_shape, const Shape &input1_shape, NdArrayDesc< N > *desc0_out, NdArrayDesc< N > *desc1_out)
Definition Utils.h:290
bool GreaterEqualFn(T lhs, T rhs)
Definition Comparison.h:33
void ComparisonWithScaling(ComparisonParams &params, const Shape &input1_shape, const T *input1_data, const Shape &input2_shape, const T *input2_data, const Shape &output_shape, bool *output_data)
Definition Comparison.h:62
void ComparisonImpl(const Shape &input1_shape, const T *input1_data, const Shape &input2_shape, const T *input2_data, const Shape &output_shape, bool *output_data)
Definition Comparison.h:40
bool LessEqualFn(T lhs, T rhs)
Definition Comparison.h:35
int MatchingFlatSize(const Shape &shape, Ts... check_shapes)
Definition Shape.h:297
int SubscriptToIndex(const NdArrayDesc< 4 > &desc, int i0, int i1, int i2, int i3)
Definition Utils.h:255
void BroadcastComparison4DSlowImpl(const Shape &unextended_input1_shape, const T *input1_data, const Shape &unextended_input2_shape, const T *input2_data, const Shape &unextended_output_shape, bool *output_data)
Definition Comparison.h:91
void BroadcastComparison4DSlow(const Shape &input1_shape, const T *input1_data, const Shape &input2_shape, const T *input2_data, const Shape &output_shape, bool *output_data)
Definition Comparison.h:123
bool NotEqualFn(T lhs, T rhs)
Definition Comparison.h:31
bool GreaterFn(T lhs, T rhs)
Definition Comparison.h:32
int32_t MultiplyByQuantizedMultiplierSmallerThanOneExp(int32_t x, int32_t quantized_multiplier, int left_shift)
Definition Utils.h:111
Definition topk_v2.h:30