1/*******************************************************************************
2 copyright (c) the taichi authors (2016- ). all rights reserved.
3 the use of this software is governed by the license file.
4*******************************************************************************/
5
6#pragma once
7
8#ifndef _CRT_SECURE_NO_WARNINGS
9#define _CRT_SECURE_NO_WARNINGS
10#endif
11
12#include <iostream>
13#include <type_traits>
14#include <cstdint>
15#include <algorithm>
16#include <vector>
17#include <string>
18#include <functional>
19
20//******************************************************************************
21// System State
22//******************************************************************************
23
24// Reference:
25// https://blog.kowalczyk.info/article/j/guide-to-predefined-macros-in-c-compilers-gcc-clang-msvc-etc..html
26
27// Platforms
28#include "taichi/common/platform_macros.h"
29
30// Avoid dependency on glibc 2.27
31#if defined(TI_PLATFORM_LINUX) && defined(TI_ARCH_x64)
32// objdump -T libtaichi_python.so| grep GLIBC_2.27
33__asm__(".symver logf,logf@GLIBC_2.2.5");
34__asm__(".symver powf,powf@GLIBC_2.2.5");
35__asm__(".symver expf,expf@GLIBC_2.2.5");
36#endif
37
38// Compilers
39
40// MSVC
41#if defined(_MSC_VER)
42#define TI_COMPILER_MSVC
43#endif
44
45// MINGW
46#if defined(__MINGW64__)
47#define TI_COMPILER_MINGW
48#endif
49
50// gcc
51#if defined(__GNUC__)
52#define TI_COMPILER__GCC
53#endif
54
55// clang
56#if defined(__clang__)
57#define TI_COMPILER_CLANG
58#endif
59
60#if defined(TI_COMPILER_MSVC)
61#define TI_ALIGNED(x) __declspec(align(x))
62#else
63#define TI_ALIGNED(x) __attribute__((aligned(x)))
64#endif
65
66#if __cplusplus >= 201703L
67#define TI_CPP17
68#else
69#if defined(TI_COMPILER_CLANG)
70static_assert(false, "For clang compilers, use -std=c++17");
71#endif
72static_assert(__cplusplus >= 201402L, "C++14 required.");
73#define TI_CPP14
74#endif
75
76// Do not disable assert...
77#ifdef NDEBUG
78#undef NDEBUG
79#endif
80
81#ifdef _WIN64
82#pragma warning(push)
83#pragma warning(disable : 4005)
84#include "taichi/platform/windows/windows.h"
85#pragma warning(pop)
86#include <intrin.h>
87#endif // _WIN64
88
89#ifndef _WIN64
90#define sscanf_s sscanf
91#define sprintf_s sprintf
92#endif
93
94#undef assert
95#ifdef _WIN64
96#ifndef TI_PASS_EXCEPTION_TO_PYTHON
97// For Visual Studio debugging...
98#define DEBUG_TRIGGER __debugbreak()
99#else
100#define DEBUG_TRIGGER
101#endif
102#else
103#define DEBUG_TRIGGER
104#endif
105
106#define TI_STATIC_ASSERT(x) static_assert((x), #x)
107
108void taichi_raise_assertion_failure_in_python(const char *msg);
109
110namespace taichi {
111
112//******************************************************************************
113// System State
114//******************************************************************************
115
116class CoreState {
117 public:
118 bool python_imported = false;
119 bool trigger_gdb_when_crash = false;
120
121 static CoreState &get_instance();
122
123 static void set_python_imported(bool val) {
124 get_instance().python_imported = val;
125 }
126
127 static void set_trigger_gdb_when_crash(bool val) {
128 get_instance().trigger_gdb_when_crash = val;
129 }
130};
131
132//******************************************************************************
133// Types
134//******************************************************************************
135
136using uchar = unsigned char;
137
138using int8 = int8_t;
139using uint8 = uint8_t;
140
141using int16 = int16_t;
142using uint16 = uint16_t;
143
144using int32 = int32_t;
145using uint32 = uint32_t;
146using uint = unsigned int;
147
148using int64 = int64_t;
149using uint64 = uint64_t;
150
151#ifdef _WIN64
152#define TI_FORCE_INLINE __forceinline
153#else
154#define TI_FORCE_INLINE inline __attribute__((always_inline))
155#endif
156
157using float32 = float;
158using float64 = double;
159
160#ifdef TI_USE_DOUBLE
161using real = float64;
162#else
163using real = float32;
164#endif
165
166// Float literal for both float32/64
167// (Learned from https://github.com/hi2p-perim/lightmetrica-v2)
168real constexpr operator"" _f(long double v) {
169 return real(v);
170}
171real constexpr operator"" _f(unsigned long long v) {
172 return real(v);
173}
174
175float32 constexpr operator"" _f32(long double v) {
176 return float32(v);
177}
178float32 constexpr operator"" _f32(unsigned long long v) {
179 return float32(v);
180}
181
182float32 constexpr operator"" _fs(long double v) {
183 return float32(v);
184}
185float32 constexpr operator"" _fs(unsigned long long v) {
186 return float32(v);
187}
188
189float64 constexpr operator"" _f64(long double v) {
190 return float64(v);
191}
192float64 constexpr operator"" _f64(unsigned long long v) {
193 return float64(v);
194}
195
196float64 constexpr operator"" _fd(long double v) {
197 return float64(v);
198}
199float64 constexpr operator"" _fd(unsigned long long v) {
200 return float64(v);
201}
202
203} // namespace taichi
204//******************************************************************************
205// Meta-programming
206//******************************************************************************
207
208#include "taichi/util/meta.h"
209
210#include "taichi/common/logging.h"
211
212namespace taichi {
213
214namespace zip {
215
216void write(std::string fn, const uint8 *data, std::size_t len);
217void write(const std::string &fn, const std::string &data);
218std::vector<uint8> read(const std::string fn, bool verbose = false);
219
220} // namespace zip
221
222//******************************************************************************
223// String Utils
224//******************************************************************************
225
226inline std::vector<std::string> split_string(const std::string &s,
227 const std::string &separators) {
228 std::vector<std::string> ret;
229 bool is_seperator[256] = {false};
230 for (auto &ch : separators) {
231 is_seperator[(unsigned int)ch] = true;
232 }
233 int begin = 0;
234 for (int i = 0; i <= (int)s.size(); i++) {
235 if (is_seperator[(uint8)s[i]] || i == (int)s.size()) {
236 ret.push_back(std::string(s.begin() + begin, s.begin() + i));
237 begin = i + 1;
238 }
239 }
240 return ret;
241}
242
243inline std::string trim_string(const std::string &s) {
244 int begin = 0, end = (int)s.size();
245 while (begin < end && s[begin] == ' ') {
246 begin++;
247 }
248 while (begin < end && s[end - 1] == ' ') {
249 end--;
250 }
251 return std::string(s.begin() + begin, s.begin() + end);
252}
253
254inline bool ends_with(std::string const &str, std::string const &ending) {
255 if (ending.size() > str.size())
256 return false;
257 else
258 return std::equal(ending.begin(), ending.end(), str.end() - ending.size());
259}
260
261inline bool starts_with(std::string const &str, std::string const &ending) {
262 if (ending.size() > str.size())
263 return false;
264 else
265 return std::equal(ending.begin(), ending.end(), str.begin());
266}
267
268} // namespace taichi
269
270//******************************************************************************
271// Serialization
272//******************************************************************************
273
274#include "taichi/common/serialization.h"
275
276//******************************************************************************
277// Misc.
278//******************************************************************************
279
280namespace taichi {
281
282extern int __trash__;
283template <typename T>
284void trash(T &&t) {
285 static_assert(!std::is_same<T, void>::value, "");
286 __trash__ = *reinterpret_cast<uint8 *>(&t);
287}
288
289class DeferedExecution {
290 std::function<void(void)> statement_;
291
292 public:
293 explicit DeferedExecution(const std::function<void(void)> &statement)
294 : statement_(statement) {
295 }
296
297 ~DeferedExecution() {
298 statement_();
299 }
300};
301
302#define TI_DEFER(x) taichi::DeferedExecution _defered([&]() { x; });
303
304std::string get_repo_dir();
305
306std::string get_python_package_dir();
307
308void set_python_package_dir(const std::string &dir);
309
310inline std::string assets_dir() {
311 return get_repo_dir() + "/assets/";
312}
313
314std::string cpp_demangle(const std::string &mangled_name);
315
316int get_version_major();
317
318int get_version_minor();
319
320int get_version_patch();
321
322std::string get_version_string();
323
324std::string get_commit_hash();
325
326std::string get_cuda_version_string();
327
328class PID {
329 public:
330 static int get_pid();
331 static int get_parent_pid();
332};
333
334} // namespace taichi
335