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
16 #include "tensorflow/compiler/xla/util.h"
17
18 #include <limits>
19 #include <list>
20
21 #include "tensorflow/compiler/xla/test.h"
22 #include "tensorflow/compiler/xla/types.h"
23
24 namespace xla {
25 namespace {
26
27 // Verifies that, even with a different number of leading spaces, the
28 // Reindent routine turns them into a uniform number of leading spaces.
29 //
30 // Also throws in some trailing whitespace on the original to show it is
31 // removed.
TEST(UtilTest,ReindentsDifferentNumberOfLeadingSpacesUniformly)32 TEST(UtilTest, ReindentsDifferentNumberOfLeadingSpacesUniformly) {
33 std::string original = R"( hello there
34 world)";
35 std::string got = Reindent(original, " ");
36 std::string want = R"( hello there
37 world)";
38 EXPECT_EQ(want, got);
39 }
40
TEST(UtilTest,HumanReadableNumFlopsExample)41 TEST(UtilTest, HumanReadableNumFlopsExample) {
42 ASSERT_EQ("1.00GFLOP/s", HumanReadableNumFlops(1e9, 1e9));
43 }
44
TEST(UtilTest,CommaSeparatedString)45 TEST(UtilTest, CommaSeparatedString) {
46 EXPECT_EQ(CommaSeparatedString({}), "");
47 EXPECT_EQ(CommaSeparatedString({"hello world"}), "hello world");
48 EXPECT_EQ(CommaSeparatedString({1, 57, 2}, "foo", "bar"), "foo1, 57, 2bar");
49 }
50
TEST(UtilTest,VectorString)51 TEST(UtilTest, VectorString) {
52 std::list<int64_t> empty_list;
53 EXPECT_EQ(VectorString(empty_list), "()");
54
55 std::vector<float> float_vector = {5.5};
56 EXPECT_EQ(VectorString(float_vector), "(5.5)");
57
58 std::set<std::string_view> string_set = {std::string_view("a"),
59 std::string_view("b")};
60 EXPECT_EQ(VectorString(string_set), "(a, b)");
61
62 EXPECT_EQ(VectorString({}), "()");
63 EXPECT_EQ(VectorString({1, 57, 2}), "(1, 57, 2)");
64 }
65
TEST(UtilTest,LogLines)66 TEST(UtilTest, LogLines) {
67 // Just make sure this code runs (not verifying the output).
68 LogLines(tensorflow::INFO, "hello\n\nworld", __FILE__, __LINE__);
69 }
70
TEST(UtilTest,CommonFactors)71 TEST(UtilTest, CommonFactors) {
72 struct {
73 std::vector<int64_t> a, b;
74 absl::InlinedVector<std::pair<int64_t, int64_t>, 8> expected;
75 } test_cases[] = {
76 {/*.a =*/{0}, /*.b =*/{0}, /*.expected =*/{{0, 0}, {1, 1}}},
77 {/*.a =*/{1}, /*.b =*/{}, /*.expected =*/{{0, 0}, {1, 0}}},
78 {/*.a =*/{}, /*.b =*/{1}, /*.expected =*/{{0, 0}, {0, 1}}},
79 {/*.a =*/{0, 10}, /*.b =*/{0, 10, 3}, /*.expected =*/{{0, 0}, {2, 3}}},
80 {/*.a =*/{1, 0}, /*.b =*/{1, 0, 1},
81 /*.expected =*/{{0, 0}, {1, 1}, {2, 2}, {2, 3}}},
82 {/*.a =*/{0, 1}, /*.b =*/{0, 1}, /*.expected =*/{{0, 0}, {1, 1}, {2, 2}}},
83 {/*.a =*/{}, /*.b =*/{}, /*.expected =*/{{0, 0}}},
84 {/*.a =*/{2, 5, 1, 3},
85 /*.b =*/{1, 10, 3, 1},
86 /*.expected =*/{{0, 0}, {0, 1}, {2, 2}, {3, 2}, {4, 3}, {4, 4}}},
87 {/*.a =*/{1, 1, 3},
88 /*.b =*/{1, 1, 3},
89 /*.expected =*/{{0, 0}, {1, 1}, {2, 2}, {3, 3}}},
90 // Splitting and combining dimensions.
91 {/*.a =*/{2, 6},
92 /*.b =*/{4, 3},
93 /*.expected =*/{{0, 0}, {2, 2}}},
94 {/*.a =*/{1, 2, 6},
95 /*.b =*/{4, 1, 3, 1},
96 /*.expected =*/{{0, 0}, {1, 0}, {3, 3}, {3, 4}}},
97 // Extra degenerated dimension (second and third dims in the output) forms
98 // single common factor group.
99 {/*.a =*/{1, 2, 1},
100 /*.b =*/{1, 1, 1, 2},
101 /*.expected =*/{{0, 0}, {1, 1}, {1, 2}, {1, 3}, {2, 4}, {3, 4}}}};
102 for (const auto& test_case : test_cases) {
103 EXPECT_EQ(test_case.expected, CommonFactors(test_case.a, test_case.b));
104 }
105 }
106
TEST(UtilTest,SanitizeFileName)107 TEST(UtilTest, SanitizeFileName) {
108 EXPECT_EQ(SanitizeFileName(""), "");
109 EXPECT_EQ(SanitizeFileName("abc"), "abc");
110 EXPECT_EQ(SanitizeFileName("/\\[]"), "____");
111 EXPECT_EQ(SanitizeFileName("/A\\B[C]"), "_A_B_C_");
112 }
113
TEST(UtilTest,RoundTripFpToString)114 TEST(UtilTest, RoundTripFpToString) {
115 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<half>(
116 false, QuietNanWithoutPayload<half>())),
117 "nan");
118 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<half>(
119 true, QuietNanWithoutPayload<half>())),
120 "-nan");
121 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<bfloat16>(
122 false, QuietNanWithoutPayload<bfloat16>())),
123 "nan");
124 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<bfloat16>(
125 true, QuietNanWithoutPayload<bfloat16>())),
126 "-nan");
127 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<float>(
128 false, QuietNanWithoutPayload<float>())),
129 "nan");
130 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<float>(
131 true, QuietNanWithoutPayload<float>())),
132 "-nan");
133 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<double>(
134 false, QuietNanWithoutPayload<double>())),
135 "nan");
136 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<double>(
137 true, QuietNanWithoutPayload<double>())),
138 "-nan");
139
140 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<half>(false, 0x1)),
141 "nan(0x1)");
142 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<half>(true, 0x1)),
143 "-nan(0x1)");
144 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<bfloat16>(false, 0x1)),
145 "nan(0x1)");
146 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<bfloat16>(true, 0x1)),
147 "-nan(0x1)");
148 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<float>(false, 0x1)),
149 "nan(0x1)");
150 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<float>(true, 0x1)),
151 "-nan(0x1)");
152 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<double>(false, 0x1)),
153 "nan(0x1)");
154 EXPECT_EQ(RoundTripFpToString(NanWithSignAndPayload<double>(true, 0x1)),
155 "-nan(0x1)");
156 }
157
TEST(UtilTest,SplitF64ToF32)158 TEST(UtilTest, SplitF64ToF32) {
159 // Overflowing the F32 exponent in SplitF64ToF32 should result in a pair of
160 // [∞,0].
161 EXPECT_EQ(SplitF64ToF32(std::numeric_limits<double>::max()).first,
162 std::numeric_limits<float>::infinity());
163 EXPECT_EQ(SplitF64ToF32(std::numeric_limits<double>::max()).second, 0.0f);
164 }
165
166 } // namespace
167 } // namespace xla
168