Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / onert-micro / luci-interpreter / pal / common / PALSoftmax.h
1 /*
2  * Copyright (c) 2021 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 LUCI_INTERPRETER_PAL_SOFTMAX_COMMON_H
19 #define LUCI_INTERPRETER_PAL_SOFTMAX_COMMON_H
20
21 namespace luci_interpreter_pal
22 {
23 namespace
24 {
25
26 inline int flatSizeSkipDim(const luci_interpreter::RuntimeShape &shape, int skip_dim)
27 {
28   const int dims_count = shape.dimensionsCount();
29   const auto *dims_data = shape.dimsData();
30   int flat_size = 1;
31   for (int i = 0; i < dims_count; ++i)
32   {
33     flat_size *= (i == skip_dim) ? 1 : dims_data[i];
34   }
35   return flat_size;
36 }
37
38 } // namespace
39
40 inline void Softmax(const double beta, const luci_interpreter::RuntimeShape &input_shape,
41                     const float *input_data, float *output_data)
42 {
43   const int trailing_dim = input_shape.dimensionsCount() - 1;
44   const int outer_size = flatSizeSkipDim(input_shape, trailing_dim);
45
46   const int depth = input_shape.dims(trailing_dim);
47
48   for (int i = 0; i < outer_size; ++i)
49   {
50     // Find max element value which we'll use to ensure numerical stability
51     // taking advantage of the following equality:
52     // exp(x[i])/sum(exp(x[i])) == exp(x[i]+C)/sum(exp(x[i]+C))
53     float max = std::numeric_limits<float>::lowest();
54     for (int c = 0; c < depth; ++c)
55     {
56       max = std::max(max, input_data[i * depth + c]);
57     }
58
59     // Compute sum.
60     float sum = 0.f;
61     for (int c = 0; c < depth; ++c)
62     {
63       const float exp_c = std::exp((input_data[i * depth + c] - max) * static_cast<float>(beta));
64       output_data[i * depth + c] = exp_c;
65       sum += exp_c;
66     }
67
68     // Compute result.
69     for (int c = 0; c < depth; ++c)
70     {
71       output_data[i * depth + c] = output_data[i * depth + c] / sum;
72     }
73   }
74 }
75
76 } // namespace luci_interpreter_pal
77
78 #endif // LUCI_INTERPRETER_PAL_SOFTMAX_COMMON_H