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