1 /*
2 * SPDX-FileCopyrightText: Copyright 2010-2020, 2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 /* ----------------------------------------------------------------------
20 * Project: CMSIS NN Library
21 * Title: arm_nn_activations_q15.c
22 * Description: Q15 neural network activation function using direct table look-up
23 *
24 * $Date: 8 September 2022
25 * $Revision: V.1.0.0
26 *
27 * Target Processor: Cortex-M cores
28 *
29 * -------------------------------------------------------------------- */
30
31 #include "arm_nn_tables.h"
32 #include "arm_nnfunctions.h"
33
34 /**
35 * @ingroup groupNN
36 */
37
38 /**
39 * @addtogroup Acti
40 * @{
41 */
42
43 /*
44 * @brief Neural network activation function using direct table look-up
45 *
46 * @note Refer header file for details.
47 *
48 */
49
arm_nn_activation_s16(const int16_t * input,int16_t * output,const uint16_t size,const uint16_t left_shift,const arm_nn_activation_type type)50 void arm_nn_activation_s16(const int16_t *input,
51 int16_t *output,
52 const uint16_t size,
53 const uint16_t left_shift,
54 const arm_nn_activation_type type)
55 {
56 uint32_t abs_input_shift, max_saturation;
57 switch (type)
58 {
59 case ARM_SIGMOID:
60 abs_input_shift = 9;
61 max_saturation = 0x7FFF << 10;
62 break;
63 case ARM_TANH:
64 default:
65 abs_input_shift = 8;
66 max_saturation = 0xFFFF << 8;
67 break;
68 }
69
70 // Use the LUT for sigmoid and take into account, that
71 // tanh(x) = 2*sigmoid(2*x) - 1
72 int32_t input_multiplier = ((int32_t)3) << left_shift;
73
74 for (int i = 0; i < size; ++i, input++, output++)
75 {
76 int32_t input_data = ((*input) * input_multiplier);
77
78 uint32_t abs_input_data = input_data > 0 ? input_data : -input_data;
79
80 uint32_t uh = abs_input_data >> abs_input_shift;
81
82 uint32_t result;
83
84 if (uh >= 255)
85 {
86 result = max_saturation;
87 }
88 else
89 {
90 uint32_t ua = sigmoid_table_uint16[uh];
91 uint32_t ub = sigmoid_table_uint16[uh + 1];
92 uint32_t ut;
93 if (type == ARM_SIGMOID)
94 {
95 ut = abs_input_data & 0x1ff;
96 }
97 else
98 {
99 ut = abs_input_data & 0x0ff;
100 }
101 result = (ua << abs_input_shift) + ut * (ub - ua);
102 }
103 if (type == ARM_SIGMOID)
104 {
105 result = (input_data >= 0) ? (result + (1 << 9)) : ((1 << 25) - result + (1 << 9) - 1);
106 result >>= 10;
107 }
108 else
109 {
110 result = (input_data >= 0) ? (result - (1 << 23)) + (1 << 7) : ((-result + (1 << 23)) + (1 << 7) - 1);
111 result >>= 8;
112 }
113 *output = (int16_t)result;
114 }
115 }
116
117 /**
118 * @} end of Acti group
119 */
120