1 /* Copyright Jukka Jyl�nki
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 /** @file assume.h
16         @author Jukka Jyl�nki
17         @brief Global compilation defines. */
18 #pragma once
19
20 #include <sstream>
21 #include "../MathBuildConfig.h"
22 #include "MathNamespace.h"
23 #include <stdio.h>
24 #include "myassert.h"
25 #include "MathLog.h"
26
27 #ifndef MARK_UNUSED
28 /// If a variable is labelled with this directive, the compiler should not emit a warning even if it is unused in the code.
29 #define MARK_UNUSED(x) ((void)x)
30 #endif
31
32 #ifdef __GNUC__
33 /// If a variable or a function definition is labelled with this directive, the compiler should not emit a warning even if it is unused
34 /// in the code.
35 #define DONT_WARN_UNUSED __attribute__((unused))
36 #else
37 #define DONT_WARN_UNUSED
38 #endif
39
40 #ifndef ARRAY_LENGTH
41 #define ARRAY_LENGTH(x) (sizeof((x))/sizeof((x)[0]))
42 #endif
43
44 // The assume() macro is used to check preconditions on the math-related functions, e.g. whether vectors are normalized, check that division by zero doesn't occur, orthonormal bases, and so on.
45
46 // The assume() macro operates differently depending on which #defines are present:
47 // #define MATH_ASSERT_ON_ASSUME - the assume() macro resolves to the assert() macro.
48 // #define MATH_DISABLE_ASSUME   - the assume() macro is silent, and disabled altogether. (no prints or breaks or anything, the checks by assume() are ignored)
49 // If neither of the above is defined (default), then
50 //  - WIN32: if MathBreakOnAssume() == true, the system will break to debugger using a call to DebugBreak().
51 //  - Other: if MathBreakOnAssume() == true, the assume() macro is equal to the assert() macro.
52 //  -   All: if MathBreakOnAssume() == false, the assume() macro uses printf() to log warnings of failed math-related assumptions.
53
54 MATH_BEGIN_NAMESPACE
55
56 /// Assigns mathBreakOnAssume = isEnabled;
57 void SetMathBreakOnAssume(bool isEnabled);
58
59 /// Returns the current state of the math break-on-assume flag.
60 /// The default startup value for this flag is false.
61 bool MathBreakOnAssume();
62
63 /// Breaks to debugger if math break-on-assume flag
64 /// Returns the current state of the math break-on-assume flag.
65 bool AssumeFailed();
66
67 template<typename T>
68 inline std::string ObjToString(const T &obj)
69 {
70         return obj.ToString();
71 }
72 /*
73 template<>
74 inline std::string ObjToString<const char*>(const char * const & obj)
75 {
76         return obj;
77 }
78 */
79 template<>
80 inline std::string ObjToString<std::string>(const std::string &obj)
81 {
82         return obj;
83 }
84
85 template<>
86 inline std::string ObjToString<float>(const float &obj)
87 {
88         std::stringstream ss;
89         ss << obj;
90         return ss.str();
91 }
92
93 template<>
94 inline std::string ObjToString<int>(const int &obj)
95 {
96         std::stringstream ss;
97         ss << obj;
98         return ss.str();
99 }
100
101 template<>
102 inline std::string ObjToString<bool>(const bool &obj)
103 {
104         std::stringstream ss;
105         ss << obj;
106         return ss.str();
107 }
108
109 template<>
110 inline std::string ObjToString<u32>(const u32 &obj)
111 {
112         std::stringstream ss;
113         ss << obj;
114         return ss.str();
115 }
116
117 MATH_END_NAMESPACE
118
119 // If MATH_ENABLE_INSECURE_OPTIMIZATIONS is defined, all input data is assumed to be correct and will
120 // not be checked against at runtime.
121 // If this flag is undefined (the default), all input is sanity checked so that user cannot crash the system
122 // e.g. with out-of-bounds accesses.
123 //#define MATH_ENABLE_INSECURE_OPTIMIZATIONS
124
125 #ifdef FAIL_USING_EXCEPTIONS
126 #include <stdexcept>
127 #define assume_failed(message) throw std::runtime_error((message))
128 #elif defined(MATH_ASSERT_ON_ASSUME)
129 #define assume(x) assert(x)
130 #define assume_failed(message) assert(false && #message)
131 #elif defined(MATH_SILENT_ASSUME)
132 #define assume(x) ((void)0)
133 #define assume_failed(message) ((void)0)
134 #else
135 #define assume_failed(message) LOGE("Assumption \"%s\" failed! in file %s, line %d!", message, __FILE__, __LINE__)
136 #endif
137
138 #ifndef assume
139 #define assume(x) \
140         MULTI_LINE_MACRO_BEGIN \
141                 if (!(x)) \
142                         assume_failed(#x " in " __FILE__ ":" STRINGIZE(__LINE__)); \
143         MULTI_LINE_MACRO_END
144 #endif
145
146 // In assume1-assume4, print1-print4 are additional helper parameters that get printed out to log in case of failure.
147 #define assume1(x, print1) \
148         MULTI_LINE_MACRO_BEGIN \
149                 if (!(x)) \
150                         assume_failed(((#x ", " #print1 ": ") + MATH_NS::ObjToString(print1) + \
151                                           (" in " __FILE__ ":" STRINGIZE(__LINE__))).c_str()); \
152         MULTI_LINE_MACRO_END
153 #define assert1 assume1
154
155 #define assume2(x, print1, print2) \
156         MULTI_LINE_MACRO_BEGIN \
157                 if (!(x)) \
158                         assume_failed(((#x ", " #print1 ": ") + MATH_NS::ObjToString(print1) + \
159                                           (", " #print2 ": ") + MATH_NS::ObjToString(print2) + \
160                                           (" in " __FILE__ ":" STRINGIZE(__LINE__))).c_str()); \
161         MULTI_LINE_MACRO_END
162 #define assert2 assume2
163
164 #define assume3(x, print1, print2, print3) \
165         MULTI_LINE_MACRO_BEGIN \
166                 if (!(x)) \
167                         assume_failed(((#x ", " #print1 ": ") + MATH_NS::ObjToString(print1) + \
168                                           (", " #print2 ": ") + MATH_NS::ObjToString(print2) + \
169                                           (", " #print3 ": ") + MATH_NS::ObjToString(print3) + \
170                                           (" in " __FILE__ ":" STRINGIZE(__LINE__))).c_str()); \
171         MULTI_LINE_MACRO_END
172 #define assert3 assume3
173
174 #define assume4(x, print1, print2, print3, print4) \
175         MULTI_LINE_MACRO_BEGIN \
176                 if (!(x)) \
177                         assume_failed(((#x ", " #print1 ": ") + MATH_NS::ObjToString(print1) + \
178                                           (", " #print2 ": ") + MATH_NS::ObjToString(print2) + \
179                                           (", " #print3 ": ") + MATH_NS::ObjToString(print3) + \
180                                           (", " #print4 ": ") + MATH_NS::ObjToString(print4) + \
181                                           (" in " __FILE__ ":" STRINGIZE(__LINE__))).c_str()); \
182         MULTI_LINE_MACRO_END
183 #define assert4 assume4
184
185 // If MATH_ASSERT_CORRECTNESS is defined, the function mathassert() is enabled to test
186 // that all forms of optimizations inside the math library produce proper results.
187 #ifdef MATH_ASSERT_CORRECTNESS
188 #define mathassert(x) assert(x)
189 #else
190 #define mathassert(x) ((void)0)
191 #endif
192
193 // Kill both assume() and mathassert() macros in OPTIMIZED_RELEASE builds.
194 #ifdef OPTIMIZED_RELEASE
195 #ifdef assume
196 #undef assume
197 #endif
198 #ifdef mathassert
199 #undef mathassert
200 #endif
201 #define assume(x) ((void)0)
202 #define mathassert(x) ((void)0)
203 #endif

Go back to previous page