1
0
mirror of https://github.com/xmrig/xmrig.git synced 2026-06-28 13:42:43 -04:00

Compare commits

..

602 Commits

Author SHA1 Message Date
MoneroOcean b6a93022f7 Fixed KCN algo 2024-06-01 11:18:15 +03:00
MoneroOcean 95d6482e2f Revert "Separate input/output flex_hash memory"
This reverts commit 2d1d781efa.
2024-06-01 11:17:57 +03:00
MoneroOcean 9d8e9add07 Fixed KCN algo 2024-06-01 11:17:47 +03:00
MoneroOcean 2d1d781efa Separate input/output flex_hash memory 2024-05-31 20:58:21 +03:00
MoneroOcean 3d8bf1036b Correct flex algo hashrate calc 2024-05-30 23:42:17 +03:00
MoneroOcean a7ebb05653 Correct flex algo hashrate calc 2024-05-30 23:42:17 +03:00
MoneroOcean d4252f7133 Correct flex algo hashrate calc 2024-05-30 23:42:17 +03:00
MoneroOcean 20184c6c9f Merge pull request #138 from Spudz76/pr-mo-fix-MODE_AUTO_ETH
Pool.h: missing ifdef like everywhere else MODE_AUTO_ETH is used
2024-05-29 20:43:52 -07:00
MoneroOcean 0ba8b72a2b Merge pull request #139 from Spudz76/pr-mo-algo-ordering
MoBenchmark: avoid flipping MSR back and forth during benchmark
2024-05-29 20:43:14 -07:00
Tony Butler f5e235c97c MoBenchmark: avoid flipping MSR back and forth during benchmark 2024-05-29 11:58:28 -06:00
Tony Butler be215004aa Pool.h: missing ifdef like everywhere else MODE_AUTO_ETH is used 2024-05-29 10:58:53 -06:00
MoneroOcean 5e90875050 Fixed compilation error with MSVC 2022 2024-05-29 19:32:51 +03:00
MoneroOcean 68c41aa45b Merge pull request #137 from Spudz76/pr-mo-flex-msvc-error
flex: fix compilation error with MSVC 2022
2024-05-29 09:31:28 -07:00
MoneroOcean 2a90c51f69 Merge branch 'master' into pr-mo-flex-msvc-error 2024-05-29 09:31:00 -07:00
MoneroOcean 4499c943be Flex algo ARM fix 2024-05-29 19:17:58 +03:00
MoneroOcean 92f27606df Flex algo ARM fix 2024-05-29 19:13:43 +03:00
Tony Butler 60b8d904c2 flex: fix compilation error with MSVC 2022 2024-05-29 10:10:24 -06:00
MoneroOcean 525530b012 Fixed issue with mining not working after brnchmark 2024-05-29 18:51:21 +03:00
MoneroOcean 0079b3c160 Merge pull request #133 from Spudz76/pr-mo-fix-disabled-algos
MoBenchmark: use ifdefs to avoid bugs when algos are compiled out
2024-05-29 08:49:19 -07:00
MoneroOcean dcf20f5f82 Merge pull request #135 from Spudz76/pr-mo-flex-warnings
flex: fix various warnings
2024-05-29 08:48:18 -07:00
MoneroOcean 700ba19244 Merge pull request #136 from Spudz76/pr-mo-algo_perf-zeros
MoBenchmark: don't write algo_perf==0.0 items to config
2024-05-29 08:46:27 -07:00
MoneroOcean 7e9881bbe6 Merge pull request #134 from Spudz76/pr-mo-fix-no-results
MoBenchmark: restore listener at the end of finish()
2024-05-29 08:45:14 -07:00
Tony Butler 7a34e3f901 MoBenchmark: don't write algo_perf==0.0 items to config 2024-05-29 09:01:24 -06:00
Tony Butler 85aca86d79 flex: fix various warnings 2024-05-29 08:16:23 -06:00
Tony Butler 976c3c2e76 MoBenchmark: restore listener at the end of finish() 2024-05-29 08:05:09 -06:00
Tony Butler 8c88ada9ea MoBenchmark: use ifdefs to avoid bugs when algos are compiled out 2024-05-29 07:45:22 -06:00
MoneroOcean adb372408a Improved Flex algo speed 2024-05-29 03:20:28 +03:00
MoneroOcean 35ede29509 Improved Flex algo speed 2024-05-29 03:07:40 +03:00
MoneroOcean 0ec9860f49 Do not rerun benchmark for disabled backends 2024-05-29 00:57:45 +03:00
MoneroOcean eca08bc751 Do not rerun benchmark for disabled backends 2024-05-29 00:57:35 +03:00
MoneroOcean 734bdb6e14 Fixed Flex algo multithread issue 2024-05-28 22:37:17 +03:00
MoneroOcean 6c890b437c Fixed Flex algo multithread issue 2024-05-28 22:36:24 +03:00
MoneroOcean 43f73163d2 Improved MO benchmark logic 2024-05-27 22:30:54 -07:00
MoneroOcean a936d10725 Improved MO benchmark logic 2024-05-27 22:30:27 -07:00
MoneroOcean 69b5f93a1b Fixed seg faults for Intel CPUs 2024-05-27 18:08:55 -07:00
MoneroOcean ce2a38e59a XEQ PR adjustment 2024-05-28 03:28:57 +03:00
AdminXeq bfebb46d62 Update CMakeLists.txt 2024-05-28 03:18:38 +03:00
m@lbit e40dffac86 RandomXEQ added 2024-05-28 03:17:05 +03:00
MoneroOcean 09b15aca7a MacOS fix 2024-05-27 11:20:45 -07:00
MoneroOcean bf3831c05b Add Flex algo (for KCN coin) algo support 2024-05-27 11:03:46 -07:00
MoneroOcean 7445870414 new gcc fix 2024-05-02 04:28:08 +03:00
MoneroOcean 9d537fc2ad Merge xmrig v6.21.3 2024-04-26 09:18:59 -07:00
MoneroOcean b14fcf3745 Update deploy.yml 2024-03-24 10:09:17 -07:00
MoneroOcean 1e758c9090 Update test.yml 2024-03-24 09:57:34 -07:00
MoneroOcean c313c1795f Merged xmrig v6.21.2 2024-03-24 09:42:58 -07:00
MoneroOcean 923dbdf429 Merged xmrig v6.21.1 2024-02-25 10:23:30 -08:00
MoneroOcean 06c383eddb Updated release build to Ubuntu 22.04 2024-01-13 02:10:44 +00:00
MoneroOcean 0925865286 Merge xmrig v6.21.0 into master 2023-11-23 16:26:11 +00:00
MoneroOcean 245822ff1f Merged xmrig v6.20.0 2023-07-03 21:05:03 +00:00
MoneroOcean 402b70c5bb Merge xmrig v6.20.0 into master 2023-07-03 17:02:50 +00:00
MoneroOcean f17975703c Merge xmrig v6.19.3 into master 2023-06-03 20:01:47 +00:00
MoneroOcean b7c536073d Merge xmrig v6.19.2 into master 2023-04-04 22:23:59 +00:00
MoneroOcean 2c543fe47a Merge xmrig v6.19.1 into master 2023-03-23 16:24:34 +00:00
MoneroOcean b8b5b8003b Merge xmrig v6.19.0 into master 2023-02-14 23:39:04 +00:00
MoneroOcean ea561aca4d Merge xmrig v6.18.1 into master 2022-10-23 18:33:57 +00:00
MoneroOcean 6e89f28d97 Post merge fix 2022-06-23 17:49:44 +00:00
MoneroOcean 4b6759adf9 Merge xmrig v6.18.0 into master 2022-06-23 17:43:36 +00:00
MoneroOcean 8ddf8de6b7 Switched mo bench from DERO to DERO HE 2022-03-31 21:31:48 +00:00
MoneroOcean e4eb9ea581 Merge xmrig v6.16.5-dev into master 2022-03-31 21:25:07 +00:00
MoneroOcean 72abe1174a Merge xmrig v6.14.0 into master 2022-02-04 15:35:26 +00:00
MoneroOcean 2a53e73ed5 Merge xmrig v6.16.3 into master 2022-01-25 18:56:52 +00:00
MoneroOcean bbe90047b8 Merge pull request #83 from Spudz76/ocean-master-cleanupCNGPU
Most of the checks for CN_GPU aren't needed as they are never called
2021-12-13 20:04:19 -08:00
Tony Butler 69ac8baec5 Most of the checks for CN_GPU aren't needed as they are never called 2021-12-04 23:00:07 -07:00
MoneroOcean bdeb44ec15 Disabled VAES for cn/gpu 2021-12-03 17:01:03 +00:00
MoneroOcean 615715e215 Merge xmrig v6.16.2 into master 2021-12-02 15:29:31 +00:00
MoneroOcean eab57aab40 Windows RTM fix 2021-12-02 15:12:57 +00:00
SChernykh 53dfbae437 Explicitly use QueryPerformanceCounter() on Windows 2021-12-02 15:12:07 +00:00
MoneroOcean 3800f67e8a VAES crash fixes 2021-12-01 06:29:12 +00:00
SChernykh 004eab8a0b VAES crash fixes 2021-12-01 06:28:30 +00:00
MoneroOcean 523a738fca Merge pull request #81 from Spudz76/ocean-master-updateCNGPU
Update CN-GPU integration
2021-11-30 17:53:47 -08:00
Tony Butler be26d56f66 Update CN-GPU integration 2021-11-29 14:20:38 -07:00
MoneroOcean 0e5b54b80a Post merge fix 2021-11-29 16:07:39 +00:00
MoneroOcean 7f801d0904 Post merge fix 2021-11-29 15:42:51 +00:00
MoneroOcean 41d5be9c65 Merge pull request #78 from Spudz76/ocean-master-fixBenchMode
Fix upstream benchmark feature clash with MoBenchmark
2021-11-29 07:37:16 -08:00
MoneroOcean 4065036ea7 Merge pull request #77 from Spudz76/ocean-master-fixMemleaks
Fix various memory leaks
2021-11-29 07:36:46 -08:00
MoneroOcean ecdb1929e2 Merge xmrig v6.16.1 into master 2021-11-29 15:34:55 +00:00
Tony Butler c807e955d3 Fix upstream benchmark feature clash with MoBenchmark 2021-11-27 13:34:15 -07:00
Tony Butler 6f5cbd7e53 Fix various memory leaks 2021-11-27 13:34:13 -07:00
MoneroOcean dabb2f7118 Added GR bench 2021-11-27 00:09:09 +00:00
MoneroOcean 1a0df95d66 Added GR bench 2021-11-27 00:06:43 +00:00
MoneroOcean 3c907d6bc4 Fixed float/double algo_perf support 2021-11-26 23:39:17 +00:00
MoneroOcean 67d796e7b5 Fixed GR algo support 2021-11-26 23:12:59 +00:00
MoneroOcean e3320d766d Fixed merge 2021-11-26 22:29:12 +00:00
MoneroOcean 2feb99053f Fixed GR algo bench support 2021-11-26 22:14:31 +00:00
MoneroOcean 9afe95e454 Merge xmrig v6.16.0 into master 2021-11-26 21:58:55 +00:00
MoneroOcean 449982aad2 Merge xmrig v6.15.3 into master 2021-11-01 16:46:52 +00:00
MoneroOcean f60350ed6c https://github.com/MoneroOcean/xmrig/issues/70 fix 2021-10-25 21:46:55 +00:00
MoneroOcean cf10b0ca26 Merge pull request #76 from Spudz76/ocean-master-fixAPIConfigCrash
Fix for crash when sending config via API
2021-10-25 14:44:54 -07:00
Tony Butler 53e2715638 Fix for crash when sending config via API 2021-10-24 04:05:15 -06:00
MoneroOcean 5aebdb84bd Increased version 2021-10-20 02:09:30 +00:00
MoneroOcean 39a77fa92d Merge branch 'master' of github.com:moneroocean/xmrig into master 2021-10-20 02:08:43 +00:00
MoneroOcean 7261d47c0e Merge pull request #71 from Spudz76/ocean-master-addAlgoMinTime
Add algo-min-time option same as meta-miner
2021-10-19 19:08:09 -07:00
Tony Butler 28b86148ed Add algo-min-time option same as meta-miner 2021-10-12 15:51:18 -06:00
MoneroOcean 6e39eee85b Merge xmrig v6.15.2 into master 2021-10-05 18:28:55 +00:00
MoneroOcean 22ab8c6254 Merge xmrig v6.15.2 into master 2021-10-05 18:09:31 +00:00
MoneroOcean 349303201a Merge xmrig v6.15.2 into master 2021-10-05 18:00:25 +00:00
MoneroOcean 356ff5c700 Merge xmrig v6.15.0 into master 2021-08-31 17:19:43 +00:00
MoneroOcean 097462e12e Merge xmrig v6.15.0 into master 2021-08-31 17:15:47 +00:00
MoneroOcean 7c13cbfc98 Merge xmrig v6.15.0 into master 2021-08-31 17:14:32 +00:00
MoneroOcean aceef09f1f Merge xmrig v6.15.0 into master 2021-08-31 17:13:03 +00:00
MoneroOcean 13f721dd78 Merge xmrig v6.15.0 into master 2021-08-31 17:07:49 +00:00
MoneroOcean 29fa5c61e0 Merge xmrig v6.15.0 into master 2021-08-31 16:45:39 +00:00
MoneroOcean e76dcad6bc Merge xmrig v6.14.1 into master 2021-08-15 04:51:41 +00:00
MoneroOcean 13bb0f14e1 Merge xmrig v6.14.1 into master 2021-08-15 04:41:24 +00:00
MoneroOcean efb40419e8 Merge xmrig v6.14.1 into master 2021-08-14 20:47:43 +00:00
MoneroOcean 054c0a174b Merge xmrig v6.14.1 into master 2021-08-14 20:39:58 +00:00
MoneroOcean 945a9cbcb9 Merge xmrig v6.14.1 into master 2021-08-14 20:33:50 +00:00
MoneroOcean 9d0d6ad9b6 Merge xmrig v6.14.1 into master 2021-08-14 20:12:23 +00:00
MoneroOcean 5579440640 Merge xmrig v6.14.0 into master 2021-08-10 14:41:29 +00:00
MoneroOcean 74f39ac947 Merge xmrig v6.14.0 into master 2021-08-10 14:32:19 +00:00
MoneroOcean ea93d0a3ad https://github.com/MoneroOcean/xmrig/issues/59 fix 2021-06-01 00:21:28 +00:00
MoneroOcean 62b422d5b7 Merge pull request #60 from Spudz76/ocean-master-fixAsteriskProfile
Fix --threads generates "*" profile without "kawpow":false to negate it.
2021-06-01 00:20:22 +00:00
MoneroOcean 027a39e22f Merge fix 2021-05-31 16:09:10 +00:00
MoneroOcean 442353b31e Revert "RandomX: rewrote dataset read code"
This reverts commit ff82ca57f2.
2021-05-31 16:01:50 +00:00
MoneroOcean 8a1ca690eb Revert "Merge fix"
This reverts commit 36b38d88a1.
2021-05-31 16:01:39 +00:00
MoneroOcean 36b38d88a1 Merge fix 2021-05-31 15:37:30 +00:00
MoneroOcean 28ad107de8 Merge xmrig v6.12.2 into master 2021-05-31 15:06:47 +00:00
Tony Butler ba2f07a1f7 Fix --threads generates "*" profile without "kawpow":false to negate it. 2021-05-30 08:32:12 -06:00
MoneroOcean 4c6d815b19 Added ARM and some CUDA fixes 2021-05-17 21:50:11 +00:00
MoneroOcean fef0e217c1 Merge pull request #53 from Spudz76/ocean-master-revertCNGPUinterleave
Revert cn/gpu interleave (fixes ARM / Apple M1)
2021-05-17 21:49:05 +00:00
MoneroOcean b765a6d3fb Merge pull request #55 from Spudz76/ocean-master-saveBeforeBenchmark
Check and save any autosized algos before launching the moBenchmark
2021-05-17 21:48:27 +00:00
Tony Butler 50bffd39d8 Check and save any autosized algos before launching the moBenchmark 2021-05-17 02:06:22 -06:00
Tony Butler 59f1b7d19b Revert cn/gpu interleave (fixes ARM / Apple M1) 2021-05-16 01:11:03 -06:00
MoneroOcean b0beffc4f0 Fixing https://github.com/MoneroOcean/xmrig/issues/50, https://github.com/MoneroOcean/xmrig/issues/41 and https://github.com/MoneroOcean/xmrig/pull/44. Thank you https://github.com/Spudz76 2021-04-27 22:28:32 +00:00
MoneroOcean 76122aedf4 Merge pull request #42 from Spudz76/fixMSVC
Adjust panthera code for MSVC 2019 compilation (fixes #41)
2021-04-27 22:23:28 +00:00
MoneroOcean 76d0982296 Merge pull request #44 from Spudz76/fixWithoutKawPow
Fix SIGSEGV when compiled without KAWPOW
2021-04-27 22:22:38 +00:00
MoneroOcean 289139a5be Merge pull request #43 from Spudz76/updateCNGPU
Collection of CN-GPU fixes and updates
2021-04-27 22:18:00 +00:00
MoneroOcean 3fdd5375be Merge xmrig v6.12.1 into master 2021-04-23 14:08:13 +00:00
MoneroOcean 699db24ce7 Fixed syntax error 2021-04-20 18:00:41 +00:00
MoneroOcean bc20f3a1d5 Fixed syntax error 2021-04-20 17:56:33 +00:00
MoneroOcean ce3a19cec1 Merge xmrig v6.12.0 into master 2021-04-20 17:07:20 +00:00
MoneroOcean 13a6b1f7b5 Merge xmrig v6.11.2 into master 2021-04-11 11:36:45 +00:00
MoneroOcean 6c75526d3e Merge xmrig v6.11.1 into master 2021-04-07 04:15:47 +00:00
MoneroOcean fd8ed2c6a6 Merge xmrig v6.11.0 into master 2021-04-06 15:17:08 +00:00
Tony Butler 50c6ad9449 Fix SIGSEGV when compiled without KAWPOW 2021-03-26 16:37:37 -06:00
Tony Butler 57d9d3ea7c Collection of CN-GPU fixes and updates 2021-03-26 16:25:58 -06:00
Tony Butler 504f608871 Adjust panthera code for MSVC 2019 compilation (fixes #41) 2021-03-26 15:48:20 -06:00
MoneroOcean 174663bb50 Fixed issue with XLA rejected shares 2021-03-12 03:56:53 +00:00
MoneroOcean 4fe9f373a4 Fixed issue with XLA 2021-03-12 03:39:00 +00:00
MoneroOcean 777765b4fd Removed DefyX support 2021-03-12 00:25:59 +00:00
MoneroOcean 5d35f324fc Merge xmrig v6.10.0 into master 2021-03-08 03:34:30 +00:00
MoneroOcean 4108d2d823 Added hwloc and ssl into compat build 2021-03-06 01:15:37 +00:00
MoneroOcean 7c6289b331 Added hwloc and ssl into compat build 2021-03-06 01:12:08 +00:00
MoneroOcean 1b89b14886 Added hwloc into compat build 2021-03-06 00:57:02 +00:00
MoneroOcean a0e2ac262c Added hwloc into compat build 2021-03-06 00:55:29 +00:00
MoneroOcean da669975e1 Added hwloc into compat build 2021-03-06 00:50:18 +00:00
MoneroOcean f6380d72e1 Enabled keepalive by default 2021-03-04 18:32:33 +00:00
MoneroOcean 85bc258811 Fixed hiveos dpeloy package name 2021-02-25 22:11:47 +00:00
MoneroOcean ab9287b7e2 Hiveos deploy fix 2021-02-22 01:13:00 +00:00
MoneroOcean e97fb6ee5b Hiveos deploy fix 2021-02-22 01:05:07 +00:00
MoneroOcean 89ca7edb59 Hiveos deploy fix 2021-02-22 00:57:42 +00:00
MoneroOcean ef99595476 Hiveos deploy fix 2021-02-22 00:48:22 +00:00
MoneroOcean aa0b9280e2 Merge fix 2021-02-22 00:37:11 +00:00
MoneroOcean 344c967881 Added hiveos mo_xmrig miner update 2021-02-22 00:33:12 +00:00
MoneroOcean 158bf879c1 Merge xmrig v6.9.0 into master 2021-02-22 00:24:10 +00:00
MoneroOcean cfe1469c43 Removed heavy tube algo from mo bench 2021-02-20 18:31:28 +00:00
MoneroOcean 5088fbdfad Merge xmrig v6.8.2 into master 2021-02-12 16:55:03 +00:00
MoneroOcean eebb03a9eb Switched to higher diff port 2021-02-10 03:20:05 +00:00
MoneroOcean 5dce0225b3 Updated to newer gcc for compat build 2021-02-03 05:09:25 +00:00
MoneroOcean 6cc0c74351 Merge xmrig v6.8.1 into master 2021-02-03 01:15:49 +00:00
MoneroOcean 0c1fda1ada Merge xmrig v6.8.0 into master 2021-01-26 16:42:24 +00:00
MoneroOcean 621d6cf03e Made compat build static 2021-01-19 18:33:04 +00:00
MoneroOcean 53861b97f0 Made compat build static 2021-01-19 17:50:38 +00:00
MoneroOcean d3d1b111fb Merge xmrig v6.7.2 into master 2021-01-15 14:40:04 +00:00
MoneroOcean 3a7eb49630 Merge xmrig v6.7.1 into master 2021-01-11 16:18:29 +00:00
MoneroOcean 1719879f7e Merge xmrig v6.7.0 into master 2020-12-23 06:46:42 +00:00
MoneroOcean 966aaa72ca Merge xmrig v6.6.2 into master 2020-12-01 16:05:54 +00:00
MoneroOcean 7ddea5c68b Fixed issue with lower rx/0 perf after algo switch 2020-11-28 21:24:02 +00:00
MoneroOcean 821c04ed0e Merge xmrig v6.6.1 into master 2020-11-26 03:57:41 +00:00
MoneroOcean 54e736aaaa Merge xmrig v6.6.0 into master 2020-11-23 15:09:11 +00:00
MoneroOcean 2a6e64ca7d Merge of xmrig v6.5.3 2020-11-15 17:25:37 +00:00
MoneroOcean 77a951a6a4 Merge xmrig v6.5.2 2020-11-13 19:47:22 +00:00
MoneroOcean 60c9c0c07d Merge of xmrig v6.5.1 2020-11-08 17:21:41 +00:00
SChernykh c8cc5c573c Update RxConfig.cpp 2020-11-06 22:41:37 +00:00
SChernykh 2c0a18d140 New MSR mod for Ryzen
+3.5% on Zen2, +1-2% on Zen3
2020-11-06 22:41:31 +00:00
MoneroOcean 59f90d76a8 Possible OpenCL cn/gpu fix 2020-11-06 21:41:19 +00:00
MoneroOcean 4bc236bfcf Possible OpenCL cn/gpu fix 2020-11-06 21:40:49 +00:00
MoneroOcean 78dcdbd2dd Possible OpenCL cn/gpu fix 2020-11-06 21:40:16 +00:00
MoneroOcean 8724ce7328 Raven algo auto switch mode 2020-11-04 01:44:56 +00:00
MoneroOcean 49278bc57f Raven algo mo bench fix 2020-11-04 01:32:14 +00:00
MoneroOcean e3c96628df Raven algo mo bench fix 2020-11-04 01:30:49 +00:00
MoneroOcean e0ea3d704d Raven algo mo bench fix 2020-11-04 00:31:27 +00:00
MoneroOcean 6e63e92349 Raven algo mo bench 2020-11-03 22:29:49 +00:00
MoneroOcean 4bafc9f3c0 Raven algo auto switch mode 2020-11-03 21:33:01 +00:00
MoneroOcean d17818bb24 Raven algo auto switch mode 2020-11-03 21:27:31 +00:00
MoneroOcean a57d1bbbda Merge of xmrig v6.5.0 2020-11-02 15:08:16 +00:00
MoneroOcean 33d5563baf Disabled Panthera algo for cuda / opencl 2020-10-27 17:53:53 +00:00
MoneroOcean bdb83b555d ARM build fix 2020-10-25 18:44:22 +00:00
MoneroOcean f650a73845 Separate bench and mo bench 2020-10-25 18:41:41 +00:00
MoneroOcean e3dc4db54f Separate bench and mo bench 2020-10-25 18:39:49 +00:00
MoneroOcean b1edcb31bd Separate bench and mo bench 2020-10-25 18:39:14 +00:00
MoneroOcean 294c9acee3 ARM fix 2020-10-25 18:35:37 +00:00
MoneroOcean 81b629acad Separate bench and mo bench 2020-10-25 04:20:01 +00:00
MoneroOcean 5a8a726f69 Fixed DERO benchmark 2020-10-19 03:40:51 +00:00
MoneroOcean 37149127f4 Fixed DERO benchmark 2020-10-19 03:31:03 +00:00
MoneroOcean 08e7720f30 Algo num fix 2020-10-19 00:03:19 +00:00
MoneroOcean 5e351798e0 Algo num fix 2020-10-19 00:02:40 +00:00
MoneroOcean 7c2ebd847e Algo num fix 2020-10-19 00:01:10 +00:00
MoneroOcean ef7a7a75a2 Updated MoBenchmark names 2020-10-18 23:35:27 +00:00
MoneroOcean 6b406cf82c Updated MoBenchmark names 2020-10-18 23:33:43 +00:00
MoneroOcean 2cf2fcaf8c Merge xmrig v6.4.0 into master 2020-10-18 22:04:56 +00:00
MoneroOcean 45f45cf8cc Removed DefyX 2020-10-14 16:08:47 +00:00
MoneroOcean 61fed602be Merge xmrig v6.3.5 2020-10-03 19:45:28 +00:00
MoneroOcean f9c7ee9002 Merge xmrig v6.3.4 sources 2020-09-23 01:14:02 +00:00
MoneroOcean 8c3eae0598 Merge xmrig v6.3.4 sources 2020-09-23 01:08:40 +00:00
MoneroOcean 9514cfd7fd Merge xmrig v6.3.4 sources 2020-09-23 01:05:58 +00:00
MoneroOcean 78c018a2d6 Merge xmrig v6.3.4 sources 2020-09-23 00:56:44 +00:00
MoneroOcean c715fc618c Fixed merge errors 2020-09-23 00:50:15 +00:00
MoneroOcean 21b156cbda Merge xmrig v6.3.4 sources 2020-09-23 00:25:27 +00:00
MoneroOcean a6b6f22d08 Merge xmrig v6.3.3 2020-08-28 08:18:41 -07:00
MoneroOcean 651306a57a xmrig v6.3.2 merge 2020-08-20 08:57:55 -07:00
MoneroOcean f4f5367a78 Fixed thread limits 2020-08-20 08:57:17 -07:00
MoneroOcean 822dfe5aef Fixed thread limit 2020-08-16 13:06:42 -07:00
MoneroOcean 57e38f070a Fixed random after benchmark crash 2020-08-16 11:42:15 -07:00
MoneroOcean 58dd3294d0 Regenerated CL headers 2020-08-01 20:38:45 -07:00
MoneroOcean a979845882 xmrig v6.3.1 merge 2020-07-31 12:12:02 -07:00
MoneroOcean 22c39226b0 xmrig v6.3.1 merge 2020-07-31 12:04:00 -07:00
MoneroOcean 54ee6bbd5d Increased bench algo time for more accurate restuls 2020-07-19 09:07:12 -07:00
MoneroOcean d4164ad366 Panthera algo fix 2020-07-16 20:07:49 -07:00
MoneroOcean 5499d5a97a Panthera algo fix 2020-07-16 20:06:33 -07:00
MoneroOcean aaf1ff1460 Added Panther (new XLA) algo support 2020-07-16 18:40:37 -07:00
MoneroOcean 35edf9a93c Try to move to MinGW builds on Windows 2020-07-16 18:33:56 -07:00
MoneroOcean 38c9f4e4d7 Try to move to MinGW builds on Windows 2020-07-16 18:30:28 -07:00
MoneroOcean 2a40277cf9 Try to move to MinGW builds on Windows 2020-07-16 18:27:54 -07:00
MoneroOcean 8de748fa65 Fixed bug 2020-07-16 18:03:54 -07:00
MoneroOcean 47acc49471 Fixed bug 2020-07-16 17:59:29 -07:00
MoneroOcean b9a84ef8e1 Fixed bug 2020-07-16 17:34:44 -07:00
MoneroOcean 087715bd93 Fixed bug 2020-07-16 17:29:30 -07:00
MoneroOcean 780e2bcd1c Fixed bug 2020-07-16 17:17:17 -07:00
MoneroOcean 338b0b10f5 Fixed bug 2020-07-16 17:13:24 -07:00
MoneroOcean 176f0edef3 Fixed bug 2020-07-16 17:03:34 -07:00
MoneroOcean 48c4f3c870 Fixed bug 2020-07-16 16:55:42 -07:00
MoneroOcean b994d6f8c8 Fixed bug 2020-07-16 16:51:09 -07:00
MoneroOcean 26e91c516b Fixed bug 2020-07-16 16:50:43 -07:00
MoneroOcean 5eafa9e455 Panthera algo implementation 2020-07-16 16:43:19 -07:00
MoneroOcean 50b1bf8a1d Fixed Ryo support 2020-07-16 12:31:59 -07:00
MoneroOcean a334a9a956 xmrig v6.3.0 based release 2020-07-16 12:23:01 -07:00
MoneroOcean aa56d62a78 New Haven fork support (July 20) 2020-07-15 14:02:22 -07:00
MoneroOcean d530624a0d https://github.com/xmrig/xmrig/pull/1777 2020-07-15 14:01:06 -07:00
MoneroOcean 284a6f06d9 Updated links to mo repo variants 2020-07-14 09:34:18 -07:00
MoneroOcean a397865b54 Renamed CI file 2020-07-14 08:32:46 -07:00
MoneroOcean cb67ab46fc Merge pull request #27 from Spudz76/ocean-master-fixups
Cleanup patchset
2020-07-13 22:13:10 -07:00
Tony Butler c4ff8c4064 Cleanup MoneroOcean patchset 2020-07-10 04:02:42 -06:00
MoneroOcean aaaaf5c1ed Merged xmrig v6.2.3 2020-07-09 10:24:41 -07:00
MoneroOcean be3388b5ea Alloy algo-perf for non moneroocean.stream pools 2020-07-04 22:45:10 -07:00
MoneroOcean 316af8c2b9 xmrig v6.2.2 based release 2020-06-30 08:12:59 -07:00
MoneroOcean 5b2b02f2d7 Enabled cn/gpu and fixed low defyx bench numbers 2020-06-10 20:51:33 -07:00
MoneroOcean 29653a1ccf Moved DefyX before rx/0 to fix defyx low bench numbers 2020-06-10 20:50:27 -07:00
MoneroOcean aab5b7f55e Enabled RYO 2020-06-10 20:31:56 -07:00
Tony Butler 57e8fe51e3 Consistently name ARQ identifiers where they were ARQMA 2020-06-10 19:02:37 -07:00
Tony Butler e2ea726a6a Add new message tagging support for benchmark output 2020-06-10 19:02:10 -07:00
Tony Butler 30fdc92884 Cleanup MoneroOcean patchset 2020-06-10 18:50:25 -07:00
MoneroOcean 42235a56da Revert "Restored original xmrig algo numbers and gave ALGO_CN_GPU 1011 number to simplify future merging"
This reverts commit 92ebd18f0b.
2020-06-10 18:47:19 -07:00
MoneroOcean 717e2ac7b6 Fixed syntax error with XMRIG_ALGO_KAWPOW enabled 2020-06-10 18:43:47 -07:00
MoneroOcean 92ebd18f0b Restored original xmrig algo numbers and gave ALGO_CN_GPU 1011 number to simplify future merging 2020-06-10 18:37:41 -07:00
Tony Butler 32b49797d9 Restore CN-GPU 2020-06-10 18:17:58 -07:00
MoneroOcean 0ada4ca4ac Merge branch 'beta' of https://github.com/xmrig/xmrig 2020-06-10 18:14:06 -07:00
MoneroOcean ca42206c42 xmrig v5.11.3 based release 2020-06-10 11:42:26 -07:00
MoneroOcean 42ab70462f Moved to Ubuntu 20.04 for latest builds 2020-06-07 15:24:33 -07:00
MoneroOcean 0e753f5077 Moved to Ubuntu 20.04 for latest builds 2020-06-07 15:23:29 -07:00
MoneroOcean 135d70c361 Update XMR address 2020-06-03 17:26:48 -07:00
MoneroOcean 51c783a313 Merge https://github.com/xmrig/xmrig 2020-05-23 11:13:42 -07:00
MoneroOcean 1d74e9fd3c Fixed CentOS 6 tools 2020-04-23 09:58:12 -07:00
MoneroOcean d89305bfcb Merge https://github.com/xmrig/xmrig 2020-04-23 09:23:11 -07:00
MoneroOcean df7a8d1a52 Merge https://github.com/xmrig/xmrig 2020-04-13 09:07:40 -07:00
MoneroOcean 4fb6c935d4 Fixed nasm and MacOS cmake 2020-03-22 17:03:15 -07:00
MoneroOcean a457b5fe51 Added MacOS build and fixed compat Linux build 2020-03-22 16:51:57 -07:00
MoneroOcean ca0f93bb22 Merge https://github.com/xmrig/xmrig 2020-03-22 16:26:51 -07:00
MoneroOcean 0bb1a29c92 Updated version 2020-03-10 14:31:01 -07:00
MoneroOcean dcb1f43663 Removed extra donate-level line 2020-03-10 14:29:33 -07:00
MoneroOcean ce244d01dd Returned cn/gpu 2020-03-10 11:05:47 -07:00
MoneroOcean 75cebc4a49 Fixed Algorithm header location 2020-03-09 11:31:55 -07:00
MoneroOcean 1251f0b89a Merge branch 'dev' of https://github.com/xmrig/xmrig 2020-03-09 11:22:58 -07:00
MoneroOcean ed8d2ee136 Merge https://github.com/xmrig/xmrig 2020-03-08 10:04:33 -07:00
MoneroOcean df48cb1f98 Merge branch 'dev' of https://github.com/xmrig/xmrig 2020-03-07 09:38:20 -08:00
MoneroOcean f9287c2e14 Merge https://github.com/xmrig/xmrig 2020-03-06 08:50:55 -08:00
MoneroOcean db6a553341 Merge https://github.com/xmrig/xmrig 2020-03-04 17:58:35 -08:00
MoneroOcean b6674abb41 Merge https://github.com/xmrig/xmrig 2020-02-25 06:20:29 -10:00
MoneroOcean e71c1b51bf Merge https://github.com/xmrig/xmrig 2020-02-15 15:41:35 -08:00
MoneroOcean baeb45e8a1 Merge https://github.com/xmrig/xmrig 2020-02-02 11:22:09 -08:00
MoneroOcean 04af1b40ba Fixed xmrig_setup 2020-01-22 17:40:14 +07:00
MoneroOcean 15bfd8df94 Fixed xmrig_setup 2020-01-22 17:40:04 +07:00
MoneroOcean 4cef605258 Test xmrig_setup update 2020-01-22 17:29:21 +07:00
MoneroOcean ccfe900992 Test xmrig_setup update 2020-01-22 17:08:35 +07:00
MoneroOcean e4986059f4 Test xmrig_setup update 2020-01-22 16:54:10 +07:00
MoneroOcean b719595802 Test xmrig_setup update 2020-01-22 16:03:05 +07:00
MoneroOcean 247bb8ca0b Test xmrig_setup update 2020-01-22 15:55:59 +07:00
MoneroOcean 6b98b916fd Removed RX_V 2020-01-20 18:37:44 +07:00
MoneroOcean 4d9491fa41 Removed RX_V algo 2020-01-20 18:31:28 +07:00
MoneroOcean 1eff7fea93 Test builds 2020-01-20 18:28:39 +07:00
MoneroOcean b4c93b7ff6 Merge https://github.com/xmrig/xmrig 2020-01-20 18:24:56 +07:00
MoneroOcean 24d45ab5b5 Removed no longer needed files 2020-01-20 18:19:46 +07:00
MoneroOcean 954be16050 Fixed bug 2020-01-20 18:13:00 +07:00
MoneroOcean 7429ec5615 Fixed bug 2020-01-20 18:11:15 +07:00
MoneroOcean 31183a55fa Fixed bug 2020-01-20 17:58:05 +07:00
MoneroOcean d7a567af73 Fixed bug 2020-01-20 17:55:37 +07:00
MoneroOcean daee4aa495 Fixed bug 2020-01-20 17:51:10 +07:00
MoneroOcean e812765a1d Fixed bug 2020-01-20 17:49:28 +07:00
MoneroOcean dd38dbe795 Fixed bug 2020-01-20 17:47:05 +07:00
MoneroOcean e9a696726f Fixed bug 2020-01-20 17:41:29 +07:00
MoneroOcean 0519d17f50 Fixed bug 2020-01-20 17:39:00 +07:00
MoneroOcean 260fc1d44b Fixed bug 2020-01-20 17:25:40 +07:00
MoneroOcean 9aaf724358 Fixed bug 2020-01-20 17:13:11 +07:00
MoneroOcean 55bf6e03a7 Fixed bug 2020-01-20 17:08:39 +07:00
MoneroOcean 1523e6c263 Fixed bug 2020-01-20 16:59:46 +07:00
MoneroOcean 067fbf15f8 Fixed bug 2020-01-20 16:52:35 +07:00
MoneroOcean e956e47b12 Fixed bug 2020-01-20 16:47:12 +07:00
MoneroOcean d03b4ba9d7 Fixed bug 2020-01-20 16:45:02 +07:00
MoneroOcean 7dbced5f95 Fixed bug 2020-01-20 16:34:40 +07:00
MoneroOcean f6db5efc7e Fixed bug 2020-01-20 16:28:42 +07:00
MoneroOcean bda6727e9f Fixed bug 2020-01-20 16:23:22 +07:00
MoneroOcean 6ea9723a4d Fixed bug 2020-01-20 16:16:15 +07:00
MoneroOcean 2ffcf5721d Fixed bug 2020-01-20 16:12:02 +07:00
MoneroOcean d6b726ff2c Fixed bug 2020-01-20 16:07:26 +07:00
MoneroOcean 88fabbd7b6 Fixed bug 2020-01-20 16:04:14 +07:00
MoneroOcean 576f5b791e Fixed bug 2020-01-20 15:58:01 +07:00
MoneroOcean 4ed9f83a0f Fixed bug 2020-01-20 15:43:37 +07:00
MoneroOcean 678de08b44 Fixed bug 2020-01-20 15:34:21 +07:00
MoneroOcean 677fdda3e2 Fixed bug 2020-01-20 15:32:02 +07:00
MoneroOcean d5694b9908 Fixed bug 2020-01-20 15:28:53 +07:00
MoneroOcean dcb20d09e8 Fixed bug 2020-01-20 15:21:18 +07:00
MoneroOcean 1489966833 Fixed bug 2020-01-20 15:19:26 +07:00
MoneroOcean 29faa30182 Fixed bug 2020-01-20 15:08:59 +07:00
MoneroOcean a89a98f3db Fixed bug 2020-01-20 15:07:15 +07:00
MoneroOcean 64a25dfe08 Fixed bug 2020-01-20 14:53:37 +07:00
MoneroOcean 98c6edf994 Use CentOS 6 container 2020-01-20 14:35:33 +07:00
MoneroOcean 12e05b601c Updated for real build 2020-01-20 13:04:09 +07:00
MoneroOcean 99e4bae97e Test stuff 2020-01-20 12:36:27 +07:00
MoneroOcean 78774060fc Defyx Ryzen fix 2019-12-21 19:35:00 -08:00
MoneroOcean 4156af42b0 Merge fix 2019-12-21 18:32:52 -08:00
MoneroOcean 4d211b7160 Merge fix 2019-12-21 18:30:56 -08:00
MoneroOcean 376c870e7e Merge fix 2019-12-21 18:24:14 -08:00
MoneroOcean 5a519b6aca Merge fix 2019-12-21 18:22:02 -08:00
MoneroOcean eb58aea9c7 Merge https://github.com/xmrig/xmrig 2019-12-21 18:18:26 -08:00
MoneroOcean 4540208c9d Pack WinRing0x64.sys 2019-12-15 16:22:52 -08:00
MoneroOcean 9a5cc546c0 Added RX_V algo perf support 2019-12-15 15:44:34 -08:00
MoneroOcean c41cc3d494 Merge https://github.com/xmvdev/xmrig 2019-12-15 15:43:17 -08:00
MoneroOcean 12aeb03da2 Merge https://github.com/xmrig/xmrig 2019-12-15 15:42:31 -08:00
MoneroOcean 8fa101b6ef Updated MSVS 2019-12-14 13:25:26 -08:00
MoneroOcean 3f98d07e76 DefyX fix 2019-12-14 13:00:13 -08:00
MoneroOcean 01e2945ab7 Merge https://github.com/xmrig/xmrig 2019-12-14 09:24:11 -08:00
MoneroOcean f3e6423e9d Merge https://github.com/xmrig/xmrig 2019-12-04 10:52:07 -08:00
MoneroOcean 16d5419dce Improved code 2019-12-01 09:01:43 -08:00
MoneroOcean 066d9086b6 DefyX fix 2019-12-01 08:50:32 -08:00
MoneroOcean 14568121e2 Merge https://github.com/xmrig/xmrig 2019-12-01 08:44:04 -08:00
MoneroOcean 6e95a8ecd6 Merge https://github.com/xmrig/xmrig 2019-11-29 13:02:41 -08:00
xmvdev 78e047a398 RandomV 2019-11-24 21:19:17 +01:00
MoneroOcean da8f0fe394 Merge https://github.com/xmrig/xmrig 2019-11-13 10:40:40 -08:00
MoneroOcean a84d95926e Merge branch 'beta' of https://github.com/xmrig/xmrig 2019-11-11 08:44:29 -08:00
MoneroOcean 6dde88e573 Fixed OCL benchmark issues 2019-11-03 09:05:13 -08:00
MoneroOcean a6b46e4c58 Fixed OCL benchmark issues 2019-11-03 08:58:15 -08:00
MoneroOcean b150a26030 Added draft support for multi backend benchmark 2019-11-02 21:22:15 -07:00
MoneroOcean 149bfbf674 Added draft support for multi backend benchmark 2019-11-02 20:43:02 -07:00
MoneroOcean 8c0db9485c Added draft support for multi backend benchmark 2019-11-02 20:40:25 -07:00
MoneroOcean 0707589033 Added draft support for multi backend benchmark 2019-11-02 20:39:37 -07:00
MoneroOcean d055ed96c4 Added draft support for multi backend benchmark 2019-11-02 20:38:36 -07:00
MoneroOcean c9e7ac7f97 Added draft support for multi backend benchmark 2019-11-02 20:36:25 -07:00
MoneroOcean f131c2e5fb Added draft support for multi backend benchmark 2019-11-02 20:31:27 -07:00
MoneroOcean c208f8eb8f Merged v4.5.0-beta 2019-11-02 12:09:14 -07:00
MoneroOcean 91462b4409 Moved version 2019-10-30 08:41:53 -07:00
MoneroOcean 2ea0f405aa Added rx/0 bench 2019-10-30 08:41:15 -07:00
MoneroOcean 1c4178eedc Removed AR2_WRKZ bench 2019-10-29 14:20:28 -07:00
MoneroOcean 245838ffae Merge branch 'beta' of https://github.com/xmrig/xmrig 2019-10-29 14:19:29 -07:00
MoneroOcean b8aa42cc3d Moved version 2019-10-17 09:55:05 -07:00
MoneroOcean 5e3e8b3004 Fixed DefyX detection as rx algo 2019-10-17 09:54:32 -07:00
MoneroOcean f9bc70234f Fixed for MinGW 2019-10-15 12:41:45 -07:00
MoneroOcean eb126cba55 Merged v4.3.1-beta 2019-10-14 21:33:52 -07:00
MoneroOcean 18413f26e8 Merged v4.3.0-beta 2019-10-10 14:54:19 -07:00
MoneroOcean fe76800fc8 Merged v4.3.0-beta 2019-10-10 14:52:12 -07:00
MoneroOcean 6df49a9c6b HWLOCK fix 2 2019-10-02 15:09:00 -07:00
MoneroOcean 93690985f4 HWLOCK fix 2019-10-02 14:59:03 -07:00
MoneroOcean 97e81f2cba Moved version 2019-10-02 14:55:01 -07:00
MoneroOcean b19a0b7f51 Removed Invalid job id processing 2019-10-02 14:54:20 -07:00
MoneroOcean 5e777a5ed9 Moved version 2019-10-01 16:54:09 -07:00
XMRig 36ade0d24e #1212 Fixed RandomX dataset re-initialization. 2019-10-01 16:48:26 -07:00
MoneroOcean d03fb91b0a Resolved conflicts 2019-09-28 20:26:20 -07:00
MoneroOcean 47ba0a015b Added extra MO specific error status 2019-09-20 15:07:02 -07:00
MoneroOcean 814dda724e Moved version 2019-09-20 10:13:14 -07:00
XMRig e0640badc0 #1180 Fixed race condition in nonce reset. 2019-09-19 10:45:47 -07:00
MoneroOcean 81c1a80a71 Added opencl: false 2019-09-19 09:34:19 -07:00
MoneroOcean d2ccc0473c Simplify build 2019-09-17 21:39:22 -07:00
MoneroOcean 701d8f093a Linux build fix 2019-09-17 21:37:55 -07:00
MoneroOcean eee969efba Windows build fix 2019-09-17 21:08:26 -07:00
MoneroOcean 79cf79d512 Moved version 2019-09-17 20:59:56 -07:00
MoneroOcean 2aaaadea13 Apply Scala config correctly 2019-09-17 20:58:55 -07:00
MoneroOcean bc16c50a81 Removed CN_WOW 2019-09-17 15:58:16 -07:00
MoneroOcean 67ddfebac3 Updated setListener usage 2019-09-17 15:57:35 -07:00
MoneroOcean 993733cb1f Merged v4.0.0-beta 2019-09-17 15:48:01 -07:00
MoneroOcean 8e428cd3b3 Moved version 2019-09-11 09:38:34 -07:00
hayzamjs b255cde117 Change to yescrypt-best.c 2019-09-11 09:37:44 -07:00
MoneroOcean f694d5d9f6 Updated version 2019-09-03 11:42:19 -07:00
MoneroOcean cdc31bd97e DefyX fix 2019-09-03 11:30:56 -07:00
MoneroOcean 4f758f460f Updated version 2019-08-30 19:17:07 -07:00
MoneroOcean aa6237a834 Restored default retries 2019-08-29 13:14:17 -07:00
MoneroOcean 7714de5bff Removed useless hash 2019-08-19 11:48:15 -07:00
MoneroOcean 70cf22f50c Updated cmake version 2019-08-18 22:47:20 -07:00
MoneroOcean 2112c75ad1 Added new algo bench 2019-08-18 15:15:25 -07:00
MoneroOcean 38d9637fbc Merge 2019-08-18 15:12:11 -07:00
MoneroOcean eba2fc88f0 Merge 2019-08-18 15:10:30 -07:00
MoneroOcean 7c8b4f72c8 Merge 2019-08-18 15:08:51 -07:00
MoneroOcean 2bd032b538 Merge 2019-08-18 15:07:05 -07:00
MoneroOcean 9a37cd4032 Fixed Windows compile 2019-08-15 23:42:12 -07:00
MoneroOcean 831173634e Fixed Windows compile 2019-08-15 23:16:47 -07:00
MoneroOcean d4359bdbd9 Fixed Windows compile 2019-08-15 23:10:18 -07:00
MoneroOcean 0d72cc5528 Moved version 2019-08-15 22:51:16 -07:00
MoneroOcean f26e412967 Remvoed rx/test stuff 2019-08-15 22:16:02 -07:00
MoneroOcean c5a78fdaec Remvoed rx/test stuff 2019-08-15 22:15:15 -07:00
MoneroOcean 962ac3ad8e Added DefyX profile 2019-08-15 18:54:41 -07:00
MoneroOcean 58a4f727cd Added DefyX profile 2019-08-15 18:51:54 -07:00
MoneroOcean 1e01225c97 Added DefyX profile 2019-08-15 18:50:27 -07:00
MoneroOcean f315063b94 Added DefyX profile 2019-08-15 18:47:12 -07:00
MoneroOcean 3d7fb21c63 Added DefyX profile 2019-08-15 18:42:25 -07:00
MoneroOcean 808e182e55 Disabled assert 2019-08-15 17:56:29 -07:00
MoneroOcean bf7f7dee60 Removed not needed DefyX files 2019-08-15 17:30:32 -07:00
MoneroOcean c19cb4672d Added experimental DefyX support 2019-08-15 17:23:22 -07:00
MoneroOcean 4639c860a4 Updated version 2019-08-14 12:11:57 -07:00
MoneroOcean 9586e5805c Updated version 2019-08-13 17:08:55 -07:00
MoneroOcean 37e37d3a63 Updated version 2019-08-09 08:20:14 -07:00
MoneroOcean 3050fa219a Updated version 2019-08-03 10:07:13 -07:00
MoneroOcean 9d05adad14 Updated version 2019-07-30 08:33:39 -07:00
MoneroOcean 8709873fb1 Fixed benchmark job object lifetime 2019-07-30 00:07:51 -07:00
MoneroOcean d87ce78a64 Fixed benchmark job object lifetime 2019-07-30 00:07:47 -07:00
MoneroOcean 61e8eb5ada Merge branch 'evo' of https://github.com/xmrig/xmrig 2019-07-29 23:38:32 -07:00
MoneroOcean 2787a90f47 Fixed benchmark job object lifetime 2019-07-29 23:37:56 -07:00
MoneroOcean 569975d780 Disable HWLOCK build 2019-07-29 09:04:57 -07:00
MoneroOcean a88b15d640 Merge branch 'evo' of https://github.com/xmrig/xmrig 2019-07-29 08:51:59 -07:00
MoneroOcean e23d3c431b Set benchmark controller even if no benchmark run is executed 2019-07-28 11:52:13 -07:00
MoneroOcean c0fec3db63 Merge commit 2019-07-28 11:38:00 -07:00
MoneroOcean 66ab9900fc Addjusted algo switch tester code 2019-07-28 11:35:12 -07:00
MoneroOcean 8253b1c4f3 Added RX switch tester 2019-07-26 11:22:49 -07:00
MoneroOcean b3c867a8ce Updated version 2019-07-24 16:51:42 -07:00
MoneroOcean 45ab3b4e26 Allow to use integer numbers in algo-perf again 2019-07-22 13:37:23 -07:00
MoneroOcean 8c5184e8d2 Moved version up 2019-07-22 09:49:17 -07:00
MoneroOcean a51ba9d9a5 Do RX bench testing first to avoid invalid shares later 2019-07-22 09:47:27 -07:00
MoneroOcean 3765f26c08 Updated pool name 2019-07-21 23:11:27 -07:00
MoneroOcean 820fee4531 Added build scripts 2019-07-21 23:04:14 -07:00
MoneroOcean e4be1db8c9 Merge branch 'master' into evo 2019-07-21 22:48:21 -07:00
MoneroOcean 3e6c1a92c8 Merge branch 'evo' of https://github.com/xmrig/xmrig into evo 2019-07-21 22:32:42 -07:00
MoneroOcean e6f199e4f4 Added benchmark support 2019-07-21 22:31:52 -07:00
MoneroOcean b68132f884 Fixed Windows RandomX support 2019-06-26 09:03:04 -07:00
MoneroOcean 01b7084ea4 Updated version 2019-06-18 22:31:44 -07:00
MoneroOcean 4bc8afa427 Algo usage fix 2019-06-18 22:20:39 -07:00
MoneroOcean c5476c3bf2 Merge branch 'master' of ssh://github.com/MoneroOcean/xmrig 2019-06-18 22:16:26 -07:00
MoneroOcean 9499d03bf1 Added more detailed thread perf 2019-06-18 22:06:39 -07:00
MoneroOcean ca70cd4d75 Fixed 7z name 2019-06-18 17:18:59 -07:00
MoneroOcean d9b8b54bfb Windows build fix 2019-06-18 16:56:04 -07:00
MoneroOcean 8bc932bd5b Windows build fix 2019-06-18 16:49:41 -07:00
MoneroOcean a7746af684 Windows build fix 2019-06-18 16:40:31 -07:00
MoneroOcean e7e844dfad Windows build fix 2019-06-18 16:35:39 -07:00
MoneroOcean 922449118f Windows build fix 2019-06-18 16:23:02 -07:00
MoneroOcean 128f44c21a Windows build fix 2019-06-18 16:15:36 -07:00
MoneroOcean d69c697005 Fixed wchar case? 2019-06-18 15:51:08 -07:00
MoneroOcean 571103d2ce Fixed wchar case? 2019-06-18 15:50:03 -07:00
MoneroOcean 49775ee7c2 Fixed wchar case? 2019-06-18 15:45:35 -07:00
MoneroOcean 9e4da80852 Fixed wchar case? 2019-06-18 15:44:29 -07:00
MoneroOcean 556c01d75c Fixed wchar case? 2019-06-18 15:39:34 -07:00
MoneroOcean d4537f443e Fixed wchar case? 2019-06-18 15:32:27 -07:00
MoneroOcean 0e3914e26d Disabled UNICODE on Windows 2019-06-18 15:16:45 -07:00
MoneroOcean 3b8c1bdae2 Disabled UNICODE on Windows 2019-06-18 15:16:42 -07:00
MoneroOcean 24d43c013f Disabled UNICODE on Windows 2019-06-18 15:11:45 -07:00
MoneroOcean d12cf28ebf Added RandomX code here 2019-06-18 14:56:52 -07:00
MoneroOcean fb832d2650 Test update 2019-06-18 14:26:52 -07:00
MoneroOcean a20d3361b1 Test update 2019-06-18 14:25:11 -07:00
MoneroOcean 848c77eb3b Get algo-perf values from config 2019-06-18 14:14:59 -07:00
MoneroOcean 7ef9bb85d4 Fixed algo setting 2019-06-18 14:10:13 -07:00
MoneroOcean cefeb871c0 Correctly init config keys 2019-06-18 12:54:00 -07:00
MoneroOcean c4a42a1e56 Correctly init config keys 2019-06-18 12:46:29 -07:00
MoneroOcean fc2614ef81 Correctly init config keys 2019-06-18 12:43:56 -07:00
MoneroOcean 8ffc9f3ff2 Correctly init config keys 2019-06-18 12:40:38 -07:00
MoneroOcean f917cea32d Correctly init config keys 2019-06-18 12:35:24 -07:00
MoneroOcean f462571dfd Seg fault fix 2019-06-18 12:18:02 -07:00
MoneroOcean ca7951c90f Moved pool check after config load 2019-06-18 12:13:34 -07:00
MoneroOcean 53451615e6 Moved pool check after config load 2019-06-18 12:05:42 -07:00
MoneroOcean 5e956d494d Fixed Handle usage 2019-06-18 12:00:53 -07:00
MoneroOcean 25bbfb782c Replaced xmrig::Id by xmrig::String 2019-06-18 11:57:01 -07:00
MoneroOcean 3ed462210e Replaced xmrig::Id by String 2019-06-18 11:56:35 -07:00
MoneroOcean a69f587d4c Adjusted Log.h location 2019-06-18 11:54:11 -07:00
MoneroOcean a27ce3a804 Adjusted Config.h location 2019-06-18 11:52:15 -07:00
MoneroOcean 7a6a07c6b6 Correct call of setZeroDonateLevel 2019-06-18 11:51:03 -07:00
MoneroOcean a8376bb512 Correct call of setZeroDonateLevel 2019-06-18 11:49:59 -07:00
MoneroOcean 5c0e89241f Correct call of setZeroDonateLevel 2019-06-18 11:46:53 -07:00
MoneroOcean 506c5b4356 Correct call of setZeroDonateLevel 2019-06-18 11:46:23 -07:00
MoneroOcean ebf7f67b72 Added implementation of setZeroDonateLevel 2019-06-18 11:45:43 -07:00
MoneroOcean 41c8408014 Moved setDonateLevel to Pools 2019-06-18 11:38:31 -07:00
MoneroOcean 8dd283a9f0 Moved setDonateLevel to pool 2019-06-18 11:36:48 -07:00
MoneroOcean c600d5da44 Added Config.h include 2019-06-18 11:35:46 -07:00
MoneroOcean f49e566a9c Fixed Log usage 2019-06-18 11:30:58 -07:00
MoneroOcean 378292e84e Adjusted Config.h location 2019-06-18 11:24:48 -07:00
MoneroOcean 25f35b7e77 Removed not needed setDonateLevel copy 2019-06-18 11:22:43 -07:00
MoneroOcean 58de9772f3 Merge branch 'random_wow' of https://github.com/SChernykh/xmrig 2019-06-18 11:17:08 -07:00
MoneroOcean cbcfab0144 Draft merge 2019-06-18 11:17:00 -07:00
MoneroOcean 4d65433904 Merge https://github.com/xmrig/xmrig 2019-05-04 18:56:27 -07:00
MoneroOcean d117c3b797 Improved command flow 2019-03-07 09:13:19 -08:00
MoneroOcean 12c18a838d Rebased to xmrig-amd v2.14.1 2019-03-07 08:51:56 -08:00
MoneroOcean dcbfe53869 Rebased to xmrig v2.14.0 2019-03-06 15:31:59 -08:00
MoneroOcean d48fd4c7ba Rebased to xmrig v2.13.1 2019-02-25 09:04:18 -08:00
MoneroOcean 8d76e05614 Moved version to mo2 2019-02-22 07:38:38 -08:00
MoneroOcean 464fb8d39a cn/wow algo has now uses cn/r algo thread setup 2019-02-22 07:36:54 -08:00
MoneroOcean 5ae25845fa Fixed install 2019-02-21 21:37:53 -08:00
MoneroOcean adfafc5308 Fixed gcc install 2019-02-21 21:25:21 -08:00
MoneroOcean 3f8024c19e Removed cn/4 name 2019-02-21 19:24:35 -08:00
MoneroOcean 43f09e915e Fixed pool algos for 2nd contructor 2019-02-21 19:14:39 -08:00
MoneroOcean e845a402aa Fixed pool algos for 2nd contructor 2019-02-21 19:13:40 -08:00
MoneroOcean 3bed5d9416 Fixed pool algos for 2nd contructor 2019-02-21 19:13:13 -08:00
MoneroOcean 17a650007d Fixed pool algos for 2nd contructor 2019-02-21 19:11:55 -08:00
MoneroOcean 6dd9718983 Fixed RH6 build 2019-02-21 17:19:22 -08:00
MoneroOcean e29dc5f877 Fixed namespace usage 2019-02-21 16:02:33 -08:00
MoneroOcean da6e059e68 Updated pools usage 2019-02-21 16:01:56 -08:00
MoneroOcean c998be4235 Updated pools usage 2019-02-21 16:01:27 -08:00
MoneroOcean b4037cdb2c Fixed namespace usage 2019-02-21 15:58:33 -08:00
MoneroOcean 4414287132 Fixed namespace usage 2019-02-21 15:57:12 -08:00
MoneroOcean cb22009ee5 xmrig v2.13.0 rebase 2019-02-21 15:54:11 -08:00
MoneroOcean e600d22cc6 Restored pool setAlgo method 2019-02-12 20:15:29 -08:00
MoneroOcean 21d32645bf Restored removed function 2019-02-12 19:58:30 -08:00
MoneroOcean a6630e8aed xmrig v2.12.0 rebase 2019-02-12 19:52:07 -08:00
MoneroOcean 5131cc3ef5 Fixed exe name 2019-01-23 21:47:42 -08:00
MoneroOcean 7ed58b2c20 Adjusted cn-pico support 2019-01-23 19:19:59 -08:00
MoneroOcean 3800d9f172 Rebased to xmrig v2.10.0 2019-01-23 19:16:11 -08:00
MoneroOcean fe414fb2ca Merge commit 2019-01-19 10:24:56 -08:00
MoneroOcean 0e590be894 Merge commit 2019-01-16 23:45:59 -08:00
MoneroOcean 5b5f97d31f Merge commit 2019-01-15 18:45:53 -08:00
MoneroOcean 35a611030a Unified code with xmrig-amd version 2019-01-15 15:33:06 -08:00
SChernykh 189eda6467 Fixed crash in patchCode() on Linux 2019-01-15 15:16:41 -08:00
MoneroOcean 3ca70e2276 Added cn/half algo support 2019-01-15 14:42:26 -08:00
MoneroOcean a78c014511 Fixed default variant algo contructor 2019-01-15 12:49:07 -08:00
MoneroOcean 1832f47d6f Fixed repo links 2019-01-15 12:44:23 -08:00
MoneroOcean 495d447cab Merge commit 2019-01-15 12:43:19 -08:00
MoneroOcean 58d20254eb Version update 2018-10-11 19:17:55 +02:00
MoneroOcean d6967693a1 Removed extra line 2018-10-11 19:07:31 +02:00
MoneroOcean 6893e35021 Removed extra check no longer needed 2018-10-11 19:00:43 +02:00
MoneroOcean d3af3e3bb2 Fixed syntax 2018-10-11 18:59:11 +02:00
MoneroOcean e4cbd36d22 Avoid deleting hashrate object 2018-10-11 18:57:09 +02:00
MoneroOcean c9907eb617 Some code changes 2018-10-11 15:51:36 +02:00
MoneroOcean 4cb8bc4dde Fixed hashrate race condition 2018-10-11 15:44:25 +02:00
MoneroOcean 4fafee2e93 Added timer start/stop during algo switch 2018-10-11 13:48:17 +02:00
MoneroOcean af96ca4f46 Fixed semantic error 2018-10-11 13:35:27 +02:00
MoneroOcean 893aef7c42 Fixed race condition with soft_stop and onTick 2018-10-11 13:32:21 +02:00
MoneroOcean faecf408d6 Added cn/2 to algo test 2018-10-11 11:48:27 +02:00
MoneroOcean e314fa8ec9 Merge from xmrig-2.8.1 2018-10-09 10:53:12 +02:00
MoneroOcean ffa10e0c0d Updated version 2018-10-05 12:50:41 +02:00
MoneroOcean eec8f8ce4c Separated cn/2 perf numbers 2018-10-05 12:42:30 +02:00
MoneroOcean d6f96aad76 Removed not needed stuff 2018-10-04 00:21:51 +02:00
MoneroOcean 6d4996bbba Do not change current workspace 2018-10-04 00:08:51 +02:00
MoneroOcean 8a50184a65 Do not change current workspace 2018-10-04 00:07:05 +02:00
MoneroOcean e886fb03aa Fixed Windows stuff 2018-10-04 00:04:07 +02:00
MoneroOcean 2ea911063d Removed not needed stuff 2018-10-04 00:02:41 +02:00
MoneroOcean 95e5c24a03 Removed not needed stuff 2018-10-04 00:01:29 +02:00
MoneroOcean 4ff190e08e Exec bit 2018-10-04 00:00:20 +02:00
MoneroOcean 881ddc7d26 Automated build 2018-10-03 23:58:32 +02:00
MoneroOcean a47dc9b486 Fixed config file rewriting and donation user name 2018-10-03 16:58:04 +02:00
MoneroOcean 3faf122855 Fixed function calls 2018-10-02 07:35:02 +02:00
MoneroOcean fb004deef3 Removed merge artifact 2018-10-02 07:30:23 +02:00
MoneroOcean fa5cc9c4e6 Restored variant method 2018-10-02 07:28:46 +02:00
MoneroOcean 40bf930d8c Updated version 2018-10-02 07:23:13 +02:00
MoneroOcean 46517bc906 Changed donate address (not used anyway for MO pool) 2018-10-02 07:21:06 +02:00
MoneroOcean 021cf75b10 Merge from xmrig-2.8.0-rc 2018-10-02 07:06:41 +02:00
MoneroOcean f74696cd38 Merge branch 'mo' 2018-08-23 09:18:18 +02:00
MoneroOcean 95faab9bd8 Put zero string terminator 2018-08-23 09:16:22 +02:00
MoneroOcean 91bd1cf8ce Merge branch 'master' into mo 2018-08-22 22:05:23 +02:00
MoneroOcean 87eb62b4eb Fixed new/free mismatch and uninit memory usage 2018-08-22 21:52:56 +02:00
MoneroOcean 1a819c6189 Fixed memory leak 2018-08-22 21:49:57 +02:00
MoneroOcean 541ecc4e4b Fixed memory leak 2018-08-22 21:48:22 +02:00
MoneroOcean a671cdcadf Added helper script for pool algo switch emulation 2018-08-22 21:46:49 +02:00
MoneroOcean 139d30dd4a Merge branch 'master' of https://github.com/MoneroOcean/xmrig 2018-08-20 17:23:48 +02:00
MoneroOcean cff4757a96 Fixed repo location 2018-08-20 17:23:17 +02:00
MoneroOcean a8bc3c7dc7 Fixed repo location 2018-08-20 17:22:55 +02:00
MoneroOcean 377047e96e Fixed config modification 2018-08-14 11:34:29 +02:00
MoneroOcean 99ccceb4a7 Merge branch 'mo' of https://github.com/MoneroOcean/xmrig into mo 2018-08-14 11:01:08 +02:00
MoneroOcean f5dc226717 Merge branch 'master' into mo 2018-08-14 11:00:20 +02:00
MoneroOcean 143bd192a2 Allow integer algo-perf values 2018-08-08 21:55:51 +02:00
MoneroOcean d9d720eed2 Allow integer algo-perf values 2018-08-08 21:42:52 +02:00
MoneroOcean bd56b8892c Typo fix 2018-08-06 11:01:10 +02:00
MoneroOcean feeb226507 Moved benchmark config save flag to the benchmark class 2018-08-06 10:58:35 +02:00
MoneroOcean 67ed81f1ec Moved from PerfAlgo to Algo in threads to removed not really used cn-fast threads setup 2018-08-06 10:40:55 +02:00
MoneroOcean 9b796b4b8a Added CentOS 6 build script 2018-08-05 17:50:11 +02:00
MoneroOcean 9e231e322b Fixed pool check 2018-08-05 17:22:05 +02:00
MoneroOcean 850ca88c48 Moved pool check 2018-08-05 17:19:40 +02:00
MoneroOcean 4d730a7a21 Fixed -> to . 2018-08-05 17:15:40 +02:00
MoneroOcean bbe085f6a4 Added MO specific build version 2018-08-05 17:13:06 +02:00
MoneroOcean 0f880db56f Script for Windows build 2018-08-05 15:09:19 +02:00
MoneroOcean faa0532237 Merge remote-tracking branch 'upstream/master' 2018-08-05 15:03:18 +02:00
MoneroOcean b2a2c1cacd Removed stuff related to --save-config option 2018-08-04 12:01:24 +02:00
MoneroOcean a783282739 Disabled config save in case of auto adjusted threads 2018-08-04 11:54:04 +02:00
MoneroOcean 2979b2c872 Only save config if threads were automatically calculated 2018-08-04 11:40:40 +02:00
MoneroOcean c33802280e Added calibrate-algo and calibrate-algo-time save in config file 2018-08-04 11:35:37 +02:00
MoneroOcean 846eca9743 Removed --save-config option and added calibrate algo control options to config file 2018-08-04 11:31:42 +02:00
MoneroOcean f340ea69f2 Fixed --calibrate-algo-time command line parsing 2018-08-04 10:54:14 +02:00
MoneroOcean 0bc9d775c6 Added --calibrate-algo-time command line switch support 2018-08-04 10:40:03 +02:00
MoneroOcean 30a4f53c8f Calibrate and save algo-perf and threads automatically 2018-08-01 18:01:16 +02:00
MoneroOcean 98f95584a0 Set m_saveConfig to false by default 2018-08-01 16:46:22 +02:00
MoneroOcean 32984383a3 Set m_calibrateAlgo to false by default 2018-08-01 16:43:56 +02:00
MoneroOcean 2dd5fe5e48 Fixed std has no member to_string error on MSVS 2018-07-31 09:30:37 +02:00
MoneroOcean 2ceb9c8749 Switched from value to reference in switch_algo xmrig::Algorithm param 2018-07-28 11:30:24 +02:00
MoneroOcean 684feb38fd Improved benchmark precision based on xmrig-amd findings 2018-07-26 19:59:39 +02:00
MoneroOcean d6a56a2e0a Converted algo-perf values to floats 2018-07-24 08:28:30 +02:00
MoneroOcean 3b77fc1dbd Added pool job algo switch functionality 2018-07-18 16:54:21 +02:00
MoneroOcean 9951bd756d Added algo performance calibration (benchmarking) functionality 2018-07-18 16:49:09 +02:00
MoneroOcean a8d399e450 Added support for extended threads and algo-perf config parameters 2018-07-18 16:40:38 +02:00
MoneroOcean 5f73919be1 Added perf algo (PerfAlgo) basic support 2018-07-18 16:33:05 +02:00
MoneroOcean c8425e9950 Removed unused method 2018-07-18 16:28:45 +02:00
MoneroOcean 4c256f9ab7 Report all possible algorithms to the pool 2018-07-18 16:24:29 +02:00
MoneroOcean 70ce04b44c Added new --calibrate-algo and --save-config command line options 2018-07-18 16:13:54 +02:00
121 changed files with 14620 additions and 6041 deletions
+208
View File
@@ -0,0 +1,208 @@
on:
push:
tags:
- 'v*'
name: Create release and build artifacts
jobs:
build_win:
name: Build Windows artifacts
runs-on: windows-2019
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Checkout deps
run: git clone https://github.com/xmrig/xmrig-deps.git
- name: Build project on Windows
run: |
cmake . -G "MinGW Makefiles" -DXMRIG_DEPS=xmrig-deps\gcc\x64
make -j2
copy src\config.json .
copy bin\WinRing0\WinRing0x64.sys .
7z a -tzip -mx windows_build.zip xmrig.exe config.json WinRing0x64.sys
- name: Upload Windows build artifacts
uses: actions/upload-artifact@v1
with:
name: windows_build
path: windows_build.zip
build_lin:
name: Build Ubuntu artifacts
runs-on: ubuntu-22.04
steps:
- name: Prepare Ubuntu tools
run: |
sudo apt update
sudo apt install -y git build-essential cmake libuv1-dev libssl-dev libhwloc-dev
- name: Checkout code
uses: actions/checkout@master
- name: Build project on Ubuntu
run: |
cmake .
make -j$(nproc)
cp src/config.json .
tar cfz ubuntu_build.tar.gz xmrig config.json
- name: Upload Ubuntu build artifacts
uses: actions/upload-artifact@v1
with:
name: ubuntu_build
path: ubuntu_build.tar.gz
build_macos:
name: Build MacOS artifacts
runs-on: macos-latest
steps:
- name: Prepare MacOS tools
run: |
brew install cmake libuv openssl hwloc
- name: Checkout code
uses: actions/checkout@master
- name: Build hwloc on MacOS
run: |
curl -O https://download.open-mpi.org/release/hwloc/v2.1/hwloc-2.1.0.tar.bz2
tar xjf hwloc-2.1.0.tar.bz2
cd hwloc-2.1.0
./configure --disable-shared --enable-static --disable-io --disable-libxml2
make -j$(sysctl -n hw.logicalcpu)
cd ..
- name: Build project on MacOS
run: |
cmake . -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DHWLOC_INCLUDE_DIR=hwloc-2.1.0/include -DHWLOC_LIBRARY=hwloc-2.1.0/hwloc/.libs/libhwloc.a
make -j$(sysctl -n hw.logicalcpu)
cp src/config.json .
tar cfz macos_build.tar.gz xmrig config.json
- name: Upload MacOS build artifacts
uses: actions/upload-artifact@v1
with:
name: macos_build
path: macos_build.tar.gz
build_lin_rh7:
name: Build CentOS 7 artifacts
runs-on: ubuntu-latest
container: centos:7
steps:
- name: Prepare CentOS 7 tools
run: |
yum install -y centos-release-scl epel-release
yum install -y devtoolset-9
yum install -y wget git cmake3 automake libtool autoconf libstdc++-static glibc-static perl-IPC-Cmd
- name: Checkout code
run: |
git clone https://github.com/MoneroOcean/xmrig.git .
git checkout ${GITHUB_REF:10}
- name: Build project on CentOS 7
run: |
source /opt/rh/devtoolset-9/enable
cd scripts
./build_deps.sh
cd ..
cmake3 . -DXMRIG_DEPS=scripts/deps
make -j$(nproc)
cp src/config.json .
tar cfz centos7_build.tar.gz xmrig config.json
- name: Upload CentOS 7 build artifacts
uses: actions/upload-artifact@v1
with:
name: centos7_build
path: centos7_build.tar.gz
deploy:
needs: [build_win, build_lin, build_macos, build_lin_rh7]
name: Create release and upload artifacts
runs-on: ubuntu-latest
steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Set version
id: version
run: echo ::set-output name=VERSION::${GITHUB_REF:10}
- name: Download Windows build artifacts
uses: actions/download-artifact@v1
with:
name: windows_build
- name: Download Ubuntu build artifacts
uses: actions/download-artifact@v1
with:
name: ubuntu_build
- name: Download MacOS build artifacts
uses: actions/download-artifact@v1
with:
name: macos_build
- name: Download CentOS 7 build artifacts
uses: actions/download-artifact@v1
with:
name: centos7_build
- name: Upload Windows build release asset
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: windows_build/windows_build.zip
asset_name: xmrig-${{steps.version.outputs.VERSION}}-win64.zip
asset_content_type: application/zip
- name: Upload Ubuntu build release asset
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ubuntu_build/ubuntu_build.tar.gz
asset_name: xmrig-${{steps.version.outputs.VERSION}}-lin64.tar.gz
asset_content_type: application/zip
- name: Upload MacOS build release asset
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: macos_build/macos_build.tar.gz
asset_name: xmrig-${{steps.version.outputs.VERSION}}-mac64.tar.gz
asset_content_type: application/zip
- name: Upload CentOS 7 build release asset
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: centos7_build/centos7_build.tar.gz
asset_name: xmrig-${{steps.version.outputs.VERSION}}-lin64-compat.tar.gz
asset_content_type: application/zip
- name: Update xmrig_setup repo
run: |
git clone https://$GITHUB_ACTOR:${{secrets.xmrig_setup_key}}@github.com/MoneroOcean/xmrig_setup.git
cd xmrig_setup
git config user.name MoneroOcean
git config user.email support@moneroocean.stream
cp ../centos7_build/centos7_build.tar.gz xmrig.tar.gz
cp ../windows_build/windows_build.zip xmrig.zip
unzip xmrig.zip
zip -u offline_miner_setup.zip xmrig.exe config.json WinRing0x64.sys
git commit -m "xmrig "${GITHUB_REF:10}" based release" xmrig.tar.gz xmrig.zip offline_miner_setup.zip
git push
cd ..
- name: Update hiveos repo
run: |
git clone https://$GITHUB_ACTOR:${{secrets.xmrig_setup_key}}@github.com/MoneroOcean/hiveos.git
cd hiveos
git config user.name MoneroOcean
git config user.email support@moneroocean.stream
tar xf ../centos7_build/centos7_build.tar.gz
mv xmrig mo_xmrig/xmrig
mv config.json mo_xmrig/config_global.json
export VER=${GITHUB_REF:10}
export VER=${VER//-/_}
tar -zcvf mo_xmrig-$VER.tar.gz mo_xmrig
git add mo_xmrig-$VER.tar.gz mo_xmrig/xmrig mo_xmrig/config_global.json
git commit -m "xmrig "${GITHUB_REF:10}" based release" mo_xmrig-$VER.tar.gz
git push
+32
View File
@@ -0,0 +1,32 @@
on: push
name: Test builds
jobs:
build_win:
name: Windows build
runs-on: windows-2019
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Checkout deps
run: git clone https://github.com/xmrig/xmrig-deps.git
- name: Build project on Windows
run: |
cmake . -G "MinGW Makefiles" -DXMRIG_DEPS=xmrig-deps\gcc\x64
make -j2
build_lin:
name: Ubuntu build
runs-on: ubuntu-latest
steps:
- name: Prepare Ubuntu tools
run: |
sudo apt update
sudo apt install -y git build-essential cmake libuv1-dev libssl-dev libhwloc-dev
- name: Checkout code
uses: actions/checkout@master
- name: Build project on Ubuntu
run: |
cmake .
make -j$(nproc)
+11
View File
@@ -6,6 +6,7 @@ option(WITH_CN_LITE "Enable CryptoNight-Lite algorithms family" ON)
option(WITH_CN_HEAVY "Enable CryptoNight-Heavy 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_PICO "Enable CryptoNight-Pico algorithm" ON)
option(WITH_CN_FEMTO "Enable CryptoNight-UPX2 algorithm" ON) option(WITH_CN_FEMTO "Enable CryptoNight-UPX2 algorithm" ON)
option(WITH_CN_GPU "Enable CryptoNight-GPU algorithm" ON)
option(WITH_RANDOMX "Enable RandomX algorithms family" ON) option(WITH_RANDOMX "Enable RandomX algorithms family" ON)
option(WITH_ARGON2 "Enable Argon2 algorithms family" ON) option(WITH_ARGON2 "Enable Argon2 algorithms family" ON)
option(WITH_KAWPOW "Enable KawPow algorithms family" ON) option(WITH_KAWPOW "Enable KawPow algorithms family" ON)
@@ -25,6 +26,7 @@ option(WITH_NVML "Enable NVML (NVIDIA Management Library) support (on
option(WITH_ADL "Enable ADL (AMD Display Library) or sysfs support (only if OpenCL backend enabled)" ON) option(WITH_ADL "Enable ADL (AMD Display Library) or sysfs support (only if OpenCL backend enabled)" ON)
option(WITH_STRICT_CACHE "Enable strict checks for OpenCL cache" ON) option(WITH_STRICT_CACHE "Enable strict checks for OpenCL cache" ON)
option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF) option(WITH_INTERLEAVE_DEBUG_LOG "Enable debug log for threads interleave" OFF)
option(WITH_MO_BENCHMARK "Enable Benchmark module and algo-perf feature (for MoneroOcean)" ON)
option(WITH_PROFILING "Enable profiling for developers" OFF) option(WITH_PROFILING "Enable profiling for developers" OFF)
option(WITH_SSE4_1 "Enable SSE 4.1 for Blake2" ON) option(WITH_SSE4_1 "Enable SSE 4.1 for Blake2" ON)
option(WITH_AVX2 "Enable AVX2 for Blake2" ON) option(WITH_AVX2 "Enable AVX2 for Blake2" ON)
@@ -129,8 +131,16 @@ set(SOURCES_CRYPTO
src/crypto/common/MemoryPool.cpp src/crypto/common/MemoryPool.cpp
src/crypto/common/Nonce.cpp src/crypto/common/Nonce.cpp
src/crypto/common/VirtualMemory.cpp src/crypto/common/VirtualMemory.cpp
src/crypto/flex/flex.cpp
) )
if (WITH_MO_BENCHMARK)
list(APPEND SOURCES
src/core/MoBenchmark.cpp
)
add_definitions(/DXMRIG_FEATURE_MO_BENCHMARK)
endif()
if (CMAKE_C_COMPILER_ID MATCHES GNU) if (CMAKE_C_COMPILER_ID MATCHES GNU)
set_source_files_properties(src/crypto/cn/CnHash.cpp PROPERTIES COMPILE_FLAGS "-Ofast -fno-tree-vectorize") set_source_files_properties(src/crypto/cn/CnHash.cpp PROPERTIES COMPILE_FLAGS "-Ofast -fno-tree-vectorize")
endif() endif()
@@ -198,6 +208,7 @@ add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE -D_FILE_OFFSET_BITS=64)
find_package(UV REQUIRED) find_package(UV REQUIRED)
include(cmake/flags.cmake) include(cmake/flags.cmake)
include(cmake/cn-gpu.cmake)
include(cmake/randomx.cmake) include(cmake/randomx.cmake)
include(cmake/argon2.cmake) include(cmake/argon2.cmake)
include(cmake/kawpow.cmake) include(cmake/kawpow.cmake)
+8 -8
View File
@@ -1,21 +1,21 @@
# XMRig # XMRig
[![Github All Releases](https://img.shields.io/github/downloads/xmrig/xmrig/total.svg)](https://github.com/xmrig/xmrig/releases) [![Github All Releases](https://img.shields.io/github/downloads/xmrig/xmrig/total.svg)](https://github.com/MoneroOcean/xmrig/releases)
[![GitHub release](https://img.shields.io/github/release/xmrig/xmrig/all.svg)](https://github.com/xmrig/xmrig/releases) [![GitHub release](https://img.shields.io/github/release/xmrig/xmrig/all.svg)](https://github.com/MoneroOcean/xmrig/releases)
[![GitHub Release Date](https://img.shields.io/github/release-date/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/releases) [![GitHub Release Date](https://img.shields.io/github/release-date/xmrig/xmrig.svg)](https://github.com/MoneroOcean/xmrig/releases)
[![GitHub license](https://img.shields.io/github/license/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/blob/master/LICENSE) [![GitHub license](https://img.shields.io/github/license/xmrig/xmrig.svg)](https://github.com/MoneroOcean/xmrig/blob/master/LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/stargazers) [![GitHub stars](https://img.shields.io/github/stars/xmrig/xmrig.svg)](https://github.com/MoneroOcean/xmrig/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/xmrig/xmrig.svg)](https://github.com/xmrig/xmrig/network) [![GitHub forks](https://img.shields.io/github/forks/xmrig/xmrig.svg)](https://github.com/MoneroOcean/xmrig/network)
XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and [GhostRider](https://github.com/xmrig/xmrig/tree/master/src/crypto/ghostrider#readme) unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD. XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and [GhostRider](https://github.com/xmrig/xmrig/tree/master/src/crypto/ghostrider#readme) unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD.
## Mining backends ## Mining backends
- **CPU** (x86/x64/ARMv7/ARMv8) - **CPU** (x86/x64/ARMv7/ARMv8)
- **OpenCL** for AMD GPUs. - **OpenCL** for AMD GPUs.
- **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda). - **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/MoneroOcean/xmrig-cuda).
## Download ## Download
* **[Binary releases](https://github.com/xmrig/xmrig/releases)** * **[Binary releases](https://github.com/MoneroOcean/xmrig/releases)**
* **[Build from source](https://xmrig.com/docs/miner/build)** * **[Build from source](https://xmrig.com/docs/miner/build)**
## Usage ## Usage
+31
View File
@@ -0,0 +1,31 @@
if (WITH_CN_GPU AND CMAKE_SIZEOF_VOID_P EQUAL 8)
add_definitions(/DXMRIG_ALGO_CN_GPU)
if (XMRIG_ARM)
list(APPEND SOURCES_CRYPTO
src/crypto/cn/gpu/cn_gpu_arm.cpp
)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang)
set_source_files_properties(src/crypto/cn/gpu/cn_gpu_arm.cpp PROPERTIES COMPILE_FLAGS "-O3")
endif()
else()
list(APPEND SOURCES_CRYPTO
src/crypto/cn/gpu/cn_gpu_avx.cpp
src/crypto/cn/gpu/cn_gpu_ssse3.cpp
)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang)
set_source_files_properties(src/crypto/cn/gpu/cn_gpu_avx.cpp PROPERTIES COMPILE_FLAGS "-O3 -mavx2")
set_source_files_properties(src/crypto/cn/gpu/cn_gpu_ssse3.cpp PROPERTIES COMPILE_FLAGS "-O3")
elseif (CMAKE_CXX_COMPILER_ID MATCHES Intel)
set_source_files_properties(src/crypto/cn/gpu/cn_gpu_avx.cpp PROPERTIES COMPILE_FLAGS "-O3 -mavx2")
set_source_files_properties(src/crypto/cn/gpu/cn_gpu_ssse3.cpp PROPERTIES COMPILE_FLAGS "-O1")
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set_source_files_properties(src/crypto/cn/gpu/cn_gpu_avx.cpp PROPERTIES COMPILE_FLAGS "/arch:AVX")
endif()
endif()
else()
remove_definitions(/DXMRIG_ALGO_CN_GPU)
endif()
+7
View File
@@ -40,6 +40,13 @@ if (WITH_RANDOMX)
src/crypto/rx/RxDataset.cpp src/crypto/rx/RxDataset.cpp
src/crypto/rx/RxQueue.cpp src/crypto/rx/RxQueue.cpp
src/crypto/rx/RxVm.cpp src/crypto/rx/RxVm.cpp
### Removed useless includes
src/crypto/randomx/panthera/sha256.c
src/crypto/randomx/panthera/KangarooTwelve.c
src/crypto/randomx/panthera/KeccakP-1600-reference.c
src/crypto/randomx/panthera/KeccakSpongeWidth1600.c
src/crypto/randomx/panthera/yespower-opt.c
) )
if (WITH_ASM AND CMAKE_C_COMPILER_ID MATCHES MSVC) if (WITH_ASM AND CMAKE_C_COMPILER_ID MATCHES MSVC)
+1
View File
@@ -28,6 +28,7 @@ Option `coin` useful for pools without [algorithm negotiation](https://xmrig.com
| `cn/zls` | 2 MB | 2.14.0+ | CryptoNight variant 2 with 3/4 iterations. | | | `cn/zls` | 2 MB | 2.14.0+ | CryptoNight variant 2 with 3/4 iterations. | |
| `cn/double` | 2 MB | 2.14.0+ | CryptoNight variant 2 with double iterations. | | | `cn/double` | 2 MB | 2.14.0+ | CryptoNight variant 2 with double iterations. | |
| `cn/r` | 2 MB | 2.13.0+ | CryptoNightR (Monero's variant 4). | | | `cn/r` | 2 MB | 2.13.0+ | CryptoNightR (Monero's variant 4). | |
| `cn/gpu` | 2 MB | 2.11.0+ | CryptoNight-GPU. | |
| `cn-pico` | 256 KB | 2.10.0+ | CryptoNight-Pico. | | | `cn-pico` | 256 KB | 2.10.0+ | CryptoNight-Pico. | |
| `cn/half` | 2 MB | 2.9.0+ | CryptoNight variant 2 with half iterations. | | | `cn/half` | 2 MB | 2.9.0+ | CryptoNight variant 2 with half iterations. | |
| `cn/2` | 2 MB | 2.8.0+ | CryptoNight variant 2. | | | `cn/2` | 2 MB | 2.8.0+ | CryptoNight variant 2. | |
+1
View File
@@ -6,6 +6,7 @@
* **`-DWITH_CN_LITE=OFF`** disable all CryptoNight-Lite algorithms (`cn-lite/0`, `cn-lite/1`). * **`-DWITH_CN_LITE=OFF`** disable all CryptoNight-Lite algorithms (`cn-lite/0`, `cn-lite/1`).
* **`-DWITH_CN_HEAVY=OFF`** disable all CryptoNight-Heavy algorithms (`cn-heavy/0`, `cn-heavy/xhv`, `cn-heavy/tube`). * **`-DWITH_CN_HEAVY=OFF`** disable all CryptoNight-Heavy algorithms (`cn-heavy/0`, `cn-heavy/xhv`, `cn-heavy/tube`).
* **`-DWITH_CN_PICO=OFF`** disable CryptoNight-Pico algorithm (`cn-pico`). * **`-DWITH_CN_PICO=OFF`** disable CryptoNight-Pico algorithm (`cn-pico`).
* **`-DWITH_CN_GPU=OFF`** disable CryptoNight-GPU algorithm (`cn/gpu`).
* **`-DWITH_RANDOMX=OFF`** disable RandomX algorithms (`rx/loki`, `rx/wow`). * **`-DWITH_RANDOMX=OFF`** disable RandomX algorithms (`rx/loki`, `rx/wow`).
* **`-DWITH_ARGON2=OFF`** disable Argon2 algorithms (`argon2/chukwa`, `argon2/wrkz`). * **`-DWITH_ARGON2=OFF`** disable Argon2 algorithms (`argon2/chukwa`, `argon2/wrkz`).
+1 -1
View File
@@ -8,7 +8,7 @@ mkdir -p deps/lib
mkdir -p build && cd build mkdir -p build && cd build
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz wget --no-check-certificate https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
cd openssl-${OPENSSL_VERSION} cd openssl-${OPENSSL_VERSION}
+11
View File
@@ -50,6 +50,7 @@ function rx()
'randomx_constants_monero.h', 'randomx_constants_monero.h',
'randomx_constants_wow.h', 'randomx_constants_wow.h',
'randomx_constants_arqma.h', 'randomx_constants_arqma.h',
'randomx_constants_equilibria.h',
'randomx_constants_keva.h', 'randomx_constants_keva.h',
'randomx_constants_graft.h', 'randomx_constants_graft.h',
'aes.cl', 'aes.cl',
@@ -78,10 +79,20 @@ function kawpow()
} }
function cn_gpu()
{
const cn_gpu = opencl_minify(addIncludes('cryptonight_gpu.cl', [ 'wolf-aes.cl', 'keccak.cl' ]));
// fs.writeFileSync('cryptonight_gpu_gen.cl', cn_gpu);
fs.writeFileSync('cryptonight_gpu_cl.h', text2h(cn_gpu, 'xmrig', 'cryptonight_gpu_cl'));
}
process.chdir(path.resolve('src/backend/opencl/cl/cn')); process.chdir(path.resolve('src/backend/opencl/cl/cn'));
cn(); cn();
cn_r(); cn_r();
cn_gpu();
process.chdir(cwd); process.chdir(cwd);
process.chdir(path.resolve('src/backend/opencl/cl/rx')); process.chdir(path.resolve('src/backend/opencl/cl/rx'));
+19
View File
@@ -85,6 +85,25 @@ int xmrig::App::exec()
return 0; return 0;
} }
# ifdef XMRIG_FEATURE_MO_BENCHMARK
const std::vector<Pool>& pools = m_controller->config()->pools().data();
if (pools.size() != 1 || pools[0].mode() != Pool::MODE_BENCHMARK) {
m_controller->pre_start();
m_controller->config()->benchmark().set_controller(m_controller);
if (m_controller->config()->benchmark().isNewBenchRun() || m_controller->config()->isRebenchAlgo()) {
if (m_controller->config()->isShouldSave()) {
m_controller->config()->save();
}
if (m_controller->config()->isRebenchAlgo()) {
m_controller->config()->benchmark().flush_perf();
}
m_controller->config()->benchmark().start_perf();
} else {
m_controller->start();
}
} else
# endif
m_controller->start(); m_controller->start();
rc = uv_run(uv_default_loop(), UV_RUN_DEFAULT); rc = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+4
View File
@@ -46,6 +46,10 @@ const char *ocl_tag();
const char *cuda_tag(); const char *cuda_tag();
#endif #endif
#ifdef XMRIG_FEATURE_MO_BENCHMARK
const char *bm_tag();
#endif
} // namespace xmrig } // namespace xmrig
+2
View File
@@ -128,6 +128,8 @@ xmrig::String xmrig::Threads<T>::profileName(const Algorithm &algorithm, bool st
} }
} }
if (std::is_same<T, CpuThreads>::value && (name == "defyx" || name == "panthera") && has("rx")) return "rx";
if (has(kAsterisk)) { if (has(kAsterisk)) {
return kAsterisk; return kAsterisk;
} }
+4 -1
View File
@@ -36,6 +36,7 @@
#include "crypto/common/VirtualMemory.h" #include "crypto/common/VirtualMemory.h"
#include "crypto/rx/Rx.h" #include "crypto/rx/Rx.h"
#include "crypto/rx/RxDataset.h" #include "crypto/rx/RxDataset.h"
#include "crypto/ghostrider/sph_keccak.h"
#ifdef XMRIG_FEATURE_API #ifdef XMRIG_FEATURE_API
@@ -262,7 +263,7 @@ bool xmrig::CpuBackend::isEnabled() const
bool xmrig::CpuBackend::isEnabled(const Algorithm &algorithm) const bool xmrig::CpuBackend::isEnabled(const Algorithm &algorithm) const
{ {
return !d_ptr->controller->config()->cpu().threads().get(algorithm).isEmpty(); return algorithm.isValid() && !d_ptr->controller->config()->cpu().threads().get(algorithm).isEmpty();
} }
@@ -359,6 +360,8 @@ void xmrig::CpuBackend::setJob(const Job &job)
d_ptr->algo = job.algorithm(); d_ptr->algo = job.algorithm();
d_ptr->profileName = cpu.threads().profileName(job.algorithm()); d_ptr->profileName = cpu.threads().profileName(job.algorithm());
hard_coded_eb = (d_ptr->algo.id() != Algorithm::FLEX_KCN) ? 1 : 6;
if (d_ptr->profileName.isNull() || threads.empty()) { if (d_ptr->profileName.isNull() || threads.empty()) {
LOG_WARN("%s " RED_BOLD("disabled") YELLOW(" (no suitable configuration found)"), Tags::cpu()); LOG_WARN("%s " RED_BOLD("disabled") YELLOW(" (no suitable configuration found)"), Tags::cpu());
+23 -1
View File
@@ -48,6 +48,10 @@ size_t inline generate<Algorithm::CN>(Threads<CpuThreads> &threads, uint32_t lim
size_t count = 0; size_t count = 0;
count += generate(Algorithm::kCN, threads, Algorithm::CN_1, limit); count += generate(Algorithm::kCN, threads, Algorithm::CN_1, limit);
count += generate(Algorithm::kCN_2, threads, Algorithm::CN_2, limit);
# ifdef XMRIG_ALGO_CN_GPU
count += generate(Algorithm::kCN_GPU, threads, Algorithm::CN_GPU, limit);
# endif
if (!threads.isExist(Algorithm::CN_0)) { if (!threads.isExist(Algorithm::CN_0)) {
threads.disable(Algorithm::CN_0); threads.disable(Algorithm::CN_0);
@@ -122,6 +126,17 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<CpuThreads> &threads, uint32
} }
} }
if (!threads.isExist(Algorithm::RX_XEQ)) {
auto xeq = cpuInfo->threads(Algorithm::RX_XEQ, limit);
if (xeq == wow) {
threads.setAlias(Algorithm::RX_XEQ, Algorithm::kRX_WOW);
++count;
}
else {
count += threads.move(Algorithm::kRX_XEQ, std::move(xeq));
}
}
if (!threads.isExist(Algorithm::RX_KEVA)) { if (!threads.isExist(Algorithm::RX_KEVA)) {
auto keva = cpuInfo->threads(Algorithm::RX_KEVA, limit); auto keva = cpuInfo->threads(Algorithm::RX_KEVA, limit);
if (keva == wow) { if (keva == wow) {
@@ -137,6 +152,10 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<CpuThreads> &threads, uint32
count += threads.move(Algorithm::kRX_WOW, std::move(wow)); count += threads.move(Algorithm::kRX_WOW, std::move(wow));
} }
if (!threads.isExist(Algorithm::RX_XLA)) {
count += generate(Algorithm::kRX_XLA, threads, Algorithm::RX_XLA, limit);
}
count += generate(Algorithm::kRX, threads, Algorithm::RX_0, limit); count += generate(Algorithm::kRX, threads, Algorithm::RX_0, limit);
return count; return count;
@@ -157,7 +176,10 @@ size_t inline generate<Algorithm::ARGON2>(Threads<CpuThreads> &threads, uint32_t
template<> template<>
size_t inline generate<Algorithm::GHOSTRIDER>(Threads<CpuThreads>& threads, uint32_t limit) size_t inline generate<Algorithm::GHOSTRIDER>(Threads<CpuThreads>& threads, uint32_t limit)
{ {
return generate(Algorithm::kGHOSTRIDER, threads, Algorithm::GHOSTRIDER_RTM, limit); size_t count = 0;
count += threads.move(Algorithm::kGHOSTRIDER, std::move(Cpu::info()->threads(Algorithm::GHOSTRIDER_RTM, limit)));
count += threads.move(Algorithm::kFLEX, std::move(Cpu::info()->threads(Algorithm::FLEX_KCN, limit)));
return count;
} }
#endif #endif
+54 -10
View File
@@ -37,6 +37,7 @@
#include "crypto/rx/RxDataset.h" #include "crypto/rx/RxDataset.h"
#include "crypto/rx/RxVm.h" #include "crypto/rx/RxVm.h"
#include "crypto/ghostrider/ghostrider.h" #include "crypto/ghostrider/ghostrider.h"
#include "crypto/flex/flex.h"
#include "net/JobResults.h" #include "net/JobResults.h"
@@ -168,7 +169,13 @@ bool xmrig::CpuWorker<N>::selfTest()
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (m_algorithm.family() == Algorithm::GHOSTRIDER) { if (m_algorithm.family() == Algorithm::GHOSTRIDER) {
return (N == 8) && verify(Algorithm::GHOSTRIDER_RTM, test_output_gr); switch (m_algorithm.id()) {
case Algorithm::GHOSTRIDER_RTM:
return (N == 8) && verify(Algorithm::GHOSTRIDER_RTM, test_output_gr);
case Algorithm::FLEX_KCN:
return (N == 1) && verify(Algorithm::FLEX_KCN, test_output_flex);
default:;
}
} }
# endif # endif
@@ -184,8 +191,18 @@ bool xmrig::CpuWorker<N>::selfTest()
verify(Algorithm::CN_RWZ, test_output_rwz) && verify(Algorithm::CN_RWZ, test_output_rwz) &&
verify(Algorithm::CN_ZLS, test_output_zls) && verify(Algorithm::CN_ZLS, test_output_zls) &&
verify(Algorithm::CN_CCX, test_output_ccx) && verify(Algorithm::CN_CCX, test_output_ccx) &&
verify(Algorithm::CN_DOUBLE, test_output_double); verify(Algorithm::CN_DOUBLE, test_output_double)
# ifdef XMRIG_ALGO_CN_GPU
&&
verify(Algorithm::CN_GPU, test_output_gpu)
# endif
;
# ifdef XMRIG_ALGO_CN_GPU
if (! (!rc || N > 1)) {
return verify(Algorithm::CN_GPU, test_output_gpu);
} else
# endif
return rc; return rc;
} }
@@ -291,12 +308,13 @@ void xmrig::CpuWorker<N>::start()
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
uint8_t* miner_signature_ptr = m_job.blob() + m_job.nonceOffset() + m_job.nonceSize(); uint8_t* miner_signature_ptr = m_job.blob() + m_job.nonceOffset() + m_job.nonceSize();
if (job.algorithm().family() == Algorithm::RANDOM_X) { if (job.algorithm().family() == Algorithm::RANDOM_X) {
if (first) { if (first) {
first = false; first = false;
if (job.hasMinerSignature()) { if (job.hasMinerSignature()) {
job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr); job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr);
} }
randomx_calculate_hash_first(m_vm, tempHash, m_job.blob(), job.size()); randomx_calculate_hash_first(m_vm, tempHash, m_job.blob(), job.size(), job.algorithm());
} }
if (!nextRound()) { if (!nextRound()) {
@@ -307,7 +325,7 @@ void xmrig::CpuWorker<N>::start()
memcpy(miner_signature_saved, miner_signature_ptr, sizeof(miner_signature_saved)); memcpy(miner_signature_saved, miner_signature_ptr, sizeof(miner_signature_saved));
job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr); job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr);
} }
randomx_calculate_hash_next(m_vm, tempHash, m_job.blob(), job.size(), m_hash); randomx_calculate_hash_next(m_vm, tempHash, m_job.blob(), job.size(), m_hash, job.algorithm());
} }
else else
# endif # endif
@@ -316,11 +334,23 @@ void xmrig::CpuWorker<N>::start()
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
case Algorithm::GHOSTRIDER: case Algorithm::GHOSTRIDER:
if (N == 8) { switch (job.algorithm()) {
ghostrider::hash_octa(m_job.blob(), job.size(), m_hash, m_ctx, m_ghHelper); case Algorithm::GHOSTRIDER_RTM:
} if (N == 8) {
else { ghostrider::hash_octa(m_job.blob(), job.size(), m_hash, m_ctx, m_ghHelper);
valid = false; } else {
valid = false;
}
break;
case Algorithm::FLEX_KCN:
if (N == 1) {
flex_hash(reinterpret_cast<const char*>(m_job.blob()), reinterpret_cast<char*>(m_hash), m_ctx);
} else {
valid = false;
}
break;
default:
valid = false;
} }
break; break;
# endif # endif
@@ -387,7 +417,8 @@ template<size_t N>
bool xmrig::CpuWorker<N>::verify(const Algorithm &algorithm, const uint8_t *referenceValue) bool xmrig::CpuWorker<N>::verify(const Algorithm &algorithm, const uint8_t *referenceValue)
{ {
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (algorithm == Algorithm::GHOSTRIDER_RTM) { switch (algorithm) {
case Algorithm::GHOSTRIDER_RTM: {
uint8_t blob[N * 80] = {}; uint8_t blob[N * 80] = {};
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
blob[i * 80 + 0] = static_cast<uint8_t>(i); blob[i * 80 + 0] = static_cast<uint8_t>(i);
@@ -414,6 +445,19 @@ bool xmrig::CpuWorker<N>::verify(const Algorithm &algorithm, const uint8_t *refe
} }
return true; return true;
}
case Algorithm::FLEX_KCN: {
const uint8_t header[80] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xcc, 0xa6, 0x6a,
0x44, 0xf8, 0xbd, 0x55, 0x45, 0xc3, 0x16, 0x4a, 0x3a, 0x76, 0xda, 0x50, 0x39, 0x53, 0x28, 0xc9, 0x07, 0x56, 0x33, 0x77,
0x5b, 0xc4, 0xc8, 0x79, 0x8f, 0xd6, 0x77, 0x2b, 0x70, 0x0d, 0x21, 0x5c, 0xf0, 0xff, 0x0f, 0x1e, 0x00, 0x00, 0x00, 0x00
};
char hash[32] = {};
flex_hash(reinterpret_cast<const char*>(header), hash, m_ctx);
return memcmp(referenceValue, hash, sizeof hash) == 0;
}
default:;
} }
# endif # endif
+1 -1
View File
@@ -55,7 +55,7 @@ public:
size_t threads() const override size_t threads() const override
{ {
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
return ((m_algorithm.family() == Algorithm::GHOSTRIDER) && m_ghHelper) ? 2 : 1; return ((m_algorithm.id() == Algorithm::GHOSTRIDER_RTM) && m_ghHelper) ? 2 : 1;
# else # else
return 1; return 1;
# endif # endif
+29 -11
View File
@@ -318,9 +318,12 @@ const char *xmrig::BasicCpuInfo::backend() const
} }
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint32_t) const xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const
{ {
const size_t count = std::thread::hardware_concurrency(); const uint32_t count = std::thread::hardware_concurrency();
const uint32_t count_limit = std::max(static_cast<uint32_t>(count * (limit / 100.0f)), 1U);
const uint32_t count_limit2 = std::max(static_cast<uint32_t>(count / 2), count_limit);
const uint32_t count_limit4 = std::max(static_cast<uint32_t>(count / 4), count_limit);
if (count == 1) { if (count == 1) {
return 1; return 1;
@@ -330,13 +333,13 @@ xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint3
# ifdef XMRIG_ALGO_CN_LITE # ifdef XMRIG_ALGO_CN_LITE
if (f == Algorithm::CN_LITE) { if (f == Algorithm::CN_LITE) {
return CpuThreads(count, 1); return CpuThreads(count_limit, 1);
} }
# endif # endif
# ifdef XMRIG_ALGO_CN_PICO # ifdef XMRIG_ALGO_CN_PICO
if (f == Algorithm::CN_PICO) { if (f == Algorithm::CN_PICO) {
return CpuThreads(count, 2); return CpuThreads(count_limit, 2);
} }
# endif # endif
@@ -348,33 +351,48 @@ xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint3
# ifdef XMRIG_ALGO_CN_HEAVY # ifdef XMRIG_ALGO_CN_HEAVY
if (f == Algorithm::CN_HEAVY) { if (f == Algorithm::CN_HEAVY) {
return CpuThreads(std::max<size_t>(count / 4, 1), 1); return CpuThreads(count_limit4, 1);
}
# endif
# ifdef XMRIG_ALGO_CN_GPU
if (algorithm == Algorithm::CN_GPU) {
return count_limit;
} }
# endif # endif
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
if (f == Algorithm::RANDOM_X) { if (f == Algorithm::RANDOM_X) {
if (algorithm == Algorithm::RX_WOW) { if (algorithm == Algorithm::RX_WOW) {
return count; return count_limit;
} }
return std::max<size_t>(count / 2, 1); if (algorithm == Algorithm::RX_XLA) {
CpuThreads threads;
for (size_t i = 0; i < count_limit2; ++i) {
threads.add(i, 0);
}
return threads;
}
return count_limit2;
} }
# endif # endif
# ifdef XMRIG_ALGO_ARGON2 # ifdef XMRIG_ALGO_ARGON2
if (f == Algorithm::ARGON2) { if (f == Algorithm::ARGON2) {
return count; return count_limit;
} }
# endif # endif
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (f == Algorithm::GHOSTRIDER) { switch (algorithm.id()) {
return CpuThreads(std::max<size_t>(count / 2, 1), 8); case Algorithm::GHOSTRIDER_RTM: return CpuThreads(std::max<size_t>(count / 2, 1), 8);
case Algorithm::FLEX_KCN: return CpuThreads(std::max<size_t>(count / 2, 1), 1);
} }
# endif # endif
return CpuThreads(std::max<size_t>(count / 2, 1), 1); return CpuThreads(count_limit2, 1);
} }
@@ -102,8 +102,9 @@ const char *xmrig::BasicCpuInfo::backend() const
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint32_t) const xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint32_t) const
{ {
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (algorithm.family() == Algorithm::GHOSTRIDER) { switch (algorithm.id()) {
return CpuThreads(threads(), 8); case Algorithm::GHOSTRIDER_RTM: return CpuThreads(threads(), 8);
case Algorithm::FLEX_KCN: return CpuThreads(threads(), 1);
} }
# endif # endif
+9 -1
View File
@@ -260,7 +260,7 @@ xmrig::CpuThreads xmrig::HwlocCpuInfo::allThreads(const Algorithm &algorithm, ui
CpuThreads threads; CpuThreads threads;
threads.reserve(m_threads); threads.reserve(m_threads);
const uint32_t intensity = (algorithm.family() == Algorithm::GHOSTRIDER) ? 8 : 0; const uint32_t intensity = (algorithm.id() == Algorithm::GHOSTRIDER_RTM) ? 8 : 0;
for (const int32_t pu : m_units) { for (const int32_t pu : m_units) {
threads.add(pu, intensity); threads.add(pu, intensity);
@@ -340,6 +340,12 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
intensity = 2; intensity = 2;
} }
# ifdef XMRIG_ALGO_CN_GPU
if (algorithm == Algorithm::CN_GPU) {
cacheHashes = PUs;
}
# endif
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
if ((algorithm.family() == Algorithm::RANDOM_X) && L3_exclusive && (PUs > cores.size()) && (PUs < cores.size() * 2)) { if ((algorithm.family() == Algorithm::RANDOM_X) && L3_exclusive && (PUs > cores.size()) && (PUs < cores.size() * 2)) {
// Use all L3+L2 on latest Intel CPUs with P-cores, E-cores and exclusive L3 cache // Use all L3+L2 on latest Intel CPUs with P-cores, E-cores and exclusive L3 cache
@@ -348,6 +354,8 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
if (extra == 0 && algorithm.l2() > 0) { if (extra == 0 && algorithm.l2() > 0) {
cacheHashes = std::min<size_t>(std::max<size_t>(L2 / algorithm.l2(), cores.size()), cacheHashes); cacheHashes = std::min<size_t>(std::max<size_t>(L2 / algorithm.l2(), cores.size()), cacheHashes);
} }
if (algorithm == Algorithm::RX_XLA) cacheHashes = cores.size();
# endif # endif
if (limit > 0) { if (limit > 0) {
+8
View File
@@ -52,6 +52,9 @@ size_t inline generate<Algorithm::CN>(Threads<CudaThreads> &threads, const std::
count += generate(Algorithm::kCN, threads, Algorithm::CN_1, devices); count += generate(Algorithm::kCN, threads, Algorithm::CN_1, devices);
count += generate(Algorithm::kCN_2, threads, Algorithm::CN_2, devices); count += generate(Algorithm::kCN_2, threads, Algorithm::CN_2, devices);
# ifdef XMRIG_ALGO_CN_GPU
count += generate(Algorithm::kCN_GPU, threads, Algorithm::CN_GPU, devices);
# endif
if (!threads.isExist(Algorithm::CN_0)) { if (!threads.isExist(Algorithm::CN_0)) {
threads.disable(Algorithm::CN_0); threads.disable(Algorithm::CN_0);
@@ -114,6 +117,7 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<CudaThreads> &threads, const
auto rx = CudaThreads(devices, Algorithm::RX_0); auto rx = CudaThreads(devices, Algorithm::RX_0);
auto wow = CudaThreads(devices, Algorithm::RX_WOW); auto wow = CudaThreads(devices, Algorithm::RX_WOW);
auto arq = CudaThreads(devices, Algorithm::RX_ARQ); auto arq = CudaThreads(devices, Algorithm::RX_ARQ);
auto xeq = CudaThreads(devices, Algorithm::RX_XEQ);
auto kva = CudaThreads(devices, Algorithm::RX_KEVA); auto kva = CudaThreads(devices, Algorithm::RX_KEVA);
if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) { if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) {
@@ -124,6 +128,10 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<CudaThreads> &threads, const
count += threads.move(Algorithm::kRX_ARQ, std::move(arq)); count += threads.move(Algorithm::kRX_ARQ, std::move(arq));
} }
if (!threads.isExist(Algorithm::RX_XEQ) && xeq != rx) {
count += threads.move(Algorithm::kRX_XEQ, std::move(xeq));
}
if (!threads.isExist(Algorithm::RX_KEVA) && kva != rx) { if (!threads.isExist(Algorithm::RX_KEVA) && kva != rx) {
count += threads.move(Algorithm::kRX_KEVA, std::move(kva)); count += threads.move(Algorithm::kRX_KEVA, std::move(kva));
} }
+8
View File
@@ -51,6 +51,9 @@ size_t inline generate<Algorithm::CN>(Threads<OclThreads> &threads, const std::v
count += generate(Algorithm::kCN, threads, Algorithm::CN_1, devices); count += generate(Algorithm::kCN, threads, Algorithm::CN_1, devices);
count += generate(Algorithm::kCN_2, threads, Algorithm::CN_2, devices); count += generate(Algorithm::kCN_2, threads, Algorithm::CN_2, devices);
# ifdef XMRIG_ALGO_CN_GPU
count += generate(Algorithm::kCN_GPU, threads, Algorithm::CN_GPU, devices);
# endif
if (!threads.isExist(Algorithm::CN_0)) { if (!threads.isExist(Algorithm::CN_0)) {
threads.disable(Algorithm::CN_0); threads.disable(Algorithm::CN_0);
@@ -113,6 +116,7 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<OclThreads> &threads, const
auto rx = OclThreads(devices, Algorithm::RX_0); auto rx = OclThreads(devices, Algorithm::RX_0);
auto wow = OclThreads(devices, Algorithm::RX_WOW); auto wow = OclThreads(devices, Algorithm::RX_WOW);
auto arq = OclThreads(devices, Algorithm::RX_ARQ); auto arq = OclThreads(devices, Algorithm::RX_ARQ);
auto xeq = OclThreads(devices, Algorithm::RX_XEQ);
if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) { if (!threads.isExist(Algorithm::RX_WOW) && wow != rx) {
count += threads.move(Algorithm::kRX_WOW, std::move(wow)); count += threads.move(Algorithm::kRX_WOW, std::move(wow));
@@ -122,6 +126,10 @@ size_t inline generate<Algorithm::RANDOM_X>(Threads<OclThreads> &threads, const
count += threads.move(Algorithm::kRX_ARQ, std::move(arq)); count += threads.move(Algorithm::kRX_ARQ, std::move(arq));
} }
if (!threads.isExist(Algorithm::RX_XEQ) && xeq != rx) {
count += threads.move(Algorithm::kRX_XEQ, std::move(xeq));
}
count += threads.move(Algorithm::kRX, std::move(rx)); count += threads.move(Algorithm::kRX, std::move(rx));
return count; return count;
+14
View File
@@ -45,6 +45,20 @@ public:
setIntensity(intensity); setIntensity(intensity);
} }
# ifdef XMRIG_ALGO_CN_GPU
OclThread(uint32_t index, uint32_t intensity, uint32_t worksize, uint32_t threads, uint32_t unrollFactor) :
m_fields(0),
m_threads(threads, -1),
m_index(index),
m_memChunk(0),
m_stridedIndex(0),
m_unrollFactor(unrollFactor),
m_worksize(worksize)
{
setIntensity(intensity);
}
# endif
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
OclThread(uint32_t index, uint32_t intensity, uint32_t worksize, uint32_t threads, bool gcnAsm, bool datasetHost, uint32_t bfactor) : OclThread(uint32_t index, uint32_t intensity, uint32_t worksize, uint32_t threads, bool gcnAsm, bool datasetHost, uint32_t bfactor) :
m_datasetHost(datasetHost), m_datasetHost(datasetHost),
+10
View File
@@ -30,6 +30,10 @@
#include "net/JobResults.h" #include "net/JobResults.h"
#ifdef XMRIG_ALGO_CN_GPU
# include "backend/opencl/runners/OclRyoRunner.h"
#endif
#ifdef XMRIG_ALGO_RANDOMX #ifdef XMRIG_ALGO_RANDOMX
# include "backend/opencl/runners/OclRxJitRunner.h" # include "backend/opencl/runners/OclRxJitRunner.h"
# include "backend/opencl/runners/OclRxVmRunner.h" # include "backend/opencl/runners/OclRxVmRunner.h"
@@ -93,6 +97,12 @@ xmrig::OclWorker::OclWorker(size_t id, const OclLaunchData &data) :
break; break;
default: default:
# ifdef XMRIG_ALGO_CN_GPU
if (m_algorithm == Algorithm::CN_GPU) {
m_runner = new OclRyoRunner(id, data);
}
else
# endif
m_runner = new OclCnRunner(id, data); m_runner = new OclCnRunner(id, data);
break; break;
} }
+10
View File
@@ -28,6 +28,10 @@
#include "base/crypto/Algorithm.h" #include "base/crypto/Algorithm.h"
#ifdef XMRIG_ALGO_CN_GPU
# include "backend/opencl/cl/cn/cryptonight_gpu_cl.h"
#endif
#ifdef XMRIG_ALGO_RANDOMX #ifdef XMRIG_ALGO_RANDOMX
# include "backend/opencl/cl/rx/randomx_cl.h" # include "backend/opencl/cl/rx/randomx_cl.h"
#endif #endif
@@ -40,6 +44,12 @@
const char *xmrig::OclSource::get(const Algorithm &algorithm) const char *xmrig::OclSource::get(const Algorithm &algorithm)
{ {
# ifdef XMRIG_ALGO_CN_GPU
if (algorithm == Algorithm::CN_GPU) {
return cryptonight_gpu_cl;
}
# endif
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
if (algorithm.family() == Algorithm::RANDOM_X) { if (algorithm.family() == Algorithm::RANDOM_X) {
return randomx_cl; return randomx_cl;
+5 -1
View File
@@ -18,9 +18,11 @@
#define ALGO_CN_PICO_0 0x63120200 #define ALGO_CN_PICO_0 0x63120200
#define ALGO_CN_PICO_TLO 0x63120274 #define ALGO_CN_PICO_TLO 0x63120274
#define ALGO_CN_UPX2 0x63110200 #define ALGO_CN_UPX2 0x63110200
#define ALGO_CN_GPU 0x63150300
#define ALGO_RX_0 0x72151200 #define ALGO_RX_0 0x72151200
#define ALGO_RX_WOW 0x72141177 #define ALGO_RX_WOW 0x72141177
#define ALGO_RX_ARQMA 0x72121061 #define ALGO_RX_ARQ 0x72121061
#define ALGO_RX_XEQ 0x72121000
#define ALGO_RX_SFX 0x72151273 #define ALGO_RX_SFX 0x72151273
#define ALGO_RX_KEVA 0x7214116b #define ALGO_RX_KEVA 0x7214116b
#define ALGO_RX_GRAFT 0x72151267 #define ALGO_RX_GRAFT 0x72151267
@@ -29,6 +31,8 @@
#define ALGO_AR2_WRKZ 0x61120000 #define ALGO_AR2_WRKZ 0x61120000
#define ALGO_KAWPOW_RVN 0x6b0f0000 #define ALGO_KAWPOW_RVN 0x6b0f0000
#define ALGO_RX_XLA 0x721211ff
#define FAMILY_UNKNOWN 0 #define FAMILY_UNKNOWN 0
#define FAMILY_CN 0x63150000 #define FAMILY_CN 0x63150000
#define FAMILY_CN_LITE 0x63140000 #define FAMILY_CN_LITE 0x63140000
File diff suppressed because it is too large Load Diff
+520
View File
@@ -0,0 +1,520 @@
#include "wolf-aes.cl"
#include "keccak.cl"
inline uint getIdx()
{
return get_global_id(0) - get_global_offset(0);
}
#define IDX(x) (x)
inline float4 _mm_add_ps(float4 a, float4 b)
{
return a + b;
}
inline float4 _mm_sub_ps(float4 a, float4 b)
{
return a - b;
}
inline float4 _mm_mul_ps(float4 a, float4 b)
{
return a * b;
}
inline float4 _mm_div_ps(float4 a, float4 b)
{
return a / b;
}
inline float4 _mm_and_ps(float4 a, int b)
{
return as_float4(as_int4(a) & (int4)(b));
}
inline float4 _mm_or_ps(float4 a, int b)
{
return as_float4(as_int4(a) | (int4)(b));
}
inline float4 _mm_fmod_ps(float4 v, float dc)
{
float4 d = (float4)(dc);
float4 c = _mm_div_ps(v, d);
c = trunc(c);
c = _mm_mul_ps(c, d);
return _mm_sub_ps(v, c);
}
inline int4 _mm_xor_si128(int4 a, int4 b)
{
return a ^ b;
}
inline float4 _mm_xor_ps(float4 a, int b)
{
return as_float4(as_int4(a) ^ (int4)(b));
}
inline int4 _mm_alignr_epi8(int4 a, const uint rot)
{
const uint right = 8 * rot;
const uint left = (32 - 8 * rot);
return (int4)(
((uint)a.x >> right) | ( a.y << left ),
((uint)a.y >> right) | ( a.z << left ),
((uint)a.z >> right) | ( a.w << left ),
((uint)a.w >> right) | ( a.x << left )
);
}
inline global int4* scratchpad_ptr(uint idx, uint n, __global int *lpad) { return (__global int4*)((__global char*)lpad + (idx & MASK) + n * 16); }
inline float4 fma_break(float4 x)
{
// Break the dependency chain by setting the exp to ?????01
x = _mm_and_ps(x, 0xFEFFFFFF);
return _mm_or_ps(x, 0x00800000);
}
inline void sub_round(float4 n0, float4 n1, float4 n2, float4 n3, float4 rnd_c, float4* n, float4* d, float4* c)
{
n1 = _mm_add_ps(n1, *c);
float4 nn = _mm_mul_ps(n0, *c);
nn = _mm_mul_ps(n1, _mm_mul_ps(nn,nn));
nn = fma_break(nn);
*n = _mm_add_ps(*n, nn);
n3 = _mm_sub_ps(n3, *c);
float4 dd = _mm_mul_ps(n2, *c);
dd = _mm_mul_ps(n3, _mm_mul_ps(dd,dd));
dd = fma_break(dd);
*d = _mm_add_ps(*d, dd);
//Constant feedback
*c = _mm_add_ps(*c, rnd_c);
*c = _mm_add_ps(*c, (float4)(0.734375f));
float4 r = _mm_add_ps(nn, dd);
r = _mm_and_ps(r, 0x807FFFFF);
r = _mm_or_ps(r, 0x40000000);
*c = _mm_add_ps(*c, r);
}
// 9*8 + 2 = 74
inline void round_compute(float4 n0, float4 n1, float4 n2, float4 n3, float4 rnd_c, float4* c, float4* r)
{
float4 n = (float4)(0.0f);
float4 d = (float4)(0.0f);
sub_round(n0, n1, n2, n3, rnd_c, &n, &d, c);
sub_round(n1, n2, n3, n0, rnd_c, &n, &d, c);
sub_round(n2, n3, n0, n1, rnd_c, &n, &d, c);
sub_round(n3, n0, n1, n2, rnd_c, &n, &d, c);
sub_round(n3, n2, n1, n0, rnd_c, &n, &d, c);
sub_round(n2, n1, n0, n3, rnd_c, &n, &d, c);
sub_round(n1, n0, n3, n2, rnd_c, &n, &d, c);
sub_round(n0, n3, n2, n1, rnd_c, &n, &d, c);
// Make sure abs(d) > 2.0 - this prevents division by zero and accidental overflows by division by < 1.0
d = _mm_and_ps(d, 0xFF7FFFFF);
d = _mm_or_ps(d, 0x40000000);
*r =_mm_add_ps(*r, _mm_div_ps(n,d));
}
inline int4 single_compute(float4 n0, float4 n1, float4 n2, float4 n3, float cnt, float4 rnd_c, __local float4* sum)
{
float4 c= (float4)(cnt);
// 35 maths calls follow (140 FLOPS)
float4 r = (float4)(0.0f);
for (int i = 0; i < 4; ++i) {
round_compute(n0, n1, n2, n3, rnd_c, &c, &r);
}
// do a quick fmod by setting exp to 2
r = _mm_and_ps(r, 0x807FFFFF);
r = _mm_or_ps(r, 0x40000000);
*sum = r; // 34
float4 x = (float4)(536870880.0f);
r = _mm_mul_ps(r, x); // 35
return convert_int4_rte(r);
}
inline void single_compute_wrap(const uint rot, int4 v0, int4 v1, int4 v2, int4 v3, float cnt, float4 rnd_c, __local float4* sum, __local int4* out)
{
float4 n0 = convert_float4_rte(v0);
float4 n1 = convert_float4_rte(v1);
float4 n2 = convert_float4_rte(v2);
float4 n3 = convert_float4_rte(v3);
int4 r = single_compute(n0, n1, n2, n3, cnt, rnd_c, sum);
*out = rot == 0 ? r : _mm_alignr_epi8(r, rot);
}
static const __constant uint look[16][4] = {
{0, 1, 2, 3},
{0, 2, 3, 1},
{0, 3, 1, 2},
{0, 3, 2, 1},
{1, 0, 2, 3},
{1, 2, 3, 0},
{1, 3, 0, 2},
{1, 3, 2, 0},
{2, 1, 0, 3},
{2, 0, 3, 1},
{2, 3, 1, 0},
{2, 3, 0, 1},
{3, 1, 2, 0},
{3, 2, 0, 1},
{3, 0, 1, 2},
{3, 0, 2, 1}
};
static const __constant float ccnt[16] = {
1.34375f,
1.28125f,
1.359375f,
1.3671875f,
1.4296875f,
1.3984375f,
1.3828125f,
1.3046875f,
1.4140625f,
1.2734375f,
1.2578125f,
1.2890625f,
1.3203125f,
1.3515625f,
1.3359375f,
1.4609375f
};
struct SharedMemChunk
{
int4 out[16];
float4 va[16];
};
__attribute__((reqd_work_group_size(WORKSIZE * 16, 1, 1)))
__kernel void cn1(__global int *lpad_in, __global int *spad, uint numThreads)
{
const uint gIdx = getIdx();
uint chunk = get_local_id(0) / 16;
__global int* lpad = (__global int*)((__global char*)lpad_in + MEMORY * (gIdx/16));
__local struct SharedMemChunk smem_in[WORKSIZE];
__local struct SharedMemChunk* smem = smem_in + chunk;
uint tid = get_local_id(0) % 16;
uint idxHash = gIdx/16;
uint s = ((__global uint*)spad)[idxHash * 50] >> 8;
float4 vs = (float4)(0);
// tid divided
const uint tidd = tid / 4;
// tid modulo
const uint tidm = tid % 4;
const uint block = tidd * 16 + tidm;
#pragma unroll CN_UNROLL
for (uint i = 0; i < ITERATIONS; i++) {
mem_fence(CLK_LOCAL_MEM_FENCE);
int tmp = ((__global int*)scratchpad_ptr(s, tidd, lpad))[tidm];
((__local int*)(smem->out))[tid] = tmp;
mem_fence(CLK_LOCAL_MEM_FENCE);
{
single_compute_wrap(
tidm,
*(smem->out + look[tid][0]),
*(smem->out + look[tid][1]),
*(smem->out + look[tid][2]),
*(smem->out + look[tid][3]),
ccnt[tid], vs, smem->va + tid,
smem->out + tid
);
}
mem_fence(CLK_LOCAL_MEM_FENCE);
int outXor = ((__local int*)smem->out)[block];
for (uint dd = block + 4; dd < (tidd + 1) * 16; dd += 4) {
outXor ^= ((__local int*)smem->out)[dd];
}
((__global int*)scratchpad_ptr(s, tidd, lpad))[tidm] = outXor ^ tmp;
((__local int*)smem->out)[tid] = outXor;
float va_tmp1 = ((__local float*)smem->va)[block] + ((__local float*)smem->va)[block + 4];
float va_tmp2 = ((__local float*)smem->va)[block+ 8] + ((__local float*)smem->va)[block + 12];
((__local float*)smem->va)[tid] = va_tmp1 + va_tmp2;
mem_fence(CLK_LOCAL_MEM_FENCE);
int out2 = ((__local int*)smem->out)[tid] ^ ((__local int*)smem->out)[tid + 4 ] ^ ((__local int*)smem->out)[tid + 8] ^ ((__local int*)smem->out)[tid + 12];
va_tmp1 = ((__local float*)smem->va)[block] + ((__local float*)smem->va)[block + 4];
va_tmp2 = ((__local float*)smem->va)[block + 8] + ((__local float*)smem->va)[block + 12];
va_tmp1 = va_tmp1 + va_tmp2;
va_tmp1 = fabs(va_tmp1);
float xx = va_tmp1 * 16777216.0f;
int xx_int = (int)xx;
((__local int*)smem->out)[tid] = out2 ^ xx_int;
((__local float*)smem->va)[tid] = va_tmp1 / 64.0f;
mem_fence(CLK_LOCAL_MEM_FENCE);
vs = smem->va[0];
s = smem->out[0].x ^ smem->out[0].y ^ smem->out[0].z ^ smem->out[0].w;
}
}
static const __constant uint skip[3] = {
20,22,22
};
inline void generate_512(uint idx, __local ulong* in, __global ulong* out)
{
ulong hash[25];
hash[0] = in[0] ^ idx;
for (int i = 1; i < 25; ++i) {
hash[i] = in[i];
}
for (int a = 0; a < 3; ++a) {
keccakf1600_1(hash);
for (int i = 0; i < skip[a]; ++i) {
out[i] = hash[i];
}
out += skip[a];
}
}
__attribute__((reqd_work_group_size(8, 8, 1)))
__kernel void cn0(__global ulong *input, int inlen, __global int *Scratchpad, __global ulong *states, uint Threads)
{
const uint gIdx = getIdx();
__local ulong State_buf[8 * 25];
__local ulong* State = State_buf + get_local_id(0) * 25;
{
states += 25 * gIdx;
Scratchpad = (__global int*)((__global char*)Scratchpad + MEMORY * gIdx);
if (get_local_id(1) == 0) {
# ifdef __NV_CL_C_VERSION
for(uint i = 0; i < 8; ++i)
State[i] = input[i];
# else
((__local ulong8 *)State)[0] = vload8(0, input);
# endif
State[8] = input[8];
State[9] = input[9];
State[10] = input[10];
((__local uint *)State)[9] &= 0x00FFFFFFU;
((__local uint *)State)[9] |= (((uint)get_global_id(0)) & 0xFF) << 24;
((__local uint *)State)[10] &= 0xFF000000U;
/* explicit cast to `uint` is required because some OpenCL implementations (e.g. NVIDIA)
* handle get_global_id and get_global_offset as signed long long int and add
* 0xFFFFFFFF... to `get_global_id` if we set on host side a 32bit offset where the first bit is `1`
* (even if it is correct casted to unsigned on the host)
*/
((__local uint *)State)[10] |= (((uint)get_global_id(0) >> 8));
for (int i = 11; i < 25; ++i) {
State[i] = 0x00UL;
}
// Last bit of padding
State[16] = 0x8000000000000000UL;
keccakf1600_2(State);
#pragma unroll
for (int i = 0; i < 25; ++i) {
states[i] = State[i];
}
}
}
}
__attribute__((reqd_work_group_size(64, 1, 1)))
__kernel void cn00(__global int *Scratchpad, __global ulong *states)
{
const uint gIdx = getIdx() / 64;
__local ulong State[25];
states += 25 * gIdx;
Scratchpad = (__global int*)((__global char*)Scratchpad + MEMORY * gIdx);
for (int i = get_local_id(0); i < 25; i += get_local_size(0)) {
State[i] = states[i];
}
barrier(CLK_LOCAL_MEM_FENCE);
for (uint i = get_local_id(0); i < MEMORY / 512; i += get_local_size(0)) {
generate_512(i, State, (__global ulong*)((__global uchar*)Scratchpad + i * 512));
}
}
__attribute__((reqd_work_group_size(8, 8, 1)))
__kernel void cn2(__global uint4 *Scratchpad, __global ulong *states, __global uint *output, ulong Target, uint Threads)
{
__local uint AES0[256], AES1[256], AES2[256], AES3[256];
uint ExpandedKey2[40];
uint4 text;
const uint gIdx = getIdx();
for (int i = get_local_id(1) * 8 + get_local_id(0); i < 256; i += 8 * 8) {
const uint tmp = AES0_C[i];
AES0[i] = tmp;
AES1[i] = rotate(tmp, 8U);
AES2[i] = rotate(tmp, 16U);
AES3[i] = rotate(tmp, 24U);
}
barrier(CLK_LOCAL_MEM_FENCE);
__local uint4 xin1[8][8];
__local uint4 xin2[8][8];
{
states += 25 * gIdx;
Scratchpad += gIdx * (MEMORY >> 4);
#if defined(__Tahiti__) || defined(__Pitcairn__)
for(int i = 0; i < 4; ++i) ((ulong *)ExpandedKey2)[i] = states[i + 4];
text = vload4(get_local_id(1) + 4, (__global uint *)states);
#else
text = vload4(get_local_id(1) + 4, (__global uint *)states);
((uint8 *)ExpandedKey2)[0] = vload8(1, (__global uint *)states);
#endif
AESExpandKey256(ExpandedKey2);
}
barrier(CLK_LOCAL_MEM_FENCE);
__local uint4* xin1_store = &xin1[get_local_id(1)][get_local_id(0)];
__local uint4* xin1_load = &xin1[(get_local_id(1) + 1) % 8][get_local_id(0)];
__local uint4* xin2_store = &xin2[get_local_id(1)][get_local_id(0)];
__local uint4* xin2_load = &xin2[(get_local_id(1) + 1) % 8][get_local_id(0)];
*xin2_store = (uint4)(0, 0, 0, 0);
{
#pragma unroll 2
for (int i = 0, i1 = get_local_id(1); i < (MEMORY >> 7); ++i, i1 = (i1 + 16) % (MEMORY >> 4)) {
text ^= Scratchpad[(uint)i1];
barrier(CLK_LOCAL_MEM_FENCE);
text ^= *xin2_load;
#pragma unroll 10
for(int j = 0; j < 10; ++j)
text = AES_Round(AES0, AES1, AES2, AES3, text, ((uint4 *)ExpandedKey2)[j]);
*xin1_store = text;
text ^= Scratchpad[(uint)i1 + 8u];
barrier(CLK_LOCAL_MEM_FENCE);
text ^= *xin1_load;
#pragma unroll 10
for(int j = 0; j < 10; ++j)
text = AES_Round(AES0, AES1, AES2, AES3, text, ((uint4 *)ExpandedKey2)[j]);
*xin2_store = text;
}
barrier(CLK_LOCAL_MEM_FENCE);
text ^= *xin2_load;
}
/* Also left over threads performe this loop.
* The left over thread results will be ignored
*/
#pragma unroll 16
for(size_t i = 0; i < 16; i++)
{
#pragma unroll 10
for (int j = 0; j < 10; ++j) {
text = AES_Round(AES0, AES1, AES2, AES3, text, ((uint4 *)ExpandedKey2)[j]);
}
barrier(CLK_LOCAL_MEM_FENCE);
*xin1_store = text;
barrier(CLK_LOCAL_MEM_FENCE);
text ^= *xin1_load;
}
__local ulong State_buf[8 * 25];
{
vstore2(as_ulong2(text), get_local_id(1) + 4, states);
}
barrier(CLK_GLOBAL_MEM_FENCE);
{
if(!get_local_id(1))
{
__local ulong* State = State_buf + get_local_id(0) * 25;
for(int i = 0; i < 25; ++i) State[i] = states[i];
keccakf1600_2(State);
if(State[3] <= Target)
{
ulong outIdx = atomic_inc(output + 0xFF);
if(outIdx < 0xFF)
output[outIdx] = get_global_id(0);
}
}
}
mem_fence(CLK_GLOBAL_MEM_FENCE);
}
@@ -0,0 +1,639 @@
#pragma once
namespace xmrig {
static const char cryptonight_gpu_cl[20170] = {
0x23,0x69,0x66,0x6e,0x64,0x65,0x66,0x20,0x57,0x4f,0x4c,0x46,0x5f,0x41,0x45,0x53,0x5f,0x43,0x4c,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x57,0x4f,0x4c,0x46,
0x5f,0x41,0x45,0x53,0x5f,0x43,0x4c,0x0a,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x53,0x54,0x41,0x54,0x49,0x43,0x0a,0x23,0x75,0x6e,0x64,0x65,0x66,0x20,0x53,0x54,0x41,
0x54,0x49,0x43,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x63,0x6c,0x5f,0x61,0x6d,0x64,0x5f,0x6d,0x65,0x64,0x69,0x61,0x5f,0x6f,
0x70,0x73,0x32,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x53,0x54,0x41,0x54,0x49,0x43,0x20,0x73,0x74,0x61,0x74,0x69,0x63,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,
0x61,0x20,0x4f,0x50,0x45,0x4e,0x43,0x4c,0x20,0x45,0x58,0x54,0x45,0x4e,0x53,0x49,0x4f,0x4e,0x20,0x63,0x6c,0x5f,0x61,0x6d,0x64,0x5f,0x6d,0x65,0x64,0x69,0x61,0x5f,
0x6f,0x70,0x73,0x32,0x20,0x3a,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x0a,0x23,0x65,0x6c,0x73,0x65,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x53,0x54,0x41,0x54,
0x49,0x43,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x69,0x6e,0x74,0x20,0x61,0x6d,0x64,0x5f,0x62,0x66,0x65,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x20,0x73,0x72,0x63,0x30,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x20,0x77,0x69,0x64,0x74,0x68,0x29,0x0a,0x7b,0x0a,0x69,0x66,0x28,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x2b,0x77,0x69,0x64,0x74,0x68,0x29,0x3c,0x33,0x32,
0x75,0x29,0x20,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x73,0x72,0x63,0x30,0x3c,0x3c,0x28,0x33,0x32,0x75,0x2d,0x6f,0x66,0x66,0x73,0x65,0x74,0x2d,0x77,
0x69,0x64,0x74,0x68,0x29,0x29,0x3e,0x3e,0x28,0x33,0x32,0x75,0x2d,0x77,0x69,0x64,0x74,0x68,0x29,0x3b,0x0a,0x7d,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x72,
0x63,0x30,0x3e,0x3e,0x6f,0x66,0x66,0x73,0x65,0x74,0x3b,0x0a,0x7d,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x53,0x54,0x41,0x54,0x49,0x43,0x20,0x63,0x6f,0x6e,0x73,
0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x41,0x45,0x53,0x30,0x5f,0x43,0x5b,0x32,0x35,0x36,0x5d,0x20,0x3d,0x0a,
0x7b,0x0a,0x30,0x78,0x41,0x35,0x36,0x33,0x36,0x33,0x43,0x36,0x55,0x2c,0x30,0x78,0x38,0x34,0x37,0x43,0x37,0x43,0x46,0x38,0x55,0x2c,0x30,0x78,0x39,0x39,0x37,0x37,
0x37,0x37,0x45,0x45,0x55,0x2c,0x30,0x78,0x38,0x44,0x37,0x42,0x37,0x42,0x46,0x36,0x55,0x2c,0x0a,0x30,0x78,0x30,0x44,0x46,0x32,0x46,0x32,0x46,0x46,0x55,0x2c,0x30,
0x78,0x42,0x44,0x36,0x42,0x36,0x42,0x44,0x36,0x55,0x2c,0x30,0x78,0x42,0x31,0x36,0x46,0x36,0x46,0x44,0x45,0x55,0x2c,0x30,0x78,0x35,0x34,0x43,0x35,0x43,0x35,0x39,
0x31,0x55,0x2c,0x0a,0x30,0x78,0x35,0x30,0x33,0x30,0x33,0x30,0x36,0x30,0x55,0x2c,0x30,0x78,0x30,0x33,0x30,0x31,0x30,0x31,0x30,0x32,0x55,0x2c,0x30,0x78,0x41,0x39,
0x36,0x37,0x36,0x37,0x43,0x45,0x55,0x2c,0x30,0x78,0x37,0x44,0x32,0x42,0x32,0x42,0x35,0x36,0x55,0x2c,0x0a,0x30,0x78,0x31,0x39,0x46,0x45,0x46,0x45,0x45,0x37,0x55,
0x2c,0x30,0x78,0x36,0x32,0x44,0x37,0x44,0x37,0x42,0x35,0x55,0x2c,0x30,0x78,0x45,0x36,0x41,0x42,0x41,0x42,0x34,0x44,0x55,0x2c,0x30,0x78,0x39,0x41,0x37,0x36,0x37,
0x36,0x45,0x43,0x55,0x2c,0x0a,0x30,0x78,0x34,0x35,0x43,0x41,0x43,0x41,0x38,0x46,0x55,0x2c,0x30,0x78,0x39,0x44,0x38,0x32,0x38,0x32,0x31,0x46,0x55,0x2c,0x30,0x78,
0x34,0x30,0x43,0x39,0x43,0x39,0x38,0x39,0x55,0x2c,0x30,0x78,0x38,0x37,0x37,0x44,0x37,0x44,0x46,0x41,0x55,0x2c,0x0a,0x30,0x78,0x31,0x35,0x46,0x41,0x46,0x41,0x45,
0x46,0x55,0x2c,0x30,0x78,0x45,0x42,0x35,0x39,0x35,0x39,0x42,0x32,0x55,0x2c,0x30,0x78,0x43,0x39,0x34,0x37,0x34,0x37,0x38,0x45,0x55,0x2c,0x30,0x78,0x30,0x42,0x46,
0x30,0x46,0x30,0x46,0x42,0x55,0x2c,0x0a,0x30,0x78,0x45,0x43,0x41,0x44,0x41,0x44,0x34,0x31,0x55,0x2c,0x30,0x78,0x36,0x37,0x44,0x34,0x44,0x34,0x42,0x33,0x55,0x2c,
0x30,0x78,0x46,0x44,0x41,0x32,0x41,0x32,0x35,0x46,0x55,0x2c,0x30,0x78,0x45,0x41,0x41,0x46,0x41,0x46,0x34,0x35,0x55,0x2c,0x0a,0x30,0x78,0x42,0x46,0x39,0x43,0x39,
0x43,0x32,0x33,0x55,0x2c,0x30,0x78,0x46,0x37,0x41,0x34,0x41,0x34,0x35,0x33,0x55,0x2c,0x30,0x78,0x39,0x36,0x37,0x32,0x37,0x32,0x45,0x34,0x55,0x2c,0x30,0x78,0x35,
0x42,0x43,0x30,0x43,0x30,0x39,0x42,0x55,0x2c,0x0a,0x30,0x78,0x43,0x32,0x42,0x37,0x42,0x37,0x37,0x35,0x55,0x2c,0x30,0x78,0x31,0x43,0x46,0x44,0x46,0x44,0x45,0x31,
0x55,0x2c,0x30,0x78,0x41,0x45,0x39,0x33,0x39,0x33,0x33,0x44,0x55,0x2c,0x30,0x78,0x36,0x41,0x32,0x36,0x32,0x36,0x34,0x43,0x55,0x2c,0x0a,0x30,0x78,0x35,0x41,0x33,
0x36,0x33,0x36,0x36,0x43,0x55,0x2c,0x30,0x78,0x34,0x31,0x33,0x46,0x33,0x46,0x37,0x45,0x55,0x2c,0x30,0x78,0x30,0x32,0x46,0x37,0x46,0x37,0x46,0x35,0x55,0x2c,0x30,
0x78,0x34,0x46,0x43,0x43,0x43,0x43,0x38,0x33,0x55,0x2c,0x0a,0x30,0x78,0x35,0x43,0x33,0x34,0x33,0x34,0x36,0x38,0x55,0x2c,0x30,0x78,0x46,0x34,0x41,0x35,0x41,0x35,
0x35,0x31,0x55,0x2c,0x30,0x78,0x33,0x34,0x45,0x35,0x45,0x35,0x44,0x31,0x55,0x2c,0x30,0x78,0x30,0x38,0x46,0x31,0x46,0x31,0x46,0x39,0x55,0x2c,0x0a,0x30,0x78,0x39,
0x33,0x37,0x31,0x37,0x31,0x45,0x32,0x55,0x2c,0x30,0x78,0x37,0x33,0x44,0x38,0x44,0x38,0x41,0x42,0x55,0x2c,0x30,0x78,0x35,0x33,0x33,0x31,0x33,0x31,0x36,0x32,0x55,
0x2c,0x30,0x78,0x33,0x46,0x31,0x35,0x31,0x35,0x32,0x41,0x55,0x2c,0x0a,0x30,0x78,0x30,0x43,0x30,0x34,0x30,0x34,0x30,0x38,0x55,0x2c,0x30,0x78,0x35,0x32,0x43,0x37,
0x43,0x37,0x39,0x35,0x55,0x2c,0x30,0x78,0x36,0x35,0x32,0x33,0x32,0x33,0x34,0x36,0x55,0x2c,0x30,0x78,0x35,0x45,0x43,0x33,0x43,0x33,0x39,0x44,0x55,0x2c,0x0a,0x30,
0x78,0x32,0x38,0x31,0x38,0x31,0x38,0x33,0x30,0x55,0x2c,0x30,0x78,0x41,0x31,0x39,0x36,0x39,0x36,0x33,0x37,0x55,0x2c,0x30,0x78,0x30,0x46,0x30,0x35,0x30,0x35,0x30,
0x41,0x55,0x2c,0x30,0x78,0x42,0x35,0x39,0x41,0x39,0x41,0x32,0x46,0x55,0x2c,0x0a,0x30,0x78,0x30,0x39,0x30,0x37,0x30,0x37,0x30,0x45,0x55,0x2c,0x30,0x78,0x33,0x36,
0x31,0x32,0x31,0x32,0x32,0x34,0x55,0x2c,0x30,0x78,0x39,0x42,0x38,0x30,0x38,0x30,0x31,0x42,0x55,0x2c,0x30,0x78,0x33,0x44,0x45,0x32,0x45,0x32,0x44,0x46,0x55,0x2c,
0x0a,0x30,0x78,0x32,0x36,0x45,0x42,0x45,0x42,0x43,0x44,0x55,0x2c,0x30,0x78,0x36,0x39,0x32,0x37,0x32,0x37,0x34,0x45,0x55,0x2c,0x30,0x78,0x43,0x44,0x42,0x32,0x42,
0x32,0x37,0x46,0x55,0x2c,0x30,0x78,0x39,0x46,0x37,0x35,0x37,0x35,0x45,0x41,0x55,0x2c,0x0a,0x30,0x78,0x31,0x42,0x30,0x39,0x30,0x39,0x31,0x32,0x55,0x2c,0x30,0x78,
0x39,0x45,0x38,0x33,0x38,0x33,0x31,0x44,0x55,0x2c,0x30,0x78,0x37,0x34,0x32,0x43,0x32,0x43,0x35,0x38,0x55,0x2c,0x30,0x78,0x32,0x45,0x31,0x41,0x31,0x41,0x33,0x34,
0x55,0x2c,0x0a,0x30,0x78,0x32,0x44,0x31,0x42,0x31,0x42,0x33,0x36,0x55,0x2c,0x30,0x78,0x42,0x32,0x36,0x45,0x36,0x45,0x44,0x43,0x55,0x2c,0x30,0x78,0x45,0x45,0x35,
0x41,0x35,0x41,0x42,0x34,0x55,0x2c,0x30,0x78,0x46,0x42,0x41,0x30,0x41,0x30,0x35,0x42,0x55,0x2c,0x0a,0x30,0x78,0x46,0x36,0x35,0x32,0x35,0x32,0x41,0x34,0x55,0x2c,
0x30,0x78,0x34,0x44,0x33,0x42,0x33,0x42,0x37,0x36,0x55,0x2c,0x30,0x78,0x36,0x31,0x44,0x36,0x44,0x36,0x42,0x37,0x55,0x2c,0x30,0x78,0x43,0x45,0x42,0x33,0x42,0x33,
0x37,0x44,0x55,0x2c,0x0a,0x30,0x78,0x37,0x42,0x32,0x39,0x32,0x39,0x35,0x32,0x55,0x2c,0x30,0x78,0x33,0x45,0x45,0x33,0x45,0x33,0x44,0x44,0x55,0x2c,0x30,0x78,0x37,
0x31,0x32,0x46,0x32,0x46,0x35,0x45,0x55,0x2c,0x30,0x78,0x39,0x37,0x38,0x34,0x38,0x34,0x31,0x33,0x55,0x2c,0x0a,0x30,0x78,0x46,0x35,0x35,0x33,0x35,0x33,0x41,0x36,
0x55,0x2c,0x30,0x78,0x36,0x38,0x44,0x31,0x44,0x31,0x42,0x39,0x55,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x2c,0x30,0x78,0x32,0x43,0x45,0x44,
0x45,0x44,0x43,0x31,0x55,0x2c,0x0a,0x30,0x78,0x36,0x30,0x32,0x30,0x32,0x30,0x34,0x30,0x55,0x2c,0x30,0x78,0x31,0x46,0x46,0x43,0x46,0x43,0x45,0x33,0x55,0x2c,0x30,
0x78,0x43,0x38,0x42,0x31,0x42,0x31,0x37,0x39,0x55,0x2c,0x30,0x78,0x45,0x44,0x35,0x42,0x35,0x42,0x42,0x36,0x55,0x2c,0x0a,0x30,0x78,0x42,0x45,0x36,0x41,0x36,0x41,
0x44,0x34,0x55,0x2c,0x30,0x78,0x34,0x36,0x43,0x42,0x43,0x42,0x38,0x44,0x55,0x2c,0x30,0x78,0x44,0x39,0x42,0x45,0x42,0x45,0x36,0x37,0x55,0x2c,0x30,0x78,0x34,0x42,
0x33,0x39,0x33,0x39,0x37,0x32,0x55,0x2c,0x0a,0x30,0x78,0x44,0x45,0x34,0x41,0x34,0x41,0x39,0x34,0x55,0x2c,0x30,0x78,0x44,0x34,0x34,0x43,0x34,0x43,0x39,0x38,0x55,
0x2c,0x30,0x78,0x45,0x38,0x35,0x38,0x35,0x38,0x42,0x30,0x55,0x2c,0x30,0x78,0x34,0x41,0x43,0x46,0x43,0x46,0x38,0x35,0x55,0x2c,0x0a,0x30,0x78,0x36,0x42,0x44,0x30,
0x44,0x30,0x42,0x42,0x55,0x2c,0x30,0x78,0x32,0x41,0x45,0x46,0x45,0x46,0x43,0x35,0x55,0x2c,0x30,0x78,0x45,0x35,0x41,0x41,0x41,0x41,0x34,0x46,0x55,0x2c,0x30,0x78,
0x31,0x36,0x46,0x42,0x46,0x42,0x45,0x44,0x55,0x2c,0x0a,0x30,0x78,0x43,0x35,0x34,0x33,0x34,0x33,0x38,0x36,0x55,0x2c,0x30,0x78,0x44,0x37,0x34,0x44,0x34,0x44,0x39,
0x41,0x55,0x2c,0x30,0x78,0x35,0x35,0x33,0x33,0x33,0x33,0x36,0x36,0x55,0x2c,0x30,0x78,0x39,0x34,0x38,0x35,0x38,0x35,0x31,0x31,0x55,0x2c,0x0a,0x30,0x78,0x43,0x46,
0x34,0x35,0x34,0x35,0x38,0x41,0x55,0x2c,0x30,0x78,0x31,0x30,0x46,0x39,0x46,0x39,0x45,0x39,0x55,0x2c,0x30,0x78,0x30,0x36,0x30,0x32,0x30,0x32,0x30,0x34,0x55,0x2c,
0x30,0x78,0x38,0x31,0x37,0x46,0x37,0x46,0x46,0x45,0x55,0x2c,0x0a,0x30,0x78,0x46,0x30,0x35,0x30,0x35,0x30,0x41,0x30,0x55,0x2c,0x30,0x78,0x34,0x34,0x33,0x43,0x33,
0x43,0x37,0x38,0x55,0x2c,0x30,0x78,0x42,0x41,0x39,0x46,0x39,0x46,0x32,0x35,0x55,0x2c,0x30,0x78,0x45,0x33,0x41,0x38,0x41,0x38,0x34,0x42,0x55,0x2c,0x0a,0x30,0x78,
0x46,0x33,0x35,0x31,0x35,0x31,0x41,0x32,0x55,0x2c,0x30,0x78,0x46,0x45,0x41,0x33,0x41,0x33,0x35,0x44,0x55,0x2c,0x30,0x78,0x43,0x30,0x34,0x30,0x34,0x30,0x38,0x30,
0x55,0x2c,0x30,0x78,0x38,0x41,0x38,0x46,0x38,0x46,0x30,0x35,0x55,0x2c,0x0a,0x30,0x78,0x41,0x44,0x39,0x32,0x39,0x32,0x33,0x46,0x55,0x2c,0x30,0x78,0x42,0x43,0x39,
0x44,0x39,0x44,0x32,0x31,0x55,0x2c,0x30,0x78,0x34,0x38,0x33,0x38,0x33,0x38,0x37,0x30,0x55,0x2c,0x30,0x78,0x30,0x34,0x46,0x35,0x46,0x35,0x46,0x31,0x55,0x2c,0x0a,
0x30,0x78,0x44,0x46,0x42,0x43,0x42,0x43,0x36,0x33,0x55,0x2c,0x30,0x78,0x43,0x31,0x42,0x36,0x42,0x36,0x37,0x37,0x55,0x2c,0x30,0x78,0x37,0x35,0x44,0x41,0x44,0x41,
0x41,0x46,0x55,0x2c,0x30,0x78,0x36,0x33,0x32,0x31,0x32,0x31,0x34,0x32,0x55,0x2c,0x0a,0x30,0x78,0x33,0x30,0x31,0x30,0x31,0x30,0x32,0x30,0x55,0x2c,0x30,0x78,0x31,
0x41,0x46,0x46,0x46,0x46,0x45,0x35,0x55,0x2c,0x30,0x78,0x30,0x45,0x46,0x33,0x46,0x33,0x46,0x44,0x55,0x2c,0x30,0x78,0x36,0x44,0x44,0x32,0x44,0x32,0x42,0x46,0x55,
0x2c,0x0a,0x30,0x78,0x34,0x43,0x43,0x44,0x43,0x44,0x38,0x31,0x55,0x2c,0x30,0x78,0x31,0x34,0x30,0x43,0x30,0x43,0x31,0x38,0x55,0x2c,0x30,0x78,0x33,0x35,0x31,0x33,
0x31,0x33,0x32,0x36,0x55,0x2c,0x30,0x78,0x32,0x46,0x45,0x43,0x45,0x43,0x43,0x33,0x55,0x2c,0x0a,0x30,0x78,0x45,0x31,0x35,0x46,0x35,0x46,0x42,0x45,0x55,0x2c,0x30,
0x78,0x41,0x32,0x39,0x37,0x39,0x37,0x33,0x35,0x55,0x2c,0x30,0x78,0x43,0x43,0x34,0x34,0x34,0x34,0x38,0x38,0x55,0x2c,0x30,0x78,0x33,0x39,0x31,0x37,0x31,0x37,0x32,
0x45,0x55,0x2c,0x0a,0x30,0x78,0x35,0x37,0x43,0x34,0x43,0x34,0x39,0x33,0x55,0x2c,0x30,0x78,0x46,0x32,0x41,0x37,0x41,0x37,0x35,0x35,0x55,0x2c,0x30,0x78,0x38,0x32,
0x37,0x45,0x37,0x45,0x46,0x43,0x55,0x2c,0x30,0x78,0x34,0x37,0x33,0x44,0x33,0x44,0x37,0x41,0x55,0x2c,0x0a,0x30,0x78,0x41,0x43,0x36,0x34,0x36,0x34,0x43,0x38,0x55,
0x2c,0x30,0x78,0x45,0x37,0x35,0x44,0x35,0x44,0x42,0x41,0x55,0x2c,0x30,0x78,0x32,0x42,0x31,0x39,0x31,0x39,0x33,0x32,0x55,0x2c,0x30,0x78,0x39,0x35,0x37,0x33,0x37,
0x33,0x45,0x36,0x55,0x2c,0x0a,0x30,0x78,0x41,0x30,0x36,0x30,0x36,0x30,0x43,0x30,0x55,0x2c,0x30,0x78,0x39,0x38,0x38,0x31,0x38,0x31,0x31,0x39,0x55,0x2c,0x30,0x78,
0x44,0x31,0x34,0x46,0x34,0x46,0x39,0x45,0x55,0x2c,0x30,0x78,0x37,0x46,0x44,0x43,0x44,0x43,0x41,0x33,0x55,0x2c,0x0a,0x30,0x78,0x36,0x36,0x32,0x32,0x32,0x32,0x34,
0x34,0x55,0x2c,0x30,0x78,0x37,0x45,0x32,0x41,0x32,0x41,0x35,0x34,0x55,0x2c,0x30,0x78,0x41,0x42,0x39,0x30,0x39,0x30,0x33,0x42,0x55,0x2c,0x30,0x78,0x38,0x33,0x38,
0x38,0x38,0x38,0x30,0x42,0x55,0x2c,0x0a,0x30,0x78,0x43,0x41,0x34,0x36,0x34,0x36,0x38,0x43,0x55,0x2c,0x30,0x78,0x32,0x39,0x45,0x45,0x45,0x45,0x43,0x37,0x55,0x2c,
0x30,0x78,0x44,0x33,0x42,0x38,0x42,0x38,0x36,0x42,0x55,0x2c,0x30,0x78,0x33,0x43,0x31,0x34,0x31,0x34,0x32,0x38,0x55,0x2c,0x0a,0x30,0x78,0x37,0x39,0x44,0x45,0x44,
0x45,0x41,0x37,0x55,0x2c,0x30,0x78,0x45,0x32,0x35,0x45,0x35,0x45,0x42,0x43,0x55,0x2c,0x30,0x78,0x31,0x44,0x30,0x42,0x30,0x42,0x31,0x36,0x55,0x2c,0x30,0x78,0x37,
0x36,0x44,0x42,0x44,0x42,0x41,0x44,0x55,0x2c,0x0a,0x30,0x78,0x33,0x42,0x45,0x30,0x45,0x30,0x44,0x42,0x55,0x2c,0x30,0x78,0x35,0x36,0x33,0x32,0x33,0x32,0x36,0x34,
0x55,0x2c,0x30,0x78,0x34,0x45,0x33,0x41,0x33,0x41,0x37,0x34,0x55,0x2c,0x30,0x78,0x31,0x45,0x30,0x41,0x30,0x41,0x31,0x34,0x55,0x2c,0x0a,0x30,0x78,0x44,0x42,0x34,
0x39,0x34,0x39,0x39,0x32,0x55,0x2c,0x30,0x78,0x30,0x41,0x30,0x36,0x30,0x36,0x30,0x43,0x55,0x2c,0x30,0x78,0x36,0x43,0x32,0x34,0x32,0x34,0x34,0x38,0x55,0x2c,0x30,
0x78,0x45,0x34,0x35,0x43,0x35,0x43,0x42,0x38,0x55,0x2c,0x0a,0x30,0x78,0x35,0x44,0x43,0x32,0x43,0x32,0x39,0x46,0x55,0x2c,0x30,0x78,0x36,0x45,0x44,0x33,0x44,0x33,
0x42,0x44,0x55,0x2c,0x30,0x78,0x45,0x46,0x41,0x43,0x41,0x43,0x34,0x33,0x55,0x2c,0x30,0x78,0x41,0x36,0x36,0x32,0x36,0x32,0x43,0x34,0x55,0x2c,0x0a,0x30,0x78,0x41,
0x38,0x39,0x31,0x39,0x31,0x33,0x39,0x55,0x2c,0x30,0x78,0x41,0x34,0x39,0x35,0x39,0x35,0x33,0x31,0x55,0x2c,0x30,0x78,0x33,0x37,0x45,0x34,0x45,0x34,0x44,0x33,0x55,
0x2c,0x30,0x78,0x38,0x42,0x37,0x39,0x37,0x39,0x46,0x32,0x55,0x2c,0x0a,0x30,0x78,0x33,0x32,0x45,0x37,0x45,0x37,0x44,0x35,0x55,0x2c,0x30,0x78,0x34,0x33,0x43,0x38,
0x43,0x38,0x38,0x42,0x55,0x2c,0x30,0x78,0x35,0x39,0x33,0x37,0x33,0x37,0x36,0x45,0x55,0x2c,0x30,0x78,0x42,0x37,0x36,0x44,0x36,0x44,0x44,0x41,0x55,0x2c,0x0a,0x30,
0x78,0x38,0x43,0x38,0x44,0x38,0x44,0x30,0x31,0x55,0x2c,0x30,0x78,0x36,0x34,0x44,0x35,0x44,0x35,0x42,0x31,0x55,0x2c,0x30,0x78,0x44,0x32,0x34,0x45,0x34,0x45,0x39,
0x43,0x55,0x2c,0x30,0x78,0x45,0x30,0x41,0x39,0x41,0x39,0x34,0x39,0x55,0x2c,0x0a,0x30,0x78,0x42,0x34,0x36,0x43,0x36,0x43,0x44,0x38,0x55,0x2c,0x30,0x78,0x46,0x41,
0x35,0x36,0x35,0x36,0x41,0x43,0x55,0x2c,0x30,0x78,0x30,0x37,0x46,0x34,0x46,0x34,0x46,0x33,0x55,0x2c,0x30,0x78,0x32,0x35,0x45,0x41,0x45,0x41,0x43,0x46,0x55,0x2c,
0x0a,0x30,0x78,0x41,0x46,0x36,0x35,0x36,0x35,0x43,0x41,0x55,0x2c,0x30,0x78,0x38,0x45,0x37,0x41,0x37,0x41,0x46,0x34,0x55,0x2c,0x30,0x78,0x45,0x39,0x41,0x45,0x41,
0x45,0x34,0x37,0x55,0x2c,0x30,0x78,0x31,0x38,0x30,0x38,0x30,0x38,0x31,0x30,0x55,0x2c,0x0a,0x30,0x78,0x44,0x35,0x42,0x41,0x42,0x41,0x36,0x46,0x55,0x2c,0x30,0x78,
0x38,0x38,0x37,0x38,0x37,0x38,0x46,0x30,0x55,0x2c,0x30,0x78,0x36,0x46,0x32,0x35,0x32,0x35,0x34,0x41,0x55,0x2c,0x30,0x78,0x37,0x32,0x32,0x45,0x32,0x45,0x35,0x43,
0x55,0x2c,0x0a,0x30,0x78,0x32,0x34,0x31,0x43,0x31,0x43,0x33,0x38,0x55,0x2c,0x30,0x78,0x46,0x31,0x41,0x36,0x41,0x36,0x35,0x37,0x55,0x2c,0x30,0x78,0x43,0x37,0x42,
0x34,0x42,0x34,0x37,0x33,0x55,0x2c,0x30,0x78,0x35,0x31,0x43,0x36,0x43,0x36,0x39,0x37,0x55,0x2c,0x0a,0x30,0x78,0x32,0x33,0x45,0x38,0x45,0x38,0x43,0x42,0x55,0x2c,
0x30,0x78,0x37,0x43,0x44,0x44,0x44,0x44,0x41,0x31,0x55,0x2c,0x30,0x78,0x39,0x43,0x37,0x34,0x37,0x34,0x45,0x38,0x55,0x2c,0x30,0x78,0x32,0x31,0x31,0x46,0x31,0x46,
0x33,0x45,0x55,0x2c,0x0a,0x30,0x78,0x44,0x44,0x34,0x42,0x34,0x42,0x39,0x36,0x55,0x2c,0x30,0x78,0x44,0x43,0x42,0x44,0x42,0x44,0x36,0x31,0x55,0x2c,0x30,0x78,0x38,
0x36,0x38,0x42,0x38,0x42,0x30,0x44,0x55,0x2c,0x30,0x78,0x38,0x35,0x38,0x41,0x38,0x41,0x30,0x46,0x55,0x2c,0x0a,0x30,0x78,0x39,0x30,0x37,0x30,0x37,0x30,0x45,0x30,
0x55,0x2c,0x30,0x78,0x34,0x32,0x33,0x45,0x33,0x45,0x37,0x43,0x55,0x2c,0x30,0x78,0x43,0x34,0x42,0x35,0x42,0x35,0x37,0x31,0x55,0x2c,0x30,0x78,0x41,0x41,0x36,0x36,
0x36,0x36,0x43,0x43,0x55,0x2c,0x0a,0x30,0x78,0x44,0x38,0x34,0x38,0x34,0x38,0x39,0x30,0x55,0x2c,0x30,0x78,0x30,0x35,0x30,0x33,0x30,0x33,0x30,0x36,0x55,0x2c,0x30,
0x78,0x30,0x31,0x46,0x36,0x46,0x36,0x46,0x37,0x55,0x2c,0x30,0x78,0x31,0x32,0x30,0x45,0x30,0x45,0x31,0x43,0x55,0x2c,0x0a,0x30,0x78,0x41,0x33,0x36,0x31,0x36,0x31,
0x43,0x32,0x55,0x2c,0x30,0x78,0x35,0x46,0x33,0x35,0x33,0x35,0x36,0x41,0x55,0x2c,0x30,0x78,0x46,0x39,0x35,0x37,0x35,0x37,0x41,0x45,0x55,0x2c,0x30,0x78,0x44,0x30,
0x42,0x39,0x42,0x39,0x36,0x39,0x55,0x2c,0x0a,0x30,0x78,0x39,0x31,0x38,0x36,0x38,0x36,0x31,0x37,0x55,0x2c,0x30,0x78,0x35,0x38,0x43,0x31,0x43,0x31,0x39,0x39,0x55,
0x2c,0x30,0x78,0x32,0x37,0x31,0x44,0x31,0x44,0x33,0x41,0x55,0x2c,0x30,0x78,0x42,0x39,0x39,0x45,0x39,0x45,0x32,0x37,0x55,0x2c,0x0a,0x30,0x78,0x33,0x38,0x45,0x31,
0x45,0x31,0x44,0x39,0x55,0x2c,0x30,0x78,0x31,0x33,0x46,0x38,0x46,0x38,0x45,0x42,0x55,0x2c,0x30,0x78,0x42,0x33,0x39,0x38,0x39,0x38,0x32,0x42,0x55,0x2c,0x30,0x78,
0x33,0x33,0x31,0x31,0x31,0x31,0x32,0x32,0x55,0x2c,0x0a,0x30,0x78,0x42,0x42,0x36,0x39,0x36,0x39,0x44,0x32,0x55,0x2c,0x30,0x78,0x37,0x30,0x44,0x39,0x44,0x39,0x41,
0x39,0x55,0x2c,0x30,0x78,0x38,0x39,0x38,0x45,0x38,0x45,0x30,0x37,0x55,0x2c,0x30,0x78,0x41,0x37,0x39,0x34,0x39,0x34,0x33,0x33,0x55,0x2c,0x0a,0x30,0x78,0x42,0x36,
0x39,0x42,0x39,0x42,0x32,0x44,0x55,0x2c,0x30,0x78,0x32,0x32,0x31,0x45,0x31,0x45,0x33,0x43,0x55,0x2c,0x30,0x78,0x39,0x32,0x38,0x37,0x38,0x37,0x31,0x35,0x55,0x2c,
0x30,0x78,0x32,0x30,0x45,0x39,0x45,0x39,0x43,0x39,0x55,0x2c,0x0a,0x30,0x78,0x34,0x39,0x43,0x45,0x43,0x45,0x38,0x37,0x55,0x2c,0x30,0x78,0x46,0x46,0x35,0x35,0x35,
0x35,0x41,0x41,0x55,0x2c,0x30,0x78,0x37,0x38,0x32,0x38,0x32,0x38,0x35,0x30,0x55,0x2c,0x30,0x78,0x37,0x41,0x44,0x46,0x44,0x46,0x41,0x35,0x55,0x2c,0x0a,0x30,0x78,
0x38,0x46,0x38,0x43,0x38,0x43,0x30,0x33,0x55,0x2c,0x30,0x78,0x46,0x38,0x41,0x31,0x41,0x31,0x35,0x39,0x55,0x2c,0x30,0x78,0x38,0x30,0x38,0x39,0x38,0x39,0x30,0x39,
0x55,0x2c,0x30,0x78,0x31,0x37,0x30,0x44,0x30,0x44,0x31,0x41,0x55,0x2c,0x0a,0x30,0x78,0x44,0x41,0x42,0x46,0x42,0x46,0x36,0x35,0x55,0x2c,0x30,0x78,0x33,0x31,0x45,
0x36,0x45,0x36,0x44,0x37,0x55,0x2c,0x30,0x78,0x43,0x36,0x34,0x32,0x34,0x32,0x38,0x34,0x55,0x2c,0x30,0x78,0x42,0x38,0x36,0x38,0x36,0x38,0x44,0x30,0x55,0x2c,0x0a,
0x30,0x78,0x43,0x33,0x34,0x31,0x34,0x31,0x38,0x32,0x55,0x2c,0x30,0x78,0x42,0x30,0x39,0x39,0x39,0x39,0x32,0x39,0x55,0x2c,0x30,0x78,0x37,0x37,0x32,0x44,0x32,0x44,
0x35,0x41,0x55,0x2c,0x30,0x78,0x31,0x31,0x30,0x46,0x30,0x46,0x31,0x45,0x55,0x2c,0x0a,0x30,0x78,0x43,0x42,0x42,0x30,0x42,0x30,0x37,0x42,0x55,0x2c,0x30,0x78,0x46,
0x43,0x35,0x34,0x35,0x34,0x41,0x38,0x55,0x2c,0x30,0x78,0x44,0x36,0x42,0x42,0x42,0x42,0x36,0x44,0x55,0x2c,0x30,0x78,0x33,0x41,0x31,0x36,0x31,0x36,0x32,0x43,0x55,
0x0a,0x7d,0x3b,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x42,0x59,0x54,0x45,0x28,0x78,0x2c,0x20,0x79,0x29,0x20,0x28,0x61,0x6d,0x64,0x5f,0x62,0x66,0x65,0x28,
0x28,0x78,0x29,0x2c,0x20,0x28,0x79,0x29,0x20,0x3c,0x3c,0x20,0x33,0x55,0x2c,0x20,0x38,0x55,0x29,0x29,0x0a,0x23,0x69,0x66,0x20,0x28,0x41,0x4c,0x47,0x4f,0x20,0x3d,
0x3d,0x20,0x41,0x4c,0x47,0x4f,0x5f,0x43,0x4e,0x5f,0x48,0x45,0x41,0x56,0x59,0x5f,0x54,0x55,0x42,0x45,0x29,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x75,0x69,0x6e,
0x74,0x34,0x20,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x5f,0x62,0x69,0x74,0x74,0x75,0x62,0x65,0x32,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,
0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x30,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,
0x74,0x20,0x2a,0x41,0x45,0x53,0x31,0x2c,0x75,0x69,0x6e,0x74,0x34,0x20,0x78,0x2c,0x75,0x69,0x6e,0x74,0x34,0x20,0x6b,0x29,0x0a,0x7b,0x0a,0x78,0x3d,0x7e,0x78,0x3b,
0x0a,0x6b,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,
0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,
0x78,0x2e,0x73,0x32,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,
0x3b,0x0a,0x78,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x6b,0x2e,0x73,0x30,0x3b,0x0a,0x6b,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,
0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,
0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,
0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x78,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x6b,0x2e,0x73,0x31,0x3b,0x0a,0x6b,
0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x32,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,
0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x33,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,
0x73,0x30,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,
0x78,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x6b,0x2e,0x73,0x32,0x3b,0x0a,0x6b,0x2e,0x73,0x33,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,
0x78,0x2e,0x73,0x33,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x30,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,
0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x78,0x2e,0x73,0x31,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,
0x78,0x2e,0x73,0x32,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6b,0x3b,0x0a,0x7d,0x0a,0x23,0x65,0x6e,0x64,0x69,
0x66,0x0a,0x75,0x69,0x6e,0x74,0x34,0x20,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,
0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x30,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,
0x45,0x53,0x31,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x32,0x2c,0x63,0x6f,0x6e,
0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x33,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,
0x34,0x20,0x58,0x2c,0x75,0x69,0x6e,0x74,0x34,0x20,0x6b,0x65,0x79,0x29,0x0a,0x7b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,
0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x31,0x29,0x5d,
0x5e,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,
0x73,0x33,0x2c,0x33,0x29,0x5d,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,
0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x31,0x29,0x5d,0x5e,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,
0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x33,0x29,0x5d,0x3b,0x0a,0x6b,
0x65,0x79,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,
0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x31,0x29,0x5d,0x5e,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x32,0x29,
0x5d,0x5e,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x33,0x29,0x5d,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x33,0x20,0x5e,0x3d,0x20,
0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,
0x30,0x2c,0x31,0x29,0x5d,0x5e,0x41,0x45,0x53,0x32,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x33,0x5b,0x42,0x59,
0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x33,0x29,0x5d,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6b,0x65,0x79,0x3b,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x34,
0x20,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x5f,0x54,0x77,0x6f,0x5f,0x54,0x61,0x62,0x6c,0x65,0x73,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,
0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x41,0x45,0x53,0x30,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,
0x74,0x20,0x2a,0x41,0x45,0x53,0x31,0x2c,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x58,0x2c,0x75,0x69,0x6e,0x74,0x34,0x20,0x6b,0x65,0x79,0x29,
0x0a,0x7b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x30,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x30,0x29,0x5d,0x5e,
0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,
0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x33,0x29,0x5d,0x2c,
0x31,0x36,0x55,0x29,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x31,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x30,
0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x32,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x41,0x45,0x53,
0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x33,
0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x32,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,
0x32,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x33,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,
0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,
0x31,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x6b,0x65,0x79,0x2e,0x73,0x33,0x20,0x5e,0x3d,0x20,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,
0x58,0x2e,0x73,0x33,0x2c,0x30,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x30,0x2c,0x31,0x29,0x5d,0x5e,0x72,0x6f,0x74,0x61,
0x74,0x65,0x28,0x41,0x45,0x53,0x30,0x5b,0x42,0x59,0x54,0x45,0x28,0x58,0x2e,0x73,0x31,0x2c,0x32,0x29,0x5d,0x5e,0x41,0x45,0x53,0x31,0x5b,0x42,0x59,0x54,0x45,0x28,
0x58,0x2e,0x73,0x32,0x2c,0x33,0x29,0x5d,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6b,0x65,0x79,0x3b,0x0a,0x7d,0x0a,0x53,0x54,0x41,
0x54,0x49,0x43,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x63,0x68,0x61,0x72,0x20,0x72,0x63,0x6f,0x6e,0x5b,
0x38,0x5d,0x3d,0x7b,0x20,0x30,0x78,0x38,0x64,0x2c,0x30,0x78,0x30,0x31,0x2c,0x30,0x78,0x30,0x32,0x2c,0x30,0x78,0x30,0x34,0x2c,0x30,0x78,0x30,0x38,0x2c,0x30,0x78,
0x31,0x30,0x2c,0x30,0x78,0x32,0x30,0x2c,0x30,0x78,0x34,0x30,0x20,0x7d,0x3b,0x0a,0x53,0x54,0x41,0x54,0x49,0x43,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,
0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x63,0x68,0x61,0x72,0x20,0x73,0x62,0x6f,0x78,0x5b,0x32,0x35,0x36,0x5d,0x20,0x3d,0x0a,0x7b,0x0a,0x30,0x78,0x36,0x33,
0x2c,0x30,0x78,0x37,0x43,0x2c,0x30,0x78,0x37,0x37,0x2c,0x30,0x78,0x37,0x42,0x2c,0x30,0x78,0x46,0x32,0x2c,0x30,0x78,0x36,0x42,0x2c,0x30,0x78,0x36,0x46,0x2c,0x30,
0x78,0x43,0x35,0x2c,0x30,0x78,0x33,0x30,0x2c,0x30,0x78,0x30,0x31,0x2c,0x30,0x78,0x36,0x37,0x2c,0x30,0x78,0x32,0x42,0x2c,0x30,0x78,0x46,0x45,0x2c,0x30,0x78,0x44,
0x37,0x2c,0x30,0x78,0x41,0x42,0x2c,0x30,0x78,0x37,0x36,0x2c,0x0a,0x30,0x78,0x43,0x41,0x2c,0x30,0x78,0x38,0x32,0x2c,0x30,0x78,0x43,0x39,0x2c,0x30,0x78,0x37,0x44,
0x2c,0x30,0x78,0x46,0x41,0x2c,0x30,0x78,0x35,0x39,0x2c,0x30,0x78,0x34,0x37,0x2c,0x30,0x78,0x46,0x30,0x2c,0x30,0x78,0x41,0x44,0x2c,0x30,0x78,0x44,0x34,0x2c,0x30,
0x78,0x41,0x32,0x2c,0x30,0x78,0x41,0x46,0x2c,0x30,0x78,0x39,0x43,0x2c,0x30,0x78,0x41,0x34,0x2c,0x30,0x78,0x37,0x32,0x2c,0x30,0x78,0x43,0x30,0x2c,0x0a,0x30,0x78,
0x42,0x37,0x2c,0x30,0x78,0x46,0x44,0x2c,0x30,0x78,0x39,0x33,0x2c,0x30,0x78,0x32,0x36,0x2c,0x30,0x78,0x33,0x36,0x2c,0x30,0x78,0x33,0x46,0x2c,0x30,0x78,0x46,0x37,
0x2c,0x30,0x78,0x43,0x43,0x2c,0x30,0x78,0x33,0x34,0x2c,0x30,0x78,0x41,0x35,0x2c,0x30,0x78,0x45,0x35,0x2c,0x30,0x78,0x46,0x31,0x2c,0x30,0x78,0x37,0x31,0x2c,0x30,
0x78,0x44,0x38,0x2c,0x30,0x78,0x33,0x31,0x2c,0x30,0x78,0x31,0x35,0x2c,0x0a,0x30,0x78,0x30,0x34,0x2c,0x30,0x78,0x43,0x37,0x2c,0x30,0x78,0x32,0x33,0x2c,0x30,0x78,
0x43,0x33,0x2c,0x30,0x78,0x31,0x38,0x2c,0x30,0x78,0x39,0x36,0x2c,0x30,0x78,0x30,0x35,0x2c,0x30,0x78,0x39,0x41,0x2c,0x30,0x78,0x30,0x37,0x2c,0x30,0x78,0x31,0x32,
0x2c,0x30,0x78,0x38,0x30,0x2c,0x30,0x78,0x45,0x32,0x2c,0x30,0x78,0x45,0x42,0x2c,0x30,0x78,0x32,0x37,0x2c,0x30,0x78,0x42,0x32,0x2c,0x30,0x78,0x37,0x35,0x2c,0x0a,
0x30,0x78,0x30,0x39,0x2c,0x30,0x78,0x38,0x33,0x2c,0x30,0x78,0x32,0x43,0x2c,0x30,0x78,0x31,0x41,0x2c,0x30,0x78,0x31,0x42,0x2c,0x30,0x78,0x36,0x45,0x2c,0x30,0x78,
0x35,0x41,0x2c,0x30,0x78,0x41,0x30,0x2c,0x30,0x78,0x35,0x32,0x2c,0x30,0x78,0x33,0x42,0x2c,0x30,0x78,0x44,0x36,0x2c,0x30,0x78,0x42,0x33,0x2c,0x30,0x78,0x32,0x39,
0x2c,0x30,0x78,0x45,0x33,0x2c,0x30,0x78,0x32,0x46,0x2c,0x30,0x78,0x38,0x34,0x2c,0x0a,0x30,0x78,0x35,0x33,0x2c,0x30,0x78,0x44,0x31,0x2c,0x30,0x78,0x30,0x30,0x2c,
0x30,0x78,0x45,0x44,0x2c,0x30,0x78,0x32,0x30,0x2c,0x30,0x78,0x46,0x43,0x2c,0x30,0x78,0x42,0x31,0x2c,0x30,0x78,0x35,0x42,0x2c,0x30,0x78,0x36,0x41,0x2c,0x30,0x78,
0x43,0x42,0x2c,0x30,0x78,0x42,0x45,0x2c,0x30,0x78,0x33,0x39,0x2c,0x30,0x78,0x34,0x41,0x2c,0x30,0x78,0x34,0x43,0x2c,0x30,0x78,0x35,0x38,0x2c,0x30,0x78,0x43,0x46,
0x2c,0x0a,0x30,0x78,0x44,0x30,0x2c,0x30,0x78,0x45,0x46,0x2c,0x30,0x78,0x41,0x41,0x2c,0x30,0x78,0x46,0x42,0x2c,0x30,0x78,0x34,0x33,0x2c,0x30,0x78,0x34,0x44,0x2c,
0x30,0x78,0x33,0x33,0x2c,0x30,0x78,0x38,0x35,0x2c,0x30,0x78,0x34,0x35,0x2c,0x30,0x78,0x46,0x39,0x2c,0x30,0x78,0x30,0x32,0x2c,0x30,0x78,0x37,0x46,0x2c,0x30,0x78,
0x35,0x30,0x2c,0x30,0x78,0x33,0x43,0x2c,0x30,0x78,0x39,0x46,0x2c,0x30,0x78,0x41,0x38,0x2c,0x0a,0x30,0x78,0x35,0x31,0x2c,0x30,0x78,0x41,0x33,0x2c,0x30,0x78,0x34,
0x30,0x2c,0x30,0x78,0x38,0x46,0x2c,0x30,0x78,0x39,0x32,0x2c,0x30,0x78,0x39,0x44,0x2c,0x30,0x78,0x33,0x38,0x2c,0x30,0x78,0x46,0x35,0x2c,0x30,0x78,0x42,0x43,0x2c,
0x30,0x78,0x42,0x36,0x2c,0x30,0x78,0x44,0x41,0x2c,0x30,0x78,0x32,0x31,0x2c,0x30,0x78,0x31,0x30,0x2c,0x30,0x78,0x46,0x46,0x2c,0x30,0x78,0x46,0x33,0x2c,0x30,0x78,
0x44,0x32,0x2c,0x0a,0x30,0x78,0x43,0x44,0x2c,0x30,0x78,0x30,0x43,0x2c,0x30,0x78,0x31,0x33,0x2c,0x30,0x78,0x45,0x43,0x2c,0x30,0x78,0x35,0x46,0x2c,0x30,0x78,0x39,
0x37,0x2c,0x30,0x78,0x34,0x34,0x2c,0x30,0x78,0x31,0x37,0x2c,0x30,0x78,0x43,0x34,0x2c,0x30,0x78,0x41,0x37,0x2c,0x30,0x78,0x37,0x45,0x2c,0x30,0x78,0x33,0x44,0x2c,
0x30,0x78,0x36,0x34,0x2c,0x30,0x78,0x35,0x44,0x2c,0x30,0x78,0x31,0x39,0x2c,0x30,0x78,0x37,0x33,0x2c,0x0a,0x30,0x78,0x36,0x30,0x2c,0x30,0x78,0x38,0x31,0x2c,0x30,
0x78,0x34,0x46,0x2c,0x30,0x78,0x44,0x43,0x2c,0x30,0x78,0x32,0x32,0x2c,0x30,0x78,0x32,0x41,0x2c,0x30,0x78,0x39,0x30,0x2c,0x30,0x78,0x38,0x38,0x2c,0x30,0x78,0x34,
0x36,0x2c,0x30,0x78,0x45,0x45,0x2c,0x30,0x78,0x42,0x38,0x2c,0x30,0x78,0x31,0x34,0x2c,0x30,0x78,0x44,0x45,0x2c,0x30,0x78,0x35,0x45,0x2c,0x30,0x78,0x30,0x42,0x2c,
0x30,0x78,0x44,0x42,0x2c,0x0a,0x30,0x78,0x45,0x30,0x2c,0x30,0x78,0x33,0x32,0x2c,0x30,0x78,0x33,0x41,0x2c,0x30,0x78,0x30,0x41,0x2c,0x30,0x78,0x34,0x39,0x2c,0x30,
0x78,0x30,0x36,0x2c,0x30,0x78,0x32,0x34,0x2c,0x30,0x78,0x35,0x43,0x2c,0x30,0x78,0x43,0x32,0x2c,0x30,0x78,0x44,0x33,0x2c,0x30,0x78,0x41,0x43,0x2c,0x30,0x78,0x36,
0x32,0x2c,0x30,0x78,0x39,0x31,0x2c,0x30,0x78,0x39,0x35,0x2c,0x30,0x78,0x45,0x34,0x2c,0x30,0x78,0x37,0x39,0x2c,0x0a,0x30,0x78,0x45,0x37,0x2c,0x30,0x78,0x43,0x38,
0x2c,0x30,0x78,0x33,0x37,0x2c,0x30,0x78,0x36,0x44,0x2c,0x30,0x78,0x38,0x44,0x2c,0x30,0x78,0x44,0x35,0x2c,0x30,0x78,0x34,0x45,0x2c,0x30,0x78,0x41,0x39,0x2c,0x30,
0x78,0x36,0x43,0x2c,0x30,0x78,0x35,0x36,0x2c,0x30,0x78,0x46,0x34,0x2c,0x30,0x78,0x45,0x41,0x2c,0x30,0x78,0x36,0x35,0x2c,0x30,0x78,0x37,0x41,0x2c,0x30,0x78,0x41,
0x45,0x2c,0x30,0x78,0x30,0x38,0x2c,0x0a,0x30,0x78,0x42,0x41,0x2c,0x30,0x78,0x37,0x38,0x2c,0x30,0x78,0x32,0x35,0x2c,0x30,0x78,0x32,0x45,0x2c,0x30,0x78,0x31,0x43,
0x2c,0x30,0x78,0x41,0x36,0x2c,0x30,0x78,0x42,0x34,0x2c,0x30,0x78,0x43,0x36,0x2c,0x30,0x78,0x45,0x38,0x2c,0x30,0x78,0x44,0x44,0x2c,0x30,0x78,0x37,0x34,0x2c,0x30,
0x78,0x31,0x46,0x2c,0x30,0x78,0x34,0x42,0x2c,0x30,0x78,0x42,0x44,0x2c,0x30,0x78,0x38,0x42,0x2c,0x30,0x78,0x38,0x41,0x2c,0x0a,0x30,0x78,0x37,0x30,0x2c,0x30,0x78,
0x33,0x45,0x2c,0x30,0x78,0x42,0x35,0x2c,0x30,0x78,0x36,0x36,0x2c,0x30,0x78,0x34,0x38,0x2c,0x30,0x78,0x30,0x33,0x2c,0x30,0x78,0x46,0x36,0x2c,0x30,0x78,0x30,0x45,
0x2c,0x30,0x78,0x36,0x31,0x2c,0x30,0x78,0x33,0x35,0x2c,0x30,0x78,0x35,0x37,0x2c,0x30,0x78,0x42,0x39,0x2c,0x30,0x78,0x38,0x36,0x2c,0x30,0x78,0x43,0x31,0x2c,0x30,
0x78,0x31,0x44,0x2c,0x30,0x78,0x39,0x45,0x2c,0x0a,0x30,0x78,0x45,0x31,0x2c,0x30,0x78,0x46,0x38,0x2c,0x30,0x78,0x39,0x38,0x2c,0x30,0x78,0x31,0x31,0x2c,0x30,0x78,
0x36,0x39,0x2c,0x30,0x78,0x44,0x39,0x2c,0x30,0x78,0x38,0x45,0x2c,0x30,0x78,0x39,0x34,0x2c,0x30,0x78,0x39,0x42,0x2c,0x30,0x78,0x31,0x45,0x2c,0x30,0x78,0x38,0x37,
0x2c,0x30,0x78,0x45,0x39,0x2c,0x30,0x78,0x43,0x45,0x2c,0x30,0x78,0x35,0x35,0x2c,0x30,0x78,0x32,0x38,0x2c,0x30,0x78,0x44,0x46,0x2c,0x0a,0x30,0x78,0x38,0x43,0x2c,
0x30,0x78,0x41,0x31,0x2c,0x30,0x78,0x38,0x39,0x2c,0x30,0x78,0x30,0x44,0x2c,0x30,0x78,0x42,0x46,0x2c,0x30,0x78,0x45,0x36,0x2c,0x30,0x78,0x34,0x32,0x2c,0x30,0x78,
0x36,0x38,0x2c,0x30,0x78,0x34,0x31,0x2c,0x30,0x78,0x39,0x39,0x2c,0x30,0x78,0x32,0x44,0x2c,0x30,0x78,0x30,0x46,0x2c,0x30,0x78,0x42,0x30,0x2c,0x30,0x78,0x35,0x34,
0x2c,0x30,0x78,0x42,0x42,0x2c,0x30,0x78,0x31,0x36,0x0a,0x7d,0x3b,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x53,0x75,0x62,0x57,0x6f,0x72,0x64,0x28,0x69,0x6e,
0x77,0x29,0x20,0x28,0x28,0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x33,0x29,0x5d,0x20,0x3c,0x3c,0x20,0x32,0x34,0x29,0x20,0x7c,
0x20,0x28,0x73,0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x32,0x29,0x5d,0x20,0x3c,0x3c,0x20,0x31,0x36,0x29,0x20,0x7c,0x20,0x28,0x73,
0x62,0x6f,0x78,0x5b,0x42,0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x31,0x29,0x5d,0x20,0x3c,0x3c,0x20,0x38,0x29,0x20,0x7c,0x20,0x73,0x62,0x6f,0x78,0x5b,0x42,
0x59,0x54,0x45,0x28,0x69,0x6e,0x77,0x2c,0x20,0x30,0x29,0x5d,0x29,0x0a,0x76,0x6f,0x69,0x64,0x20,0x41,0x45,0x53,0x45,0x78,0x70,0x61,0x6e,0x64,0x4b,0x65,0x79,0x32,
0x35,0x36,0x28,0x75,0x69,0x6e,0x74,0x20,0x2a,0x6b,0x65,0x79,0x62,0x75,0x66,0x29,0x0a,0x7b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x20,0x63,0x3d,0x38,
0x2c,0x69,0x3d,0x31,0x3b,0x20,0x63,0x3c,0x34,0x30,0x3b,0x20,0x2b,0x2b,0x63,0x29,0x20,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x74,0x3d,0x28,0x28,0x21,0x28,0x63,0x26,
0x37,0x29,0x29,0x7c,0x7c,0x28,0x28,0x63,0x26,0x37,0x29,0x3d,0x3d,0x34,0x29,0x29,0x3f,0x53,0x75,0x62,0x57,0x6f,0x72,0x64,0x28,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,
0x63,0x2d,0x31,0x5d,0x29,0x3a,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,0x63,0x2d,0x31,0x5d,0x3b,0x0a,0x6b,0x65,0x79,0x62,0x75,0x66,0x5b,0x63,0x5d,0x3d,0x6b,0x65,0x79,
0x62,0x75,0x66,0x5b,0x63,0x2d,0x38,0x5d,0x5e,0x28,0x28,0x21,0x28,0x63,0x26,0x37,0x29,0x29,0x3f,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x2c,0x32,0x34,0x55,0x29,
0x5e,0x61,0x73,0x5f,0x75,0x69,0x6e,0x74,0x28,0x28,0x75,0x63,0x68,0x61,0x72,0x34,0x29,0x28,0x72,0x63,0x6f,0x6e,0x5b,0x69,0x2b,0x2b,0x5d,0x2c,0x30,0x55,0x2c,0x30,
0x55,0x2c,0x30,0x55,0x29,0x29,0x3a,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x23,0x69,0x66,0x6e,0x64,0x65,0x66,0x20,0x58,0x4d,
0x52,0x49,0x47,0x5f,0x4b,0x45,0x43,0x43,0x41,0x4b,0x5f,0x43,0x4c,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x58,0x4d,0x52,0x49,0x47,0x5f,0x4b,0x45,0x43,0x43,
0x41,0x4b,0x5f,0x43,0x4c,0x0a,0x53,0x54,0x41,0x54,0x49,0x43,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x6c,
0x6f,0x6e,0x67,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x5f,0x72,0x6e,0x64,0x63,0x5b,0x32,0x34,0x5d,0x20,0x3d,0x0a,0x7b,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x32,0x2c,0x30,
0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x61,0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,
0x30,0x38,0x30,0x30,0x30,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x62,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,0x31,0x2c,
0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x39,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x38,0x61,0x2c,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x38,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x30,0x39,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x61,0x2c,
0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,0x62,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x30,0x38,0x62,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,0x39,0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x33,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x32,
0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x2c,0x0a,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x38,0x30,0x30,0x61,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x61,0x2c,0x30,0x78,0x38,0x30,0x30,
0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x38,0x31,0x2c,0x0a,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x38,
0x30,0x2c,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x2c,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,
0x30,0x30,0x30,0x38,0x30,0x30,0x38,0x0a,0x7d,0x3b,0x0a,0x53,0x54,0x41,0x54,0x49,0x43,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,
0x6e,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x5f,0x72,0x6f,0x74,0x63,0x5b,0x32,0x34,0x5d,0x20,0x3d,0x0a,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,0x0a,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,
0x0a,0x7d,0x3b,0x0a,0x53,0x54,0x41,0x54,0x49,0x43,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x69,0x6e,0x74,
0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x5f,0x70,0x69,0x6c,0x6e,0x5b,0x32,0x34,0x5d,0x20,0x3d,0x0a,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,0x0a,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,0x0a,0x7d,0x3b,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6b,0x65,
0x63,0x63,0x61,0x6b,0x66,0x31,0x36,0x30,0x30,0x5f,0x31,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x69,0x6e,0x74,0x20,0x69,0x2c,0x72,
0x6f,0x75,0x6e,0x64,0x3b,0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x74,0x2c,0x62,0x63,0x5b,0x35,0x5d,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,
0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x72,0x6f,0x75,0x6e,0x64,0x3d,0x30,0x3b,0x20,0x72,0x6f,0x75,0x6e,0x64,0x3c,0x32,0x34,0x3b,0x20,0x2b,0x2b,
0x72,0x6f,0x75,0x6e,0x64,0x29,0x20,0x7b,0x0a,0x62,0x63,0x5b,0x30,0x5d,0x3d,0x73,0x74,0x5b,0x30,0x5d,0x5e,0x73,0x74,0x5b,0x35,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x30,
0x5d,0x5e,0x73,0x74,0x5b,0x31,0x35,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x30,0x5d,0x3b,0x0a,0x62,0x63,0x5b,0x31,0x5d,0x3d,0x73,0x74,0x5b,0x31,0x5d,0x5e,0x73,0x74,0x5b,
0x36,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x31,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x36,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x31,0x5d,0x3b,0x0a,0x62,0x63,0x5b,0x32,0x5d,0x3d,0x73,
0x74,0x5b,0x32,0x5d,0x5e,0x73,0x74,0x5b,0x37,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x32,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x37,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x32,0x5d,0x3b,
0x0a,0x62,0x63,0x5b,0x33,0x5d,0x3d,0x73,0x74,0x5b,0x33,0x5d,0x5e,0x73,0x74,0x5b,0x38,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x33,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x38,0x5d,
0x5e,0x73,0x74,0x5b,0x32,0x33,0x5d,0x3b,0x0a,0x62,0x63,0x5b,0x34,0x5d,0x3d,0x73,0x74,0x5b,0x34,0x5d,0x5e,0x73,0x74,0x5b,0x39,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x34,
0x5d,0x5e,0x73,0x74,0x5b,0x31,0x39,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x34,0x5d,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,
0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x35,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x7b,0x0a,0x74,0x3d,0x62,0x63,0x5b,0x28,0x69,0x2b,
0x34,0x29,0x20,0x25,0x20,0x35,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x62,0x63,0x5b,0x28,0x69,0x2b,0x31,0x29,0x20,0x25,0x20,0x35,0x5d,0x2c,0x31,0x55,0x4c,
0x29,0x3b,0x0a,0x73,0x74,0x5b,0x69,0x20,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x3b,0x0a,0x73,0x74,0x5b,0x69,0x2b,0x35,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x3b,0x0a,0x73,0x74,
0x5b,0x69,0x2b,0x31,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x3b,0x0a,0x73,0x74,0x5b,0x69,0x2b,0x31,0x35,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x3b,0x0a,0x73,0x74,0x5b,0x69,
0x2b,0x32,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x74,0x3b,0x0a,0x7d,0x0a,0x74,0x3d,0x73,0x74,0x5b,0x31,0x5d,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,
0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x32,0x34,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x7b,0x0a,0x62,0x63,
0x5b,0x30,0x5d,0x3d,0x73,0x74,0x5b,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x5f,0x70,0x69,0x6c,0x6e,0x5b,0x69,0x5d,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x6b,0x65,0x63,0x63,
0x61,0x6b,0x66,0x5f,0x70,0x69,0x6c,0x6e,0x5b,0x69,0x5d,0x5d,0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x2c,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x29,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,0x23,0x70,0x72,0x61,0x67,0x6d,
0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,
0x2b,0x3d,0x35,0x29,0x20,0x7b,0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x74,0x6d,0x70,0x5b,0x35,0x5d,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,
0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x78,0x3d,0x30,0x3b,0x20,0x78,0x3c,0x35,0x3b,0x20,0x2b,0x2b,0x78,0x29,0x20,0x7b,0x0a,
0x74,0x6d,0x70,0x5b,0x78,0x5d,0x3d,0x62,0x69,0x74,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x73,0x74,0x5b,0x69,0x2b,0x78,0x5d,0x5e,0x73,0x74,0x5b,0x69,0x2b,0x28,0x28,
0x78,0x2b,0x32,0x29,0x20,0x25,0x20,0x35,0x29,0x5d,0x2c,0x73,0x74,0x5b,0x69,0x2b,0x78,0x5d,0x2c,0x73,0x74,0x5b,0x69,0x2b,0x28,0x28,0x78,0x2b,0x31,0x29,0x20,0x25,
0x20,0x35,0x29,0x5d,0x29,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,0x69,
0x6e,0x74,0x20,0x78,0x3d,0x30,0x3b,0x20,0x78,0x3c,0x35,0x3b,0x20,0x2b,0x2b,0x78,0x29,0x20,0x7b,0x0a,0x73,0x74,0x5b,0x69,0x2b,0x78,0x5d,0x3d,0x74,0x6d,0x70,0x5b,
0x78,0x5d,0x3b,0x0a,0x7d,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,0x6f,
0x75,0x6e,0x64,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x31,0x36,0x30,0x30,0x5f,0x32,0x28,0x5f,0x5f,0x6c,
0x6f,0x63,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x69,0x6e,0x74,0x20,0x69,0x2c,0x72,0x6f,0x75,0x6e,0x64,0x3b,0x0a,0x75,
0x6c,0x6f,0x6e,0x67,0x20,0x74,0x2c,0x62,0x63,0x5b,0x35,0x5d,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,
0x6f,0x72,0x20,0x28,0x72,0x6f,0x75,0x6e,0x64,0x3d,0x30,0x3b,0x20,0x72,0x6f,0x75,0x6e,0x64,0x3c,0x32,0x34,0x3b,0x20,0x2b,0x2b,0x72,0x6f,0x75,0x6e,0x64,0x29,0x20,
0x7b,0x0a,0x62,0x63,0x5b,0x30,0x5d,0x3d,0x73,0x74,0x5b,0x30,0x5d,0x5e,0x73,0x74,0x5b,0x35,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x30,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x35,
0x5d,0x5e,0x73,0x74,0x5b,0x32,0x30,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x73,0x74,0x5b,0x32,0x5d,0x5e,0x73,0x74,0x5b,0x37,0x5d,0x5e,0x73,0x74,0x5b,0x31,
0x32,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x37,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x32,0x5d,0x2c,0x31,0x55,0x4c,0x29,0x3b,0x0a,0x62,0x63,0x5b,0x31,0x5d,0x3d,0x73,0x74,0x5b,
0x31,0x5d,0x5e,0x73,0x74,0x5b,0x36,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x31,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x36,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x31,0x5d,0x5e,0x72,0x6f,
0x74,0x61,0x74,0x65,0x28,0x73,0x74,0x5b,0x33,0x5d,0x5e,0x73,0x74,0x5b,0x38,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x33,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x38,0x5d,0x5e,0x73,
0x74,0x5b,0x32,0x33,0x5d,0x2c,0x31,0x55,0x4c,0x29,0x3b,0x0a,0x62,0x63,0x5b,0x32,0x5d,0x3d,0x73,0x74,0x5b,0x32,0x5d,0x5e,0x73,0x74,0x5b,0x37,0x5d,0x5e,0x73,0x74,
0x5b,0x31,0x32,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x37,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x32,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x73,0x74,0x5b,0x34,0x5d,0x5e,
0x73,0x74,0x5b,0x39,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x34,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x39,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x34,0x5d,0x2c,0x31,0x55,0x4c,0x29,0x3b,
0x0a,0x62,0x63,0x5b,0x33,0x5d,0x3d,0x73,0x74,0x5b,0x33,0x5d,0x5e,0x73,0x74,0x5b,0x38,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x33,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x38,0x5d,
0x5e,0x73,0x74,0x5b,0x32,0x33,0x5d,0x5e,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x73,0x74,0x5b,0x30,0x5d,0x5e,0x73,0x74,0x5b,0x35,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x30,
0x5d,0x5e,0x73,0x74,0x5b,0x31,0x35,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x30,0x5d,0x2c,0x31,0x55,0x4c,0x29,0x3b,0x0a,0x62,0x63,0x5b,0x34,0x5d,0x3d,0x73,0x74,0x5b,0x34,
0x5d,0x5e,0x73,0x74,0x5b,0x39,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x34,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x39,0x5d,0x5e,0x73,0x74,0x5b,0x32,0x34,0x5d,0x5e,0x72,0x6f,0x74,
0x61,0x74,0x65,0x28,0x73,0x74,0x5b,0x31,0x5d,0x5e,0x73,0x74,0x5b,0x36,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x31,0x5d,0x5e,0x73,0x74,0x5b,0x31,0x36,0x5d,0x5e,0x73,0x74,
0x5b,0x32,0x31,0x5d,0x2c,0x31,0x55,0x4c,0x29,0x3b,0x0a,0x73,0x74,0x5b,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x34,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x35,0x5d,
0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x34,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x31,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x34,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x31,
0x35,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x34,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x32,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x34,0x5d,0x3b,0x0a,0x73,0x74,
0x5b,0x31,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x36,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x74,
0x5b,0x31,0x31,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x31,0x36,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x30,0x5d,0x3b,0x0a,
0x73,0x74,0x5b,0x32,0x31,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x32,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x31,0x5d,0x3b,
0x0a,0x73,0x74,0x5b,0x37,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x31,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x31,0x32,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x31,0x5d,
0x3b,0x0a,0x73,0x74,0x5b,0x31,0x37,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x31,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x32,0x32,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,
0x31,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x33,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x32,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x38,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,
0x32,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x31,0x33,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x32,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x31,0x38,0x5d,0x20,0x5e,0x3d,0x20,0x62,
0x63,0x5b,0x32,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x32,0x33,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x32,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x34,0x5d,0x20,0x5e,0x3d,0x20,
0x62,0x63,0x5b,0x33,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x39,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x33,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x31,0x34,0x5d,0x20,0x5e,0x3d,
0x20,0x62,0x63,0x5b,0x33,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x31,0x39,0x5d,0x20,0x5e,0x3d,0x20,0x62,0x63,0x5b,0x33,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x32,0x34,0x5d,0x20,
0x5e,0x3d,0x20,0x62,0x63,0x5b,0x33,0x5d,0x3b,0x0a,0x74,0x3d,0x73,0x74,0x5b,0x31,0x5d,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,
0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x32,0x34,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x7b,0x0a,0x62,0x63,0x5b,0x30,0x5d,
0x3d,0x73,0x74,0x5b,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x5f,0x70,0x69,0x6c,0x6e,0x5b,0x69,0x5d,0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,
0x5f,0x70,0x69,0x6c,0x6e,0x5b,0x69,0x5d,0x5d,0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x2c,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x29,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,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,
0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,0x2b,0x3d,0x35,
0x29,0x20,0x7b,0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x74,0x6d,0x70,0x31,0x3d,0x73,0x74,0x5b,0x69,0x5d,0x2c,0x74,0x6d,0x70,0x32,0x3d,0x73,0x74,0x5b,0x69,0x2b,0x31,
0x5d,0x3b,0x0a,0x73,0x74,0x5b,0x69,0x5d,0x3d,0x62,0x69,0x74,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x73,0x74,0x5b,0x69,0x5d,0x5e,0x73,0x74,0x5b,0x69,0x2b,0x32,0x5d,
0x2c,0x73,0x74,0x5b,0x69,0x5d,0x2c,0x73,0x74,0x5b,0x69,0x2b,0x31,0x5d,0x29,0x3b,0x0a,0x73,0x74,0x5b,0x69,0x2b,0x31,0x5d,0x3d,0x62,0x69,0x74,0x73,0x65,0x6c,0x65,
0x63,0x74,0x28,0x73,0x74,0x5b,0x69,0x2b,0x31,0x5d,0x5e,0x73,0x74,0x5b,0x69,0x2b,0x33,0x5d,0x2c,0x73,0x74,0x5b,0x69,0x2b,0x31,0x5d,0x2c,0x73,0x74,0x5b,0x69,0x2b,
0x32,0x5d,0x29,0x3b,0x0a,0x73,0x74,0x5b,0x69,0x2b,0x32,0x5d,0x3d,0x62,0x69,0x74,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x73,0x74,0x5b,0x69,0x2b,0x32,0x5d,0x5e,0x73,
0x74,0x5b,0x69,0x2b,0x34,0x5d,0x2c,0x73,0x74,0x5b,0x69,0x2b,0x32,0x5d,0x2c,0x73,0x74,0x5b,0x69,0x2b,0x33,0x5d,0x29,0x3b,0x0a,0x73,0x74,0x5b,0x69,0x2b,0x33,0x5d,
0x3d,0x62,0x69,0x74,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x73,0x74,0x5b,0x69,0x2b,0x33,0x5d,0x5e,0x74,0x6d,0x70,0x31,0x2c,0x73,0x74,0x5b,0x69,0x2b,0x33,0x5d,0x2c,
0x73,0x74,0x5b,0x69,0x2b,0x34,0x5d,0x29,0x3b,0x0a,0x73,0x74,0x5b,0x69,0x2b,0x34,0x5d,0x3d,0x62,0x69,0x74,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x73,0x74,0x5b,0x69,
0x2b,0x34,0x5d,0x5e,0x74,0x6d,0x70,0x32,0x2c,0x73,0x74,0x5b,0x69,0x2b,0x34,0x5d,0x2c,0x74,0x6d,0x70,0x31,0x29,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,0x6f,0x75,0x6e,0x64,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x23,0x65,0x6e,0x64,
0x69,0x66,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x75,0x69,0x6e,0x74,0x20,0x67,0x65,0x74,0x49,0x64,0x78,0x28,0x29,0x0a,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,
0x20,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x2d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x6f,0x66,0x66,
0x73,0x65,0x74,0x28,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x49,0x44,0x58,0x28,0x78,0x29,0x20,0x28,0x78,0x29,0x0a,0x69,0x6e,0x6c,
0x69,0x6e,0x65,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x61,0x64,0x64,0x5f,0x70,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x61,0x2c,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x62,0x29,0x0a,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x61,0x2b,0x62,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x73,0x75,0x62,0x5f,0x70,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x61,0x2c,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x20,0x62,0x29,0x0a,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x61,0x2d,0x62,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x6d,0x75,0x6c,0x5f,0x70,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x61,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x62,0x29,
0x0a,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x61,0x2a,0x62,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,
0x6d,0x6d,0x5f,0x64,0x69,0x76,0x5f,0x70,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x61,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x62,0x29,0x0a,0x7b,0x0a,0x72,
0x65,0x74,0x75,0x72,0x6e,0x20,0x61,0x2f,0x62,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x61,
0x6e,0x64,0x5f,0x70,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x61,0x2c,0x69,0x6e,0x74,0x20,0x62,0x29,0x0a,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x61,
0x73,0x5f,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x61,0x73,0x5f,0x69,0x6e,0x74,0x34,0x28,0x61,0x29,0x26,0x28,0x69,0x6e,0x74,0x34,0x29,0x28,0x62,0x29,0x29,0x3b,0x0a,
0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x6f,0x72,0x5f,0x70,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x20,0x61,0x2c,0x69,0x6e,0x74,0x20,0x62,0x29,0x0a,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x61,0x73,0x5f,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x61,0x73,0x5f,
0x69,0x6e,0x74,0x34,0x28,0x61,0x29,0x7c,0x28,0x69,0x6e,0x74,0x34,0x29,0x28,0x62,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x66,0x6d,0x6f,0x64,0x5f,0x70,0x73,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x76,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x20,0x64,
0x63,0x29,0x0a,0x7b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x64,0x3d,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x29,0x28,0x64,0x63,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x20,0x63,0x3d,0x5f,0x6d,0x6d,0x5f,0x64,0x69,0x76,0x5f,0x70,0x73,0x28,0x76,0x2c,0x64,0x29,0x3b,0x0a,0x63,0x3d,0x74,0x72,0x75,0x6e,0x63,0x28,0x63,0x29,
0x3b,0x0a,0x63,0x3d,0x5f,0x6d,0x6d,0x5f,0x6d,0x75,0x6c,0x5f,0x70,0x73,0x28,0x63,0x2c,0x64,0x29,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x5f,0x6d,0x6d,0x5f,
0x73,0x75,0x62,0x5f,0x70,0x73,0x28,0x76,0x2c,0x63,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x69,0x6e,0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x78,
0x6f,0x72,0x5f,0x73,0x69,0x31,0x32,0x38,0x28,0x69,0x6e,0x74,0x34,0x20,0x61,0x2c,0x69,0x6e,0x74,0x34,0x20,0x62,0x29,0x0a,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,
0x20,0x61,0x5e,0x62,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x78,0x6f,0x72,0x5f,0x70,0x73,
0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x61,0x2c,0x69,0x6e,0x74,0x20,0x62,0x29,0x0a,0x7b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x61,0x73,0x5f,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x28,0x61,0x73,0x5f,0x69,0x6e,0x74,0x34,0x28,0x61,0x29,0x5e,0x28,0x69,0x6e,0x74,0x34,0x29,0x28,0x62,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,
0x69,0x6e,0x65,0x20,0x69,0x6e,0x74,0x34,0x20,0x5f,0x6d,0x6d,0x5f,0x61,0x6c,0x69,0x67,0x6e,0x72,0x5f,0x65,0x70,0x69,0x38,0x28,0x69,0x6e,0x74,0x34,0x20,0x61,0x2c,
0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x72,0x6f,0x74,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x72,0x69,0x67,
0x68,0x74,0x3d,0x38,0x2a,0x72,0x6f,0x74,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x6c,0x65,0x66,0x74,0x3d,0x28,0x33,0x32,0x2d,0x38,0x2a,
0x72,0x6f,0x74,0x29,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x69,0x6e,0x74,0x34,0x29,0x28,0x0a,0x28,0x28,0x75,0x69,0x6e,0x74,0x29,0x61,0x2e,0x78,0x3e,
0x3e,0x72,0x69,0x67,0x68,0x74,0x29,0x7c,0x28,0x20,0x61,0x2e,0x79,0x3c,0x3c,0x6c,0x65,0x66,0x74,0x20,0x29,0x2c,0x0a,0x28,0x28,0x75,0x69,0x6e,0x74,0x29,0x61,0x2e,
0x79,0x3e,0x3e,0x72,0x69,0x67,0x68,0x74,0x29,0x7c,0x28,0x20,0x61,0x2e,0x7a,0x3c,0x3c,0x6c,0x65,0x66,0x74,0x20,0x29,0x2c,0x0a,0x28,0x28,0x75,0x69,0x6e,0x74,0x29,
0x61,0x2e,0x7a,0x3e,0x3e,0x72,0x69,0x67,0x68,0x74,0x29,0x7c,0x28,0x20,0x61,0x2e,0x77,0x3c,0x3c,0x6c,0x65,0x66,0x74,0x20,0x29,0x2c,0x0a,0x28,0x28,0x75,0x69,0x6e,
0x74,0x29,0x61,0x2e,0x77,0x3e,0x3e,0x72,0x69,0x67,0x68,0x74,0x29,0x7c,0x28,0x20,0x61,0x2e,0x78,0x3c,0x3c,0x6c,0x65,0x66,0x74,0x20,0x29,0x0a,0x29,0x3b,0x0a,0x7d,
0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x34,0x2a,0x20,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,
0x70,0x74,0x72,0x28,0x75,0x69,0x6e,0x74,0x20,0x69,0x64,0x78,0x2c,0x75,0x69,0x6e,0x74,0x20,0x6e,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,
0x20,0x2a,0x6c,0x70,0x61,0x64,0x29,0x20,0x7b,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x34,0x2a,
0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x68,0x61,0x72,0x2a,0x29,0x6c,0x70,0x61,0x64,0x2b,0x28,0x69,0x64,0x78,0x26,0x4d,0x41,0x53,0x4b,
0x29,0x2b,0x6e,0x2a,0x31,0x36,0x29,0x3b,0x20,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x6d,0x61,0x5f,0x62,0x72,0x65,
0x61,0x6b,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x78,0x29,0x0a,0x7b,0x0a,0x78,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x6e,0x64,0x5f,0x70,0x73,0x28,0x78,0x2c,0x30,0x78,
0x46,0x45,0x46,0x46,0x46,0x46,0x46,0x46,0x29,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x5f,0x6d,0x6d,0x5f,0x6f,0x72,0x5f,0x70,0x73,0x28,0x78,0x2c,0x30,0x78,
0x30,0x30,0x38,0x30,0x30,0x30,0x30,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x76,0x6f,0x69,0x64,0x20,0x73,0x75,0x62,0x5f,0x72,0x6f,0x75,
0x6e,0x64,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x30,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x31,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x32,
0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x33,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x2a,0x20,
0x6e,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x2a,0x20,0x64,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x2a,0x20,0x63,0x29,0x0a,0x7b,0x0a,0x6e,0x31,0x3d,0x5f,0x6d,0x6d,0x5f,
0x61,0x64,0x64,0x5f,0x70,0x73,0x28,0x6e,0x31,0x2c,0x2a,0x63,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x6e,0x3d,0x5f,0x6d,0x6d,0x5f,0x6d,0x75,0x6c,
0x5f,0x70,0x73,0x28,0x6e,0x30,0x2c,0x2a,0x63,0x29,0x3b,0x0a,0x6e,0x6e,0x3d,0x5f,0x6d,0x6d,0x5f,0x6d,0x75,0x6c,0x5f,0x70,0x73,0x28,0x6e,0x31,0x2c,0x5f,0x6d,0x6d,
0x5f,0x6d,0x75,0x6c,0x5f,0x70,0x73,0x28,0x6e,0x6e,0x2c,0x6e,0x6e,0x29,0x29,0x3b,0x0a,0x6e,0x6e,0x3d,0x66,0x6d,0x61,0x5f,0x62,0x72,0x65,0x61,0x6b,0x28,0x6e,0x6e,
0x29,0x3b,0x0a,0x2a,0x6e,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x64,0x64,0x5f,0x70,0x73,0x28,0x2a,0x6e,0x2c,0x6e,0x6e,0x29,0x3b,0x0a,0x6e,0x33,0x3d,0x5f,0x6d,0x6d,0x5f,
0x73,0x75,0x62,0x5f,0x70,0x73,0x28,0x6e,0x33,0x2c,0x2a,0x63,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x64,0x64,0x3d,0x5f,0x6d,0x6d,0x5f,0x6d,0x75,0x6c,
0x5f,0x70,0x73,0x28,0x6e,0x32,0x2c,0x2a,0x63,0x29,0x3b,0x0a,0x64,0x64,0x3d,0x5f,0x6d,0x6d,0x5f,0x6d,0x75,0x6c,0x5f,0x70,0x73,0x28,0x6e,0x33,0x2c,0x5f,0x6d,0x6d,
0x5f,0x6d,0x75,0x6c,0x5f,0x70,0x73,0x28,0x64,0x64,0x2c,0x64,0x64,0x29,0x29,0x3b,0x0a,0x64,0x64,0x3d,0x66,0x6d,0x61,0x5f,0x62,0x72,0x65,0x61,0x6b,0x28,0x64,0x64,
0x29,0x3b,0x0a,0x2a,0x64,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x64,0x64,0x5f,0x70,0x73,0x28,0x2a,0x64,0x2c,0x64,0x64,0x29,0x3b,0x0a,0x2a,0x63,0x3d,0x5f,0x6d,0x6d,0x5f,
0x61,0x64,0x64,0x5f,0x70,0x73,0x28,0x2a,0x63,0x2c,0x72,0x6e,0x64,0x5f,0x63,0x29,0x3b,0x0a,0x2a,0x63,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x64,0x64,0x5f,0x70,0x73,0x28,
0x2a,0x63,0x2c,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x29,0x28,0x30,0x2e,0x37,0x33,0x34,0x33,0x37,0x35,0x66,0x29,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x72,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x64,0x64,0x5f,0x70,0x73,0x28,0x6e,0x6e,0x2c,0x64,0x64,0x29,0x3b,0x0a,0x72,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x6e,0x64,0x5f,0x70,
0x73,0x28,0x72,0x2c,0x30,0x78,0x38,0x30,0x37,0x46,0x46,0x46,0x46,0x46,0x29,0x3b,0x0a,0x72,0x3d,0x5f,0x6d,0x6d,0x5f,0x6f,0x72,0x5f,0x70,0x73,0x28,0x72,0x2c,0x30,
0x78,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x29,0x3b,0x0a,0x2a,0x63,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x64,0x64,0x5f,0x70,0x73,0x28,0x2a,0x63,0x2c,0x72,0x29,0x3b,
0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x76,0x6f,0x69,0x64,0x20,0x72,0x6f,0x75,0x6e,0x64,0x5f,0x63,0x6f,0x6d,0x70,0x75,0x74,0x65,0x28,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x6e,0x30,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x31,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x32,0x2c,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x20,0x6e,0x33,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x2a,0x20,0x63,0x2c,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x2a,0x20,0x72,0x29,0x0a,0x7b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x3d,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x29,0x28,0x30,0x2e,0x30,0x66,0x29,
0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x64,0x3d,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x29,0x28,0x30,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x73,0x75,0x62,0x5f,0x72,
0x6f,0x75,0x6e,0x64,0x28,0x6e,0x30,0x2c,0x6e,0x31,0x2c,0x6e,0x32,0x2c,0x6e,0x33,0x2c,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x26,0x6e,0x2c,0x26,0x64,0x2c,0x63,0x29,0x3b,
0x0a,0x73,0x75,0x62,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x6e,0x31,0x2c,0x6e,0x32,0x2c,0x6e,0x33,0x2c,0x6e,0x30,0x2c,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x26,0x6e,0x2c,
0x26,0x64,0x2c,0x63,0x29,0x3b,0x0a,0x73,0x75,0x62,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x6e,0x32,0x2c,0x6e,0x33,0x2c,0x6e,0x30,0x2c,0x6e,0x31,0x2c,0x72,0x6e,0x64,
0x5f,0x63,0x2c,0x26,0x6e,0x2c,0x26,0x64,0x2c,0x63,0x29,0x3b,0x0a,0x73,0x75,0x62,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x6e,0x33,0x2c,0x6e,0x30,0x2c,0x6e,0x31,0x2c,
0x6e,0x32,0x2c,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x26,0x6e,0x2c,0x26,0x64,0x2c,0x63,0x29,0x3b,0x0a,0x73,0x75,0x62,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x6e,0x33,0x2c,
0x6e,0x32,0x2c,0x6e,0x31,0x2c,0x6e,0x30,0x2c,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x26,0x6e,0x2c,0x26,0x64,0x2c,0x63,0x29,0x3b,0x0a,0x73,0x75,0x62,0x5f,0x72,0x6f,0x75,
0x6e,0x64,0x28,0x6e,0x32,0x2c,0x6e,0x31,0x2c,0x6e,0x30,0x2c,0x6e,0x33,0x2c,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x26,0x6e,0x2c,0x26,0x64,0x2c,0x63,0x29,0x3b,0x0a,0x73,
0x75,0x62,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x6e,0x31,0x2c,0x6e,0x30,0x2c,0x6e,0x33,0x2c,0x6e,0x32,0x2c,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x26,0x6e,0x2c,0x26,0x64,
0x2c,0x63,0x29,0x3b,0x0a,0x73,0x75,0x62,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x6e,0x30,0x2c,0x6e,0x33,0x2c,0x6e,0x32,0x2c,0x6e,0x31,0x2c,0x72,0x6e,0x64,0x5f,0x63,
0x2c,0x26,0x6e,0x2c,0x26,0x64,0x2c,0x63,0x29,0x3b,0x0a,0x64,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x6e,0x64,0x5f,0x70,0x73,0x28,0x64,0x2c,0x30,0x78,0x46,0x46,0x37,0x46,
0x46,0x46,0x46,0x46,0x29,0x3b,0x0a,0x64,0x3d,0x5f,0x6d,0x6d,0x5f,0x6f,0x72,0x5f,0x70,0x73,0x28,0x64,0x2c,0x30,0x78,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x29,
0x3b,0x0a,0x2a,0x72,0x20,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x64,0x64,0x5f,0x70,0x73,0x28,0x2a,0x72,0x2c,0x5f,0x6d,0x6d,0x5f,0x64,0x69,0x76,0x5f,0x70,0x73,0x28,0x6e,
0x2c,0x64,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x69,0x6e,0x74,0x34,0x20,0x73,0x69,0x6e,0x67,0x6c,0x65,0x5f,0x63,0x6f,0x6d,0x70,0x75,
0x74,0x65,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x30,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x31,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x32,
0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x33,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x20,0x63,0x6e,0x74,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x72,0x6e,0x64,0x5f,
0x63,0x2c,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x2a,0x20,0x73,0x75,0x6d,0x29,0x0a,0x7b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x63,0x3d,0x20,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x29,0x28,0x63,0x6e,0x74,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x72,0x3d,0x28,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x29,0x28,0x30,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x34,0x3b,0x20,0x2b,0x2b,
0x69,0x29,0x20,0x7b,0x0a,0x72,0x6f,0x75,0x6e,0x64,0x5f,0x63,0x6f,0x6d,0x70,0x75,0x74,0x65,0x28,0x6e,0x30,0x2c,0x6e,0x31,0x2c,0x6e,0x32,0x2c,0x6e,0x33,0x2c,0x72,
0x6e,0x64,0x5f,0x63,0x2c,0x26,0x63,0x2c,0x26,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x72,0x3d,0x5f,0x6d,0x6d,0x5f,0x61,0x6e,0x64,0x5f,0x70,0x73,0x28,0x72,0x2c,0x30,0x78,
0x38,0x30,0x37,0x46,0x46,0x46,0x46,0x46,0x29,0x3b,0x0a,0x72,0x3d,0x5f,0x6d,0x6d,0x5f,0x6f,0x72,0x5f,0x70,0x73,0x28,0x72,0x2c,0x30,0x78,0x34,0x30,0x30,0x30,0x30,
0x30,0x30,0x30,0x29,0x3b,0x0a,0x2a,0x73,0x75,0x6d,0x3d,0x72,0x3b,0x20,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x78,0x3d,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x29,
0x28,0x35,0x33,0x36,0x38,0x37,0x30,0x38,0x38,0x30,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x72,0x3d,0x5f,0x6d,0x6d,0x5f,0x6d,0x75,0x6c,0x5f,0x70,0x73,0x28,0x72,0x2c,0x78,
0x29,0x3b,0x20,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x63,0x6f,0x6e,0x76,0x65,0x72,0x74,0x5f,0x69,0x6e,0x74,0x34,0x5f,0x72,0x74,0x65,0x28,0x72,0x29,0x3b,0x0a,
0x7d,0x0a,0x69,0x6e,0x6c,0x69,0x6e,0x65,0x20,0x76,0x6f,0x69,0x64,0x20,0x73,0x69,0x6e,0x67,0x6c,0x65,0x5f,0x63,0x6f,0x6d,0x70,0x75,0x74,0x65,0x5f,0x77,0x72,0x61,
0x70,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x72,0x6f,0x74,0x2c,0x69,0x6e,0x74,0x34,0x20,0x76,0x30,0x2c,0x69,0x6e,0x74,0x34,0x20,0x76,0x31,
0x2c,0x69,0x6e,0x74,0x34,0x20,0x76,0x32,0x2c,0x69,0x6e,0x74,0x34,0x20,0x76,0x33,0x2c,0x66,0x6c,0x6f,0x61,0x74,0x20,0x63,0x6e,0x74,0x2c,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x20,0x72,0x6e,0x64,0x5f,0x63,0x2c,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x2a,0x20,0x73,0x75,0x6d,0x2c,0x5f,0x5f,0x6c,0x6f,
0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,0x34,0x2a,0x20,0x6f,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x30,0x3d,0x63,0x6f,0x6e,0x76,0x65,
0x72,0x74,0x5f,0x66,0x6c,0x6f,0x61,0x74,0x34,0x5f,0x72,0x74,0x65,0x28,0x76,0x30,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x31,0x3d,0x63,0x6f,0x6e,
0x76,0x65,0x72,0x74,0x5f,0x66,0x6c,0x6f,0x61,0x74,0x34,0x5f,0x72,0x74,0x65,0x28,0x76,0x31,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x32,0x3d,0x63,
0x6f,0x6e,0x76,0x65,0x72,0x74,0x5f,0x66,0x6c,0x6f,0x61,0x74,0x34,0x5f,0x72,0x74,0x65,0x28,0x76,0x32,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x33,
0x3d,0x63,0x6f,0x6e,0x76,0x65,0x72,0x74,0x5f,0x66,0x6c,0x6f,0x61,0x74,0x34,0x5f,0x72,0x74,0x65,0x28,0x76,0x33,0x29,0x3b,0x0a,0x69,0x6e,0x74,0x34,0x20,0x72,0x3d,
0x73,0x69,0x6e,0x67,0x6c,0x65,0x5f,0x63,0x6f,0x6d,0x70,0x75,0x74,0x65,0x28,0x6e,0x30,0x2c,0x6e,0x31,0x2c,0x6e,0x32,0x2c,0x6e,0x33,0x2c,0x63,0x6e,0x74,0x2c,0x72,
0x6e,0x64,0x5f,0x63,0x2c,0x73,0x75,0x6d,0x29,0x3b,0x0a,0x2a,0x6f,0x75,0x74,0x3d,0x72,0x6f,0x74,0x3d,0x3d,0x30,0x3f,0x72,0x3a,0x5f,0x6d,0x6d,0x5f,0x61,0x6c,0x69,
0x67,0x6e,0x72,0x5f,0x65,0x70,0x69,0x38,0x28,0x72,0x2c,0x72,0x6f,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,
0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x6c,0x6f,0x6f,0x6b,0x5b,0x31,0x36,0x5d,0x5b,0x34,0x5d,0x3d,0x7b,0x0a,0x7b,0x30,
0x2c,0x31,0x2c,0x32,0x2c,0x33,0x7d,0x2c,0x0a,0x7b,0x30,0x2c,0x32,0x2c,0x33,0x2c,0x31,0x7d,0x2c,0x0a,0x7b,0x30,0x2c,0x33,0x2c,0x31,0x2c,0x32,0x7d,0x2c,0x0a,0x7b,
0x30,0x2c,0x33,0x2c,0x32,0x2c,0x31,0x7d,0x2c,0x0a,0x7b,0x31,0x2c,0x30,0x2c,0x32,0x2c,0x33,0x7d,0x2c,0x0a,0x7b,0x31,0x2c,0x32,0x2c,0x33,0x2c,0x30,0x7d,0x2c,0x0a,
0x7b,0x31,0x2c,0x33,0x2c,0x30,0x2c,0x32,0x7d,0x2c,0x0a,0x7b,0x31,0x2c,0x33,0x2c,0x32,0x2c,0x30,0x7d,0x2c,0x0a,0x7b,0x32,0x2c,0x31,0x2c,0x30,0x2c,0x33,0x7d,0x2c,
0x0a,0x7b,0x32,0x2c,0x30,0x2c,0x33,0x2c,0x31,0x7d,0x2c,0x0a,0x7b,0x32,0x2c,0x33,0x2c,0x31,0x2c,0x30,0x7d,0x2c,0x0a,0x7b,0x32,0x2c,0x33,0x2c,0x30,0x2c,0x31,0x7d,
0x2c,0x0a,0x7b,0x33,0x2c,0x31,0x2c,0x32,0x2c,0x30,0x7d,0x2c,0x0a,0x7b,0x33,0x2c,0x32,0x2c,0x30,0x2c,0x31,0x7d,0x2c,0x0a,0x7b,0x33,0x2c,0x30,0x2c,0x31,0x2c,0x32,
0x7d,0x2c,0x0a,0x7b,0x33,0x2c,0x30,0x2c,0x32,0x2c,0x31,0x7d,0x0a,0x7d,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,
0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x63,0x63,0x6e,0x74,0x5b,0x31,0x36,0x5d,0x3d,0x7b,0x0a,0x31,0x2e,0x33,0x34,0x33,0x37,0x35,
0x66,0x2c,0x0a,0x31,0x2e,0x32,0x38,0x31,0x32,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x33,0x35,0x39,0x33,0x37,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x33,0x36,0x37,0x31,0x38,0x37,
0x35,0x66,0x2c,0x0a,0x31,0x2e,0x34,0x32,0x39,0x36,0x38,0x37,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x33,0x39,0x38,0x34,0x33,0x37,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x33,0x38,
0x32,0x38,0x31,0x32,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x33,0x30,0x34,0x36,0x38,0x37,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x34,0x31,0x34,0x30,0x36,0x32,0x35,0x66,0x2c,0x0a,
0x31,0x2e,0x32,0x37,0x33,0x34,0x33,0x37,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x32,0x35,0x37,0x38,0x31,0x32,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x32,0x38,0x39,0x30,0x36,0x32,
0x35,0x66,0x2c,0x0a,0x31,0x2e,0x33,0x32,0x30,0x33,0x31,0x32,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x33,0x35,0x31,0x35,0x36,0x32,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x33,0x33,
0x35,0x39,0x33,0x37,0x35,0x66,0x2c,0x0a,0x31,0x2e,0x34,0x36,0x30,0x39,0x33,0x37,0x35,0x66,0x0a,0x7d,0x3b,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x68,0x61,
0x72,0x65,0x64,0x4d,0x65,0x6d,0x43,0x68,0x75,0x6e,0x6b,0x0a,0x7b,0x0a,0x69,0x6e,0x74,0x34,0x20,0x6f,0x75,0x74,0x5b,0x31,0x36,0x5d,0x3b,0x0a,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x20,0x76,0x61,0x5b,0x31,0x36,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,0x28,0x72,0x65,0x71,
0x64,0x5f,0x77,0x6f,0x72,0x6b,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,0x69,0x7a,0x65,0x28,0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x2a,0x31,0x36,0x2c,0x31,0x2c,
0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x63,0x6e,0x31,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,
0x69,0x6e,0x74,0x20,0x2a,0x6c,0x70,0x61,0x64,0x5f,0x69,0x6e,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x20,0x2a,0x73,0x70,0x61,0x64,0x2c,
0x75,0x69,0x6e,0x74,0x20,0x6e,0x75,0x6d,0x54,0x68,0x72,0x65,0x61,0x64,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x67,0x49,
0x64,0x78,0x3d,0x67,0x65,0x74,0x49,0x64,0x78,0x28,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x63,0x68,0x75,0x6e,0x6b,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,
0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x2f,0x31,0x36,0x3b,0x0a,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x20,0x6c,0x70,0x61,0x64,0x3d,0x28,
0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x68,0x61,0x72,0x2a,0x29,0x6c,
0x70,0x61,0x64,0x5f,0x69,0x6e,0x2b,0x4d,0x45,0x4d,0x4f,0x52,0x59,0x2a,0x28,0x67,0x49,0x64,0x78,0x2f,0x31,0x36,0x29,0x29,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,
0x6c,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x68,0x61,0x72,0x65,0x64,0x4d,0x65,0x6d,0x43,0x68,0x75,0x6e,0x6b,0x20,0x73,0x6d,0x65,0x6d,0x5f,0x69,0x6e,0x5b,
0x57,0x4f,0x52,0x4b,0x53,0x49,0x5a,0x45,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x68,0x61,0x72,0x65,0x64,
0x4d,0x65,0x6d,0x43,0x68,0x75,0x6e,0x6b,0x2a,0x20,0x73,0x6d,0x65,0x6d,0x3d,0x73,0x6d,0x65,0x6d,0x5f,0x69,0x6e,0x2b,0x63,0x68,0x75,0x6e,0x6b,0x3b,0x0a,0x75,0x69,
0x6e,0x74,0x20,0x74,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x20,0x25,0x20,0x31,0x36,0x3b,0x0a,0x75,0x69,0x6e,
0x74,0x20,0x69,0x64,0x78,0x48,0x61,0x73,0x68,0x3d,0x67,0x49,0x64,0x78,0x2f,0x31,0x36,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x73,0x3d,0x28,0x28,0x5f,0x5f,0x67,0x6c,
0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x29,0x73,0x70,0x61,0x64,0x29,0x5b,0x69,0x64,0x78,0x48,0x61,0x73,0x68,0x2a,0x35,0x30,0x5d,0x3e,0x3e,0x38,0x3b,
0x0a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x76,0x73,0x3d,0x28,0x66,0x6c,0x6f,0x61,0x74,0x34,0x29,0x28,0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
0x6e,0x74,0x20,0x74,0x69,0x64,0x64,0x3d,0x74,0x69,0x64,0x2f,0x34,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x74,0x69,0x64,0x6d,0x3d,0x74,
0x69,0x64,0x20,0x25,0x20,0x34,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x62,0x6c,0x6f,0x63,0x6b,0x3d,0x74,0x69,0x64,0x64,0x2a,0x31,0x36,
0x2b,0x74,0x69,0x64,0x6d,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x43,0x4e,0x5f,0x55,0x4e,0x52,0x4f,0x4c,0x4c,0x0a,
0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x49,0x54,0x45,0x52,0x41,0x54,0x49,0x4f,0x4e,0x53,0x3b,0x20,0x69,0x2b,0x2b,
0x29,0x20,0x7b,0x0a,0x6d,0x65,0x6d,0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,
0x45,0x29,0x3b,0x0a,0x69,0x6e,0x74,0x20,0x74,0x6d,0x70,0x3d,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x73,0x63,0x72,0x61,
0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x70,0x74,0x72,0x28,0x73,0x2c,0x74,0x69,0x64,0x64,0x2c,0x6c,0x70,0x61,0x64,0x29,0x29,0x5b,0x74,0x69,0x64,0x6d,0x5d,0x3b,0x0a,
0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x28,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x29,0x29,0x5b,0x74,0x69,0x64,0x5d,
0x3d,0x74,0x6d,0x70,0x3b,0x0a,0x6d,0x65,0x6d,0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,
0x4e,0x43,0x45,0x29,0x3b,0x0a,0x7b,0x0a,0x73,0x69,0x6e,0x67,0x6c,0x65,0x5f,0x63,0x6f,0x6d,0x70,0x75,0x74,0x65,0x5f,0x77,0x72,0x61,0x70,0x28,0x0a,0x74,0x69,0x64,
0x6d,0x2c,0x0a,0x2a,0x28,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x2b,0x6c,0x6f,0x6f,0x6b,0x5b,0x74,0x69,0x64,0x5d,0x5b,0x30,0x5d,0x29,0x2c,0x0a,0x2a,0x28,
0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x2b,0x6c,0x6f,0x6f,0x6b,0x5b,0x74,0x69,0x64,0x5d,0x5b,0x31,0x5d,0x29,0x2c,0x0a,0x2a,0x28,0x73,0x6d,0x65,0x6d,0x2d,
0x3e,0x6f,0x75,0x74,0x2b,0x6c,0x6f,0x6f,0x6b,0x5b,0x74,0x69,0x64,0x5d,0x5b,0x32,0x5d,0x29,0x2c,0x0a,0x2a,0x28,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x2b,
0x6c,0x6f,0x6f,0x6b,0x5b,0x74,0x69,0x64,0x5d,0x5b,0x33,0x5d,0x29,0x2c,0x0a,0x63,0x63,0x6e,0x74,0x5b,0x74,0x69,0x64,0x5d,0x2c,0x76,0x73,0x2c,0x73,0x6d,0x65,0x6d,
0x2d,0x3e,0x76,0x61,0x2b,0x74,0x69,0x64,0x2c,0x0a,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x2b,0x74,0x69,0x64,0x0a,0x29,0x3b,0x0a,0x7d,0x0a,0x6d,0x65,0x6d,
0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x69,0x6e,0x74,
0x20,0x6f,0x75,0x74,0x58,0x6f,0x72,0x3d,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,
0x29,0x5b,0x62,0x6c,0x6f,0x63,0x6b,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x20,0x64,0x64,0x3d,0x62,0x6c,0x6f,0x63,0x6b,0x2b,0x34,0x3b,0x20,
0x64,0x64,0x3c,0x28,0x74,0x69,0x64,0x64,0x2b,0x31,0x29,0x2a,0x31,0x36,0x3b,0x20,0x64,0x64,0x2b,0x3d,0x34,0x29,0x20,0x7b,0x0a,0x6f,0x75,0x74,0x58,0x6f,0x72,0x20,
0x5e,0x3d,0x20,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x29,0x5b,0x64,0x64,0x5d,
0x3b,0x0a,0x7d,0x0a,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x73,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5f,0x70,
0x74,0x72,0x28,0x73,0x2c,0x74,0x69,0x64,0x64,0x2c,0x6c,0x70,0x61,0x64,0x29,0x29,0x5b,0x74,0x69,0x64,0x6d,0x5d,0x3d,0x6f,0x75,0x74,0x58,0x6f,0x72,0x5e,0x74,0x6d,
0x70,0x3b,0x0a,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x29,0x5b,0x74,0x69,0x64,
0x5d,0x3d,0x6f,0x75,0x74,0x58,0x6f,0x72,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x76,0x61,0x5f,0x74,0x6d,0x70,0x31,0x3d,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,
0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x62,0x6c,0x6f,0x63,0x6b,0x5d,0x2b,0x28,0x28,0x5f,0x5f,0x6c,0x6f,
0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x62,0x6c,0x6f,0x63,0x6b,0x2b,0x34,0x5d,0x3b,0x0a,0x66,
0x6c,0x6f,0x61,0x74,0x20,0x76,0x61,0x5f,0x74,0x6d,0x70,0x32,0x3d,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x2a,0x29,0x73,0x6d,
0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x62,0x6c,0x6f,0x63,0x6b,0x2b,0x20,0x38,0x5d,0x2b,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x62,0x6c,0x6f,0x63,0x6b,0x2b,0x31,0x32,0x5d,0x3b,0x0a,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,
0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x74,0x69,0x64,0x5d,0x3d,0x76,0x61,0x5f,0x74,0x6d,0x70,0x31,0x2b,
0x76,0x61,0x5f,0x74,0x6d,0x70,0x32,0x3b,0x0a,0x6d,0x65,0x6d,0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,
0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x69,0x6e,0x74,0x20,0x6f,0x75,0x74,0x32,0x3d,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,
0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x29,0x5b,0x74,0x69,0x64,0x5d,0x5e,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,
0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x29,0x5b,0x74,0x69,0x64,0x2b,0x34,0x20,0x5d,0x5e,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,
0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x29,0x5b,0x74,0x69,0x64,0x2b,0x38,0x5d,0x5e,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,
0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x29,0x5b,0x74,0x69,0x64,0x2b,0x31,0x32,0x5d,0x3b,0x0a,0x76,0x61,0x5f,0x74,0x6d,0x70,0x31,0x3d,0x28,
0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x62,0x6c,0x6f,0x63,0x6b,0x5d,
0x2b,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x62,0x6c,0x6f,0x63,
0x6b,0x2b,0x34,0x5d,0x3b,0x0a,0x76,0x61,0x5f,0x74,0x6d,0x70,0x32,0x3d,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x2a,0x29,0x73,
0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x62,0x6c,0x6f,0x63,0x6b,0x2b,0x38,0x5d,0x2b,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,0x5b,0x62,0x6c,0x6f,0x63,0x6b,0x2b,0x31,0x32,0x5d,0x3b,0x0a,0x76,0x61,0x5f,0x74,0x6d,0x70,0x31,0x3d,
0x76,0x61,0x5f,0x74,0x6d,0x70,0x31,0x2b,0x76,0x61,0x5f,0x74,0x6d,0x70,0x32,0x3b,0x0a,0x76,0x61,0x5f,0x74,0x6d,0x70,0x31,0x3d,0x66,0x61,0x62,0x73,0x28,0x76,0x61,
0x5f,0x74,0x6d,0x70,0x31,0x29,0x3b,0x0a,0x66,0x6c,0x6f,0x61,0x74,0x20,0x78,0x78,0x3d,0x76,0x61,0x5f,0x74,0x6d,0x70,0x31,0x2a,0x31,0x36,0x37,0x37,0x37,0x32,0x31,
0x36,0x2e,0x30,0x66,0x3b,0x0a,0x69,0x6e,0x74,0x20,0x78,0x78,0x5f,0x69,0x6e,0x74,0x3d,0x28,0x69,0x6e,0x74,0x29,0x78,0x78,0x3b,0x0a,0x28,0x28,0x5f,0x5f,0x6c,0x6f,
0x63,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x29,0x5b,0x74,0x69,0x64,0x5d,0x3d,0x6f,0x75,0x74,0x32,0x5e,0x78,0x78,
0x5f,0x69,0x6e,0x74,0x3b,0x0a,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x2a,0x29,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,0x29,
0x5b,0x74,0x69,0x64,0x5d,0x3d,0x76,0x61,0x5f,0x74,0x6d,0x70,0x31,0x2f,0x36,0x34,0x2e,0x30,0x66,0x3b,0x0a,0x6d,0x65,0x6d,0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,
0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x76,0x73,0x3d,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x76,0x61,
0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x3d,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x5b,0x30,0x5d,0x2e,0x78,0x5e,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x5b,
0x30,0x5d,0x2e,0x79,0x5e,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x5b,0x30,0x5d,0x2e,0x7a,0x5e,0x73,0x6d,0x65,0x6d,0x2d,0x3e,0x6f,0x75,0x74,0x5b,0x30,0x5d,
0x2e,0x77,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x5f,0x5f,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,
0x75,0x69,0x6e,0x74,0x20,0x73,0x6b,0x69,0x70,0x5b,0x33,0x5d,0x3d,0x7b,0x0a,0x32,0x30,0x2c,0x32,0x32,0x2c,0x32,0x32,0x0a,0x7d,0x3b,0x0a,0x69,0x6e,0x6c,0x69,0x6e,
0x65,0x20,0x76,0x6f,0x69,0x64,0x20,0x67,0x65,0x6e,0x65,0x72,0x61,0x74,0x65,0x5f,0x35,0x31,0x32,0x28,0x75,0x69,0x6e,0x74,0x20,0x69,0x64,0x78,0x2c,0x5f,0x5f,0x6c,
0x6f,0x63,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x2a,0x20,0x69,0x6e,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x2a,0x20,0x6f,
0x75,0x74,0x29,0x0a,0x7b,0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x68,0x61,0x73,0x68,0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x68,0x61,0x73,0x68,0x5b,0x30,0x5d,0x3d,0x69,0x6e,
0x5b,0x30,0x5d,0x5e,0x69,0x64,0x78,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x2b,0x2b,0x69,
0x29,0x20,0x7b,0x0a,0x68,0x61,0x73,0x68,0x5b,0x69,0x5d,0x3d,0x69,0x6e,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x61,0x3d,
0x30,0x3b,0x20,0x61,0x3c,0x33,0x3b,0x20,0x2b,0x2b,0x61,0x29,0x20,0x7b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x31,0x36,0x30,0x30,0x5f,0x31,0x28,0x68,0x61,0x73,
0x68,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x73,0x6b,0x69,0x70,0x5b,0x61,0x5d,0x3b,0x20,0x2b,0x2b,0x69,
0x29,0x20,0x7b,0x0a,0x6f,0x75,0x74,0x5b,0x69,0x5d,0x3d,0x68,0x61,0x73,0x68,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x6f,0x75,0x74,0x2b,0x3d,0x73,0x6b,0x69,0x70,0x5b,
0x61,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,0x28,0x72,0x65,0x71,0x64,0x5f,0x77,0x6f,0x72,0x6b,
0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,0x69,0x7a,0x65,0x28,0x38,0x2c,0x38,0x2c,0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,
0x69,0x64,0x20,0x63,0x6e,0x30,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x69,0x6e,0x70,0x75,0x74,0x2c,0x69,0x6e,0x74,
0x20,0x69,0x6e,0x6c,0x65,0x6e,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x20,0x2a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2c,
0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x73,0x74,0x61,0x74,0x65,0x73,0x2c,0x75,0x69,0x6e,0x74,0x20,0x54,0x68,0x72,0x65,
0x61,0x64,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x67,0x49,0x64,0x78,0x3d,0x67,0x65,0x74,0x49,0x64,0x78,0x28,0x29,0x3b,
0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x53,0x74,0x61,0x74,0x65,0x5f,0x62,0x75,0x66,0x5b,0x38,0x2a,0x32,0x35,0x5d,0x3b,0x0a,
0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x2a,0x20,0x53,0x74,0x61,0x74,0x65,0x3d,0x53,0x74,0x61,0x74,0x65,0x5f,0x62,0x75,0x66,0x2b,0x67,
0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x2a,0x32,0x35,0x3b,0x0a,0x7b,0x0a,0x73,0x74,0x61,0x74,0x65,0x73,0x2b,0x3d,0x32,0x35,0x2a,
0x67,0x49,0x64,0x78,0x3b,0x0a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x3d,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,
0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x68,0x61,0x72,0x2a,0x29,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2b,0x4d,0x45,0x4d,0x4f,
0x52,0x59,0x2a,0x67,0x49,0x64,0x78,0x29,0x3b,0x0a,0x69,0x66,0x28,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x3d,0x3d,0x30,0x29,
0x20,0x7b,0x0a,0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x5f,0x5f,0x4e,0x56,0x5f,0x43,0x4c,0x5f,0x43,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x0a,0x66,0x6f,0x72,0x28,
0x75,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x0a,0x53,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x69,0x6e,0x70,
0x75,0x74,0x5b,0x69,0x5d,0x3b,0x0a,0x23,0x65,0x6c,0x73,0x65,0x0a,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x38,0x20,0x2a,0x29,
0x53,0x74,0x61,0x74,0x65,0x29,0x5b,0x30,0x5d,0x3d,0x76,0x6c,0x6f,0x61,0x64,0x38,0x28,0x30,0x2c,0x69,0x6e,0x70,0x75,0x74,0x29,0x3b,0x0a,0x23,0x65,0x6e,0x64,0x69,
0x66,0x0a,0x53,0x74,0x61,0x74,0x65,0x5b,0x38,0x5d,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5b,0x38,0x5d,0x3b,0x0a,0x53,0x74,0x61,0x74,0x65,0x5b,0x39,0x5d,0x3d,0x69,0x6e,
0x70,0x75,0x74,0x5b,0x39,0x5d,0x3b,0x0a,0x53,0x74,0x61,0x74,0x65,0x5b,0x31,0x30,0x5d,0x3d,0x69,0x6e,0x70,0x75,0x74,0x5b,0x31,0x30,0x5d,0x3b,0x0a,0x28,0x28,0x5f,
0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x29,0x53,0x74,0x61,0x74,0x65,0x29,0x5b,0x39,0x5d,0x20,0x26,0x3d,0x20,0x30,0x78,0x30,0x30,0x46,
0x46,0x46,0x46,0x46,0x46,0x55,0x3b,0x0a,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x29,0x53,0x74,0x61,0x74,0x65,0x29,0x5b,
0x39,0x5d,0x7c,0x3d,0x28,0x28,0x28,0x75,0x69,0x6e,0x74,0x29,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x29,0x26,0x30,0x78,
0x46,0x46,0x29,0x3c,0x3c,0x32,0x34,0x3b,0x0a,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x29,0x53,0x74,0x61,0x74,0x65,0x29,
0x5b,0x31,0x30,0x5d,0x20,0x26,0x3d,0x20,0x30,0x78,0x46,0x46,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x3b,0x0a,0x28,0x28,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,
0x69,0x6e,0x74,0x20,0x2a,0x29,0x53,0x74,0x61,0x74,0x65,0x29,0x5b,0x31,0x30,0x5d,0x7c,0x3d,0x28,0x28,0x28,0x75,0x69,0x6e,0x74,0x29,0x67,0x65,0x74,0x5f,0x67,0x6c,
0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3e,0x3e,0x38,0x29,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x31,0x3b,0x20,
0x69,0x3c,0x32,0x35,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x7b,0x0a,0x53,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x30,0x78,0x30,0x30,0x55,0x4c,0x3b,0x0a,0x7d,0x0a,
0x53,0x74,0x61,0x74,0x65,0x5b,0x31,0x36,0x5d,0x3d,0x30,0x78,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x55,0x4c,0x3b,0x0a,
0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x31,0x36,0x30,0x30,0x5f,0x32,0x28,0x53,0x74,0x61,0x74,0x65,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,0x32,0x35,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x7b,0x0a,
0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x69,0x5d,0x3d,0x53,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x7d,0x0a,0x7d,0x0a,0x5f,0x5f,0x61,0x74,
0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,0x28,0x72,0x65,0x71,0x64,0x5f,0x77,0x6f,0x72,0x6b,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,0x69,0x7a,0x65,0x28,
0x36,0x34,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x63,0x6e,0x30,0x30,0x28,0x5f,0x5f,0x67,
0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x20,0x2a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,
0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x73,0x74,0x61,0x74,0x65,0x73,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x67,0x49,0x64,0x78,0x3d,
0x67,0x65,0x74,0x49,0x64,0x78,0x28,0x29,0x2f,0x36,0x34,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x53,0x74,0x61,0x74,0x65,
0x5b,0x32,0x35,0x5d,0x3b,0x0a,0x73,0x74,0x61,0x74,0x65,0x73,0x2b,0x3d,0x32,0x35,0x2a,0x67,0x49,0x64,0x78,0x3b,0x0a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,
0x64,0x3d,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x69,0x6e,0x74,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x63,0x68,0x61,0x72,
0x2a,0x29,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2b,0x4d,0x45,0x4d,0x4f,0x52,0x59,0x2a,0x67,0x49,0x64,0x78,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,
0x69,0x6e,0x74,0x20,0x69,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,0x2b,0x3d,
0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x73,0x69,0x7a,0x65,0x28,0x30,0x29,0x29,0x20,0x7b,0x0a,0x53,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x73,0x74,
0x61,0x74,0x65,0x73,0x5b,0x69,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,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x20,0x69,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,
0x64,0x28,0x30,0x29,0x3b,0x20,0x69,0x3c,0x4d,0x45,0x4d,0x4f,0x52,0x59,0x2f,0x35,0x31,0x32,0x3b,0x20,0x69,0x2b,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,
0x5f,0x73,0x69,0x7a,0x65,0x28,0x30,0x29,0x29,0x20,0x7b,0x0a,0x67,0x65,0x6e,0x65,0x72,0x61,0x74,0x65,0x5f,0x35,0x31,0x32,0x28,0x69,0x2c,0x53,0x74,0x61,0x74,0x65,
0x2c,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x2a,0x29,0x28,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x63,0x68,
0x61,0x72,0x2a,0x29,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2b,0x69,0x2a,0x35,0x31,0x32,0x29,0x29,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x5f,0x5f,0x61,0x74,
0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,0x28,0x72,0x65,0x71,0x64,0x5f,0x77,0x6f,0x72,0x6b,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,0x69,0x7a,0x65,0x28,
0x38,0x2c,0x38,0x2c,0x31,0x29,0x29,0x29,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x63,0x6e,0x32,0x28,0x5f,0x5f,0x67,0x6c,0x6f,
0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,
0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x73,0x74,0x61,0x74,0x65,0x73,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x2a,0x6f,0x75,0x74,0x70,
0x75,0x74,0x2c,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x54,0x61,0x72,0x67,0x65,0x74,0x2c,0x75,0x69,0x6e,0x74,0x20,0x54,0x68,0x72,0x65,0x61,0x64,0x73,0x29,0x0a,0x7b,0x0a,
0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x20,0x41,0x45,0x53,0x30,0x5b,0x32,0x35,0x36,0x5d,0x2c,0x41,0x45,0x53,0x31,0x5b,0x32,0x35,0x36,0x5d,
0x2c,0x41,0x45,0x53,0x32,0x5b,0x32,0x35,0x36,0x5d,0x2c,0x41,0x45,0x53,0x33,0x5b,0x32,0x35,0x36,0x5d,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x20,0x45,0x78,0x70,0x61,0x6e,
0x64,0x65,0x64,0x4b,0x65,0x79,0x32,0x5b,0x34,0x30,0x5d,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x34,0x20,0x74,0x65,0x78,0x74,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,
0x69,0x6e,0x74,0x20,0x67,0x49,0x64,0x78,0x3d,0x67,0x65,0x74,0x49,0x64,0x78,0x28,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x67,0x65,
0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x2a,0x38,0x2b,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,
0x20,0x69,0x3c,0x32,0x35,0x36,0x3b,0x20,0x69,0x2b,0x3d,0x38,0x2a,0x38,0x29,0x20,0x7b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,0x74,0x6d,0x70,
0x3d,0x41,0x45,0x53,0x30,0x5f,0x43,0x5b,0x69,0x5d,0x3b,0x0a,0x41,0x45,0x53,0x30,0x5b,0x69,0x5d,0x3d,0x74,0x6d,0x70,0x3b,0x0a,0x41,0x45,0x53,0x31,0x5b,0x69,0x5d,
0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x6d,0x70,0x2c,0x38,0x55,0x29,0x3b,0x0a,0x41,0x45,0x53,0x32,0x5b,0x69,0x5d,0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,
0x74,0x6d,0x70,0x2c,0x31,0x36,0x55,0x29,0x3b,0x0a,0x41,0x45,0x53,0x33,0x5b,0x69,0x5d,0x3d,0x72,0x6f,0x74,0x61,0x74,0x65,0x28,0x74,0x6d,0x70,0x2c,0x32,0x34,0x55,
0x29,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,
0x29,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x78,0x69,0x6e,0x31,0x5b,0x38,0x5d,0x5b,0x38,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,
0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x20,0x78,0x69,0x6e,0x32,0x5b,0x38,0x5d,0x5b,0x38,0x5d,0x3b,0x0a,0x7b,0x0a,0x73,0x74,0x61,0x74,0x65,0x73,0x2b,
0x3d,0x32,0x35,0x2a,0x67,0x49,0x64,0x78,0x3b,0x0a,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x2b,0x3d,0x67,0x49,0x64,0x78,0x2a,0x28,0x4d,0x45,0x4d,0x4f,
0x52,0x59,0x3e,0x3e,0x34,0x29,0x3b,0x0a,0x23,0x69,0x66,0x20,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x28,0x5f,0x5f,0x54,0x61,0x68,0x69,0x74,0x69,0x5f,0x5f,0x29,0x20,
0x7c,0x7c,0x20,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x28,0x5f,0x5f,0x50,0x69,0x74,0x63,0x61,0x69,0x72,0x6e,0x5f,0x5f,0x29,0x0a,0x66,0x6f,0x72,0x28,0x69,0x6e,0x74,
0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x34,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x28,0x28,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x2a,0x29,0x45,0x78,0x70,0x61,0x6e,0x64,
0x65,0x64,0x4b,0x65,0x79,0x32,0x29,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x69,0x2b,0x34,0x5d,0x3b,0x0a,0x74,0x65,0x78,0x74,0x3d,0x76,0x6c,0x6f,
0x61,0x64,0x34,0x28,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x2b,0x34,0x2c,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,
0x75,0x69,0x6e,0x74,0x20,0x2a,0x29,0x73,0x74,0x61,0x74,0x65,0x73,0x29,0x3b,0x0a,0x23,0x65,0x6c,0x73,0x65,0x0a,0x74,0x65,0x78,0x74,0x3d,0x76,0x6c,0x6f,0x61,0x64,
0x34,0x28,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x2b,0x34,0x2c,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,
0x6e,0x74,0x20,0x2a,0x29,0x73,0x74,0x61,0x74,0x65,0x73,0x29,0x3b,0x0a,0x28,0x28,0x75,0x69,0x6e,0x74,0x38,0x20,0x2a,0x29,0x45,0x78,0x70,0x61,0x6e,0x64,0x65,0x64,
0x4b,0x65,0x79,0x32,0x29,0x5b,0x30,0x5d,0x3d,0x76,0x6c,0x6f,0x61,0x64,0x38,0x28,0x31,0x2c,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,
0x20,0x2a,0x29,0x73,0x74,0x61,0x74,0x65,0x73,0x29,0x3b,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x41,0x45,0x53,0x45,0x78,0x70,0x61,0x6e,0x64,0x4b,0x65,0x79,0x32,
0x35,0x36,0x28,0x45,0x78,0x70,0x61,0x6e,0x64,0x65,0x64,0x4b,0x65,0x79,0x32,0x29,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,
0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x2a,
0x20,0x78,0x69,0x6e,0x31,0x5f,0x73,0x74,0x6f,0x72,0x65,0x3d,0x26,0x78,0x69,0x6e,0x31,0x5b,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,
0x29,0x5d,0x5b,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,
0x74,0x34,0x2a,0x20,0x78,0x69,0x6e,0x31,0x5f,0x6c,0x6f,0x61,0x64,0x3d,0x26,0x78,0x69,0x6e,0x31,0x5b,0x28,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,
0x64,0x28,0x31,0x29,0x2b,0x31,0x29,0x20,0x25,0x20,0x38,0x5d,0x5b,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x5d,0x3b,0x0a,0x5f,
0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x2a,0x20,0x78,0x69,0x6e,0x32,0x5f,0x73,0x74,0x6f,0x72,0x65,0x3d,0x26,0x78,0x69,0x6e,0x32,0x5b,0x67,
0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x5d,0x5b,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x5d,
0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x34,0x2a,0x20,0x78,0x69,0x6e,0x32,0x5f,0x6c,0x6f,0x61,0x64,0x3d,0x26,0x78,0x69,0x6e,0x32,
0x5b,0x28,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x2b,0x31,0x29,0x20,0x25,0x20,0x38,0x5d,0x5b,0x67,0x65,0x74,0x5f,0x6c,0x6f,
0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x5d,0x3b,0x0a,0x2a,0x78,0x69,0x6e,0x32,0x5f,0x73,0x74,0x6f,0x72,0x65,0x3d,0x28,0x75,0x69,0x6e,0x74,0x34,0x29,0x28,
0x30,0x2c,0x30,0x2c,0x30,0x2c,0x30,0x29,0x3b,0x0a,0x7b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x32,0x0a,0x66,0x6f,0x72,
0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x2c,0x69,0x31,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x3b,0x20,0x69,0x3c,
0x28,0x4d,0x45,0x4d,0x4f,0x52,0x59,0x3e,0x3e,0x37,0x29,0x3b,0x20,0x2b,0x2b,0x69,0x2c,0x69,0x31,0x3d,0x28,0x69,0x31,0x2b,0x31,0x36,0x29,0x20,0x25,0x20,0x28,0x4d,
0x45,0x4d,0x4f,0x52,0x59,0x3e,0x3e,0x34,0x29,0x29,0x20,0x7b,0x0a,0x74,0x65,0x78,0x74,0x20,0x5e,0x3d,0x20,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5b,
0x28,0x75,0x69,0x6e,0x74,0x29,0x69,0x31,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,0x74,0x65,0x78,0x74,0x20,0x5e,0x3d,0x20,0x2a,0x78,0x69,0x6e,0x32,0x5f,0x6c,0x6f,0x61,0x64,0x3b,0x0a,0x23,0x70,0x72,
0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x30,0x0a,0x66,0x6f,0x72,0x28,0x69,0x6e,0x74,0x20,0x6a,0x3d,0x30,0x3b,0x20,0x6a,0x3c,0x31,0x30,
0x3b,0x20,0x2b,0x2b,0x6a,0x29,0x0a,0x74,0x65,0x78,0x74,0x3d,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x28,0x41,0x45,0x53,0x30,0x2c,0x41,0x45,0x53,0x31,0x2c,
0x41,0x45,0x53,0x32,0x2c,0x41,0x45,0x53,0x33,0x2c,0x74,0x65,0x78,0x74,0x2c,0x28,0x28,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x29,0x45,0x78,0x70,0x61,0x6e,0x64,0x65,
0x64,0x4b,0x65,0x79,0x32,0x29,0x5b,0x6a,0x5d,0x29,0x3b,0x0a,0x2a,0x78,0x69,0x6e,0x31,0x5f,0x73,0x74,0x6f,0x72,0x65,0x3d,0x74,0x65,0x78,0x74,0x3b,0x0a,0x74,0x65,
0x78,0x74,0x20,0x5e,0x3d,0x20,0x53,0x63,0x72,0x61,0x74,0x63,0x68,0x70,0x61,0x64,0x5b,0x28,0x75,0x69,0x6e,0x74,0x29,0x69,0x31,0x2b,0x38,0x75,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,0x74,0x65,0x78,
0x74,0x20,0x5e,0x3d,0x20,0x2a,0x78,0x69,0x6e,0x31,0x5f,0x6c,0x6f,0x61,0x64,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,
0x31,0x30,0x0a,0x66,0x6f,0x72,0x28,0x69,0x6e,0x74,0x20,0x6a,0x3d,0x30,0x3b,0x20,0x6a,0x3c,0x31,0x30,0x3b,0x20,0x2b,0x2b,0x6a,0x29,0x0a,0x74,0x65,0x78,0x74,0x3d,
0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x28,0x41,0x45,0x53,0x30,0x2c,0x41,0x45,0x53,0x31,0x2c,0x41,0x45,0x53,0x32,0x2c,0x41,0x45,0x53,0x33,0x2c,0x74,0x65,
0x78,0x74,0x2c,0x28,0x28,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x29,0x45,0x78,0x70,0x61,0x6e,0x64,0x65,0x64,0x4b,0x65,0x79,0x32,0x29,0x5b,0x6a,0x5d,0x29,0x3b,0x0a,
0x2a,0x78,0x69,0x6e,0x32,0x5f,0x73,0x74,0x6f,0x72,0x65,0x3d,0x74,0x65,0x78,0x74,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,0x74,0x65,0x78,0x74,0x20,0x5e,0x3d,0x20,0x2a,0x78,0x69,0x6e,0x32,0x5f,
0x6c,0x6f,0x61,0x64,0x3b,0x0a,0x7d,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x36,0x0a,0x66,0x6f,0x72,0x28,0x73,0x69,
0x7a,0x65,0x5f,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x31,0x36,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x7b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,
0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x30,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x6a,0x3d,0x30,0x3b,0x20,0x6a,0x3c,0x31,0x30,0x3b,0x20,0x2b,0x2b,0x6a,
0x29,0x20,0x7b,0x0a,0x74,0x65,0x78,0x74,0x3d,0x41,0x45,0x53,0x5f,0x52,0x6f,0x75,0x6e,0x64,0x28,0x41,0x45,0x53,0x30,0x2c,0x41,0x45,0x53,0x31,0x2c,0x41,0x45,0x53,
0x32,0x2c,0x41,0x45,0x53,0x33,0x2c,0x74,0x65,0x78,0x74,0x2c,0x28,0x28,0x75,0x69,0x6e,0x74,0x34,0x20,0x2a,0x29,0x45,0x78,0x70,0x61,0x6e,0x64,0x65,0x64,0x4b,0x65,
0x79,0x32,0x29,0x5b,0x6a,0x5d,0x29,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,
0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x2a,0x78,0x69,0x6e,0x31,0x5f,0x73,0x74,0x6f,0x72,0x65,0x3d,0x74,0x65,0x78,0x74,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,0x74,0x65,0x78,0x74,0x20,0x5e,0x3d,
0x20,0x2a,0x78,0x69,0x6e,0x31,0x5f,0x6c,0x6f,0x61,0x64,0x3b,0x0a,0x7d,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x53,0x74,0x61,
0x74,0x65,0x5f,0x62,0x75,0x66,0x5b,0x38,0x2a,0x32,0x35,0x5d,0x3b,0x0a,0x7b,0x0a,0x76,0x73,0x74,0x6f,0x72,0x65,0x32,0x28,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,
0x32,0x28,0x74,0x65,0x78,0x74,0x29,0x2c,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x2b,0x34,0x2c,0x73,0x74,0x61,0x74,0x65,0x73,
0x29,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x47,0x4c,0x4f,0x42,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,
0x45,0x29,0x3b,0x0a,0x7b,0x0a,0x69,0x66,0x28,0x21,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x31,0x29,0x29,0x0a,0x7b,0x0a,0x5f,0x5f,0x6c,
0x6f,0x63,0x61,0x6c,0x20,0x75,0x6c,0x6f,0x6e,0x67,0x2a,0x20,0x53,0x74,0x61,0x74,0x65,0x3d,0x53,0x74,0x61,0x74,0x65,0x5f,0x62,0x75,0x66,0x2b,0x67,0x65,0x74,0x5f,
0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x2a,0x32,0x35,0x3b,0x0a,0x66,0x6f,0x72,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x32,
0x35,0x3b,0x20,0x2b,0x2b,0x69,0x29,0x20,0x53,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x73,0x5b,0x69,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,
0x61,0x6b,0x66,0x31,0x36,0x30,0x30,0x5f,0x32,0x28,0x53,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a,0x69,0x66,0x28,0x53,0x74,0x61,0x74,0x65,0x5b,0x33,0x5d,0x3c,0x3d,0x54,
0x61,0x72,0x67,0x65,0x74,0x29,0x0a,0x7b,0x0a,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x6f,0x75,0x74,0x49,0x64,0x78,0x3d,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,
0x28,0x6f,0x75,0x74,0x70,0x75,0x74,0x2b,0x30,0x78,0x46,0x46,0x29,0x3b,0x0a,0x69,0x66,0x28,0x6f,0x75,0x74,0x49,0x64,0x78,0x3c,0x30,0x78,0x46,0x46,0x29,0x0a,0x6f,
0x75,0x74,0x70,0x75,0x74,0x5b,0x6f,0x75,0x74,0x49,0x64,0x78,0x5d,0x3d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,
0x7d,0x0a,0x7d,0x0a,0x7d,0x0a,0x6d,0x65,0x6d,0x5f,0x66,0x65,0x6e,0x63,0x65,0x28,0x43,0x4c,0x4b,0x5f,0x47,0x4c,0x4f,0x42,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,
0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x7d,0x0a,0x00
};
} // namespace xmrig
+3 -1
View File
@@ -4,8 +4,10 @@
#include "randomx_constants_monero.h" #include "randomx_constants_monero.h"
#elif (ALGO == ALGO_RX_WOW) #elif (ALGO == ALGO_RX_WOW)
#include "randomx_constants_wow.h" #include "randomx_constants_wow.h"
#elif (ALGO == ALGO_RX_ARQMA) #elif (ALGO == ALGO_RX_ARQ)
#include "randomx_constants_arqma.h" #include "randomx_constants_arqma.h"
#elif (ALGO == ALGO_RX_XEQ)
#include "randomx_constants_equilibria.h"
#elif (ALGO == ALGO_RX_KEVA) #elif (ALGO == ALGO_RX_KEVA)
#include "randomx_constants_keva.h" #include "randomx_constants_keva.h"
#elif (ALGO == ALGO_RX_GRAFT) #elif (ALGO == ALGO_RX_GRAFT)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,96 @@
/*
Copyright (c) 2019 SChernykh
This file is part of RandomX OpenCL.
RandomX OpenCL 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.
RandomX OpenCL 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 RandomX OpenCL. If not, see <http://www.gnu.org/licenses/>.
*/
//Dataset base size in bytes. Must be a power of 2.
#define RANDOMX_DATASET_BASE_SIZE 2147483648
//Dataset extra size. Must be divisible by 64.
#define RANDOMX_DATASET_EXTRA_SIZE 33554368
//Scratchpad L3 size in bytes. Must be a power of 2.
#define RANDOMX_SCRATCHPAD_L3 262144
//Scratchpad L2 size in bytes. Must be a power of two and less than or equal to RANDOMX_SCRATCHPAD_L3.
#define RANDOMX_SCRATCHPAD_L2 131072
//Scratchpad L1 size in bytes. Must be a power of two (minimum 64) and less than or equal to RANDOMX_SCRATCHPAD_L2.
#define RANDOMX_SCRATCHPAD_L1 16384
//Jump condition mask size in bits.
#define RANDOMX_JUMP_BITS 8
//Jump condition mask offset in bits. The sum of RANDOMX_JUMP_BITS and RANDOMX_JUMP_OFFSET must not exceed 16.
#define RANDOMX_JUMP_OFFSET 8
//Integer instructions
#define RANDOMX_FREQ_IADD_RS 16
#define RANDOMX_FREQ_IADD_M 7
#define RANDOMX_FREQ_ISUB_R 16
#define RANDOMX_FREQ_ISUB_M 7
#define RANDOMX_FREQ_IMUL_R 16
#define RANDOMX_FREQ_IMUL_M 4
#define RANDOMX_FREQ_IMULH_R 4
#define RANDOMX_FREQ_IMULH_M 1
#define RANDOMX_FREQ_ISMULH_R 4
#define RANDOMX_FREQ_ISMULH_M 1
#define RANDOMX_FREQ_IMUL_RCP 8
#define RANDOMX_FREQ_INEG_R 2
#define RANDOMX_FREQ_IXOR_R 15
#define RANDOMX_FREQ_IXOR_M 5
#define RANDOMX_FREQ_IROR_R 8
#define RANDOMX_FREQ_IROL_R 2
#define RANDOMX_FREQ_ISWAP_R 4
//Floating point instructions
#define RANDOMX_FREQ_FSWAP_R 4
#define RANDOMX_FREQ_FADD_R 16
#define RANDOMX_FREQ_FADD_M 5
#define RANDOMX_FREQ_FSUB_R 16
#define RANDOMX_FREQ_FSUB_M 5
#define RANDOMX_FREQ_FSCAL_R 6
#define RANDOMX_FREQ_FMUL_R 32
#define RANDOMX_FREQ_FDIV_M 4
#define RANDOMX_FREQ_FSQRT_R 6
//Control instructions
#define RANDOMX_FREQ_CBRANCH 25
#define RANDOMX_FREQ_CFROUND 1
//Store instruction
#define RANDOMX_FREQ_ISTORE 16
//No-op instruction
#define RANDOMX_FREQ_NOP 0
#define RANDOMX_DATASET_ITEM_SIZE 64
#define RANDOMX_PROGRAM_SIZE 256
#define HASH_SIZE 64
#define ENTROPY_SIZE (128 + RANDOMX_PROGRAM_SIZE * 8)
#define REGISTERS_SIZE 256
#define IMM_BUF_SIZE (RANDOMX_PROGRAM_SIZE * 4 - REGISTERS_SIZE)
#define IMM_INDEX_COUNT ((IMM_BUF_SIZE / 4) - 2)
#define VM_STATE_SIZE (REGISTERS_SIZE + IMM_BUF_SIZE + RANDOMX_PROGRAM_SIZE * 4)
#define ROUNDING_MODE (RANDOMX_FREQ_CFROUND ? -1 : 0)
// Scratchpad L1/L2/L3 bits
#define LOC_L1 (32 - 14)
#define LOC_L2 (32 - 17)
#define LOC_L3 (32 - 18)
@@ -0,0 +1,87 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 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>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/opencl/OclThreads.h"
#include "backend/opencl/wrappers/OclDevice.h"
#include "base/crypto/Algorithm.h"
#include <algorithm>
namespace xmrig {
constexpr const size_t oneMiB = 1024u * 1024u;
bool ocl_generic_cn_gpu_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads)
{
if (algorithm != Algorithm::CN_GPU) {
return false;
}
uint32_t worksize = 8;
uint32_t numThreads = 1u;
size_t minFreeMem = 128u * oneMiB;
if (device.type() == OclDevice::Vega_10 || device.type() == OclDevice::Vega_20) {
minFreeMem = oneMiB;
worksize = 16;
}
else if (device.type() == OclDevice::Navi_10) {
numThreads = 2u;
}
else if (device.name() == "Fiji") {
worksize = 16;
}
size_t maxThreads = device.computeUnits() * 6 * 8;
const size_t maxAvailableFreeMem = device.freeMemSize() - minFreeMem;
const size_t memPerThread = std::min(device.maxMemAllocSize(), maxAvailableFreeMem);
size_t memPerHash = algorithm.l3() + 240u;
size_t maxIntensity = memPerThread / memPerHash;
size_t possibleIntensity = std::min(maxThreads, maxIntensity);
size_t intensity = 0;
size_t cuUtilization = ((possibleIntensity * 100) / (worksize * device.computeUnits())) % 100;
if (cuUtilization >= 75) {
intensity = (possibleIntensity / worksize) * worksize;
}
else {
intensity = (possibleIntensity / (worksize * device.computeUnits())) * device.computeUnits() * worksize;
}
threads.add(OclThread(device.index(), intensity, worksize, numThreads, 1));
return true;
}
} // namespace xmrig
@@ -0,0 +1,44 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/opencl/kernels/Cn00RyoKernel.h"
#include "backend/opencl/wrappers/OclLib.h"
void xmrig::Cn00RyoKernel::enqueue(cl_command_queue queue, size_t threads)
{
const size_t gthreads = threads * 64;
const size_t lthreads = 64;
enqueueNDRange(queue, 1, nullptr, &gthreads, &lthreads);
}
// __kernel void cn00(__global int *Scratchpad, __global ulong *states)
void xmrig::Cn00RyoKernel::setArgs(cl_mem scratchpads, cl_mem states)
{
setArg(0, sizeof(cl_mem), &scratchpads);
setArg(1, sizeof(cl_mem), &states);
}
@@ -0,0 +1,48 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CN00RYOKERNEL_H
#define XMRIG_CN00RYOKERNEL_H
#include "backend/opencl/wrappers/OclKernel.h"
namespace xmrig {
class Cn00RyoKernel : public OclKernel
{
public:
inline Cn00RyoKernel(cl_program program) : OclKernel(program, "cn00") {}
void enqueue(cl_command_queue queue, size_t threads);
void setArgs(cl_mem scratchpads, cl_mem states);
};
} // namespace xmrig
#endif /* XMRIG_CN00RYOKERNEL_H */
@@ -0,0 +1,48 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include "backend/opencl/kernels/Cn1RyoKernel.h"
#include "backend/opencl/wrappers/OclLib.h"
void xmrig::Cn1RyoKernel::enqueue(cl_command_queue queue, size_t threads, size_t worksize)
{
const size_t gthreads = threads * 16;
const size_t lthreads = worksize * 16;
enqueueNDRange(queue, 1, nullptr, &gthreads, &lthreads);
}
// __kernel void cn1(__global int *lpad_in, __global int *spad, uint numThreads)
void xmrig::Cn1RyoKernel::setArgs(cl_mem scratchpads, cl_mem states, uint32_t threads)
{
setArg(0, sizeof(cl_mem), &scratchpads);
setArg(1, sizeof(cl_mem), &states);
setArg(2, sizeof(uint32_t), &threads);
}
+48
View File
@@ -0,0 +1,48 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CN1RYOKERNEL_H
#define XMRIG_CN1RYOKERNEL_H
#include "backend/opencl/wrappers/OclKernel.h"
namespace xmrig {
class Cn1RyoKernel : public OclKernel
{
public:
inline Cn1RyoKernel(cl_program program) : OclKernel(program, "cn1") {}
void enqueue(cl_command_queue queue, size_t threads, size_t worksize);
void setArgs(cl_mem scratchpads, cl_mem states, uint32_t threads);
};
} // namespace xmrig
#endif /* XMRIG_CN1RYOKERNEL_H */
@@ -0,0 +1,53 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/opencl/kernels/Cn2RyoKernel.h"
#include "backend/opencl/wrappers/OclLib.h"
void xmrig::Cn2RyoKernel::enqueue(cl_command_queue queue, uint32_t nonce, size_t threads)
{
const size_t offset[2] = { nonce, 1 };
const size_t gthreads[2] = { threads, 8 };
static const size_t lthreads[2] = { 8, 8 };
enqueueNDRange(queue, 2, offset, gthreads, lthreads);
}
// __kernel void cn2(__global uint4 *Scratchpad, __global ulong *states, __global uint *output, ulong Target, uint Threads)
void xmrig::Cn2RyoKernel::setArgs(cl_mem scratchpads, cl_mem states, cl_mem output, uint32_t threads)
{
setArg(0, sizeof(cl_mem), &scratchpads);
setArg(1, sizeof(cl_mem), &states);
setArg(2, sizeof(cl_mem), &output);
setArg(4, sizeof(uint32_t), &threads);
}
void xmrig::Cn2RyoKernel::setTarget(uint64_t target)
{
setArg(3, sizeof(cl_ulong), &target);
}
+49
View File
@@ -0,0 +1,49 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CN2RYOKERNEL_H
#define XMRIG_CN2RYOKERNEL_H
#include "backend/opencl/wrappers/OclKernel.h"
namespace xmrig {
class Cn2RyoKernel : public OclKernel
{
public:
inline Cn2RyoKernel(cl_program program) : OclKernel(program, "cn2") {}
void enqueue(cl_command_queue queue, uint32_t nonce, size_t threads);
void setArgs(cl_mem scratchpads, cl_mem states, cl_mem output, uint32_t threads);
void setTarget(uint64_t target);
};
} // namespace xmrig
#endif /* XMRIG_CN2RYOKERNEL_H */
+17
View File
@@ -127,6 +127,23 @@ if (WITH_OPENCL)
) )
endif() endif()
if (WITH_CN_GPU AND CMAKE_SIZEOF_VOID_P EQUAL 8)
list(APPEND HEADERS_BACKEND_OPENCL
src/backend/opencl/kernels/Cn00RyoKernel.h
src/backend/opencl/kernels/Cn1RyoKernel.h
src/backend/opencl/kernels/Cn2RyoKernel.h
src/backend/opencl/runners/OclRyoRunner.h
)
list(APPEND SOURCES_BACKEND_OPENCL
src/backend/opencl/generators/ocl_generic_cn_gpu_generator.cpp
src/backend/opencl/kernels/Cn00RyoKernel.cpp
src/backend/opencl/kernels/Cn1RyoKernel.cpp
src/backend/opencl/kernels/Cn2RyoKernel.cpp
src/backend/opencl/runners/OclRyoRunner.cpp
)
endif()
if (WITH_STRICT_CACHE) if (WITH_STRICT_CACHE)
add_definitions(/DXMRIG_STRICT_OPENCL_CACHE) add_definitions(/DXMRIG_STRICT_OPENCL_CACHE)
else() else()
+129
View File
@@ -0,0 +1,129 @@
/* 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>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "backend/opencl/runners/OclRyoRunner.h"
#include "backend/opencl/kernels/Cn00RyoKernel.h"
#include "backend/opencl/kernels/Cn0Kernel.h"
#include "backend/opencl/kernels/Cn1RyoKernel.h"
#include "backend/opencl/kernels/Cn2RyoKernel.h"
#include "backend/opencl/kernels/CnBranchKernel.h"
#include "backend/opencl/OclLaunchData.h"
#include "backend/opencl/wrappers/OclLib.h"
#include "base/io/log/Log.h"
#include "base/net/stratum/Job.h"
#include "crypto/cn/CnAlgo.h"
#include <stdexcept>
xmrig::OclRyoRunner::OclRyoRunner(size_t index, const OclLaunchData &data) : OclBaseRunner(index, data)
{
m_options += " -DITERATIONS=" + std::to_string(CnAlgo<>::iterations(m_algorithm)) + "U";
m_options += " -DMASK=" + std::to_string(CnAlgo<>::mask(m_algorithm)) + "U";
m_options += " -DWORKSIZE=" + std::to_string(data.thread.worksize()) + "U";
m_options += " -DMEMORY=" + std::to_string(m_algorithm.l3()) + "LU";
m_options += " -DCN_UNROLL=" + std::to_string(data.thread.unrollFactor());
m_options += " -cl-fp32-correctly-rounded-divide-sqrt";
}
xmrig::OclRyoRunner::~OclRyoRunner()
{
delete m_cn00;
delete m_cn0;
delete m_cn1;
delete m_cn2;
OclLib::release(m_scratchpads);
OclLib::release(m_states);
}
size_t xmrig::OclRyoRunner::bufferSize() const
{
return OclBaseRunner::bufferSize() + align(data().algorithm.l3() * m_intensity) + align(200 * m_intensity);
}
void xmrig::OclRyoRunner::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;
assert(g_thd % w_size == 0);
enqueueWriteBuffer(m_output, CL_FALSE, sizeof(cl_uint) * 0xFF, sizeof(cl_uint), &zero);
m_cn0->enqueue(m_queue, nonce, g_thd);
m_cn00->enqueue(m_queue, g_thd);
m_cn1->enqueue(m_queue, g_thd, w_size);
m_cn2->enqueue(m_queue, nonce, g_thd);
finalize(hashOutput);
}
void xmrig::OclRyoRunner::set(const Job &job, uint8_t *blob)
{
if (job.size() > (Job::kMaxBlobSize - 4)) {
throw std::length_error("job size too big");
}
blob[job.size()] = 0x01;
memset(blob + job.size() + 1, 0, Job::kMaxBlobSize - job.size() - 1);
enqueueWriteBuffer(m_input, CL_TRUE, 0, Job::kMaxBlobSize, blob);
m_cn2->setTarget(job.target());
}
void xmrig::OclRyoRunner::build()
{
OclBaseRunner::build();
m_cn00 = new Cn00RyoKernel(m_program);
m_cn00->setArgs(m_scratchpads, m_states);
m_cn0 = new Cn0Kernel(m_program);
m_cn0->setArgs(m_input, 0, m_scratchpads, m_states, m_intensity);
m_cn1 = new Cn1RyoKernel(m_program);
m_cn1->setArgs(m_scratchpads, m_states, m_intensity);
m_cn2 = new Cn2RyoKernel(m_program);
m_cn2->setArgs(m_scratchpads, m_states, m_output, m_intensity);
}
void xmrig::OclRyoRunner::init()
{
OclBaseRunner::init();
m_scratchpads = createSubBuffer(CL_MEM_READ_WRITE, data().algorithm.l3() * m_intensity);
m_states = createSubBuffer(CL_MEM_READ_WRITE, 200 * m_intensity);
}
+70
View File
@@ -0,0 +1,70 @@
/* 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>
*
* 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_OCLRYORUNNER_H
#define XMRIG_OCLRYORUNNER_H
#include "backend/opencl/runners/OclBaseRunner.h"
namespace xmrig {
class Cn00RyoKernel;
class Cn0Kernel;
class Cn1RyoKernel;
class Cn2RyoKernel;
class OclRyoRunner : public OclBaseRunner
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(OclRyoRunner)
OclRyoRunner(size_t index, const OclLaunchData &data);
~OclRyoRunner() override;
protected:
size_t bufferSize() const override;
void run(uint32_t nonce, uint32_t *hashOutput) override;
void set(const Job &job, uint8_t *blob) override;
void build() override;
void init() override;
private:
cl_mem m_scratchpads = nullptr;
cl_mem m_states = nullptr;
Cn00RyoKernel *m_cn00 = nullptr;
Cn0Kernel *m_cn0 = nullptr;
Cn1RyoKernel *m_cn1 = nullptr;
Cn2RyoKernel *m_cn2 = nullptr;
};
} /* namespace xmrig */
#endif // XMRIG_OCLRYORUNNER_H
+8 -1
View File
@@ -54,6 +54,10 @@ extern bool ocl_generic_kawpow_generator(const OclDevice& device, const Algorith
extern bool ocl_vega_cn_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads); extern bool ocl_vega_cn_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads);
extern bool ocl_generic_cn_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads); extern bool ocl_generic_cn_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads);
#ifdef XMRIG_ALGO_CN_GPU
extern bool ocl_generic_cn_gpu_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads);
#endif
static ocl_gen_config_fun generators[] = { static ocl_gen_config_fun generators[] = {
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
@@ -63,7 +67,10 @@ static ocl_gen_config_fun generators[] = {
ocl_generic_kawpow_generator, ocl_generic_kawpow_generator,
# endif # endif
ocl_vega_cn_generator, ocl_vega_cn_generator,
ocl_generic_cn_generator ocl_generic_cn_generator,
# ifdef XMRIG_ALGO_CN_GPU
ocl_generic_cn_gpu_generator,
# endif
}; };
+39 -2
View File
@@ -74,11 +74,16 @@ const char *Algorithm::kCN_PICO_TLO = "cn-pico/tlo";
const char *Algorithm::kCN_UPX2 = "cn/upx2"; const char *Algorithm::kCN_UPX2 = "cn/upx2";
#endif #endif
#ifdef XMRIG_ALGO_CN_GPU
const char *Algorithm::kCN_GPU = "cn/gpu";
#endif
#ifdef XMRIG_ALGO_RANDOMX #ifdef XMRIG_ALGO_RANDOMX
const char *Algorithm::kRX = "rx"; const char *Algorithm::kRX = "rx";
const char *Algorithm::kRX_0 = "rx/0"; const char *Algorithm::kRX_0 = "rx/0";
const char *Algorithm::kRX_WOW = "rx/wow"; const char *Algorithm::kRX_WOW = "rx/wow";
const char *Algorithm::kRX_ARQ = "rx/arq"; const char *Algorithm::kRX_ARQ = "rx/arq";
const char *Algorithm::kRX_XEQ = "rx/xeq";
const char *Algorithm::kRX_GRAFT = "rx/graft"; const char *Algorithm::kRX_GRAFT = "rx/graft";
const char *Algorithm::kRX_SFX = "rx/sfx"; const char *Algorithm::kRX_SFX = "rx/sfx";
const char *Algorithm::kRX_KEVA = "rx/keva"; const char *Algorithm::kRX_KEVA = "rx/keva";
@@ -99,6 +104,12 @@ const char *Algorithm::kKAWPOW_RVN = "kawpow";
#ifdef XMRIG_ALGO_GHOSTRIDER #ifdef XMRIG_ALGO_GHOSTRIDER
const char* Algorithm::kGHOSTRIDER = "ghostrider"; const char* Algorithm::kGHOSTRIDER = "ghostrider";
const char* Algorithm::kGHOSTRIDER_RTM = "ghostrider"; const char* Algorithm::kGHOSTRIDER_RTM = "ghostrider";
const char* Algorithm::kFLEX = "flex";
const char* Algorithm::kFLEX_KCN = "flex";
#endif
#ifdef XMRIG_ALGO_RANDOMX
const char *Algorithm::kRX_XLA = "panthera";
#endif #endif
@@ -141,10 +152,15 @@ static const std::map<uint32_t, const char *> kAlgorithmNames = {
ALGO_NAME(CN_UPX2), ALGO_NAME(CN_UPX2),
# endif # endif
# ifdef XMRIG_ALGO_CN_GPU
ALGO_NAME(CN_GPU),
# endif
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
ALGO_NAME(RX_0), ALGO_NAME(RX_0),
ALGO_NAME(RX_WOW), ALGO_NAME(RX_WOW),
ALGO_NAME(RX_ARQ), ALGO_NAME(RX_ARQ),
ALGO_NAME(RX_XEQ),
ALGO_NAME(RX_GRAFT), ALGO_NAME(RX_GRAFT),
ALGO_NAME(RX_SFX), ALGO_NAME(RX_SFX),
ALGO_NAME(RX_KEVA), ALGO_NAME(RX_KEVA),
@@ -160,8 +176,13 @@ static const std::map<uint32_t, const char *> kAlgorithmNames = {
ALGO_NAME(KAWPOW_RVN), ALGO_NAME(KAWPOW_RVN),
# endif # endif
# ifdef XMRIG_ALGO_RANDOMX
ALGO_NAME(RX_XLA),
# endif
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
ALGO_NAME(GHOSTRIDER_RTM), ALGO_NAME(GHOSTRIDER_RTM),
ALGO_NAME(FLEX_KCN),
# endif # endif
}; };
@@ -247,6 +268,11 @@ static const std::map<const char *, Algorithm::Id, aliasCompare> kAlgorithmAlias
ALGO_ALIAS(CN_UPX2, "cryptonight-upx/2"), ALGO_ALIAS(CN_UPX2, "cryptonight-upx/2"),
# endif # endif
# ifdef XMRIG_ALGO_CN_GPU
ALGO_ALIAS_AUTO(CN_GPU), ALGO_ALIAS(CN_GPU, "cryptonight/gpu"),
ALGO_ALIAS(CN_GPU, "cryptonight_gpu"),
# endif
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
ALGO_ALIAS_AUTO(RX_0), ALGO_ALIAS(RX_0, "randomx/0"), ALGO_ALIAS_AUTO(RX_0), ALGO_ALIAS(RX_0, "randomx/0"),
ALGO_ALIAS(RX_0, "randomx/test"), ALGO_ALIAS(RX_0, "randomx/test"),
@@ -257,6 +283,8 @@ static const std::map<const char *, Algorithm::Id, aliasCompare> kAlgorithmAlias
ALGO_ALIAS(RX_WOW, "randomwow"), ALGO_ALIAS(RX_WOW, "randomwow"),
ALGO_ALIAS_AUTO(RX_ARQ), ALGO_ALIAS(RX_ARQ, "randomx/arq"), ALGO_ALIAS_AUTO(RX_ARQ), ALGO_ALIAS(RX_ARQ, "randomx/arq"),
ALGO_ALIAS(RX_ARQ, "randomarq"), ALGO_ALIAS(RX_ARQ, "randomarq"),
ALGO_ALIAS_AUTO(RX_XEQ), ALGO_ALIAS(RX_XEQ, "randomx/xeq"),
ALGO_ALIAS(RX_XEQ, "randomxeq"),
ALGO_ALIAS_AUTO(RX_GRAFT), ALGO_ALIAS(RX_GRAFT, "randomx/graft"), ALGO_ALIAS_AUTO(RX_GRAFT), ALGO_ALIAS(RX_GRAFT, "randomx/graft"),
ALGO_ALIAS(RX_GRAFT, "randomgraft"), ALGO_ALIAS(RX_GRAFT, "randomgraft"),
ALGO_ALIAS_AUTO(RX_SFX), ALGO_ALIAS(RX_SFX, "randomx/sfx"), ALGO_ALIAS_AUTO(RX_SFX), ALGO_ALIAS(RX_SFX, "randomx/sfx"),
@@ -275,9 +303,15 @@ static const std::map<const char *, Algorithm::Id, aliasCompare> kAlgorithmAlias
ALGO_ALIAS_AUTO(KAWPOW_RVN), ALGO_ALIAS(KAWPOW_RVN, "kawpow/rvn"), ALGO_ALIAS_AUTO(KAWPOW_RVN), ALGO_ALIAS(KAWPOW_RVN, "kawpow/rvn"),
# endif # endif
# ifdef XMRIG_ALGO_RANDOMX
ALGO_ALIAS_AUTO(RX_XLA), ALGO_ALIAS(RX_XLA, "Panthera"),
# endif
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
ALGO_ALIAS_AUTO(GHOSTRIDER_RTM), ALGO_ALIAS(GHOSTRIDER_RTM, "ghostrider/rtm"), ALGO_ALIAS_AUTO(GHOSTRIDER_RTM), ALGO_ALIAS(GHOSTRIDER_RTM, "ghostrider/rtm"),
ALGO_ALIAS(GHOSTRIDER_RTM, "gr"), ALGO_ALIAS(GHOSTRIDER_RTM, "gr"),
ALGO_ALIAS_AUTO(FLEX_KCN), ALGO_ALIAS(FLEX_KCN, "flex/kcn"),
ALGO_ALIAS(FLEX_KCN, "flex"),
# endif # endif
}; };
@@ -350,10 +384,13 @@ std::vector<xmrig::Algorithm> xmrig::Algorithm::all(const std::function<bool(con
CN_HEAVY_0, CN_HEAVY_TUBE, CN_HEAVY_XHV, CN_HEAVY_0, CN_HEAVY_TUBE, CN_HEAVY_XHV,
CN_PICO_0, CN_PICO_TLO, CN_PICO_0, CN_PICO_TLO,
CN_UPX2, CN_UPX2,
RX_0, RX_WOW, RX_ARQ, RX_GRAFT, RX_SFX, RX_KEVA, CN_GPU,
RX_0, RX_WOW, RX_ARQ, RX_XEQ, RX_GRAFT, RX_SFX, RX_KEVA,
RX_XLA,
AR2_CHUKWA, AR2_CHUKWA_V2, AR2_WRKZ, AR2_CHUKWA, AR2_CHUKWA_V2, AR2_WRKZ,
KAWPOW_RVN, KAWPOW_RVN,
GHOSTRIDER_RTM GHOSTRIDER_RTM,
FLEX_KCN
}; };
Algorithms out; Algorithms out;
+16
View File
@@ -65,6 +65,7 @@ public:
CN_PICO_0 = 0x63120200, // "cn-pico" CryptoNight-Pico CN_PICO_0 = 0x63120200, // "cn-pico" CryptoNight-Pico
CN_PICO_TLO = 0x63120274, // "cn-pico/tlo" CryptoNight-Pico (TLO) CN_PICO_TLO = 0x63120274, // "cn-pico/tlo" CryptoNight-Pico (TLO)
CN_UPX2 = 0x63110200, // "cn/upx2" Uplexa (UPX2) CN_UPX2 = 0x63110200, // "cn/upx2" Uplexa (UPX2)
CN_GPU = 0x63150300, // "cn/gpu" CryptoNight-GPU (Ryo).
CN_GR_0 = 0x63130100, // "cn/dark" GhostRider CN_GR_0 = 0x63130100, // "cn/dark" GhostRider
CN_GR_1 = 0x63130101, // "cn/dark-lite" GhostRider CN_GR_1 = 0x63130101, // "cn/dark-lite" GhostRider
CN_GR_2 = 0x63150102, // "cn/fast" GhostRider CN_GR_2 = 0x63150102, // "cn/fast" GhostRider
@@ -72,9 +73,11 @@ public:
CN_GR_4 = 0x63120104, // "cn/turtle" GhostRider CN_GR_4 = 0x63120104, // "cn/turtle" GhostRider
CN_GR_5 = 0x63120105, // "cn/turtle-lite" GhostRider CN_GR_5 = 0x63120105, // "cn/turtle-lite" GhostRider
GHOSTRIDER_RTM = 0x6c150000, // "ghostrider" GhostRider GHOSTRIDER_RTM = 0x6c150000, // "ghostrider" GhostRider
FLEX_KCN = 0x6c150001, // "flex" Flex
RX_0 = 0x72151200, // "rx/0" RandomX (reference configuration). RX_0 = 0x72151200, // "rx/0" RandomX (reference configuration).
RX_WOW = 0x72141177, // "rx/wow" RandomWOW (Wownero). RX_WOW = 0x72141177, // "rx/wow" RandomWOW (Wownero).
RX_ARQ = 0x72121061, // "rx/arq" RandomARQ (Arqma). RX_ARQ = 0x72121061, // "rx/arq" RandomARQ (Arqma).
RX_XEQ = 0x72121000,
RX_GRAFT = 0x72151267, // "rx/graft" RandomGRAFT (Graft). RX_GRAFT = 0x72151267, // "rx/graft" RandomGRAFT (Graft).
RX_SFX = 0x72151273, // "rx/sfx" RandomSFX (Safex Cash). RX_SFX = 0x72151273, // "rx/sfx" RandomSFX (Safex Cash).
RX_KEVA = 0x7214116b, // "rx/keva" RandomKEVA (Keva). RX_KEVA = 0x7214116b, // "rx/keva" RandomKEVA (Keva).
@@ -82,6 +85,8 @@ public:
AR2_CHUKWA_V2 = 0x61140000, // "argon2/chukwav2" Argon2id (Chukwa v2). AR2_CHUKWA_V2 = 0x61140000, // "argon2/chukwav2" Argon2id (Chukwa v2).
AR2_WRKZ = 0x61120000, // "argon2/wrkz" Argon2id (WRKZ) AR2_WRKZ = 0x61120000, // "argon2/wrkz" Argon2id (WRKZ)
KAWPOW_RVN = 0x6b0f0000, // "kawpow/rvn" KawPow (RVN) KAWPOW_RVN = 0x6b0f0000, // "kawpow/rvn" KawPow (RVN)
RX_XLA = 0x721211ff, // "panthera" Panthera (Scala2).
}; };
enum Family : uint32_t { enum Family : uint32_t {
@@ -136,11 +141,16 @@ public:
static const char *kCN_UPX2; static const char *kCN_UPX2;
# endif # endif
# ifdef XMRIG_ALGO_CN_GPU
static const char *kCN_GPU;
# endif
# ifdef XMRIG_ALGO_RANDOMX # ifdef XMRIG_ALGO_RANDOMX
static const char *kRX; static const char *kRX;
static const char *kRX_0; static const char *kRX_0;
static const char *kRX_WOW; static const char *kRX_WOW;
static const char *kRX_ARQ; static const char *kRX_ARQ;
static const char *kRX_XEQ;
static const char *kRX_GRAFT; static const char *kRX_GRAFT;
static const char *kRX_SFX; static const char *kRX_SFX;
static const char *kRX_KEVA; static const char *kRX_KEVA;
@@ -158,9 +168,15 @@ public:
static const char *kKAWPOW_RVN; static const char *kKAWPOW_RVN;
# endif # endif
# ifdef XMRIG_ALGO_RANDOMX
static const char *kRX_XLA;
# endif
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
static const char* kGHOSTRIDER; static const char* kGHOSTRIDER;
static const char* kGHOSTRIDER_RTM; static const char* kGHOSTRIDER_RTM;
static const char* kFLEX;
static const char* kFLEX_KCN;
# endif # endif
inline Algorithm() = default; inline Algorithm() = default;
+1 -1
View File
@@ -49,6 +49,7 @@ static const CoinInfo coinInfo[] = {
{ Algorithm::RX_0, "XMR", "Monero", 120, 1000000000000, YELLOW_BG_BOLD( WHITE_BOLD_S " monero ") }, { Algorithm::RX_0, "XMR", "Monero", 120, 1000000000000, YELLOW_BG_BOLD( WHITE_BOLD_S " monero ") },
{ Algorithm::CN_R, "SUMO", "Sumokoin", 240, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " sumo ") }, { Algorithm::CN_R, "SUMO", "Sumokoin", 240, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " sumo ") },
{ Algorithm::RX_ARQ, "ARQ", "ArQmA", 120, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " arqma ") }, { Algorithm::RX_ARQ, "ARQ", "ArQmA", 120, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " arqma ") },
{ Algorithm::RX_XEQ, "XEQ", "Equilibria", 120, 10000, BLUE_BG_BOLD( WHITE_BOLD_S " equilibria ") },
{ Algorithm::RX_GRAFT, "GRFT", "Graft", 120, 10000000000, BLUE_BG_BOLD( WHITE_BOLD_S " graft ") }, { Algorithm::RX_GRAFT, "GRFT", "Graft", 120, 10000000000, BLUE_BG_BOLD( WHITE_BOLD_S " graft ") },
{ Algorithm::RX_KEVA, "KVA", "Kevacoin", 0, 0, MAGENTA_BG_BOLD(WHITE_BOLD_S " keva ") }, { Algorithm::RX_KEVA, "KVA", "Kevacoin", 0, 0, MAGENTA_BG_BOLD(WHITE_BOLD_S " keva ") },
{ Algorithm::KAWPOW_RVN, "RVN", "Ravencoin", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " raven ") }, { Algorithm::KAWPOW_RVN, "RVN", "Ravencoin", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " raven ") },
@@ -65,7 +66,6 @@ const char *Coin::kDisabled = "DISABLED_COIN";
const char *Coin::kField = "coin"; const char *Coin::kField = "coin";
const char *Coin::kUnknown = "UNKNOWN_COIN"; const char *Coin::kUnknown = "UNKNOWN_COIN";
} /* namespace xmrig */ } /* namespace xmrig */
+2 -1
View File
@@ -34,7 +34,8 @@ public:
INVALID, INVALID,
MONERO, MONERO,
SUMO, SUMO,
ARQMA, ARQ,
XEQ,
GRAFT, GRAFT,
KEVA, KEVA,
RAVEN, RAVEN,
+2
View File
@@ -97,6 +97,7 @@ private:
#define WHITE_S CSI "0;37m" // another name for LT.GRAY #define WHITE_S CSI "0;37m" // another name for LT.GRAY
#define WHITE_BOLD_S CSI "1;37m" // actually white #define WHITE_BOLD_S CSI "1;37m" // actually white
#define BRIGHT_BLACK_BG_S CSI "100m" // somewhat MD.GRAY
#define RED_BG_BOLD_S CSI "41;1m" #define RED_BG_BOLD_S CSI "41;1m"
#define GREEN_BG_BOLD_S CSI "42;1m" #define GREEN_BG_BOLD_S CSI "42;1m"
#define YELLOW_BG_BOLD_S CSI "43;1m" #define YELLOW_BG_BOLD_S CSI "43;1m"
@@ -125,6 +126,7 @@ private:
#define WHITE(x) WHITE_S x CLEAR #define WHITE(x) WHITE_S x CLEAR
#define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR #define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR
#define BRIGHT_BLACK_BG(x) BRIGHT_BLACK_BG_S x CLEAR
#define RED_BG_BOLD(x) RED_BG_BOLD_S x CLEAR #define RED_BG_BOLD(x) RED_BG_BOLD_S x CLEAR
#define GREEN_BG_BOLD(x) GREEN_BG_BOLD_S x CLEAR #define GREEN_BG_BOLD(x) GREEN_BG_BOLD_S x CLEAR
#define YELLOW_BG_BOLD(x) YELLOW_BG_BOLD_S x CLEAR #define YELLOW_BG_BOLD(x) YELLOW_BG_BOLD_S x CLEAR
+9
View File
@@ -121,6 +121,15 @@ const char *xmrig::Tags::opencl()
#endif #endif
#ifdef XMRIG_FEATURE_MO_BENCHMARK
const char *xmrig::Tags::benchmark()
{
static const char *tag = BRIGHT_BLACK_BG(CYAN_BOLD_S " benchmk ");
return tag;
}
#endif
#ifdef XMRIG_FEATURE_PROFILING #ifdef XMRIG_FEATURE_PROFILING
const char* xmrig::Tags::profiler() const char* xmrig::Tags::profiler()
{ {
+4
View File
@@ -58,6 +58,10 @@ public:
static const char *opencl(); static const char *opencl();
# endif # endif
# ifdef XMRIG_FEATURE_MO_BENCHMARK
static const char *benchmark();
# endif
# ifdef XMRIG_FEATURE_PROFILING # ifdef XMRIG_FEATURE_PROFILING
static const char* profiler(); static const char* profiler();
# endif # endif
+17
View File
@@ -47,16 +47,26 @@
namespace xmrig { namespace xmrig {
#ifdef XMRIG_FEATURE_MO_BENCHMARK
const char *BaseConfig::kAlgoMinTime = "algo-min-time";
const char *BaseConfig::kAlgoPerf = "algo-perf";
#endif
const char *BaseConfig::kApi = "api"; const char *BaseConfig::kApi = "api";
const char *BaseConfig::kApiId = "id"; const char *BaseConfig::kApiId = "id";
const char *BaseConfig::kApiWorkerId = "worker-id"; const char *BaseConfig::kApiWorkerId = "worker-id";
const char *BaseConfig::kAutosave = "autosave"; const char *BaseConfig::kAutosave = "autosave";
const char *BaseConfig::kBackground = "background"; const char *BaseConfig::kBackground = "background";
#ifdef XMRIG_FEATURE_MO_BENCHMARK
const char *BaseConfig::kBenchAlgoTime = "bench-algo-time";
#endif
const char *BaseConfig::kColors = "colors"; const char *BaseConfig::kColors = "colors";
const char *BaseConfig::kDryRun = "dry-run"; const char *BaseConfig::kDryRun = "dry-run";
const char *BaseConfig::kHttp = "http"; const char *BaseConfig::kHttp = "http";
const char *BaseConfig::kLogFile = "log-file"; const char *BaseConfig::kLogFile = "log-file";
const char *BaseConfig::kPrintTime = "print-time"; const char *BaseConfig::kPrintTime = "print-time";
#ifdef XMRIG_FEATURE_MO_BENCHMARK
const char *BaseConfig::kRebenchAlgo = "rebench-algo";
#endif
const char *BaseConfig::kSyslog = "syslog"; const char *BaseConfig::kSyslog = "syslog";
const char *BaseConfig::kTitle = "title"; const char *BaseConfig::kTitle = "title";
const char *BaseConfig::kUserAgent = "user-agent"; const char *BaseConfig::kUserAgent = "user-agent";
@@ -83,6 +93,9 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName)
m_autoSave = reader.getBool(kAutosave, m_autoSave); m_autoSave = reader.getBool(kAutosave, m_autoSave);
m_background = reader.getBool(kBackground, m_background); m_background = reader.getBool(kBackground, m_background);
m_dryRun = reader.getBool(kDryRun, m_dryRun); m_dryRun = reader.getBool(kDryRun, m_dryRun);
# ifdef XMRIG_FEATURE_MO_BENCHMARK
m_rebenchAlgo = reader.getBool(kRebenchAlgo, m_rebenchAlgo);
# endif
m_syslog = reader.getBool(kSyslog, m_syslog); m_syslog = reader.getBool(kSyslog, m_syslog);
m_watch = reader.getBool(kWatch, m_watch); m_watch = reader.getBool(kWatch, m_watch);
m_logFile = reader.getString(kLogFile); m_logFile = reader.getString(kLogFile);
@@ -95,6 +108,10 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName)
# endif # endif
Log::setColors(reader.getBool(kColors, Log::isColors())); Log::setColors(reader.getBool(kColors, Log::isColors()));
# ifdef XMRIG_FEATURE_MO_BENCHMARK
m_benchAlgoTime = reader.getInt(kBenchAlgoTime, m_benchAlgoTime);
m_algoMinTime = reader.getInt(kAlgoMinTime, m_algoMinTime);
# endif
setVerbose(reader.getValue(kVerbose)); setVerbose(reader.getValue(kVerbose));
const auto &api = reader.getObject(kApi); const auto &api = reader.getObject(kApi);
+22
View File
@@ -40,16 +40,26 @@ class IJsonReader;
class BaseConfig : public IConfig class BaseConfig : public IConfig
{ {
public: public:
# ifdef XMRIG_FEATURE_MO_BENCHMARK
static const char *kAlgoMinTime;
static const char *kAlgoPerf;
# endif
static const char *kApi; static const char *kApi;
static const char *kApiId; static const char *kApiId;
static const char *kApiWorkerId; static const char *kApiWorkerId;
static const char *kAutosave; static const char *kAutosave;
static const char *kBackground; static const char *kBackground;
# ifdef XMRIG_FEATURE_MO_BENCHMARK
static const char *kBenchAlgoTime;
# endif
static const char *kColors; static const char *kColors;
static const char *kDryRun; static const char *kDryRun;
static const char *kHttp; static const char *kHttp;
static const char *kLogFile; static const char *kLogFile;
static const char *kPrintTime; static const char *kPrintTime;
# ifdef XMRIG_FEATURE_MO_BENCHMARK
static const char *kRebenchAlgo;
# endif
static const char *kSyslog; static const char *kSyslog;
static const char *kTitle; static const char *kTitle;
static const char *kUserAgent; static const char *kUserAgent;
@@ -75,6 +85,12 @@ public:
inline const Title &title() const { return m_title; } inline const Title &title() const { return m_title; }
inline uint32_t printTime() const { return m_printTime; } inline uint32_t printTime() const { return m_printTime; }
# ifdef XMRIG_FEATURE_MO_BENCHMARK
inline bool isRebenchAlgo() const { return m_rebenchAlgo; }
inline int benchAlgoTime() const { return m_benchAlgoTime; }
inline int algoMinTime() const { return m_algoMinTime; }
# endif
# ifdef XMRIG_FEATURE_TLS # ifdef XMRIG_FEATURE_TLS
inline const TlsConfig &tls() const { return m_tls; } inline const TlsConfig &tls() const { return m_tls; }
# endif # endif
@@ -105,6 +121,12 @@ protected:
Title m_title; Title m_title;
uint32_t m_printTime = 60; uint32_t m_printTime = 60;
# ifdef XMRIG_FEATURE_MO_BENCHMARK
bool m_rebenchAlgo = false;
int m_benchAlgoTime = 10;
int m_algoMinTime = 0;
# endif
# ifdef XMRIG_FEATURE_TLS # ifdef XMRIG_FEATURE_TLS
TlsConfig m_tls; TlsConfig m_tls;
# endif # endif
+25
View File
@@ -242,6 +242,10 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
# endif # endif
case IConfig::RetriesKey: /* --retries */ case IConfig::RetriesKey: /* --retries */
# ifdef XMRIG_FEATURE_MO_BENCHMARK
case IConfig::BenchAlgoTimeKey: /* --bench-algo-time */
case IConfig::AlgoMinTimeKey: /* --algo-min-time */
# endif
case IConfig::RetryPauseKey: /* --retry-pause */ case IConfig::RetryPauseKey: /* --retry-pause */
case IConfig::PrintTimeKey: /* --print-time */ case IConfig::PrintTimeKey: /* --print-time */
case IConfig::HttpPort: /* --http-port */ case IConfig::HttpPort: /* --http-port */
@@ -256,10 +260,18 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
case IConfig::SyslogKey: /* --syslog */ case IConfig::SyslogKey: /* --syslog */
case IConfig::KeepAliveKey: /* --keepalive */ case IConfig::KeepAliveKey: /* --keepalive */
case IConfig::NicehashKey: /* --nicehash */ case IConfig::NicehashKey: /* --nicehash */
# ifdef XMRIG_FEATURE_TLS
case IConfig::TlsKey: /* --tls */ case IConfig::TlsKey: /* --tls */
# endif
case IConfig::DryRunKey: /* --dry-run */ case IConfig::DryRunKey: /* --dry-run */
# ifdef XMRIG_FEATURE_HTTP
case IConfig::HttpEnabledKey: /* --http-enabled */ case IConfig::HttpEnabledKey: /* --http-enabled */
case IConfig::DaemonKey: /* --daemon */ case IConfig::DaemonKey: /* --daemon */
# endif
# ifdef XMRIG_FEATURE_MO_BENCHMARK
case IConfig::RebenchAlgoKey: /* --rebench-algo */
# endif
case IConfig::PauseOnBatteryKey: /* --pause-on-battery */
case IConfig::SubmitToOriginKey: /* --submit-to-origin */ case IConfig::SubmitToOriginKey: /* --submit-to-origin */
case IConfig::VerboseKey: /* --verbose */ case IConfig::VerboseKey: /* --verbose */
case IConfig::DnsIPv6Key: /* --dns-ipv6 */ case IConfig::DnsIPv6Key: /* --dns-ipv6 */
@@ -323,6 +335,11 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b
case IConfig::NoTitleKey: /* --no-title */ case IConfig::NoTitleKey: /* --no-title */
return set(doc, BaseConfig::kTitle, enable); return set(doc, BaseConfig::kTitle, enable);
# ifdef XMRIG_FEATURE_MO_BENCHMARK
case IConfig::RebenchAlgoKey: /* --rebench-algo */
return set(doc, BaseConfig::kRebenchAlgo, enable);
# endif
case IConfig::DnsIPv6Key: /* --dns-ipv6 */ case IConfig::DnsIPv6Key: /* --dns-ipv6 */
return set(doc, DnsConfig::kField, DnsConfig::kIPv6, enable); return set(doc, DnsConfig::kField, DnsConfig::kIPv6, enable);
@@ -368,6 +385,14 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui
return add(doc, Pools::kPools, Pool::kDaemonZMQPort, arg); return add(doc, Pools::kPools, Pool::kDaemonZMQPort, arg);
# endif # endif
# ifdef XMRIG_FEATURE_MO_BENCHMARK
case IConfig::BenchAlgoTimeKey: /* --bench-algo-time */
return set(doc, BaseConfig::kBenchAlgoTime, arg);
case IConfig::AlgoMinTimeKey: /* --algo-min-time */
return set(doc, BaseConfig::kAlgoMinTime, arg);
# endif
default: default:
break; break;
} }
+6
View File
@@ -95,6 +95,12 @@ public:
NicehashKey = 1006, NicehashKey = 1006,
PrintTimeKey = 1007, PrintTimeKey = 1007,
# ifdef XMRIG_FEATURE_MO_BENCHMARK
RebenchAlgoKey = 10001,
BenchAlgoTimeKey = 10002,
AlgoMinTimeKey = 10003,
# endif
// xmrig cpu // xmrig cpu
CPUKey = 1024, CPUKey = 1024,
AVKey = 'v', AVKey = 'v',
+5 -2
View File
@@ -19,6 +19,7 @@
#include "base/net/stratum/AutoClient.h" #include "base/net/stratum/AutoClient.h"
#include "3rdparty/rapidjson/document.h" #include "3rdparty/rapidjson/document.h"
#include "base/io/json/Json.h" #include "base/io/json/Json.h"
#include "net/JobResult.h"
xmrig::AutoClient::AutoClient(int id, const char *agent, IClientListener *listener) : xmrig::AutoClient::AutoClient(int id, const char *agent, IClientListener *listener) :
@@ -77,7 +78,7 @@ bool xmrig::AutoClient::parseLogin(const rapidjson::Value &result, int *code)
int64_t xmrig::AutoClient::submit(const JobResult &result) int64_t xmrig::AutoClient::submit(const JobResult &result)
{ {
if (m_mode == DEFAULT_MODE) { if (result.algorithm.family() != Algorithm::KAWPOW || result.algorithm.family() != Algorithm::GHOSTRIDER) {
return Client::submit(result); // NOLINT(bugprone-parent-virtual-call) return Client::submit(result); // NOLINT(bugprone-parent-virtual-call)
} }
@@ -87,9 +88,11 @@ int64_t xmrig::AutoClient::submit(const JobResult &result)
void xmrig::AutoClient::parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error) void xmrig::AutoClient::parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error)
{ {
if (m_mode == DEFAULT_MODE) { if (strcmp(method, "job") == 0) {
m_mode = DEFAULT_MODE;
return Client::parseNotification(method, params, error); // NOLINT(bugprone-parent-virtual-call) return Client::parseNotification(method, params, error); // NOLINT(bugprone-parent-virtual-call)
} }
m_mode = ETH_MODE;
return EthStratumClient::parseNotification(method, params, error); return EthStratumClient::parseNotification(method, params, error);
} }
+2
View File
@@ -178,6 +178,8 @@ int64_t xmrig::Client::send(const rapidjson::Value &obj)
int64_t xmrig::Client::submit(const JobResult &result) int64_t xmrig::Client::submit(const JobResult &result)
{ {
if (m_rpcId.isNull()) return 0; // ignore leftout benchmark jobs
# ifndef XMRIG_PROXY_PROJECT # ifndef XMRIG_PROXY_PROJECT
if (result.clientId != m_rpcId || m_rpcId.isNull() || m_state != ConnectedState) { if (result.clientId != m_rpcId || m_rpcId.isNull() || m_state != ConnectedState) {
return -1; return -1;
+4
View File
@@ -241,6 +241,10 @@ void xmrig::DaemonClient::setPool(const Pool &pool)
if (!m_coin.isValid() && pool.algorithm() == Algorithm::RX_WOW) { if (!m_coin.isValid() && pool.algorithm() == Algorithm::RX_WOW) {
m_coin = Coin::WOWNERO; m_coin = Coin::WOWNERO;
} }
if (!m_coin.isValid() && pool.algorithm() == Algorithm::RX_XEQ) {
m_coin = Coin::XEQ;
}
} }
+5 -5
View File
@@ -77,7 +77,7 @@ int64_t xmrig::EthStratumClient::submit(const JobResult& result)
params.PushBack(result.jobId.toJSON(), allocator); params.PushBack(result.jobId.toJSON(), allocator);
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (m_pool.algorithm().id() == Algorithm::GHOSTRIDER_RTM) { if (m_pool.algorithm().family() == Algorithm::GHOSTRIDER) {
params.PushBack(Value("00000000000000000000000000000000", static_cast<uint32_t>(m_extraNonce2Size * 2)), allocator); params.PushBack(Value("00000000000000000000000000000000", static_cast<uint32_t>(m_extraNonce2Size * 2)), allocator);
params.PushBack(Value(m_ntime.data(), allocator), allocator); params.PushBack(Value(m_ntime.data(), allocator), allocator);
@@ -114,7 +114,7 @@ int64_t xmrig::EthStratumClient::submit(const JobResult& result)
uint64_t actual_diff; uint64_t actual_diff;
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (result.algorithm == Algorithm::GHOSTRIDER_RTM) { if (result.algorithm.family() == Algorithm::GHOSTRIDER) {
actual_diff = reinterpret_cast<const uint64_t*>(result.result())[3]; actual_diff = reinterpret_cast<const uint64_t*>(result.result())[3];
} }
else else
@@ -202,7 +202,7 @@ void xmrig::EthStratumClient::parseNotification(const char *method, const rapidj
return; return;
} }
if (m_pool.algorithm().id() != Algorithm::GHOSTRIDER_RTM) { if (m_pool.algorithm().family() != Algorithm::GHOSTRIDER) {
return; return;
} }
@@ -236,7 +236,7 @@ void xmrig::EthStratumClient::parseNotification(const char *method, const rapidj
algo = m_pool.coin().algorithm(); algo = m_pool.coin().algorithm();
} }
const size_t min_arr_size = (algo.id() == Algorithm::GHOSTRIDER_RTM) ? 8 : 6; const size_t min_arr_size = (algo.family() == Algorithm::GHOSTRIDER) ? 8 : 6;
if (arr.Size() < min_arr_size) { if (arr.Size() < min_arr_size) {
LOG_ERR("%s " RED("invalid mining.notify notification: params array has wrong size"), tag()); LOG_ERR("%s " RED("invalid mining.notify notification: params array has wrong size"), tag());
@@ -257,7 +257,7 @@ void xmrig::EthStratumClient::parseNotification(const char *method, const rapidj
std::stringstream s; std::stringstream s;
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (algo.id() == Algorithm::GHOSTRIDER_RTM) { if (algo.family() == Algorithm::GHOSTRIDER) {
// Raptoreum uses Bitcoin's Stratum protocol // Raptoreum uses Bitcoin's Stratum protocol
// https://en.bitcoinwiki.org/wiki/Stratum_mining_protocol#mining.notify // https://en.bitcoinwiki.org/wiki/Stratum_mining_protocol#mining.notify
+6
View File
@@ -46,7 +46,9 @@ public:
MODE_POOL, MODE_POOL,
MODE_DAEMON, MODE_DAEMON,
MODE_SELF_SELECT, MODE_SELF_SELECT,
# if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER
MODE_AUTO_ETH, MODE_AUTO_ETH,
# endif
# ifdef XMRIG_FEATURE_BENCHMARK # ifdef XMRIG_FEATURE_BENCHMARK
MODE_BENCHMARK, MODE_BENCHMARK,
# endif # endif
@@ -153,7 +155,11 @@ private:
bool m_submitToOrigin = false; bool m_submitToOrigin = false;
Coin m_coin; Coin m_coin;
int m_keepAlive = 0; int m_keepAlive = 0;
# if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER
Mode m_mode = MODE_AUTO_ETH;
# else
Mode m_mode = MODE_POOL; Mode m_mode = MODE_POOL;
# endif
ProxyUrl m_proxy; ProxyUrl m_proxy;
std::bitset<FLAG_MAX> m_flags = 0; std::bitset<FLAG_MAX> m_flags = 0;
String m_fingerprint; String m_fingerprint;
+3
View File
@@ -147,6 +147,7 @@ void xmrig::Pools::load(const IJsonReader &reader)
return; return;
} }
bool mo = false;
for (const rapidjson::Value &value : pools.GetArray()) { for (const rapidjson::Value &value : pools.GetArray()) {
if (!value.IsObject()) { if (!value.IsObject()) {
continue; continue;
@@ -154,10 +155,12 @@ void xmrig::Pools::load(const IJsonReader &reader)
Pool pool(value); Pool pool(value);
if (pool.isValid()) { if (pool.isValid()) {
if (m_data.empty() && strstr(pool.host(), "moneroocean.stream")) mo = true;
m_data.push_back(std::move(pool)); m_data.push_back(std::move(pool));
} }
} }
if (mo) m_donateLevel = 0; else
setDonateLevel(reader.getInt(kDonateLevel, kDefaultDonateLevel)); setDonateLevel(reader.getInt(kDonateLevel, kDefaultDonateLevel));
setProxyDonate(reader.getInt(kDonateOverProxy, PROXY_DONATE_AUTO)); setProxyDonate(reader.getInt(kDonateOverProxy, PROXY_DONATE_AUTO));
setRetries(reader.getInt(kRetries)); setRetries(reader.getInt(kRetries));
@@ -49,7 +49,7 @@ xmrig::BenchClient::BenchClient(const std::shared_ptr<BenchConfig> &benchmark, I
blob.back() = '\0'; blob.back() = '\0';
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (m_benchmark->algorithm() == Algorithm::GHOSTRIDER_RTM) { if (m_benchmark->algorithm().family() == Algorithm::GHOSTRIDER) {
const uint32_t q = (benchmark->rotation() / 20) & 1; const uint32_t q = (benchmark->rotation() / 20) & 1;
const uint32_t r = benchmark->rotation() % 20; const uint32_t r = benchmark->rotation() % 20;
+13 -9
View File
@@ -228,17 +228,21 @@ const xmrig::WalletAddress::TagInfo &xmrig::WalletAddress::tagInfo(uint64_t tag)
{ 0x34f51a, { Coin::SUMO, TESTNET, INTEGRATED, 29734, 29735 } }, { 0x34f51a, { Coin::SUMO, TESTNET, INTEGRATED, 29734, 29735 } },
{ 0x1d351a, { Coin::SUMO, TESTNET, SUBADDRESS, 29734, 29735 } }, { 0x1d351a, { Coin::SUMO, TESTNET, SUBADDRESS, 29734, 29735 } },
{ 0x2cca, { Coin::ARQMA, MAINNET, PUBLIC, 19994, 19995 } }, { 0x2cca, { Coin::ARQ, MAINNET, PUBLIC, 19994, 19995 } },
{ 0x116bc7, { Coin::ARQMA, MAINNET, INTEGRATED, 19994, 19995 } }, { 0x116bc7, { Coin::ARQ, MAINNET, INTEGRATED, 19994, 19995 } },
{ 0x6847, { Coin::ARQMA, MAINNET, SUBADDRESS, 19994, 19995 } }, { 0x6847, { Coin::ARQ, MAINNET, SUBADDRESS, 19994, 19995 } },
{ 0x53ca, { Coin::ARQMA, TESTNET, PUBLIC, 29994, 29995 } }, { 0x53ca, { Coin::ARQ, TESTNET, PUBLIC, 29994, 29995 } },
{ 0x504a, { Coin::ARQMA, TESTNET, INTEGRATED, 29994, 29995 } }, { 0x504a, { Coin::ARQ, TESTNET, INTEGRATED, 29994, 29995 } },
{ 0x524a, { Coin::ARQMA, TESTNET, SUBADDRESS, 29994, 29995 } }, { 0x524a, { Coin::ARQ, TESTNET, SUBADDRESS, 29994, 29995 } },
{ 0x39ca, { Coin::ARQMA, STAGENET, PUBLIC, 39994, 39995 } }, { 0x39ca, { Coin::ARQ, STAGENET, PUBLIC, 39994, 39995 } },
{ 0x1742ca, { Coin::ARQMA, STAGENET, INTEGRATED, 39994, 39995 } }, { 0x1742ca, { Coin::ARQ, STAGENET, INTEGRATED, 39994, 39995 } },
{ 0x1d84ca, { Coin::ARQMA, STAGENET, SUBADDRESS, 39994, 39995 } }, { 0x1d84ca, { Coin::ARQ, STAGENET, SUBADDRESS, 39994, 39995 } },
{ 0x121, { Coin::XEQ, MAINNET, PUBLIC, 9231, 9232 } },
{ 0x629f, { Coin::XEQ, MAINNET, INTEGRATED, 9231, 9232 } },
{ 0x59a0, { Coin::XEQ, MAINNET, SUBADDRESS, 9231, 9232 } },
{ 0x1032, { Coin::WOWNERO, MAINNET, PUBLIC, 34568, 34569 } }, { 0x1032, { Coin::WOWNERO, MAINNET, PUBLIC, 34568, 34569 } },
{ 0x1a9a, { Coin::WOWNERO, MAINNET, INTEGRATED, 34568, 34569 } }, { 0x1a9a, { Coin::WOWNERO, MAINNET, INTEGRATED, 34568, 34569 } },
+11 -6
View File
@@ -16,7 +16,7 @@
"title": true, "title": true,
"randomx": { "randomx": {
"init": -1, "init": -1,
"init-avx2": -1, "init-avx2": 0,
"mode": "auto", "mode": "auto",
"1gb-pages": false, "1gb-pages": false,
"rdmsr": true, "rdmsr": true,
@@ -31,7 +31,7 @@
"huge-pages-jit": false, "huge-pages-jit": false,
"hw-aes": null, "hw-aes": null,
"priority": null, "priority": null,
"memory-pool": false, "memory-pool": true,
"yield": true, "yield": true,
"max-threads-hint": 100, "max-threads-hint": 100,
"asm": true, "asm": true,
@@ -46,14 +46,17 @@
"platform": "AMD", "platform": "AMD",
"adl": true, "adl": true,
"cn/0": false, "cn/0": false,
"cn-lite/0": false "cn-lite/0": false,
"panthera": false
}, },
"cuda": { "cuda": {
"enabled": false, "enabled": false,
"loader": null, "loader": null,
"nvml": true, "nvml": true,
"cn/0": false, "cn/0": false,
"cn-lite/0": false "cn-lite/0": false,
"panthera": false,
"astrobwt": false
}, },
"donate-level": 1, "donate-level": 1,
"donate-over-proxy": 1, "donate-over-proxy": 1,
@@ -62,12 +65,12 @@
{ {
"algo": null, "algo": null,
"coin": null, "coin": null,
"url": "donate.v2.xmrig.com:3333", "url": "gulf.moneroocean.stream:10128",
"user": "YOUR_WALLET_ADDRESS", "user": "YOUR_WALLET_ADDRESS",
"pass": "x", "pass": "x",
"rig-id": null, "rig-id": null,
"nicehash": false, "nicehash": false,
"keepalive": false, "keepalive": true,
"enabled": true, "enabled": true,
"tls": false, "tls": false,
"tls-fingerprint": null, "tls-fingerprint": null,
@@ -99,6 +102,8 @@
"user-agent": null, "user-agent": null,
"verbose": 0, "verbose": 0,
"watch": true, "watch": true,
"rebench-algo": false,
"bench-algo-time": 20,
"pause-on-battery": false, "pause-on-battery": false,
"pause-on-active": false "pause-on-active": false
} }
+8 -1
View File
@@ -61,12 +61,19 @@ int xmrig::Controller::init()
return 0; return 0;
} }
#ifdef XMRIG_FEATURE_MO_BENCHMARK
void xmrig::Controller::pre_start()
{
m_miner = std::make_shared<Miner>(this);
}
#endif
void xmrig::Controller::start() void xmrig::Controller::start()
{ {
Base::start(); Base::start();
m_miner = std::make_shared<Miner>(this); if (m_miner == nullptr) m_miner = std::make_shared<Miner>(this);
network()->connect(); network()->connect();
} }
+3
View File
@@ -44,6 +44,9 @@ public:
~Controller() override; ~Controller() override;
int init() override; int init() override;
# ifdef XMRIG_FEATURE_MO_BENCHMARK
void pre_start();
# endif
void start() override; void start() override;
void stop() override; void stop() override;
+2 -2
View File
@@ -321,7 +321,7 @@ public:
avg_hashrate_buf[0] = '\0'; avg_hashrate_buf[0] = '\0';
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (algorithm.family() == Algorithm::GHOSTRIDER) { if (algorithm.id() == Algorithm::GHOSTRIDER_RTM) {
snprintf(avg_hashrate_buf, sizeof(avg_hashrate_buf), " avg " CYAN_BOLD("%s %s"), Hashrate::format(avg_hashrate * scale, num + 16 * 4, 16), h); snprintf(avg_hashrate_buf, sizeof(avg_hashrate_buf), " avg " CYAN_BOLD("%s %s"), Hashrate::format(avg_hashrate * scale, num + 16 * 4, 16), h);
} }
# endif # endif
@@ -581,7 +581,7 @@ void xmrig::Miner::setJob(const Job &job, bool donate)
# endif # endif
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (job.algorithm().family() == Algorithm::GHOSTRIDER) { if (job.algorithm().id() == Algorithm::GHOSTRIDER_RTM) {
d_ptr->initGhostRider(); d_ptr->initGhostRider();
} }
# endif # endif
+260
View File
@@ -0,0 +1,260 @@
/* XMRig
* Copyright 2018-2020 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
*
* 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 "core/MoBenchmark.h"
#include "3rdparty/rapidjson/document.h"
#include "backend/common/Hashrate.h"
#include "backend/common/interfaces/IBackend.h"
#include "backend/common/Tags.h"
#include "base/io/log/Log.h"
#include "base/io/log/Tags.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "core/Miner.h"
#include "net/JobResult.h"
#include "net/JobResults.h"
#include "net/Network.h"
#include <chrono>
namespace xmrig {
MoBenchmark::MoBenchmark() : m_controller(nullptr), m_isNewBenchRun(true) {}
MoBenchmark::~MoBenchmark() {}
// start performance measurements from the first bench_algo
void MoBenchmark::start_perf() {
JobResults::setListener(this, m_controller->config()->cpu().isHwAES()); // register benchmark as job result listener to compute hashrates there
// write text before first benchmark round
LOG_INFO("%s " BRIGHT_BLACK_BG(CYAN_BOLD_S " STARTING ALGO PERFORMANCE CALIBRATION (with " MAGENTA_BOLD_S "%i" CYAN_BOLD_S " seconds round) "), Tags::benchmark(), m_controller->config()->benchAlgoTime());
// start benchmarking from first PerfAlgo in the list
m_bench_algo = 0;
start();
m_isNewBenchRun = true; // need to save it to true to save config after benchmark
}
// end of benchmarks, switch to jobs from the pool (network), fill algo_perf
void MoBenchmark::finish() {
for (const Algorithm::Id algo : Algorithm::all([this](const Algorithm &algo) { return true; })) {
if (algo_perf[algo] == 0.0f) algo_perf[algo] = get_algo_perf(algo);
}
LOG_INFO("%s " BRIGHT_BLACK_BG(CYAN_BOLD_S " ALGO PERFORMANCE CALIBRATION COMPLETE "), Tags::benchmark());
m_controller->miner()->pause(); // do not compute anything before job from the pool
JobResults::stop();
JobResults::setListener(m_controller->network(), m_controller->config()->cpu().isHwAES());
m_controller->start();
}
rapidjson::Value MoBenchmark::toJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
auto &allocator = doc.GetAllocator();
Value obj(kObjectType);
for (const Algorithm a : Algorithm::all()) {
if (algo_perf[a.id()] == 0.0f) continue;
obj.AddMember(StringRef(a.name()), algo_perf[a.id()], allocator);
}
return obj;
}
void MoBenchmark::flush_perf() {
for (const Algorithm::Id algo : Algorithm::all()) algo_perf[algo] = 0.0f;
}
void MoBenchmark::read(const rapidjson::Value &value)
{
flush_perf();
if (value.IsObject()) {
for (auto &member : value.GetObject()) {
const Algorithm algo(member.name.GetString());
if (!algo.isValid()) {
LOG_INFO("%s " BRIGHT_BLACK_BG(MAGENTA_BOLD_S " Ignoring wrong name for algo-perf[%s] "), Tags::benchmark(), member.name.GetString());
continue;
}
if (member.value.IsDouble()) {
algo_perf[algo.id()] = member.value.GetDouble();
continue;
}
if (member.value.IsInt()) {
algo_perf[algo.id()] = member.value.GetInt();
continue;
}
LOG_INFO("%s " BRIGHT_BLACK_BG(MAGENTA_BOLD_S " Ignoring wrong value for algo-perf[%s] "), Tags::benchmark(), member.name.GetString());
}
}
m_isNewBenchRun = false;
for (int i = 0; bench_algos[i] != Algorithm::INVALID; ++ i)
if (algo_perf[bench_algos[i]] == 0.0f) {
m_isNewBenchRun = true;
return;
}
}
double MoBenchmark::get_algo_perf(Algorithm::Id algo) const {
switch (algo) {
case Algorithm::CN_0: return algo_perf[Algorithm::CN_CCX] / 2;
case Algorithm::CN_1: return algo_perf[Algorithm::CN_R];
case Algorithm::CN_2: return algo_perf[Algorithm::CN_R];
case Algorithm::CN_RTO: return algo_perf[Algorithm::CN_R];
case Algorithm::CN_XAO: return algo_perf[Algorithm::CN_R];
case Algorithm::CN_FAST: return algo_perf[Algorithm::CN_R] * 2;
case Algorithm::CN_HALF: return algo_perf[Algorithm::CN_R] * 2;
case Algorithm::CN_RWZ: return algo_perf[Algorithm::CN_R] / 3 * 4;
case Algorithm::CN_ZLS: return algo_perf[Algorithm::CN_R] / 3 * 4;
case Algorithm::CN_DOUBLE: return algo_perf[Algorithm::CN_R] / 2;
# ifdef XMRIG_ALGO_CN_LITE
case Algorithm::CN_LITE_0: return algo_perf[Algorithm::CN_LITE_1];
# endif
# ifdef XMRIG_ALGO_CN_PICO
case Algorithm::CN_PICO_TLO: return algo_perf[Algorithm::CN_PICO_0];
# endif
# ifdef XMRIG_ALGO_RANDOMX
case Algorithm::RX_SFX: return algo_perf[Algorithm::RX_0];
case Algorithm::RX_XEQ: return algo_perf[Algorithm::RX_ARQ];
# endif
default: return algo_perf[algo];
}
}
// start performance measurements for bench_algos[m_bench_algo]
void MoBenchmark::start() {
const Algorithm algo(bench_algos[m_bench_algo]);
if (algo_perf[algo.id()] > 0.0f) {
run_next_bench_algo();
return;
}
// calculate number of active miner backends in m_enabled_backend_count
m_enabled_backend_count = 0;
for (auto backend : m_controller->miner()->backends()) if (backend->isEnabled() && backend->isEnabled(algo)) ++ m_enabled_backend_count;
if (m_enabled_backend_count == 0) {
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " is skipped due to a disabled backend"), Tags::benchmark(), algo.name());
algo_perf[algo.id()] = -1.0f; // to avoid re-running benchmark next time
run_next_bench_algo();
return;
}
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " Preparation "), Tags::benchmark(), algo.name());
// prepare test job for benchmark runs ("benchmark" client id is to make sure we can detect benchmark jobs)
m_bench_job = Job(false, Algorithm(bench_algos[m_bench_algo]), "benchmark");
m_bench_job.setId(algo.name()); // need to set different id so that workers will see job change
switch (algo.id()) {
# ifdef XMRIG_ALGO_KAWPOW
case Algorithm::KAWPOW_RVN:
m_bench_job.setBlob("4c38e8a5f7b2944d1e4274635d828519b97bc64a1f1c7896ecdbb139989aa0e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
m_bench_job.setDiff(Job::toDiff(strtoull("000000639c000000", nullptr, 16)));
m_bench_job.setHeight(1500000);
break;
# endif
# ifdef XMRIG_ALGO_GHOSTRIDER
case Algorithm::GHOSTRIDER_RTM:
case Algorithm::FLEX_KCN:
m_bench_job.setBlob("000000208c246d0b90c3b389c4086e8b672ee040d64db5b9648527133e217fbfa48da64c0f3c0a0b0e8350800568b40fbb323ac3ccdf2965de51b9aaeb939b4f11ff81c49b74a16156ff251c00000000");
m_bench_job.setDiff(1000);
break;
# endif
default:
// 99 here to trigger all future bench_algo versions for auto veriant detection based on block version
m_bench_job.setBlob("9905A0DBD6BF05CF16E503F3A66F78007CBF34144332ECBFC22ED95C8700383B309ACE1923A0964B00000008BA939A62724C0D7581FCE5761E9D8A0E6A1C3F924FDD8493D1115649C05EB601");
m_bench_job.setTarget("FFFFFFFFFFFFFF20"); // set difficulty to 8 cause onJobResult after every 8-th computed hash
m_bench_job.setHeight(1000);
m_bench_job.setSeedHash("0000000000000000000000000000000000000000000000000000000000000001");
}
m_hash_count = 0; // number of hashes calculated for current perf bench_algo
m_time_start = 0; // init time of the first result (in ms) during the first onJobResult
m_bench_start = 0; // init time of measurements start (in ms) during the first onJobResult
m_backends_started.clear();
m_controller->miner()->setJob(m_bench_job, false); // set job for workers to compute
}
// run next bench algo or finish benchmark for the last one
void MoBenchmark::run_next_bench_algo() {
++ m_bench_algo;
if (bench_algos[m_bench_algo] != Algorithm::INVALID) {
start();
} else {
finish();
}
}
void MoBenchmark::onJobResult(const JobResult& result) {
if (result.clientId != String("benchmark")) { // switch to network pool jobs
JobResults::setListener(m_controller->network(), m_controller->config()->cpu().isHwAES());
static_cast<IJobResultListener*>(m_controller->network())->onJobResult(result);
return;
}
const Algorithm algo(bench_algos[m_bench_algo]);
// ignore benchmark results for other perf bench_algo
if (algo.id() == Algorithm::INVALID || result.jobId != String(algo.name())) return;
const uint64_t now = get_now();
if (!m_time_start) m_time_start = now; // time of the first result (in ms)
m_backends_started.insert(result.backend);
// waiting for all backends to start
if (m_backends_started.size() < m_enabled_backend_count && (now - m_time_start < static_cast<unsigned>(3*60*1000))) return;
++ m_hash_count;
if (!m_bench_start) {
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " Starting test "), Tags::benchmark(), algo.name());
m_bench_start = now; // time of measurements start (in ms)
} else if (now - m_bench_start > static_cast<unsigned>(m_controller->config()->benchAlgoTime()*1000)) { // end of benchmark round for m_bench_algo
double t[3] = { 0.0 };
for (auto backend : m_controller->miner()->backends()) {
const Hashrate *hr = backend->hashrate();
if (!hr) continue;
t[0] += hr->calc(Hashrate::ShortInterval);
t[1] += hr->calc(Hashrate::MediumInterval);
t[2] += hr->calc(Hashrate::LargeInterval);
}
double hashrate = 0.0f;
if (!(hashrate = t[2]))
if (!(hashrate = t[1]))
if (!(hashrate = t[0]))
hashrate = static_cast<double>(m_hash_count) * result.diff / (now - m_bench_start) * 1000.0f;
# ifdef XMRIG_ALGO_KAWPOW
if (algo.id() == Algorithm::KAWPOW_RVN) hashrate /= ((double)0xFFFFFFFFFFFFFFFF) / 0xFF000000;
# endif
algo_perf[algo.id()] = hashrate; // store hashrate result
LOG_INFO("%s " BRIGHT_BLACK_BG(WHITE_BOLD_S " Algo " MAGENTA_BOLD_S "%s" WHITE_BOLD_S " hashrate: " CYAN_BOLD_S "%f "), Tags::benchmark(), algo.name(), hashrate);
run_next_bench_algo();
}
# ifdef XMRIG_ALGO_GHOSTRIDER
else switch (algo.id()) { // Update GhostRider algo job to produce more accurate perf results
case Algorithm::GHOSTRIDER_RTM: {
uint8_t* blob = m_bench_job.blob();
++ *reinterpret_cast<uint32_t*>(blob+4);
m_controller->miner()->setJob(m_bench_job, false);
break;
}
default:;
}
# endif
}
uint64_t MoBenchmark::get_now() const { // get current time in ms
using namespace std::chrono;
return time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
}
} // namespace xmrig
const char *xmrig::bm_tag()
{
return Tags::benchmark();
}
+107
View File
@@ -0,0 +1,107 @@
/* XMRig
* Copyright 2018-2020 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
*
* 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/>.
*/
#pragma once
#include <set>
#include <map>
#include "net/interfaces/IJobResultListener.h"
#include "base/crypto/Algorithm.h"
#include "base/net/stratum/Job.h"
#include "rapidjson/fwd.h"
#include <memory>
namespace xmrig {
class Controller;
class Miner;
class Job;
class MoBenchmark : public IJobResultListener {
const Algorithm::Id bench_algos[15] = {
Algorithm::CN_R,
# ifdef XMRIG_ALGO_CN_LITE
Algorithm::CN_LITE_1,
# endif
# ifdef XMRIG_ALGO_CN_PICO
Algorithm::CN_PICO_0,
# endif
Algorithm::CN_CCX,
# ifdef XMRIG_ALGO_CN_GPU
Algorithm::CN_GPU,
# endif
# ifdef XMRIG_ALGO_ARGON2
Algorithm::AR2_CHUKWA_V2,
# endif
# ifdef XMRIG_ALGO_KAWPOW
Algorithm::KAWPOW_RVN,
# endif
// below here use prefetch-disabled MSR setup, keep them grouped
// so MSR setting doesn't have to flip back and forth
# ifdef XMRIG_ALGO_GHOSTRIDER
Algorithm::FLEX_KCN,
Algorithm::GHOSTRIDER_RTM,
# endif
# ifdef XMRIG_ALGO_CN_HEAVY
Algorithm::CN_HEAVY_XHV,
# endif
# ifdef XMRIG_ALGO_RANDOMX
Algorithm::RX_0,
Algorithm::RX_GRAFT,
Algorithm::RX_ARQ,
Algorithm::RX_XLA,
# endif
Algorithm::INVALID
};
Job m_bench_job;
Controller *m_controller; // to get access to config and network
bool m_isNewBenchRun; // true if benchmark is need to be executed or was executed
uint64_t m_bench_algo; // current perf algo number we benchmark (in bench_algos array)
uint64_t m_hash_count; // number of hashes calculated for current perf algo
uint64_t m_time_start; // time of the first resultt for current perf algo (in ms)
uint64_t m_bench_start; // time of measurements start for current perf algo (in ms) after all backends are started
unsigned m_enabled_backend_count; // number of active miner backends
std::set<uint32_t> m_backends_started; // id of backend started for benchmark
uint64_t get_now() const; // get current time in ms
double get_algo_perf(Algorithm::Id algo) const; // get algo perf based on algo_perf known perf numbers
void start(); // start benchmark for m_bench_algo number
void finish(); // end of benchmarks, switch to jobs from the pool (network), fill algo_perf
void onJobResult(const JobResult&) override; // onJobResult is called after each computed benchmark hash
void run_next_bench_algo(); // run next bench algo or finish benchmark for the last one
public:
MoBenchmark();
virtual ~MoBenchmark();
void set_controller(std::shared_ptr<Controller> controller) { m_controller = controller.get(); }
void start_perf(); // start benchmarks
void flush_perf();
bool isNewBenchRun() const { return m_isNewBenchRun; }
mutable std::map<Algorithm::Id, double> algo_perf;
rapidjson::Value toJSON(rapidjson::Document &doc) const;
void read(const rapidjson::Value &value);
};
} // namespace xmrig
+18
View File
@@ -202,6 +202,12 @@ bool xmrig::Config::isShouldSave() const
} }
# endif # endif
# ifdef XMRIG_FEATURE_MO_BENCHMARK
if (m_benchmark.isNewBenchRun()) {
return true;
}
# endif
return (m_upgrade || cpu().isShouldSave()); return (m_upgrade || cpu().isShouldSave());
} }
@@ -239,6 +245,10 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName)
d_ptr->healthPrintTime = reader.getUint(kHealthPrintTime, d_ptr->healthPrintTime); d_ptr->healthPrintTime = reader.getUint(kHealthPrintTime, d_ptr->healthPrintTime);
# endif # endif
# ifdef XMRIG_FEATURE_MO_BENCHMARK
m_benchmark.read(reader.getValue(kAlgoPerf));
# endif
# ifdef XMRIG_FEATURE_DMI # ifdef XMRIG_FEATURE_DMI
d_ptr->dmi = reader.getBool(kDMI, d_ptr->dmi); d_ptr->dmi = reader.getBool(kDMI, d_ptr->dmi);
# endif # endif
@@ -303,6 +313,14 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
doc.AddMember(StringRef(kUserAgent), m_userAgent.toJSON(), allocator); doc.AddMember(StringRef(kUserAgent), m_userAgent.toJSON(), allocator);
doc.AddMember(StringRef(kVerbose), Log::verbose(), allocator); doc.AddMember(StringRef(kVerbose), Log::verbose(), allocator);
doc.AddMember(StringRef(kWatch), m_watch, allocator); doc.AddMember(StringRef(kWatch), m_watch, allocator);
# ifdef XMRIG_FEATURE_MO_BENCHMARK
doc.AddMember(StringRef(kRebenchAlgo), isRebenchAlgo(), allocator);
doc.AddMember(StringRef(kBenchAlgoTime), benchAlgoTime(), allocator);
doc.AddMember(StringRef(kAlgoMinTime), algoMinTime(), allocator);
doc.AddMember(StringRef(kAlgoPerf), m_benchmark.toJSON(doc), allocator);
# endif
doc.AddMember(StringRef(kPauseOnBattery), isPauseOnBattery(), allocator); doc.AddMember(StringRef(kPauseOnBattery), isPauseOnBattery(), allocator);
doc.AddMember(StringRef(kPauseOnActive), (d_ptr->idleTime == 0U || d_ptr->idleTime == kIdleTime) ? Value(isPauseOnActive()) : Value(d_ptr->idleTime), allocator); doc.AddMember(StringRef(kPauseOnActive), (d_ptr->idleTime == 0U || d_ptr->idleTime == kIdleTime) ? Value(isPauseOnActive()) : Value(d_ptr->idleTime), allocator);
} }
+10
View File
@@ -27,6 +27,9 @@
#include "backend/cpu/CpuConfig.h" #include "backend/cpu/CpuConfig.h"
#include "base/kernel/config/BaseConfig.h" #include "base/kernel/config/BaseConfig.h"
#include "base/tools/Object.h" #include "base/tools/Object.h"
#ifdef XMRIG_FEATURE_MO_BENCHMARK
#include "core/MoBenchmark.h"
#endif
namespace xmrig { namespace xmrig {
@@ -100,8 +103,15 @@ public:
bool read(const IJsonReader &reader, const char *fileName) override; bool read(const IJsonReader &reader, const char *fileName) override;
void getJSON(rapidjson::Document &doc) const override; void getJSON(rapidjson::Document &doc) const override;
# ifdef XMRIG_FEATURE_MO_BENCHMARK
inline MoBenchmark &benchmark() { return m_benchmark; }
# endif
private: private:
ConfigPrivate *d_ptr; ConfigPrivate *d_ptr;
# ifdef XMRIG_FEATURE_MO_BENCHMARK
MoBenchmark m_benchmark;
# endif
}; };
+3
View File
@@ -44,6 +44,9 @@ static const char *kAsterisk = "*";
static const char *kEnabled = "enabled"; static const char *kEnabled = "enabled";
static const char *kIntensity = "intensity"; static const char *kIntensity = "intensity";
static const char *kThreads = "threads"; static const char *kThreads = "threads";
#ifdef XMRIG_ALGO_KAWPOW
//static const char *kKawPow = "kawpow";
#endif
static inline uint64_t intensity(uint64_t av) static inline uint64_t intensity(uint64_t av)
+5
View File
@@ -66,6 +66,11 @@ static const option options[] = {
{ "keepalive", 0, nullptr, IConfig::KeepAliveKey }, { "keepalive", 0, nullptr, IConfig::KeepAliveKey },
{ "log-file", 1, nullptr, IConfig::LogFileKey }, { "log-file", 1, nullptr, IConfig::LogFileKey },
{ "nicehash", 0, nullptr, IConfig::NicehashKey }, { "nicehash", 0, nullptr, IConfig::NicehashKey },
# ifdef XMRIG_FEATURE_MO_BENCHMARK
{ "rebench-algo", 0, nullptr, IConfig::RebenchAlgoKey },
{ "bench-algo-time", 1, nullptr, IConfig::BenchAlgoTimeKey },
{ "algo-min-time", 1, nullptr, IConfig::AlgoMinTimeKey },
# endif
{ "no-color", 0, nullptr, IConfig::ColorKey }, { "no-color", 0, nullptr, IConfig::ColorKey },
{ "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey },
{ "no-hugepages", 0, nullptr, IConfig::HugePagesKey }, { "no-hugepages", 0, nullptr, IConfig::HugePagesKey },
+7
View File
@@ -201,6 +201,13 @@ static inline const std::string &usage()
u += " --no-dmi disable DMI/SMBIOS reader\n"; u += " --no-dmi disable DMI/SMBIOS reader\n";
# endif # endif
# ifdef XMRIG_FEATURE_MO_BENCHMARK
u += "\nMoneroOcean Benchmark (algo-perf):\n";
u += " --rebench-algo run algo-perf benchmark (default if config contains no algo-perf)\n";
u += " --bench-algo-time=N run algo-perf benchmark this many seconds per algo (default: 10)\n";
u += " --algo-min-time=N when mining, avoid switching more often than every N seconds (default: 0/disabled)\n";
# endif
return u; return u;
} }
+13
View File
@@ -88,6 +88,11 @@ public:
return CN_ITER / 32; return CN_ITER / 32;
# endif # endif
# ifdef XMRIG_ALGO_CN_GPU
case Algorithm::CN_GPU:
return 0xC000;
# endif
default: default:
break; break;
} }
@@ -109,6 +114,12 @@ public:
} }
# endif # endif
# ifdef XMRIG_ALGO_CN_GPU
if (algo == Algorithm::CN_GPU) {
return 0x1FFFC0;
}
# endif
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (algo == Algorithm::CN_GR_1) { if (algo == Algorithm::CN_GR_1) {
return 0x3FFF0; return 0x3FFF0;
@@ -142,10 +153,12 @@ template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_0>::iterations()
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_TLO>::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 uint32_t CnAlgo<Algorithm::CN_CCX>::iterations() const { return CN_ITER / 2; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_UPX2>::iterations() const { return CN_ITER / 32; } template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_UPX2>::iterations() const { return CN_ITER / 32; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_GPU>::iterations() const { return 0xC000; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_0>::mask() const { return 0x1FFF0; } 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; } template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_UPX2>::mask() const { return 0x1FFF0; }
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_GPU>::mask() const { return 0x1FFFC0; }
#ifdef XMRIG_ALGO_GHOSTRIDER #ifdef XMRIG_ALGO_GHOSTRIDER
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_GR_0>::iterations() const { return CN_ITER / 4; } template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_GR_0>::iterations() const { return CN_ITER / 4; }
+6
View File
@@ -356,6 +356,12 @@ xmrig::CnHash::CnHash()
ADD_FN_ASM(Algorithm::CN_UPX2); ADD_FN_ASM(Algorithm::CN_UPX2);
# endif # endif
# ifdef XMRIG_ALGO_CN_GPU
m_map[Algorithm::CN_GPU] = new cn_hash_fun_array{};
m_map[Algorithm::CN_GPU]->data[AV_SINGLE][Assembly::NONE] = cryptonight_single_hash_gpu<Algorithm::CN_GPU, false>;
m_map[Algorithm::CN_GPU]->data[AV_SINGLE_SOFT][Assembly::NONE] = cryptonight_single_hash_gpu<Algorithm::CN_GPU, true>;
# endif
# ifdef XMRIG_ALGO_ARGON2 # ifdef XMRIG_ALGO_ARGON2
m_map[Algorithm::AR2_CHUKWA] = new cn_hash_fun_array{}; 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][Assembly::NONE] = argon2::single_hash<Algorithm::AR2_CHUKWA>;
+1 -1
View File
@@ -30,7 +30,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#if defined _MSC_VER || defined XMRIG_ARM #if defined _MSC_VER || defined XMRIG_ARM || defined __INTEL_COMPILER
# define ABI_ATTRIBUTE # define ABI_ATTRIBUTE
#else #else
# define ABI_ATTRIBUTE __attribute__((ms_abi)) # define ABI_ATTRIBUTE __attribute__((ms_abi))
+73 -1
View File
@@ -63,8 +63,13 @@ static inline void do_skein_hash(const uint8_t *input, size_t len, uint8_t *outp
xmr_skein(input, output); xmr_skein(input, output);
} }
static inline void do_flex_skein_hash(const uint8_t* input, size_t len, uint8_t* output) {
int r = skein_hash(512, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash}; void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
void (* const extra_hashes_flex[3])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_flex_skein_hash};
// This will shift and xor tmp1 into itself as 4 32-bit vals such as // This will shift and xor tmp1 into itself as 4 32-bit vals such as
@@ -230,7 +235,11 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
{ {
constexpr CnAlgo<ALGO> props; constexpr CnAlgo<ALGO> props;
# ifdef XMRIG_ALGO_CN_GPU
constexpr bool IS_HEAVY = props.isHeavy() || ALGO == Algorithm::CN_GPU;
# else
constexpr bool IS_HEAVY = props.isHeavy(); constexpr bool IS_HEAVY = props.isHeavy();
# endif
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
@@ -539,10 +548,73 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
cn_implode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(ctx[0]->memory), reinterpret_cast<__m128i *>(ctx[0]->state)); cn_implode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(ctx[0]->memory), reinterpret_cast<__m128i *>(ctx[0]->state));
keccakf(h0, 24); keccakf(h0, 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output); if (height == 101) // Flex algo ugly hack
extra_hashes_flex[ctx[0]->state[0] & 2](ctx[0]->state, 200, output);
else
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
} }
} /* namespace xmrig */
#ifdef XMRIG_ALGO_CN_GPU
template<size_t ITER, uint32_t MASK>
void cn_gpu_inner_arm(const uint8_t *spad, uint8_t *lpad);
namespace xmrig {
template<size_t MEM>
void cn_explode_scratchpad_gpu(const uint8_t *input, uint8_t *output)
{
constexpr size_t hash_size = 200; // 25x8 bytes
alignas(16) uint64_t hash[25];
for (uint64_t i = 0; i < MEM / 512; i++) {
memcpy(hash, input, hash_size);
hash[0] ^= i;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 160);
output += 160;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 176);
output += 176;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 176);
output += 176;
}
}
template<xmrig::Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_single_hash_gpu(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height)
{
constexpr CnAlgo<ALGO> props;
keccak(input, size, ctx[0]->state);
cn_explode_scratchpad_gpu<props.memory()>(ctx[0]->state, ctx[0]->memory);
fesetround(FE_TONEAREST);
cn_gpu_inner_arm<props.iterations(), props.mask()>(ctx[0]->state, ctx[0]->memory);
cn_implode_scratchpad<ALGO, SOFT_AES>(reinterpret_cast<const __m128i *>(ctx[0]->memory), reinterpret_cast<__m128i *>(ctx[0]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24);
memcpy(output, ctx[0]->state, 32);
}
} /* namespace xmrig */
#endif
namespace xmrig {
template<Algorithm::Id ALGO, bool SOFT_AES> template<Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx, uint64_t height) inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx, uint64_t height)
{ {
+22
View File
@@ -387,6 +387,23 @@ const static uint8_t test_output_femto_upx2[256] = {
#endif #endif
#ifdef XMRIG_ALGO_CN_GPU
// "cn/gpu"
const static uint8_t test_output_gpu[160] = {
0xE5, 0x5C, 0xB2, 0x3E, 0x51, 0x64, 0x9A, 0x59, 0xB1, 0x27, 0xB9, 0x6B, 0x51, 0x5F, 0x2B, 0xF7,
0xBF, 0xEA, 0x19, 0x97, 0x41, 0xA0, 0x21, 0x6C, 0xF8, 0x38, 0xDE, 0xD0, 0x6E, 0xFF, 0x82, 0xDF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif
#ifdef XMRIG_ALGO_ARGON2 #ifdef XMRIG_ALGO_ARGON2
// "argon2/chukwa" // "argon2/chukwa"
const static uint8_t argon2_chukwa_test_out[256] = { const static uint8_t argon2_chukwa_test_out[256] = {
@@ -452,6 +469,11 @@ const static uint8_t test_output_gr[256] = {
0xC4, 0xA7, 0xC7, 0x77, 0xAD, 0xF8, 0x09, 0x61, 0x16, 0xBB, 0xAA, 0x7E, 0xAB, 0xC3, 0x00, 0x25, 0xC4, 0xA7, 0xC7, 0x77, 0xAD, 0xF8, 0x09, 0x61, 0x16, 0xBB, 0xAA, 0x7E, 0xAB, 0xC3, 0x00, 0x25,
0xBA, 0xA8, 0x97, 0xC7, 0x7D, 0x38, 0x46, 0x0E, 0x59, 0xAC, 0xCB, 0xAE, 0xFE, 0x3C, 0x6F, 0x01 0xBA, 0xA8, 0x97, 0xC7, 0x7D, 0x38, 0x46, 0x0E, 0x59, 0xAC, 0xCB, 0xAE, 0xFE, 0x3C, 0x6F, 0x01
}; };
// "Flex"
const static uint8_t test_output_flex[32] = {
0x2e, 0x4f, 0x85, 0x7a, 0xa8, 0x10, 0x08, 0xc4, 0xd1, 0xfe, 0x9a, 0xcd, 0x74, 0x89, 0xe8, 0x4d,
0x3b, 0xc5, 0x5b, 0x70, 0x54, 0xe6, 0xc0, 0x2b, 0x2c, 0x0e, 0x1b, 0x76, 0xcc, 0xa0, 0xda, 0x7b
};
#endif #endif
+106 -10
View File
@@ -76,8 +76,14 @@ static inline void do_skein_hash(const uint8_t *input, size_t len, uint8_t *outp
xmr_skein(input, output); xmr_skein(input, output);
} }
static inline void do_flex_skein_hash(const uint8_t* input, size_t len, uint8_t* output) {
int r = skein_hash(512, input, 8 * len, (uint8_t*)output);
assert(SKEIN_SUCCESS == r);
}
void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash}; void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
void (* const extra_hashes_flex[3])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_flex_skein_hash};
#if (defined(__i386__) || defined(_M_IX86)) && !(defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 15)) #if (defined(__i386__) || defined(_M_IX86)) && !(defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 15))
@@ -294,8 +300,14 @@ static NOINLINE void cn_explode_scratchpad(cryptonight_ctx *ctx)
{ {
constexpr CnAlgo<ALGO> props; constexpr CnAlgo<ALGO> props;
# ifdef XMRIG_ALGO_CN_GPU
constexpr bool IS_HEAVY = props.isHeavy() || ALGO == Algorithm::CN_GPU;
# else
constexpr bool IS_HEAVY = props.isHeavy();
# endif
# ifdef XMRIG_VAES # ifdef XMRIG_VAES
if (!SOFT_AES && !props.isHeavy() && cn_vaes_enabled) { if (!SOFT_AES && !IS_HEAVY && cn_vaes_enabled) {
cn_explode_scratchpad_vaes(ctx, props.memory(), props.half_mem()); cn_explode_scratchpad_vaes(ctx, props.memory(), props.half_mem());
return; return;
} }
@@ -408,14 +420,19 @@ static NOINLINE void cn_implode_scratchpad(cryptonight_ctx *ctx)
{ {
constexpr CnAlgo<ALGO> props; constexpr CnAlgo<ALGO> props;
# ifdef XMRIG_ALGO_CN_GPU
constexpr bool IS_HEAVY = props.isHeavy() || ALGO == Algorithm::CN_GPU;
# else
constexpr bool IS_HEAVY = props.isHeavy();
# endif
# ifdef XMRIG_VAES # ifdef XMRIG_VAES
if (!SOFT_AES && !props.isHeavy() && cn_vaes_enabled) { if (!SOFT_AES && !IS_HEAVY && cn_vaes_enabled) {
cn_implode_scratchpad_vaes(ctx, props.memory(), props.half_mem()); cn_implode_scratchpad_vaes(ctx, props.memory(), props.half_mem());
return; return;
} }
# endif # endif
constexpr bool IS_HEAVY = props.isHeavy();
constexpr size_t N = (props.memory() / sizeof(__m128i)) / (props.half_mem() ? 2 : 1); constexpr size_t N = (props.memory() / sizeof(__m128i)) / (props.half_mem() ? 2 : 1);
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
@@ -578,8 +595,10 @@ static inline __m128i int_sqrt_v2(const uint64_t n0)
r >>= 19; r >>= 19;
uint64_t x2 = (s - (1022ULL << 32)) * (r - s - (1022ULL << 32) + 1); uint64_t x2 = (s - (1022ULL << 32)) * (r - s - (1022ULL << 32) + 1);
# if (defined(_MSC_VER) || __GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 1)) && (defined(__x86_64__) || defined(_M_AMD64)) # if (defined(_MSC_VER) || __GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 1)) && (defined(__x86_64__) || defined(_M_AMD64)) && !defined(__INTEL_COMPILER)
_addcarry_u64(_subborrow_u64(0, x2, n0, (unsigned long long int*)&x2), r, 0, (unsigned long long int*)&r); _addcarry_u64(_subborrow_u64(0, x2, n0, (unsigned long long int*)&x2), r, 0, (unsigned long long int*)&r);
# elif defined(__INTEL_COMPILER)
_addcarry_u64(_subborrow_u64(0, x2, n0, (unsigned long int*)&x2), r, 0, (unsigned long int*)&r);
# else # else
if (x2 < n0) ++r; if (x2 < n0) ++r;
# endif # endif
@@ -840,13 +859,86 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
cn_implode_scratchpad<ALGO, SOFT_AES, interleave>(ctx[0]); cn_implode_scratchpad<ALGO, SOFT_AES, interleave>(ctx[0]);
keccakf(h0, 24); keccakf(h0, 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output); if (height == 101) // Flex algo ugly hack
extra_hashes_flex[ctx[0]->state[0] & 2](ctx[0]->state, 200, output);
else
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
} }
} /* namespace xmrig */ } /* namespace xmrig */
#ifdef XMRIG_ALGO_CN_GPU
template<size_t ITER, uint32_t MASK>
void cn_gpu_inner_avx(const uint8_t *spad, uint8_t *lpad);
template<size_t ITER, uint32_t MASK>
void cn_gpu_inner_ssse3(const uint8_t *spad, uint8_t *lpad);
namespace xmrig {
template<size_t MEM>
static NOINLINE void cn_explode_scratchpad_gpu(cryptonight_ctx *ctx)
{
const uint8_t* input = reinterpret_cast<const uint8_t*>(ctx->state);
uint8_t* output = reinterpret_cast<uint8_t*>(ctx->memory);
constexpr size_t hash_size = 200; // 25x8 bytes
alignas(16) uint64_t hash[25];
for (uint64_t i = 0; i < MEM / 512; i++) {
memcpy(hash, input, hash_size);
hash[0] ^= i;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 160);
output += 160;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 176);
output += 176;
xmrig::keccakf(hash, 24);
memcpy(output, hash, 176);
output += 176;
}
}
template<Algorithm::Id ALGO, bool SOFT_AES>
inline void cryptonight_single_hash_gpu(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height)
{
constexpr CnAlgo<ALGO> props;
keccak(input, size, ctx[0]->state);
cn_explode_scratchpad_gpu<props.memory()>(ctx[0]);
# ifdef _MSC_VER
_control87(RC_NEAR, MCW_RC);
# else
fesetround(FE_TONEAREST);
# endif
if (xmrig::Cpu::info()->hasAVX2()) {
cn_gpu_inner_avx<props.iterations(), props.mask()>(ctx[0]->state, ctx[0]->memory);
} else {
cn_gpu_inner_ssse3<props.iterations(), props.mask()>(ctx[0]->state, ctx[0]->memory);
}
cn_implode_scratchpad<ALGO, SOFT_AES, 0>(ctx[0]);
keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24);
memcpy(output, ctx[0]->state, 32);
}
} /* namespace xmrig */
#endif
#ifdef XMRIG_FEATURE_ASM #ifdef XMRIG_FEATURE_ASM
extern "C" void cnv1_single_mainloop_asm(cryptonight_ctx * *ctx); extern "C" void cnv1_single_mainloop_asm(cryptonight_ctx * *ctx);
extern "C" void cnv1_double_mainloop_asm(cryptonight_ctx **ctx); extern "C" void cnv1_double_mainloop_asm(cryptonight_ctx **ctx);
@@ -1042,7 +1134,10 @@ inline void cryptonight_single_hash_asm(const uint8_t *__restrict__ input, size_
cn_implode_scratchpad<ALGO, false, 0>(ctx[0]); cn_implode_scratchpad<ALGO, false, 0>(ctx[0]);
keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24); keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output); if (height == 101) // Flex algo ugly hack
extra_hashes_flex[ctx[0]->state[0] & 2](ctx[0]->state, 200, output);
else
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
} }
@@ -1155,9 +1250,7 @@ static NOINLINE void cryptonight_single_hash_gr_sse41(const uint8_t* __restrict_
keccak(input, size, ctx[0]->state); keccak(input, size, ctx[0]->state);
if (props.half_mem()) { if (props.half_mem()) ctx[0]->first_half = true;
ctx[0]->first_half = true;
}
cn_explode_scratchpad<ALGO, false, 0>(ctx[0]); cn_explode_scratchpad<ALGO, false, 0>(ctx[0]);
VARIANT1_INIT(0); VARIANT1_INIT(0);
@@ -1172,7 +1265,10 @@ static NOINLINE void cryptonight_single_hash_gr_sse41(const uint8_t* __restrict_
cn_implode_scratchpad<ALGO, false, 0>(ctx[0]); cn_implode_scratchpad<ALGO, false, 0>(ctx[0]);
keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24); keccakf(reinterpret_cast<uint64_t*>(ctx[0]->state), 24);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output); if (height == 101) // Flex algo ugly hack
extra_hashes_flex[ctx[0]->state[0] & 2](ctx[0]->state, 200, output);
else
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
} }
+240
View File
@@ -0,0 +1,240 @@
/* 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-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 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 <arm_neon.h>
#include "crypto/cn/CnAlgo.h"
inline void vandq_f32(float32x4_t &v, uint32_t v2)
{
uint32x4_t vc = vdupq_n_u32(v2);
v = (float32x4_t)vandq_u32((uint32x4_t)v, vc);
}
inline void vorq_f32(float32x4_t &v, uint32_t v2)
{
uint32x4_t vc = vdupq_n_u32(v2);
v = (float32x4_t)vorrq_u32((uint32x4_t)v, vc);
}
template <size_t v>
inline void vrot_si32(int32x4_t &r)
{
r = (int32x4_t)vextq_s8((int8x16_t)r, (int8x16_t)r, v);
}
template <>
inline void vrot_si32<0>(int32x4_t &r)
{
}
inline uint32_t vheor_s32(const int32x4_t &v)
{
int32x4_t v0 = veorq_s32(v, vrev64q_s32(v));
int32x2_t vf = veor_s32(vget_high_s32(v0), vget_low_s32(v0));
return (uint32_t)vget_lane_s32(vf, 0);
}
inline void prep_dv(int32_t *idx, int32x4_t &v, float32x4_t &n)
{
v = vld1q_s32(idx);
n = vcvtq_f32_s32(v);
}
inline void sub_round(const float32x4_t &n0, const float32x4_t &n1, const float32x4_t &n2, const float32x4_t &n3, const float32x4_t &rnd_c, float32x4_t &n, float32x4_t &d, float32x4_t &c)
{
float32x4_t ln1 = vaddq_f32(n1, c);
float32x4_t nn = vmulq_f32(n0, c);
nn = vmulq_f32(ln1, vmulq_f32(nn, nn));
vandq_f32(nn, 0xFEFFFFFF);
vorq_f32(nn, 0x00800000);
n = vaddq_f32(n, nn);
float32x4_t ln3 = vsubq_f32(n3, c);
float32x4_t dd = vmulq_f32(n2, c);
dd = vmulq_f32(ln3, vmulq_f32(dd, dd));
vandq_f32(dd, 0xFEFFFFFF);
vorq_f32(dd, 0x00800000);
d = vaddq_f32(d, dd);
//Constant feedback
c = vaddq_f32(c, rnd_c);
c = vaddq_f32(c, vdupq_n_f32(0.734375f));
float32x4_t r = vaddq_f32(nn, dd);
vandq_f32(r, 0x807FFFFF);
vorq_f32(r, 0x40000000);
c = vaddq_f32(c, r);
}
inline void round_compute(const float32x4_t &n0, const float32x4_t &n1, const float32x4_t &n2, const float32x4_t &n3, const float32x4_t &rnd_c, float32x4_t &c, float32x4_t &r)
{
float32x4_t n = vdupq_n_f32(0.0f), d = vdupq_n_f32(0.0f);
sub_round(n0, n1, n2, n3, rnd_c, n, d, c);
sub_round(n1, n2, n3, n0, rnd_c, n, d, c);
sub_round(n2, n3, n0, n1, rnd_c, n, d, c);
sub_round(n3, n0, n1, n2, rnd_c, n, d, c);
sub_round(n3, n2, n1, n0, rnd_c, n, d, c);
sub_round(n2, n1, n0, n3, rnd_c, n, d, c);
sub_round(n1, n0, n3, n2, rnd_c, n, d, c);
sub_round(n0, n3, n2, n1, rnd_c, n, d, c);
// Make sure abs(d) > 2.0 - this prevents division by zero and accidental overflows by division by < 1.0
vandq_f32(d, 0xFF7FFFFF);
vorq_f32(d, 0x40000000);
r = vaddq_f32(r, vdivq_f32(n, d));
}
// 112×4 = 448
template <bool add>
inline int32x4_t single_compute(const float32x4_t &n0, const float32x4_t &n1, const float32x4_t &n2, const float32x4_t &n3, float cnt, const float32x4_t &rnd_c, float32x4_t &sum)
{
float32x4_t c = vdupq_n_f32(cnt);
float32x4_t r = vdupq_n_f32(0.0f);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
// do a quick fmod by setting exp to 2
vandq_f32(r, 0x807FFFFF);
vorq_f32(r, 0x40000000);
if (add) {
sum = vaddq_f32(sum, r);
} else {
sum = r;
}
const float32x4_t cc2 = vdupq_n_f32(536870880.0f);
r = vmulq_f32(r, cc2); // 35
return vcvtq_s32_f32(r);
}
template<size_t rot>
inline void single_compute_wrap(const float32x4_t &n0, const float32x4_t &n1, const float32x4_t &n2, const float32x4_t &n3, float cnt, const float32x4_t &rnd_c, float32x4_t &sum, int32x4_t &out)
{
int32x4_t r = single_compute<rot % 2 != 0>(n0, n1, n2, n3, cnt, rnd_c, sum);
vrot_si32<rot>(r);
out = veorq_s32(out, r);
}
template<uint32_t MASK>
inline int32_t *scratchpad_ptr(uint8_t* lpad, uint32_t idx, size_t n) { return reinterpret_cast<int32_t *>(lpad + (idx & MASK) + n * 16); }
template<size_t ITER, uint32_t MASK>
void cn_gpu_inner_arm(const uint8_t *spad, uint8_t *lpad)
{
uint32_t s = reinterpret_cast<const uint32_t*>(spad)[0] >> 8;
int32_t *idx0 = scratchpad_ptr<MASK>(lpad, s, 0);
int32_t *idx1 = scratchpad_ptr<MASK>(lpad, s, 1);
int32_t *idx2 = scratchpad_ptr<MASK>(lpad, s, 2);
int32_t *idx3 = scratchpad_ptr<MASK>(lpad, s, 3);
float32x4_t sum0 = vdupq_n_f32(0.0f);
for (size_t i = 0; i < ITER; i++) {
float32x4_t n0, n1, n2, n3;
int32x4_t v0, v1, v2, v3;
float32x4_t suma, sumb, sum1, sum2, sum3;
prep_dv(idx0, v0, n0);
prep_dv(idx1, v1, n1);
prep_dv(idx2, v2, n2);
prep_dv(idx3, v3, n3);
float32x4_t rc = sum0;
int32x4_t out, out2;
out = vdupq_n_s32(0);
single_compute_wrap<0>(n0, n1, n2, n3, 1.3437500f, rc, suma, out);
single_compute_wrap<1>(n0, n2, n3, n1, 1.2812500f, rc, suma, out);
single_compute_wrap<2>(n0, n3, n1, n2, 1.3593750f, rc, sumb, out);
single_compute_wrap<3>(n0, n3, n2, n1, 1.3671875f, rc, sumb, out);
sum0 = vaddq_f32(suma, sumb);
vst1q_s32(idx0, veorq_s32(v0, out));
out2 = out;
out = vdupq_n_s32(0);
single_compute_wrap<0>(n1, n0, n2, n3, 1.4296875f, rc, suma, out);
single_compute_wrap<1>(n1, n2, n3, n0, 1.3984375f, rc, suma, out);
single_compute_wrap<2>(n1, n3, n0, n2, 1.3828125f, rc, sumb, out);
single_compute_wrap<3>(n1, n3, n2, n0, 1.3046875f, rc, sumb, out);
sum1 = vaddq_f32(suma, sumb);
vst1q_s32(idx1, veorq_s32(v1, out));
out2 = veorq_s32(out2, out);
out = vdupq_n_s32(0);
single_compute_wrap<0>(n2, n1, n0, n3, 1.4140625f, rc, suma, out);
single_compute_wrap<1>(n2, n0, n3, n1, 1.2734375f, rc, suma, out);
single_compute_wrap<2>(n2, n3, n1, n0, 1.2578125f, rc, sumb, out);
single_compute_wrap<3>(n2, n3, n0, n1, 1.2890625f, rc, sumb, out);
sum2 = vaddq_f32(suma, sumb);
vst1q_s32(idx2, veorq_s32(v2, out));
out2 = veorq_s32(out2, out);
out = vdupq_n_s32(0);
single_compute_wrap<0>(n3, n1, n2, n0, 1.3203125f, rc, suma, out);
single_compute_wrap<1>(n3, n2, n0, n1, 1.3515625f, rc, suma, out);
single_compute_wrap<2>(n3, n0, n1, n2, 1.3359375f, rc, sumb, out);
single_compute_wrap<3>(n3, n0, n2, n1, 1.4609375f, rc, sumb, out);
sum3 = vaddq_f32(suma, sumb);
vst1q_s32(idx3, veorq_s32(v3, out));
out2 = veorq_s32(out2, out);
sum0 = vaddq_f32(sum0, sum1);
sum2 = vaddq_f32(sum2, sum3);
sum0 = vaddq_f32(sum0, sum2);
const float32x4_t cc1 = vdupq_n_f32(16777216.0f);
const float32x4_t cc2 = vdupq_n_f32(64.0f);
vandq_f32(sum0, 0x7fffffff); // take abs(va) by masking the float sign bit
// vs range 0 - 64
n0 = vmulq_f32(sum0, cc1);
v0 = vcvtq_s32_f32(n0);
v0 = veorq_s32(v0, out2);
uint32_t n = vheor_s32(v0);
// vs is now between 0 and 1
sum0 = vdivq_f32(sum0, cc2);
idx0 = scratchpad_ptr<MASK>(lpad, n, 0);
idx1 = scratchpad_ptr<MASK>(lpad, n, 1);
idx2 = scratchpad_ptr<MASK>(lpad, n, 2);
idx3 = scratchpad_ptr<MASK>(lpad, n, 3);
}
}
template void cn_gpu_inner_arm<xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().iterations(), xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().mask()>(const uint8_t* spad, uint8_t* lpad);
+211
View File
@@ -0,0 +1,211 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <support@xmrig.com>
*
* 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 "crypto/cn/CnAlgo.h"
#ifdef __GNUC__
# include <x86intrin.h>
#else
# include <intrin.h>
# define __restrict__ __restrict
#endif
#ifndef _mm256_bslli_epi128
#define _mm256_bslli_epi128(a, count) _mm256_slli_si256((a), (count))
#endif
#ifndef _mm256_bsrli_epi128
#define _mm256_bsrli_epi128(a, count) _mm256_srli_si256((a), (count))
#endif
inline void prep_dv_avx(__m256i* idx, __m256i& v, __m256& n01)
{
v = _mm256_load_si256(idx);
n01 = _mm256_cvtepi32_ps(v);
}
inline __m256 fma_break(const __m256& x)
{
// Break the dependency chain by setting the exp to ?????01
__m256 xx = _mm256_and_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0xFEFFFFFF)), x);
return _mm256_or_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0x00800000)), xx);
}
// 14
inline void sub_round(const __m256& n0, const __m256& n1, const __m256& n2, const __m256& n3, const __m256& rnd_c, __m256& n, __m256& d, __m256& c)
{
__m256 nn = _mm256_mul_ps(n0, c);
nn = _mm256_mul_ps(_mm256_add_ps(n1, c), _mm256_mul_ps(nn, nn));
nn = fma_break(nn);
n = _mm256_add_ps(n, nn);
__m256 dd = _mm256_mul_ps(n2, c);
dd = _mm256_mul_ps(_mm256_sub_ps(n3, c), _mm256_mul_ps(dd, dd));
dd = fma_break(dd);
d = _mm256_add_ps(d, dd);
//Constant feedback
c = _mm256_add_ps(c, rnd_c);
c = _mm256_add_ps(c, _mm256_set1_ps(0.734375f));
__m256 r = _mm256_add_ps(nn, dd);
r = _mm256_and_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0x807FFFFF)), r);
r = _mm256_or_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0x40000000)), r);
c = _mm256_add_ps(c, r);
}
// 14*8 + 2 = 112
inline void round_compute(const __m256& n0, const __m256& n1, const __m256& n2, const __m256& n3, const __m256& rnd_c, __m256& c, __m256& r)
{
__m256 n = _mm256_setzero_ps(), d = _mm256_setzero_ps();
sub_round(n0, n1, n2, n3, rnd_c, n, d, c);
sub_round(n1, n2, n3, n0, rnd_c, n, d, c);
sub_round(n2, n3, n0, n1, rnd_c, n, d, c);
sub_round(n3, n0, n1, n2, rnd_c, n, d, c);
sub_round(n3, n2, n1, n0, rnd_c, n, d, c);
sub_round(n2, n1, n0, n3, rnd_c, n, d, c);
sub_round(n1, n0, n3, n2, rnd_c, n, d, c);
sub_round(n0, n3, n2, n1, rnd_c, n, d, c);
// Make sure abs(d) > 2.0 - this prevents division by zero and accidental overflows by division by < 1.0
d = _mm256_and_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0xFF7FFFFF)), d);
d = _mm256_or_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0x40000000)), d);
r = _mm256_add_ps(r, _mm256_div_ps(n, d));
}
// 112×4 = 448
template <bool add>
inline __m256i double_compute(const __m256& n0, const __m256& n1, const __m256& n2, const __m256& n3,
float lcnt, float hcnt, const __m256& rnd_c, __m256& sum)
{
__m256 c = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_set1_ps(lcnt)), _mm_set1_ps(hcnt), 1);
__m256 r = _mm256_setzero_ps();
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
// do a quick fmod by setting exp to 2
r = _mm256_and_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0x807FFFFF)), r);
r = _mm256_or_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0x40000000)), r);
if(add)
sum = _mm256_add_ps(sum, r);
else
sum = r;
r = _mm256_mul_ps(r, _mm256_set1_ps(536870880.0f)); // 35
return _mm256_cvttps_epi32(r);
}
template <size_t rot>
inline void double_compute_wrap(const __m256& n0, const __m256& n1, const __m256& n2, const __m256& n3,
float lcnt, float hcnt, const __m256& rnd_c, __m256& sum, __m256i& out)
{
__m256i r = double_compute<rot % 2 != 0>(n0, n1, n2, n3, lcnt, hcnt, rnd_c, sum);
if(rot != 0)
r = _mm256_or_si256(_mm256_bslli_epi128(r, 16 - rot), _mm256_bsrli_epi128(r, rot));
out = _mm256_xor_si256(out, r);
}
template<uint32_t MASK>
inline __m256i* scratchpad_ptr(uint8_t* lpad, uint32_t idx, size_t n) { return reinterpret_cast<__m256i*>(lpad + (idx & MASK) + n*16); }
template<size_t ITER, uint32_t MASK>
void cn_gpu_inner_avx(const uint8_t* spad, uint8_t* lpad)
{
uint32_t s = reinterpret_cast<const uint32_t*>(spad)[0] >> 8;
__m256i* idx0 = scratchpad_ptr<MASK>(lpad, s, 0);
__m256i* idx2 = scratchpad_ptr<MASK>(lpad, s, 2);
__m256 sum0 = _mm256_setzero_ps();
for(size_t i = 0; i < ITER; i++)
{
__m256i v01, v23;
__m256 suma, sumb, sum1;
__m256 rc = sum0;
__m256 n01, n23;
prep_dv_avx(idx0, v01, n01);
prep_dv_avx(idx2, v23, n23);
__m256i out, out2;
__m256 n10, n22, n33;
n10 = _mm256_permute2f128_ps(n01, n01, 0x01);
n22 = _mm256_permute2f128_ps(n23, n23, 0x00);
n33 = _mm256_permute2f128_ps(n23, n23, 0x11);
out = _mm256_setzero_si256();
double_compute_wrap<0>(n01, n10, n22, n33, 1.3437500f, 1.4296875f, rc, suma, out);
double_compute_wrap<1>(n01, n22, n33, n10, 1.2812500f, 1.3984375f, rc, suma, out);
double_compute_wrap<2>(n01, n33, n10, n22, 1.3593750f, 1.3828125f, rc, sumb, out);
double_compute_wrap<3>(n01, n33, n22, n10, 1.3671875f, 1.3046875f, rc, sumb, out);
_mm256_store_si256(idx0, _mm256_xor_si256(v01, out));
sum0 = _mm256_add_ps(suma, sumb);
out2 = out;
__m256 n11, n02, n30;
n11 = _mm256_permute2f128_ps(n01, n01, 0x11);
n02 = _mm256_permute2f128_ps(n01, n23, 0x20);
n30 = _mm256_permute2f128_ps(n01, n23, 0x03);
out = _mm256_setzero_si256();
double_compute_wrap<0>(n23, n11, n02, n30, 1.4140625f, 1.3203125f, rc, suma, out);
double_compute_wrap<1>(n23, n02, n30, n11, 1.2734375f, 1.3515625f, rc, suma, out);
double_compute_wrap<2>(n23, n30, n11, n02, 1.2578125f, 1.3359375f, rc, sumb, out);
double_compute_wrap<3>(n23, n30, n02, n11, 1.2890625f, 1.4609375f, rc, sumb, out);
_mm256_store_si256(idx2, _mm256_xor_si256(v23, out));
sum1 = _mm256_add_ps(suma, sumb);
out2 = _mm256_xor_si256(out2, out);
out2 = _mm256_xor_si256(_mm256_permute2x128_si256(out2,out2,0x41), out2);
suma = _mm256_permute2f128_ps(sum0, sum1, 0x30);
sumb = _mm256_permute2f128_ps(sum0, sum1, 0x21);
sum0 = _mm256_add_ps(suma, sumb);
sum0 = _mm256_add_ps(sum0, _mm256_permute2f128_ps(sum0, sum0, 0x41));
// Clear the high 128 bits
__m128 sum = _mm256_castps256_ps128(sum0);
sum = _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)), sum); // take abs(va) by masking the float sign bit
// vs range 0 - 64
__m128i v0 = _mm_cvttps_epi32(_mm_mul_ps(sum, _mm_set1_ps(16777216.0f)));
v0 = _mm_xor_si128(v0, _mm256_castsi256_si128(out2));
__m128i v1 = _mm_shuffle_epi32(v0, _MM_SHUFFLE(0, 1, 2, 3));
v0 = _mm_xor_si128(v0, v1);
v1 = _mm_shuffle_epi32(v0, _MM_SHUFFLE(0, 1, 0, 1));
v0 = _mm_xor_si128(v0, v1);
// vs is now between 0 and 1
sum = _mm_div_ps(sum, _mm_set1_ps(64.0f));
sum0 = _mm256_insertf128_ps(_mm256_castps128_ps256(sum), sum, 1);
uint32_t n = _mm_cvtsi128_si32(v0);
idx0 = scratchpad_ptr<MASK>(lpad, n, 0);
idx2 = scratchpad_ptr<MASK>(lpad, n, 2);
}
}
template void cn_gpu_inner_avx<xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().iterations(), xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().mask()>(const uint8_t* spad, uint8_t* lpad);
+212
View File
@@ -0,0 +1,212 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <support@xmrig.com>
*
* 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 "crypto/cn/CnAlgo.h"
#ifdef __GNUC__
# include <x86intrin.h>
#else
# include <intrin.h>
# define __restrict__ __restrict
#endif
inline void prep_dv(__m128i* idx, __m128i& v, __m128& n)
{
v = _mm_load_si128(idx);
n = _mm_cvtepi32_ps(v);
}
inline __m128 fma_break(__m128 x)
{
// Break the dependency chain by setting the exp to ?????01
x = _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0xFEFFFFFF)), x);
return _mm_or_ps(_mm_castsi128_ps(_mm_set1_epi32(0x00800000)), x);
}
// 14
inline void sub_round(__m128 n0, __m128 n1, __m128 n2, __m128 n3, __m128 rnd_c, __m128& n, __m128& d, __m128& c)
{
n1 = _mm_add_ps(n1, c);
__m128 nn = _mm_mul_ps(n0, c);
nn = _mm_mul_ps(n1, _mm_mul_ps(nn,nn));
nn = fma_break(nn);
n = _mm_add_ps(n, nn);
n3 = _mm_sub_ps(n3, c);
__m128 dd = _mm_mul_ps(n2, c);
dd = _mm_mul_ps(n3, _mm_mul_ps(dd,dd));
dd = fma_break(dd);
d = _mm_add_ps(d, dd);
//Constant feedback
c = _mm_add_ps(c, rnd_c);
c = _mm_add_ps(c, _mm_set1_ps(0.734375f));
__m128 r = _mm_add_ps(nn, dd);
r = _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0x807FFFFF)), r);
r = _mm_or_ps(_mm_castsi128_ps(_mm_set1_epi32(0x40000000)), r);
c = _mm_add_ps(c, r);
}
// 14*8 + 2 = 112
inline void round_compute(__m128 n0, __m128 n1, __m128 n2, __m128 n3, __m128 rnd_c, __m128& c, __m128& r)
{
__m128 n = _mm_setzero_ps(), d = _mm_setzero_ps();
sub_round(n0, n1, n2, n3, rnd_c, n, d, c);
sub_round(n1, n2, n3, n0, rnd_c, n, d, c);
sub_round(n2, n3, n0, n1, rnd_c, n, d, c);
sub_round(n3, n0, n1, n2, rnd_c, n, d, c);
sub_round(n3, n2, n1, n0, rnd_c, n, d, c);
sub_round(n2, n1, n0, n3, rnd_c, n, d, c);
sub_round(n1, n0, n3, n2, rnd_c, n, d, c);
sub_round(n0, n3, n2, n1, rnd_c, n, d, c);
// Make sure abs(d) > 2.0 - this prevents division by zero and accidental overflows by division by < 1.0
d = _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0xFF7FFFFF)), d);
d = _mm_or_ps(_mm_castsi128_ps(_mm_set1_epi32(0x40000000)), d);
r =_mm_add_ps(r, _mm_div_ps(n,d));
}
// 112×4 = 448
template<bool add>
inline __m128i single_compute(__m128 n0, __m128 n1, __m128 n2, __m128 n3, float cnt, __m128 rnd_c, __m128& sum)
{
__m128 c = _mm_set1_ps(cnt);
__m128 r = _mm_setzero_ps();
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
round_compute(n0, n1, n2, n3, rnd_c, c, r);
// do a quick fmod by setting exp to 2
r = _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0x807FFFFF)), r);
r = _mm_or_ps(_mm_castsi128_ps(_mm_set1_epi32(0x40000000)), r);
if(add)
sum = _mm_add_ps(sum, r);
else
sum = r;
r = _mm_mul_ps(r, _mm_set1_ps(536870880.0f)); // 35
return _mm_cvttps_epi32(r);
}
template<size_t rot>
inline void single_compute_wrap(__m128 n0, __m128 n1, __m128 n2, __m128 n3, float cnt, __m128 rnd_c, __m128& sum, __m128i& out)
{
__m128i r = single_compute<rot % 2 != 0>(n0, n1, n2, n3, cnt, rnd_c, sum);
if(rot != 0)
r = _mm_or_si128(_mm_slli_si128(r, 16 - rot), _mm_srli_si128(r, rot));
out = _mm_xor_si128(out, r);
}
template<uint32_t MASK>
inline __m128i* scratchpad_ptr(uint8_t* lpad, uint32_t idx, size_t n) { return reinterpret_cast<__m128i*>(lpad + (idx & MASK) + n*16); }
template<size_t ITER, uint32_t MASK>
void cn_gpu_inner_ssse3(const uint8_t* spad, uint8_t* lpad)
{
uint32_t s = reinterpret_cast<const uint32_t*>(spad)[0] >> 8;
__m128i* idx0 = scratchpad_ptr<MASK>(lpad, s, 0);
__m128i* idx1 = scratchpad_ptr<MASK>(lpad, s, 1);
__m128i* idx2 = scratchpad_ptr<MASK>(lpad, s, 2);
__m128i* idx3 = scratchpad_ptr<MASK>(lpad, s, 3);
__m128 sum0 = _mm_setzero_ps();
for(size_t i = 0; i < ITER; i++)
{
__m128 n0, n1, n2, n3;
__m128i v0, v1, v2, v3;
__m128 suma, sumb, sum1, sum2, sum3;
prep_dv(idx0, v0, n0);
prep_dv(idx1, v1, n1);
prep_dv(idx2, v2, n2);
prep_dv(idx3, v3, n3);
__m128 rc = sum0;
__m128i out, out2;
out = _mm_setzero_si128();
single_compute_wrap<0>(n0, n1, n2, n3, 1.3437500f, rc, suma, out);
single_compute_wrap<1>(n0, n2, n3, n1, 1.2812500f, rc, suma, out);
single_compute_wrap<2>(n0, n3, n1, n2, 1.3593750f, rc, sumb, out);
single_compute_wrap<3>(n0, n3, n2, n1, 1.3671875f, rc, sumb, out);
sum0 = _mm_add_ps(suma, sumb);
_mm_store_si128(idx0, _mm_xor_si128(v0, out));
out2 = out;
out = _mm_setzero_si128();
single_compute_wrap<0>(n1, n0, n2, n3, 1.4296875f, rc, suma, out);
single_compute_wrap<1>(n1, n2, n3, n0, 1.3984375f, rc, suma, out);
single_compute_wrap<2>(n1, n3, n0, n2, 1.3828125f, rc, sumb, out);
single_compute_wrap<3>(n1, n3, n2, n0, 1.3046875f, rc, sumb, out);
sum1 = _mm_add_ps(suma, sumb);
_mm_store_si128(idx1, _mm_xor_si128(v1, out));
out2 = _mm_xor_si128(out2, out);
out = _mm_setzero_si128();
single_compute_wrap<0>(n2, n1, n0, n3, 1.4140625f, rc, suma, out);
single_compute_wrap<1>(n2, n0, n3, n1, 1.2734375f, rc, suma, out);
single_compute_wrap<2>(n2, n3, n1, n0, 1.2578125f, rc, sumb, out);
single_compute_wrap<3>(n2, n3, n0, n1, 1.2890625f, rc, sumb, out);
sum2 = _mm_add_ps(suma, sumb);
_mm_store_si128(idx2, _mm_xor_si128(v2, out));
out2 = _mm_xor_si128(out2, out);
out = _mm_setzero_si128();
single_compute_wrap<0>(n3, n1, n2, n0, 1.3203125f, rc, suma, out);
single_compute_wrap<1>(n3, n2, n0, n1, 1.3515625f, rc, suma, out);
single_compute_wrap<2>(n3, n0, n1, n2, 1.3359375f, rc, sumb, out);
single_compute_wrap<3>(n3, n0, n2, n1, 1.4609375f, rc, sumb, out);
sum3 = _mm_add_ps(suma, sumb);
_mm_store_si128(idx3, _mm_xor_si128(v3, out));
out2 = _mm_xor_si128(out2, out);
sum0 = _mm_add_ps(sum0, sum1);
sum2 = _mm_add_ps(sum2, sum3);
sum0 = _mm_add_ps(sum0, sum2);
sum0 = _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)), sum0); // take abs(va) by masking the float sign bit
// vs range 0 - 64
n0 = _mm_mul_ps(sum0, _mm_set1_ps(16777216.0f));
v0 = _mm_cvttps_epi32(n0);
v0 = _mm_xor_si128(v0, out2);
v1 = _mm_shuffle_epi32(v0, _MM_SHUFFLE(0, 1, 2, 3));
v0 = _mm_xor_si128(v0, v1);
v1 = _mm_shuffle_epi32(v0, _MM_SHUFFLE(0, 1, 0, 1));
v0 = _mm_xor_si128(v0, v1);
// vs is now between 0 and 1
sum0 = _mm_div_ps(sum0, _mm_set1_ps(64.0f));
uint32_t n = _mm_cvtsi128_si32(v0);
idx0 = scratchpad_ptr<MASK>(lpad, n, 0);
idx1 = scratchpad_ptr<MASK>(lpad, n, 1);
idx2 = scratchpad_ptr<MASK>(lpad, n, 2);
idx3 = scratchpad_ptr<MASK>(lpad, n, 3);
}
}
template void cn_gpu_inner_ssse3<xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().iterations(), xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().mask()>(const uint8_t* spad, uint8_t* lpad);
+2 -2
View File
@@ -47,11 +47,11 @@ xmrig::MemoryPool::MemoryPool(size_t size, bool hugePages, uint32_t node)
return; return;
} }
constexpr size_t alignment = 1 << 24; constexpr size_t alignment = 0; //1 << 24;
m_memory = new VirtualMemory(size * pageSize + alignment, hugePages, false, false, node); m_memory = new VirtualMemory(size * pageSize + alignment, hugePages, false, false, node);
m_alignOffset = (alignment - (((size_t)m_memory->scratchpad()) % alignment)) % alignment; //m_alignOffset = (alignment - (((size_t)m_memory->scratchpad()) % alignment)) % alignment;
} }
+299
View File
@@ -0,0 +1,299 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "crypto/cn/CnHash.h"
#include "backend/cpu/Cpu.h"
extern "C" {
#include "../randomx/panthera/sysendian.h"
#include "../ghostrider/sph_blake.h"
#include "../ghostrider/sph_bmw.h"
#include "../ghostrider/sph_groestl.h"
#include "../ghostrider/sph_jh.h"
#include "../ghostrider/sph_keccak.h"
#include "../ghostrider/sph_skein.h"
#include "../ghostrider/sph_luffa.h"
#include "../ghostrider/sph_cubehash.h"
#include "../ghostrider/sph_shavite.h"
#include "../ghostrider/sph_simd.h"
#include "../ghostrider/sph_echo.h"
#include "../ghostrider/sph_hamsi.h"
#include "../ghostrider/sph_fugue.h"
#include "../ghostrider/sph_shabal.h"
#include "../ghostrider/sph_whirlpool.h"
#include "../ghostrider/sph_sha2.h"
}
#include <stdio.h>
using namespace xmrig;
enum Algo {
BLAKE = 0,
BMW,
GROESTL,
KECCAK,
SKEIN,
LUFFA,
CUBEHASH,
SHAVITE,
SIMD,
ECHO,
HAMSI,
FUGUE,
SHABAL,
WHIRLPOOL,
HASH_FUNC_COUNT
};
enum CNAlgo {
CNDark = 0,
CNDarklite,
CNFast,
CNLite,
CNTurtle,
CNTurtlelite,
CN_HASH_FUNC_COUNT
};
static void selectAlgo(unsigned char nibble, bool* selectedAlgos, uint8_t* selectedIndex, int algoCount, int* currentCount) {
uint8_t algoDigit = (nibble & 0x0F) % algoCount;
if(!selectedAlgos[algoDigit]) {
selectedAlgos[algoDigit] = true;
selectedIndex[currentCount[0]] = algoDigit;
currentCount[0] = currentCount[0] + 1;
}
algoDigit = (nibble >> 4) % algoCount;
if(!selectedAlgos[algoDigit]) {
selectedAlgos[algoDigit] = true;
selectedIndex[currentCount[0]] = algoDigit;
currentCount[0] = currentCount[0] + 1;
}
}
static void getAlgoString(void *mem, unsigned int size, uint8_t* selectedAlgoOutput, int algoCount) {
unsigned char *p = (unsigned char *)mem;
unsigned int len = size/2;
bool* selectedAlgo = new bool[algoCount];
for(int z=0; z < algoCount; z++) {
selectedAlgo[z] = false;
}
int selectedCount = 0;
for (unsigned int i=0;i<len; i++) {
selectAlgo(p[i], selectedAlgo, selectedAlgoOutput, algoCount, &selectedCount);
if(selectedCount == algoCount) {
break;
}
}
if(selectedCount < algoCount) {
for(uint8_t i = 0; i < algoCount; i++) {
if(!selectedAlgo[i]) {
selectedAlgoOutput[selectedCount] = i;
selectedCount++;
}
}
}
delete [] selectedAlgo;
}
void print_hex_memory(void *mem, unsigned int size) {
unsigned char *p = (unsigned char *)mem;
unsigned int len = size/2;
for (unsigned int i=0;i<len; i++) {
printf("%02x", p[(len - i - 1)]);
}
printf("\n");
}
void SwapBytes(void *pv, unsigned int n)
{
char *p = (char*)pv;
unsigned int lo, hi;
for(lo=0, hi=n-1; hi>lo; lo++, hi--)
{
char tmp=p[lo];
p[lo] = p[hi];
p[hi] = tmp;
}
}
void flex_hash(const char* input, char* output, cryptonight_ctx** ctx) {
uint32_t hash[64/4];
sph_blake512_context ctx_blake;
sph_bmw512_context ctx_bmw;
sph_groestl512_context ctx_groestl;
sph_keccak512_context ctx_keccak;
sph_skein512_context ctx_skein;
sph_luffa512_context ctx_luffa;
sph_cubehash512_context ctx_cubehash;
sph_shavite512_context ctx_shavite;
sph_simd512_context ctx_simd;
sph_echo512_context ctx_echo;
sph_hamsi512_context ctx_hamsi;
sph_fugue512_context ctx_fugue;
sph_shabal512_context ctx_shabal;
sph_whirlpool_context ctx_whirlpool;
void *in = (void*) input;
int size = 80;
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, in, size);
sph_keccak512_close(&ctx_keccak, hash);
uint8_t selectedAlgoOutput[15] = {0};
uint8_t selectedCNAlgoOutput[14] = {0};
getAlgoString(&hash, 64, selectedAlgoOutput, 14);
getAlgoString(&hash, 64, selectedCNAlgoOutput, 6);
//printf("previous hash=");
//print_hex_memory(&input[4], 64);
const CnHash::AlgoVariant av = Cpu::info()->hasAES() ? CnHash::AV_SINGLE : CnHash::AV_SINGLE_SOFT;
int i;
for (i = 0; i < 18; i++)
{
uint8_t algo;
uint8_t cnAlgo;
int coreSelection;
int cnSelection = -1;
if(i < 5) {
coreSelection = i;
} else if(i < 11) {
coreSelection = i-1;
} else {
coreSelection = i-2;
}
if(i==5) {
coreSelection = -1;
cnSelection = 0;
}
if(i==11) {
coreSelection = -1;
cnSelection = 1;
}
if(i==17) {
coreSelection = -1;
cnSelection = 2;
}
if(coreSelection >= 0) {
algo = selectedAlgoOutput[(uint8_t)coreSelection];
} else {
algo = 16; // skip core hashing for this loop iteration
}
if(cnSelection >=0) {
cnAlgo = selectedCNAlgoOutput[(uint8_t)cnSelection];
} else {
cnAlgo = 14; // skip cn hashing for this loop iteration
}
//selection cnAlgo. if a CN algo is selected then core algo will not be selected
cn_hash_fun f;
switch(cnAlgo)
{
case CNDark:
//cryptonightdark_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_0, av, Assembly::AUTO);
break;
case CNDarklite:
//cryptonightdarklite_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_1, av, Assembly::AUTO);
break;
case CNFast:
//cryptonightfast_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_2, av, Assembly::AUTO);
break;
case CNLite:
//cryptonightlite_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_3, av, Assembly::AUTO);
break;
case CNTurtle:
//cryptonightturtle_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_4, av, Assembly::AUTO);
break;
case CNTurtlelite:
//cryptonightturtlelite_hash((const char*)in, (char*)hash, size, 1);
f = CnHash::fn(Algorithm::CN_GR_5, av, Assembly::AUTO);
break;
default:
f = nullptr;
}
if (f) f((const uint8_t*)in, size, (uint8_t*)hash, ctx, 101);
//selection core algo
switch (algo) {
case BLAKE:
sph_blake512_init(&ctx_blake);
sph_blake512(&ctx_blake, in, size);
sph_blake512_close(&ctx_blake, hash);
break;
case BMW:
sph_bmw512_init(&ctx_bmw);
sph_bmw512(&ctx_bmw, in, size);
sph_bmw512_close(&ctx_bmw, hash);
break;
case GROESTL:
sph_groestl512_init(&ctx_groestl);
sph_groestl512(&ctx_groestl, in, size);
sph_groestl512_close(&ctx_groestl, hash);
break;
case KECCAK:
sph_keccak512_init(&ctx_keccak);
sph_keccak512(&ctx_keccak, in, size);
sph_keccak512_close(&ctx_keccak, hash);
break;
case SKEIN:
sph_skein512_init(&ctx_skein);
sph_skein512(&ctx_skein, in, size);
sph_skein512_close(&ctx_skein, hash);
break;
case LUFFA:
sph_luffa512_init(&ctx_luffa);
sph_luffa512(&ctx_luffa, in, size);
sph_luffa512_close(&ctx_luffa, hash);
break;
case CUBEHASH:
sph_cubehash512_init(&ctx_cubehash);
sph_cubehash512(&ctx_cubehash, in, size);
sph_cubehash512_close(&ctx_cubehash, hash);
break;
case SHAVITE:
sph_shavite512_init(&ctx_shavite);
sph_shavite512(&ctx_shavite, in, size);
sph_shavite512_close(&ctx_shavite, hash);
break;
case SIMD:
sph_simd512_init(&ctx_simd);
sph_simd512(&ctx_simd, in, size);
sph_simd512_close(&ctx_simd, hash);
break;
case ECHO:
sph_echo512_init(&ctx_echo);
sph_echo512(&ctx_echo, in, size);
sph_echo512_close(&ctx_echo, hash);
break;
case HAMSI:
sph_hamsi512_init(&ctx_hamsi);
sph_hamsi512(&ctx_hamsi, in, size);
sph_hamsi512_close(&ctx_hamsi, hash);
break;
case FUGUE:
sph_fugue512_init(&ctx_fugue);
sph_fugue512(&ctx_fugue, in, size);
sph_fugue512_close(&ctx_fugue, hash);
break;
case SHABAL:
sph_shabal512_init(&ctx_shabal);
sph_shabal512(&ctx_shabal, in, size);
sph_shabal512_close(&ctx_shabal, hash);
break;
case WHIRLPOOL:
sph_whirlpool_init(&ctx_whirlpool);
sph_whirlpool(&ctx_whirlpool, in, size);
sph_whirlpool_close(&ctx_whirlpool, hash);
break;
}
in = (void*) hash;
size = 64;
}
sph_keccak256_init(&ctx_keccak);
sph_keccak256(&ctx_keccak, in, size);
sph_keccak256_close(&ctx_keccak, hash);
memcpy(output, hash, 32);
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
struct cryptonight_ctx;
void flex_hash(const char* input, char* output, cryptonight_ctx** ctx);
@@ -22,7 +22,6 @@
mov rsi, rdx ;# uint8_t* scratchpad mov rsi, rdx ;# uint8_t* scratchpad
mov rax, rbp mov rax, rbp
ror rbp, 32
;# zero integer registers ;# zero integer registers
xor r8, r8 xor r8, r8
@@ -35,7 +35,6 @@
mov rbx, r9 ;# loop counter mov rbx, r9 ;# loop counter
mov rax, rbp mov rax, rbp
ror rbp, 32
;# zero integer registers ;# zero integer registers
xor r8, r8 xor r8, r8
+12 -11
View File
@@ -1,16 +1,17 @@
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" xor rbp, rax ;# modify "mx"
mov edx, ebp ;# edx = mx mov edx, ebp ;# edx = mx
and edx, RANDOMX_DATASET_BASE_MASK and edx, RANDOMX_DATASET_BASE_MASK
prefetchnta byte ptr [rdi+rdx] prefetchnta byte ptr [rdi+rdx]
xor r9, qword ptr [rdi+rcx+8] ror rbp, 32 ;# swap "ma" and "mx"
xor r10, qword ptr [rdi+rcx+16] mov edx, ebp ;# edx = ma
xor r11, qword ptr [rdi+rcx+24] and edx, RANDOMX_DATASET_BASE_MASK
xor r12, qword ptr [rdi+rcx+32] lea rcx, [rdi+rdx] ;# dataset cache line
xor r13, qword ptr [rdi+rcx+40] xor r8, qword ptr [rcx+0]
xor r14, qword ptr [rdi+rcx+48] xor r9, qword ptr [rcx+8]
xor r15, qword ptr [rdi+rcx+56] 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]
@@ -0,0 +1,17 @@
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]
+1 -1
View File
@@ -74,7 +74,7 @@ namespace randomx {
constexpr int SuperscalarMaxSize = 3 * RANDOMX_SUPERSCALAR_MAX_LATENCY + 2; constexpr int SuperscalarMaxSize = 3 * RANDOMX_SUPERSCALAR_MAX_LATENCY + 2;
constexpr size_t CacheLineSize = RANDOMX_DATASET_ITEM_SIZE; constexpr size_t CacheLineSize = RANDOMX_DATASET_ITEM_SIZE;
#define ScratchpadSize RandomX_CurrentConfig.ScratchpadL3_Size #define ScratchpadSize RandomX_CurrentConfig.ScratchpadL3_Size
#define CacheLineAlignMask RandomX_ConfigurationBase::CacheLineAlignMask_Calculated #define CacheLineAlignMask RandomX_CurrentConfig.CacheLineAlignMask_Calculated
#define DatasetExtraItems RandomX_ConfigurationBase::DatasetExtraItems_Calculated #define DatasetExtraItems RandomX_ConfigurationBase::DatasetExtraItems_Calculated
constexpr int StoreL3Condition = 14; constexpr int StoreL3Condition = 14;
+2 -2
View File
@@ -90,7 +90,7 @@ static size_t CalcDatasetItemSize()
// Prologue // Prologue
((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch - (uint8_t*)randomx_calc_dataset_item_aarch64) + ((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch - (uint8_t*)randomx_calc_dataset_item_aarch64) +
// Main loop // Main loop
RandomX_ConfigurationBase::CacheAccesses * ( RandomX_CurrentConfig.CacheAccesses * (
// Main loop prologue // Main loop prologue
((uint8_t*)randomx_calc_dataset_item_aarch64_mix - ((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch)) + 4 + ((uint8_t*)randomx_calc_dataset_item_aarch64_mix - ((uint8_t*)randomx_calc_dataset_item_aarch64_prefetch)) + 4 +
// Inner main loop (instructions) // Inner main loop (instructions)
@@ -259,7 +259,7 @@ void JitCompilerA64::generateSuperscalarHash(SuperscalarProgram(&programs)[N])
num32bitLiterals = 64; num32bitLiterals = 64;
constexpr uint32_t tmp_reg = 12; constexpr uint32_t tmp_reg = 12;
for (size_t i = 0; i < RandomX_ConfigurationBase::CacheAccesses; ++i) for (size_t i = 0; i < RandomX_CurrentConfig.CacheAccesses; ++i)
{ {
// and x11, x10, CacheSize / CacheLineSize - 1 // and x11, x10, CacheSize / CacheLineSize - 1
emit32(0x92400000 | 11 | (10 << 5) | ((RandomX_CurrentConfig.Log2_CacheSize - 1) << 10), code, codePos); emit32(0x92400000 | 11 | (10 << 5) | ((RandomX_CurrentConfig.Log2_CacheSize - 1) << 10), code, codePos);
+14 -1
View File
@@ -337,7 +337,20 @@ namespace randomx {
vm_flags = flags; vm_flags = flags;
generateProgramPrologue(prog, pcfg); generateProgramPrologue(prog, pcfg);
emit(codeReadDataset, readDatasetSize, code, codePos);
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;
generateProgramEpilogue(prog, pcfg); generateProgramEpilogue(prog, pcfg);
} }
@@ -48,6 +48,7 @@
.global DECL(randomx_program_loop_load_xop) .global DECL(randomx_program_loop_load_xop)
.global DECL(randomx_program_start) .global DECL(randomx_program_start)
.global DECL(randomx_program_read_dataset) .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_init)
.global DECL(randomx_program_read_dataset_sshash_fin) .global DECL(randomx_program_read_dataset_sshash_fin)
.global DECL(randomx_program_loop_store) .global DECL(randomx_program_loop_store)
@@ -139,6 +140,9 @@ DECL(randomx_program_start):
DECL(randomx_program_read_dataset): DECL(randomx_program_read_dataset):
#include "asm/program_read_dataset.inc" #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): DECL(randomx_program_read_dataset_sshash_init):
#include "asm/program_read_dataset_sshash_init.inc" #include "asm/program_read_dataset_sshash_init.inc"
@@ -39,6 +39,7 @@ PUBLIC randomx_program_loop_load
PUBLIC randomx_program_loop_load_xop PUBLIC randomx_program_loop_load_xop
PUBLIC randomx_program_start PUBLIC randomx_program_start
PUBLIC randomx_program_read_dataset PUBLIC randomx_program_read_dataset
PUBLIC randomx_program_read_dataset_ryzen
PUBLIC randomx_program_read_dataset_sshash_init PUBLIC randomx_program_read_dataset_sshash_init
PUBLIC randomx_program_read_dataset_sshash_fin PUBLIC randomx_program_read_dataset_sshash_fin
PUBLIC randomx_dataset_init PUBLIC randomx_dataset_init
@@ -135,6 +136,10 @@ randomx_program_read_dataset PROC
include asm/program_read_dataset.inc include asm/program_read_dataset.inc
randomx_program_read_dataset ENDP randomx_program_read_dataset ENDP
randomx_program_read_dataset_ryzen PROC
include asm/program_read_dataset_ryzen.inc
randomx_program_read_dataset_ryzen ENDP
randomx_program_read_dataset_sshash_init PROC randomx_program_read_dataset_sshash_init PROC
include asm/program_read_dataset_sshash_init.inc include asm/program_read_dataset_sshash_init.inc
randomx_program_read_dataset_sshash_init ENDP randomx_program_read_dataset_sshash_init ENDP
@@ -40,6 +40,7 @@ extern "C" {
void randomx_program_loop_load_xop(); void randomx_program_loop_load_xop();
void randomx_program_start(); void randomx_program_start();
void randomx_program_read_dataset(); void randomx_program_read_dataset();
void randomx_program_read_dataset_ryzen();
void randomx_program_read_dataset_sshash_init(); void randomx_program_read_dataset_sshash_init();
void randomx_program_read_dataset_sshash_fin(); void randomx_program_read_dataset_sshash_fin();
void randomx_program_loop_store(); void randomx_program_loop_store();
@@ -0,0 +1,271 @@
/*
Implementation by Ronny Van Keer, hereby denoted as "the implementer".
For more information, feedback or questions, please refer to our website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#include <string.h>
#include "KangarooTwelve.h"
#ifndef KeccakP1600timesN_excluded
// #include "KeccakP-1600-times2-SnP.h"
// #include "KeccakP-1600-times4-SnP.h"
// #include "KeccakP-1600-times8-SnP.h"
#endif
#define chunkSize 8192
#define laneSize 8
#define suffixLeaf 0x0B /* '110': message hop, simple padding, inner node */
#define security 128
#define capacity (2*security)
#define capacityInBytes (capacity/8)
#define capacityInLanes (capacityInBytes/laneSize)
#define rate (1600-capacity)
#define rateInBytes (rate/8)
#define rateInLanes (rateInBytes/laneSize)
#define ParallelSpongeFastLoop( Parallellism ) \
while ( inLen >= Parallellism * chunkSize ) { \
ALIGN(KeccakP1600times##Parallellism##_statesAlignment) unsigned char states[KeccakP1600times##Parallellism##_statesSizeInBytes]; \
unsigned char intermediate[Parallellism*capacityInBytes]; \
unsigned int localBlockLen = chunkSize; \
const unsigned char * localInput = input; \
unsigned int i; \
unsigned int fastLoopOffset; \
\
KeccakP1600times##Parallellism##_StaticInitialize(); \
KeccakP1600times##Parallellism##_InitializeAll(states); \
fastLoopOffset = KeccakP1600times##Parallellism##_12rounds_FastLoop_Absorb(states, rateInLanes, chunkSize / laneSize, rateInLanes, localInput, Parallellism * chunkSize); \
localBlockLen -= fastLoopOffset; \
localInput += fastLoopOffset; \
for ( i = 0; i < Parallellism; ++i, localInput += chunkSize ) { \
KeccakP1600times##Parallellism##_AddBytes(states, i, localInput, 0, localBlockLen); \
KeccakP1600times##Parallellism##_AddByte(states, i, suffixLeaf, localBlockLen); \
KeccakP1600times##Parallellism##_AddByte(states, i, 0x80, rateInBytes-1); \
} \
KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \
input += Parallellism * chunkSize; \
inLen -= Parallellism * chunkSize; \
ktInstance->blockNumber += Parallellism; \
KeccakP1600times##Parallellism##_ExtractLanesAll(states, intermediate, capacityInLanes, capacityInLanes ); \
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, Parallellism * capacityInBytes) != 0) return 1; \
}
#define ParallelSpongeLoop( Parallellism ) \
while ( inLen >= Parallellism * chunkSize ) { \
ALIGN(KeccakP1600times##Parallellism##_statesAlignment) unsigned char states[KeccakP1600times##Parallellism##_statesSizeInBytes]; \
unsigned char intermediate[Parallellism*capacityInBytes]; \
unsigned int localBlockLen = chunkSize; \
const unsigned char * localInput = input; \
unsigned int i; \
\
KeccakP1600times##Parallellism##_StaticInitialize(); \
KeccakP1600times##Parallellism##_InitializeAll(states); \
while(localBlockLen >= rateInBytes) { \
KeccakP1600times##Parallellism##_AddLanesAll(states, localInput, rateInLanes, chunkSize / laneSize); \
KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \
localBlockLen -= rateInBytes; \
localInput += rateInBytes; \
} \
for ( i = 0; i < Parallellism; ++i, localInput += chunkSize ) { \
KeccakP1600times##Parallellism##_AddBytes(states, i, localInput, 0, localBlockLen); \
KeccakP1600times##Parallellism##_AddByte(states, i, suffixLeaf, localBlockLen); \
KeccakP1600times##Parallellism##_AddByte(states, i, 0x80, rateInBytes-1); \
} \
KeccakP1600times##Parallellism##_PermuteAll_12rounds(states); \
input += Parallellism * chunkSize; \
inLen -= Parallellism * chunkSize; \
ktInstance->blockNumber += Parallellism; \
KeccakP1600times##Parallellism##_ExtractLanesAll(states, intermediate, capacityInLanes, capacityInLanes ); \
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, Parallellism * capacityInBytes) != 0) return 1; \
}
static unsigned int right_encode( unsigned char * encbuf, size_t value )
{
unsigned int n, i;
size_t v;
for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
; /* empty */
for ( i = 1; i <= n; ++i )
encbuf[i-1] = (unsigned char)(value >> (8 * (n-i)));
encbuf[n] = (unsigned char)n;
return n + 1;
}
int KangarooTwelve_Initialize(KangarooTwelve_Instance *ktInstance, size_t outputLen)
{
ktInstance->fixedOutputLength = outputLen;
ktInstance->queueAbsorbedLen = 0;
ktInstance->blockNumber = 0;
ktInstance->phase = ABSORBING;
return KeccakWidth1600_12rounds_SpongeInitialize(&ktInstance->finalNode, rate, capacity);
}
int KangarooTwelve_Update(KangarooTwelve_Instance *ktInstance, const unsigned char *input, size_t inLen)
{
if (ktInstance->phase != ABSORBING)
return 1;
if ( ktInstance->blockNumber == 0 ) {
/* First block, absorb in final node */
unsigned int len = (inLen < (chunkSize - ktInstance->queueAbsorbedLen)) ? inLen : (chunkSize - ktInstance->queueAbsorbedLen);
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, input, len) != 0)
return 1;
input += len;
inLen -= len;
ktInstance->queueAbsorbedLen += len;
if ( (ktInstance->queueAbsorbedLen == chunkSize) && (inLen != 0) ) {
/* First block complete and more input data available, finalize it */
const unsigned char padding = 0x03; /* '110^6': message hop, simple padding */
ktInstance->queueAbsorbedLen = 0;
ktInstance->blockNumber = 1;
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, &padding, 1) != 0)
return 1;
ktInstance->finalNode.byteIOIndex = (ktInstance->finalNode.byteIOIndex + 7) & ~7; /* Zero padding up to 64 bits */
}
}
else if ( ktInstance->queueAbsorbedLen != 0 ) {
/* There is data in the queue, absorb further in queue until block complete */
unsigned int len = (inLen < (chunkSize - ktInstance->queueAbsorbedLen)) ? inLen : (chunkSize - ktInstance->queueAbsorbedLen);
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->queueNode, input, len) != 0)
return 1;
input += len;
inLen -= len;
ktInstance->queueAbsorbedLen += len;
if ( ktInstance->queueAbsorbedLen == chunkSize ) {
unsigned char intermediate[capacityInBytes];
ktInstance->queueAbsorbedLen = 0;
++ktInstance->blockNumber;
if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0)
return 1;
if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0)
return 1;
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0)
return 1;
}
}
#if defined(KeccakP1600times8_implementation) && !defined(KeccakP1600times8_isFallback)
#if defined(KeccakP1600times8_12rounds_FastLoop_supported)
ParallelSpongeFastLoop( 8 )
#else
ParallelSpongeLoop( 8 )
#endif
#endif
#if defined(KeccakP1600times4_implementation) && !defined(KeccakP1600times4_isFallback)
#if defined(KeccakP1600times4_12rounds_FastLoop_supported)
ParallelSpongeFastLoop( 4 )
#else
ParallelSpongeLoop( 4 )
#endif
#endif
#if defined(KeccakP1600times2_implementation) && !defined(KeccakP1600times2_isFallback)
#if defined(KeccakP1600times2_12rounds_FastLoop_supported)
ParallelSpongeFastLoop( 2 )
#else
ParallelSpongeLoop( 2 )
#endif
#endif
while ( inLen > 0 ) {
unsigned int len = (inLen < chunkSize) ? inLen : chunkSize;
if (KeccakWidth1600_12rounds_SpongeInitialize(&ktInstance->queueNode, rate, capacity) != 0)
return 1;
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->queueNode, input, len) != 0)
return 1;
input += len;
inLen -= len;
if ( len == chunkSize ) {
unsigned char intermediate[capacityInBytes];
++ktInstance->blockNumber;
if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0)
return 1;
if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0)
return 1;
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0)
return 1;
}
else
ktInstance->queueAbsorbedLen = len;
}
return 0;
}
int KangarooTwelve_Final(KangarooTwelve_Instance *ktInstance, unsigned char * output, const unsigned char * customization, size_t customLen)
{
unsigned char encbuf[sizeof(size_t)+1+2];
unsigned char padding;
if (ktInstance->phase != ABSORBING)
return 1;
/* Absorb customization | right_encode(customLen) */
if ((customLen != 0) && (KangarooTwelve_Update(ktInstance, customization, customLen) != 0))
return 1;
if (KangarooTwelve_Update(ktInstance, encbuf, right_encode(encbuf, customLen)) != 0)
return 1;
if ( ktInstance->blockNumber == 0 ) {
/* Non complete first block in final node, pad it */
padding = 0x07; /* '11': message hop, final node */
}
else {
unsigned int n;
if ( ktInstance->queueAbsorbedLen != 0 ) {
/* There is data in the queue node */
unsigned char intermediate[capacityInBytes];
++ktInstance->blockNumber;
if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->queueNode, suffixLeaf) != 0)
return 1;
if (KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->queueNode, intermediate, capacityInBytes) != 0)
return 1;
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, intermediate, capacityInBytes) != 0)
return 1;
}
--ktInstance->blockNumber; /* Absorb right_encode(number of Chaining Values) || 0xFF || 0xFF */
n = right_encode(encbuf, ktInstance->blockNumber);
encbuf[n++] = 0xFF;
encbuf[n++] = 0xFF;
if (KeccakWidth1600_12rounds_SpongeAbsorb(&ktInstance->finalNode, encbuf, n) != 0)
return 1;
padding = 0x06; /* '01': chaining hop, final node */
}
if (KeccakWidth1600_12rounds_SpongeAbsorbLastFewBits(&ktInstance->finalNode, padding) != 0)
return 1;
if ( ktInstance->fixedOutputLength != 0 ) {
ktInstance->phase = FINAL;
return KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->finalNode, output, ktInstance->fixedOutputLength);
}
ktInstance->phase = SQUEEZING;
return 0;
}
int KangarooTwelve_Squeeze(KangarooTwelve_Instance *ktInstance, unsigned char * output, size_t outputLen)
{
if (ktInstance->phase != SQUEEZING)
return 1;
return KeccakWidth1600_12rounds_SpongeSqueeze(&ktInstance->finalNode, output, outputLen);
}
int KangarooTwelve( const unsigned char * input, size_t inLen, unsigned char * output, size_t outLen, const unsigned char * customization, size_t customLen )
{
KangarooTwelve_Instance ktInstance;
if (outLen == 0)
return 1;
if (KangarooTwelve_Initialize(&ktInstance, outLen) != 0)
return 1;
if (KangarooTwelve_Update(&ktInstance, input, inLen) != 0)
return 1;
return KangarooTwelve_Final(&ktInstance, output, customization, customLen);
}
@@ -0,0 +1,89 @@
/*
Implementation by Ronny Van Keer, hereby denoted as "the implementer".
For more information, feedback or questions, please refer to our website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KangarooTwelve_h_
#define _KangarooTwelve_h_
#ifndef KeccakP1600_excluded
#include <stddef.h>
#include "align.h"
#include "KeccakSpongeWidth1600.h"
#include "Phases.h"
typedef KCP_Phases KangarooTwelve_Phases;
typedef struct {
KeccakWidth1600_12rounds_SpongeInstance queueNode;
KeccakWidth1600_12rounds_SpongeInstance finalNode;
size_t fixedOutputLength;
size_t blockNumber;
unsigned int queueAbsorbedLen;
KangarooTwelve_Phases phase;
} KangarooTwelve_Instance;
/** Extendable ouput function KangarooTwelve.
* @param input Pointer to the input message (M).
* @param inputByteLen The length of the input message in bytes.
* @param output Pointer to the output buffer.
* @param outputByteLen The desired number of output bytes.
* @param customization Pointer to the customization string (C).
* @param customByteLen The length of the customization string in bytes.
* @return 0 if successful, 1 otherwise.
*/
int KangarooTwelve(const unsigned char *input, size_t inputByteLen, unsigned char *output, size_t outputByteLen, const unsigned char *customization, size_t customByteLen );
/**
* Function to initialize a KangarooTwelve instance.
* @param ktInstance Pointer to the instance to be initialized.
* @param outputByteLen The desired number of output bytes,
* or 0 for an arbitrarily-long output.
* @return 0 if successful, 1 otherwise.
*/
int KangarooTwelve_Initialize(KangarooTwelve_Instance *ktInstance, size_t outputByteLen);
/**
* Function to give input data to be absorbed.
* @param ktInstance Pointer to the instance initialized by KangarooTwelve_Initialize().
* @param input Pointer to the input message data (M).
* @param inputByteLen The number of bytes provided in the input message data.
* @return 0 if successful, 1 otherwise.
*/
int KangarooTwelve_Update(KangarooTwelve_Instance *ktInstance, const unsigned char *input, size_t inputByteLen);
/**
* Function to call after all the input message has been input, and to get
* output bytes if the length was specified when calling KangarooTwelve_Initialize().
* @param ktInstance Pointer to the hash instance initialized by KangarooTwelve_Initialize().
* If @a outputByteLen was not 0 in the call to KangarooTwelve_Initialize(), the number of
* output bytes is equal to @a outputByteLen.
* If @a outputByteLen was 0 in the call to KangarooTwelve_Initialize(), the output bytes
* must be extracted using the KangarooTwelve_Squeeze() function.
* @param output Pointer to the buffer where to store the output data.
* @param customization Pointer to the customization string (C).
* @param customByteLen The length of the customization string in bytes.
* @return 0 if successful, 1 otherwise.
*/
int KangarooTwelve_Final(KangarooTwelve_Instance *ktInstance, unsigned char *output, const unsigned char *customization, size_t customByteLen);
/**
* Function to squeeze output data.
* @param ktInstance Pointer to the hash instance initialized by KangarooTwelve_Initialize().
* @param data Pointer to the buffer where to store the output data.
* @param outputByteLen The number of output bytes desired.
* @pre KangarooTwelve_Final() must have been already called.
* @return 0 if successful, 1 otherwise.
*/
int KangarooTwelve_Squeeze(KangarooTwelve_Instance *ktInstance, unsigned char *output, size_t outputByteLen);
#endif
#endif
@@ -0,0 +1,41 @@
/*
Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
hereby denoted as "the implementer".
For more information, feedback or questions, please refer to our website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
---
Please refer to SnP-documentation.h for more details.
*/
#ifndef _KeccakP_1600_SnP_h_
#define _KeccakP_1600_SnP_h_
#define KeccakP1600_implementation "64-bit reference implementation"
#define KeccakP1600_stateSizeInBytes 200
#define KeccakP1600_stateAlignment 8
#ifdef KeccakReference
void KeccakP1600_StaticInitialize( void );
#else
#define KeccakP1600_StaticInitialize()
#endif
void KeccakP1600_Initialize(void *state);
void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset);
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount);
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds);
void KeccakP1600_Permute_12rounds(void *state);
void KeccakP1600_Permute_24rounds(void *state);
void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length);
void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);
#endif
@@ -0,0 +1,402 @@
/*
Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
hereby denoted as "the implementer".
For more information, feedback or questions, please refer to our website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
---
This file implements Keccak-p[1600] in a SnP-compatible way.
Please refer to SnP-documentation.h for more details.
This implementation comes with KeccakP-1600-SnP.h in the same folder.
Please refer to LowLevel.build for the exact list of other files it must be combined with.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "brg_endian.h"
#ifdef KeccakReference
#include "displayIntermediateValues.h"
#endif
typedef unsigned char UINT8;
typedef unsigned long long UINT64;
typedef UINT64 tKeccakLane;
#define maxNrRounds 24
#define nrLanes 25
#define index(x, y) (((x)%5)+5*((y)%5))
#ifdef KeccakReference
static tKeccakLane KeccakRoundConstants[maxNrRounds];
static unsigned int KeccakRhoOffsets[nrLanes];
/* ---------------------------------------------------------------- */
void KeccakP1600_InitializeRoundConstants(void);
void KeccakP1600_InitializeRhoOffsets(void);
static int LFSR86540(UINT8 *LFSR);
void KeccakP1600_StaticInitialize(void)
{
if (sizeof(tKeccakLane) != 8) {
printf("tKeccakLane should be 64-bit wide\n");
abort();
}
KeccakP1600_InitializeRoundConstants();
KeccakP1600_InitializeRhoOffsets();
}
void KeccakP1600_InitializeRoundConstants(void)
{
UINT8 LFSRstate = 0x01;
unsigned int i, j, bitPosition;
for(i=0; i<maxNrRounds; i++) {
KeccakRoundConstants[i] = 0;
for(j=0; j<7; j++) {
bitPosition = (1<<j)-1; /* 2^j-1 */
if (LFSR86540(&LFSRstate))
KeccakRoundConstants[i] ^= (tKeccakLane)1<<bitPosition;
}
}
}
void KeccakP1600_InitializeRhoOffsets(void)
{
unsigned int x, y, t, newX, newY;
KeccakRhoOffsets[index(0, 0)] = 0;
x = 1;
y = 0;
for(t=0; t<24; t++) {
KeccakRhoOffsets[index(x, y)] = ((t+1)*(t+2)/2) % 64;
newX = (0*x+1*y) % 5;
newY = (2*x+3*y) % 5;
x = newX;
y = newY;
}
}
static int LFSR86540(UINT8 *LFSR)
{
int result = ((*LFSR) & 0x01) != 0;
if (((*LFSR) & 0x80) != 0)
/* Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1 */
(*LFSR) = ((*LFSR) << 1) ^ 0x71;
else
(*LFSR) <<= 1;
return result;
}
#else
static const tKeccakLane KeccakRoundConstants[maxNrRounds] =
{
0x0000000000000001,
0x0000000000008082,
0x800000000000808a,
0x8000000080008000,
0x000000000000808b,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008a,
0x0000000000000088,
0x0000000080008009,
0x000000008000000a,
0x000000008000808b,
0x800000000000008b,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800a,
0x800000008000000a,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008,
};
static const unsigned int KeccakRhoOffsets[nrLanes] =
{
0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14
};
#endif
/* ---------------------------------------------------------------- */
void KeccakP1600_Initialize(void *state)
{
memset(state, 0, 1600/8);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset)
{
assert(offset < 200);
((unsigned char *)state)[offset] ^= byte;
}
/* ---------------------------------------------------------------- */
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
{
unsigned int i;
assert(offset < 200);
assert(offset+length <= 200);
for(i=0; i<length; i++)
((unsigned char *)state)[offset+i] ^= data[i];
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length)
{
assert(offset < 200);
assert(offset+length <= 200);
memcpy((unsigned char*)state+offset, data, length);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount)
{
assert(byteCount <= 200);
memset(state, 0, byteCount);
}
/* ---------------------------------------------------------------- */
void KeccakP1600OnWords(tKeccakLane *state, unsigned int nrRounds);
void KeccakP1600Round(tKeccakLane *state, unsigned int indexRound);
static void theta(tKeccakLane *A);
static void rho(tKeccakLane *A);
static void pi(tKeccakLane *A);
static void chi(tKeccakLane *A);
static void iota(tKeccakLane *A, unsigned int indexRound);
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds)
{
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
tKeccakLane stateAsWords[1600/64];
#endif
#ifdef KeccakReference
displayStateAsBytes(1, "Input of permutation", (const unsigned char *)state, 1600);
#endif
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
KeccakP1600OnWords((tKeccakLane*)state, nrounds);
#else
fromBytesToWords(stateAsWords, (const unsigned char *)state);
KeccakP1600OnWords(stateAsWords, nrounds);
fromWordsToBytes((unsigned char *)state, stateAsWords);
#endif
#ifdef KeccakReference
displayStateAsBytes(1, "State after permutation", (const unsigned char *)state, 1600);
#endif
}
void KeccakP1600_Permute_12rounds(void *state)
{
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
tKeccakLane stateAsWords[1600/64];
#endif
#ifdef KeccakReference
displayStateAsBytes(1, "Input of permutation", (const unsigned char *)state, 1600);
#endif
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
KeccakP1600OnWords((tKeccakLane*)state, 12);
#else
fromBytesToWords(stateAsWords, (const unsigned char *)state);
KeccakP1600OnWords(stateAsWords, 12);
fromWordsToBytes((unsigned char *)state, stateAsWords);
#endif
#ifdef KeccakReference
displayStateAsBytes(1, "State after permutation", (const unsigned char *)state, 1600);
#endif
}
void KeccakP1600_Permute_24rounds(void *state)
{
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
tKeccakLane stateAsWords[1600/64];
#endif
#ifdef KeccakReference
displayStateAsBytes(1, "Input of permutation", (const unsigned char *)state, 1600);
#endif
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
KeccakP1600OnWords((tKeccakLane*)state, 24);
#else
fromBytesToWords(stateAsWords, (const unsigned char *)state);
KeccakP1600OnWords(stateAsWords, 24);
fromWordsToBytes((unsigned char *)state, stateAsWords);
#endif
#ifdef KeccakReference
displayStateAsBytes(1, "State after permutation", (const unsigned char *)state, 1600);
#endif
}
void KeccakP1600OnWords(tKeccakLane *state, unsigned int nrRounds)
{
unsigned int i;
#ifdef KeccakReference
displayStateAsLanes(3, "Same, with lanes as 64-bit words", state, 1600);
#endif
for(i=(maxNrRounds-nrRounds); i<maxNrRounds; i++)
KeccakP1600Round(state, i);
}
void KeccakP1600Round(tKeccakLane *state, unsigned int indexRound)
{
#ifdef KeccakReference
displayRoundNumber(3, indexRound);
#endif
theta(state);
#ifdef KeccakReference
displayStateAsLanes(3, "After theta", state, 1600);
#endif
rho(state);
#ifdef KeccakReference
displayStateAsLanes(3, "After rho", state, 1600);
#endif
pi(state);
#ifdef KeccakReference
displayStateAsLanes(3, "After pi", state, 1600);
#endif
chi(state);
#ifdef KeccakReference
displayStateAsLanes(3, "After chi", state, 1600);
#endif
iota(state, indexRound);
#ifdef KeccakReference
displayStateAsLanes(3, "After iota", state, 1600);
#endif
}
#define ROL64(a, offset) ((offset != 0) ? ((((tKeccakLane)a) << offset) ^ (((tKeccakLane)a) >> (64-offset))) : a)
static void theta(tKeccakLane *A)
{
unsigned int x, y;
tKeccakLane C[5], D[5];
for(x=0; x<5; x++) {
C[x] = 0;
for(y=0; y<5; y++)
C[x] ^= A[index(x, y)];
}
for(x=0; x<5; x++)
D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5];
for(x=0; x<5; x++)
for(y=0; y<5; y++)
A[index(x, y)] ^= D[x];
}
static void rho(tKeccakLane *A)
{
unsigned int x, y;
for(x=0; x<5; x++) for(y=0; y<5; y++)
A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x, y)]);
}
static void pi(tKeccakLane *A)
{
unsigned int x, y;
tKeccakLane tempA[25];
for(x=0; x<5; x++) for(y=0; y<5; y++)
tempA[index(x, y)] = A[index(x, y)];
for(x=0; x<5; x++) for(y=0; y<5; y++)
A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)];
}
static void chi(tKeccakLane *A)
{
unsigned int x, y;
tKeccakLane C[5];
for(y=0; y<5; y++) {
for(x=0; x<5; x++)
C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & A[index(x+2, y)]);
for(x=0; x<5; x++)
A[index(x, y)] = C[x];
}
}
static void iota(tKeccakLane *A, unsigned int indexRound)
{
A[index(0, 0)] ^= KeccakRoundConstants[indexRound];
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length)
{
assert(offset < 200);
assert(offset+length <= 200);
memcpy(data, (unsigned char*)state+offset, length);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length)
{
unsigned int i;
assert(offset < 200);
assert(offset+length <= 200);
for(i=0; i<length; i++)
output[i] = input[i] ^ ((unsigned char *)state)[offset+i];
}
/* ---------------------------------------------------------------- */
void KeccakP1600_DisplayRoundConstants(FILE *f)
{
unsigned int i;
for(i=0; i<maxNrRounds; i++) {
fprintf(f, "RC[%02i][0][0] = ", i);
fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] >> 32));
fprintf(f, "%08X", (unsigned int)(KeccakRoundConstants[i] & 0xFFFFFFFFULL));
fprintf(f, "\n");
}
fprintf(f, "\n");
}
void KeccakP1600_DisplayRhoOffsets(FILE *f)
{
unsigned int x, y;
for(y=0; y<5; y++) for(x=0; x<5; x++) {
fprintf(f, "RhoOffset[%i][%i] = ", x, y);
fprintf(f, "%2i", KeccakRhoOffsets[index(x, y)]);
fprintf(f, "\n");
}
fprintf(f, "\n");
}
@@ -0,0 +1,35 @@
/*
Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,
Michaël Peeters, Gilles Van Assche and Ronny Van Keer,
hereby denoted as "the implementer".
For more information, feedback or questions, please refer to our website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#ifndef _KeccakSpongeCommon_h_
#define _KeccakSpongeCommon_h_
#include <string.h>
#include "align.h"
#define KCP_DeclareSpongeStructure(prefix, size, alignment) \
ALIGN(alignment) typedef struct prefix##_SpongeInstanceStruct { \
unsigned char state[size]; \
unsigned int rate; \
unsigned int byteIOIndex; \
int squeezing; \
} prefix##_SpongeInstance;
#define KCP_DeclareSpongeFunctions(prefix) \
int prefix##_Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen); \
int prefix##_SpongeInitialize(prefix##_SpongeInstance *spongeInstance, unsigned int rate, unsigned int capacity); \
int prefix##_SpongeAbsorb(prefix##_SpongeInstance *spongeInstance, const unsigned char *data, size_t dataByteLen); \
int prefix##_SpongeAbsorbLastFewBits(prefix##_SpongeInstance *spongeInstance, unsigned char delimitedData); \
int prefix##_SpongeSqueeze(prefix##_SpongeInstance *spongeInstance, unsigned char *data, size_t dataByteLen);
#endif

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