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 "gmock/gmock-matchers.h"
18 #include "gtest/gtest.h"
19 #include "tensor_utils.h"
20
21 namespace android {
22 namespace nn {
23 namespace tensor_utils {
24
25 namespace {
26
27 using ::testing::FloatNear;
28 using ::testing::Matcher;
29
ArrayFloatNear(const std::vector<float> & values,float max_abs_error=1.e-6)30 std::vector<Matcher<float>> ArrayFloatNear(const std::vector<float>& values,
31 float max_abs_error=1.e-6) {
32 std::vector<Matcher<float>> matchers;
33 matchers.reserve(values.size());
34 for (const float& v : values) {
35 matchers.emplace_back(FloatNear(v, max_abs_error));
36 }
37 return matchers;
38 }
39
40 } // anonymous namespace
41
TEST(uKernels,ClipTest)42 TEST(uKernels, ClipTest) {
43 constexpr int kVectorSize = 10;
44 constexpr float kAbsLimit = 2.0;
45 static float input[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0,
46 -2.5, 3.0, -3.5, 4.0, -4.5};
47 std::vector<float> output(kVectorSize);
48 ClipVector(input, kVectorSize, kAbsLimit, output.data());
49 EXPECT_THAT(output,
50 ElementsAreArray(ArrayFloatNear(
51 {0.0, -0.5, 1.0, -1.5, 2.0, -2.0, 2.0, -2.0, 2.0, -2.0})));
52 }
53
TEST(uKernels,MatrixBatchVectorMultiplyAccumulateTest)54 TEST(uKernels, MatrixBatchVectorMultiplyAccumulateTest) {
55 constexpr int kRow = 3;
56 constexpr int kCol = 4;
57 constexpr int kBatch = 2;
58 static float matrix[kRow * kCol] = {1.0, 2.0, 3.0, 4.0, //
59 -1.0, -2.0, -3.0, -4.0, //
60 1.0, -2.0, 3.0, -4.0};
61 static float vector[kCol * kBatch] = {1.0, -1.0, 1.0, -1.0, //
62 2.0, -2.0, 2.0, -2.0};
63 std::vector<float> output(kRow * kBatch);
64 std::fill(output.begin(), output.end(), 3.0);
65 MatrixBatchVectorMultiplyAccumulate(matrix, kRow, kCol, vector, kBatch,
66 output.data(), /*result_stride=*/1);
67 EXPECT_THAT(output, ElementsAreArray(ArrayFloatNear({1., 5., 13., //
68 -1., 7., 23.})));
69 }
70
TEST(uKernels,VectorVectorCwiseProductTest)71 TEST(uKernels, VectorVectorCwiseProductTest) {
72 constexpr int kVectorSize = 10;
73 static float input1[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0,
74 -2.5, 3.0, -3.5, 4.0, -4.5};
75 static float input2[kVectorSize] = {0.1, -0.1, 0.1, -0.1, 0.1,
76 -0.1, 0.1, -0.1, 0.1, -0.1};
77 std::vector<float> output(kVectorSize);
78 VectorVectorCwiseProduct(input1, input2, kVectorSize, output.data());
79 EXPECT_THAT(output,
80 ElementsAreArray(ArrayFloatNear(
81 {0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45})));
82 }
83
TEST(uKernels,VectorVectorCwiseProductAccumulateTest)84 TEST(uKernels, VectorVectorCwiseProductAccumulateTest) {
85 constexpr int kVectorSize = 10;
86 static float input1[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0,
87 -2.5, 3.0, -3.5, 4.0, -4.5};
88 static float input2[kVectorSize] = {0.1, -0.1, 0.1, -0.1, 0.1,
89 -0.1, 0.1, -0.1, 0.1, -0.1};
90 std::vector<float> output(kVectorSize);
91 std::fill(output.begin(), output.end(), 1.0);
92 VectorVectorCwiseProductAccumulate(input1, input2, kVectorSize,
93 output.data());
94 EXPECT_THAT(output,
95 ElementsAreArray(ArrayFloatNear(
96 {1.0, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45})));
97 }
98
TEST(uKernels,VectorBatchVectorAssignTest)99 TEST(uKernels, VectorBatchVectorAssignTest) {
100 constexpr int kVectorSize = 5;
101 constexpr int kBatchSize = 3;
102 static float input[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0};
103 std::vector<float> output(kVectorSize * kBatchSize);
104 VectorBatchVectorAssign(input, kVectorSize, kBatchSize, output.data());
105 EXPECT_THAT(output, ElementsAreArray(ArrayFloatNear(
106 {0.0, -0.5, 1.0, -1.5, 2.0, 0.0, -0.5, 1.0, -1.5, 2.0,
107 0.0, -0.5, 1.0, -1.5, 2.0})));
108 }
109
TEST(uKernels,ApplySigmoidToVectorTest)110 TEST(uKernels, ApplySigmoidToVectorTest) {
111 constexpr int kVectorSize = 5;
112 static float input[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0};
113 std::vector<float> output(kVectorSize);
114 ApplySigmoidToVector(input, kVectorSize, output.data());
115 EXPECT_THAT(output, ElementsAreArray(ArrayFloatNear(
116 {0.5, 0.377541, 0.731059, 0.182426, 0.880797})));
117 }
118
TEST(uKernels,ApplyActivationToVectorTest)119 TEST(uKernels, ApplyActivationToVectorTest) {
120 constexpr int kVectorSize = 5;
121 static float input[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0};
122 std::vector<float> output(kVectorSize);
123 ApplyActivationToVector(input, kVectorSize, kActivationRelu, output.data());
124 EXPECT_THAT(output,
125 ElementsAreArray(ArrayFloatNear({0.0, 0.0, 1.0, 0.0, 2.0})));
126
127 ApplyActivationToVector(input, kVectorSize, kActivationTanh, output.data());
128 EXPECT_THAT(output, ElementsAreArray(ArrayFloatNear(
129 {0.0, -0.462117, 0.761594, -0.905148, 0.964028})));
130 }
131
TEST(uKernels,CopyVectorTest)132 TEST(uKernels, CopyVectorTest) {
133 constexpr int kVectorSize = 5;
134 static float input[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0};
135 std::vector<float> output(kVectorSize);
136 CopyVector(input, kVectorSize, output.data());
137 EXPECT_THAT(output,
138 ElementsAreArray(ArrayFloatNear({0.0, -0.5, 1.0, -1.5, 2.0})));
139 }
140
TEST(uKernels,Sub1VectorTest)141 TEST(uKernels, Sub1VectorTest) {
142 constexpr int kVectorSize = 5;
143 static float input[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0};
144 std::vector<float> output(kVectorSize);
145 Sub1Vector(input, kVectorSize, output.data());
146 EXPECT_THAT(output,
147 ElementsAreArray(ArrayFloatNear({1.0, 1.5, 0.0, 2.5, -1.0})));
148 }
149
TEST(uKernels,ZeroVectorTest)150 TEST(uKernels, ZeroVectorTest) {
151 constexpr int kVectorSize = 5;
152 std::vector<float> output(kVectorSize);
153 ZeroVector(output.data(), kVectorSize);
154 EXPECT_THAT(output,
155 ElementsAreArray(ArrayFloatNear({0.0, 0.0, 0.0, 0.0, 0.0})));
156 }
157
TEST(uKernels,BatchVectorBatchVectorDotProductTest)158 TEST(uKernels, BatchVectorBatchVectorDotProductTest) {
159 constexpr int kVectorSize = 5;
160 constexpr int kBatch = 2;
161 static float input1[kVectorSize * kBatch] = {0.0, -0.5, 1.0, -1.5, 2.0,
162 -2.5, 3.0, -3.5, 4.0, -4.5};
163 static float input2[kVectorSize * kBatch] = {0.1, -0.1, 0.1, -0.1, 0.1,
164 -0.1, 0.1, -0.1, 0.1, -0.1};
165 std::vector<float> output(kBatch);
166 BatchVectorBatchVectorDotProduct(input1, input2, kVectorSize, kBatch,
167 output.data(), /*result_stride=*/1);
168 EXPECT_THAT(output, ElementsAreArray(ArrayFloatNear({0.5, 1.75})));
169 }
170
TEST(uKernels,VectorShiftLeftTest)171 TEST(uKernels, VectorShiftLeftTest) {
172 constexpr int kVectorSize = 5;
173 static float input[kVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0};
174 std::vector<float> result(kVectorSize);
175 VectorShiftLeft(input, kVectorSize, 3.0);
176 result.assign(input, input + kVectorSize);
177 EXPECT_THAT(result,
178 ElementsAreArray(ArrayFloatNear({-0.5, 1.0, -1.5, 2.0, 3.0})));
179 }
180
TEST(uKernels,ReductionSumVectorTest)181 TEST(uKernels, ReductionSumVectorTest) {
182 constexpr int kInputVectorSize = 10;
183 constexpr int kOutputVectorSize = 5;
184 constexpr int kReductionSize = 2;
185 static float input[kInputVectorSize] = {0.0, -0.5, 1.0, -1.5, 2.0,
186 0.0, -0.5, 1.0, 1.0, 2.0};
187 std::vector<float> result(kOutputVectorSize);
188 ReductionSumVector(input,
189 /*input_stride=*/1, result.data(), kOutputVectorSize,
190 kReductionSize);
191 EXPECT_THAT(result,
192 ElementsAreArray(ArrayFloatNear({-0.5, -0.5, 2.0, 0.5, 3.0})));
193 }
194
195 } // namespace tensor_utils
196 } // namespace nn
197 } // namespace android
198