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