• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 Google LLC. 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 #ifndef TENSORFLOW_LITE_EXPERIMENTAL_RUY_CHECK_MACROS_H_
17 #define TENSORFLOW_LITE_EXPERIMENTAL_RUY_CHECK_MACROS_H_
18 
19 #include <cstdio>
20 #include <cstdlib>
21 #include <type_traits>
22 
23 namespace ruy {
24 namespace check_macros {
25 
26 constexpr int kValueBufSize = 32;
27 
28 template <typename T, typename Enable = void>
29 struct ToString {
RunToString30   static void Run(const T& value, char* buf) {
31     snprintf(buf, kValueBufSize, "(?)");
32   }
33 };
34 
35 template <>
36 struct ToString<float, void> {
37   static void Run(float value, char* buf) {
38     snprintf(buf, kValueBufSize, "%.9g", static_cast<double>(value));
39   }
40 };
41 
42 template <>
43 struct ToString<double, void> {
44   static void Run(double value, char* buf) {
45     snprintf(buf, kValueBufSize, "%.16g", value);
46   }
47 };
48 
49 template <typename T>
50 struct ToString<T, typename std::enable_if<std::is_integral<T>::value>::type> {
51   static void Run(const T& value, char* buf) {
52     snprintf(buf, kValueBufSize, "%lld", static_cast<long long>(value));
53   }
54 };
55 
56 template <typename T>
57 struct ToString<T*, void> {
58   static void Run(T* value, char* buf) {
59     snprintf(buf, kValueBufSize, "%p", value);
60   }
61 };
62 
63 template <typename T>
64 struct ToString<T, typename std::enable_if<std::is_enum<T>::value>::type> {
65   static void Run(const T& value, char* buf) {
66     snprintf(buf, kValueBufSize, "(enum value %d)", static_cast<int>(value));
67   }
68 };
69 
70 inline void Failure(const char* file, int line, const char* macro,
71                     const char* condition) {
72   fprintf(stderr, "%s:%d: %s condition not satisfied: %s\n", file, line, macro,
73           condition);
74   abort();
75 }
76 
77 template <typename LhsType, typename RhsType>
78 inline void Failure(const char* file, int line, const char* macro,
79                     const char* lhs, const LhsType& lhs_value, const char* op,
80                     const char* rhs, const RhsType& rhs_value) {
81   char lhs_value_buf[kValueBufSize];
82   ToString<LhsType>::Run(lhs_value, lhs_value_buf);
83   char rhs_value_buf[kValueBufSize];
84   ToString<RhsType>::Run(rhs_value, rhs_value_buf);
85   fprintf(stderr,
86           "%s:%d: %s condition not satisfied:   [ %s %s %s ]   with values   [ "
87           "%s %s %s ].\n",
88           file, line, macro, lhs, op, rhs, lhs_value_buf, op, rhs_value_buf);
89   abort();
90 }
91 
92 #define RUY_CHECK_IMPL(macro, condition)                                  \
93   do {                                                                    \
94     if (!(condition)) {                                                   \
95       ruy::check_macros::Failure(__FILE__, __LINE__, #macro, #condition); \
96     }                                                                     \
97   } while (false)
98 
99 #define RUY_CHECK_OP_IMPL(macro, lhs, op, rhs)                                \
100   do {                                                                        \
101     const auto& lhs_value = (lhs);                                            \
102     const auto& rhs_value = (rhs);                                            \
103     if (!(lhs_value op rhs_value)) {                                          \
104       ruy::check_macros::Failure(__FILE__, __LINE__, #macro, #lhs, lhs_value, \
105                                  #op, #rhs, rhs_value);                       \
106     }                                                                         \
107   } while (false)
108 
109 #define RUY_CHECK(condition) RUY_CHECK_IMPL(RUY_CHECK, condition)
110 #define RUY_CHECK_EQ(x, y) RUY_CHECK_OP_IMPL(RUY_CHECK_EQ, x, ==, y)
111 #define RUY_CHECK_NE(x, y) RUY_CHECK_OP_IMPL(RUY_CHECK_NE, x, !=, y)
112 #define RUY_CHECK_GE(x, y) RUY_CHECK_OP_IMPL(RUY_CHECK_GE, x, >=, y)
113 #define RUY_CHECK_GT(x, y) RUY_CHECK_OP_IMPL(RUY_CHECK_GT, x, >, y)
114 #define RUY_CHECK_LE(x, y) RUY_CHECK_OP_IMPL(RUY_CHECK_LE, x, <=, y)
115 #define RUY_CHECK_LT(x, y) RUY_CHECK_OP_IMPL(RUY_CHECK_LT, x, <, y)
116 
117 #ifdef NDEBUG
118 #define RUY_DCHECK(condition)
119 #define RUY_DCHECK_EQ(x, y)
120 #define RUY_DCHECK_NE(x, y)
121 #define RUY_DCHECK_GE(x, y)
122 #define RUY_DCHECK_GT(x, y)
123 #define RUY_DCHECK_LE(x, y)
124 #define RUY_DCHECK_LT(x, y)
125 #else
126 #define RUY_DCHECK(condition) RUY_CHECK(condition)
127 #define RUY_DCHECK_EQ(x, y) RUY_CHECK_EQ(x, y)
128 #define RUY_DCHECK_NE(x, y) RUY_CHECK_NE(x, y)
129 #define RUY_DCHECK_GE(x, y) RUY_CHECK_GE(x, y)
130 #define RUY_DCHECK_GT(x, y) RUY_CHECK_GT(x, y)
131 #define RUY_DCHECK_LE(x, y) RUY_CHECK_LE(x, y)
132 #define RUY_DCHECK_LT(x, y) RUY_CHECK_LT(x, y)
133 #endif
134 
135 }  // end namespace check_macros
136 }  // end namespace ruy
137 
138 #endif  // TENSORFLOW_LITE_EXPERIMENTAL_RUY_CHECK_MACROS_H_
139