• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2018 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 <math.h>
16 #include <stdint.h>
17 
18 #include <vector>
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 #include "tensorflow/lite/kernels/internal/test_util.h"
23 #include "tensorflow/lite/kernels/test_util.h"
24 #include "tensorflow/lite/schema/schema_generated.h"
25 
26 namespace tflite {
27 namespace {
28 
29 using ::testing::ElementsAre;
30 using ::testing::ElementsAreArray;
31 
32 template <typename T>
33 class PowOpModel : public SingleOpModel {
34  public:
PowOpModel(const TensorData & input1,const TensorData & input2,const TensorData & output)35   PowOpModel(const TensorData& input1, const TensorData& input2,
36              const TensorData& output) {
37     input1_ = AddInput(input1);
38     input2_ = AddInput(input2);
39     output_ = AddOutput(output);
40     SetBuiltinOp(BuiltinOperator_POW, BuiltinOptions_PowOptions,
41                  CreatePowOptions(builder_).Union());
42     BuildInterpreter({GetShape(input1_), GetShape(input2_)});
43   }
44 
input1()45   int input1() { return input1_; }
input2()46   int input2() { return input2_; }
47 
GetOutput()48   std::vector<T> GetOutput() { return ExtractVector<T>(output_); }
GetOutputShape()49   std::vector<int> GetOutputShape() { return GetTensorShape(output_); }
50 
51  private:
52   int input1_;
53   int input2_;
54   int output_;
55 };
56 
TEST(PowOpModel,Simple)57 TEST(PowOpModel, Simple) {
58   PowOpModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
59                             {TensorType_INT32, {1, 2, 2, 1}},
60                             {TensorType_INT32, {}});
61   model.PopulateTensor<int32_t>(model.input1(), {12, 2, 7, 8});
62   model.PopulateTensor<int32_t>(model.input2(), {1, 2, 3, 1});
63   ASSERT_EQ(model.Invoke(), kTfLiteOk);
64   EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
65   EXPECT_THAT(model.GetOutput(), ElementsAre(12, 4, 343, 8));
66 }
67 
TEST(PowOpModel,NegativeAndZeroValue)68 TEST(PowOpModel, NegativeAndZeroValue) {
69   PowOpModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
70                             {TensorType_INT32, {1, 2, 2, 1}},
71                             {TensorType_INT32, {}});
72   model.PopulateTensor<int32_t>(model.input1(), {0, 2, -7, 8});
73   model.PopulateTensor<int32_t>(model.input2(), {1, 2, 3, 0});
74   ASSERT_EQ(model.Invoke(), kTfLiteOk);
75   EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
76   EXPECT_THAT(model.GetOutput(), ElementsAre(0, 4, -343, 1));
77 }
78 
TEST(PowOpModel,Float)79 TEST(PowOpModel, Float) {
80   PowOpModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
81                           {TensorType_FLOAT32, {1, 2, 2, 1}},
82                           {TensorType_FLOAT32, {}});
83   model.PopulateTensor<float>(model.input1(), {0.3, 0.4, 0.7, 5.8});
84   model.PopulateTensor<float>(model.input2(), {0.5, 2.7, 3.1, 3.2});
85   ASSERT_EQ(model.Invoke(), kTfLiteOk);
86   EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
87   EXPECT_THAT(model.GetOutput(),
88               ElementsAreArray(ArrayFloatNear(
89                   {0.5477226, 0.08424846, 0.33098164, 277.313}, 1e-3)));
90 }
91 
TEST(PowOpModel,NegativeFloatTest)92 TEST(PowOpModel, NegativeFloatTest) {
93   PowOpModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
94                           {TensorType_FLOAT32, {1, 2, 2, 1}},
95                           {TensorType_FLOAT32, {}});
96   model.PopulateTensor<float>(model.input1(), {0.3, 0.4, 0.7, 5.8});
97   model.PopulateTensor<float>(model.input2(), {0.5, -2.7, 3.1, -3.2});
98   ASSERT_EQ(model.Invoke(), kTfLiteOk);
99   EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
100   EXPECT_THAT(model.GetOutput(),
101               ElementsAreArray(ArrayFloatNear(
102                   {0.5477226, 11.869653, 0.33098164, 0.003606}, 1e-3)));
103 }
104 
TEST(PowOpModel,BroadcastTest)105 TEST(PowOpModel, BroadcastTest) {
106   PowOpModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
107                             {TensorType_INT32, {1}}, {TensorType_INT32, {}});
108   model.PopulateTensor<int32_t>(model.input1(), {12, 2, 7, 8});
109   model.PopulateTensor<int32_t>(model.input2(), {4});
110   ASSERT_EQ(model.Invoke(), kTfLiteOk);
111   EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
112   EXPECT_THAT(model.GetOutput(), ElementsAre(20736, 16, 2401, 4096));
113 }
114 
TEST(PowOpModel,BroadcastFloatTest)115 TEST(PowOpModel, BroadcastFloatTest) {
116   PowOpModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
117                           {TensorType_FLOAT32, {1}}, {TensorType_FLOAT32, {}});
118   model.PopulateTensor<float>(model.input1(), {12, 2, 7, 8});
119   model.PopulateTensor<float>(model.input2(), {4});
120   ASSERT_EQ(model.Invoke(), kTfLiteOk);
121   EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
122   EXPECT_THAT(model.GetOutput(), ElementsAre(20736, 16, 2401, 4096));
123 }
124 
125 template <typename T>
CalculateTrueResults(const std::vector<T> & input_data,T exponent,int flat_size,std::vector<T> * output_data)126 void CalculateTrueResults(const std::vector<T>& input_data, T exponent,
127                           int flat_size, std::vector<T>* output_data) {
128   for (int i = 0; i < flat_size; ++i) {
129     output_data->at(i) = std::pow(input_data[i], exponent);
130   }
131 }
132 
TEST(PowOpModel,FloatSingleIntegerExponentTest)133 TEST(PowOpModel, FloatSingleIntegerExponentTest) {
134   PowOpModel<float> model({TensorType_FLOAT32, {1, 2, 2, 1}},
135                           {TensorType_FLOAT32, {1}}, {TensorType_FLOAT32, {}});
136   const int input_size = 1 * 2 * 2 * 1;
137   for (int i = 1; i < 20; ++i) {
138     std::vector<float> input_data(input_size);
139     for (int index = 0; index < input_size; ++index) {
140       // For exponent is float case, if base < 0, we will result in nan, so
141       // we only populate positive base.
142       input_data[index] = UniformRandomFloat(0, 1.5);
143     }
144     model.PopulateTensor<float>(model.input1(), input_data);
145     float exponent = static_cast<float>(i);
146     // Random deviate exponent, e.g., 1.99999 or 2.00001.
147     exponent += UniformRandomInt(-1, 1) * 1e-5;
148     model.PopulateTensor<float>(model.input2(), {exponent});
149     ASSERT_EQ(model.Invoke(), kTfLiteOk);
150     EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
151     std::vector<float> output_data(input_size);
152     CalculateTrueResults(input_data, exponent, input_size, &output_data);
153     EXPECT_THAT(model.GetOutput(),
154                 ElementsAreArray(ArrayFloatNear(output_data, 1e-2)));
155   }
156 }
157 
TEST(PowOpModel,IntSingleIntegerExponentTest)158 TEST(PowOpModel, IntSingleIntegerExponentTest) {
159   PowOpModel<int32_t> model({TensorType_INT32, {1, 2, 2, 1}},
160                             {TensorType_INT32, {1}}, {TensorType_INT32, {}});
161   const int input_size = 1 * 2 * 2 * 1;
162   for (int i = 1; i < 20; ++i) {
163     std::vector<int32_t> input_data(input_size);
164     for (int index = 0; index < input_size; ++index) {
165       input_data[index] = UniformRandomInt(-2, -2);
166     }
167     model.PopulateTensor<int32_t>(model.input1(), input_data);
168     int exponent = i;
169     model.PopulateTensor<int32_t>(model.input2(), {exponent});
170     ASSERT_EQ(model.Invoke(), kTfLiteOk);
171     EXPECT_THAT(model.GetOutputShape(), ElementsAre(1, 2, 2, 1));
172     std::vector<int32_t> output_data(input_size);
173     CalculateTrueResults(input_data, exponent, input_size, &output_data);
174     EXPECT_THAT(model.GetOutput(), ElementsAreArray(output_data));
175   }
176 }
177 
178 }  // namespace
179 }  // namespace tflite
180