1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 #include <string.h> 16 17 #include "tensorflow/contrib/lite/builtin_op_data.h" 18 #include "tensorflow/contrib/lite/kernels/activation_functor.h" 19 #include "tensorflow/contrib/lite/kernels/op_macros.h" 20 21 namespace tflite { 22 namespace tensor_utils { 23 24 float 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 30 void 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 48 void 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 56 float 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 65 void 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 81 void 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 89 void 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 101 void 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 108 void PortableApplySigmoidToVector(const float* vector, int v_size, 109 float* result) { 110 auto sigmoid_func = ActivationFunctor(kTfLiteActSigmoid); 111 for (int v = 0; v < v_size; v++) { 112 *result++ = (sigmoid_func)(*vector++); 113 } 114 } 115 116 void PortableApplyActivationToVector(const float* vector, int v_size, 117 TfLiteFusedActivation 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 125 void PortableCopyVector(const float* vector, int v_size, float* result) { 126 memcpy(result, vector, v_size * sizeof(float)); 127 } 128 129 void 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 135 void PortableZeroVector(float* vector, int v_size) { 136 memset(vector, 0, v_size * sizeof(float)); 137 } 138 139 void 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 146 void PortableVectorShiftLeft(float* vector, int v_size, float shift_value) { 147 TF_LITE_ASSERT(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 154 void PortableReductionSumVector(const float* input_vector, float* output_vector, 155 int output_size, int reduction_size) { 156 const float* input_vector_ptr = input_vector; 157 for (int o = 0; o < output_size; o++) { 158 for (int r = 0; r < reduction_size; r++) { 159 output_vector[o] += *input_vector_ptr++; 160 } 161 } 162 } 163 164 } // namespace tensor_utils 165 } // namespace tflite 166