1/*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ActivationFunctor.h"
18#include "Utils.h"
19
20namespace android {
21namespace nn {
22namespace tensor_utils {
23
24float PortableClip(float f, float abs_limit) {
25  float result = (abs_limit < f) ? abs_limit : f;
26  result = (-abs_limit > result) ? -abs_limit : result;
27  return result;
28}
29
30void PortableMatrixBatchVectorMultiplyAccumulate(const float* matrix,
31                                                 int m_rows, int m_cols,
32                                                 const float* vector,
33                                                 int n_batch, float* result,
34                                                 int result_stride) {
35  float* result_in_batch = result;
36  for (int b = 0; b < n_batch; b++) {
37    const float* matrix_ptr = matrix;
38    for (int r = 0; r < m_rows; r++) {
39      const float* vector_in_batch = vector + b * m_cols;
40      for (int c = 0; c < m_cols; c++) {
41        *result_in_batch += *matrix_ptr++ * *vector_in_batch++;
42      }
43      result_in_batch += result_stride;
44    }
45  }
46}
47
48void PortableVectorVectorCwiseProduct(const float* vector1,
49                                      const float* vector2, int v_size,
50                                      float* result) {
51  for (int v = 0; v < v_size; v++) {
52    *result++ = *vector1++ * *vector2++;
53  }
54}
55
56float PortableVectorVectorDotProduct(const float* vector1, const float* vector2,
57                                     int v_size) {
58  float result = 0.0;
59  for (int v = 0; v < v_size; v++) {
60    result += *vector1++ * *vector2++;
61  }
62  return result;
63}
64
65void PortableBatchVectorBatchVectorDotProduct(const float* vector1,
66                                              const float* vector2, int v_size,
67                                              int n_batch, float* result,
68                                              int result_stride) {
69  float* result_ptr = result;
70  const float* vector1_ptr = vector1;
71  const float* vector2_ptr = vector2;
72  for (int b = 0; b < n_batch; b++) {
73    *result_ptr =
74        PortableVectorVectorDotProduct(vector1_ptr, vector2_ptr, v_size);
75    vector1_ptr += v_size;
76    vector2_ptr += v_size;
77    result_ptr += result_stride;
78  }
79}
80
81void PortableVectorVectorCwiseProductAccumulate(const float* vector1,
82                                                const float* vector2,
83                                                int v_size, float* result) {
84  for (int v = 0; v < v_size; v++) {
85    *result++ += *vector1++ * *vector2++;
86  }
87}
88
89void PortableVectorBatchVectorCwiseProductAccumulate(const float* vector,
90                                                     int v_size,
91                                                     const float* batch_vector,
92                                                     int n_batch,
93                                                     float* result) {
94  for (int b = 0; b < n_batch; b++) {
95    for (int v = 0; v < v_size; v++) {
96      *result++ += vector[v] * *batch_vector++;
97    }
98  }
99}
100
101void PortableVectorBatchVectorAssign(const float* vector, int v_size,
102                                     int n_batch, float* batch_vector) {
103  for (int b = 0; b < n_batch; b++) {
104    memcpy(batch_vector + b * v_size, vector, v_size * sizeof(float));
105  }
106}
107
108void PortableApplySigmoidToVector(const float* vector, int v_size,
109                                  float* result) {
110  auto sigmoid_func = ActivationFunctor(kActivationSigmoid);
111  for (int v = 0; v < v_size; v++) {
112    *result++ = (sigmoid_func)(*vector++);
113  }
114}
115
116void PortableApplyActivationToVector(const float* vector, int v_size,
117                                     ActivationFn activation,
118                                     float* result) {
119  auto activation_func = ActivationFunctor(activation);
120  for (int v = 0; v < v_size; v++) {
121    *result++ = (activation_func)(*vector++);
122  }
123}
124
125void PortableCopyVector(const float* vector, int v_size, float* result) {
126  memcpy(result, vector, v_size * sizeof(float));
127}
128
129void PortableSub1Vector(const float* vector, int v_size, float* result) {
130  for (int v = 0; v < v_size; v++) {
131    *result++ = 1.0f - *vector++;
132  }
133}
134
135void PortableZeroVector(float* vector, int v_size) {
136  memset(vector, 0, v_size * sizeof(float));
137}
138
139void PortableClipVector(const float* vector, int v_size, float abs_limit,
140                        float* result) {
141  for (int v = 0; v < v_size; v++) {
142    *result++ = PortableClip(*vector++, abs_limit);
143  }
144}
145
146void PortableVectorShiftLeft(float* vector, int v_size, float shift_value) {
147  nnAssert(v_size > 0);
148  for (int i = 0; i < v_size - 1; i++) {
149    vector[i] = vector[i + 1];
150  }
151  vector[v_size - 1] = shift_value;
152}
153
154void PortableReductionSumVector(const float* input_vector, int input_stride,
155                                float* output_vector, int output_size,
156                                int reduction_size) {
157  const float* input_vector_ptr = input_vector;
158  for (int o = 0; o < output_size; o++) {
159    for (int r = 0; r < reduction_size; r++) {
160      output_vector[o] += *input_vector_ptr;
161      input_vector_ptr += input_stride;
162    }
163  }
164}
165
166}  // namespace tensor_utils
167}  // namespace nn
168}  // namespace android
169