1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-07 16:05:05 -05:00

Compare commits

...

139 Commits

Author SHA1 Message Date
XMRig
230ff87634 v6.14.1 2021-08-15 00:42:47 +07:00
XMRig
19adf2630a Merge branch 'dev' 2021-08-15 00:42:12 +07:00
xmrig
3de4b16117 Update CHANGELOG.md 2021-08-15 00:37:23 +07:00
XMRig
602e3a7587 Fix algorithms order. 2021-08-14 05:48:37 +07:00
XMRig
4f6ffb67c1 Cleanup. 2021-08-14 04:58:01 +07:00
xmrig
a0194ddd18 Merge pull request #2537 from SChernykh/dev
Fixed Termux build
2021-08-13 21:14:35 +07:00
SChernykh
30f7e876a2 Update CnHash.cpp 2021-08-13 16:03:15 +02:00
SChernykh
5958490c23 Fixed Termux build 2021-08-13 12:02:03 +02:00
XMRig
f92ad4423d Fix Job::getNumTransactions. 2021-08-12 22:30:47 +07:00
XMRig
e0749a82c2 Fix cn-pico name. 2021-08-12 17:52:52 +07:00
xmrig
440aa003af Merge pull request #2532 from xmrig/feature-stable-algo-id
Refactoring: Stable (persistent) algorithms IDs.
2021-08-12 02:03:39 +07:00
XMRig
9580f5395f Removed shortName. 2021-08-11 22:26:34 +07:00
XMRig
e9ae4deb91 Removed duplicate strings. 2021-08-11 22:07:43 +07:00
XMRig
aee0762424 Fix typo. 2021-08-11 16:27:36 +07:00
XMRig
e6332eff2b Implemented stable algorithm ids. 2021-08-11 03:46:34 +07:00
XMRig
d0a632f557 Optimize CnHash storage. 2021-08-10 14:54:35 +07:00
XMRig
f4cdc527b0 #2527 Fix narrowing conversion. 2021-08-10 01:40:36 +07:00
XMRig
661dc515ab namespace cleanup. 2021-08-09 23:51:07 +07:00
XMRig
6d9bafe068 v6.14.1-dev 2021-08-09 17:20:15 +07:00
XMRig
202c8aaee8 Merge branch 'master' into dev 2021-08-09 17:19:48 +07:00
XMRig
410084384e v6.14.0 2021-08-09 16:09:15 +07:00
XMRig
43e98c509a Merge branch 'dev' 2021-08-09 16:08:20 +07:00
XMRig
08d79ddcdc v6.14.0-dev 2021-08-08 19:36:54 +07:00
xmrig
0fdf063760 Merge pull request #2512 from SChernykh/dev
Show the number of transactions in pool job
2021-08-08 00:52:06 +07:00
SChernykh
929205536c Show the number of transactions in pool job
Useful to check if pool/proxy is working properly and can also be used to compare different pools.
2021-08-07 19:38:31 +02:00
XMRig
d24581c963 #2492 Add missing --huge-pages-jit command line option. 2021-07-24 12:27:48 +07:00
xmrig
2eb2e90631 Merge pull request #2484 from SChernykh/zmq
ZeroMQ support for solo mining
2021-07-17 17:14:42 +07:00
SChernykh
0842e6b9d2 ZeroMQ support for solo mining
Gets new blocks from daemon immediately without polling, saving ~0.5 seconds on average when daemon gets new block from the network. Also saves some CPU cycles because it doesn't need to poll daemon every second.

Testing: add "daemon-zmq-port": 28083 to xmrig's pool config in config.json and run ./monerod --testnet --zmq-pub tcp://127.0.0.1:28083
2021-07-15 11:13:14 +02:00
XMRig
93805cd167 #2476 Fixed crash in DMI memory reader. 2021-07-06 23:07:31 +07:00
xmrig
755fe28bc3 Merge pull request #2472 from SChernykh/dev
Updates from xmrig-proxy
2021-07-05 19:13:14 +07:00
SChernykh
59d780169f Merge branch 'dev' of https://github.com/SChernykh/xmrig into dev 2021-07-05 13:57:16 +02:00
SChernykh
a30ede04f3 Updates from xmrig-proxy 2021-07-05 13:56:37 +02:00
XMRig
3f2dfa4279 Sync with proxy. 2021-07-05 02:31:29 +07:00
XMRig
7177b42903 v6.13.2-dev 2021-07-03 16:00:30 +07:00
XMRig
21638c2f58 Merge branch 'master' into dev 2021-07-03 16:00:05 +07:00
XMRig
02b2b87bb6 v6.13.1 2021-07-03 15:29:49 +07:00
XMRig
c8a9dba8fd Merge branch 'dev' 2021-07-03 15:29:14 +07:00
xmrig
9a77d39a3f Update CHANGELOG.md 2021-07-03 15:16:47 +07:00
xmrig
28a1d0fe1e Merge pull request #2468 from SChernykh/dev
Fix: don't send miner signature during regular mining
2021-07-02 00:37:04 +07:00
XMRig
0243789c04 v6.13.1-dev 2021-07-02 00:36:32 +07:00
XMRig
45dd58f808 Merge branch 'master' into dev 2021-07-02 00:35:52 +07:00
SChernykh
1b4abe1e98 Fix: don't send miner signature during regular mining 2021-07-01 19:31:55 +02:00
XMRig
9f778742a6 v6.13.0 2021-07-01 20:03:52 +07:00
XMRig
015f8aeed4 Merge branch 'dev' 2021-07-01 20:02:38 +07:00
xmrig
9e6311a7e0 Update CHANGELOG.md 2021-07-01 13:54:09 +07:00
XMRig
0af9d2e75b v6.13.0-dev 2021-06-28 19:02:48 +07:00
xmrig
6e2a84a46c Merge pull request #2445 from SChernykh/miner_signature
Support for solo mining with miner signatures (Wownero)
2021-06-28 18:11:13 +07:00
SChernykh
6bb8913066 Correct handling of block submit responses for Dero 2021-06-24 18:06:07 +02:00
SChernykh
cf104ebdc5 Update signing algorithm 2021-06-21 23:49:13 +02:00
XMRig
ecba750442 Add token support for online benchmark. 2021-06-20 09:28:39 +07:00
SChernykh
3967badc55 Added profiling 2021-06-19 16:19:16 +02:00
SChernykh
3f3f9b0661 Fixed GCC warnings 2021-06-19 14:54:03 +02:00
SChernykh
e3fc78a66c Fix Wownero hardfork version 2021-06-18 13:52:24 +02:00
SChernykh
e6d833c227 Proxy miner signature support 2021-06-17 22:48:08 +02:00
SChernykh
ebe299902c Proxy miner signature support (WIP) 2021-06-17 16:58:18 +02:00
SChernykh
bc63b63a2a More sanity checks 2021-06-17 13:18:34 +02:00
SChernykh
e739e7d704 More error handling in DaemonClient::parseJob 2021-06-17 10:39:22 +02:00
SChernykh
1bae083587 Fixed CalculateMerkleTreeHash 2021-06-17 10:26:17 +02:00
SChernykh
88959bd703 BlockTemplate: miner tx and root hash updating 2021-06-16 23:44:05 +02:00
SChernykh
93e689d601 Fix buffer size in generateMinerSignature 2021-06-16 18:20:11 +02:00
SChernykh
a136790bee Added support for solo mining with miner signatures (Wownero) 2021-06-16 18:07:36 +02:00
SChernykh
29f2dd4b9e Cleanup 2021-06-16 11:47:17 +02:00
SChernykh
3003c067d3 Fixed random32_unbiased 2021-06-16 00:19:49 +02:00
SChernykh
89bc6418b1 Secret key derivation 2021-06-16 00:10:34 +02:00
SChernykh
8458b4ee39 Added signature functions 2021-06-15 15:51:29 +02:00
SChernykh
7bfb801ce2 Cryptonote tools WIP 2021-06-15 00:28:32 +02:00
xmrig
4567499905 Merge pull request #2433 from candrews/patch-2
Fix shellcheck warnings in randomx_boost.sh
2021-06-09 23:41:58 +07:00
Craig Andrews
9b63955b09 Fix shellcheck warnings in randomx_boost.sh
Checked using www.shellcheck.net

Specific issues addessed:
* https://github.com/koalaman/shellcheck/wiki/SC2002
* Use POSIX instead of bash for wider compatibility
* Fail on error
2021-06-08 21:56:02 -04:00
XMRig
0414511de0 v6.12.3-dev 2021-05-31 13:51:41 +07:00
XMRig
b61dad128c Merge branch 'master' into dev 2021-05-31 13:49:35 +07:00
XMRig
80ae339343 v6.12.2 2021-05-31 12:58:30 +07:00
XMRig
4d87555398 Merge branch 'dev' 2021-05-31 12:57:55 +07:00
xmrig
bef82c5de6 Update CHANGELOG.md 2021-05-30 21:28:28 +07:00
xmrig
b069ad5dd1 Merge pull request #2358 from zzjzxq33/patch-1
Update openssl version to 1.1.1k
2021-05-30 17:53:53 +07:00
xmrig
f6a0646271 Merge pull request #2401 from SChernykh/dev
RandomX: fix broken light mode mining
2021-05-22 18:54:29 +07:00
SChernykh
b5f1a1feae RandomX: fix broken light mode mining
It broke after #2395
2021-05-22 13:49:22 +02:00
XMRig
1ce059da1c Add "argon2/ninja" algorithm alias. 2021-05-22 15:10:50 +07:00
xmrig
2929451ee1 Merge pull request #2398 from SChernykh/dev
RandomX ARMv8: optimized dataset read
2021-05-21 09:58:54 +07:00
SChernykh
94fecb5e92 RandomX ARMv8: optimized dataset read
Break dependency from readReg2 and readReg3. It should run faster on superscalar and out-of-order CPUs i.e. Apple M1.
2021-05-20 21:24:28 +02:00
xmrig
3bfa5ea038 Merge pull request #2395 from SChernykh/dev
RandomX: rewrote dataset read code
2021-05-20 18:58:48 +07:00
SChernykh
ff82ca57f2 RandomX: rewrote dataset read code
Unified code for AMD and Intel
1% faster on Intel
0.15% faster on AMD Ryzen
2021-05-20 12:45:42 +02:00
xmrig
7f7b1fb073 Merge pull request #2393 from SChernykh/dev
RandomX: added BMI2 version for scratchpad prefetch
2021-05-19 22:54:58 +07:00
SChernykh
d443dd86f1 RandomX: added BMI2 version for scratchpad prefetch
Saves 1 instruction and 1 byte in the main loop.
2021-05-19 17:52:16 +02:00
xmrig
3ac8f6b23a Merge pull request #2386 from SChernykh/dev
Enabled IMUL_RCP optimization for light mode mining
2021-05-17 16:36:23 +07:00
SChernykh
9b1f020a8b Enabled IMUL_RCP optimization for light mode mining
Better fix for #2377
2021-05-17 11:26:40 +02:00
XMRig
8bf88a4e74 Merge branch 'Spudz76-dev-fixCLKawPowPlatformHandling' into dev 2021-05-16 10:10:33 +07:00
XMRig
08a2c143f5 Regenerate OpenCL headers. 2021-05-16 10:09:29 +07:00
Tony Butler
4eb9a1aad5 Fix CL code for KawPow where it assumes everything is AMD 2021-05-15 20:34:57 -06:00
xmrig
c8c40586a1 Merge pull request #2378 from SChernykh/dev
Fixed broken light mode mining on x86
2021-05-16 07:03:57 +07:00
SChernykh
29cb416107 Fixed broken light mode mining on x86 2021-05-15 21:41:39 +02:00
xmrig
465169ff12 Merge pull request #2375 from Spudz76/dev-fixMacOSCudaLoader
Fixup MacOS CUDA backend default loader name
2021-05-14 18:48:09 +07:00
Tony Butler
df2bcd8192 Fixup MacOS CUDA backend default loader name 2021-05-14 05:28:31 -06:00
zzjzxq33
d89bb56964 Update openssl version to 1.1.1k 2021-05-09 11:11:46 +08:00
XMRig
87a0864e3b ...and --cpu-affinity. 2021-05-08 04:36:09 +07:00
XMRig
ecf5579f36 #2351 Fixed help output for --cpu-priority option. 2021-05-08 04:34:22 +07:00
xmrig
d5523d819f Merge pull request #2341 from SChernykh/dev
Update sse2neon.h
2021-05-03 23:17:12 +07:00
SChernykh
dbda2e9ccd Update sse2neon.h 2021-05-03 18:08:59 +02:00
xmrig
8babd7bc0a Merge pull request #2340 from SChernykh/dev
Fix AES detection on FreeBSD on ARM
2021-05-03 19:06:49 +07:00
SChernykh
27ced139a6 Fix AES detection on FreeBSD on ARM 2021-05-03 09:57:43 +02:00
xmrig
b46849e813 Merge pull request #2322 from SChernykh/dev
Update randomx_boost.sh
2021-04-28 19:12:37 +07:00
SChernykh
a96a6108ff Update randomx_boost.sh
- Support builtin MSR, see #2283
- Added detection of AMD EPYC CPUs
2021-04-28 14:10:30 +02:00
xmrig
c50c78b700 Merge pull request #2312 from SChernykh/dev
Add  missing allow_writes=on to randomx_boost.sh
2021-04-25 20:46:07 +07:00
SChernykh
cd7ab2c79f Add missing allow_writes=on to randomx_boost.sh 2021-04-25 15:31:30 +02:00
XMRig
695fbc013b #2280 Disable GPU backends in benchmark mode. 2021-04-25 15:28:45 +07:00
XMRig
a403c53543 Merge branch 'jsonboss-patch-1' into dev 2021-04-24 23:22:56 +07:00
XMRig
e26fbc96e9 Removed unnecessary system call. 2021-04-24 23:22:10 +07:00
XMRig
259c165e60 Merge branch 'patch-1' of https://github.com/jsonboss/xmrig into jsonboss-patch-1 2021-04-24 22:14:59 +07:00
XMRig
7897bf02dc v6.12.2-dev 2021-04-24 01:53:07 +07:00
XMRig
05f62c5ccc Merge branch 'master' into dev 2021-04-24 01:52:37 +07:00
XMRig
d82e100e30 v6.12.1 2021-04-23 19:43:12 +07:00
XMRig
5f869a414c Merge branch 'dev' 2021-04-23 19:42:29 +07:00
xmrig
7fd6be7d83 Update CHANGELOG.md 2021-04-23 18:54:42 +07:00
xmrig
ae6c536e98 Merge pull request #2296 from SChernykh/dev
Fixed Zen3 asm for cn/upx2
2021-04-21 19:52:52 +07:00
XMRig
c66c593123 v6.12.1-dev 2021-04-21 19:51:03 +07:00
XMRig
b3788b2ba3 Merge branch 'master' into dev 2021-04-21 19:49:54 +07:00
SChernykh
b7adb34c37 Fixed Zen3 asm for cn/upx2
- Invalid rounding mode was used which caused rejected shares sometimes
- Also optimized CN implode/explode functions a bit.
2021-04-21 13:22:25 +02:00
XMRig
ace8409a56 v6.12.0 2021-04-20 20:55:58 +07:00
XMRig
e2c757d9dd Merge branch 'dev' 2021-04-20 20:55:35 +07:00
xmrig
da35de993f Update CHANGELOG.md 2021-04-19 23:20:10 +07:00
xmrig
854b7618ef Merge pull request #2289 from SChernykh/dev
RandomX: optimized IMUL_RCP instruction
2021-04-19 22:54:02 +07:00
SChernykh
3477f9fbc1 RandomX: optimized IMUL_RCP instruction
+0.4% on AMD Zen2
+0.3% on AMD Zen3
+0.1% on Intel SandyBridge
+0.3% on rx/wow on Intel SandyBridge
2021-04-19 17:43:58 +02:00
xmrig
5799744f2f Update CHANGELOG.md 2021-04-19 20:56:45 +07:00
xmrig
61d165a314 Merge pull request #2287 from SChernykh/dev
Fixed rounding mode after running cn/upx
2021-04-19 18:06:16 +07:00
SChernykh
69186f2470 Optimized cn/upx for Zen3
0.9% faster
2021-04-19 12:29:44 +02:00
SChernykh
730d4a6cee Fix dvision by zero check in percent() 2021-04-19 12:05:07 +02:00
SChernykh
54bc91d5e3 Fixed rounding mode after running cn/upx 2021-04-19 12:02:57 +02:00
jsonboss
2012ffb231 support builtin msr 2021-04-19 10:38:27 +08:00
XMRig
5f9e0ebc6c v6.12.0-dev 2021-04-18 20:12:03 +07:00
xmrig
f314c69a70 Merge pull request #2278 from SChernykh/dev
Optimized cn/upx2
2021-04-17 23:41:26 +07:00
SChernykh
16fe462cad Optimized cn/upx2 for Ryzen CPUs 2021-04-17 18:18:26 +02:00
xmrig
e6e2987ddf Merge pull request #2276 from SChernykh/dev
Added support for Uplexa (cn/upx2 algorithm)
2021-04-17 20:10:54 +07:00
SChernykh
ed456b02cf Update CnHash.cpp 2021-04-17 15:06:31 +02:00
SChernykh
da7f5826cb Added support for Uplexa (cn/upx2 algorithm) 2021-04-17 14:53:42 +02:00
XMRig
6cb398bb42 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2021-04-14 23:44:42 +07:00
XMRig
748be760e8 Added support for --user command line option for the benchmark. 2021-04-14 23:43:31 +07:00
xmrig
4a4118bb8e Merge pull request #2261 from SChernykh/dev
Show total hashrate if compiled without OpenCL
2021-04-13 19:06:42 +07:00
SChernykh
77f1bf0861 Show total hashrate if compiled without OpenCL 2021-04-13 14:02:29 +02:00
XMRig
6bb29b3e7b v6.11.3-dev 2021-04-11 21:13:39 +07:00
XMRig
f720772338 Merge branch 'master' into dev 2021-04-11 21:13:08 +07:00
120 changed files with 15317 additions and 7431 deletions

View File

@@ -1,3 +1,43 @@
# v6.14.1
- [#2532](https://github.com/xmrig/xmrig/pull/2532) Refactoring: stable (persistent) algorithms IDs.
- [#2537](https://github.com/xmrig/xmrig/pull/2537) Fixed Termux build.
# v6.14.0
- [#2484](https://github.com/xmrig/xmrig/pull/2484) Added ZeroMQ support for solo mining.
- [#2476](https://github.com/xmrig/xmrig/issues/2476) Fixed crash in DMI memory reader.
- [#2492](https://github.com/xmrig/xmrig/issues/2492) Added missing `--huge-pages-jit` command line option.
- [#2512](https://github.com/xmrig/xmrig/pull/2512) Added show the number of transactions in pool job.
# v6.13.1
- [#2468](https://github.com/xmrig/xmrig/pull/2468) Fixed regression in previous version: don't send miner signature during regular mining.
# v6.13.0
- [#2445](https://github.com/xmrig/xmrig/pull/2445) Added support for solo mining with miner signatures for the upcoming Wownero fork.
# v6.12.2
- [#2280](https://github.com/xmrig/xmrig/issues/2280) GPU backends are now disabled in benchmark mode.
- [#2322](https://github.com/xmrig/xmrig/pull/2322) Improved MSR compatibility with recent Linux kernels and updated `randomx_boost.sh`.
- [#2340](https://github.com/xmrig/xmrig/pull/2340) Fixed AES detection on FreeBSD on ARM.
- [#2341](https://github.com/xmrig/xmrig/pull/2341) `sse2neon` updated to the latest version.
- [#2351](https://github.com/xmrig/xmrig/issues/2351) Fixed help output for `--cpu-priority` and `--cpu-affinity` option.
- [#2375](https://github.com/xmrig/xmrig/pull/2375) Fixed macOS CUDA backend default loader name.
- [#2378](https://github.com/xmrig/xmrig/pull/2378) Fixed broken light mode mining on x86.
- [#2379](https://github.com/xmrig/xmrig/pull/2379) Fixed CL code for KawPow where it assumes everything is AMD.
- [#2386](https://github.com/xmrig/xmrig/pull/2386) RandomX: enabled `IMUL_RCP` optimization for light mode mining.
- [#2393](https://github.com/xmrig/xmrig/pull/2393) RandomX: added BMI2 version for scratchpad prefetch.
- [#2395](https://github.com/xmrig/xmrig/pull/2395) RandomX: rewrote dataset read code.
- [#2398](https://github.com/xmrig/xmrig/pull/2398) RandomX: optimized ARMv8 dataset read.
- Added `argon2/ninja` alias for `argon2/wrkz` algorithm.
# v6.12.1
- [#2296](https://github.com/xmrig/xmrig/pull/2296) Fixed Zen3 assembly code for `cn/upx2` algorithm.
# v6.12.0
- [#2276](https://github.com/xmrig/xmrig/pull/2276) Added support for Uplexa (`cn/upx2` algorithm).
- [#2261](https://github.com/xmrig/xmrig/pull/2261) Show total hashrate if compiled without OpenCL.
- [#2289](https://github.com/xmrig/xmrig/pull/2289) RandomX: optimized `IMUL_RCP` instruction.
- Added support for `--user` command line option for online benchmark.
# v6.11.2
- [#2207](https://github.com/xmrig/xmrig/issues/2207) Fixed regression in HTTP parser and llhttp updated to v5.1.0.

View File

@@ -5,6 +5,7 @@ option(WITH_HWLOC "Enable hwloc support" ON)
option(WITH_CN_LITE "Enable CryptoNight-Lite algorithms family" ON)
option(WITH_CN_HEAVY "Enable CryptoNight-Heavy algorithms family" ON)
option(WITH_CN_PICO "Enable CryptoNight-Pico algorithm" ON)
option(WITH_CN_FEMTO "Enable CryptoNight-UPX2 algorithm" ON)
option(WITH_RANDOMX "Enable RandomX algorithms family" ON)
option(WITH_ARGON2 "Enable Argon2 algorithms family" ON)
option(WITH_ASTROBWT "Enable AstroBWT algorithms family" ON)
@@ -196,6 +197,10 @@ if (WITH_CN_PICO)
add_definitions(/DXMRIG_ALGO_CN_PICO)
endif()
if (WITH_CN_FEMTO)
add_definitions(/DXMRIG_ALGO_CN_FEMTO)
endif()
if (WITH_EMBEDDED_CONFIG)
add_definitions(/DXMRIG_FEATURE_EMBEDDED_CONFIG)
endif()

View File

@@ -1,3 +1,7 @@
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
add_definitions(/DXMRIG_64_BIT)
endif()
if (WIN32)
set(XMRIG_OS_WIN ON)
elseif (APPLE)

View File

@@ -1,6 +1,6 @@
#!/bin/bash -e
OPENSSL_VERSION="1.1.1j"
OPENSSL_VERSION="1.1.1k"
mkdir -p deps
mkdir -p deps/include
@@ -17,4 +17,4 @@ 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 ..
cd ..

View File

@@ -1,28 +1,34 @@
#!/bin/bash
#!/bin/sh -e
modprobe msr
MSR_FILE=/sys/module/msr/parameters/allow_writes
if cat /proc/cpuinfo | grep "AMD Ryzen" > /dev/null;
if test -e "$MSR_FILE"; then
echo on > $MSR_FILE
else
modprobe msr allow_writes=on
fi
if grep -E 'AMD Ryzen|AMD EPYC' /proc/cpuinfo > /dev/null;
then
if cat /proc/cpuinfo | grep "cpu family[[:space:]]:[[:space:]]25" > /dev/null;
if grep "cpu family[[:space:]]:[[:space:]]25" /proc/cpuinfo > /dev/null;
then
echo "Detected Ryzen (Zen3)"
echo "Detected Zen3 CPU"
wrmsr -a 0xc0011020 0x4480000000000
wrmsr -a 0xc0011021 0x1c000200000040
wrmsr -a 0xc0011022 0xc000000401500000
wrmsr -a 0xc001102b 0x2000cc14
echo "MSR register values for Ryzen (Zen3) applied"
echo "MSR register values for Zen3 applied"
else
echo "Detected Ryzen (Zen1/Zen2)"
echo "Detected Zen1/Zen2 CPU"
wrmsr -a 0xc0011020 0
wrmsr -a 0xc0011021 0x40
wrmsr -a 0xc0011022 0x1510000
wrmsr -a 0xc001102b 0x2000cc16
echo "MSR register values for Ryzen (Zen1/Zen2) applied"
echo "MSR register values for Zen1/Zen2 applied"
fi
elif cat /proc/cpuinfo | grep "Intel" > /dev/null;
elif grep "Intel" /proc/cpuinfo > /dev/null;
then
echo "Detected Intel"
echo "Detected Intel CPU"
wrmsr -a 0x1a4 0xf
echo "MSR register values for Intel applied"
else

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -22,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/common/Threads.h"
#include "3rdparty/rapidjson/document.h"
#include "backend/cpu/CpuThreads.h"
@@ -43,7 +36,6 @@ namespace xmrig {
static const char *kAsterisk = "*";
static const char *kCn2 = "cn/2";
} // namespace xmrig
@@ -112,7 +104,7 @@ xmrig::String xmrig::Threads<T>::profileName(const Algorithm &algorithm, bool st
return String();
}
const String name = algorithm.shortName();
const String name = algorithm.name();
if (has(name)) {
return name;
}
@@ -125,8 +117,8 @@ xmrig::String xmrig::Threads<T>::profileName(const Algorithm &algorithm, bool st
return String();
}
if (algorithm.family() == Algorithm::CN && CnAlgo<>::base(algorithm) == Algorithm::CN_2 && has(kCn2)) {
return kCn2;
if (algorithm.family() == Algorithm::CN && algorithm.base() == Algorithm::CN_2 && has(Algorithm::kCN_2)) {
return Algorithm::kCN_2;
}
if (name.contains("/")) {
@@ -155,11 +147,11 @@ void xmrig::Threads<T>::toJSON(rapidjson::Value &out, rapidjson::Document &doc)
}
for (const Algorithm &algo : m_disabled) {
out.AddMember(StringRef(algo.shortName()), false, allocator);
out.AddMember(StringRef(algo.name()), false, allocator);
}
for (const auto &kv : m_aliases) {
out.AddMember(StringRef(kv.first.shortName()), kv.second.toJSON(), allocator);
out.AddMember(StringRef(kv.first.name()), kv.second.toJSON(), allocator);
}
}

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -22,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_THREADS_H
#define XMRIG_THREADS_H
@@ -45,7 +40,7 @@ public:
inline bool has(const char *profile) const { return m_profiles.count(profile) > 0; }
inline bool isDisabled(const Algorithm &algo) const { return m_disabled.count(algo) > 0; }
inline bool isEmpty() const { return m_profiles.empty(); }
inline bool isExist(const Algorithm &algo) const { return isDisabled(algo) || m_aliases.count(algo) > 0 || has(algo.shortName()); }
inline bool isExist(const Algorithm &algo) const { return isDisabled(algo) || m_aliases.count(algo) > 0 || has(algo.name()); }
inline const T &get(const Algorithm &algo, bool strict = false) const { return get(profileName(algo, strict)); }
inline void disable(const Algorithm &algo) { m_disabled.insert(algo); }
inline void setAlias(const Algorithm &algo, const char *profile) { m_aliases[algo] = profile; }

View File

@@ -85,9 +85,10 @@ public:
}
inline int32_t nonceOffset() const { return currentJob().nonceOffset(); }
inline size_t nonceSize() const { return currentJob().nonceSize(); }
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)

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -22,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mutex>
@@ -297,7 +290,7 @@ const xmrig::String &xmrig::CpuBackend::type() const
void xmrig::CpuBackend::prepare(const Job &nextJob)
{
# ifdef XMRIG_ALGO_ARGON2
const xmrig::Algorithm::Family f = nextJob.algorithm().family();
const auto f = nextJob.algorithm().family();
if ((f == Algorithm::ARGON2) || (f == Algorithm::RANDOM_X)) {
if (argon2::Impl::select(d_ptr->controller->config()->cpu().argon2Impl())) {
LOG_INFO("%s use " WHITE_BOLD("argon2") " implementation " CSI "1;%dm" "%s",
@@ -334,13 +327,11 @@ void xmrig::CpuBackend::printHashrate(bool details)
i++;
}
# ifdef XMRIG_FEATURE_OPENCL
Log::print(WHITE_BOLD_S "| - | - | %7s | %7s | %7s |",
Hashrate::format(hashrate()->calc(Hashrate::ShortInterval), num, sizeof num / 3),
Hashrate::format(hashrate()->calc(Hashrate::MediumInterval), num + 8, sizeof num / 3),
Hashrate::format(hashrate()->calc(Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3)
);
# endif
}

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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

@@ -197,6 +197,7 @@ void xmrig::CpuConfig::generate()
count += xmrig::generate<Algorithm::CN_LITE>(m_threads, m_limit);
count += xmrig::generate<Algorithm::CN_HEAVY>(m_threads, m_limit);
count += xmrig::generate<Algorithm::CN_PICO>(m_threads, m_limit);
count += xmrig::generate<Algorithm::CN_FEMTO>(m_threads, m_limit);
count += xmrig::generate<Algorithm::RANDOM_X>(m_threads, m_limit);
count += xmrig::generate<Algorithm::ARGON2>(m_threads, m_limit);
count += xmrig::generate<Algorithm::ASTROBWT>(m_threads, m_limit);

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -53,7 +47,7 @@ size_t inline generate<Algorithm::CN>(Threads<CpuThreads> &threads, uint32_t lim
{
size_t count = 0;
count += generate("cn", threads, Algorithm::CN_1, limit);
count += generate(Algorithm::kCN, threads, Algorithm::CN_1, limit);
if (!threads.isExist(Algorithm::CN_0)) {
threads.disable(Algorithm::CN_0);
@@ -70,7 +64,7 @@ size_t inline generate<Algorithm::CN_LITE>(Threads<CpuThreads> &threads, uint32_
{
size_t count = 0;
count += generate("cn-lite", threads, Algorithm::CN_LITE_1, limit);
count += generate(Algorithm::kCN_LITE, threads, Algorithm::CN_LITE_1, limit);
if (!threads.isExist(Algorithm::CN_LITE_0)) {
threads.disable(Algorithm::CN_LITE_0);
@@ -86,7 +80,7 @@ size_t inline generate<Algorithm::CN_LITE>(Threads<CpuThreads> &threads, uint32_
template<>
size_t inline generate<Algorithm::CN_HEAVY>(Threads<CpuThreads> &threads, uint32_t limit)
{
return generate("cn-heavy", threads, Algorithm::CN_HEAVY_0, limit);
return generate(Algorithm::kCN_HEAVY, threads, Algorithm::CN_HEAVY_0, limit);
}
#endif
@@ -95,7 +89,16 @@ size_t inline generate<Algorithm::CN_HEAVY>(Threads<CpuThreads> &threads, uint32
template<>
size_t inline generate<Algorithm::CN_PICO>(Threads<CpuThreads> &threads, uint32_t limit)
{
return generate("cn-pico", threads, Algorithm::CN_PICO_0, limit);
return generate(Algorithm::kCN_PICO, threads, Algorithm::CN_PICO_0, limit);
}
#endif
#ifdef XMRIG_ALGO_CN_FEMTO
template<>
size_t inline generate<Algorithm::CN_FEMTO>(Threads<CpuThreads>& threads, uint32_t limit)
{
return generate(Algorithm::kCN_UPX2, threads, Algorithm::CN_UPX2, limit);
}
#endif
@@ -111,30 +114,30 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<CpuThreads> &threads, uint32
if (!threads.isExist(Algorithm::RX_ARQ)) {
auto arq = cpuInfo->threads(Algorithm::RX_ARQ, limit);
if (arq == wow) {
threads.setAlias(Algorithm::RX_ARQ, "rx/wow");
threads.setAlias(Algorithm::RX_ARQ, Algorithm::kRX_WOW);
++count;
}
else {
count += threads.move("rx/arq", std::move(arq));
count += threads.move(Algorithm::kRX_ARQ, std::move(arq));
}
}
if (!threads.isExist(Algorithm::RX_KEVA)) {
auto keva = cpuInfo->threads(Algorithm::RX_KEVA, limit);
if (keva == wow) {
threads.setAlias(Algorithm::RX_KEVA, "rx/wow");
threads.setAlias(Algorithm::RX_KEVA, Algorithm::kRX_WOW);
++count;
}
else {
count += threads.move("rx/keva", std::move(keva));
count += threads.move(Algorithm::kRX_KEVA, std::move(keva));
}
}
if (!threads.isExist(Algorithm::RX_WOW)) {
count += threads.move("rx/wow", std::move(wow));
count += threads.move(Algorithm::kRX_WOW, std::move(wow));
}
count += generate("rx", threads, Algorithm::RX_0, limit);
count += generate(Algorithm::kRX, threads, Algorithm::RX_0, limit);
return count;
}
@@ -145,7 +148,7 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<CpuThreads> &threads, uint32
template<>
size_t inline generate<Algorithm::ARGON2>(Threads<CpuThreads> &threads, uint32_t limit)
{
return generate("argon2", threads, Algorithm::AR2_CHUKWA_V2, limit);
return generate(Algorithm::kAR2, threads, Algorithm::AR2_CHUKWA_V2, limit);
}
#endif
@@ -154,7 +157,7 @@ size_t inline generate<Algorithm::ARGON2>(Threads<CpuThreads> &threads, uint32_t
template<>
size_t inline generate<Algorithm::ASTROBWT>(Threads<CpuThreads>& threads, uint32_t limit)
{
return generate("astrobwt", threads, Algorithm::ASTROBWT_DERO, limit);
return generate(Algorithm::kASTROBWT, threads, Algorithm::ASTROBWT_DERO, limit);
}
#endif

View File

@@ -193,6 +193,12 @@ bool xmrig::CpuWorker<N>::selfTest()
}
# endif
# ifdef XMRIG_ALGO_CN_FEMTO
if (m_algorithm.family() == Algorithm::CN_FEMTO) {
return verify(Algorithm::CN_UPX2, test_output_femto_upx2);
}
# endif
# ifdef XMRIG_ALGO_ARGON2
if (m_algorithm.family() == Algorithm::ARGON2) {
return verify(Algorithm::AR2_CHUKWA, argon2_chukwa_test_out) &&
@@ -268,10 +274,16 @@ void xmrig::CpuWorker<N>::start()
bool valid = true;
uint8_t miner_signature_saved[64];
uint8_t* miner_signature_ptr = m_job.blob() + m_job.nonceOffset() + m_job.nonceSize();
# ifdef XMRIG_ALGO_RANDOMX
if (job.algorithm().family() == Algorithm::RANDOM_X) {
if (first) {
first = false;
if (job.hasMinerSignature()) {
job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr);
}
randomx_calculate_hash_first(m_vm, tempHash, m_job.blob(), job.size());
}
@@ -279,6 +291,10 @@ void xmrig::CpuWorker<N>::start()
break;
}
if (job.hasMinerSignature()) {
memcpy(miner_signature_saved, miner_signature_ptr, sizeof(miner_signature_saved));
job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr);
}
randomx_calculate_hash_next(m_vm, tempHash, m_job.blob(), job.size(), m_hash);
}
else
@@ -313,7 +329,7 @@ void xmrig::CpuWorker<N>::start()
else
# endif
if (value < job.target()) {
JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32));
JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32), job.hasMinerSignature() ? miner_signature_saved : nullptr);
}
}
m_count += N;

View File

@@ -309,26 +309,34 @@ xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint3
return 1;
}
const auto f = algorithm.family();
# ifdef XMRIG_ALGO_CN_LITE
if (algorithm.family() == Algorithm::CN_LITE) {
if (f == Algorithm::CN_LITE) {
return CpuThreads(count, 1);
}
# endif
# ifdef XMRIG_ALGO_CN_PICO
if (algorithm.family() == Algorithm::CN_PICO) {
if (f == Algorithm::CN_PICO) {
return CpuThreads(count, 2);
}
# endif
# ifdef XMRIG_ALGO_CN_FEMTO
if (f == Algorithm::CN_FEMTO) {
return CpuThreads(count, 2);
}
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
if (algorithm.family() == Algorithm::CN_HEAVY) {
if (f == Algorithm::CN_HEAVY) {
return CpuThreads(std::max<size_t>(count / 4, 1), 1);
}
# endif
# ifdef XMRIG_ALGO_RANDOMX
if (algorithm.family() == Algorithm::RANDOM_X) {
if (f == Algorithm::RANDOM_X) {
if (algorithm == Algorithm::RX_WOW) {
return count;
}
@@ -338,13 +346,13 @@ xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint3
# endif
# ifdef XMRIG_ALGO_ARGON2
if (algorithm.family() == Algorithm::ARGON2) {
if (f == Algorithm::ARGON2) {
return count;
}
# endif
# ifdef XMRIG_ALGO_ASTROBWT
if (algorithm.family() == Algorithm::ASTROBWT) {
if (f == Algorithm::ASTROBWT) {
CpuThreads threads;
for (size_t i = 0; i < count; ++i) {
threads.add(i, 0);

View File

@@ -28,7 +28,15 @@
#if __ARM_FEATURE_CRYPTO && !defined(__APPLE__)
# include <sys/auxv.h>
# include <asm/hwcap.h>
# ifndef __FreeBSD__
# include <asm/hwcap.h>
# else
# include <stdint.h>
# include <machine/armreg.h>
# ifndef ID_AA64ISAR0_AES_VAL
# define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
# endif
# endif
#endif
@@ -62,10 +70,13 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
# endif
# if __ARM_FEATURE_CRYPTO
# if !defined(__APPLE__)
m_flags.set(FLAG_AES, getauxval(AT_HWCAP) & HWCAP_AES);
# else
# if defined(__APPLE__)
m_flags.set(FLAG_AES, true);
# elif defined(__FreeBSD__)
uint64_t isar0 = READ_SPECIALREG(id_aa64isar0_el1);
m_flags.set(FLAG_AES, ID_AA64ISAR0_AES_VAL(isar0) >= ID_AA64ISAR0_AES_BASE);
# else
m_flags.set(FLAG_AES, getauxval(AT_HWCAP) & HWCAP_AES);
# endif
# endif

View File

@@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef XMRIG_HWLOC_DEBUG
# include <uv.h>
#endif
@@ -259,7 +258,7 @@ xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm, uint3
}
if (threads.isEmpty()) {
LOG_WARN("hwloc auto configuration for algorithm \"%s\" failed.", algorithm.shortName());
LOG_WARN("hwloc auto configuration for algorithm \"%s\" failed.", algorithm.name());
return BasicCpuInfo::threads(algorithm, limit);
}
@@ -336,11 +335,10 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
size_t cacheHashes = ((L3 + extra) + (scratchpad / 2)) / scratchpad;
# ifdef XMRIG_ALGO_CN_PICO
if (intensity && algorithm == Algorithm::CN_PICO_0 && (cacheHashes / PUs) >= 2) {
const auto family = algorithm.family();
if (intensity && ((family == Algorithm::CN_PICO) || (family == Algorithm::CN_FEMTO)) && (cacheHashes / PUs) >= 2) {
intensity = 2;
}
# endif
# ifdef XMRIG_ALGO_RANDOMX
if (extra == 0 && algorithm.l2() > 0) {

View File

@@ -179,6 +179,7 @@ void xmrig::CudaConfig::generate()
count += xmrig::generate<Algorithm::CN_LITE>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_HEAVY>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_PICO>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_FEMTO>(m_threads, devices);
count += xmrig::generate<Algorithm::RANDOM_X>(m_threads, devices);
count += xmrig::generate<Algorithm::ASTROBWT>(m_threads, devices);
count += xmrig::generate<Algorithm::KAWPOW>(m_threads, devices);

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -56,8 +50,8 @@ size_t inline generate<Algorithm::CN>(Threads<CudaThreads> &threads, const std::
{
size_t count = 0;
count += generate("cn", threads, Algorithm::CN_1, devices);
count += generate("cn/2", threads, Algorithm::CN_2, devices);
count += generate(Algorithm::kCN, threads, Algorithm::CN_1, devices);
count += generate(Algorithm::kCN_2, threads, Algorithm::CN_2, devices);
if (!threads.isExist(Algorithm::CN_0)) {
threads.disable(Algorithm::CN_0);
@@ -72,7 +66,7 @@ size_t inline generate<Algorithm::CN>(Threads<CudaThreads> &threads, const std::
template<>
size_t inline generate<Algorithm::CN_LITE>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
size_t count = generate("cn-lite", threads, Algorithm::CN_LITE_1, devices);
size_t count = generate(Algorithm::kCN_LITE, threads, Algorithm::CN_LITE_1, devices);
if (!threads.isExist(Algorithm::CN_LITE_0)) {
threads.disable(Algorithm::CN_LITE_0);
@@ -88,7 +82,7 @@ size_t inline generate<Algorithm::CN_LITE>(Threads<CudaThreads> &threads, const
template<>
size_t inline generate<Algorithm::CN_HEAVY>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
return generate("cn-heavy", threads, Algorithm::CN_HEAVY_0, devices);
return generate(Algorithm::kCN_HEAVY, threads, Algorithm::CN_HEAVY_0, devices);
}
#endif
@@ -97,7 +91,16 @@ size_t inline generate<Algorithm::CN_HEAVY>(Threads<CudaThreads> &threads, const
template<>
size_t inline generate<Algorithm::CN_PICO>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
return generate("cn-pico", threads, Algorithm::CN_PICO_0, devices);
return generate(Algorithm::kCN_PICO, threads, Algorithm::CN_PICO_0, devices);
}
#endif
#ifdef XMRIG_ALGO_CN_FEMTO
template<>
size_t inline generate<Algorithm::CN_FEMTO>(Threads<CudaThreads>& threads, const std::vector<CudaDevice>& devices)
{
return generate(Algorithm::kCN_UPX2, threads, Algorithm::CN_UPX2, devices);
}
#endif
@@ -114,18 +117,18 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<CudaThreads> &threads, const
auto kva = CudaThreads(devices, Algorithm::RX_KEVA);
if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) {
count += threads.move("rx/wow", std::move(wow));
count += threads.move(Algorithm::kRX_WOW, std::move(wow));
}
if (!threads.isExist(Algorithm::RX_ARQ) && arq != rx) {
count += threads.move("rx/arq", std::move(arq));
count += threads.move(Algorithm::kRX_ARQ, std::move(arq));
}
if (!threads.isExist(Algorithm::RX_KEVA) && kva != rx) {
count += threads.move("rx/keva", std::move(kva));
count += threads.move(Algorithm::kRX_KEVA, std::move(kva));
}
count += threads.move("rx", std::move(rx));
count += threads.move(Algorithm::kRX, std::move(rx));
return count;
}
@@ -136,7 +139,7 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<CudaThreads> &threads, const
template<>
size_t inline generate<Algorithm::ASTROBWT>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
return generate("astrobwt", threads, Algorithm::ASTROBWT_DERO, devices);
return generate(Algorithm::kASTROBWT, threads, Algorithm::ASTROBWT_DERO, devices);
}
#endif
@@ -145,7 +148,7 @@ size_t inline generate<Algorithm::ASTROBWT>(Threads<CudaThreads> &threads, const
template<>
size_t inline generate<Algorithm::KAWPOW>(Threads<CudaThreads> &threads, const std::vector<CudaDevice> &devices)
{
return generate("kawpow", threads, Algorithm::KAWPOW_RVN, devices);
return generate(Algorithm::kKAWPOW, threads, Algorithm::KAWPOW_RVN, devices);
}
#endif

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -22,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdexcept>
#include <uv.h>
@@ -48,7 +41,7 @@ enum Version : uint32_t
static uv_lib_t cudaLib;
#if defined(__APPLE__)
static String defaultLoader = "/System/Library/Frameworks/OpenCL.framework/OpenCL";
static String defaultLoader = "libxmrig-cuda.dylib";
#elif defined(_WIN32)
static String defaultLoader = "xmrig-cuda.dll";
#else
@@ -199,7 +192,7 @@ bool xmrig::CudaLib::deviceInfo(nvid_ctx *ctx, int32_t blocks, int32_t threads,
{
const Algorithm algo = RxAlgo::id(algorithm);
return pDeviceInfo_v2(ctx, blocks, threads, algo.isValid() ? algo.shortName() : nullptr, dataset_host);
return pDeviceInfo_v2(ctx, blocks, threads, algo.isValid() ? algo.name() : nullptr, dataset_host);
}
@@ -243,7 +236,7 @@ bool xmrig::CudaLib::setJob(nvid_ctx *ctx, const void *data, size_t size, const
{
const Algorithm algo = RxAlgo::id(algorithm);
return pSetJob_v2(ctx, data, size, algo.shortName());
return pSetJob_v2(ctx, data, size, algo.name());
}

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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

@@ -219,6 +219,7 @@ void xmrig::OclConfig::generate()
count += xmrig::generate<Algorithm::CN_LITE>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_HEAVY>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_PICO>(m_threads, devices);
count += xmrig::generate<Algorithm::CN_FEMTO>(m_threads, devices);
count += xmrig::generate<Algorithm::RANDOM_X>(m_threads, devices);
count += xmrig::generate<Algorithm::ASTROBWT>(m_threads, devices);
count += xmrig::generate<Algorithm::KAWPOW>(m_threads, devices);

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -55,8 +49,8 @@ size_t inline generate<Algorithm::CN>(Threads<OclThreads> &threads, const std::v
{
size_t count = 0;
count += generate("cn", threads, Algorithm::CN_1, devices);
count += generate("cn/2", threads, Algorithm::CN_2, devices);
count += generate(Algorithm::kCN, threads, Algorithm::CN_1, devices);
count += generate(Algorithm::kCN_2, threads, Algorithm::CN_2, devices);
if (!threads.isExist(Algorithm::CN_0)) {
threads.disable(Algorithm::CN_0);
@@ -71,7 +65,7 @@ size_t inline generate<Algorithm::CN>(Threads<OclThreads> &threads, const std::v
template<>
size_t inline generate<Algorithm::CN_LITE>(Threads<OclThreads> &threads, const std::vector<OclDevice> &devices)
{
size_t count = generate("cn-lite", threads, Algorithm::CN_LITE_1, devices);
size_t count = generate(Algorithm::kCN_LITE, threads, Algorithm::CN_LITE_1, devices);
if (!threads.isExist(Algorithm::CN_LITE_0)) {
threads.disable(Algorithm::CN_LITE_0);
@@ -87,7 +81,7 @@ size_t inline generate<Algorithm::CN_LITE>(Threads<OclThreads> &threads, const s
template<>
size_t inline generate<Algorithm::CN_HEAVY>(Threads<OclThreads> &threads, const std::vector<OclDevice> &devices)
{
return generate("cn-heavy", threads, Algorithm::CN_HEAVY_0, devices);
return generate(Algorithm::kCN_HEAVY, threads, Algorithm::CN_HEAVY_0, devices);
}
#endif
@@ -96,7 +90,16 @@ size_t inline generate<Algorithm::CN_HEAVY>(Threads<OclThreads> &threads, const
template<>
size_t inline generate<Algorithm::CN_PICO>(Threads<OclThreads> &threads, const std::vector<OclDevice> &devices)
{
return generate("cn-pico", threads, Algorithm::CN_PICO_0, devices);
return generate(Algorithm::kCN_PICO, threads, Algorithm::CN_PICO_0, devices);
}
#endif
#ifdef XMRIG_ALGO_CN_FEMTO
template<>
size_t inline generate<Algorithm::CN_FEMTO>(Threads<OclThreads>& threads, const std::vector<OclDevice>& devices)
{
return generate(Algorithm::kCN_UPX2, threads, Algorithm::CN_UPX2, devices);
}
#endif
@@ -112,14 +115,14 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<OclThreads> &threads, const
auto arq = OclThreads(devices, Algorithm::RX_ARQ);
if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) {
count += threads.move("rx/wow", std::move(wow));
count += threads.move(Algorithm::kRX_WOW, std::move(wow));
}
if (!threads.isExist(Algorithm::RX_ARQ) && arq != rx) {
count += threads.move("rx/arq", std::move(arq));
count += threads.move(Algorithm::kRX_ARQ, std::move(arq));
}
count += threads.move("rx", std::move(rx));
count += threads.move(Algorithm::kRX, std::move(rx));
return count;
}
@@ -130,7 +133,7 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<OclThreads> &threads, const
template<>
size_t inline generate<Algorithm::ASTROBWT>(Threads<OclThreads>& threads, const std::vector<OclDevice>& devices)
{
return generate("astrobwt", threads, Algorithm::ASTROBWT_DERO, devices);
return generate(Algorithm::kASTROBWT, threads, Algorithm::ASTROBWT_DERO, devices);
}
#endif
@@ -139,7 +142,7 @@ size_t inline generate<Algorithm::ASTROBWT>(Threads<OclThreads>& threads, const
template<>
size_t inline generate<Algorithm::KAWPOW>(Threads<OclThreads>& threads, const std::vector<OclDevice>& devices)
{
return generate("kawpow", threads, Algorithm::KAWPOW_RVN, devices);
return generate(Algorithm::kKAWPOW, threads, Algorithm::KAWPOW_RVN, devices);
}
#endif

View File

@@ -1,39 +1,41 @@
#define ALGO_CN_0 0
#define ALGO_CN_1 1
#define ALGO_CN_2 2
#define ALGO_CN_R 3
#define ALGO_CN_FAST 4
#define ALGO_CN_HALF 5
#define ALGO_CN_XAO 6
#define ALGO_CN_RTO 7
#define ALGO_CN_RWZ 8
#define ALGO_CN_ZLS 9
#define ALGO_CN_DOUBLE 10
#define ALGO_CN_LITE_0 11
#define ALGO_CN_LITE_1 12
#define ALGO_CN_HEAVY_0 13
#define ALGO_CN_HEAVY_TUBE 14
#define ALGO_CN_HEAVY_XHV 15
#define ALGO_CN_PICO_0 16
#define ALGO_CN_PICO_TLO 17
#define ALGO_CN_CCX 18
#define ALGO_RX_0 19
#define ALGO_RX_WOW 20
#define ALGO_RX_ARQMA 21
#define ALGO_RX_SFX 22
#define ALGO_RX_KEVA 23
#define ALGO_AR2_CHUKWA 24
#define ALGO_AR2_CHUKWA_V2 25
#define ALGO_AR2_WRKZ 26
#define ALGO_ASTROBWT_DERO 27
#define ALGO_KAWPOW_RVN 28
#define ALGO_CN_0 0x63150000
#define ALGO_CN_1 0x63150100
#define ALGO_CN_2 0x63150200
#define ALGO_CN_R 0x63150272
#define ALGO_CN_FAST 0x63150166
#define ALGO_CN_HALF 0x63150268
#define ALGO_CN_XAO 0x63150078
#define ALGO_CN_RTO 0x63150172
#define ALGO_CN_RWZ 0x63150277
#define ALGO_CN_ZLS 0x6315027a
#define ALGO_CN_DOUBLE 0x63150264
#define ALGO_CN_CCX 0x63150063
#define ALGO_CN_LITE_0 0x63140000
#define ALGO_CN_LITE_1 0x63140100
#define ALGO_CN_HEAVY_0 0x63160000
#define ALGO_CN_HEAVY_TUBE 0x63160172
#define ALGO_CN_HEAVY_XHV 0x63160068
#define ALGO_CN_PICO_0 0x63120200
#define ALGO_CN_PICO_TLO 0x63120274
#define ALGO_CN_UPX2 0x63110200
#define ALGO_RX_0 0x72151200
#define ALGO_RX_WOW 0x72141177
#define ALGO_RX_ARQMA 0x72121061
#define ALGO_RX_SFX 0x72151273
#define ALGO_RX_KEVA 0x7214116b
#define ALGO_AR2_CHUKWA 0x61130000
#define ALGO_AR2_CHUKWA_V2 0x61140000
#define ALGO_AR2_WRKZ 0x61120000
#define ALGO_ASTROBWT_DERO 0x41000000
#define ALGO_KAWPOW_RVN 0x6b0f0000
#define FAMILY_UNKNOWN 0
#define FAMILY_CN 1
#define FAMILY_CN_LITE 2
#define FAMILY_CN_HEAVY 3
#define FAMILY_CN_PICO 4
#define FAMILY_RANDOM_X 5
#define FAMILY_ARGON2 6
#define FAMILY_ASTROBWT 7
#define FAMILY_KAWPOW 8
#define FAMILY_CN 0x63150000
#define FAMILY_CN_LITE 0x63140000
#define FAMILY_CN_HEAVY 0x63160000
#define FAMILY_CN_PICO 0x63120000
#define FAMILY_CN_FEMTO 0x63110000
#define FAMILY_RANDOM_X 0x72000000
#define FAMILY_ARGON2 0x61000000
#define FAMILY_ASTROBWT 0x41000000
#define FAMILY_KAWPOW 0x6b000000

View File

@@ -514,7 +514,7 @@ __kernel void cn1(__global ulong *input, __global uint4 *Scratchpad, __global ul
c = AES_Round(AES0, AES1, AES2, AES3, c, ((uint4 *)a)[0]);
{
# if (ALGO == ALGO_CN_RWZ)
# if ((ALGO == ALGO_CN_RWZ) || (ALGO == ALGO_CN_UPX2))
const ulong2 chunk1 = as_ulong2(SCRATCHPAD_CHUNK(3));
const ulong2 chunk2 = as_ulong2(SCRATCHPAD_CHUNK(2));
const ulong2 chunk3 = as_ulong2(SCRATCHPAD_CHUNK(1));
@@ -561,7 +561,7 @@ __kernel void cn1(__global ulong *input, __global uint4 *Scratchpad, __global ul
t ^= chunk2;
const ulong2 chunk3 = as_ulong2(SCRATCHPAD_CHUNK(3));
# if (ALGO == ALGO_CN_RWZ)
# if ((ALGO == ALGO_CN_RWZ) || (ALGO == ALGO_CN_UPX2))
SCRATCHPAD_CHUNK(1) = as_uint4(chunk1 + bx1);
SCRATCHPAD_CHUNK(2) = as_uint4(chunk3 + bx0);
SCRATCHPAD_CHUNK(3) = as_uint4(chunk2 + ((ulong2 *)a)[0]);

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,11 @@ typedef unsigned long uint64_t;
#endif
#ifndef PLATFORM
#ifdef cl_amd_media_ops
#define PLATFORM OPENCL_PLATFORM_AMD
#else
#define PLATFORM OPENCL_PLATFORM_UNKNOWN
#endif
#endif
#define HASHES_PER_GROUP (GROUP_SIZE / PROGPOW_LANES)

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,8 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright (c) 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -23,7 +18,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/opencl/OclThreads.h"
#include "backend/opencl/wrappers/OclDevice.h"
#include "base/crypto/Algorithm.h"
@@ -36,31 +30,31 @@
namespace xmrig {
constexpr const size_t oneMiB = 1024u * 1024u;
constexpr const size_t oneMiB = 1024U * 1024U;
static inline uint32_t getMaxThreads(const OclDevice &device, const Algorithm &algorithm)
{
if (device.vendorId() == OCL_VENDOR_NVIDIA && (device.name().contains("P100") || device.name().contains("V100"))) {
return 40000u;
return 40000U;
}
const uint32_t ratio = (algorithm.l3() <= oneMiB) ? 2u : 1u;
const uint32_t ratio = (algorithm.l3() <= oneMiB) ? 2U : 1U;
if (device.vendorId() == OCL_VENDOR_INTEL) {
return ratio * device.computeUnits() * 8;
}
return ratio * 1000u;
return ratio * 1000U;
}
static inline uint32_t getPossibleIntensity(const OclDevice &device, const Algorithm &algorithm)
{
const uint32_t maxThreads = getMaxThreads(device, algorithm);
const size_t minFreeMem = (maxThreads == 40000u ? 512u : 128u) * oneMiB;
const size_t minFreeMem = (maxThreads == 40000U ? 512U : 128U) * oneMiB;
const size_t availableMem = device.freeMemSize() - minFreeMem;
const size_t perThread = algorithm.l3() + 224u;
const size_t perThread = algorithm.l3() + 224U;
const auto maxIntensity = static_cast<uint32_t>(availableMem / perThread);
return std::min<uint32_t>(maxThreads, maxIntensity);
@@ -98,7 +92,7 @@ static uint32_t getStridedIndex(const OclDevice &device, const Algorithm &algori
return 0;
}
return CnAlgo<>::base(algorithm) == Algorithm::CN_2 ? 2 : 1;
return algorithm.base() == Algorithm::CN_2 ? 2 : 1;
}

View File

@@ -1,13 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -23,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/opencl/OclThreads.h"
#include "backend/opencl/wrappers/OclDevice.h"
#include "base/crypto/Algorithm.h"
@@ -36,7 +28,7 @@
namespace xmrig {
constexpr const size_t oneMiB = 1024u * 1024u;
constexpr const size_t oneMiB = 1024U * 1024U;
static inline bool isMatch(const OclDevice &device, const Algorithm &algorithm)
@@ -49,23 +41,23 @@ static inline bool isMatch(const OclDevice &device, const Algorithm &algorithm)
static inline uint32_t getMaxThreads(const OclDevice &device, const Algorithm &algorithm)
{
const uint32_t ratio = (algorithm.l3() <= oneMiB) ? 2u : 1u;
const uint32_t ratio = (algorithm.l3() <= oneMiB) ? 2U : 1U;
if (device.type() == OclDevice::Vega_10) {
if (device.computeUnits() == 56 && algorithm.family() == Algorithm::CN && CnAlgo<>::base(algorithm) == Algorithm::CN_2) {
return 1792u;
if (device.computeUnits() == 56 && algorithm.family() == Algorithm::CN && algorithm.base() == Algorithm::CN_2) {
return 1792U;
}
}
return ratio * 2024u;
return ratio * 2024U;
}
static inline uint32_t getPossibleIntensity(const OclDevice &device, const Algorithm &algorithm)
{
const uint32_t maxThreads = getMaxThreads(device, algorithm);
const size_t availableMem = device.freeMemSize() - (128u * oneMiB);
const size_t perThread = algorithm.l3() + 224u;
const size_t availableMem = device.freeMemSize() - (128U * oneMiB);
const size_t perThread = algorithm.l3() + 224U;
const auto maxIntensity = static_cast<uint32_t>(availableMem / perThread);
return std::min<uint32_t>(maxThreads, maxIntensity);
@@ -88,27 +80,24 @@ static inline uint32_t getIntensity(const OclDevice &device, const Algorithm &al
static inline uint32_t getWorksize(const Algorithm &algorithm)
{
if (algorithm.family() == Algorithm::CN_PICO) {
const auto f = algorithm.family();
if (f == Algorithm::CN_PICO || f == Algorithm::CN_FEMTO) {
return 64;
}
if (CnAlgo<>::base(algorithm) == Algorithm::CN_2) {
return 16;
}
return 8;
return algorithm.base() == Algorithm::CN_2 ? 16 : 8;
}
static uint32_t getStridedIndex(const Algorithm &algorithm)
{
return CnAlgo<>::base(algorithm) == Algorithm::CN_2 ? 2 : 1;
return algorithm.base() == Algorithm::CN_2 ? 2 : 1;
}
static inline uint32_t getMemChunk(const Algorithm &algorithm)
{
return CnAlgo<>::base(algorithm) == Algorithm::CN_2 ? 1 : 2;
return algorithm.base() == Algorithm::CN_2 ? 1 : 2;
}

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -22,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/opencl/runners/OclCnRunner.h"
#include "backend/opencl/kernels/Cn0Kernel.h"
#include "backend/opencl/kernels/Cn1Kernel.h"
@@ -39,10 +32,12 @@
xmrig::OclCnRunner::OclCnRunner(size_t index, const OclLaunchData &data) : OclBaseRunner(index, data)
{
uint32_t stridedIndex = data.thread.stridedIndex();
const auto f = m_algorithm.family();
if (data.device.vendorId() == OCL_VENDOR_NVIDIA) {
stridedIndex = 0;
}
else if (stridedIndex == 1 && (m_algorithm.family() == Algorithm::CN_PICO || (m_algorithm.family() == Algorithm::CN && CnAlgo<>::base(m_algorithm) == Algorithm::CN_2))) {
else if (stridedIndex == 1 && (f == Algorithm::CN_PICO || f == Algorithm::CN_FEMTO || (f == Algorithm::CN && m_algorithm.base() == Algorithm::CN_2))) {
stridedIndex = 2;
}
@@ -50,10 +45,10 @@ xmrig::OclCnRunner::OclCnRunner(size_t index, const OclLaunchData &data) : OclBa
m_options += " -DMASK=" + std::to_string(CnAlgo<>::mask(m_algorithm)) + "U";
m_options += " -DWORKSIZE=" + std::to_string(data.thread.worksize()) + "U";
m_options += " -DSTRIDED_INDEX=" + std::to_string(stridedIndex) + "U";
m_options += " -DMEM_CHUNK_EXPONENT=" + std::to_string(1u << data.thread.memChunk()) + "U";
m_options += " -DMEM_CHUNK_EXPONENT=" + std::to_string(1U << data.thread.memChunk()) + "U";
m_options += " -DMEMORY=" + std::to_string(m_algorithm.l3()) + "LU";
m_options += " -DALGO=" + std::to_string(m_algorithm.id());
m_options += " -DALGO_BASE=" + std::to_string(CnAlgo<>::base(m_algorithm));
m_options += " -DALGO_BASE=" + std::to_string(m_algorithm.base());
m_options += " -DALGO_FAMILY=" + std::to_string(m_algorithm.family());
m_options += " -DCN_UNROLL=" + std::to_string(data.thread.unrollFactor());
}
@@ -94,7 +89,7 @@ void xmrig::OclCnRunner::run(uint32_t nonce, uint32_t *hashOutput)
static const cl_uint zero = 0;
const size_t w_size = data().thread.worksize();
const size_t g_thd = ((m_intensity + w_size - 1u) / w_size) * w_size;
const size_t g_thd = ((m_intensity + w_size - 1U) / w_size) * w_size;
assert(g_thd % w_size == 0);

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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

@@ -70,8 +70,15 @@ set(HEADERS_BASE
src/base/net/tools/Storage.h
src/base/tools/Arguments.h
src/base/tools/Baton.h
src/base/tools/bswap_64.h
src/base/tools/Buffer.h
src/base/tools/Chrono.h
src/base/tools/cryptonote/BlobReader.h
src/base/tools/cryptonote/BlockTemplate.h
src/base/tools/cryptonote/crypto-ops.h
src/base/tools/cryptonote/Signatures.h
src/base/tools/cryptonote/umul128.h
src/base/tools/cryptonote/WalletAddress.h
src/base/tools/Cvt.h
src/base/tools/Handle.h
src/base/tools/String.h
@@ -126,6 +133,11 @@ set(SOURCES_BASE
src/base/tools/Cvt.cpp
src/base/tools/String.cpp
src/base/tools/Timer.cpp
src/base/tools/cryptonote/BlockTemplate.cpp
src/base/tools/cryptonote/Signatures.cpp
src/base/tools/cryptonote/WalletAddress.cpp
src/base/tools/cryptonote/crypto-ops.c
src/base/tools/cryptonote/crypto-ops-data.c
)

View File

@@ -1,13 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -23,15 +17,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/crypto/Algorithm.h"
#include "3rdparty/rapidjson/document.h"
#include "base/tools/String.h"
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#ifdef _MSC_VER
@@ -42,93 +36,249 @@
namespace xmrig {
struct AlgoName
{
const char *name;
const char *shortName;
const Algorithm::Id id;
const char *Algorithm::kINVALID = "invalid";
const char *Algorithm::kCN = "cn";
const char *Algorithm::kCN_0 = "cn/0";
const char *Algorithm::kCN_1 = "cn/1";
const char *Algorithm::kCN_2 = "cn/2";
const char *Algorithm::kCN_R = "cn/r";
const char *Algorithm::kCN_FAST = "cn/fast";
const char *Algorithm::kCN_HALF = "cn/half";
const char *Algorithm::kCN_XAO = "cn/xao";
const char *Algorithm::kCN_RTO = "cn/rto";
const char *Algorithm::kCN_RWZ = "cn/rwz";
const char *Algorithm::kCN_ZLS = "cn/zls";
const char *Algorithm::kCN_DOUBLE = "cn/double";
const char *Algorithm::kCN_CCX = "cn/ccx";
#ifdef XMRIG_ALGO_CN_LITE
const char *Algorithm::kCN_LITE = "cn-lite";
const char *Algorithm::kCN_LITE_0 = "cn-lite/0";
const char *Algorithm::kCN_LITE_1 = "cn-lite/1";
#endif
#ifdef XMRIG_ALGO_CN_HEAVY
const char *Algorithm::kCN_HEAVY = "cn-heavy";
const char *Algorithm::kCN_HEAVY_0 = "cn-heavy/0";
const char *Algorithm::kCN_HEAVY_TUBE = "cn-heavy/tube";
const char *Algorithm::kCN_HEAVY_XHV = "cn-heavy/xhv";
#endif
#ifdef XMRIG_ALGO_CN_PICO
const char *Algorithm::kCN_PICO = "cn-pico";
const char *Algorithm::kCN_PICO_0 = "cn-pico";
const char *Algorithm::kCN_PICO_TLO = "cn-pico/tlo";
#endif
#ifdef XMRIG_ALGO_CN_FEMTO
const char *Algorithm::kCN_UPX2 = "cn/upx2";
#endif
#ifdef XMRIG_ALGO_RANDOMX
const char *Algorithm::kRX = "rx";
const char *Algorithm::kRX_0 = "rx/0";
const char *Algorithm::kRX_WOW = "rx/wow";
const char *Algorithm::kRX_ARQ = "rx/arq";
const char *Algorithm::kRX_SFX = "rx/sfx";
const char *Algorithm::kRX_KEVA = "rx/keva";
#endif
#ifdef XMRIG_ALGO_ARGON2
const char *Algorithm::kAR2 = "argon2";
const char *Algorithm::kAR2_CHUKWA = "argon2/chukwa";
const char *Algorithm::kAR2_CHUKWA_V2 = "argon2/chukwav2";
const char *Algorithm::kAR2_WRKZ = "argon2/ninja";
#endif
#ifdef XMRIG_ALGO_ASTROBWT
const char *Algorithm::kASTROBWT = "astrobwt";
const char *Algorithm::kASTROBWT_DERO = "astrobwt";
#endif
#ifdef XMRIG_ALGO_KAWPOW
const char *Algorithm::kKAWPOW = "kawpow";
const char *Algorithm::kKAWPOW_RVN = "kawpow";
#endif
#define ALGO_NAME(ALGO) { Algorithm::ALGO, Algorithm::k##ALGO }
#define ALGO_ALIAS(ALGO, NAME) { NAME, Algorithm::ALGO }
#define ALGO_ALIAS_AUTO(ALGO) { Algorithm::k##ALGO, Algorithm::ALGO }
#ifdef _MSC_VER
# define strcasecmp _stricmp
#endif
static const std::map<uint32_t, const char *> kAlgorithmNames = {
ALGO_NAME(CN_0),
ALGO_NAME(CN_1),
ALGO_NAME(CN_2),
ALGO_NAME(CN_R),
ALGO_NAME(CN_FAST),
ALGO_NAME(CN_HALF),
ALGO_NAME(CN_XAO),
ALGO_NAME(CN_RTO),
ALGO_NAME(CN_RWZ),
ALGO_NAME(CN_ZLS),
ALGO_NAME(CN_DOUBLE),
ALGO_NAME(CN_CCX),
# ifdef XMRIG_ALGO_CN_LITE
ALGO_NAME(CN_LITE_0),
ALGO_NAME(CN_LITE_1),
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
ALGO_NAME(CN_HEAVY_0),
ALGO_NAME(CN_HEAVY_TUBE),
ALGO_NAME(CN_HEAVY_XHV),
# endif
# ifdef XMRIG_ALGO_CN_PICO
ALGO_NAME(CN_PICO_0),
ALGO_NAME(CN_PICO_TLO),
# endif
# ifdef XMRIG_ALGO_CN_FEMTO
ALGO_NAME(CN_UPX2),
# endif
# ifdef XMRIG_ALGO_RANDOMX
ALGO_NAME(RX_0),
ALGO_NAME(RX_WOW),
ALGO_NAME(RX_ARQ),
ALGO_NAME(RX_SFX),
ALGO_NAME(RX_KEVA),
# endif
# ifdef XMRIG_ALGO_ARGON2
ALGO_NAME(AR2_CHUKWA),
ALGO_NAME(AR2_CHUKWA_V2),
ALGO_NAME(AR2_WRKZ),
# endif
# ifdef XMRIG_ALGO_ASTROBWT
ALGO_NAME(ASTROBWT_DERO),
# endif
# ifdef XMRIG_ALGO_KAWPOW
ALGO_NAME(KAWPOW_RVN),
# endif
};
static AlgoName const algorithm_names[] = {
{ "cryptonight/0", "cn/0", Algorithm::CN_0 },
{ "cryptonight", "cn", Algorithm::CN_0 },
{ "cryptonight/1", "cn/1", Algorithm::CN_1 },
{ "cryptonight-monerov7", nullptr, Algorithm::CN_1 },
{ "cryptonight_v7", nullptr, Algorithm::CN_1 },
{ "cryptonight/2", "cn/2", Algorithm::CN_2 },
{ "cryptonight-monerov8", nullptr, Algorithm::CN_2 },
{ "cryptonight_v8", nullptr, Algorithm::CN_2 },
{ "cryptonight/r", "cn/r", Algorithm::CN_R },
{ "cryptonight_r", nullptr, Algorithm::CN_R },
{ "cryptonight/fast", "cn/fast", Algorithm::CN_FAST },
{ "cryptonight/msr", "cn/msr", Algorithm::CN_FAST },
{ "cryptonight/half", "cn/half", Algorithm::CN_HALF },
{ "cryptonight/xao", "cn/xao", Algorithm::CN_XAO },
{ "cryptonight_alloy", nullptr, Algorithm::CN_XAO },
{ "cryptonight/rto", "cn/rto", Algorithm::CN_RTO },
{ "cryptonight/rwz", "cn/rwz", Algorithm::CN_RWZ },
{ "cryptonight/zls", "cn/zls", Algorithm::CN_ZLS },
{ "cryptonight/double", "cn/double", Algorithm::CN_DOUBLE },
struct aliasCompare
{
inline bool operator()(const char *a, const char *b) const { return strcasecmp(a, b) < 0; }
};
static const std::map<const char *, Algorithm::Id, aliasCompare> kAlgorithmAliases = {
ALGO_ALIAS_AUTO(CN_0), ALGO_ALIAS(CN_0, "cryptonight/0"),
ALGO_ALIAS(CN_0, "cryptonight"),
ALGO_ALIAS(CN_0, "cn"),
ALGO_ALIAS_AUTO(CN_1), ALGO_ALIAS(CN_1, "cryptonight/1"),
ALGO_ALIAS(CN_1, "cryptonight-monerov7"),
ALGO_ALIAS(CN_1, "cryptonight_v7"),
ALGO_ALIAS_AUTO(CN_2), ALGO_ALIAS(CN_2, "cryptonight/2"),
ALGO_ALIAS(CN_2, "cryptonight-monerov8"),
ALGO_ALIAS(CN_2, "cryptonight_v8"),
ALGO_ALIAS_AUTO(CN_FAST), ALGO_ALIAS(CN_FAST, "cryptonight/fast"),
ALGO_ALIAS(CN_FAST, "cryptonight/msr"),
ALGO_ALIAS(CN_FAST, "cn/msr"),
ALGO_ALIAS_AUTO(CN_R), ALGO_ALIAS(CN_R, "cryptonight/r"),
ALGO_ALIAS(CN_R, "cryptonight_r"),
ALGO_ALIAS_AUTO(CN_XAO), ALGO_ALIAS(CN_XAO, "cryptonight/xao"),
ALGO_ALIAS(CN_XAO, "cryptonight_alloy"),
ALGO_ALIAS_AUTO(CN_HALF), ALGO_ALIAS(CN_HALF, "cryptonight/half"),
ALGO_ALIAS_AUTO(CN_RTO), ALGO_ALIAS(CN_RTO, "cryptonight/rto"),
ALGO_ALIAS_AUTO(CN_RWZ), ALGO_ALIAS(CN_RWZ, "cryptonight/rwz"),
ALGO_ALIAS_AUTO(CN_ZLS), ALGO_ALIAS(CN_ZLS, "cryptonight/zls"),
ALGO_ALIAS_AUTO(CN_DOUBLE), ALGO_ALIAS(CN_DOUBLE, "cryptonight/double"),
ALGO_ALIAS_AUTO(CN_CCX), ALGO_ALIAS(CN_CCX, "cryptonight/ccx"),
ALGO_ALIAS(CN_CCX, "cryptonight/conceal"),
ALGO_ALIAS(CN_CCX, "cn/conceal"),
# ifdef XMRIG_ALGO_CN_LITE
{ "cryptonight-lite/0", "cn-lite/0", Algorithm::CN_LITE_0 },
{ "cryptonight-lite/1", "cn-lite/1", Algorithm::CN_LITE_1 },
{ "cryptonight-lite", "cn-lite", Algorithm::CN_LITE_1 },
{ "cryptonight-light", "cn-light", Algorithm::CN_LITE_1 },
{ "cryptonight_lite", nullptr, Algorithm::CN_LITE_1 },
{ "cryptonight-aeonv7", nullptr, Algorithm::CN_LITE_1 },
{ "cryptonight_lite_v7", nullptr, Algorithm::CN_LITE_1 },
ALGO_ALIAS_AUTO(CN_LITE_0), ALGO_ALIAS(CN_LITE_0, "cryptonight-lite/0"),
ALGO_ALIAS(CN_LITE_0, "cryptonight-lite"),
ALGO_ALIAS(CN_LITE_0, "cryptonight-light"),
ALGO_ALIAS(CN_LITE_0, "cn-lite"),
ALGO_ALIAS(CN_LITE_0, "cn-light"),
ALGO_ALIAS(CN_LITE_0, "cryptonight_lite"),
ALGO_ALIAS_AUTO(CN_LITE_1), ALGO_ALIAS(CN_LITE_1, "cryptonight-lite/1"),
ALGO_ALIAS(CN_LITE_1, "cryptonight-aeonv7"),
ALGO_ALIAS(CN_LITE_1, "cryptonight_lite_v7"),
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
{ "cryptonight-heavy/0", "cn-heavy/0", Algorithm::CN_HEAVY_0 },
{ "cryptonight-heavy", "cn-heavy", Algorithm::CN_HEAVY_0 },
{ "cryptonight_heavy", nullptr, Algorithm::CN_HEAVY_0 },
{ "cryptonight-heavy/xhv", "cn-heavy/xhv", Algorithm::CN_HEAVY_XHV },
{ "cryptonight_haven", nullptr, Algorithm::CN_HEAVY_XHV },
{ "cryptonight-heavy/tube", "cn-heavy/tube", Algorithm::CN_HEAVY_TUBE },
{ "cryptonight-bittube2", nullptr, Algorithm::CN_HEAVY_TUBE },
ALGO_ALIAS_AUTO(CN_HEAVY_0), ALGO_ALIAS(CN_HEAVY_0, "cryptonight-heavy/0"),
ALGO_ALIAS(CN_HEAVY_0, "cryptonight-heavy"),
ALGO_ALIAS(CN_HEAVY_0, "cn-heavy"),
ALGO_ALIAS(CN_HEAVY_0, "cryptonight_heavy"),
ALGO_ALIAS_AUTO(CN_HEAVY_XHV), ALGO_ALIAS(CN_HEAVY_XHV, "cryptonight-heavy/xhv"),
ALGO_ALIAS(CN_HEAVY_XHV, "cryptonight_haven"),
ALGO_ALIAS_AUTO(CN_HEAVY_TUBE), ALGO_ALIAS(CN_HEAVY_TUBE, "cryptonight-heavy/tube"),
ALGO_ALIAS(CN_HEAVY_TUBE, "cryptonight-bittube2"),
# endif
# ifdef XMRIG_ALGO_CN_PICO
{ "cryptonight-pico", "cn-pico", Algorithm::CN_PICO_0 },
{ "cryptonight-pico/trtl", "cn-pico/trtl", Algorithm::CN_PICO_0 },
{ "cryptonight-turtle", "cn-trtl", Algorithm::CN_PICO_0 },
{ "cryptonight-ultralite", "cn-ultralite", Algorithm::CN_PICO_0 },
{ "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 },
{ "cryptonight-pico/tlo", "cn-pico/tlo", Algorithm::CN_PICO_TLO },
{ "cryptonight/ultra", "cn/ultra", Algorithm::CN_PICO_TLO },
{ "cryptonight-talleo", "cn-talleo", Algorithm::CN_PICO_TLO },
{ "cryptonight_talleo", "cn_talleo", Algorithm::CN_PICO_TLO },
ALGO_ALIAS_AUTO(CN_PICO_0), ALGO_ALIAS(CN_PICO_0, "cryptonight-pico"),
ALGO_ALIAS(CN_PICO_0, "cn-pico/0"),
ALGO_ALIAS(CN_PICO_0, "cryptonight-pico/trtl"),
ALGO_ALIAS(CN_PICO_0, "cn-pico/trtl"),
ALGO_ALIAS(CN_PICO_0, "cryptonight-turtle"),
ALGO_ALIAS(CN_PICO_0, "cn-trtl"),
ALGO_ALIAS(CN_PICO_0, "cryptonight-ultralite"),
ALGO_ALIAS(CN_PICO_0, "cn-ultralite"),
ALGO_ALIAS(CN_PICO_0, "cryptonight_turtle"),
ALGO_ALIAS(CN_PICO_0, "cn_turtle"),
ALGO_ALIAS_AUTO(CN_PICO_TLO), ALGO_ALIAS(CN_PICO_TLO, "cryptonight-pico/tlo"),
ALGO_ALIAS(CN_PICO_TLO, "cryptonight/ultra"),
ALGO_ALIAS(CN_PICO_TLO, "cn/ultra"),
ALGO_ALIAS(CN_PICO_TLO, "cryptonight-talleo"),
ALGO_ALIAS(CN_PICO_TLO, "cn-talleo"),
ALGO_ALIAS(CN_PICO_TLO, "cryptonight_talleo"),
ALGO_ALIAS(CN_PICO_TLO, "cn_talleo"),
# endif
# ifdef XMRIG_ALGO_CN_FEMTO
ALGO_ALIAS_AUTO(CN_UPX2), ALGO_ALIAS(CN_UPX2, "cryptonight/upx2"),
ALGO_ALIAS(CN_UPX2, "cn-extremelite/upx2"),
ALGO_ALIAS(CN_UPX2, "cryptonight-upx/2"),
# endif
# ifdef XMRIG_ALGO_RANDOMX
{ "randomx/0", "rx/0", Algorithm::RX_0 },
{ "randomx/test", "rx/test", Algorithm::RX_0 },
{ "RandomX", "rx", Algorithm::RX_0 },
{ "randomx/wow", "rx/wow", Algorithm::RX_WOW },
{ "RandomWOW", nullptr, Algorithm::RX_WOW },
{ "randomx/arq", "rx/arq", Algorithm::RX_ARQ },
{ "RandomARQ", nullptr, Algorithm::RX_ARQ },
{ "randomx/sfx", "rx/sfx", Algorithm::RX_SFX },
{ "RandomSFX", nullptr, Algorithm::RX_SFX },
{ "randomx/keva", "rx/keva", Algorithm::RX_KEVA },
{ "RandomKEVA", nullptr, Algorithm::RX_KEVA },
ALGO_ALIAS_AUTO(RX_0), ALGO_ALIAS(RX_0, "randomx/0"),
ALGO_ALIAS(RX_0, "randomx/test"),
ALGO_ALIAS(RX_0, "rx/test"),
ALGO_ALIAS(RX_0, "randomx"),
ALGO_ALIAS(RX_0, "rx"),
ALGO_ALIAS_AUTO(RX_WOW), ALGO_ALIAS(RX_WOW, "randomx/wow"),
ALGO_ALIAS(RX_WOW, "randomwow"),
ALGO_ALIAS_AUTO(RX_ARQ), ALGO_ALIAS(RX_ARQ, "randomx/arq"),
ALGO_ALIAS(RX_ARQ, "randomarq"),
ALGO_ALIAS_AUTO(RX_SFX), ALGO_ALIAS(RX_SFX, "randomx/sfx"),
ALGO_ALIAS(RX_SFX, "randomsfx"),
ALGO_ALIAS_AUTO(RX_KEVA), ALGO_ALIAS(RX_KEVA, "randomx/keva"),
ALGO_ALIAS(RX_KEVA, "randomkeva"),
# endif
# ifdef XMRIG_ALGO_ARGON2
{ "argon2/chukwa", nullptr, Algorithm::AR2_CHUKWA },
{ "chukwa", nullptr, Algorithm::AR2_CHUKWA },
{ "argon2/chukwav2", nullptr, Algorithm::AR2_CHUKWA_V2 },
{ "chukwav2", nullptr, Algorithm::AR2_CHUKWA_V2 },
{ "argon2/wrkz", nullptr, Algorithm::AR2_WRKZ },
ALGO_ALIAS_AUTO(AR2_CHUKWA), ALGO_ALIAS(AR2_CHUKWA, "chukwa"),
ALGO_ALIAS_AUTO(AR2_CHUKWA_V2), ALGO_ALIAS(AR2_CHUKWA, "chukwav2"),
ALGO_ALIAS_AUTO(AR2_WRKZ), ALGO_ALIAS(AR2_WRKZ, "argon2/wrkz"),
# endif
# ifdef XMRIG_ALGO_ASTROBWT
{ "astrobwt", nullptr, Algorithm::ASTROBWT_DERO },
{ "astrobwt/dero", nullptr, Algorithm::ASTROBWT_DERO },
ALGO_ALIAS_AUTO(ASTROBWT_DERO), ALGO_ALIAS(ASTROBWT_DERO, "astrobwt/dero"),
# endif
# ifdef XMRIG_ALGO_KAWPOW
{ "kawpow", nullptr, Algorithm::KAWPOW_RVN },
{ "kawpow/rvn", nullptr, Algorithm::KAWPOW_RVN },
ALGO_ALIAS_AUTO(KAWPOW_RVN), ALGO_ALIAS(KAWPOW_RVN, "kawpow/rvn"),
# endif
{ "cryptonight/ccx", "cn/ccx", Algorithm::CN_CCX },
{ "cryptonight/conceal", "cn/conceal", Algorithm::CN_CCX },
};
@@ -141,11 +291,30 @@ xmrig::Algorithm::Algorithm(const rapidjson::Value &value) :
}
xmrig::Algorithm::Algorithm(uint32_t id) :
m_id(kAlgorithmNames.count(id) ? static_cast<Id>(id) : INVALID)
{
}
const char *xmrig::Algorithm::name() const
{
if (!isValid()) {
return kINVALID;
}
assert(kAlgorithmNames.count(m_id));
const auto it = kAlgorithmNames.find(m_id);
return it != kAlgorithmNames.end() ? it->second : kINVALID;
}
rapidjson::Value xmrig::Algorithm::toJSON() const
{
using namespace rapidjson;
return isValid() ? Value(StringRef(shortName())) : Value(kNullType);
return isValid() ? Value(StringRef(name())) : Value(kNullType);
}
@@ -155,237 +324,46 @@ rapidjson::Value xmrig::Algorithm::toJSON(rapidjson::Document &) const
}
size_t xmrig::Algorithm::l2() const
{
# ifdef XMRIG_ALGO_RANDOMX
switch (m_id) {
case RX_0:
case RX_SFX:
return 0x40000;
case RX_WOW:
case RX_KEVA:
return 0x20000;
case RX_ARQ:
return 0x10000;
default:
break;
}
# endif
return 0;
}
size_t xmrig::Algorithm::l3() const
{
constexpr size_t oneMiB = 0x100000;
const auto f = family();
assert(f != UNKNOWN);
switch (f) {
case CN:
return oneMiB * 2;
case CN_LITE:
return oneMiB;
case CN_HEAVY:
return oneMiB * 4;
case CN_PICO:
return oneMiB / 4;
default:
break;
}
# ifdef XMRIG_ALGO_RANDOMX
if (f == RANDOM_X) {
switch (m_id) {
case RX_0:
case RX_SFX:
return oneMiB * 2;
case RX_WOW:
case RX_KEVA:
return oneMiB;
case RX_ARQ:
return oneMiB / 4;
default:
break;
}
}
# endif
# ifdef XMRIG_ALGO_ARGON2
if (f == ARGON2) {
switch (m_id) {
case AR2_CHUKWA:
return oneMiB / 2;
case AR2_CHUKWA_V2:
return oneMiB;
case AR2_WRKZ:
return oneMiB / 4;
default:
break;
}
}
# endif
# ifdef XMRIG_ALGO_ASTROBWT
if (f == ASTROBWT) {
switch (m_id) {
case ASTROBWT_DERO:
return oneMiB * 20;
default:
break;
}
}
# endif
# ifdef XMRIG_ALGO_KAWPOW
if (f == KAWPOW) {
switch (m_id) {
case KAWPOW_RVN:
return 32768;
default:
break;
}
}
# endif
return 0;
}
uint32_t xmrig::Algorithm::maxIntensity() const
{
# ifdef XMRIG_ALGO_RANDOMX
if (family() == RANDOM_X) {
return 1;
}
# endif
# ifdef XMRIG_ALGO_ARGON2
if (family() == ARGON2) {
return 1;
}
# endif
# ifdef XMRIG_ALGO_ASTROBWT
if (family() == ASTROBWT) {
return 1;
}
# endif
return 5;
}
xmrig::Algorithm::Family xmrig::Algorithm::family(Id id)
{
switch (id) {
case CN_0:
case CN_1:
case CN_2:
case CN_R:
case CN_FAST:
case CN_HALF:
case CN_XAO:
case CN_RTO:
case CN_RWZ:
case CN_ZLS:
case CN_DOUBLE:
case CN_CCX:
return CN;
# ifdef XMRIG_ALGO_CN_LITE
case CN_LITE_0:
case CN_LITE_1:
return CN_LITE;
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
case CN_HEAVY_0:
case CN_HEAVY_TUBE:
case CN_HEAVY_XHV:
return CN_HEAVY;
# endif
# ifdef XMRIG_ALGO_CN_PICO
case CN_PICO_0:
case CN_PICO_TLO:
return CN_PICO;
# endif
# ifdef XMRIG_ALGO_RANDOMX
case RX_0:
case RX_WOW:
case RX_ARQ:
case RX_SFX:
case RX_KEVA:
return RANDOM_X;
# endif
# ifdef XMRIG_ALGO_ARGON2
case AR2_CHUKWA:
case AR2_CHUKWA_V2:
case AR2_WRKZ:
return ARGON2;
# endif
# ifdef XMRIG_ALGO_ASTROBWT
case ASTROBWT_DERO:
return ASTROBWT;
# endif
# ifdef XMRIG_ALGO_KAWPOW
case KAWPOW_RVN:
return KAWPOW;
# endif
default:
break;
}
return UNKNOWN;
}
xmrig::Algorithm::Id xmrig::Algorithm::parse(const char *name)
{
if (name == nullptr || strlen(name) < 1) {
return INVALID;
}
for (const AlgoName &item : algorithm_names) {
if ((strcasecmp(name, item.name) == 0) || (item.shortName != nullptr && strcasecmp(name, item.shortName) == 0)) {
return item.id;
}
}
const auto it = kAlgorithmAliases.find(name);
return INVALID;
return it != kAlgorithmAliases.end() ? it->second : INVALID;
}
const char *xmrig::Algorithm::name(bool shortName) const
size_t xmrig::Algorithm::count()
{
for (const AlgoName &item : algorithm_names) {
if (item.id == m_id) {
return (shortName && item.shortName) ? item.shortName : item.name;
return kAlgorithmNames.size();
}
std::vector<xmrig::Algorithm> xmrig::Algorithm::all(const std::function<bool(const Algorithm &algo)> &filter)
{
static const std::vector<Id> order = {
CN_0, CN_1, CN_2, CN_R, CN_FAST, CN_HALF, CN_XAO, CN_RTO, CN_RWZ, CN_ZLS, CN_DOUBLE, CN_CCX,
CN_LITE_0, CN_LITE_1,
CN_HEAVY_0, CN_HEAVY_TUBE, CN_HEAVY_XHV,
CN_PICO_0, CN_PICO_TLO,
CN_UPX2,
RX_0, RX_WOW, RX_ARQ, RX_SFX, RX_KEVA,
AR2_CHUKWA, AR2_CHUKWA_V2, AR2_WRKZ,
ASTROBWT_DERO,
KAWPOW_RVN
};
Algorithms out;
out.reserve(count());
for (const Id algo : order) {
if (kAlgorithmNames.count(algo) && (!filter || filter(algo))) {
out.emplace_back(algo);
}
}
return "invalid";
return out;
}

View File

@@ -1,13 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -27,6 +21,7 @@
#define XMRIG_ALGORITHM_H
#include <functional>
#include <vector>
@@ -39,87 +34,172 @@ namespace xmrig {
class Algorithm
{
public:
// Changes in following file is required if this enum changed:
// Changes in following file may required if this enum changed:
//
// src/backend/opencl/cl/cn/algorithm.cl
//
enum Id : int {
INVALID = -1,
CN_0, // "cn/0" CryptoNight (original).
CN_1, // "cn/1" CryptoNight variant 1 also known as Monero7 and CryptoNightV7.
CN_2, // "cn/2" CryptoNight variant 2.
CN_R, // "cn/r" CryptoNightR (Monero's variant 4).
CN_FAST, // "cn/fast" CryptoNight variant 1 with half iterations.
CN_HALF, // "cn/half" CryptoNight variant 2 with half iterations (Masari/Torque).
CN_XAO, // "cn/xao" CryptoNight variant 0 (modified, Alloy only).
CN_RTO, // "cn/rto" CryptoNight variant 1 (modified, Arto only).
CN_RWZ, // "cn/rwz" CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft).
CN_ZLS, // "cn/zls" CryptoNight variant 2 with 3/4 iterations (Zelerius).
CN_DOUBLE, // "cn/double" CryptoNight variant 2 with double iterations (X-CASH).
CN_LITE_0, // "cn-lite/0" CryptoNight-Lite variant 0.
CN_LITE_1, // "cn-lite/1" CryptoNight-Lite variant 1.
CN_HEAVY_0, // "cn-heavy/0" CryptoNight-Heavy (4 MB).
CN_HEAVY_TUBE, // "cn-heavy/tube" CryptoNight-Heavy (modified, TUBE only).
CN_HEAVY_XHV, // "cn-heavy/xhv" CryptoNight-Heavy (modified, Haven Protocol only).
CN_PICO_0, // "cn-pico" CryptoNight-Pico
CN_PICO_TLO, // "cn-pico/tlo" CryptoNight-Pico (TLO)
CN_CCX, // "cn/ccx" Conceal (CCX)
RX_0, // "rx/0" RandomX (reference configuration).
RX_WOW, // "rx/wow" RandomWOW (Wownero).
RX_ARQ, // "rx/arq" RandomARQ (Arqma).
RX_SFX, // "rx/sfx" RandomSFX (Safex Cash).
RX_KEVA, // "rx/keva" RandomKEVA (Keva).
AR2_CHUKWA, // "argon2/chukwa" Argon2id (Chukwa).
AR2_CHUKWA_V2, // "argon2/chukwav2" Argon2id (Chukwa v2).
AR2_WRKZ, // "argon2/wrkz" Argon2id (WRKZ)
ASTROBWT_DERO, // "astrobwt" AstroBWT (Dero)
KAWPOW_RVN, // "kawpow/rvn" KawPow (RVN)
MAX
// Id encoding:
// 1 byte: family
// 1 byte: L3 memory as power of 2 (if applicable).
// 1 byte: L2 memory for RandomX algorithms as power of 2, base variant for CryptoNight algorithms or 0x00.
// 1 byte: extra variant (coin) id.
enum Id : uint32_t {
INVALID = 0,
CN_0 = 0x63150000, // "cn/0" CryptoNight (original).
CN_1 = 0x63150100, // "cn/1" CryptoNight variant 1 also known as Monero7 and CryptoNightV7.
CN_2 = 0x63150200, // "cn/2" CryptoNight variant 2.
CN_R = 0x63150272, // "cn/r" CryptoNightR (Monero's variant 4).
CN_FAST = 0x63150166, // "cn/fast" CryptoNight variant 1 with half iterations.
CN_HALF = 0x63150268, // "cn/half" CryptoNight variant 2 with half iterations (Masari/Torque).
CN_XAO = 0x63150078, // "cn/xao" CryptoNight variant 0 (modified, Alloy only).
CN_RTO = 0x63150172, // "cn/rto" CryptoNight variant 1 (modified, Arto only).
CN_RWZ = 0x63150277, // "cn/rwz" CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft).
CN_ZLS = 0x6315027a, // "cn/zls" CryptoNight variant 2 with 3/4 iterations (Zelerius).
CN_DOUBLE = 0x63150264, // "cn/double" CryptoNight variant 2 with double iterations (X-CASH).
CN_CCX = 0x63150063, // "cn/ccx" Conceal (CCX)
CN_LITE_0 = 0x63140000, // "cn-lite/0" CryptoNight-Lite variant 0.
CN_LITE_1 = 0x63140100, // "cn-lite/1" CryptoNight-Lite variant 1.
CN_HEAVY_0 = 0x63160000, // "cn-heavy/0" CryptoNight-Heavy (4 MB).
CN_HEAVY_TUBE = 0x63160172, // "cn-heavy/tube" CryptoNight-Heavy (modified, TUBE only).
CN_HEAVY_XHV = 0x63160068, // "cn-heavy/xhv" CryptoNight-Heavy (modified, Haven Protocol only).
CN_PICO_0 = 0x63120200, // "cn-pico" CryptoNight-Pico
CN_PICO_TLO = 0x63120274, // "cn-pico/tlo" CryptoNight-Pico (TLO)
CN_UPX2 = 0x63110200, // "cn/upx2" Uplexa (UPX2)
RX_0 = 0x72151200, // "rx/0" RandomX (reference configuration).
RX_WOW = 0x72141177, // "rx/wow" RandomWOW (Wownero).
RX_ARQ = 0x72121061, // "rx/arq" RandomARQ (Arqma).
RX_SFX = 0x72151273, // "rx/sfx" RandomSFX (Safex Cash).
RX_KEVA = 0x7214116b, // "rx/keva" RandomKEVA (Keva).
AR2_CHUKWA = 0x61130000, // "argon2/chukwa" Argon2id (Chukwa).
AR2_CHUKWA_V2 = 0x61140000, // "argon2/chukwav2" Argon2id (Chukwa v2).
AR2_WRKZ = 0x61120000, // "argon2/wrkz" Argon2id (WRKZ)
ASTROBWT_DERO = 0x41000000, // "astrobwt" AstroBWT (Dero)
KAWPOW_RVN = 0x6b0f0000, // "kawpow/rvn" KawPow (RVN)
};
enum Family : int {
UNKNOWN,
CN,
CN_LITE,
CN_HEAVY,
CN_PICO,
RANDOM_X,
ARGON2,
ASTROBWT,
KAWPOW
enum Family : uint32_t {
UNKNOWN = 0,
CN_ANY = 0x63000000,
CN = 0x63150000,
CN_LITE = 0x63140000,
CN_HEAVY = 0x63160000,
CN_PICO = 0x63120000,
CN_FEMTO = 0x63110000,
RANDOM_X = 0x72000000,
ARGON2 = 0x61000000,
ASTROBWT = 0x41000000,
KAWPOW = 0x6b000000
};
static const char *kINVALID;
static const char *kCN;
static const char *kCN_0;
static const char *kCN_1;
static const char *kCN_2;
static const char *kCN_R;
static const char *kCN_FAST;
static const char *kCN_HALF;
static const char *kCN_XAO;
static const char *kCN_RTO;
static const char *kCN_RWZ;
static const char *kCN_ZLS;
static const char *kCN_DOUBLE;
static const char *kCN_CCX;
# ifdef XMRIG_ALGO_CN_LITE
static const char *kCN_LITE;
static const char *kCN_LITE_0;
static const char *kCN_LITE_1;
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
static const char *kCN_HEAVY;
static const char *kCN_HEAVY_0;
static const char *kCN_HEAVY_TUBE;
static const char *kCN_HEAVY_XHV;
# endif
# ifdef XMRIG_ALGO_CN_PICO
static const char *kCN_PICO;
static const char *kCN_PICO_0;
static const char *kCN_PICO_TLO;
# endif
# ifdef XMRIG_ALGO_CN_FEMTO
static const char *kCN_UPX2;
# endif
# ifdef XMRIG_ALGO_RANDOMX
static const char *kRX;
static const char *kRX_0;
static const char *kRX_WOW;
static const char *kRX_ARQ;
static const char *kRX_SFX;
static const char *kRX_KEVA;
# endif
# ifdef XMRIG_ALGO_ARGON2
static const char *kAR2;
static const char *kAR2_CHUKWA;
static const char *kAR2_CHUKWA_V2;
static const char *kAR2_WRKZ;
# endif
# ifdef XMRIG_ALGO_ASTROBWT
static const char *kASTROBWT;
static const char *kASTROBWT_DERO;
# endif
# ifdef XMRIG_ALGO_KAWPOW
static const char *kKAWPOW;
static const char *kKAWPOW_RVN;
# endif
inline Algorithm() = default;
inline Algorithm(const char *algo) : m_id(parse(algo)) {}
inline Algorithm(Id id) : m_id(id) {}
inline Algorithm(const char *algo) : m_id(parse(algo)) {}
inline Algorithm(Id id) : m_id(id) {}
Algorithm(const rapidjson::Value &value);
Algorithm(uint32_t id);
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; }
inline bool isValid() const { return m_id != INVALID && family() != UNKNOWN; }
inline const char *name() const { return name(false); }
inline const char *shortName() const { return name(true); }
inline Family family() const { return family(m_id); }
inline Id id() const { return m_id; }
static inline constexpr bool isCN(Id id) { return (id & 0xff000000) == CN_ANY; }
static inline constexpr Id base(Id id) { return isCN(id) ? static_cast<Id>(CN_0 | (id & 0xff00)) : INVALID; }
static inline constexpr size_t l2(Id id) { return family(id) == RANDOM_X ? (1U << ((id >> 8) & 0xff)) : 0U; }
static inline constexpr size_t l3(Id id) { return 1U << ((id >> 16) & 0xff); }
static inline constexpr uint32_t family(Id id) { return id & (isCN(id) ? 0xffff0000 : 0xff000000); }
inline bool operator!=(Algorithm::Id id) const { return m_id != id; }
inline bool operator!=(const Algorithm &other) const { return !isEqual(other); }
inline bool operator==(Algorithm::Id id) const { return m_id == id; }
inline bool operator==(const Algorithm &other) const { return isEqual(other); }
inline operator Algorithm::Id() const { return m_id; }
inline bool isCN() const { return isCN(m_id); }
inline bool isEqual(const Algorithm &other) const { return m_id == other.m_id; }
inline bool isValid() const { return m_id != INVALID && family() > UNKNOWN; }
inline Id base() const { return base(m_id); }
inline Id id() const { return m_id; }
inline size_t l2() const { return l2(m_id); }
inline uint32_t family() const { return family(m_id); }
inline uint32_t maxIntensity() const { return isCN() ? 5 : 1; };
inline size_t l3() const
{
# ifdef XMRIG_ALGO_ASTROBWT
return m_id != ASTROBWT_DERO ? l3(m_id) : 0x100000 * 20;
# else
return l3(m_id);
# endif
}
inline bool operator!=(Algorithm::Id id) const { return m_id != id; }
inline bool operator!=(const Algorithm &other) const { return !isEqual(other); }
inline bool operator==(Algorithm::Id id) const { return m_id == id; }
inline bool operator==(const Algorithm &other) const { return isEqual(other); }
inline operator Algorithm::Id() const { return m_id; }
const char *name() const;
rapidjson::Value toJSON() const;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
size_t l2() const;
size_t l3() const;
uint32_t maxIntensity() const;
static Family family(Id id);
static Id parse(const char *name);
static size_t count();
static std::vector<Algorithm> all(const std::function<bool(const Algorithm &algo)> &filter = nullptr);
private:
const char *name(bool shortName) const;
Id m_id = INVALID;
};

View File

@@ -56,7 +56,8 @@ static CoinName const coin_names[] = {
{ "ravencoin", Coin::RAVEN },
{ "raven", Coin::RAVEN },
{ "rvn", Coin::RAVEN },
{ "conceal", Coin::CONCEAL }
{ "conceal", Coin::CONCEAL },
{ "wownero", Coin::WOWNERO }
};
@@ -85,6 +86,9 @@ xmrig::Algorithm::Id xmrig::Coin::algorithm(uint8_t blobVersion) const
case CONCEAL:
return Algorithm::CN_CCX;
case WOWNERO:
return Algorithm::RX_WOW;
case INVALID:
break;
}

View File

@@ -44,7 +44,8 @@ public:
DERO,
KEVA,
RAVEN,
CONCEAL
CONCEAL,
WOWNERO
};

View File

@@ -181,6 +181,9 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
case IConfig::PasswordKey: /* --pass */
return add(doc, Pools::kPools, Pool::kPass, arg);
case IConfig::SpendSecretKey: /* --spend-secret-key */
return add(doc, Pools::kPools, Pool::kSpendSecretKey, arg);
case IConfig::RigIdKey: /* --rig-id */
return add(doc, Pools::kPools, Pool::kRigId, arg);
@@ -239,13 +242,14 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
return set(doc, BaseConfig::kTls, TlsConfig::kGen, arg);
# endif
case IConfig::RetriesKey: /* --retries */
case IConfig::RetryPauseKey: /* --retry-pause */
case IConfig::PrintTimeKey: /* --print-time */
case IConfig::HttpPort: /* --http-port */
case IConfig::DonateLevelKey: /* --donate-level */
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
case IConfig::DnsTtlKey: /* --dns-ttl */
case IConfig::RetriesKey: /* --retries */
case IConfig::RetryPauseKey: /* --retry-pause */
case IConfig::PrintTimeKey: /* --print-time */
case IConfig::HttpPort: /* --http-port */
case IConfig::DonateLevelKey: /* --donate-level */
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
case IConfig::DnsTtlKey: /* --dns-ttl */
case IConfig::DaemonZMQPortKey: /* --daemon-zmq-port */
return transformUint64(doc, key, static_cast<uint64_t>(strtol(arg, nullptr, 10)));
case IConfig::BackgroundKey: /* --background */
@@ -356,6 +360,9 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui
# ifdef XMRIG_FEATURE_HTTP
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
return add(doc, Pools::kPools, Pool::kDaemonPollInterval, arg);
case IConfig::DaemonZMQPortKey: /* --daemon-zmq-port */
return add(doc, Pools::kPools, Pool::kDaemonZMQPort, arg);
# endif
default:

View File

@@ -84,6 +84,9 @@ public:
SubmitToOriginKey = 1052,
DnsIPv6Key = 1053,
DnsTtlKey = 1054,
SpendSecretKey = 1055,
DaemonZMQPortKey = 1056,
HugePagesJitKey = 1057,
// xmrig common
CPUPriorityKey = 1021,

View File

@@ -1,13 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -53,6 +47,7 @@
#include "base/net/tools/NetBuffer.h"
#include "base/tools/Chrono.h"
#include "base/tools/Cvt.h"
#include "base/tools/cryptonote/BlobReader.h"
#include "net/JobResult.h"
@@ -83,7 +78,8 @@ static const char *states[] = {
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
BaseClient(id, listener),
m_agent(agent),
m_sendBuf(1024)
m_sendBuf(1024),
m_tempBuf(256)
{
m_reader.setListener(this);
m_key = m_storage.add(this);
@@ -198,11 +194,16 @@ int64_t xmrig::Client::submit(const JobResult &result)
const char *nonce = result.nonce;
const char *data = result.result;
# else
char *nonce = m_sendBuf.data();
char *data = m_sendBuf.data() + 16;
char *nonce = m_tempBuf.data();
char *data = m_tempBuf.data() + 16;
char *signature = m_tempBuf.data() + 88;
Cvt::toHex(nonce, sizeof(uint32_t) * 2 + 1, reinterpret_cast<const uint8_t *>(&result.nonce), sizeof(uint32_t));
Cvt::toHex(data, 65, result.result(), 32);
if (result.minerSignature()) {
Cvt::toHex(signature, 129, result.minerSignature(), 64);
}
# endif
Document doc(kObjectType);
@@ -214,8 +215,18 @@ int64_t xmrig::Client::submit(const JobResult &result)
params.AddMember("nonce", StringRef(nonce), allocator);
params.AddMember("result", StringRef(data), allocator);
# ifndef XMRIG_PROXY_PROJECT
if (result.minerSignature()) {
params.AddMember("sig", StringRef(signature), allocator);
}
# else
if (result.sig) {
params.AddMember("sig", StringRef(result.sig), allocator);
}
# endif
if (has<EXT_ALGO>() && result.algorithm.isValid()) {
params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator);
params.AddMember("algo", StringRef(result.algorithm.name()), allocator);
}
JsonRequest::create(doc, m_sequence, "submit", params);
@@ -427,6 +438,8 @@ bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
return false;
}
job.setSigKey(Json::getString(params, "sig_key"));
m_job.setClientId(m_rpcId);
if (m_job != job) {
@@ -496,7 +509,7 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo
m_listener->onVerifyAlgorithm(this, algorithm, &ok);
if (!ok && !isQuiet()) {
LOG_ERR("%s " RED("incompatible/disabled algorithm ") RED_BOLD("\"%s\" ") RED("detected, reconnect"), tag(), algorithm.shortName());
LOG_ERR("%s " RED("incompatible/disabled algorithm ") RED_BOLD("\"%s\" ") RED("detected, reconnect"), tag(), algorithm.name());
}
return ok;

View File

@@ -1,13 +1,7 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -137,6 +131,7 @@ private:
std::bitset<EXT_MAX> m_extensions;
std::shared_ptr<DnsRequest> m_dns;
std::vector<char> m_sendBuf;
std::vector<char> m_tempBuf;
String m_rpcId;
Tls *m_tls = nullptr;
uint64_t m_expire = 0;

View File

@@ -31,12 +31,18 @@
#include "base/io/json/JsonRequest.h"
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/dns/Dns.h"
#include "base/net/dns/DnsRecords.h"
#include "base/net/http/Fetch.h"
#include "base/net/http/HttpData.h"
#include "base/net/http/HttpListener.h"
#include "base/net/stratum/SubmitResult.h"
#include "base/net/tools/NetBuffer.h"
#include "base/tools/bswap_64.h"
#include "base/tools/Cvt.h"
#include "base/tools/Timer.h"
#include "base/tools/cryptonote/Signatures.h"
#include "base/tools/cryptonote/WalletAddress.h"
#include "net/JobResult.h"
@@ -46,7 +52,11 @@
namespace xmrig {
static const char *kBlocktemplateBlob = "blocktemplate_blob";
Storage<DaemonClient> DaemonClient::m_storage;
static const char* kBlocktemplateBlob = "blocktemplate_blob";
static const char *kGetHeight = "/getheight";
static const char *kGetInfo = "/getinfo";
static const char *kHash = "hash";
@@ -55,6 +65,12 @@ static const char *kJsonRPC = "/json_rpc";
static constexpr size_t kBlobReserveSize = 8;
static const char kZMQGreeting[64] = { static_cast<char>(-1), 0, 0, 0, 0, 0, 0, 0, 0, 127, 3, 0, 'N', 'U', 'L', 'L' };
static constexpr size_t kZMQGreetingSize1 = 11;
static const char kZMQHandshake[] = "\4\x19\5READY\xbSocket-Type\0\0\0\3SUB";
static const char kZMQSubscribe[] = "\0\x18\1json-minimal-chain_main";
}
@@ -63,12 +79,25 @@ xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) :
{
m_httpListener = std::make_shared<HttpListener>(this);
m_timer = new Timer(this);
m_key = m_storage.add(this);
}
xmrig::DaemonClient::~DaemonClient()
{
delete m_timer;
delete m_ZMQSocket;
}
void xmrig::DaemonClient::deleteLater()
{
if (m_pool.zmq_port() >= 0) {
ZMQClose(true);
}
else {
delete this;
}
}
@@ -94,16 +123,36 @@ bool xmrig::DaemonClient::isTLS() const
int64_t xmrig::DaemonClient::submit(const JobResult &result)
{
if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 32)) {
if (result.jobId != m_currentJobId) {
return -1;
}
char *data = (m_apiVersion == API_DERO) ? m_blockhashingblob.data() : m_blocktemplate.data();
char *data = (m_apiVersion == API_DERO) ? m_blockhashingblob.data() : m_blocktemplateStr.data();
const size_t sig_offset = m_job.nonceOffset() + m_job.nonceSize();
# ifdef XMRIG_PROXY_PROJECT
memcpy(data + 78, result.nonce, 8);
memcpy(data + m_job.nonceOffset() * 2, result.nonce, 8);
if (m_blocktemplate.has_miner_signature && result.sig) {
memcpy(data + sig_offset * 2, result.sig, 64 * 2);
memcpy(data + m_blocktemplate.tx_pubkey_index * 2, result.sig_data, 32 * 2);
memcpy(data + m_blocktemplate.eph_public_key_index * 2, result.sig_data + 32 * 2, 32 * 2);
}
if (result.extra_nonce >= 0) {
Cvt::toHex(data + m_blocktemplate.tx_extra_nonce_index * 2, 8, reinterpret_cast<const uint8_t*>(&result.extra_nonce), 4);
}
# else
Cvt::toHex(data + 78, 8, reinterpret_cast<const uint8_t *>(&result.nonce), 4);
Cvt::toHex(data + m_job.nonceOffset() * 2, 8, reinterpret_cast<const uint8_t*>(&result.nonce), 4);
if (m_blocktemplate.has_miner_signature) {
Cvt::toHex(data + sig_offset * 2, 128, result.minerSignature(), 64);
}
# endif
using namespace rapidjson;
@@ -111,11 +160,11 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result)
Value params(kArrayType);
if (m_apiVersion == API_DERO) {
params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator());
params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator());
params.PushBack(m_blockhashingblob.toJSON(), doc.GetAllocator());
}
else {
params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator());
params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator());
}
JsonRequest::create(doc, m_sequence, "submitblock", params);
@@ -137,7 +186,13 @@ void xmrig::DaemonClient::connect()
}
setState(ConnectingState);
getBlockTemplate();
if (m_pool.zmq_port() >= 0) {
m_dns = Dns::resolve(m_pool.host(), this);
}
else {
getBlockTemplate();
}
}
@@ -216,7 +271,7 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data)
void xmrig::DaemonClient::onTimer(const Timer *)
{
if (m_state == ConnectingState) {
getBlockTemplate();
connect();
}
else if (m_state == ConnectedState) {
if (m_apiVersion == API_DERO) {
@@ -229,6 +284,43 @@ void xmrig::DaemonClient::onTimer(const Timer *)
}
void xmrig::DaemonClient::onResolved(const DnsRecords& records, int status, const char* error)
{
m_dns.reset();
if (status < 0 && records.isEmpty()) {
if (!isQuiet()) {
LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), error);
}
retry();
return;
}
if (m_ZMQSocket) {
delete m_ZMQSocket;
}
const auto& record = records.get();
m_ip = record.ip();
uv_connect_t* req = new uv_connect_t;
req->data = m_storage.ptr(m_key);
m_ZMQSocket = new uv_tcp_t;
m_ZMQSocket->data = m_storage.ptr(m_key);
uv_tcp_init(uv_default_loop(), m_ZMQSocket);
uv_tcp_nodelay(m_ZMQSocket, 1);
# ifndef WIN32
uv_tcp_keepalive(m_ZMQSocket, 1, 60);
# endif
uv_tcp_connect(req, m_ZMQSocket, record.addr(m_pool.zmq_port()), onZMQConnect);
}
bool xmrig::DaemonClient::isOutdated(uint64_t height, const char *hash) const
{
return m_job.height() != height || m_prevHash != hash;
@@ -241,31 +333,136 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
String blocktemplate = Json::getString(params, kBlocktemplateBlob);
if (blocktemplate.isNull()) {
LOG_ERR("Empty block template received from daemon");
*code = 1;
return false;
}
Coin pool_coin = m_pool.coin();
if (!pool_coin.isValid() && (m_pool.algorithm() == Algorithm::RX_WOW)) {
pool_coin = Coin::WOWNERO;
}
if (!m_blocktemplate.Init(blocktemplate, pool_coin)) {
LOG_ERR("Invalid block template received from daemon");
*code = 2;
return false;
}
# ifdef XMRIG_PROXY_PROJECT
const size_t k = m_blocktemplate.miner_tx_prefix_begin_index;
job.setMinerTx(
m_blocktemplate.raw_blob.data() + k,
m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_end_index,
m_blocktemplate.eph_public_key_index - k,
m_blocktemplate.tx_pubkey_index - k,
m_blocktemplate.tx_extra_nonce_index - k,
m_blocktemplate.tx_extra_nonce_size,
m_blocktemplate.miner_tx_merkle_tree_branch
);
# endif
m_blockhashingblob = Json::getString(params, "blockhashing_blob");
if (m_blocktemplate.has_miner_signature) {
if (m_pool.spendSecretKey().isEmpty()) {
LOG_ERR("Secret spend key is not set");
*code = 4;
return false;
}
if (m_pool.spendSecretKey().size() != 64) {
LOG_ERR("Secret spend key has invalid length. It must be 64 hex characters.");
*code = 5;
return false;
}
uint8_t secret_spendkey[32];
if (!Cvt::fromHex(secret_spendkey, 32, m_pool.spendSecretKey(), 64)) {
LOG_ERR("Secret spend key is not a valid hex data.");
*code = 6;
return false;
}
uint8_t public_spendkey[32];
if (!secret_key_to_public_key(secret_spendkey, public_spendkey)) {
LOG_ERR("Secret spend key is invalid.");
*code = 7;
return false;
}
# ifdef XMRIG_PROXY_PROJECT
job.setSpendSecretKey(secret_spendkey);
# else
uint8_t secret_viewkey[32];
derive_view_secret_key(secret_spendkey, secret_viewkey);
uint8_t public_viewkey[32];
if (!secret_key_to_public_key(secret_viewkey, public_viewkey)) {
LOG_ERR("Secret view key is invalid.");
*code = 8;
return false;
}
uint8_t derivation[32];
if (!generate_key_derivation(m_blocktemplate.raw_blob.data() + m_blocktemplate.tx_pubkey_index, secret_viewkey, derivation)) {
LOG_ERR("Failed to generate key derivation for miner signature.");
*code = 9;
return false;
}
WalletAddress user_address;
if (!user_address.Decode(m_pool.user())) {
LOG_ERR("Invalid wallet address.");
*code = 10;
return false;
}
if (memcmp(user_address.public_spend_key, public_spendkey, sizeof(public_spendkey)) != 0) {
LOG_ERR("Wallet address and spend key don't match.");
*code = 11;
return false;
}
if (memcmp(user_address.public_view_key, public_viewkey, sizeof(public_viewkey)) != 0) {
LOG_ERR("Wallet address and view key don't match.");
*code = 12;
return false;
}
uint8_t eph_secret_key[32];
derive_secret_key(derivation, 0, secret_spendkey, eph_secret_key);
job.setEphemeralKeys(m_blocktemplate.raw_blob.data() + m_blocktemplate.eph_public_key_index, eph_secret_key);
# endif
}
if (m_apiVersion == API_DERO) {
const uint64_t offset = Json::getUint64(params, "reserved_offset");
Cvt::toHex(m_blockhashingblob.data() + offset * 2, kBlobReserveSize * 2, Cvt::randomBytes(kBlobReserveSize).data(), kBlobReserveSize);
}
if (m_pool.coin().isValid()) {
uint8_t blobVersion = 0;
Cvt::fromHex(&blobVersion, 1, m_blockhashingblob.data(), 2);
job.setAlgorithm(m_pool.coin().algorithm(blobVersion));
if (pool_coin.isValid()) {
job.setAlgorithm(pool_coin.algorithm(m_blocktemplate.major_version));
}
if (blocktemplate.isNull() || !job.setBlob(m_blockhashingblob)) {
*code = 4;
if (!job.setBlob(m_blockhashingblob)) {
*code = 3;
return false;
}
job.setSeedHash(Json::getString(params, "seed_hash"));
job.setHeight(Json::getUint64(params, kHeight));
job.setDiff(Json::getUint64(params, "difficulty"));
job.setId(blocktemplate.data() + blocktemplate.size() - 32);
m_job = std::move(job);
m_blocktemplate = std::move(blocktemplate);
m_prevHash = Json::getString(params, "prev_hash");
m_currentJobId = Cvt::toHex(Cvt::randomBytes(4));
job.setId(m_currentJobId);
m_job = std::move(job);
m_blocktemplateStr = std::move(blocktemplate);
m_prevHash = Json::getString(params, "prev_hash");
if (m_apiVersion == API_DERO) {
// Truncate to 32 bytes to have the same data as in get_info RPC
@@ -315,8 +512,19 @@ bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &resu
return true;
}
if (handleSubmitResponse(id)) {
getBlockTemplate();
const char* error_msg = nullptr;
if ((m_apiVersion == API_DERO) && result.HasMember("status")) {
error_msg = result["status"].GetString();
if (!error_msg || (strlen(error_msg) == 0) || (strcmp(error_msg, "OK") == 0)) {
error_msg = nullptr;
}
}
if (handleSubmitResponse(id, error_msg)) {
if (error_msg || (m_pool.zmq_port() < 0)) {
getBlockTemplate();
}
return true;
}
@@ -368,6 +576,10 @@ void xmrig::DaemonClient::retry()
setState(ConnectingState);
}
if ((m_ZMQConnectionState != ZMQ_NOT_CONNECTED) && (m_ZMQConnectionState != ZMQ_DISCONNECTING)) {
uv_close(reinterpret_cast<uv_handle_t*>(m_ZMQSocket), onZMQClose);
}
m_timer->stop();
m_timer->start(m_retryPause, 0);
}
@@ -395,8 +607,10 @@ void xmrig::DaemonClient::setState(SocketState state)
m_failures = 0;
m_listener->onLoginSuccess(this);
const uint64_t interval = std::max<uint64_t>(20, m_pool.pollInterval());
m_timer->start(interval, interval);
if (m_pool.zmq_port() < 0) {
const uint64_t interval = std::max<uint64_t>(20, m_pool.pollInterval());
m_timer->start(interval, interval);
}
}
break;
@@ -409,3 +623,282 @@ void xmrig::DaemonClient::setState(SocketState state)
break;
}
}
void xmrig::DaemonClient::onZMQConnect(uv_connect_t* req, int status)
{
DaemonClient* client = getClient(req->data);
delete req;
if (!client) {
return;
}
if (status < 0) {
LOG_ERR("%s " RED("ZMQ connect error: ") RED_BOLD("\"%s\""), client->tag(), uv_strerror(status));
client->retry();
return;
}
client->ZMQConnected();
}
void xmrig::DaemonClient::onZMQRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
DaemonClient* client = getClient(stream->data);
if (client) {
client->ZMQRead(nread, buf);
}
NetBuffer::release(buf);
}
void xmrig::DaemonClient::onZMQClose(uv_handle_t* handle)
{
DaemonClient* client = getClient(handle->data);
if (client) {
# ifdef APP_DEBUG
LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" disconnected"), client->m_pool.host().data(), client->m_pool.zmq_port());
# endif
client->m_ZMQConnectionState = ZMQ_NOT_CONNECTED;
}
}
void xmrig::DaemonClient::onZMQShutdown(uv_handle_t* handle)
{
DaemonClient* client = getClient(handle->data);
if (client) {
# ifdef APP_DEBUG
LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" shutdown"), client->m_pool.host().data(), client->m_pool.zmq_port());
# endif
client->m_ZMQConnectionState = ZMQ_NOT_CONNECTED;
m_storage.remove(client->m_key);
}
}
void xmrig::DaemonClient::ZMQConnected()
{
# ifdef APP_DEBUG
LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" connected"), m_pool.host().data(), m_pool.zmq_port());
# endif
m_ZMQConnectionState = ZMQ_GREETING_1;
m_ZMQSendBuf.reserve(256);
m_ZMQRecvBuf.reserve(256);
if (ZMQWrite(kZMQGreeting, kZMQGreetingSize1)) {
uv_read_start(reinterpret_cast<uv_stream_t*>(m_ZMQSocket), NetBuffer::onAlloc, onZMQRead);
}
}
bool xmrig::DaemonClient::ZMQWrite(const char* data, size_t size)
{
m_ZMQSendBuf.assign(data, data + size);
uv_buf_t buf;
buf.base = m_ZMQSendBuf.data();
buf.len = static_cast<uint32_t>(m_ZMQSendBuf.size());
const int rc = uv_try_write(reinterpret_cast<uv_stream_t*>(m_ZMQSocket), &buf, 1);
if (static_cast<size_t>(rc) == buf.len) {
return true;
}
LOG_ERR("%s " RED("ZMQ write failed, rc = %d"), tag(), rc);
ZMQClose();
return false;
}
void xmrig::DaemonClient::ZMQRead(ssize_t nread, const uv_buf_t* buf)
{
if (nread <= 0) {
LOG_ERR("%s " RED("ZMQ read failed, nread = %" PRId64), tag(), nread);
ZMQClose();
return;
}
m_ZMQRecvBuf.insert(m_ZMQRecvBuf.end(), buf->base, buf->base + nread);
do {
switch (m_ZMQConnectionState) {
case ZMQ_GREETING_1:
if (m_ZMQRecvBuf.size() >= kZMQGreetingSize1) {
if ((m_ZMQRecvBuf[0] == static_cast<char>(-1)) && (m_ZMQRecvBuf[9] == 127) && (m_ZMQRecvBuf[10] == 3)) {
ZMQWrite(kZMQGreeting + kZMQGreetingSize1, sizeof(kZMQGreeting) - kZMQGreetingSize1);
m_ZMQConnectionState = ZMQ_GREETING_2;
break;
}
else {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format"), tag());
ZMQClose();
}
}
return;
case ZMQ_GREETING_2:
if (m_ZMQRecvBuf.size() >= sizeof(kZMQGreeting)) {
if (memcmp(m_ZMQRecvBuf.data() + 12, kZMQGreeting + 12, 20) == 0) {
m_ZMQConnectionState = ZMQ_HANDSHAKE;
m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + sizeof(kZMQGreeting));
ZMQWrite(kZMQHandshake, sizeof(kZMQHandshake) - 1);
break;
}
else {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format 2"), tag());
ZMQClose();
}
}
return;
case ZMQ_HANDSHAKE:
if (m_ZMQRecvBuf.size() >= 2) {
if (m_ZMQRecvBuf[0] != 4) {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake format"), tag());
ZMQClose();
return;
}
const size_t size = static_cast<unsigned char>(m_ZMQRecvBuf[1]);
if (size < 18) {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake size"), tag());
ZMQClose();
return;
}
if (m_ZMQRecvBuf.size() < size + 2) {
return;
}
if (memcmp(m_ZMQRecvBuf.data() + 2, kZMQHandshake + 2, 18) != 0) {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake data"), tag());
ZMQClose();
return;
}
ZMQWrite(kZMQSubscribe, sizeof(kZMQSubscribe) - 1);
m_ZMQConnectionState = ZMQ_CONNECTED;
m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + size + 2);
getBlockTemplate();
break;
}
return;
case ZMQ_CONNECTED:
ZMQParse();
return;
default:
return;
}
} while (true);
}
void xmrig::DaemonClient::ZMQParse()
{
# ifdef APP_DEBUG
std::vector<char> msg;
# endif
size_t msg_size = 0;
char* data = m_ZMQRecvBuf.data();
size_t avail = m_ZMQRecvBuf.size();
bool more;
do {
if (avail < 1) {
return;
}
more = (data[0] & 1) != 0;
const bool long_size = (data[0] & 2) != 0;
const bool command = (data[0] & 4) != 0;
++data;
--avail;
uint64_t size = 0;
if (long_size)
{
if (avail < sizeof(uint64_t)) {
return;
}
size = bswap_64(*((uint64_t*)data));
data += sizeof(uint64_t);
avail -= sizeof(uint64_t);
}
else
{
if (avail < sizeof(uint8_t)) {
return;
}
size = static_cast<uint8_t>(*data);
++data;
--avail;
}
if (size > 1024U - msg_size)
{
LOG_ERR("%s " RED("ZMQ message is too large, size = %" PRIu64 " bytes"), tag(), size);
ZMQClose();
return;
}
if (avail < size) {
return;
}
if (!command) {
# ifdef APP_DEBUG
msg.insert(msg.end(), data, data + size);
# endif
msg_size += size;
}
data += size;
avail -= size;
} while (more);
m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + (data - m_ZMQRecvBuf.data()));
# ifdef APP_DEBUG
LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" read ") CYAN_BOLD("%zu") BLACK_BOLD(" bytes") " %s", m_pool.host().data(), m_pool.zmq_port(), msg.size(), msg.data());
# endif
getBlockTemplate();
}
bool xmrig::DaemonClient::ZMQClose(bool shutdown)
{
if ((m_ZMQConnectionState == ZMQ_NOT_CONNECTED) || (m_ZMQConnectionState == ZMQ_DISCONNECTING)) {
if (shutdown) {
m_storage.remove(m_key);
}
return false;
}
m_ZMQConnectionState = ZMQ_DISCONNECTING;
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_ZMQSocket)) == 0) {
uv_close(reinterpret_cast<uv_handle_t*>(m_ZMQSocket), shutdown ? onZMQShutdown : onZMQClose);
if (!shutdown) {
retry();
}
return true;
}
return false;
}

View File

@@ -27,10 +27,16 @@
#define XMRIG_DAEMONCLIENT_H
#include <uv.h>
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/kernel/interfaces/ITimerListener.h"
#include "base/net/stratum/BaseClient.h"
#include "base/tools/Object.h"
#include "base/tools/cryptonote/BlockTemplate.h"
#include "base/net/tools/Storage.h"
#include <memory>
@@ -39,7 +45,10 @@
namespace xmrig {
class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener
class DnsRequest;
class DaemonClient : public BaseClient, public IDnsListener, public ITimerListener, public IHttpListener
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(DaemonClient)
@@ -56,6 +65,7 @@ protected:
void onHttpData(const HttpData &data) override;
void onTimer(const Timer *timer) override;
void onResolved(const DnsRecords& records, int status, const char* error) override;
inline bool hasExtension(Extension) const noexcept override { return false; }
inline const char *mode() const override { return "daemon"; }
@@ -63,7 +73,7 @@ protected:
inline const char *tlsVersion() const override { return m_tlsVersion; }
inline int64_t send(const rapidjson::Value &, Callback) override { return -1; }
inline int64_t send(const rapidjson::Value &) override { return -1; }
inline void deleteLater() override { delete this; }
void deleteLater() override;
inline void tick(uint64_t) override {}
private:
@@ -83,7 +93,8 @@ private:
} m_apiVersion = API_MONERO;
std::shared_ptr<IHttpListener> m_httpListener;
String m_blocktemplate;
String m_currentJobId;
String m_blocktemplateStr;
String m_blockhashingblob;
String m_prevHash;
String m_tlsFingerprint;
@@ -91,6 +102,40 @@ private:
Timer *m_timer;
uint64_t m_blocktemplateRequestHeight = 0;
String m_blocktemplateRequestHash;
BlockTemplate m_blocktemplate;
private:
static inline DaemonClient* getClient(void* data) { return m_storage.get(data); }
uintptr_t m_key = 0;
static Storage<DaemonClient> m_storage;
static void onZMQConnect(uv_connect_t* req, int status);
static void onZMQRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
static void onZMQClose(uv_handle_t* handle);
static void onZMQShutdown(uv_handle_t* handle);
void ZMQConnected();
bool ZMQWrite(const char* data, size_t size);
void ZMQRead(ssize_t nread, const uv_buf_t* buf);
void ZMQParse();
bool ZMQClose(bool shutdown = false);
std::shared_ptr<DnsRequest> m_dns;
uv_tcp_t* m_ZMQSocket = nullptr;
enum {
ZMQ_NOT_CONNECTED,
ZMQ_GREETING_1,
ZMQ_GREETING_2,
ZMQ_HANDSHAKE,
ZMQ_CONNECTED,
ZMQ_DISCONNECTING,
} m_ZMQConnectionState = ZMQ_NOT_CONNECTED;
std::vector<char> m_ZMQSendBuf;
std::vector<char> m_ZMQRecvBuf;
};

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -213,7 +213,7 @@ void xmrig::EthStratumClient::parseNotification(const char *method, const rapidj
if (!ok) {
if (!isQuiet()) {
LOG_ERR("[%s] incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algo.shortName());
LOG_ERR("[%s] incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algo.name());
}
close();
return;

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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

@@ -7,8 +7,8 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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
@@ -32,6 +32,9 @@
#include "base/net/stratum/Job.h"
#include "base/tools/Buffer.h"
#include "base/tools/Cvt.h"
#include "base/tools/cryptonote/BlockTemplate.h"
#include "base/tools/cryptonote/Signatures.h"
#include "base/crypto/keccak.h"
xmrig::Job::Job(bool nicehash, const Algorithm &algorithm, const String &clientId) :
@@ -141,6 +144,50 @@ void xmrig::Job::setDiff(uint64_t diff)
}
void xmrig::Job::setSigKey(const char *sig_key)
{
constexpr const size_t size = 64;
if (!sig_key || strlen(sig_key) != size * 2) {
return;
}
# ifndef XMRIG_PROXY_PROJECT
const auto buf = Cvt::fromHex(sig_key, size * 2);
if (buf.size() == size) {
setEphemeralKeys(buf.data(), buf.data() + 32);
}
# else
m_rawSigKey = sig_key;
# endif
}
uint32_t xmrig::Job::getNumTransactions() const
{
if (!(m_algorithm.isCN() || m_algorithm.family() == Algorithm::RANDOM_X)) {
return 0;
}
uint32_t num_transactions = 0;
// Monero (and some other coins) has the number of transactions encoded as varint in the end of hashing blob
const size_t expected_tx_offset = (m_algorithm == Algorithm::RX_WOW) ? 141 : 75;
if ((m_size > expected_tx_offset) && (m_size <= expected_tx_offset + 4)) {
for (size_t i = expected_tx_offset, k = 0; i < m_size; ++i, k += 7) {
const uint8_t b = m_blob[i];
num_transactions |= static_cast<uint32_t>(b & 0x7F) << k;
if ((b & 0x80) == 0) {
break;
}
}
}
return num_transactions;
}
void xmrig::Job::copy(const Job &other)
{
m_algorithm = other.m_algorithm;
@@ -161,6 +208,7 @@ void xmrig::Job::copy(const Job &other)
# ifdef XMRIG_PROXY_PROJECT
m_rawSeedHash = other.m_rawSeedHash;
m_rawSigKey = other.m_rawSigKey;
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
@@ -169,6 +217,24 @@ void xmrig::Job::copy(const Job &other)
# ifdef XMRIG_FEATURE_BENCHMARK
m_benchSize = other.m_benchSize;
# endif
# ifdef XMRIG_PROXY_PROJECT
memcpy(m_spendSecretKey, other.m_spendSecretKey, sizeof(m_spendSecretKey));
memcpy(m_viewSecretKey, other.m_viewSecretKey, sizeof(m_viewSecretKey));
memcpy(m_spendPublicKey, other.m_spendPublicKey, sizeof(m_spendPublicKey));
memcpy(m_viewPublicKey, other.m_viewPublicKey, sizeof(m_viewPublicKey));
m_minerTxPrefix = other.m_minerTxPrefix;
m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = other.m_minerTxMerkleTreeBranch;
# else
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey));
# endif
m_hasMinerSignature = other.m_hasMinerSignature;
}
@@ -196,6 +262,7 @@ void xmrig::Job::move(Job &&other)
# ifdef XMRIG_PROXY_PROJECT
m_rawSeedHash = std::move(other.m_rawSeedHash);
m_rawSigKey = std::move(other.m_rawSigKey);
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
@@ -204,4 +271,115 @@ void xmrig::Job::move(Job &&other)
# ifdef XMRIG_FEATURE_BENCHMARK
m_benchSize = other.m_benchSize;
# endif
# ifdef XMRIG_PROXY_PROJECT
memcpy(m_spendSecretKey, other.m_spendSecretKey, sizeof(m_spendSecretKey));
memcpy(m_viewSecretKey, other.m_viewSecretKey, sizeof(m_viewSecretKey));
memcpy(m_spendPublicKey, other.m_spendPublicKey, sizeof(m_spendPublicKey));
memcpy(m_viewPublicKey, other.m_viewPublicKey, sizeof(m_viewPublicKey));
m_minerTxPrefix = std::move(other.m_minerTxPrefix);
m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch);
# else
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey));
# endif
m_hasMinerSignature = other.m_hasMinerSignature;
}
#ifdef XMRIG_PROXY_PROJECT
void xmrig::Job::setSpendSecretKey(const uint8_t *key)
{
m_hasMinerSignature = true;
memcpy(m_spendSecretKey, key, sizeof(m_spendSecretKey));
derive_view_secret_key(m_spendSecretKey, m_viewSecretKey);
secret_key_to_public_key(m_spendSecretKey, m_spendPublicKey);
secret_key_to_public_key(m_viewSecretKey, m_viewPublicKey);
}
void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer &minerTxMerkleTreeBranch)
{
m_minerTxPrefix.assign(begin, end);
m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch;
}
void xmrig::Job::setExtraNonceInMinerTx(uint32_t extra_nonce)
{
memcpy(m_minerTxPrefix.data() + m_minerTxExtraNonceOffset, &extra_nonce, std::min(m_minerTxExtraNonceSize, sizeof(uint32_t)));
}
void xmrig::Job::generateSignatureData(String &signatureData) const
{
uint8_t* eph_public_key = m_minerTxPrefix.data() + m_minerTxEphPubKeyOffset;
uint8_t* txkey_pub = m_minerTxPrefix.data() + m_minerTxPubKeyOffset;
uint8_t txkey_sec[32];
generate_keys(txkey_pub, txkey_sec);
uint8_t derivation[32];
generate_key_derivation(m_viewPublicKey, txkey_sec, derivation);
derive_public_key(derivation, 0, m_spendPublicKey, eph_public_key);
uint8_t buf[32 * 3] = {};
memcpy(buf, txkey_pub, 32);
memcpy(buf + 32, eph_public_key, 32);
generate_key_derivation(txkey_pub, m_viewSecretKey, derivation);
derive_secret_key(derivation, 0, m_spendSecretKey, buf + 64);
signatureData = Cvt::toHex(buf, sizeof(buf));
}
void xmrig::Job::generateHashingBlob(String &blob) const
{
uint8_t root_hash[32];
const uint8_t* p = m_minerTxPrefix.data();
BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash);
uint64_t root_hash_offset = nonceOffset() + nonceSize();
if (m_hasMinerSignature) {
root_hash_offset += BlockTemplate::SIGNATURE_SIZE + 2 /* vote */;
}
blob = rawBlob();
Cvt::toHex(blob.data() + root_hash_offset * 2, 64, root_hash, BlockTemplate::HASH_SIZE);
}
#else
void xmrig::Job::generateMinerSignature(const uint8_t* blob, size_t size, uint8_t* out_sig) const
{
uint8_t tmp[kMaxBlobSize];
memcpy(tmp, blob, size);
// Fill signature with zeros
memset(tmp + nonceOffset() + nonceSize(), 0, BlockTemplate::SIGNATURE_SIZE);
uint8_t prefix_hash[32];
xmrig::keccak(tmp, static_cast<int>(size), prefix_hash, sizeof(prefix_hash));
xmrig::generate_signature(prefix_hash, m_ephPublicKey, m_ephSecretKey, out_sig);
}
#endif

View File

@@ -7,8 +7,8 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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
@@ -63,6 +63,7 @@ public:
bool setSeedHash(const char *hash);
bool setTarget(const char *target);
void setDiff(uint64_t diff);
void setSigKey(const char *sig_key);
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return (m_size > 0 && m_diff > 0) || !m_poolWallet.isEmpty(); }
@@ -82,7 +83,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 nonceMask() const { return isNicehash() ? 0xFFFFFFULL : (nonceSize() == sizeof(uint64_t) ? (static_cast<uint64_t>(-1LL) >> (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); }
@@ -102,6 +103,7 @@ public:
inline const char *rawBlob() const { return m_rawBlob; }
inline const char *rawTarget() const { return m_rawTarget; }
inline const String &rawSeedHash() const { return m_rawSeedHash; }
inline const String &rawSigKey() const { return m_rawSigKey; }
# endif
static inline uint64_t toDiff(uint64_t target) { return target ? (0xFFFFFFFFFFFFFFFFULL / target) : 0; }
@@ -116,6 +118,29 @@ public:
inline void setBenchSize(uint32_t size) { m_benchSize = size; }
# endif
# ifdef XMRIG_PROXY_PROJECT
void setSpendSecretKey(const uint8_t* key);
void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer& minerTxMerkleTreeBranch);
void setExtraNonceInMinerTx(uint32_t extra_nonce);
void generateSignatureData(String& signatureData) const;
void generateHashingBlob(String& blob) const;
# else
inline const uint8_t* ephSecretKey() const { return m_hasMinerSignature ? m_ephSecretKey : nullptr; }
inline void setEphemeralKeys(const uint8_t *pub_key, const uint8_t *sec_key)
{
m_hasMinerSignature = true;
memcpy(m_ephPublicKey, pub_key, sizeof(m_ephSecretKey));
memcpy(m_ephSecretKey, sec_key, sizeof(m_ephSecretKey));
}
void generateMinerSignature(const uint8_t* blob, size_t size, uint8_t* out_sig) const;
# endif
inline bool hasMinerSignature() const { return m_hasMinerSignature; }
uint32_t getNumTransactions() const;
private:
void copy(const Job &other);
void move(Job &&other);
@@ -139,8 +164,27 @@ private:
char m_rawBlob[kMaxBlobSize * 2 + 8]{};
char m_rawTarget[24]{};
String m_rawSeedHash;
String m_rawSigKey;
// Miner signatures
uint8_t m_spendSecretKey[32]{};
uint8_t m_viewSecretKey[32]{};
uint8_t m_spendPublicKey[32]{};
uint8_t m_viewPublicKey[32]{};
mutable Buffer m_minerTxPrefix;
size_t m_minerTxEphPubKeyOffset = 0;
size_t m_minerTxPubKeyOffset = 0;
size_t m_minerTxExtraNonceOffset = 0;
size_t m_minerTxExtraNonceSize = 0;
Buffer m_minerTxMerkleTreeBranch;
# else
// Miner signatures
uint8_t m_ephPublicKey[32]{};
uint8_t m_ephSecretKey[32]{};
# endif
bool m_hasMinerSignature = false;
# ifdef XMRIG_FEATURE_BENCHMARK
uint32_t m_benchSize = 0;
# endif

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -22,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/net/stratum/NetworkState.h"
#include "3rdparty/rapidjson/document.h"
#include "base/io/log/Log.h"
@@ -196,7 +189,7 @@ void xmrig::NetworkState::printConnection() const
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());
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") WHITE_BOLD("%s"), "algorithm", m_algorithm.name());
printDiff(m_diff);
printLatency(latency());
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-17s") CYAN_BOLD("%" PRIu64 "s"), "connection time", connectionTime() / 1000);

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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

@@ -1,7 +1,7 @@
/* XMRig
* Copyright (c) 2019 Howard Chu <https://github.com/hyc>
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -17,7 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <cstring>
#include <cstdlib>
@@ -66,6 +65,7 @@ const char *Pool::kAlgo = "algo";
const char *Pool::kCoin = "coin";
const char *Pool::kDaemon = "daemon";
const char *Pool::kDaemonPollInterval = "daemon-poll-interval";
const char *Pool::kDaemonZMQPort = "daemon-zmq-port";
const char *Pool::kEnabled = "enabled";
const char *Pool::kFingerprint = "tls-fingerprint";
const char *Pool::kKeepalive = "keepalive";
@@ -78,6 +78,7 @@ const char *Pool::kSubmitToOrigin = "submit-to-origin";
const char *Pool::kTls = "tls";
const char *Pool::kUrl = "url";
const char *Pool::kUser = "user";
const char *Pool::kSpendSecretKey = "spend-secret-key";
const char *Pool::kNicehashHost = "nicehash.com";
@@ -92,12 +93,13 @@ xmrig::Pool::Pool(const char *url) :
}
xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls, Mode mode) :
xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, Mode mode) :
m_keepAlive(keepAlive),
m_mode(mode),
m_flags(1 << FLAG_ENABLED),
m_password(password),
m_user(user),
m_spendSecretKey(spendSecretKey),
m_pollInterval(kDefaultPollInterval),
m_url(host, port, tls)
{
@@ -115,15 +117,17 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
return;
}
m_user = Json::getString(object, kUser);
m_password = Json::getString(object, kPass);
m_rigId = Json::getString(object, kRigId);
m_fingerprint = Json::getString(object, kFingerprint);
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
m_algorithm = Json::getString(object, kAlgo);
m_coin = Json::getString(object, kCoin);
m_daemon = Json::getString(object, kSelfSelect);
m_proxy = Json::getValue(object, kSOCKS5);
m_user = Json::getString(object, kUser);
m_spendSecretKey = Json::getString(object, kSpendSecretKey);
m_password = Json::getString(object, kPass);
m_rigId = Json::getString(object, kRigId);
m_fingerprint = Json::getString(object, kFingerprint);
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
m_algorithm = Json::getString(object, kAlgo);
m_coin = Json::getString(object, kCoin);
m_daemon = Json::getString(object, kSelfSelect);
m_proxy = Json::getValue(object, kSOCKS5);
m_zmqPort = Json::getInt(object, kDaemonZMQPort, m_zmqPort);
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash) || m_url.host().contains(kNicehashHost));
@@ -270,6 +274,10 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
obj.AddMember(StringRef(kUrl), url().toJSON(), allocator);
obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator);
if (!m_spendSecretKey.isEmpty()) {
obj.AddMember(StringRef(kSpendSecretKey), m_spendSecretKey.toJSON(), allocator);
}
if (m_mode != MODE_DAEMON) {
obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator);
obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator);
@@ -294,6 +302,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
if (m_mode == MODE_DAEMON) {
obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator);
obj.AddMember(StringRef(kDaemonZMQPort), m_zmqPort, allocator);
}
else {
obj.AddMember(StringRef(kSelfSelect), m_daemon.url().toJSON(), allocator);
@@ -312,7 +321,7 @@ std::string xmrig::Pool::printableName() const
out += std::string(" coin ") + WHITE_BOLD_S + m_coin.name() + CLEAR;
}
else {
out += std::string(" algo ") + WHITE_BOLD_S + (m_algorithm.isValid() ? m_algorithm.shortName() : "auto") + CLEAR;
out += std::string(" algo ") + WHITE_BOLD_S + (m_algorithm.isValid() ? m_algorithm.name() : "auto") + CLEAR;
}
if (m_mode == MODE_SELF_SELECT) {
@@ -329,6 +338,9 @@ void xmrig::Pool::print() const
LOG_NOTICE("url: %s", url().data());
LOG_DEBUG ("host: %s", host().data());
LOG_DEBUG ("port: %d", static_cast<int>(port()));
if (m_zmqPort >= 0) {
LOG_DEBUG("zmq-port: %d", m_zmqPort);
}
LOG_DEBUG ("user: %s", m_user.data());
LOG_DEBUG ("pass: %s", m_password.data());
LOG_DEBUG ("rig-id %s", m_rigId.data());

View File

@@ -1,7 +1,7 @@
/* XMRig
* Copyright (c) 2019 Howard Chu <https://github.com/hyc>
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -71,6 +71,8 @@ public:
static const char *kTls;
static const char *kUrl;
static const char *kUser;
static const char* kSpendSecretKey;
static const char* kDaemonZMQPort;
static const char *kNicehashHost;
constexpr static int kKeepAliveTimeout = 60;
@@ -78,7 +80,7 @@ public:
constexpr static uint64_t kDefaultPollInterval = 1000;
Pool() = default;
Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls, Mode mode);
Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, Mode mode);
Pool(const char *url);
Pool(const rapidjson::Value &object);
@@ -101,10 +103,12 @@ public:
inline const String &rigId() const { return m_rigId; }
inline const String &url() const { return m_url.url(); }
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
inline const String &spendSecretKey() const { return m_spendSecretKey; }
inline const Url &daemon() const { return m_daemon; }
inline int keepAlive() const { return m_keepAlive; }
inline Mode mode() const { return m_mode; }
inline uint16_t port() const { return m_url.port(); }
inline int zmq_port() const { return m_zmqPort; }
inline uint64_t pollInterval() const { return m_pollInterval; }
inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; }
inline void setPassword(const String &password) { m_password = password; }
@@ -149,9 +153,11 @@ private:
String m_password;
String m_rigId;
String m_user;
String m_spendSecretKey;
uint64_t m_pollInterval = kDefaultPollInterval;
Url m_daemon;
Url m_url;
int m_zmqPort = -1;
# ifdef XMRIG_FEATURE_BENCHMARK
std::shared_ptr<BenchConfig> m_benchmark;

View File

@@ -57,6 +57,12 @@ public:
Pools();
# ifdef XMRIG_FEATURE_BENCHMARK
inline bool isBenchmark() const { return !!m_benchmark; }
# else
inline constexpr static bool isBenchmark() { return false; }
# endif
inline const std::vector<Pool> &data() const { return m_data; }
inline int retries() const { return m_retries; }
inline int retryPause() const { return m_retryPause; }

View File

@@ -61,7 +61,8 @@ xmrig::BenchClient::BenchClient(const std::shared_ptr<BenchConfig> &benchmark, I
# ifdef XMRIG_FEATURE_HTTP
if (m_benchmark->isSubmit()) {
m_mode = ONLINE_BENCH;
m_mode = ONLINE_BENCH;
m_token = m_benchmark->token();
return;
}
@@ -262,7 +263,7 @@ void xmrig::BenchClient::start()
tag(),
size < 1000000 ? size / 1000 : size / 1000000,
size < 1000000 ? "K" : "M",
m_job.algorithm().shortName());
m_job.algorithm().name());
m_listener->onLoginSuccess(this);
m_listener->onJobReceived(this, m_job, rapidjson::Value());
@@ -334,6 +335,7 @@ void xmrig::BenchClient::send(Request request)
{
doc.AddMember(StringRef(BenchConfig::kSize), m_benchmark->size(), allocator);
doc.AddMember(StringRef(BenchConfig::kAlgo), m_benchmark->algorithm().toJSON(), allocator);
doc.AddMember(StringRef(BenchConfig::kUser), m_benchmark->user().toJSON(), allocator);
doc.AddMember("version", APP_VERSION, allocator);
doc.AddMember("threads", m_threads, allocator);
doc.AddMember("steady_ready_ts", m_readyTime, allocator);
@@ -349,6 +351,11 @@ void xmrig::BenchClient::send(Request request)
# endif
FetchRequest req(HTTP_POST, m_ip, BenchConfig::kApiPort, "/1/benchmark", doc, BenchConfig::kApiTLS, true);
if (!m_token.isEmpty()) {
req.headers.insert({ "Authorization", fmt::format("Bearer {}", m_token)});
}
fetch(tag(), std::move(req), m_httpListener);
}
break;

View File

@@ -41,6 +41,7 @@ const char *BenchConfig::kSeed = "seed";
const char *BenchConfig::kSize = "size";
const char *BenchConfig::kSubmit = "submit";
const char *BenchConfig::kToken = "token";
const char *BenchConfig::kUser = "user";
const char *BenchConfig::kVerify = "verify";
#ifndef XMRIG_DEBUG_BENCHMARK_API
@@ -59,8 +60,8 @@ xmrig::BenchConfig::BenchConfig(uint32_t size, const String &id, const rapidjson
m_id(id),
m_seed(Json::getString(object, kSeed)),
m_token(Json::getString(object, kToken)),
m_size(size),
m_hash(0)
m_user(Json::getString(object, kUser)),
m_size(size)
{
if (!m_algorithm.isValid() || m_algorithm.family() != Algorithm::RANDOM_X) {
m_algorithm = Algorithm::RX_0;
@@ -111,6 +112,7 @@ rapidjson::Value xmrig::BenchConfig::toJSON(rapidjson::Document &doc) const
out.AddMember(StringRef(kVerify), m_id.toJSON(), allocator);
out.AddMember(StringRef(kToken), m_token.toJSON(), allocator);
out.AddMember(StringRef(kSeed), m_seed.toJSON(), allocator);
out.AddMember(StringRef(kUser), m_user.toJSON(), allocator);
if (m_hash) {
out.AddMember(StringRef(kHash), Value(fmt::format("{:016X}", m_hash).c_str(), allocator), allocator);

View File

@@ -39,6 +39,7 @@ public:
static const char *kSize;
static const char *kSubmit;
static const char *kToken;
static const char *kUser;
static const char *kVerify;
# ifndef XMRIG_DEBUG_BENCHMARK_API
@@ -59,6 +60,7 @@ public:
inline const String &id() const { return m_id; }
inline const String &seed() const { return m_seed; }
inline const String &token() const { return m_token; }
inline const String &user() const { return m_user; }
inline uint32_t size() const { return m_size; }
inline uint64_t hash() const { return m_hash; }
@@ -73,8 +75,9 @@ private:
String m_id;
String m_seed;
String m_token;
String m_user;
uint32_t m_size;
uint64_t m_hash;
uint64_t m_hash = 0;
};

37
src/base/tools/bswap_64.h Normal file
View File

@@ -0,0 +1,37 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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_BSWAP_64_H
#define XMRIG_BSWAP_64_H
#ifdef _MSC_VER
#include <stdlib.h>
#define bswap_64(x) _byteswap_uint64(x)
#elif defined __GNUC__
#define bswap_64(x) __builtin_bswap64(x)
#else
#include <byteswap.h>
#endif
#endif /* XMRIG_BSWAP_64_H */

View File

@@ -0,0 +1,104 @@
/* XMRig
* Copyright 2012-2013 The Cryptonote developers
* Copyright 2014-2021 The Monero Project
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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_BLOBREADER_H
#define XMRIG_BLOBREADER_H
#include <cstdint>
namespace xmrig {
class CBlobReader
{
public:
inline CBlobReader(const void* data, size_t size)
: m_data(reinterpret_cast<const uint8_t*>(data))
, m_size(size)
, m_index(0)
{}
inline bool operator()(uint8_t& data) { return getByte(data); }
inline bool operator()(uint64_t& data) { return getVarint(data); }
template<size_t N>
inline bool operator()(uint8_t(&data)[N])
{
for (size_t i = 0; i < N; ++i) {
if (!getByte(data[i])) {
return false;
}
}
return true;
}
template<typename T>
inline void readItems(T& data, size_t count)
{
data.resize(count);
for (size_t i = 0; i < count; ++i)
operator()(data[i]);
}
inline size_t index() const { return m_index; }
inline void skip(size_t N) { m_index += N; }
private:
inline bool getByte(uint8_t& data)
{
if (m_index >= m_size) {
return false;
}
data = m_data[m_index++];
return true;
}
inline bool getVarint(uint64_t& data)
{
uint64_t result = 0;
uint8_t t;
int shift = 0;
do {
if (!getByte(t)) {
return false;
}
result |= static_cast<uint64_t>(t & 0x7F) << shift;
shift += 7;
} while (t & 0x80);
data = result;
return true;
}
const uint8_t* m_data;
size_t m_size;
size_t m_index;
};
} /* namespace xmrig */
#endif /* XMRIG_BLOBREADER_H */

View File

@@ -0,0 +1,260 @@
/* XMRig
* Copyright 2012-2013 The Cryptonote developers
* Copyright 2014-2021 The Monero Project
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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/crypto/keccak.h"
#include "base/tools/Cvt.h"
#include "base/tools/cryptonote/BlobReader.h"
#include "base/tools/cryptonote/BlockTemplate.h"
namespace xmrig {
bool BlockTemplate::Init(const String& blockTemplate, Coin coin)
{
raw_blob = Cvt::fromHex(blockTemplate);
CBlobReader ar(raw_blob.data(), raw_blob.size());
// Block header
ar(major_version);
ar(minor_version);
ar(timestamp);
ar(prev_id);
ar(nonce);
// Wownero block template has miner signature starting from version 18
has_miner_signature = (coin == Coin::WOWNERO) && (major_version >= 18);
if (has_miner_signature) {
ar(miner_signature);
ar(vote);
}
// Miner transaction begin
// Prefix begin
miner_tx_prefix_begin_index = ar.index();
ar(tx_version);
ar(unlock_time);
ar(num_inputs);
// must be 1 input
if (num_inputs != 1)
return false;
ar(input_type);
// input type must be txin_gen (0xFF)
if (input_type != 0xFF)
return false;
ar(height);
ar(num_outputs);
// must be 1 output
if (num_outputs != 1)
return false;
ar(amount);
ar(output_type);
// output type must be txout_to_key (2)
if (output_type != 2)
return false;
eph_public_key_index = ar.index();
ar(eph_public_key);
ar(extra_size);
const uint64_t tx_extra_index = ar.index();
ar.readItems(extra, extra_size);
CBlobReader ar_extra(extra.data(), extra_size);
tx_extra_nonce_size = 0;
tx_extra_nonce_index = 0;
while (ar_extra.index() < extra_size) {
uint64_t extra_tag = 0;
ar_extra(extra_tag);
switch (extra_tag) {
case 0x01: // TX_EXTRA_TAG_PUBKEY
tx_pubkey_index = tx_extra_index + ar_extra.index();
ar_extra.skip(KEY_SIZE);
break;
case 0x02: // TX_EXTRA_NONCE
ar_extra(tx_extra_nonce_size);
tx_extra_nonce_index = tx_extra_index + ar_extra.index();
ar_extra.skip(tx_extra_nonce_size);
break;
default:
return false; // TODO: handle other tags
}
}
miner_tx_prefix_end_index = ar.index();
// Prefix end
// RCT signatures (empty in miner transaction)
ar(vin_rct_type);
// must be RCTTypeNull (0)
if (vin_rct_type != 0)
return false;
const size_t miner_tx_end = ar.index();
// Miner transaction end
// Miner transaction must have exactly 1 byte with value 0 after the prefix
if ((miner_tx_end != miner_tx_prefix_end_index + 1) || (raw_blob[miner_tx_prefix_end_index] != 0))
return false;
// Other transaction hashes
ar(num_hashes);
# ifdef XMRIG_PROXY_PROJECT
hashes.resize((num_hashes + 1) * HASH_SIZE);
CalculateMinerTxHash(raw_blob.data() + miner_tx_prefix_begin_index, raw_blob.data() + miner_tx_prefix_end_index, hashes.data());
for (uint64_t i = 1; i <= num_hashes; ++i) {
uint8_t h[HASH_SIZE];
ar(h);
memcpy(hashes.data() + i * HASH_SIZE, h, HASH_SIZE);
}
CalculateMerkleTreeHash();
# endif
return true;
}
void BlockTemplate::CalculateMinerTxHash(const uint8_t* prefix_begin, const uint8_t* prefix_end, uint8_t* hash)
{
uint8_t hashes[HASH_SIZE * 3];
// Calculate 3 partial hashes
// 1. Prefix
keccak(prefix_begin, static_cast<int>(prefix_end - prefix_begin), hashes, HASH_SIZE);
// 2. Base RCT, single 0 byte in miner tx
static const uint8_t known_second_hash[HASH_SIZE] = {
188,54,120,158,122,30,40,20,54,70,66,41,130,143,129,125,102,18,247,180,119,214,101,145,255,150,169,224,100,188,201,138
};
memcpy(hashes + HASH_SIZE, known_second_hash, HASH_SIZE);
// 3. Prunable RCT, empty in miner tx
memset(hashes + HASH_SIZE * 2, 0, HASH_SIZE);
// Calculate miner transaction hash
keccak(hashes, sizeof(hashes), hash, HASH_SIZE);
}
void BlockTemplate::CalculateMerkleTreeHash()
{
miner_tx_merkle_tree_branch.clear();
const uint64_t count = num_hashes + 1;
uint8_t* h = hashes.data();
if (count == 1) {
memcpy(root_hash, h, HASH_SIZE);
}
else if (count == 2) {
miner_tx_merkle_tree_branch.insert(miner_tx_merkle_tree_branch.end(), h + HASH_SIZE, h + HASH_SIZE * 2);
keccak(h, HASH_SIZE * 2, root_hash, HASH_SIZE);
}
else {
size_t i, j, cnt;
for (i = 0, cnt = 1; cnt <= count; ++i, cnt <<= 1) {}
cnt >>= 1;
miner_tx_merkle_tree_branch.reserve(HASH_SIZE * (i - 1));
Buffer ints(cnt * HASH_SIZE);
memcpy(ints.data(), h, (cnt * 2 - count) * HASH_SIZE);
for (i = cnt * 2 - count, j = cnt * 2 - count; j < cnt; i += 2, ++j) {
if (i == 0) {
miner_tx_merkle_tree_branch.insert(miner_tx_merkle_tree_branch.end(), h + HASH_SIZE, h + HASH_SIZE * 2);
}
keccak(h + i * HASH_SIZE, HASH_SIZE * 2, ints.data() + j * HASH_SIZE, HASH_SIZE);
}
while (cnt > 2) {
cnt >>= 1;
for (i = 0, j = 0; j < cnt; i += 2, ++j) {
if (i == 0) {
miner_tx_merkle_tree_branch.insert(miner_tx_merkle_tree_branch.end(), ints.data() + HASH_SIZE, ints.data() + HASH_SIZE * 2);
}
keccak(ints.data() + i * HASH_SIZE, HASH_SIZE * 2, ints.data() + j * HASH_SIZE, HASH_SIZE);
}
}
miner_tx_merkle_tree_branch.insert(miner_tx_merkle_tree_branch.end(), ints.data() + HASH_SIZE, ints.data() + HASH_SIZE * 2);
keccak(ints.data(), HASH_SIZE * 2, root_hash, HASH_SIZE);
}
}
void BlockTemplate::CalculateRootHash(const uint8_t* prefix_begin, const uint8_t* prefix_end, const Buffer& miner_tx_merkle_tree_branch, uint8_t* root_hash)
{
CalculateMinerTxHash(prefix_begin, prefix_end, root_hash);
for (size_t i = 0; i < miner_tx_merkle_tree_branch.size(); i += HASH_SIZE) {
uint8_t h[HASH_SIZE * 2];
memcpy(h, root_hash, HASH_SIZE);
memcpy(h + HASH_SIZE, miner_tx_merkle_tree_branch.data() + i, HASH_SIZE);
keccak(h, HASH_SIZE * 2, root_hash, HASH_SIZE);
}
}
void BlockTemplate::GenerateHashingBlob()
{
hashingBlob.clear();
hashingBlob.reserve(miner_tx_prefix_begin_index + HASH_SIZE + 3);
hashingBlob.assign(raw_blob.begin(), raw_blob.begin() + miner_tx_prefix_begin_index);
hashingBlob.insert(hashingBlob.end(), root_hash, root_hash + HASH_SIZE);
uint64_t k = num_hashes + 1;
while (k >= 0x80) {
hashingBlob.emplace_back((static_cast<uint8_t>(k) & 0x7F) | 0x80);
k >>= 7;
}
hashingBlob.emplace_back(static_cast<uint8_t>(k));
}
} /* namespace xmrig */

View File

@@ -0,0 +1,96 @@
/* XMRig
* Copyright 2012-2013 The Cryptonote developers
* Copyright 2014-2021 The Monero Project
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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_BLOCKTEMPLATE_H
#define XMRIG_BLOCKTEMPLATE_H
#include "base/crypto/Coin.h"
#include "base/tools/Buffer.h"
#include "base/tools/String.h"
namespace xmrig {
struct BlockTemplate
{
enum {
HASH_SIZE = 32,
KEY_SIZE = 32,
SIGNATURE_SIZE = 64,
NONCE_SIZE = 4,
};
Buffer raw_blob;
size_t eph_public_key_index;
size_t tx_pubkey_index;
uint64_t tx_extra_nonce_size;
size_t tx_extra_nonce_index;
size_t miner_tx_prefix_begin_index;
size_t miner_tx_prefix_end_index;
// Block header
uint8_t major_version;
uint8_t minor_version;
uint64_t timestamp;
uint8_t prev_id[HASH_SIZE];
uint8_t nonce[NONCE_SIZE];
bool has_miner_signature;
uint8_t miner_signature[SIGNATURE_SIZE];
uint8_t vote[2];
// Miner tx
uint64_t tx_version;
uint64_t unlock_time;
uint64_t num_inputs;
uint8_t input_type;
uint64_t height;
uint64_t num_outputs;
uint64_t amount;
uint8_t output_type;
uint8_t eph_public_key[KEY_SIZE];
uint64_t extra_size;
Buffer extra;
uint8_t vin_rct_type;
// Transaction hashes
uint64_t num_hashes;
Buffer hashes;
Buffer miner_tx_merkle_tree_branch;
uint8_t root_hash[HASH_SIZE];
Buffer hashingBlob;
bool Init(const String& blockTemplate, Coin coin);
static void CalculateMinerTxHash(const uint8_t* prefix_begin, const uint8_t* prefix_end, uint8_t* hash);
static void CalculateRootHash(const uint8_t* prefix_begin, const uint8_t* prefix_end, const Buffer& miner_tx_merkle_tree_branch, uint8_t* root_hash);
void CalculateMerkleTreeHash();
void GenerateHashingBlob();
};
} /* namespace xmrig */
#endif /* XMRIG_BLOCKTEMPLATE_H */

View File

@@ -0,0 +1,233 @@
/* XMRig
* Copyright 2012-2013 The Cryptonote developers
* Copyright 2014-2021 The Monero Project
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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/crypto/keccak.h"
#include "base/tools/cryptonote/Signatures.h"
extern "C" {
#include "base/tools/cryptonote/crypto-ops.h"
}
#include "base/tools/Cvt.h"
#ifdef XMRIG_PROXY_PROJECT
#define PROFILE_SCOPE(x)
#else
#include "crypto/rx/Profiler.h"
#endif
struct ec_scalar { char data[32]; };
struct hash { char data[32]; };
struct ec_point { char data[32]; };
struct signature { ec_scalar c, r; };
struct s_comm { hash h; ec_point key; ec_point comm; };
static inline void random_scalar(ec_scalar& res)
{
// Don't care about bias or possible 0 after reduce: probability ~10^-76, not happening in this universe.
// Performance matters more. It's a miner after all.
xmrig::Cvt::randomBytes(res.data, sizeof(res.data));
sc_reduce32((uint8_t*) res.data);
}
static void hash_to_scalar(const void* data, size_t length, ec_scalar& res)
{
xmrig::keccak((const uint8_t*) data, length, (uint8_t*) &res, sizeof(res));
sc_reduce32((uint8_t*) &res);
}
static void derivation_to_scalar(const uint8_t* derivation, size_t output_index, ec_scalar& res)
{
struct {
uint8_t derivation[32];
uint8_t output_index[(sizeof(size_t) * 8 + 6) / 7];
} buf;
uint8_t* end = buf.output_index;
memcpy(buf.derivation, derivation, sizeof(buf.derivation));
size_t k = output_index;
while (k >= 0x80) {
*(end++) = (static_cast<uint8_t>(k) & 0x7F) | 0x80;
k >>= 7;
}
*(end++) = static_cast<uint8_t>(k);
hash_to_scalar(&buf, end - reinterpret_cast<uint8_t*>(&buf), res);
}
namespace xmrig {
void generate_signature(const uint8_t* prefix_hash, const uint8_t* pub, const uint8_t* sec, uint8_t* sig_bytes)
{
PROFILE_SCOPE(GenerateSignature);
ge_p3 tmp3;
ec_scalar k;
s_comm buf;
memcpy(buf.h.data, prefix_hash, sizeof(buf.h.data));
memcpy(buf.key.data, pub, sizeof(buf.key.data));
signature& sig = *reinterpret_cast<signature*>(sig_bytes);
do {
random_scalar(k);
ge_scalarmult_base(&tmp3, (unsigned char*)&k);
ge_p3_tobytes((unsigned char*)&buf.comm, &tmp3);
hash_to_scalar(&buf, sizeof(s_comm), sig.c);
if (!sc_isnonzero((const unsigned char*)sig.c.data)) {
continue;
}
sc_mulsub((unsigned char*)&sig.r, (unsigned char*)&sig.c, sec, (unsigned char*)&k);
} while (!sc_isnonzero((const unsigned char*)sig.r.data));
}
bool check_signature(const uint8_t* prefix_hash, const uint8_t* pub, const uint8_t* sig_bytes)
{
ge_p2 tmp2;
ge_p3 tmp3;
ec_scalar c;
s_comm buf;
memcpy(buf.h.data, prefix_hash, sizeof(buf.h.data));
memcpy(buf.key.data, pub, sizeof(buf.key.data));
if (ge_frombytes_vartime(&tmp3, pub) != 0) {
return false;
}
const signature& sig = *reinterpret_cast<const signature*>(sig_bytes);
if (sc_check((const uint8_t*)&sig.c) != 0 || sc_check((const uint8_t*)&sig.r) != 0 || !sc_isnonzero((const uint8_t*)&sig.c)) {
return false;
}
ge_double_scalarmult_base_vartime(&tmp2, (const uint8_t*)&sig.c, &tmp3, (const uint8_t*)&sig.r);
ge_tobytes((uint8_t*)&buf.comm, &tmp2);
static const ec_point infinity = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
if (memcmp(&buf.comm, &infinity, 32) == 0) {
return false;
}
hash_to_scalar(&buf, sizeof(s_comm), c);
sc_sub((uint8_t*)&c, (uint8_t*)&c, (const uint8_t*)&sig.c);
return sc_isnonzero((uint8_t*)&c) == 0;
}
bool generate_key_derivation(const uint8_t* key1, const uint8_t* key2, uint8_t* derivation)
{
ge_p3 point;
ge_p2 point2;
ge_p1p1 point3;
if (ge_frombytes_vartime(&point, key1) != 0) {
return false;
}
ge_scalarmult(&point2, key2, &point);
ge_mul8(&point3, &point2);
ge_p1p1_to_p2(&point2, &point3);
ge_tobytes(derivation, &point2);
return true;
}
void derive_secret_key(const uint8_t* derivation, size_t output_index, const uint8_t* base, uint8_t* derived_key)
{
ec_scalar scalar;
derivation_to_scalar(derivation, output_index, scalar);
sc_add(derived_key, base, (uint8_t*) &scalar);
}
bool derive_public_key(const uint8_t* derivation, size_t output_index, const uint8_t* base, uint8_t* derived_key)
{
ec_scalar scalar;
ge_p3 point1;
ge_p3 point2;
ge_cached point3;
ge_p1p1 point4;
ge_p2 point5;
if (ge_frombytes_vartime(&point1, base) != 0) {
return false;
}
derivation_to_scalar(derivation, output_index, scalar);
ge_scalarmult_base(&point2, (uint8_t*) &scalar);
ge_p3_to_cached(&point3, &point2);
ge_add(&point4, &point1, &point3);
ge_p1p1_to_p2(&point5, &point4);
ge_tobytes(derived_key, &point5);
return true;
}
void derive_view_secret_key(const uint8_t* spend_secret_key, uint8_t* view_secret_key)
{
keccak(spend_secret_key, 32, view_secret_key, 32);
sc_reduce32(view_secret_key);
}
void generate_keys(uint8_t* pub, uint8_t* sec)
{
random_scalar(*((ec_scalar*)sec));
ge_p3 point;
ge_scalarmult_base(&point, sec);
ge_p3_tobytes(pub, &point);
}
bool secret_key_to_public_key(const uint8_t* sec, uint8_t* pub)
{
if (sc_check(sec) != 0) {
return false;
}
ge_p3 point;
ge_scalarmult_base(&point, sec);
ge_p3_tobytes(pub, &point);
return true;
}
} /* namespace xmrig */

View File

@@ -0,0 +1,46 @@
/* XMRig
* Copyright 2012-2013 The Cryptonote developers
* Copyright 2014-2021 The Monero Project
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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_SIGNATURES_H
#define XMRIG_SIGNATURES_H
#include <cstdint>
namespace xmrig {
void generate_signature(const uint8_t* prefix_hash, const uint8_t* pub, const uint8_t* sec, uint8_t* sig);
bool check_signature(const uint8_t* prefix_hash, const uint8_t* pub, const uint8_t* sig);
bool generate_key_derivation(const uint8_t* key1, const uint8_t* key2, uint8_t* derivation);
void derive_secret_key(const uint8_t* derivation, size_t output_index, const uint8_t* base, uint8_t* derived_key);
bool derive_public_key(const uint8_t* derivation, size_t output_index, const uint8_t* base, uint8_t* derived_key);
void derive_view_secret_key(const uint8_t* spend_secret_key, uint8_t* view_secret_key);
void generate_keys(uint8_t* pub, uint8_t* sec);
bool secret_key_to_public_key(const uint8_t* sec, uint8_t* pub);
} /* namespace xmrig */
#endif /* XMRIG_SIGNATURES_H */

View File

@@ -0,0 +1,114 @@
/* XMRig
* Copyright 2012-2013 The Cryptonote developers
* Copyright 2014-2021 The Monero Project
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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/crypto/keccak.h"
#include "base/tools/cryptonote/BlobReader.h"
#include "base/tools/cryptonote/WalletAddress.h"
#include "base/tools/cryptonote/umul128.h"
#include "base/tools/Buffer.h"
#include <array>
namespace xmrig {
bool WalletAddress::Decode(const String& address)
{
static constexpr std::array<int, 9> block_sizes{ 0, 2, 3, 5, 6, 7, 9, 10, 11 };
static constexpr char alphabet[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
constexpr size_t alphabet_size = sizeof(alphabet) - 1;
int8_t reverse_alphabet[256];
memset(reverse_alphabet, -1, sizeof(reverse_alphabet));
for (size_t i = 0; i < alphabet_size; ++i) {
reverse_alphabet[static_cast<int>(alphabet[i])] = i;
}
const int len = static_cast<int>(address.size());
const int num_full_blocks = len / block_sizes.back();
const int last_block_size = len % block_sizes.back();
int last_block_size_index = -1;
for (size_t i = 0; i < block_sizes.size(); ++i) {
if (block_sizes[i] == last_block_size) {
last_block_size_index = i;
break;
}
}
if (last_block_size_index < 0) {
return false;
}
Buffer data;
data.reserve(static_cast<size_t>(num_full_blocks) * sizeof(uint64_t) + last_block_size_index);
const char* address_data = address.data();
for (int i = 0; i <= num_full_blocks; ++i) {
uint64_t num = 0;
uint64_t order = 1;
for (int j = ((i < num_full_blocks) ? block_sizes.back() : last_block_size) - 1; j >= 0; --j) {
const int digit = reverse_alphabet[static_cast<int>(address_data[j])];
if (digit < 0) {
return false;
}
uint64_t hi;
const uint64_t tmp = num + __umul128(order, static_cast<uint64_t>(digit), &hi);
if ((tmp < num) || hi) {
return false;
}
num = tmp;
order *= alphabet_size;
}
address_data += block_sizes.back();
uint8_t* p = reinterpret_cast<uint8_t*>(&num);
for (int j = ((i < num_full_blocks) ? sizeof(num) : last_block_size_index) - 1; j >= 0; --j) {
data.emplace_back(p[j]);
}
}
CBlobReader ar(data.data(), data.size());
ar(tag);
ar(public_spend_key);
ar(public_view_key);
ar(checksum);
uint8_t md[200];
keccak(data.data(), data.size() - sizeof(checksum), md);
if (memcmp(checksum, md, sizeof(checksum)) != 0) {
return false;
}
return true;
}
} /* namespace xmrig */

View File

@@ -0,0 +1,45 @@
/* XMRig
* Copyright 2012-2013 The Cryptonote developers
* Copyright 2014-2021 The Monero Project
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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_WALLETADDRESS_H
#define XMRIG_WALLETADDRESS_H
#include "base/tools/String.h"
namespace xmrig {
struct WalletAddress
{
uint64_t tag;
uint8_t public_spend_key[32];
uint8_t public_view_key[32];
uint8_t checksum[4];
bool Decode(const String& address);
};
} /* namespace xmrig */
#endif /* XMRIG_WALLETADDRESS_H */

View File

@@ -0,0 +1,879 @@
// Copyright (c) 2014-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <stdint.h>
#include "crypto-ops.h"
/* sqrt(x) is such an integer y that 0 <= y <= p - 1, y % 2 = 0, and y^2 = x (mod p). */
/* d = -121665 / 121666 */
const fe fe_d = {-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116}; /* d */
const fe fe_sqrtm1 = {-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482}; /* sqrt(-1) */
const fe fe_d2 = {-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199}; /* 2 * d */
/* base[i][j] = (j+1)*256^i*B */
const ge_precomp ge_base[32][8] = {
{
{{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}},
{{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303},
{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081},
{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}},
{{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}},
{{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540},
{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397},
{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}},
{{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}},
{{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777},
{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737},
{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}},
{{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}},
{{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726},
{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955},
{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}}
}, {
{{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171},
{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510},
{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}},
{{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639},
{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963},
{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}},
{{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568},
{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335},
{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}},
{{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007},
{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772},
{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}},
{{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567},
{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686},
{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}},
{{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887},
{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954},
{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}},
{{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833},
{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532},
{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}},
{{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268},
{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214},
{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}}
}, {
{{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800},
{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645},
{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}},
{{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933},
{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182},
{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}},
{{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991},
{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880},
{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}},
{{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295},
{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788},
{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}},
{{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026},
{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347},
{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}},
{{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395},
{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278},
{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}},
{{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995},
{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596},
{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}},
{{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060},
{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608},
{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}}
}, {
{{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389},
{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016},
{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}},
{{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505},
{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553},
{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}},
{{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220},
{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631},
{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}},
{{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556},
{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749},
{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}},
{{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391},
{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253},
{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}},
{{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958},
{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082},
{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}},
{{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521},
{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807},
{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}},
{{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134},
{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455},
{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}}
}, {
{{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069},
{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746},
{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}},
{{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837},
{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906},
{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}},
{{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817},
{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098},
{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}},
{{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504},
{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727},
{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}},
{{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003},
{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605},
{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}},
{{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701},
{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683},
{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}},
{{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563},
{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260},
{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}},
{{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672},
{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686},
{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}}
}, {
{{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182},
{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277},
{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}},
{{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474},
{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539},
{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}},
{{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970},
{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756},
{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}},
{{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683},
{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655},
{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}},
{{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125},
{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839},
{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}},
{{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294},
{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899},
{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}},
{{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294},
{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949},
{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}},
{{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420},
{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940},
{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}}
}, {
{{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567},
{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127},
{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}},
{{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887},
{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964},
{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}},
{{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244},
{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999},
{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}},
{{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274},
{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236},
{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}},
{{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761},
{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884},
{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}},
{{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638},
{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490},
{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}},
{{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736},
{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124},
{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}},
{{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029},
{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048},
{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}}
}, {
{{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593},
{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071},
{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}},
{{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687},
{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441},
{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}},
{{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460},
{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007},
{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}},
{{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005},
{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674},
{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}},
{{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590},
{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957},
{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}},
{{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740},
{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122},
{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}},
{{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885},
{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140},
{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}},
{{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155},
{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260},
{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}}
}, {
{{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677},
{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815},
{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}},
{{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203},
{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208},
{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}},
{{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850},
{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389},
{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}},
{{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689},
{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880},
{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}},
{{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632},
{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412},
{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}},
{{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038},
{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232},
{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}},
{{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856},
{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738},
{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}},
{{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718},
{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697},
{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}}
}, {
{{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912},
{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358},
{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}},
{{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307},
{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977},
{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}},
{{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644},
{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616},
{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}},
{{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099},
{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341},
{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}},
{{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646},
{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425},
{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}},
{{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743},
{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822},
{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}},
{{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985},
{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702},
{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}},
{{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293},
{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100},
{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}}
}, {
{{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186},
{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610},
{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}},
{{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220},
{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025},
{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}},
{{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992},
{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027},
{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}},
{{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901},
{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952},
{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}},
{{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390},
{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730},
{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}},
{{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180},
{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272},
{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}},
{{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970},
{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772},
{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}},
{{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750},
{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373},
{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}}
}, {
{{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144},
{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195},
{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}},
{{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684},
{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518},
{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}},
{{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793},
{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794},
{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}},
{{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921},
{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518},
{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}},
{{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278},
{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024},
{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}},
{{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783},
{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717},
{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}},
{{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333},
{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048},
{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}},
{{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760},
{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757},
{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}}
}, {
{{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468},
{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184},
{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}},
{{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066},
{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882},
{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}},
{{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101},
{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279},
{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}},
{{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709},
{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714},
{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}},
{{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464},
{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847},
{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}},
{{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414},
{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158},
{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}},
{{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415},
{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459},
{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}},
{{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412},
{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743},
{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}}
}, {
{{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022},
{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429},
{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}},
{{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861},
{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000},
{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}},
{{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815},
{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642},
{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}},
{{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574},
{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742},
{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}},
{{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020},
{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772},
{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}},
{{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953},
{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218},
{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}},
{{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073},
{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325},
{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}},
{{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870},
{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863},
{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}}
}, {
{{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267},
{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663},
{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}},
{{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673},
{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943},
{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}},
{{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238},
{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064},
{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}},
{{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052},
{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904},
{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}},
{{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979},
{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841},
{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}},
{{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324},
{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940},
{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}},
{{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184},
{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114},
{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}},
{{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784},
{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091},
{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}}
}, {
{{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208},
{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864},
{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}},
{{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233},
{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212},
{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}},
{{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068},
{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397},
{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}},
{{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889},
{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038},
{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}},
{{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875},
{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905},
{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}},
{{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818},
{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714},
{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}},
{{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931},
{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024},
{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}},
{{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204},
{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817},
{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}}
}, {
{{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504},
{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768},
{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}},
{{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790},
{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438},
{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}},
{{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971},
{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905},
{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}},
{{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409},
{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499},
{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}},
{{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664},
{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324},
{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}},
{{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990},
{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914},
{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}},
{{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257},
{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433},
{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}},
{{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045},
{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093},
{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}}
}, {
{{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191},
{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507},
{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}},
{{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018},
{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109},
{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}},
{{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528},
{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625},
{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}},
{{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033},
{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866},
{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}},
{{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075},
{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347},
{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}},
{{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165},
{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588},
{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}},
{{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017},
{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883},
{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}},
{{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043},
{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663},
{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}}
}, {
{{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860},
{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466},
{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}},
{{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997},
{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295},
{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}},
{{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385},
{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109},
{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}},
{{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424},
{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185},
{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}},
{{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325},
{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593},
{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}},
{{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644},
{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801},
{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}},
{{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884},
{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577},
{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}},
{{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473},
{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644},
{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}}
}, {
{{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599},
{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768},
{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}},
{{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328},
{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369},
{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}},
{{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815},
{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025},
{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}},
{{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448},
{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981},
{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}},
{{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501},
{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073},
{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}},
{{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845},
{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211},
{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}},
{{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096},
{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803},
{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}},
{{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965},
{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505},
{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}}
}, {
{{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782},
{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900},
{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}},
{{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208},
{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232},
{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}},
{{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271},
{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326},
{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}},
{{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300},
{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570},
{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}},
{{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994},
{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913},
{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}},
{{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730},
{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096},
{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}},
{{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411},
{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905},
{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}},
{{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870},
{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498},
{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}}
}, {
{{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677},
{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647},
{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}},
{{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468},
{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375},
{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}},
{{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725},
{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612},
{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}},
{{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944},
{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928},
{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}},
{{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139},
{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963},
{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}},
{{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734},
{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680},
{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}},
{{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931},
{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654},
{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}},
{{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180},
{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684},
{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}}
}, {
{{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501},
{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413},
{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}},
{{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874},
{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962},
{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}},
{{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152},
{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063},
{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}},
{{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146},
{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183},
{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}},
{{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421},
{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622},
{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}},
{{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663},
{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753},
{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}},
{{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862},
{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118},
{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}},
{{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380},
{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824},
{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}}
}, {
{{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438},
{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584},
{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}},
{{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471},
{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610},
{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}},
{{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650},
{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369},
{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}},
{{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462},
{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793},
{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}},
{{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226},
{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019},
{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}},
{{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171},
{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132},
{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}},
{{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181},
{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210},
{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}},
{{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935},
{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105},
{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}}
}, {
{{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852},
{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581},
{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}},
{{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844},
{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025},
{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}},
{{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068},
{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192},
{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}},
{{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259},
{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426},
{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}},
{{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305},
{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832},
{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}},
{{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011},
{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447},
{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}},
{{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245},
{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859},
{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}},
{{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707},
{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848},
{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}}
}, {
{{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391},
{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215},
{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}},
{{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713},
{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849},
{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}},
{{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940},
{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031},
{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}},
{{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243},
{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116},
{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}},
{{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509},
{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883},
{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}},
{{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660},
{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273},
{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}},
{{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560},
{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135},
{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}},
{{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739},
{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756},
{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}}
}, {
{{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347},
{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028},
{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}},
{{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799},
{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609},
{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}},
{{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989},
{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523},
{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}},
{{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045},
{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377},
{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}},
{{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016},
{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426},
{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}},
{{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396},
{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080},
{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}},
{{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275},
{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074},
{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}},
{{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717},
{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101},
{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}}
}, {
{{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632},
{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415},
{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}},
{{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876},
{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625},
{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}},
{{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164},
{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595},
{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}},
{{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858},
{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193},
{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}},
{{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942},
{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635},
{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}},
{{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935},
{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415},
{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}},
{{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018},
{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778},
{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}},
{{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385},
{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503},
{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}}
}, {
{{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056},
{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838},
{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}},
{{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691},
{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118},
{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}},
{{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269},
{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904},
{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}},
{{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193},
{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910},
{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}},
{{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667},
{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481},
{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}},
{{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640},
{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278},
{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}},
{{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272},
{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012},
{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}},
{{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046},
{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345},
{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}}
}, {
{{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937},
{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636},
{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}},
{{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429},
{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576},
{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}},
{{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490},
{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104},
{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}},
{{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275},
{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511},
{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}},
{{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439},
{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939},
{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}},
{{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310},
{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608},
{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}},
{{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101},
{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418},
{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}},
{{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356},
{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996},
{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}}
}, {
{{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728},
{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658},
{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}},
{{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001},
{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766},
{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}},
{{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458},
{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628},
{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}},
{{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062},
{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616},
{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}},
{{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383},
{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814},
{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}},
{{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417},
{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222},
{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}},
{{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597},
{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970},
{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}},
{{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647},
{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511},
{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}}
}, {
{{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834},
{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461},
{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}},
{{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516},
{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547},
{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}},
{{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038},
{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741},
{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}},
{{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747},
{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323},
{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}},
{{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373},
{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228},
{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}},
{{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399},
{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831},
{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}},
{{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313},
{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958},
{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}},
{{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743},
{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684},
{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}}
}
};
const ge_precomp ge_Bi[8] = {
{{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}}, {{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}}, {{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}}, {{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}}, {{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877},
{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951},
{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}}, {{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436},
{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918},
{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}}, {{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800},
{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305},
{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}}, {{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876},
{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619},
{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}}
};
/* A = 2 * (1 - d) / (1 + d) = 486662 */
const fe fe_ma2 = {-12721188, -3529, 0, 0, 0, 0, 0, 0, 0, 0}; /* -A^2 */
const fe fe_ma = {-486662, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* -A */
const fe fe_fffb1 = {-31702527, -2466483, -26106795, -12203692, -12169197, -321052, 14850977, -10296299, -16929438, -407568}; /* sqrt(-2 * A * (A + 2)) */
const fe fe_fffb2 = {8166131, -6741800, -17040804, 3154616, 21461005, 1466302, -30876704, -6368709, 10503587, -13363080}; /* sqrt(2 * A * (A + 2)) */
const fe fe_fffb3 = {-13620103, 14639558, 4532995, 7679154, 16815101, -15883539, -22863840, -14813421, 13716513, -6477756}; /* sqrt(-sqrt(-1) * A * (A + 2)) */
const fe fe_fffb4 = {-21786234, -12173074, 21573800, 4524538, -4645904, 16204591, 8012863, -8444712, 3212926, 6885324}; /* sqrt(sqrt(-1) * A * (A + 2)) */
const ge_p3 ge_p3_identity = { {0}, {1, 0}, {1, 0}, {0} };
const ge_p3 ge_p3_H = {
{7329926, -15101362, 31411471, 7614783, 27996851, -3197071, -11157635, -6878293, 466949, -7986503},
{5858699, 5096796, 21321203, -7536921, -5553480, -11439507, -5627669, 15045946, 19977121, 5275251},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{23443568, -5110398, -8776029, -4345135, 6889568, -14710814, 7474843, 3279062, 14550766, -7453428}
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
// Copyright (c) 2014-2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
/* From fe.h */
typedef int32_t fe[10];
/* From ge.h */
typedef struct {
fe X;
fe Y;
fe Z;
} ge_p2;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p3;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p1p1;
typedef struct {
fe yplusx;
fe yminusx;
fe xy2d;
} ge_precomp;
typedef struct {
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
} ge_cached;
/* From ge_add.c */
void ge_add(ge_p1p1 *, const ge_p3 *, const ge_cached *);
/* From ge_double_scalarmult.c, modified */
typedef ge_cached ge_dsmp[8];
extern const ge_precomp ge_Bi[8];
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s);
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *);
void ge_triple_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
void ge_double_scalarmult_base_vartime_p3(ge_p3 *, const unsigned char *, const ge_p3 *, const unsigned char *);
/* From ge_frombytes.c, modified */
extern const fe fe_sqrtm1;
extern const fe fe_d;
int ge_frombytes_vartime(ge_p3 *, const unsigned char *);
/* From ge_p1p1_to_p2.c */
void ge_p1p1_to_p2(ge_p2 *, const ge_p1p1 *);
/* From ge_p1p1_to_p3.c */
void ge_p1p1_to_p3(ge_p3 *, const ge_p1p1 *);
/* From ge_p2_dbl.c */
void ge_p2_dbl(ge_p1p1 *, const ge_p2 *);
/* From ge_p3_to_cached.c */
extern const fe fe_d2;
void ge_p3_to_cached(ge_cached *, const ge_p3 *);
/* From ge_p3_to_p2.c */
void ge_p3_to_p2(ge_p2 *, const ge_p3 *);
/* From ge_p3_tobytes.c */
void ge_p3_tobytes(unsigned char *, const ge_p3 *);
/* From ge_scalarmult_base.c */
extern const ge_precomp ge_base[32][8];
void ge_scalarmult_base(ge_p3 *, const unsigned char *);
/* From ge_tobytes.c */
void ge_tobytes(unsigned char *, const ge_p2 *);
/* From sc_reduce.c */
void sc_reduce(unsigned char *);
/* New code */
void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *);
void ge_scalarmult_p3(ge_p3 *, const unsigned char *, const ge_p3 *);
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp);
void ge_triple_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
void ge_double_scalarmult_precomp_vartime2(ge_p2 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
void ge_double_scalarmult_precomp_vartime2_p3(ge_p3 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
void ge_mul8(ge_p1p1 *, const ge_p2 *);
extern const fe fe_ma2;
extern const fe fe_ma;
extern const fe fe_fffb1;
extern const fe fe_fffb2;
extern const fe fe_fffb3;
extern const fe fe_fffb4;
extern const ge_p3 ge_p3_identity;
extern const ge_p3 ge_p3_H;
void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *);
void sc_0(unsigned char *);
void sc_reduce32(unsigned char *);
void sc_add(unsigned char *, const unsigned char *, const unsigned char *);
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *);
void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *);
void sc_mul(unsigned char *, const unsigned char *, const unsigned char *);
void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c);
int sc_check(const unsigned char *);
int sc_isnonzero(const unsigned char *); /* Doesn't normalize */
// internal
uint64_t load_3(const unsigned char *in);
uint64_t load_4(const unsigned char *in);
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void fe_add(fe h, const fe f, const fe g);
void fe_tobytes(unsigned char *, const fe);
void fe_invert(fe out, const fe z);
int ge_p3_is_point_at_infinity(const ge_p3 *p);

View File

@@ -0,0 +1,68 @@
/*
* 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
* 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/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*
*/
#pragma once
#include <cstdint>
#ifdef XMRIG_64_BIT
# ifdef _MSC_VER
# include <intrin.h>
# pragma intrinsic(_umul128)
# define __umul128 _umul128
# elif defined __GNUC__
static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
{
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
*hi = r >> 64;
return (uint64_t) r;
}
# define __umul128 _umul128
# endif
#else
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
uint64_t a = multiplier >> 32;
uint64_t b = multiplier & 0xFFFFFFFF;
uint64_t c = multiplicand >> 32;
uint64_t d = multiplicand & 0xFFFFFFFF;
//uint64_t ac = a * c;
uint64_t ad = a * d;
//uint64_t bc = b * c;
uint64_t bd = b * d;
uint64_t adbc = ad + (b * c);
uint64_t adbc_carry = adbc < ad ? 1 : 0;
// multiplier * multiplicand = product_hi * 2^64 + product_lo
uint64_t product_lo = bd + (adbc << 32);
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
return product_lo;
}
#endif

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -22,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <mutex>
#include <thread>
@@ -116,15 +109,7 @@ public:
inline void rebuild()
{
algorithms.clear();
for (int i = 0; i < Algorithm::MAX; ++i) {
const Algorithm algo(static_cast<Algorithm::Id>(i));
if (algo.isValid() && isEnabled(algo)) {
algorithms.push_back(algo);
}
}
algorithms = Algorithm::all([this](const Algorithm &algo) { return isEnabled(algo); });
}
@@ -171,7 +156,7 @@ public:
Value algo(kArrayType);
for (const Algorithm &a : algorithms) {
algo.PushBack(StringRef(a.shortName()), allocator);
algo.PushBack(StringRef(a.name()), allocator);
}
reply.AddMember("algorithms", algo, allocator);

View File

@@ -1,12 +1,6 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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

@@ -225,11 +225,15 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName)
# endif
# ifdef XMRIG_FEATURE_OPENCL
d_ptr->cl.read(reader.getValue(kOcl));
if (!pools().isBenchmark()) {
d_ptr->cl.read(reader.getValue(kOcl));
}
# endif
# ifdef XMRIG_FEATURE_CUDA
d_ptr->cuda.read(reader.getValue(kCuda));
if (!pools().isBenchmark()) {
d_ptr->cuda.read(reader.getValue(kCuda));
}
# endif
# if defined(XMRIG_FEATURE_NVML) || defined (XMRIG_FEATURE_ADL)

View File

@@ -195,6 +195,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const
case IConfig::RandomXCacheQoSKey: /* --cache-qos */
return set(doc, RxConfig::kField, RxConfig::kCacheQoS, true);
case IConfig::HugePagesJitKey: /* --huge-pages-jit */
return set(doc, CpuConfig::kField, CpuConfig::kHugePagesJit, true);
# endif
# ifdef XMRIG_FEATURE_OPENCL
@@ -262,6 +265,7 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const
case IConfig::BenchTokenKey: /* --token */
case IConfig::BenchSeedKey: /* --seed */
case IConfig::BenchHashKey: /* --hash */
case IConfig::UserKey: /* --user */
return transformBenchmark(doc, key, arg);
# endif
@@ -347,6 +351,9 @@ void xmrig::ConfigTransform::transformBenchmark(rapidjson::Document &doc, int ke
case IConfig::BenchHashKey: /* --hash */
return set(doc, BenchConfig::kBenchmark, BenchConfig::kHash, arg);
case IConfig::UserKey: /* --user */
return set(doc, BenchConfig::kBenchmark, BenchConfig::kUser, arg);
}
}
#endif

View File

@@ -52,6 +52,7 @@ static const option options[] = {
{ "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey },
{ "self-select", 1, nullptr, IConfig::SelfSelectKey },
{ "submit-to-origin", 0, nullptr, IConfig::SubmitToOriginKey },
{ "daemon-zmq-port", 1, nullptr, IConfig::DaemonZMQPortKey },
# endif
{ "av", 1, nullptr, IConfig::AVKey },
{ "background", 0, nullptr, IConfig::BackgroundKey },
@@ -68,6 +69,8 @@ static const option options[] = {
{ "no-huge-pages", 0, nullptr, IConfig::HugePagesKey },
{ "no-hugepages", 0, nullptr, IConfig::HugePagesKey },
{ "hugepage-size", 1, nullptr, IConfig::HugePageSizeKey },
{ "huge-pages-jit", 0, nullptr, IConfig::HugePagesJitKey },
{ "hugepages-jit", 0, nullptr, IConfig::HugePagesJitKey },
{ "pass", 1, nullptr, IConfig::PasswordKey },
{ "print-time", 1, nullptr, IConfig::PrintTimeKey },
{ "retries", 1, nullptr, IConfig::RetriesKey },
@@ -96,6 +99,7 @@ static const option options[] = {
{ "pause-on-active", 1, nullptr, IConfig::PauseOnActiveKey },
{ "dns-ipv6", 0, nullptr, IConfig::DnsIPv6Key },
{ "dns-ttl", 1, nullptr, IConfig::DnsTtlKey },
{ "spend-secret-key", 1, nullptr, IConfig::SpendSecretKey },
# ifdef XMRIG_FEATURE_BENCHMARK
{ "stress", 0, nullptr, IConfig::StressKey },
{ "bench", 1, nullptr, IConfig::BenchKey },

View File

@@ -79,15 +79,18 @@ static inline const std::string &usage()
u += " --no-cpu disable CPU mining backend\n";
u += " -t, --threads=N number of CPU threads, proper CPU affinity required for some optimizations.\n";
u += " --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n";
u += " --cpu-affinity=N set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n";
u += " -v, --av=N algorithm variation, 0 auto select\n";
u += " --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n";
u += " --cpu-priority=N set process priority (0 idle, 2 normal to 5 highest)\n";
u += " --cpu-max-threads-hint=N maximum CPU threads count (in percentage) hint for autoconfig\n";
u += " --cpu-memory-pool=N number of 2 MB pages for persistent memory pool, -1 (auto), 0 (disable)\n";
u += " --cpu-no-yield prefer maximum hashrate rather than system response/stability\n";
u += " --no-huge-pages disable huge pages support\n";
# ifdef XMRIG_OS_LINUX
u += " --hugepage-size=N custom hugepage size in kB\n";
# endif
# ifdef XMRIG_ALGO_RANDOMX
u += " --huge-pages-jit enable huge pages support for RandomX JIT code\n";
# endif
u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n";

View File

@@ -30,6 +30,7 @@
#include "crypto/astrobwt/AstroBWT.h"
#include "backend/cpu/Cpu.h"
#include "base/crypto/sha3.h"
#include "base/tools/bswap_64.h"
#include "crypto/cn/CryptoNight.h"
@@ -54,21 +55,6 @@ __attribute__((ms_abi))
void SHA3_256_AVX2_ASM(const void* in, size_t inBytes, void* out);
#endif
#ifdef _MSC_VER
#include <stdlib.h>
#define bswap_64(x) _byteswap_uint64(x)
#elif defined __GNUC__
#define bswap_64(x) __builtin_bswap64(x)
#else
#include <byteswap.h>
#endif
#ifdef XMRIG_ARM
extern "C" {
#include "salsa20_ref/ecrypt-sync.h"

View File

@@ -1,13 +1,6 @@
/* 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 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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
@@ -44,20 +37,13 @@ class CnAlgo
public:
constexpr CnAlgo() {};
constexpr inline Algorithm::Id base() const { static_assert(ALGO > Algorithm::INVALID && ALGO < Algorithm::RX_0, "invalid CRYPTONIGHT algorithm"); return Algorithm::CN_2; }
constexpr inline bool isHeavy() const { return memory() == CN_MEMORY * 2; }
constexpr inline Algorithm::Id base() const { static_assert(Algorithm::isCN(ALGO), "invalid CRYPTONIGHT algorithm"); return Algorithm::base(ALGO); }
constexpr inline bool isHeavy() const { return Algorithm::family(ALGO) == Algorithm::CN_HEAVY; }
constexpr inline bool isR() const { return ALGO == Algorithm::CN_R; }
constexpr inline size_t memory() const { static_assert(ALGO > Algorithm::INVALID && ALGO < Algorithm::RX_0, "invalid CRYPTONIGHT algorithm"); return CN_MEMORY; }
constexpr inline uint32_t iterations() const { static_assert(ALGO > Algorithm::INVALID && ALGO < Algorithm::RX_0, "invalid CRYPTONIGHT algorithm"); return CN_ITER; }
constexpr inline size_t memory() const { static_assert(Algorithm::isCN(ALGO), "invalid CRYPTONIGHT algorithm"); return Algorithm::l3(ALGO); }
constexpr inline uint32_t iterations() const { static_assert(Algorithm::isCN(ALGO), "invalid CRYPTONIGHT algorithm"); return CN_ITER; }
constexpr inline uint32_t mask() const { return static_cast<uint32_t>(((memory() - 1) / 16) * 16); }
inline static size_t memory(Algorithm::Id algo)
{
Algorithm algorithm(algo);
return algorithm.isCN() ? algorithm.l3() : 0;
}
inline static uint32_t iterations(Algorithm::Id algo)
{
switch (algo) {
@@ -96,6 +82,11 @@ public:
return CN_ITER / 8;
# endif
# ifdef XMRIG_ALGO_CN_FEMTO
case Algorithm::CN_UPX2:
return CN_ITER / 32;
# endif
default:
break;
}
@@ -111,73 +102,20 @@ public:
}
# endif
return ((memory(algo) - 1) / 16) * 16;
}
inline static Algorithm::Id base(Algorithm::Id algo)
{
switch (algo) {
case Algorithm::CN_0:
case Algorithm::CN_XAO:
# ifdef XMRIG_ALGO_CN_LITE
case Algorithm::CN_LITE_0:
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
case Algorithm::CN_HEAVY_0:
case Algorithm::CN_HEAVY_XHV:
# endif
case Algorithm::CN_CCX:
return Algorithm::CN_0;
case Algorithm::CN_1:
case Algorithm::CN_FAST:
case Algorithm::CN_RTO:
# ifdef XMRIG_ALGO_CN_LITE
case Algorithm::CN_LITE_1:
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
case Algorithm::CN_HEAVY_TUBE:
return Algorithm::CN_1;
# endif
case Algorithm::CN_2:
case Algorithm::CN_R:
case Algorithm::CN_HALF:
case Algorithm::CN_RWZ:
case Algorithm::CN_ZLS:
case Algorithm::CN_DOUBLE:
# ifdef XMRIG_ALGO_CN_PICO
case Algorithm::CN_PICO_0:
case Algorithm::CN_PICO_TLO:
# endif
return Algorithm::CN_2;
default:
break;
# ifdef XMRIG_ALGO_CN_FEMTO
if (algo == Algorithm::CN_UPX2) {
return 0x1FFF0;
}
# endif
return Algorithm::INVALID;
return ((Algorithm::l3(algo) - 1) / 16) * 16;
}
private:
constexpr const static size_t CN_MEMORY = 0x200000;
constexpr const static uint32_t CN_ITER = 0x80000;
constexpr const static uint32_t CN_ITER = 0x80000;
};
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_0>::base() const { return Algorithm::CN_0; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_XAO>::base() const { return Algorithm::CN_0; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_LITE_0>::base() const { return Algorithm::CN_0; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_HEAVY_0>::base() const { return Algorithm::CN_0; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_HEAVY_XHV>::base() const { return Algorithm::CN_0; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_CCX>::base() const { return Algorithm::CN_0; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_1>::base() const { return Algorithm::CN_1; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_FAST>::base() const { return Algorithm::CN_1; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_RTO>::base() const { return Algorithm::CN_1; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_LITE_1>::base() const { return Algorithm::CN_1; }
template<> constexpr inline Algorithm::Id CnAlgo<Algorithm::CN_HEAVY_TUBE>::base() const { return Algorithm::CN_1; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_FAST>::iterations() const { return CN_ITER / 2; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_HALF>::iterations() const { return CN_ITER / 2; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_LITE_0>::iterations() const { return CN_ITER / 2; }
@@ -192,18 +130,11 @@ template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_ZLS>::iterations() con
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_0>::iterations() const { return CN_ITER / 8; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_TLO>::iterations() const { return CN_ITER / 8; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_CCX>::iterations() const { return CN_ITER / 2; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_LITE_0>::memory() const { return CN_MEMORY / 2; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_LITE_1>::memory() const { return CN_MEMORY / 2; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_HEAVY_0>::memory() const { return CN_MEMORY * 2; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_HEAVY_TUBE>::memory() const { return CN_MEMORY * 2; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_HEAVY_XHV>::memory() const { return CN_MEMORY * 2; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_PICO_0>::memory() const { return CN_MEMORY / 8; }
template<> constexpr inline size_t CnAlgo<Algorithm::CN_PICO_TLO>::memory() const { return CN_MEMORY / 8; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_UPX2>::iterations() const { return CN_ITER / 32; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_0>::mask() const { return 0x1FFF0; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_UPX2>::mask() const { return 0x1FFF0; }
} /* namespace xmrig */

View File

@@ -1,13 +1,7 @@
/* 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 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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
@@ -23,11 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdio>
#include "backend/cpu/Cpu.h"
#include "crypto/cn/CnHash.h"
#include "backend/cpu/Cpu.h"
#include "base/tools/cryptonote/umul128.h"
#include "crypto/common/VirtualMemory.h"
@@ -48,27 +40,30 @@
#endif
#define ADD_FN(algo) \
m_map[algo][AV_SINGLE][Assembly::NONE] = cryptonight_single_hash<algo, false, 0>; \
m_map[algo][AV_SINGLE_SOFT][Assembly::NONE] = cryptonight_single_hash<algo, true, 0>; \
m_map[algo][AV_DOUBLE][Assembly::NONE] = cryptonight_double_hash<algo, false>; \
m_map[algo][AV_DOUBLE_SOFT][Assembly::NONE] = cryptonight_double_hash<algo, true>; \
m_map[algo][AV_TRIPLE][Assembly::NONE] = cryptonight_triple_hash<algo, false>; \
m_map[algo][AV_TRIPLE_SOFT][Assembly::NONE] = cryptonight_triple_hash<algo, true>; \
m_map[algo][AV_QUAD][Assembly::NONE] = cryptonight_quad_hash<algo, false>; \
m_map[algo][AV_QUAD_SOFT][Assembly::NONE] = cryptonight_quad_hash<algo, true>; \
m_map[algo][AV_PENTA][Assembly::NONE] = cryptonight_penta_hash<algo, false>; \
m_map[algo][AV_PENTA_SOFT][Assembly::NONE] = cryptonight_penta_hash<algo, true>;
#define ADD_FN(algo) do { \
m_map[algo] = new cn_hash_fun_array{}; \
m_map[algo]->data[AV_SINGLE][Assembly::NONE] = cryptonight_single_hash<algo, false, 0>; \
m_map[algo]->data[AV_SINGLE_SOFT][Assembly::NONE] = cryptonight_single_hash<algo, true, 0>; \
m_map[algo]->data[AV_DOUBLE][Assembly::NONE] = cryptonight_double_hash<algo, false>; \
m_map[algo]->data[AV_DOUBLE_SOFT][Assembly::NONE] = cryptonight_double_hash<algo, true>; \
m_map[algo]->data[AV_TRIPLE][Assembly::NONE] = cryptonight_triple_hash<algo, false>; \
m_map[algo]->data[AV_TRIPLE_SOFT][Assembly::NONE] = cryptonight_triple_hash<algo, true>; \
m_map[algo]->data[AV_QUAD][Assembly::NONE] = cryptonight_quad_hash<algo, false>; \
m_map[algo]->data[AV_QUAD_SOFT][Assembly::NONE] = cryptonight_quad_hash<algo, true>; \
m_map[algo]->data[AV_PENTA][Assembly::NONE] = cryptonight_penta_hash<algo, false>; \
m_map[algo]->data[AV_PENTA_SOFT][Assembly::NONE] = cryptonight_penta_hash<algo, true>; \
} while (0)
#ifdef XMRIG_FEATURE_ASM
# define ADD_FN_ASM(algo) \
m_map[algo][AV_SINGLE][Assembly::INTEL] = cryptonight_single_hash_asm<algo, Assembly::INTEL>; \
m_map[algo][AV_SINGLE][Assembly::RYZEN] = cryptonight_single_hash_asm<algo, Assembly::RYZEN>; \
m_map[algo][AV_SINGLE][Assembly::BULLDOZER] = cryptonight_single_hash_asm<algo, Assembly::BULLDOZER>; \
m_map[algo][AV_DOUBLE][Assembly::INTEL] = cryptonight_double_hash_asm<algo, Assembly::INTEL>; \
m_map[algo][AV_DOUBLE][Assembly::RYZEN] = cryptonight_double_hash_asm<algo, Assembly::RYZEN>; \
m_map[algo][AV_DOUBLE][Assembly::BULLDOZER] = cryptonight_double_hash_asm<algo, Assembly::BULLDOZER>;
# define ADD_FN_ASM(algo) do { \
m_map[algo]->data[AV_SINGLE][Assembly::INTEL] = cryptonight_single_hash_asm<algo, Assembly::INTEL>; \
m_map[algo]->data[AV_SINGLE][Assembly::RYZEN] = cryptonight_single_hash_asm<algo, Assembly::RYZEN>; \
m_map[algo]->data[AV_SINGLE][Assembly::BULLDOZER] = cryptonight_single_hash_asm<algo, Assembly::BULLDOZER>; \
m_map[algo]->data[AV_DOUBLE][Assembly::INTEL] = cryptonight_double_hash_asm<algo, Assembly::INTEL>; \
m_map[algo]->data[AV_DOUBLE][Assembly::RYZEN] = cryptonight_double_hash_asm<algo, Assembly::RYZEN>; \
m_map[algo]->data[AV_DOUBLE][Assembly::BULLDOZER] = cryptonight_double_hash_asm<algo, Assembly::BULLDOZER>; \
} while (0)
namespace xmrig {
@@ -99,8 +94,11 @@ cn_mainloop_fun cn_double_mainloop_ryzen_asm = nullptr;
cn_mainloop_fun cn_double_mainloop_bulldozer_asm = nullptr;
cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm = nullptr;
cn_mainloop_fun cn_upx2_mainloop_asm = nullptr;
cn_mainloop_fun cn_upx2_double_mainloop_asm = nullptr;
template<typename T, typename U>
template<Algorithm::Id SOURCE_ALGO = Algorithm::CN_2, typename T, typename U>
static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t mask = CnAlgo<Algorithm::CN_HALF>().mask())
{
auto p = reinterpret_cast<const uint8_t*>(src);
@@ -124,11 +122,11 @@ static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t ma
auto patched_data = reinterpret_cast<uint8_t*>(dst);
for (size_t i = 0; i + sizeof(uint32_t) <= size; ++i) {
switch (*(uint32_t*)(patched_data + i)) {
case CnAlgo<Algorithm::CN_2>().iterations():
case CnAlgo<SOURCE_ALGO>().iterations():
*(uint32_t*)(patched_data + i) = iterations;
break;
case CnAlgo<Algorithm::CN_2>().mask():
case CnAlgo<SOURCE_ALGO>().mask():
*(uint32_t*)(patched_data + i) = mask;
break;
}
@@ -138,7 +136,7 @@ static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t ma
static void patchAsmVariants()
{
const int allocation_size = 81920;
const int allocation_size = 131072;
auto base = static_cast<uint8_t *>(VirtualMemory::allocateExecutableMemory(allocation_size, false));
cn_half_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x0000);
@@ -170,6 +168,11 @@ static void patchAsmVariants()
cn_tlo_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x13000);
# endif
# ifdef XMRIG_ALGO_CN_FEMTO
cn_upx2_mainloop_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x14000);
cn_upx2_double_mainloop_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x15000);
# endif
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_HALF>().iterations();
@@ -219,6 +222,16 @@ static void patchAsmVariants()
patchCode(cn_double_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER);
}
# ifdef XMRIG_ALGO_CN_FEMTO
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_UPX2>().iterations();
constexpr uint32_t MASK = CnAlgo<Algorithm::CN_UPX2>().mask();
patchCode<Algorithm::CN_RWZ>(cn_upx2_mainloop_asm, cnv2_rwz_mainloop_asm, ITER, MASK);
patchCode<Algorithm::CN_RWZ>(cn_upx2_double_mainloop_asm, cnv2_rwz_double_mainloop_asm, ITER, MASK);
}
#endif
VirtualMemory::protectRX(base, allocation_size);
VirtualMemory::flushInstructionCache(base, allocation_size);
}
@@ -272,18 +285,29 @@ xmrig::CnHash::CnHash()
ADD_FN(Algorithm::CN_CCX);
# ifdef XMRIG_ALGO_CN_FEMTO
ADD_FN(Algorithm::CN_UPX2);
ADD_FN_ASM(Algorithm::CN_UPX2);
# endif
# ifdef XMRIG_ALGO_ARGON2
m_map[Algorithm::AR2_CHUKWA][AV_SINGLE][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA>;
m_map[Algorithm::AR2_CHUKWA][AV_SINGLE_SOFT][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA>;
m_map[Algorithm::AR2_CHUKWA_V2][AV_SINGLE][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA_V2>;
m_map[Algorithm::AR2_CHUKWA_V2][AV_SINGLE_SOFT][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA_V2>;
m_map[Algorithm::AR2_WRKZ][AV_SINGLE][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_WRKZ>;
m_map[Algorithm::AR2_WRKZ][AV_SINGLE_SOFT][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_WRKZ>;
m_map[Algorithm::AR2_CHUKWA] = new cn_hash_fun_array{};
m_map[Algorithm::AR2_CHUKWA]->data[AV_SINGLE][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA>;
m_map[Algorithm::AR2_CHUKWA]->data[AV_SINGLE_SOFT][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA>;
m_map[Algorithm::AR2_CHUKWA_V2] = new cn_hash_fun_array{};
m_map[Algorithm::AR2_CHUKWA_V2]->data[AV_SINGLE][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA_V2>;
m_map[Algorithm::AR2_CHUKWA_V2]->data[AV_SINGLE_SOFT][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA_V2>;
m_map[Algorithm::AR2_WRKZ] = new cn_hash_fun_array{};
m_map[Algorithm::AR2_WRKZ]->data[AV_SINGLE][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_WRKZ>;
m_map[Algorithm::AR2_WRKZ]->data[AV_SINGLE_SOFT][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_WRKZ>;
# endif
# ifdef XMRIG_ALGO_ASTROBWT
m_map[Algorithm::ASTROBWT_DERO][AV_SINGLE][Assembly::NONE] = astrobwt::single_hash<Algorithm::ASTROBWT_DERO>;
m_map[Algorithm::ASTROBWT_DERO][AV_SINGLE_SOFT][Assembly::NONE] = astrobwt::single_hash<Algorithm::ASTROBWT_DERO>;
m_map[Algorithm::ASTROBWT_DERO] = new cn_hash_fun_array{};
m_map[Algorithm::ASTROBWT_DERO]->data[AV_SINGLE][Assembly::NONE] = astrobwt::single_hash<Algorithm::ASTROBWT_DERO>;
m_map[Algorithm::ASTROBWT_DERO]->data[AV_SINGLE_SOFT][Assembly::NONE] = astrobwt::single_hash<Algorithm::ASTROBWT_DERO>;
# endif
# ifdef XMRIG_FEATURE_ASM
@@ -294,20 +318,30 @@ xmrig::CnHash::CnHash()
xmrig::cn_hash_fun xmrig::CnHash::fn(const Algorithm &algorithm, AlgoVariant av, Assembly::Id assembly)
{
assert(cnHash.m_map.count(algorithm));
if (!algorithm.isValid()) {
return nullptr;
}
const auto it = cnHash.m_map.find(algorithm);
if (it == cnHash.m_map.end()) {
return nullptr;
}
# ifdef XMRIG_ALGO_CN_HEAVY
// cn-heavy optimization for Zen3 CPUs
if ((av == AV_SINGLE) && (assembly != Assembly::NONE) && (Cpu::info()->arch() == ICpuInfo::ARCH_ZEN3)) {
switch (algorithm.id()) {
case xmrig::Algorithm::CN_HEAVY_0:
return cryptonight_single_hash<xmrig::Algorithm::CN_HEAVY_0, false, 3>;
case xmrig::Algorithm::CN_HEAVY_TUBE:
return cryptonight_single_hash<xmrig::Algorithm::CN_HEAVY_TUBE, false, 3>;
case xmrig::Algorithm::CN_HEAVY_XHV:
return cryptonight_single_hash<xmrig::Algorithm::CN_HEAVY_XHV, false, 3>;
case Algorithm::CN_HEAVY_0:
return cryptonight_single_hash<Algorithm::CN_HEAVY_0, false, 3>;
case Algorithm::CN_HEAVY_TUBE:
return cryptonight_single_hash<Algorithm::CN_HEAVY_TUBE, false, 3>;
case Algorithm::CN_HEAVY_XHV:
return cryptonight_single_hash<Algorithm::CN_HEAVY_XHV, false, 3>;
default:
break;
}
@@ -315,11 +349,11 @@ xmrig::cn_hash_fun xmrig::CnHash::fn(const Algorithm &algorithm, AlgoVariant av,
# endif
# ifdef XMRIG_FEATURE_ASM
cn_hash_fun fun = cnHash.m_map[algorithm][av][Cpu::assembly(assembly)];
cn_hash_fun fun = it->second->data[av][Cpu::assembly(assembly)];
if (fun) {
return fun;
}
# endif
return cnHash.m_map[algorithm][av][Assembly::NONE];
return it->second->data[av][Assembly::NONE];
}

View File

@@ -1,13 +1,7 @@
/* 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 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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
@@ -29,6 +23,7 @@
#include <cstddef>
#include <cstdint>
#include <map>
#include "crypto/cn/CnAlgo.h"
@@ -68,7 +63,11 @@ public:
static cn_hash_fun fn(const Algorithm &algorithm, AlgoVariant av, Assembly::Id assembly);
private:
cn_hash_fun m_map[Algorithm::MAX][AV_MAX][Assembly::MAX] = {};
struct cn_hash_fun_array {
cn_hash_fun data[AV_MAX][Assembly::MAX];
};
std::map<Algorithm, cn_hash_fun_array*> m_map;
};

View File

@@ -67,41 +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};
#if defined (__arm64__) || defined (__aarch64__)
static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
{
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
*hi = r >> 64;
return (uint64_t) r;
}
#else
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
uint64_t a = multiplier >> 32;
uint64_t b = multiplier & 0xFFFFFFFF;
uint64_t c = multiplicand >> 32;
uint64_t d = multiplicand & 0xFFFFFFFF;
//uint64_t ac = a * c;
uint64_t ad = a * d;
//uint64_t bc = b * c;
uint64_t bd = b * d;
uint64_t adbc = ad + (b * c);
uint64_t adbc_carry = adbc < ad ? 1 : 0;
// multiplier * multiplicand = product_hi * 2^64 + product_lo
uint64_t product_lo = bd + (adbc << 32);
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
return product_lo;
}
#endif
// This will shift and xor tmp1 into itself as 4 32-bit vals such as
// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
static inline __m128i sl_xor(__m128i tmp1)
@@ -395,7 +360,7 @@ static inline void cryptonight_monero_tweak(const uint8_t* l, uint64_t idx, __m1
uint64_t* mem_out = (uint64_t*)&l[idx];
if (props.base() == Algorithm::CN_2) {
VARIANT2_SHUFFLE(l, idx, ax0, bx0, bx1, cx, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
VARIANT2_SHUFFLE(l, idx, ax0, bx0, bx1, cx, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0));
_mm_store_si128((__m128i *)mem_out, _mm_xor_si128(bx0, cx));
} else {
__m128i tmp = _mm_xor_si128(bx0, cx);
@@ -528,7 +493,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l0, idx0 & MASK, ax0, bx0, bx1, cx, 0);
} else {
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx0, bx1, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx0, bx1, hi, lo, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0));
}
}
@@ -704,7 +669,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l0, idx0 & MASK, ax0, bx00, bx01, cx0, 0);
} else {
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx00, bx01, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx00, bx01, hi, lo, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0));
}
}
@@ -764,7 +729,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l1, idx1 & MASK, ax1, bx10, bx11, cx1, 0);
} else {
VARIANT2_SHUFFLE2(l1, idx1 & MASK, ax1, bx10, bx11, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l1, idx1 & MASK, ax1, bx10, bx11, hi, lo, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0));
}
}

View File

@@ -370,6 +370,23 @@ const static uint8_t test_output_pico_tlo[160] = {
#endif
#ifdef XMRIG_ALGO_CN_FEMTO
// "cn/upx2"
const static uint8_t test_output_femto_upx2[160] = {
0xAA, 0xBB, 0xB8, 0xED, 0x14, 0xA8, 0x35, 0xFA, 0x22, 0xCF, 0xB1, 0xB5, 0xDE, 0xA8, 0x72, 0xB0,
0xA1, 0xD6, 0xCB, 0xD8, 0x46, 0xF4, 0x39, 0x1C, 0x0F, 0x01, 0xF3, 0x87, 0x5E, 0x3A, 0x37, 0x61,
0x38, 0x59, 0x15, 0x72, 0xF8, 0x20, 0xD4, 0xDE, 0x25, 0x3C, 0xF5, 0x5A, 0x21, 0x92, 0xB6, 0x22,
0xB0, 0x28, 0x9E, 0x2E, 0x5C, 0x36, 0x16, 0xE6, 0x1E, 0x78, 0x7A, 0x8F, 0xE4, 0x62, 0xEC, 0x5A,
0xFD, 0x58, 0xCC, 0x6F, 0x3C, 0xD3, 0x8A, 0x0B, 0x5B, 0x6C, 0x83, 0x4E, 0x9B, 0xD4, 0xC2, 0x5A,
0x43, 0x2C, 0x48, 0x98, 0xF3, 0x16, 0xCA, 0x87, 0xE9, 0x5F, 0x44, 0x93, 0x53, 0x48, 0x00, 0xA3,
0xE8, 0xE4, 0xB6, 0x9D, 0x5A, 0x3B, 0x49, 0x2C, 0x21, 0xE9, 0x4B, 0x02, 0xFC, 0x87, 0x8D, 0x75,
0x66, 0x05, 0xAF, 0xA3, 0x9D, 0xC9, 0xD8, 0x88, 0x2D, 0x67, 0x31, 0x21, 0x4C, 0x4D, 0x88, 0x7D,
0x86, 0x9E, 0x4D, 0x74, 0xF4, 0x4C, 0x57, 0x27, 0xCF, 0xEF, 0x86, 0x01, 0xB0, 0x52, 0x18, 0xF3,
0xAD, 0xE4, 0x52, 0x5E, 0xB0, 0x4A, 0x97, 0xB4, 0x96, 0x18, 0xB6, 0x9C, 0x93, 0x0E, 0x49, 0xBB,
};
#endif
#ifdef XMRIG_ALGO_ARGON2
// "argon2/chukwa"
const static uint8_t argon2_chukwa_test_out[160] = {

View File

@@ -75,18 +75,7 @@ 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};
#if defined(__x86_64__) || defined(_M_AMD64)
# ifdef __GNUC__
static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
{
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
*hi = r >> 64;
return (uint64_t) r;
}
# else
#define __umul128 _umul128
# endif
#elif defined(__i386__) || defined(_M_IX86)
#if defined(__i386__) || defined(_M_IX86)
static inline int64_t _mm_cvtsi128_si64(__m128i a)
{
return ((uint64_t)(uint32_t)_mm_cvtsi128_si32(a) | ((uint64_t)(uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(a, 4)) << 32));
@@ -95,31 +84,6 @@ static inline int64_t _mm_cvtsi128_si64(__m128i a)
static inline __m128i _mm_cvtsi64_si128(int64_t a) {
return _mm_set_epi64x(0, a);
}
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
uint64_t a = multiplier >> 32;
uint64_t b = multiplier & 0xFFFFFFFF;
uint64_t c = multiplicand >> 32;
uint64_t d = multiplicand & 0xFFFFFFFF;
//uint64_t ac = a * c;
uint64_t ad = a * d;
//uint64_t bc = b * c;
uint64_t bd = b * d;
uint64_t adbc = ad + (b * c);
uint64_t adbc_carry = adbc < ad ? 1 : 0;
// multiplier * multiplicand = product_hi * 2^64 + product_lo
uint64_t product_lo = bd + (adbc << 32);
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
return product_lo;
}
#endif
@@ -377,12 +341,15 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
_mm_store_si128(output + 1, xin1);
_mm_store_si128(output + 2, xin2);
_mm_store_si128(output + 3, xin3);
output += (64 << interleave) / sizeof(__m128i);
_mm_store_si128(output + 0, xin4);
_mm_store_si128(output + 1, xin5);
_mm_store_si128(output + 2, xin6);
_mm_store_si128(output + 3, xin7);
output += (64 << interleave) / sizeof(__m128i);
constexpr int output_increment = (64 << interleave) / sizeof(__m128i);
_mm_store_si128(output + output_increment + 0, xin4);
_mm_store_si128(output + output_increment + 1, xin5);
_mm_store_si128(output + output_increment + 2, xin6);
_mm_store_si128(output + output_increment + 3, xin7);
output += output_increment * 2;
}
}
@@ -414,13 +381,15 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout1 = _mm_xor_si128(_mm_load_si128(input + 1), xout1);
xout2 = _mm_xor_si128(_mm_load_si128(input + 2), xout2);
xout3 = _mm_xor_si128(_mm_load_si128(input + 3), xout3);
input += (64 << interleave) / sizeof(__m128i);
xout4 = _mm_xor_si128(_mm_load_si128(input + 0), xout4);
xout5 = _mm_xor_si128(_mm_load_si128(input + 1), xout5);
xout6 = _mm_xor_si128(_mm_load_si128(input + 2), xout6);
xout7 = _mm_xor_si128(_mm_load_si128(input + 3), xout7);
input += (64 << interleave) / sizeof(__m128i);
constexpr int input_increment = (64 << interleave) / sizeof(__m128i);
xout4 = _mm_xor_si128(_mm_load_si128(input + input_increment + 0), xout4);
xout5 = _mm_xor_si128(_mm_load_si128(input + input_increment + 1), xout5);
xout6 = _mm_xor_si128(_mm_load_si128(input + input_increment + 2), xout6);
xout7 = _mm_xor_si128(_mm_load_si128(input + input_increment + 3), xout7);
input += input_increment * 2;
i += 8;
if ((interleave > 0) && (i < props.memory() / sizeof(__m128i))) {
@@ -563,7 +532,7 @@ static inline void cryptonight_monero_tweak(uint64_t *mem_out, const uint8_t *l,
constexpr CnAlgo<ALGO> props;
if (props.base() == Algorithm::CN_2) {
VARIANT2_SHUFFLE(l, idx, ax0, bx0, bx1, cx, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
VARIANT2_SHUFFLE(l, idx, ax0, bx0, bx1, cx, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0));
_mm_store_si128(reinterpret_cast<__m128i *>(mem_out), _mm_xor_si128(bx0, cx));
} else {
__m128i tmp = _mm_xor_si128(bx0, cx);
@@ -715,7 +684,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l0, idx0 & MASK, ax0, bx0, bx1, cx, 0);
} else {
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx0, bx1, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx0, bx1, hi, lo, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0));
}
}
@@ -789,6 +758,7 @@ extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx **ctx);
extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx **ctx);
extern "C" void cnv2_rwz_mainloop_asm(cryptonight_ctx **ctx);
extern "C" void cnv2_rwz_double_mainloop_asm(cryptonight_ctx **ctx);
extern "C" void cnv2_upx_double_mainloop_zen3_asm(cryptonight_ctx * *ctx);
namespace xmrig {
@@ -822,6 +792,8 @@ extern cn_mainloop_fun cn_double_mainloop_ryzen_asm;
extern cn_mainloop_fun cn_double_mainloop_bulldozer_asm;
extern cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm;
extern cn_mainloop_fun cn_upx2_mainloop_asm;
extern cn_mainloop_fun cn_upx2_double_mainloop_asm;
} // namespace xmrig
@@ -934,6 +906,11 @@ inline void cryptonight_single_hash_asm(const uint8_t *__restrict__ input, size_
cn_double_mainloop_bulldozer_asm(ctx);
}
}
# ifdef XMRIG_ALGO_CN_FEMTO
else if (ALGO == Algorithm::CN_UPX2) {
cn_upx2_mainloop_asm(ctx);
}
# endif
else if (props.isR()) {
ctx[0]->generated_code(ctx);
}
@@ -976,6 +953,16 @@ inline void cryptonight_double_hash_asm(const uint8_t *__restrict__ input, size_
else if (ALGO == Algorithm::CN_PICO_TLO) {
cn_tlo_double_mainloop_sandybridge_asm(ctx);
}
# endif
# ifdef XMRIG_ALGO_CN_FEMTO
else if (ALGO == Algorithm::CN_UPX2) {
if (Cpu::info()->arch() == ICpuInfo::ARCH_ZEN3) {
cnv2_upx_double_mainloop_zen3_asm(ctx);
}
else {
cn_upx2_double_mainloop_asm(ctx);
}
}
# endif
else if (ALGO == Algorithm::CN_RWZ) {
cnv2_rwz_double_mainloop_asm(ctx);
@@ -1134,7 +1121,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l0, idx0 & MASK, ax0, bx00, bx01, cx0, 0);
} else {
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx00, bx01, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx00, bx01, hi, lo, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0));
}
}
@@ -1192,7 +1179,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
if (ALGO == Algorithm::CN_R) {
VARIANT2_SHUFFLE(l1, idx1 & MASK, ax1, bx10, bx11, cx1, 0);
} else {
VARIANT2_SHUFFLE2(l1, idx1 & MASK, ax1, bx10, bx11, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0));
VARIANT2_SHUFFLE2(l1, idx1 & MASK, ax1, bx10, bx11, hi, lo, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0));
}
}
@@ -1302,7 +1289,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
if (ALGO == Algorithm::CN_R) { \
VARIANT2_SHUFFLE(l, idx & MASK, a, b0, b1, c, 0); \
} else { \
VARIANT2_SHUFFLE2(l, idx & MASK, a, b0, b1, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0)); \
VARIANT2_SHUFFLE2(l, idx & MASK, a, b0, b1, hi, lo, (((ALGO == Algorithm::CN_RWZ) || (ALGO == Algorithm::CN_UPX2)) ? 1 : 0)); \
} \
} \
if (ALGO == Algorithm::CN_R) { \

View File

@@ -0,0 +1,320 @@
mov rax, rsp
push rbx
push rbp
push rsi
push rdi
push r12
push r13
push r14
push r15
sub rsp, 232
mov rdi, QWORD PTR [rcx+8]
mov edx, 768
mov rbx, QWORD PTR [rcx]
mov ecx, 256
movaps XMMWORD PTR [rax-88], xmm6
movaps XMMWORD PTR [rax-104], xmm7
mov r13, QWORD PTR [rdi+224]
movq xmm0, QWORD PTR [rdi+104]
mov r12, QWORD PTR [rbx+224]
movaps XMMWORD PTR [rax-120], xmm8
movaps XMMWORD PTR [rax-136], xmm9
movaps XMMWORD PTR [rax-152], xmm10
movaps XMMWORD PTR [rsp+112], xmm11
movaps XMMWORD PTR [rsp+96], xmm12
movaps XMMWORD PTR [rsp+80], xmm13
movq xmm13, QWORD PTR [rbx+96]
movaps XMMWORD PTR [rsp+64], xmm14
movq xmm14, QWORD PTR [rbx+104]
movaps XMMWORD PTR [rsp+48], xmm15
movq xmm15, QWORD PTR [rdi+96]
mov QWORD PTR [rsp], r13
movdqa XMMWORD PTR [rsp+32], xmm0
stmxcsr DWORD PTR [rsp+24]
mov DWORD PTR [rsp+28], 16256
ldmxcsr DWORD PTR [rsp+28]
mov rcx, QWORD PTR [rbx+56]
xorps xmm12, xmm12
xor rcx, QWORD PTR [rbx+24]
mov rax, QWORD PTR [rbx+48]
xor rax, QWORD PTR [rbx+16]
mov rsi, QWORD PTR [rbx+32]
mov rbp, QWORD PTR [rdi+32]
movq xmm0, rcx
mov rcx, QWORD PTR [rbx+88]
xor rcx, QWORD PTR [rbx+72]
movq xmm7, rax
mov rax, QWORD PTR [rbx+80]
xor rax, QWORD PTR [rbx+64]
mov r14, QWORD PTR [rbx+40]
mov r15, QWORD PTR [rdi+40]
xor rsi, QWORD PTR [rbx]
xor rbp, QWORD PTR [rdi]
movq xmm9, rax
mov rax, QWORD PTR [rdi+48]
xor rax, QWORD PTR [rdi+16]
xor r14, QWORD PTR [rbx+8]
xor r15, QWORD PTR [rdi+8]
movq xmm8, rax
punpcklqdq xmm7, xmm0
mov eax, 1023
shl rax, 52
movq xmm11, rax
punpcklqdq xmm11, xmm11
mov rax, QWORD PTR [rdi+80]
movq xmm0, rcx
mov rcx, QWORD PTR [rdi+56]
xor rcx, QWORD PTR [rdi+24]
punpcklqdq xmm9, xmm0
mov QWORD PTR [rsp+8], 16384
movq xmm0, rcx
mov rcx, QWORD PTR [rdi+88]
xor rcx, QWORD PTR [rdi+72]
xor rax, QWORD PTR [rdi+64]
punpcklqdq xmm8, xmm0
movq xmm0, rcx
movq xmm10, rax
mov rax, 4389456576511
mov QWORD PTR [rsp+16], rax
mov rax, -4389456576512
mov QWORD PTR [rsp+216], rax
punpcklqdq xmm10, xmm0
ALIGN(64)
upx2_main_loop:
mov rdx, rsi
mov r9, rbp
and edx, 131056
and r9d, 131056
movdqu xmm6, XMMWORD PTR [rdx+r12]
lea r8, QWORD PTR [rdx+r12]
movdqu xmm4, XMMWORD PTR [r9+r13]
lea r10, QWORD PTR [r9+r13]
mov ecx, edx
mov eax, edx
xor rax, 32
xor rcx, 48
xor rdx, 16
movq xmm0, r14
movq xmm3, rsi
movq xmm5, rbp
punpcklqdq xmm3, xmm0
movq xmm0, r15
movdqu xmm2, XMMWORD PTR [rax+r12]
movdqu xmm1, XMMWORD PTR [rcx+r12]
paddq xmm2, xmm3
punpcklqdq xmm5, xmm0
paddq xmm1, xmm7
aesenc xmm6, xmm3
aesenc xmm4, xmm5
movdqa xmm0, xmm9
movq rdi, xmm4
paddq xmm0, XMMWORD PTR [rdx+r12]
movdqu XMMWORD PTR [rdx+r12], xmm0
xor edx, edx
movdqu XMMWORD PTR [rax+r12], xmm1
movdqa xmm0, xmm6
movdqu XMMWORD PTR [rcx+r12], xmm2
pxor xmm0, xmm7
movdqu XMMWORD PTR [r8], xmm0
mov ecx, r9d
xor rcx, 48
mov eax, r9d
xor rax, 32
xor r9, 16
movdqa xmm0, xmm10
movdqu xmm1, XMMWORD PTR [rcx+r13]
movdqu xmm2, XMMWORD PTR [rax+r13]
paddq xmm1, xmm8
paddq xmm0, XMMWORD PTR [r9+r13]
paddq xmm2, xmm5
movdqu XMMWORD PTR [r9+r13], xmm0
movq r9, xmm6
movdqu XMMWORD PTR [rax+r13], xmm1
movdqa xmm0, xmm4
movdqu XMMWORD PTR [rcx+r13], xmm2
pxor xmm0, xmm8
movdqu XMMWORD PTR [r10], xmm0
movq rcx, xmm14
mov rax, rcx
movq r10, xmm13
shl rax, 32
movdqa xmm0, xmm6
xor r10, rax
psrldq xmm0, 8
lea r8, QWORD PTR [rcx+rcx]
movq rax, xmm0
add r8d, r9d
mov ecx, -2147483647
or r8, rcx
mov r11, r9
div r8
and r11d, 131056
movaps xmm1, xmm12
mov eax, eax
add r11, r12
shl rdx, 32
add rdx, rax
xor r10, QWORD PTR [r11]
mov rbx, QWORD PTR [r11+8]
lea r8, QWORD PTR [rdx+r9]
movq xmm13, rdx
mov rax, r8
shr rax, 12
movq xmm0, rax
paddq xmm0, xmm11
sqrtsd xmm1, xmm0
movq rdx, xmm1
mov rax, rdx
shr rdx, 19
shr rax, 20
mov rcx, rdx
sub rcx, rax
add rax, QWORD PTR [rsp+216]
sub rcx, QWORD PTR [rsp+16]
mov r13, QWORD PTR [rsp]
imul rcx, rax
mov rax, r10
sub rcx, r8
mov rcx, r9
adc rdx, 0
xor rcx, 32
and ecx, 131056
movq xmm14, rdx
movdqu xmm1, XMMWORD PTR [rcx+r12]
mul r9
paddq xmm1, xmm3
mov r8, rax
xor r8, QWORD PTR [rcx+r12+8]
add r14, r8
movq xmm0, rax
movq xmm2, rdx
xor rdx, QWORD PTR [rcx+r12]
mov rax, r9
xor rax, 48
punpcklqdq xmm2, xmm0
and eax, 131056
add rsi, rdx
xor r9, 16
xor edx, edx
and r9d, 131056
movdqu xmm0, XMMWORD PTR [rax+r12]
paddq xmm0, xmm7
pxor xmm2, XMMWORD PTR [r9+r12]
paddq xmm2, xmm9
movdqu XMMWORD PTR [r9+r12], xmm2
movq r9, xmm15
movdqu XMMWORD PTR [rcx+r12], xmm0
movdqa xmm0, xmm4
mov rcx, QWORD PTR [rsp+32]
movdqu XMMWORD PTR [rax+r12], xmm1
mov rax, rcx
shl rax, 32
movaps xmm1, xmm12
xor r9, rax
psrldq xmm0, 8
lea r8, QWORD PTR [rcx+rcx]
mov QWORD PTR [r11], rsi
add r8d, edi
mov QWORD PTR [r11+8], r14
movq rax, xmm0
mov ecx, -2147483647
or r8, rcx
xor rsi, r10
div r8
mov r10, rdi
xor r14, rbx
mov eax, eax
and r10d, 131056
shl rdx, 32
add r10, r13
add rdx, rax
xor r9, QWORD PTR [r10]
mov r11, QWORD PTR [r10+8]
lea r8, QWORD PTR [rdx+rdi]
mov rax, r8
movq xmm15, rdx
shr rax, 12
movq xmm0, rax
paddq xmm0, xmm11
sqrtsd xmm1, xmm0
movq rdx, xmm1
mov rax, rdx
shr rax, 20
shr rdx, 19
mov rcx, rdx
sub rcx, rax
sub rcx, QWORD PTR [rsp+16]
movdqa xmm9, xmm7
movdqa xmm7, xmm6
add rax, QWORD PTR [rsp+216]
imul rcx, rax
mov rax, r9
sub rcx, r8
mov rcx, rdi
adc rdx, 0
xor rcx, 32
and ecx, 131056
mov QWORD PTR [rsp+32], rdx
movdqu xmm1, XMMWORD PTR [rcx+r13]
mul rdi
paddq xmm1, xmm5
mov r8, rax
xor r8, QWORD PTR [rcx+r13+8]
add r15, r8
movq xmm0, rax
movq xmm2, rdx
xor rdx, QWORD PTR [rcx+r13]
mov rax, rdi
xor rdi, 16
punpcklqdq xmm2, xmm0
xor rax, 48
and edi, 131056
and eax, 131056
add rbp, rdx
pxor xmm2, XMMWORD PTR [rdi+r13]
movdqu xmm0, XMMWORD PTR [rax+r13]
paddq xmm2, xmm10
movdqu XMMWORD PTR [rdi+r13], xmm2
paddq xmm0, xmm8
movdqu XMMWORD PTR [rcx+r13], xmm0
movdqa xmm10, xmm8
movdqu XMMWORD PTR [rax+r13], xmm1
movdqa xmm8, xmm4
mov QWORD PTR [r10], rbp
xor rbp, r9
mov QWORD PTR [r10+8], r15
xor r15, r11
sub QWORD PTR [rsp+8], 1
jne upx2_main_loop
ldmxcsr DWORD PTR [rsp+24]
movaps xmm13, XMMWORD PTR [rsp+80]
lea r11, QWORD PTR [rsp+232]
movaps xmm6, XMMWORD PTR [r11-24]
movaps xmm7, XMMWORD PTR [r11-40]
movaps xmm8, XMMWORD PTR [r11-56]
movaps xmm9, XMMWORD PTR [r11-72]
movaps xmm10, XMMWORD PTR [r11-88]
movaps xmm11, XMMWORD PTR [r11-104]
movaps xmm12, XMMWORD PTR [r11-120]
movaps xmm14, XMMWORD PTR [rsp+64]
movaps xmm15, XMMWORD PTR [rsp+48]
mov rsp, r11
pop r15
pop r14
pop r13
pop r12
pop rdi
pop rsi
pop rbp
pop rbx

View File

@@ -17,6 +17,7 @@
.global FN_PREFIX(cnv2_double_mainloop_sandybridge_asm)
.global FN_PREFIX(cnv2_rwz_mainloop_asm)
.global FN_PREFIX(cnv2_rwz_double_mainloop_asm)
.global FN_PREFIX(cnv2_upx_double_mainloop_zen3_asm)
ALIGN(64)
FN_PREFIX(cnv2_mainloop_ivybridge_asm):
@@ -72,6 +73,15 @@ FN_PREFIX(cnv2_rwz_double_mainloop_asm):
ret 0
mov eax, 3735929054
ALIGN(64)
FN_PREFIX(cnv2_upx_double_mainloop_zen3_asm):
sub rsp, 48
mov rcx, rdi
#include "cn2/cnv2_upx_double_mainloop_zen3.inc"
add rsp, 48
ret 0
mov eax, 3735929054
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

View File

@@ -48,5 +48,12 @@ cnv2_rwz_double_mainloop_asm PROC
mov eax, 3735929054
cnv2_rwz_double_mainloop_asm ENDP
ALIGN(64)
cnv2_upx_double_mainloop_zen3_asm PROC
INCLUDE cn2/cnv2_upx_double_mainloop_zen3.inc
ret 0
mov eax, 3735929054
cnv2_upx_double_mainloop_zen3_asm ENDP
_TEXT_CNV2_MAINLOOP ENDS
END

View File

@@ -0,0 +1,320 @@
mov rax, rsp
push rbx
push rbp
push rsi
push rdi
push r12
push r13
push r14
push r15
sub rsp, 232
mov rdi, QWORD PTR [rcx+8]
mov edx, 768
mov rbx, QWORD PTR [rcx]
mov ecx, 256
movaps XMMWORD PTR [rax-88], xmm6
movaps XMMWORD PTR [rax-104], xmm7
mov r13, QWORD PTR [rdi+224]
movd xmm0, QWORD PTR [rdi+104]
mov r12, QWORD PTR [rbx+224]
movaps XMMWORD PTR [rax-120], xmm8
movaps XMMWORD PTR [rax-136], xmm9
movaps XMMWORD PTR [rax-152], xmm10
movaps XMMWORD PTR [rsp+112], xmm11
movaps XMMWORD PTR [rsp+96], xmm12
movaps XMMWORD PTR [rsp+80], xmm13
movd xmm13, QWORD PTR [rbx+96]
movaps XMMWORD PTR [rsp+64], xmm14
movd xmm14, QWORD PTR [rbx+104]
movaps XMMWORD PTR [rsp+48], xmm15
movd xmm15, QWORD PTR [rdi+96]
mov QWORD PTR [rsp], r13
movdqa XMMWORD PTR [rsp+32], xmm0
stmxcsr DWORD PTR [rsp+24]
mov DWORD PTR [rsp+28], 16256
ldmxcsr DWORD PTR [rsp+28]
mov rcx, QWORD PTR [rbx+56]
xorps xmm12, xmm12
xor rcx, QWORD PTR [rbx+24]
mov rax, QWORD PTR [rbx+48]
xor rax, QWORD PTR [rbx+16]
mov rsi, QWORD PTR [rbx+32]
mov rbp, QWORD PTR [rdi+32]
movd xmm0, rcx
mov rcx, QWORD PTR [rbx+88]
xor rcx, QWORD PTR [rbx+72]
movd xmm7, rax
mov rax, QWORD PTR [rbx+80]
xor rax, QWORD PTR [rbx+64]
mov r14, QWORD PTR [rbx+40]
mov r15, QWORD PTR [rdi+40]
xor rsi, QWORD PTR [rbx]
xor rbp, QWORD PTR [rdi]
movd xmm9, rax
mov rax, QWORD PTR [rdi+48]
xor rax, QWORD PTR [rdi+16]
xor r14, QWORD PTR [rbx+8]
xor r15, QWORD PTR [rdi+8]
movd xmm8, rax
punpcklqdq xmm7, xmm0
mov eax, 1023
shl rax, 52
movd xmm11, rax
punpcklqdq xmm11, xmm11
mov rax, QWORD PTR [rdi+80]
movd xmm0, rcx
mov rcx, QWORD PTR [rdi+56]
xor rcx, QWORD PTR [rdi+24]
punpcklqdq xmm9, xmm0
mov QWORD PTR [rsp+8], 16384
movd xmm0, rcx
mov rcx, QWORD PTR [rdi+88]
xor rcx, QWORD PTR [rdi+72]
xor rax, QWORD PTR [rdi+64]
punpcklqdq xmm8, xmm0
movd xmm0, rcx
movd xmm10, rax
mov rax, 4389456576511
mov QWORD PTR [rsp+16], rax
mov rax, -4389456576512
mov QWORD PTR [rsp+216], rax
punpcklqdq xmm10, xmm0
ALIGN(64)
upx2_main_loop:
mov rdx, rsi
mov r9, rbp
and edx, 131056
and r9d, 131056
movdqu xmm6, XMMWORD PTR [rdx+r12]
lea r8, QWORD PTR [rdx+r12]
movdqu xmm4, XMMWORD PTR [r9+r13]
lea r10, QWORD PTR [r9+r13]
mov ecx, edx
mov eax, edx
xor rax, 32
xor rcx, 48
xor rdx, 16
movd xmm0, r14
movd xmm3, rsi
movd xmm5, rbp
punpcklqdq xmm3, xmm0
movd xmm0, r15
movdqu xmm2, XMMWORD PTR [rax+r12]
movdqu xmm1, XMMWORD PTR [rcx+r12]
paddq xmm2, xmm3
punpcklqdq xmm5, xmm0
paddq xmm1, xmm7
aesenc xmm6, xmm3
aesenc xmm4, xmm5
movdqa xmm0, xmm9
movd rdi, xmm4
paddq xmm0, XMMWORD PTR [rdx+r12]
movdqu XMMWORD PTR [rdx+r12], xmm0
xor edx, edx
movdqu XMMWORD PTR [rax+r12], xmm1
movdqa xmm0, xmm6
movdqu XMMWORD PTR [rcx+r12], xmm2
pxor xmm0, xmm7
movdqu XMMWORD PTR [r8], xmm0
mov ecx, r9d
xor rcx, 48
mov eax, r9d
xor rax, 32
xor r9, 16
movdqa xmm0, xmm10
movdqu xmm1, XMMWORD PTR [rcx+r13]
movdqu xmm2, XMMWORD PTR [rax+r13]
paddq xmm1, xmm8
paddq xmm0, XMMWORD PTR [r9+r13]
paddq xmm2, xmm5
movdqu XMMWORD PTR [r9+r13], xmm0
movd r9, xmm6
movdqu XMMWORD PTR [rax+r13], xmm1
movdqa xmm0, xmm4
movdqu XMMWORD PTR [rcx+r13], xmm2
pxor xmm0, xmm8
movdqu XMMWORD PTR [r10], xmm0
movd rcx, xmm14
mov rax, rcx
movd r10, xmm13
shl rax, 32
movdqa xmm0, xmm6
xor r10, rax
psrldq xmm0, 8
lea r8, QWORD PTR [rcx+rcx]
movd rax, xmm0
add r8d, r9d
mov ecx, -2147483647
or r8, rcx
mov r11, r9
div r8
and r11d, 131056
movaps xmm1, xmm12
mov eax, eax
add r11, r12
shl rdx, 32
add rdx, rax
xor r10, QWORD PTR [r11]
mov rbx, QWORD PTR [r11+8]
lea r8, QWORD PTR [rdx+r9]
movd xmm13, rdx
mov rax, r8
shr rax, 12
movd xmm0, rax
paddq xmm0, xmm11
sqrtsd xmm1, xmm0
movd rdx, xmm1
mov rax, rdx
shr rdx, 19
shr rax, 20
mov rcx, rdx
sub rcx, rax
add rax, QWORD PTR [rsp+216]
sub rcx, QWORD PTR [rsp+16]
mov r13, QWORD PTR [rsp]
imul rcx, rax
mov rax, r10
sub rcx, r8
mov rcx, r9
adc rdx, 0
xor rcx, 32
and ecx, 131056
movd xmm14, rdx
movdqu xmm1, XMMWORD PTR [rcx+r12]
mul r9
paddq xmm1, xmm3
mov r8, rax
xor r8, QWORD PTR [rcx+r12+8]
add r14, r8
movd xmm0, rax
movd xmm2, rdx
xor rdx, QWORD PTR [rcx+r12]
mov rax, r9
xor rax, 48
punpcklqdq xmm2, xmm0
and eax, 131056
add rsi, rdx
xor r9, 16
xor edx, edx
and r9d, 131056
movdqu xmm0, XMMWORD PTR [rax+r12]
paddq xmm0, xmm7
pxor xmm2, XMMWORD PTR [r9+r12]
paddq xmm2, xmm9
movdqu XMMWORD PTR [r9+r12], xmm2
movd r9, xmm15
movdqu XMMWORD PTR [rcx+r12], xmm0
movdqa xmm0, xmm4
mov rcx, QWORD PTR [rsp+32]
movdqu XMMWORD PTR [rax+r12], xmm1
mov rax, rcx
shl rax, 32
movaps xmm1, xmm12
xor r9, rax
psrldq xmm0, 8
lea r8, QWORD PTR [rcx+rcx]
mov QWORD PTR [r11], rsi
add r8d, edi
mov QWORD PTR [r11+8], r14
movd rax, xmm0
mov ecx, -2147483647
or r8, rcx
xor rsi, r10
div r8
mov r10, rdi
xor r14, rbx
mov eax, eax
and r10d, 131056
shl rdx, 32
add r10, r13
add rdx, rax
xor r9, QWORD PTR [r10]
mov r11, QWORD PTR [r10+8]
lea r8, QWORD PTR [rdx+rdi]
mov rax, r8
movd xmm15, rdx
shr rax, 12
movd xmm0, rax
paddq xmm0, xmm11
sqrtsd xmm1, xmm0
movd rdx, xmm1
mov rax, rdx
shr rax, 20
shr rdx, 19
mov rcx, rdx
sub rcx, rax
sub rcx, QWORD PTR [rsp+16]
movdqa xmm9, xmm7
movdqa xmm7, xmm6
add rax, QWORD PTR [rsp+216]
imul rcx, rax
mov rax, r9
sub rcx, r8
mov rcx, rdi
adc rdx, 0
xor rcx, 32
and ecx, 131056
mov QWORD PTR [rsp+32], rdx
movdqu xmm1, XMMWORD PTR [rcx+r13]
mul rdi
paddq xmm1, xmm5
mov r8, rax
xor r8, QWORD PTR [rcx+r13+8]
add r15, r8
movd xmm0, rax
movd xmm2, rdx
xor rdx, QWORD PTR [rcx+r13]
mov rax, rdi
xor rdi, 16
punpcklqdq xmm2, xmm0
xor rax, 48
and edi, 131056
and eax, 131056
add rbp, rdx
pxor xmm2, XMMWORD PTR [rdi+r13]
movdqu xmm0, XMMWORD PTR [rax+r13]
paddq xmm2, xmm10
movdqu XMMWORD PTR [rdi+r13], xmm2
paddq xmm0, xmm8
movdqu XMMWORD PTR [rcx+r13], xmm0
movdqa xmm10, xmm8
movdqu XMMWORD PTR [rax+r13], xmm1
movdqa xmm8, xmm4
mov QWORD PTR [r10], rbp
xor rbp, r9
mov QWORD PTR [r10+8], r15
xor r15, r11
sub QWORD PTR [rsp+8], 1
jne upx2_main_loop
ldmxcsr DWORD PTR [rsp+24]
movaps xmm13, XMMWORD PTR [rsp+80]
lea r11, QWORD PTR [rsp+232]
movaps xmm6, XMMWORD PTR [r11-24]
movaps xmm7, XMMWORD PTR [r11-40]
movaps xmm8, XMMWORD PTR [r11-56]
movaps xmm9, XMMWORD PTR [r11-72]
movaps xmm10, XMMWORD PTR [r11-88]
movaps xmm11, XMMWORD PTR [r11-104]
movaps xmm12, XMMWORD PTR [r11-120]
movaps xmm14, XMMWORD PTR [rsp+64]
movaps xmm15, XMMWORD PTR [rsp+48]
mov rsp, r11
pop r15
pop r14
pop r13
pop r12
pop rdi
pop rsi
pop rbp
pop rbx

View File

@@ -7,6 +7,7 @@
.global cnv2_double_mainloop_sandybridge_asm
.global cnv2_rwz_mainloop_asm
.global cnv2_rwz_double_mainloop_asm
.global cnv2_upx_double_mainloop_zen3_asm
ALIGN(64)
cnv2_mainloop_ivybridge_asm:
@@ -43,3 +44,9 @@ cnv2_rwz_double_mainloop_asm:
#include "cn2/cnv2_rwz_double_main_loop.inc"
ret 0
mov eax, 3735929054
ALIGN(64)
cnv2_upx_double_mainloop_zen3_asm:
#include "cn2/cnv2_upx_double_mainloop_zen3.inc"
ret 0
mov eax, 3735929054

View File

@@ -48,5 +48,12 @@ cnv2_rwz_double_mainloop_asm PROC
mov eax, 3735929054
cnv2_rwz_double_mainloop_asm ENDP
ALIGN(64)
cnv2_upx_double_mainloop_zen3_asm PROC
INCLUDE cn2/cnv2_upx_double_mainloop_zen3.inc
ret 0
mov eax, 3735929054
cnv2_upx_double_mainloop_zen3_asm ENDP
_TEXT_CNV2_MAINLOOP ENDS
END

View File

@@ -278,6 +278,7 @@ typedef int64x2_t __m128i; /* 128-bit vector containing integers */
#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f64(x)
#define vreinterpretq_u32_m128d(x) vreinterpretq_u32_f64(x)
#define vreinterpretq_u64_m128d(x) vreinterpretq_u64_f64(x)
#define vreinterpretq_f64_m128d(x) (x)
@@ -342,10 +343,10 @@ typedef union ALIGN_STRUCT(16) SIMDVec {
/* Backwards compatibility for compilers with lack of specific type support */
// Older gcc does not define vld1q_u8_x4 type
#if defined(__GNUC__) && !defined(__clang__) && \
((__GNUC__ == 10 && (__GNUC_MINOR__ <= 2)) || \
(__GNUC__ == 9 && (__GNUC_MINOR__ <= 3)) || \
(__GNUC__ == 8 && (__GNUC_MINOR__ <= 4)) || __GNUC__ <= 7)
#if defined(__GNUC__) && !defined(__clang__) && \
((__GNUC__ <= 10 && defined(__arm__)) || \
(__GNUC__ == 10 && __GNUC_MINOR__ < 3 && defined(__aarch64__)) || \
(__GNUC__ <= 9 && defined(__aarch64__)))
FORCE_INLINE uint8x16x4_t _sse2neon_vld1q_u8_x4(const uint8_t *p)
{
uint8x16x4_t ret;
@@ -955,13 +956,34 @@ FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a)
vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
}
// Stores four 32-bit integer values as (as a __m128i value) at the address p.
// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
// Stores 128-bits of integer data a at the address p.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si128
FORCE_INLINE void _mm_storeu_si128(__m128i *p, __m128i a)
{
vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a));
}
// Stores 64-bits of integer data a at the address p.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si64
FORCE_INLINE void _mm_storeu_si64(void *p, __m128i a)
{
vst1q_lane_s64((int64_t *) p, vreinterpretq_s64_m128i(a), 0);
}
// Stores 32-bits of integer data a at the address p.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si32
FORCE_INLINE void _mm_storeu_si32(void *p, __m128i a)
{
vst1q_lane_s32((int32_t *) p, vreinterpretq_s32_m128i(a), 0);
}
// Stores 16-bits of integer data a at the address p.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_si16
FORCE_INLINE void _mm_storeu_si16(void *p, __m128i a)
{
vst1q_lane_s16((int16_t *) p, vreinterpretq_s16_m128i(a), 0);
}
// Stores the lower single - precision, floating - point value.
// https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx
FORCE_INLINE void _mm_store_ss(float *p, __m128 a)
@@ -2317,20 +2339,34 @@ FORCE_INLINE __m128i _mm_shuffle_epi8(__m128i a, __m128i b)
// ENDFOR
// FORCE_INLINE __m128i _mm_blend_epi16(__m128i a, __m128i b,
// __constrange(0,255) int imm)
#define _mm_blend_epi16(a, b, imm) \
__extension__({ \
const uint16_t _mask[8] = {((imm) & (1 << 0)) ? 0xFFFF : 0x0000, \
((imm) & (1 << 1)) ? 0xFFFF : 0x0000, \
((imm) & (1 << 2)) ? 0xFFFF : 0x0000, \
((imm) & (1 << 3)) ? 0xFFFF : 0x0000, \
((imm) & (1 << 4)) ? 0xFFFF : 0x0000, \
((imm) & (1 << 5)) ? 0xFFFF : 0x0000, \
((imm) & (1 << 6)) ? 0xFFFF : 0x0000, \
((imm) & (1 << 7)) ? 0xFFFF : 0x0000}; \
uint16x8_t _mask_vec = vld1q_u16(_mask); \
uint16x8_t _a = vreinterpretq_u16_m128i(a); \
uint16x8_t _b = vreinterpretq_u16_m128i(b); \
vreinterpretq_m128i_u16(vbslq_u16(_mask_vec, _b, _a)); \
#define _mm_blend_epi16(a, b, imm) \
__extension__({ \
const uint16_t _mask[8] = {((imm) & (1 << 0)) ? (uint16_t) -1 : 0x0, \
((imm) & (1 << 1)) ? (uint16_t) -1 : 0x0, \
((imm) & (1 << 2)) ? (uint16_t) -1 : 0x0, \
((imm) & (1 << 3)) ? (uint16_t) -1 : 0x0, \
((imm) & (1 << 4)) ? (uint16_t) -1 : 0x0, \
((imm) & (1 << 5)) ? (uint16_t) -1 : 0x0, \
((imm) & (1 << 6)) ? (uint16_t) -1 : 0x0, \
((imm) & (1 << 7)) ? (uint16_t) -1 : 0x0}; \
uint16x8_t _mask_vec = vld1q_u16(_mask); \
uint16x8_t _a = vreinterpretq_u16_m128i(a); \
uint16x8_t _b = vreinterpretq_u16_m128i(b); \
vreinterpretq_m128i_u16(vbslq_u16(_mask_vec, _b, _a)); \
})
// Blend packed double-precision (64-bit) floating-point elements from a and b
// using control mask imm8, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blend_pd
#define _mm_blend_pd(a, b, imm) \
__extension__({ \
const uint64_t _mask[2] = { \
((imm) & (1 << 0)) ? ~UINT64_C(0) : UINT64_C(0), \
((imm) & (1 << 1)) ? ~UINT64_C(0) : UINT64_C(0)}; \
uint64x2_t _mask_vec = vld1q_u64(_mask); \
uint64x2_t _a = vreinterpretq_u64_m128d(a); \
uint64x2_t _b = vreinterpretq_u64_m128d(b); \
vreinterpretq_m128d_u64(vbslq_u64(_mask_vec, _b, _a)); \
})
// Blend packed 8-bit integers from a and b using mask, and store the results in
@@ -2434,8 +2470,7 @@ FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
__m128i ret; \
if (unlikely(imm) == 0) { \
ret = a; \
} \
if (likely(0 < (imm) && (imm) < 16)) { \
} else if (likely(0 < (imm) && (imm) < 16)) { \
ret = vreinterpretq_m128i_u16( \
vshlq_u16(vreinterpretq_u16_m128i(a), vdupq_n_s16(-imm))); \
} else { \
@@ -2463,8 +2498,7 @@ FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
__m128i ret; \
if (unlikely((imm) == 0)) { \
ret = a; \
} \
if (likely(0 < (imm) && (imm) < 32)) { \
} else if (likely(0 < (imm) && (imm) < 32)) { \
ret = vreinterpretq_m128i_u32( \
vshlq_u32(vreinterpretq_u32_m128i(a), vdupq_n_s32(-imm))); \
} else { \
@@ -2491,8 +2525,7 @@ FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
__m128i ret; \
if (unlikely((imm) == 0)) { \
ret = a; \
} \
if (likely(0 < (imm) && (imm) < 64)) { \
} else if (likely(0 < (imm) && (imm) < 64)) { \
ret = vreinterpretq_m128i_u64( \
vshlq_u64(vreinterpretq_u64_m128i(a), vdupq_n_s64(-imm))); \
} else { \
@@ -2520,8 +2553,7 @@ FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
__m128i ret; \
if (unlikely((imm) == 0)) { \
ret = a; \
} \
if (likely(0 < (imm) && (imm) < 32)) { \
} else if (likely(0 < (imm) && (imm) < 32)) { \
ret = vreinterpretq_m128i_s32( \
vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(-imm))); \
} else { \
@@ -2575,6 +2607,33 @@ FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm)
ret; \
})
// Compute the square root of packed double-precision (64-bit) floating-point
// elements in a, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sqrt_pd
FORCE_INLINE __m128d _mm_sqrt_pd(__m128d a)
{
#if defined(__aarch64__)
return vreinterpretq_m128d_f64(vsqrtq_f64(vreinterpretq_f64_m128d(a)));
#else
double a0 = sqrt(((double *) &a)[0]);
double a1 = sqrt(((double *) &a)[1]);
return _mm_set_pd(a1, a0);
#endif
}
// Compute the square root of the lower double-precision (64-bit) floating-point
// element in b, store the result in the lower element of dst, and copy the
// upper element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sqrt_sd
FORCE_INLINE __m128d _mm_sqrt_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return _mm_move_sd(a, _mm_sqrt_pd(b));
#else
return _mm_set_pd(((double *) &a)[1], sqrt(((double *) &b)[0]));
#endif
}
// Shifts the 8 signed or unsigned 16-bit integers in a left by count bits while
// shifting in zeros.
//
@@ -2769,6 +2828,16 @@ FORCE_INLINE int _mm_movemask_epi8(__m128i a)
return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8);
}
// Set each bit of mask dst based on the most significant bit of the
// corresponding packed double-precision (64-bit) floating-point element in a.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movemask_pd
FORCE_INLINE int _mm_movemask_pd(__m128d a)
{
uint64x2_t input = vreinterpretq_u64_m128d(a);
uint64x2_t high_bits = vshrq_n_u64(input, 63);
return vgetq_lane_u64(high_bits, 0) | (vgetq_lane_u64(high_bits, 1) << 1);
}
// Copy the lower 64-bit integer in a to dst.
//
// dst[63:0] := a[63:0]
@@ -2944,6 +3013,13 @@ FORCE_INLINE __m128i _mm_subs_epu8(__m128i a, __m128i b)
vqsubq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
}
#define _mm_ucomieq_sd _mm_comieq_sd
#define _mm_ucomige_sd _mm_comige_sd
#define _mm_ucomigt_sd _mm_comigt_sd
#define _mm_ucomile_sd _mm_comile_sd
#define _mm_ucomilt_sd _mm_comilt_sd
#define _mm_ucomineq_sd _mm_comineq_sd
// Subtracts the 16 signed 8-bit integers of b from the 16 signed 8-bit integers
// of a and saturates.
//
@@ -3805,6 +3881,32 @@ FORCE_INLINE __m128 _mm_fmadd_ps(__m128 a, __m128 b, __m128 c)
#endif
}
// Alternatively add and subtract packed double-precision (64-bit)
// floating-point elements in a to/from packed elements in b, and store the
// results in dst.
//
// FOR j := 0 to 1
// i := j*64
// IF ((j & 1) == 0)
// dst[i+63:i] := a[i+63:i] - b[i+63:i]
// ELSE
// dst[i+63:i] := a[i+63:i] + b[i+63:i]
// FI
// ENDFOR
//
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_addsub_pd
FORCE_INLINE __m128d _mm_addsub_pd(__m128d a, __m128d b)
{
__m128d mask = _mm_set_pd(1.0f, -1.0f);
#if defined(__aarch64__)
return vreinterpretq_m128d_f64(vfmaq_f64(vreinterpretq_f64_m128d(a),
vreinterpretq_f64_m128d(b),
vreinterpretq_f64_m128d(mask)));
#else
return _mm_add_pd(_mm_mul_pd(b, mask), a);
#endif
}
// Alternatively add and subtract packed single-precision (32-bit)
// floating-point elements in a to/from packed elements in b, and store the
// results in dst.
@@ -4032,6 +4134,7 @@ FORCE_INLINE __m128 _mm_sqrt_ss(__m128 in)
// Computes the approximations of the reciprocal square roots of the four
// single-precision floating point values of in.
// The current precision is 1% error.
// https://msdn.microsoft.com/en-us/library/22hfsh53(v=vs.100).aspx
FORCE_INLINE __m128 _mm_rsqrt_ps(__m128 in)
{
@@ -4240,6 +4343,22 @@ FORCE_INLINE __m128d _mm_max_pd(__m128d a, __m128d b)
#endif
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b, store the maximum value in the lower element of dst, and copy the upper
// element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_sd
FORCE_INLINE __m128d _mm_max_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return _mm_move_sd(a, _mm_max_pd(a, b));
#else
double *da = (double *) &a;
double *db = (double *) &b;
double c[2] = {fmax(da[0], db[0]), da[1]};
return vld1q_f32((float32_t *) c);
#endif
}
// Computes the pairwise minima of the 16 unsigned 8-bit integers from a and the
// 16 unsigned 8-bit integers from b.
// https://msdn.microsoft.com/ko-kr/library/17k8cf58(v=vs.100).aspxx
@@ -4249,6 +4368,42 @@ FORCE_INLINE __m128i _mm_min_epu8(__m128i a, __m128i b)
vminq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b)));
}
// Compare packed double-precision (64-bit) floating-point elements in a and b,
// and store packed minimum values in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pd
FORCE_INLINE __m128d _mm_min_pd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return vreinterpretq_m128d_f64(
vminq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
#else
uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
uint64_t d[2];
d[0] = (*(double *) &a0) < (*(double *) &b0) ? a0 : b0;
d[1] = (*(double *) &a1) < (*(double *) &b1) ? a1 : b1;
return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b, store the minimum value in the lower element of dst, and copy the upper
// element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_sd
FORCE_INLINE __m128d _mm_min_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return _mm_move_sd(a, _mm_min_pd(a, b));
#else
double *da = (double *) &a;
double *db = (double *) &b;
double c[2] = {fmin(da[0], db[0]), da[1]};
return vld1q_f32((float32_t *) c);
#endif
}
// Computes the pairwise minima of the 8 signed 16-bit integers from a and the 8
// signed 16-bit integers from b.
// https://msdn.microsoft.com/en-us/library/vstudio/6te997ew(v=vs.100).aspx
@@ -4448,6 +4603,23 @@ FORCE_INLINE __m128i _mm_hadd_epi16(__m128i _a, __m128i _b)
#endif
}
// Horizontally subtract adjacent pairs of double-precision (64-bit)
// floating-point elements in a and b, and pack the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_pd
FORCE_INLINE __m128d _mm_hsub_pd(__m128d _a, __m128d _b)
{
#if defined(__aarch64__)
return vreinterpretq_m128d_f64(vsubq_f64(
vuzp1q_f64(vreinterpretq_f64_m128d(_a), vreinterpretq_f64_m128d(_b)),
vuzp2q_f64(vreinterpretq_f64_m128d(_a), vreinterpretq_f64_m128d(_b))));
#else
double *da = (double *) &_a;
double *db = (double *) &_b;
double c[] = {da[0] - da[1], db[0] - db[1]};
return vreinterpretq_m128d_u64(vld1q_u64((uint64_t *) c));
#endif
}
// Horizontally substract adjacent pairs of single-precision (32-bit)
// floating-point elements in a and b, and pack the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_ps
@@ -4808,6 +4980,57 @@ FORCE_INLINE __m128d _mm_cmpeq_pd(__m128d a, __m128d b)
#endif
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b for equality, store the result in the lower element of dst, and copy the
// upper element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpeq_sd
FORCE_INLINE __m128d _mm_cmpeq_sd(__m128d a, __m128d b)
{
return _mm_move_sd(a, _mm_cmpeq_pd(a, b));
}
// Compare packed double-precision (64-bit) floating-point elements in a and b
// for greater-than-or-equal, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_pd
FORCE_INLINE __m128d _mm_cmpge_pd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return vreinterpretq_m128d_u64(
vcgeq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
#else
uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
uint64_t d[2];
d[0] = (*(double *) &a0) >= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
d[1] = (*(double *) &a1) >= (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b for greater-than-or-equal, store the result in the lower element of dst,
// and copy the upper element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpge_sd
FORCE_INLINE __m128d _mm_cmpge_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return _mm_move_sd(a, _mm_cmpge_pd(a, b));
#else
// expand "_mm_cmpge_pd()" to reduce unnecessary operations
uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
uint64_t d[2];
d[0] = (*(double *) &a0) >= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
d[1] = a1;
return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
// Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or
// unsigned 16-bit integers in b for equality.
// https://msdn.microsoft.com/en-us/library/2ay060te(v=vs.100).aspx
@@ -4872,6 +5095,95 @@ FORCE_INLINE __m128d _mm_cmplt_pd(__m128d a, __m128d b)
#endif
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b for less-than, store the result in the lower element of dst, and copy the
// upper element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmplt_sd
FORCE_INLINE __m128d _mm_cmplt_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return _mm_move_sd(a, _mm_cmplt_pd(a, b));
#else
uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
uint64_t d[2];
d[0] = (*(double *) &a0) < (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
d[1] = a1;
return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
// Compare packed double-precision (64-bit) floating-point elements in a and b
// for not-equal, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_pd
FORCE_INLINE __m128d _mm_cmpneq_pd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return vreinterpretq_m128d_s32(vmvnq_s32(vreinterpretq_s32_u64(
vceqq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)))));
#else
// (a == b) -> (a_lo == b_lo) && (a_hi == b_hi)
uint32x4_t cmp =
vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b));
uint32x4_t swapped = vrev64q_u32(cmp);
return vreinterpretq_m128d_u32(vmvnq_u32(vandq_u32(cmp, swapped)));
#endif
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b for not-equal, store the result in the lower element of dst, and copy the
// upper element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpneq_sd
FORCE_INLINE __m128d _mm_cmpneq_sd(__m128d a, __m128d b)
{
return _mm_move_sd(a, _mm_cmpneq_pd(a, b));
}
// Compare packed double-precision (64-bit) floating-point elements in a and b
// for not-greater-than-or-equal, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnge_pd
FORCE_INLINE __m128d _mm_cmpnge_pd(__m128d a, __m128d b)
{
return _mm_cmplt_pd(a, b);
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b for not-greater-than-or-equal, store the result in the lower element of
// dst, and copy the upper element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpnge_sd
FORCE_INLINE __m128d _mm_cmpnge_sd(__m128d a, __m128d b)
{
return _mm_cmplt_sd(a, b);
}
// Compare packed double-precision (64-bit) floating-point elements in a and b
// for not-greater-than, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_cmpngt_pd
#define _mm_cmpngt_pd(a, b) _mm_cmple_pd(a, b)
// Compare the lower double-precision (64-bit) floating-point element in a and b
// for equality, and return the boolean result (0 or 1).
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comieq_sd
FORCE_INLINE int _mm_comieq_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return !!vgetq_lane_u64(vceqq_f64(a, b), 0);
#else
uint32x4_t a_not_nan =
vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(a));
uint32x4_t b_not_nan =
vceqq_u32(vreinterpretq_u32_m128d(b), vreinterpretq_u32_m128d(b));
uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan);
uint32x4_t a_eq_b =
vceqq_u32(vreinterpretq_u32_m128d(a), vreinterpretq_u32_m128d(b));
uint64x2_t and_results = vandq_u64(vreinterpretq_u64_u32(a_and_b_not_nan),
vreinterpretq_u64_u32(a_eq_b));
return !!vgetq_lane_u64(and_results, 0);
#endif
}
// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers
// in b for greater than.
//
@@ -4887,6 +5199,90 @@ FORCE_INLINE __m128i _mm_cmpgt_epi8(__m128i a, __m128i b)
vcgtq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b)));
}
// Compare packed double-precision (64-bit) floating-point elements in a and b
// for greater-than, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_pd
FORCE_INLINE __m128d _mm_cmpgt_pd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return vreinterpretq_m128d_u64(
vcgtq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
#else
uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
uint64_t d[2];
d[0] = (*(double *) &a0) > (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
d[1] = (*(double *) &a1) > (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b for greater-than, store the result in the lower element of dst, and copy
// the upper element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmpgt_sd
FORCE_INLINE __m128d _mm_cmpgt_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return _mm_move_sd(a, _mm_cmpgt_pd(a, b));
#else
// expand "_mm_cmpge_pd()" to reduce unnecessary operations
uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
uint64_t d[2];
d[0] = (*(double *) &a0) > (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
d[1] = a1;
return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
// Compare packed double-precision (64-bit) floating-point elements in a and b
// for less-than-or-equal, and store the results in dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_pd
FORCE_INLINE __m128d _mm_cmple_pd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return vreinterpretq_m128d_u64(
vcleq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b)));
#else
uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
uint64_t b1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(b));
uint64_t d[2];
d[0] = (*(double *) &a0) <= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
d[1] = (*(double *) &a1) <= (*(double *) &b1) ? ~UINT64_C(0) : UINT64_C(0);
return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
// Compare the lower double-precision (64-bit) floating-point elements in a and
// b for less-than-or-equal, store the result in the lower element of dst, and
// copy the upper element from a to the upper element of dst.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cmple_sd
FORCE_INLINE __m128d _mm_cmple_sd(__m128d a, __m128d b)
{
#if defined(__aarch64__)
return _mm_move_sd(a, _mm_cmple_pd(a, b));
#else
// expand "_mm_cmpge_pd()" to reduce unnecessary operations
uint64_t a0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(a));
uint64_t a1 = (uint64_t) vget_high_u64(vreinterpretq_u64_m128d(a));
uint64_t b0 = (uint64_t) vget_low_u64(vreinterpretq_u64_m128d(b));
uint64_t d[2];
d[0] = (*(double *) &a0) <= (*(double *) &b0) ? ~UINT64_C(0) : UINT64_C(0);
d[1] = a1;
return vreinterpretq_m128d_u64(vld1q_u64(d));
#endif
}
// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers
// in b for less than.
//
@@ -4944,31 +5340,9 @@ FORCE_INLINE __m128i _mm_cmpgt_epi64(__m128i a, __m128i b)
return vreinterpretq_m128i_u64(
vcgtq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)));
#else
// ARMv7 lacks vcgtq_s64.
// This is based off of Clang's SSE2 polyfill:
// (a > b) -> ((a_hi > b_hi) || (a_lo > b_lo && a_hi == b_hi))
// Mask the sign bit out since we need a signed AND an unsigned comparison
// and it is ugly to try and split them.
int32x4_t mask = vreinterpretq_s32_s64(vdupq_n_s64(0x80000000ull));
int32x4_t a_mask = veorq_s32(vreinterpretq_s32_m128i(a), mask);
int32x4_t b_mask = veorq_s32(vreinterpretq_s32_m128i(b), mask);
// Check if a > b
int64x2_t greater = vreinterpretq_s64_u32(vcgtq_s32(a_mask, b_mask));
// Copy upper mask to lower mask
// a_hi > b_hi
int64x2_t gt_hi = vshrq_n_s64(greater, 63);
// Copy lower mask to upper mask
// a_lo > b_lo
int64x2_t gt_lo = vsliq_n_s64(greater, greater, 32);
// Compare for equality
int64x2_t equal = vreinterpretq_s64_u32(vceqq_s32(a_mask, b_mask));
// Copy upper mask to lower mask
// a_hi == b_hi
int64x2_t eq_hi = vshrq_n_s64(equal, 63);
// a_hi > b_hi || (a_lo > b_lo && a_hi == b_hi)
int64x2_t ret = vorrq_s64(gt_hi, vandq_s64(gt_lo, eq_hi));
return vreinterpretq_m128i_s64(ret);
return vreinterpretq_m128i_s64(vshrq_n_s64(
vqsubq_s64(vreinterpretq_s64_m128i(b), vreinterpretq_s64_m128i(a)),
63));
#endif
}
@@ -5368,6 +5742,28 @@ FORCE_INLINE __m128d _mm_cvtepi32_pd(__m128i a)
#endif
}
// Convert packed signed 32-bit integers in a to packed double-precision
// (64-bit) floating-point elements, and store the results in dst.
//
// FOR j := 0 to 1
// i := j*32
// m := j*64
// dst[m+63:m] := Convert_Int32_To_FP64(a[i+31:i])
// ENDFOR
//
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32_pd
FORCE_INLINE __m128d _mm_cvtpi32_pd(__m64 a)
{
#if defined(__aarch64__)
return vreinterpretq_m128d_f64(
vcvtq_f64_s64(vmovl_s32(vreinterpret_s32_m64(a))));
#else
double a0 = (double) vget_lane_s32(vreinterpret_s32_m64(a), 0);
double a1 = (double) vget_lane_s32(vreinterpret_s32_m64(a), 1);
return _mm_set_pd(a1, a0);
#endif
}
// Converts the four unsigned 8-bit integers in the lower 16 bits to four
// unsigned 32-bit integers.
FORCE_INLINE __m128i _mm_cvtepu8_epi16(__m128i a)
@@ -5647,6 +6043,15 @@ FORCE_INLINE __m128d _mm_load1_pd(const double *p)
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd1
#define _mm_load_pd1 _mm_load1_pd
// Load a double-precision (64-bit) floating-point element from memory into both
// elements of dst.
//
// dst[63:0] := MEM[mem_addr+63:mem_addr]
// dst[127:64] := MEM[mem_addr+63:mem_addr]
//
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loaddup_pd
#define _mm_loaddup_pd _mm_load1_pd
// Load a double-precision (64-bit) floating-point element from memory into the
// upper element of dst, and copy the lower element from a to dst. mem_addr does
// not need to be aligned on any particular boundary.
@@ -6986,6 +7391,14 @@ FORCE_INLINE void _mm_sfence(void)
__sync_synchronize();
}
// Store 64-bits of integer data from a into memory using a non-temporal memory
// hint.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_pi
FORCE_INLINE void _mm_stream_pi(__m64 *p, __m64 a)
{
vst1_s64((int64_t *) p, vreinterpret_s64_m64(a));
}
// Store 128-bits (composed of 4 packed single-precision (32-bit) floating-
// point elements) from a into memory using a non-temporal memory hint.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_ps
@@ -6998,6 +7411,22 @@ FORCE_INLINE void _mm_stream_ps(float *p, __m128 a)
#endif
}
// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point
// elements) from a into memory using a non-temporal memory hint. mem_addr must
// be aligned on a 16-byte boundary or a general-protection exception may be
// generated.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_pd
FORCE_INLINE void _mm_stream_pd(double *p, __m128d a)
{
#if __has_builtin(__builtin_nontemporal_store)
__builtin_nontemporal_store(a, (float32x4_t *) p);
#elif defined(__aarch64__)
vst1q_f64(p, vreinterpretq_f64_m128d(a));
#else
vst1q_s64((int64_t *) p, vreinterpretq_s64_m128d(a));
#endif
}
// Stores the data in a to the address p without polluting the caches. If the
// cache line containing address p is already in the cache, the cache will be
// updated.
@@ -7011,6 +7440,15 @@ FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a)
#endif
}
// Store 32-bit integer a into memory using a non-temporal hint to minimize
// cache pollution. If the cache line containing address mem_addr is already in
// the cache, the cache will be updated.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_si32
FORCE_INLINE void _mm_stream_si32(int *p, int a)
{
vst1q_lane_s32((int32_t *) p, vdupq_n_s32(a), 0);
}
// Load 128-bits of integer data from memory into dst using a non-temporal
// memory hint. mem_addr must be aligned on a 16-byte boundary or a
// general-protection exception may be generated.
@@ -7065,6 +7503,12 @@ FORCE_INLINE void _mm_maskmove_si64(__m64 a, __m64 mask, char *mem_addr)
vst1_s8((int8_t *) mem_addr, masked);
}
// Conditionally store 8-bit integer elements from a into memory using mask
// (elements are not stored when the highest bit is not set in the corresponding
// element) and a non-temporal memory hint.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_maskmovq
#define _m_maskmovq(a, mask, mem_addr) _mm_maskmove_si64(a, mask, mem_addr)
// Free aligned memory that was allocated with _mm_malloc.
// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_free
FORCE_INLINE void _mm_free(void *addr)

View File

@@ -41,7 +41,7 @@ public:
size_t size = 0;
inline bool isFullyAllocated() const { return allocated == total; }
inline double percent() const { return allocated == 0 ? 0.0 : static_cast<double>(allocated) / total * 100.0; }
inline double percent() const { return total == 0 ? 0.0 : static_cast<double>(allocated) / total * 100.0; }
inline void reset() { allocated = 0; total = 0; size = 0; }
inline HugePagesInfo &operator+=(const HugePagesInfo &other)

View File

@@ -0,0 +1,17 @@
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
db 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 81
add rsp, 128

View File

@@ -22,6 +22,7 @@
mov rsi, rdx ;# uint8_t* scratchpad
mov rax, rbp
ror rbp, 32
;# zero integer registers
xor r8, r8

View File

@@ -35,6 +35,7 @@
mov rbx, r9 ;# loop counter
mov rax, rbp
ror rbp, 32
;# zero integer registers
xor r8, r8

View File

@@ -1,17 +1,16 @@
mov ecx, ebp ;# ecx = ma
and ecx, RANDOMX_DATASET_BASE_MASK
xor r8, qword ptr [rdi+rcx]
ror rbp, 32 ;# swap "ma" and "mx"
xor rbp, rax ;# modify "mx"
mov edx, ebp ;# edx = mx
and edx, RANDOMX_DATASET_BASE_MASK
prefetchnta byte ptr [rdi+rdx]
ror rbp, 32 ;# swap "ma" and "mx"
mov edx, ebp ;# edx = ma
and edx, RANDOMX_DATASET_BASE_MASK
lea rcx, [rdi+rdx] ;# dataset cache line
xor r8, qword ptr [rcx+0]
xor r9, qword ptr [rcx+8]
xor r10, qword ptr [rcx+16]
xor r11, qword ptr [rcx+24]
xor r12, qword ptr [rcx+32]
xor r13, qword ptr [rcx+40]
xor r14, qword ptr [rcx+48]
xor r15, qword ptr [rcx+56]
xor r9, qword ptr [rdi+rcx+8]
xor r10, qword ptr [rdi+rcx+16]
xor r11, qword ptr [rdi+rcx+24]
xor r12, qword ptr [rdi+rcx+32]
xor r13, qword ptr [rdi+rcx+40]
xor r14, qword ptr [rdi+rcx+48]
xor r15, qword ptr [rdi+rcx+56]

View File

@@ -1,17 +0,0 @@
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 edx, ebp ;# edx = mx
and edx, RANDOMX_DATASET_BASE_MASK
prefetchnta byte ptr [rdi+rdx]
ror rbp, 32 ;# swap "ma" and "mx"
xor r9, qword ptr [rdi+rcx+8]
xor r10, qword ptr [rdi+rcx+16]
xor r11, qword ptr [rdi+rcx+24]
xor r12, qword ptr [rdi+rcx+32]
xor r13, qword ptr [rdi+rcx+40]
xor r14, qword ptr [rdi+rcx+48]
xor r15, qword ptr [rdi+rcx+56]

View File

@@ -7,4 +7,4 @@
xor r13, qword ptr [rsp+16]
xor r14, qword ptr [rsp+8]
xor r15, qword ptr [rsp+0]
add rsp, 72
add rsp, 200

View File

@@ -1,4 +1,4 @@
sub rsp, 72
sub rsp, 200
mov qword ptr [rsp+64], rbx
mov qword ptr [rsp+56], r8
mov qword ptr [rsp+48], r9
@@ -8,10 +8,10 @@
mov qword ptr [rsp+16], r13
mov qword ptr [rsp+8], r14
mov qword ptr [rsp+0], r15
xor rbp, rax ;# modify "mx"
ror rbp, 32 ;# swap "ma" and "mx"
mov ebx, ebp ;# ecx = ma
and ebx, RANDOMX_DATASET_BASE_MASK
shr ebx, 6 ;# ebx = Dataset block number
xor rbp, rax ;# modify "mx"
mov rbx, rbp ;# ebx = ma
shr rbx, 38
and ebx, RANDOMX_DATASET_BASE_MASK / 64 ;# ebx = Dataset block number
;# add ebx, datasetOffset / 64
;# call 32768

View File

@@ -304,6 +304,9 @@ literal_v14: .fill 2,8,0
literal_v15: .fill 2,8,0
DECL(randomx_program_aarch64_vm_instructions_end):
# Calculate dataset pointer for dataset read
# Do it here to break false dependency from readReg2 and readReg3 (see next line)
lsr x10, x9, 32
# mx ^= r[readReg2] ^ r[readReg3];
eor x9, x9, x18
@@ -321,8 +324,6 @@ DECL(randomx_program_aarch64_cacheline_align_mask1):
# mx <-> ma
ror x9, x9, 32
# Calculate dataset pointer for dataset read
mov w10, w9
DECL(randomx_program_aarch64_cacheline_align_mask2):
# Actual mask will be inserted by JIT compiler
and x10, x10, 1

View File

@@ -110,13 +110,12 @@ namespace randomx {
#define ADDR(x) ((uint8_t*)&x)
# endif
#define codePrefetchScratchpad ADDR(randomx_prefetch_scratchpad)
#define codePrefetchScratchpadEnd ADDR(randomx_prefetch_scratchpad_end)
#define codePrologue ADDR(randomx_program_prologue)
#define codeLoopBegin ADDR(randomx_program_loop_begin)
#define codeLoopLoad ADDR(randomx_program_loop_load)
#define codeLoopLoadXOP ADDR(randomx_program_loop_load_xop)
#define codeProgamStart ADDR(randomx_program_start)
#define codeReadDataset ADDR(randomx_program_read_dataset)
#define codeReadDatasetLightSshInit ADDR(randomx_program_read_dataset_sshash_init)
#define codeReadDatasetLightSshFin ADDR(randomx_program_read_dataset_sshash_fin)
#define codeDatasetInit ADDR(randomx_dataset_init)
@@ -134,10 +133,10 @@ namespace randomx {
#define codeShhEnd ADDR(randomx_sshash_end)
#define codeShhInit ADDR(randomx_sshash_init)
#define prefetchScratchpadSize (codePrefetchScratchpadEnd - codePrefetchScratchpad)
#define prologueSize (codeLoopBegin - codePrologue)
#define loopLoadSize (codeLoopLoadXOP - codeLoopLoad)
#define loopLoadXOPSize (codeProgamStart - codeLoopLoadXOP)
#define readDatasetSize (codeReadDatasetLightSshInit - codeReadDataset)
#define readDatasetLightInitSize (codeReadDatasetLightSshFin - codeReadDatasetLightSshInit)
#define readDatasetLightFinSize (codeLoopStore - codeReadDatasetLightSshFin)
#define loopStoreSize (codeLoopEnd - codeLoopStore)
@@ -321,26 +320,13 @@ namespace randomx {
vm_flags = flags;
generateProgramPrologue(prog, pcfg);
uint8_t* p;
uint32_t n;
if (flags & RANDOMX_FLAG_AMD) {
p = RandomX_CurrentConfig.codeReadDatasetRyzenTweaked;
n = RandomX_CurrentConfig.codeReadDatasetRyzenTweakedSize;
}
else {
p = RandomX_CurrentConfig.codeReadDatasetTweaked;
n = RandomX_CurrentConfig.codeReadDatasetTweakedSize;
}
memcpy(code + codePos, p, n);
codePos += n;
emit(codeReadDataset, readDatasetSize, code, codePos);
generateProgramEpilogue(prog, pcfg);
}
void JitCompilerX86::generateProgramLight(Program& prog, ProgramConfiguration& pcfg, uint32_t datasetOffset) {
generateProgramPrologue(prog, pcfg);
emit(RandomX_CurrentConfig.codeReadDatasetLightSshInitTweaked, readDatasetLightInitSize, code, codePos);
emit(codeReadDatasetLightSshInit, readDatasetLightInitSize, code, codePos);
*(uint32_t*)(code + codePos) = 0xc381;
codePos += 2;
emit32(datasetOffset / CacheLineSize, code, codePos);
@@ -428,7 +414,10 @@ namespace randomx {
xmrig::RxFix::setMainLoopBounds(mainLoopBounds);
# endif
memcpy(code + prologueSize - 48, &pcfg.eMask, sizeof(pcfg.eMask));
imul_rcp_storage = code + (ADDR(randomx_program_imul_rcp_store) - codePrologue) + 2;
imul_rcp_storage_used = 0;
memcpy(imul_rcp_storage - 34, &pcfg.eMask, sizeof(pcfg.eMask));
codePos = codePosFirst;
prevCFROUND = 0;
@@ -464,7 +453,7 @@ namespace randomx {
void JitCompilerX86::generateProgramEpilogue(Program& prog, ProgramConfiguration& pcfg) {
*(uint64_t*)(code + codePos) = 0xc03349c08b49ull + (static_cast<uint64_t>(pcfg.readReg0) << 16) + (static_cast<uint64_t>(pcfg.readReg1) << 40);
codePos += 6;
emit(RandomX_CurrentConfig.codePrefetchScratchpadTweaked, prefetchScratchpadSize, code, codePos);
emit(RandomX_CurrentConfig.codePrefetchScratchpadTweaked, RandomX_CurrentConfig.codePrefetchScratchpadTweakedSize, code, codePos);
memcpy(code + codePos, codeLoopStore, loopStoreSize);
codePos += loopStoreSize;
@@ -1012,13 +1001,24 @@ namespace randomx {
uint64_t divisor = instr.getImm32();
if (!isZeroOrPowerOf2(divisor)) {
*(uint32_t*)(p + pos) = 0xb848;
pos += 2;
emit64(randomx_reciprocal_fast(divisor), p, pos);
const uint32_t dst = instr.dst % RegistersCount;
emit32(0xc0af0f4c + (dst << 27), p, pos);
const uint64_t reciprocal = randomx_reciprocal_fast(divisor);
if (imul_rcp_storage_used < 16) {
*(uint64_t*)(imul_rcp_storage) = reciprocal;
*(uint64_t*)(p + pos) = 0x2444AF0F4Cull + (dst << 27) + (static_cast<uint64_t>(248 - imul_rcp_storage_used * 8) << 40);
++imul_rcp_storage_used;
imul_rcp_storage += 11;
pos += 6;
}
else {
*(uint32_t*)(p + pos) = 0xb848;
pos += 2;
emit64(reciprocal, p, pos);
emit32(0xc0af0f4c + (dst << 27), p, pos);
}
registerUsage[dst] = pos;
}

View File

@@ -104,6 +104,9 @@ namespace randomx {
uint8_t* allocatedCode = nullptr;
size_t allocatedSize = 0;
uint8_t* imul_rcp_storage = nullptr;
uint32_t imul_rcp_storage_used = 0;
void generateProgramPrologue(Program&, ProgramConfiguration&);
void generateProgramEpilogue(Program&, ProgramConfiguration&);
template<bool rax>

View File

@@ -38,15 +38,16 @@
#endif
.global DECL(randomx_prefetch_scratchpad)
.global DECL(randomx_prefetch_scratchpad_bmi2)
.global DECL(randomx_prefetch_scratchpad_end)
.global DECL(randomx_program_prologue)
.global DECL(randomx_program_prologue_first_load)
.global DECL(randomx_program_imul_rcp_store)
.global DECL(randomx_program_loop_begin)
.global DECL(randomx_program_loop_load)
.global DECL(randomx_program_loop_load_xop)
.global DECL(randomx_program_start)
.global DECL(randomx_program_read_dataset)
.global DECL(randomx_program_read_dataset_ryzen)
.global DECL(randomx_program_read_dataset_sshash_init)
.global DECL(randomx_program_read_dataset_sshash_fin)
.global DECL(randomx_program_loop_store)
@@ -79,6 +80,13 @@ DECL(randomx_prefetch_scratchpad):
and edx, RANDOMX_SCRATCHPAD_MASK
prefetcht0 [rsi+rdx]
DECL(randomx_prefetch_scratchpad_bmi2):
rorx rdx, rax, 32
and eax, RANDOMX_SCRATCHPAD_MASK
prefetcht0 [rsi+rax]
and edx, RANDOMX_SCRATCHPAD_MASK
prefetcht0 [rsi+rdx]
DECL(randomx_prefetch_scratchpad_end):
.balign 64
@@ -106,11 +114,15 @@ DECL(randomx_program_prologue_first_load):
nop
nop
nop
jmp DECL(randomx_program_loop_begin)
jmp DECL(randomx_program_imul_rcp_store)
.balign 64
#include "asm/program_xmm_constants.inc"
DECL(randomx_program_imul_rcp_store):
#include "asm/program_imul_rcp_store.inc"
jmp DECL(randomx_program_loop_begin)
.balign 64
DECL(randomx_program_loop_begin):
nop
@@ -127,9 +139,6 @@ DECL(randomx_program_start):
DECL(randomx_program_read_dataset):
#include "asm/program_read_dataset.inc"
DECL(randomx_program_read_dataset_ryzen):
#include "asm/program_read_dataset_ryzen.inc"
DECL(randomx_program_read_dataset_sshash_init):
#include "asm/program_read_dataset_sshash_init.inc"

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