aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow
diff options
context:
space:
mode:
authorGravatar Justin Lebar <jlebar@google.com>2017-04-30 19:48:05 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2017-04-30 21:08:12 -0700
commite370aa6434ce3e17f8fa2a9df690500a8dc03d4e (patch)
treea5f7f1e3ac2e3b87f80a256aed5df37b45df6734 /tensorflow
parentdac34e886862ab92c7ee37e1abf8970608abde74 (diff)
Add ReferenceUtil::ApplyElementwise2D.
Change: 154687238
Diffstat (limited to 'tensorflow')
-rw-r--r--tensorflow/compiler/xla/reference_util.h39
-rw-r--r--tensorflow/compiler/xla/reference_util_test.cc44
2 files changed, 67 insertions, 16 deletions
diff --git a/tensorflow/compiler/xla/reference_util.h b/tensorflow/compiler/xla/reference_util.h
index cdcad08c33..0327612129 100644
--- a/tensorflow/compiler/xla/reference_util.h
+++ b/tensorflow/compiler/xla/reference_util.h
@@ -406,7 +406,46 @@ class ReferenceUtil {
const PaddingConfig& padding,
const float pad);
+ // ApplyElementwise2D(f, x, y, ...) returns the Array2D formed by running
+ // f(x[i], y[i], ...) for each array element in the Array2Ds x, y, ....
+ //
+ // The given arrays must have the same size and element type, and the return
+ // type of f must be implicitly convertible to the arrays' element type.
+ //
+ // Example usage:
+ //
+ // Array2D<float> x, y, z = ...;
+ // std::unique_ptr<Array2D> result = ReferenceUtil::ApplyElementwise2D(
+ // [](float a, float b, float c) { return a * b + c; }, x, y, z);
+ //
+ template <typename F, typename T1, typename... Ts>
+ static std::unique_ptr<Array2D<T1>> ApplyElementwise2D(
+ F&& f, const Array2D<T1>& array1, const Array2D<Ts>&... arrays) {
+ AssertSameSize2D(array1, arrays...);
+ auto result = MakeUnique<Array2D<T1>>(array1.n1(), array1.n1());
+ for (int64 i = 0; i < array1.n1(); ++i) {
+ for (int64 j = 0; j < array1.n2(); ++j) {
+ (*result)(i, j) = f(array1(i, j), arrays(i, j)...);
+ }
+ }
+ return result;
+ }
+
private:
+ template <typename T1, typename T2, typename... Ts>
+ static void AssertSameSize2D(const Array2D<T1>& array1,
+ const Array2D<T2>& array2,
+ const Array2D<Ts>&... arrays) {
+ static_assert(std::is_same<T1, T2>::value, "Args must be same type.");
+ CHECK_EQ(array1.n1(), array2.n1());
+ CHECK_EQ(array1.n2(), array2.n2());
+ AssertSameSize2D(array2, arrays...);
+ }
+
+ // Recursive base case for AssertSameSize2D.
+ template <typename Array1>
+ static void AssertSameSize2D(const Array1& array1) {}
+
TF_DISALLOW_COPY_AND_ASSIGN(ReferenceUtil);
};
diff --git a/tensorflow/compiler/xla/reference_util_test.cc b/tensorflow/compiler/xla/reference_util_test.cc
index b0aa558402..f839ac019d 100644
--- a/tensorflow/compiler/xla/reference_util_test.cc
+++ b/tensorflow/compiler/xla/reference_util_test.cc
@@ -52,9 +52,9 @@ class ReferenceUtilTest : public ::testing::Test {
TEST_F(ReferenceUtilTest, TransposeArray2D) {
auto result = ReferenceUtil::TransposeArray2D(*matrix_);
- auto result_literal = LiteralUtil::CreateR2FromArray2D(*result);
+ auto actual_literal = LiteralUtil::CreateR2FromArray2D(*result);
LiteralTestUtil::ExpectR2Near<float>({{1.f, 4.f}, {2.f, 5.f}, {3.f, 6.f}},
- *result_literal, ErrorSpec(0.0001));
+ *actual_literal, ErrorSpec(0.0001));
}
TEST_F(ReferenceUtilTest, MatmulArray2D) {
@@ -62,32 +62,32 @@ TEST_F(ReferenceUtilTest, MatmulArray2D) {
{7.f, 8.f}, {9.f, 10.f}, {11.f, 12.f},
});
auto result = ReferenceUtil::MatmulArray2D(*matrix_, rhs);
- auto result_literal = LiteralUtil::CreateR2FromArray2D(*result);
+ auto actual_literal = LiteralUtil::CreateR2FromArray2D(*result);
LiteralTestUtil::ExpectR2Near<float>({{58.f, 64.f}, {139.f, 154.f}},
- *result_literal, ErrorSpec(0.0001));
+ *actual_literal, ErrorSpec(0.0001));
}
TEST_F(ReferenceUtilTest, ReduceToColArray2D) {
auto add = [](float lhs, float rhs) { return lhs + rhs; };
auto result = ReferenceUtil::ReduceToColArray2D(*matrix_, 0.0f, add);
- auto result_literal = LiteralUtil::CreateR1<float>(*result);
- LiteralTestUtil::ExpectR1Near<float>({6.f, 15.f}, *result_literal,
+ auto actual_literal = LiteralUtil::CreateR1<float>(*result);
+ LiteralTestUtil::ExpectR1Near<float>({6.f, 15.f}, *actual_literal,
ErrorSpec(0.0001));
}
TEST_F(ReferenceUtilTest, ReduceToRowArray2D) {
auto add = [](float lhs, float rhs) { return lhs + rhs; };
auto result = ReferenceUtil::ReduceToRowArray2D(*matrix_, 0.0f, add);
- auto result_literal = LiteralUtil::CreateR1<float>(*result);
- LiteralTestUtil::ExpectR1Near<float>({5.f, 7.f, 9.f}, *result_literal,
+ auto actual_literal = LiteralUtil::CreateR1<float>(*result);
+ LiteralTestUtil::ExpectR1Near<float>({5.f, 7.f, 9.f}, *actual_literal,
ErrorSpec(0.0001));
}
TEST_F(ReferenceUtilTest, MapArray2D) {
auto identity = [](float value) { return log(exp(value)); };
auto result = ReferenceUtil::MapArray2D(*matrix_, identity);
- auto result_literal = LiteralUtil::CreateR2FromArray2D(*result);
- LiteralTestUtil::ExpectR2NearArray2D(*matrix_, *result_literal,
+ auto actual_literal = LiteralUtil::CreateR2FromArray2D(*result);
+ LiteralTestUtil::ExpectR2NearArray2D(*matrix_, *actual_literal,
ErrorSpec(0.0001));
}
@@ -96,9 +96,9 @@ TEST_F(ReferenceUtilTest, MapWithIndexArray2D) {
return value + row + col;
};
auto result = ReferenceUtil::MapWithIndexArray2D(*matrix_, add_index);
- auto result_literal = LiteralUtil::CreateR2FromArray2D(*result);
+ auto actual_literal = LiteralUtil::CreateR2FromArray2D(*result);
LiteralTestUtil::ExpectR2Near<float>({{1.f, 3.f, 5.f}, {5.f, 7.f, 9.f}},
- *result_literal, ErrorSpec(0.0001));
+ *actual_literal, ErrorSpec(0.0001));
}
TEST_F(ReferenceUtilTest, MapArray4D) {
@@ -107,11 +107,11 @@ TEST_F(ReferenceUtilTest, MapArray4D) {
input->FillWithMultiples(1.0f);
auto multiply_by_two = [](float value) { return 2 * value; };
auto result = ReferenceUtil::MapArray4D(*input, multiply_by_two);
- auto result_literal = LiteralUtil::CreateR4FromArray4D(*result);
+ auto actual_literal = LiteralUtil::CreateR4FromArray4D(*result);
Array4D<float> expected(/*planes=*/2, /*depth=*/3, /*height=*/4, /*width=*/5);
expected.FillWithMultiples(2.0f);
- LiteralTestUtil::ExpectR4NearArray4D(expected, *result_literal,
+ LiteralTestUtil::ExpectR4NearArray4D(expected, *actual_literal,
ErrorSpec(0.0001));
}
@@ -124,11 +124,11 @@ TEST_F(ReferenceUtilTest, MapWithIndexArray4D) {
return value - (3 * 4 * 5 * plane + 4 * 5 * depth + 5 * height + width);
};
auto result = ReferenceUtil::MapWithIndexArray4D(*input, subtract_index);
- auto result_literal = LiteralUtil::CreateR4FromArray4D(*result);
+ auto actual_literal = LiteralUtil::CreateR4FromArray4D(*result);
Array4D<float> expected(/*planes=*/2, /*depth=*/3, /*height=*/4, /*width=*/5);
expected.Fill(0.0f);
- LiteralTestUtil::ExpectR4NearArray4D(expected, *result_literal,
+ LiteralTestUtil::ExpectR4NearArray4D(expected, *actual_literal,
ErrorSpec(0.0001));
}
@@ -302,5 +302,17 @@ TEST_F(ReferenceUtilTest, ConvGeneralDimensionsWithValidPadding) {
ErrorSpec(0.0001));
}
+TEST_F(ReferenceUtilTest, ApplyElementwise2D) {
+ Array2D<float> a({{1, 2}, {3, 4}});
+ Array2D<float> b({{10, 20}, {30, 40}});
+ Array2D<float> c({{100, 200}, {300, 400}});
+
+ auto actual = ReferenceUtil::ApplyElementwise2D(
+ [](float x, float y, float z) { return 100 * x + 10 * y + z; }, a, b, c);
+ auto actual_literal = LiteralUtil::CreateR2FromArray2D(*actual);
+ LiteralTestUtil::ExpectR2Near({{300.f, 600.f}, {900.f, 1200.f}},
+ *actual_literal, ErrorSpec(0.0001));
+}
+
} // namespace
} // namespace xla