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

Compare commits

..

134 Commits

Author SHA1 Message Date
XMRig
36ed0b4309 v6.3.4 2020-09-23 06:00:07 +07:00
XMRig
cb0bba7e10 Merge branch 'dev' 2020-09-23 05:59:35 +07:00
xmrig
51a72afb0e Update CHANGELOG.md 2020-09-23 05:29:29 +07:00
xmrig
b1b0a3ba95 Merge pull request #1843 from SChernykh/dev
RandomX improved performance of GCC compiled binaries
2020-09-23 04:44:47 +07:00
SChernykh
9768bf65d1 RandomX improved performance of GCC compiled binaries
JIT compilator was slower compared to MSVC compiled binary. Up to +0.1% speedup on rx/wow in Linux.
2020-09-22 13:48:11 +02:00
xmrig
1584cca6d1 Merge pull request #1842 from SChernykh/dev
RandomX: AES improvements
2020-09-22 03:13:23 +07:00
SChernykh
891a46382e RandomX: AES improvements
- A bit faster hardware AES code when compiled with MSVC
- More reliable software AES benchmark
2020-09-21 17:51:08 +02:00
xmrig
db920e8006 Merge pull request #1841 from SChernykh/dev
Fixed Cryptonight OpenCL for AMD 20.7.2 drivers
2020-09-20 04:14:49 +07:00
SChernykh
768a4581e0 Fixed Cryptonight OpenCL for AMD 20.7.2 drivers
Vega 64 + Windows 10 + AMD 20.7.2 drivers were broken on Cryptonight algorithms.
2020-09-19 23:12:05 +02:00
xmrig
866245b525 Merge pull request #1840 from SChernykh/dev
RandomX refactoring, moved more stuff to compile time
2020-09-19 02:01:06 +07:00
SChernykh
c7476e076b RandomX refactoring, moved more stuff to compile time
Small x86 JIT compiler speedup.
2020-09-18 20:51:25 +02:00
xmrig
d11a313d88 Merge pull request #1835 from SChernykh/dev
RandomX: returned old soft AES impl and auto-select between the two
2020-09-16 01:54:40 +07:00
SChernykh
8d1168385a RandomX: returned old soft AES impl and auto-select between the two 2020-09-15 20:48:27 +02:00
xmrig
852fe14604 Merge pull request #1831 from cohcho/nonce_iteration_without_tests
reserve at most 1 bit for wrapping detection
2020-09-14 02:12:49 +07:00
cohcho
30be1cd102 reserve at most 1 bit for wrapping detection 2020-09-13 18:42:16 +00:00
xmrig
fa0bb0e1bf Merge pull request #1830 from SChernykh/dev
RandomX: added performance profiler (for developers)
2020-09-13 04:38:03 +07:00
SChernykh
a05393727c RandomX: added performance profiler (for developers)
Also optimized Blake2b SSE4.1 code size to avoid code cache pollution.
2020-09-12 23:07:52 +02:00
xmrig
adf833b60a Merge pull request #1827 from cohcho/nonce_iteration_without_tests
nonce iteration optimization
2020-09-10 19:33:23 +07:00
xmrig
23daceb4dc Merge pull request #1828 from SChernykh/dev
RandomX: added SSE4.1-optimized Blake2b
2020-09-10 19:31:51 +07:00
SChernykh
4a9db89527 RandomX: added SSE4.1-optimized Blake2b
+0.15% on `rx/0`
+0.3% on `rx/wow`
2020-09-10 14:28:40 +02:00
cohcho
060c1af4c4 fix nonce mask 2020-09-09 19:39:52 +00:00
cohcho
b826985d05 nonce iteration optimization
efficient and correct nonce iteration without duplicates
2020-09-09 10:03:37 +00:00
xmrig
0f09883429 Merge pull request #1823 from SChernykh/dev
RandomX: added parameter for scratchpad prefetch mode
2020-09-04 21:31:18 +07:00
SChernykh
a84b45b1bb RandomX: added parameter for scratchpad prefetch mode
`scratchpad_prefetch_mode` can have 4 values:
0: off
1: use `prefetcht0` instruction (default, same as previous XMRig versions)
2: use `prefetchnta` instruction (faster on Coffee Lake and a few other CPUs)
3: use `mov` instruction
2020-09-04 16:16:07 +02:00
XMRig
a5b6383f7b v6.3.4 2020-08-28 23:50:16 +07:00
XMRig
24f8f76714 Merge branch 'master' into dev 2020-08-28 23:49:47 +07:00
XMRig
ba336122c0 v6.3.3 2020-08-28 21:39:26 +07:00
XMRig
591744174c Merge branch 'dev' 2020-08-28 21:38:55 +07:00
xmrig
fc85017948 Update CHANGELOG.md 2020-08-28 21:25:26 +07:00
xmrig
24f541a0dd Update README.md 2020-08-26 23:09:05 +07:00
XMRig
f552577e71 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2020-08-26 16:11:48 +07:00
XMRig
a06ec06e8b Fix colors on macOS. 2020-08-26 16:11:29 +07:00
xmrig
96833d4790 Merge pull request #1817 from SChernykh/dev
Fixed self-select login sequence
2020-08-25 21:23:19 +07:00
SChernykh
5611ae9a30 Fixed self-select login sequence
In self-select mode, we only have pool wallet right after login.
2020-08-25 16:17:48 +02:00
XMRig
72c8404d18 Fix compile warnings. 2020-08-24 10:04:46 +07:00
XMRig
bc128d11d9 Add strip for clang. 2020-08-23 23:48:05 +07:00
XMRig
ff13675d31 Improved CUDA loader error reporting and fixed plugin load on Linux. 2020-08-23 21:30:12 +07:00
XMRig
4b682b6633 Better scripts/build.*.sh compatibility. 2020-08-23 15:46:56 +07:00
XMRig
879e160ba3 Fix compile warning. 2020-08-23 14:22:08 +07:00
XMRig
9a6b8594f3 Removed bzip2 dependency for hwloc build. 2020-08-21 09:14:22 +07:00
XMRig
a354e9d217 Fixed tag in OclLib. 2020-08-21 08:21:51 +07:00
XMRig
950b5fa75e Disable GPU backends with static build on Linux. 2020-08-20 15:02:31 +07:00
XMRig
9f66d59c0a Merge branch 'master' of https://github.com/alxnegrila/xmrig into dev 2020-08-20 14:40:53 +07:00
XMRig
9d99fef52e v6.3.3-dev 2020-08-20 13:54:52 +07:00
XMRig
3b22f1704f Merge branch 'master' into dev 2020-08-20 13:54:24 +07:00
xmrig
c89ad6b36d Update README.md 2020-08-20 13:44:20 +07:00
xmrig
45300f1ff5 Update README.md 2020-08-20 13:43:20 +07:00
XMRig
847d08cdbc v6.3.2 2020-08-20 12:54:22 +07:00
XMRig
81af1e964d Merge branch 'dev' 2020-08-20 12:53:45 +07:00
xmrig
3662e45435 Update CHANGELOG.md 2020-08-20 12:49:31 +07:00
XMRig
f06e30e343 Merge branch 'battery-macos' of https://github.com/jtgrassie/xmrig into dev 2020-08-20 12:46:09 +07:00
xmrig
34d4aa4012 Update CHANGELOG.md 2020-08-19 07:42:10 +07:00
XMRig
3e4bf8cd6c Fix compile warning 2020-08-17 06:08:14 +07:00
XMRig
206b675892 Always use all available threads on ARM. 2020-08-16 17:36:38 +07:00
XMRig
00b4ae9c36 Fixed compile warning and updated build.uv.sh. 2020-08-16 16:03:27 +07:00
XMRig
8d5ea745bb Merge branch 'dev' of github.com:xmrig/xmrig into dev 2020-08-16 15:47:57 +07:00
XMRig
cac48cdd27 Added ARM CPU name detection based on lscpu code. 2020-08-16 15:47:29 +07:00
xmrig
c20010ed54 Merge pull request #1807 from SChernykh/dev
RandomX JIT: optimized address mask calculation
2020-08-12 21:48:20 +07:00
SChernykh
5926dee354 RandomX JIT: optimized address mask calculation 2020-08-12 16:45:16 +02:00
Jethro Grassie
b78b0b5c6b fix macos battery detection 2020-08-11 18:04:56 -04:00
XMRig
43afa437e4 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2020-08-07 21:55:06 +07:00
XMRig
050568a4ab Fixed rare protocol error in HTTP client. 2020-08-07 21:54:22 +07:00
xmrig
8bf40cea36 Update CHANGELOG.md 2020-08-01 13:02:11 +07:00
XMRig
ae3ff0f570 Fixed RandomX cache initialization if 1GB pages fails to allocate on a first NUMA node. 2020-08-01 12:30:02 +07:00
xmrig
0addf91a70 Merge pull request #1794 from SChernykh/dev
More robust 1 GB pages handling
2020-07-31 20:45:27 +07:00
SChernykh
abb78302b8 Try to allocate scratchpad from dataset's 1 GB huge pages, if normal huge pages are not available 2020-07-31 13:37:22 +02:00
XMRig
e5579d8635 v6.3.2-dev 2020-07-31 16:50:23 +07:00
XMRig
3986c43fa5 Merge branch 'master' into dev 2020-07-31 16:48:54 +07:00
SChernykh
838cc08680 Force 2 MB pages size in allocateLargePagesMemory() on Linux 2020-07-31 09:55:49 +02:00
XMRig
a0fe49f946 v6.3.1 2020-07-31 13:20:56 +07:00
XMRig
70dbe8562c Merge branch 'dev' 2020-07-31 13:20:11 +07:00
xmrig
41fcd1e49a Update CHANGELOG.md 2020-07-31 13:16:58 +07:00
xmrig
90195caa1d Merge pull request #1792 from SChernykh/dev
Fixed crash in RelWithDbgInfo MSVC build
2020-07-29 15:42:09 +07:00
SChernykh
cdb6287d89 Fixed crash in RelWithDbgInfo MSVC build
Same problem as in https://github.com/xmrig/xmrig/pull/1784 , fixed with compiler flags this time.
2020-07-29 10:39:58 +02:00
XMRig
32e9b7e34a Added command line option --pause-on-battery and renamed config option. 2020-07-23 15:45:01 +07:00
XMRig
6484bbb716 Add tags 2020-07-23 10:26:56 +07:00
xmrig
e59806d6ae Merge pull request #1786 from SChernykh/dev
Added mining on battery setting
2020-07-23 09:20:06 +07:00
SChernykh
299b180b28 Added mining on battery setting 2020-07-22 20:21:42 +02:00
XMRig
1acd88ed39 Cleanup 2020-07-22 21:27:40 +07:00
XMRig
109c088e8a Cleanup usage output. 2020-07-22 19:58:08 +07:00
xmrig
bb18239642 Update README.md 2020-07-22 09:14:25 +07:00
xmrig
ccded7cc0a Merge pull request #1784 from SChernykh/dev
Fixed RandomX initialization for VS debug builds
2020-07-21 19:04:02 +07:00
SChernykh
5bc89fdc8b Fixed RandomX initialization for VS debug builds 2020-07-21 10:10:07 +02:00
XMRig
70c7f33a20 Added command line options --cache-qos (--randomx-cache-qos) and --argon2-impl (--cpu-argon2-impl). 2020-07-20 09:17:59 +07:00
XMRig
1ec185a3a0 v6.3.1-dev 2020-07-17 03:13:02 +07:00
XMRig
6aa4eeefbb Merge branch 'master' into dev 2020-07-17 03:12:36 +07:00
XMRig
10ea567084 v6.3.0 2020-07-17 00:17:55 +07:00
XMRig
028d6503aa Merge branch 'dev' 2020-07-17 00:17:24 +07:00
XMRig
51346c2b2b v6.3.0-dev 2020-07-17 00:04:31 +07:00
XMRig
ca535c7813 Sync changes with the proxy. 2020-07-16 23:29:21 +07:00
xmrig
ba80e27349 Merge pull request #1780 from SChernykh/dev
Cryptonight OpenCL: fix for long input data
2020-07-16 19:56:20 +07:00
SChernykh
bd8cf54a0b Cryptonight OpenCL: fix for long input data 2020-07-16 10:39:32 +02:00
XMRig
e0eed7d5d6 Fixed build without MSR support. 2020-07-16 05:15:35 +07:00
XMRig
8dff08f15f Merge branch 'haven-protocol-org-master' into dev 2020-07-15 23:33:53 +07:00
XMRig
47d68b068b Merge branch 'master' of https://github.com/haven-protocol-org/xmrig into haven-protocol-org-master 2020-07-15 23:33:17 +07:00
Neil Coggins
a648a8b9be Increased max blob size to support Haven offshore capability 2020-07-14 11:52:43 +01:00
xmrig
7eefccc6bc Merge pull request #1776 from SChernykh/dev
Removed cache QoS warning at exit on unsupported CPUs
2020-07-14 01:45:18 +07:00
SChernykh
1bf159d1e8 Removed cache QoS warning at exit on unsupported CPUs 2020-07-13 20:43:49 +02:00
xmrig
bf46cb8684 Merge pull request #1774 from SChernykh/dev
RandomX: added cache QoS support
2020-07-14 01:35:46 +07:00
SChernykh
72c385c870 Cache QoS: fix for seting MSR 2020-07-13 20:30:44 +02:00
SChernykh
c83429c55c RandomX: added cache QoS support
False by default. If set to true, all non-mining CPU cores will not have access to L3 cache.
2020-07-13 17:23:18 +02:00
xmrig
e5a2689052 Merge pull request #1771 from jserv/update-sse2neon
Adopt new SSE2NEON and reduce ARM-specific changes
2020-07-11 02:32:56 +07:00
Jim Huang
b665d2d865 Adopt new SSE2NEON and reduce ARM-specific changes
This patch updated SSE2NEON [1], which contains more functions
provided by Intel intrinsics, only implemented with NEON-based
counterparts to produce the exact semantics of the intrinsics.
Consequently, ARM-specific changes against CryptoNight_arm can
be reduced as well.

[1] https://github.com/DLTcollab/sse2neon/
2020-07-11 01:55:11 +08:00
XMRig
e06a76ef1c v6.2.4-dev 2020-07-10 03:12:00 +07:00
XMRig
f523fddbfd Merge branch 'master' into dev 2020-07-10 02:49:33 +07:00
XMRig
30165ce4be v6.2.3 2020-07-09 22:24:35 +07:00
XMRig
83a10cce8c Merge branch 'dev' 2020-07-09 22:24:01 +07:00
xmrig
71cc486553 Update CHANGELOG.md 2020-07-09 22:23:16 +07:00
xmrig
2eaf8edf0e Merge pull request #1766 from SChernykh/dev
RandomX: tweaked Ryzen code
2020-07-05 21:16:21 +07:00
SChernykh
3d740e81a2 RandomX: tweaked Ryzen code
Very small speedup
2020-07-05 16:06:59 +02:00
xmrig
ef475d98da Update CHANGELOG.md 2020-07-04 19:11:29 +07:00
xmrig
5e92acab34 Merge pull request #1763 from SChernykh/dev
KawPow: fixed more duplicate share errors
2020-07-04 02:37:03 +07:00
SChernykh
935b8a1106 KawPow: fixed more duplicate share errors 2020-07-03 21:33:44 +02:00
xmrig
c371a7a2bb Update CHANGELOG.md 2020-07-04 00:29:50 +07:00
XMRig
4fe011b469 Fix tab/space inconsistency. 2020-07-03 21:36:06 +07:00
XMRig
bf32802a82 #1754 Fixed GPU health readings for pre Vega GPUs. 2020-07-03 21:14:21 +07:00
xmrig
ccfbba94f2 Merge pull request #1761 from SChernykh/dev
Fix typo
2020-07-02 19:41:19 +07:00
SChernykh
70d7fe9b59 Fix typo 2020-07-02 14:29:52 +02:00
xmrig
34a5c89ee2 Merge pull request #1760 from SChernykh/dev
KawPow: fixed rare duplicate share errors
2020-07-02 19:23:28 +07:00
SChernykh
39ed25cf7b KawPow: fixed rare duplicate share errors 2020-07-02 11:36:31 +02:00
XMRig
26c2200af3 #1756 Added results and connection reports. 2020-07-01 23:10:37 +07:00
xmrig
aa5a7c3c13 Merge pull request #1759 from SChernykh/dev
Fixed DAG initialization on slower AMD GPUs
2020-06-30 21:59:32 +07:00
SChernykh
08ca51ec4c Fixed DAG initialization on slower AMD GPUs
Display driver could reset on GPUs with screen connected.
2020-06-30 16:53:56 +02:00
xmrig
bbd9945866 Merge pull request #1752 from SChernykh/dev
Print error message when MSR mod fails
2020-06-27 00:59:25 +07:00
SChernykh
59313d9cc3 Print error message when MSR mod fails
Make sure user knows that hashrate is worse than it could be.
2020-06-26 19:54:06 +02:00
xmrig
2da5d31a5d Merge pull request #1749 from SChernykh/dev
KawPow: optimized CPU share verification
2020-06-26 17:39:37 +07:00
SChernykh
5724d8beb6 KawPow: optimized CPU share verification
- 2 times faster CPU share verification (11 -> 5 ms)
- 1.5 times faster light cache initialization
2020-06-26 12:31:26 +02:00
XMRig
03e9797b92 Merge branch 'dev' of https://github.com/SChernykh/xmrig into dev 2020-06-23 19:12:34 +07:00
XMRig
74bd9460d7 v6.2.3-dev 2020-06-23 19:05:54 +07:00
XMRig
f033cb7f46 Merge branch 'master' into dev 2020-06-23 19:05:21 +07:00
SChernykh
38cf5b6324 Fixed AstroBWT OpenCL compilation on some systems 2020-06-23 13:55:43 +02:00
XMRig
16863763d3 #1742 Fixed crash when use HTTP API. 2020-06-23 16:17:06 +07:00
xmrig
aa1934d273 Update CHANGELOG.md 2020-06-23 12:55:48 +07:00
Alexandru Negrila
89e6998054 Fix OpenSSL static link when BUILD_STATIC=ON is provided 2020-04-09 09:09:21 +03:00
135 changed files with 11644 additions and 7398 deletions

View File

@@ -1,4 +1,58 @@
# v6.3.4
- [#1823](https://github.com/xmrig/xmrig/pull/1823) RandomX: added new option `scratchpad_prefetch_mode`.
- [#1827](https://github.com/xmrig/xmrig/pull/1827) [#1831](https://github.com/xmrig/xmrig/pull/1831) Improved nonce iteration performance.
- [#1828](https://github.com/xmrig/xmrig/pull/1828) RandomX: added SSE4.1-optimized Blake2b.
- [#1830](https://github.com/xmrig/xmrig/pull/1830) RandomX: added performance profiler (for developers).
- [#1835](https://github.com/xmrig/xmrig/pull/1835) RandomX: returned old soft AES implementation and added auto-select between the two.
- [#1840](https://github.com/xmrig/xmrig/pull/1840) RandomX: moved more stuff to compile time, small x86 JIT compiler speedup.
- [#1841](https://github.com/xmrig/xmrig/pull/1841) Fixed Cryptonight OpenCL for AMD 20.7.2 drivers.
- [#1842](https://github.com/xmrig/xmrig/pull/1842) RandomX: AES improvements, a bit faster hardware AES code when compiled with MSVC.
- [#1843](https://github.com/xmrig/xmrig/pull/1843) RandomX: improved performance of GCC compiled binaries.
# v6.3.3
- [#1817](https://github.com/xmrig/xmrig/pull/1817) Fixed self-select login sequence.
- Added brand new [build from source](https://xmrig.com/docs/miner/build) documentation.
- New binary downloads for macOS (`macos-x64`), FreeBSD (`freebsd-static-x64`), Linux (`linux-static-x64`), Ubuntu 18.04 (`bionic-x64`), Ubuntu 20.04 (`focal-x64`).
- Generic Linux download `xenial-x64` renamed to `linux-x64`.
- Builds without SSL/TLS support are no longer provided.
- Improved CUDA loader error reporting and fixed plugin load on Linux.
- Fixed build warnings with Clang compiler.
- Fixed colors on macOS.
# v6.3.2
- [#1794](https://github.com/xmrig/xmrig/pull/1794) More robust 1 GB pages handling.
- Don't allocate 1 GB per thread if 1 GB is the default huge page size.
- Try to allocate scratchpad from dataset's 1 GB huge pages, if normal huge pages are not available.
- Correctly initialize RandomX cache if 1 GB pages fail to allocate on a first NUMA node.
- [#1806](https://github.com/xmrig/xmrig/pull/1806) Fixed macOS battery detection.
- [#1809](https://github.com/xmrig/xmrig/issues/1809) Improved auto configuration on ARM CPUs.
- Added retrieving ARM CPU names, based on lscpu code and database.
# v6.3.1
- [#1786](https://github.com/xmrig/xmrig/pull/1786) Added `pause-on-battery` option, supported on Windows and Linux.
- Added command line options `--randomx-cache-qos` and `--argon2-impl`.
# v6.3.0
- [#1771](https://github.com/xmrig/xmrig/pull/1771) Adopted new SSE2NEON and reduced ARM-specific changes.
- [#1774](https://github.com/xmrig/xmrig/pull/1774) RandomX: Added new option `cache_qos` in `randomx` object for cache QoS support.
- [#1777](https://github.com/xmrig/xmrig/pull/1777) Added support for upcoming Haven offshore fork.
- [#1780](https://github.com/xmrig/xmrig/pull/1780) CryptoNight OpenCL: fix for long input data.
# v6.2.3
- [#1745](https://github.com/xmrig/xmrig/pull/1745) AstroBWT: fixed OpenCL compilation on some systems.
- [#1749](https://github.com/xmrig/xmrig/pull/1749) KawPow: optimized CPU share verification.
- [#1752](https://github.com/xmrig/xmrig/pull/1752) RandomX: added error message when MSR mod fails.
- [#1754](https://github.com/xmrig/xmrig/issues/1754) Fixed GPU health readings for pre Vega GPUs on Linux.
- [#1756](https://github.com/xmrig/xmrig/issues/1756) Added results and connection reports.
- [#1759](https://github.com/xmrig/xmrig/pull/1759) KawPow: fixed DAG initialization on slower AMD GPUs.
- [#1763](https://github.com/xmrig/xmrig/pull/1763) KawPow: fixed rare duplicate share errors.
- [#1766](https://github.com/xmrig/xmrig/pull/1766) RandomX: small speedup on Ryzen CPUs.
# v6.2.2
- [#1742](https://github.com/xmrig/xmrig/issues/1742) Fixed crash when use HTTP API.
# v6.2.1
- [#1726](https://github.com/xmrig/xmrig/issues/1726) Fixed detection of AVX2/AVX512.
- [#1728](https://github.com/xmrig/xmrig/issues/1728) Fixed, 32 bit Windows builds was crash on start.
- [#1729](https://github.com/xmrig/xmrig/pull/1729) Fixed KawPow crash on old CPUs.
- [#1730](https://github.com/xmrig/xmrig/pull/1730) Improved displaying information for compute errors on GPUs.

View File

@@ -23,6 +23,7 @@ option(WITH_NVML "Enable NVML (NVIDIA Management Library) support (on
option(WITH_ADL "Enable ADL (AMD Display Library) or sysfs support (only if OpenCL 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)
option(WITH_PROFILING "Enable profiling for developers" OFF)
option(BUILD_STATIC "Build static binary" OFF)
option(ARM_TARGET "Force use specific ARM target 8 or 7" 0)
@@ -143,6 +144,8 @@ elseif (XMRIG_OS_APPLE)
src/App_unix.cpp
src/crypto/common/VirtualMemory_unix.cpp
)
find_library(IOKIT_LIBRARY IOKit)
set(EXTRA_LIBS ${IOKIT_LIBRARY})
else()
list(APPEND SOURCES_OS
src/App_unix.cpp
@@ -196,10 +199,6 @@ include_directories(src)
include_directories(src/3rdparty)
include_directories(${UV_INCLUDE_DIR})
if (BUILD_STATIC)
set(CMAKE_EXE_LINKER_FLAGS " -static")
endif()
if (WITH_DEBUG_LOG)
add_definitions(/DAPP_DEBUG)
endif()
@@ -211,3 +210,7 @@ if (WIN32)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/bin/WinRing0/WinRing0x64.sys" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_BUILD_TYPE STREQUAL Release)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
endif()

121
README.md
View File

@@ -2,130 +2,35 @@
[![Github All Releases](https://img.shields.io/github/downloads/xmrig/xmrig/total.svg)](https://github.com/xmrig/xmrig/releases)
[![GitHub release](https://img.shields.io/github/release/xmrig/xmrig/all.svg)](https://github.com/xmrig/xmrig/releases)
[![GitHub Release Date](https://img.shields.io/github/release-date-pre/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/releases)
[![GitHub Release Date](https://img.shields.io/github/release-date/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/releases)
[![GitHub license](https://img.shields.io/github/license/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/blob/master/LICENSE)
[![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 High performance, open source, cross platform RandomX, KawPow, CryptoNight, AstroBWT and Argon2 CPU/GPU miner, with official support for Windows.
XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and AstroBWT unified CPU/GPU miner. Official binaries are available for Windows, Linux, macOS and FreeBSD.
## Mining backends
- **CPU** (x64/x86/ARM)
- **CPU** (x64/ARMv8)
- **OpenCL** for AMD GPUs.
- **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda).
<img src="doc/screenshot_v5_2_0.png" width="833" >
## Download
* Binary releases: https://github.com/xmrig/xmrig/releases
* Git tree: https://github.com/xmrig/xmrig.git
* Clone with `git clone https://github.com/xmrig/xmrig.git` :hammer: [Build instructions](https://github.com/xmrig/xmrig/wiki/Build).
* **[Binary releases](https://github.com/xmrig/xmrig/releases)**
* **[Build from source](https://xmrig.com/docs/miner/build)**
## 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.
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](https://xmrig.com/docs/miner/command-line-options) 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:
-o, --url=URL URL of mining server
-a, --algo=ALGO mining algorithm https://xmrig.com/docs/algorithms
--coin=COIN specify coin instead of algorithm
-u, --user=USERNAME username for mining server
-p, --pass=PASSWORD password for mining server
-O, --userpass=U:P username:password pair for mining server
-x, --proxy=HOST:PORT connect through a SOCKS5 proxy
-k, --keepalive send keepalive packet for prevent timeout (needs pool support)
--nicehash enable nicehash.com support
--rig-id=ID rig identifier for pool-side statistics (needs pool support)
--tls enable SSL/TLS support (needs pool support)
--tls-fingerprint=HEX pool TLS certificate fingerprint for strict certificate pinning
--daemon use daemon RPC instead of pool for solo mining
--daemon-poll-interval=N daemon poll interval in milliseconds (default: 1000)
-r, --retries=N number of times to retry before switch to backup server (default: 5)
-R, --retry-pause=N time to pause between retries (default: 5)
--user-agent set custom user-agent string for pool
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)
--donate-over-proxy=N control donate over xmrig-proxy feature
CPU backend:
--no-cpu disable CPU mining backend
-t, --threads=N number of CPU threads
-v, --av=N algorithm variation, 0 auto select
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)
--cpu-max-threads-hint=N maximum CPU threads count (in percentage) hint for autoconfig
--cpu-memory-pool=N number of 2 MB pages for persistent memory pool, -1 (auto), 0 (disable)
--cpu-no-yield prefer maximum hashrate rather than system response/stability
--no-huge-pages disable huge pages support
--asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer
--randomx-init=N thread count to initialize RandomX dataset
--randomx-no-numa disable NUMA support for RandomX
--randomx-mode=MODE RandomX mode: auto, fast, light
--randomx-1gb-pages use 1GB hugepages for dataset (Linux only)
--randomx-wrmsr=N write custom value (0-15) to Intel MSR register 0x1a4 or disable MSR mod (-1)
--randomx-no-rdmsr disable reverting initial MSR values on exit
--astrobwt-max-size=N skip hashes with large stage 2 size, default: 550, min: 400, max: 1200
--astrobwt-avx2 enable AVX2 optimizations for AstroBWT algorithm
API:
--api-worker-id=ID custom worker-id for API
--api-id=ID custom instance ID for API
--http-host=HOST bind host for HTTP API (default: 127.0.0.1)
--http-port=N bind port for HTTP API
--http-access-token=T access token for HTTP API
--http-no-restricted enable full remote access to HTTP API (only if access token set)
OpenCL backend:
--opencl enable OpenCL mining backend
--opencl-devices=N comma separated list of OpenCL devices to use
--opencl-platform=N OpenCL platform index or name
--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
TLS:
--tls-gen=HOSTNAME generate TLS certificate for specific hostname
--tls-cert=FILE load TLS certificate chain from a file in the PEM format
--tls-cert-key=FILE load TLS certificate private key from a file in the PEM format
--tls-dhparam=FILE load DH parameters for DHE ciphers from a file in the PEM format
--tls-protocols=N enable specified TLS protocols, example: "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3"
--tls-ciphers=S set list of available ciphers (TLSv1.2 and below)
--tls-ciphersuites=S set list of available TLSv1.3 ciphersuites
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
--verbose verbose output
Misc:
-c, --config=FILE load a JSON-format configuration file
-B, --background run the miner in the background
-V, --version output version information and exit
-h, --help display this help and exit
--dry-run test configuration and exit
--export-topology export hwloc topology to a XML file and exit
--title set custom console window title
--no-title disable setting console window title
```
* **[Wizard](https://xmrig.com/wizard)** helps you create initial configuration for the miner.
* **[Workers](http://workers.xmrig.info)** helps manage your miners via HTTP API.
## Donations
* Default donation 5% (5 minutes in 100 minutes) can be reduced to 1% via option `donate-level` or disabled in source code.
* Default donation 1% (1 minute in 100 minutes) can be increased via option `donate-level` or disabled in source code.
* XMR: `48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD`
* BTC: `1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT`
## Developers
* **[xmrig](https://github.com/xmrig)**
* **[sech1](https://github.com/SChernykh)**
## Contacts
* support@xmrig.com

View File

@@ -10,6 +10,11 @@ if (WITH_TLS)
set(OPENSSL_USE_STATIC_LIBS TRUE)
endif()
if (BUILD_STATIC)
set(OPENSSL_USE_STATIC_LIBS TRUE)
endif()
find_package(OpenSSL)
if (OPENSSL_FOUND)

View File

@@ -29,8 +29,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -flax-vector-conversions")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -msse4.1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -msse4.1")
add_definitions(/DHAVE_ROTR)
endif()
@@ -45,6 +45,10 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
endif()
if (BUILD_STATIC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
endif()
add_definitions(/D_GNU_SOURCE)
if (${CMAKE_VERSION} VERSION_LESS "3.1.0")
@@ -60,6 +64,9 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set(CMAKE_C_FLAGS_RELEASE "/MT /O2 /Oi /DNDEBUG /GL")
set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Oi /DNDEBUG /GL")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/Ob1 /GL")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/Ob1 /GL")
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
add_definitions(/D_CRT_NONSTDC_NO_WARNINGS)
add_definitions(/DNOMINMAX)
@@ -80,8 +87,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -msse4.1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -msse4.1")
check_symbol_exists("_rotr" "x86intrin.h" HAVE_ROTR)
if (HAVE_ROTR)
@@ -89,6 +96,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
endif()
endif()
if (BUILD_STATIC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
endif()
endif()
if (NOT WIN32)

View File

@@ -8,12 +8,12 @@ mkdir -p deps/lib
mkdir -p build && cd build
wget https://download.open-mpi.org/release/hwloc/v2.2/hwloc-${HWLOC_VERSION}.tar.bz2 -O hwloc-${HWLOC_VERSION}.tar.bz2
tar -xjf hwloc-${HWLOC_VERSION}.tar.bz2
wget https://download.open-mpi.org/release/hwloc/v2.2/hwloc-${HWLOC_VERSION}.tar.gz -O hwloc-${HWLOC_VERSION}.tar.gz
tar -xzf hwloc-${HWLOC_VERSION}.tar.gz
cd hwloc-${HWLOC_VERSION}
./configure --disable-shared --enable-static --disable-io --disable-libudev --disable-libxml2
make -j$(nproc)
cp -fr include/ ../../deps
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps
cp hwloc/.libs/libhwloc.a ../../deps/lib
cd ..

19
scripts/build.hwloc1.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash -e
HWLOC_VERSION="1.11.13"
mkdir -p deps
mkdir -p deps/include
mkdir -p deps/lib
mkdir -p build && cd build
wget https://download.open-mpi.org/release/hwloc/v1.11/hwloc-${HWLOC_VERSION}.tar.gz -O hwloc-${HWLOC_VERSION}.tar.gz
tar -xzf hwloc-${HWLOC_VERSION}.tar.gz
cd hwloc-${HWLOC_VERSION}
./configure --disable-shared --enable-static --disable-io --disable-libudev --disable-libxml2
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps
cp src/.libs/libhwloc.a ../../deps/lib
cd ..

View File

@@ -13,8 +13,8 @@ tar -xzf libressl-${LIBRESSL_VERSION}.tar.gz
cd libressl-${LIBRESSL_VERSION}
./configure --disable-shared
make -j$(nproc)
cp -fr include/ ../../deps
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps
cp crypto/.libs/libcrypto.a ../../deps/lib
cp ssl/.libs/libssl.a ../../deps/lib
cd ..

View File

@@ -13,8 +13,8 @@ tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
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
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps
cp libcrypto.a ../../deps/lib
cp libssl.a ../../deps/lib
cd ..

View File

@@ -1,6 +1,6 @@
#!/bin/bash -e
UV_VERSION="1.38.0"
UV_VERSION="1.38.1"
mkdir -p deps
mkdir -p deps/include
@@ -14,7 +14,7 @@ tar -xzf v${UV_VERSION}.tar.gz
cd libuv-${UV_VERSION}
sh autogen.sh
./configure --disable-shared
make -j$(nproc)
cp -fr include/ ../../deps
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
cp -fr include ../../deps
cp .libs/libuv.a ../../deps/lib
cd ..

View File

@@ -33,6 +33,18 @@
#include "data_sizes.h"
#include "base/crypto/sha3.h"
#if defined(_M_X64) || defined(__x86_64__) || defined(__SSE2__)
#ifdef __GNUC__
#include <x86intrin.h>
#else
#include <intrin.h>
#endif
#define kp_prefetch(x) _mm_prefetch((x), _MM_HINT_T0);
#else
#define kp_prefetch(x)
#endif
#define SHA3_256(a, b, c) sha3_HashBuffer(256, SHA3_FLAGS_KECCAK, b, c, a, 32)
#define SHA3_512(a, b, c) sha3_HashBuffer(512, SHA3_FLAGS_KECCAK, b, c, a, 64)
@@ -157,46 +169,53 @@ void ethash_calculate_dag_item_opt(
memcpy(ret, init, sizeof(node));
ret->words[0] ^= node_index;
SHA3_512(ret->bytes, ret->bytes, sizeof(node));
#if defined(_M_X64) && ENABLE_SSE
__m128i const fnv_prime = _mm_set1_epi32(FNV_PRIME);
__m128i xmm0 = ret->xmm[0];
__m128i xmm1 = ret->xmm[1];
__m128i xmm2 = ret->xmm[2];
__m128i xmm3 = ret->xmm[3];
#endif
for (uint32_t i = 0; i != num_parents; ++i) {
uint32_t parent_index = fast_mod(fnv_hash(node_index ^ i, ret->words[i % NODE_WORDS]), light->num_parent_nodes, light->reciprocal, light->increment, light->shift);
node const* parent = &cache_nodes[parent_index];
#if defined(_M_X64) && ENABLE_SSE
{
xmm0 = _mm_mullo_epi32(xmm0, fnv_prime);
xmm1 = _mm_mullo_epi32(xmm1, fnv_prime);
xmm2 = _mm_mullo_epi32(xmm2, fnv_prime);
xmm3 = _mm_mullo_epi32(xmm3, fnv_prime);
xmm0 = _mm_xor_si128(xmm0, parent->xmm[0]);
xmm1 = _mm_xor_si128(xmm1, parent->xmm[1]);
xmm2 = _mm_xor_si128(xmm2, parent->xmm[2]);
xmm3 = _mm_xor_si128(xmm3, parent->xmm[3]);
// have to write to ret as values are used to compute index
ret->xmm[0] = xmm0;
ret->xmm[1] = xmm1;
ret->xmm[2] = xmm2;
ret->xmm[3] = xmm3;
for (unsigned w = 0; w != NODE_WORDS; ++w) {
ret->words[w] = fnv_hash(ret->words[w], parent->words[w]);
}
#else
{
for (unsigned w = 0; w != NODE_WORDS; ++w) {
ret->words[w] = fnv_hash(ret->words[w], parent->words[w]);
}
}
#endif
}
SHA3_512(ret->bytes, ret->bytes, sizeof(node));
}
void ethash_calculate_dag_item4_opt(
node* ret,
uint32_t node_index,
uint32_t num_parents,
ethash_light_t const light
)
{
node const* cache_nodes = (node const*)light->cache;
for (size_t i = 0; i < 4; ++i) {
node const* init = &cache_nodes[fast_mod(node_index + i, light->num_parent_nodes, light->reciprocal, light->increment, light->shift)];
memcpy(ret + i, init, sizeof(node));
ret[i].words[0] ^= node_index + i;
SHA3_512(ret[i].bytes, ret[i].bytes, sizeof(node));
}
for (uint32_t i = 0; i != num_parents; ++i) {
node const* parent[4];
for (uint32_t j = 0; j < 4; ++j) {
const uint32_t parent_index = fast_mod(fnv_hash((node_index + j) ^ i, ret[j].words[i % NODE_WORDS]), light->num_parent_nodes, light->reciprocal, light->increment, light->shift);
parent[j] = &cache_nodes[parent_index];
kp_prefetch(parent[j]);
}
for (unsigned w = 0; w != NODE_WORDS; ++w) ret[0].words[w] = fnv_hash(ret[0].words[w], parent[0]->words[w]);
for (unsigned w = 0; w != NODE_WORDS; ++w) ret[1].words[w] = fnv_hash(ret[1].words[w], parent[1]->words[w]);
for (unsigned w = 0; w != NODE_WORDS; ++w) ret[2].words[w] = fnv_hash(ret[2].words[w], parent[2]->words[w]);
for (unsigned w = 0; w != NODE_WORDS; ++w) ret[3].words[w] = fnv_hash(ret[3].words[w], parent[3]->words[w]);
}
for (size_t i = 0; i < 4; ++i) {
SHA3_512(ret[i].bytes, ret[i].bytes, sizeof(node));
}
}
bool ethash_compute_full_data(
void* mem,
uint64_t full_size,

View File

@@ -161,6 +161,13 @@ void ethash_calculate_dag_item_opt(
ethash_light_t const cache
);
void ethash_calculate_dag_item4_opt(
node* ret,
uint32_t node_index,
uint32_t num_parents,
ethash_light_t const cache
);
void ethash_quick_hash(
ethash_h256_t* return_hash,
ethash_h256_t const* header_hash,

View File

@@ -37,8 +37,6 @@
#include "base/kernel/Platform.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "core/Miner.h"
#include "net/Network.h"
#include "Summary.h"
#include "version.h"
@@ -107,7 +105,7 @@ void xmrig::App::onConsoleCommand(char command)
close();
}
else {
m_controller->miner()->execCommand(command);
m_controller->execCommand(command);
}
}

View File

@@ -161,11 +161,14 @@ static void print_commands(Config *)
{
if (Log::isColors()) {
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"));
MAGENTA_BG(WHITE_BOLD_S "p") WHITE_BOLD("ause, ")
MAGENTA_BG(WHITE_BOLD_S "r") WHITE_BOLD("esume, ")
WHITE_BOLD("re") MAGENTA_BG(WHITE_BOLD_S "s") WHITE_BOLD("ults, ")
MAGENTA_BG(WHITE_BOLD_S "c") WHITE_BOLD("onnection")
);
}
else {
Log::print(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume");
Log::print(" * COMMANDS 'h' hashrate, 'p' pause, 'r' resume, 's' results, 'c' connection");
}
}

View File

@@ -47,11 +47,6 @@ const char *cuda_tag();
#endif
#ifdef XMRIG_ALGO_RANDOMX
const char *rx_tag();
#endif
} // namespace xmrig

View File

@@ -66,14 +66,12 @@ public:
inline bool nextRound(uint32_t rounds, uint32_t roundSize)
{
bool ok = true;
m_rounds[index()]++;
if ((m_rounds[index()] % rounds) == 0) {
for (size_t i = 0; i < N; ++i) {
*nonce(i) = Nonce::next(index(), *nonce(i), rounds * roundSize, currentJob().isNicehash(), &ok);
if (!ok) {
break;
if (!Nonce::next(index(), nonce(i), rounds * roundSize, nonceMask())) {
return false;
}
}
}
@@ -83,13 +81,14 @@ public:
}
}
return ok;
return true;
}
private:
inline int32_t nonceOffset() const { return currentJob().nonceOffset(); }
inline size_t nonceSize() const { return currentJob().nonceSize(); }
inline uint64_t nonceMask() const { return m_nonce_mask[index()]; }
inline void save(const Job &job, uint32_t reserveCount, Nonce::Backend backend)
{
@@ -97,12 +96,13 @@ private:
const size_t size = job.size();
m_jobs[index()] = job;
m_rounds[index()] = 0;
m_nonce_mask[index()] = job.nonceMask();
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());
Nonce::next(index(), nonce(i), reserveCount, nonceMask());
}
}
@@ -110,6 +110,7 @@ private:
alignas(16) uint8_t m_blobs[2][Job::kMaxBlobSize * N]{};
Job m_jobs[2];
uint32_t m_rounds[2] = { 0, 0 };
uint64_t m_nonce_mask[2];
uint64_t m_sequence = 0;
uint8_t m_index = 0;
};
@@ -125,28 +126,23 @@ inline uint32_t *xmrig::WorkerJob<1>::nonce(size_t)
template<>
inline bool xmrig::WorkerJob<1>::nextRound(uint32_t rounds, uint32_t roundSize)
{
bool ok = true;
m_rounds[index()]++;
uint32_t* n = nonce();
const uint32_t prev_nonce = *n;
if ((m_rounds[index()] % rounds) == 0) {
*n = Nonce::next(index(), *n, rounds * roundSize, currentJob().isNicehash(), &ok);
if (!Nonce::next(index(), n, rounds * roundSize, nonceMask())) {
return false;
}
if (nonceSize() == sizeof(uint64_t)) {
m_jobs[index()].nonce()[1] = n[1];
}
}
else {
*n += roundSize;
}
// Increment higher 32 bits of a 64-bit nonce when lower 32 bits overflow
if (!currentJob().isNicehash() && (nonceSize() == sizeof(uint64_t)) && (*n < prev_nonce)) {
++n[1];
Job& job = m_jobs[index()];
memcpy(job.blob(), blob(), job.size());
}
return ok;
return true;
}
@@ -156,11 +152,12 @@ inline void xmrig::WorkerJob<1>::save(const Job &job, uint32_t reserveCount, Non
m_index = job.index();
m_jobs[index()] = job;
m_rounds[index()] = 0;
m_nonce_mask[index()] = job.nonceMask();
m_jobs[index()].setBackend(backend);
memcpy(blob(), job.blob(), job.size());
*nonce() = Nonce::next(index(), *nonce(), reserveCount, currentJob().isNicehash());
Nonce::next(index(), nonce(), reserveCount, nonceMask());
}

View File

@@ -36,6 +36,7 @@
#include "crypto/common/Nonce.h"
#include "crypto/common/VirtualMemory.h"
#include "crypto/rx/Rx.h"
#include "crypto/rx/RxDataset.h"
#include "crypto/rx/RxVm.h"
#include "net/JobResults.h"
@@ -118,7 +119,9 @@ void xmrig::CpuWorker<N>::allocateRandomX_VM()
}
if (!m_vm) {
m_vm = RxVm::create(dataset, m_memory->scratchpad(), !m_hwAES, m_assembly, m_node);
// Try to allocate scratchpad from dataset's 1 GB huge pages, if normal huge pages are not available
uint8_t* scratchpad = m_memory->isHugePages() ? m_memory->scratchpad() : dataset->tryAllocateScrathpad();
m_vm = RxVm::create(dataset, scratchpad ? scratchpad : m_memory->scratchpad(), !m_hwAES, m_assembly, m_node);
}
}
#endif

View File

@@ -72,6 +72,10 @@ endif()
if (XMRIG_ARM)
list(APPEND SOURCES_CPUID src/backend/cpu/platform/BasicCpuInfo_arm.cpp)
if (XMRIG_OS_UNIX)
list(APPEND SOURCES_CPUID src/backend/cpu/platform/lscpu_arm.cpp)
endif()
else()
list(APPEND SOURCES_CPUID src/backend/cpu/platform/BasicCpuInfo.cpp)
endif()

View File

@@ -28,6 +28,7 @@
#include "backend/cpu/CpuThreads.h"
#include "base/crypto/Algorithm.h"
#include "base/tools/Object.h"
#include "crypto/common/Assembly.h"
@@ -37,6 +38,8 @@ namespace xmrig {
class ICpuInfo
{
public:
XMRIG_DISABLE_COPY_MOVE(ICpuInfo)
enum Vendor : uint32_t {
VENDOR_UNKNOWN,
VENDOR_INTEL,
@@ -60,11 +63,14 @@ public:
FLAG_PDPE1GB,
FLAG_SSE2,
FLAG_SSSE3,
FLAG_SSE41,
FLAG_XOP,
FLAG_POPCNT,
FLAG_CAT_L3,
FLAG_MAX
};
ICpuInfo() = default;
virtual ~ICpuInfo() = default;
# if defined(__x86_64__) || defined(_M_AMD64) || defined (__arm64__) || defined (__aarch64__)
@@ -79,6 +85,7 @@ public:
virtual bool hasAVX2() const = 0;
virtual bool hasBMI2() const = 0;
virtual bool hasOneGbPages() const = 0;
virtual bool hasCatL3() const = 0;
virtual const char *backend() const = 0;
virtual const char *brand() const = 0;
virtual CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const = 0;
@@ -91,6 +98,7 @@ public:
virtual size_t packages() const = 0;
virtual size_t threads() const = 0;
virtual Vendor vendor() const = 0;
virtual bool jccErratum() const = 0;
};

View File

@@ -57,7 +57,7 @@
namespace xmrig {
static const std::array<const char *, ICpuInfo::FLAG_MAX> flagNames = { "aes", "avx2", "avx512f", "bmi2", "osxsave", "pdpe1gb", "sse2", "ssse3", "xop" };
static const std::array<const char *, ICpuInfo::FLAG_MAX> flagNames = { "aes", "avx2", "avx512f", "bmi2", "osxsave", "pdpe1gb", "sse2", "ssse3", "sse4.1", "xop", "popcnt", "cat_l3" };
static const std::array<const char *, ICpuInfo::MSR_MOD_MAX> msrNames = { "none", "ryzen", "intel", "custom" };
@@ -66,7 +66,7 @@ static inline void cpuid(uint32_t level, int32_t output[4])
memset(output, 0, sizeof(int32_t) * 4);
# ifdef _MSC_VER
__cpuid(output, static_cast<int>(level));
__cpuidex(output, static_cast<int>(level), 0);
# else
__cpuid_count(level, 0, output[0], output[1], output[2], output[3]);
# endif
@@ -141,8 +141,10 @@ static inline bool has_bmi2() { return has_feature(EXTENDED_FEATURES,
static inline bool has_pdpe1gb() { return has_feature(PROCESSOR_EXT_INFO, EDX_Reg, 1 << 26); }
static inline bool has_sse2() { return has_feature(PROCESSOR_INFO, EDX_Reg, 1 << 26); }
static inline bool has_ssse3() { return has_feature(PROCESSOR_INFO, ECX_Reg, 1 << 9); }
static inline bool has_sse41() { return has_feature(PROCESSOR_INFO, ECX_Reg, 1 << 19); }
static inline bool has_xop() { return has_feature(0x80000001, ECX_Reg, 1 << 11); }
static inline bool has_popcnt() { return has_feature(PROCESSOR_INFO, ECX_Reg, 1 << 23); }
static inline bool has_cat_l3() { return has_feature(EXTENDED_FEATURES, EBX_Reg, 1 << 15) && has_feature(0x10, EBX_Reg, 1 << 1); }
} // namespace xmrig
@@ -176,8 +178,10 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
m_flags.set(FLAG_PDPE1GB, has_pdpe1gb());
m_flags.set(FLAG_SSE2, has_sse2());
m_flags.set(FLAG_SSSE3, has_ssse3());
m_flags.set(FLAG_SSE41, has_sse41());
m_flags.set(FLAG_XOP, has_xop());
m_flags.set(FLAG_POPCNT, has_popcnt());
m_flags.set(FLAG_CAT_L3, has_cat_l3());
# ifdef XMRIG_FEATURE_ASM
if (hasAES()) {
@@ -208,6 +212,37 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
m_vendor = VENDOR_INTEL;
m_assembly = Assembly::INTEL;
m_msrMod = MSR_MOD_INTEL;
struct
{
unsigned int stepping : 4;
unsigned int model : 4;
unsigned int family : 4;
unsigned int processor_type : 2;
unsigned int reserved1 : 2;
unsigned int ext_model : 4;
unsigned int ext_family : 8;
unsigned int reserved2 : 4;
} processor_info;
cpuid(1, data);
memcpy(&processor_info, data, sizeof(processor_info));
// Intel JCC erratum mitigation
if (processor_info.family == 6) {
const uint32_t model = processor_info.model | (processor_info.ext_model << 4);
const uint32_t stepping = processor_info.stepping;
// Affected CPU models and stepping numbers are taken from https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf
m_jccErratum =
((model == 0x4E) && (stepping == 0x3)) ||
((model == 0x55) && (stepping == 0x4)) ||
((model == 0x5E) && (stepping == 0x3)) ||
((model == 0x8E) && (stepping >= 0x9) && (stepping <= 0xC)) ||
((model == 0x9E) && (stepping >= 0x9) && (stepping <= 0xD)) ||
((model == 0xA6) && (stepping == 0x0)) ||
((model == 0xAE) && (stepping == 0xA));
}
}
}
# endif

View File

@@ -51,6 +51,7 @@ protected:
inline bool hasAVX2() const override { return has(FLAG_AVX2); }
inline bool hasBMI2() const override { return has(FLAG_BMI2); }
inline bool hasOneGbPages() const override { return has(FLAG_PDPE1GB); }
inline bool hasCatL3() const override { return has(FLAG_CAT_L3); }
inline const char *brand() const override { return m_brand; }
inline MsrMod msrMod() const override { return m_msrMod; }
inline size_t cores() const override { return 0; }
@@ -60,11 +61,13 @@ protected:
inline size_t packages() const override { return 1; }
inline size_t threads() const override { return m_threads; }
inline Vendor vendor() const override { return m_vendor; }
inline bool jccErratum() const override { return m_jccErratum; }
protected:
char m_brand[64 + 6]{};
size_t m_threads;
Vendor m_vendor = VENDOR_UNKNOWN;
bool m_jccErratum = false;
private:
Assembly m_assembly = Assembly::NONE;

View File

@@ -1,10 +1,4 @@
/* 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-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <support@xmrig.com>
*
@@ -22,6 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/tools/String.h"
#include <array>
#include <cstring>
#include <thread>
@@ -37,6 +35,15 @@
#include "3rdparty/rapidjson/document.h"
#ifdef XMRIG_OS_UNIX
namespace xmrig {
extern String cpu_name_arm();
} // namespace xmrig
#endif
xmrig::BasicCpuInfo::BasicCpuInfo() :
m_threads(std::thread::hardware_concurrency())
{
@@ -53,6 +60,13 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
m_flags.set(FLAG_AES, true);
# endif
# endif
# ifdef XMRIG_OS_UNIX
auto name = cpu_name_arm();
if (!name.isNull()) {
strncpy(m_brand, name, sizeof(m_brand) - 1);
}
# endif
}

View File

@@ -218,10 +218,11 @@ xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm, uint3
{
# ifdef XMRIG_ALGO_ASTROBWT
if (algorithm == Algorithm::ASTROBWT_DERO) {
return BasicCpuInfo::threads(algorithm, limit);
return allThreads(algorithm, limit);
}
# endif
# ifndef XMRIG_ARM
if (L2() == 0 && L3() == 0) {
return BasicCpuInfo::threads(algorithm, limit);
}
@@ -263,11 +264,35 @@ xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm, uint3
}
return threads;
# else
return allThreads(algorithm, limit);
# endif
}
xmrig::CpuThreads xmrig::HwlocCpuInfo::allThreads(const Algorithm &algorithm, uint32_t limit) const
{
CpuThreads threads;
threads.reserve(m_threads);
hwloc_obj_t pu = nullptr;
while ((pu = hwloc_get_next_obj_by_type(m_topology, HWLOC_OBJ_PU, pu)) != nullptr) {
threads.add(pu->os_index, 0);
}
if (threads.isEmpty()) {
return BasicCpuInfo::threads(algorithm, limit);
}
return threads;
}
void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const
{
# ifndef XMRIG_ARM
constexpr size_t oneMiB = 1024U * 1024U;
size_t PUs = countByType(cache, HWLOC_OBJ_PU);
@@ -366,4 +391,5 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
pu_id++;
}
# endif
}

View File

@@ -70,6 +70,7 @@ protected:
inline size_t packages() const override { return m_packages; }
private:
CpuThreads allThreads(const Algorithm &algorithm, uint32_t limit) const;
void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const;

View File

@@ -0,0 +1,314 @@
/* XMRig
* Copyright 2018 Riku Voipio <riku.voipio@iki.fi>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 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 "base/tools/String.h"
#include <cstdio>
#include <cctype>
namespace xmrig {
struct lscpu_desc
{
String vendor;
String model;
inline bool isReady() const { return !vendor.isNull() && !model.isNull(); }
};
struct id_part {
const int id;
const char *name;
};
struct hw_impl {
const int id;
const id_part *parts;
const char *name;
};
static const id_part arm_part[] = {
{ 0x810, "ARM810" },
{ 0x920, "ARM920" },
{ 0x922, "ARM922" },
{ 0x926, "ARM926" },
{ 0x940, "ARM940" },
{ 0x946, "ARM946" },
{ 0x966, "ARM966" },
{ 0xa20, "ARM1020" },
{ 0xa22, "ARM1022" },
{ 0xa26, "ARM1026" },
{ 0xb02, "ARM11 MPCore" },
{ 0xb36, "ARM1136" },
{ 0xb56, "ARM1156" },
{ 0xb76, "ARM1176" },
{ 0xc05, "Cortex-A5" },
{ 0xc07, "Cortex-A7" },
{ 0xc08, "Cortex-A8" },
{ 0xc09, "Cortex-A9" },
{ 0xc0d, "Cortex-A17" }, /* Originally A12 */
{ 0xc0f, "Cortex-A15" },
{ 0xc0e, "Cortex-A17" },
{ 0xc14, "Cortex-R4" },
{ 0xc15, "Cortex-R5" },
{ 0xc17, "Cortex-R7" },
{ 0xc18, "Cortex-R8" },
{ 0xc20, "Cortex-M0" },
{ 0xc21, "Cortex-M1" },
{ 0xc23, "Cortex-M3" },
{ 0xc24, "Cortex-M4" },
{ 0xc27, "Cortex-M7" },
{ 0xc60, "Cortex-M0+" },
{ 0xd01, "Cortex-A32" },
{ 0xd03, "Cortex-A53" },
{ 0xd04, "Cortex-A35" },
{ 0xd05, "Cortex-A55" },
{ 0xd07, "Cortex-A57" },
{ 0xd08, "Cortex-A72" },
{ 0xd09, "Cortex-A73" },
{ 0xd0a, "Cortex-A75" },
{ 0xd0b, "Cortex-A76" },
{ 0xd0c, "Neoverse-N1" },
{ 0xd13, "Cortex-R52" },
{ 0xd20, "Cortex-M23" },
{ 0xd21, "Cortex-M33" },
{ 0xd4a, "Neoverse-E1" },
{ -1, nullptr },
};
static const id_part brcm_part[] = {
{ 0x0f, "Brahma B15" },
{ 0x100, "Brahma B53" },
{ 0x516, "ThunderX2" },
{ -1, nullptr },
};
static const id_part dec_part[] = {
{ 0xa10, "SA110" },
{ 0xa11, "SA1100" },
{ -1, nullptr },
};
static const id_part cavium_part[] = {
{ 0x0a0, "ThunderX" },
{ 0x0a1, "ThunderX 88XX" },
{ 0x0a2, "ThunderX 81XX" },
{ 0x0a3, "ThunderX 83XX" },
{ 0x0af, "ThunderX2 99xx" },
{ -1, nullptr },
};
static const id_part apm_part[] = {
{ 0x000, "X-Gene" },
{ -1, nullptr },
};
static const id_part qcom_part[] = {
{ 0x00f, "Scorpion" },
{ 0x02d, "Scorpion" },
{ 0x04d, "Krait" },
{ 0x06f, "Krait" },
{ 0x201, "Kryo" },
{ 0x205, "Kryo" },
{ 0x211, "Kryo" },
{ 0x800, "Falkor V1/Kryo" },
{ 0x801, "Kryo V2" },
{ 0xc00, "Falkor" },
{ 0xc01, "Saphira" },
{ -1, nullptr },
};
static const id_part samsung_part[] = {
{ 0x001, "exynos-m1" },
{ -1, nullptr },
};
static const id_part nvidia_part[] = {
{ 0x000, "Denver" },
{ 0x003, "Denver 2" },
{ -1, nullptr },
};
static const id_part marvell_part[] = {
{ 0x131, "Feroceon 88FR131" },
{ 0x581, "PJ4/PJ4b" },
{ 0x584, "PJ4B-MP" },
{ -1, nullptr },
};
static const id_part faraday_part[] = {
{ 0x526, "FA526" },
{ 0x626, "FA626" },
{ -1, nullptr },
};
static const id_part intel_part[] = {
{ 0x200, "i80200" },
{ 0x210, "PXA250A" },
{ 0x212, "PXA210A" },
{ 0x242, "i80321-400" },
{ 0x243, "i80321-600" },
{ 0x290, "PXA250B/PXA26x" },
{ 0x292, "PXA210B" },
{ 0x2c2, "i80321-400-B0" },
{ 0x2c3, "i80321-600-B0" },
{ 0x2d0, "PXA250C/PXA255/PXA26x" },
{ 0x2d2, "PXA210C" },
{ 0x411, "PXA27x" },
{ 0x41c, "IPX425-533" },
{ 0x41d, "IPX425-400" },
{ 0x41f, "IPX425-266" },
{ 0x682, "PXA32x" },
{ 0x683, "PXA930/PXA935" },
{ 0x688, "PXA30x" },
{ 0x689, "PXA31x" },
{ 0xb11, "SA1110" },
{ 0xc12, "IPX1200" },
{ -1, nullptr },
};
static const id_part hisi_part[] = {
{ 0xd01, "Kunpeng-920" }, /* aka tsv110 */
{ -1, nullptr },
};
static const hw_impl hw_implementer[] = {
{ 0x41, arm_part, "ARM" },
{ 0x42, brcm_part, "Broadcom" },
{ 0x43, cavium_part, "Cavium" },
{ 0x44, dec_part, "DEC" },
{ 0x48, hisi_part, "HiSilicon" },
{ 0x4e, nvidia_part, "Nvidia" },
{ 0x50, apm_part, "APM" },
{ 0x51, qcom_part, "Qualcomm" },
{ 0x53, samsung_part, "Samsung" },
{ 0x56, marvell_part, "Marvell" },
{ 0x66, faraday_part, "Faraday" },
{ 0x69, intel_part, "Intel" }
};
static bool lookup(char *line, const char *pattern, String &value)
{
if (!*line || !value.isNull()) {
return false;
}
char *p;
int len = strlen(pattern);
if (strncmp(line, pattern, len) != 0) {
return false;
}
for (p = line + len; isspace(*p); p++);
if (*p != ':') {
return false;
}
for (++p; isspace(*p); p++);
if (!*p) {
return false;
}
const char *v = p;
len = strlen(line) - 1;
for (p = line + len; isspace(*(p-1)); p--);
*p = '\0';
value = v;
return true;
}
static bool read_basicinfo(lscpu_desc *desc)
{
auto fp = fopen("/proc/cpuinfo", "r");
if (!fp) {
return false;
}
char buf[BUFSIZ];
while (fgets(buf, sizeof(buf), fp) != nullptr) {
if (!lookup(buf, "CPU implementer", desc->vendor)) {
lookup(buf, "CPU part", desc->model);
}
if (desc->isReady()) {
break;
}
}
fclose(fp);
return desc->isReady();
}
static bool arm_cpu_decode(lscpu_desc *desc)
{
if ((strncmp(desc->vendor, "0x", 2) != 0 || strncmp(desc->model, "0x", 2) != 0)) {
return false;
}
const int vendor = strtol(desc->vendor, nullptr, 0);
const int model = strtol(desc->model, nullptr, 0);
for (const auto &impl : hw_implementer) {
if (impl.id != vendor) {
continue;
}
for (size_t i = 0; impl.parts[i].id != -1; ++i) {
if (impl.parts[i].id == model) {
desc->model = impl.parts[i].name;
return true;
}
}
}
return false;
}
String cpu_name_arm()
{
lscpu_desc desc;
if (read_basicinfo(&desc) && arm_cpu_decode(&desc)) {
return desc.model;
}
return {};
}
} // namespace xmrig

View File

@@ -152,7 +152,9 @@ public:
}
if (!CudaLib::init(cuda.loader())) {
return printDisabled(kLabel, RED_S " (failed to load CUDA plugin)");
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") RED_BOLD("disabled ") RED("(%s)"), kLabel, CudaLib::lastError());
return;
}
runtimeVersion = CudaLib::runtimeVersion();

View File

@@ -1,3 +1,9 @@
if (BUILD_STATIC AND XMRIG_OS_UNIX AND WITH_CUDA)
message(WARNING "CUDA backend is not compatible with static build, use -DWITH_CUDA=OFF to suppress this warning")
set(WITH_CUDA OFF)
endif()
if (WITH_CUDA)
add_definitions(/DXMRIG_FEATURE_CUDA)

View File

@@ -30,6 +30,7 @@
#include "backend/cuda/wrappers/CudaLib.h"
#include "base/io/Env.h"
#include "base/io/log/Log.h"
#include "base/kernel/Process.h"
#include "crypto/rx/RxAlgo.h"
@@ -46,6 +47,14 @@ enum Version : uint32_t
static uv_lib_t cudaLib;
#if defined(__APPLE__)
static String defaultLoader = "/System/Library/Frameworks/OpenCL.framework/OpenCL";
#elif defined(_WIN32)
static String defaultLoader = "xmrig-cuda.dll";
#else
static String defaultLoader = "libxmrig-cuda.so";
#endif
static const char *kAlloc = "alloc";
static const char *kAstroBWTHash = "astroBWTHash";
@@ -125,11 +134,12 @@ static setJob_v2_t pSetJob_v2 = 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("symbol not found (" #x ")"); }
#define DLSYM(x) if (uv_dlsym(&cudaLib, k##x, reinterpret_cast<void**>(&p##x)) == -1) { throw std::runtime_error(std::string("symbol not found: ") + k##x); }
bool CudaLib::m_initialized = false;
bool CudaLib::m_ready = false;
String CudaLib::m_error;
String CudaLib::m_loader;
@@ -139,9 +149,22 @@ String CudaLib::m_loader;
bool xmrig::CudaLib::init(const char *fileName)
{
if (!m_initialized) {
m_loader = fileName == nullptr ? defaultLoader() : Env::expand(fileName);
m_ready = uv_dlopen(m_loader, &cudaLib) == 0 && load();
m_initialized = true;
m_loader = fileName == nullptr ? defaultLoader : Env::expand(fileName);
if (!open()) {
return false;
}
try {
load();
} catch (std::exception &ex) {
m_error = (std::string(m_loader) + ": " + ex.what()).c_str();
return false;
}
m_ready = true;
}
return m_ready;
@@ -150,7 +173,7 @@ bool xmrig::CudaLib::init(const char *fileName)
const char *xmrig::CudaLib::lastError() noexcept
{
return uv_dlerror(&cudaLib);
return m_error;
}
@@ -344,66 +367,70 @@ void xmrig::CudaLib::release(nvid_ctx *ctx) noexcept
}
bool xmrig::CudaLib::load()
bool xmrig::CudaLib::open()
{
if (uv_dlsym(&cudaLib, kVersion, reinterpret_cast<void**>(&pVersion)) == -1) {
m_error = nullptr;
if (uv_dlopen(m_loader, &cudaLib) == 0) {
return true;
}
# ifdef XMRIG_OS_LINUX
if (m_loader == defaultLoader) {
m_loader = Process::location(Process::ExeLocation, m_loader);
}
else {
return false;
}
if (uv_dlopen(m_loader, &cudaLib) == 0) {
return true;
}
# endif
m_error = uv_dlerror(&cudaLib);
return false;
}
void xmrig::CudaLib::load()
{
DLSYM(Version);
if (pVersion(ApiVersion) != 3U) {
return false;
throw std::runtime_error("API version mismatch");
}
uv_dlsym(&cudaLib, kDeviceInfo_v2, reinterpret_cast<void**>(&pDeviceInfo_v2));
uv_dlsym(&cudaLib, kSetJob_v2, reinterpret_cast<void**>(&pSetJob_v2));
DLSYM(Alloc);
DLSYM(CnHash);
DLSYM(DeviceCount);
DLSYM(DeviceInit);
DLSYM(DeviceInt);
DLSYM(DeviceName);
DLSYM(DeviceUint);
DLSYM(DeviceUlong);
DLSYM(Init);
DLSYM(LastError);
DLSYM(PluginVersion);
DLSYM(Release);
DLSYM(RxHash);
DLSYM(RxPrepare);
DLSYM(AstroBWTHash);
DLSYM(AstroBWTPrepare);
DLSYM(KawPowHash);
DLSYM(KawPowPrepare_v2);
DLSYM(KawPowStopHash);
try {
DLSYM(Alloc);
DLSYM(CnHash);
DLSYM(DeviceCount);
DLSYM(DeviceInit);
DLSYM(DeviceInt);
DLSYM(DeviceName);
DLSYM(DeviceUint);
DLSYM(DeviceUlong);
DLSYM(Init);
DLSYM(LastError);
DLSYM(PluginVersion);
DLSYM(Release);
DLSYM(RxHash);
DLSYM(RxPrepare);
DLSYM(AstroBWTHash);
DLSYM(AstroBWTPrepare);
DLSYM(KawPowHash);
DLSYM(KawPowPrepare_v2);
DLSYM(KawPowStopHash);
DLSYM(Version);
uv_dlsym(&cudaLib, kDeviceInfo_v2, reinterpret_cast<void**>(&pDeviceInfo_v2));
if (!pDeviceInfo_v2) {
DLSYM(DeviceInfo);
}
if (!pDeviceInfo_v2) {
DLSYM(DeviceInfo);
}
if (!pSetJob_v2) {
DLSYM(SetJob);
}
} catch (std::exception &ex) {
LOG_ERR("Error loading CUDA library: %s", ex.what());
return false;
uv_dlsym(&cudaLib, kSetJob_v2, reinterpret_cast<void**>(&pSetJob_v2));
if (!pSetJob_v2) {
DLSYM(SetJob);
}
pInit();
return true;
}
xmrig::String 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

@@ -99,11 +99,12 @@ public:
static void release(nvid_ctx *ctx) noexcept;
private:
static bool load();
static String defaultLoader();
static bool open();
static void load();
static bool m_initialized;
static bool m_ready;
static String m_error;
static String m_loader;
};

View File

@@ -163,7 +163,7 @@ __kernel void filter(uint32_t nonce, uint32_t bwt_max_size, __global const uint3
filtered_hashes[index] = nonce + global_id;
#pragma unroll(8)
#pragma unroll 8
for (uint32_t i = 0; i < 8; ++i)
filtered_hashes[index + i + 1] = hash[i];
}
@@ -183,7 +183,7 @@ __kernel void prepare_batch2(__global uint32_t* hashes, __global uint32_t* filte
const uint32_t stage2_size = STAGE1_SIZE + (filtered_hash[1] & 0xfffff);
data_sizes[global_id] = stage2_size;
#pragma unroll(8)
#pragma unroll 8
for (uint32_t i = 0; i < 8; ++i)
hash[i] = filtered_hash[i + 1];
}

View File

@@ -2,7 +2,7 @@
namespace xmrig {
static const char astrobwt_cl[12440] = {
static const char astrobwt_cl[12434] = {
0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x75,0x63,0x68,0x61,0x72,0x20,0x75,0x69,0x6e,0x74,0x38,0x5f,0x74,0x3b,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x75,
0x73,0x68,0x6f,0x72,0x74,0x20,0x75,0x69,0x6e,0x74,0x31,0x36,0x5f,0x74,0x3b,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x75,0x69,0x6e,0x74,0x20,0x75,0x69,0x6e,
0x74,0x33,0x32,0x5f,0x74,0x3b,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x3b,0x0a,0x74,
@@ -119,279 +119,279 @@ static const char astrobwt_cl[12440] = {
0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x29,0x2c,0x31,0x29,0x2a,0x28,0x33,0x36,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x29,0x2b,0x31,0x3b,0x0a,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x69,0x6e,0x64,
0x65,0x78,0x5d,0x3d,0x6e,0x6f,0x6e,0x63,0x65,0x2b,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,
0x6f,0x6c,0x6c,0x28,0x38,0x29,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x2b,
0x2b,0x69,0x29,0x0a,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x69,0x6e,0x64,0x65,0x78,0x2b,0x69,0x2b,0x31,0x5d,0x3d,0x68,
0x61,0x73,0x68,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x70,0x72,0x65,0x70,0x61,0x72,
0x65,0x5f,0x62,0x61,0x74,0x63,0x68,0x32,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,
0x65,0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,
0x61,0x73,0x68,0x65,0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x64,0x61,0x74,0x61,0x5f,0x73,0x69,
0x7a,0x65,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x3d,
0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,
0x20,0x4e,0x3d,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x30,0x5d,0x2d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,
0x5f,0x73,0x69,0x7a,0x65,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x3d,0x3d,0x30,0x29,0x0a,0x66,0x69,0x6c,0x74,0x65,
0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x30,0x5d,0x3d,0x4e,0x3b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,
0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x3d,0x68,0x61,0x73,0x68,0x65,0x73,0x2b,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x2a,0x38,0x3b,0x0a,0x5f,0x5f,0x67,
0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x3d,0x66,0x69,
0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x2b,0x28,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x2b,0x4e,0x29,0x2a,0x39,0x2b,0x31,0x3b,
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x32,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x53,0x54,0x41,0x47,
0x45,0x31,0x5f,0x53,0x49,0x5a,0x45,0x2b,0x28,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x5b,0x31,0x5d,0x26,0x30,0x78,0x66,0x66,0x66,0x66,
0x66,0x29,0x3b,0x0a,0x64,0x61,0x74,0x61,0x5f,0x73,0x69,0x7a,0x65,0x73,0x5b,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x5d,0x3d,0x73,0x74,0x61,0x67,0x65,0x32,
0x5f,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x28,0x38,0x29,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x68,0x61,0x73,0x68,0x5b,0x69,0x5d,0x3d,0x66,0x69,
0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x5b,0x69,0x2b,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,
0x64,0x20,0x66,0x69,0x6e,0x64,0x5f,0x73,0x68,0x61,0x72,0x65,0x73,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,
0x74,0x36,0x34,0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x65,0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,
0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x2c,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,
0x74,0x61,0x72,0x67,0x65,0x74,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x68,0x61,0x72,0x65,0x73,
0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x6e,0x64,0x65,0x78,0x3d,
0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x67,0x6c,0x6f,0x62,
0x61,0x6c,0x5f,0x69,0x6e,0x64,0x65,0x78,0x2a,0x34,0x2b,0x33,0x5d,0x3c,0x74,0x61,0x72,0x67,0x65,0x74,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x64,0x78,0x3d,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x73,0x68,0x61,0x72,0x65,0x73,0x2b,0x30,0x78,0x46,
0x46,0x29,0x3b,0x0a,0x69,0x66,0x28,0x69,0x64,0x78,0x3c,0x30,0x78,0x46,0x46,0x29,0x0a,0x73,0x68,0x61,0x72,0x65,0x73,0x5b,0x69,0x64,0x78,0x5d,0x3d,0x66,0x69,0x6c,
0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x28,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x30,0x5d,
0x2b,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x6e,0x64,0x65,0x78,0x29,0x2a,0x39,0x2b,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,
0x20,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x76,0x2c,0x63,0x29,0x20,0x28,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x76,0x2c,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,
0x29,0x63,0x29,0x29,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x58,0x4f,0x52,0x28,0x76,0x2c,0x77,0x29,0x20,0x28,0x28,0x76,0x29,0x20,0x5e,0x20,0x28,0x77,0x29,
0x29,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x50,0x4c,0x55,0x53,0x28,0x76,0x2c,0x77,0x29,0x20,0x28,0x28,0x76,0x29,0x20,0x2b,0x20,0x28,0x77,0x29,0x29,0x0a,
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,0x53,0x41,0x4c,0x53,0x41,0x32,0x30,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5f,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,0x53,0x61,0x6c,0x73,0x61,0x32,0x30,0x5f,0x58,0x4f,0x52,0x4b,0x65,0x79,0x53,0x74,0x72,0x65,0x61,0x6d,
0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6b,0x65,0x79,0x73,0x2c,0x5f,
0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,
0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x73,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,
0x5f,0x74,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x74,0x72,0x69,0x64,0x65,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,
0x6f,0x6c,0x6c,0x20,0x38,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x2b,0x2b,
0x69,0x29,0x0a,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x69,0x6e,0x64,0x65,0x78,0x2b,0x69,0x2b,0x31,0x5d,0x3d,0x68,0x61,
0x73,0x68,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x70,0x72,0x65,0x70,0x61,0x72,0x65,
0x5f,0x62,0x61,0x74,0x63,0x68,0x32,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x65,
0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,
0x73,0x68,0x65,0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x64,0x61,0x74,0x61,0x5f,0x73,0x69,0x7a,
0x65,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x3d,0x67,
0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x4e,0x3d,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x30,0x5d,0x2d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,
0x73,0x69,0x7a,0x65,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x3d,0x3d,0x30,0x29,0x0a,0x66,0x69,0x6c,0x74,0x65,0x72,
0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x30,0x5d,0x3d,0x4e,0x3b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x3d,0x68,0x61,0x73,0x68,0x65,0x73,0x2b,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x2a,0x38,0x3b,0x0a,0x5f,0x5f,0x67,0x6c,
0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x3d,0x66,0x69,0x6c,
0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x2b,0x28,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x2b,0x4e,0x29,0x2a,0x39,0x2b,0x31,0x3b,0x0a,
0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x32,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x53,0x54,0x41,0x47,0x45,
0x31,0x5f,0x53,0x49,0x5a,0x45,0x2b,0x28,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x5b,0x31,0x5d,0x26,0x30,0x78,0x66,0x66,0x66,0x66,0x66,
0x29,0x3b,0x0a,0x64,0x61,0x74,0x61,0x5f,0x73,0x69,0x7a,0x65,0x73,0x5b,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x5d,0x3d,0x73,0x74,0x61,0x67,0x65,0x32,0x5f,
0x73,0x69,0x7a,0x65,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x38,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,
0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x68,0x61,0x73,0x68,0x5b,0x69,0x5d,0x3d,0x66,0x69,0x6c,0x74,
0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x5b,0x69,0x2b,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,
0x66,0x69,0x6e,0x64,0x5f,0x73,0x68,0x61,0x72,0x65,0x73,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x36,
0x34,0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x65,0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,
0x32,0x5f,0x74,0x2a,0x20,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x2c,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x74,0x61,
0x72,0x67,0x65,0x74,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x68,0x61,0x72,0x65,0x73,0x29,0x0a,
0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x6e,0x64,0x65,0x78,0x3d,0x67,0x65,
0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x67,0x6c,0x6f,0x62,0x61,0x6c,
0x5f,0x69,0x6e,0x64,0x65,0x78,0x2a,0x34,0x2b,0x33,0x5d,0x3c,0x74,0x61,0x72,0x67,0x65,0x74,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x33,0x32,0x5f,0x74,0x20,0x69,0x64,0x78,0x3d,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x73,0x68,0x61,0x72,0x65,0x73,0x2b,0x30,0x78,0x46,0x46,0x29,
0x3b,0x0a,0x69,0x66,0x28,0x69,0x64,0x78,0x3c,0x30,0x78,0x46,0x46,0x29,0x0a,0x73,0x68,0x61,0x72,0x65,0x73,0x5b,0x69,0x64,0x78,0x5d,0x3d,0x66,0x69,0x6c,0x74,0x65,
0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x28,0x66,0x69,0x6c,0x74,0x65,0x72,0x65,0x64,0x5f,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x30,0x5d,0x2b,0x67,
0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x6e,0x64,0x65,0x78,0x29,0x2a,0x39,0x2b,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x52,
0x4f,0x54,0x41,0x54,0x45,0x28,0x76,0x2c,0x63,0x29,0x20,0x28,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x76,0x2c,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x63,
0x29,0x29,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x58,0x4f,0x52,0x28,0x76,0x2c,0x77,0x29,0x20,0x28,0x28,0x76,0x29,0x20,0x5e,0x20,0x28,0x77,0x29,0x29,0x0a,
0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x50,0x4c,0x55,0x53,0x28,0x76,0x2c,0x77,0x29,0x20,0x28,0x28,0x76,0x29,0x20,0x2b,0x20,0x28,0x77,0x29,0x29,0x0a,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,0x53,0x41,0x4c,0x53,0x41,0x32,0x30,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5f,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,0x53,0x61,0x6c,0x73,0x61,0x32,0x30,0x5f,0x58,0x4f,0x52,0x4b,0x65,0x79,0x53,0x74,0x72,0x65,0x61,0x6d,0x28,0x5f,
0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6b,0x65,0x79,0x73,0x2c,0x5f,0x5f,0x67,
0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,
0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x73,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,
0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x74,0x72,0x69,0x64,0x65,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,
0x20,0x74,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,
0x5f,0x74,0x20,0x67,0x3d,0x67,0x65,0x74,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x36,0x34,0x5f,0x74,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x67,0x2a,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,
0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x74,0x72,0x69,0x64,0x65,0x29,0x2b,0x31,0x32,0x38,0x3b,0x0a,0x7b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x70,0x3d,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x2b,0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,
0x74,0x2d,0x31,0x32,0x38,0x29,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x74,0x3b,0x20,0x69,0x3c,0x31,0x32,0x38,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x29,0x3b,0x20,0x69,0x2b,0x3d,0x53,0x41,0x4c,0x53,0x41,0x32,0x30,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,0x29,0x0a,0x70,0x5b,0x69,0x5d,0x3d,
0x30,0x3b,0x0a,0x7d,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6b,0x3d,
0x6b,0x65,0x79,0x73,0x2b,0x67,0x2a,0x38,0x3b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6f,0x75,0x74,
0x70,0x75,0x74,0x3d,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x2b,0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2b,0x28,0x74,0x2a,0x36,0x34,
0x29,0x29,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,
0x32,0x5f,0x74,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x73,0x5b,0x67,0x5d,0x3b,
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x3d,0x6b,0x5b,0x30,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x32,0x3d,0x6b,0x5b,0x31,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x6a,0x33,0x3d,0x6b,0x5b,0x32,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x34,0x3d,0x6b,0x5b,0x33,0x5d,0x3b,
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x31,0x3d,0x6b,0x5b,0x34,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,
0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x32,0x3d,0x6b,0x5b,0x35,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x20,0x6a,0x31,0x33,0x3d,0x6b,0x5b,0x36,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x34,0x3d,0x6b,
0x5b,0x37,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x30,0x3d,0x30,0x78,0x36,0x31,0x37,0x30,0x37,0x38,0x36,
0x35,0x55,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x35,0x3d,0x30,0x78,0x33,0x33,0x32,0x30,0x36,0x34,0x36,0x45,
0x55,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x30,0x3d,0x30,0x78,0x37,0x39,0x36,0x32,0x32,0x44,0x33,0x32,
0x55,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x35,0x3d,0x30,0x78,0x36,0x42,0x32,0x30,0x36,0x35,0x37,0x34,
0x55,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x36,0x3d,0x30,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x37,0x3d,0x30,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x38,0x3d,0x30,
0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x39,0x3d,0x30,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,
0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x74,0x2a,0x36,0x34,0x3b,0x20,0x69,0x3c,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x3b,0x20,0x69,0x2b,0x3d,0x53,
0x41,0x4c,0x53,0x41,0x32,0x30,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,0x2a,0x36,0x34,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x38,0x5f,0x31,0x3d,0x6a,0x38,0x2b,0x28,0x69,0x2f,0x36,0x34,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x78,0x30,0x3d,0x6a,0x30,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x3d,0x6a,0x31,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x78,0x32,0x3d,0x6a,0x32,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x33,0x3d,0x6a,0x33,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x78,0x34,0x3d,0x6a,0x34,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x35,0x3d,0x6a,0x35,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x78,0x36,0x3d,0x6a,0x36,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x37,0x3d,0x6a,0x37,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
0x78,0x38,0x3d,0x6a,0x38,0x5f,0x31,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x39,0x3d,0x6a,0x39,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x20,0x78,0x31,0x30,0x3d,0x6a,0x31,0x30,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x31,0x3d,0x6a,0x31,0x31,0x3b,0x0a,0x75,0x69,0x6e,
0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x32,0x3d,0x6a,0x31,0x32,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x33,0x3d,0x6a,0x31,0x33,0x3b,
0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x34,0x3d,0x6a,0x31,0x34,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x35,0x3d,
0x6a,0x31,0x35,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x35,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,
0x32,0x5f,0x74,0x20,0x6a,0x3d,0x30,0x3b,0x20,0x6a,0x3c,0x31,0x30,0x3b,0x20,0x2b,0x2b,0x6a,0x29,0x0a,0x7b,0x0a,0x78,0x34,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x34,
0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x30,0x2c,0x78,0x31,0x32,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x38,0x3d,0x58,0x4f,
0x52,0x28,0x20,0x78,0x38,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x34,0x2c,0x78,0x30,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,
0x31,0x32,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x32,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x38,0x2c,0x78,0x34,0x29,0x2c,0x31,
0x33,0x29,0x29,0x3b,0x0a,0x78,0x30,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x30,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x32,0x2c,
0x78,0x38,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x39,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x39,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,
0x28,0x20,0x78,0x35,0x2c,0x78,0x31,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x31,0x33,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x33,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,
0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x39,0x2c,0x78,0x35,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x31,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x31,0x2c,0x52,0x4f,
0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x33,0x2c,0x78,0x39,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x35,0x3d,0x58,0x4f,0x52,0x28,0x20,
0x78,0x35,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x31,0x2c,0x78,0x31,0x33,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x31,
0x34,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x34,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x30,0x2c,0x78,0x36,0x29,0x2c,0x37,0x29,
0x29,0x3b,0x0a,0x78,0x32,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x32,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x34,0x2c,0x78,0x31,
0x30,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x36,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x36,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,
0x78,0x32,0x2c,0x78,0x31,0x34,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x31,0x30,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x30,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,
0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x36,0x2c,0x78,0x32,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x33,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x33,0x2c,0x52,
0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x35,0x2c,0x78,0x31,0x31,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x37,0x3d,0x58,0x4f,0x52,0x28,
0x20,0x78,0x37,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x33,0x2c,0x78,0x31,0x35,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x31,
0x31,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x31,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x37,0x2c,0x78,0x33,0x29,0x2c,0x31,0x33,
0x29,0x29,0x3b,0x0a,0x78,0x31,0x35,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x35,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x31,0x2c,
0x78,0x37,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x31,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x31,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,
0x28,0x20,0x78,0x30,0x2c,0x78,0x33,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x32,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x32,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,
0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x31,0x2c,0x78,0x30,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x33,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x33,0x2c,0x52,0x4f,0x54,
0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x32,0x2c,0x78,0x31,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x30,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,
0x30,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x33,0x2c,0x78,0x32,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x36,0x3d,0x58,
0x4f,0x52,0x28,0x20,0x78,0x36,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x35,0x2c,0x78,0x34,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,
0x78,0x37,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x37,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x36,0x2c,0x78,0x35,0x29,0x2c,0x39,
0x29,0x29,0x3b,0x0a,0x78,0x34,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x34,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x37,0x2c,0x78,
0x36,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x35,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x35,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,
0x20,0x78,0x34,0x2c,0x78,0x37,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x31,0x31,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x31,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,
0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x30,0x2c,0x78,0x39,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x38,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x38,0x2c,0x52,0x4f,
0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x31,0x2c,0x78,0x31,0x30,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x39,0x3d,0x58,0x4f,0x52,0x28,0x20,
0x78,0x39,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x38,0x2c,0x78,0x31,0x31,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x31,
0x30,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x30,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x39,0x2c,0x78,0x38,0x29,0x2c,0x31,0x38,
0x29,0x29,0x3b,0x0a,0x78,0x31,0x32,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x32,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x35,0x2c,
0x78,0x31,0x34,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x31,0x33,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x33,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,
0x53,0x28,0x78,0x31,0x32,0x2c,0x78,0x31,0x35,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x31,0x34,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x34,0x2c,0x52,0x4f,0x54,0x41,
0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x33,0x2c,0x78,0x31,0x32,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x31,0x35,0x3d,0x58,0x4f,0x52,0x28,0x78,
0x31,0x35,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x34,0x2c,0x78,0x31,0x33,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x7d,0x0a,
0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x30,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x30,0x2c,0x6a,0x30,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x5d,
0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x2c,0x6a,0x31,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x32,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x32,0x2c,
0x6a,0x32,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x33,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x33,0x2c,0x6a,0x33,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,
0x75,0x74,0x5b,0x34,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x34,0x2c,0x6a,0x34,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x35,0x5d,0x3d,0x50,0x4c,0x55,
0x53,0x28,0x78,0x35,0x2c,0x6a,0x35,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x36,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x36,0x2c,0x6a,0x36,0x29,0x3b,
0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x37,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x37,0x2c,0x6a,0x37,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x38,
0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x38,0x2c,0x6a,0x38,0x5f,0x31,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x39,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,
0x78,0x39,0x2c,0x6a,0x39,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x30,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x30,0x2c,0x6a,0x31,0x30,0x29,
0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x31,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x31,0x2c,0x6a,0x31,0x31,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,
0x75,0x74,0x5b,0x31,0x32,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x32,0x2c,0x6a,0x31,0x32,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x33,0x5d,
0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x33,0x2c,0x6a,0x31,0x33,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x34,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,
0x78,0x31,0x34,0x2c,0x6a,0x31,0x34,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x35,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x35,0x2c,0x6a,0x31,
0x35,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x2b,0x3d,0x28,0x53,0x41,0x4c,0x53,0x41,0x32,0x30,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,0x2a,
0x36,0x34,0x29,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,
0x43,0x4c,0x4b,0x5f,0x47,0x4c,0x4f,0x42,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x69,0x66,0x28,0x74,0x3c,0x31,0x36,0x29,0x0a,
0x7b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x70,0x3d,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x2b,0x28,
0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2b,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x2b,0x33,0x29,0x2f,0x73,0x69,0x7a,
0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x3b,0x0a,0x70,0x5b,0x74,0x5d,0x3d,0x30,0x3b,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x28,0x74,0x3d,0x3d,
0x30,0x29,0x26,0x26,0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x26,0x33,0x29,0x29,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x5b,0x28,0x6f,0x75,
0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2b,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x29,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,
0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x5d,0x20,0x26,0x3d,0x20,0x30,0x78,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x55,0x3e,0x3e,0x28,0x28,0x34,0x2d,0x28,
0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x26,0x33,0x29,0x29,0x3c,0x3c,0x33,0x29,0x3b,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x52,
0x4f,0x55,0x4e,0x44,0x53,0x20,0x32,0x34,0x20,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x52,0x36,0x34,0x28,0x61,0x2c,0x62,0x2c,0x63,0x29,0x20,0x28,0x28,0x28,
0x61,0x29,0x20,0x3c,0x3c,0x20,0x62,0x29,0x20,0x7c,0x20,0x28,0x28,0x61,0x29,0x20,0x3e,0x3e,0x20,0x63,0x29,0x29,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,
0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x72,0x63,0x5b,0x32,0x5d,0x5b,0x52,0x4f,0x55,0x4e,0x44,0x53,0x5d,0x3d,0x7b,
0x0a,0x7b,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x32,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x41,0x55,0x4c,
0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x42,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x55,0x4c,
0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,0x31,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x39,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x41,0x55,0x4c,
0x2c,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x38,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x30,0x39,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x41,0x55,0x4c,
0x2c,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,0x42,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x42,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x39,0x55,0x4c,
0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x33,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x32,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x55,0x4c,
0x2c,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x41,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x41,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,0x31,0x55,0x4c,
0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x30,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x30,0x38,0x55,0x4c,
0x7d,0x2c,0x0a,0x7b,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,
0x30,0x55,0x4c,0x2c,0x0a,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,
0x2c,0x30,0x55,0x4c,0x2c,0x0a,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,
0x4c,0x2c,0x30,0x55,0x4c,0x7d,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x20,0x72,
0x6f,0x5b,0x32,0x35,0x5d,0x5b,0x32,0x5d,0x3d,0x7b,0x0a,0x7b,0x20,0x30,0x2c,0x36,0x34,0x7d,0x2c,0x7b,0x34,0x34,0x2c,0x32,0x30,0x7d,0x2c,0x7b,0x34,0x33,0x2c,0x32,
0x31,0x7d,0x2c,0x7b,0x32,0x31,0x2c,0x34,0x33,0x7d,0x2c,0x7b,0x31,0x34,0x2c,0x35,0x30,0x7d,0x2c,0x0a,0x7b,0x20,0x31,0x2c,0x36,0x33,0x7d,0x2c,0x7b,0x20,0x36,0x2c,
0x35,0x38,0x7d,0x2c,0x7b,0x32,0x35,0x2c,0x33,0x39,0x7d,0x2c,0x7b,0x20,0x38,0x2c,0x35,0x36,0x7d,0x2c,0x7b,0x31,0x38,0x2c,0x34,0x36,0x7d,0x2c,0x0a,0x7b,0x36,0x32,
0x2c,0x32,0x7d,0x2c,0x7b,0x35,0x35,0x2c,0x39,0x7d,0x2c,0x7b,0x33,0x39,0x2c,0x32,0x35,0x7d,0x2c,0x7b,0x34,0x31,0x2c,0x32,0x33,0x7d,0x2c,0x7b,0x20,0x32,0x2c,0x36,
0x32,0x7d,0x2c,0x0a,0x7b,0x32,0x38,0x2c,0x33,0x36,0x7d,0x2c,0x7b,0x32,0x30,0x2c,0x34,0x34,0x7d,0x2c,0x7b,0x20,0x33,0x2c,0x36,0x31,0x7d,0x2c,0x7b,0x34,0x35,0x2c,
0x31,0x39,0x7d,0x2c,0x7b,0x36,0x31,0x2c,0x33,0x7d,0x2c,0x0a,0x7b,0x32,0x37,0x2c,0x33,0x37,0x7d,0x2c,0x7b,0x33,0x36,0x2c,0x32,0x38,0x7d,0x2c,0x7b,0x31,0x30,0x2c,
0x35,0x34,0x7d,0x2c,0x7b,0x31,0x35,0x2c,0x34,0x39,0x7d,0x2c,0x7b,0x35,0x36,0x2c,0x38,0x7d,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,
0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x20,0x61,0x5b,0x32,0x35,0x5d,0x3d,0x7b,0x0a,0x30,0x2c,0x36,0x2c,0x31,0x32,0x2c,0x31,0x38,0x2c,0x32,0x34,0x2c,
0x0a,0x31,0x2c,0x37,0x2c,0x31,0x33,0x2c,0x31,0x39,0x2c,0x32,0x30,0x2c,0x0a,0x32,0x2c,0x38,0x2c,0x31,0x34,0x2c,0x31,0x35,0x2c,0x32,0x31,0x2c,0x0a,0x33,0x2c,0x39,
0x2c,0x31,0x30,0x2c,0x31,0x36,0x2c,0x32,0x32,0x2c,0x0a,0x34,0x2c,0x35,0x2c,0x31,0x31,0x2c,0x31,0x37,0x2c,0x32,0x33,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,
0x73,0x74,0x61,0x6e,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x20,0x62,0x5b,0x32,0x35,0x5d,0x3d,0x7b,0x0a,0x30,0x2c,0x31,0x2c,0x32,0x2c,0x33,0x2c,
0x34,0x2c,0x0a,0x31,0x2c,0x32,0x2c,0x33,0x2c,0x34,0x2c,0x30,0x2c,0x0a,0x32,0x2c,0x33,0x2c,0x34,0x2c,0x30,0x2c,0x31,0x2c,0x0a,0x33,0x2c,0x34,0x2c,0x30,0x2c,0x31,
0x2c,0x32,0x2c,0x0a,0x34,0x2c,0x30,0x2c,0x31,0x2c,0x32,0x2c,0x33,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x69,0x6e,0x74,0x20,0x63,0x5b,0x32,0x35,0x5d,0x5b,0x33,0x5d,0x3d,0x7b,0x0a,0x7b,0x20,0x30,0x2c,0x31,0x2c,0x32,0x7d,0x2c,0x7b,0x20,0x31,0x2c,0x32,0x2c,
0x33,0x7d,0x2c,0x7b,0x20,0x32,0x2c,0x33,0x2c,0x34,0x7d,0x2c,0x7b,0x20,0x33,0x2c,0x34,0x2c,0x30,0x7d,0x2c,0x7b,0x20,0x34,0x2c,0x30,0x2c,0x31,0x7d,0x2c,0x0a,0x7b,
0x20,0x35,0x2c,0x36,0x2c,0x37,0x7d,0x2c,0x7b,0x20,0x36,0x2c,0x37,0x2c,0x38,0x7d,0x2c,0x7b,0x20,0x37,0x2c,0x38,0x2c,0x39,0x7d,0x2c,0x7b,0x20,0x38,0x2c,0x39,0x2c,
0x35,0x7d,0x2c,0x7b,0x20,0x39,0x2c,0x35,0x2c,0x36,0x7d,0x2c,0x0a,0x7b,0x31,0x30,0x2c,0x31,0x31,0x2c,0x31,0x32,0x7d,0x2c,0x7b,0x31,0x31,0x2c,0x31,0x32,0x2c,0x31,
0x33,0x7d,0x2c,0x7b,0x31,0x32,0x2c,0x31,0x33,0x2c,0x31,0x34,0x7d,0x2c,0x7b,0x31,0x33,0x2c,0x31,0x34,0x2c,0x31,0x30,0x7d,0x2c,0x7b,0x31,0x34,0x2c,0x31,0x30,0x2c,
0x31,0x31,0x7d,0x2c,0x0a,0x7b,0x31,0x35,0x2c,0x31,0x36,0x2c,0x31,0x37,0x7d,0x2c,0x7b,0x31,0x36,0x2c,0x31,0x37,0x2c,0x31,0x38,0x7d,0x2c,0x7b,0x31,0x37,0x2c,0x31,
0x38,0x2c,0x31,0x39,0x7d,0x2c,0x7b,0x31,0x38,0x2c,0x31,0x39,0x2c,0x31,0x35,0x7d,0x2c,0x7b,0x31,0x39,0x2c,0x31,0x35,0x2c,0x31,0x36,0x7d,0x2c,0x0a,0x7b,0x32,0x30,
0x2c,0x32,0x31,0x2c,0x32,0x32,0x7d,0x2c,0x7b,0x32,0x31,0x2c,0x32,0x32,0x2c,0x32,0x33,0x7d,0x2c,0x7b,0x32,0x32,0x2c,0x32,0x33,0x2c,0x32,0x34,0x7d,0x2c,0x7b,0x32,
0x33,0x2c,0x32,0x34,0x2c,0x32,0x30,0x7d,0x2c,0x7b,0x32,0x34,0x2c,0x32,0x30,0x2c,0x32,0x31,0x7d,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,
0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x20,0x64,0x5b,0x32,0x35,0x5d,0x3d,0x7b,0x0a,0x30,0x2c,0x31,0x2c,0x32,0x2c,0x33,0x2c,0x34,0x2c,0x0a,0x31,
0x30,0x2c,0x31,0x31,0x2c,0x31,0x32,0x2c,0x31,0x33,0x2c,0x31,0x34,0x2c,0x0a,0x32,0x30,0x2c,0x32,0x31,0x2c,0x32,0x32,0x2c,0x32,0x33,0x2c,0x32,0x34,0x2c,0x0a,0x35,
0x2c,0x36,0x2c,0x37,0x2c,0x38,0x2c,0x39,0x2c,0x0a,0x31,0x35,0x2c,0x31,0x36,0x2c,0x31,0x37,0x2c,0x31,0x38,0x2c,0x31,0x39,0x0a,0x7d,0x3b,0x0a,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,
0x33,0x32,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x73,0x68,0x61,0x33,0x28,0x5f,0x5f,0x67,
0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x38,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x73,0x2c,0x5f,0x5f,0x67,0x6c,
0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x73,
0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x74,0x72,0x69,0x64,0x65,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,
0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x65,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,
0x5f,0x74,0x20,0x74,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x33,0x32,0x5f,0x74,0x20,0x67,0x3d,0x67,0x65,0x74,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x67,0x2a,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,
0x74,0x29,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x74,0x72,0x69,0x64,0x65,0x29,0x2b,0x31,0x32,0x38,0x3b,0x0a,0x7b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,
0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x70,0x3d,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x2b,0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,
0x73,0x65,0x74,0x2d,0x31,0x32,0x38,0x29,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,
0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x74,0x3b,0x20,0x69,0x3c,0x31,0x32,0x38,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,
0x32,0x5f,0x74,0x29,0x3b,0x20,0x69,0x2b,0x3d,0x53,0x41,0x4c,0x53,0x41,0x32,0x30,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,0x29,0x0a,0x70,0x5b,0x69,
0x5d,0x3d,0x30,0x3b,0x0a,0x7d,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,
0x6b,0x3d,0x6b,0x65,0x79,0x73,0x2b,0x67,0x2a,0x38,0x3b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6f,
0x75,0x74,0x70,0x75,0x74,0x3d,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x2b,0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2b,0x28,0x74,0x2a,
0x36,0x34,0x29,0x29,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,
0x74,0x33,0x32,0x5f,0x74,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x73,0x5b,0x67,
0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x3d,0x6b,0x5b,0x30,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,
0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x32,0x3d,0x6b,0x5b,0x31,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x20,0x6a,0x33,0x3d,0x6b,0x5b,0x32,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x34,0x3d,0x6b,0x5b,0x33,
0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x31,0x3d,0x6b,0x5b,0x34,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x32,0x3d,0x6b,0x5b,0x35,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,
0x32,0x5f,0x74,0x20,0x6a,0x31,0x33,0x3d,0x6b,0x5b,0x36,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x34,
0x3d,0x6b,0x5b,0x37,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x30,0x3d,0x30,0x78,0x36,0x31,0x37,0x30,0x37,
0x38,0x36,0x35,0x55,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x35,0x3d,0x30,0x78,0x33,0x33,0x32,0x30,0x36,0x34,
0x36,0x45,0x55,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x30,0x3d,0x30,0x78,0x37,0x39,0x36,0x32,0x32,0x44,
0x33,0x32,0x55,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x31,0x35,0x3d,0x30,0x78,0x36,0x42,0x32,0x30,0x36,0x35,
0x37,0x34,0x55,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x36,0x3d,0x30,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,
0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x37,0x3d,0x30,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x38,
0x3d,0x30,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x39,0x3d,0x30,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x74,0x2a,0x36,0x34,0x3b,0x20,0x69,0x3c,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x3b,0x20,0x69,0x2b,
0x3d,0x53,0x41,0x4c,0x53,0x41,0x32,0x30,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,0x2a,0x36,0x34,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,
0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x38,0x5f,0x31,0x3d,0x6a,0x38,0x2b,0x28,0x69,0x2f,0x36,0x34,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x20,0x78,0x30,0x3d,0x6a,0x30,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x3d,0x6a,0x31,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x20,0x78,0x32,0x3d,0x6a,0x32,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x33,0x3d,0x6a,0x33,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x20,0x78,0x34,0x3d,0x6a,0x34,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x35,0x3d,0x6a,0x35,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x20,0x78,0x36,0x3d,0x6a,0x36,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x37,0x3d,0x6a,0x37,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
0x74,0x20,0x78,0x38,0x3d,0x6a,0x38,0x5f,0x31,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x39,0x3d,0x6a,0x39,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,
0x32,0x5f,0x74,0x20,0x78,0x31,0x30,0x3d,0x6a,0x31,0x30,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x31,0x3d,0x6a,0x31,0x31,0x3b,0x0a,0x75,
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x32,0x3d,0x6a,0x31,0x32,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x33,0x3d,0x6a,0x31,
0x33,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,0x34,0x3d,0x6a,0x31,0x34,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x78,0x31,
0x35,0x3d,0x6a,0x31,0x35,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x28,0x35,0x29,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6a,0x3d,0x30,0x3b,0x20,0x6a,0x3c,0x31,0x30,0x3b,0x20,0x2b,0x2b,0x6a,0x29,0x0a,0x7b,0x0a,0x78,0x34,0x3d,0x58,0x4f,0x52,0x28,
0x20,0x78,0x34,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x30,0x2c,0x78,0x31,0x32,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x38,
0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x38,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x34,0x2c,0x78,0x30,0x29,0x2c,0x39,0x29,0x29,
0x3b,0x0a,0x78,0x31,0x32,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x32,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x38,0x2c,0x78,0x34,
0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x30,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x30,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,
0x31,0x32,0x2c,0x78,0x38,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x39,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x39,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,
0x4c,0x55,0x53,0x28,0x20,0x78,0x35,0x2c,0x78,0x31,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x31,0x33,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x33,0x2c,0x52,0x4f,0x54,
0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x39,0x2c,0x78,0x35,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x31,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x31,
0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x33,0x2c,0x78,0x39,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x35,0x3d,0x58,0x4f,
0x52,0x28,0x20,0x78,0x35,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x31,0x2c,0x78,0x31,0x33,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,
0x0a,0x78,0x31,0x34,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x34,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x30,0x2c,0x78,0x36,0x29,
0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x32,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x32,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x34,
0x2c,0x78,0x31,0x30,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x36,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x36,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,
0x53,0x28,0x20,0x78,0x32,0x2c,0x78,0x31,0x34,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x31,0x30,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x30,0x2c,0x52,0x4f,0x54,
0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x36,0x2c,0x78,0x32,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x33,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,
0x33,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x35,0x2c,0x78,0x31,0x31,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x37,0x3d,0x58,
0x4f,0x52,0x28,0x20,0x78,0x37,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x33,0x2c,0x78,0x31,0x35,0x29,0x2c,0x39,0x29,0x29,0x3b,
0x0a,0x78,0x31,0x31,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x31,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x37,0x2c,0x78,0x33,0x29,
0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x31,0x35,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x35,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,
0x31,0x31,0x2c,0x78,0x37,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x31,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x31,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,
0x4c,0x55,0x53,0x28,0x20,0x78,0x30,0x2c,0x78,0x33,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x32,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x32,0x2c,0x52,0x4f,0x54,0x41,
0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x31,0x2c,0x78,0x30,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x33,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x33,0x2c,
0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x32,0x2c,0x78,0x31,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x30,0x3d,0x58,0x4f,0x52,
0x28,0x20,0x78,0x30,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x33,0x2c,0x78,0x32,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,
0x36,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x36,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x35,0x2c,0x78,0x34,0x29,0x2c,0x37,0x29,
0x29,0x3b,0x0a,0x78,0x37,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x37,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x36,0x2c,0x78,0x35,
0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x34,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x34,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,
0x37,0x2c,0x78,0x36,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x35,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x35,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,
0x55,0x53,0x28,0x20,0x78,0x34,0x2c,0x78,0x37,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x31,0x31,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x31,0x2c,0x52,0x4f,0x54,
0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x30,0x2c,0x78,0x39,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x38,0x3d,0x58,0x4f,0x52,0x28,0x20,0x78,0x38,
0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x31,0x2c,0x78,0x31,0x30,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x39,0x3d,0x58,0x4f,
0x52,0x28,0x20,0x78,0x39,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x38,0x2c,0x78,0x31,0x31,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,
0x0a,0x78,0x31,0x30,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x30,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x20,0x78,0x39,0x2c,0x78,0x38,0x29,
0x2c,0x31,0x38,0x29,0x29,0x3b,0x0a,0x78,0x31,0x32,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x32,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,
0x31,0x35,0x2c,0x78,0x31,0x34,0x29,0x2c,0x37,0x29,0x29,0x3b,0x0a,0x78,0x31,0x33,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x33,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,
0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x32,0x2c,0x78,0x31,0x35,0x29,0x2c,0x39,0x29,0x29,0x3b,0x0a,0x78,0x31,0x34,0x3d,0x58,0x4f,0x52,0x28,0x78,0x31,0x34,0x2c,0x52,
0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x33,0x2c,0x78,0x31,0x32,0x29,0x2c,0x31,0x33,0x29,0x29,0x3b,0x0a,0x78,0x31,0x35,0x3d,0x58,0x4f,
0x52,0x28,0x78,0x31,0x35,0x2c,0x52,0x4f,0x54,0x41,0x54,0x45,0x28,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x34,0x2c,0x78,0x31,0x33,0x29,0x2c,0x31,0x38,0x29,0x29,0x3b,
0x0a,0x7d,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x30,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x30,0x2c,0x6a,0x30,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,
0x5b,0x31,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x2c,0x6a,0x31,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x32,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,
0x78,0x32,0x2c,0x6a,0x32,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x33,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x33,0x2c,0x6a,0x33,0x29,0x3b,0x0a,0x6f,
0x75,0x74,0x70,0x75,0x74,0x5b,0x34,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x34,0x2c,0x6a,0x34,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x35,0x5d,0x3d,
0x50,0x4c,0x55,0x53,0x28,0x78,0x35,0x2c,0x6a,0x35,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x36,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x36,0x2c,0x6a,
0x36,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x37,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x37,0x2c,0x6a,0x37,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,
0x74,0x5b,0x38,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x38,0x2c,0x6a,0x38,0x5f,0x31,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x39,0x5d,0x3d,0x50,0x4c,
0x55,0x53,0x28,0x78,0x39,0x2c,0x6a,0x39,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x30,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x30,0x2c,0x6a,
0x31,0x30,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x31,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x31,0x2c,0x6a,0x31,0x31,0x29,0x3b,0x0a,0x6f,
0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x32,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x32,0x2c,0x6a,0x31,0x32,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,
0x31,0x33,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x33,0x2c,0x6a,0x31,0x33,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x34,0x5d,0x3d,0x50,0x4c,
0x55,0x53,0x28,0x78,0x31,0x34,0x2c,0x6a,0x31,0x34,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b,0x31,0x35,0x5d,0x3d,0x50,0x4c,0x55,0x53,0x28,0x78,0x31,0x35,
0x2c,0x6a,0x31,0x35,0x29,0x3b,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x2b,0x3d,0x28,0x53,0x41,0x4c,0x53,0x41,0x32,0x30,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,
0x5a,0x45,0x2a,0x36,0x34,0x29,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,
0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x47,0x4c,0x4f,0x42,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x69,0x66,0x28,0x74,0x3c,0x31,
0x36,0x29,0x0a,0x7b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x70,0x3d,0x6f,0x75,0x74,0x70,0x75,0x74,
0x73,0x2b,0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2b,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x2b,0x33,0x29,0x2f,
0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x3b,0x0a,0x70,0x5b,0x74,0x5d,0x3d,0x30,0x3b,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x28,
0x74,0x3d,0x3d,0x30,0x29,0x26,0x26,0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x26,0x33,0x29,0x29,0x0a,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x5b,
0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2b,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x29,0x2f,0x73,0x69,0x7a,0x65,
0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x5d,0x20,0x26,0x3d,0x20,0x30,0x78,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x55,0x3e,0x3e,0x28,0x28,
0x34,0x2d,0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x26,0x33,0x29,0x29,0x3c,0x3c,0x33,0x29,0x3b,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,
0x65,0x20,0x52,0x4f,0x55,0x4e,0x44,0x53,0x20,0x32,0x34,0x20,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x52,0x36,0x34,0x28,0x61,0x2c,0x62,0x2c,0x63,0x29,0x20,
0x28,0x28,0x28,0x61,0x29,0x20,0x3c,0x3c,0x20,0x62,0x29,0x20,0x7c,0x20,0x28,0x28,0x61,0x29,0x20,0x3e,0x3e,0x20,0x63,0x29,0x29,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,
0x74,0x61,0x6e,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x72,0x63,0x5b,0x32,0x5d,0x5b,0x52,0x4f,0x55,0x4e,0x44,0x53,
0x5d,0x3d,0x7b,0x0a,0x7b,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x32,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,
0x41,0x55,0x4c,0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x42,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,
0x31,0x55,0x4c,0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,0x31,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x39,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,
0x41,0x55,0x4c,0x2c,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x38,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x30,0x39,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,
0x41,0x55,0x4c,0x2c,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,0x42,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x42,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,
0x39,0x55,0x4c,0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x33,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x32,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,
0x30,0x55,0x4c,0x2c,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x41,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x41,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,
0x31,0x55,0x4c,0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x30,0x55,0x4c,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x55,0x4c,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x30,
0x38,0x55,0x4c,0x7d,0x2c,0x0a,0x7b,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,
0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x0a,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,
0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x0a,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,
0x2c,0x30,0x55,0x4c,0x2c,0x30,0x55,0x4c,0x7d,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,
0x74,0x20,0x72,0x6f,0x5b,0x32,0x35,0x5d,0x5b,0x32,0x5d,0x3d,0x7b,0x0a,0x7b,0x20,0x30,0x2c,0x36,0x34,0x7d,0x2c,0x7b,0x34,0x34,0x2c,0x32,0x30,0x7d,0x2c,0x7b,0x34,
0x33,0x2c,0x32,0x31,0x7d,0x2c,0x7b,0x32,0x31,0x2c,0x34,0x33,0x7d,0x2c,0x7b,0x31,0x34,0x2c,0x35,0x30,0x7d,0x2c,0x0a,0x7b,0x20,0x31,0x2c,0x36,0x33,0x7d,0x2c,0x7b,
0x20,0x36,0x2c,0x35,0x38,0x7d,0x2c,0x7b,0x32,0x35,0x2c,0x33,0x39,0x7d,0x2c,0x7b,0x20,0x38,0x2c,0x35,0x36,0x7d,0x2c,0x7b,0x31,0x38,0x2c,0x34,0x36,0x7d,0x2c,0x0a,
0x7b,0x36,0x32,0x2c,0x32,0x7d,0x2c,0x7b,0x35,0x35,0x2c,0x39,0x7d,0x2c,0x7b,0x33,0x39,0x2c,0x32,0x35,0x7d,0x2c,0x7b,0x34,0x31,0x2c,0x32,0x33,0x7d,0x2c,0x7b,0x20,
0x32,0x2c,0x36,0x32,0x7d,0x2c,0x0a,0x7b,0x32,0x38,0x2c,0x33,0x36,0x7d,0x2c,0x7b,0x32,0x30,0x2c,0x34,0x34,0x7d,0x2c,0x7b,0x20,0x33,0x2c,0x36,0x31,0x7d,0x2c,0x7b,
0x34,0x35,0x2c,0x31,0x39,0x7d,0x2c,0x7b,0x36,0x31,0x2c,0x33,0x7d,0x2c,0x0a,0x7b,0x32,0x37,0x2c,0x33,0x37,0x7d,0x2c,0x7b,0x33,0x36,0x2c,0x32,0x38,0x7d,0x2c,0x7b,
0x31,0x30,0x2c,0x35,0x34,0x7d,0x2c,0x7b,0x31,0x35,0x2c,0x34,0x39,0x7d,0x2c,0x7b,0x35,0x36,0x2c,0x38,0x7d,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,
0x61,0x6e,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x20,0x61,0x5b,0x32,0x35,0x5d,0x3d,0x7b,0x0a,0x30,0x2c,0x36,0x2c,0x31,0x32,0x2c,0x31,0x38,0x2c,
0x32,0x34,0x2c,0x0a,0x31,0x2c,0x37,0x2c,0x31,0x33,0x2c,0x31,0x39,0x2c,0x32,0x30,0x2c,0x0a,0x32,0x2c,0x38,0x2c,0x31,0x34,0x2c,0x31,0x35,0x2c,0x32,0x31,0x2c,0x0a,
0x33,0x2c,0x39,0x2c,0x31,0x30,0x2c,0x31,0x36,0x2c,0x32,0x32,0x2c,0x0a,0x34,0x2c,0x35,0x2c,0x31,0x31,0x2c,0x31,0x37,0x2c,0x32,0x33,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,
0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x20,0x62,0x5b,0x32,0x35,0x5d,0x3d,0x7b,0x0a,0x30,0x2c,0x31,0x2c,0x32,
0x2c,0x33,0x2c,0x34,0x2c,0x0a,0x31,0x2c,0x32,0x2c,0x33,0x2c,0x34,0x2c,0x30,0x2c,0x0a,0x32,0x2c,0x33,0x2c,0x34,0x2c,0x30,0x2c,0x31,0x2c,0x0a,0x33,0x2c,0x34,0x2c,
0x30,0x2c,0x31,0x2c,0x32,0x2c,0x0a,0x34,0x2c,0x30,0x2c,0x31,0x2c,0x32,0x2c,0x33,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x63,
0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x20,0x63,0x5b,0x32,0x35,0x5d,0x5b,0x33,0x5d,0x3d,0x7b,0x0a,0x7b,0x20,0x30,0x2c,0x31,0x2c,0x32,0x7d,0x2c,0x7b,0x20,0x31,
0x2c,0x32,0x2c,0x33,0x7d,0x2c,0x7b,0x20,0x32,0x2c,0x33,0x2c,0x34,0x7d,0x2c,0x7b,0x20,0x33,0x2c,0x34,0x2c,0x30,0x7d,0x2c,0x7b,0x20,0x34,0x2c,0x30,0x2c,0x31,0x7d,
0x2c,0x0a,0x7b,0x20,0x35,0x2c,0x36,0x2c,0x37,0x7d,0x2c,0x7b,0x20,0x36,0x2c,0x37,0x2c,0x38,0x7d,0x2c,0x7b,0x20,0x37,0x2c,0x38,0x2c,0x39,0x7d,0x2c,0x7b,0x20,0x38,
0x2c,0x39,0x2c,0x35,0x7d,0x2c,0x7b,0x20,0x39,0x2c,0x35,0x2c,0x36,0x7d,0x2c,0x0a,0x7b,0x31,0x30,0x2c,0x31,0x31,0x2c,0x31,0x32,0x7d,0x2c,0x7b,0x31,0x31,0x2c,0x31,
0x32,0x2c,0x31,0x33,0x7d,0x2c,0x7b,0x31,0x32,0x2c,0x31,0x33,0x2c,0x31,0x34,0x7d,0x2c,0x7b,0x31,0x33,0x2c,0x31,0x34,0x2c,0x31,0x30,0x7d,0x2c,0x7b,0x31,0x34,0x2c,
0x31,0x30,0x2c,0x31,0x31,0x7d,0x2c,0x0a,0x7b,0x31,0x35,0x2c,0x31,0x36,0x2c,0x31,0x37,0x7d,0x2c,0x7b,0x31,0x36,0x2c,0x31,0x37,0x2c,0x31,0x38,0x7d,0x2c,0x7b,0x31,
0x37,0x2c,0x31,0x38,0x2c,0x31,0x39,0x7d,0x2c,0x7b,0x31,0x38,0x2c,0x31,0x39,0x2c,0x31,0x35,0x7d,0x2c,0x7b,0x31,0x39,0x2c,0x31,0x35,0x2c,0x31,0x36,0x7d,0x2c,0x0a,
0x7b,0x32,0x30,0x2c,0x32,0x31,0x2c,0x32,0x32,0x7d,0x2c,0x7b,0x32,0x31,0x2c,0x32,0x32,0x2c,0x32,0x33,0x7d,0x2c,0x7b,0x32,0x32,0x2c,0x32,0x33,0x2c,0x32,0x34,0x7d,
0x2c,0x7b,0x32,0x33,0x2c,0x32,0x34,0x2c,0x32,0x30,0x7d,0x2c,0x7b,0x32,0x34,0x2c,0x32,0x30,0x2c,0x32,0x31,0x7d,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x63,0x6f,0x6e,0x73,
0x74,0x61,0x6e,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x69,0x6e,0x74,0x20,0x64,0x5b,0x32,0x35,0x5d,0x3d,0x7b,0x0a,0x30,0x2c,0x31,0x2c,0x32,0x2c,0x33,0x2c,0x34,
0x2c,0x0a,0x31,0x30,0x2c,0x31,0x31,0x2c,0x31,0x32,0x2c,0x31,0x33,0x2c,0x31,0x34,0x2c,0x0a,0x32,0x30,0x2c,0x32,0x31,0x2c,0x32,0x32,0x2c,0x32,0x33,0x2c,0x32,0x34,
0x2c,0x0a,0x35,0x2c,0x36,0x2c,0x37,0x2c,0x38,0x2c,0x39,0x2c,0x0a,0x31,0x35,0x2c,0x31,0x36,0x2c,0x31,0x37,0x2c,0x31,0x38,0x2c,0x31,0x39,0x0a,0x7d,0x3b,0x0a,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,0x33,0x32,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x73,0x68,0x61,0x33,0x28,
0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x38,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x73,0x2c,0x5f,
0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,
0x7a,0x65,0x73,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x74,0x72,0x69,0x64,0x65,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,
0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x65,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,
0x74,0x33,0x32,0x5f,0x74,0x20,0x74,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x3d,0x67,0x65,0x74,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x74,0x3e,
0x3d,0x32,0x35,0x29,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x3d,0x74,0x20,
0x25,0x20,0x35,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,
0x3d,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x74,0x72,0x69,0x64,0x65,0x29,0x2a,0x67,0x3b,0x0a,0x5f,0x5f,0x67,
0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x3d,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,
0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x29,0x28,0x69,0x6e,0x70,0x75,0x74,0x73,0x2b,0x69,0x6e,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x29,0x3b,
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x69,0x6e,0x70,0x75,0x74,
0x5f,0x73,0x69,0x7a,0x65,0x73,0x5b,0x67,0x5d,0x2b,0x31,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x41,0x5b,
0x32,0x35,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x43,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,
0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x44,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x41,0x5b,0x74,0x5d,0x3d,0x30,0x3b,0x0a,0x63,0x6f,0x6e,
0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x77,0x6f,0x72,0x64,0x73,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x2f,0x73,0x69,0x7a,
0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x74,0x61,
0x69,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x20,0x25,0x20,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,
0x36,0x34,0x5f,0x74,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3d,0x30,0x3b,0x0a,0x66,0x6f,0x72,
0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x77,0x6f,0x72,0x64,0x73,0x3b,0x20,0x2b,0x2b,0x69,0x2c,0x2b,0x2b,0x69,
0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x41,0x5b,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x5d,0x20,0x5e,0x3d,0x20,0x2a,0x69,0x6e,0x70,0x75,0x74,0x3b,0x0a,
0x2b,0x2b,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3b,0x0a,0x69,0x66,0x28,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3d,0x3d,0x31,0x37,0x29,0x0a,0x7b,
0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x28,0x52,0x4f,0x55,0x4e,0x44,0x53,0x29,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,
0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x52,0x4f,0x55,0x4e,0x44,0x53,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x7b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x41,0x5b,0x73,0x5d,
0x5e,0x41,0x5b,0x73,0x2b,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x30,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x32,0x30,0x5d,0x3b,
0x0a,0x44,0x5b,0x74,0x5d,0x3d,0x43,0x5b,0x62,0x5b,0x32,0x30,0x2b,0x73,0x5d,0x5d,0x5e,0x52,0x36,0x34,0x28,0x43,0x5b,0x62,0x5b,0x35,0x2b,0x73,0x5d,0x5d,0x2c,0x31,
0x2c,0x36,0x33,0x29,0x3b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x52,0x36,0x34,0x28,0x41,0x5b,0x61,0x5b,0x74,0x5d,0x5d,0x5e,0x44,0x5b,0x62,0x5b,0x74,0x5d,0x5d,0x2c,0x72,
0x6f,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x64,0x5b,0x74,0x5d,0x5d,0x3d,0x43,0x5b,0x63,0x5b,0x74,
0x5d,0x5b,0x30,0x5d,0x5d,0x5e,0x28,0x28,0x7e,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x5d,0x29,0x26,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x32,0x5d,0x5d,0x29,
0x3b,0x0a,0x41,0x5b,0x74,0x5d,0x20,0x5e,0x3d,0x20,0x72,0x63,0x5b,0x28,0x74,0x3d,0x3d,0x30,0x29,0x3f,0x30,0x3a,0x31,0x5d,0x5b,0x69,0x5d,0x3b,0x20,0x0a,0x7d,0x0a,
0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3d,0x30,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x74,0x61,0x69,0x6c,0x3d,0x30,
0x3b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x38,0x5f,0x74,0x2a,0x20,0x70,0x3d,0x28,0x5f,0x5f,0x67,
0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x38,0x5f,0x74,0x2a,0x29,0x69,0x6e,0x70,0x75,0x74,0x3b,0x0a,0x66,0x6f,0x72,0x20,
0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x74,0x61,0x69,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x3b,0x20,0x2b,0x2b,0x69,0x29,
0x0a,0x7b,0x0a,0x74,0x61,0x69,0x6c,0x7c,0x3d,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x28,0x70,0x5b,0x69,0x5d,0x29,0x3c,0x3c,0x28,0x69,0x2a,0x38,0x29,
0x3b,0x0a,0x7d,0x0a,0x41,0x5b,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x61,0x69,0x6c,0x5e,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,
0x34,0x5f,0x74,0x29,0x28,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x28,0x30,0x78,0x30,0x32,0x7c,0x28,0x31,0x3c,0x3c,0x32,0x29,0x29,0x29,0x3c,0x3c,
0x28,0x74,0x61,0x69,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x2a,0x38,0x29,0x29,0x29,0x3b,0x0a,0x41,0x5b,0x31,0x36,0x5d,0x20,0x5e,0x3d,0x20,0x30,0x78,0x38,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x4c,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x28,0x31,
0x29,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x52,0x4f,0x55,0x4e,0x44,0x53,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x7b,
0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x41,0x5b,0x73,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x30,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x35,
0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x32,0x30,0x5d,0x3b,0x0a,0x44,0x5b,0x74,0x5d,0x3d,0x43,0x5b,0x62,0x5b,0x32,0x30,0x2b,0x73,0x5d,0x5d,0x5e,0x52,0x36,0x34,0x28,0x43,
0x5b,0x62,0x5b,0x35,0x2b,0x73,0x5d,0x5d,0x2c,0x31,0x2c,0x36,0x33,0x29,0x3b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x52,0x36,0x34,0x28,0x41,0x5b,0x61,0x5b,0x74,0x5d,0x5d,
0x5e,0x44,0x5b,0x62,0x5b,0x74,0x5d,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x64,
0x5b,0x74,0x5d,0x5d,0x3d,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x5d,0x5e,0x28,0x28,0x7e,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x5d,0x29,0x26,0x43,
0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x32,0x5d,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x74,0x5d,0x20,0x5e,0x3d,0x20,0x72,0x63,0x5b,0x28,0x74,0x3d,0x3d,0x30,0x29,0x3f,0x30,0x3a,
0x31,0x5d,0x5b,0x69,0x5d,0x3b,0x20,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x74,0x3c,0x34,0x29,0x0a,0x7b,0x0a,0x68,0x61,0x73,0x68,0x65,0x73,0x2b,0x3d,0x67,0x2a,0x28,0x33,
0x32,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x29,0x3b,0x0a,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x74,0x5d,0x3d,0x41,
0x5b,0x74,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,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,0x33,0x32,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,
0x76,0x6f,0x69,0x64,0x20,0x73,0x68,0x61,0x33,0x5f,0x69,0x6e,0x69,0x74,0x69,0x61,0x6c,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,
0x20,0x75,0x69,0x6e,0x74,0x38,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x64,0x61,0x74,0x61,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x6e,
0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6e,0x6f,0x6e,0x63,0x65,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,
0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x65,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,
0x32,0x5f,0x74,0x20,0x74,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,
0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x3d,0x67,0x65,0x74,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x74,0x3e,0x3d,0x32,
0x35,0x29,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x3d,0x74,0x20,0x25,0x20,
0x35,0x3b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x3d,0x28,0x5f,0x5f,0x67,
0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x29,0x28,0x69,0x6e,0x70,0x75,0x74,0x5f,0x64,0x61,0x74,0x61,0x29,0x3b,0x0a,0x5f,0x5f,
0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x41,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,
0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x43,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x44,
0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x41,0x5b,0x74,0x5d,0x3d,0x28,0x74,0x3c,0x31,0x36,0x29,0x3f,0x69,0x6e,0x70,0x75,0x74,0x5b,0x74,0x5d,0x3a,0x30,0x3b,0x0a,0x5f,0x5f,
0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,0x6f,0x73,0x3d,0x28,0x5f,0x5f,0x6c,0x6f,0x63,
0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x29,0x28,0x41,0x29,0x2b,0x39,0x3b,0x0a,0x6e,0x6f,0x6e,0x63,0x65,0x2b,0x3d,0x67,0x3b,0x0a,0x6e,0x6f,
0x6e,0x63,0x65,0x5f,0x70,0x6f,0x73,0x5b,0x30,0x5d,0x3d,0x28,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,0x6f,0x73,0x5b,0x30,0x5d,0x26,0x30,0x78,0x46,0x46,0x46,0x46,0x46,
0x46,0x55,0x29,0x7c,0x28,0x28,0x6e,0x6f,0x6e,0x63,0x65,0x26,0x30,0x78,0x46,0x46,0x29,0x3c,0x3c,0x32,0x34,0x29,0x3b,0x0a,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,0x6f,
0x73,0x5b,0x31,0x5d,0x3d,0x28,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,0x6f,0x73,0x5b,0x31,0x5d,0x26,0x30,0x78,0x46,0x46,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x29,0x7c,
0x28,0x6e,0x6f,0x6e,0x63,0x65,0x3e,0x3e,0x38,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3d,0x69,
0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x74,0x61,0x69,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x20,
0x25,0x20,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x3b,0x0a,0x41,0x5b,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x5d,
0x20,0x5e,0x3d,0x20,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x28,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x28,0x30,0x78,0x30,0x32,0x7c,
0x28,0x31,0x3c,0x3c,0x32,0x29,0x29,0x29,0x3c,0x3c,0x28,0x74,0x61,0x69,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x2a,0x38,0x29,0x29,0x3b,0x0a,0x41,0x5b,0x31,0x36,0x5d,0x20,
0x5e,0x3d,0x20,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x4c,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,
0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x28,0x52,0x4f,0x55,0x4e,0x44,0x53,0x29,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,
0x52,0x4f,0x55,0x4e,0x44,0x53,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x7b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x41,0x5b,0x73,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x35,0x5d,0x5e,
0x41,0x5b,0x73,0x2b,0x31,0x30,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x32,0x30,0x5d,0x3b,0x0a,0x44,0x5b,0x74,0x5d,0x3d,0x43,0x5b,
0x62,0x5b,0x32,0x30,0x2b,0x73,0x5d,0x5d,0x5e,0x52,0x36,0x34,0x28,0x43,0x5b,0x62,0x5b,0x35,0x2b,0x73,0x5d,0x5d,0x2c,0x31,0x2c,0x36,0x33,0x29,0x3b,0x0a,0x43,0x5b,
0x74,0x5d,0x3d,0x52,0x36,0x34,0x28,0x41,0x5b,0x61,0x5b,0x74,0x5d,0x5d,0x5e,0x44,0x5b,0x62,0x5b,0x74,0x5d,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x2c,
0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x64,0x5b,0x74,0x5d,0x5d,0x3d,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x5d,0x5e,0x28,0x28,
0x7e,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x5d,0x29,0x26,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x32,0x5d,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x74,0x5d,0x20,0x5e,
0x3d,0x20,0x72,0x63,0x5b,0x28,0x74,0x3d,0x3d,0x30,0x29,0x3f,0x30,0x3a,0x31,0x5d,0x5b,0x69,0x5d,0x3b,0x20,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x74,0x3c,0x34,0x29,0x0a,
0x7b,0x0a,0x68,0x61,0x73,0x68,0x65,0x73,0x2b,0x3d,0x67,0x2a,0x28,0x33,0x32,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,
0x29,0x3b,0x0a,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x74,0x5d,0x3d,0x41,0x5b,0x74,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x00
0x33,0x32,0x5f,0x74,0x20,0x67,0x3d,0x67,0x65,0x74,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x74,0x3e,0x3d,0x32,0x35,
0x29,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x3d,0x74,0x20,0x25,0x20,0x35,
0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x28,0x28,
0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x74,0x72,0x69,0x64,0x65,0x29,0x2a,0x67,0x3b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,
0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x3d,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,
0x74,0x36,0x34,0x5f,0x74,0x2a,0x29,0x28,0x69,0x6e,0x70,0x75,0x74,0x73,0x2b,0x69,0x6e,0x70,0x75,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x29,0x3b,0x0a,0x63,0x6f,
0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,
0x7a,0x65,0x73,0x5b,0x67,0x5d,0x2b,0x31,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x41,0x5b,0x32,0x35,0x5d,
0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x43,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,
0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x44,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x41,0x5b,0x74,0x5d,0x3d,0x30,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,
0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x77,0x6f,0x72,0x64,0x73,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,
0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x74,0x61,0x69,0x6c,0x5f,
0x73,0x69,0x7a,0x65,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x20,0x25,0x20,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,
0x74,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3d,0x30,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x77,0x6f,0x72,0x64,0x73,0x3b,0x20,0x2b,0x2b,0x69,0x2c,0x2b,0x2b,0x69,0x6e,0x70,0x75,
0x74,0x29,0x0a,0x7b,0x0a,0x41,0x5b,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x5d,0x20,0x5e,0x3d,0x20,0x2a,0x69,0x6e,0x70,0x75,0x74,0x3b,0x0a,0x2b,0x2b,0x77,
0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3b,0x0a,0x69,0x66,0x28,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3d,0x3d,0x31,0x37,0x29,0x0a,0x7b,0x0a,0x23,0x70,
0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x52,0x4f,0x55,0x4e,0x44,0x53,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,
0x3b,0x20,0x69,0x3c,0x52,0x4f,0x55,0x4e,0x44,0x53,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x7b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x41,0x5b,0x73,0x5d,0x5e,0x41,0x5b,0x73,
0x2b,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x30,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x32,0x30,0x5d,0x3b,0x0a,0x44,0x5b,0x74,
0x5d,0x3d,0x43,0x5b,0x62,0x5b,0x32,0x30,0x2b,0x73,0x5d,0x5d,0x5e,0x52,0x36,0x34,0x28,0x43,0x5b,0x62,0x5b,0x35,0x2b,0x73,0x5d,0x5d,0x2c,0x31,0x2c,0x36,0x33,0x29,
0x3b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x52,0x36,0x34,0x28,0x41,0x5b,0x61,0x5b,0x74,0x5d,0x5d,0x5e,0x44,0x5b,0x62,0x5b,0x74,0x5d,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,
0x5b,0x30,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x64,0x5b,0x74,0x5d,0x5d,0x3d,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x30,0x5d,
0x5d,0x5e,0x28,0x28,0x7e,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x5d,0x29,0x26,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x32,0x5d,0x5d,0x29,0x3b,0x0a,0x41,0x5b,
0x74,0x5d,0x20,0x5e,0x3d,0x20,0x72,0x63,0x5b,0x28,0x74,0x3d,0x3d,0x30,0x29,0x3f,0x30,0x3a,0x31,0x5d,0x5b,0x69,0x5d,0x3b,0x20,0x0a,0x7d,0x0a,0x77,0x6f,0x72,0x64,
0x49,0x6e,0x64,0x65,0x78,0x3d,0x30,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x74,0x61,0x69,0x6c,0x3d,0x30,0x3b,0x0a,0x5f,0x5f,
0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x38,0x5f,0x74,0x2a,0x20,0x70,0x3d,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,
0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x38,0x5f,0x74,0x2a,0x29,0x69,0x6e,0x70,0x75,0x74,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,
0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x74,0x61,0x69,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x7b,0x0a,0x74,
0x61,0x69,0x6c,0x7c,0x3d,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x28,0x70,0x5b,0x69,0x5d,0x29,0x3c,0x3c,0x28,0x69,0x2a,0x38,0x29,0x3b,0x0a,0x7d,0x0a,
0x41,0x5b,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x61,0x69,0x6c,0x5e,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,
0x28,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x28,0x30,0x78,0x30,0x32,0x7c,0x28,0x31,0x3c,0x3c,0x32,0x29,0x29,0x29,0x3c,0x3c,0x28,0x74,0x61,0x69,
0x6c,0x5f,0x73,0x69,0x7a,0x65,0x2a,0x38,0x29,0x29,0x29,0x3b,0x0a,0x41,0x5b,0x31,0x36,0x5d,0x20,0x5e,0x3d,0x20,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x4c,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,
0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x52,0x4f,0x55,0x4e,0x44,0x53,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x7b,0x0a,0x43,0x5b,0x74,0x5d,
0x3d,0x41,0x5b,0x73,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x30,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x35,0x5d,0x5e,0x41,0x5b,0x73,
0x2b,0x32,0x30,0x5d,0x3b,0x0a,0x44,0x5b,0x74,0x5d,0x3d,0x43,0x5b,0x62,0x5b,0x32,0x30,0x2b,0x73,0x5d,0x5d,0x5e,0x52,0x36,0x34,0x28,0x43,0x5b,0x62,0x5b,0x35,0x2b,
0x73,0x5d,0x5d,0x2c,0x31,0x2c,0x36,0x33,0x29,0x3b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x52,0x36,0x34,0x28,0x41,0x5b,0x61,0x5b,0x74,0x5d,0x5d,0x5e,0x44,0x5b,0x62,0x5b,
0x74,0x5d,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x64,0x5b,0x74,0x5d,0x5d,0x3d,
0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x5d,0x5e,0x28,0x28,0x7e,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x31,0x5d,0x5d,0x29,0x26,0x43,0x5b,0x63,0x5b,0x74,0x5d,
0x5b,0x32,0x5d,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x74,0x5d,0x20,0x5e,0x3d,0x20,0x72,0x63,0x5b,0x28,0x74,0x3d,0x3d,0x30,0x29,0x3f,0x30,0x3a,0x31,0x5d,0x5b,0x69,0x5d,
0x3b,0x20,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x74,0x3c,0x34,0x29,0x0a,0x7b,0x0a,0x68,0x61,0x73,0x68,0x65,0x73,0x2b,0x3d,0x67,0x2a,0x28,0x33,0x32,0x2f,0x73,0x69,0x7a,
0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x29,0x3b,0x0a,0x68,0x61,0x73,0x68,0x65,0x73,0x5b,0x74,0x5d,0x3d,0x41,0x5b,0x74,0x5d,0x3b,0x0a,
0x7d,0x0a,0x7d,0x0a,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,0x33,0x32,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,
0x73,0x68,0x61,0x33,0x5f,0x69,0x6e,0x69,0x74,0x69,0x61,0x6c,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x38,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x64,0x61,0x74,0x61,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,
0x69,0x7a,0x65,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6e,0x6f,0x6e,0x63,0x65,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,
0x36,0x34,0x5f,0x74,0x2a,0x20,0x68,0x61,0x73,0x68,0x65,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x74,
0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,
0x20,0x67,0x3d,0x67,0x65,0x74,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x74,0x3e,0x3d,0x32,0x35,0x29,0x0a,0x72,0x65,
0x74,0x75,0x72,0x6e,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x3d,0x74,0x20,0x25,0x20,0x35,0x3b,0x0a,0x5f,0x5f,
0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x20,0x69,0x6e,0x70,0x75,0x74,0x3d,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,
0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x2a,0x29,0x28,0x69,0x6e,0x70,0x75,0x74,0x5f,0x64,0x61,0x74,0x61,0x29,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,
0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x41,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,
0x74,0x20,0x43,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x44,0x5b,0x32,0x35,0x5d,0x3b,
0x0a,0x41,0x5b,0x74,0x5d,0x3d,0x28,0x74,0x3c,0x31,0x36,0x29,0x3f,0x69,0x6e,0x70,0x75,0x74,0x5b,0x74,0x5d,0x3a,0x30,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,
0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,0x6f,0x73,0x3d,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,
0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x29,0x28,0x41,0x29,0x2b,0x39,0x3b,0x0a,0x6e,0x6f,0x6e,0x63,0x65,0x2b,0x3d,0x67,0x3b,0x0a,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,
0x6f,0x73,0x5b,0x30,0x5d,0x3d,0x28,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,0x6f,0x73,0x5b,0x30,0x5d,0x26,0x30,0x78,0x46,0x46,0x46,0x46,0x46,0x46,0x55,0x29,0x7c,0x28,
0x28,0x6e,0x6f,0x6e,0x63,0x65,0x26,0x30,0x78,0x46,0x46,0x29,0x3c,0x3c,0x32,0x34,0x29,0x3b,0x0a,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,0x6f,0x73,0x5b,0x31,0x5d,0x3d,
0x28,0x6e,0x6f,0x6e,0x63,0x65,0x5f,0x70,0x6f,0x73,0x5b,0x31,0x5d,0x26,0x30,0x78,0x46,0x46,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x29,0x7c,0x28,0x6e,0x6f,0x6e,0x63,
0x65,0x3e,0x3e,0x38,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5f,
0x73,0x69,0x7a,0x65,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,
0x74,0x33,0x32,0x5f,0x74,0x20,0x74,0x61,0x69,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5f,0x73,0x69,0x7a,0x65,0x20,0x25,0x20,0x73,0x69,0x7a,
0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x3b,0x0a,0x41,0x5b,0x77,0x6f,0x72,0x64,0x49,0x6e,0x64,0x65,0x78,0x5d,0x20,0x5e,0x3d,0x20,0x28,
0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x28,0x28,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x28,0x30,0x78,0x30,0x32,0x7c,0x28,0x31,0x3c,0x3c,0x32,
0x29,0x29,0x29,0x3c,0x3c,0x28,0x74,0x61,0x69,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x2a,0x38,0x29,0x29,0x3b,0x0a,0x41,0x5b,0x31,0x36,0x5d,0x20,0x5e,0x3d,0x20,0x30,0x78,
0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x4c,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,
0x6c,0x6c,0x20,0x52,0x4f,0x55,0x4e,0x44,0x53,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x52,0x4f,0x55,0x4e,0x44,0x53,
0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x7b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x41,0x5b,0x73,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x30,
0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x31,0x35,0x5d,0x5e,0x41,0x5b,0x73,0x2b,0x32,0x30,0x5d,0x3b,0x0a,0x44,0x5b,0x74,0x5d,0x3d,0x43,0x5b,0x62,0x5b,0x32,0x30,0x2b,0x73,
0x5d,0x5d,0x5e,0x52,0x36,0x34,0x28,0x43,0x5b,0x62,0x5b,0x35,0x2b,0x73,0x5d,0x5d,0x2c,0x31,0x2c,0x36,0x33,0x29,0x3b,0x0a,0x43,0x5b,0x74,0x5d,0x3d,0x52,0x36,0x34,
0x28,0x41,0x5b,0x61,0x5b,0x74,0x5d,0x5d,0x5e,0x44,0x5b,0x62,0x5b,0x74,0x5d,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x2c,0x72,0x6f,0x5b,0x74,0x5d,0x5b,
0x31,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x64,0x5b,0x74,0x5d,0x5d,0x3d,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x30,0x5d,0x5d,0x5e,0x28,0x28,0x7e,0x43,0x5b,0x63,0x5b,0x74,
0x5d,0x5b,0x31,0x5d,0x5d,0x29,0x26,0x43,0x5b,0x63,0x5b,0x74,0x5d,0x5b,0x32,0x5d,0x5d,0x29,0x3b,0x0a,0x41,0x5b,0x74,0x5d,0x20,0x5e,0x3d,0x20,0x72,0x63,0x5b,0x28,
0x74,0x3d,0x3d,0x30,0x29,0x3f,0x30,0x3a,0x31,0x5d,0x5b,0x69,0x5d,0x3b,0x20,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x74,0x3c,0x34,0x29,0x0a,0x7b,0x0a,0x68,0x61,0x73,0x68,
0x65,0x73,0x2b,0x3d,0x67,0x2a,0x28,0x33,0x32,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x29,0x3b,0x0a,0x68,0x61,0x73,
0x68,0x65,0x73,0x5b,0x74,0x5d,0x3d,0x41,0x5b,0x74,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x00
};
} // namespace xmrig

View File

@@ -82,7 +82,7 @@ __kernel void Salsa20_XORKeyStream(__global const uint32_t* keys, __global uint3
uint32_t x14 = j14;
uint32_t x15 = j15;
#pragma unroll(5)
#pragma unroll 5
for (uint32_t j = 0; j < 10; ++j)
{
x4 = XOR( x4,ROTATE(PLUS( x0,x12), 7));

View File

@@ -111,7 +111,7 @@ __kernel void sha3(__global const uint8_t* inputs, __global const uint32_t* inpu
++wordIndex;
if (wordIndex == 17)
{
#pragma unroll(ROUNDS)
#pragma unroll ROUNDS
for (int i = 0; i < ROUNDS; ++i)
{
C[t] = A[s] ^ A[s+5] ^ A[s+10] ^ A[s+15] ^ A[s+20];
@@ -133,7 +133,7 @@ __kernel void sha3(__global const uint8_t* inputs, __global const uint32_t* inpu
A[wordIndex] ^= tail ^ ((uint64_t)(((uint64_t)(0x02 | (1 << 2))) << (tail_size * 8)));
A[16] ^= 0x8000000000000000UL;
#pragma unroll(1)
#pragma unroll 1
for (int i = 0; i < ROUNDS; ++i)
{
C[t] = A[s] ^ A[s+5] ^ A[s+10] ^ A[s+15] ^ A[s+20];
@@ -180,7 +180,7 @@ __kernel void sha3_initial(__global const uint8_t* input_data, uint32_t input_si
A[wordIndex] ^= (uint64_t)(((uint64_t)(0x02 | (1 << 2))) << (tail_size * 8));
A[16] ^= 0x8000000000000000UL;
#pragma unroll(ROUNDS)
#pragma unroll ROUNDS
for (int i = 0; i < ROUNDS; ++i)
{
C[t] = A[s] ^ A[s+5] ^ A[s+10] ^ A[s+15] ^ A[s+20];

View File

@@ -71,7 +71,7 @@ inline ulong getIdx()
__attribute__((reqd_work_group_size(8, 8, 1)))
__kernel void cn0(__global ulong *input, __global uint4 *Scratchpad, __global ulong *states, uint Threads)
__kernel void cn0(__global ulong *input, int inlen, __global uint4 *Scratchpad, __global ulong *states, uint Threads)
{
uint ExpandedKey1[40];
__local uint AES0[256], AES1[256], AES2[256], AES3[256];
@@ -109,34 +109,25 @@ __kernel void cn0(__global ulong *input, __global uint4 *Scratchpad, __global ul
if (get_local_id(1) == 0) {
__local ulong* State = State_buf + get_local_id(0) * 25;
((__local ulong8 *)State)[0] = vload8(0, input);
State[8] = input[8];
State[9] = input[9];
State[10] = input[10];
State[11] = input[11];
State[12] = input[12];
State[13] = input[13];
State[14] = input[14];
State[15] = input[15];
((__local uint *)State)[9] &= 0x00FFFFFFU;
((__local uint *)State)[9] |= (((uint)get_global_id(0)) & 0xFF) << 24;
((__local uint *)State)[10] &= 0xFF000000U;
/* explicit cast to `uint` is required because some OpenCL implementations (e.g. NVIDIA)
* handle get_global_id and get_global_offset as signed long long int and add
* 0xFFFFFFFF... to `get_global_id` if we set on host side a 32bit offset where the first bit is `1`
* (even if it is correct casted to unsigned on the host)
*/
((__local uint *)State)[10] |= (((uint)get_global_id(0) >> 8));
// Last bit of padding
State[16] = 0x8000000000000000UL;
for (int i = 17; i < 25; ++i) {
State[i] = 0x00UL;
#pragma unroll
for (int i = 0; i < 25; ++i) {
State[i] = 0;
}
keccakf1600_2(State);
// Input length must be a multiple of 136 and padded on the host side
for (int i = 0; inlen > 0; i += 17, inlen -= 136) {
#pragma unroll
for (int j = 0; j < 17; ++j) {
State[j] ^= input[i + j];
}
if (i == 0) {
((__local uint *)State)[9] &= 0x00FFFFFFU;
((__local uint *)State)[9] |= (((uint)get_global_id(0)) & 0xFF) << 24;
((__local uint *)State)[10] &= 0xFF000000U;
((__local uint *)State)[10] |= (((uint)get_global_id(0) >> 8));
}
keccakf1600_2(State);
}
#pragma unroll 1
for (int i = 0; i < 25; ++i) {
@@ -908,7 +899,7 @@ __kernel void Blake(__global ulong *states, __global uint *BranchBuf, __global u
((uint8 *)h)[0] = vload8(0U, c_IV256);
for (uint i = 0; i < 3; ++i) {
for (volatile uint i = 0; i < 3; ++i) {
((uint16 *)m)[0] = vload16(i, (__global uint *)states);
for (uint x = 0; x < 16; ++x) {
m[x] = SWAP4(m[x]);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -38,10 +38,11 @@ void xmrig::Cn0Kernel::enqueue(cl_command_queue queue, uint32_t nonce, size_t th
// __kernel void cn0(__global ulong *input, __global uint4 *Scratchpad, __global ulong *states, uint Threads)
void xmrig::Cn0Kernel::setArgs(cl_mem input, cl_mem scratchpads, cl_mem states, uint32_t threads)
void xmrig::Cn0Kernel::setArgs(cl_mem input, int inlen, cl_mem scratchpads, cl_mem states, uint32_t threads)
{
setArg(0, sizeof(cl_mem), &input);
setArg(1, sizeof(cl_mem), &scratchpads);
setArg(2, sizeof(cl_mem), &states);
setArg(3, sizeof(uint32_t), &threads);
setArg(1, sizeof(int), &inlen);
setArg(2, sizeof(cl_mem), &scratchpads);
setArg(3, sizeof(cl_mem), &states);
setArg(4, sizeof(uint32_t), &threads);
}

View File

@@ -38,7 +38,7 @@ public:
inline Cn0Kernel(cl_program program) : OclKernel(program, "cn0") {}
void enqueue(cl_command_queue queue, uint32_t nonce, size_t threads);
void setArgs(cl_mem input, cl_mem scratchpads, cl_mem states, uint32_t threads);
void setArgs(cl_mem input, int inlen, cl_mem scratchpads, cl_mem states, uint32_t threads);
};

View File

@@ -1,3 +1,9 @@
if (BUILD_STATIC AND XMRIG_OS_UNIX AND WITH_OPENCL)
message(WARNING "OpenCL backend is not compatible with static build, use -DWITH_OPENCL=OFF to suppress this warning")
set(WITH_OPENCL OFF)
endif()
if (WITH_OPENCL)
add_definitions(/DCL_TARGET_OPENCL_VERSION=200)
add_definitions(/DCL_USE_DEPRECATED_OPENCL_1_2_APIS)

View File

@@ -122,10 +122,16 @@ void xmrig::OclCnRunner::set(const Job &job, uint8_t *blob)
throw std::length_error("job size too big");
}
blob[job.size()] = 0x01;
memset(blob + job.size() + 1, 0, Job::kMaxBlobSize - job.size() - 1);
const int inlen = static_cast<int>(job.size() + 136 - (job.size() % 136));
enqueueWriteBuffer(m_input, CL_TRUE, 0, Job::kMaxBlobSize, blob);
blob[job.size()] = 0x01;
memset(blob + job.size() + 1, 0, inlen - job.size() - 1);
blob[inlen - 1] |= 0x80;
enqueueWriteBuffer(m_input, CL_TRUE, 0, inlen, blob);
m_cn0->setArg(1, sizeof(int), &inlen);
if (m_algorithm == Algorithm::CN_R && m_height != job.height()) {
delete m_cn1;
@@ -152,7 +158,7 @@ void xmrig::OclCnRunner::build()
OclBaseRunner::build();
m_cn0 = new Cn0Kernel(m_program);
m_cn0->setArgs(m_input, m_scratchpads, m_states, m_intensity);
m_cn0->setArgs(m_input, 0, m_scratchpads, m_states, m_intensity);
m_cn2 = new Cn2Kernel(m_program);
m_cn2->setArgs(m_scratchpads, m_states, m_branches, m_intensity);

View File

@@ -157,7 +157,7 @@ void OclKawPowRunner::set(const Job &job, uint8_t *blob)
const uint32_t dag_words = dag_size / sizeof(node);
m_calculateDagKernel->setArgs(0, m_lightCache, m_dag, dag_words, m_lightCacheSize / sizeof(node));
constexpr uint32_t N = 1 << 20;
constexpr uint32_t N = 1 << 18;
for (uint32_t start = 0; start < dag_words; start += N) {
m_calculateDagKernel->setArg(0, sizeof(start), &start);

View File

@@ -1,6 +1,7 @@
/* XMRig
* Copyright 2008-2018 Advanced Micro Devices, Inc.
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2020 Patrick Bollinger <https://github.com/pjbollinger>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -82,7 +83,7 @@ static inline std::string sysfs_prefix(const PciTopology &topology)
for (uint32_t i = 1; i < 10; ++i) {
const std::string prefix = path + std::to_string(i) + "/";
if (sysfs_is_amdgpu(prefix + "name") && sysfs_read(prefix + "freq1_input")) {
if (sysfs_is_amdgpu(prefix + "name") && (sysfs_read(prefix + "temp1_input") || sysfs_read(prefix + "power1_average"))) {
return prefix;
}
}
@@ -116,6 +117,7 @@ void xmrig::AdlLib::close()
}
// https://dri.freedesktop.org/docs/drm/gpu/amdgpu.html#gpu-power-thermal-controls-and-monitoring
AdlHealth xmrig::AdlLib::health(const OclDevice &device)
{
if (!isReady() || device.vendorId() != OCL_VENDOR_AMD) {
@@ -134,6 +136,10 @@ AdlHealth xmrig::AdlLib::health(const OclDevice &device)
health.rpm = sysfs_read(prefix + "fan1_input");
health.temperature = sysfs_read(prefix + "temp2_input") / 1000;
if (!health.temperature) {
health.temperature = sysfs_read(prefix + "temp1_input") / 1000;
}
return health;
}

View File

@@ -44,7 +44,7 @@
static uv_lib_t oclLib;
static const char *kErrorTemplate = MAGENTA_BG_BOLD(WHITE_BOLD_S " ocl ") RED(" error ") RED_BOLD("%s") RED(" when calling ") RED_BOLD("%s");
static const char *kErrorTemplate = MAGENTA_BG_BOLD(WHITE_BOLD_S " opencl ") RED(" error ") RED_BOLD("%s") RED(" when calling ") RED_BOLD("%s");
static const char *kBuildProgram = "clBuildProgram";
static const char *kCreateBuffer = "clCreateBuffer";

View File

@@ -222,3 +222,15 @@ if (WITH_KAWPOW)
src/base/net/stratum/EthStratumClient.cpp
)
endif()
if (WITH_PROFILING)
add_definitions(/DXMRIG_FEATURE_PROFILING)
list(APPEND HEADERS_BASE
src/base/tools/Profiler.h
)
list(APPEND SOURCES_BASE
src/base/tools/Profiler.cpp
)
endif()

View File

@@ -135,6 +135,12 @@ static AlgoName const algorithm_names[] = {
} /* namespace xmrig */
xmrig::Algorithm::Algorithm(const rapidjson::Value &value) :
m_id(parse(value.GetString()))
{
}
rapidjson::Value xmrig::Algorithm::toJSON() const
{
using namespace rapidjson;
@@ -143,6 +149,12 @@ rapidjson::Value xmrig::Algorithm::toJSON() const
}
rapidjson::Value xmrig::Algorithm::toJSON(rapidjson::Document &) const
{
return toJSON();
}
size_t xmrig::Algorithm::l2() const
{
# ifdef XMRIG_ALGO_RANDOMX

View File

@@ -92,6 +92,7 @@ public:
inline Algorithm() = default;
inline Algorithm(const char *algo) : m_id(parse(algo)) {}
inline Algorithm(Id id) : m_id(id) {}
Algorithm(const rapidjson::Value &value);
inline bool isCN() const { auto f = family(); return f == CN || f == CN_LITE || f == CN_HEAVY || f == CN_PICO; }
inline bool isEqual(const Algorithm &other) const { return m_id == other.m_id; }
@@ -108,6 +109,7 @@ public:
inline operator Algorithm::Id() const { return m_id; }
rapidjson::Value toJSON() const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
size_t l2() const;
size_t l3() const;
uint32_t maxIntensity() const;

View File

@@ -36,9 +36,7 @@ static const rapidjson::Value kNullValue;
}
xmrig::JsonChain::JsonChain()
{
}
xmrig::JsonChain::JsonChain() = default;
bool xmrig::JsonChain::add(rapidjson::Document &&doc)
@@ -66,8 +64,10 @@ bool xmrig::JsonChain::addFile(const char *fileName)
if (doc.HasParseError()) {
const size_t offset = doc.GetErrorOffset();
size_t line, pos;
size_t line;
size_t pos;
std::vector<std::string> s;
if (Json::convertOffset(fileName, offset, line, pos, s)) {
for (const auto& t : s) {
LOG_ERR("%s", t.c_str());

View File

@@ -81,7 +81,13 @@ private:
#define CLEAR CSI "0m" // all attributes off
#define BRIGHT_BLACK_S CSI "0;90m" // somewhat MD.GRAY
#define BLACK_S CSI "0;30m"
#define BLACK_BOLD_S CSI "1;30m" // another name for GRAY
#ifdef XMRIG_OS_APPLE
# define BLACK_BOLD_S CSI "0;37m"
#else
# define BLACK_BOLD_S CSI "1;30m" // another name for GRAY
#endif
#define RED_S CSI "0;31m"
#define RED_BOLD_S CSI "1;31m"
#define GREEN_S CSI "0;32m"

View File

@@ -73,6 +73,16 @@ const char *xmrig::Tags::randomx()
#endif
#ifdef XMRIG_PROXY_PROJECT
const char *xmrig::Tags::proxy()
{
static const char *tag = MAGENTA_BG_BOLD(WHITE_BOLD_S " proxy ");
return tag;
}
#endif
#ifdef XMRIG_FEATURE_CUDA
const char *xmrig::Tags::nvidia()
{
@@ -91,3 +101,13 @@ const char *xmrig::Tags::opencl()
return tag;
}
#endif
#ifdef XMRIG_FEATURE_PROFILING
const char* xmrig::Tags::profiler()
{
static const char* tag = CYAN_BG_BOLD(WHITE_BOLD_S " profile ");
return tag;
}
#endif

View File

@@ -42,6 +42,10 @@ public:
# endif
# endif
# ifdef XMRIG_PROXY_PROJECT
static const char *proxy();
# endif
# ifdef XMRIG_FEATURE_CUDA
static const char *nvidia();
# endif
@@ -49,6 +53,10 @@ public:
# ifdef XMRIG_FEATURE_OPENCL
static const char *opencl();
# endif
# ifdef XMRIG_FEATURE_PROFILING
static const char* profiler();
# endif
};

View File

@@ -84,7 +84,7 @@ static int showVersion()
# if defined(LIBRESSL_VERSION_TEXT)
printf("LibreSSL/%s\n", LIBRESSL_VERSION_TEXT + 9);
# elif defined(OPENSSL_VERSION_TEXT)
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
constexpr const char *v = &OPENSSL_VERSION_TEXT[8];
printf("OpenSSL/%.*s\n", static_cast<int>(strchr(v, ' ') - v), v);
# endif
}

View File

@@ -54,6 +54,8 @@ public:
static inline const char *userAgent() { return m_userAgent; }
static bool isOnBatteryPower();
private:
static char *createUserAgent();

View File

@@ -22,6 +22,8 @@
*/
#include <IOKit/IOKitLib.h>
#include <IOKit/ps/IOPowerSources.h>
#include <mach/thread_act.h>
#include <mach/thread_policy.h>
#include <stdio.h>
@@ -29,6 +31,7 @@
#include <sys/resource.h>
#include <uv.h>
#include <thread>
#include <fstream>
#include "base/kernel/Platform.h"
@@ -107,3 +110,8 @@ void xmrig::Platform::setThreadPriority(int priority)
setpriority(PRIO_PROCESS, 0, prio);
}
bool xmrig::Platform::isOnBatteryPower()
{
return IOPSGetTimeRemainingEstimate() != kIOPSTimeRemainingUnlimited;
}

View File

@@ -38,6 +38,7 @@
#include <unistd.h>
#include <uv.h>
#include <thread>
#include <fstream>
#include "base/kernel/Platform.h"
@@ -146,3 +147,19 @@ void xmrig::Platform::setThreadPriority(int priority)
}
# endif
}
bool xmrig::Platform::isOnBatteryPower()
{
for (int i = 0; i <= 1; ++i) {
char buf[64];
snprintf(buf, 64, "/sys/class/power_supply/BAT%d/status", i);
std::ifstream f(buf);
if (f.is_open()) {
std::string status;
f >> status;
return (status == "Discharging");
}
}
return false;
}

View File

@@ -157,3 +157,12 @@ void xmrig::Platform::setThreadPriority(int priority)
SetThreadPriority(GetCurrentThread(), prio);
}
bool xmrig::Platform::isOnBatteryPower()
{
SYSTEM_POWER_STATUS st;
if (GetSystemPowerStatus(&st)) {
return (st.ACLineStatus == 0);
}
return false;
}

View File

@@ -61,6 +61,7 @@ const char *BaseConfig::kColors = "colors";
const char *BaseConfig::kDryRun = "dry-run";
const char *BaseConfig::kHttp = "http";
const char *BaseConfig::kLogFile = "log-file";
const char *BaseConfig::kPauseOnBattery = "pause-on-battery";
const char *BaseConfig::kPrintTime = "print-time";
const char *BaseConfig::kSyslog = "syslog";
const char *BaseConfig::kTitle = "title";
@@ -85,15 +86,16 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName)
return false;
}
m_autoSave = reader.getBool(kAutosave, m_autoSave);
m_background = reader.getBool(kBackground, m_background);
m_dryRun = reader.getBool(kDryRun, m_dryRun);
m_syslog = reader.getBool(kSyslog, m_syslog);
m_watch = reader.getBool(kWatch, m_watch);
m_logFile = reader.getString(kLogFile);
m_userAgent = reader.getString(kUserAgent);
m_printTime = std::min(reader.getUint(kPrintTime, m_printTime), 3600U);
m_title = reader.getValue(kTitle);
m_autoSave = reader.getBool(kAutosave, m_autoSave);
m_background = reader.getBool(kBackground, m_background);
m_dryRun = reader.getBool(kDryRun, m_dryRun);
m_syslog = reader.getBool(kSyslog, m_syslog);
m_watch = reader.getBool(kWatch, m_watch);
m_pauseOnBattery = reader.getBool(kPauseOnBattery, m_pauseOnBattery);
m_logFile = reader.getString(kLogFile);
m_userAgent = reader.getString(kUserAgent);
m_printTime = std::min(reader.getUint(kPrintTime, m_printTime), 3600U);
m_title = reader.getValue(kTitle);
# ifdef XMRIG_FEATURE_TLS
m_tls = reader.getValue(kTls);
@@ -155,7 +157,7 @@ void xmrig::BaseConfig::printVersions()
snprintf(buf, sizeof buf, "LibreSSL/%s ", LIBRESSL_VERSION_TEXT + 9);
libs += buf;
# elif defined(OPENSSL_VERSION_TEXT)
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
constexpr const char *v = &OPENSSL_VERSION_TEXT[8];
snprintf(buf, sizeof buf, "OpenSSL/%.*s ", static_cast<int>(strchr(v, ' ') - v), v);
libs += buf;
# endif

View File

@@ -55,6 +55,7 @@ public:
static const char *kDryRun;
static const char *kHttp;
static const char *kLogFile;
static const char *kPauseOnBattery;
static const char *kPrintTime;
static const char *kSyslog;
static const char *kTitle;
@@ -71,6 +72,7 @@ public:
inline bool isAutoSave() const { return m_autoSave; }
inline bool isBackground() const { return m_background; }
inline bool isDryRun() const { return m_dryRun; }
inline bool isPauseOnBattery() const { return m_pauseOnBattery; }
inline bool isSyslog() const { return m_syslog; }
inline const char *logFile() const { return m_logFile.data(); }
inline const char *userAgent() const { return m_userAgent.data(); }
@@ -95,12 +97,13 @@ public:
void printVersions();
protected:
bool m_autoSave = true;
bool m_background = false;
bool m_dryRun = false;
bool m_syslog = false;
bool m_upgrade = false;
bool m_watch = true;
bool m_autoSave = true;
bool m_background = false;
bool m_dryRun = false;
bool m_pauseOnBattery = false;
bool m_syslog = false;
bool m_upgrade = false;
bool m_watch = true;
Http m_http;
Pools m_pools;
String m_apiId;

View File

@@ -247,6 +247,7 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
case IConfig::HttpEnabledKey: /* --http-enabled */
case IConfig::DaemonKey: /* --daemon */
case IConfig::VerboseKey: /* --verbose */
case IConfig::PauseOnBatteryKey: /* --pause-on-battery */
return transformBoolean(doc, key, true);
case IConfig::ColorKey: /* --no-color */
@@ -305,6 +306,9 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b
case IConfig::NoTitleKey: /* --no-title */
return set(doc, BaseConfig::kTitle, enable);
case IConfig::PauseOnBatteryKey: /* --pause-on-battery */
return set(doc, BaseConfig::kPauseOnBattery, enable);
default:
break;
}

View File

@@ -76,6 +76,7 @@ public:
DataDirKey = 1035,
TitleKey = 1037,
NoTitleKey = 1038,
PauseOnBatteryKey = 1041,
// xmrig common
CPUPriorityKey = 1021,
@@ -101,6 +102,8 @@ public:
YieldKey = 1030,
AstroBWTMaxSizeKey = 1034,
AstroBWTAVX2Key = 1036,
Argon2ImplKey = 1039,
RandomXCacheQoSKey = 1040,
// xmrig amd
OclPlatformKey = 1400,

View File

@@ -126,6 +126,10 @@ bool xmrig::HttpContext::isRequest() const
size_t xmrig::HttpContext::parse(const char *data, size_t size)
{
if (size == 0) {
return size;
}
return http_parser_execute(m_parser, &http_settings, data, size);
}

View File

@@ -29,13 +29,20 @@ namespace xmrig {
class HttpListener : public IHttpListener
{
public:
inline HttpListener(IHttpListener *listener, const char *tag = nullptr) : m_tag(tag), m_listener(listener) {}
inline HttpListener(IHttpListener *listener, const char *tag = nullptr) :
# ifdef APP_DEBUG
m_tag(tag),
# endif
m_listener(listener)
{}
protected:
void onHttpData(const HttpData &data) override;
private:
# ifdef APP_DEBUG
const char *m_tag;
# endif
IHttpListener *m_listener;
};

View File

@@ -45,7 +45,9 @@ class Job
public:
// Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk.
// SECOR increase requirements for blob size: https://github.com/xmrig/xmrig/issues/913
static constexpr const size_t kMaxBlobSize = 128;
// Haven (XHV) offshore increases requirements by adding pricing_record struct (192 bytes) to block_header.
// Round it up to 408 (136*3) for a convenient keccak calculation in OpenCL
static constexpr const size_t kMaxBlobSize = 408;
static constexpr const size_t kMaxSeedSize = 32;
Job() = default;
@@ -63,7 +65,7 @@ public:
void setDiff(uint64_t diff);
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
inline bool isValid() const { return (m_size > 0 && m_diff > 0) || !m_poolWallet.isEmpty(); }
inline bool setId(const char *id) { return m_id = id; }
inline const Algorithm &algorithm() const { return m_algorithm; }
inline const Buffer &seed() const { return m_seed; }
@@ -80,6 +82,7 @@ public:
inline uint32_t backend() const { return m_backend; }
inline uint64_t diff() const { return m_diff; }
inline uint64_t height() const { return m_height; }
inline uint64_t nonceMask() const { return isNicehash() ? 0xFFFFFFULL : (nonceSize() == sizeof(uint64_t) ? (-1ull >> (extraNonce().size() * 4)): 0xFFFFFFFFULL); }
inline uint64_t target() const { return m_target; }
inline uint8_t *blob() { return m_blob; }
inline uint8_t fixedByte() const { return *(m_blob + 42); }

View File

@@ -25,6 +25,7 @@
#include "base/net/stratum/NetworkState.h"
#include "3rdparty/rapidjson/document.h"
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IClient.h"
#include "base/kernel/interfaces/IStrategy.h"
#include "base/net/stratum/Job.h"
@@ -40,6 +41,80 @@
namespace xmrig {
inline static void printCount(uint64_t accepted, uint64_t rejected)
{
float percent = 100.0;
int color = 2;
if (!accepted) {
percent = 0.0;
color = 1;
}
else if (rejected) {
percent = static_cast<float>(accepted) / (accepted + rejected) * 100.0;
color = 3;
}
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") CSI "1;3%dm%" PRIu64 CLEAR CSI "0;3%dm (%1.1f%%)", "accepted", color, accepted, color, percent);
if (rejected) {
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") RED_BOLD("%" PRIu64), "rejected", rejected);
}
}
inline static void printHashes(uint64_t accepted, uint64_t hashes)
{
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") CYAN_BOLD("%" PRIu64) " avg " CYAN("%1.0f"),
"pool-side hashes", hashes, static_cast<double>(hashes) / accepted);
}
inline static void printAvgTime(uint64_t time)
{
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") CSI "1;3%dm%1.1fs", "avg result time", (time < 10000 ? 3 : 2), time / 1000.0);
}
static void printDiff(uint64_t diff)
{
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") CYAN_BOLD("%s"), "difficulty", NetworkState::humanDiff(diff).c_str());
}
inline static void printDiff(size_t i, uint64_t diff, uint64_t hashes)
{
if (!diff) {
return;
}
const double effort = static_cast<double>(hashes) / diff * 100.0;
const double target = (i + 1) * 100.0;
const int color = effort > (target + 100.0) ? 1 : (effort > target ? 3 : 2);
Log::print("%3zu | %10s | " CSI "0;3%dm%8.2f" CLEAR " |", i + 1, NetworkState::humanDiff(diff).c_str(), color, effort);
}
inline static void printLatency(uint32_t latency)
{
if (!latency) {
return;
}
const int color = latency < 100 ? 2 : (latency > 500 ? 1 : 3);
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") CSI "1;3%dm%ums", "ping time", color, latency);
}
} // namespace xmrig
xmrig::NetworkState::NetworkState(IStrategyListener *listener) : StrategyProxy(listener)
{
}
@@ -54,7 +129,8 @@ rapidjson::Value xmrig::NetworkState::getConnection(rapidjson::Document &doc, in
Value connection(kObjectType);
connection.AddMember("pool", StringRef(m_pool), allocator);
connection.AddMember("ip", m_ip.toJSON(), allocator);
connection.AddMember("uptime", connectionTime(), allocator);
connection.AddMember("uptime", connectionTime() / 1000, allocator);
connection.AddMember("uptime_ms", connectionTime(), allocator);
connection.AddMember("ping", latency(), allocator);
connection.AddMember("failures", m_failures, allocator);
connection.AddMember("tls", m_tls.toJSON(), allocator);
@@ -64,7 +140,8 @@ rapidjson::Value xmrig::NetworkState::getConnection(rapidjson::Document &doc, in
connection.AddMember("diff", m_diff, allocator);
connection.AddMember("accepted", m_accepted, allocator);
connection.AddMember("rejected", m_rejected, allocator);
connection.AddMember("avg_time", avgTime(), allocator);
connection.AddMember("avg_time", avgTime() / 1000, allocator);
connection.AddMember("avg_time_ms", avgTime(), allocator);
connection.AddMember("hashes_total", m_hashes, allocator);
if (version == 1) {
@@ -85,11 +162,14 @@ rapidjson::Value xmrig::NetworkState::getResults(rapidjson::Document &doc, int v
results.AddMember("diff_current", m_diff, allocator);
results.AddMember("shares_good", m_accepted, allocator);
results.AddMember("shares_total", m_accepted + m_rejected, allocator);
results.AddMember("avg_time", avgTime(), allocator);
results.AddMember("avg_time", avgTime() / 1000, allocator);
results.AddMember("avg_time_ms", avgTime(), allocator);
results.AddMember("hashes_total", m_hashes, allocator);
Value best(kArrayType);
for (uint64_t i : topDiff) {
best.Reserve(m_topDiff.size(), allocator);
for (uint64_t i : m_topDiff) {
best.PushBack(i, allocator);
}
@@ -104,6 +184,84 @@ rapidjson::Value xmrig::NetworkState::getResults(rapidjson::Document &doc, int v
#endif
void xmrig::NetworkState::printConnection() const
{
if (!m_active) {
LOG_NOTICE(YELLOW_BOLD_S "no active connection");
return;
}
Log::print(MAGENTA_BOLD_S " - CONNECTION");
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") CYAN_BOLD("%s ") BLACK_BOLD("(%s) ") GREEN_BOLD("%s"),
"pool address", m_pool, m_ip.data(), m_tls.isNull() ? "" : m_tls.data());
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") WHITE_BOLD("%s"), "algorithm", m_algorithm.shortName());
printDiff(m_diff);
printLatency(latency());
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") CYAN_BOLD("%" PRIu64 "s"), "connection time", connectionTime() / 1000);
}
void xmrig::NetworkState::printResults() const
{
if (!m_hashes) {
LOG_NOTICE(YELLOW_BOLD_S "no any results yet");
return;
}
Log::print(MAGENTA_BOLD_S " - RESULTS");
printCount(m_accepted, m_rejected);
printHashes(m_accepted, m_hashes);
printDiff(m_diff);
if (m_active && !m_latency.empty()) {
printAvgTime(avgTime());
}
Log::print(MAGENTA_BOLD_S " - TOP 10");
Log::print(WHITE_BOLD_S " # | DIFFICULTY | EFFORT %% |");
for (size_t i = 0; i < m_topDiff.size(); ++i) {
printDiff(i, m_topDiff[i], m_hashes);
}
}
const char *xmrig::NetworkState::scaleDiff(uint64_t &diff)
{
if (diff >= 100000000000) {
diff /= 1000000000;
return "G";
}
if (diff >= 100000000) {
diff /= 1000000;
return "M";
}
if (diff >= 1000000) {
diff /= 1000;
return "K";
}
return "";
}
std::string xmrig::NetworkState::humanDiff(uint64_t diff)
{
const char *scale = scaleDiff(diff);
return std::to_string(diff) + scale;
}
void xmrig::NetworkState::onActive(IStrategy *strategy, IClient *client)
{
snprintf(m_pool, sizeof(m_pool) - 1, "%s:%d", client->pool().host().data(), client->pool().port());
@@ -145,16 +303,6 @@ void xmrig::NetworkState::onResultAccepted(IStrategy *strategy, IClient *client,
}
uint32_t xmrig::NetworkState::avgTime() const
{
if (m_latency.empty()) {
return 0;
}
return connectionTime() / (uint32_t)m_latency.size();
}
uint32_t xmrig::NetworkState::latency() const
{
const size_t calls = m_latency.size();
@@ -169,9 +317,19 @@ uint32_t xmrig::NetworkState::latency() const
}
uint64_t xmrig::NetworkState::avgTime() const
{
if (m_latency.empty()) {
return 0;
}
return connectionTime() / m_latency.size();
}
uint64_t xmrig::NetworkState::connectionTime() const
{
return m_active ? ((Chrono::steadyMSecs() - m_connectionTime) / 1000) : 0;
return m_active ? ((Chrono::steadyMSecs() - m_connectionTime)) : 0;
}
@@ -185,10 +343,10 @@ void xmrig::NetworkState::add(const SubmitResult &result, const char *error)
m_accepted++;
m_hashes += result.diff;
const size_t ln = topDiff.size() - 1;
if (result.actualDiff > topDiff[ln]) {
topDiff[ln] = result.actualDiff;
std::sort(topDiff.rbegin(), topDiff.rend());
const size_t ln = m_topDiff.size() - 1;
if (result.actualDiff > m_topDiff[ln]) {
m_topDiff[ln] = result.actualDiff;
std::sort(m_topDiff.rbegin(), m_topDiff.rend());
}
m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : static_cast<uint16_t>(result.elapsed));

View File

@@ -32,6 +32,7 @@
#include <array>
#include <string>
#include <vector>
@@ -52,6 +53,12 @@ public:
rapidjson::Value getResults(rapidjson::Document &doc, int version) const;
# endif
void printConnection() const;
void printResults() const;
static const char *scaleDiff(uint64_t &diff);
static std::string humanDiff(uint64_t diff);
protected:
void onActive(IStrategy *strategy, IClient *client) override;
void onJob(IStrategy *strategy, IClient *client, const Job &job, const rapidjson::Value &params) override;
@@ -59,8 +66,8 @@ protected:
void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) override;
private:
uint32_t avgTime() const;
uint32_t latency() const;
uint64_t avgTime() const;
uint64_t connectionTime() const;
void add(const SubmitResult &result, const char *error);
void stop();
@@ -68,7 +75,7 @@ private:
Algorithm m_algorithm;
bool m_active = false;
char m_pool[256]{};
std::array<uint64_t, 10> topDiff { { } };
std::array<uint64_t, 10> m_topDiff { { } };
std::vector<uint16_t> m_latency;
String m_fingerprint;
String m_ip;

101
src/base/tools/Profiler.cpp Normal file
View File

@@ -0,0 +1,101 @@
/* XMRig
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 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 "base/tools/Profiler.h"
#include "base/io/log/Log.h"
#include "base/io/log/Tags.h"
#include <cstring>
#include <sstream>
#include <thread>
#include <chrono>
#include <algorithm>
#ifdef XMRIG_FEATURE_PROFILING
ProfileScopeData* ProfileScopeData::s_data[MAX_DATA_COUNT] = {};
volatile long ProfileScopeData::s_dataCount = 0;
double ProfileScopeData::s_tscSpeed = 0.0;
#ifndef NOINLINE
#ifdef __GNUC__
#define NOINLINE __attribute__ ((noinline))
#elif _MSC_VER
#define NOINLINE __declspec(noinline)
#else
#define NOINLINE
#endif
#endif
static std::string get_thread_id()
{
std::stringstream ss;
ss << std::this_thread::get_id();
std::string s = ss.str();
if (s.length() > ProfileScopeData::MAX_THREAD_ID_LENGTH) {
s.resize(ProfileScopeData::MAX_THREAD_ID_LENGTH);
}
return s;
}
NOINLINE void ProfileScopeData::Register(ProfileScopeData* data)
{
#ifdef _MSC_VER
const long id = _InterlockedIncrement(&s_dataCount) - 1;
#else
const long id = __sync_fetch_and_add(&s_dataCount, 1);
#endif
if (static_cast<unsigned long>(id) < MAX_DATA_COUNT) {
s_data[id] = data;
const std::string s = get_thread_id();
memcpy(data->m_threadId, s.c_str(), s.length() + 1);
}
}
NOINLINE void ProfileScopeData::Init()
{
using namespace std::chrono;
const uint64_t t1 = static_cast<uint64_t>(time_point_cast<nanoseconds>(high_resolution_clock::now()).time_since_epoch().count());
const uint64_t count1 = ReadTSC();
for (;;)
{
const uint64_t t2 = static_cast<uint64_t>(time_point_cast<nanoseconds>(high_resolution_clock::now()).time_since_epoch().count());
const uint64_t count2 = ReadTSC();
if (t2 - t1 > 1000000000) {
s_tscSpeed = (count2 - count1) * 1e9 / (t2 - t1);
LOG_INFO("%s TSC speed = %.3f GHz", xmrig::Tags::profiler(), s_tscSpeed / 1e9);
return;
}
}
}
#endif /* XMRIG_FEATURE_PROFILING */

133
src/base/tools/Profiler.h Normal file
View File

@@ -0,0 +1,133 @@
/* XMRig
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 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_PROFILER_H
#define XMRIG_PROFILER_H
#ifndef FORCE_INLINE
#if defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#elif defined(__GNUC__)
#define FORCE_INLINE __attribute__((always_inline)) inline
#elif defined(__clang__)
#define FORCE_INLINE __inline__
#else
#define FORCE_INLINE
#endif
#endif
#ifdef XMRIG_FEATURE_PROFILING
#include <cstdint>
#include <cstddef>
#include <type_traits>
#if defined(_MSC_VER)
#include <intrin.h>
#endif
static FORCE_INLINE uint64_t ReadTSC()
{
#ifdef _MSC_VER
return __rdtsc();
#else
uint32_t hi, lo;
__asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
return (((uint64_t)hi) << 32) | lo;
#endif
}
struct ProfileScopeData
{
const char* m_name;
uint64_t m_totalCycles;
uint32_t m_totalSamples;
enum
{
MAX_THREAD_ID_LENGTH = 11,
MAX_SAMPLE_COUNT = 128,
MAX_DATA_COUNT = 1024
};
char m_threadId[MAX_THREAD_ID_LENGTH + 1];
static ProfileScopeData* s_data[MAX_DATA_COUNT];
static volatile long s_dataCount;
static double s_tscSpeed;
static void Register(ProfileScopeData* data);
static void Init();
};
static_assert(std::is_trivial<ProfileScopeData>::value, "ProfileScopeData must be a trivial struct");
static_assert(sizeof(ProfileScopeData) <= 32, "ProfileScopeData struct is too big");
class ProfileScope
{
public:
FORCE_INLINE ProfileScope(ProfileScopeData& data)
: m_data(data)
{
if (m_data.m_totalCycles == 0) {
ProfileScopeData::Register(&data);
}
m_startCounter = ReadTSC();
}
FORCE_INLINE ~ProfileScope()
{
m_data.m_totalCycles += ReadTSC() - m_startCounter;
++m_data.m_totalSamples;
}
private:
ProfileScopeData& m_data;
uint64_t m_startCounter;
};
#define PROFILE_SCOPE(x) static thread_local ProfileScopeData x##_data{#x}; ProfileScope x(x##_data);
#else /* XMRIG_FEATURE_PROFILING */
#define PROFILE_SCOPE(x)
#endif /* XMRIG_FEATURE_PROFILING */
#include "crypto/randomx/blake2/blake2.h"
struct rx_blake2b_wrapper
{
FORCE_INLINE static void run(void* out, size_t outlen, const void* in, size_t inlen)
{
PROFILE_SCOPE(RandomX_Blake2b);
rx_blake2b(out, outlen, in, inlen);
}
};
#endif /* XMRIG_PROFILER_H */

View File

@@ -20,7 +20,9 @@
"1gb-pages": false,
"rdmsr": true,
"wrmsr": true,
"numa": true
"cache_qos": false,
"numa": true,
"scratchpad_prefetch_mode": 1
},
"cpu": {
"enabled": true,
@@ -90,5 +92,6 @@
},
"user-agent": null,
"verbose": 0,
"watch": true
"watch": true,
"pause-on-battery": false
}

View File

@@ -98,3 +98,10 @@ xmrig::Network *xmrig::Controller::network() const
return m_network;
}
void xmrig::Controller::execCommand(char command)
{
miner()->execCommand(command);
network()->execCommand(command);
}

View File

@@ -52,6 +52,7 @@ public:
Miner *miner() const;
Network *network() const;
void execCommand(char command);
private:
Miner *m_miner = nullptr;

View File

@@ -38,6 +38,7 @@
#include "base/kernel/Platform.h"
#include "base/net/stratum/Job.h"
#include "base/tools/Object.h"
#include "base/tools/Profiler.h"
#include "base/tools/Timer.h"
#include "core/config/Config.h"
#include "core/Controller.h"
@@ -267,6 +268,44 @@ public:
h = "MH/s";
}
# ifdef XMRIG_FEATURE_PROFILING
ProfileScopeData* data[ProfileScopeData::MAX_DATA_COUNT];
const uint32_t n = std::min<uint32_t>(ProfileScopeData::s_dataCount, ProfileScopeData::MAX_DATA_COUNT);
memcpy(data, ProfileScopeData::s_data, n * sizeof(ProfileScopeData*));
std::sort(data, data + n, [](ProfileScopeData* a, ProfileScopeData* b) {
return strcmp(a->m_threadId, b->m_threadId) < 0;
});
for (uint32_t i = 0; i < n;)
{
uint32_t n1 = i;
while ((n1 < n) && (strcmp(data[i]->m_threadId, data[n1]->m_threadId) == 0)) {
++n1;
}
std::sort(data + i, data + n1, [](ProfileScopeData* a, ProfileScopeData* b) {
return a->m_totalCycles > b->m_totalCycles;
});
for (uint32_t j = i; j < n1; ++j) {
ProfileScopeData* p = data[j];
LOG_INFO("%s Thread %6s | %-30s | %7.3f%% | %9.0f ns",
Tags::profiler(),
p->m_threadId,
p->m_name,
p->m_totalCycles * 100.0 / data[i]->m_totalCycles,
p->m_totalCycles / p->m_totalSamples * 1e9 / ProfileScopeData::s_tscSpeed
);
}
LOG_INFO("%s --------------|--------------------------------|----------|-------------", Tags::profiler());
i = n1;
}
# endif
LOG_INFO("%s " WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("%s") " max " CYAN_BOLD("%s %s"),
Tags::miner(),
Hashrate::format(speed[0] * scale, num, sizeof(num) / 4),
@@ -287,6 +326,7 @@ public:
bool active = false;
bool enabled = true;
bool reset = true;
bool battery_power = false;
Controller *controller;
Job job;
mutable std::map<Algorithm::Id, double> maxHashrate;
@@ -310,6 +350,10 @@ xmrig::Miner::Miner(Controller *controller)
Platform::setThreadPriority(std::min(priority + 1, 5));
}
# ifdef XMRIG_FEATURE_PROFILING
ProfileScopeData::Init();
# endif
# ifdef XMRIG_ALGO_RANDOMX
Rx::init(this);
# endif
@@ -429,13 +473,24 @@ void xmrig::Miner::setEnabled(bool enabled)
return;
}
if (d_ptr->battery_power && enabled) {
LOG_INFO("%s " YELLOW_BOLD("can't resume while on battery power"), Tags::miner());
return;
}
d_ptr->enabled = enabled;
if (enabled) {
LOG_INFO(GREEN_BOLD("resumed"));
LOG_INFO("%s " GREEN_BOLD("resumed"), Tags::miner());
}
else {
LOG_INFO(YELLOW_BOLD("paused") ", press " MAGENTA_BG_BOLD(" r ") " to resume");
if (d_ptr->battery_power) {
LOG_INFO("%s " YELLOW_BOLD("paused"), Tags::miner());
}
else {
LOG_INFO("%s " YELLOW_BOLD("paused") ", press " MAGENTA_BG_BOLD(" r ") " to resume", Tags::miner());
}
}
if (!d_ptr->active) {
@@ -538,6 +593,20 @@ void xmrig::Miner::onTimer(const Timer *)
}
d_ptr->ticks++;
if (d_ptr->controller->config()->isPauseOnBattery()) {
const bool battery_power = Platform::isOnBatteryPower();
if (battery_power && d_ptr->enabled) {
LOG_INFO("%s " YELLOW_BOLD("on battery power"), Tags::miner());
d_ptr->battery_power = true;
setEnabled(false);
}
else if (!battery_power && !d_ptr->enabled && d_ptr->battery_power) {
LOG_INFO("%s " GREEN_BOLD("on AC power"), Tags::miner());
d_ptr->battery_power = false;
setEnabled(true);
}
}
}

View File

@@ -252,4 +252,5 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
doc.AddMember(StringRef(kUserAgent), m_userAgent.toJSON(), allocator);
doc.AddMember(StringRef(kVerbose), Log::verbose(), allocator);
doc.AddMember(StringRef(kWatch), m_watch, allocator);
doc.AddMember(StringRef(kPauseOnBattery), isPauseOnBattery(), allocator);
}

View File

@@ -5,8 +5,8 @@
* 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>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 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
@@ -151,6 +151,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const
case IConfig::YieldKey: /* --cpu-no-yield */
return set(doc, kCpu, "yield", false);
case IConfig::Argon2ImplKey: /* --argon2-impl */
return set(doc, kCpu, "argon2-impl", arg);
# ifdef XMRIG_FEATURE_ASM
case IConfig::AssemblyKey: /* --asm */
return set(doc, kCpu, "asm", arg);
@@ -186,6 +189,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const
case IConfig::RandomXRdmsrKey: /* --randomx-no-rdmsr */
return set(doc, kRandomX, "rdmsr", false);
case IConfig::RandomXCacheQoSKey: /* --cache-qos */
return set(doc, kRandomX, "cache_qos", true);
# endif
# ifdef XMRIG_FEATURE_OPENCL

View File

@@ -5,8 +5,8 @@
* 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>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 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

View File

@@ -51,7 +51,12 @@ R"===(
"randomx": {
"init": -1,
"mode": "auto",
"numa": true
"1gb-pages": false,
"rdmsr": true,
"wrmsr": true,
"cache_qos": false,
"numa": true,
"scratchpad_prefetch_mode": 1
},
"cpu": {
"enabled": true,
@@ -109,7 +114,8 @@ R"===(
"retry-pause": 5,
"syslog": false,
"user-agent": null,
"watch": true
"watch": true,
"pause-on-battery": false
}
)===";
#endif

View File

@@ -87,11 +87,15 @@ static const option options[] = {
{ "cpu-max-threads-hint", 1, nullptr, IConfig::CPUMaxThreadsKey },
{ "cpu-memory-pool", 1, nullptr, IConfig::MemoryPoolKey },
{ "cpu-no-yield", 0, nullptr, IConfig::YieldKey },
{ "no-yield", 0, nullptr, IConfig::YieldKey },
{ "cpu-argon2-impl", 1, nullptr, IConfig::Argon2ImplKey },
{ "argon2-impl", 1, nullptr, IConfig::Argon2ImplKey },
{ "verbose", 0, nullptr, IConfig::VerboseKey },
{ "proxy", 1, nullptr, IConfig::ProxyKey },
{ "data-dir", 1, nullptr, IConfig::DataDirKey },
{ "title", 1, nullptr, IConfig::TitleKey },
{ "no-title", 0, nullptr, IConfig::NoTitleKey },
{ "pause-on-battery", 0, nullptr, IConfig::PauseOnBatteryKey },
# ifdef XMRIG_FEATURE_TLS
{ "tls", 0, nullptr, IConfig::TlsKey },
{ "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey },
@@ -116,6 +120,8 @@ static const option options[] = {
{ "wrmsr", 2, nullptr, IConfig::RandomXWrmsrKey },
{ "randomx-no-rdmsr", 0, nullptr, IConfig::RandomXRdmsrKey },
{ "no-rdmsr", 0, nullptr, IConfig::RandomXRdmsrKey },
{ "randomx-cache-qos", 0, nullptr, IConfig::RandomXCacheQoSKey },
{ "cache-qos", 0, nullptr, IConfig::RandomXCacheQoSKey },
# endif
#ifdef XMRIG_ALGO_ASTROBWT
{ "astrobwt-max-size", 1, nullptr, IConfig::AstroBWTMaxSizeKey },

View File

@@ -69,7 +69,7 @@ static inline const std::string &usage()
u += " -r, --retries=N number of times to retry before switch to backup server (default: 5)\n";
u += " -R, --retry-pause=N time to pause between retries (default: 5)\n";
u += " --user-agent set custom user-agent string for pool\n";
u += " --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n";
u += " --donate-level=N donate level, default 1%% (1 minute in 100 minutes)\n";
u += " --donate-over-proxy=N control donate over xmrig-proxy feature\n";
u += "\nCPU backend:\n";
@@ -85,13 +85,18 @@ static inline const std::string &usage()
u += " --no-huge-pages disable huge pages support\n";
u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n";
# if defined(__x86_64__) || defined(_M_AMD64)
u += " --argon2-impl=IMPL argon2 implementation: x86_64, SSE2, SSSE3, XOP, AVX2, AVX-512F\n";
# endif
# ifdef XMRIG_ALGO_RANDOMX
u += " --randomx-init=N threads count to initialize RandomX dataset\n";
u += " --randomx-no-numa disable NUMA support for RandomX\n";
u += " --randomx-mode=MODE RandomX mode: auto, fast, light\n";
u += " --randomx-1gb-pages use 1GB hugepages for dataset (Linux only)\n";
u += " --randomx-wrmsr=N write custom value (0-15) to Intel MSR register 0x1a4 or disable MSR mod (-1)\n";
u += " --randomx-1gb-pages use 1GB hugepages for RandomX dataset (Linux only)\n";
u += " --randomx-wrmsr=N write custom value(s) to MSR registers or disable MSR mod (-1)\n";
u += " --randomx-no-rdmsr disable reverting initial MSR values on exit\n";
u += " --randomx-cache-qos enable Cache QoS\n";
# endif
# ifdef XMRIG_ALGO_ASTROBWT
@@ -99,16 +104,6 @@ static inline const std::string &usage()
u += " --astrobwt-avx2 enable AVX2 optimizations for AstroBWT algorithm";
# endif
# ifdef XMRIG_FEATURE_HTTP
u += "\nAPI:\n";
u += " --api-worker-id=ID custom worker-id for API\n";
u += " --api-id=ID custom instance ID for API\n";
u += " --http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n";
u += " --http-port=N bind port for HTTP API\n";
u += " --http-access-token=T access token for HTTP API\n";
u += " --http-no-restricted enable full remote access to HTTP API (only if access token set)\n";
# endif
# ifdef XMRIG_FEATURE_OPENCL
u += "\nOpenCL backend:\n";
u += " --opencl enable OpenCL mining backend\n";
@@ -131,6 +126,16 @@ static inline const std::string &usage()
u += " --no-nvml disable NVML (NVIDIA Management Library) support\n";
# endif
# ifdef XMRIG_FEATURE_HTTP
u += "\nAPI:\n";
u += " --api-worker-id=ID custom worker-id for API\n";
u += " --api-id=ID custom instance ID for API\n";
u += " --http-host=HOST bind host for HTTP API (default: 127.0.0.1)\n";
u += " --http-port=N bind port for HTTP API\n";
u += " --http-access-token=T access token for HTTP API\n";
u += " --http-no-restricted enable full remote access to HTTP API (only if access token set)\n";
# endif
# ifdef XMRIG_FEATURE_TLS
u += "\nTLS:\n";
u += " --tls-gen=HOSTNAME generate TLS certificate for specific hostname\n";
@@ -172,6 +177,7 @@ static inline const std::string &usage()
u += " --title set custom console window title\n";
u += " --no-title disable setting console window title\n";
# endif
u += " --pause-on-battery pause mine on battery power\n";
return u;
}

View File

@@ -72,8 +72,8 @@ bool xmrig::argon2::Impl::select(const String &nameHint, bool benchmark)
}
}
if (hint.isEmpty() || argon2_select_impl_by_name(hint) == 0) {
argon2_select_impl();
if (!hint.isEmpty()) {
argon2_select_impl_by_name(hint);
}
# endif

View File

@@ -33,7 +33,6 @@
#include "crypto/cn/CryptoNight_monero.h"
#include "crypto/cn/CryptoNight.h"
#include "crypto/cn/soft_aes.h"
#include "crypto/common/portable/mm_malloc.h"
extern "C"
@@ -68,34 +67,6 @@ static inline void do_skein_hash(const uint8_t *input, size_t len, uint8_t *outp
void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
static inline __attribute__((always_inline)) __m128i _mm_set_epi64x(const uint64_t a, const uint64_t b)
{
return vcombine_u64(vcreate_u64(b), vcreate_u64(a));
}
#if __ARM_FEATURE_CRYPTO
static inline __attribute__((always_inline)) __m128i _mm_aesenc_si128(__m128i v, __m128i rkey)
{
alignas(16) const __m128i zero = { 0 };
return veorq_u8(vaesmcq_u8(vaeseq_u8(v, zero)), rkey );
}
#else
static inline __attribute__((always_inline)) __m128i _mm_aesenc_si128(__m128i v, __m128i rkey)
{
alignas(16) const __m128i zero = { 0 };
return zero;
}
#endif
/* this one was not implemented yet so here it is */
static inline __attribute__((always_inline)) uint64_t _mm_cvtsi128_si64(__m128i a)
{
return vgetq_lane_u64(a, 0);
}
#if defined (__arm64__) || defined (__aarch64__)
static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
{

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,7 @@
#if defined(XMRIG_ARM)
# include "crypto/cn/SSE2NEON.h"
# include "crypto/cn/sse2neon.h"
#elif defined(__GNUC__)
# include <x86intrin.h>
#else

4151
src/crypto/cn/sse2neon.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -26,18 +26,14 @@
#include "crypto/common/Nonce.h"
#include <mutex>
namespace xmrig {
std::atomic<bool> Nonce::m_paused;
std::atomic<uint64_t> Nonce::m_sequence[Nonce::MAX];
uint32_t Nonce::m_nonces[2] = { 0, 0 };
std::atomic<uint64_t> Nonce::m_nonces[2] = { {0}, {0} };
static std::mutex mutex;
static Nonce nonce;
@@ -54,40 +50,34 @@ xmrig::Nonce::Nonce()
}
uint32_t xmrig::Nonce::next(uint8_t index, uint32_t nonce, uint32_t reserveCount, bool nicehash, bool *ok)
bool xmrig::Nonce::next(uint8_t index, uint32_t *nonce, uint32_t reserveCount, uint64_t mask)
{
uint32_t next;
mask &= 0x7FFFFFFFFFFFFFFFULL;
if (reserveCount == 0 || mask < reserveCount - 1) {
return false;
}
std::lock_guard<std::mutex> lock(mutex);
if (nicehash) {
if ((m_nonces[index] + reserveCount) > 0x1000000) {
if (ok) {
*ok = false;
}
pause(true);
return 0;
uint64_t counter = m_nonces[index].fetch_add(reserveCount, std::memory_order_relaxed);
while (true) {
if (mask < counter) {
return false;
}
next = (nonce & 0xFF000000) | m_nonces[index];
else if (mask - counter <= reserveCount - 1) {
pause(true);
if (mask - counter < reserveCount - 1) {
return false;
}
}
else if (0xFFFFFFFFUL - (uint32_t)counter < reserveCount - 1) {
counter = m_nonces[index].fetch_add(reserveCount, std::memory_order_relaxed);
continue;
}
*nonce = (nonce[0] & ~mask) | counter;
if (mask > 0xFFFFFFFFULL) {
nonce[1] = (nonce[1] & (~mask >> 32)) | (counter >> 32);
}
return true;
}
else {
next = m_nonces[index];
}
m_nonces[index] += reserveCount;
return next;
}
void xmrig::Nonce::reset(uint8_t index)
{
std::lock_guard<std::mutex> lock(mutex);
m_nonces[index] = 0;
}

View File

@@ -49,18 +49,18 @@ public:
static inline bool isPaused() { return m_paused.load(std::memory_order_relaxed); }
static inline uint64_t sequence(Backend backend) { return m_sequence[backend].load(std::memory_order_relaxed); }
static inline void pause(bool paused) { m_paused = paused; }
static inline void reset(uint8_t index) { m_nonces[index] = 0; }
static inline void stop(Backend backend) { m_sequence[backend] = 0; }
static inline void touch(Backend backend) { m_sequence[backend]++; }
static uint32_t next(uint8_t index, uint32_t nonce, uint32_t reserveCount, bool nicehash, bool *ok = nullptr);
static void reset(uint8_t index);
static bool next(uint8_t index, uint32_t *nonce, uint32_t reserveCount, uint64_t mask);
static void stop();
static void touch();
private:
static std::atomic<bool> m_paused;
static std::atomic<uint64_t> m_sequence[MAX];
static uint32_t m_nonces[2];
static std::atomic<uint64_t> m_nonces[2];
};

View File

@@ -51,6 +51,7 @@ static std::mutex mutex;
xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool oneGbPages, bool usePool, uint32_t node, size_t alignSize) :
m_size(align(size)),
m_capacity(m_size),
m_node(node)
{
if (usePool) {
@@ -69,6 +70,7 @@ xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool oneGbPages
}
if (oneGbPages && allocateOneGbPagesMemory()) {
m_capacity = align(size, 1ULL << 30);
return;
}

View File

@@ -52,6 +52,7 @@ public:
inline bool isHugePages() const { return m_flags.test(FLAG_HUGEPAGES); }
inline bool isOneGbPages() const { return m_flags.test(FLAG_1GB_PAGES); }
inline size_t size() const { return m_size; }
inline size_t capacity() const { return m_capacity; }
inline uint8_t *raw() const { return m_scratchpad; }
inline uint8_t *scratchpad() const { return m_scratchpad; }
@@ -88,6 +89,7 @@ private:
void freeLargePagesMemory();
const size_t m_size;
size_t m_capacity;
const uint32_t m_node;
std::bitset<FLAG_MAX> m_flags;
uint8_t *m_scratchpad = nullptr;

View File

@@ -82,7 +82,17 @@ void *xmrig::VirtualMemory::allocateLargePagesMemory(size_t size)
# elif defined(__FreeBSD__)
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0);
# else
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0);
# if defined(MAP_HUGE_2MB)
constexpr int flag_2mb = MAP_HUGE_2MB;
# elif defined(MAP_HUGE_SHIFT)
constexpr int flag_2mb = (21 << MAP_HUGE_SHIFT);
# else
constexpr int flag_2mb = 0;
# endif
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE | flag_2mb, 0, 0);
# endif
return mem == MAP_FAILED ? nullptr : mem;

View File

@@ -91,10 +91,10 @@ bool KPCache::init(uint32_t epoch)
const uint32_t a = (cache_nodes * i) / n;
const uint32_t b = (cache_nodes * (i + 1)) / n;
threads.emplace_back([this, a, b, cache_nodes, &cache]() {
for (uint32_t j = a; j < b; ++j) {
ethash_calculate_dag_item_opt(((node*)m_DAGCache.data()) + j, j, num_dataset_parents, &cache);
}
threads.emplace_back([this, a, b, &cache]() {
uint32_t j = a;
for (; j + 4 <= b; j += 4) ethash_calculate_dag_item4_opt(((node*)m_DAGCache.data()) + j, j, num_dataset_parents, &cache);
for (; j < b; ++j) ethash_calculate_dag_item_opt(((node*)m_DAGCache.data()) + j, j, num_dataset_parents, &cache);
});
}

View File

@@ -285,10 +285,7 @@ void KPHash::calculate(const KPCache& light_cache, uint32_t block_height, const
uint32_t item_index = (mix[r % LANES][0] % num_items) * 4;
node item[4];
ethash_calculate_dag_item_opt(item + 0, item_index + 0, KPCache::num_dataset_parents, &cache);
ethash_calculate_dag_item_opt(item + 1, item_index + 1, KPCache::num_dataset_parents, &cache);
ethash_calculate_dag_item_opt(item + 2, item_index + 2, KPCache::num_dataset_parents, &cache);
ethash_calculate_dag_item_opt(item + 3, item_index + 3, KPCache::num_dataset_parents, &cache);
ethash_calculate_dag_item4_opt(item, item_index, KPCache::num_dataset_parents, &cache);
uint32_t dst_counter = 0;
uint32_t src_counter = 0;

View File

@@ -28,6 +28,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "crypto/randomx/soft_aes.h"
#include "crypto/randomx/randomx.h"
#include "base/tools/Profiler.h"
#define AES_HASH_1R_STATE0 0xd7983aad, 0xcc82db47, 0x9fa856de, 0x92b52c0d
#define AES_HASH_1R_STATE1 0xace78057, 0xf59e125a, 0x15c7b798, 0x338d996e
@@ -49,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Hashing throughput: >20 GiB/s per CPU core with hardware AES
*/
template<bool softAes>
template<int softAes>
void hashAes1Rx4(const void *input, size_t inputSize, void *hash) {
const uint8_t* inptr = (uint8_t*)input;
const uint8_t* inputEnd = inptr + inputSize;
@@ -117,7 +118,7 @@ template void hashAes1Rx4<true>(const void *input, size_t inputSize, void *hash)
The modified state is written back to 'state' to allow multiple
calls to this function.
*/
template<bool softAes>
template<int softAes>
void fillAes1Rx4(void *state, size_t outputSize, void *buffer) {
const uint8_t* outptr = (uint8_t*)buffer;
const uint8_t* outputEnd = outptr + outputSize;
@@ -158,7 +159,7 @@ void fillAes1Rx4(void *state, size_t outputSize, void *buffer) {
template void fillAes1Rx4<true>(void *state, size_t outputSize, void *buffer);
template void fillAes1Rx4<false>(void *state, size_t outputSize, void *buffer);
template<bool softAes>
template<int softAes>
void fillAes4Rx4(void *state, size_t outputSize, void *buffer) {
const uint8_t* outptr = (uint8_t*)buffer;
const uint8_t* outputEnd = outptr + outputSize;
@@ -213,8 +214,10 @@ void fillAes4Rx4(void *state, size_t outputSize, void *buffer) {
template void fillAes4Rx4<true>(void *state, size_t outputSize, void *buffer);
template void fillAes4Rx4<false>(void *state, size_t outputSize, void *buffer);
template<bool softAes>
template<int softAes>
void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state) {
PROFILE_SCOPE(RandomX_AES);
uint8_t* scratchpadPtr = (uint8_t*)scratchpad;
const uint8_t* scratchpadEnd = scratchpadPtr + scratchpadSize;
@@ -241,38 +244,29 @@ void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, voi
for (int i = 0; i < 2; ++i) {
//process 64 bytes at a time in 4 lanes
while (scratchpadPtr < scratchpadEnd) {
hash_state0 = aesenc<softAes>(hash_state0, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 0));
hash_state1 = aesdec<softAes>(hash_state1, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 1));
hash_state2 = aesenc<softAes>(hash_state2, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 2));
hash_state3 = aesdec<softAes>(hash_state3, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 3));
#define HASH_STATE(k) \
hash_state0 = aesenc<softAes>(hash_state0, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + k * 4 + 0)); \
hash_state1 = aesdec<softAes>(hash_state1, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + k * 4 + 1)); \
hash_state2 = aesenc<softAes>(hash_state2, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + k * 4 + 2)); \
hash_state3 = aesdec<softAes>(hash_state3, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + k * 4 + 3));
fill_state0 = aesdec<softAes>(fill_state0, key0);
fill_state1 = aesenc<softAes>(fill_state1, key1);
fill_state2 = aesdec<softAes>(fill_state2, key2);
fill_state3 = aesenc<softAes>(fill_state3, key3);
#define FILL_STATE(k) \
fill_state0 = aesdec<softAes>(fill_state0, key0); \
fill_state1 = aesenc<softAes>(fill_state1, key1); \
fill_state2 = aesdec<softAes>(fill_state2, key2); \
fill_state3 = aesenc<softAes>(fill_state3, key3); \
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + k * 4 + 0, fill_state0); \
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + k * 4 + 1, fill_state1); \
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + k * 4 + 2, fill_state2); \
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + k * 4 + 3, fill_state3);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 0, fill_state0);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 1, fill_state1);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 2, fill_state2);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 3, fill_state3);
HASH_STATE(0);
HASH_STATE(1);
FILL_STATE(0);
FILL_STATE(1);
rx_prefetch_t0(prefetchPtr);
hash_state0 = aesenc<softAes>(hash_state0, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 4));
hash_state1 = aesdec<softAes>(hash_state1, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 5));
hash_state2 = aesenc<softAes>(hash_state2, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 6));
hash_state3 = aesdec<softAes>(hash_state3, rx_load_vec_i128((rx_vec_i128*)scratchpadPtr + 7));
fill_state0 = aesdec<softAes>(fill_state0, key0);
fill_state1 = aesenc<softAes>(fill_state1, key1);
fill_state2 = aesdec<softAes>(fill_state2, key2);
fill_state3 = aesenc<softAes>(fill_state3, key3);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 4, fill_state0);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 5, fill_state1);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 6, fill_state2);
rx_store_vec_i128((rx_vec_i128*)scratchpadPtr + 7, fill_state3);
rx_prefetch_t0(prefetchPtr + 64);
scratchpadPtr += 128;
@@ -308,5 +302,6 @@ void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, voi
rx_store_vec_i128((rx_vec_i128*)hash + 3, hash_state3);
}
template void hashAndFillAes1Rx4<false>(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);
template void hashAndFillAes1Rx4<true>(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);
template void hashAndFillAes1Rx4<0>(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);
template void hashAndFillAes1Rx4<1>(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);
template void hashAndFillAes1Rx4<2>(void* scratchpad, size_t scratchpadSize, void* hash, void* fill_state);

View File

@@ -30,14 +30,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstddef>
template<bool softAes>
template<int softAes>
void hashAes1Rx4(const void *input, size_t inputSize, void *hash);
template<bool softAes>
template<int softAes>
void fillAes1Rx4(void *state, size_t outputSize, void *buffer);
template<bool softAes>
template<int softAes>
void fillAes4Rx4(void *state, size_t outputSize, void *buffer);
template<bool softAes>
template<int softAes>
void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);

View File

@@ -1,13 +1,12 @@
mov rcx, rbp ;# ecx = ma
shr rcx, 32
and ecx, RANDOMX_DATASET_BASE_MASK
xor r8, qword ptr [rdi+rcx]
xor rbp, rax ;# modify "mx"
mov rax, qword ptr [rdi+rcx]
mov edx, ebp ;# edx = mx
and edx, RANDOMX_DATASET_BASE_MASK
prefetchnta byte ptr [rdi+rdx]
ror rbp, 32 ;# swap "ma" and "mx"
xor r8, rax
xor r9, qword ptr [rdi+rcx+8]
xor r10, qword ptr [rdi+rcx+16]
xor r11, qword ptr [rdi+rcx+24]

View File

@@ -92,7 +92,7 @@ extern "C" {
int rx_blake2b_final(blake2b_state *S, void *out, size_t outlen);
/* Simple API */
int rx_blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen);
int rx_blake2b(void *out, size_t outlen, const void *in, size_t inlen);
/* Argon2 Team - Begin Code */
int rxa2_blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);

View File

@@ -0,0 +1,123 @@
/*
BLAKE2 reference source code package - optimized C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#ifndef BLAKE2B_ROUND_H
#define BLAKE2B_ROUND_H
#define LOADU(p) _mm_loadu_si128( (const __m128i *)(p) )
#define STOREU(p,r) _mm_storeu_si128((__m128i *)(p), r)
#define TOF(reg) _mm_castsi128_ps((reg))
#define TOI(reg) _mm_castps_si128((reg))
#define LIKELY(x) __builtin_expect((x),1)
/* Microarchitecture-specific macros */
#define _mm_roti_epi64(x, c) \
(-(c) == 32) ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2,3,0,1)) \
: (-(c) == 24) ? _mm_shuffle_epi8((x), r24) \
: (-(c) == 16) ? _mm_shuffle_epi8((x), r16) \
: (-(c) == 63) ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_add_epi64((x), (x))) \
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_slli_epi64((x), 64-(-(c))))
#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -32); \
row4h = _mm_roti_epi64(row4h, -32); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -24); \
row2h = _mm_roti_epi64(row2h, -24); \
#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \
row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \
row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \
\
row4l = _mm_xor_si128(row4l, row1l); \
row4h = _mm_xor_si128(row4h, row1h); \
\
row4l = _mm_roti_epi64(row4l, -16); \
row4h = _mm_roti_epi64(row4h, -16); \
\
row3l = _mm_add_epi64(row3l, row4l); \
row3h = _mm_add_epi64(row3h, row4h); \
\
row2l = _mm_xor_si128(row2l, row3l); \
row2h = _mm_xor_si128(row2h, row3h); \
\
row2l = _mm_roti_epi64(row2l, -63); \
row2h = _mm_roti_epi64(row2h, -63); \
#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = _mm_alignr_epi8(row2h, row2l, 8); \
t1 = _mm_alignr_epi8(row2l, row2h, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4h, row4l, 8); \
t1 = _mm_alignr_epi8(row4l, row4h, 8); \
row4l = t1; \
row4h = t0;
#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \
t0 = _mm_alignr_epi8(row2l, row2h, 8); \
t1 = _mm_alignr_epi8(row2h, row2l, 8); \
row2l = t0; \
row2h = t1; \
\
t0 = row3l; \
row3l = row3h; \
row3h = t0; \
\
t0 = _mm_alignr_epi8(row4l, row4h, 8); \
t1 = _mm_alignr_epi8(row4h, row4l, 8); \
row4l = t1; \
row4h = t0;
#define LOAD_MSG(r, i, b0, b1) \
do { \
b0 = _mm_set_epi64x(m[blake2b_sigma_sse41[r][i * 4 + 1]], m[blake2b_sigma_sse41[r][i * 4 + 0]]); \
b1 = _mm_set_epi64x(m[blake2b_sigma_sse41[r][i * 4 + 3]], m[blake2b_sigma_sse41[r][i * 4 + 2]]); \
} while(0)
#define ROUND(r) \
LOAD_MSG(r, 0, b0, b1); \
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
LOAD_MSG(r, 1, b0, b1); \
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \
LOAD_MSG(r, 2, b0, b1); \
G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
LOAD_MSG(r, 3, b0, b1); \
G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \
UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);
#endif

View File

@@ -39,12 +39,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "crypto/randomx/blake2/blake2.h"
#include "crypto/randomx/blake2/blake2-impl.h"
#if defined(_M_X64) || defined(__x86_64__)
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include <smmintrin.h>
#include "blake2b-round.h"
#endif
static const uint64_t blake2b_IV[8] = {
UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179) };
#if defined(_M_X64) || defined(__x86_64__)
static const uint8_t blake2b_sigma_sse41[12][16] = {
{0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
{14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3},
{11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4},
{7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8},
{9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13},
{2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9},
{12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11},
{13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10},
{6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5},
{10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0},
{0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
{14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3},
};
#endif
static const uint8_t blake2b_sigma[12][16] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
@@ -179,7 +207,47 @@ int rx_blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t
return 0;
}
static void rx_blake2b_compress(blake2b_state *S, const uint8_t *block) {
#if defined(_M_X64) || defined(__x86_64__)
static void rx_blake2b_compress_sse41(blake2b_state* S, const uint8_t *block)
{
__m128i row1l, row1h;
__m128i row2l, row2h;
__m128i row3l, row3h;
__m128i row4l, row4h;
__m128i b0, b1;
__m128i t0, t1;
const __m128i r16 = _mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9);
const __m128i r24 = _mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10);
row1l = LOADU(&S->h[0]);
row1h = LOADU(&S->h[2]);
row2l = LOADU(&S->h[4]);
row2h = LOADU(&S->h[6]);
row3l = LOADU(&blake2b_IV[0]);
row3h = LOADU(&blake2b_IV[2]);
row4l = _mm_xor_si128(LOADU(&blake2b_IV[4]), LOADU(&S->t[0]));
row4h = _mm_xor_si128(LOADU(&blake2b_IV[6]), LOADU(&S->f[0]));
const uint64_t* m = (const uint64_t*)(block);
for (uint32_t r = 0; r < 12; ++r) {
ROUND(r);
}
row1l = _mm_xor_si128(row3l, row1l);
row1h = _mm_xor_si128(row3h, row1h);
STOREU(&S->h[0], _mm_xor_si128(LOADU(&S->h[0]), row1l));
STOREU(&S->h[2], _mm_xor_si128(LOADU(&S->h[2]), row1h));
row2l = _mm_xor_si128(row4l, row2l);
row2h = _mm_xor_si128(row4h, row2h);
STOREU(&S->h[4], _mm_xor_si128(LOADU(&S->h[4]), row2l));
STOREU(&S->h[6], _mm_xor_si128(LOADU(&S->h[6]), row2h));
}
#undef ROUND
#endif
static void rx_blake2b_compress_integer(blake2b_state *S, const uint8_t *block) {
uint64_t m[16];
uint64_t v[16];
unsigned int i, r;
@@ -237,6 +305,20 @@ static void rx_blake2b_compress(blake2b_state *S, const uint8_t *block) {
#undef ROUND
}
#if defined(_M_X64) || defined(__x86_64__)
uint32_t rx_blake2b_use_sse41 = 0;
#define rx_blake2b_compress(S, block) \
if (rx_blake2b_use_sse41) \
rx_blake2b_compress_sse41(S, block); \
else \
rx_blake2b_compress_integer(S, block);
#else
#define rx_blake2b_compress(S, block) rx_blake2b_compress_integer(S, block);
#endif
int rx_blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
const uint8_t *pin = (const uint8_t *)in;
@@ -260,14 +342,14 @@ int rx_blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
size_t fill = BLAKE2B_BLOCKBYTES - left;
memcpy(&S->buf[left], pin, fill);
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
rx_blake2b_compress(S, S->buf);
rx_blake2b_compress(S, S->buf);
S->buflen = 0;
inlen -= fill;
pin += fill;
/* Avoid buffer copies when possible */
while (inlen > BLAKE2B_BLOCKBYTES) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
rx_blake2b_compress(S, pin);
rx_blake2b_compress(S, pin);
inlen -= BLAKE2B_BLOCKBYTES;
pin += BLAKE2B_BLOCKBYTES;
}
@@ -294,7 +376,7 @@ int rx_blake2b_final(blake2b_state *S, void *out, size_t outlen) {
blake2b_increment_counter(S, S->buflen);
blake2b_set_lastblock(S);
memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
rx_blake2b_compress(S, S->buf);
rx_blake2b_compress(S, S->buf);
for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
@@ -307,8 +389,7 @@ int rx_blake2b_final(blake2b_state *S, void *out, size_t outlen) {
return 0;
}
int rx_blake2b(void *out, size_t outlen, const void *in, size_t inlen,
const void *key, size_t keylen) {
int rx_blake2b(void *out, size_t outlen, const void *in, size_t inlen) {
blake2b_state S;
int ret = -1;
@@ -321,25 +402,14 @@ int rx_blake2b(void *out, size_t outlen, const void *in, size_t inlen,
goto fail;
}
if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) {
if (rx_blake2b_init(&S, outlen) < 0) {
goto fail;
}
if (keylen > 0) {
if (rx_blake2b_init_key(&S, outlen, key, keylen) < 0) {
goto fail;
}
}
else {
if (rx_blake2b_init(&S, outlen) < 0) {
goto fail;
}
}
if (rx_blake2b_update(&S, in, inlen) < 0) {
if (rx_blake2b_update(&S, in, inlen) < 0) {
goto fail;
}
ret = rx_blake2b_final(&S, out, outlen);
ret = rx_blake2b_final(&S, out, outlen);
fail:
//clear_internal_memory(&S, sizeof(S));
@@ -361,43 +431,42 @@ int rxa2_blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
store32(outlen_bytes, (uint32_t)outlen);
#define TRY(statement) \
do { \
ret = statement; \
if (ret < 0) { \
goto fail; \
} \
} while ((void)0, 0)
do { \
ret = statement; \
if (ret < 0) { \
goto fail; \
} \
} while ((void)0, 0)
if (outlen <= BLAKE2B_OUTBYTES) {
TRY(rx_blake2b_init(&blake_state, outlen));
TRY(rx_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(rx_blake2b_update(&blake_state, in, inlen));
TRY(rx_blake2b_final(&blake_state, out, outlen));
TRY(rx_blake2b_init(&blake_state, outlen));
TRY(rx_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(rx_blake2b_update(&blake_state, in, inlen));
TRY(rx_blake2b_final(&blake_state, out, outlen));
}
else {
uint32_t toproduce;
uint8_t out_buffer[BLAKE2B_OUTBYTES];
uint8_t in_buffer[BLAKE2B_OUTBYTES];
TRY(rx_blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
TRY(rx_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(rx_blake2b_update(&blake_state, in, inlen));
TRY(rx_blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
TRY(rx_blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
TRY(rx_blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
TRY(rx_blake2b_update(&blake_state, in, inlen));
TRY(rx_blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
while (toproduce > BLAKE2B_OUTBYTES) {
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
TRY(rx_blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
BLAKE2B_OUTBYTES, NULL, 0));
TRY(rx_blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
BLAKE2B_OUTBYTES));
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
out += BLAKE2B_OUTBYTES / 2;
toproduce -= BLAKE2B_OUTBYTES / 2;
}
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
TRY(rx_blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
0));
TRY(rx_blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES));
memcpy(out, out_buffer, toproduce);
}
fail:

View File

@@ -55,7 +55,7 @@ namespace randomx {
void Blake2Generator::checkData(const size_t bytesNeeded) {
if (dataIndex + bytesNeeded > sizeof(data)) {
rx_blake2b(data, sizeof(data), data, sizeof(data), nullptr, 0);
rx_blake2b(data, sizeof(data), data, sizeof(data));
dataIndex = 0;
}
}

View File

@@ -79,9 +79,9 @@ namespace randomx {
}
void BytecodeMachine::compileInstruction(RANDOMX_GEN_ARGS) {
int opcode = instr.opcode;
uint32_t opcode = instr.opcode;
if (opcode < RandomX_CurrentConfig.CEIL_IADD_RS) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IADD_RS) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IADD_RS;
@@ -99,8 +99,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IADD_RS;
if (opcode < RandomX_CurrentConfig.CEIL_IADD_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IADD_M) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IADD_M;
@@ -108,7 +109,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
if (src != dst) {
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
}
else {
ibc.isrc = &zero;
@@ -117,8 +118,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IADD_M;
if (opcode < RandomX_CurrentConfig.CEIL_ISUB_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_ISUB_R) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::ISUB_R;
@@ -133,8 +135,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_ISUB_R;
if (opcode < RandomX_CurrentConfig.CEIL_ISUB_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_ISUB_M) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::ISUB_M;
@@ -142,7 +145,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
if (src != dst) {
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
}
else {
ibc.isrc = &zero;
@@ -151,8 +154,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_ISUB_M;
if (opcode < RandomX_CurrentConfig.CEIL_IMUL_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IMUL_R) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IMUL_R;
@@ -167,8 +171,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IMUL_R;
if (opcode < RandomX_CurrentConfig.CEIL_IMUL_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IMUL_M) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IMUL_M;
@@ -176,7 +181,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
if (src != dst) {
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
}
else {
ibc.isrc = &zero;
@@ -185,8 +190,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IMUL_M;
if (opcode < RandomX_CurrentConfig.CEIL_IMULH_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IMULH_R) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IMULH_R;
@@ -195,8 +201,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IMULH_R;
if (opcode < RandomX_CurrentConfig.CEIL_IMULH_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IMULH_M) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IMULH_M;
@@ -204,7 +211,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
if (src != dst) {
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
}
else {
ibc.isrc = &zero;
@@ -213,8 +220,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IMULH_M;
if (opcode < RandomX_CurrentConfig.CEIL_ISMULH_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_ISMULH_R) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::ISMULH_R;
@@ -223,8 +231,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_ISMULH_R;
if (opcode < RandomX_CurrentConfig.CEIL_ISMULH_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_ISMULH_M) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::ISMULH_M;
@@ -232,7 +241,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
if (src != dst) {
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
}
else {
ibc.isrc = &zero;
@@ -241,8 +250,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_ISMULH_M;
if (opcode < RandomX_CurrentConfig.CEIL_IMUL_RCP) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IMUL_RCP) {
uint64_t divisor = instr.getImm32();
if (!isZeroOrPowerOf2(divisor)) {
auto dst = instr.dst % RegistersCount;
@@ -257,16 +267,18 @@ namespace randomx {
}
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IMUL_RCP;
if (opcode < RandomX_CurrentConfig.CEIL_INEG_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_INEG_R) {
auto dst = instr.dst % RegistersCount;
ibc.type = InstructionType::INEG_R;
ibc.idst = &nreg->r[dst];
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_INEG_R;
if (opcode < RandomX_CurrentConfig.CEIL_IXOR_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IXOR_R) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IXOR_R;
@@ -281,8 +293,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IXOR_R;
if (opcode < RandomX_CurrentConfig.CEIL_IXOR_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IXOR_M) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IXOR_M;
@@ -290,7 +303,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
if (src != dst) {
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
}
else {
ibc.isrc = &zero;
@@ -299,8 +312,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IXOR_M;
if (opcode < RandomX_CurrentConfig.CEIL_IROR_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IROR_R) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IROR_R;
@@ -315,8 +329,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IROR_R;
if (opcode < RandomX_CurrentConfig.CEIL_IROL_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_IROL_R) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::IROL_R;
@@ -331,8 +346,9 @@ namespace randomx {
registerUsage[dst] = i;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_IROL_R;
if (opcode < RandomX_CurrentConfig.CEIL_ISWAP_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_ISWAP_R) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
if (src != dst) {
@@ -347,8 +363,9 @@ namespace randomx {
}
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_ISWAP_R;
if (opcode < RandomX_CurrentConfig.CEIL_FSWAP_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FSWAP_R) {
auto dst = instr.dst % RegistersCount;
ibc.type = InstructionType::FSWAP_R;
if (dst < RegisterCountFlt)
@@ -357,8 +374,9 @@ namespace randomx {
ibc.fdst = &nreg->e[dst - RegisterCountFlt];
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FSWAP_R;
if (opcode < RandomX_CurrentConfig.CEIL_FADD_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FADD_R) {
auto dst = instr.dst % RegisterCountFlt;
auto src = instr.src % RegisterCountFlt;
ibc.type = InstructionType::FADD_R;
@@ -366,19 +384,21 @@ namespace randomx {
ibc.fsrc = &nreg->a[src];
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FADD_R;
if (opcode < RandomX_CurrentConfig.CEIL_FADD_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FADD_M) {
auto dst = instr.dst % RegisterCountFlt;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::FADD_M;
ibc.fdst = &nreg->f[dst];
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
ibc.imm = signExtend2sCompl(instr.getImm32());
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FADD_M;
if (opcode < RandomX_CurrentConfig.CEIL_FSUB_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FSUB_R) {
auto dst = instr.dst % RegisterCountFlt;
auto src = instr.src % RegisterCountFlt;
ibc.type = InstructionType::FSUB_R;
@@ -386,26 +406,29 @@ namespace randomx {
ibc.fsrc = &nreg->a[src];
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FSUB_R;
if (opcode < RandomX_CurrentConfig.CEIL_FSUB_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FSUB_M) {
auto dst = instr.dst % RegisterCountFlt;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::FSUB_M;
ibc.fdst = &nreg->f[dst];
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
ibc.imm = signExtend2sCompl(instr.getImm32());
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FSUB_M;
if (opcode < RandomX_CurrentConfig.CEIL_FSCAL_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FSCAL_R) {
auto dst = instr.dst % RegisterCountFlt;
ibc.fdst = &nreg->f[dst];
ibc.type = InstructionType::FSCAL_R;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FSCAL_R;
if (opcode < RandomX_CurrentConfig.CEIL_FMUL_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FMUL_R) {
auto dst = instr.dst % RegisterCountFlt;
auto src = instr.src % RegisterCountFlt;
ibc.type = InstructionType::FMUL_R;
@@ -413,52 +436,56 @@ namespace randomx {
ibc.fsrc = &nreg->a[src];
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FMUL_R;
if (opcode < RandomX_CurrentConfig.CEIL_FDIV_M) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FDIV_M) {
auto dst = instr.dst % RegisterCountFlt;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::FDIV_M;
ibc.fdst = &nreg->e[dst];
ibc.isrc = &nreg->r[src];
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
ibc.imm = signExtend2sCompl(instr.getImm32());
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FDIV_M;
if (opcode < RandomX_CurrentConfig.CEIL_FSQRT_R) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_FSQRT_R) {
auto dst = instr.dst % RegisterCountFlt;
ibc.type = InstructionType::FSQRT_R;
ibc.fdst = &nreg->e[dst];
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_FSQRT_R;
if (opcode < RandomX_CurrentConfig.CEIL_CBRANCH) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_CBRANCH) {
ibc.type = InstructionType::CBRANCH;
//jump condition
int creg = instr.dst % RegistersCount;
ibc.idst = &nreg->r[creg];
ibc.target = registerUsage[creg];
int shift = instr.getModCond() + RandomX_CurrentConfig.JumpOffset;
ibc.imm = signExtend2sCompl(instr.getImm32()) | (1ULL << shift);
if (RandomX_CurrentConfig.JumpOffset > 0 || shift > 0) //clear the bit below the condition mask - this limits the number of successive jumps to 2
ibc.imm &= ~(1ULL << (shift - 1));
ibc.memMask = RandomX_CurrentConfig.ConditionMask_Calculated << shift;
const int shift = instr.getModCond();
ibc.imm = signExtend2sCompl(instr.getImm32()) | ((1ULL << RandomX_ConfigurationBase::JumpOffset) << shift);
ibc.imm &= ~((1ULL << (RandomX_ConfigurationBase::JumpOffset - 1)) << shift);
ibc.memMask = RandomX_ConfigurationBase::ConditionMask_Calculated << shift;
//mark all registers as used
for (unsigned j = 0; j < RegistersCount; ++j) {
registerUsage[j] = i;
}
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_CBRANCH;
if (opcode < RandomX_CurrentConfig.CEIL_CFROUND) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_CFROUND) {
auto src = instr.src % RegistersCount;
ibc.isrc = &nreg->r[src];
ibc.type = InstructionType::CFROUND;
ibc.imm = instr.getImm32() & 63;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_CFROUND;
if (opcode < RandomX_CurrentConfig.CEIL_ISTORE) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_ISTORE) {
auto dst = instr.dst % RegistersCount;
auto src = instr.src % RegistersCount;
ibc.type = InstructionType::ISTORE;
@@ -466,13 +493,14 @@ namespace randomx {
ibc.isrc = &nreg->r[src];
ibc.imm = signExtend2sCompl(instr.getImm32());
if (instr.getModCond() < StoreL3Condition)
ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
ibc.memMask = AddressMask[instr.getModMem()];
else
ibc.memMask = ScratchpadL3Mask;
return;
}
opcode -= RandomX_CurrentConfig.RANDOMX_FREQ_ISTORE;
if (opcode < RandomX_CurrentConfig.CEIL_NOP) {
if (opcode < RandomX_CurrentConfig.RANDOMX_FREQ_NOP) {
ibc.type = InstructionType::NOP;
return;
}

View File

@@ -225,7 +225,7 @@ namespace randomx {
}
static void exe_CFROUND(RANDOMX_EXE_ARGS) {
rx_set_rounding_mode(rotr64(*ibc.isrc, ibc.imm) % 4);
rx_set_rounding_mode(rotr64(*ibc.isrc, static_cast<uint32_t>(ibc.imm)) % 4);
}
static void exe_ISTORE(RANDOMX_EXE_ARGS) {

View File

@@ -74,8 +74,8 @@ namespace randomx {
constexpr int SuperscalarMaxSize = 3 * RANDOMX_SUPERSCALAR_MAX_LATENCY + 2;
constexpr size_t CacheLineSize = RANDOMX_DATASET_ITEM_SIZE;
#define ScratchpadSize RandomX_CurrentConfig.ScratchpadL3_Size
#define CacheLineAlignMask RandomX_CurrentConfig.CacheLineAlignMask_Calculated
#define DatasetExtraItems RandomX_CurrentConfig.DatasetExtraItems_Calculated
#define CacheLineAlignMask RandomX_ConfigurationBase::CacheLineAlignMask_Calculated
#define DatasetExtraItems RandomX_ConfigurationBase::DatasetExtraItems_Calculated
constexpr int StoreL3Condition = 14;
//Prevent some unsafe configurations.
@@ -126,10 +126,7 @@ namespace randomx {
double hi;
};
#define ScratchpadL1Mask RandomX_CurrentConfig.ScratchpadL1Mask_Calculated
#define ScratchpadL1Mask16 RandomX_CurrentConfig.ScratchpadL1Mask16_Calculated
#define ScratchpadL2Mask RandomX_CurrentConfig.ScratchpadL2Mask_Calculated
#define ScratchpadL2Mask16 RandomX_CurrentConfig.ScratchpadL2Mask16_Calculated
#define AddressMask RandomX_CurrentConfig.AddressMask_Calculated
#define ScratchpadL3Mask RandomX_CurrentConfig.ScratchpadL3Mask_Calculated
#define ScratchpadL3Mask64 RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated
constexpr int RegistersCount = 8;

View File

@@ -414,7 +414,7 @@ FORCE_INLINE void rx_store_vec_f128(double* mem_addr, rx_vec_f128 val) {
}
FORCE_INLINE rx_vec_f128 rx_swap_vec_f128(rx_vec_f128 a) {
float64x2_t temp;
float64x2_t temp{};
temp = vcopyq_laneq_f64(temp, 1, a, 1);
a = vcopyq_laneq_f64(a, 1, a, 0);
return vcopyq_laneq_f64(a, 0, temp, 1);
@@ -505,7 +505,7 @@ FORCE_INLINE void rx_store_vec_i128(rx_vec_i128* mem_addr, rx_vec_i128 val) {
FORCE_INLINE rx_vec_f128 rx_cvt_packed_int_vec_f128(const void* addr) {
double lo = unsigned32ToSigned2sCompl(load32((uint8_t*)addr + 0));
double hi = unsigned32ToSigned2sCompl(load32((uint8_t*)addr + 4));
rx_vec_f128 x;
rx_vec_f128 x{};
x = vsetq_lane_f64(lo, x, 0);
x = vsetq_lane_f64(hi, x, 1);
return x;

View File

@@ -75,11 +75,11 @@ static size_t CalcDatasetItemSize()
// Prologue
((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch - (uint8_t*)randomx_calc_dataset_item_aarch64) +
// Main loop
RandomX_CurrentConfig.CacheAccesses * (
RandomX_ConfigurationBase::CacheAccesses * (
// Main loop prologue
((uint8_t*)randomx_calc_dataset_item_aarch64_mix - ((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch)) + 4 +
// Inner main loop (instructions)
((RandomX_CurrentConfig.SuperscalarLatency * 3) + 2) * 16 +
((RandomX_ConfigurationBase::SuperscalarLatency * 3) + 2) * 16 +
// Main loop epilogue
((uint8_t*)randomx_calc_dataset_item_aarch64_store_result - (uint8_t*)randomx_calc_dataset_item_aarch64_mix) + 4
) +
@@ -235,7 +235,7 @@ void JitCompilerA64::generateSuperscalarHash(SuperscalarProgram(&programs)[N], s
num32bitLiterals = 64;
constexpr uint32_t tmp_reg = 12;
for (size_t i = 0; i < RandomX_CurrentConfig.CacheAccesses; ++i)
for (size_t i = 0; i < RandomX_ConfigurationBase::CacheAccesses; ++i)
{
// and x11, x10, CacheSize / CacheLineSize - 1
emit32(0x92400000 | 11 | (10 << 5) | ((RandomX_CurrentConfig.Log2_CacheSize - 1) << 10), code, codePos);
@@ -946,7 +946,7 @@ void JitCompilerA64::h_CBRANCH(Instruction& instr, uint32_t& codePos)
const uint32_t dst = IntRegMap[instr.dst];
const uint32_t modCond = instr.getModCond();
const uint32_t shift = modCond + RandomX_CurrentConfig.JumpOffset;
const uint32_t shift = modCond + RandomX_ConfigurationBase::JumpOffset;
const uint32_t imm = (instr.getImm32() | (1U << shift)) & ~(1U << (shift - 1));
emitAddImmediate(dst, dst, imm, code, k);

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