-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
suanPan.h
353 lines (303 loc) · 11.3 KB
/
suanPan.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/*******************************************************************************
* Copyright (C) 2017-2024 Theodore Chang
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#ifndef SUANPAN_H
#define SUANPAN_H
// SUANPAN_DEBUG
// _DEBUG --> MSVC
// DEBUG --> GCC
#if defined(_DEBUG) || defined(DEBUG) || !defined(NDEBUG)
#define SUANPAN_DEBUG
#define SUANPAN_EXTRA_DEBUG
#else
#define ARMA_NO_DEBUG
#endif
#ifdef SUANPAN_SUPERLUMT
#define ARMA_DONT_USE_SUPERLU
#else
#define ARMA_USE_SUPERLU
#endif
#ifdef SUANPAN_MKL
#define MKL_DIRECT_CALL
#endif
#ifdef SUANPAN_HDF5
#define ARMA_USE_HDF5
#endif
#ifdef SUANPAN_MAGMA
#ifndef SUANPAN_CUDA
#undef SUANPAN_MAGMA
#endif
#endif
// SUANPAN_WIN
// WIN32 _WIN32 __WIN32 __WIN32__ --> MSVC GCC
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__)
#ifndef SUANPAN_WIN
#define SUANPAN_WIN
#endif
#endif
// SUANPAN_WIN
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN64__)
#ifndef SUANPAN_WIN
#define SUANPAN_WIN
#endif
#endif
#ifdef SUANPAN_WIN
#ifndef NOMINMAX
#define NOMINMAX
#endif
#endif
// SUANPAN_UNIX
#if defined(unix) || defined(__unix__) || defined(__linux__) || defined(linux)
#ifndef SUANPAN_UNIX
#define SUANPAN_UNIX
#endif
#endif
#ifdef SUANPAN_VERSION
#undef SUANPAN_VERSION
#endif
#ifdef SUANPAN_COMPILER
#undef SUANPAN_COMPILER
#endif
// SUANPAN_VERSION SUANPAN_COMPILER
#ifdef __clang__
// __clang__ --> clang
#ifdef SUANPAN_VERSION
#undef SUANPAN_VERSION
#endif
#define SUANPAN_VERSION __VERSION__
#ifdef SUANPAN_COMPILER
#undef SUANPAN_COMPILER
#endif
#define SUANPAN_COMPILER "CLANG"
#define SUANPAN_CLANG
#elif defined(__GNUG__)
// __GNUG__ --> GCC
#define SUANPAN_VERSION __VERSION__
#define SUANPAN_COMPILER "GCC"
#define SUANPAN_GCC
#elif defined(_MSC_BUILD)
// _MSC_BUILD --> MSVC
#define SUANPAN_VERSION _MSC_FULL_VER
#define SUANPAN_COMPILER "MSVC"
#define SUANPAN_MSVC
// cuda unused local function
#pragma warning(disable : 4505)
#elif defined(__ICC)
// __ICC --> Intel C++
#define SUANPAN_VERSION __ICC
#define SUANPAN_COMPILER "INTEL"
#define SUANPAN_INTEL
#ifdef SUANPAN_WIN
#undef SUANPAN_WIN
#endif
#ifndef SUANPAN_UNIX
#define SUANPAN_UNIX
#endif
#elif defined(__ICL)
// __ICL --> Intel C++
#define SUANPAN_VERSION __ICL
#define SUANPAN_COMPILER "INTEL"
#define SUANPAN_INTEL
#ifdef SUANPAN_UNIX
#undef SUANPAN_UNIX
#endif
#ifndef SUANPAN_WIN
#define SUANPAN_WIN
#endif
#endif
// _USRDLL --> MSVC
#ifdef _USRDLL
#ifndef SUANPAN_DLL
#define SUANPAN_DLL
#endif
#endif
#ifdef SUANPAN_WIN
// WIN MSVC GCC IMPORT
#define SUANPAN_IMPORT extern "C" __declspec(dllimport)
// WIN MSVC GCC EXPORT
#define SUANPAN_EXPORT extern "C" __declspec(dllexport)
#elif defined(SUANPAN_UNIX)
// UNIX GCC IMPORT
#define SUANPAN_IMPORT extern "C"
// UNIX GCC EXPORT
#define SUANPAN_EXPORT extern "C"
#else
// EMPTY
#define SUANPAN_IMPORT extern "C"
#define SUANPAN_EXPORT extern "C"
#endif
#ifdef SUANPAN_DLL
SUANPAN_IMPORT bool SUANPAN_PRINT;
SUANPAN_IMPORT bool SUANPAN_VERBOSE;
SUANPAN_IMPORT bool SUANPAN_COLOR;
SUANPAN_IMPORT unsigned SUANPAN_WARNING_COUNT;
SUANPAN_IMPORT unsigned SUANPAN_ERROR_COUNT;
#else
SUANPAN_EXPORT bool SUANPAN_PRINT;
SUANPAN_EXPORT bool SUANPAN_VERBOSE;
SUANPAN_EXPORT bool SUANPAN_COLOR;
SUANPAN_EXPORT unsigned SUANPAN_WARNING_COUNT;
SUANPAN_EXPORT unsigned SUANPAN_ERROR_COUNT;
#endif
constexpr auto SUANPAN_EXIT = 1;
constexpr auto SUANPAN_SUCCESS = 0;
constexpr auto SUANPAN_FAIL = -1;
// TWO IMPLEMENTATIONS
#ifndef SUANPAN_WIN
#define _strcmpi strcasecmp
#endif
#ifdef SUANPAN_MT
#include <oneapi/tbb/parallel_for_each.h>
#include <oneapi/tbb/parallel_sort.h>
#define suanpan_sort tbb::parallel_sort
#define suanpan_for_each tbb::parallel_for_each
#else
#define suanpan_sort std::sort
#define suanpan_for_each std::for_each
#endif
#include <iostream>
inline auto& SUANPAN_COUT = std::cout;
inline auto& SUANPAN_CWRN = std::cout;
inline auto& SUANPAN_CERR = std::cout;
inline auto& SUANPAN_CFTL = std::cout;
#define ARMA_COUT_STREAM SUANPAN_COUT
#define ARMA_CERR_STREAM SUANPAN_COUT
#include <armadillo/armadillo>
using namespace arma;
#include <filesystem>
namespace fs = std::filesystem;
#include <fmt/color.h>
#include <mutex>
namespace suanpan {
inline std::mutex print_mutex;
inline std::string pattern(const std::string_view header, const std::string_view file_name, const std::string_view format) {
std::string pattern{header};
pattern += fs::path(file_name).filename().string();
pattern += ":{} ~> ";
pattern += format;
return pattern;
}
template<typename... T> void debug(const std::string_view file_name, const int line, const std::string_view format_str, const T&... args) {
if(!SUANPAN_VERBOSE || !SUANPAN_PRINT) return;
const std::scoped_lock lock(print_mutex);
if(SUANPAN_COLOR) SUANPAN_COUT << fmt::vformat(fg(fmt::color::coral), pattern("[DEBUG] ", file_name, format_str), fmt::make_format_args(line, args...));
else SUANPAN_COUT << fmt::vformat(pattern("[DEBUG] ", file_name, format_str), fmt::make_format_args(line, args...));
}
template<typename... T> void warning(const std::string_view file_name, const int line, const std::string_view format_str, const T&... args) {
SUANPAN_WARNING_COUNT += 1;
if(!SUANPAN_PRINT) return;
const std::scoped_lock lock(print_mutex);
if(SUANPAN_COLOR) SUANPAN_CWRN << fmt::vformat(fg(fmt::color::slate_blue), pattern("[WARNING] ", file_name, format_str), fmt::make_format_args(line, args...));
else SUANPAN_CWRN << fmt::vformat(pattern("[WARNING] ", file_name, format_str), fmt::make_format_args(line, args...));
}
template<typename... T> void error(const std::string_view file_name, const int line, const std::string_view format_str, const T&... args) {
SUANPAN_ERROR_COUNT += 1;
if(!SUANPAN_PRINT) return;
const std::scoped_lock lock(print_mutex);
if(SUANPAN_COLOR) SUANPAN_CERR << fmt::vformat(fg(fmt::color::orange), pattern("[ERROR] ", file_name, format_str), fmt::make_format_args(line, args...));
else SUANPAN_CERR << fmt::vformat(pattern("[ERROR] ", file_name, format_str), fmt::make_format_args(line, args...));
}
template<typename... T> void fatal(const std::string_view file_name, const int line, const std::string_view format_str, const T&... args) {
if(!SUANPAN_PRINT) return;
const std::scoped_lock lock(print_mutex);
if(SUANPAN_COLOR) SUANPAN_CFTL << fmt::vformat(fg(fmt::color::violet), pattern("[FATAL] ", file_name, format_str), fmt::make_format_args(line, args...));
else SUANPAN_CFTL << fmt::vformat(pattern("[FATAL] ", file_name, format_str), fmt::make_format_args(line, args...));
}
template<typename... T> void info(const std::string_view format_str, const T&... args) {
if(!SUANPAN_PRINT) return;
const std::scoped_lock lock(print_mutex);
if(SUANPAN_COLOR) SUANPAN_COUT << fmt::vformat(fg(fmt::color::green_yellow), format_str, fmt::make_format_args(args...));
else SUANPAN_COUT << fmt::vformat(format_str, fmt::make_format_args(args...));
}
template<typename... T> std::string format(const std::string_view format_str, const T&... args) { return fmt::vformat(format_str, fmt::make_format_args(args...)); }
template<typename T> std::string format(const Col<T>& in_vec) {
std::string output;
if(std::is_floating_point_v<T>) for(const auto I : in_vec) output += format(" {: 1.4e}", I);
else for(const auto I : in_vec) output += format(" {:6d}", I);
output += '\n';
return output;
}
template<typename T> void info(const Col<T>& in_vec) {
if(!SUANPAN_PRINT) return;
const std::scoped_lock lock(print_mutex);
if(SUANPAN_COLOR) SUANPAN_COUT << fmt::format(fg(fmt::color::green_yellow), format(in_vec));
else SUANPAN_COUT << format(in_vec);
}
template<typename T> void info(const std::string_view format_str, const Col<T>& in_vec) {
if(!SUANPAN_PRINT) return;
std::string output = format(format_str);
if(format_str.back() != '\t' && format_str.back() != '\n') output += '\n';
output += format(in_vec);
const std::scoped_lock lock(print_mutex);
if(SUANPAN_COLOR) SUANPAN_COUT << fmt::format(fg(fmt::color::green_yellow), output);
else SUANPAN_COUT << output;
}
template<typename... T> void highlight(const std::string_view format_str, const T&... args) {
if(!SUANPAN_PRINT) return;
const std::scoped_lock lock(print_mutex);
if(SUANPAN_COLOR) SUANPAN_COUT << fmt::vformat(fg(fmt::color::crimson), format_str, fmt::make_format_args(args...));
else SUANPAN_COUT << fmt::vformat(format_str, fmt::make_format_args(args...));
}
}
#ifdef SUANPAN_MSVC
#pragma warning(disable : 4100)
#endif
#include <functional>
inline void suanpan_assert(const std::function<void()>& F) {
#ifdef SUANPAN_DEBUG
F();
#endif
}
#ifdef SUANPAN_MSVC
#pragma warning(default : 4100)
#endif
#define suanpan_info suanpan::info
#define suanpan_highlight suanpan::highlight
#define suanpan_debug(...) suanpan::debug(__FILE__, __LINE__, ##__VA_ARGS__)
#define suanpan_warning(...) suanpan::warning(__FILE__, __LINE__, ##__VA_ARGS__)
#define suanpan_error(...) suanpan::error(__FILE__, __LINE__, ##__VA_ARGS__)
#define suanpan_fatal(...) suanpan::fatal(__FILE__, __LINE__, ##__VA_ARGS__)
#include <memory>
using std::shared_ptr;
using std::unique_ptr;
using std::weak_ptr;
using std::make_shared;
using std::make_unique;
using std::exception;
using std::invalid_argument;
using std::logic_error;
using std::out_of_range;
using std::istringstream;
using std::ostringstream;
using std::string;
template<class T> concept sp_d = std::is_floating_point_v<T>;
template<class T> concept sp_i = std::is_integral_v<T>;
namespace suanpan {
template<class IN, class FN> requires requires(IN& x) { x.begin(); x.end(); }
void for_all(IN& from, FN&& func) {
suanpan_for_each(from.begin(), from.end(), std::forward<FN>(func));
}
}
#if defined(SUANPAN_CLANG) && !defined(__cpp_lib_ranges)
// as of clang 13, ranges support is not complete
namespace std::ranges {
template<class IN, class OUT, class FN> OUT transform(IN& from, OUT to, FN&& func) { return std::transform(from.begin(), from.end(), to, std::forward<FN>(func)); }
template<class IN, class FN> FN for_each(IN& from, FN&& func) { return std::for_each(from.begin(), from.end(), std::forward<FN>(func)); }
template<class IN, class OUT> OUT copy(IN& from, OUT to) { return std::copy(from.begin(), from.end(), to); }
} // namespace std::ranges
#endif
template<typename T1> [[nodiscard]] typename enable_if2<is_arma_type<T1>::value, typename T1::pod_type>::result inf_norm(const T1& X) { return arma::norm(X, "inf"); }
#endif