1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-06 23:52:38 -05:00

Compare commits

...

145 Commits

Author SHA1 Message Date
XMRig
84ebf9d372 Merge branch 'dev' 2019-12-01 15:30:06 +07:00
xmrig
2d5a7b6aa8 Update CHANGELOG.md 2019-12-01 15:28:05 +07:00
xmrig
e9b51b7baa Merge pull request #1351 from SChernykh/dev
RandomX fixes
2019-12-01 14:55:22 +07:00
SChernykh
84d7eb05f3 RandomX fixes
Intel JCC erratum fix and various other improvements, see more here: https://www.phoronix.com/scan.php?page=article&item=intel-jcc-microcode&num=1
2019-12-01 08:46:35 +01:00
XMRig
41e374f0d9 #1329 Revert version in master branch. 2019-11-29 19:06:50 +07:00
xmrig
c53fa07d2b Update CHANGELOG.md 2019-11-29 13:54:30 +07:00
XMRig
8791261220 Use total memory (Linux report low free memory) and fix typo. 2019-11-29 13:43:26 +07:00
XMRig
c7d2639010 Changed memory print format. 2019-11-29 13:25:24 +07:00
XMRig
c529770d38 Use uv_get_free_memory. 2019-11-29 13:12:36 +07:00
XMRig
64fb4f265b Added option "mode" (or --randomx-mode) for RandomX. 2019-11-29 13:00:17 +07:00
XMRig
ca9a3063d8 v5.1.0-dev 2019-11-29 11:27:09 +07:00
XMRig
33f6b91146 Added total memory size to summary. 2019-11-29 11:06:28 +07:00
XMRig
ada99a6dd1 Added "resources" field to API. 2019-11-29 10:50:30 +07:00
XMRig
7d1be2d234 Code cleanup. 2019-11-29 10:17:05 +07:00
XMRig
2b87a10cf2 Fixed zero size buffers handling. 2019-11-28 07:28:28 +07:00
XMRig
d224c0e7d8 Minor changes, based on https://github.com/xmrig/xmrig-nvidia/pull/305 2019-11-28 05:14:17 +07:00
XMRig
921abd4623 #1309 Fixed null pointer dereference. 2019-11-24 00:53:58 +07:00
XMRig
6e7b440630 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2019-11-21 15:45:12 +07:00
XMRig
cd723e32e8 #1307 Fixed incorrect job method for SelfSelectClient. 2019-11-21 15:44:39 +07:00
xmrig
b13d9a04eb Update CMAKE_OPTIONS.md 2019-11-21 04:53:12 +07:00
XMRig
258f936272 Merge branch 'dev' 2019-11-21 00:32:40 +07:00
XMRig
997f90dae7 Added PGP key and signed hashes for 5.0.1 release. 2019-11-21 00:27:50 +07:00
XMRig
5d559971ca Fixed isTLS method. 2019-11-20 15:36:02 +07:00
XMRig
8102526abc Added build_deps.sh for creating xmrig-deps on Linux. 2019-11-19 22:21:24 +07:00
XMRig
af30f8cd4b v5.0.2-dev 2019-11-19 03:59:46 +07:00
XMRig
4418ee743a Merge branch 'master' into dev 2019-11-19 03:56:49 +07:00
XMRig
fa18a75177 v5.0.1 2019-11-18 21:44:51 +07:00
XMRig
0e7c0e2903 Merge branch 'dev' 2019-11-18 21:43:18 +07:00
xmrig
f3c1435b01 Update CHANGELOG.md 2019-11-18 15:24:50 +07:00
XMRig
fb28b931cc Use static OpenSSL libs on macOS. 2019-11-16 18:56:34 +07:00
xmrig
dd980fde49 Update CMAKE_OPTIONS.md 2019-11-16 14:47:09 +07:00
xmrig
ca77fda511 Merge pull request #1290 from SChernykh/dev
Fix for 32-bit ARM compilation
2019-11-15 22:27:14 +07:00
SChernykh
e3f726796b Use XMRIG_ARMv8 macro 2019-11-15 16:12:26 +01:00
SChernykh
3953568a0e Fix for 32-bit ARM compilation 2019-11-15 16:00:48 +01:00
XMRig
f9bc3fb09b Fixed memory allocation on old low memory AMD GPUs. 2019-11-15 19:42:35 +07:00
xmrig
0497ab072b Update CHANGELOG.md 2019-11-15 18:19:43 +07:00
XMRig
5431601cef Don't print health report if CUDA backend disabled. 2019-11-15 18:09:09 +07:00
XMRig
aeb2c6e8ec #1285 Added command line options --cuda-bfactor-hint and --cuda-bsleep-hint. 2019-11-15 03:10:58 +07:00
XMRig
79f4685d9a Fixed wrong line ending in generated CL code. 2019-11-15 01:27:30 +07:00
XMRig
5fa7a743f5 #1284 Fixed build without RandomX. 2019-11-14 15:11:47 +07:00
XMRig
9124ed9348 v5.0.1-dev 2019-11-14 14:46:54 +07:00
XMRig
55133d03cf Merge branch 'master' into dev 2019-11-14 14:46:25 +07:00
XMRig
77eb79ced5 v5.0.0 2019-11-13 13:29:22 +07:00
XMRig
9d24d181d7 Merge branch 'dev' 2019-11-13 13:25:09 +07:00
XMRig
b011b935b4 Merge branch 'evo' into dev 2019-11-13 13:17:52 +07:00
XMRig
d807ba27a6 v5.0.0-evo 2019-11-13 12:22:02 +07:00
XMRig
2847c814d2 v4.6.2-evo 2019-11-13 02:15:55 +07:00
xmrig
f77c4c67f2 Update CHANGELOG.md 2019-11-13 02:00:03 +07:00
XMRig
13d256e737 Merge branch 'beta' into evo 2019-11-13 00:41:58 +07:00
XMRig
ed4cfd55ac #1274 Added --cuda-devices command line option. 2019-11-13 00:40:22 +07:00
xmrig
f965fd5a8c Merge pull request #1277 from SChernykh/evo
Fix function names for clang on Apple
2019-11-12 20:45:48 +07:00
SChernykh
472ec1a0e6 Fix function names for clang on Apple 2019-11-12 14:42:21 +01:00
XMRig
74d62c92cd v4.6.1-beta 2019-11-10 22:10:51 +07:00
XMRig
7e47b04676 Merge branch 'evo' into beta 2019-11-10 22:10:15 +07:00
xmrig
d19c152d9a Update CHANGELOG.md 2019-11-10 22:09:18 +07:00
XMRig
2abea46a87 #1273 Fixed crash when use "GET /2/backends" API endpoint with disabled CUDA. 2019-11-10 22:05:52 +07:00
XMRig
e450e62b40 v4.6.1 2019-11-10 13:54:10 +07:00
XMRig
e6afd12d4f Merge branch 'beta' into evo 2019-11-10 13:28:26 +07:00
xmrig
2ba19c9827 Merge pull request #1272 from SChernykh/evo
Optimized hashrate calculation
2019-11-09 23:38:46 +07:00
SChernykh
426bc8f0c4 Optimized hashrate calculation 2019-11-09 17:29:12 +01:00
XMRig
f9f7567b17 v4.6.0-beta 2019-11-09 20:40:59 +07:00
XMRig
d2b3ffc710 Merge branch 'evo' into beta 2019-11-09 20:39:30 +07:00
xmrig
ed2f2c5a60 Update CHANGELOG.md 2019-11-09 20:36:29 +07:00
XMRig
c235145121 Make option "dataset_host" available only for RandomX. 2019-11-06 19:00:50 +07:00
xmrig
f8d1488e33 Merge pull request #1263 from SChernykh/evo
RandomX: added support for dataset on host
2019-11-06 17:53:06 +07:00
SChernykh
0013e610d5 Updated required API version 2019-11-05 23:27:15 +01:00
SChernykh
2c9b034c08 RandomX: added support for dataset on host 2019-11-05 22:24:48 +01:00
XMRig
455cdf96f0 v4.5.0-beta 2019-11-02 19:32:25 +07:00
XMRig
5519e97e6e Merge branch 'evo' into beta 2019-11-02 19:30:47 +07:00
xmrig
4c4a674a4b Update CHANGELOG.md 2019-11-02 04:22:57 +07:00
xmrig
239aecb0bb Update README.md 2019-11-02 04:08:07 +07:00
xmrig
b1e23b46dd Update README.md 2019-11-02 04:03:03 +07:00
XMRig
9d679462ed Sync changes with proxy. 2019-11-01 21:51:03 +07:00
XMRig
be31811920 Merge branch 'feature-nvml' into evo 2019-11-01 04:09:36 +07:00
XMRig
26ed6254dc Added "health-print-time" option. 2019-11-01 04:08:52 +07:00
XMRig
1cb4d73fe3 Added manual (e key) health reports. 2019-11-01 00:09:28 +07:00
XMRig
f110b5000b Fixed switching from non RandomX algorithm to RandomX. 2019-10-30 22:40:09 +07:00
XMRig
83f437f979 Implemented NvmlLib. 2019-10-30 20:26:21 +07:00
XMRig
175a7b06b7 Added initial NVML stub. 2019-10-30 15:33:06 +07:00
xmrig
9d580693db Update CMAKE_OPTIONS.md 2019-10-29 17:26:03 +07:00
XMRig
3bdf7111ce Fixed singular form for threads. 2019-10-29 17:18:46 +07:00
XMRig
23ebcfb2db Display backend for shares. 2019-10-29 15:43:13 +07:00
XMRig
b1eac17d60 Added version information to API. 2019-10-29 14:25:40 +07:00
XMRig
9dfa38f1e7 Added command line options --cuda and --cuda-loader. 2019-10-29 00:42:49 +07:00
XMRig
80fd0f9fab Fix CUDA plugin name for Linux. 2019-10-28 14:54:24 +07:00
XMRig
58174e5e91 v4.5.0-evo 2019-10-28 13:30:03 +07:00
XMRig
ab7f0cb4cc Merge branch 'feature-cuda' into evo 2019-10-28 13:29:15 +07:00
XMRig
f6f480264e Merge branch 'evo' of github.com:xmrig/xmrig into evo 2019-10-28 13:28:43 +07:00
XMRig
8cd265c38c Added CUDA threads to API. 2019-10-28 13:18:00 +07:00
XMRig
99fe304c1f Don't generate CUDA config on fly. 2019-10-28 01:47:55 +07:00
XMRig
7889634b40 Added RandomX support. 2019-10-28 01:18:08 +07:00
XMRig
0e224abb0a Improved error handling. 2019-10-27 19:51:21 +07:00
XMRig
c9f7cbae09 Implemented cryptonight mining. 2019-10-27 17:53:00 +07:00
xmrig
2e537013a2 Merge pull request #1253 from SChernykh/evo
Fix VS2019 compilation
2019-10-27 02:08:09 +07:00
SChernykh
7cb9b92347 Fix VS2019 compilation 2019-10-26 13:32:30 +02:00
XMRig
bb2cc0deb7 Added CudaWorker and CudaLaunchData. 2019-10-26 17:37:54 +07:00
XMRig
d4a3024996 Implemented CUDA config generation. 2019-10-26 03:12:55 +07:00
XMRig
77d5b73724 Added CudaDevice class. 2019-10-26 00:49:59 +07:00
XMRig
ec717f27b5 Added CudaLib stub. 2019-10-25 16:46:49 +07:00
XMRig
0fc215c457 Added initial CUDA backend stub. 2019-10-23 16:37:56 +07:00
XMRig
534a764023 Merge branch 'beta' into evo 2019-10-23 11:53:02 +07:00
XMRig
dc705d88ab Fixed "coin" option for self select mode. 2019-10-22 16:54:36 +07:00
xmrig
6e9fd5a430 Update CHANGELOG.md 2019-10-22 15:28:15 +07:00
XMRig
e3f37bc2f9 v4.4.0-beta 2019-10-22 14:15:40 +07:00
XMRig
f6d58c7d46 Merge branch 'evo' into beta 2019-10-22 14:15:01 +07:00
XMRig
48545c5916 Fixed compile warnings. 2019-10-22 13:09:58 +07:00
XMRig
f7dcfffdb1 Removed unused class member. 2019-10-22 12:30:04 +07:00
XMRig
52281906c6 Fixed "huge-pages" option. 2019-10-21 23:01:30 +07:00
XMRig
487b2a3655 Merge branch 'evo' of github.com:xmrig/xmrig into evo 2019-10-21 21:27:51 +07:00
XMRig
71ee145f70 Added "paused" field to API. 2019-10-21 21:27:05 +07:00
xmrig
da20d74145 Update CHANGELOG.md 2019-10-21 20:22:35 +07:00
XMRig
c29fa62260 #1241 Revert changes in ConsoleLog for Windows. 2019-10-20 23:59:29 +07:00
XMRig
5613912ec4 Added "self-select" to config example. 2019-10-20 16:04:22 +07:00
xmrig
b77c5428f9 Update CHANGELOG.md 2019-10-20 16:02:49 +07:00
xmrig
2012ce384e Update README.md 2019-10-20 11:48:23 +07:00
XMRig
6b40ede2bc Don't add "self-select" field to generated config if it not supported. 2019-10-19 02:39:46 +07:00
xmrig
128c5f67ad Merge pull request #1248 from SChernykh/evo
Fixed code cache cleanup on iOS/Darwin
2019-10-18 23:27:39 +07:00
SChernykh
578bebb04d Prefer sys_icache_invalidate on iOS
Also break compilation with error if clear cache is not available
2019-10-18 18:17:57 +02:00
SChernykh
5611249af7 Fixed __builtin___clear_cache detection 2019-10-18 18:04:13 +02:00
SChernykh
a56febcd13 Force HAVE_BUILTIN_CLEAR_CACHE for GNU compilers
They always have __builtin___clear_cache
2019-10-18 17:39:57 +02:00
SChernykh
0ad992985c Update jit_compiler_a64.cpp 2019-10-18 16:36:50 +02:00
SChernykh
1a66c3f1a1 Update jit_compiler_a64.cpp 2019-10-18 16:32:01 +02:00
SChernykh
a2ef2fd9d9 Update jit_compiler_a64.cpp 2019-10-18 16:28:49 +02:00
XMRig
5c02cb50da Fix copy/paste typo. 2019-10-18 21:26:15 +07:00
SChernykh
998c55030a Fixed code cache cleanup on iOS/Darwin 2019-10-18 16:26:15 +02:00
xmrig
079de97fab Merge pull request #1247 from SChernykh/evo
Fix ARM64 code alignment
2019-10-18 21:24:14 +07:00
SChernykh
432addab33 Fix ARM64 code alignemtn 2019-10-18 16:18:45 +02:00
XMRig
10d292092a #1246 Fixed build on iOS. 2019-10-18 12:02:10 +07:00
XMRig
a02ee96651 Merge branch 'feature-self-select' into evo 2019-10-17 00:59:05 +07:00
XMRig
d783febad6 Added error handling for self-select mode. 2019-10-17 00:57:35 +07:00
xmrig
ea6d9073b7 Merge pull request #1243 from komatom/evo_globalmemsize_fix
Fixes OclDevice::globalMemSize() that sometimes returns 0
2019-10-16 20:33:54 +07:00
XMRig
83a5923568 Added send with callback. 2019-10-16 19:34:33 +07:00
Anton Kamenov
9e2b63890c Use functions to get memory variables 2019-10-14 14:14:12 +03:00
Anton Kamenov
ed08895d4a Fixes OclDevice::globalMemSize() that sometimes returns 0 2019-10-14 13:34:17 +03:00
xmrig
5b4026694d Merge pull request #1240 from SChernykh/evo
Sync with latest RandomX code
2019-10-14 10:07:20 +07:00
SChernykh
c9798ba2e9 Sync with latest RandomX code
Fix a possible out-of-bounds access in superscalar generator
2019-10-13 22:13:29 +02:00
XMRig
3752551e53 Self-select initial working implementation. 2019-10-12 19:48:18 +07:00
XMRig
a62f6f9552 Merge branch 'evo' into feature-self-select 2019-10-12 13:08:12 +07:00
XMRig
e9d2e194f3 Added SelfSelectClient stub. 2019-10-12 00:24:47 +07:00
XMRig
6009fffa7b v4.3.1-beta 2019-10-11 23:23:44 +07:00
XMRig
fad1e5fb3c Merge branch 'evo' into beta 2019-10-11 23:23:22 +07:00
XMRig
228f02c361 Fixed regression. 2019-10-11 23:21:02 +07:00
XMRig
72c45d882b Prepare for self select. 2019-10-11 14:55:12 +07:00
XMRig
4dc7a8103b Added class Url. 2019-10-11 09:58:11 +07:00
XMRig
71108e1bde v4.4.0-evo 2019-10-10 17:12:13 +07:00
178 changed files with 12607 additions and 8235 deletions

View File

@@ -1,90 +1,41 @@
# v4.3.0-beta
# v5.1.0
- [#1351](https://github.com/xmrig/xmrig/pull/1351) RandomX optimizations and fixes.
- Improved RandomX performance (up to +6-7% on Intel CPUs, +2-3% on Ryzen CPUs)
- Added workaround for Intel JCC erratum bug see https://www.phoronix.com/scan.php?page=article&item=intel-jcc-microcode&num=1 for details.
- Note! Always disable "Hardware prefetcher" and "Adjacent cacheline prefetch" in BIOS for Intel CPUs to get the optimal RandomX performance.
- [#1307](https://github.com/xmrig/xmrig/issues/1307) Fixed mining resume after donation round for pools with `self-select` feature.
- [#1318](https://github.com/xmrig/xmrig/issues/1318#issuecomment-559676080) Added option `"mode"` (or `--randomx-mode`) for RandomX.
- Added memory information on miner startup.
- Added `resources` field to summary API with memory information and load average.
# v5.0.1
- [#1234](https://github.com/xmrig/xmrig/issues/1234) Fixed compatibility with some AMD GPUs.
- [#1284](https://github.com/xmrig/xmrig/issues/1284) Fixed build without RandomX.
- [#1285](https://github.com/xmrig/xmrig/issues/1285) Added command line options `--cuda-bfactor-hint` and `--cuda-bsleep-hint`.
- [#1290](https://github.com/xmrig/xmrig/pull/1290) Fixed 32-bit ARM compilation.
# v5.0.0
This version is first stable unified 3 in 1 GPU+CPU release, OpenCL support built in in miner and not require additional external dependencies on compile time, NVIDIA CUDA available as external [CUDA plugin](https://github.com/xmrig/xmrig-cuda), for convenient, 3 in 1 downloads with recent CUDA version also provided.
This release based on 4.x.x series and include all features from v4.6.2-beta, changelog below include only the most important changes, [full changelog](doc/CHANGELOG_OLD.md) available separately.
- [#1272](https://github.com/xmrig/xmrig/pull/1272) Optimized hashrate calculation.
- [#1263](https://github.com/xmrig/xmrig/pull/1263) Added new option `dataset_host` for NVIDIA GPUs with less than 4 GB memory (RandomX only).
- [#1068](https://github.com/xmrig/xmrig/pull/1068) Added support for `self-select` stratum protocol extension.
- [#1227](https://github.com/xmrig/xmrig/pull/1227) Added new algorithm `rx/arq`, RandomX variant for upcoming ArQmA fork.
- [#808](https://github.com/xmrig/xmrig/issues/808#issuecomment-539297156) Added experimental support for persistent memory for CPU mining threads.
- [#1221](https://github.com/xmrig/xmrig/issues/1221) Improved RandomX dataset memory usage and initialization speed for NUMA machines.
# v4.2.1-beta
- [#1150](https://github.com/xmrig/xmrig/issues/1150) Fixed build on FreeBSD.
- [#1175](https://github.com/xmrig/xmrig/issues/1175) Fixed support for systems where total count of NUMA nodes not equal usable nodes count.
- [#1199](https://github.com/xmrig/xmrig/issues/1199) Fixed excessive memory allocation for OpenCL threads with low intensity.
- [#1212](https://github.com/xmrig/xmrig/issues/1212) Fixed low RandomX performance after fast algorithm switching.
# v4.2.0-beta
- [#1202](https://github.com/xmrig/xmrig/issues/1202) Fixed algorithm verification in donate strategy.
- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork.
- Added config option `cpu/max-threads-hint` and command line option `--cpu-max-threads-hint`.
# v4.1.0-beta
- **OpenCL backend disabled by default.**.
- [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd.
- [#1185](https://github.com/xmrig/xmrig/pull/1185) Added JIT compiler for RandomX on ARMv8.
- Improved API endpoint `GET /2/backends` and added support for this endpoint to [workers.xmrig.info](http://workers.xmrig.info).
- Added command line option `--no-cpu` to disable CPU backend.
- Added OpenCL specific command line options: `--opencl`, `--opencl-devices`, `--opencl-platform`, `--opencl-loader` and `--opencl-no-cache`.
- Added CUDA specific command line options: `--cuda`, `--cuda-loader` and `--no-nvml`.
- Removed command line option `--http-enabled`, HTTP API enabled automatically if any other `--http-*` option provided.
# v4.0.1-beta
- [#1177](https://github.com/xmrig/xmrig/issues/1177) Fixed compatibility with old AMD drivers.
- [#1180](https://github.com/xmrig/xmrig/issues/1180) Fixed possible duplicated shares after algorithm switching.
- Added support for case if not all backend threads successfully started.
- Fixed wrong config file permissions after write (only gcc builds on recent Windows 10 affected).
# v4.0.0-beta
- [#1172](https://github.com/xmrig/xmrig/issues/1172) **Added OpenCL mining backend.**
- [#268](https://github.com/xmrig/xmrig-amd/pull/268) [#270](https://github.com/xmrig/xmrig-amd/pull/270) [#271](https://github.com/xmrig/xmrig-amd/pull/271) [#273](https://github.com/xmrig/xmrig-amd/pull/273) [#274](https://github.com/xmrig/xmrig-amd/pull/274) [#1171](https://github.com/xmrig/xmrig/pull/1171) Added RandomX support for OpenCL, thanks [@SChernykh](https://github.com/SChernykh).
- Algorithm `cn/wow` removed, as no longer alive.
# v3.2.0
- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork.
- [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd.
# v3.1.3
- [#1180](https://github.com/xmrig/xmrig/issues/1180) Fixed possible duplicated shares after algorithm switching.
- Fixed wrong config file permissions after write (only gcc builds on recent Windows 10 affected).
# v3.1.2
- Many RandomX optimizations and fixes.
- [#1132](https://github.com/xmrig/xmrig/issues/1132) Fixed build on CentOS 7.
- [#1163](https://github.com/xmrig/xmrig/pull/1163) Optimized soft AES code, up to +30% hashrate on CPU without AES support and other optimizations.
- [#1166](https://github.com/xmrig/xmrig/pull/1166) Fixed crash when initialize dataset with big threads count (eg 272).
- [#1168](https://github.com/xmrig/xmrig/pull/1168) Optimized loading from scratchpad.
- [#1128](https://github.com/xmrig/xmrig/issues/1128) Fixed CMake 2.8 compatibility.
# v3.1.1
- [#1133](https://github.com/xmrig/xmrig/issues/1133) Fixed syslog regression.
- [#1138](https://github.com/xmrig/xmrig/issues/1138) Fixed multiple network bugs.
- [#1141](https://github.com/xmrig/xmrig/issues/1141) Fixed log in background mode.
- [#1142](https://github.com/xmrig/xmrig/pull/1142) RandomX hashrate improved by 0.5-1.5% depending on variant and CPU.
- [#1146](https://github.com/xmrig/xmrig/pull/1146) Fixed race condition in RandomX thread init.
- [#1148](https://github.com/xmrig/xmrig/pull/1148) Fixed, on Linux linker marking entire executable as having an executable stack.
- Fixed, for Argon2 algorithms command line options like `--threads` was ignored.
- Fixed command line options for single pool, free order allowed again.
# v3.1.0
- [#1107](https://github.com/xmrig/xmrig/issues/1107#issuecomment-522235892) Added Argon2 algorithm family: `argon2/chukwa` and `argon2/wrkz`.
# v3.0.0
- **[#1111](https://github.com/xmrig/xmrig/pull/1111) Added RandomX (`rx/test`) algorithm for testing and benchmarking.**
- **[#1036](https://github.com/xmrig/xmrig/pull/1036) Added RandomWOW (`rx/wow`) algorithm for [Wownero](http://wownero.org/).**
- **[#1050](https://github.com/xmrig/xmrig/pull/1050) Added RandomXL (`rx/loki`) algorithm for [Loki](https://loki.network/).**
- **[#1077](https://github.com/xmrig/xmrig/issues/1077) Added NUMA support via hwloc**.
- **Added flexible [multi algorithm](doc/CPU.md) configuration.**
- **Added unlimited switching between incompatible algorithms, all mining options can be changed in runtime.**
- [#257](https://github.com/xmrig/xmrig-nvidia/pull/257) New logging subsystem, file and syslog now always without colors.
- [#314](https://github.com/xmrig/xmrig-proxy/issues/314) Added donate over proxy feature.
- [#1007](https://github.com/xmrig/xmrig/issues/1007) Old HTTP API backend based on libmicrohttpd, replaced to custom HTTP server (libuv + http_parser).
- [#1010](https://github.com/xmrig/xmrig/pull/1010#issuecomment-482632107) Added daemon support (solo mining).
- [#1066](https://github.com/xmrig/xmrig/issues/1066#issuecomment-518080529) Added error message if pool not ready for RandomX.
- [#1105](https://github.com/xmrig/xmrig/issues/1105) Improved auto configuration for `cn-pico` algorithm.
- Added commands `pause` and `resume` via JSON RPC 2.0 API (`POST /json_rpc`).
- Added command line option `--export-topology` for export hwloc topology to a XML file.
- Breaked backward compatibility with previous configs and command line, `variant` option replaced to `algo`, global option `algo` removed, all CPU related settings moved to `cpu` object.
- Options `av`, `safe` and `max-cpu-usage` removed.
- Algorithm `cn/msr` renamed to `cn/fast`.
- Algorithm `cn/xtl` removed.
- API endpoint `GET /1/threads` replaced to `GET /2/backends`.
- Added global uptime and extended connection information in API.
- API now return current algorithm.
# Previous versions
[doc/CHANGELOG_OLD.md](doc/CHANGELOG_OLD.md)

View File

@@ -15,6 +15,8 @@ option(WITH_TLS "Enable OpenSSL support" ON)
option(WITH_ASM "Enable ASM PoW implementations" ON)
option(WITH_EMBEDDED_CONFIG "Enable internal embedded JSON config" OFF)
option(WITH_OPENCL "Enable OpenCL backend" ON)
option(WITH_CUDA "Enable CUDA backend" ON)
option(WITH_NVML "Enable NVML (NVIDIA Management Library) support (only if CUDA backend enabled)" ON)
option(WITH_STRICT_CACHE "Enable strict checks for OpenCL cache" ON)
option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF)

View File

@@ -9,19 +9,15 @@
[![GitHub stars](https://img.shields.io/github/stars/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/network)
XMRig is a high performance RandomX and CryptoNight CPU miner, with official support for Windows.
XMRig High performance, open source, cross platform RandomX, CryptoNight and Argon2 CPU/GPU miner, with official support for Windows.
* This is the **CPU-mining** version, there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia) and [AMD GPU version]( https://github.com/xmrig/xmrig-amd).
## Mining backends
- **CPU** (x64/x86/ARM)
- **OpenCL** for AMD GPUs.
- **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda).
<img src="doc/screenshot.png" width="808" >
#### Table of contents
* [Download](#download)
* [Usage](#usage)
* [Build](https://github.com/xmrig/xmrig/wiki/Build)
* [Donations](#donations)
* [Contacts](#contacts)
## Download
* Binary releases: https://github.com/xmrig/xmrig/releases
* Git tree: https://github.com/xmrig/xmrig.git
@@ -30,6 +26,9 @@ XMRig is a high performance RandomX and CryptoNight CPU miner, with official sup
## Usage
The preferred way to configure the miner is the [JSON config file](src/config.json) as it is more flexible and human friendly. The command line interface does not cover all features, such as mining profiles for different algorithms. Important options can be changed during runtime without miner restart by editing the config file or executing API calls.
* **[xmrig.com/wizard](https://xmrig.com/wizard)** helps you create initial configuration for the miner.
* **[workers.xmrig.info](http://workers.xmrig.info)** helps manage your miners via HTTP API.
### Command line options
```
Network:
@@ -64,6 +63,7 @@ CPU backend:
--asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer
--randomx-init=N threads count to initialize RandomX dataset
--randomx-no-numa disable NUMA support for RandomX
--randomx-mode=MODE RandomX mode: auto, fast, light
API:
--api-worker-id=ID custom worker-id for API
@@ -75,15 +75,25 @@ API:
OpenCL backend:
--opencl enable OpenCL mining backend
--opencl-devices=N list of OpenCL devices to use
--opencl-devices=N comma separated list of OpenCL devices to use
--opencl-platform=N OpenCL platform index or name
--opencl-loader=N path to OpenCL-ICD-Loader (OpenCL.dll or libOpenCL.so)
--opencl-loader=PATH path to OpenCL-ICD-Loader (OpenCL.dll or libOpenCL.so)
--opencl-no-cache disable OpenCL cache
--print-platforms print available OpenCL platforms and exit
CUDA backend:
--cuda enable CUDA mining backend
--cuda-loader=PATH path to CUDA plugin (xmrig-cuda.dll or libxmrig-cuda.so)
--cuda-devices=N comma separated list of CUDA devices to use
--cuda-bfactor-hint=N bfactor hint for autoconfig (0-12)
--cuda-bsleep-hint=N bsleep hint for autoconfig
--no-nvml disable NVML (NVIDIA Management Library) support
Logging:
-S, --syslog use system log for output messages
-l, --log-file=FILE log all output to a file
--print-time=N print hashrate report every N seconds
--health-print-time=N print health report every N seconds
--no-color disable colored output
Misc:

View File

@@ -6,6 +6,8 @@ if (WITH_TLS)
set(OPENSSL_MSVC_STATIC_RT TRUE)
set(EXTRA_LIBS ${EXTRA_LIBS} Crypt32)
elseif (APPLE)
set(OPENSSL_USE_STATIC_LIBS TRUE)
endif()
find_package(OpenSSL)

View File

@@ -54,6 +54,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-2")
add_definitions(/DHAVE_BUILTIN_CLEAR_CACHE)
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")

View File

@@ -1,3 +1,116 @@
# v4.6.2-beta
- [#1274](https://github.com/xmrig/xmrig/issues/1274) Added `--cuda-devices` command line option.
- [#1277](https://github.com/xmrig/xmrig/pull/1277) Fixed function names for clang on Apple.
# v4.6.1-beta
- [#1272](https://github.com/xmrig/xmrig/pull/1272) Optimized hashrate calculation.
- [#1273](https://github.com/xmrig/xmrig/issues/1273) Fixed crash when use `GET /2/backends` API endpoint with disabled CUDA.
# v4.6.0-beta
- [#1263](https://github.com/xmrig/xmrig/pull/1263) Added new option `dataset_host` for NVIDIA GPUs with less than 4 GB memory (RandomX only).
# v4.5.0-beta
- Added NVIDIA CUDA support via external [CUDA plugun](https://github.com/xmrig/xmrig-cuda). XMRig now is unified 3 in 1 miner.
# v4.4.0-beta
- [#1068](https://github.com/xmrig/xmrig/pull/1068) Added support for `self-select` stratum protocol extension.
- [#1240](https://github.com/xmrig/xmrig/pull/1240) Sync with the latest RandomX code.
- [#1241](https://github.com/xmrig/xmrig/issues/1241) Fixed regression with colors on old Windows systems.
- [#1243](https://github.com/xmrig/xmrig/pull/1243) Fixed incorrect OpenCL memory size detection in some cases.
- [#1247](https://github.com/xmrig/xmrig/pull/1247) Fixed ARM64 RandomX code alignment.
- [#1248](https://github.com/xmrig/xmrig/pull/1248) Fixed RandomX code cache cleanup on iOS/Darwin.
# v4.3.1-beta
- Fixed regression in v4.3.0, miner didn't create `cn` mining profile with default config example.
# v4.3.0-beta
- [#1227](https://github.com/xmrig/xmrig/pull/1227) Added new algorithm `rx/arq`, RandomX variant for upcoming ArQmA fork.
- [#808](https://github.com/xmrig/xmrig/issues/808#issuecomment-539297156) Added experimental support for persistent memory for CPU mining threads.
- [#1221](https://github.com/xmrig/xmrig/issues/1221) Improved RandomX dataset memory usage and initialization speed for NUMA machines.
# v4.2.1-beta
- [#1150](https://github.com/xmrig/xmrig/issues/1150) Fixed build on FreeBSD.
- [#1175](https://github.com/xmrig/xmrig/issues/1175) Fixed support for systems where total count of NUMA nodes not equal usable nodes count.
- [#1199](https://github.com/xmrig/xmrig/issues/1199) Fixed excessive memory allocation for OpenCL threads with low intensity.
- [#1212](https://github.com/xmrig/xmrig/issues/1212) Fixed low RandomX performance after fast algorithm switching.
# v4.2.0-beta
- [#1202](https://github.com/xmrig/xmrig/issues/1202) Fixed algorithm verification in donate strategy.
- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork.
- Added config option `cpu/max-threads-hint` and command line option `--cpu-max-threads-hint`.
# v4.1.0-beta
- **OpenCL backend disabled by default.**.
- [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd.
- [#1185](https://github.com/xmrig/xmrig/pull/1185) Added JIT compiler for RandomX on ARMv8.
- Improved API endpoint `GET /2/backends` and added support for this endpoint to [workers.xmrig.info](http://workers.xmrig.info).
- Added command line option `--no-cpu` to disable CPU backend.
- Added OpenCL specific command line options: `--opencl`, `--opencl-devices`, `--opencl-platform`, `--opencl-loader` and `--opencl-no-cache`.
- Removed command line option `--http-enabled`, HTTP API enabled automatically if any other `--http-*` option provided.
# v4.0.1-beta
- [#1177](https://github.com/xmrig/xmrig/issues/1177) Fixed compatibility with old AMD drivers.
- [#1180](https://github.com/xmrig/xmrig/issues/1180) Fixed possible duplicated shares after algorithm switching.
- Added support for case if not all backend threads successfully started.
- Fixed wrong config file permissions after write (only gcc builds on recent Windows 10 affected).
# v4.0.0-beta
- [#1172](https://github.com/xmrig/xmrig/issues/1172) **Added OpenCL mining backend.**
- [#268](https://github.com/xmrig/xmrig-amd/pull/268) [#270](https://github.com/xmrig/xmrig-amd/pull/270) [#271](https://github.com/xmrig/xmrig-amd/pull/271) [#273](https://github.com/xmrig/xmrig-amd/pull/273) [#274](https://github.com/xmrig/xmrig-amd/pull/274) [#1171](https://github.com/xmrig/xmrig/pull/1171) Added RandomX support for OpenCL, thanks [@SChernykh](https://github.com/SChernykh).
- Algorithm `cn/wow` removed, as no longer alive.
# v3.2.0
- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork.
- [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd.
# v3.1.3
- [#1180](https://github.com/xmrig/xmrig/issues/1180) Fixed possible duplicated shares after algorithm switching.
- Fixed wrong config file permissions after write (only gcc builds on recent Windows 10 affected).
# v3.1.2
- Many RandomX optimizations and fixes.
- [#1132](https://github.com/xmrig/xmrig/issues/1132) Fixed build on CentOS 7.
- [#1163](https://github.com/xmrig/xmrig/pull/1163) Optimized soft AES code, up to +30% hashrate on CPU without AES support and other optimizations.
- [#1166](https://github.com/xmrig/xmrig/pull/1166) Fixed crash when initialize dataset with big threads count (eg 272).
- [#1168](https://github.com/xmrig/xmrig/pull/1168) Optimized loading from scratchpad.
- [#1128](https://github.com/xmrig/xmrig/issues/1128) Fixed CMake 2.8 compatibility.
# v3.1.1
- [#1133](https://github.com/xmrig/xmrig/issues/1133) Fixed syslog regression.
- [#1138](https://github.com/xmrig/xmrig/issues/1138) Fixed multiple network bugs.
- [#1141](https://github.com/xmrig/xmrig/issues/1141) Fixed log in background mode.
- [#1142](https://github.com/xmrig/xmrig/pull/1142) RandomX hashrate improved by 0.5-1.5% depending on variant and CPU.
- [#1146](https://github.com/xmrig/xmrig/pull/1146) Fixed race condition in RandomX thread init.
- [#1148](https://github.com/xmrig/xmrig/pull/1148) Fixed, on Linux linker marking entire executable as having an executable stack.
- Fixed, for Argon2 algorithms command line options like `--threads` was ignored.
- Fixed command line options for single pool, free order allowed again.
# v3.1.0
- [#1107](https://github.com/xmrig/xmrig/issues/1107#issuecomment-522235892) Added Argon2 algorithm family: `argon2/chukwa` and `argon2/wrkz`.
# v3.0.0
- **[#1111](https://github.com/xmrig/xmrig/pull/1111) Added RandomX (`rx/test`) algorithm for testing and benchmarking.**
- **[#1036](https://github.com/xmrig/xmrig/pull/1036) Added RandomWOW (`rx/wow`) algorithm for [Wownero](http://wownero.org/).**
- **[#1050](https://github.com/xmrig/xmrig/pull/1050) Added RandomXL (`rx/loki`) algorithm for [Loki](https://loki.network/).**
- **[#1077](https://github.com/xmrig/xmrig/issues/1077) Added NUMA support via hwloc**.
- **Added flexible [multi algorithm](doc/CPU.md) configuration.**
- **Added unlimited switching between incompatible algorithms, all mining options can be changed in runtime.**
- [#257](https://github.com/xmrig/xmrig-nvidia/pull/257) New logging subsystem, file and syslog now always without colors.
- [#314](https://github.com/xmrig/xmrig-proxy/issues/314) Added donate over proxy feature.
- [#1007](https://github.com/xmrig/xmrig/issues/1007) Old HTTP API backend based on libmicrohttpd, replaced to custom HTTP server (libuv + http_parser).
- [#1010](https://github.com/xmrig/xmrig/pull/1010#issuecomment-482632107) Added daemon support (solo mining).
- [#1066](https://github.com/xmrig/xmrig/issues/1066#issuecomment-518080529) Added error message if pool not ready for RandomX.
- [#1105](https://github.com/xmrig/xmrig/issues/1105) Improved auto configuration for `cn-pico` algorithm.
- Added commands `pause` and `resume` via JSON RPC 2.0 API (`POST /json_rpc`).
- Added command line option `--export-topology` for export hwloc topology to a XML file.
- Breaked backward compatibility with previous configs and command line, `variant` option replaced to `algo`, global option `algo` removed, all CPU related settings moved to `cpu` object.
- Options `av`, `safe` and `max-cpu-usage` removed.
- Algorithm `cn/msr` renamed to `cn/fast`.
- Algorithm `cn/xtl` removed.
- API endpoint `GET /1/threads` replaced to `GET /2/backends`.
- Added global uptime and extended connection information in API.
- API now return current algorithm.
# v2.99.6-beta
- Added commands `pause` and `resume` via JSON RPC 2.0 API (`POST /json_rpc`).
- Fixed autoconfig regression (since 2.99.5), mostly `rx/wow` was affected by this bug.

View File

@@ -1,5 +1,5 @@
# CMake options
This document contains list of useful cmake options.
**Recent version of this document: https://xmrig.com/docs/miner/cmake-options**
## Algorithms
@@ -21,6 +21,8 @@ This feature add external dependency to libhwloc (1.10.0+) (except MSVC builds).
* **`-DWITH_TLS=OFF`** disable SSL/TLS support (secure connections to pool). This feature add external dependency to OpenSSL.
* **`-DWITH_ASM=OFF`** disable assembly optimizations for modern CryptoNight algorithms.
* **`-DWITH_EMBEDDED_CONFIG=ON`** Enable [embedded](https://github.com/xmrig/xmrig/issues/957) config support.
* **`-DWITH_OPENCL=OFF`** Disable OpenCL backend.
* **`-DWITH_CUDA=OFF`** Disable CUDA backend.
## Debug options
@@ -30,7 +32,7 @@ This feature add external dependency to libhwloc (1.10.0+) (except MSVC builds).
## Special build options
* **`-DXMRIG_DEPS=<path>`** path to precompiled dependensices https://github.com/xmrig/xmrig-deps
* **`-DXMRIG_DEPS=<path>`** path to precompiled dependencies https://github.com/xmrig/xmrig-deps
* **`-DARM_TARGET=<number>`** override ARM target, possible values `7` (ARMv7) and `8` (ARMv8).
* **`-DUV_INCLUDE_DIR=<path>`** custom path to libuv headers.
* **`-DUV_LIBRARY=<path>`** custom path to libuv library.

30
doc/gpg_keys/xmrig.asc Normal file
View File

@@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBF3VSRIBCADfFjDUbq0WLGulFeSou0A+jTvweNllPyLNOn3SNCC0XLEYyEcu
JiEBK80DlvR06TVr8Aw1rT5S2iH0i5Tl8DqShH2mmcN1rBp1M0Y95D89KVj3BIhE
nxmgmD4N3Wgm+5FmEH4W/RpG1xdYWJx3eJhtWPdFJqpg083E2D5P30wIQem+EnTR
5YrtTZPh5cPj2KRY+UmsDE3ahmxCgP7LYgnnpZQlWBBiMV932s7MvYBPJQc1wecS
0wi1zxyS81xHc3839EkA7wueCeNo+5jha+KH66tMKsfrI2WvfPHTCPjK9v7WJc/O
/eRp9d+wacn09D1L6CoRO0ers5p10GO84VhTABEBAAG0GVhNUmlnIDxzdXBwb3J0
QHhtcmlnLmNvbT6JAU4EEwEIADgWIQSaxM6o5m41pcfN3BtEalNji+lECQUCXdVJ
EgIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRBEalNji+lECbkQB/9nRou0
tOlBwYn8xVgBu7IiDWNVETRWfrjrtdTvSahgbbo6lWgjA/vBLkjN9fISdBQ/n/Mt
hNDJbEtxHHt2baJhvT8du1eWcIHHXCV/rmv+iY/hTXa1gKqHiHDJrtYSVBG3BMme
1rdsUHTiKf3t5yRHOXAfY2C+XNblKAV7mhlxQBiKxdFDIkFEQKNrHNUvnzkOqoCT
2kTZZ2tPUMQdOn1eek6zG/+C7SwcBpJnakJ8jce4yA/xZbOVKetNWO3Ufu3TE34k
OdA+H4PU9+fV77XfOY8DtXeS3boUI97ei+4s/mwX/NFC0i8CPXyefxl3WRUBGDOI
w//kPNQVh4HobOCeuQENBF3VSRIBCADl29WorEi+vRA/3kg9VUXtxSU6caibFS3N
VXANiFRjrOmICdfrIgOSGNrYCQFsXu0Xe0udDYVX8yX6WJk+CT02Pdg0gkXiKoze
KrnK15mo3xXbb2tr1o9ROPgwY/o2AwQHj0o1JhdS2cybfuRiUQRoGgBX7a9X0cTY
r4ZJvOjzgAajl3ciwB3yWUmDiRlzZpO7YWESXbOhGVzyCnP5MlMEJ/fPRw9h38vK
HNKLhzcRfsLpXk34ghY3SxIv4NWUfuZXFWqpSdC9JgNc5zA72lJEQcF4DHJCKl7B
ddmrfsr9mdiIpo+/ZZFPPngdeZ2kvkJ2YKaZNVu2XooJARPQ8B8tABEBAAGJATYE
GAEIACAWIQSaxM6o5m41pcfN3BtEalNji+lECQUCXdVJEgIbDAAKCRBEalNji+lE
CdPUB/4nH1IdhHGmfko2kxdaHqQgCGLqh3pcrQXD9mBv/LYVnoHZpVRHsIDgg2Z4
lQYrIRRqe69FjVxo7sA2eMIlV0GRDlUrw+HeURFpEhKPEdwFy6i/cti2MY0YxOrB
TvQoRutUoMnyjM4TBJWaaqccbTsavMdLmG3JHdAkiHtUis/fUwVctmEQwN+d/J2b
wJAtliqw3nXchUfdIfwHF/7hg8seUuYUaifzkazBZhVWvRkTVLVanzZ51HRfuzwD
ntaa7kfYGdE+4TKOylAPh+8E6WnR19RRTpsaW0dVBgOiBTE0uc7rUv2HWS/u6RUR
t7ldSBzkuDTlM2V59Iq2hXoSC6dT
=cIG9
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,5 @@
6bb1a2e3a0fbca5195be6022f2a9fbff8a353c37c7542e7ab89420cb45b64505 xmrig-5.0.1-gcc-win32.zip
24dba9ec281acfb2ea2c401ebd0e4e2d1f1ee5fd557da5ff3c7049020c1f78b6 xmrig-5.0.1-gcc-win64.zip
86d65c6693ec9e35cd7547329580638b85c9eb0cf8383892a1c15199de5b556f xmrig-5.0.1-msvc-cuda10_1-win64.zip
0fbfe518b1c4b6993b0f66ff01302626375b15620ccf8f64d6fb97845068ffca xmrig-5.0.1-msvc-win64.zip
aa34890738a3494de2fa0e44db346937fea7339852f5f10b5d4655f95e2d8f1f xmrig-5.0.1-xenial-x64.tar.gz

View File

@@ -0,0 +1,11 @@
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEmsTOqOZuNaXHzdwbRGpTY4vpRAkFAl3VcsoACgkQRGpTY4vp
RAm9vQgA1MyTUU2jley2TCYLUzQy2Fffc8fbXYv64r44jbWOjC/6qo2iIlRgPhIc
oVyPKr5TYS3QjDzCEm8IvozS0YudS6soESbPzqDonboK8pd0K4bsML9TQY2feV7A
NL5vln0rfVHp1wxLLrQpfBqAgvJUXEyaHece6gFQN79JOGhEo2bHL2NyrOl+FViS
b2BaMtXq410Fh+XT6ShnOaG/2EuO8ZqSGdCO6A/2LHQw1UY+mZiCvue6P6B06HmB
WD/urOv38V389v+V+Sp4UlEW6VpBOOjvtChoVWtLt+tKzydrnt2EmoWWWg475pka
4G6whHuMWS8CTt5/PDhJpvVXNQTIOw==
=C764
-----END PGP SIGNATURE-----

43
scripts/build_deps.sh Executable file
View File

@@ -0,0 +1,43 @@
#!/bin/bash -e
UV_VERSION="1.33.1"
OPENSSL_VERSION="1.1.1d"
HWLOC_VERSION="2.1.0"
mkdir deps
mkdir deps/include
mkdir deps/lib
mkdir build && cd build
wget https://github.com/libuv/libuv/archive/v${UV_VERSION}.tar.gz
tar -xzf v${UV_VERSION}.tar.gz
wget https://download.open-mpi.org/release/hwloc/v2.1/hwloc-${HWLOC_VERSION}.tar.bz2
tar -xjf hwloc-${HWLOC_VERSION}.tar.bz2
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
cd libuv-${UV_VERSION}
sh autogen.sh
./configure --disable-shared
make -j$(nproc)
cp -fr include/ ../../deps
cp .libs/libuv.a ../../deps/lib
cd ..
cd hwloc-${HWLOC_VERSION}
./configure --disable-shared --enable-static --disable-io --disable-libudev --disable-libxml2
make -j$(nproc)
cp -fr include/ ../../deps
cp hwloc/.libs/libhwloc.a ../../deps/lib
cd ..
cd openssl-${OPENSSL_VERSION}
./config -no-shared -no-asm -no-zlib -no-comp -no-dgram -no-filenames -no-cms
make -j$(nproc)
cp -fr include/ ../../deps
cp libcrypto.a ../../deps/lib
cp libssl.a ../../deps/lib
cd ../..

View File

@@ -2,7 +2,8 @@
function opencl_minify(input)
{
let out = input.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); // comments
let out = input.replace(/\r/g, '');
out = out.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, ''); // comments
out = out.replace(/^#\s+/gm, '#'); // macros with spaces
out = out.replace(/\n{2,}/g, '\n'); // empty lines
out = out.replace(/^\s+/gm, ''); // leading whitespace
@@ -10,7 +11,7 @@ function opencl_minify(input)
let array = out.split('\n').map(line => {
if (line[0] === '#') {
return line
return line;
}
line = line.replace(/, /g, ',');

View File

@@ -33,6 +33,7 @@
#include "base/io/Console.h"
#include "base/io/log/Log.h"
#include "base/kernel/Signals.h"
#include "base/kernel/Platform.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "core/Miner.h"
@@ -89,6 +90,8 @@ int xmrig::App::exec()
m_controller->start();
Platform::setThreadPriority(5);
rc = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
@@ -98,29 +101,12 @@ int xmrig::App::exec()
void xmrig::App::onConsoleCommand(char command)
{
switch (command) {
case 'h':
case 'H':
m_controller->miner()->printHashrate(true);
break;
case 'p':
case 'P':
m_controller->miner()->setEnabled(false);
break;
case 'r':
case 'R':
m_controller->miner()->setEnabled(true);
break;
case 3:
if (command == 3) {
LOG_WARN("Ctrl+C received, exiting");
close();
break;
default:
break;
}
else {
m_controller->miner()->execCommand(command);
}
}

View File

@@ -23,8 +23,8 @@
*/
#include <inttypes.h>
#include <stdio.h>
#include <cinttypes>
#include <cstdio>
#include <uv.h>
@@ -59,10 +59,10 @@ inline static const char *asmName(Assembly::Id assembly)
#endif
static void print_memory(Config *) {
static void print_memory(Config *config) {
# ifdef _WIN32
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s",
"HUGE PAGES", VirtualMemory::isHugepagesAvailable() ? GREEN_BOLD("permission granted") : RED_BOLD("unavailable"));
"HUGE PAGES", config->cpu().isHugePages() ? (VirtualMemory::isHugepagesAvailable() ? GREEN_BOLD("permission granted") : RED_BOLD("unavailable")) : RED_BOLD("disabled"));
# endif
}
@@ -102,6 +102,23 @@ static void print_cpu(Config *)
}
static void print_memory()
{
constexpr size_t oneGiB = 1024U * 1024U * 1024U;
const auto freeMem = static_cast<double>(uv_get_free_memory());
const auto totalMem = static_cast<double>(uv_get_total_memory());
const double percent = freeMem > 0 ? ((totalMem - freeMem) / totalMem * 100.0) : 100.0;
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%.1f/%.1f GB") BLACK_BOLD(" (%.0f%%)"),
"MEMORY",
(totalMem - freeMem) / oneGiB,
totalMem / oneGiB,
percent
);
}
static void print_threads(Config *config)
{
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s%d%%"),
@@ -126,9 +143,9 @@ static void print_threads(Config *config)
static void print_commands(Config *)
{
if (Log::colors) {
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BOLD("h") WHITE_BOLD("ashrate, ")
MAGENTA_BOLD("p") WHITE_BOLD("ause, ")
MAGENTA_BOLD("r") WHITE_BOLD("esume"));
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("COMMANDS ") MAGENTA_BG(WHITE_BOLD_S "h") WHITE_BOLD("ashrate, ")
MAGENTA_BG(WHITE_BOLD_S "p") WHITE_BOLD("ause, ")
MAGENTA_BG(WHITE_BOLD_S "r") WHITE_BOLD("esume"));
}
else {
Log::print(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume");
@@ -144,6 +161,7 @@ void xmrig::Summary::print(Controller *controller)
controller->config()->printVersions();
print_memory(controller->config());
print_cpu(controller->config());
print_memory();
print_threads(controller->config());
controller->config()->pools().print();

View File

@@ -1,5 +1,6 @@
include (src/backend/cpu/cpu.cmake)
include (src/backend/opencl/opencl.cmake)
include (src/backend/cuda/cuda.cmake)
include (src/backend/common/common.cmake)
@@ -7,10 +8,12 @@ set(HEADERS_BACKEND
"${HEADERS_BACKEND_COMMON}"
"${HEADERS_BACKEND_CPU}"
"${HEADERS_BACKEND_OPENCL}"
"${HEADERS_BACKEND_CUDA}"
)
set(SOURCES_BACKEND
"${SOURCES_BACKEND_COMMON}"
"${SOURCES_BACKEND_CPU}"
"${SOURCES_BACKEND_OPENCL}"
"${SOURCES_BACKEND_CUDA}"
)

View File

@@ -47,7 +47,6 @@ inline static const char *format(double h, char *buf, size_t size)
xmrig::Hashrate::Hashrate(size_t threads) :
m_highest(0.0),
m_threads(threads)
{
m_counts = new uint64_t*[threads];
@@ -100,30 +99,30 @@ double xmrig::Hashrate::calc(size_t threadId, size_t ms) const
uint64_t earliestHashCount = 0;
uint64_t earliestStamp = 0;
uint64_t lastestStamp = 0;
uint64_t lastestHashCnt = 0;
bool haveFullSet = false;
for (size_t i = 1; i < kBucketSize; i++) {
const size_t idx = (m_top[threadId] - i) & kBucketMask;
const uint64_t timeStampLimit = xmrig::Chrono::highResolutionMSecs() - ms;
uint64_t* timestamps = m_timestamps[threadId];
uint64_t* counts = m_counts[threadId];
if (m_timestamps[threadId][idx] == 0) {
const size_t idx_start = (m_top[threadId] - 1) & kBucketMask;
size_t idx = idx_start;
uint64_t lastestStamp = timestamps[idx];
uint64_t lastestHashCnt = counts[idx];
do {
if (timestamps[idx] < timeStampLimit) {
haveFullSet = (timestamps[idx] != 0);
if (idx != idx_start) {
idx = (idx + 1) & kBucketMask;
earliestStamp = timestamps[idx];
earliestHashCount = counts[idx];
}
break;
}
if (lastestStamp == 0) {
lastestStamp = m_timestamps[threadId][idx];
lastestHashCnt = m_counts[threadId][idx];
}
if (xmrig::Chrono::highResolutionMSecs() - m_timestamps[threadId][idx] > ms) {
haveFullSet = true;
break;
}
earliestStamp = m_timestamps[threadId][idx];
earliestHashCount = m_counts[threadId][idx];
}
idx = (idx - 1) & kBucketMask;
} while (idx != idx_start);
if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) {
return nan("");
@@ -150,15 +149,6 @@ void xmrig::Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp)
}
void xmrig::Hashrate::updateHighest()
{
double highest = calc(ShortInterval);
if (std::isnormal(highest) && highest > m_highest) {
m_highest = highest;
}
}
const char *xmrig::Hashrate::format(double h, char *buf, size_t size)
{
return ::format(h, buf, size);

View File

@@ -53,9 +53,7 @@ public:
double calc(size_t ms) const;
double calc(size_t threadId, size_t ms) const;
void add(size_t threadId, uint64_t count, uint64_t timestamp);
void updateHighest();
inline double highest() const { return m_highest; }
inline size_t threads() const { return m_threads; }
static const char *format(double h, char *buf, size_t size);
@@ -70,7 +68,6 @@ private:
constexpr static size_t kBucketSize = 2 << 11;
constexpr static size_t kBucketMask = kBucketSize - 1;
double m_highest;
size_t m_threads;
uint32_t* m_top;
uint64_t** m_counts;

View File

@@ -27,10 +27,15 @@
#define XMRIG_TAGS_H
#include <cstdint>
namespace xmrig {
const char *backend_tag(uint32_t backend);
const char *cpu_tag();
const char *net_tag();
#ifdef XMRIG_FEATURE_OPENCL
@@ -38,6 +43,12 @@ const char *ocl_tag();
#endif
#ifdef XMRIG_FEATURE_CUDA
const char *cuda_tag();
#endif
#ifdef XMRIG_ALGO_RANDOMX
const char *rx_tag();
#endif

View File

@@ -34,6 +34,11 @@
#endif
#ifdef XMRIG_FEATURE_CUDA
# include "backend/cuda/CudaThreads.h"
#endif
namespace xmrig {
@@ -167,4 +172,8 @@ template class Threads<CpuThreads>;
template class Threads<OclThreads>;
#endif
#ifdef XMRIG_FEATURE_CUDA
template class Threads<CudaThreads>;
#endif
} // namespace xmrig

View File

@@ -26,7 +26,7 @@
#define XMRIG_WORKERJOB_H
#include <string.h>
#include <cstring>
#include "base/net/stratum/Job.h"
@@ -47,9 +47,9 @@ public:
inline uint8_t index() const { return m_index; }
inline void add(const Job &job, uint64_t sequence, uint32_t reserveCount)
inline void add(const Job &job, uint32_t reserveCount, Nonce::Backend backend)
{
m_sequence = sequence;
m_sequence = Nonce::sequence(backend);
if (currentJob() == job) {
return;
@@ -60,7 +60,7 @@ public:
return;
}
save(job, reserveCount);
save(job, reserveCount, backend);
}
@@ -82,13 +82,15 @@ public:
private:
inline void save(const Job &job, uint32_t reserveCount)
inline void save(const Job &job, uint32_t reserveCount, Nonce::Backend backend)
{
m_index = job.index();
const size_t size = job.size();
m_jobs[index()] = job;
m_rounds[index()] = 0;
m_jobs[index()].setBackend(backend);
for (size_t i = 0; i < N; ++i) {
memcpy(m_blobs[index()] + (i * size), job.blob(), size);
*nonce(i) = Nonce::next(index(), *nonce(i), reserveCount, job.isNicehash());
@@ -96,7 +98,7 @@ private:
}
alignas(16) uint8_t m_blobs[2][Job::kMaxBlobSize * N];
alignas(16) uint8_t m_blobs[2][Job::kMaxBlobSize * N]{};
Job m_jobs[2];
uint32_t m_rounds[2] = { 0, 0 };
uint64_t m_sequence = 0;
@@ -126,12 +128,14 @@ inline void xmrig::WorkerJob<1>::nextRound(uint32_t rounds, uint32_t roundSize)
template<>
inline void xmrig::WorkerJob<1>::save(const Job &job, uint32_t reserveCount)
inline void xmrig::WorkerJob<1>::save(const Job &job, uint32_t reserveCount, Nonce::Backend backend)
{
m_index = job.index();
m_jobs[index()] = job;
m_rounds[index()] = 0;
m_jobs[index()].setBackend(backend);
memcpy(blob(), job.blob(), job.size());
*nonce() = Nonce::next(index(), *nonce(), reserveCount, currentJob().isNicehash());
}

View File

@@ -37,6 +37,11 @@
#endif
#ifdef XMRIG_FEATURE_CUDA
# include "backend/cuda/CudaWorker.h"
#endif
namespace xmrig {
@@ -104,6 +109,11 @@ void xmrig::Workers<T>::start(const std::vector<T> &data)
for (Thread<T> *worker : m_workers) {
worker->start(Workers<T>::onReady);
// This sleep is important for optimal caching!
// Threads must allocate scratchpads in order so that adjacent cores will use adjacent scratchpads
// Sub-optimal caching can result in up to 0.5% hashrate penalty
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
@@ -139,8 +149,6 @@ void xmrig::Workers<T>::tick(uint64_t)
d_ptr->hashrate->add(handle->id(), handle->worker()->hashCount(), handle->worker()->timestamp());
}
d_ptr->hashrate->updateHighest();
}
@@ -160,7 +168,7 @@ void xmrig::Workers<T>::onReady(void *arg)
assert(worker != nullptr);
if (!worker || !worker->selfTest()) {
LOG_ERR("%s " RED("thread ") RED_BOLD("#%zu") RED(" self-test failed"), T::tag(), worker->id());
LOG_ERR("%s " RED("thread ") RED_BOLD("#%zu") RED(" self-test failed"), T::tag(), worker ? worker->id() : 0);
handle->backend()->start(worker, false);
delete worker;
@@ -217,4 +225,16 @@ template class Workers<OclLaunchData>;
#endif
#ifdef XMRIG_FEATURE_CUDA
template<>
xmrig::IWorker *xmrig::Workers<CudaLaunchData>::create(Thread<CudaLaunchData> *handle)
{
return new CudaWorker(handle->id(), handle->config());
}
template class Workers<CudaLaunchData>;
#endif
} // namespace xmrig

View File

@@ -37,6 +37,11 @@
#endif
#ifdef XMRIG_FEATURE_CUDA
# include "backend/cuda/CudaLaunchData.h"
#endif
namespace xmrig {
@@ -80,6 +85,13 @@ extern template class Workers<OclLaunchData>;
#endif
#ifdef XMRIG_FEATURE_CUDA
template<>
IWorker *Workers<CudaLaunchData>::create(Thread<CudaLaunchData> *handle);
extern template class Workers<CudaLaunchData>;
#endif
} // namespace xmrig

View File

@@ -53,6 +53,7 @@ public:
virtual const Hashrate *hashrate() const = 0;
virtual const String &profileName() const = 0;
virtual const String &type() const = 0;
virtual void execCommand(char command) = 0;
virtual void prepare(const Job &nextJob) = 0;
virtual void printHashrate(bool details) = 0;
virtual void setJob(const Job &job) = 0;

View File

@@ -24,6 +24,9 @@
#define XMRIG_IRXSTORAGE_H
#include "crypto/rx/RxConfig.h"
#include <cstdint>
#include <utility>
@@ -43,7 +46,7 @@ public:
virtual RxDataset *dataset(const Job &job, uint32_t nodeId) const = 0;
virtual std::pair<uint32_t, uint32_t> hugePages() const = 0;
virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages) = 0;
virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages, RxConfig::Mode mode) = 0;
};

View File

@@ -146,10 +146,11 @@ public:
inline void start()
{
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"),
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" thread%s)") " scratchpad " CYAN_BOLD("%zu KB"),
tag,
profileName.data(),
threads.size(),
threads.size() > 1 ? "s" : "",
algo.l3() / 1024
);
@@ -210,6 +211,24 @@ public:
} // namespace xmrig
const char *xmrig::backend_tag(uint32_t backend)
{
# ifdef XMRIG_FEATURE_OPENCL
if (backend == Nonce::OPENCL) {
return ocl_tag();
}
# endif
# ifdef XMRIG_FEATURE_CUDA
if (backend == Nonce::CUDA) {
return cuda_tag();
}
# endif
return tag;
}
const char *xmrig::cpu_tag()
{
return tag;

View File

@@ -50,6 +50,8 @@ public:
~CpuBackend() override;
protected:
inline void execCommand(char) override {}
bool isEnabled() const override;
bool isEnabled(const Algorithm &algorithm) const override;
const Hashrate *hashrate() const override;

View File

@@ -53,7 +53,7 @@ size_t inline generate<Algorithm::CN>(Threads<CpuThreads> &threads, uint32_t lim
{
size_t count = 0;
count += generate("cn", threads, Algorithm::CN_0, limit);
count += generate("cn", threads, Algorithm::CN_1, limit);
if (!threads.isExist(Algorithm::CN_0)) {
threads.disable(Algorithm::CN_0);

View File

@@ -185,8 +185,20 @@ void xmrig::CpuWorker<N>::start()
consumeJob();
}
uint64_t storeStatsMask = 7;
# ifdef XMRIG_ALGO_RANDOMX
bool first = true;
uint64_t tempHash[8] = {};
// RandomX is faster, we don't need to store stats so often
if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) {
storeStatsMask = 63;
}
# endif
while (!Nonce::isOutdated(Nonce::CPU, m_job.sequence())) {
if ((m_count & 0x7) == 0) {
if ((m_count & storeStatsMask) == 0) {
storeStats();
}
@@ -196,26 +208,34 @@ void xmrig::CpuWorker<N>::start()
break;
}
uint32_t current_job_nonces[N];
for (size_t i = 0; i < N; ++i) {
current_job_nonces[i] = *m_job.nonce(i);
}
# ifdef XMRIG_ALGO_RANDOMX
if (job.algorithm().family() == Algorithm::RANDOM_X) {
randomx_calculate_hash(m_vm->get(), m_job.blob(), job.size(), m_hash);
if (first) {
first = false;
randomx_calculate_hash_first(m_vm->get(), tempHash, m_job.blob(), job.size());
}
m_job.nextRound(kReserveCount, 1);
randomx_calculate_hash_next(m_vm->get(), tempHash, m_job.blob(), job.size(), m_hash);
}
else
# endif
{
fn(job.algorithm())(m_job.blob(), job.size(), m_hash, m_ctx, job.height());
m_job.nextRound(kReserveCount, 1);
}
for (size_t i = 0; i < N; ++i) {
if (*reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24) < job.target()) {
JobResults::submit(job, *m_job.nonce(i), m_hash + (i * 32));
JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32));
}
}
m_job.nextRound(kReserveCount, 1);
m_count += N;
std::this_thread::yield();
}
consumeJob();
@@ -303,7 +323,7 @@ void xmrig::CpuWorker<N>::consumeJob()
return;
}
m_job.add(m_miner->job(), Nonce::sequence(Nonce::CPU), kReserveCount);
m_job.add(m_miner->job(), kReserveCount, Nonce::CPU);
# ifdef XMRIG_ALGO_RANDOMX
if (m_job.currentJob().algorithm().family() == Algorithm::RANDOM_X) {

View File

@@ -0,0 +1,526 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include <mutex>
#include <string>
#include "backend/cuda/CudaBackend.h"
#include "backend/common/Hashrate.h"
#include "backend/common/interfaces/IWorker.h"
#include "backend/common/Tags.h"
#include "backend/common/Workers.h"
#include "backend/cuda/CudaConfig.h"
#include "backend/cuda/CudaThreads.h"
#include "backend/cuda/CudaWorker.h"
#include "backend/cuda/wrappers/CudaDevice.h"
#include "backend/cuda/wrappers/CudaLib.h"
#include "base/io/log/Log.h"
#include "base/net/stratum/Job.h"
#include "base/tools/Chrono.h"
#include "base/tools/String.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "rapidjson/document.h"
#ifdef XMRIG_FEATURE_API
# include "base/api/interfaces/IApiRequest.h"
#endif
#ifdef XMRIG_FEATURE_NVML
#include "backend/cuda/wrappers/NvmlLib.h"
namespace xmrig { static const char *kNvmlLabel = "NVML"; }
#endif
namespace xmrig {
extern template class Threads<CudaThreads>;
constexpr const size_t oneMiB = 1024U * 1024U;
static const char *kLabel = "CUDA";
static const char *tag = GREEN_BG_BOLD(WHITE_BOLD_S " nv ");
static const String kType = "cuda";
static std::mutex mutex;
static void printDisabled(const char *label, const char *reason)
{
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") RED_BOLD("disabled") "%s", label, reason);
}
struct CudaLaunchStatus
{
public:
inline size_t threads() const { return m_threads; }
inline bool started(bool ready)
{
ready ? m_started++ : m_errors++;
return (m_started + m_errors) == m_threads;
}
inline void start(size_t threads)
{
m_started = 0;
m_errors = 0;
m_threads = threads;
m_ts = Chrono::steadyMSecs();
CudaWorker::ready = false;
}
inline void print() const
{
if (m_started == 0) {
LOG_ERR("%s " RED_BOLD("disabled") YELLOW(" (failed to start threads)"), tag);
return;
}
LOG_INFO("%s" GREEN_BOLD(" READY") " threads " "%s%zu/%zu" BLACK_BOLD(" (%" PRIu64 " ms)"),
tag,
m_errors == 0 ? CYAN_BOLD_S : YELLOW_BOLD_S,
m_started,
m_threads,
Chrono::steadyMSecs() - m_ts
);
}
private:
size_t m_errors = 0;
size_t m_started = 0;
size_t m_threads = 0;
uint64_t m_ts = 0;
};
class CudaBackendPrivate
{
public:
inline CudaBackendPrivate(Controller *controller) :
controller(controller)
{
init(controller->config()->cuda());
}
void init(const CudaConfig &cuda)
{
if (!cuda.isEnabled()) {
return printDisabled(kLabel, "");
}
if (!CudaLib::init(cuda.loader())) {
return printDisabled(kLabel, RED_S " (failed to load CUDA plugin)");
}
runtimeVersion = CudaLib::runtimeVersion();
driverVersion = CudaLib::driverVersion();
if (!runtimeVersion || !driverVersion || !CudaLib::deviceCount()) {
return printDisabled(kLabel, RED_S " (no devices)");
}
if (!devices.empty()) {
return;
}
devices = CudaLib::devices(cuda.bfactor(), cuda.bsleep(), cuda.devicesHint());
if (devices.empty()) {
return printDisabled(kLabel, RED_S " (no devices)");
}
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") "/" WHITE_BOLD("%s") BLACK_BOLD("/%s"), kLabel,
CudaLib::version(runtimeVersion).c_str(), CudaLib::version(driverVersion).c_str(), CudaLib::pluginVersion());
# ifdef XMRIG_FEATURE_NVML
if (cuda.isNvmlEnabled()) {
if (NvmlLib::init(cuda.nvmlLoader())) {
NvmlLib::assign(devices);
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") WHITE_BOLD("%s") "/" GREEN_BOLD("%s") " press " MAGENTA_BG(WHITE_BOLD_S "e") " for health report",
kNvmlLabel,
NvmlLib::version(),
NvmlLib::driverVersion()
);
}
else {
printDisabled(kNvmlLabel, RED_S " (failed to load NVML)");
}
}
else {
printDisabled(kNvmlLabel, "");
}
# endif
for (const CudaDevice &device : devices) {
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") GREEN_BOLD(" %s ") WHITE_BOLD("%u/%u MHz") " smx:" WHITE_BOLD("%u") " arch:" WHITE_BOLD("%u%u") " mem:" CYAN("%zu/%zu") " MB",
"CUDA GPU",
device.index(),
device.topology().toString().data(),
device.name().data(),
device.clock(),
device.memoryClock(),
device.smx(),
device.computeCapability(true),
device.computeCapability(false),
device.freeMemSize() / oneMiB,
device.globalMemSize() / oneMiB);
}
}
inline void start(const Job &)
{
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" thread%s)") " scratchpad " CYAN_BOLD("%zu KB"),
tag,
profileName.data(),
threads.size(),
threads.size() > 1 ? "s" : "",
algo.l3() / 1024
);
Log::print(WHITE_BOLD("| # | GPU | BUS ID | I | T | B | BF | BS | MEM | NAME"));
size_t i = 0;
for (const auto &data : threads) {
Log::print("|" CYAN_BOLD("%3zu") " |" CYAN_BOLD("%4u") " |" YELLOW(" %7s") " |" CYAN_BOLD("%5d") " |" CYAN_BOLD("%4d") " |"
CYAN_BOLD("%4d") " |" CYAN_BOLD("%3d") " |" CYAN_BOLD("%4d") " |" CYAN("%5zu") " | " GREEN("%s"),
i,
data.thread.index(),
data.device.topology().toString().data(),
data.thread.threads() * data.thread.blocks(),
data.thread.threads(),
data.thread.blocks(),
data.thread.bfactor(),
data.thread.bsleep(),
(data.thread.threads() * data.thread.blocks()) * algo.l3() / oneMiB,
data.device.name().data()
);
i++;
}
status.start(threads.size());
workers.start(threads);
}
# ifdef XMRIG_FEATURE_NVML
void printHealth()
{
for (const auto &device : devices) {
const auto health = NvmlLib::health(device.nvmlDevice());
std::string clocks;
if (health.clock && health.memClock) {
clocks += " " + std::to_string(health.clock) + "/" + std::to_string(health.memClock) + " MHz";
}
std::string fans;
if (!health.fanSpeed.empty()) {
for (size_t i = 0; i < health.fanSpeed.size(); ++i) {
fans += " fan" + std::to_string(i) + ":" CYAN_BOLD_S + std::to_string(health.fanSpeed[i]) + "%" CLEAR;
}
}
LOG_INFO(CYAN_BOLD("#%u") YELLOW(" %s") MAGENTA_BOLD("%4uW") CSI "1;%um %2uC" CLEAR WHITE_BOLD("%s") "%s",
device.index(),
device.topology().toString().data(),
health.power,
health.temperature < 60 ? 32 : (health.temperature > 85 ? 31 : 33),
health.temperature,
clocks.c_str(),
fans.c_str()
);
}
}
# endif
Algorithm algo;
Controller *controller;
CudaLaunchStatus status;
std::vector<CudaDevice> devices;
std::vector<CudaLaunchData> threads;
String profileName;
uint32_t driverVersion = 0;
uint32_t runtimeVersion = 0;
Workers<CudaLaunchData> workers;
};
} // namespace xmrig
const char *xmrig::cuda_tag()
{
return tag;
}
xmrig::CudaBackend::CudaBackend(Controller *controller) :
d_ptr(new CudaBackendPrivate(controller))
{
d_ptr->workers.setBackend(this);
}
xmrig::CudaBackend::~CudaBackend()
{
delete d_ptr;
CudaLib::close();
# ifdef XMRIG_FEATURE_NVML
NvmlLib::close();
# endif
}
bool xmrig::CudaBackend::isEnabled() const
{
return d_ptr->controller->config()->cuda().isEnabled() && CudaLib::isInitialized() && !d_ptr->devices.empty();;
}
bool xmrig::CudaBackend::isEnabled(const Algorithm &algorithm) const
{
return !d_ptr->controller->config()->cuda().threads().get(algorithm).isEmpty();
}
const xmrig::Hashrate *xmrig::CudaBackend::hashrate() const
{
return d_ptr->workers.hashrate();
}
const xmrig::String &xmrig::CudaBackend::profileName() const
{
return d_ptr->profileName;
}
const xmrig::String &xmrig::CudaBackend::type() const
{
return kType;
}
void xmrig::CudaBackend::execCommand(char command)
{
# ifdef XMRIG_FEATURE_NVML
if (command == 'e' || command == 'E') {
d_ptr->printHealth();
}
# endif
}
void xmrig::CudaBackend::prepare(const Job &)
{
}
void xmrig::CudaBackend::printHashrate(bool details)
{
if (!details || !hashrate()) {
return;
}
char num[8 * 3] = { 0 };
Log::print(WHITE_BOLD_S "| CUDA # | AFFINITY | 10s H/s | 60s H/s | 15m H/s |");
size_t i = 0;
for (const auto &data : d_ptr->threads) {
Log::print("| %8zu | %8" PRId64 " | %7s | %7s | %7s |" CYAN_BOLD(" #%u") YELLOW(" %s") GREEN(" %s"),
i,
data.thread.affinity(),
Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval), num, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval), num + 8, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3),
data.device.index(),
data.device.topology().toString().data(),
data.device.name().data()
);
i++;
}
Log::print(WHITE_BOLD_S "| - | - | %7s | %7s | %7s |",
Hashrate::format(hashrate()->calc(Hashrate::ShortInterval), num, sizeof num / 3),
Hashrate::format(hashrate()->calc(Hashrate::MediumInterval), num + 8, sizeof num / 3),
Hashrate::format(hashrate()->calc(Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3)
);
}
void xmrig::CudaBackend::setJob(const Job &job)
{
const auto &cuda = d_ptr->controller->config()->cuda();
if (cuda.isEnabled()) {
d_ptr->init(cuda);
}
if (!isEnabled()) {
return stop();
}
auto threads = cuda.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->devices);
if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) {
return;
}
d_ptr->algo = job.algorithm();
d_ptr->profileName = cuda.threads().profileName(job.algorithm());
if (d_ptr->profileName.isNull() || threads.empty()) {
LOG_WARN("%s " RED_BOLD("disabled") YELLOW(" (no suitable configuration found)"), tag);
return stop();
}
stop();
d_ptr->threads = std::move(threads);
d_ptr->start(job);
}
void xmrig::CudaBackend::start(IWorker *worker, bool ready)
{
mutex.lock();
if (d_ptr->status.started(ready)) {
d_ptr->status.print();
CudaWorker::ready = true;
}
mutex.unlock();
if (ready) {
worker->start();
}
}
void xmrig::CudaBackend::stop()
{
if (d_ptr->threads.empty()) {
return;
}
const uint64_t ts = Chrono::steadyMSecs();
d_ptr->workers.stop();
d_ptr->threads.clear();
LOG_INFO("%s" YELLOW(" stopped") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
}
void xmrig::CudaBackend::tick(uint64_t ticks)
{
d_ptr->workers.tick(ticks);
# ifdef XMRIG_FEATURE_NVML
if (isEnabled()) {
auto seconds = d_ptr->controller->config()->healthPrintTime();
if (seconds && ticks && (ticks % (seconds * 2)) == 0) {
d_ptr->printHealth();
}
}
# endif
}
#ifdef XMRIG_FEATURE_API
rapidjson::Value xmrig::CudaBackend::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value out(kObjectType);
out.AddMember("type", type().toJSON(), allocator);
out.AddMember("enabled", isEnabled(), allocator);
out.AddMember("algo", d_ptr->algo.toJSON(), allocator);
out.AddMember("profile", profileName().toJSON(), allocator);
if (CudaLib::isReady()) {
Value versions(kObjectType);
versions.AddMember("cuda-runtime", Value(CudaLib::version(d_ptr->runtimeVersion).c_str(), allocator), allocator);
versions.AddMember("cuda-driver", Value(CudaLib::version(d_ptr->driverVersion).c_str(), allocator), allocator);
versions.AddMember("plugin", String(CudaLib::pluginVersion()).toJSON(doc), allocator);
# ifdef XMRIG_FEATURE_NVML
if (NvmlLib::isReady()) {
versions.AddMember("nvml", StringRef(NvmlLib::version()), allocator);
versions.AddMember("driver", StringRef(NvmlLib::driverVersion()), allocator);
}
# endif
out.AddMember("versions", versions, allocator);
}
if (d_ptr->threads.empty() || !hashrate()) {
return out;
}
out.AddMember("hashrate", hashrate()->toJSON(doc), allocator);
Value threads(kArrayType);
size_t i = 0;
for (const auto &data : d_ptr->threads) {
Value thread = data.thread.toJSON(doc);
thread.AddMember("hashrate", hashrate()->toJSON(i, doc), allocator);
data.device.toJSON(thread, doc);
i++;
threads.PushBack(thread, allocator);
}
out.AddMember("threads", threads, allocator);
return out;
}
void xmrig::CudaBackend::handleRequest(IApiRequest &)
{
}
#endif

View File

@@ -0,0 +1,80 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDABACKEND_H
#define XMRIG_CUDABACKEND_H
#include <utility>
#include "backend/common/interfaces/IBackend.h"
#include "base/tools/Object.h"
namespace xmrig {
class Controller;
class CudaBackendPrivate;
class Miner;
class CudaBackend : public IBackend
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(CudaBackend)
CudaBackend(Controller *controller);
~CudaBackend() override;
protected:
bool isEnabled() const override;
bool isEnabled(const Algorithm &algorithm) const override;
const Hashrate *hashrate() const override;
const String &profileName() const override;
const String &type() const override;
void execCommand(char command) override;
void prepare(const Job &nextJob) override;
void printHashrate(bool details) override;
void setJob(const Job &job) override;
void start(IWorker *worker, bool ready) override;
void stop() override;
void tick(uint64_t ticks) override;
# ifdef XMRIG_FEATURE_API
rapidjson::Value toJSON(rapidjson::Document &doc) const override;
void handleRequest(IApiRequest &request) override;
# endif
private:
CudaBackendPrivate *d_ptr;
};
} /* namespace xmrig */
#endif /* XMRIG_CUDABACKEND_H */

View File

@@ -0,0 +1,201 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/CudaConfig.h"
#include "backend/common/Tags.h"
#include "backend/cuda/CudaConfig_gen.h"
#include "backend/cuda/wrappers/CudaLib.h"
#include "base/io/json/Json.h"
#include "base/io/log/Log.h"
#include "rapidjson/document.h"
namespace xmrig {
static bool generated = false;
static const char *kBfactorHint = "bfactor-hint";
static const char *kBsleepHint = "bsleep-hint";
static const char *kDevicesHint = "devices-hint";
static const char *kEnabled = "enabled";
static const char *kLoader = "loader";
#ifdef XMRIG_FEATURE_NVML
static const char *kNvml = "nvml";
#endif
extern template class Threads<CudaThreads>;
}
rapidjson::Value xmrig::CudaConfig::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value obj(kObjectType);
obj.AddMember(StringRef(kEnabled), m_enabled, allocator);
obj.AddMember(StringRef(kLoader), m_loader.toJSON(), allocator);
# ifdef XMRIG_FEATURE_NVML
if (m_nvmlLoader.isNull()) {
obj.AddMember(StringRef(kNvml), m_nvml, allocator);
}
else {
obj.AddMember(StringRef(kNvml), m_nvmlLoader.toJSON(), allocator);
}
# endif
m_threads.toJSON(obj, doc);
return obj;
}
std::vector<xmrig::CudaLaunchData> xmrig::CudaConfig::get(const Miner *miner, const Algorithm &algorithm, const std::vector<CudaDevice> &devices) const
{
auto deviceIndex = [&devices](uint32_t index) -> int {
for (uint32_t i = 0; i < devices.size(); ++i) {
if (devices[i].index() == index) {
return i;
}
}
return -1;
};
std::vector<CudaLaunchData> out;
const auto &threads = m_threads.get(algorithm);
if (threads.isEmpty()) {
return out;
}
out.reserve(threads.count());
for (const auto &thread : threads.data()) {
const int index = deviceIndex(thread.index());
if (index == -1) {
LOG_INFO("%s" YELLOW(" skip non-existing device with index ") YELLOW_BOLD("%u"), cuda_tag(), thread.index());
continue;
}
out.emplace_back(miner, algorithm, thread, devices[static_cast<size_t>(index)]);
}
return out;
}
void xmrig::CudaConfig::read(const rapidjson::Value &value)
{
if (value.IsObject()) {
m_enabled = Json::getBool(value, kEnabled, m_enabled);
m_loader = Json::getString(value, kLoader);
m_bfactor = std::min(Json::getUint(value, kBfactorHint, m_bfactor), 12u);
m_bsleep = Json::getUint(value, kBsleepHint, m_bsleep);
setDevicesHint(Json::getString(value, kDevicesHint));
# ifdef XMRIG_FEATURE_NVML
auto &nvml = Json::getValue(value, kNvml);
if (nvml.IsString()) {
m_nvmlLoader = nvml.GetString();
}
else if (nvml.IsBool()) {
m_nvml = nvml.GetBool();
}
# endif
m_threads.read(value);
generate();
}
else if (value.IsBool()) {
m_enabled = value.GetBool();
generate();
}
else {
m_shouldSave = true;
generate();
}
}
void xmrig::CudaConfig::generate()
{
if (generated) {
return;
}
if (!isEnabled() || m_threads.has("*")) {
return;
}
if (!CudaLib::init(loader())) {
return;
}
if (!CudaLib::runtimeVersion() || !CudaLib::driverVersion() || !CudaLib::deviceCount()) {
return;
}
const auto devices = CudaLib::devices(bfactor(), bsleep(), m_devicesHint);
if (devices.empty()) {
return;
}
size_t count = 0;
count += xmrig::generate<Algorithm::CN>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_LITE>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_HEAVY>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_PICO>(m_threads, devices);
count += xmrig::generate<Algorithm::RANDOM_X>(m_threads, devices);
generated = true;
m_shouldSave = count > 0;
}
void xmrig::CudaConfig::setDevicesHint(const char *devicesHint)
{
if (devicesHint == nullptr) {
return;
}
const auto indexes = String(devicesHint).split(',');
m_devicesHint.reserve(indexes.size());
for (const auto &index : indexes) {
m_devicesHint.push_back(strtoul(index, nullptr, 10));
}
}

View File

@@ -0,0 +1,87 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDACONFIG_H
#define XMRIG_CUDACONFIG_H
#include "backend/cuda/CudaLaunchData.h"
#include "backend/common/Threads.h"
#include "backend/cuda/CudaThreads.h"
namespace xmrig {
class CudaConfig
{
public:
CudaConfig() = default;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
std::vector<CudaLaunchData> get(const Miner *miner, const Algorithm &algorithm, const std::vector<CudaDevice> &devices) const;
void read(const rapidjson::Value &value);
inline bool isEnabled() const { return m_enabled; }
inline bool isShouldSave() const { return m_shouldSave; }
inline const std::vector<uint32_t> &devicesHint() const { return m_devicesHint; }
inline const String &loader() const { return m_loader; }
inline const Threads<CudaThreads> &threads() const { return m_threads; }
inline int32_t bfactor() const { return m_bfactor; }
inline int32_t bsleep() const { return m_bsleep; }
# ifdef XMRIG_FEATURE_NVML
inline bool isNvmlEnabled() const { return m_nvml; }
inline const String &nvmlLoader() const { return m_nvmlLoader; }
# endif
private:
void generate();
void setDevicesHint(const char *devicesHint);
bool m_enabled = false;
bool m_shouldSave = false;
std::vector<uint32_t> m_devicesHint;
String m_loader;
Threads<CudaThreads> m_threads;
# ifdef _WIN32
int32_t m_bfactor = 6;
int32_t m_bsleep = 25;
# else
int32_t m_bfactor = 0;
int32_t m_bsleep = 0;
# endif
# ifdef XMRIG_FEATURE_NVML
bool m_nvml = true;
String m_nvmlLoader;
# endif
};
} /* namespace xmrig */
#endif /* XMRIG_CUDACONFIG_H */

View File

@@ -0,0 +1,137 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDACONFIG_GEN_H
#define XMRIG_CUDACONFIG_GEN_H
#include "backend/common/Threads.h"
#include "backend/cuda/CudaThreads.h"
#include "backend/cuda/wrappers/CudaDevice.h"
#include <algorithm>
namespace xmrig {
static inline size_t generate(const char *key, Threads<CudaThreads> &threads, const Algorithm &algorithm, const std::vector<CudaDevice> &devices)
{
if (threads.isExist(algorithm) || threads.has(key)) {
return 0;
}
return threads.move(key, CudaThreads(devices, algorithm));
}
template<Algorithm::Family FAMILY>
static inline size_t generate(Threads<CudaThreads> &, const std::vector<CudaDevice> &) { return 0; }
template<>
size_t inline generate<Algorithm::CN>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
size_t count = 0;
count += generate("cn", threads, Algorithm::CN_1, devices);
count += generate("cn/2", threads, Algorithm::CN_2, devices);
if (!threads.isExist(Algorithm::CN_0)) {
threads.disable(Algorithm::CN_0);
count++;
}
# ifdef XMRIG_ALGO_CN_GPU
count += generate("cn/gpu", threads, Algorithm::CN_GPU, devices);
# endif
return count;
}
#ifdef XMRIG_ALGO_CN_LITE
template<>
size_t inline generate<Algorithm::CN_LITE>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
size_t count = generate("cn-lite", threads, Algorithm::CN_LITE_1, devices);
if (!threads.isExist(Algorithm::CN_LITE_0)) {
threads.disable(Algorithm::CN_LITE_0);
++count;
}
return count;
}
#endif
#ifdef XMRIG_ALGO_CN_HEAVY
template<>
size_t inline generate<Algorithm::CN_HEAVY>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
return generate("cn-heavy", threads, Algorithm::CN_HEAVY_0, devices);
}
#endif
#ifdef XMRIG_ALGO_CN_PICO
template<>
size_t inline generate<Algorithm::CN_PICO>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
return generate("cn-pico", threads, Algorithm::CN_PICO_0, devices);
}
#endif
#ifdef XMRIG_ALGO_RANDOMX
template<>
size_t inline generate<Algorithm::RANDOM_X>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
size_t count = 0;
auto rx = CudaThreads(devices, Algorithm::RX_0);
auto wow = CudaThreads(devices, Algorithm::RX_WOW);
auto arq = CudaThreads(devices, Algorithm::RX_ARQ);
if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) {
count += threads.move("rx/wow", std::move(wow));
}
if (!threads.isExist(Algorithm::RX_ARQ) && arq != rx) {
count += threads.move("rx/arq", std::move(arq));
}
count += threads.move("rx", std::move(rx));
return count;
}
#endif
} /* namespace xmrig */
#endif /* XMRIG_CUDACONFIG_GEN_H */

View File

@@ -0,0 +1,51 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/CudaLaunchData.h"
#include "backend/common/Tags.h"
xmrig::CudaLaunchData::CudaLaunchData(const Miner *miner, const Algorithm &algorithm, const CudaThread &thread, const CudaDevice &device) :
algorithm(algorithm),
miner(miner),
device(device),
thread(thread)
{
}
bool xmrig::CudaLaunchData::isEqual(const CudaLaunchData &other) const
{
return (other.algorithm.family() == algorithm.family() &&
other.algorithm.l3() == algorithm.l3() &&
other.thread == thread);
}
const char *xmrig::CudaLaunchData::tag()
{
return cuda_tag();
}

View File

@@ -0,0 +1,66 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDALAUNCHDATA_H
#define XMRIG_CUDALAUNCHDATA_H
#include "backend/cuda/CudaThread.h"
#include "crypto/common/Algorithm.h"
#include "crypto/common/Nonce.h"
namespace xmrig {
class CudaDevice;
class Miner;
class CudaLaunchData
{
public:
CudaLaunchData(const Miner *miner, const Algorithm &algorithm, const CudaThread &thread, const CudaDevice &device);
bool isEqual(const CudaLaunchData &other) const;
inline constexpr static Nonce::Backend backend() { return Nonce::CUDA; }
inline bool operator!=(const CudaLaunchData &other) const { return !isEqual(other); }
inline bool operator==(const CudaLaunchData &other) const { return isEqual(other); }
static const char *tag();
const Algorithm algorithm;
const Miner *miner;
const CudaDevice &device;
const CudaThread thread;
};
} // namespace xmrig
#endif /* XMRIG_OCLLAUNCHDATA_H */

View File

@@ -0,0 +1,113 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/CudaThread.h"
#include "backend/cuda/wrappers/CudaLib.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
#include <algorithm>
namespace xmrig {
static const char *kAffinity = "affinity";
static const char *kBFactor = "bfactor";
static const char *kBlocks = "blocks";
static const char *kBSleep = "bsleep";
static const char *kIndex = "index";
static const char *kThreads = "threads";
static const char *kDatasetHost = "dataset_host";
} // namespace xmrig
xmrig::CudaThread::CudaThread(const rapidjson::Value &value)
{
if (!value.IsObject()) {
return;
}
m_index = Json::getUint(value, kIndex);
m_threads = Json::getInt(value, kThreads);
m_blocks = Json::getInt(value, kBlocks);
m_bfactor = std::min(Json::getUint(value, kBFactor, m_bfactor), 12u);
m_bsleep = Json::getUint(value, kBSleep, m_bsleep);
m_affinity = Json::getUint64(value, kAffinity, m_affinity);
if (Json::getValue(value, kDatasetHost).IsInt()) {
m_datasetHost = Json::getInt(value, kDatasetHost, m_datasetHost) != 0;
}
else {
m_datasetHost = Json::getBool(value, kDatasetHost);
}
}
xmrig::CudaThread::CudaThread(uint32_t index, nvid_ctx *ctx) :
m_blocks(CudaLib::deviceInt(ctx, CudaLib::DeviceBlocks)),
m_datasetHost(CudaLib::deviceInt(ctx, CudaLib::DeviceDatasetHost)),
m_threads(CudaLib::deviceInt(ctx, CudaLib::DeviceThreads)),
m_index(index),
m_bfactor(CudaLib::deviceUint(ctx, CudaLib::DeviceBFactor)),
m_bsleep(CudaLib::deviceUint(ctx, CudaLib::DeviceBSleep))
{
}
bool xmrig::CudaThread::isEqual(const CudaThread &other) const
{
return m_blocks == other.m_blocks &&
m_threads == other.m_threads &&
m_affinity == other.m_affinity &&
m_index == other.m_index &&
m_bfactor == other.m_bfactor &&
m_bsleep == other.m_bsleep &&
m_datasetHost == other.m_datasetHost;
}
rapidjson::Value xmrig::CudaThread::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value out(kObjectType);
out.AddMember(StringRef(kIndex), index(), allocator);
out.AddMember(StringRef(kThreads), threads(), allocator);
out.AddMember(StringRef(kBlocks), blocks(), allocator);
out.AddMember(StringRef(kBFactor), bfactor(), allocator);
out.AddMember(StringRef(kBSleep), bsleep(), allocator);
out.AddMember(StringRef(kAffinity), affinity(), allocator);
if (m_datasetHost >= 0) {
out.AddMember(StringRef(kDatasetHost), m_datasetHost > 0, allocator);
}
return out;
}

View File

@@ -0,0 +1,81 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDATHREAD_H
#define XMRIG_CUDATHREAD_H
using nvid_ctx = struct nvid_ctx;
#include "crypto/common/Algorithm.h"
#include "rapidjson/fwd.h"
namespace xmrig {
class CudaThread
{
public:
CudaThread() = delete;
CudaThread(const rapidjson::Value &value);
CudaThread(uint32_t index, nvid_ctx *ctx);
inline bool isValid() const { return m_blocks > 0 && m_threads > 0; }
inline int32_t bfactor() const { return static_cast<int32_t>(m_bfactor); }
inline int32_t blocks() const { return m_blocks; }
inline int32_t bsleep() const { return static_cast<int32_t>(m_bsleep); }
inline int32_t datasetHost() const { return m_datasetHost; }
inline int32_t threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; }
inline uint32_t index() const { return m_index; }
inline bool operator!=(const CudaThread &other) const { return !isEqual(other); }
inline bool operator==(const CudaThread &other) const { return isEqual(other); }
bool isEqual(const CudaThread &other) const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
private:
int32_t m_blocks = 0;
int32_t m_datasetHost = -1;
int32_t m_threads = 0;
int64_t m_affinity = -1;
uint32_t m_index = 0;
# ifdef _WIN32
uint32_t m_bfactor = 6;
uint32_t m_bsleep = 25;
# else
uint32_t m_bfactor = 0;
uint32_t m_bsleep = 0;
# endif
};
} /* namespace xmrig */
#endif /* XMRIG_CUDATHREAD_H */

View File

@@ -0,0 +1,79 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/CudaThreads.h"
#include "base/io/json/Json.h"
#include "rapidjson/document.h"
#include <algorithm>
xmrig::CudaThreads::CudaThreads(const rapidjson::Value &value)
{
if (value.IsArray()) {
for (auto &v : value.GetArray()) {
CudaThread thread(v);
if (thread.isValid()) {
add(std::move(thread));
}
}
}
}
xmrig::CudaThreads::CudaThreads(const std::vector<CudaDevice> &devices, const Algorithm &algorithm)
{
for (const auto &device : devices) {
device.generate(algorithm, *this);
}
}
bool xmrig::CudaThreads::isEqual(const CudaThreads &other) const
{
if (isEmpty() && other.isEmpty()) {
return true;
}
return count() == other.count() && std::equal(m_data.begin(), m_data.end(), other.m_data.begin());
}
rapidjson::Value xmrig::CudaThreads::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value out(kArrayType);
out.SetArray();
for (const CudaThread &thread : m_data) {
out.PushBack(thread.toJSON(doc), allocator);
}
return out;
}

View File

@@ -0,0 +1,66 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDATHREADS_H
#define XMRIG_CUDATHREADS_H
#include <vector>
#include "backend/cuda/CudaThread.h"
#include "backend/cuda/wrappers/CudaDevice.h"
namespace xmrig {
class CudaThreads
{
public:
CudaThreads() = default;
CudaThreads(const rapidjson::Value &value);
CudaThreads(const std::vector<CudaDevice> &devices, const Algorithm &algorithm);
inline bool isEmpty() const { return m_data.empty(); }
inline const std::vector<CudaThread> &data() const { return m_data; }
inline size_t count() const { return m_data.size(); }
inline void add(CudaThread &&thread) { m_data.push_back(thread); }
inline void reserve(size_t capacity) { m_data.reserve(capacity); }
inline bool operator!=(const CudaThreads &other) const { return !isEqual(other); }
inline bool operator==(const CudaThreads &other) const { return isEqual(other); }
bool isEqual(const CudaThreads &other) const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
private:
std::vector<CudaThread> m_data;
};
} /* namespace xmrig */
#endif /* XMRIG_CUDATHREADS_H */

View File

@@ -0,0 +1,171 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/CudaWorker.h"
#include "backend/common/Tags.h"
#include "backend/cuda/runners/CudaCnRunner.h"
#include "base/io/log/Log.h"
#include "base/tools/Chrono.h"
#include "core/Miner.h"
#include "crypto/common/Nonce.h"
#include "net/JobResults.h"
#ifdef XMRIG_ALGO_RANDOMX
# include "backend/cuda/runners/CudaRxRunner.h"
#endif
#include <cassert>
#include <thread>
namespace xmrig {
static constexpr uint32_t kReserveCount = 32768;
std::atomic<bool> CudaWorker::ready;
static inline bool isReady() { return !Nonce::isPaused() && CudaWorker::ready; }
static inline uint32_t roundSize(uint32_t intensity) { return kReserveCount / intensity + 1; }
} // namespace xmrig
xmrig::CudaWorker::CudaWorker(size_t id, const CudaLaunchData &data) :
Worker(id, data.thread.affinity(), -1),
m_algorithm(data.algorithm),
m_miner(data.miner)
{
switch (m_algorithm.family()) {
case Algorithm::RANDOM_X:
# ifdef XMRIG_ALGO_RANDOMX
m_runner = new CudaRxRunner(id, data);
# endif
break;
case Algorithm::ARGON2:
break;
default:
m_runner = new CudaCnRunner(id, data);
break;
}
if (!m_runner || !m_runner->init()) {
return;
}
}
xmrig::CudaWorker::~CudaWorker()
{
delete m_runner;
}
bool xmrig::CudaWorker::selfTest()
{
return m_runner != nullptr;
}
size_t xmrig::CudaWorker::intensity() const
{
return m_runner ? m_runner->intensity() : 0;
}
void xmrig::CudaWorker::start()
{
while (Nonce::sequence(Nonce::CUDA) > 0) {
if (!isReady()) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
while (!isReady() && Nonce::sequence(Nonce::CUDA) > 0);
if (Nonce::sequence(Nonce::CUDA) == 0) {
break;
}
if (!consumeJob()) {
return;
}
}
while (!Nonce::isOutdated(Nonce::CUDA, m_job.sequence())) {
uint32_t foundNonce[10] = { 0 };
uint32_t foundCount = 0;
if (!m_runner->run(*m_job.nonce(), &foundCount, foundNonce)) {
return;
}
if (foundCount) {
JobResults::submit(m_job.currentJob(), foundNonce, foundCount);
}
const size_t batch_size = intensity();
m_job.nextRound(roundSize(batch_size), batch_size);
storeStats();
std::this_thread::yield();
}
if (!consumeJob()) {
return;
}
}
}
bool xmrig::CudaWorker::consumeJob()
{
if (Nonce::sequence(Nonce::CUDA) == 0) {
return false;
}
const size_t batch_size = intensity();
m_job.add(m_miner->job(), roundSize(batch_size) * batch_size, Nonce::CUDA);
return m_runner->set(m_job.currentJob(), m_job.blob());;
}
void xmrig::CudaWorker::storeStats()
{
if (!isReady()) {
return;
}
m_count += intensity();
Worker::storeStats();
}

View File

@@ -0,0 +1,73 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDAWORKER_H
#define XMRIG_CUDAWORKER_H
#include "backend/common/Worker.h"
#include "backend/common/WorkerJob.h"
#include "backend/cuda/CudaLaunchData.h"
#include "base/tools/Object.h"
#include "net/JobResult.h"
namespace xmrig {
class ICudaRunner;
class CudaWorker : public Worker
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(CudaWorker)
CudaWorker(size_t id, const CudaLaunchData &data);
~CudaWorker() override;
static std::atomic<bool> ready;
protected:
bool selfTest() override;
size_t intensity() const override;
void start() override;
private:
bool consumeJob();
void storeStats();
const Algorithm m_algorithm;
const Miner *m_miner;
ICudaRunner *m_runner = nullptr;
WorkerJob<1> m_job;
};
} // namespace xmrig
#endif /* XMRIG_CUDAWORKER_H */

View File

@@ -0,0 +1,56 @@
if (WITH_CUDA)
add_definitions(/DXMRIG_FEATURE_CUDA)
set(HEADERS_BACKEND_CUDA
src/backend/cuda/CudaBackend.h
src/backend/cuda/CudaConfig_gen.h
src/backend/cuda/CudaConfig.h
src/backend/cuda/CudaLaunchData.h
src/backend/cuda/CudaThread.h
src/backend/cuda/CudaThreads.h
src/backend/cuda/CudaWorker.h
src/backend/cuda/interfaces/ICudaRunner.h
src/backend/cuda/runners/CudaBaseRunner.h
src/backend/cuda/runners/CudaCnRunner.h
src/backend/cuda/wrappers/CudaDevice.h
src/backend/cuda/wrappers/CudaLib.h
)
set(SOURCES_BACKEND_CUDA
src/backend/cuda/CudaBackend.cpp
src/backend/cuda/CudaConfig.cpp
src/backend/cuda/CudaLaunchData.cpp
src/backend/cuda/CudaThread.cpp
src/backend/cuda/CudaThreads.cpp
src/backend/cuda/CudaWorker.cpp
src/backend/cuda/runners/CudaBaseRunner.cpp
src/backend/cuda/runners/CudaCnRunner.cpp
src/backend/cuda/wrappers/CudaDevice.cpp
src/backend/cuda/wrappers/CudaLib.cpp
)
if (WITH_NVML AND NOT APPLE)
add_definitions(/DXMRIG_FEATURE_NVML)
list(APPEND HEADERS_BACKEND_CUDA
src/backend/cuda/wrappers/nvml_lite.h
src/backend/cuda/wrappers/NvmlHealth.h
src/backend/cuda/wrappers/NvmlLib.h
)
list(APPEND SOURCES_BACKEND_CUDA src/backend/cuda/wrappers/NvmlLib.cpp)
else()
remove_definitions(/DXMRIG_FEATURE_NVML)
endif()
if (WITH_RANDOMX)
list(APPEND HEADERS_BACKEND_CUDA src/backend/cuda/runners/CudaRxRunner.h)
list(APPEND SOURCES_BACKEND_CUDA src/backend/cuda/runners/CudaRxRunner.cpp)
endif()
else()
remove_definitions(/DXMRIG_FEATURE_CUDA)
remove_definitions(/DXMRIG_FEATURE_NVML)
set(HEADERS_BACKEND_CUDA "")
set(SOURCES_BACKEND_CUDA "")
endif()

View File

@@ -0,0 +1,71 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_ICUDARUNNER_H
#define XMRIG_ICUDARUNNER_H
#include "base/tools/Object.h"
#include <cstdint>
namespace xmrig {
class Job;
class ICudaRunner
{
public:
XMRIG_DISABLE_COPY_MOVE(ICudaRunner)
ICudaRunner() = default;
virtual ~ICudaRunner() = default;
// virtual cl_context ctx() const = 0;
// virtual const Algorithm &algorithm() const = 0;
// virtual const char *buildOptions() const = 0;
// virtual const char *deviceKey() const = 0;
// virtual const char *source() const = 0;
// virtual const OclLaunchData &data() const = 0;
virtual size_t intensity() const = 0;
// virtual size_t threadId() const = 0;
// virtual uint32_t deviceIndex() const = 0;
// virtual void build() = 0;
virtual bool init() = 0;
virtual bool run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce) = 0;
virtual bool set(const Job &job, uint8_t *blob) = 0;
protected:
// virtual size_t bufferSize() const = 0;
};
} /* namespace xmrig */
#endif // XMRIG_ICUDARUNNER_H

View File

@@ -0,0 +1,83 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/runners/CudaBaseRunner.h"
#include "backend/cuda/wrappers/CudaLib.h"
#include "backend/cuda/CudaLaunchData.h"
#include "backend/common/Tags.h"
#include "base/io/log/Log.h"
#include "base/net/stratum/Job.h"
xmrig::CudaBaseRunner::CudaBaseRunner(size_t id, const CudaLaunchData &data) :
m_data(data),
m_threadId(id)
{
}
xmrig::CudaBaseRunner::~CudaBaseRunner()
{
CudaLib::release(m_ctx);
}
bool xmrig::CudaBaseRunner::init()
{
m_ctx = CudaLib::alloc(m_data.thread.index(), m_data.thread.bfactor(), m_data.thread.bsleep());
if (CudaLib::deviceInfo(m_ctx, m_data.thread.blocks(), m_data.thread.threads(), m_data.algorithm, m_data.thread.datasetHost()) != 0) {
return false;
}
return callWrapper(CudaLib::deviceInit(m_ctx));
}
bool xmrig::CudaBaseRunner::set(const Job &job, uint8_t *blob)
{
m_height = job.height();
m_target = job.target();
return callWrapper(CudaLib::setJob(m_ctx, blob, job.size(), job.algorithm()));
}
size_t xmrig::CudaBaseRunner::intensity() const
{
return m_data.thread.threads() * m_data.thread.blocks();
}
bool xmrig::CudaBaseRunner::callWrapper(bool result) const
{
if (!result) {
const char *error = CudaLib::lastError(m_ctx);
if (error) {
LOG_ERR("%s" RED_S " thread " RED_BOLD("#%zu") RED_S " failed with error " RED_BOLD("%s"), cuda_tag(), m_threadId, error);
}
}
return result;
}

View File

@@ -0,0 +1,68 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDABASERUNNER_H
#define XMRIG_CUDABASERUNNER_H
#include "backend/cuda/interfaces/ICudaRunner.h"
using nvid_ctx = struct nvid_ctx;
namespace xmrig {
class CudaLaunchData;
class CudaBaseRunner : public ICudaRunner
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(CudaBaseRunner)
CudaBaseRunner(size_t id, const CudaLaunchData &data);
~CudaBaseRunner() override;
protected:
bool init() override;
bool set(const Job &job, uint8_t *blob) override;
size_t intensity() const override;
protected:
bool callWrapper(bool result) const;
const CudaLaunchData &m_data;
const size_t m_threadId;
nvid_ctx *m_ctx = nullptr;
uint64_t m_height = 0;
uint64_t m_target = 0;
};
} /* namespace xmrig */
#endif // XMRIG_CUDABASERUNNER_H

View File

@@ -0,0 +1,38 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/runners/CudaCnRunner.h"
#include "backend/cuda/wrappers/CudaLib.h"
xmrig::CudaCnRunner::CudaCnRunner(size_t index, const CudaLaunchData &data) : CudaBaseRunner(index, data)
{
}
bool xmrig::CudaCnRunner::run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce)
{
return callWrapper(CudaLib::cnHash(m_ctx, startNonce, m_height, m_target, rescount, resnonce));
}

View File

@@ -0,0 +1,48 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDACNRUNNER_H
#define XMRIG_CUDACNRUNNER_H
#include "backend/cuda/runners/CudaBaseRunner.h"
namespace xmrig {
class CudaCnRunner : public CudaBaseRunner
{
public:
CudaCnRunner(size_t index, const CudaLaunchData &data);
protected:
bool run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce) override;
};
} /* namespace xmrig */
#endif // XMRIG_CUDACNRUNNER_H

View File

@@ -0,0 +1,66 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/runners/CudaRxRunner.h"
#include "backend/cuda/CudaLaunchData.h"
#include "backend/cuda/wrappers/CudaLib.h"
#include "base/net/stratum/Job.h"
#include "crypto/rx/Rx.h"
#include "crypto/rx/RxDataset.h"
xmrig::CudaRxRunner::CudaRxRunner(size_t index, const CudaLaunchData &data) : CudaBaseRunner(index, data),
m_datasetHost(data.thread.datasetHost() > 0)
{
m_intensity = m_data.thread.threads() * m_data.thread.blocks();
const size_t scratchpads_size = m_intensity * m_data.algorithm.l3();
const size_t num_scratchpads = scratchpads_size / m_data.algorithm.l3();
if (m_intensity > num_scratchpads) {
m_intensity = num_scratchpads;
}
m_intensity -= m_intensity % 32;
}
bool xmrig::CudaRxRunner::run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce)
{
return callWrapper(CudaLib::rxHash(m_ctx, startNonce, m_target, rescount, resnonce));
}
bool xmrig::CudaRxRunner::set(const Job &job, uint8_t *blob)
{
const bool rc = CudaBaseRunner::set(job, blob);
if (!rc || m_ready) {
return rc;
}
auto dataset = Rx::dataset(job, 0);
m_ready = callWrapper(CudaLib::rxPrepare(m_ctx, dataset->raw(), dataset->size(false), m_datasetHost, m_intensity));
return m_ready;
}

View File

@@ -0,0 +1,56 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDARXRUNNER_H
#define XMRIG_CUDARXRUNNER_H
#include "backend/cuda/runners/CudaBaseRunner.h"
namespace xmrig {
class CudaRxRunner : public CudaBaseRunner
{
public:
CudaRxRunner(size_t index, const CudaLaunchData &data);
protected:
inline size_t intensity() const override { return m_intensity; }
bool run(uint32_t startNonce, uint32_t *rescount, uint32_t *resnonce) override;
bool set(const Job &job, uint8_t *blob) override;
private:
bool m_ready = false;
const bool m_datasetHost = false;
size_t m_intensity = 0;
};
} /* namespace xmrig */
#endif // XMRIG_CUDARXRUNNER_H

View File

@@ -0,0 +1,152 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include "backend/cuda/wrappers/CudaDevice.h"
#include "backend/cuda/CudaThreads.h"
#include "backend/cuda/wrappers/CudaLib.h"
#include "base/io/log/Log.h"
#include "crypto/common/Algorithm.h"
#include "rapidjson/document.h"
#ifdef XMRIG_FEATURE_NVML
# include "backend/cuda/wrappers/NvmlLib.h"
#endif
#include <algorithm>
xmrig::CudaDevice::CudaDevice(uint32_t index, int32_t bfactor, int32_t bsleep) :
m_index(index)
{
auto ctx = CudaLib::alloc(index, bfactor, bsleep);
if (CudaLib::deviceInfo(ctx, 0, 0, Algorithm::INVALID) != 0) {
CudaLib::release(ctx);
return;
}
m_ctx = ctx;
m_name = CudaLib::deviceName(ctx);
m_topology = PciTopology(CudaLib::deviceUint(ctx, CudaLib::DevicePciBusID), CudaLib::deviceUint(ctx, CudaLib::DevicePciDeviceID), 0);
}
xmrig::CudaDevice::CudaDevice(CudaDevice &&other) noexcept :
m_index(other.m_index),
m_ctx(other.m_ctx),
m_topology(other.m_topology),
m_name(std::move(other.m_name))
{
other.m_ctx = nullptr;
}
xmrig::CudaDevice::~CudaDevice()
{
CudaLib::release(m_ctx);
}
size_t xmrig::CudaDevice::freeMemSize() const
{
return CudaLib::deviceUlong(m_ctx, CudaLib::DeviceMemoryFree);
}
size_t xmrig::CudaDevice::globalMemSize() const
{
return CudaLib::deviceUlong(m_ctx, CudaLib::DeviceMemoryTotal);
}
uint32_t xmrig::CudaDevice::clock() const
{
return CudaLib::deviceUint(m_ctx, CudaLib::DeviceClockRate) / 1000;
}
uint32_t xmrig::CudaDevice::computeCapability(bool major) const
{
return CudaLib::deviceUint(m_ctx, major ? CudaLib::DeviceArchMajor : CudaLib::DeviceArchMinor);
}
uint32_t xmrig::CudaDevice::memoryClock() const
{
return CudaLib::deviceUint(m_ctx, CudaLib::DeviceMemoryClockRate) / 1000;
}
uint32_t xmrig::CudaDevice::smx() const
{
return CudaLib::deviceUint(m_ctx, CudaLib::DeviceSmx);
}
void xmrig::CudaDevice::generate(const Algorithm &algorithm, CudaThreads &threads) const
{
if (CudaLib::deviceInfo(m_ctx, -1, -1, algorithm) != 0) {
return;
}
threads.add(CudaThread(m_index, m_ctx));
}
#ifdef XMRIG_FEATURE_API
void xmrig::CudaDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
out.AddMember("name", name().toJSON(doc), allocator);
out.AddMember("bus_id", topology().toString().toJSON(doc), allocator);
out.AddMember("smx", smx(), allocator);
out.AddMember("arch", arch(), allocator);
out.AddMember("global_mem", static_cast<uint64_t>(globalMemSize()), allocator);
out.AddMember("clock", clock(), allocator);
out.AddMember("memory_clock", memoryClock(), allocator);
# ifdef XMRIG_FEATURE_NVML
if (m_nvmlDevice) {
auto data = NvmlLib::health(m_nvmlDevice);
Value health(kObjectType);
health.AddMember("temperature", data.temperature, allocator);
health.AddMember("power", data.power, allocator);
health.AddMember("clock", data.clock, allocator);
health.AddMember("mem_clock", data.memClock, allocator);
Value fanSpeed(kArrayType);
for (auto speed : data.fanSpeed) {
fanSpeed.PushBack(speed, allocator);
}
health.AddMember("fan_speed", fanSpeed, allocator);
out.AddMember("health", health, allocator);
}
# endif
}
#endif

View File

@@ -0,0 +1,94 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDADEVICE_H
#define XMRIG_CUDADEVICE_H
#include "backend/common/misc/PciTopology.h"
#include "base/tools/String.h"
using nvid_ctx = struct nvid_ctx;
using nvmlDevice_t = struct nvmlDevice_st *;
namespace xmrig {
class Algorithm;
class CudaThreads;
class CudaDevice
{
public:
CudaDevice() = delete;
CudaDevice(const CudaDevice &other) = delete;
CudaDevice(CudaDevice &&other) noexcept;
CudaDevice(uint32_t index, int32_t bfactor, int32_t bsleep);
~CudaDevice();
size_t freeMemSize() const;
size_t globalMemSize() const;
uint32_t clock() const;
uint32_t computeCapability(bool major = true) const;
uint32_t memoryClock() const;
uint32_t smx() const;
void generate(const Algorithm &algorithm, CudaThreads &threads) const;
inline bool isValid() const { return m_ctx != nullptr; }
inline const PciTopology &topology() const { return m_topology; }
inline const String &name() const { return m_name; }
inline uint32_t arch() const { return (computeCapability(true) * 10) + computeCapability(false); }
inline uint32_t index() const { return m_index; }
# ifdef XMRIG_FEATURE_NVML
inline nvmlDevice_t nvmlDevice() const { return m_nvmlDevice; }
inline void setNvmlDevice(nvmlDevice_t device) { m_nvmlDevice = device; }
# endif
# ifdef XMRIG_FEATURE_API
void toJSON(rapidjson::Value &out, rapidjson::Document &doc) const;
# endif
CudaDevice &operator=(const CudaDevice &other) = delete;
CudaDevice &operator=(CudaDevice &&other) = delete;
private:
const uint32_t m_index = 0;
nvid_ctx *m_ctx = nullptr;
PciTopology m_topology;
String m_name;
# ifdef XMRIG_FEATURE_NVML
nvmlDevice_t m_nvmlDevice = nullptr;
# endif
};
} // namespace xmrig
#endif /* XMRIG_CUDADEVICE_H */

View File

@@ -0,0 +1,330 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include <stdexcept>
#include <uv.h>
#include "backend/cuda/wrappers/CudaLib.h"
namespace xmrig {
enum Version : uint32_t
{
ApiVersion,
DriverVersion,
RuntimeVersion
};
static uv_lib_t cudaLib;
static const char *kAlloc = "alloc";
static const char *kCnHash = "cnHash";
static const char *kDeviceCount = "deviceCount";
static const char *kDeviceInfo = "deviceInfo";
static const char *kDeviceInit = "deviceInit";
static const char *kDeviceInt = "deviceInt";
static const char *kDeviceName = "deviceName";
static const char *kDeviceUint = "deviceUint";
static const char *kDeviceUlong = "deviceUlong";
static const char *kInit = "init";
static const char *kLastError = "lastError";
static const char *kPluginVersion = "pluginVersion";
static const char *kRelease = "release";
static const char *kRxHash = "rxHash";
static const char *kRxPrepare = "rxPrepare";
static const char *kSetJob = "setJob";
static const char *kSymbolNotFound = "symbol not found";
static const char *kVersion = "version";
using alloc_t = nvid_ctx * (*)(uint32_t, int32_t, int32_t);
using cnHash_t = bool (*)(nvid_ctx *, uint32_t, uint64_t, uint64_t, uint32_t *, uint32_t *);
using deviceCount_t = uint32_t (*)();
using deviceInfo_t = int32_t (*)(nvid_ctx *, int32_t, int32_t, int32_t, int32_t);
using deviceInit_t = bool (*)(nvid_ctx *);
using deviceInt_t = int32_t (*)(nvid_ctx *, CudaLib::DeviceProperty);
using deviceName_t = const char * (*)(nvid_ctx *);
using deviceUint_t = uint32_t (*)(nvid_ctx *, CudaLib::DeviceProperty);
using deviceUlong_t = uint64_t (*)(nvid_ctx *, CudaLib::DeviceProperty);
using init_t = void (*)();
using lastError_t = const char * (*)(nvid_ctx *);
using pluginVersion_t = const char * (*)();
using release_t = void (*)(nvid_ctx *);
using rxHash_t = bool (*)(nvid_ctx *, uint32_t, uint64_t, uint32_t *, uint32_t *);
using rxPrepare_t = bool (*)(nvid_ctx *, const void *, size_t, bool, uint32_t);
using setJob_t = bool (*)(nvid_ctx *, const void *, size_t, int32_t);
using version_t = uint32_t (*)(Version);
static alloc_t pAlloc = nullptr;
static cnHash_t pCnHash = nullptr;
static deviceCount_t pDeviceCount = nullptr;
static deviceInfo_t pDeviceInfo = nullptr;
static deviceInit_t pDeviceInit = nullptr;
static deviceInt_t pDeviceInt = nullptr;
static deviceName_t pDeviceName = nullptr;
static deviceUint_t pDeviceUint = nullptr;
static deviceUlong_t pDeviceUlong = nullptr;
static init_t pInit = nullptr;
static lastError_t pLastError = nullptr;
static pluginVersion_t pPluginVersion = nullptr;
static release_t pRelease = nullptr;
static rxHash_t pRxHash = nullptr;
static rxPrepare_t pRxPrepare = nullptr;
static setJob_t pSetJob = nullptr;
static version_t pVersion = nullptr;
#define DLSYM(x) if (uv_dlsym(&cudaLib, k##x, reinterpret_cast<void**>(&p##x)) == -1) { throw std::runtime_error(kSymbolNotFound); }
bool CudaLib::m_initialized = false;
bool CudaLib::m_ready = false;
String CudaLib::m_loader;
} // namespace xmrig
bool xmrig::CudaLib::init(const char *fileName)
{
if (!m_initialized) {
m_loader = fileName == nullptr ? defaultLoader() : fileName;
m_ready = uv_dlopen(m_loader, &cudaLib) == 0 && load();
m_initialized = true;
}
return m_ready;
}
const char *xmrig::CudaLib::lastError() noexcept
{
return uv_dlerror(&cudaLib);
}
void xmrig::CudaLib::close()
{
uv_dlclose(&cudaLib);
}
bool xmrig::CudaLib::cnHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t height, uint64_t target, uint32_t *rescount, uint32_t *resnonce)
{
return pCnHash(ctx, startNonce, height, target, rescount, resnonce);
}
bool xmrig::CudaLib::deviceInit(nvid_ctx *ctx) noexcept
{
return pDeviceInit(ctx);
}
bool xmrig::CudaLib::rxHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t target, uint32_t *rescount, uint32_t *resnonce) noexcept
{
return pRxHash(ctx, startNonce, target, rescount, resnonce);
}
bool xmrig::CudaLib::rxPrepare(nvid_ctx *ctx, const void *dataset, size_t datasetSize, bool dataset_host, uint32_t batchSize) noexcept
{
return pRxPrepare(ctx, dataset, datasetSize, dataset_host, batchSize);
}
bool xmrig::CudaLib::setJob(nvid_ctx *ctx, const void *data, size_t size, const Algorithm &algorithm) noexcept
{
return pSetJob(ctx, data, size, algorithm);
}
const char *xmrig::CudaLib::deviceName(nvid_ctx *ctx) noexcept
{
return pDeviceName(ctx);
}
const char *xmrig::CudaLib::lastError(nvid_ctx *ctx) noexcept
{
return pLastError(ctx);
}
const char *xmrig::CudaLib::pluginVersion() noexcept
{
return pPluginVersion();
}
int xmrig::CudaLib::deviceInfo(nvid_ctx *ctx, int32_t blocks, int32_t threads, const Algorithm &algorithm, int32_t dataset_host) noexcept
{
return pDeviceInfo(ctx, blocks, threads, algorithm, dataset_host);
}
int32_t xmrig::CudaLib::deviceInt(nvid_ctx *ctx, DeviceProperty property) noexcept
{
return pDeviceInt(ctx, property);
}
nvid_ctx *xmrig::CudaLib::alloc(uint32_t id, int32_t bfactor, int32_t bsleep) noexcept
{
return pAlloc(id, bfactor, bsleep);
}
std::string xmrig::CudaLib::version(uint32_t version)
{
return std::to_string(version / 1000) + "." + std::to_string((version % 1000) / 10);
}
std::vector<xmrig::CudaDevice> xmrig::CudaLib::devices(int32_t bfactor, int32_t bsleep, const std::vector<uint32_t> &hints) noexcept
{
const uint32_t count = deviceCount();
if (!count) {
return {};
}
std::vector<CudaDevice> out;
out.reserve(count);
if (hints.empty()) {
for (uint32_t i = 0; i < count; ++i) {
CudaDevice device(i, bfactor, bsleep);
if (device.isValid()) {
out.emplace_back(std::move(device));
}
}
}
else {
for (const uint32_t i : hints) {
if (i >= count) {
continue;
}
CudaDevice device(i, bfactor, bsleep);
if (device.isValid()) {
out.emplace_back(std::move(device));
}
}
}
return out;
}
uint32_t xmrig::CudaLib::deviceCount() noexcept
{
return pDeviceCount();
}
uint32_t xmrig::CudaLib::deviceUint(nvid_ctx *ctx, DeviceProperty property) noexcept
{
return pDeviceUint(ctx, property);
}
uint32_t xmrig::CudaLib::driverVersion() noexcept
{
return pVersion(DriverVersion);
}
uint32_t xmrig::CudaLib::runtimeVersion() noexcept
{
return pVersion(RuntimeVersion);
}
uint64_t xmrig::CudaLib::deviceUlong(nvid_ctx *ctx, DeviceProperty property) noexcept
{
return pDeviceUlong(ctx, property);
}
void xmrig::CudaLib::release(nvid_ctx *ctx) noexcept
{
pRelease(ctx);
}
bool xmrig::CudaLib::load()
{
if (uv_dlsym(&cudaLib, kVersion, reinterpret_cast<void**>(&pVersion)) == -1) {
return false;
}
if (pVersion(ApiVersion) != 2u) {
return false;
}
try {
DLSYM(Alloc);
DLSYM(CnHash);
DLSYM(DeviceCount);
DLSYM(DeviceInfo);
DLSYM(DeviceInit);
DLSYM(DeviceInt);
DLSYM(DeviceName);
DLSYM(DeviceUint);
DLSYM(DeviceUlong);
DLSYM(Init);
DLSYM(LastError);
DLSYM(PluginVersion);
DLSYM(Release);
DLSYM(RxHash);
DLSYM(RxPrepare);
DLSYM(SetJob);
DLSYM(Version);
} catch (std::exception &ex) {
return false;
}
pInit();
return true;
}
const char *xmrig::CudaLib::defaultLoader()
{
# if defined(__APPLE__)
return "/System/Library/Frameworks/OpenCL.framework/OpenCL"; // FIXME
# elif defined(_WIN32)
return "xmrig-cuda.dll";
# else
return "libxmrig-cuda.so";
# endif
}

View File

@@ -0,0 +1,109 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_CUDALIB_H
#define XMRIG_CUDALIB_H
using nvid_ctx = struct nvid_ctx;
#include "backend/cuda/wrappers/CudaDevice.h"
#include "base/tools/String.h"
#include "crypto/common/Algorithm.h"
#include <vector>
#include <string>
namespace xmrig {
class CudaLib
{
public:
enum DeviceProperty : uint32_t
{
DeviceId,
DeviceAlgorithm,
DeviceArchMajor,
DeviceArchMinor,
DeviceSmx,
DeviceBlocks,
DeviceThreads,
DeviceBFactor,
DeviceBSleep,
DeviceClockRate,
DeviceMemoryClockRate,
DeviceMemoryTotal,
DeviceMemoryFree,
DevicePciBusID,
DevicePciDeviceID,
DevicePciDomainID,
DeviceDatasetHost,
};
static bool init(const char *fileName = nullptr);
static const char *lastError() noexcept;
static void close();
static inline bool isInitialized() { return m_initialized; }
static inline bool isReady() noexcept { return m_ready; }
static inline const String &loader() { return m_loader; }
static bool cnHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t height, uint64_t target, uint32_t *rescount, uint32_t *resnonce);
static bool deviceInit(nvid_ctx *ctx) noexcept;
static bool rxHash(nvid_ctx *ctx, uint32_t startNonce, uint64_t target, uint32_t *rescount, uint32_t *resnonce) noexcept;
static bool rxPrepare(nvid_ctx *ctx, const void *dataset, size_t datasetSize, bool dataset_host, uint32_t batchSize) noexcept;
static bool setJob(nvid_ctx *ctx, const void *data, size_t size, const Algorithm &algorithm) noexcept;
static const char *deviceName(nvid_ctx *ctx) noexcept;
static const char *lastError(nvid_ctx *ctx) noexcept;
static const char *pluginVersion() noexcept;
static int deviceInfo(nvid_ctx *ctx, int32_t blocks, int32_t threads, const Algorithm &algorithm, int32_t dataset_host = -1) noexcept;
static int32_t deviceInt(nvid_ctx *ctx, DeviceProperty property) noexcept;
static nvid_ctx *alloc(uint32_t id, int32_t bfactor, int32_t bsleep) noexcept;
static std::string version(uint32_t version);
static std::vector<CudaDevice> devices(int32_t bfactor, int32_t bsleep, const std::vector<uint32_t> &hints) noexcept;
static uint32_t deviceCount() noexcept;
static uint32_t deviceUint(nvid_ctx *ctx, DeviceProperty property) noexcept;
static uint32_t driverVersion() noexcept;
static uint32_t runtimeVersion() noexcept;
static uint64_t deviceUlong(nvid_ctx *ctx, DeviceProperty property) noexcept;
static void release(nvid_ctx *ctx) noexcept;
private:
static bool load();
static const char *defaultLoader();
static bool m_initialized;
static bool m_ready;
static String m_loader;
};
} // namespace xmrig
#endif /* XMRIG_CUDALIB_H */

View File

@@ -0,0 +1,43 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_NVMLHEALTH_H
#define XMRIG_NVMLHEALTH_H
#include <cstdint>
#include <vector>
struct NvmlHealth
{
std::vector<uint32_t> fanSpeed;
uint32_t clock = 0;
uint32_t memClock = 0;
uint32_t power = 0;
uint32_t temperature = 0;
};
#endif /* XMRIG_NVMLHEALTH_H */

View File

@@ -0,0 +1,227 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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/>.
*/
#include <stdexcept>
#include <uv.h>
#include "backend/cuda/wrappers/NvmlLib.h"
#include "backend/cuda/wrappers/nvml_lite.h"
#include "base/io/log/Log.h"
namespace xmrig {
static uv_lib_t nvmlLib;
static const char *kNvmlDeviceGetClockInfo = "nvmlDeviceGetClockInfo";
static const char *kNvmlDeviceGetCount = "nvmlDeviceGetCount_v2";
static const char *kNvmlDeviceGetFanSpeed = "nvmlDeviceGetFanSpeed";
static const char *kNvmlDeviceGetFanSpeed_v2 = "nvmlDeviceGetFanSpeed_v2";
static const char *kNvmlDeviceGetHandleByIndex = "nvmlDeviceGetHandleByIndex_v2";
static const char *kNvmlDeviceGetPciInfo = "nvmlDeviceGetPciInfo_v2";
static const char *kNvmlDeviceGetPowerUsage = "nvmlDeviceGetPowerUsage";
static const char *kNvmlDeviceGetTemperature = "nvmlDeviceGetTemperature";
static const char *kNvmlInit = "nvmlInit_v2";
static const char *kNvmlShutdown = "nvmlShutdown";
static const char *kNvmlSystemGetDriverVersion = "nvmlSystemGetDriverVersion";
static const char *kNvmlSystemGetNVMLVersion = "nvmlSystemGetNVMLVersion";
static const char *kSymbolNotFound = "symbol not found";
static nvmlReturn_t (*pNvmlDeviceGetClockInfo)(nvmlDevice_t device, uint32_t type, uint32_t *clock) = nullptr;
static nvmlReturn_t (*pNvmlDeviceGetCount)(uint32_t *deviceCount) = nullptr;
static nvmlReturn_t (*pNvmlDeviceGetFanSpeed_v2)(nvmlDevice_t device, uint32_t fan, uint32_t *speed) = nullptr;
static nvmlReturn_t (*pNvmlDeviceGetFanSpeed)(nvmlDevice_t device, uint32_t *speed) = nullptr;
static nvmlReturn_t (*pNvmlDeviceGetHandleByIndex)(uint32_t index, nvmlDevice_t *device) = nullptr;
static nvmlReturn_t (*pNvmlDeviceGetPciInfo)(nvmlDevice_t device, nvmlPciInfo_t *pci) = nullptr;
static nvmlReturn_t (*pNvmlDeviceGetPowerUsage)(nvmlDevice_t device, uint32_t *power) = nullptr;
static nvmlReturn_t (*pNvmlDeviceGetTemperature)(nvmlDevice_t device, uint32_t sensorType, uint32_t *temp) = nullptr;
static nvmlReturn_t (*pNvmlInit)() = nullptr;
static nvmlReturn_t (*pNvmlShutdown)() = nullptr;
static nvmlReturn_t (*pNvmlSystemGetDriverVersion)(char *version, uint32_t length) = nullptr;
static nvmlReturn_t (*pNvmlSystemGetNVMLVersion)(char *version, uint32_t length) = nullptr;
#define DLSYM(x) if (uv_dlsym(&nvmlLib, k##x, reinterpret_cast<void**>(&p##x)) == -1) { throw std::runtime_error(kSymbolNotFound); }
bool NvmlLib::m_initialized = false;
bool NvmlLib::m_ready = false;
char NvmlLib::m_driverVersion[80] = { 0 };
char NvmlLib::m_nvmlVersion[80] = { 0 };
String NvmlLib::m_loader;
} // namespace xmrig
bool xmrig::NvmlLib::init(const char *fileName)
{
if (!m_initialized) {
m_loader = fileName;
m_ready = dlopen() && load();
m_initialized = true;
}
return m_ready;
}
const char *xmrig::NvmlLib::lastError() noexcept
{
return uv_dlerror(&nvmlLib);
}
void xmrig::NvmlLib::close()
{
if (m_ready) {
pNvmlShutdown();
}
uv_dlclose(&nvmlLib);
}
bool xmrig::NvmlLib::assign(std::vector<CudaDevice> &devices)
{
uint32_t count = 0;
if (pNvmlDeviceGetCount(&count) != NVML_SUCCESS) {
return false;
}
for (uint32_t i = 0; i < count; i++) {
nvmlDevice_t nvmlDevice;
if (pNvmlDeviceGetHandleByIndex(i, &nvmlDevice) != NVML_SUCCESS) {
continue;
}
nvmlPciInfo_t pci;
if (pNvmlDeviceGetPciInfo(nvmlDevice, &pci) != NVML_SUCCESS) {
continue;
}
for (auto &device : devices) {
if (device.topology().bus() == pci.bus && device.topology().device() == pci.device) {
device.setNvmlDevice(nvmlDevice);
}
}
}
return true;
}
NvmlHealth xmrig::NvmlLib::health(nvmlDevice_t device)
{
if (!device) {
return {};
}
NvmlHealth health;
pNvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &health.temperature);
pNvmlDeviceGetPowerUsage(device, &health.power);
pNvmlDeviceGetClockInfo(device, NVML_CLOCK_SM, &health.clock);
pNvmlDeviceGetClockInfo(device, NVML_CLOCK_MEM, &health.memClock);
if (health.power) {
health.power /= 1000;
}
uint32_t speed = 0;
if (pNvmlDeviceGetFanSpeed_v2) {
uint32_t i = 0;
while (pNvmlDeviceGetFanSpeed_v2(device, i, &speed) == NVML_SUCCESS) {
health.fanSpeed.push_back(speed);
++i;
}
}
else {
pNvmlDeviceGetFanSpeed(device, &speed);
health.fanSpeed.push_back(speed);
}
return health;
}
bool xmrig::NvmlLib::dlopen()
{
if (!m_loader.isNull()) {
return uv_dlopen(m_loader, &nvmlLib) == 0;
}
# ifdef _WIN32
if (uv_dlopen("nvml.dll", &nvmlLib) == 0) {
return true;
}
char path[MAX_PATH] = { 0 };
ExpandEnvironmentStringsA("%PROGRAMFILES%\\NVIDIA Corporation\\NVSMI\\nvml.dll", path, sizeof(path));
return uv_dlopen(path, &nvmlLib) == 0;
# else
return uv_dlopen("libnvidia-ml.so", &nvmlLib) == 0;
# endif
}
bool xmrig::NvmlLib::load()
{
try {
DLSYM(NvmlDeviceGetClockInfo);
DLSYM(NvmlDeviceGetCount);
DLSYM(NvmlDeviceGetFanSpeed);
DLSYM(NvmlDeviceGetHandleByIndex);
DLSYM(NvmlDeviceGetPciInfo);
DLSYM(NvmlDeviceGetPowerUsage);
DLSYM(NvmlDeviceGetTemperature);
DLSYM(NvmlInit);
DLSYM(NvmlShutdown);
DLSYM(NvmlSystemGetDriverVersion);
DLSYM(NvmlSystemGetNVMLVersion);
} catch (std::exception &ex) {
return false;
}
uv_dlsym(&nvmlLib, kNvmlDeviceGetFanSpeed_v2, reinterpret_cast<void**>(&pNvmlDeviceGetFanSpeed_v2));
if (pNvmlInit() != NVML_SUCCESS) {
return false;
}
pNvmlSystemGetDriverVersion(m_driverVersion, sizeof(m_driverVersion));
pNvmlSystemGetNVMLVersion(m_nvmlVersion, sizeof(m_nvmlVersion));
return true;
}

View File

@@ -0,0 +1,66 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_NVMLLIB_H
#define XMRIG_NVMLLIB_H
#include "backend/cuda/wrappers/CudaDevice.h"
#include "backend/cuda/wrappers/NvmlHealth.h"
namespace xmrig {
class NvmlLib
{
public:
static bool init(const char *fileName = nullptr);
static const char *lastError() noexcept;
static void close();
static bool assign(std::vector<CudaDevice> &devices);
static NvmlHealth health(nvmlDevice_t device);
static inline bool isInitialized() noexcept { return m_initialized; }
static inline bool isReady() noexcept { return m_ready; }
static inline const char *driverVersion() noexcept { return m_driverVersion; }
static inline const char *version() noexcept { return m_nvmlVersion; }
private:
static bool dlopen();
static bool load();
static bool m_initialized;
static bool m_ready;
static char m_driverVersion[80];
static char m_nvmlVersion[80];
static String m_loader;
};
} // namespace xmrig
#endif /* XMRIG_NVMLLIB_H */

View File

@@ -0,0 +1,55 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 XMRIG_NVML_LITE_H
#define XMRIG_NVML_LITE_H
#include <cstdint>
#define NVML_SUCCESS 0
#define NVML_TEMPERATURE_GPU 0
#define NVML_CLOCK_SM 1
#define NVML_CLOCK_MEM 2
using nvmlReturn_t = uint32_t;
using nvmlDevice_t = struct nvmlDevice_st *;
struct nvmlPciInfo_t
{
char busIdLegacy[16]{};
unsigned int domain = 0;
unsigned int bus = 0;
unsigned int device = 0;
unsigned int pciDeviceId = 0;
unsigned int pciSubSystemId = 0;
char busId[32]{};
};
#endif /* XMRIG_NVML_LITE_H */

View File

@@ -58,7 +58,7 @@ namespace xmrig {
extern template class Threads<OclThreads>;
constexpr const size_t oneMiB = 1024u * 1024u;
constexpr const size_t oneMiB = 1024U * 1024U;
static const char *tag = MAGENTA_BG_BOLD(WHITE_BOLD_S " ocl ");
static const String kType = "opencl";
static std::mutex mutex;
@@ -153,7 +153,8 @@ public:
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu ") WHITE_BOLD("%s") "/" WHITE_BOLD("%s"), "OPENCL", platform.index(), platform.name().data(), platform.version().data());
for (const OclDevice &device : devices) {
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") " %s " WHITE_BOLD("%uMHz") " cu:" WHITE_BOLD("%u") " mem:" CYAN("%zu/%zu") " MB", "OPENCL GPU",
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("#%zu") YELLOW(" %s") " %s " WHITE_BOLD("%u MHz") " cu:" WHITE_BOLD("%u") " mem:" CYAN("%zu/%zu") " MB",
"OPENCL GPU",
device.index(),
device.topology().toString().data(),
device.printableName().data(),
@@ -167,10 +168,11 @@ public:
inline void start(const Job &job)
{
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"),
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" thread%s)") " scratchpad " CYAN_BOLD("%zu KB"),
tag,
profileName.data(),
threads.size(),
threads.size() > 1 ? "s" : "",
algo.l3() / 1024
);
@@ -284,7 +286,7 @@ void xmrig::OclBackend::printHashrate(bool details)
Log::print(WHITE_BOLD_S "| OPENCL # | AFFINITY | 10s H/s | 60s H/s | 15m H/s |");
size_t i = 0;
for (const OclLaunchData &data : d_ptr->threads) {
for (const auto &data : d_ptr->threads) {
Log::print("| %8zu | %8" PRId64 " | %7s | %7s | %7s |" CYAN_BOLD(" #%u") YELLOW(" %s") " %s",
i,
data.affinity,
@@ -309,7 +311,7 @@ void xmrig::OclBackend::printHashrate(bool details)
void xmrig::OclBackend::setJob(const Job &job)
{
const OclConfig &cl = d_ptr->controller->config()->cl();
const auto &cl = d_ptr->controller->config()->cl();
if (cl.isEnabled()) {
d_ptr->init(cl);
}
@@ -318,7 +320,7 @@ void xmrig::OclBackend::setJob(const Job &job)
return stop();
}
std::vector<OclLaunchData> threads = cl.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->platform, d_ptr->devices, tag);
auto threads = cl.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->platform, d_ptr->devices);
if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) {
return;
}
@@ -408,7 +410,7 @@ rapidjson::Value xmrig::OclBackend::toJSON(rapidjson::Document &doc) const
Value threads(kArrayType);
size_t i = 0;
for (const OclLaunchData &data : d_ptr->threads) {
for (const auto &data : d_ptr->threads) {
Value thread = data.thread.toJSON(doc);
thread.AddMember("affinity", data.affinity, allocator);
thread.AddMember("hashrate", hashrate()->toJSON(i, doc), allocator);

View File

@@ -30,6 +30,7 @@
#include "backend/common/interfaces/IBackend.h"
#include "base/tools/Object.h"
namespace xmrig {
@@ -43,17 +44,15 @@ class Miner;
class OclBackend : public IBackend
{
public:
OclBackend() = delete;
OclBackend(const OclBackend &other) = delete;
XMRIG_DISABLE_COPY_MOVE_DEFAULT(OclBackend)
OclBackend(Controller *controller);
OclBackend(OclBackend &&other) = delete;
~OclBackend() override;
OclBackend &operator=(const OclBackend &other) = delete;
OclBackend &operator=(OclBackend &&other) = delete;
protected:
inline void execCommand(char) override {}
bool isEnabled() const override;
bool isEnabled(const Algorithm &algorithm) const override;
const Hashrate *hashrate() const override;

View File

@@ -24,6 +24,7 @@
#include "backend/opencl/OclConfig.h"
#include "backend/common/Tags.h"
#include "backend/opencl/OclConfig_gen.h"
#include "backend/opencl/wrappers/OclLib.h"
#include "base/io/json/Json.h"
@@ -113,10 +114,10 @@ rapidjson::Value xmrig::OclConfig::toJSON(rapidjson::Document &doc) const
}
std::vector<xmrig::OclLaunchData> xmrig::OclConfig::get(const Miner *miner, const Algorithm &algorithm, const OclPlatform &platform, const std::vector<OclDevice> &devices, const char *tag) const
std::vector<xmrig::OclLaunchData> xmrig::OclConfig::get(const Miner *miner, const Algorithm &algorithm, const OclPlatform &platform, const std::vector<OclDevice> &devices) const
{
std::vector<OclLaunchData> out;
const OclThreads &threads = m_threads.get(algorithm);
const auto &threads = m_threads.get(algorithm);
if (threads.isEmpty()) {
return out;
@@ -124,9 +125,9 @@ std::vector<xmrig::OclLaunchData> xmrig::OclConfig::get(const Miner *miner, cons
out.reserve(threads.count() * 2);
for (const OclThread &thread : threads.data()) {
for (const auto &thread : threads.data()) {
if (thread.index() >= devices.size()) {
LOG_INFO("%s" YELLOW(" skip non-existing device with index ") YELLOW_BOLD("%u"), tag, thread.index());
LOG_INFO("%s" YELLOW(" skip non-existing device with index ") YELLOW_BOLD("%u"), ocl_tag(), thread.index());
continue;
}

View File

@@ -42,7 +42,7 @@ public:
OclPlatform platform() const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
std::vector<OclLaunchData> get(const Miner *miner, const Algorithm &algorithm, const OclPlatform &platform, const std::vector<OclDevice> &devices, const char *tag) const;
std::vector<OclLaunchData> get(const Miner *miner, const Algorithm &algorithm, const OclPlatform &platform, const std::vector<OclDevice> &devices) const;
void read(const rapidjson::Value &value);
inline bool isCacheEnabled() const { return m_cache; }

View File

@@ -55,7 +55,7 @@ size_t inline generate<Algorithm::CN>(Threads<OclThreads> &threads, const std::v
{
size_t count = 0;
count += generate("cn", threads, Algorithm::CN_0, devices);
count += generate("cn", threads, Algorithm::CN_1, devices);
count += generate("cn/2", threads, Algorithm::CN_2, devices);
if (!threads.isExist(Algorithm::CN_0)) {

View File

@@ -46,7 +46,7 @@ xmrig::OclThreads::OclThreads(const rapidjson::Value &value)
xmrig::OclThreads::OclThreads(const std::vector<OclDevice> &devices, const Algorithm &algorithm)
{
for (const OclDevice &device : devices) {
for (const auto &device : devices) {
device.generate(algorithm, *this);
}
}

View File

@@ -206,7 +206,7 @@ bool xmrig::OclWorker::consumeJob()
return false;
}
m_job.add(m_miner->job(), Nonce::sequence(Nonce::OPENCL), roundSize(m_intensity) * m_intensity);
m_job.add(m_miner->job(), roundSize(m_intensity) * m_intensity, Nonce::OPENCL);
try {
m_runner->set(m_job.currentJob(), m_job.blob());

View File

@@ -30,6 +30,7 @@
#include "backend/common/Worker.h"
#include "backend/common/WorkerJob.h"
#include "backend/opencl/OclLaunchData.h"
#include "base/tools/Object.h"
#include "net/JobResult.h"
@@ -42,16 +43,12 @@ class IOclRunner;
class OclWorker : public Worker
{
public:
OclWorker() = delete;
OclWorker(const OclWorker &other) = delete;
OclWorker(OclWorker &&other) = delete;
XMRIG_DISABLE_COPY_MOVE_DEFAULT(OclWorker)
OclWorker(size_t id, const OclLaunchData &data);
~OclWorker() override;
OclWorker &operator=(const OclWorker &other) = delete;
OclWorker &operator=(OclWorker &&other) = delete;
static std::atomic<bool> ready;
protected:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,379 +2,358 @@
namespace xmrig {
static char cryptonight_r_defines_cl[8353] = {
0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x0d,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,
static char cryptonight_r_defines_cl[7709] = {
0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,
0x20,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x4e,0x29,0x20,0x28,0x2a,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,
0x75,0x69,0x6e,0x74,0x34,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,0x28,0x73,0x63,0x72,0x61,0x74,0x63,0x68,
0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x29,0x20,0x2b,0x20,0x28,0x69,0x64,0x78,0x31,0x20,0x5e,0x20,0x28,0x4e,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x29,0x29,0x0d,
0x23,0x65,0x6c,0x73,0x65,0x0d,0x23,0x69,0x66,0x20,0x28,0x53,0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x30,0x29,0x0d,0x23,
0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x29,0x20,0x2b,0x20,0x28,0x69,0x64,0x78,0x31,0x20,0x5e,0x20,0x28,0x4e,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x29,0x29,0x0a,
0x23,0x65,0x6c,0x73,0x65,0x0a,0x23,0x69,0x66,0x20,0x28,0x53,0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x30,0x29,0x0a,0x23,
0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x4e,0x29,0x20,0x28,0x2a,0x28,0x5f,0x5f,
0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,
0x28,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x20,0x2b,0x20,0x28,0x69,0x64,0x78,0x20,0x5e,0x20,0x28,0x4e,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x29,
0x29,0x0d,0x23,0x65,0x6c,0x69,0x66,0x20,0x28,0x53,0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x31,0x29,0x0d,0x23,0x64,0x65,
0x29,0x0a,0x23,0x65,0x6c,0x69,0x66,0x20,0x28,0x53,0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x31,0x29,0x0a,0x23,0x64,0x65,
0x66,0x69,0x6e,0x65,0x20,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x4e,0x29,0x20,0x28,0x2a,0x28,0x5f,0x5f,0x67,0x6c,
0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,0x28,0x53,
0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x20,0x2b,0x20,0x6d,0x75,0x6c,0x32,0x34,0x28,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x28,0x69,0x64,0x78,0x20,0x5e,
0x20,0x28,0x4e,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x2c,0x20,0x54,0x68,0x72,0x65,0x61,0x64,0x73,0x29,0x29,0x29,0x0d,0x23,0x65,0x6c,0x69,0x66,0x20,0x28,0x53,0x54,
0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x32,0x29,0x0d,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x53,0x43,0x52,0x41,0x54,0x43,
0x20,0x28,0x4e,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x2c,0x20,0x54,0x68,0x72,0x65,0x61,0x64,0x73,0x29,0x29,0x29,0x0a,0x23,0x65,0x6c,0x69,0x66,0x20,0x28,0x53,0x54,
0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x32,0x29,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x53,0x43,0x52,0x41,0x54,0x43,
0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x4e,0x29,0x20,0x28,0x2a,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x2a,
0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,0x28,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x20,
0x2b,0x20,0x28,0x28,0x28,0x69,0x64,0x78,0x20,0x5e,0x20,0x28,0x4e,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x20,0x25,0x20,0x28,0x4d,0x45,0x4d,0x5f,0x43,0x48,0x55,0x4e,
0x4b,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x20,0x2b,0x20,0x28,0x28,0x69,0x64,0x78,0x20,0x5e,0x20,0x28,0x4e,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x20,0x2f,0x20,0x28,
0x4d,0x45,0x4d,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x20,0x2a,0x20,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x20,0x2a,0x20,0x28,0x4d,
0x45,0x4d,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x29,0x29,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,
0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x52,0x4f,0x54,0x5f,0x42,0x49,0x54,0x53,0x20,0x33,0x32,0x0d,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x4d,0x45,0x4d,0x5f,
0x43,0x48,0x55,0x4e,0x4b,0x20,0x28,0x31,0x20,0x3c,0x3c,0x20,0x4d,0x45,0x4d,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x5f,0x45,0x58,0x50,0x4f,0x4e,0x45,0x4e,0x54,0x29,0x0d,
0x23,0x69,0x66,0x6e,0x64,0x65,0x66,0x20,0x57,0x4f,0x4c,0x46,0x5f,0x41,0x45,0x53,0x5f,0x43,0x4c,0x0d,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x57,0x4f,0x4c,0x46,
0x5f,0x41,0x45,0x53,0x5f,0x43,0x4c,0x0d,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x63,0x6c,0x5f,0x61,0x6d,0x64,0x5f,0x6d,0x65,0x64,0x69,0x61,0x5f,0x6f,0x70,0x73,0x32,
0x0d,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x4f,0x50,0x45,0x4e,0x43,0x4c,0x20,0x45,0x58,0x54,0x45,0x4e,0x53,0x49,0x4f,0x4e,0x20,0x63,0x6c,0x5f,0x61,0x6d,0x64,
0x5f,0x6d,0x65,0x64,0x69,0x61,0x5f,0x6f,0x70,0x73,0x32,0x20,0x3a,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x0d,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x78,0x6d,0x72,
0x45,0x4d,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x20,0x3c,0x3c,0x20,0x34,0x29,0x29,0x29,0x29,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,
0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x52,0x4f,0x54,0x5f,0x42,0x49,0x54,0x53,0x20,0x33,0x32,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x4d,0x45,0x4d,0x5f,
0x43,0x48,0x55,0x4e,0x4b,0x20,0x28,0x31,0x20,0x3c,0x3c,0x20,0x4d,0x45,0x4d,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x5f,0x45,0x58,0x50,0x4f,0x4e,0x45,0x4e,0x54,0x29,0x0a,
0x23,0x69,0x66,0x6e,0x64,0x65,0x66,0x20,0x57,0x4f,0x4c,0x46,0x5f,0x41,0x45,0x53,0x5f,0x43,0x4c,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x57,0x4f,0x4c,0x46,
0x5f,0x41,0x45,0x53,0x5f,0x43,0x4c,0x0a,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x63,0x6c,0x5f,0x61,0x6d,0x64,0x5f,0x6d,0x65,0x64,0x69,0x61,0x5f,0x6f,0x70,0x73,0x32,
0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x4f,0x50,0x45,0x4e,0x43,0x4c,0x20,0x45,0x58,0x54,0x45,0x4e,0x53,0x49,0x4f,0x4e,0x20,0x63,0x6c,0x5f,0x61,0x6d,0x64,
0x5f,0x6d,0x65,0x64,0x69,0x61,0x5f,0x6f,0x70,0x73,0x32,0x20,0x3a,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x78,0x6d,0x72,
0x69,0x67,0x5f,0x61,0x6d,0x64,0x5f,0x62,0x66,0x65,0x28,0x73,0x72,0x63,0x30,0x2c,0x20,0x73,0x72,0x63,0x31,0x2c,0x20,0x73,0x72,0x63,0x32,0x29,0x20,0x61,0x6d,0x64,
0x5f,0x62,0x66,0x65,0x28,0x73,0x72,0x63,0x30,0x2c,0x20,0x73,0x72,0x63,0x31,0x2c,0x20,0x73,0x72,0x63,0x32,0x29,0x0d,0x23,0x65,0x6c,0x73,0x65,0x0d,0x69,0x6e,0x6c,
0x5f,0x62,0x66,0x65,0x28,0x73,0x72,0x63,0x30,0x2c,0x20,0x73,0x72,0x63,0x31,0x2c,0x20,0x73,0x72,0x63,0x32,0x29,0x0a,0x23,0x65,0x6c,0x73,0x65,0x0a,0x69,0x6e,0x6c,
0x69,0x6e,0x65,0x20,0x69,0x6e,0x74,0x20,0x78,0x6d,0x72,0x69,0x67,0x5f,0x61,0x6d,0x64,0x5f,0x62,0x66,0x65,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x20,0x73,0x72,0x63,0x30,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,
0x75,0x69,0x6e,0x74,0x20,0x77,0x69,0x64,0x74,0x68,0x29,0x0d,0x7b,0x0d,0x69,0x66,0x20,0x28,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x77,0x69,0x64,0x74,
0x68,0x29,0x20,0x3c,0x20,0x33,0x32,0x75,0x29,0x20,0x7b,0x0d,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x73,0x72,0x63,0x30,0x20,0x3c,0x3c,0x20,0x28,0x33,0x32,0x75,
0x20,0x2d,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x77,0x69,0x64,0x74,0x68,0x29,0x29,0x20,0x3e,0x3e,0x20,0x28,0x33,0x32,0x75,0x20,0x2d,0x20,0x77,0x69,
0x64,0x74,0x68,0x29,0x3b,0x0d,0x7d,0x0d,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x72,0x63,0x30,0x20,0x3e,0x3e,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x3b,0x0d,0x7d,
0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,
0x75,0x69,0x6e,0x74,0x20,0x41,0x45,0x53,0x30,0x5f,0x43,0x5b,0x32,0x35,0x36,0x5d,0x20,0x3d,0x0d,0x7b,0x0d,0x30,0x78,0x41,0x35,0x36,0x33,0x36,0x33,0x43,0x36,0x55,
0x2c,0x20,0x30,0x78,0x38,0x34,0x37,0x43,0x37,0x43,0x46,0x38,0x55,0x2c,0x20,0x30,0x78,0x39,0x39,0x37,0x37,0x37,0x37,0x45,0x45,0x55,0x2c,0x20,0x30,0x78,0x38,0x44,
0x37,0x42,0x37,0x42,0x46,0x36,0x55,0x2c,0x0d,0x30,0x78,0x30,0x44,0x46,0x32,0x46,0x32,0x46,0x46,0x55,0x2c,0x20,0x30,0x78,0x42,0x44,0x36,0x42,0x36,0x42,0x44,0x36,
0x55,0x2c,0x20,0x30,0x78,0x42,0x31,0x36,0x46,0x36,0x46,0x44,0x45,0x55,0x2c,0x20,0x30,0x78,0x35,0x34,0x43,0x35,0x43,0x35,0x39,0x31,0x55,0x2c,0x0d,0x30,0x78,0x35,
0x30,0x33,0x30,0x33,0x30,0x36,0x30,0x55,0x2c,0x20,0x30,0x78,0x30,0x33,0x30,0x31,0x30,0x31,0x30,0x32,0x55,0x2c,0x20,0x30,0x78,0x41,0x39,0x36,0x37,0x36,0x37,0x43,
0x45,0x55,0x2c,0x20,0x30,0x78,0x37,0x44,0x32,0x42,0x32,0x42,0x35,0x36,0x55,0x2c,0x0d,0x30,0x78,0x31,0x39,0x46,0x45,0x46,0x45,0x45,0x37,0x55,0x2c,0x20,0x30,0x78,
0x36,0x32,0x44,0x37,0x44,0x37,0x42,0x35,0x55,0x2c,0x20,0x30,0x78,0x45,0x36,0x41,0x42,0x41,0x42,0x34,0x44,0x55,0x2c,0x20,0x30,0x78,0x39,0x41,0x37,0x36,0x37,0x36,
0x45,0x43,0x55,0x2c,0x0d,0x30,0x78,0x34,0x35,0x43,0x41,0x43,0x41,0x38,0x46,0x55,0x2c,0x20,0x30,0x78,0x39,0x44,0x38,0x32,0x38,0x32,0x31,0x46,0x55,0x2c,0x20,0x30,
0x78,0x34,0x30,0x43,0x39,0x43,0x39,0x38,0x39,0x55,0x2c,0x20,0x30,0x78,0x38,0x37,0x37,0x44,0x37,0x44,0x46,0x41,0x55,0x2c,0x0d,0x30,0x78,0x31,0x35,0x46,0x41,0x46,
0x41,0x45,0x46,0x55,0x2c,0x20,0x30,0x78,0x45,0x42,0x35,0x39,0x35,0x39,0x42,0x32,0x55,0x2c,0x20,0x30,0x78,0x43,0x39,0x34,0x37,0x34,0x37,0x38,0x45,0x55,0x2c,0x20,
0x30,0x78,0x30,0x42,0x46,0x30,0x46,0x30,0x46,0x42,0x55,0x2c,0x0d,0x30,0x78,0x45,0x43,0x41,0x44,0x41,0x44,0x34,0x31,0x55,0x2c,0x20,0x30,0x78,0x36,0x37,0x44,0x34,
0x44,0x34,0x42,0x33,0x55,0x2c,0x20,0x30,0x78,0x46,0x44,0x41,0x32,0x41,0x32,0x35,0x46,0x55,0x2c,0x20,0x30,0x78,0x45,0x41,0x41,0x46,0x41,0x46,0x34,0x35,0x55,0x2c,
0x0d,0x30,0x78,0x42,0x46,0x39,0x43,0x39,0x43,0x32,0x33,0x55,0x2c,0x20,0x30,0x78,0x46,0x37,0x41,0x34,0x41,0x34,0x35,0x33,0x55,0x2c,0x20,0x30,0x78,0x39,0x36,0x37,
0x32,0x37,0x32,0x45,0x34,0x55,0x2c,0x20,0x30,0x78,0x35,0x42,0x43,0x30,0x43,0x30,0x39,0x42,0x55,0x2c,0x0d,0x30,0x78,0x43,0x32,0x42,0x37,0x42,0x37,0x37,0x35,0x55,
0x2c,0x20,0x30,0x78,0x31,0x43,0x46,0x44,0x46,0x44,0x45,0x31,0x55,0x2c,0x20,0x30,0x78,0x41,0x45,0x39,0x33,0x39,0x33,0x33,0x44,0x55,0x2c,0x20,0x30,0x78,0x36,0x41,
0x32,0x36,0x32,0x36,0x34,0x43,0x55,0x2c,0x0d,0x30,0x78,0x35,0x41,0x33,0x36,0x33,0x36,0x36,0x43,0x55,0x2c,0x20,0x30,0x78,0x34,0x31,0x33,0x46,0x33,0x46,0x37,0x45,
0x55,0x2c,0x20,0x30,0x78,0x30,0x32,0x46,0x37,0x46,0x37,0x46,0x35,0x55,0x2c,0x20,0x30,0x78,0x34,0x46,0x43,0x43,0x43,0x43,0x38,0x33,0x55,0x2c,0x0d,0x30,0x78,0x35,
0x43,0x33,0x34,0x33,0x34,0x36,0x38,0x55,0x2c,0x20,0x30,0x78,0x46,0x34,0x41,0x35,0x41,0x35,0x35,0x31,0x55,0x2c,0x20,0x30,0x78,0x33,0x34,0x45,0x35,0x45,0x35,0x44,
0x31,0x55,0x2c,0x20,0x30,0x78,0x30,0x38,0x46,0x31,0x46,0x31,0x46,0x39,0x55,0x2c,0x0d,0x30,0x78,0x39,0x33,0x37,0x31,0x37,0x31,0x45,0x32,0x55,0x2c,0x20,0x30,0x78,
0x37,0x33,0x44,0x38,0x44,0x38,0x41,0x42,0x55,0x2c,0x20,0x30,0x78,0x35,0x33,0x33,0x31,0x33,0x31,0x36,0x32,0x55,0x2c,0x20,0x30,0x78,0x33,0x46,0x31,0x35,0x31,0x35,
0x32,0x41,0x55,0x2c,0x0d,0x30,0x78,0x30,0x43,0x30,0x34,0x30,0x34,0x30,0x38,0x55,0x2c,0x20,0x30,0x78,0x35,0x32,0x43,0x37,0x43,0x37,0x39,0x35,0x55,0x2c,0x20,0x30,
0x78,0x36,0x35,0x32,0x33,0x32,0x33,0x34,0x36,0x55,0x2c,0x20,0x30,0x78,0x35,0x45,0x43,0x33,0x43,0x33,0x39,0x44,0x55,0x2c,0x0d,0x30,0x78,0x32,0x38,0x31,0x38,0x31,
0x38,0x33,0x30,0x55,0x2c,0x20,0x30,0x78,0x41,0x31,0x39,0x36,0x39,0x36,0x33,0x37,0x55,0x2c,0x20,0x30,0x78,0x30,0x46,0x30,0x35,0x30,0x35,0x30,0x41,0x55,0x2c,0x20,
0x30,0x78,0x42,0x35,0x39,0x41,0x39,0x41,0x32,0x46,0x55,0x2c,0x0d,0x30,0x78,0x30,0x39,0x30,0x37,0x30,0x37,0x30,0x45,0x55,0x2c,0x20,0x30,0x78,0x33,0x36,0x31,0x32,
0x31,0x32,0x32,0x34,0x55,0x2c,0x20,0x30,0x78,0x39,0x42,0x38,0x30,0x38,0x30,0x31,0x42,0x55,0x2c,0x20,0x30,0x78,0x33,0x44,0x45,0x32,0x45,0x32,0x44,0x46,0x55,0x2c,
0x0d,0x30,0x78,0x32,0x36,0x45,0x42,0x45,0x42,0x43,0x44,0x55,0x2c,0x20,0x30,0x78,0x36,0x39,0x32,0x37,0x32,0x37,0x34,0x45,0x55,0x2c,0x20,0x30,0x78,0x43,0x44,0x42,
0x32,0x42,0x32,0x37,0x46,0x55,0x2c,0x20,0x30,0x78,0x39,0x46,0x37,0x35,0x37,0x35,0x45,0x41,0x55,0x2c,0x0d,0x30,0x78,0x31,0x42,0x30,0x39,0x30,0x39,0x31,0x32,0x55,
0x2c,0x20,0x30,0x78,0x39,0x45,0x38,0x33,0x38,0x33,0x31,0x44,0x55,0x2c,0x20,0x30,0x78,0x37,0x34,0x32,0x43,0x32,0x43,0x35,0x38,0x55,0x2c,0x20,0x30,0x78,0x32,0x45,
0x31,0x41,0x31,0x41,0x33,0x34,0x55,0x2c,0x0d,0x30,0x78,0x32,0x44,0x31,0x42,0x31,0x42,0x33,0x36,0x55,0x2c,0x20,0x30,0x78,0x42,0x32,0x36,0x45,0x36,0x45,0x44,0x43,
0x55,0x2c,0x20,0x30,0x78,0x45,0x45,0x35,0x41,0x35,0x41,0x42,0x34,0x55,0x2c,0x20,0x30,0x78,0x46,0x42,0x41,0x30,0x41,0x30,0x35,0x42,0x55,0x2c,0x0d,0x30,0x78,0x46,
0x36,0x35,0x32,0x35,0x32,0x41,0x34,0x55,0x2c,0x20,0x30,0x78,0x34,0x44,0x33,0x42,0x33,0x42,0x37,0x36,0x55,0x2c,0x20,0x30,0x78,0x36,0x31,0x44,0x36,0x44,0x36,0x42,
0x37,0x55,0x2c,0x20,0x30,0x78,0x43,0x45,0x42,0x33,0x42,0x33,0x37,0x44,0x55,0x2c,0x0d,0x30,0x78,0x37,0x42,0x32,0x39,0x32,0x39,0x35,0x32,0x55,0x2c,0x20,0x30,0x78,
0x33,0x45,0x45,0x33,0x45,0x33,0x44,0x44,0x55,0x2c,0x20,0x30,0x78,0x37,0x31,0x32,0x46,0x32,0x46,0x35,0x45,0x55,0x2c,0x20,0x30,0x78,0x39,0x37,0x38,0x34,0x38,0x34,
0x31,0x33,0x55,0x2c,0x0d,0x30,0x78,0x46,0x35,0x35,0x33,0x35,0x33,0x41,0x36,0x55,0x2c,0x20,0x30,0x78,0x36,0x38,0x44,0x31,0x44,0x31,0x42,0x39,0x55,0x2c,0x20,0x30,
0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x2c,0x20,0x30,0x78,0x32,0x43,0x45,0x44,0x45,0x44,0x43,0x31,0x55,0x2c,0x0d,0x30,0x78,0x36,0x30,0x32,0x30,0x32,
0x30,0x34,0x30,0x55,0x2c,0x20,0x30,0x78,0x31,0x46,0x46,0x43,0x46,0x43,0x45,0x33,0x55,0x2c,0x20,0x30,0x78,0x43,0x38,0x42,0x31,0x42,0x31,0x37,0x39,0x55,0x2c,0x20,
0x30,0x78,0x45,0x44,0x35,0x42,0x35,0x42,0x42,0x36,0x55,0x2c,0x0d,0x30,0x78,0x42,0x45,0x36,0x41,0x36,0x41,0x44,0x34,0x55,0x2c,0x20,0x30,0x78,0x34,0x36,0x43,0x42,
0x43,0x42,0x38,0x44,0x55,0x2c,0x20,0x30,0x78,0x44,0x39,0x42,0x45,0x42,0x45,0x36,0x37,0x55,0x2c,0x20,0x30,0x78,0x34,0x42,0x33,0x39,0x33,0x39,0x37,0x32,0x55,0x2c,
0x0d,0x30,0x78,0x44,0x45,0x34,0x41,0x34,0x41,0x39,0x34,0x55,0x2c,0x20,0x30,0x78,0x44,0x34,0x34,0x43,0x34,0x43,0x39,0x38,0x55,0x2c,0x20,0x30,0x78,0x45,0x38,0x35,
0x38,0x35,0x38,0x42,0x30,0x55,0x2c,0x20,0x30,0x78,0x34,0x41,0x43,0x46,0x43,0x46,0x38,0x35,0x55,0x2c,0x0d,0x30,0x78,0x36,0x42,0x44,0x30,0x44,0x30,0x42,0x42,0x55,
0x2c,0x20,0x30,0x78,0x32,0x41,0x45,0x46,0x45,0x46,0x43,0x35,0x55,0x2c,0x20,0x30,0x78,0x45,0x35,0x41,0x41,0x41,0x41,0x34,0x46,0x55,0x2c,0x20,0x30,0x78,0x31,0x36,
0x46,0x42,0x46,0x42,0x45,0x44,0x55,0x2c,0x0d,0x30,0x78,0x43,0x35,0x34,0x33,0x34,0x33,0x38,0x36,0x55,0x2c,0x20,0x30,0x78,0x44,0x37,0x34,0x44,0x34,0x44,0x39,0x41,
0x55,0x2c,0x20,0x30,0x78,0x35,0x35,0x33,0x33,0x33,0x33,0x36,0x36,0x55,0x2c,0x20,0x30,0x78,0x39,0x34,0x38,0x35,0x38,0x35,0x31,0x31,0x55,0x2c,0x0d,0x30,0x78,0x43,
0x46,0x34,0x35,0x34,0x35,0x38,0x41,0x55,0x2c,0x20,0x30,0x78,0x31,0x30,0x46,0x39,0x46,0x39,0x45,0x39,0x55,0x2c,0x20,0x30,0x78,0x30,0x36,0x30,0x32,0x30,0x32,0x30,
0x34,0x55,0x2c,0x20,0x30,0x78,0x38,0x31,0x37,0x46,0x37,0x46,0x46,0x45,0x55,0x2c,0x0d,0x30,0x78,0x46,0x30,0x35,0x30,0x35,0x30,0x41,0x30,0x55,0x2c,0x20,0x30,0x78,
0x34,0x34,0x33,0x43,0x33,0x43,0x37,0x38,0x55,0x2c,0x20,0x30,0x78,0x42,0x41,0x39,0x46,0x39,0x46,0x32,0x35,0x55,0x2c,0x20,0x30,0x78,0x45,0x33,0x41,0x38,0x41,0x38,
0x34,0x42,0x55,0x2c,0x0d,0x30,0x78,0x46,0x33,0x35,0x31,0x35,0x31,0x41,0x32,0x55,0x2c,0x20,0x30,0x78,0x46,0x45,0x41,0x33,0x41,0x33,0x35,0x44,0x55,0x2c,0x20,0x30,
0x78,0x43,0x30,0x34,0x30,0x34,0x30,0x38,0x30,0x55,0x2c,0x20,0x30,0x78,0x38,0x41,0x38,0x46,0x38,0x46,0x30,0x35,0x55,0x2c,0x0d,0x30,0x78,0x41,0x44,0x39,0x32,0x39,
0x32,0x33,0x46,0x55,0x2c,0x20,0x30,0x78,0x42,0x43,0x39,0x44,0x39,0x44,0x32,0x31,0x55,0x2c,0x20,0x30,0x78,0x34,0x38,0x33,0x38,0x33,0x38,0x37,0x30,0x55,0x2c,0x20,
0x30,0x78,0x30,0x34,0x46,0x35,0x46,0x35,0x46,0x31,0x55,0x2c,0x0d,0x30,0x78,0x44,0x46,0x42,0x43,0x42,0x43,0x36,0x33,0x55,0x2c,0x20,0x30,0x78,0x43,0x31,0x42,0x36,
0x42,0x36,0x37,0x37,0x55,0x2c,0x20,0x30,0x78,0x37,0x35,0x44,0x41,0x44,0x41,0x41,0x46,0x55,0x2c,0x20,0x30,0x78,0x36,0x33,0x32,0x31,0x32,0x31,0x34,0x32,0x55,0x2c,
0x0d,0x30,0x78,0x33,0x30,0x31,0x30,0x31,0x30,0x32,0x30,0x55,0x2c,0x20,0x30,0x78,0x31,0x41,0x46,0x46,0x46,0x46,0x45,0x35,0x55,0x2c,0x20,0x30,0x78,0x30,0x45,0x46,
0x33,0x46,0x33,0x46,0x44,0x55,0x2c,0x20,0x30,0x78,0x36,0x44,0x44,0x32,0x44,0x32,0x42,0x46,0x55,0x2c,0x0d,0x30,0x78,0x34,0x43,0x43,0x44,0x43,0x44,0x38,0x31,0x55,
0x2c,0x20,0x30,0x78,0x31,0x34,0x30,0x43,0x30,0x43,0x31,0x38,0x55,0x2c,0x20,0x30,0x78,0x33,0x35,0x31,0x33,0x31,0x33,0x32,0x36,0x55,0x2c,0x20,0x30,0x78,0x32,0x46,
0x45,0x43,0x45,0x43,0x43,0x33,0x55,0x2c,0x0d,0x30,0x78,0x45,0x31,0x35,0x46,0x35,0x46,0x42,0x45,0x55,0x2c,0x20,0x30,0x78,0x41,0x32,0x39,0x37,0x39,0x37,0x33,0x35,
0x55,0x2c,0x20,0x30,0x78,0x43,0x43,0x34,0x34,0x34,0x34,0x38,0x38,0x55,0x2c,0x20,0x30,0x78,0x33,0x39,0x31,0x37,0x31,0x37,0x32,0x45,0x55,0x2c,0x0d,0x30,0x78,0x35,
0x37,0x43,0x34,0x43,0x34,0x39,0x33,0x55,0x2c,0x20,0x30,0x78,0x46,0x32,0x41,0x37,0x41,0x37,0x35,0x35,0x55,0x2c,0x20,0x30,0x78,0x38,0x32,0x37,0x45,0x37,0x45,0x46,
0x43,0x55,0x2c,0x20,0x30,0x78,0x34,0x37,0x33,0x44,0x33,0x44,0x37,0x41,0x55,0x2c,0x0d,0x30,0x78,0x41,0x43,0x36,0x34,0x36,0x34,0x43,0x38,0x55,0x2c,0x20,0x30,0x78,
0x45,0x37,0x35,0x44,0x35,0x44,0x42,0x41,0x55,0x2c,0x20,0x30,0x78,0x32,0x42,0x31,0x39,0x31,0x39,0x33,0x32,0x55,0x2c,0x20,0x30,0x78,0x39,0x35,0x37,0x33,0x37,0x33,
0x45,0x36,0x55,0x2c,0x0d,0x30,0x78,0x41,0x30,0x36,0x30,0x36,0x30,0x43,0x30,0x55,0x2c,0x20,0x30,0x78,0x39,0x38,0x38,0x31,0x38,0x31,0x31,0x39,0x55,0x2c,0x20,0x30,
0x78,0x44,0x31,0x34,0x46,0x34,0x46,0x39,0x45,0x55,0x2c,0x20,0x30,0x78,0x37,0x46,0x44,0x43,0x44,0x43,0x41,0x33,0x55,0x2c,0x0d,0x30,0x78,0x36,0x36,0x32,0x32,0x32,
0x32,0x34,0x34,0x55,0x2c,0x20,0x30,0x78,0x37,0x45,0x32,0x41,0x32,0x41,0x35,0x34,0x55,0x2c,0x20,0x30,0x78,0x41,0x42,0x39,0x30,0x39,0x30,0x33,0x42,0x55,0x2c,0x20,
0x30,0x78,0x38,0x33,0x38,0x38,0x38,0x38,0x30,0x42,0x55,0x2c,0x0d,0x30,0x78,0x43,0x41,0x34,0x36,0x34,0x36,0x38,0x43,0x55,0x2c,0x20,0x30,0x78,0x32,0x39,0x45,0x45,
0x45,0x45,0x43,0x37,0x55,0x2c,0x20,0x30,0x78,0x44,0x33,0x42,0x38,0x42,0x38,0x36,0x42,0x55,0x2c,0x20,0x30,0x78,0x33,0x43,0x31,0x34,0x31,0x34,0x32,0x38,0x55,0x2c,
0x0d,0x30,0x78,0x37,0x39,0x44,0x45,0x44,0x45,0x41,0x37,0x55,0x2c,0x20,0x30,0x78,0x45,0x32,0x35,0x45,0x35,0x45,0x42,0x43,0x55,0x2c,0x20,0x30,0x78,0x31,0x44,0x30,
0x42,0x30,0x42,0x31,0x36,0x55,0x2c,0x20,0x30,0x78,0x37,0x36,0x44,0x42,0x44,0x42,0x41,0x44,0x55,0x2c,0x0d,0x30,0x78,0x33,0x42,0x45,0x30,0x45,0x30,0x44,0x42,0x55,
0x2c,0x20,0x30,0x78,0x35,0x36,0x33,0x32,0x33,0x32,0x36,0x34,0x55,0x2c,0x20,0x30,0x78,0x34,0x45,0x33,0x41,0x33,0x41,0x37,0x34,0x55,0x2c,0x20,0x30,0x78,0x31,0x45,
0x30,0x41,0x30,0x41,0x31,0x34,0x55,0x2c,0x0d,0x30,0x78,0x44,0x42,0x34,0x39,0x34,0x39,0x39,0x32,0x55,0x2c,0x20,0x30,0x78,0x30,0x41,0x30,0x36,0x30,0x36,0x30,0x43,
0x55,0x2c,0x20,0x30,0x78,0x36,0x43,0x32,0x34,0x32,0x34,0x34,0x38,0x55,0x2c,0x20,0x30,0x78,0x45,0x34,0x35,0x43,0x35,0x43,0x42,0x38,0x55,0x2c,0x0d,0x30,0x78,0x35,
0x44,0x43,0x32,0x43,0x32,0x39,0x46,0x55,0x2c,0x20,0x30,0x78,0x36,0x45,0x44,0x33,0x44,0x33,0x42,0x44,0x55,0x2c,0x20,0x30,0x78,0x45,0x46,0x41,0x43,0x41,0x43,0x34,
0x33,0x55,0x2c,0x20,0x30,0x78,0x41,0x36,0x36,0x32,0x36,0x32,0x43,0x34,0x55,0x2c,0x0d,0x30,0x78,0x41,0x38,0x39,0x31,0x39,0x31,0x33,0x39,0x55,0x2c,0x20,0x30,0x78,
0x41,0x34,0x39,0x35,0x39,0x35,0x33,0x31,0x55,0x2c,0x20,0x30,0x78,0x33,0x37,0x45,0x34,0x45,0x34,0x44,0x33,0x55,0x2c,0x20,0x30,0x78,0x38,0x42,0x37,0x39,0x37,0x39,
0x46,0x32,0x55,0x2c,0x0d,0x30,0x78,0x33,0x32,0x45,0x37,0x45,0x37,0x44,0x35,0x55,0x2c,0x20,0x30,0x78,0x34,0x33,0x43,0x38,0x43,0x38,0x38,0x42,0x55,0x2c,0x20,0x30,
0x78,0x35,0x39,0x33,0x37,0x33,0x37,0x36,0x45,0x55,0x2c,0x20,0x30,0x78,0x42,0x37,0x36,0x44,0x36,0x44,0x44,0x41,0x55,0x2c,0x0d,0x30,0x78,0x38,0x43,0x38,0x44,0x38,
0x44,0x30,0x31,0x55,0x2c,0x20,0x30,0x78,0x36,0x34,0x44,0x35,0x44,0x35,0x42,0x31,0x55,0x2c,0x20,0x30,0x78,0x44,0x32,0x34,0x45,0x34,0x45,0x39,0x43,0x55,0x2c,0x20,
0x30,0x78,0x45,0x30,0x41,0x39,0x41,0x39,0x34,0x39,0x55,0x2c,0x0d,0x30,0x78,0x42,0x34,0x36,0x43,0x36,0x43,0x44,0x38,0x55,0x2c,0x20,0x30,0x78,0x46,0x41,0x35,0x36,
0x35,0x36,0x41,0x43,0x55,0x2c,0x20,0x30,0x78,0x30,0x37,0x46,0x34,0x46,0x34,0x46,0x33,0x55,0x2c,0x20,0x30,0x78,0x32,0x35,0x45,0x41,0x45,0x41,0x43,0x46,0x55,0x2c,
0x0d,0x30,0x78,0x41,0x46,0x36,0x35,0x36,0x35,0x43,0x41,0x55,0x2c,0x20,0x30,0x78,0x38,0x45,0x37,0x41,0x37,0x41,0x46,0x34,0x55,0x2c,0x20,0x30,0x78,0x45,0x39,0x41,
0x45,0x41,0x45,0x34,0x37,0x55,0x2c,0x20,0x30,0x78,0x31,0x38,0x30,0x38,0x30,0x38,0x31,0x30,0x55,0x2c,0x0d,0x30,0x78,0x44,0x35,0x42,0x41,0x42,0x41,0x36,0x46,0x55,
0x2c,0x20,0x30,0x78,0x38,0x38,0x37,0x38,0x37,0x38,0x46,0x30,0x55,0x2c,0x20,0x30,0x78,0x36,0x46,0x32,0x35,0x32,0x35,0x34,0x41,0x55,0x2c,0x20,0x30,0x78,0x37,0x32,
0x32,0x45,0x32,0x45,0x35,0x43,0x55,0x2c,0x0d,0x30,0x78,0x32,0x34,0x31,0x43,0x31,0x43,0x33,0x38,0x55,0x2c,0x20,0x30,0x78,0x46,0x31,0x41,0x36,0x41,0x36,0x35,0x37,
0x55,0x2c,0x20,0x30,0x78,0x43,0x37,0x42,0x34,0x42,0x34,0x37,0x33,0x55,0x2c,0x20,0x30,0x78,0x35,0x31,0x43,0x36,0x43,0x36,0x39,0x37,0x55,0x2c,0x0d,0x30,0x78,0x32,
0x33,0x45,0x38,0x45,0x38,0x43,0x42,0x55,0x2c,0x20,0x30,0x78,0x37,0x43,0x44,0x44,0x44,0x44,0x41,0x31,0x55,0x2c,0x20,0x30,0x78,0x39,0x43,0x37,0x34,0x37,0x34,0x45,
0x38,0x55,0x2c,0x20,0x30,0x78,0x32,0x31,0x31,0x46,0x31,0x46,0x33,0x45,0x55,0x2c,0x0d,0x30,0x78,0x44,0x44,0x34,0x42,0x34,0x42,0x39,0x36,0x55,0x2c,0x20,0x30,0x78,
0x44,0x43,0x42,0x44,0x42,0x44,0x36,0x31,0x55,0x2c,0x20,0x30,0x78,0x38,0x36,0x38,0x42,0x38,0x42,0x30,0x44,0x55,0x2c,0x20,0x30,0x78,0x38,0x35,0x38,0x41,0x38,0x41,
0x30,0x46,0x55,0x2c,0x0d,0x30,0x78,0x39,0x30,0x37,0x30,0x37,0x30,0x45,0x30,0x55,0x2c,0x20,0x30,0x78,0x34,0x32,0x33,0x45,0x33,0x45,0x37,0x43,0x55,0x2c,0x20,0x30,
0x78,0x43,0x34,0x42,0x35,0x42,0x35,0x37,0x31,0x55,0x2c,0x20,0x30,0x78,0x41,0x41,0x36,0x36,0x36,0x36,0x43,0x43,0x55,0x2c,0x0d,0x30,0x78,0x44,0x38,0x34,0x38,0x34,
0x38,0x39,0x30,0x55,0x2c,0x20,0x30,0x78,0x30,0x35,0x30,0x33,0x30,0x33,0x30,0x36,0x55,0x2c,0x20,0x30,0x78,0x30,0x31,0x46,0x36,0x46,0x36,0x46,0x37,0x55,0x2c,0x20,
0x30,0x78,0x31,0x32,0x30,0x45,0x30,0x45,0x31,0x43,0x55,0x2c,0x0d,0x30,0x78,0x41,0x33,0x36,0x31,0x36,0x31,0x43,0x32,0x55,0x2c,0x20,0x30,0x78,0x35,0x46,0x33,0x35,
0x33,0x35,0x36,0x41,0x55,0x2c,0x20,0x30,0x78,0x46,0x39,0x35,0x37,0x35,0x37,0x41,0x45,0x55,0x2c,0x20,0x30,0x78,0x44,0x30,0x42,0x39,0x42,0x39,0x36,0x39,0x55,0x2c,
0x0d,0x30,0x78,0x39,0x31,0x38,0x36,0x38,0x36,0x31,0x37,0x55,0x2c,0x20,0x30,0x78,0x35,0x38,0x43,0x31,0x43,0x31,0x39,0x39,0x55,0x2c,0x20,0x30,0x78,0x32,0x37,0x31,
0x44,0x31,0x44,0x33,0x41,0x55,0x2c,0x20,0x30,0x78,0x42,0x39,0x39,0x45,0x39,0x45,0x32,0x37,0x55,0x2c,0x0d,0x30,0x78,0x33,0x38,0x45,0x31,0x45,0x31,0x44,0x39,0x55,
0x2c,0x20,0x30,0x78,0x31,0x33,0x46,0x38,0x46,0x38,0x45,0x42,0x55,0x2c,0x20,0x30,0x78,0x42,0x33,0x39,0x38,0x39,0x38,0x32,0x42,0x55,0x2c,0x20,0x30,0x78,0x33,0x33,
0x31,0x31,0x31,0x31,0x32,0x32,0x55,0x2c,0x0d,0x30,0x78,0x42,0x42,0x36,0x39,0x36,0x39,0x44,0x32,0x55,0x2c,0x20,0x30,0x78,0x37,0x30,0x44,0x39,0x44,0x39,0x41,0x39,
0x55,0x2c,0x20,0x30,0x78,0x38,0x39,0x38,0x45,0x38,0x45,0x30,0x37,0x55,0x2c,0x20,0x30,0x78,0x41,0x37,0x39,0x34,0x39,0x34,0x33,0x33,0x55,0x2c,0x0d,0x30,0x78,0x42,
0x36,0x39,0x42,0x39,0x42,0x32,0x44,0x55,0x2c,0x20,0x30,0x78,0x32,0x32,0x31,0x45,0x31,0x45,0x33,0x43,0x55,0x2c,0x20,0x30,0x78,0x39,0x32,0x38,0x37,0x38,0x37,0x31,
0x35,0x55,0x2c,0x20,0x30,0x78,0x32,0x30,0x45,0x39,0x45,0x39,0x43,0x39,0x55,0x2c,0x0d,0x30,0x78,0x34,0x39,0x43,0x45,0x43,0x45,0x38,0x37,0x55,0x2c,0x20,0x30,0x78,
0x46,0x46,0x35,0x35,0x35,0x35,0x41,0x41,0x55,0x2c,0x20,0x30,0x78,0x37,0x38,0x32,0x38,0x32,0x38,0x35,0x30,0x55,0x2c,0x20,0x30,0x78,0x37,0x41,0x44,0x46,0x44,0x46,
0x41,0x35,0x55,0x2c,0x0d,0x30,0x78,0x38,0x46,0x38,0x43,0x38,0x43,0x30,0x33,0x55,0x2c,0x20,0x30,0x78,0x46,0x38,0x41,0x31,0x41,0x31,0x35,0x39,0x55,0x2c,0x20,0x30,
0x78,0x38,0x30,0x38,0x39,0x38,0x39,0x30,0x39,0x55,0x2c,0x20,0x30,0x78,0x31,0x37,0x30,0x44,0x30,0x44,0x31,0x41,0x55,0x2c,0x0d,0x30,0x78,0x44,0x41,0x42,0x46,0x42,
0x46,0x36,0x35,0x55,0x2c,0x20,0x30,0x78,0x33,0x31,0x45,0x36,0x45,0x36,0x44,0x37,0x55,0x2c,0x20,0x30,0x78,0x43,0x36,0x34,0x32,0x34,0x32,0x38,0x34,0x55,0x2c,0x20,
0x30,0x78,0x42,0x38,0x36,0x38,0x36,0x38,0x44,0x30,0x55,0x2c,0x0d,0x30,0x78,0x43,0x33,0x34,0x31,0x34,0x31,0x38,0x32,0x55,0x2c,0x20,0x30,0x78,0x42,0x30,0x39,0x39,
0x39,0x39,0x32,0x39,0x55,0x2c,0x20,0x30,0x78,0x37,0x37,0x32,0x44,0x32,0x44,0x35,0x41,0x55,0x2c,0x20,0x30,0x78,0x31,0x31,0x30,0x46,0x30,0x46,0x31,0x45,0x55,0x2c,
0x0d,0x30,0x78,0x43,0x42,0x42,0x30,0x42,0x30,0x37,0x42,0x55,0x2c,0x20,0x30,0x78,0x46,0x43,0x35,0x34,0x35,0x34,0x41,0x38,0x55,0x2c,0x20,0x30,0x78,0x44,0x36,0x42,
0x42,0x42,0x42,0x36,0x44,0x55,0x2c,0x20,0x30,0x78,0x33,0x41,0x31,0x36,0x31,0x36,0x32,0x43,0x55,0x0d,0x7d,0x3b,0x0d,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x42,
0x59,0x54,0x45,0x28,0x78,0x2c,0x20,0x79,0x29,0x20,0x28,0x78,0x6d,0x72,0x69,0x67,0x5f,0x61,0x6d,0x64,0x5f,0x62,0x66,0x65,0x28,0x28,0x78,0x29,0x2c,0x20,0x28,0x79,
0x29,0x20,0x3c,0x3c,0x20,0x33,0x55,0x2c,0x20,0x38,0x55,0x29,0x29,0x0d,0x23,0x69,0x66,0x20,0x28,0x41,0x4c,0x47,0x4f,0x20,0x3d,0x3d,0x20,0x41,0x4c,0x47,0x4f,0x5f,
0x43,0x4e,0x5f,0x48,0x45,0x41,0x56,0x59,0x5f,0x54,0x55,0x42,0x45,0x29,0x0d,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x41,0x45,0x53,0x5f,
0x52,0x6f,0x75,0x6e,0x64,0x5f,0x62,0x69,0x74,0x74,0x75,0x62,0x65,0x32,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,
0x74,0x20,0x2a,0x41,0x45,0x53,0x30,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,
0x31,0x2c,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x78,0x2c,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x6b,0x29,0x0d,0x7b,0x0d,0x78,0x20,0x3d,0x20,0x7e,0x78,0x3b,0x0d,0x6b,
0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,
0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,
0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,0x20,
0x33,0x29,0x5d,0x2c,0x20,0x31,0x36,0x55,0x29,0x3b,0x0d,0x78,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x6b,0x2e,0x73,0x30,0x3b,0x0d,0x6b,0x2e,0x73,0x31,0x20,0x5e,0x3d,
0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,
0x28,0x78,0x2e,0x73,0x32,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,
0x73,0x33,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x20,0x33,0x29,0x5d,0x2c,0x20,0x31,
0x36,0x55,0x29,0x3b,0x0d,0x78,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x6b,0x2e,0x73,0x31,0x3b,0x0d,0x6b,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,
0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,
0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x20,0x32,0x29,
0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x20,0x33,0x29,0x5d,0x2c,0x20,0x31,0x36,0x55,0x29,0x3b,0x0d,0x78,
0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x6b,0x2e,0x73,0x32,0x3b,0x0d,0x6b,0x2e,0x73,0x33,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,
0x2e,0x73,0x33,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,
0x20,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,
0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,0x20,0x33,0x29,0x5d,0x2c,0x20,0x31,0x36,0x55,0x29,0x3b,0x0d,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
0x6b,0x3b,0x0d,0x7d,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x75,0x69,0x6e,0x74,0x34,0x20,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x28,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x30,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,
0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x31,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,
0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x32,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,
0x53,0x33,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x58,0x2c,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x6b,0x65,0x79,0x29,0x0d,0x7b,0x0d,
0x6b,0x65,0x79,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,
0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,0x45,0x28,
0x58,0x2e,0x73,0x32,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x20,0x33,0x29,0x5d,0x3b,
0x0d,0x6b,0x65,0x79,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,
0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,0x45,
0x28,0x58,0x2e,0x73,0x33,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x20,0x33,0x29,0x5d,
0x3b,0x0d,0x6b,0x65,0x79,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x20,0x30,0x29,0x5d,0x20,
0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,
0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x20,0x33,0x29,
0x5d,0x3b,0x0d,0x6b,0x65,0x79,0x2e,0x73,0x33,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x20,0x30,0x29,0x5d,
0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,
0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x20,0x33,
0x29,0x5d,0x3b,0x0d,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6b,0x65,0x79,0x3b,0x0d,0x7d,0x0d,0x75,0x69,0x6e,0x74,0x34,0x20,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,
0x64,0x5f,0x54,0x77,0x6f,0x5f,0x54,0x61,0x62,0x6c,0x65,0x73,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,
0x2a,0x41,0x45,0x53,0x30,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x31,0x2c,
0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x58,0x2c,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x6b,0x65,0x79,0x29,0x0d,0x7b,0x0d,0x6b,0x65,0x79,
0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,
0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,
0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x20,
0x33,0x29,0x5d,0x2c,0x20,0x31,0x36,0x55,0x29,0x3b,0x0d,0x6b,0x65,0x79,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,
0x2e,0x73,0x31,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,
0x20,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,
0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x20,0x33,0x29,0x5d,0x2c,0x20,0x31,0x36,0x55,0x29,0x3b,0x0d,0x6b,0x65,0x79,0x2e,0x73,0x32,0x20,
0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,
0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,
0x58,0x2e,0x73,0x30,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x20,0x33,0x29,0x5d,0x2c,
0x20,0x31,0x36,0x55,0x29,0x3b,0x0d,0x6b,0x65,0x79,0x2e,0x73,0x33,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,
0x20,0x30,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x20,0x31,0x29,0x5d,0x20,0x5e,0x20,0x72,0x6f,0x74,
0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x20,0x32,0x29,0x5d,0x20,0x5e,0x20,0x41,0x45,0x53,0x31,0x5b,0x42,
0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x20,0x33,0x29,0x5d,0x2c,0x20,0x31,0x36,0x55,0x29,0x3b,0x0d,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6b,0x65,0x79,0x3b,
0x0d,0x7d,0x0d,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x63,0x68,0x61,0x72,
0x20,0x72,0x63,0x6f,0x6e,0x5b,0x38,0x5d,0x20,0x3d,0x20,0x7b,0x20,0x30,0x78,0x38,0x64,0x2c,0x20,0x30,0x78,0x30,0x31,0x2c,0x20,0x30,0x78,0x30,0x32,0x2c,0x20,0x30,
0x78,0x30,0x34,0x2c,0x20,0x30,0x78,0x30,0x38,0x2c,0x20,0x30,0x78,0x31,0x30,0x2c,0x20,0x30,0x78,0x32,0x30,0x2c,0x20,0x30,0x78,0x34,0x30,0x20,0x7d,0x3b,0x0d,0x73,
0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x63,0x68,0x61,0x72,0x20,0x73,0x62,0x6f,
0x78,0x5b,0x32,0x35,0x36,0x5d,0x20,0x3d,0x0d,0x7b,0x0d,0x30,0x78,0x36,0x33,0x2c,0x20,0x30,0x78,0x37,0x43,0x2c,0x20,0x30,0x78,0x37,0x37,0x2c,0x20,0x30,0x78,0x37,
0x42,0x2c,0x20,0x30,0x78,0x46,0x32,0x2c,0x20,0x30,0x78,0x36,0x42,0x2c,0x20,0x30,0x78,0x36,0x46,0x2c,0x20,0x30,0x78,0x43,0x35,0x2c,0x20,0x30,0x78,0x33,0x30,0x2c,
0x20,0x30,0x78,0x30,0x31,0x2c,0x20,0x30,0x78,0x36,0x37,0x2c,0x20,0x30,0x78,0x32,0x42,0x2c,0x20,0x30,0x78,0x46,0x45,0x2c,0x20,0x30,0x78,0x44,0x37,0x2c,0x20,0x30,
0x78,0x41,0x42,0x2c,0x20,0x30,0x78,0x37,0x36,0x2c,0x0d,0x30,0x78,0x43,0x41,0x2c,0x20,0x30,0x78,0x38,0x32,0x2c,0x20,0x30,0x78,0x43,0x39,0x2c,0x20,0x30,0x78,0x37,
0x44,0x2c,0x20,0x30,0x78,0x46,0x41,0x2c,0x20,0x30,0x78,0x35,0x39,0x2c,0x20,0x30,0x78,0x34,0x37,0x2c,0x20,0x30,0x78,0x46,0x30,0x2c,0x20,0x30,0x78,0x41,0x44,0x2c,
0x20,0x30,0x78,0x44,0x34,0x2c,0x20,0x30,0x78,0x41,0x32,0x2c,0x20,0x30,0x78,0x41,0x46,0x2c,0x20,0x30,0x78,0x39,0x43,0x2c,0x20,0x30,0x78,0x41,0x34,0x2c,0x20,0x30,
0x78,0x37,0x32,0x2c,0x20,0x30,0x78,0x43,0x30,0x2c,0x0d,0x30,0x78,0x42,0x37,0x2c,0x20,0x30,0x78,0x46,0x44,0x2c,0x20,0x30,0x78,0x39,0x33,0x2c,0x20,0x30,0x78,0x32,
0x36,0x2c,0x20,0x30,0x78,0x33,0x36,0x2c,0x20,0x30,0x78,0x33,0x46,0x2c,0x20,0x30,0x78,0x46,0x37,0x2c,0x20,0x30,0x78,0x43,0x43,0x2c,0x20,0x30,0x78,0x33,0x34,0x2c,
0x20,0x30,0x78,0x41,0x35,0x2c,0x20,0x30,0x78,0x45,0x35,0x2c,0x20,0x30,0x78,0x46,0x31,0x2c,0x20,0x30,0x78,0x37,0x31,0x2c,0x20,0x30,0x78,0x44,0x38,0x2c,0x20,0x30,
0x78,0x33,0x31,0x2c,0x20,0x30,0x78,0x31,0x35,0x2c,0x0d,0x30,0x78,0x30,0x34,0x2c,0x20,0x30,0x78,0x43,0x37,0x2c,0x20,0x30,0x78,0x32,0x33,0x2c,0x20,0x30,0x78,0x43,
0x33,0x2c,0x20,0x30,0x78,0x31,0x38,0x2c,0x20,0x30,0x78,0x39,0x36,0x2c,0x20,0x30,0x78,0x30,0x35,0x2c,0x20,0x30,0x78,0x39,0x41,0x2c,0x20,0x30,0x78,0x30,0x37,0x2c,
0x20,0x30,0x78,0x31,0x32,0x2c,0x20,0x30,0x78,0x38,0x30,0x2c,0x20,0x30,0x78,0x45,0x32,0x2c,0x20,0x30,0x78,0x45,0x42,0x2c,0x20,0x30,0x78,0x32,0x37,0x2c,0x20,0x30,
0x78,0x42,0x32,0x2c,0x20,0x30,0x78,0x37,0x35,0x2c,0x0d,0x30,0x78,0x30,0x39,0x2c,0x20,0x30,0x78,0x38,0x33,0x2c,0x20,0x30,0x78,0x32,0x43,0x2c,0x20,0x30,0x78,0x31,
0x41,0x2c,0x20,0x30,0x78,0x31,0x42,0x2c,0x20,0x30,0x78,0x36,0x45,0x2c,0x20,0x30,0x78,0x35,0x41,0x2c,0x20,0x30,0x78,0x41,0x30,0x2c,0x20,0x30,0x78,0x35,0x32,0x2c,
0x20,0x30,0x78,0x33,0x42,0x2c,0x20,0x30,0x78,0x44,0x36,0x2c,0x20,0x30,0x78,0x42,0x33,0x2c,0x20,0x30,0x78,0x32,0x39,0x2c,0x20,0x30,0x78,0x45,0x33,0x2c,0x20,0x30,
0x78,0x32,0x46,0x2c,0x20,0x30,0x78,0x38,0x34,0x2c,0x0d,0x30,0x78,0x35,0x33,0x2c,0x20,0x30,0x78,0x44,0x31,0x2c,0x20,0x30,0x78,0x30,0x30,0x2c,0x20,0x30,0x78,0x45,
0x44,0x2c,0x20,0x30,0x78,0x32,0x30,0x2c,0x20,0x30,0x78,0x46,0x43,0x2c,0x20,0x30,0x78,0x42,0x31,0x2c,0x20,0x30,0x78,0x35,0x42,0x2c,0x20,0x30,0x78,0x36,0x41,0x2c,
0x20,0x30,0x78,0x43,0x42,0x2c,0x20,0x30,0x78,0x42,0x45,0x2c,0x20,0x30,0x78,0x33,0x39,0x2c,0x20,0x30,0x78,0x34,0x41,0x2c,0x20,0x30,0x78,0x34,0x43,0x2c,0x20,0x30,
0x78,0x35,0x38,0x2c,0x20,0x30,0x78,0x43,0x46,0x2c,0x0d,0x30,0x78,0x44,0x30,0x2c,0x20,0x30,0x78,0x45,0x46,0x2c,0x20,0x30,0x78,0x41,0x41,0x2c,0x20,0x30,0x78,0x46,
0x42,0x2c,0x20,0x30,0x78,0x34,0x33,0x2c,0x20,0x30,0x78,0x34,0x44,0x2c,0x20,0x30,0x78,0x33,0x33,0x2c,0x20,0x30,0x78,0x38,0x35,0x2c,0x20,0x30,0x78,0x34,0x35,0x2c,
0x20,0x30,0x78,0x46,0x39,0x2c,0x20,0x30,0x78,0x30,0x32,0x2c,0x20,0x30,0x78,0x37,0x46,0x2c,0x20,0x30,0x78,0x35,0x30,0x2c,0x20,0x30,0x78,0x33,0x43,0x2c,0x20,0x30,
0x78,0x39,0x46,0x2c,0x20,0x30,0x78,0x41,0x38,0x2c,0x0d,0x30,0x78,0x35,0x31,0x2c,0x20,0x30,0x78,0x41,0x33,0x2c,0x20,0x30,0x78,0x34,0x30,0x2c,0x20,0x30,0x78,0x38,
0x46,0x2c,0x20,0x30,0x78,0x39,0x32,0x2c,0x20,0x30,0x78,0x39,0x44,0x2c,0x20,0x30,0x78,0x33,0x38,0x2c,0x20,0x30,0x78,0x46,0x35,0x2c,0x20,0x30,0x78,0x42,0x43,0x2c,
0x20,0x30,0x78,0x42,0x36,0x2c,0x20,0x30,0x78,0x44,0x41,0x2c,0x20,0x30,0x78,0x32,0x31,0x2c,0x20,0x30,0x78,0x31,0x30,0x2c,0x20,0x30,0x78,0x46,0x46,0x2c,0x20,0x30,
0x78,0x46,0x33,0x2c,0x20,0x30,0x78,0x44,0x32,0x2c,0x0d,0x30,0x78,0x43,0x44,0x2c,0x20,0x30,0x78,0x30,0x43,0x2c,0x20,0x30,0x78,0x31,0x33,0x2c,0x20,0x30,0x78,0x45,
0x43,0x2c,0x20,0x30,0x78,0x35,0x46,0x2c,0x20,0x30,0x78,0x39,0x37,0x2c,0x20,0x30,0x78,0x34,0x34,0x2c,0x20,0x30,0x78,0x31,0x37,0x2c,0x20,0x30,0x78,0x43,0x34,0x2c,
0x20,0x30,0x78,0x41,0x37,0x2c,0x20,0x30,0x78,0x37,0x45,0x2c,0x20,0x30,0x78,0x33,0x44,0x2c,0x20,0x30,0x78,0x36,0x34,0x2c,0x20,0x30,0x78,0x35,0x44,0x2c,0x20,0x30,
0x78,0x31,0x39,0x2c,0x20,0x30,0x78,0x37,0x33,0x2c,0x0d,0x30,0x78,0x36,0x30,0x2c,0x20,0x30,0x78,0x38,0x31,0x2c,0x20,0x30,0x78,0x34,0x46,0x2c,0x20,0x30,0x78,0x44,
0x43,0x2c,0x20,0x30,0x78,0x32,0x32,0x2c,0x20,0x30,0x78,0x32,0x41,0x2c,0x20,0x30,0x78,0x39,0x30,0x2c,0x20,0x30,0x78,0x38,0x38,0x2c,0x20,0x30,0x78,0x34,0x36,0x2c,
0x20,0x30,0x78,0x45,0x45,0x2c,0x20,0x30,0x78,0x42,0x38,0x2c,0x20,0x30,0x78,0x31,0x34,0x2c,0x20,0x30,0x78,0x44,0x45,0x2c,0x20,0x30,0x78,0x35,0x45,0x2c,0x20,0x30,
0x78,0x30,0x42,0x2c,0x20,0x30,0x78,0x44,0x42,0x2c,0x0d,0x30,0x78,0x45,0x30,0x2c,0x20,0x30,0x78,0x33,0x32,0x2c,0x20,0x30,0x78,0x33,0x41,0x2c,0x20,0x30,0x78,0x30,
0x41,0x2c,0x20,0x30,0x78,0x34,0x39,0x2c,0x20,0x30,0x78,0x30,0x36,0x2c,0x20,0x30,0x78,0x32,0x34,0x2c,0x20,0x30,0x78,0x35,0x43,0x2c,0x20,0x30,0x78,0x43,0x32,0x2c,
0x20,0x30,0x78,0x44,0x33,0x2c,0x20,0x30,0x78,0x41,0x43,0x2c,0x20,0x30,0x78,0x36,0x32,0x2c,0x20,0x30,0x78,0x39,0x31,0x2c,0x20,0x30,0x78,0x39,0x35,0x2c,0x20,0x30,
0x78,0x45,0x34,0x2c,0x20,0x30,0x78,0x37,0x39,0x2c,0x0d,0x30,0x78,0x45,0x37,0x2c,0x20,0x30,0x78,0x43,0x38,0x2c,0x20,0x30,0x78,0x33,0x37,0x2c,0x20,0x30,0x78,0x36,
0x44,0x2c,0x20,0x30,0x78,0x38,0x44,0x2c,0x20,0x30,0x78,0x44,0x35,0x2c,0x20,0x30,0x78,0x34,0x45,0x2c,0x20,0x30,0x78,0x41,0x39,0x2c,0x20,0x30,0x78,0x36,0x43,0x2c,
0x20,0x30,0x78,0x35,0x36,0x2c,0x20,0x30,0x78,0x46,0x34,0x2c,0x20,0x30,0x78,0x45,0x41,0x2c,0x20,0x30,0x78,0x36,0x35,0x2c,0x20,0x30,0x78,0x37,0x41,0x2c,0x20,0x30,
0x78,0x41,0x45,0x2c,0x20,0x30,0x78,0x30,0x38,0x2c,0x0d,0x30,0x78,0x42,0x41,0x2c,0x20,0x30,0x78,0x37,0x38,0x2c,0x20,0x30,0x78,0x32,0x35,0x2c,0x20,0x30,0x78,0x32,
0x45,0x2c,0x20,0x30,0x78,0x31,0x43,0x2c,0x20,0x30,0x78,0x41,0x36,0x2c,0x20,0x30,0x78,0x42,0x34,0x2c,0x20,0x30,0x78,0x43,0x36,0x2c,0x20,0x30,0x78,0x45,0x38,0x2c,
0x20,0x30,0x78,0x44,0x44,0x2c,0x20,0x30,0x78,0x37,0x34,0x2c,0x20,0x30,0x78,0x31,0x46,0x2c,0x20,0x30,0x78,0x34,0x42,0x2c,0x20,0x30,0x78,0x42,0x44,0x2c,0x20,0x30,
0x78,0x38,0x42,0x2c,0x20,0x30,0x78,0x38,0x41,0x2c,0x0d,0x30,0x78,0x37,0x30,0x2c,0x20,0x30,0x78,0x33,0x45,0x2c,0x20,0x30,0x78,0x42,0x35,0x2c,0x20,0x30,0x78,0x36,
0x36,0x2c,0x20,0x30,0x78,0x34,0x38,0x2c,0x20,0x30,0x78,0x30,0x33,0x2c,0x20,0x30,0x78,0x46,0x36,0x2c,0x20,0x30,0x78,0x30,0x45,0x2c,0x20,0x30,0x78,0x36,0x31,0x2c,
0x20,0x30,0x78,0x33,0x35,0x2c,0x20,0x30,0x78,0x35,0x37,0x2c,0x20,0x30,0x78,0x42,0x39,0x2c,0x20,0x30,0x78,0x38,0x36,0x2c,0x20,0x30,0x78,0x43,0x31,0x2c,0x20,0x30,
0x78,0x31,0x44,0x2c,0x20,0x30,0x78,0x39,0x45,0x2c,0x0d,0x30,0x78,0x45,0x31,0x2c,0x20,0x30,0x78,0x46,0x38,0x2c,0x20,0x30,0x78,0x39,0x38,0x2c,0x20,0x30,0x78,0x31,
0x31,0x2c,0x20,0x30,0x78,0x36,0x39,0x2c,0x20,0x30,0x78,0x44,0x39,0x2c,0x20,0x30,0x78,0x38,0x45,0x2c,0x20,0x30,0x78,0x39,0x34,0x2c,0x20,0x30,0x78,0x39,0x42,0x2c,
0x20,0x30,0x78,0x31,0x45,0x2c,0x20,0x30,0x78,0x38,0x37,0x2c,0x20,0x30,0x78,0x45,0x39,0x2c,0x20,0x30,0x78,0x43,0x45,0x2c,0x20,0x30,0x78,0x35,0x35,0x2c,0x20,0x30,
0x78,0x32,0x38,0x2c,0x20,0x30,0x78,0x44,0x46,0x2c,0x0d,0x30,0x78,0x38,0x43,0x2c,0x20,0x30,0x78,0x41,0x31,0x2c,0x20,0x30,0x78,0x38,0x39,0x2c,0x20,0x30,0x78,0x30,
0x44,0x2c,0x20,0x30,0x78,0x42,0x46,0x2c,0x20,0x30,0x78,0x45,0x36,0x2c,0x20,0x30,0x78,0x34,0x32,0x2c,0x20,0x30,0x78,0x36,0x38,0x2c,0x20,0x30,0x78,0x34,0x31,0x2c,
0x20,0x30,0x78,0x39,0x39,0x2c,0x20,0x30,0x78,0x32,0x44,0x2c,0x20,0x30,0x78,0x30,0x46,0x2c,0x20,0x30,0x78,0x42,0x30,0x2c,0x20,0x30,0x78,0x35,0x34,0x2c,0x20,0x30,
0x78,0x42,0x42,0x2c,0x20,0x30,0x78,0x31,0x36,0x0d,0x7d,0x3b,0x0d,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x53,0x75,0x62,0x57,0x6f,0x72,0x64,0x28,0x69,0x6e,0x77,
0x29,0x20,0x28,0x28,0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x33,0x29,0x5d,0x20,0x3c,0x3c,0x20,0x32,0x34,0x29,0x20,0x7c,0x20,
0x28,0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x32,0x29,0x5d,0x20,0x3c,0x3c,0x20,0x31,0x36,0x29,0x20,0x7c,0x20,0x28,0x73,0x62,
0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x31,0x29,0x5d,0x20,0x3c,0x3c,0x20,0x38,0x29,0x20,0x7c,0x20,0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,
0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x30,0x29,0x5d,0x29,0x0d,0x76,0x6f,0x69,0x64,0x20,0x41,0x45,0x53,0x45,0x78,0x70,0x61,0x6e,0x64,0x4b,0x65,0x79,0x32,0x35,
0x36,0x28,0x75,0x69,0x6e,0x74,0x20,0x2a,0x6b,0x65,0x79,0x62,0x75,0x66,0x29,0x0d,0x7b,0x0d,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x20,0x63,0x20,0x3d,0x20,
0x38,0x2c,0x20,0x69,0x20,0x3d,0x20,0x31,0x3b,0x20,0x63,0x20,0x3c,0x20,0x34,0x30,0x3b,0x20,0x2b,0x2b,0x63,0x29,0x20,0x7b,0x0d,0x75,0x69,0x6e,0x74,0x20,0x74,0x20,
0x3d,0x20,0x28,0x28,0x21,0x28,0x63,0x20,0x26,0x20,0x37,0x29,0x29,0x20,0x7c,0x7c,0x20,0x28,0x28,0x63,0x20,0x26,0x20,0x37,0x29,0x20,0x3d,0x3d,0x20,0x34,0x29,0x29,
0x20,0x3f,0x20,0x53,0x75,0x62,0x57,0x6f,0x72,0x64,0x28,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,0x63,0x20,0x2d,0x20,0x31,0x5d,0x29,0x20,0x3a,0x20,0x6b,0x65,0x79,0x62,
0x75,0x66,0x5b,0x63,0x20,0x2d,0x20,0x31,0x5d,0x3b,0x0d,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,0x63,0x5d,0x20,0x3d,0x20,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,0x63,0x20,
0x2d,0x20,0x38,0x5d,0x20,0x5e,0x20,0x28,0x28,0x21,0x28,0x63,0x20,0x26,0x20,0x37,0x29,0x29,0x20,0x3f,0x20,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x2c,0x20,0x32,
0x34,0x55,0x29,0x20,0x5e,0x20,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x28,0x28,0x75,0x63,0x68,0x61,0x72,0x34,0x29,0x28,0x72,0x63,0x6f,0x6e,0x5b,0x69,0x2b,0x2b,0x5d,
0x2c,0x20,0x30,0x55,0x2c,0x20,0x30,0x55,0x2c,0x20,0x30,0x55,0x29,0x29,0x20,0x3a,0x20,0x74,0x29,0x3b,0x0d,0x7d,0x0d,0x7d,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,
0x00
0x20,0x73,0x72,0x63,0x30,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x20,0x77,0x69,0x64,0x74,0x68,0x29,0x0a,0x7b,0x0a,0x69,0x66,0x28,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x2b,0x77,0x69,0x64,0x74,0x68,0x29,0x3c,0x33,0x32,
0x75,0x29,0x20,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x73,0x72,0x63,0x30,0x3c,0x3c,0x28,0x33,0x32,0x75,0x2d,0x6f,0x66,0x66,0x73,0x65,0x74,0x2d,0x77,
0x69,0x64,0x74,0x68,0x29,0x29,0x3e,0x3e,0x28,0x33,0x32,0x75,0x2d,0x77,0x69,0x64,0x74,0x68,0x29,0x3b,0x0a,0x7d,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x72,
0x63,0x30,0x3e,0x3e,0x6f,0x66,0x66,0x73,0x65,0x74,0x3b,0x0a,0x7d,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x41,0x45,0x53,0x30,0x5f,0x43,0x5b,0x32,0x35,0x36,0x5d,0x20,0x3d,0x0a,
0x7b,0x0a,0x30,0x78,0x41,0x35,0x36,0x33,0x36,0x33,0x43,0x36,0x55,0x2c,0x30,0x78,0x38,0x34,0x37,0x43,0x37,0x43,0x46,0x38,0x55,0x2c,0x30,0x78,0x39,0x39,0x37,0x37,
0x37,0x37,0x45,0x45,0x55,0x2c,0x30,0x78,0x38,0x44,0x37,0x42,0x37,0x42,0x46,0x36,0x55,0x2c,0x0a,0x30,0x78,0x30,0x44,0x46,0x32,0x46,0x32,0x46,0x46,0x55,0x2c,0x30,
0x78,0x42,0x44,0x36,0x42,0x36,0x42,0x44,0x36,0x55,0x2c,0x30,0x78,0x42,0x31,0x36,0x46,0x36,0x46,0x44,0x45,0x55,0x2c,0x30,0x78,0x35,0x34,0x43,0x35,0x43,0x35,0x39,
0x31,0x55,0x2c,0x0a,0x30,0x78,0x35,0x30,0x33,0x30,0x33,0x30,0x36,0x30,0x55,0x2c,0x30,0x78,0x30,0x33,0x30,0x31,0x30,0x31,0x30,0x32,0x55,0x2c,0x30,0x78,0x41,0x39,
0x36,0x37,0x36,0x37,0x43,0x45,0x55,0x2c,0x30,0x78,0x37,0x44,0x32,0x42,0x32,0x42,0x35,0x36,0x55,0x2c,0x0a,0x30,0x78,0x31,0x39,0x46,0x45,0x46,0x45,0x45,0x37,0x55,
0x2c,0x30,0x78,0x36,0x32,0x44,0x37,0x44,0x37,0x42,0x35,0x55,0x2c,0x30,0x78,0x45,0x36,0x41,0x42,0x41,0x42,0x34,0x44,0x55,0x2c,0x30,0x78,0x39,0x41,0x37,0x36,0x37,
0x36,0x45,0x43,0x55,0x2c,0x0a,0x30,0x78,0x34,0x35,0x43,0x41,0x43,0x41,0x38,0x46,0x55,0x2c,0x30,0x78,0x39,0x44,0x38,0x32,0x38,0x32,0x31,0x46,0x55,0x2c,0x30,0x78,
0x34,0x30,0x43,0x39,0x43,0x39,0x38,0x39,0x55,0x2c,0x30,0x78,0x38,0x37,0x37,0x44,0x37,0x44,0x46,0x41,0x55,0x2c,0x0a,0x30,0x78,0x31,0x35,0x46,0x41,0x46,0x41,0x45,
0x46,0x55,0x2c,0x30,0x78,0x45,0x42,0x35,0x39,0x35,0x39,0x42,0x32,0x55,0x2c,0x30,0x78,0x43,0x39,0x34,0x37,0x34,0x37,0x38,0x45,0x55,0x2c,0x30,0x78,0x30,0x42,0x46,
0x30,0x46,0x30,0x46,0x42,0x55,0x2c,0x0a,0x30,0x78,0x45,0x43,0x41,0x44,0x41,0x44,0x34,0x31,0x55,0x2c,0x30,0x78,0x36,0x37,0x44,0x34,0x44,0x34,0x42,0x33,0x55,0x2c,
0x30,0x78,0x46,0x44,0x41,0x32,0x41,0x32,0x35,0x46,0x55,0x2c,0x30,0x78,0x45,0x41,0x41,0x46,0x41,0x46,0x34,0x35,0x55,0x2c,0x0a,0x30,0x78,0x42,0x46,0x39,0x43,0x39,
0x43,0x32,0x33,0x55,0x2c,0x30,0x78,0x46,0x37,0x41,0x34,0x41,0x34,0x35,0x33,0x55,0x2c,0x30,0x78,0x39,0x36,0x37,0x32,0x37,0x32,0x45,0x34,0x55,0x2c,0x30,0x78,0x35,
0x42,0x43,0x30,0x43,0x30,0x39,0x42,0x55,0x2c,0x0a,0x30,0x78,0x43,0x32,0x42,0x37,0x42,0x37,0x37,0x35,0x55,0x2c,0x30,0x78,0x31,0x43,0x46,0x44,0x46,0x44,0x45,0x31,
0x55,0x2c,0x30,0x78,0x41,0x45,0x39,0x33,0x39,0x33,0x33,0x44,0x55,0x2c,0x30,0x78,0x36,0x41,0x32,0x36,0x32,0x36,0x34,0x43,0x55,0x2c,0x0a,0x30,0x78,0x35,0x41,0x33,
0x36,0x33,0x36,0x36,0x43,0x55,0x2c,0x30,0x78,0x34,0x31,0x33,0x46,0x33,0x46,0x37,0x45,0x55,0x2c,0x30,0x78,0x30,0x32,0x46,0x37,0x46,0x37,0x46,0x35,0x55,0x2c,0x30,
0x78,0x34,0x46,0x43,0x43,0x43,0x43,0x38,0x33,0x55,0x2c,0x0a,0x30,0x78,0x35,0x43,0x33,0x34,0x33,0x34,0x36,0x38,0x55,0x2c,0x30,0x78,0x46,0x34,0x41,0x35,0x41,0x35,
0x35,0x31,0x55,0x2c,0x30,0x78,0x33,0x34,0x45,0x35,0x45,0x35,0x44,0x31,0x55,0x2c,0x30,0x78,0x30,0x38,0x46,0x31,0x46,0x31,0x46,0x39,0x55,0x2c,0x0a,0x30,0x78,0x39,
0x33,0x37,0x31,0x37,0x31,0x45,0x32,0x55,0x2c,0x30,0x78,0x37,0x33,0x44,0x38,0x44,0x38,0x41,0x42,0x55,0x2c,0x30,0x78,0x35,0x33,0x33,0x31,0x33,0x31,0x36,0x32,0x55,
0x2c,0x30,0x78,0x33,0x46,0x31,0x35,0x31,0x35,0x32,0x41,0x55,0x2c,0x0a,0x30,0x78,0x30,0x43,0x30,0x34,0x30,0x34,0x30,0x38,0x55,0x2c,0x30,0x78,0x35,0x32,0x43,0x37,
0x43,0x37,0x39,0x35,0x55,0x2c,0x30,0x78,0x36,0x35,0x32,0x33,0x32,0x33,0x34,0x36,0x55,0x2c,0x30,0x78,0x35,0x45,0x43,0x33,0x43,0x33,0x39,0x44,0x55,0x2c,0x0a,0x30,
0x78,0x32,0x38,0x31,0x38,0x31,0x38,0x33,0x30,0x55,0x2c,0x30,0x78,0x41,0x31,0x39,0x36,0x39,0x36,0x33,0x37,0x55,0x2c,0x30,0x78,0x30,0x46,0x30,0x35,0x30,0x35,0x30,
0x41,0x55,0x2c,0x30,0x78,0x42,0x35,0x39,0x41,0x39,0x41,0x32,0x46,0x55,0x2c,0x0a,0x30,0x78,0x30,0x39,0x30,0x37,0x30,0x37,0x30,0x45,0x55,0x2c,0x30,0x78,0x33,0x36,
0x31,0x32,0x31,0x32,0x32,0x34,0x55,0x2c,0x30,0x78,0x39,0x42,0x38,0x30,0x38,0x30,0x31,0x42,0x55,0x2c,0x30,0x78,0x33,0x44,0x45,0x32,0x45,0x32,0x44,0x46,0x55,0x2c,
0x0a,0x30,0x78,0x32,0x36,0x45,0x42,0x45,0x42,0x43,0x44,0x55,0x2c,0x30,0x78,0x36,0x39,0x32,0x37,0x32,0x37,0x34,0x45,0x55,0x2c,0x30,0x78,0x43,0x44,0x42,0x32,0x42,
0x32,0x37,0x46,0x55,0x2c,0x30,0x78,0x39,0x46,0x37,0x35,0x37,0x35,0x45,0x41,0x55,0x2c,0x0a,0x30,0x78,0x31,0x42,0x30,0x39,0x30,0x39,0x31,0x32,0x55,0x2c,0x30,0x78,
0x39,0x45,0x38,0x33,0x38,0x33,0x31,0x44,0x55,0x2c,0x30,0x78,0x37,0x34,0x32,0x43,0x32,0x43,0x35,0x38,0x55,0x2c,0x30,0x78,0x32,0x45,0x31,0x41,0x31,0x41,0x33,0x34,
0x55,0x2c,0x0a,0x30,0x78,0x32,0x44,0x31,0x42,0x31,0x42,0x33,0x36,0x55,0x2c,0x30,0x78,0x42,0x32,0x36,0x45,0x36,0x45,0x44,0x43,0x55,0x2c,0x30,0x78,0x45,0x45,0x35,
0x41,0x35,0x41,0x42,0x34,0x55,0x2c,0x30,0x78,0x46,0x42,0x41,0x30,0x41,0x30,0x35,0x42,0x55,0x2c,0x0a,0x30,0x78,0x46,0x36,0x35,0x32,0x35,0x32,0x41,0x34,0x55,0x2c,
0x30,0x78,0x34,0x44,0x33,0x42,0x33,0x42,0x37,0x36,0x55,0x2c,0x30,0x78,0x36,0x31,0x44,0x36,0x44,0x36,0x42,0x37,0x55,0x2c,0x30,0x78,0x43,0x45,0x42,0x33,0x42,0x33,
0x37,0x44,0x55,0x2c,0x0a,0x30,0x78,0x37,0x42,0x32,0x39,0x32,0x39,0x35,0x32,0x55,0x2c,0x30,0x78,0x33,0x45,0x45,0x33,0x45,0x33,0x44,0x44,0x55,0x2c,0x30,0x78,0x37,
0x31,0x32,0x46,0x32,0x46,0x35,0x45,0x55,0x2c,0x30,0x78,0x39,0x37,0x38,0x34,0x38,0x34,0x31,0x33,0x55,0x2c,0x0a,0x30,0x78,0x46,0x35,0x35,0x33,0x35,0x33,0x41,0x36,
0x55,0x2c,0x30,0x78,0x36,0x38,0x44,0x31,0x44,0x31,0x42,0x39,0x55,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x2c,0x30,0x78,0x32,0x43,0x45,0x44,
0x45,0x44,0x43,0x31,0x55,0x2c,0x0a,0x30,0x78,0x36,0x30,0x32,0x30,0x32,0x30,0x34,0x30,0x55,0x2c,0x30,0x78,0x31,0x46,0x46,0x43,0x46,0x43,0x45,0x33,0x55,0x2c,0x30,
0x78,0x43,0x38,0x42,0x31,0x42,0x31,0x37,0x39,0x55,0x2c,0x30,0x78,0x45,0x44,0x35,0x42,0x35,0x42,0x42,0x36,0x55,0x2c,0x0a,0x30,0x78,0x42,0x45,0x36,0x41,0x36,0x41,
0x44,0x34,0x55,0x2c,0x30,0x78,0x34,0x36,0x43,0x42,0x43,0x42,0x38,0x44,0x55,0x2c,0x30,0x78,0x44,0x39,0x42,0x45,0x42,0x45,0x36,0x37,0x55,0x2c,0x30,0x78,0x34,0x42,
0x33,0x39,0x33,0x39,0x37,0x32,0x55,0x2c,0x0a,0x30,0x78,0x44,0x45,0x34,0x41,0x34,0x41,0x39,0x34,0x55,0x2c,0x30,0x78,0x44,0x34,0x34,0x43,0x34,0x43,0x39,0x38,0x55,
0x2c,0x30,0x78,0x45,0x38,0x35,0x38,0x35,0x38,0x42,0x30,0x55,0x2c,0x30,0x78,0x34,0x41,0x43,0x46,0x43,0x46,0x38,0x35,0x55,0x2c,0x0a,0x30,0x78,0x36,0x42,0x44,0x30,
0x44,0x30,0x42,0x42,0x55,0x2c,0x30,0x78,0x32,0x41,0x45,0x46,0x45,0x46,0x43,0x35,0x55,0x2c,0x30,0x78,0x45,0x35,0x41,0x41,0x41,0x41,0x34,0x46,0x55,0x2c,0x30,0x78,
0x31,0x36,0x46,0x42,0x46,0x42,0x45,0x44,0x55,0x2c,0x0a,0x30,0x78,0x43,0x35,0x34,0x33,0x34,0x33,0x38,0x36,0x55,0x2c,0x30,0x78,0x44,0x37,0x34,0x44,0x34,0x44,0x39,
0x41,0x55,0x2c,0x30,0x78,0x35,0x35,0x33,0x33,0x33,0x33,0x36,0x36,0x55,0x2c,0x30,0x78,0x39,0x34,0x38,0x35,0x38,0x35,0x31,0x31,0x55,0x2c,0x0a,0x30,0x78,0x43,0x46,
0x34,0x35,0x34,0x35,0x38,0x41,0x55,0x2c,0x30,0x78,0x31,0x30,0x46,0x39,0x46,0x39,0x45,0x39,0x55,0x2c,0x30,0x78,0x30,0x36,0x30,0x32,0x30,0x32,0x30,0x34,0x55,0x2c,
0x30,0x78,0x38,0x31,0x37,0x46,0x37,0x46,0x46,0x45,0x55,0x2c,0x0a,0x30,0x78,0x46,0x30,0x35,0x30,0x35,0x30,0x41,0x30,0x55,0x2c,0x30,0x78,0x34,0x34,0x33,0x43,0x33,
0x43,0x37,0x38,0x55,0x2c,0x30,0x78,0x42,0x41,0x39,0x46,0x39,0x46,0x32,0x35,0x55,0x2c,0x30,0x78,0x45,0x33,0x41,0x38,0x41,0x38,0x34,0x42,0x55,0x2c,0x0a,0x30,0x78,
0x46,0x33,0x35,0x31,0x35,0x31,0x41,0x32,0x55,0x2c,0x30,0x78,0x46,0x45,0x41,0x33,0x41,0x33,0x35,0x44,0x55,0x2c,0x30,0x78,0x43,0x30,0x34,0x30,0x34,0x30,0x38,0x30,
0x55,0x2c,0x30,0x78,0x38,0x41,0x38,0x46,0x38,0x46,0x30,0x35,0x55,0x2c,0x0a,0x30,0x78,0x41,0x44,0x39,0x32,0x39,0x32,0x33,0x46,0x55,0x2c,0x30,0x78,0x42,0x43,0x39,
0x44,0x39,0x44,0x32,0x31,0x55,0x2c,0x30,0x78,0x34,0x38,0x33,0x38,0x33,0x38,0x37,0x30,0x55,0x2c,0x30,0x78,0x30,0x34,0x46,0x35,0x46,0x35,0x46,0x31,0x55,0x2c,0x0a,
0x30,0x78,0x44,0x46,0x42,0x43,0x42,0x43,0x36,0x33,0x55,0x2c,0x30,0x78,0x43,0x31,0x42,0x36,0x42,0x36,0x37,0x37,0x55,0x2c,0x30,0x78,0x37,0x35,0x44,0x41,0x44,0x41,
0x41,0x46,0x55,0x2c,0x30,0x78,0x36,0x33,0x32,0x31,0x32,0x31,0x34,0x32,0x55,0x2c,0x0a,0x30,0x78,0x33,0x30,0x31,0x30,0x31,0x30,0x32,0x30,0x55,0x2c,0x30,0x78,0x31,
0x41,0x46,0x46,0x46,0x46,0x45,0x35,0x55,0x2c,0x30,0x78,0x30,0x45,0x46,0x33,0x46,0x33,0x46,0x44,0x55,0x2c,0x30,0x78,0x36,0x44,0x44,0x32,0x44,0x32,0x42,0x46,0x55,
0x2c,0x0a,0x30,0x78,0x34,0x43,0x43,0x44,0x43,0x44,0x38,0x31,0x55,0x2c,0x30,0x78,0x31,0x34,0x30,0x43,0x30,0x43,0x31,0x38,0x55,0x2c,0x30,0x78,0x33,0x35,0x31,0x33,
0x31,0x33,0x32,0x36,0x55,0x2c,0x30,0x78,0x32,0x46,0x45,0x43,0x45,0x43,0x43,0x33,0x55,0x2c,0x0a,0x30,0x78,0x45,0x31,0x35,0x46,0x35,0x46,0x42,0x45,0x55,0x2c,0x30,
0x78,0x41,0x32,0x39,0x37,0x39,0x37,0x33,0x35,0x55,0x2c,0x30,0x78,0x43,0x43,0x34,0x34,0x34,0x34,0x38,0x38,0x55,0x2c,0x30,0x78,0x33,0x39,0x31,0x37,0x31,0x37,0x32,
0x45,0x55,0x2c,0x0a,0x30,0x78,0x35,0x37,0x43,0x34,0x43,0x34,0x39,0x33,0x55,0x2c,0x30,0x78,0x46,0x32,0x41,0x37,0x41,0x37,0x35,0x35,0x55,0x2c,0x30,0x78,0x38,0x32,
0x37,0x45,0x37,0x45,0x46,0x43,0x55,0x2c,0x30,0x78,0x34,0x37,0x33,0x44,0x33,0x44,0x37,0x41,0x55,0x2c,0x0a,0x30,0x78,0x41,0x43,0x36,0x34,0x36,0x34,0x43,0x38,0x55,
0x2c,0x30,0x78,0x45,0x37,0x35,0x44,0x35,0x44,0x42,0x41,0x55,0x2c,0x30,0x78,0x32,0x42,0x31,0x39,0x31,0x39,0x33,0x32,0x55,0x2c,0x30,0x78,0x39,0x35,0x37,0x33,0x37,
0x33,0x45,0x36,0x55,0x2c,0x0a,0x30,0x78,0x41,0x30,0x36,0x30,0x36,0x30,0x43,0x30,0x55,0x2c,0x30,0x78,0x39,0x38,0x38,0x31,0x38,0x31,0x31,0x39,0x55,0x2c,0x30,0x78,
0x44,0x31,0x34,0x46,0x34,0x46,0x39,0x45,0x55,0x2c,0x30,0x78,0x37,0x46,0x44,0x43,0x44,0x43,0x41,0x33,0x55,0x2c,0x0a,0x30,0x78,0x36,0x36,0x32,0x32,0x32,0x32,0x34,
0x34,0x55,0x2c,0x30,0x78,0x37,0x45,0x32,0x41,0x32,0x41,0x35,0x34,0x55,0x2c,0x30,0x78,0x41,0x42,0x39,0x30,0x39,0x30,0x33,0x42,0x55,0x2c,0x30,0x78,0x38,0x33,0x38,
0x38,0x38,0x38,0x30,0x42,0x55,0x2c,0x0a,0x30,0x78,0x43,0x41,0x34,0x36,0x34,0x36,0x38,0x43,0x55,0x2c,0x30,0x78,0x32,0x39,0x45,0x45,0x45,0x45,0x43,0x37,0x55,0x2c,
0x30,0x78,0x44,0x33,0x42,0x38,0x42,0x38,0x36,0x42,0x55,0x2c,0x30,0x78,0x33,0x43,0x31,0x34,0x31,0x34,0x32,0x38,0x55,0x2c,0x0a,0x30,0x78,0x37,0x39,0x44,0x45,0x44,
0x45,0x41,0x37,0x55,0x2c,0x30,0x78,0x45,0x32,0x35,0x45,0x35,0x45,0x42,0x43,0x55,0x2c,0x30,0x78,0x31,0x44,0x30,0x42,0x30,0x42,0x31,0x36,0x55,0x2c,0x30,0x78,0x37,
0x36,0x44,0x42,0x44,0x42,0x41,0x44,0x55,0x2c,0x0a,0x30,0x78,0x33,0x42,0x45,0x30,0x45,0x30,0x44,0x42,0x55,0x2c,0x30,0x78,0x35,0x36,0x33,0x32,0x33,0x32,0x36,0x34,
0x55,0x2c,0x30,0x78,0x34,0x45,0x33,0x41,0x33,0x41,0x37,0x34,0x55,0x2c,0x30,0x78,0x31,0x45,0x30,0x41,0x30,0x41,0x31,0x34,0x55,0x2c,0x0a,0x30,0x78,0x44,0x42,0x34,
0x39,0x34,0x39,0x39,0x32,0x55,0x2c,0x30,0x78,0x30,0x41,0x30,0x36,0x30,0x36,0x30,0x43,0x55,0x2c,0x30,0x78,0x36,0x43,0x32,0x34,0x32,0x34,0x34,0x38,0x55,0x2c,0x30,
0x78,0x45,0x34,0x35,0x43,0x35,0x43,0x42,0x38,0x55,0x2c,0x0a,0x30,0x78,0x35,0x44,0x43,0x32,0x43,0x32,0x39,0x46,0x55,0x2c,0x30,0x78,0x36,0x45,0x44,0x33,0x44,0x33,
0x42,0x44,0x55,0x2c,0x30,0x78,0x45,0x46,0x41,0x43,0x41,0x43,0x34,0x33,0x55,0x2c,0x30,0x78,0x41,0x36,0x36,0x32,0x36,0x32,0x43,0x34,0x55,0x2c,0x0a,0x30,0x78,0x41,
0x38,0x39,0x31,0x39,0x31,0x33,0x39,0x55,0x2c,0x30,0x78,0x41,0x34,0x39,0x35,0x39,0x35,0x33,0x31,0x55,0x2c,0x30,0x78,0x33,0x37,0x45,0x34,0x45,0x34,0x44,0x33,0x55,
0x2c,0x30,0x78,0x38,0x42,0x37,0x39,0x37,0x39,0x46,0x32,0x55,0x2c,0x0a,0x30,0x78,0x33,0x32,0x45,0x37,0x45,0x37,0x44,0x35,0x55,0x2c,0x30,0x78,0x34,0x33,0x43,0x38,
0x43,0x38,0x38,0x42,0x55,0x2c,0x30,0x78,0x35,0x39,0x33,0x37,0x33,0x37,0x36,0x45,0x55,0x2c,0x30,0x78,0x42,0x37,0x36,0x44,0x36,0x44,0x44,0x41,0x55,0x2c,0x0a,0x30,
0x78,0x38,0x43,0x38,0x44,0x38,0x44,0x30,0x31,0x55,0x2c,0x30,0x78,0x36,0x34,0x44,0x35,0x44,0x35,0x42,0x31,0x55,0x2c,0x30,0x78,0x44,0x32,0x34,0x45,0x34,0x45,0x39,
0x43,0x55,0x2c,0x30,0x78,0x45,0x30,0x41,0x39,0x41,0x39,0x34,0x39,0x55,0x2c,0x0a,0x30,0x78,0x42,0x34,0x36,0x43,0x36,0x43,0x44,0x38,0x55,0x2c,0x30,0x78,0x46,0x41,
0x35,0x36,0x35,0x36,0x41,0x43,0x55,0x2c,0x30,0x78,0x30,0x37,0x46,0x34,0x46,0x34,0x46,0x33,0x55,0x2c,0x30,0x78,0x32,0x35,0x45,0x41,0x45,0x41,0x43,0x46,0x55,0x2c,
0x0a,0x30,0x78,0x41,0x46,0x36,0x35,0x36,0x35,0x43,0x41,0x55,0x2c,0x30,0x78,0x38,0x45,0x37,0x41,0x37,0x41,0x46,0x34,0x55,0x2c,0x30,0x78,0x45,0x39,0x41,0x45,0x41,
0x45,0x34,0x37,0x55,0x2c,0x30,0x78,0x31,0x38,0x30,0x38,0x30,0x38,0x31,0x30,0x55,0x2c,0x0a,0x30,0x78,0x44,0x35,0x42,0x41,0x42,0x41,0x36,0x46,0x55,0x2c,0x30,0x78,
0x38,0x38,0x37,0x38,0x37,0x38,0x46,0x30,0x55,0x2c,0x30,0x78,0x36,0x46,0x32,0x35,0x32,0x35,0x34,0x41,0x55,0x2c,0x30,0x78,0x37,0x32,0x32,0x45,0x32,0x45,0x35,0x43,
0x55,0x2c,0x0a,0x30,0x78,0x32,0x34,0x31,0x43,0x31,0x43,0x33,0x38,0x55,0x2c,0x30,0x78,0x46,0x31,0x41,0x36,0x41,0x36,0x35,0x37,0x55,0x2c,0x30,0x78,0x43,0x37,0x42,
0x34,0x42,0x34,0x37,0x33,0x55,0x2c,0x30,0x78,0x35,0x31,0x43,0x36,0x43,0x36,0x39,0x37,0x55,0x2c,0x0a,0x30,0x78,0x32,0x33,0x45,0x38,0x45,0x38,0x43,0x42,0x55,0x2c,
0x30,0x78,0x37,0x43,0x44,0x44,0x44,0x44,0x41,0x31,0x55,0x2c,0x30,0x78,0x39,0x43,0x37,0x34,0x37,0x34,0x45,0x38,0x55,0x2c,0x30,0x78,0x32,0x31,0x31,0x46,0x31,0x46,
0x33,0x45,0x55,0x2c,0x0a,0x30,0x78,0x44,0x44,0x34,0x42,0x34,0x42,0x39,0x36,0x55,0x2c,0x30,0x78,0x44,0x43,0x42,0x44,0x42,0x44,0x36,0x31,0x55,0x2c,0x30,0x78,0x38,
0x36,0x38,0x42,0x38,0x42,0x30,0x44,0x55,0x2c,0x30,0x78,0x38,0x35,0x38,0x41,0x38,0x41,0x30,0x46,0x55,0x2c,0x0a,0x30,0x78,0x39,0x30,0x37,0x30,0x37,0x30,0x45,0x30,
0x55,0x2c,0x30,0x78,0x34,0x32,0x33,0x45,0x33,0x45,0x37,0x43,0x55,0x2c,0x30,0x78,0x43,0x34,0x42,0x35,0x42,0x35,0x37,0x31,0x55,0x2c,0x30,0x78,0x41,0x41,0x36,0x36,
0x36,0x36,0x43,0x43,0x55,0x2c,0x0a,0x30,0x78,0x44,0x38,0x34,0x38,0x34,0x38,0x39,0x30,0x55,0x2c,0x30,0x78,0x30,0x35,0x30,0x33,0x30,0x33,0x30,0x36,0x55,0x2c,0x30,
0x78,0x30,0x31,0x46,0x36,0x46,0x36,0x46,0x37,0x55,0x2c,0x30,0x78,0x31,0x32,0x30,0x45,0x30,0x45,0x31,0x43,0x55,0x2c,0x0a,0x30,0x78,0x41,0x33,0x36,0x31,0x36,0x31,
0x43,0x32,0x55,0x2c,0x30,0x78,0x35,0x46,0x33,0x35,0x33,0x35,0x36,0x41,0x55,0x2c,0x30,0x78,0x46,0x39,0x35,0x37,0x35,0x37,0x41,0x45,0x55,0x2c,0x30,0x78,0x44,0x30,
0x42,0x39,0x42,0x39,0x36,0x39,0x55,0x2c,0x0a,0x30,0x78,0x39,0x31,0x38,0x36,0x38,0x36,0x31,0x37,0x55,0x2c,0x30,0x78,0x35,0x38,0x43,0x31,0x43,0x31,0x39,0x39,0x55,
0x2c,0x30,0x78,0x32,0x37,0x31,0x44,0x31,0x44,0x33,0x41,0x55,0x2c,0x30,0x78,0x42,0x39,0x39,0x45,0x39,0x45,0x32,0x37,0x55,0x2c,0x0a,0x30,0x78,0x33,0x38,0x45,0x31,
0x45,0x31,0x44,0x39,0x55,0x2c,0x30,0x78,0x31,0x33,0x46,0x38,0x46,0x38,0x45,0x42,0x55,0x2c,0x30,0x78,0x42,0x33,0x39,0x38,0x39,0x38,0x32,0x42,0x55,0x2c,0x30,0x78,
0x33,0x33,0x31,0x31,0x31,0x31,0x32,0x32,0x55,0x2c,0x0a,0x30,0x78,0x42,0x42,0x36,0x39,0x36,0x39,0x44,0x32,0x55,0x2c,0x30,0x78,0x37,0x30,0x44,0x39,0x44,0x39,0x41,
0x39,0x55,0x2c,0x30,0x78,0x38,0x39,0x38,0x45,0x38,0x45,0x30,0x37,0x55,0x2c,0x30,0x78,0x41,0x37,0x39,0x34,0x39,0x34,0x33,0x33,0x55,0x2c,0x0a,0x30,0x78,0x42,0x36,
0x39,0x42,0x39,0x42,0x32,0x44,0x55,0x2c,0x30,0x78,0x32,0x32,0x31,0x45,0x31,0x45,0x33,0x43,0x55,0x2c,0x30,0x78,0x39,0x32,0x38,0x37,0x38,0x37,0x31,0x35,0x55,0x2c,
0x30,0x78,0x32,0x30,0x45,0x39,0x45,0x39,0x43,0x39,0x55,0x2c,0x0a,0x30,0x78,0x34,0x39,0x43,0x45,0x43,0x45,0x38,0x37,0x55,0x2c,0x30,0x78,0x46,0x46,0x35,0x35,0x35,
0x35,0x41,0x41,0x55,0x2c,0x30,0x78,0x37,0x38,0x32,0x38,0x32,0x38,0x35,0x30,0x55,0x2c,0x30,0x78,0x37,0x41,0x44,0x46,0x44,0x46,0x41,0x35,0x55,0x2c,0x0a,0x30,0x78,
0x38,0x46,0x38,0x43,0x38,0x43,0x30,0x33,0x55,0x2c,0x30,0x78,0x46,0x38,0x41,0x31,0x41,0x31,0x35,0x39,0x55,0x2c,0x30,0x78,0x38,0x30,0x38,0x39,0x38,0x39,0x30,0x39,
0x55,0x2c,0x30,0x78,0x31,0x37,0x30,0x44,0x30,0x44,0x31,0x41,0x55,0x2c,0x0a,0x30,0x78,0x44,0x41,0x42,0x46,0x42,0x46,0x36,0x35,0x55,0x2c,0x30,0x78,0x33,0x31,0x45,
0x36,0x45,0x36,0x44,0x37,0x55,0x2c,0x30,0x78,0x43,0x36,0x34,0x32,0x34,0x32,0x38,0x34,0x55,0x2c,0x30,0x78,0x42,0x38,0x36,0x38,0x36,0x38,0x44,0x30,0x55,0x2c,0x0a,
0x30,0x78,0x43,0x33,0x34,0x31,0x34,0x31,0x38,0x32,0x55,0x2c,0x30,0x78,0x42,0x30,0x39,0x39,0x39,0x39,0x32,0x39,0x55,0x2c,0x30,0x78,0x37,0x37,0x32,0x44,0x32,0x44,
0x35,0x41,0x55,0x2c,0x30,0x78,0x31,0x31,0x30,0x46,0x30,0x46,0x31,0x45,0x55,0x2c,0x0a,0x30,0x78,0x43,0x42,0x42,0x30,0x42,0x30,0x37,0x42,0x55,0x2c,0x30,0x78,0x46,
0x43,0x35,0x34,0x35,0x34,0x41,0x38,0x55,0x2c,0x30,0x78,0x44,0x36,0x42,0x42,0x42,0x42,0x36,0x44,0x55,0x2c,0x30,0x78,0x33,0x41,0x31,0x36,0x31,0x36,0x32,0x43,0x55,
0x0a,0x7d,0x3b,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x42,0x59,0x54,0x45,0x28,0x78,0x2c,0x20,0x79,0x29,0x20,0x28,0x78,0x6d,0x72,0x69,0x67,0x5f,0x61,0x6d,
0x64,0x5f,0x62,0x66,0x65,0x28,0x28,0x78,0x29,0x2c,0x20,0x28,0x79,0x29,0x20,0x3c,0x3c,0x20,0x33,0x55,0x2c,0x20,0x38,0x55,0x29,0x29,0x0a,0x23,0x69,0x66,0x20,0x28,
0x41,0x4c,0x47,0x4f,0x20,0x3d,0x3d,0x20,0x41,0x4c,0x47,0x4f,0x5f,0x43,0x4e,0x5f,0x48,0x45,0x41,0x56,0x59,0x5f,0x54,0x55,0x42,0x45,0x29,0x0a,0x69,0x6e,0x6c,0x69,
0x6e,0x65,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x5f,0x62,0x69,0x74,0x74,0x75,0x62,0x65,0x32,0x28,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x30,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,
0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x31,0x2c,0x75,0x69,0x6e,0x74,0x34,0x20,0x78,0x2c,0x75,0x69,0x6e,0x74,0x34,0x20,0x6b,0x29,0x0a,0x7b,
0x0a,0x78,0x3d,0x7e,0x78,0x3b,0x0a,0x6b,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x30,0x29,
0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,
0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,0x33,0x29,
0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x78,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x6b,0x2e,0x73,0x30,0x3b,0x0a,0x6b,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x41,0x45,
0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,
0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,
0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x78,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x6b,
0x2e,0x73,0x31,0x3b,0x0a,0x6b,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,0x30,0x29,0x5d,0x5e,
0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,
0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x33,0x29,0x5d,0x2c,
0x31,0x36,0x55,0x29,0x3b,0x0a,0x78,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x6b,0x2e,0x73,0x32,0x3b,0x0a,0x6b,0x2e,0x73,0x33,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,
0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x31,0x29,
0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,
0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6b,0x3b,0x0a,0x7d,
0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x75,0x69,0x6e,0x74,0x34,0x20,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,
0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x30,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,
0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x31,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,
0x53,0x32,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x33,0x2c,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x58,0x2c,0x75,0x69,0x6e,0x74,0x34,0x20,0x6b,0x65,0x79,0x29,0x0a,0x7b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x30,0x20,0x5e,0x3d,
0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,
0x73,0x31,0x2c,0x31,0x29,0x5d,0x5e,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x33,0x5b,0x42,
0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x33,0x29,0x5d,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,
0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x31,0x29,0x5d,0x5e,0x41,0x45,
0x53,0x32,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,
0x33,0x29,0x5d,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x30,0x29,
0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x31,0x29,0x5d,0x5e,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,
0x2e,0x73,0x30,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x33,0x29,0x5d,0x3b,0x0a,0x6b,0x65,0x79,0x2e,
0x73,0x33,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,
0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x31,0x29,0x5d,0x5e,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x32,0x29,0x5d,0x5e,0x41,
0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x33,0x29,0x5d,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6b,0x65,0x79,0x3b,0x0a,0x7d,
0x0a,0x75,0x69,0x6e,0x74,0x34,0x20,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x5f,0x54,0x77,0x6f,0x5f,0x54,0x61,0x62,0x6c,0x65,0x73,0x28,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x30,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,
0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x31,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x58,0x2c,0x75,0x69,0x6e,0x74,
0x34,0x20,0x6b,0x65,0x79,0x29,0x0a,0x7b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,
0x30,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,
0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,
0x33,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,
0x58,0x2e,0x73,0x31,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,
0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,
0x58,0x2e,0x73,0x30,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,
0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x31,0x29,0x5d,0x5e,0x72,
0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,
0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x33,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,
0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x31,0x29,
0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,
0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6b,0x65,0x79,0x3b,
0x0a,0x7d,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x63,0x68,0x61,0x72,
0x20,0x72,0x63,0x6f,0x6e,0x5b,0x38,0x5d,0x3d,0x7b,0x20,0x30,0x78,0x38,0x64,0x2c,0x30,0x78,0x30,0x31,0x2c,0x30,0x78,0x30,0x32,0x2c,0x30,0x78,0x30,0x34,0x2c,0x30,
0x78,0x30,0x38,0x2c,0x30,0x78,0x31,0x30,0x2c,0x30,0x78,0x32,0x30,0x2c,0x30,0x78,0x34,0x30,0x20,0x7d,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,
0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x63,0x68,0x61,0x72,0x20,0x73,0x62,0x6f,0x78,0x5b,0x32,0x35,0x36,0x5d,0x20,0x3d,0x0a,
0x7b,0x0a,0x30,0x78,0x36,0x33,0x2c,0x30,0x78,0x37,0x43,0x2c,0x30,0x78,0x37,0x37,0x2c,0x30,0x78,0x37,0x42,0x2c,0x30,0x78,0x46,0x32,0x2c,0x30,0x78,0x36,0x42,0x2c,
0x30,0x78,0x36,0x46,0x2c,0x30,0x78,0x43,0x35,0x2c,0x30,0x78,0x33,0x30,0x2c,0x30,0x78,0x30,0x31,0x2c,0x30,0x78,0x36,0x37,0x2c,0x30,0x78,0x32,0x42,0x2c,0x30,0x78,
0x46,0x45,0x2c,0x30,0x78,0x44,0x37,0x2c,0x30,0x78,0x41,0x42,0x2c,0x30,0x78,0x37,0x36,0x2c,0x0a,0x30,0x78,0x43,0x41,0x2c,0x30,0x78,0x38,0x32,0x2c,0x30,0x78,0x43,
0x39,0x2c,0x30,0x78,0x37,0x44,0x2c,0x30,0x78,0x46,0x41,0x2c,0x30,0x78,0x35,0x39,0x2c,0x30,0x78,0x34,0x37,0x2c,0x30,0x78,0x46,0x30,0x2c,0x30,0x78,0x41,0x44,0x2c,
0x30,0x78,0x44,0x34,0x2c,0x30,0x78,0x41,0x32,0x2c,0x30,0x78,0x41,0x46,0x2c,0x30,0x78,0x39,0x43,0x2c,0x30,0x78,0x41,0x34,0x2c,0x30,0x78,0x37,0x32,0x2c,0x30,0x78,
0x43,0x30,0x2c,0x0a,0x30,0x78,0x42,0x37,0x2c,0x30,0x78,0x46,0x44,0x2c,0x30,0x78,0x39,0x33,0x2c,0x30,0x78,0x32,0x36,0x2c,0x30,0x78,0x33,0x36,0x2c,0x30,0x78,0x33,
0x46,0x2c,0x30,0x78,0x46,0x37,0x2c,0x30,0x78,0x43,0x43,0x2c,0x30,0x78,0x33,0x34,0x2c,0x30,0x78,0x41,0x35,0x2c,0x30,0x78,0x45,0x35,0x2c,0x30,0x78,0x46,0x31,0x2c,
0x30,0x78,0x37,0x31,0x2c,0x30,0x78,0x44,0x38,0x2c,0x30,0x78,0x33,0x31,0x2c,0x30,0x78,0x31,0x35,0x2c,0x0a,0x30,0x78,0x30,0x34,0x2c,0x30,0x78,0x43,0x37,0x2c,0x30,
0x78,0x32,0x33,0x2c,0x30,0x78,0x43,0x33,0x2c,0x30,0x78,0x31,0x38,0x2c,0x30,0x78,0x39,0x36,0x2c,0x30,0x78,0x30,0x35,0x2c,0x30,0x78,0x39,0x41,0x2c,0x30,0x78,0x30,
0x37,0x2c,0x30,0x78,0x31,0x32,0x2c,0x30,0x78,0x38,0x30,0x2c,0x30,0x78,0x45,0x32,0x2c,0x30,0x78,0x45,0x42,0x2c,0x30,0x78,0x32,0x37,0x2c,0x30,0x78,0x42,0x32,0x2c,
0x30,0x78,0x37,0x35,0x2c,0x0a,0x30,0x78,0x30,0x39,0x2c,0x30,0x78,0x38,0x33,0x2c,0x30,0x78,0x32,0x43,0x2c,0x30,0x78,0x31,0x41,0x2c,0x30,0x78,0x31,0x42,0x2c,0x30,
0x78,0x36,0x45,0x2c,0x30,0x78,0x35,0x41,0x2c,0x30,0x78,0x41,0x30,0x2c,0x30,0x78,0x35,0x32,0x2c,0x30,0x78,0x33,0x42,0x2c,0x30,0x78,0x44,0x36,0x2c,0x30,0x78,0x42,
0x33,0x2c,0x30,0x78,0x32,0x39,0x2c,0x30,0x78,0x45,0x33,0x2c,0x30,0x78,0x32,0x46,0x2c,0x30,0x78,0x38,0x34,0x2c,0x0a,0x30,0x78,0x35,0x33,0x2c,0x30,0x78,0x44,0x31,
0x2c,0x30,0x78,0x30,0x30,0x2c,0x30,0x78,0x45,0x44,0x2c,0x30,0x78,0x32,0x30,0x2c,0x30,0x78,0x46,0x43,0x2c,0x30,0x78,0x42,0x31,0x2c,0x30,0x78,0x35,0x42,0x2c,0x30,
0x78,0x36,0x41,0x2c,0x30,0x78,0x43,0x42,0x2c,0x30,0x78,0x42,0x45,0x2c,0x30,0x78,0x33,0x39,0x2c,0x30,0x78,0x34,0x41,0x2c,0x30,0x78,0x34,0x43,0x2c,0x30,0x78,0x35,
0x38,0x2c,0x30,0x78,0x43,0x46,0x2c,0x0a,0x30,0x78,0x44,0x30,0x2c,0x30,0x78,0x45,0x46,0x2c,0x30,0x78,0x41,0x41,0x2c,0x30,0x78,0x46,0x42,0x2c,0x30,0x78,0x34,0x33,
0x2c,0x30,0x78,0x34,0x44,0x2c,0x30,0x78,0x33,0x33,0x2c,0x30,0x78,0x38,0x35,0x2c,0x30,0x78,0x34,0x35,0x2c,0x30,0x78,0x46,0x39,0x2c,0x30,0x78,0x30,0x32,0x2c,0x30,
0x78,0x37,0x46,0x2c,0x30,0x78,0x35,0x30,0x2c,0x30,0x78,0x33,0x43,0x2c,0x30,0x78,0x39,0x46,0x2c,0x30,0x78,0x41,0x38,0x2c,0x0a,0x30,0x78,0x35,0x31,0x2c,0x30,0x78,
0x41,0x33,0x2c,0x30,0x78,0x34,0x30,0x2c,0x30,0x78,0x38,0x46,0x2c,0x30,0x78,0x39,0x32,0x2c,0x30,0x78,0x39,0x44,0x2c,0x30,0x78,0x33,0x38,0x2c,0x30,0x78,0x46,0x35,
0x2c,0x30,0x78,0x42,0x43,0x2c,0x30,0x78,0x42,0x36,0x2c,0x30,0x78,0x44,0x41,0x2c,0x30,0x78,0x32,0x31,0x2c,0x30,0x78,0x31,0x30,0x2c,0x30,0x78,0x46,0x46,0x2c,0x30,
0x78,0x46,0x33,0x2c,0x30,0x78,0x44,0x32,0x2c,0x0a,0x30,0x78,0x43,0x44,0x2c,0x30,0x78,0x30,0x43,0x2c,0x30,0x78,0x31,0x33,0x2c,0x30,0x78,0x45,0x43,0x2c,0x30,0x78,
0x35,0x46,0x2c,0x30,0x78,0x39,0x37,0x2c,0x30,0x78,0x34,0x34,0x2c,0x30,0x78,0x31,0x37,0x2c,0x30,0x78,0x43,0x34,0x2c,0x30,0x78,0x41,0x37,0x2c,0x30,0x78,0x37,0x45,
0x2c,0x30,0x78,0x33,0x44,0x2c,0x30,0x78,0x36,0x34,0x2c,0x30,0x78,0x35,0x44,0x2c,0x30,0x78,0x31,0x39,0x2c,0x30,0x78,0x37,0x33,0x2c,0x0a,0x30,0x78,0x36,0x30,0x2c,
0x30,0x78,0x38,0x31,0x2c,0x30,0x78,0x34,0x46,0x2c,0x30,0x78,0x44,0x43,0x2c,0x30,0x78,0x32,0x32,0x2c,0x30,0x78,0x32,0x41,0x2c,0x30,0x78,0x39,0x30,0x2c,0x30,0x78,
0x38,0x38,0x2c,0x30,0x78,0x34,0x36,0x2c,0x30,0x78,0x45,0x45,0x2c,0x30,0x78,0x42,0x38,0x2c,0x30,0x78,0x31,0x34,0x2c,0x30,0x78,0x44,0x45,0x2c,0x30,0x78,0x35,0x45,
0x2c,0x30,0x78,0x30,0x42,0x2c,0x30,0x78,0x44,0x42,0x2c,0x0a,0x30,0x78,0x45,0x30,0x2c,0x30,0x78,0x33,0x32,0x2c,0x30,0x78,0x33,0x41,0x2c,0x30,0x78,0x30,0x41,0x2c,
0x30,0x78,0x34,0x39,0x2c,0x30,0x78,0x30,0x36,0x2c,0x30,0x78,0x32,0x34,0x2c,0x30,0x78,0x35,0x43,0x2c,0x30,0x78,0x43,0x32,0x2c,0x30,0x78,0x44,0x33,0x2c,0x30,0x78,
0x41,0x43,0x2c,0x30,0x78,0x36,0x32,0x2c,0x30,0x78,0x39,0x31,0x2c,0x30,0x78,0x39,0x35,0x2c,0x30,0x78,0x45,0x34,0x2c,0x30,0x78,0x37,0x39,0x2c,0x0a,0x30,0x78,0x45,
0x37,0x2c,0x30,0x78,0x43,0x38,0x2c,0x30,0x78,0x33,0x37,0x2c,0x30,0x78,0x36,0x44,0x2c,0x30,0x78,0x38,0x44,0x2c,0x30,0x78,0x44,0x35,0x2c,0x30,0x78,0x34,0x45,0x2c,
0x30,0x78,0x41,0x39,0x2c,0x30,0x78,0x36,0x43,0x2c,0x30,0x78,0x35,0x36,0x2c,0x30,0x78,0x46,0x34,0x2c,0x30,0x78,0x45,0x41,0x2c,0x30,0x78,0x36,0x35,0x2c,0x30,0x78,
0x37,0x41,0x2c,0x30,0x78,0x41,0x45,0x2c,0x30,0x78,0x30,0x38,0x2c,0x0a,0x30,0x78,0x42,0x41,0x2c,0x30,0x78,0x37,0x38,0x2c,0x30,0x78,0x32,0x35,0x2c,0x30,0x78,0x32,
0x45,0x2c,0x30,0x78,0x31,0x43,0x2c,0x30,0x78,0x41,0x36,0x2c,0x30,0x78,0x42,0x34,0x2c,0x30,0x78,0x43,0x36,0x2c,0x30,0x78,0x45,0x38,0x2c,0x30,0x78,0x44,0x44,0x2c,
0x30,0x78,0x37,0x34,0x2c,0x30,0x78,0x31,0x46,0x2c,0x30,0x78,0x34,0x42,0x2c,0x30,0x78,0x42,0x44,0x2c,0x30,0x78,0x38,0x42,0x2c,0x30,0x78,0x38,0x41,0x2c,0x0a,0x30,
0x78,0x37,0x30,0x2c,0x30,0x78,0x33,0x45,0x2c,0x30,0x78,0x42,0x35,0x2c,0x30,0x78,0x36,0x36,0x2c,0x30,0x78,0x34,0x38,0x2c,0x30,0x78,0x30,0x33,0x2c,0x30,0x78,0x46,
0x36,0x2c,0x30,0x78,0x30,0x45,0x2c,0x30,0x78,0x36,0x31,0x2c,0x30,0x78,0x33,0x35,0x2c,0x30,0x78,0x35,0x37,0x2c,0x30,0x78,0x42,0x39,0x2c,0x30,0x78,0x38,0x36,0x2c,
0x30,0x78,0x43,0x31,0x2c,0x30,0x78,0x31,0x44,0x2c,0x30,0x78,0x39,0x45,0x2c,0x0a,0x30,0x78,0x45,0x31,0x2c,0x30,0x78,0x46,0x38,0x2c,0x30,0x78,0x39,0x38,0x2c,0x30,
0x78,0x31,0x31,0x2c,0x30,0x78,0x36,0x39,0x2c,0x30,0x78,0x44,0x39,0x2c,0x30,0x78,0x38,0x45,0x2c,0x30,0x78,0x39,0x34,0x2c,0x30,0x78,0x39,0x42,0x2c,0x30,0x78,0x31,
0x45,0x2c,0x30,0x78,0x38,0x37,0x2c,0x30,0x78,0x45,0x39,0x2c,0x30,0x78,0x43,0x45,0x2c,0x30,0x78,0x35,0x35,0x2c,0x30,0x78,0x32,0x38,0x2c,0x30,0x78,0x44,0x46,0x2c,
0x0a,0x30,0x78,0x38,0x43,0x2c,0x30,0x78,0x41,0x31,0x2c,0x30,0x78,0x38,0x39,0x2c,0x30,0x78,0x30,0x44,0x2c,0x30,0x78,0x42,0x46,0x2c,0x30,0x78,0x45,0x36,0x2c,0x30,
0x78,0x34,0x32,0x2c,0x30,0x78,0x36,0x38,0x2c,0x30,0x78,0x34,0x31,0x2c,0x30,0x78,0x39,0x39,0x2c,0x30,0x78,0x32,0x44,0x2c,0x30,0x78,0x30,0x46,0x2c,0x30,0x78,0x42,
0x30,0x2c,0x30,0x78,0x35,0x34,0x2c,0x30,0x78,0x42,0x42,0x2c,0x30,0x78,0x31,0x36,0x0a,0x7d,0x3b,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x53,0x75,0x62,0x57,
0x6f,0x72,0x64,0x28,0x69,0x6e,0x77,0x29,0x20,0x28,0x28,0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x33,0x29,0x5d,0x20,0x3c,0x3c,
0x20,0x32,0x34,0x29,0x20,0x7c,0x20,0x28,0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x32,0x29,0x5d,0x20,0x3c,0x3c,0x20,0x31,0x36,
0x29,0x20,0x7c,0x20,0x28,0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x31,0x29,0x5d,0x20,0x3c,0x3c,0x20,0x38,0x29,0x20,0x7c,0x20,
0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x30,0x29,0x5d,0x29,0x0a,0x76,0x6f,0x69,0x64,0x20,0x41,0x45,0x53,0x45,0x78,0x70,0x61,
0x6e,0x64,0x4b,0x65,0x79,0x32,0x35,0x36,0x28,0x75,0x69,0x6e,0x74,0x20,0x2a,0x6b,0x65,0x79,0x62,0x75,0x66,0x29,0x0a,0x7b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,
0x6e,0x74,0x20,0x63,0x3d,0x38,0x2c,0x69,0x3d,0x31,0x3b,0x20,0x63,0x3c,0x34,0x30,0x3b,0x20,0x2b,0x2b,0x63,0x29,0x20,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x74,0x3d,
0x28,0x28,0x21,0x28,0x63,0x26,0x37,0x29,0x29,0x7c,0x7c,0x28,0x28,0x63,0x26,0x37,0x29,0x3d,0x3d,0x34,0x29,0x29,0x3f,0x53,0x75,0x62,0x57,0x6f,0x72,0x64,0x28,0x6b,
0x65,0x79,0x62,0x75,0x66,0x5b,0x63,0x2d,0x31,0x5d,0x29,0x3a,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,0x63,0x2d,0x31,0x5d,0x3b,0x0a,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,
0x63,0x5d,0x3d,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,0x63,0x2d,0x38,0x5d,0x5e,0x28,0x28,0x21,0x28,0x63,0x26,0x37,0x29,0x29,0x3f,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,
0x74,0x2c,0x32,0x34,0x55,0x29,0x5e,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x28,0x28,0x75,0x63,0x68,0x61,0x72,0x34,0x29,0x28,0x72,0x63,0x6f,0x6e,0x5b,0x69,0x2b,0x2b,
0x5d,0x2c,0x30,0x55,0x2c,0x30,0x55,0x2c,0x30,0x55,0x29,0x29,0x3a,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x00
};
static char cryptonight_r_cl[3415] = {
static char cryptonight_r_cl[3424] = {
0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,0x28,0x72,0x65,0x71,0x64,0x5f,0x77,0x6f,0x72,0x6b,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,
0x69,0x7a,0x65,0x28,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0d,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,
0x69,0x7a,0x65,0x28,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,
0x64,0x20,0x4b,0x45,0x52,0x4e,0x45,0x4c,0x5f,0x4e,0x41,0x4d,0x45,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x69,0x6e,
0x70,0x75,0x74,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2c,0x5f,
0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x73,0x74,0x61,0x74,0x65,0x73,0x2c,0x75,0x69,0x6e,0x74,0x20,0x54,0x68,0x72,0x65,0x61,
0x64,0x73,0x29,0x0d,0x7b,0x0d,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x61,0x5b,0x32,0x5d,0x2c,0x62,0x5b,0x34,0x5d,0x3b,0x0d,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,
0x64,0x73,0x29,0x0a,0x7b,0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x61,0x5b,0x32,0x5d,0x2c,0x62,0x5b,0x34,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,
0x69,0x6e,0x74,0x20,0x41,0x45,0x53,0x30,0x5b,0x32,0x35,0x36,0x5d,0x2c,0x41,0x45,0x53,0x31,0x5b,0x32,0x35,0x36,0x5d,0x2c,0x41,0x45,0x53,0x32,0x5b,0x32,0x35,0x36,
0x5d,0x2c,0x41,0x45,0x53,0x33,0x5b,0x32,0x35,0x36,0x5d,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x67,0x49,0x64,0x78,0x3d,0x67,0x65,
0x5d,0x2c,0x41,0x45,0x53,0x33,0x5b,0x32,0x35,0x36,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x67,0x49,0x64,0x78,0x3d,0x67,0x65,
0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x2d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,
0x28,0x30,0x29,0x3b,0x0d,0x66,0x6f,0x72,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x20,
0x69,0x3c,0x32,0x35,0x36,0x3b,0x20,0x69,0x2b,0x3d,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x29,0x20,0x7b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x20,0x74,0x6d,0x70,0x3d,0x41,0x45,0x53,0x30,0x5f,0x43,0x5b,0x69,0x5d,0x3b,0x0d,0x41,0x45,0x53,0x30,0x5b,0x69,0x5d,0x3d,0x74,0x6d,0x70,0x3b,0x0d,0x41,0x45,0x53,
0x31,0x5b,0x69,0x5d,0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x6d,0x70,0x2c,0x38,0x55,0x29,0x3b,0x0d,0x41,0x45,0x53,0x32,0x5b,0x69,0x5d,0x3d,0x72,0x6f,0x74,
0x61,0x74,0x65,0x28,0x74,0x6d,0x70,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0d,0x41,0x45,0x53,0x33,0x5b,0x69,0x5d,0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x6d,0x70,
0x2c,0x32,0x34,0x55,0x29,0x3b,0x0d,0x7d,0x0d,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,
0x45,0x4e,0x43,0x45,0x29,0x3b,0x0d,0x7b,0x0d,0x73,0x74,0x61,0x74,0x65,0x73,0x2b,0x3d,0x32,0x35,0x2a,0x67,0x49,0x64,0x78,0x3b,0x0d,0x23,0x69,0x66,0x20,0x64,0x65,
0x66,0x69,0x6e,0x65,0x64,0x28,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x29,0x0d,0x53,0x63,0x72,0x61,0x74,0x63,0x68,
0x70,0x61,0x64,0x2b,0x3d,0x67,0x49,0x64,0x78,0x2a,0x28,0x49,0x54,0x45,0x52,0x41,0x54,0x49,0x4f,0x4e,0x53,0x3e,0x3e,0x32,0x29,0x3b,0x0d,0x23,0x65,0x6c,0x73,0x65,
0x0d,0x23,0x69,0x66,0x28,0x53,0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x3d,0x3d,0x30,0x29,0x0d,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,
0x64,0x2b,0x3d,0x67,0x49,0x64,0x78,0x2a,0x28,0x4d,0x45,0x4d,0x4f,0x52,0x59,0x3e,0x3e,0x34,0x29,0x3b,0x0d,0x23,0x65,0x6c,0x69,0x66,0x28,0x53,0x54,0x52,0x49,0x44,
0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x3d,0x3d,0x31,0x29,0x0d,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2b,0x3d,0x67,0x49,0x64,0x78,0x3b,0x0d,0x23,
0x65,0x6c,0x69,0x66,0x28,0x53,0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x3d,0x3d,0x32,0x29,0x0d,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,
0x64,0x2b,0x3d,0x67,0x65,0x74,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x28,0x30,0x29,0x2a,0x28,0x4d,0x45,0x4d,0x4f,0x52,0x59,0x3e,0x3e,0x34,0x29,0x2a,0x57,
0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x2b,0x4d,0x45,0x4d,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x2a,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,
0x29,0x3b,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x61,0x5b,0x30,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x30,0x5d,0x5e,
0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x34,0x5d,0x3b,0x0d,0x61,0x5b,0x31,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,
0x5b,0x35,0x5d,0x3b,0x0d,0x62,0x5b,0x30,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x32,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x36,0x5d,0x3b,0x0d,0x62,
0x5b,0x31,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x33,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x37,0x5d,0x3b,0x0d,0x62,0x5b,0x32,0x5d,0x3d,0x73,0x74,
0x61,0x74,0x65,0x73,0x5b,0x38,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x30,0x5d,0x3b,0x0d,0x62,0x5b,0x33,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,
0x39,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x31,0x5d,0x3b,0x0d,0x7d,0x0d,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x62,0x78,0x30,0x3d,0x28,0x28,0x75,0x6c,
0x6f,0x6e,0x67,0x32,0x20,0x2a,0x29,0x62,0x29,0x5b,0x30,0x5d,0x3b,0x0d,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x62,0x78,0x31,0x3d,0x28,0x28,0x75,0x6c,0x6f,0x6e,0x67,
0x32,0x20,0x2a,0x29,0x62,0x29,0x5b,0x31,0x5d,0x3b,0x0d,0x6d,0x65,0x6d,0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,
0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0d,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,
0x49,0x4f,0x4e,0x0d,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x20,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,
0x6e,0x65,0x5f,0x62,0x75,0x66,0x5b,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x5d,0x3b,0x0d,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,
0x2a,0x20,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3d,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,
0x65,0x5f,0x62,0x75,0x66,0x2b,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x7b,0x0d,
0x75,0x69,0x6e,0x74,0x20,0x72,0x30,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x32,0x5d,0x29,0x2e,0x73,0x30,0x3b,
0x0d,0x75,0x69,0x6e,0x74,0x20,0x72,0x31,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x32,0x5d,0x29,0x2e,0x73,0x31,
0x3b,0x0d,0x75,0x69,0x6e,0x74,0x20,0x72,0x32,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x33,0x5d,0x29,0x2e,0x73,
0x30,0x3b,0x0d,0x75,0x69,0x6e,0x74,0x20,0x72,0x33,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x33,0x5d,0x29,0x2e,
0x73,0x31,0x3b,0x0d,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x43,0x4e,0x5f,0x55,0x4e,0x52,0x4f,0x4c,0x4c,0x0d,0x66,0x6f,0x72,
0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x49,0x54,0x45,0x52,0x41,0x54,0x49,0x4f,0x4e,0x53,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x7b,0x0d,
0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x0d,0x75,0x69,0x6e,0x74,0x20,0x69,0x64,
0x78,0x3d,0x61,0x5b,0x30,0x5d,0x26,0x30,0x78,0x31,0x46,0x46,0x46,0x43,0x30,0x3b,0x0d,0x75,0x69,0x6e,0x74,0x20,0x69,0x64,0x78,0x31,0x3d,0x61,0x5b,0x30,0x5d,0x26,
0x30,0x78,0x33,0x30,0x3b,0x0d,0x2a,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3d,0x2a,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,
0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,0x28,0x53,0x63,0x72,
0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x2b,0x69,0x64,0x78,0x29,0x3b,0x0d,0x23,0x65,0x6c,0x73,0x65,0x0d,0x75,0x69,0x6e,0x74,0x20,0x69,0x64,0x78,0x3d,0x61,0x5b,
0x30,0x5d,0x26,0x4d,0x41,0x53,0x4b,0x3b,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x75,0x69,0x6e,0x74,0x34,0x20,0x63,0x3d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,
0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x30,0x29,0x3b,0x0d,0x63,0x3d,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x28,0x41,0x45,0x53,0x30,0x2c,0x41,0x45,
0x53,0x31,0x2c,0x41,0x45,0x53,0x32,0x2c,0x41,0x45,0x53,0x33,0x2c,0x63,0x2c,0x28,0x28,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,0x29,0x3b,
0x0d,0x7b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x31,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,
0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x31,0x29,0x29,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,
0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x32,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,
0x43,0x48,0x55,0x4e,0x4b,0x28,0x32,0x29,0x29,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x33,0x3d,0x61,
0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x33,0x29,0x29,0x3b,0x0d,0x63,
0x20,0x5e,0x3d,0x20,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x31,0x29,0x5e,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,
0x75,0x6e,0x6b,0x32,0x29,0x5e,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x33,0x29,0x3b,0x0d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,
0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x31,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x33,0x2b,0x62,0x78,0x31,0x29,
0x3b,0x0d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x32,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,
0x68,0x75,0x6e,0x6b,0x31,0x2b,0x62,0x78,0x30,0x29,0x3b,0x0d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x33,0x29,0x3d,
0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x32,0x2b,0x28,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,
0x29,0x3b,0x0d,0x7d,0x0d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x30,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,
0x34,0x28,0x62,0x78,0x30,0x29,0x5e,0x63,0x3b,0x0d,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,
0x4f,0x4e,0x0d,0x2a,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,
0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,0x28,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x2b,0x69,0x64,0x78,0x29,0x3d,0x2a,0x73,0x63,0x72,0x61,0x74,
0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3b,0x0d,0x69,0x64,0x78,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x63,0x29,0x2e,0x73,0x30,0x26,
0x30,0x78,0x31,0x46,0x46,0x46,0x43,0x30,0x3b,0x0d,0x69,0x64,0x78,0x31,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x63,0x29,0x2e,0x73,0x30,0x26,0x30,
0x78,0x33,0x30,0x3b,0x0d,0x2a,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3d,0x2a,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,
0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,0x28,0x53,0x63,0x72,0x61,
0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x2b,0x69,0x64,0x78,0x29,0x3b,0x0d,0x23,0x65,0x6c,0x73,0x65,0x0d,0x69,0x64,0x78,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,
0x32,0x28,0x63,0x29,0x2e,0x73,0x30,0x26,0x4d,0x41,0x53,0x4b,0x3b,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x75,0x69,0x6e,0x74,0x34,0x20,0x74,0x6d,0x70,0x3d,0x53,
0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x30,0x29,0x3b,0x0d,0x74,0x6d,0x70,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x72,0x30,
0x2b,0x72,0x31,0x3b,0x0d,0x74,0x6d,0x70,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x72,0x32,0x2b,0x72,0x33,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x20,0x72,0x34,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x30,0x5d,0x29,0x2e,0x73,0x30,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,
0x74,0x20,0x72,0x35,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x31,0x5d,0x29,0x2e,0x73,0x30,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x20,0x72,0x36,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x62,0x78,0x30,0x29,0x2e,0x73,0x30,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x20,0x72,0x37,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x62,0x78,0x31,0x29,0x2e,0x73,0x30,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x20,0x72,0x38,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x62,0x78,0x31,0x29,0x2e,0x73,0x32,0x3b,0x0d,0x58,0x4d,0x52,0x49,0x47,0x5f,0x49,0x4e,
0x43,0x4c,0x55,0x44,0x45,0x5f,0x52,0x41,0x4e,0x44,0x4f,0x4d,0x5f,0x4d,0x41,0x54,0x48,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x32,0x20,0x61,0x6c,
0x3d,0x28,0x75,0x69,0x6e,0x74,0x32,0x29,0x28,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x30,0x5d,0x29,0x2e,0x73,0x30,0x5e,0x72,0x32,0x2c,0x61,0x73,
0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x30,0x5d,0x29,0x2e,0x73,0x31,0x5e,0x72,0x33,0x29,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x32,
0x20,0x61,0x68,0x3d,0x28,0x75,0x69,0x6e,0x74,0x32,0x29,0x28,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x31,0x5d,0x29,0x2e,0x73,0x30,0x5e,0x72,0x30,
0x2c,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x31,0x5d,0x29,0x2e,0x73,0x31,0x5e,0x72,0x31,0x29,0x3b,0x0d,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x74,
0x3b,0x0d,0x74,0x2e,0x73,0x30,0x3d,0x6d,0x75,0x6c,0x5f,0x68,0x69,0x28,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x63,0x29,0x2e,0x73,0x30,0x2c,0x61,0x73,
0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x74,0x6d,0x70,0x29,0x2e,0x73,0x30,0x29,0x3b,0x0d,0x74,0x2e,0x73,0x31,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,
0x28,0x63,0x29,0x2e,0x73,0x30,0x2a,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x74,0x6d,0x70,0x29,0x2e,0x73,0x30,0x3b,0x0d,0x7b,0x0d,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x31,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,
0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x31,0x29,0x29,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,
0x6e,0x6b,0x32,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x32,
0x29,0x29,0x3b,0x0d,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x33,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,
0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x33,0x29,0x29,0x3b,0x0d,0x63,0x20,0x5e,0x3d,0x20,0x61,0x73,0x5f,
0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x31,0x29,0x5e,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x32,0x29,0x5e,0x61,
0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x33,0x29,0x3b,0x0d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,
0x4b,0x28,0x31,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x33,0x2b,0x62,0x78,0x31,0x29,0x3b,0x0d,0x53,0x43,0x52,0x41,0x54,
0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x32,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x31,0x2b,0x62,
0x78,0x30,0x29,0x3b,0x0d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x33,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,
0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x32,0x2b,0x28,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,0x29,0x3b,0x0d,0x7d,0x0d,0x61,0x5b,
0x31,0x5d,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x28,0x61,0x68,0x29,0x2b,0x74,0x2e,0x73,0x31,0x3b,0x0d,0x61,0x5b,0x30,0x5d,0x3d,0x61,0x73,0x5f,0x75,0x6c,
0x6f,0x6e,0x67,0x28,0x61,0x6c,0x29,0x2b,0x74,0x2e,0x73,0x30,0x3b,0x0d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x30,
0x29,0x3d,0x28,0x28,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,0x3b,0x0d,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,
0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x0d,0x2a,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x29,0x28,
0x28,0x30,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x20,
0x69,0x3c,0x32,0x35,0x36,0x3b,0x20,0x69,0x2b,0x3d,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x29,0x20,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x20,0x74,0x6d,0x70,0x3d,0x41,0x45,0x53,0x30,0x5f,0x43,0x5b,0x69,0x5d,0x3b,0x0a,0x41,0x45,0x53,0x30,0x5b,0x69,0x5d,0x3d,0x74,0x6d,0x70,0x3b,0x0a,0x41,0x45,0x53,
0x31,0x5b,0x69,0x5d,0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x6d,0x70,0x2c,0x38,0x55,0x29,0x3b,0x0a,0x41,0x45,0x53,0x32,0x5b,0x69,0x5d,0x3d,0x72,0x6f,0x74,
0x61,0x74,0x65,0x28,0x74,0x6d,0x70,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x41,0x45,0x53,0x33,0x5b,0x69,0x5d,0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x6d,0x70,
0x2c,0x32,0x34,0x55,0x29,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,
0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x7b,0x0a,0x73,0x74,0x61,0x74,0x65,0x73,0x2b,0x3d,0x32,0x35,0x2a,0x67,0x49,0x64,0x78,0x3b,0x0a,0x23,0x69,0x66,0x20,0x64,0x65,
0x66,0x69,0x6e,0x65,0x64,0x28,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x29,0x0a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,
0x70,0x61,0x64,0x2b,0x3d,0x67,0x49,0x64,0x78,0x2a,0x28,0x49,0x54,0x45,0x52,0x41,0x54,0x49,0x4f,0x4e,0x53,0x3e,0x3e,0x32,0x29,0x3b,0x0a,0x23,0x65,0x6c,0x73,0x65,
0x0a,0x23,0x69,0x66,0x20,0x28,0x53,0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x30,0x29,0x0a,0x53,0x63,0x72,0x61,0x74,0x63,
0x68,0x70,0x61,0x64,0x2b,0x3d,0x67,0x49,0x64,0x78,0x2a,0x28,0x4d,0x45,0x4d,0x4f,0x52,0x59,0x3e,0x3e,0x34,0x29,0x3b,0x0a,0x23,0x65,0x6c,0x69,0x66,0x20,0x28,0x53,
0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x31,0x29,0x0a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2b,0x3d,0x67,
0x49,0x64,0x78,0x3b,0x0a,0x23,0x65,0x6c,0x69,0x66,0x20,0x28,0x53,0x54,0x52,0x49,0x44,0x45,0x44,0x5f,0x49,0x4e,0x44,0x45,0x58,0x20,0x3d,0x3d,0x20,0x32,0x29,0x0a,
0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2b,0x3d,0x67,0x65,0x74,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x28,0x30,0x29,0x2a,0x28,0x4d,0x45,0x4d,
0x4f,0x52,0x59,0x3e,0x3e,0x34,0x29,0x2a,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x2b,0x4d,0x45,0x4d,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x2a,0x67,0x65,0x74,0x5f,0x6c,
0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x61,0x5b,0x30,0x5d,0x3d,0x73,
0x74,0x61,0x74,0x65,0x73,0x5b,0x30,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x61,0x5b,0x31,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,
0x31,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x35,0x5d,0x3b,0x0a,0x62,0x5b,0x30,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x32,0x5d,0x5e,0x73,0x74,0x61,
0x74,0x65,0x73,0x5b,0x36,0x5d,0x3b,0x0a,0x62,0x5b,0x31,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x33,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x37,0x5d,
0x3b,0x0a,0x62,0x5b,0x32,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x38,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x30,0x5d,0x3b,0x0a,0x62,0x5b,0x33,
0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x39,0x5d,0x5e,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x31,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x32,
0x20,0x62,0x78,0x30,0x3d,0x28,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x2a,0x29,0x62,0x29,0x5b,0x30,0x5d,0x3b,0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x62,0x78,
0x31,0x3d,0x28,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x2a,0x29,0x62,0x29,0x5b,0x31,0x5d,0x3b,0x0a,0x6d,0x65,0x6d,0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,
0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,
0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x20,0x73,0x63,0x72,0x61,
0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x5f,0x62,0x75,0x66,0x5b,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,
0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x20,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3d,0x73,0x63,0x72,0x61,0x74,
0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x5f,0x62,0x75,0x66,0x2b,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,
0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x72,0x30,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x73,0x74,0x61,0x74,0x65,0x73,
0x5b,0x31,0x32,0x5d,0x29,0x2e,0x73,0x30,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x72,0x31,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x73,0x74,0x61,0x74,0x65,
0x73,0x5b,0x31,0x32,0x5d,0x29,0x2e,0x73,0x31,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x72,0x32,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x73,0x74,0x61,0x74,
0x65,0x73,0x5b,0x31,0x33,0x5d,0x29,0x2e,0x73,0x30,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x72,0x33,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x73,0x74,0x61,
0x74,0x65,0x73,0x5b,0x31,0x33,0x5d,0x29,0x2e,0x73,0x31,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x43,0x4e,0x5f,0x55,
0x4e,0x52,0x4f,0x4c,0x4c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x49,0x54,0x45,0x52,0x41,0x54,0x49,0x4f,0x4e,0x53,
0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x7b,0x0a,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,
0x4e,0x0a,0x75,0x69,0x6e,0x74,0x20,0x69,0x64,0x78,0x3d,0x61,0x5b,0x30,0x5d,0x26,0x30,0x78,0x31,0x46,0x46,0x46,0x43,0x30,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x69,
0x64,0x78,0x31,0x3d,0x61,0x5b,0x30,0x5d,0x26,0x30,0x78,0x33,0x30,0x3b,0x0a,0x2a,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3d,
0x2a,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,
0x68,0x61,0x72,0x2a,0x29,0x28,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x2b,0x69,0x64,0x78,0x29,0x3b,0x0a,0x23,0x65,0x6c,0x73,0x65,0x0a,0x75,0x69,
0x6e,0x74,0x20,0x69,0x64,0x78,0x3d,0x61,0x5b,0x30,0x5d,0x26,0x4d,0x41,0x53,0x4b,0x3b,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x75,0x69,0x6e,0x74,0x34,0x20,0x63,
0x3d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x30,0x29,0x3b,0x0a,0x63,0x3d,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,
0x64,0x28,0x41,0x45,0x53,0x30,0x2c,0x41,0x45,0x53,0x31,0x2c,0x41,0x45,0x53,0x32,0x2c,0x41,0x45,0x53,0x33,0x2c,0x63,0x2c,0x28,0x28,0x75,0x69,0x6e,0x74,0x34,0x20,
0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,0x29,0x3b,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x31,0x3d,
0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x31,0x29,0x29,0x3b,0x0a,
0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x32,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,
0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x32,0x29,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,
0x20,0x63,0x68,0x75,0x6e,0x6b,0x33,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,
0x4e,0x4b,0x28,0x33,0x29,0x29,0x3b,0x0a,0x63,0x20,0x5e,0x3d,0x20,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x31,0x29,0x5e,0x61,0x73,
0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x32,0x29,0x5e,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x33,0x29,0x3b,
0x0a,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x31,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,
0x75,0x6e,0x6b,0x33,0x2b,0x62,0x78,0x31,0x29,0x3b,0x0a,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x32,0x29,0x3d,0x61,
0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x31,0x2b,0x62,0x78,0x30,0x29,0x3b,0x0a,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,
0x43,0x48,0x55,0x4e,0x4b,0x28,0x33,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x32,0x2b,0x28,0x28,0x75,0x6c,0x6f,0x6e,0x67,
0x32,0x20,0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,0x29,0x3b,0x0a,0x7d,0x0a,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x30,
0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x62,0x78,0x30,0x29,0x5e,0x63,0x3b,0x0a,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,
0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x0a,0x2a,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x29,0x28,
0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,0x28,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x2b,0x69,0x64,
0x78,0x29,0x3d,0x2a,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3b,0x0d,0x23,0x65,0x6e,0x64,0x69,0x66,0x0d,0x28,0x28,0x75,0x69,
0x6e,0x74,0x34,0x20,0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x6d,0x70,0x3b,0x0d,0x62,0x78,0x31,0x3d,0x62,0x78,0x30,0x3b,0x0d,0x62,0x78,0x30,
0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x63,0x29,0x3b,0x0d,0x7d,0x0d,0x7d,0x0d,0x6d,0x65,0x6d,0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,0x4b,
0x5f,0x47,0x4c,0x4f,0x42,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0d,0x7d,0x0d,0x00
0x78,0x29,0x3d,0x2a,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3b,0x0a,0x69,0x64,0x78,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,
0x67,0x32,0x28,0x63,0x29,0x2e,0x73,0x30,0x26,0x30,0x78,0x31,0x46,0x46,0x46,0x43,0x30,0x3b,0x0a,0x69,0x64,0x78,0x31,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,
0x32,0x28,0x63,0x29,0x2e,0x73,0x30,0x26,0x30,0x78,0x33,0x30,0x3b,0x0a,0x2a,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3d,0x2a,
0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,
0x61,0x72,0x2a,0x29,0x28,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x29,0x2b,0x69,0x64,0x78,0x29,0x3b,0x0a,0x23,0x65,0x6c,0x73,0x65,0x0a,0x69,0x64,0x78,
0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x63,0x29,0x2e,0x73,0x30,0x26,0x4d,0x41,0x53,0x4b,0x3b,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x75,0x69,
0x6e,0x74,0x34,0x20,0x74,0x6d,0x70,0x3d,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x30,0x29,0x3b,0x0a,0x74,0x6d,0x70,
0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x72,0x30,0x2b,0x72,0x31,0x3b,0x0a,0x74,0x6d,0x70,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x72,0x32,0x2b,0x72,0x33,0x3b,0x0a,0x63,
0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x72,0x34,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x30,0x5d,0x29,0x2e,0x73,0x30,0x3b,0x0a,
0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x72,0x35,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x31,0x5d,0x29,0x2e,0x73,0x30,0x3b,
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x72,0x36,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x62,0x78,0x30,0x29,0x2e,0x73,0x30,0x3b,
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x72,0x37,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x62,0x78,0x31,0x29,0x2e,0x73,0x30,0x3b,
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x72,0x38,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x62,0x78,0x31,0x29,0x2e,0x73,0x32,0x3b,
0x0a,0x58,0x4d,0x52,0x49,0x47,0x5f,0x49,0x4e,0x43,0x4c,0x55,0x44,0x45,0x5f,0x52,0x41,0x4e,0x44,0x4f,0x4d,0x5f,0x4d,0x41,0x54,0x48,0x0a,0x63,0x6f,0x6e,0x73,0x74,
0x20,0x75,0x69,0x6e,0x74,0x32,0x20,0x61,0x6c,0x3d,0x28,0x75,0x69,0x6e,0x74,0x32,0x29,0x28,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x30,0x5d,0x29,
0x2e,0x73,0x30,0x5e,0x72,0x32,0x2c,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x30,0x5d,0x29,0x2e,0x73,0x31,0x5e,0x72,0x33,0x29,0x3b,0x0a,0x63,0x6f,
0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x32,0x20,0x61,0x68,0x3d,0x28,0x75,0x69,0x6e,0x74,0x32,0x29,0x28,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,
0x31,0x5d,0x29,0x2e,0x73,0x30,0x5e,0x72,0x30,0x2c,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x32,0x28,0x61,0x5b,0x31,0x5d,0x29,0x2e,0x73,0x31,0x5e,0x72,0x31,0x29,0x3b,
0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x74,0x3b,0x0a,0x74,0x2e,0x73,0x30,0x3d,0x6d,0x75,0x6c,0x5f,0x68,0x69,0x28,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,
0x28,0x63,0x29,0x2e,0x73,0x30,0x2c,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x74,0x6d,0x70,0x29,0x2e,0x73,0x30,0x29,0x3b,0x0a,0x74,0x2e,0x73,0x31,0x3d,
0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x63,0x29,0x2e,0x73,0x30,0x2a,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x74,0x6d,0x70,0x29,0x2e,0x73,
0x30,0x3b,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x31,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,
0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x31,0x29,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,
0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x32,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,
0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x32,0x29,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x63,0x68,0x75,0x6e,0x6b,0x33,
0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x33,0x29,0x29,0x3b,
0x0a,0x63,0x20,0x5e,0x3d,0x20,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x31,0x29,0x5e,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,
0x63,0x68,0x75,0x6e,0x6b,0x32,0x29,0x5e,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x33,0x29,0x3b,0x0a,0x53,0x43,0x52,0x41,0x54,0x43,
0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x31,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x33,0x2b,0x62,0x78,
0x31,0x29,0x3b,0x0a,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x32,0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,
0x28,0x63,0x68,0x75,0x6e,0x6b,0x31,0x2b,0x62,0x78,0x30,0x29,0x3b,0x0a,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x33,
0x29,0x3d,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x34,0x28,0x63,0x68,0x75,0x6e,0x6b,0x32,0x2b,0x28,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x20,0x2a,0x29,0x61,0x29,0x5b,
0x30,0x5d,0x29,0x3b,0x0a,0x7d,0x0a,0x61,0x5b,0x31,0x5d,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x28,0x61,0x68,0x29,0x2b,0x74,0x2e,0x73,0x31,0x3b,0x0a,0x61,
0x5b,0x30,0x5d,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x28,0x61,0x6c,0x29,0x2b,0x74,0x2e,0x73,0x30,0x3b,0x0a,0x53,0x43,0x52,0x41,0x54,0x43,0x48,0x50,0x41,
0x44,0x5f,0x43,0x48,0x55,0x4e,0x4b,0x28,0x30,0x29,0x3d,0x28,0x28,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,0x3b,0x0a,0x23,0x69,0x66,0x64,
0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x0a,0x2a,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,
0x75,0x69,0x6e,0x74,0x31,0x36,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,0x61,0x72,0x2a,0x29,0x28,0x53,0x63,0x72,0x61,0x74,
0x63,0x68,0x70,0x61,0x64,0x29,0x2b,0x69,0x64,0x78,0x29,0x3d,0x2a,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x6c,0x69,0x6e,0x65,0x3b,0x0a,0x23,0x65,
0x6e,0x64,0x69,0x66,0x0a,0x28,0x28,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x29,0x61,0x29,0x5b,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x6d,0x70,0x3b,0x0a,0x62,0x78,0x31,
0x3d,0x62,0x78,0x30,0x3b,0x0a,0x62,0x78,0x30,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x32,0x28,0x63,0x29,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x6d,0x65,0x6d,0x5f,
0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,0x4b,0x5f,0x47,0x4c,0x4f,0x42,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x7d,0x0a,0x00
};
} // namespace xmrig

File diff suppressed because it is too large Load Diff

View File

@@ -39,8 +39,8 @@ constexpr size_t oneGiB = 1024 * 1024 * 1024;
xmrig::OclBaseRunner::OclBaseRunner(size_t id, const OclLaunchData &data) :
m_algorithm(data.algorithm),
m_ctx(data.ctx),
m_algorithm(data.algorithm),
m_source(OclSource::get(data.algorithm)),
m_data(data),
m_align(OclLib::getUint(data.device.id(), CL_DEVICE_MEM_BASE_ADDR_ALIGN)),
@@ -100,11 +100,13 @@ void xmrig::OclBaseRunner::init()
m_queue = OclLib::createCommandQueue(m_ctx, data().device.id());
size_t size = align(bufferSize());
const size_t limit = data().device.freeMemSize();
if (size < oneGiB && data().device.vendorId() == OCL_VENDOR_AMD && data().device.freeMemSize() >= oneGiB) {
m_buffer = OclSharedState::get(data().device.index()).createBuffer(m_ctx, size, m_offset);
if (size < oneGiB && data().device.vendorId() == OCL_VENDOR_AMD && limit >= oneGiB) {
m_buffer = OclSharedState::get(data().device.index()).createBuffer(m_ctx, size, m_offset, limit);
}
else {
if (!m_buffer) {
m_buffer = OclLib::createBuffer(m_ctx, CL_MEM_READ_WRITE, size);
}

View File

@@ -70,21 +70,21 @@ protected:
void enqueueWriteBuffer(cl_mem buffer, cl_bool blocking_write, size_t offset, size_t size, const void *ptr);
void finalize(uint32_t *hashOutput);
Algorithm m_algorithm;
cl_command_queue m_queue = nullptr;
cl_context m_ctx;
cl_mem m_buffer = nullptr;
cl_mem m_input = nullptr;
cl_mem m_output = nullptr;
cl_program m_program = nullptr;
const Algorithm m_algorithm;
const char *m_source;
const OclLaunchData &m_data;
const size_t m_align;
const size_t m_threadId;
const uint32_t m_intensity;
size_t m_offset = 0;
std::string m_deviceKey;
std::string m_options;
uint32_t m_intensity;
};

View File

@@ -40,13 +40,20 @@
constexpr size_t oneGiB = 1024 * 1024 * 1024;
cl_mem xmrig::OclSharedData::createBuffer(cl_context context, size_t size, size_t &offset)
cl_mem xmrig::OclSharedData::createBuffer(cl_context context, size_t size, size_t &offset, size_t limit)
{
std::lock_guard<std::mutex> lock(m_mutex);
offset += size * m_offset++;
const size_t pos = offset + (size * m_offset);
size = std::max(size * m_threads, oneGiB);
if (size > limit) {
return nullptr;
}
offset = pos;
++m_offset;
if (!m_buffer) {
m_buffer = OclLib::createBuffer(context, CL_MEM_READ_WRITE, size);
}

View File

@@ -45,7 +45,7 @@ class OclSharedData
public:
OclSharedData() = default;
cl_mem createBuffer(cl_context context, size_t size, size_t &offset);
cl_mem createBuffer(cl_context context, size_t size, size_t &offset, size_t limit);
uint64_t adjustDelay(size_t id);
uint64_t resumeDelay(size_t id);
void release();

View File

@@ -132,6 +132,8 @@ xmrig::OclDevice::OclDevice(uint32_t index, cl_device_id id, cl_platform_id plat
m_board(OclLib::getString(id, 0x4038 /* CL_DEVICE_BOARD_NAME_AMD */)),
m_name(OclLib::getString(id, CL_DEVICE_NAME)),
m_vendor(OclLib::getString(id, CL_DEVICE_VENDOR)),
m_maxMemoryAlloc(OclLib::getUlong(id, CL_DEVICE_MAX_MEM_ALLOC_SIZE)),
m_globalMemory(OclLib::getUlong(id, CL_DEVICE_GLOBAL_MEM_SIZE)),
m_computeUnits(OclLib::getUint(id, CL_DEVICE_MAX_COMPUTE_UNITS, 1)),
m_index(index)
{
@@ -155,24 +157,6 @@ xmrig::OclDevice::OclDevice(uint32_t index, cl_device_id id, cl_platform_id plat
}
size_t xmrig::OclDevice::freeMemSize() const
{
return std::min(maxMemAllocSize(), globalMemSize());
}
size_t xmrig::OclDevice::globalMemSize() const
{
return OclLib::getUlong(id(), CL_DEVICE_GLOBAL_MEM_SIZE);
}
size_t xmrig::OclDevice::maxMemAllocSize() const
{
return OclLib::getUlong(id(), CL_DEVICE_MAX_MEM_ALLOC_SIZE);
}
xmrig::String xmrig::OclDevice::printableName() const
{
const size_t size = m_board.size() + m_name.size() + 64;

View File

@@ -26,13 +26,13 @@
#define XMRIG_OCLDEVICE_H
#include <vector>
#include "backend/common/misc/PciTopology.h"
#include "backend/opencl/wrappers/OclVendor.h"
#include "base/tools/String.h"
#include <algorithm>
#include <vector>
using cl_device_id = struct _cl_device_id *;
using cl_platform_id = struct _cl_platform_id *;
@@ -62,9 +62,6 @@ public:
OclDevice() = delete;
OclDevice(uint32_t index, cl_device_id id, cl_platform_id platform);
size_t freeMemSize() const;
size_t globalMemSize() const;
size_t maxMemAllocSize() const;
String printableName() const;
uint32_t clock() const;
void generate(const Algorithm &algorithm, OclThreads &threads) const;
@@ -78,6 +75,9 @@ public:
inline OclVendor vendorId() const { return m_vendorId; }
inline Type type() const { return m_type; }
inline uint32_t computeUnits() const { return m_computeUnits; }
inline size_t freeMemSize() const { return std::min(maxMemAllocSize(), globalMemSize()); }
inline size_t globalMemSize() const { return m_globalMemory; }
inline size_t maxMemAllocSize() const { return m_maxMemoryAlloc; }
inline uint32_t index() const { return m_index; }
# ifdef XMRIG_FEATURE_API
@@ -90,6 +90,8 @@ private:
const String m_board;
const String m_name;
const String m_vendor;
const size_t m_maxMemoryAlloc = 0;
const size_t m_globalMemory = 0;
const uint32_t m_computeUnits = 1;
const uint32_t m_index = 0;
OclVendor m_vendorId = OCL_VENDOR_UNKNOWN;

View File

@@ -77,6 +77,7 @@ static const char *kRetainMemObject = "clRetainMemObject";
static const char *kRetainProgram = "clRetainProgram";
static const char *kSetKernelArg = "clSetKernelArg";
static const char *kSetMemObjectDestructorCallback = "clSetMemObjectDestructorCallback";
static const char *kSymbolNotFound = "symbol not found";
static const char *kUnloadPlatformCompiler = "clUnloadPlatformCompiler";
@@ -156,7 +157,7 @@ static setKernelArg_t pSetKernelArg = nu
static setMemObjectDestructorCallback_t pSetMemObjectDestructorCallback = nullptr;
static unloadPlatformCompiler_t pUnloadPlatformCompiler = nullptr;
#define DLSYM(x) if (uv_dlsym(&oclLib, k##x, reinterpret_cast<void**>(&p##x)) == -1) { return false; }
#define DLSYM(x) if (uv_dlsym(&oclLib, k##x, reinterpret_cast<void**>(&p##x)) == -1) { throw std::runtime_error(kSymbolNotFound); }
namespace xmrig {
@@ -210,6 +211,7 @@ void xmrig::OclLib::close()
bool xmrig::OclLib::load()
{
try {
DLSYM(CreateCommandQueue);
DLSYM(CreateContext);
DLSYM(BuildProgram);
@@ -243,6 +245,9 @@ bool xmrig::OclLib::load()
DLSYM(CreateSubBuffer);
DLSYM(RetainProgram);
DLSYM(RetainMemObject);
} catch (std::exception &ex) {
return false;
}
# if defined(CL_VERSION_2_0)
uv_dlsym(&oclLib, kCreateCommandQueueWithProperties, reinterpret_cast<void**>(&pCreateCommandQueueWithProperties));

View File

@@ -49,12 +49,48 @@
#endif
#include <thread>
namespace xmrig {
static rapidjson::Value getResources(rapidjson::Document &doc)
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
size_t rss = 0;
uv_resident_set_memory(&rss);
Value out(kObjectType);
Value memory(kObjectType);
Value load_average(kArrayType);
memory.AddMember("free", uv_get_free_memory(), allocator);
memory.AddMember("total", uv_get_total_memory(), allocator);
memory.AddMember("resident_set_memory", static_cast<uint64_t>(rss), allocator);
double loadavg[3] = { 0.0 };
uv_loadavg(loadavg);
load_average.PushBack(loadavg[0], allocator);
load_average.PushBack(loadavg[1], allocator);
load_average.PushBack(loadavg[2], allocator);
out.AddMember("memory", memory, allocator);
out.AddMember("load_average", load_average, allocator);
out.AddMember("hardware_concurrency", std::thread::hardware_concurrency(), allocator);
return out;
}
} // namespace xmrig
xmrig::Api::Api(Base *base) :
m_base(base),
m_id(),
m_workerId(),
m_timestamp(Chrono::currentMSecsSinceEpoch()),
m_httpd(nullptr)
m_timestamp(Chrono::currentMSecsSinceEpoch())
{
base->addListener(this);
@@ -117,10 +153,13 @@ void xmrig::Api::exec(IApiRequest &request)
auto &allocator = request.doc().GetAllocator();
request.accept();
request.reply().AddMember("id", StringRef(m_id), allocator);
request.reply().AddMember("worker_id", StringRef(m_workerId), allocator);
request.reply().AddMember("uptime", (Chrono::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator);
request.reply().AddMember("restricted", request.isRestricted(), allocator);
auto &reply = request.reply();
reply.AddMember("id", StringRef(m_id), allocator);
reply.AddMember("worker_id", StringRef(m_workerId), allocator);
reply.AddMember("uptime", (Chrono::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator);
reply.AddMember("restricted", request.isRestricted(), allocator);
reply.AddMember("resources", getResources(request.doc()), allocator);
Value features(kArrayType);
# ifdef XMRIG_FEATURE_API
@@ -144,7 +183,7 @@ void xmrig::Api::exec(IApiRequest &request)
# ifdef XMRIG_FEATURE_OPENCL
features.PushBack("opencl", allocator);
# endif
request.reply().AddMember("features", features, allocator);
reply.AddMember("features", features, allocator);
}
for (IApiListener *listener : m_listeners) {
@@ -179,13 +218,13 @@ void xmrig::Api::genId(const String &id)
if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) {
uint8_t hash[200];
const size_t addrSize = sizeof(interfaces[i].phys_addr);
const size_t inSize = strlen(APP_KIND) + addrSize + sizeof(uint16_t);
const uint16_t port = static_cast<uint16_t>(m_base->config()->http().port());
const size_t inSize = (sizeof(APP_KIND) - 1) + addrSize + sizeof(uint16_t);
const auto port = static_cast<uint16_t>(m_base->config()->http().port());
uint8_t *input = new uint8_t[inSize]();
auto*input = new uint8_t[inSize]();
memcpy(input, &port, sizeof(uint16_t));
memcpy(input + sizeof(uint16_t), interfaces[i].phys_addr, addrSize);
memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, strlen(APP_KIND));
memcpy(input + sizeof(uint16_t) + addrSize, APP_KIND, (sizeof(APP_KIND) - 1));
keccak(input, inSize, hash);
Buffer::toHex(hash, 8, m_id);

View File

@@ -70,10 +70,10 @@ private:
void genWorkerId(const String &id);
Base *m_base;
char m_id[32];
char m_workerId[128];
char m_id[32]{};
char m_workerId[128]{};
const uint64_t m_timestamp;
Httpd *m_httpd;
Httpd *m_httpd = nullptr;
std::vector<IApiListener *> m_listeners;
};

View File

@@ -23,9 +23,9 @@
*/
#include "base/api/Httpd.h"
#include "3rdparty/http-parser/http_parser.h"
#include "base/api/Api.h"
#include "base/api/Httpd.h"
#include "base/io/log/Log.h"
#include "base/net/http/HttpApiResponse.h"
#include "base/net/http/HttpData.h"
@@ -58,9 +58,7 @@ xmrig::Httpd::Httpd(Base *base) :
}
xmrig::Httpd::~Httpd()
{
}
xmrig::Httpd::~Httpd() = default;
bool xmrig::Httpd::start()

View File

@@ -26,11 +26,12 @@
#define XMRIG_HTTPD_H
#include <stdint.h>
#include <cstdint>
#include "base/kernel/interfaces/IBaseListener.h"
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/tools/Object.h"
namespace xmrig {
@@ -44,6 +45,8 @@ class TcpServer;
class Httpd : public IBaseListener, public IHttpListener
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Httpd)
Httpd(Base *base);
~Httpd() override;

View File

@@ -33,6 +33,4 @@ xmrig::ApiRequest::ApiRequest(Source source, bool restricted) :
}
xmrig::ApiRequest::~ApiRequest()
{
}
xmrig::ApiRequest::~ApiRequest() = default;

View File

@@ -29,6 +29,7 @@
#include "base/api/interfaces/IApiRequest.h"
#include "base/tools/String.h"
#include "base/tools/Object.h"
namespace xmrig {
@@ -37,6 +38,8 @@ namespace xmrig {
class ApiRequest : public IApiRequest
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(ApiRequest)
ApiRequest(Source source, bool restricted);
~ApiRequest() override;
@@ -63,8 +66,8 @@ protected:
String m_rpcMethod;
private:
bool m_restricted;
Source m_source;
const bool m_restricted;
const Source m_source;
};

View File

@@ -41,6 +41,7 @@ set(HEADERS_BASE
src/base/net/stratum/strategies/FailoverStrategy.h
src/base/net/stratum/strategies/SinglePoolStrategy.h
src/base/net/stratum/SubmitResult.h
src/base/net/stratum/Url.h
src/base/net/tools/RecvBuf.h
src/base/net/tools/Storage.h
src/base/tools/Arguments.h
@@ -78,6 +79,7 @@ set(SOURCES_BASE
src/base/net/stratum/Pools.cpp
src/base/net/stratum/strategies/FailoverStrategy.cpp
src/base/net/stratum/strategies/SinglePoolStrategy.cpp
src/base/net/stratum/Url.cpp
src/base/tools/Arguments.cpp
src/base/tools/Buffer.cpp
src/base/tools/String.cpp
@@ -137,6 +139,7 @@ if (WITH_HTTP)
src/base/net/http/HttpResponse.h
src/base/net/http/HttpServer.h
src/base/net/stratum/DaemonClient.h
src/base/net/stratum/SelfSelectClient.h
src/base/net/tools/TcpServer.h
)
@@ -152,6 +155,7 @@ if (WITH_HTTP)
src/base/net/http/HttpResponse.cpp
src/base/net/http/HttpServer.cpp
src/base/net/stratum/DaemonClient.cpp
src/base/net/stratum/SelfSelectClient.cpp
src/base/net/tools/TcpServer.cpp
)

View File

@@ -82,6 +82,7 @@ private:
#define WHITE_S CSI "0;37m" // another name for LT.GRAY
#define WHITE_BOLD_S CSI "1;37m" // actually white
#define GREEN_BG_BOLD_S CSI "42;1m"
#define BLUE_BG_S CSI "44m"
#define BLUE_BG_BOLD_S CSI "44;1m"
#define MAGENTA_BG_S CSI "45m"
@@ -107,6 +108,7 @@ private:
#define WHITE(x) WHITE_S x CLEAR
#define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR
#define GREEN_BG_BOLD(x) GREEN_BG_BOLD_S x CLEAR
#define BLUE_BG(x) BLUE_BG_S x CLEAR
#define BLUE_BG_BOLD(x) BLUE_BG_BOLD_S x CLEAR
#define MAGENTA_BG(x) MAGENTA_BG_S x CLEAR

View File

@@ -49,6 +49,8 @@ xmrig::ConsoleLog::ConsoleLog()
uv_tty_set_mode(m_tty, UV_TTY_MODE_NORMAL);
# ifdef WIN32
m_stream = reinterpret_cast<uv_stream_t*>(m_tty);
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle != INVALID_HANDLE_VALUE) {
DWORD mode = 0;
@@ -67,15 +69,27 @@ xmrig::ConsoleLog::~ConsoleLog()
}
void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t, bool colors)
void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t size, bool colors)
{
if (!m_tty || Log::colors != colors) {
return;
}
# ifdef _WIN32
uv_buf_t buf = uv_buf_init(const_cast<char *>(line), static_cast<unsigned int>(size));
if (!isWritable()) {
fputs(line, stdout);
fflush(stdout);
}
else {
uv_try_write(m_stream, &buf, 1);
}
# else
fputs(line, stdout);
fflush(stdout);
# endif
}
bool xmrig::ConsoleLog::isSupported() const
@@ -83,3 +97,15 @@ bool xmrig::ConsoleLog::isSupported() const
const uv_handle_type type = uv_guess_handle(1);
return type == UV_TTY || type == UV_NAMED_PIPE;
}
#ifdef WIN32
bool xmrig::ConsoleLog::isWritable() const
{
if (!m_stream || uv_is_writable(m_stream) != 1) {
return false;
}
return isSupported();
}
#endif

View File

@@ -53,6 +53,12 @@ private:
bool isSupported() const;
uv_tty_t *m_tty = nullptr;
# ifdef _WIN32
bool isWritable() const;
uv_stream_t *m_stream = nullptr;
# endif
};

View File

@@ -63,11 +63,6 @@
#include "version.h"
xmrig::BaseConfig::BaseConfig()
{
}
void xmrig::BaseConfig::printVersions()
{
char buf[256] = { 0 };

View File

@@ -31,9 +31,6 @@
#include "base/net/stratum/Pools.h"
struct option;
namespace xmrig {
@@ -43,7 +40,7 @@ class IJsonReader;
class BaseConfig : public IConfig
{
public:
BaseConfig();
BaseConfig() = default;
inline bool isAutoSave() const { return m_autoSave; }
inline bool isBackground() const { return m_background; }

View File

@@ -183,6 +183,9 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
case IConfig::FingerprintKey: /* --tls-fingerprint */
return add(doc, kPools, "tls-fingerprint", arg);
case IConfig::SelfSelectKey: /* --self-select */
return add(doc, kPools, "self-select", arg);
case IConfig::LogFileKey: /* --log-file */
return set(doc, "log-file", arg);

View File

@@ -26,7 +26,10 @@
#define XMRIG_ICLIENT_H
#include <stdint.h>
#include "rapidjson/fwd.h"
#include <functional>
namespace xmrig {
@@ -51,6 +54,8 @@ public:
EXT_MAX
};
using Callback = std::function<void(const rapidjson::Value &result, bool success, uint64_t elapsed)>;
virtual ~IClient() = default;
virtual bool disconnect() = 0;
@@ -64,6 +69,9 @@ public:
virtual const Pool &pool() const = 0;
virtual const String &ip() const = 0;
virtual int id() const = 0;
virtual int64_t send(const rapidjson::Value &obj, Callback callback) = 0;
virtual int64_t send(const rapidjson::Value &obj) = 0;
virtual int64_t sequence() const = 0;
virtual int64_t submit(const JobResult &result) = 0;
virtual void connect() = 0;
virtual void connect(const Pool &pool) = 0;
@@ -75,7 +83,6 @@ public:
virtual void setRetries(int retries) = 0;
virtual void setRetryPause(uint64_t ms) = 0;
virtual void tick(uint64_t now) = 0;
};

View File

@@ -26,7 +26,7 @@
#define XMRIG_ICLIENTLISTENER_H
#include <stdint.h>
#include <cstdint>
#include "rapidjson/fwd.h"

View File

@@ -72,6 +72,7 @@ public:
ProxyDonateKey = 1017,
DaemonKey = 1018,
DaemonPollKey = 1019,
SelfSelectKey = 1028,
// xmrig common
CPUPriorityKey = 1021,
@@ -88,6 +89,7 @@ public:
AssemblyKey = 1015,
RandomXInitKey = 1022,
RandomXNumaKey = 1023,
RandomXModeKey = 1029,
CPUMaxThreadsKey = 1026,
MemoryPoolKey = 1027,
@@ -124,6 +126,7 @@ public:
TlsProtocolsKey = 1114,
AlgoExtKey = 1115,
ProxyPasswordKey = 1116,
LoginFileKey = 'L',
// xmrig nvidia
CudaMaxThreadsKey = 1200,
@@ -133,6 +136,10 @@ public:
CudaLaunchKey = 1204,
CudaAffinityKey = 1205,
CudaMaxUsageKey = 1206,
CudaKey = 1207,
CudaLoaderKey = 1208,
NvmlKey = 1209,
HealthPrintTimeKey = 1210,
};
virtual ~IConfig() = default;

View File

@@ -26,7 +26,7 @@
#define XMRIG_ISTRATEGY_H
#include <stdint.h>
#include <cstdint>
namespace xmrig {

View File

@@ -23,9 +23,9 @@
*/
#include "base/net/http/Http.h"
#include "3rdparty/rapidjson/document.h"
#include "base/io/json/Json.h"
#include "base/net/http/Http.h"
namespace xmrig {
@@ -41,10 +41,7 @@ static const char *kToken = "access-token";
xmrig::Http::Http() :
m_enabled(false),
m_restricted(true),
m_host(kLocalhost),
m_port(0)
m_host(kLocalhost)
{
}

View File

@@ -38,7 +38,7 @@ class Http
public:
Http();
inline bool isAuthRequired() const { return m_restricted == false || !m_token.isNull(); }
inline bool isAuthRequired() const { return !m_restricted || !m_token.isNull(); }
inline bool isEnabled() const { return m_enabled; }
inline bool isRestricted() const { return m_restricted; }
inline const String &host() const { return m_host; }
@@ -58,11 +58,11 @@ public:
void setPort(int port);
private:
bool m_enabled;
bool m_restricted;
bool m_enabled = false;
bool m_restricted = true;
String m_host;
String m_token;
uint16_t m_port;
uint16_t m_port = 0;
};

View File

@@ -66,7 +66,7 @@ public:
inline static void onWrite(uv_write_t *req, int) { delete reinterpret_cast<ClientWriteBaton *>(req->data); }
uv_buf_t bufs[2];
uv_buf_t bufs[2]{};
private:
std::string m_body;
@@ -78,9 +78,7 @@ private:
xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) :
HttpContext(HTTP_RESPONSE, listener),
m_quiet(false),
m_port(0)
HttpContext(HTTP_RESPONSE, listener)
{
this->method = method;
this->url = url;
@@ -127,7 +125,7 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status)
sockaddr *addr = dns.get().addr(m_port);
uv_connect_t *req = new uv_connect_t;
auto req = new uv_connect_t;
req->data = this;
uv_tcp_connect(req, m_tcp, addr, onConnect);
@@ -140,7 +138,7 @@ void xmrig::HttpClient::handshake()
headers.insert({ "Connection", "close" });
headers.insert({ "User-Agent", Platform::userAgent() });
if (body.size()) {
if (!body.empty()) {
headers.insert({ "Content-Length", std::to_string(body.size()) });
}
@@ -169,14 +167,14 @@ void xmrig::HttpClient::read(const char *data, size_t size)
void xmrig::HttpClient::write(const std::string &header)
{
ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body));
auto baton = new ClientWriteBaton(header, std::move(body));
uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite);
}
void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
{
HttpClient *client = static_cast<HttpClient *>(req->data);
auto client = static_cast<HttpClient *>(req->data);
if (!client) {
delete req;
return;
@@ -205,7 +203,7 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status)
},
[](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf)
{
HttpClient *client = static_cast<HttpClient*>(tcp->data);
auto client = static_cast<HttpClient*>(tcp->data);
if (nread >= 0) {
client->read(buf->base, static_cast<size_t>(nread));

View File

@@ -30,6 +30,7 @@
#include "base/net/http/HttpContext.h"
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/tools/Object.h"
namespace xmrig {
@@ -41,6 +42,8 @@ class String;
class HttpClient : public HttpContext, public IDnsListener
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpClient);
HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0);
~HttpClient() override;
@@ -57,13 +60,13 @@ protected:
virtual void read(const char *data, size_t size);
virtual void write(const std::string &header);
bool m_quiet;
bool m_quiet = false;
private:
static void onConnect(uv_connect_t *req, int status);
Dns *m_dns;
uint16_t m_port;
uint16_t m_port = 0;
};

View File

@@ -24,27 +24,30 @@
*/
#include "base/net/http/HttpContext.h"
#include "3rdparty/http-parser/http_parser.h"
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/tools/Chrono.h"
#include <algorithm>
#include <uv.h>
#include "3rdparty/http-parser/http_parser.h"
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/net/http/HttpContext.h"
namespace xmrig {
static http_parser_settings http_settings;
static std::map<uint64_t, HttpContext *> storage;
static uint64_t SEQUENCE = 0;
} // namespace xmrig
xmrig::HttpContext::HttpContext(int parser_type, IHttpListener *listener) :
HttpData(SEQUENCE++),
m_wasHeaderValue(false),
m_timestamp(Chrono::steadyMSecs()),
m_listener(listener)
{
storage[id()] = this;
@@ -96,6 +99,12 @@ std::string xmrig::HttpContext::ip() const
}
uint64_t xmrig::HttpContext::elapsed() const
{
return Chrono::steadyMSecs() - m_timestamp;
}
void xmrig::HttpContext::close(int status)
{
if (status < 0 && m_listener) {
@@ -136,7 +145,7 @@ void xmrig::HttpContext::closeAll()
int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_t length)
{
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
auto ctx = static_cast<HttpContext*>(parser->data);
if (ctx->m_wasHeaderValue) {
if (!ctx->m_lastHeaderField.empty()) {
@@ -155,7 +164,7 @@ int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_
int xmrig::HttpContext::onHeaderValue(http_parser *parser, const char *at, size_t length)
{
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
auto ctx = static_cast<HttpContext*>(parser->data);
if (!ctx->m_wasHeaderValue) {
ctx->m_lastHeaderValue = std::string(at, length);
@@ -185,7 +194,7 @@ void xmrig::HttpContext::attach(http_parser_settings *settings)
settings->on_header_value = onHeaderValue;
settings->on_headers_complete = [](http_parser* parser) -> int {
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
auto ctx = static_cast<HttpContext*>(parser->data);
ctx->status = parser->status_code;
if (parser->type == HTTP_REQUEST) {
@@ -208,7 +217,7 @@ void xmrig::HttpContext::attach(http_parser_settings *settings)
settings->on_message_complete = [](http_parser *parser) -> int
{
HttpContext *ctx = static_cast<HttpContext*>(parser->data);
auto ctx = static_cast<HttpContext*>(parser->data);
ctx->m_listener->onHttpData(*ctx);
ctx->m_listener = nullptr;

View File

@@ -28,15 +28,16 @@
#define XMRIG_HTTPCONTEXT_H
typedef struct http_parser http_parser;
typedef struct http_parser_settings http_parser_settings;
typedef struct uv_connect_s uv_connect_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
using http_parser = struct http_parser;
using http_parser_settings = struct http_parser_settings;
using uv_connect_t = struct uv_connect_s;
using uv_handle_t = struct uv_handle_s;
using uv_stream_t = struct uv_stream_s;
using uv_tcp_t = struct uv_tcp_s;
#include "base/net/http/HttpData.h"
#include "base/tools/Object.h"
namespace xmrig {
@@ -48,6 +49,8 @@ class IHttpListener;
class HttpContext : public HttpData
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpContext)
HttpContext(int parser_type, IHttpListener *listener);
virtual ~HttpContext();
@@ -56,6 +59,7 @@ public:
size_t parse(const char *data, size_t size);
std::string ip() const;
uint64_t elapsed() const;
void close(int status = 0);
static HttpContext *get(uint64_t id);
@@ -71,7 +75,8 @@ private:
void setHeader();
bool m_wasHeaderValue;
bool m_wasHeaderValue = false;
const uint64_t m_timestamp;
http_parser *m_parser;
IHttpListener *m_listener;
std::string m_lastHeaderField;

View File

@@ -38,12 +38,12 @@ namespace xmrig {
class HttpData
{
public:
inline HttpData(uint64_t id) : method(0), status(0), m_id(id) {}
inline HttpData(uint64_t id) : m_id(id) {}
inline uint64_t id() const { return m_id; }
int method;
int status;
int method = 0;
int status = 0;
std::map<const std::string, const std::string> headers;
std::string body;
std::string url;

Some files were not shown because too many files have changed in this diff Show More