]> git.sesse.net Git - stockfish/commitdiff
Merge remote-tracking branch 'upstream/master' into HEAD
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 14 Mar 2021 15:58:42 +0000 (16:58 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 14 Mar 2021 15:58:42 +0000 (16:58 +0100)
61 files changed:
.gitignore [new file with mode: 0644]
AUTHORS
README.md
Top CPU Contributors.txt
src/Makefile
src/benchmark.cpp
src/bitbase.cpp
src/bitboard.cpp
src/bitboard.h
src/endgame.cpp
src/endgame.h
src/evaluate.cpp
src/evaluate.h
src/main.cpp
src/material.cpp
src/material.h
src/misc.cpp
src/misc.h
src/movegen.cpp
src/movegen.h
src/movepick.cpp
src/movepick.h
src/nnue/architectures/halfkp_256x2-32-32.h
src/nnue/evaluate_nnue.cpp
src/nnue/evaluate_nnue.h
src/nnue/features/feature_set.h
src/nnue/features/features_common.h
src/nnue/features/half_kp.cpp
src/nnue/features/half_kp.h
src/nnue/features/index_list.h
src/nnue/layers/affine_transform.h
src/nnue/layers/clipped_relu.h
src/nnue/layers/input_slice.h
src/nnue/nnue_accumulator.h
src/nnue/nnue_architecture.h
src/nnue/nnue_common.h
src/nnue/nnue_feature_transformer.h
src/pawns.cpp
src/pawns.h
src/position.cpp
src/position.h
src/psqt.cpp
src/psqt.h [new file with mode: 0644]
src/search.cpp
src/search.h
src/syzygy/tbprobe.cpp
src/syzygy/tbprobe.h
src/thread.cpp
src/thread.h
src/thread_win32_osx.h
src/timeman.cpp
src/timeman.h
src/tt.cpp
src/tt.h
src/tune.cpp
src/tune.h
src/types.h
src/uci.cpp
src/uci.h
src/ucioption.cpp
tests/instrumented.sh

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8981efc
--- /dev/null
@@ -0,0 +1,12 @@
+# Files from build
+**/*.o
+**/*.s
+src/.depend
+
+# Built binary
+src/stockfish*
+src/-lstdc++.res
+
+# Neural network for the NNUE evaluation
+**/*.nnue
+
diff --git a/AUTHORS b/AUTHORS
index b31a36e9d625f5d61ca620b4c333c0de98cfa3d2..662cc6ecef96cc0a7ff0bf6051f14f26c55386f4 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -24,6 +24,7 @@ Ali AlZhrani (Cooffe)
 Andrew Grant (AndyGrant)
 Andrey Neporada (nepal)
 Andy Duplain
+Antoine Champion (antoinechampion)
 Aram Tumanian (atumanian)
 Arjun Temurnikar
 Auguste Pop
@@ -33,6 +34,7 @@ Bill Henry (VoyagerOne)
 Bojun Guo (noobpwnftw, Nooby)
 braich
 Brian Sheppard (SapphireBrand, briansheppard-toast)
+Bruno de Melo Costa (BM123499)
 Bryan Cross (crossbr)
 candirufish
 Chess13234
@@ -45,6 +47,7 @@ Dariusz Orzechowski (dorzechowski)
 David Zar
 Daylen Yang (daylen)
 Deshawn Mohan-Smith (GoldenRare)
+Dieter Dobbelaere (ddobbelaere)
 DiscanX
 Dominik Schlösser (domschl)
 double-beep
@@ -98,6 +101,7 @@ Ken Takusagawa
 kinderchocolate
 Kiran Panditrao (Krgp)
 Kojirion
+Krystian Kuzniarek (kuzkry)
 Leonardo Ljubičić (ICCF World Champion)
 Leonid Pechenik (lp--)
 Linus Arver (listx)
@@ -110,6 +114,7 @@ Maciej Żenczykowski (zenczykowski)
 Malcolm Campbell (xoto10)
 Mark Tenzer (31m059)
 marotear
+Matt Ginsberg (mattginsberg)
 Matthew Lai (matthewlai)
 Matthew Sullivan (Matt14916)
 Maxim Molchanov (Maxim)
@@ -163,6 +168,7 @@ Sergio Vieri (sergiovieri)
 sf-x
 Shane Booth (shane31)
 Shawn Varghese (xXH4CKST3RXx)
+Siad Daboul (Topologist)
 Stefan Geschwentner (locutus2)
 Stefano Cardanobile (Stefano80)
 Steinar Gunderson (sesse)
index eb7aa5a749a39b1dee310e3626e8700dd7358f75..fdc6fd619fa0ba1c6e5ef5f8889b6025ba8efa40 100644 (file)
--- a/README.md
+++ b/README.md
@@ -24,6 +24,8 @@ This distribution of Stockfish consists of the following files:
   * Readme.md, the file you are currently reading.
 
   * Copying.txt, a text file containing the GNU General Public License version 3.
+  
+  * AUTHORS, a text file with the list of authors for the project
 
   * src, a subdirectory containing the full source code, including a Makefile
     that can be used to compile Stockfish on Unix-like systems.
@@ -31,17 +33,6 @@ This distribution of Stockfish consists of the following files:
   * a file with the .nnue extension, storing the neural network for the NNUE 
     evaluation. Binary distributions will have this file embedded.
 
-Note: to use the NNUE evaluation, the additional data file with neural network parameters
-needs to be available. Normally, this file is already embedded in the binary or it can be downloaded.
-The filename for the default (recommended) net can be found as the default
-value of the `EvalFile` UCI option, with the format `nn-[SHA256 first 12 digits].nnue`
-(for instance, `nn-c157e0a5755b.nnue`). This file can be downloaded from
-```
-https://tests.stockfishchess.org/api/nn/[filename]
-```
-replacing `[filename]` as needed.
-
-
 ## UCI options
 
 Currently, Stockfish has the following UCI options:
@@ -53,6 +44,9 @@ Currently, Stockfish has the following UCI options:
   * #### Hash
     The size of the hash table in MB. It is recommended to set Hash after setting Threads.
 
+  * #### Clear Hash
+    Clear the hash table.
+
   * #### Ponder
     Let Stockfish ponder its next move while the opponent is thinking.
 
@@ -109,7 +103,7 @@ Currently, Stockfish has the following UCI options:
   * #### SyzygyProbeDepth
     Minimum remaining search depth for which a position is probed. Set this option
     to a higher value to probe less aggressively if you experience too much slowdown
-    (in terms of nps) due to TB probing.
+    (in terms of nps) due to tablebase probing.
 
   * #### Syzygy50MoveRule
     Disable to let fifty-move rule draws detected by Syzygy tablebase probes count
@@ -139,13 +133,10 @@ Currently, Stockfish has the following UCI options:
     Tells the engine to use nodes searched instead of wall time to account for
     elapsed time. Useful for engine testing.
 
-  * #### Clear Hash
-    Clear the hash table.
-
   * #### Debug Log File
     Write all communication to and from the engine into a text file.
 
-## A note on classical and NNUE evaluation
+## A note on classical evaluation versus NNUE evaluation
 
 Both approaches assign a value to a position that is used in alpha-beta (PVS) search
 to find the best move. The classical evaluation computes this value as a function
@@ -158,18 +149,29 @@ The NNUE evaluation was first introduced in shogi, and ported to Stockfish after
 It can be evaluated efficiently on CPUs, and exploits the fact that only parts
 of the neural network need to be updated after a typical chess move.
 [The nodchip repository](https://github.com/nodchip/Stockfish) provides additional
-tools to train and develop the NNUE networks.
+tools to train and develop the NNUE networks. On CPUs supporting modern vector instructions
+(avx2 and similar), the NNUE evaluation results in much stronger playing strength, even
+if the nodes per second computed by the engine is somewhat lower (roughly 80% of nps
+is typical).
 
-On CPUs supporting modern vector instructions (avx2 and similar), the NNUE evaluation
-results in stronger playing strength, even if the nodes per second computed by the engine
-is somewhat lower (roughly 60% of nps is typical).
+Notes:
 
-Note that the NNUE evaluation depends on the Stockfish binary and the network parameter
-file (see EvalFile). Not every parameter file is compatible with a given Stockfish binary.
-The default value of the EvalFile UCI option is the name of a network that is guaranteed
-to be compatible with that binary.
+1) the NNUE evaluation depends on the Stockfish binary and the network parameter
+file (see the EvalFile UCI option). Not every parameter file is compatible with a given
+Stockfish binary, but the default value of the EvalFile UCI option is the name of a network
+that is guaranteed to be compatible with that binary.
+
+2) to use the NNUE evaluation, the additional data file with neural network parameters
+needs to be available. Normally, this file is already embedded in the binary or it 
+can be downloaded. The filename for the default (recommended) net can be found as the default
+value of the `EvalFile` UCI option, with the format `nn-[SHA256 first 12 digits].nnue`
+(for instance, `nn-c157e0a5755b.nnue`). This file can be downloaded from
+```
+https://tests.stockfishchess.org/api/nn/[filename]
+```
+replacing `[filename]` as needed.
 
-## What to expect from Syzygybases?
+## What to expect from the Syzygy tablebases?
 
 If the engine is searching a position that is not in the tablebases (e.g.
 a position with 8 pieces), it will access the tablebases during the search.
@@ -187,9 +189,9 @@ will not report a mate score, even if the position is known to be won.**
 It is therefore clear that this behaviour is not identical to what one might
 be used to with Nalimov tablebases. There are technical reasons for this
 difference, the main technical reason being that Nalimov tablebases use the
-DTM metric (distance-to-mate), while Syzygybases use a variation of the
+DTM metric (distance-to-mate), while the Syzygy tablebases use a variation of the
 DTZ metric (distance-to-zero, zero meaning any move that resets the 50-move
-counter). This special metric is one of the reasons that Syzygybases are
+counter). This special metric is one of the reasons that the Syzygy tablebases are
 more compact than Nalimov tablebases, while still storing all information
 needed for optimal play and in addition being able to take into account
 the 50-move rule.
@@ -272,8 +274,9 @@ generic rather than being focused on Stockfish's precise implementation.
 Nevertheless, a helpful resource.
 
 * The latest source can always be found on [GitHub](https://github.com/official-stockfish/Stockfish).
-Discussions about Stockfish take place in the [FishCooking](https://groups.google.com/forum/#!forum/fishcooking)
-group and engine testing is done on [Fishtest](https://tests.stockfishchess.org/tests).
+Discussions about Stockfish take place these days mainly in the [FishCooking](https://groups.google.com/forum/#!forum/fishcooking)
+group and on the [Stockfish Discord channel](https://discord.gg/nv8gDtt).
+The engine testing is done on [Fishtest](https://tests.stockfishchess.org/tests).
 If you want to help improve Stockfish, please read this [guideline](https://github.com/glinscott/fishtest/wiki/Creating-my-first-test)
 first, where the basics of Stockfish development are explained.
 
@@ -288,9 +291,10 @@ it (either by itself or as part of some bigger software package), or
 using it as the starting point for a software project of your own.
 
 The only real limitation is that whenever you distribute Stockfish in
-some way, you must always include the full source code, or a pointer
-to where the source code can be found. If you make any changes to the
-source code, these changes must also be made available under the GPL.
+some way, you MUST always include the full source code, or a pointer
+to where the source code can be found, to generate the exact binary
+you are distributing. If you make any changes to the source code,
+these changes must also be made available under the GPL.
 
 For full details, read the copy of the GPL v3 found in the file named
 *Copying.txt*.
index 482e90000745c298fe22bb11af99e6da39d311df..f5347ea154128088167dd78a05e43a8503d619e5 100644 (file)
-Contributors with >10,000 CPU hours as of Sept 2, 2020
+Contributors to Fishtest with >10,000 CPU hours, as of Feb 15, 2021.
 Thank you!
 
-Username                  CPU Hours   Games played
---------------------------------------------------
-noobpwnftw                 19352969     1231459677
-mlang                        957168       61657446
-dew                          949885       56893432
-mibere                       703817       46865007
-crunchy                      427035       27344275
-cw                           416006       27521077
-JojoM                        415904       24479564
-fastgm                       404873       23953472
-CSU_Dynasty                  335774       22850550
-tvijlbrief                   335199       21871270
-Fisherman                    325053       21786603
-gvreuls                      311480       20751516
-ctoks                        275877       18710423
-velislav                     241267       15596372
-glinscott                    217799       13780820
-nordlandia                   211692       13484886
-bcross                       206213       14934233
-bking_US                     198894       11876016
-leszek                       189170       11446821
-mgrabiak                     183896       11778092
-drabel                       181408       12489478
-TueRens                      181349       12192000
-Thanar                       179852       12365359
-vdv                          175171        9881246
-robal                        166948       10702862
-spams                        157128       10319326
-marrco                       149947        9376421
-sqrt2                        147963        9724586
-vdbergh                      137041        8926915
-CoffeeOne                    136294        5004100
-malala                       136182        8002293
-mhoram                       128934        8177193
-davar                        122092        7960001
-dsmith                       122059        7570238
-xoto                         119696        8222144
-grandphish2                  116481        7582197
-Data                         113305        8220352
-BrunoBanani                  112960        7436849
-ElbertoOne                    99028        7023771
-MaZePallas                    98571        6362619
-brabos                        92118        6186135
-psk                           89957        5984901
-sunu                          88463        6007033
-sterni1971                    86948        5613788
-Vizvezdenec                   83752        5343724
-BRAVONE                       81239        5054681
-nssy                          76497        5259388
-teddybaer                     75125        5407666
-Pking_cda                     73776        5293873
-jromang                       70695        4940891
-solarlight                    70517        5028306
-dv8silencer                   70287        3883992
-Bobo1239                      68515        4652287
-racerschmacer                 67468        4935996
-manap                         66273        4121774
-tinker                        63458        4213726
-linrock                       59082        4516053
-robnjr                        57262        4053117
-Freja                         56938        3733019
-ttruscott                     56005        3679485
-renouve                       53811        3501516
-cuistot                       52532        3014920
-finfish                       51360        3370515
-eva42                         51272        3599691
-rkl                           50759        3840947
-rap                           49985        3219146
-pb00067                       49727        3298270
-ronaldjerum                   47654        3240695
-bigpen0r                      47278        3291647
-biffhero                      46564        3111352
-VoyagerOne                    45386        3445881
-speedycpu                     43842        3003273
-jbwiebe                       43305        2805433
-Antihistamine                 41788        2761312
-mhunt                         41735        2691355
-eastorwest                    40387        2812173
-homyur                        39893        2850481
-gri                           39871        2515779
-oryx                          38228        2941656
-0x3C33                        37773        2529097
-SC                            37290        2731014
-csnodgrass                    36207        2688994
-jmdana                        36108        2205261
-strelock                      34716        2074055
-Garf                          33800        2747562
-EthanOConnor                  33370        2090311
-slakovv                       32915        2021889
-Spprtr                        32591        2139601
-Prcuvu                        30377        2170122
-anst                          30301        2190091
-jkiiski                       30136        1904470
-hyperbolic.tom                29840        2017394
-Pyafue                        29650        1902349
-OuaisBla                      27629        1578000
-chriswk                       26902        1868317
-achambord                     26582        1767323
-Patrick_G                     26276        1801617
-yorkman                       26193        1992080
-SFTUser                       25182        1675689
-nabildanial                   24942        1519409
-Sharaf_DG                     24765        1786697
-ncfish1                       24411        1520927
-agg177                        23890        1395014
-JanErik                       23408        1703875
-Isidor                        23388        1680691
-Norabor                       22976        1587862
-cisco2015                     22880        1759669
-Zirie                         22542        1472937
-team-oh                       22272        1636708
-MazeOfGalious                 21978        1629593
-sg4032                        21945        1643065
-ianh2105                      21725        1632562
-xor12                         21628        1680365
-dex                           21612        1467203
-nesoneg                       21494        1463031
-horst.prack                   20878        1465656
-0xB00B1ES                     20590        1208666
-j3corre                       20405         941444
-Adrian.Schmidt123             20316        1281436
-wei                           19973        1745989
-rstoesser                     19569        1293588
-eudhan                        19274        1283717
-Ente                          19070        1373058
-jundery                       18445        1115855
-iisiraider                    18247        1101015
-ville                         17883        1384026
-chris                         17698        1487385
-purplefishies                 17595        1092533
-DragonLord                    17014        1162790
-dju                           16515         929427
-IgorLeMasson                  16064        1147232
-ako027ako                     15671        1173203
-Nikolay.IT                    15154        1068349
-Andrew Grant                  15114         895539
-yurikvelo                     15027        1165616
-OssumOpossum                  14857        1007129
-enedene                       14476         905279
-bpfliegel                     14298         884523
-jpulman                       13982         870599
-joster                        13794         950160
-Nesa92                        13786        1114691
-Dark_wizzie                   13422        1007152
-Hjax                          13350         900887
-Fifis                         13313         965473
-mabichito                     12903         749391
-thijsk                        12886         722107
-crocogoat                     12876        1048802
-AdrianSA                      12860         804972
-Flopzee                       12698         894821
-fatmurphy                     12547         853210
-SapphireBrand                 12416         969604
-modolief                      12386         896470
-scuzzi                        12362         833465
-pgontarz                      12151         848794
-stocky                        11954         699440
-mschmidt                      11941         803401
-infinity                      11470         727027
-torbjo                        11387         728873
-Thomas A. Anderson            11372         732094
-snicolet                      11106         869170
-amicic                        10779         733593
-rpngn                         10712         688203
-d64                           10680         771144
-basepi                        10637         744851
-jjoshua2                      10559         670905
-dzjp                          10343         732529
-ols                           10259         570669
-lbraesch                      10252         647825
+Username                CPU Hours       Games played
+----------------------------------------------------
+noobpwnftw               23930906         1560559941
+dew                       1169948           70333008
+mlang                      957168           61657446
+mibere                     703840           46867607
+tvijlbrief                 517888           33379462
+JojoM                      515404           30334272
+cw                         443276           29385549
+crunchy                    427035           27344275
+grandphish2                425794           26347253
+fastgm                     414133           24519696
+gvreuls                    377843           24708884
+CSU_Dynasty                338718           23030006
+Fisherman                  326795           21820747
+TueRens                    313730           19490246
+ctoks                      298442           20052551
+velislav                   270519           17355456
+bcross                     241064           17196165
+glinscott                  217799           13780820
+nordlandia                 211692           13484886
+bking_US                   198894           11876016
+drabel                     191096           13129722
+leszek                     189170           11446821
+mgrabiak                   187153           12013300
+robal                      181389           11539242
+Thanar                     179852           12365359
+vdv                        175274            9889046
+spams                      157128           10319326
+marrco                     150292            9401741
+sqrt2                      147963            9724586
+CoffeeOne                  137086            5022516
+vdbergh                    137041            8926915
+malala                     136182            8002293
+mhoram                     132780            8398229
+xoto                       124729            8652088
+davar                      122092            7960001
+dsmith                     122059            7570238
+Data                       113305            8220352
+BrunoBanani                112960            7436849
+pemo                       109598            5036441
+Dantist                    106768            6431396
+MaZePallas                 102741            6630419
+ElbertoOne                  99028            7023771
+brabos                      92118            6186135
+linrock                     90903            6708639
+psk                         89957            5984901
+sunu                        88614            6020673
+sterni1971                  86948            5613788
+Vizvezdenec                 83761            5344740
+BRAVONE                     81239            5054681
+nssy                        76497            5259388
+cuistot                     76366            4370584
+racerschmacer               75753            5442626
+teddybaer                   75125            5407666
+Pking_cda                   73776            5293873
+0x3C33                      73133            4670293
+jromang                     72117            5054915
+solarlight                  70517            5028306
+dv8silencer                 70287            3883992
+Bobo1239                    68515            4652287
+manap                       66273            4121774
+tinker                      64321            4268390
+robnjr                      57262            4053117
+Freja                       56938            3733019
+ttruscott                   56010            3680085
+rkl                         54986            4150767
+renouve                     53811            3501516
+finfish                     51360            3370515
+eva42                       51272            3599691
+rap                         49985            3219146
+pb00067                     49727            3298270
+amicic                      49691            3042481
+ronaldjerum                 47654            3240695
+bigpen0r                    47278            3291647
+biffhero                    46564            3111352
+VoyagerOne                  45476            3452465
+eastorwest                  45033            3071805
+speedycpu                   43842            3003273
+jbwiebe                     43305            2805433
+Antihistamine               41788            2761312
+mhunt                       41735            2691355
+homyur                      39893            2850481
+gri                         39871            2515779
+oryx                        38282            2944400
+Spprtr                      38157            2470529
+SC                          37290            2731014
+csnodgrass                  36207            2688994
+jmdana                      36157            2210661
+strelock                    34716            2074055
+Garf                        33800            2747562
+skiminki                    33515            2055584
+EthanOConnor                33370            2090311
+slakovv                     32915            2021889
+yurikvelo                   32600            2255966
+Prcuvu                      30377            2170122
+manapbk                     30326            1770143
+anst                        30301            2190091
+jkiiski                     30136            1904470
+hyperbolic.tom              29840            2017394
+Pyafue                      29650            1902349
+qurashee                    27758            1509620
+OuaisBla                    27636            1578800
+chriswk                     26902            1868317
+achambord                   26582            1767323
+Fifis                       26376            1776853
+Patrick_G                   26276            1801617
+yorkman                     26193            1992080
+SFTUser                     25182            1675689
+nabildanial                 24942            1519409
+Sharaf_DG                   24765            1786697
+ncfish1                     24411            1520927
+agg177                      23890            1395014
+JanErik                     23408            1703875
+Isidor                      23388            1680691
+Norabor                     23164            1591830
+cisco2015                   22895            1762069
+Zirie                       22542            1472937
+team-oh                     22272            1636708
+MazeOfGalious               21978            1629593
+sg4032                      21945            1643065
+ianh2105                    21725            1632562
+xor12                       21628            1680365
+dex                         21612            1467203
+nesoneg                     21494            1463031
+jjoshua2                    20997            1422689
+horst.prack                 20878            1465656
+0xB00B1ES                   20590            1208666
+sphinx                      20515            1352368
+j3corre                     20405            941444
+Adrian.Schmidt123           20316            1281436
+Ente                        20017            1432602
+wei                         19973            1745989
+rstoesser                   19569            1293588
+eudhan                      19274            1283717
+jundery                     18445            1115855
+iisiraider                  18247            1101015
+ville                       17883            1384026
+chris                       17698            1487385
+purplefishies               17595            1092533
+DMBK                        17357            1279152
+DragonLord                  17014            1162790
+dju                         16515             929427
+IgorLeMasson                16064            1147232
+ako027ako                   15671            1173203
+Nikolay.IT                  15154            1068349
+Andrew Grant                15114             895539
+OssumOpossum                14857            1007129
+enedene                     14476             905279
+bpfliegel                   14298             884523
+jpulman                     13982             870599
+joster                      13794             950160
+Nesa92                      13786            1114691
+crocogoat                   13753            1114622
+Hjax                        13535             915487
+Dark_wizzie                 13422            1007152
+mpx86                       12941             693640
+mabichito                   12903             749391
+thijsk                      12886             722107
+AdrianSA                    12860             804972
+Flopzee                     12698             894821
+fatmurphy                   12547             853210
+scuzzi                      12511             845761
+Karby                       12429             735880
+SapphireBrand               12416             969604
+modolief                    12386             896470
+pgontarz                    12151             848794
+stocky                      11954             699440
+mschmidt                    11941             803401
+infinity                    11470             727027
+torbjo                      11395             729145
+Thomas A. Anderson          11372             732094
+d64                         11263             789184
+Maxim                       11129             804704
+snicolet                    11106             869170
+MooTheCow                   11008             694942
+savage84                    10965             641068
+Rudolphous                  10915             741268
+Wolfgang                    10809             580032
+rpngn                       10712             688203
+basepi                      10637             744851
+michaelrpg                  10409             735127
+dzjp                        10343             732529
+ali-al-zhrani               10324             726502
+ols                         10259             570669
+lbraesch                    10252             647825
index e3466ea1bb8791979a6430d27cd35f1b15c50315..d7e09c8c682b510872f613c10118b12118b2cea9 100644 (file)
@@ -1,7 +1,5 @@
 # Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-# Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
-# Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
-# Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
+# Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 #
 # Stockfish is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -369,9 +367,11 @@ ifeq ($(COMP),clang)
 
        ifneq ($(KERNEL),Darwin)
        ifneq ($(KERNEL),OpenBSD)
+       ifneq ($(KERNEL),FreeBSD)
                LDFLAGS += -latomic
        endif
        endif
+       endif
 
        ifeq ($(arch),$(filter $(arch),armv7 armv8))
                ifeq ($(OS),Android)
@@ -482,6 +482,10 @@ ifeq ($(optimize),yes)
                        CXXFLAGS += -mdynamic-no-pic
                endif
        endif
+
+       ifeq ($(comp),clang)
+               CXXFLAGS += -fexperimental-new-pass-manager
+       endif
 endif
 
 ### 3.4 Bits
@@ -591,7 +595,7 @@ endif
 ifeq ($(optimize),yes)
 ifeq ($(debug), no)
        ifeq ($(comp),clang)
-               CXXFLAGS += -flto=thin
+               CXXFLAGS += -flto
                ifneq ($(findstring MINGW,$(KERNEL)),)
                        CXXFLAGS += -fuse-ld=lld
                else ifneq ($(findstring MSYS,$(KERNEL)),)
@@ -611,7 +615,7 @@ ifeq ($(debug), no)
                        LDFLAGS += -save-temps
                endif
        else
-               CXXFLAGS += -flto=thin
+               CXXFLAGS += -flto
                LDFLAGS += $(CXXFLAGS)
        endif
 
index ffb631a28558fa18c55dc35dc7b349330b1e2e5d..7945a4535ca4eb82dfc65ae4d4a3834839ca5801 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -92,6 +92,8 @@ const vector<string> Defaults = {
 
 } // namespace
 
+namespace Stockfish {
+
 /// setup_bench() builds a list of UCI commands to be run by bench. There
 /// are five parameters: TT size in MB, number of search threads that
 /// should be used, the limit value spent for each position, a file name
@@ -168,3 +170,5 @@ vector<string> setup_bench(const Position& current, istream& is) {
 
   return list;
 }
+
+} // namespace Stockfish
index bbe8e9a7e33bfc7514f2ef122bc78e446969be4b..ece9ec72b23968605cc535c1beb22203650e9762 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
 #include "bitboard.h"
 #include "types.h"
 
+namespace Stockfish {
+
 namespace {
 
   // There are 24 possible pawn squares: files A to D and ranks from 2 to 7.
@@ -66,7 +68,6 @@ namespace {
 
 } // namespace
 
-
 bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color stm) {
 
   assert(file_of(wpsq) <= FILE_D);
@@ -96,7 +97,6 @@ void Bitbases::init() {
           KPKBitbase.set(idx);
 }
 
-
 namespace {
 
   KPKPosition::KPKPosition(unsigned idx) {
@@ -168,3 +168,5 @@ namespace {
   }
 
 } // namespace
+
+} // namespace Stockfish
index 80206b58af93c512c56dc841f0af82ba6f7579d8..a202144912390bf316e0b9ea0e1e4cab45367e67 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -22,6 +22,8 @@
 #include "bitboard.h"
 #include "misc.h"
 
+namespace Stockfish {
+
 uint8_t PopCnt16[1 << 16];
 uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
 
@@ -42,7 +44,6 @@ namespace {
 
 }
 
-
 /// safe_destination() returns the bitboard of target square for the given step
 /// from the given square. If the step is off the board, returns empty bitboard.
 
@@ -55,7 +56,7 @@ inline Bitboard safe_destination(Square s, int step) {
 /// Bitboards::pretty() returns an ASCII representation of a bitboard suitable
 /// to be printed to standard output. Useful for debugging.
 
-const std::string Bitboards::pretty(Bitboard b) {
+std::string Bitboards::pretty(Bitboard b) {
 
   std::string s = "+---+---+---+---+---+---+---+---+\n";
 
@@ -111,7 +112,6 @@ void Bitboards::init() {
   }
 }
 
-
 namespace {
 
   Bitboard sliding_attack(PieceType pt, Square sq, Bitboard occupied) {
@@ -211,3 +211,5 @@ namespace {
     }
   }
 }
+
+} // namespace Stockfish
index 29d8f66d41525533a8602c469b0f749920bd4c7f..e14fe0df7d30c2d3bec0d6d83e2ee833fa61c0c9 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
 #include "types.h"
 
+namespace Stockfish {
+
 namespace Bitbases {
 
 void init();
 bool probe(Square wksq, Square wpsq, Square bksq, Color us);
 
-}
+} // namespace Stockfish::Bitbases
 
 namespace Bitboards {
 
 void init();
-const std::string pretty(Bitboard b);
+std::string pretty(Bitboard b);
 
-}
+} // namespace Stockfish::Bitboards
 
 constexpr Bitboard AllSquares = ~Bitboard(0);
 constexpr Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
@@ -430,4 +432,6 @@ inline Square frontmost_sq(Color c, Bitboard b) {
   return c == WHITE ? msb(b) : lsb(b);
 }
 
+} // namespace Stockfish
+
 #endif // #ifndef BITBOARD_H_INCLUDED
index 7e005a28277f8d85b639d82af2439e5f5b672670..a44d3a1c5e66f3c10a1f40853c41794f80dc81dc 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -22,6 +22,8 @@
 #include "endgame.h"
 #include "movegen.h"
 
+namespace Stockfish {
+
 namespace {
 
   // Used to drive the king towards the edge of the board
@@ -741,3 +743,5 @@ ScaleFactor Endgame<KPKP>::operator()(const Position& pos) const {
   // it's probably at least a draw even with the pawn.
   return Bitbases::probe(strongKing, strongPawn, weakKing, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
 }
+
+} // namespace Stockfish
index 1351d88ab1c482d856f947d3f79b5bbf375d03d2..146111b95791511a361a9af8ff96e24aca81fe46 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
 #include "position.h"
 #include "types.h"
 
+namespace Stockfish {
 
 /// EndgameCode lists all supported endgame functions by corresponding codes
 
@@ -120,4 +121,6 @@ namespace Endgames {
   }
 }
 
+} // namespace Stockfish
+
 #endif // #ifndef ENDGAME_H_INCLUDED
index 7671f6052df6050c7d2d21d84dcf173472658c5b..d43b8fa76c59a1a40a1aa37ce135a39d889e52e1 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #include "incbin/incbin.h"
 
 
-// Macro to embed the default NNUE file data in the engine binary (using incbin.h, by Dale Weiler).
+// Macro to embed the default efficiently updatable neural network (NNUE) file
+// data in the engine binary (using incbin.h, by Dale Weiler).
 // This macro invocation will declare the following three variables
 //     const unsigned char        gEmbeddedNNUEData[];  // a pointer to the embedded data
 //     const unsigned char *const gEmbeddedNNUEEnd;     // a marker to the end
 //     const unsigned int         gEmbeddedNNUESize;    // the size of the embedded file
-// Note that this does not work in Microsof Visual Studio.
+// Note that this does not work in Microsoft Visual Studio.
 #if !defined(_MSC_VER) && !defined(NNUE_EMBEDDING_OFF)
   INCBIN(EmbeddedNNUE, EvalFileDefaultName);
 #else
 
 
 using namespace std;
-using namespace Eval::NNUE;
+using namespace Stockfish::Eval::NNUE;
+
+namespace Stockfish {
 
 namespace Eval {
 
   bool useNNUE;
   string eval_file_loaded = "None";
 
-  /// NNUE::init() tries to load a nnue network at startup time, or when the engine
+  /// NNUE::init() tries to load a NNUE network at startup time, or when the engine
   /// receives a UCI command "setoption name EvalFile value nn-[a-z0-9]{12}.nnue"
-  /// The name of the nnue network is always retrieved from the EvalFile option.
+  /// The name of the NNUE network is always retrieved from the EvalFile option.
   /// We search the given network in three locations: internally (the default
   /// network may be embedded in the binary), in the active working directory and
   /// in the engine directory. Distro packagers may define the DEFAULT_NNUE_DIRECTORY
@@ -225,7 +228,7 @@ namespace {
   // BishopPawns[distance from edge] contains a file-dependent penalty for pawns on
   // squares of the same color as our bishop.
   constexpr Score BishopPawns[int(FILE_NB) / 2] = {
-    S(3, 8), S(3, 9), S(1, 8), S(3, 7)
+    S(3, 8), S(3, 9), S(2, 8), S(3, 8)
   };
 
   // KingProtector[knight/bishop] contains penalty for each distance unit to own king
@@ -233,7 +236,7 @@ namespace {
 
   // Outpost[knight/bishop] contains bonuses for each knight or bishop occupying a
   // pawn protected square on rank 4 to 6 which is also safe from a pawn attack.
-  constexpr Score Outpost[] = { S(56, 34), S(31, 23) };
+  constexpr Score Outpost[] = { S(57, 38), S(31, 24) };
 
   // PassedRank[Rank] contains a bonus according to the rank of a passed pawn
   constexpr Score PassedRank[RANK_NB] = {
@@ -255,7 +258,7 @@ namespace {
   };
 
   // Assorted bonuses and penalties
-  constexpr Score BadOutpost          = S( -7, 36);
+  constexpr Score UncontestedOutpost  = S(  1, 10);
   constexpr Score BishopOnKingRing    = S( 24,  0);
   constexpr Score BishopXRayPawns     = S(  4,  5);
   constexpr Score CorneredBishop      = S( 50, 50);
@@ -422,13 +425,12 @@ namespace {
             score += BishopOnKingRing;
 
         int mob = popcount(b & mobilityArea[Us]);
-
         mobility[Us] += MobilityBonus[Pt - 2][mob];
 
         if (Pt == BISHOP || Pt == KNIGHT)
         {
             // Bonus if the piece is on an outpost square or can reach one
-            // Reduced bonus for knights (BadOutpost) if few relevant targets
+            // Bonus for knights (UncontestedOutpost) if few relevant targets
             bb = OutpostRanks & (attackedBy[Us][PAWN] | shift<Down>(pos.pieces(PAWN)))
                               & ~pe->pawn_attacks_span(Them);
             Bitboard targets = pos.pieces(Them) & ~pos.pieces(PAWN);
@@ -437,7 +439,7 @@ namespace {
                 && bb & s & ~CenterFiles // on a side outpost
                 && !(b & targets)        // no relevant attacks
                 && (!more_than_one(targets & (s & QueenSide ? QueenSide : KingSide))))
-                score += BadOutpost;
+                score += UncontestedOutpost * popcount(pos.pieces(PAWN) & (s & QueenSide ? QueenSide : KingSide));
             else if (bb & s)
                 score += Outpost[Pt == BISHOP];
             else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us))
@@ -450,7 +452,7 @@ namespace {
             // Penalty if the piece is far from the king
             score -= KingProtector[Pt == BISHOP] * distance(pos.square<KING>(Us), s);
 
-            if (Pt == BISHOP)
+            if constexpr (Pt == BISHOP)
             {
                 // Penalty according to the number of our pawns on the same color square as the
                 // bishop, bigger when the center files are blocked with pawns and smaller
@@ -482,7 +484,7 @@ namespace {
             }
         }
 
-        if (Pt == ROOK)
+        if constexpr (Pt == ROOK)
         {
             // Bonuses for rook on a (semi-)open or closed file
             if (pos.is_on_semiopen_file(Us, s))
@@ -509,7 +511,7 @@ namespace {
             }
         }
 
-        if (Pt == QUEEN)
+        if constexpr (Pt == QUEEN)
         {
             // Penalty if any relative pin or discovered attack against the queen
             Bitboard queenPinners;
@@ -517,7 +519,7 @@ namespace {
                 score -= WeakQueen;
         }
     }
-    if (T)
+    if constexpr (T)
         Trace::add(Pt, Us, score);
 
     return score;
@@ -617,7 +619,7 @@ namespace {
     // Penalty if king flank is under attack, potentially moving toward the king
     score -= FlankAttacks * kingFlankAttack;
 
-    if (T)
+    if constexpr (T)
         Trace::add(KING, Us, score);
 
     return score;
@@ -718,7 +720,7 @@ namespace {
         score += SliderOnQueen * popcount(b & safe & attackedBy2[Us]) * (1 + queenImbalance);
     }
 
-    if (T)
+    if constexpr (T)
         Trace::add(THREAT, Us, score);
 
     return score;
@@ -811,7 +813,7 @@ namespace {
         score += bonus - PassedFile * edge_distance(file_of(s));
     }
 
-    if (T)
+    if constexpr (T)
         Trace::add(PASSED, Us, score);
 
     return score;
@@ -852,7 +854,7 @@ namespace {
     int weight = pos.count<ALL_PIECES>(Us) - 3 + std::min(pe->blocked_count(), 9);
     Score score = make_score(bonus * weight * weight / 16, 0);
 
-    if (T)
+    if constexpr (T)
         Trace::add(SPACE, Us, score);
 
     return score;
@@ -947,7 +949,7 @@ namespace {
        + eg * int(PHASE_MIDGAME - me->game_phase()) * ScaleFactor(sf) / SCALE_FACTOR_NORMAL;
     v /= PHASE_MIDGAME;
 
-    if (T)
+    if constexpr (T)
     {
         Trace::add(WINNABLE, make_score(u, eg * ScaleFactor(sf) / SCALE_FACTOR_NORMAL - eg_value(score)));
         Trace::add(TOTAL, make_score(mg, eg * ScaleFactor(sf) / SCALE_FACTOR_NORMAL));
@@ -1019,7 +1021,7 @@ make_v:
     Value v = winnable(score);
 
     // In case of tracing add all remaining individual evaluation terms
-    if (T)
+    if constexpr (T)
     {
         Trace::add(MATERIAL, pos.psq_score());
         Trace::add(IMBALANCE, me->imbalance());
@@ -1052,8 +1054,8 @@ Value Eval::evaluate(const Position& pos) {
   {
       // Scale and shift NNUE for compatibility with search and classical evaluation
       auto  adjusted_NNUE = [&](){
-         int mat = pos.non_pawn_material() + PawnValueMg * pos.count<PAWN>();
-         return NNUE::evaluate(pos) * (679 + mat / 32) / 1024 + Tempo;
+         int mat = pos.non_pawn_material() + 2 * PawnValueMg * pos.count<PAWN>();
+         return NNUE::evaluate(pos) * (641 + mat / 32 - 4 * pos.rule50_count()) / 1024 + Tempo;
       };
 
       // If there is PSQ imbalance use classical eval, with small probability if it is small
@@ -1146,3 +1148,5 @@ std::string Eval::trace(const Position& pos) {
 
   return ss.str();
 }
+
+} // namespace Stockfish
index 7dbc35deabdb4427243ea96388bf955e95cf8460..6210bd5816b8be77b7223f0c1b1b4eaab715b411 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
 
 #include "types.h"
 
+namespace Stockfish {
+
 class Position;
 
 namespace Eval {
@@ -49,4 +51,6 @@ namespace Eval {
 
 } // namespace Eval
 
+} // namespace Stockfish
+
 #endif // #ifndef EVALUATE_H_INCLUDED
index e8548ac1a451bdb4c4204ec5a4e0df315397c4ed..a2c741e53e2e4bd0f9bbfa458d6ceb69932a909f 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #include "bitboard.h"
 #include "endgame.h"
 #include "position.h"
+#include "psqt.h"
 #include "search.h"
+#include "syzygy/tbprobe.h"
 #include "thread.h"
 #include "tt.h"
 #include "uci.h"
-#include "syzygy/tbprobe.h"
 
 #include <grpc/grpc.h>
 #include <grpc++/server.h>
@@ -225,6 +226,8 @@ namespace PSQT {
   void init();
 }
 
+using namespace Stockfish;
+
 int main(int argc, char* argv[]) {
 
   std::cout << engine_info() << std::endl;
index f77972e352c0d9395054750bca0ebe93aef3e73c..84d7a4bd0a6331327e96735af16a981ea6ac25c8 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
 using namespace std;
 
+namespace Stockfish {
+
 namespace {
   #define S(mg, eg) make_score(mg, eg)
 
   // Polynomial material imbalance parameters
 
+  // One Score parameter for each pair (our piece, another of our pieces)
   constexpr Score QuadraticOurs[][PIECE_TYPE_NB] = {
-    //            OUR PIECES
-    // pair pawn knight bishop rook queen
+    // OUR PIECE 2
+    // bishop pair    pawn         knight       bishop       rook           queen
     {S(1419, 1455)                                                                  }, // Bishop pair
     {S( 101,   28), S( 37,  39)                                                     }, // Pawn
-    {S(  57,   64), S(249, 187), S(-49, -62)                                        }, // Knight      OUR PIECES
+    {S(  57,   64), S(249, 187), S(-49, -62)                                        }, // Knight      OUR PIECE 1
     {S(   0,    0), S(118, 137), S( 10,  27), S(  0,   0)                           }, // Bishop
     {S( -63,  -68), S( -5,   3), S(100,  81), S(132, 118), S(-246, -244)            }, // Rook
     {S(-210, -211), S( 37,  14), S(147, 141), S(161, 105), S(-158, -174), S(-9,-31) }  // Queen
   };
 
+  // One Score parameter for each pair (our piece, their piece)
   constexpr Score QuadraticTheirs[][PIECE_TYPE_NB] = {
-    //           THEIR PIECES
-    // pair pawn knight bishop rook queen
+    // THEIR PIECE
+    // bishop pair   pawn         knight       bishop       rook         queen
     {                                                                               }, // Bishop pair
     {S(  33,  30)                                                                   }, // Pawn
-    {S(  46,  18), S(106,  84)                                                      }, // Knight      OUR PIECES
+    {S(  46,  18), S(106,  84)                                                      }, // Knight      OUR PIECE
     {S(  75,  35), S( 59,  44), S( 60,  15)                                         }, // Bishop
     {S(  26,  35), S(  6,  22), S( 38,  39), S(-12,  -2)                            }, // Rook
     {S(  97,  93), S(100, 163), S(-58, -91), S(112, 192), S(276, 225)               }  // Queen
@@ -221,3 +225,5 @@ Entry* probe(const Position& pos) {
 }
 
 } // namespace Material
+
+} // namespace Stockfish
index 28da59dbf3303ddd0ac1319acd0948669f232948..26535a535afb295bdcbcfe6bfe66664ff4b2a6e6 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 #include "position.h"
 #include "types.h"
 
-namespace Material {
+namespace Stockfish::Material {
 
 /// Material::Entry contains various information about a material configuration.
 /// It contains a material imbalance evaluation, a function pointer to a special
@@ -66,6 +66,6 @@ typedef HashTable<Entry, 8192> Table;
 
 Entry* probe(const Position& pos);
 
-} // namespace Material
+} // namespace Stockfish::Material
 
 #endif // #ifndef MATERIAL_H_INCLUDED
index 832a9ac18f93465baca9eb9c54de107453c71916..81602d71101690f09418990da1c94815e51e3d98 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -61,6 +61,8 @@ typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY);
 
 using namespace std;
 
+namespace Stockfish {
+
 namespace {
 
 /// Version number. If Version is left empty, then compile date in the format
@@ -138,7 +140,7 @@ public:
 /// the program was compiled) or "Stockfish <Version>", depending on whether
 /// Version is empty.
 
-const string engine_info(bool to_uci) {
+string engine_info(bool to_uci) {
 
   const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
   string month, day, year;
@@ -162,7 +164,7 @@ const string engine_info(bool to_uci) {
 
 /// compiler_info() returns a string trying to describe the compiler we use
 
-const std::string compiler_info() {
+std::string compiler_info() {
 
   #define stringify2(x) #x
   #define stringify(x) stringify2(x)
@@ -361,7 +363,7 @@ void std_aligned_free(void* ptr) {
 /// aligned_large_pages_alloc() will return suitably aligned memory, if possible using large pages.
 
 #if defined(_WIN32)
-
+#if defined(_WIN64)
 static void* aligned_large_pages_alloc_win(size_t allocSize) {
 
   HANDLE hProcessToken { };
@@ -406,15 +408,20 @@ static void* aligned_large_pages_alloc_win(size_t allocSize) {
 
   return mem;
 }
+#endif
 
 void* aligned_large_pages_alloc(size_t allocSize) {
 
+#if defined(_WIN64)
   // Try to allocate large pages
   void* mem = aligned_large_pages_alloc_win(allocSize);
 
   // Fall back to regular, page aligned, allocation if necessary
   if (!mem)
       mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+#else
+  void* mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+#endif
 
   return mem;
 }
@@ -627,3 +634,5 @@ void init(int argc, char* argv[]) {
 
 
 } // namespace CommandLine
+
+} // namespace Stockfish
index 682ef81641c041869fb255e6732a53b6b651da9c..f834e470cbf8799b49915196e8c805a3dd24139d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
 #include "types.h"
 
-const std::string engine_info(bool to_uci = false);
-const std::string compiler_info();
+namespace Stockfish {
+
+std::string engine_info(bool to_uci = false);
+std::string compiler_info();
 void prefetch(void* addr);
 void start_logger(const std::string& fname);
 void* std_aligned_alloc(size_t alignment, size_t size);
@@ -143,4 +145,6 @@ namespace CommandLine {
   extern std::string workingDirectory; // path of the working directory
 }
 
+} // namespace Stockfish
+
 #endif // #ifndef MISC_H_INCLUDED
index cc1518a078de7d48064e93cbd23e8ad6b95b54be..c5d76afa43b0bc59e7b43b94174ef08dcb694d70 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -21,6 +21,8 @@
 #include "movegen.h"
 #include "position.h"
 
+namespace Stockfish {
+
 namespace {
 
   template<GenType Type, Direction D>
@@ -85,7 +87,7 @@ namespace {
 
             // Add pawn pushes which give discovered check. This is possible only
             // if the pawn is not on the same file as the enemy king, because we
-            // don't generate captures. Note that a possible discovery check
+            // don't generate captures. Note that a possible discovered check
             // promotion has been already generated amongst the captures.
             Bitboard dcCandidateQuiets = pos.blockers_for_king(Them) & pawnsNotOn7;
             if (dcCandidateQuiets)
@@ -134,7 +136,7 @@ namespace {
             moveList = make_promotions<Type, Up     >(moveList, pop_lsb(&b3), ksq);
     }
 
-    // Standard and en-passant captures
+    // Standard and en passant captures
     if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
     {
         Bitboard b1 = shift<UpRight>(pawnsNotOn7) & enemies;
@@ -156,10 +158,8 @@ namespace {
         {
             assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6));
 
-            // An en passant capture can be an evasion only if the checking piece
-            // is the double pushed pawn and so is in the target. Otherwise this
-            // is a discovery check and we are forced to do otherwise.
-            if (Type == EVASIONS && !(target & (pos.ep_square() - Up)))
+            // An en passant capture cannot resolve a discovered check.
+            if (Type == EVASIONS && (target & (pos.ep_square() + Up)))
                 return moveList;
 
             b1 = pawnsNotOn7 & pawn_attacks_bb(Them, pos.ep_square());
@@ -167,7 +167,7 @@ namespace {
             assert(b1);
 
             while (b1)
-                *moveList++ = make<ENPASSANT>(pop_lsb(&b1), pos.ep_square());
+                *moveList++ = make<EN_PASSANT>(pop_lsb(&b1), pos.ep_square());
         }
     }
 
@@ -175,30 +175,24 @@ namespace {
   }
 
 
-  template<Color Us, PieceType Pt, bool Checks>
-  ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
+  template<PieceType Pt, bool Checks>
+  ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard piecesToMove, Bitboard target) {
 
     static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()");
 
-    Bitboard bb = pos.pieces(Us, Pt);
+    Bitboard bb = piecesToMove & pos.pieces(Pt);
 
-    while (bb) {
-        Square from = pop_lsb(&bb);
+    if (!bb)
+        return moveList;
 
-        if (Checks)
-        {
-            if (    (Pt == BISHOP || Pt == ROOK || Pt == QUEEN)
-                && !(attacks_bb<Pt>(from) & target & pos.check_squares(Pt)))
-                continue;
+    [[maybe_unused]] const Bitboard checkSquares = pos.check_squares(Pt);
 
-            if (pos.blockers_for_king(~Us) & from)
-                continue;
-        }
+    while (bb) {
+        Square from = pop_lsb(&bb);
 
         Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
-
-        if (Checks)
-            b &= pos.check_squares(Pt);
+        if constexpr (Checks)
+            b &= checkSquares;
 
         while (b)
             *moveList++ = make_move(from, pop_lsb(&b));
@@ -210,8 +204,14 @@ namespace {
 
   template<Color Us, GenType Type>
   ExtMove* generate_all(const Position& pos, ExtMove* moveList) {
-    constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantations
-    Bitboard target;
+
+    static_assert(Type != LEGAL, "Unsupported type in generate_all()");
+
+    constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations
+    Bitboard target, piecesToMove = pos.pieces(Us);
+
+    if(Type == QUIET_CHECKS)
+        piecesToMove &= ~pos.blockers_for_king(~Us);
 
     switch (Type)
     {
@@ -223,23 +223,18 @@ namespace {
             target = ~pos.pieces();
             break;
         case EVASIONS:
-        {
-            Square checksq = lsb(pos.checkers());
-            target = between_bb(pos.square<KING>(Us), checksq) | checksq;
+            target = between_bb(pos.square<KING>(Us), lsb(pos.checkers())) | pos.checkers();
             break;
-        }
         case NON_EVASIONS:
             target = ~pos.pieces(Us);
             break;
-        default:
-            static_assert(true, "Unsupported type in generate_all()");
     }
 
     moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
-    moveList = generate_moves<Us, KNIGHT, Checks>(pos, moveList, target);
-    moveList = generate_moves<Us, BISHOP, Checks>(pos, moveList, target);
-    moveList = generate_moves<Us,   ROOK, Checks>(pos, moveList, target);
-    moveList = generate_moves<Us,  QUEEN, Checks>(pos, moveList, target);
+    moveList = generate_moves<KNIGHT, Checks>(pos, moveList, piecesToMove, target);
+    moveList = generate_moves<BISHOP, Checks>(pos, moveList, piecesToMove, target);
+    moveList = generate_moves<  ROOK, Checks>(pos, moveList, piecesToMove, target);
+    moveList = generate_moves< QUEEN, Checks>(pos, moveList, piecesToMove, target);
 
     if (Type != QUIET_CHECKS && Type != EVASIONS)
     {
@@ -261,7 +256,7 @@ namespace {
 
 
 /// <CAPTURES>     Generates all pseudo-legal captures plus queen and checking knight promotions
-/// <QUIETS>       Generates all pseudo-legal non-captures and underpromotions(except checking knight)
+/// <QUIETS>       Generates all pseudo-legal non-captures and underpromotions (except checking knight)
 /// <NON_EVASIONS> Generates all pseudo-legal captures and non-captures
 ///
 /// Returns a pointer to the end of the move list.
@@ -284,8 +279,8 @@ template ExtMove* generate<QUIETS>(const Position&, ExtMove*);
 template ExtMove* generate<NON_EVASIONS>(const Position&, ExtMove*);
 
 
-/// generate<QUIET_CHECKS> generates all pseudo-legal non-captures.
-/// Returns a pointer to the end of the move list.
+/// generate<QUIET_CHECKS> generates all pseudo-legal non-captures giving check,
+/// except castling. Returns a pointer to the end of the move list.
 template<>
 ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
 
@@ -358,7 +353,7 @@ ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
   moveList = pos.checkers() ? generate<EVASIONS    >(pos, moveList)
                             : generate<NON_EVASIONS>(pos, moveList);
   while (cur != moveList)
-      if (   (pinned || from_sq(*cur) == ksq || type_of(*cur) == ENPASSANT)
+      if (  ((pinned && pinned & from_sq(*cur)) || from_sq(*cur) == ksq || type_of(*cur) == EN_PASSANT)
           && !pos.legal(*cur))
           *cur = (--moveList)->move;
       else
@@ -366,3 +361,5 @@ ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {
 
   return moveList;
 }
+
+} // namespace Stockfish
index fb616d000e1b680035d148a78e4b94a875f4d119..3f895f05ad481bdf9e092bfdd7ff814de906ad51 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
 
 #include "types.h"
 
+namespace Stockfish {
+
 class Position;
 
 enum GenType {
@@ -70,4 +72,6 @@ private:
   ExtMove moveList[MAX_MOVES], *last;
 };
 
+} // namespace Stockfish
+
 #endif // #ifndef MOVEGEN_H_INCLUDED
index f5e023855561063a15ab79770f11b1ed9b6d5257..4ff4cff44b448f518a534a776b1321eef83387ba 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -20,6 +20,8 @@
 
 #include "movepick.h"
 
+namespace Stockfish {
+
 namespace {
 
   enum Stages {
@@ -99,15 +101,15 @@ void MovePicker::score() {
   static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
 
   for (auto& m : *this)
-      if (Type == CAPTURES)
+      if constexpr (Type == CAPTURES)
           m.value =  int(PieceValue[MG][pos.piece_on(to_sq(m))]) * 6
                    + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))];
 
-      else if (Type == QUIETS)
+      else if constexpr (Type == QUIETS)
           m.value =      (*mainHistory)[pos.side_to_move()][from_to(m)]
                    + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
-                   + 2 * (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
-                   + 2 * (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
+                   +     (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
+                   +     (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
                    +     (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)]
                    + (ply < MAX_LPH ? std::min(4, depth / 3) * (*lowPlyHistory)[ply][from_to(m)] : 0);
 
@@ -117,8 +119,8 @@ void MovePicker::score() {
               m.value =  PieceValue[MG][pos.piece_on(to_sq(m))]
                        - Value(type_of(pos.moved_piece(m)));
           else
-              m.value =  (*mainHistory)[pos.side_to_move()][from_to(m)]
-                       + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
+              m.value =      (*mainHistory)[pos.side_to_move()][from_to(m)]
+                       + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
                        - (1 << 28);
       }
 }
@@ -142,7 +144,7 @@ Move MovePicker::select(Pred filter) {
 }
 
 /// MovePicker::next_move() is the most important method of the MovePicker class. It
-/// returns a new pseudo legal move every time it is called until there are no more
+/// returns a new pseudo-legal move every time it is called until there are no more
 /// moves left, picking the move with the highest score from a list of generated moves.
 Move MovePicker::next_move(bool skipQuiets) {
 
@@ -263,3 +265,5 @@ top:
   assert(false);
   return MOVE_NONE; // Silence warning
 }
+
+} // namespace Stockfish
index 4c0ad55172d15101466b53babba99c2b9ea90f08..c76d49572b8af63f5c6bd8240e8bf909c0856ccd 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -27,6 +27,8 @@
 #include "position.h"
 #include "types.h"
 
+namespace Stockfish {
+
 /// StatsEntry stores the stat table value. It is usually a number but could
 /// be a move or even a nested history. We use a class instead of naked value
 /// to directly call history update operator<<() on the entry so to use stats
@@ -84,7 +86,7 @@ enum StatsType { NoCaptures, Captures };
 /// unsuccessful during the current search, and is used for reduction and move
 /// ordering decisions. It uses 2 tables (one for each color) indexed by
 /// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
-typedef Stats<int16_t, 10692, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
+typedef Stats<int16_t, 13365, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;
 
 /// At higher depths LowPlyHistory records successful quiet moves near the root
 /// and quiet moves which are/were in the PV (ttPv). It is cleared with each new
@@ -108,12 +110,12 @@ typedef Stats<int16_t, 29952, PIECE_NB, SQUARE_NB> PieceToHistory;
 typedef Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB> ContinuationHistory;
 
 
-/// MovePicker class is used to pick one pseudo legal move at a time from the
+/// MovePicker class is used to pick one pseudo-legal move at a time from the
 /// current position. The most important method is next_move(), which returns a
-/// new pseudo legal move each time it is called, until there are no moves left,
-/// when MOVE_NONE is returned. In order to improve the efficiency of the alpha
-/// beta algorithm, MovePicker attempts to return the moves which are most likely
-/// to get a cut-off first.
+/// new pseudo-legal move each time it is called, until there are no moves left,
+/// when MOVE_NONE is returned. In order to improve the efficiency of the
+/// alpha-beta algorithm, MovePicker attempts to return the moves which are most
+/// likely to get a cut-off first.
 class MovePicker {
 
   enum PickType { Next, Best };
@@ -156,4 +158,6 @@ private:
   ExtMove moves[MAX_MOVES];
 };
 
+} // namespace Stockfish
+
 #endif // #ifndef MOVEPICK_H_INCLUDED
index 9216bd41746dbffc2ffb38d9041ff7d9b3cb82a6..a6768204649f2a9e10f7cf4fa1974cd9c3ba1bd0 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 #include "../layers/affine_transform.h"
 #include "../layers/clipped_relu.h"
 
-namespace Eval::NNUE {
+namespace Stockfish::Eval::NNUE {
 
 // Input features used in evaluation function
 using RawFeatures = Features::FeatureSet<
@@ -49,6 +49,6 @@ using OutputLayer = AffineTransform<HiddenLayer2, 1>;
 
 using Network = Layers::OutputLayer;
 
-}  // namespace Eval::NNUE
+}  // namespace Stockfish::Eval::NNUE
 
 #endif // #ifndef NNUE_HALFKP_256X2_32_32_H_INCLUDED
index 382d8ff9d0623a7d5744a1ac7c89e22c1e181a22..5416f13e1f77b502c255a22792072605832a32e3 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@
 
 #include "evaluate_nnue.h"
 
-namespace Eval::NNUE {
+namespace Stockfish::Eval::NNUE {
 
   // Input feature converter
   LargePagePtr<FeatureTransformer> feature_transformer;
@@ -141,4 +141,4 @@ namespace Eval::NNUE {
     return ReadParameters(stream);
   }
 
-} // namespace Eval::NNUE
+} // namespace Stockfish::Eval::NNUE
index 6cacf37e3856ee4b7573d4ead39fc1c5bca6d0c6..24aa6cc0051e4e2a068c7459f02ed0477f24c5ce 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
 
 #include <memory>
 
-namespace Eval::NNUE {
+namespace Stockfish::Eval::NNUE {
 
   // Hash value of evaluation function structure
   constexpr std::uint32_t kHashValue =
@@ -54,6 +54,6 @@ namespace Eval::NNUE {
   template <typename T>
   using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>;
 
-}  // namespace Eval::NNUE
+}  // namespace Stockfish::Eval::NNUE
 
 #endif // #ifndef NNUE_EVALUATE_NNUE_H_INCLUDED
index 975824b658cfc9b1b07c4a4602f11c48164ac49b..a3fea9c0b2c30c2b340e101145cf5d05a2633d16 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 #include "features_common.h"
 #include <array>
 
-namespace Eval::NNUE::Features {
+namespace Stockfish::Eval::NNUE::Features {
 
   // Class template that represents a list of values
   template <typename T, T... Values>
@@ -64,6 +64,6 @@ namespace Eval::NNUE::Features {
 
   };
 
-}  // namespace Eval::NNUE::Features
+}  // namespace Stockfish::Eval::NNUE::Features
 
 #endif // #ifndef NNUE_FEATURE_SET_H_INCLUDED
index d00a35df918e6695d6ecf34d1214daf0d17f702d..118ec9532a1b7de8278d8bc32c47a00dd91be08d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 #include "../../evaluate.h"
 #include "../nnue_common.h"
 
-namespace Eval::NNUE::Features {
+namespace Stockfish::Eval::NNUE::Features {
 
   class IndexList;
 
@@ -40,6 +40,6 @@ namespace Eval::NNUE::Features {
     kFriend // side to move
   };
 
-}  // namespace Eval::NNUE::Features
+}  // namespace Stockfish::Eval::NNUE::Features
 
 #endif // #ifndef NNUE_FEATURES_COMMON_H_INCLUDED
index 29322f040893fc9f40161b64f3a6527961b078ca..ac6317e7da66d4c424f523e39a993e9aa6ecfe51 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
 #include "half_kp.h"
 #include "index_list.h"
 
-namespace Eval::NNUE::Features {
+namespace Stockfish::Eval::NNUE::Features {
 
   // Orient a square according to perspective (rotates by 180 for black)
   inline Square orient(Color perspective, Square s) {
@@ -65,4 +65,4 @@ namespace Eval::NNUE::Features {
 
   template class HalfKP<Side::kFriend>;
 
-}  // namespace Eval::NNUE::Features
+}  // namespace Stockfish::Eval::NNUE::Features
index 708fd7ea0badd445cb2f83af418cf44c79037058..2461acb725a2a5899ecc45368a1747e5fc901e32 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 #include "../../evaluate.h"
 #include "features_common.h"
 
-namespace Eval::NNUE::Features {
+namespace Stockfish::Eval::NNUE::Features {
 
   // Feature HalfKP: Combination of the position of own king
   // and the position of pieces other than kings
@@ -54,6 +54,6 @@ namespace Eval::NNUE::Features {
                                      IndexList* removed, IndexList* added);
   };
 
-}  // namespace Eval::NNUE::Features
+}  // namespace Stockfish::Eval::NNUE::Features
 
 #endif // #ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED
index d9ad680adf7b436f0f4587e88a536e83637f7603..9f03993bedecae37cbdda8318c550625995302bb 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 #include "../../position.h"
 #include "../nnue_architecture.h"
 
-namespace Eval::NNUE::Features {
+namespace Stockfish::Eval::NNUE::Features {
 
   // Class template used for feature index list
   template <typename T, std::size_t MaxSize>
@@ -59,6 +59,6 @@ namespace Eval::NNUE::Features {
       : public ValueList<IndexType, RawFeatures::kMaxActiveDimensions> {
   };
 
-}  // namespace Eval::NNUE::Features
+}  // namespace Stockfish::Eval::NNUE::Features
 
 #endif // NNUE_FEATURES_INDEX_LIST_H_INCLUDED
index a715ca85090b8d5c3d530152768810fdd2c94da5..d2713c5aaf6078a556cb0b953fa819f37968f87d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 #include <iostream>
 #include "../nnue_common.h"
 
-namespace Eval::NNUE::Layers {
+namespace Stockfish::Eval::NNUE::Layers {
 
   // Affine transformation layer
   template <typename PreviousLayer, IndexType OutputDimensions>
@@ -41,6 +41,11 @@ namespace Eval::NNUE::Layers {
     static constexpr IndexType kOutputDimensions = OutputDimensions;
     static constexpr IndexType kPaddedInputDimensions =
         CeilToMultiple<IndexType>(kInputDimensions, kMaxSimdWidth);
+#if defined (USE_AVX512)
+    static constexpr const IndexType kOutputSimdWidth = kSimdWidth / 2;
+#elif defined (USE_SSSE3)
+    static constexpr const IndexType kOutputSimdWidth = kSimdWidth / 4;
+#endif
 
     // Size of forward propagation buffer used in this layer
     static constexpr std::size_t kSelfBufferSize =
@@ -65,51 +70,55 @@ namespace Eval::NNUE::Layers {
       for (std::size_t i = 0; i < kOutputDimensions; ++i)
         biases_[i] = read_little_endian<BiasType>(stream);
       for (std::size_t i = 0; i < kOutputDimensions * kPaddedInputDimensions; ++i)
+#if !defined (USE_SSSE3)
         weights_[i] = read_little_endian<WeightType>(stream);
+#else
+        weights_[
+          (i / 4) % (kPaddedInputDimensions / 4) * kOutputDimensions * 4 +
+          i / kPaddedInputDimensions * 4 +
+          i % 4
+        ] = read_little_endian<WeightType>(stream);
 
-#if defined (USE_SSSE3)
-      // Determine if quadruplets of weight and input products can be summed using 16bits
+      // Determine if eights of weight and input products can be summed using 16bits
       // without saturation. We assume worst case combinations of 0 and 127 for all inputs.
-      if (!stream.fail())
+      if (kOutputDimensions > 1 && !stream.fail())
       {
-          auto can_saturate = [](const WeightType* w, int idx[4]) {
-              int pSum = 0, nSum = 0;
-              for (int p = 0; p < 4; ++p)
-                  if (w[idx[p]] > 0)
-                      pSum += w[idx[p]];
-                  else
-                      nSum += w[idx[p]];
-
-              return pSum > 258 || nSum < -258;
-          };
-
-          for (IndexType i = 0; i < kOutputDimensions; ++i)
-          {
-              canSaturate16[i] = false;
-              const WeightType* w = &weights_[i * kPaddedInputDimensions];
-#if defined (USE_AVX512)
-              for (IndexType j = 0; j < (kPaddedInputDimensions & ~127) && !canSaturate16[i]; j += 128)
-                  for (int k = 0; k < 64 && !canSaturate16[i]; k += 2)
-                  {
-                      int spacing[4] = { 0, 1, 64, 65 };
-                      canSaturate16[i] = can_saturate(&w[j + k], spacing);
-                  }
-#elif defined (USE_AVX2)
-              for (IndexType j = 0; j < (kPaddedInputDimensions & ~63) && !canSaturate16[i]; j += 64)
-                  for (int k = 0; k < 32 && !canSaturate16[i]; k += 2)
+          canSaturate16.count = 0;
+#if !defined(USE_VNNI)
+          for (IndexType i = 0; i < kPaddedInputDimensions; i += 16)
+              for (IndexType j = 0; j < kOutputDimensions; ++j)
+                  for (int x = 0; x < 2; ++x)
                   {
-                      int spacing[4] = { 0, 1, 32, 33 };
-                      canSaturate16[i] = can_saturate(&w[j + k], spacing);
-                  }
-#elif defined (USE_SSSE3)
-              for (IndexType j = 0; j < (kPaddedInputDimensions & ~31) && !canSaturate16[i]; j += 32)
-                  for (int k = 0; k < 16 && !canSaturate16[i]; k += 2)
-                  {
-                      int spacing[4] = { 0, 1, 16, 17 };
-                      canSaturate16[i] = can_saturate(&w[j + k], spacing);
+                      WeightType* w = &weights_[i * kOutputDimensions + j * 4 + x * 2];
+                      int sum[2] = {0, 0};
+                      for (int k = 0; k < 8; ++k)
+                      {
+                          IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2;
+                          sum[w[idx] < 0] += w[idx];
+                      }
+                      for (int sign : {-1, 1})
+                          while (sign * sum[sign == -1] > 258)
+                          {
+                              int maxK = 0, maxW = 0;
+                              for (int k = 0; k < 8; ++k)
+                              {
+                                  IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2;
+                                  if (maxW < sign * w[idx])
+                                      maxK = k, maxW = sign * w[idx];
+                              }
+
+                              IndexType idx = maxK / 2 * kOutputDimensions * 4 + maxK % 2;
+                              sum[sign == -1] -= w[idx];
+                              canSaturate16.add(j, i + maxK / 2 * 4 + maxK % 2 + x * 2, w[idx]);
+                              w[idx] = 0;
+                          }
                   }
+
+          // Non functional optimization for faster more linear access
+          std::sort(canSaturate16.ids, canSaturate16.ids + canSaturate16.count,
+                    [](const typename CanSaturate::Entry& e1, const typename CanSaturate::Entry& e2)
+                    { return e1.in == e2.in ? e1.out < e2.out : e1.in < e2.in; });
 #endif
-          }
       }
 #endif
 
@@ -130,104 +139,6 @@ namespace Eval::NNUE::Layers {
         return _mm512_reduce_add_epi32(sum) + bias;
       };
 
-      // This function takes
-      //   sum0 = [xmm0a, xmm0b, xmm0c, xmm0d]
-      //   sum1 = [xmm1a, xmm1b, xmm1c, xmm1d]
-      //   sum2 = [xmm2a, xmm2b, xmm2c, xmm2d]
-      //   sum3 = [xmm3a, xmm3b, xmm3c, xmm3d]
-      // and returns
-      //   ret = [
-      //     reduce_add_epi32(xmm0a), reduce_add_epi32(xmm1a), reduce_add_epi32(xmm2a), reduce_add_epi32(xmm3a),
-      //     reduce_add_epi32(xmm0b), reduce_add_epi32(xmm1b), reduce_add_epi32(xmm2b), reduce_add_epi32(xmm3b),
-      //     reduce_add_epi32(xmm0c), reduce_add_epi32(xmm1c), reduce_add_epi32(xmm2c), reduce_add_epi32(xmm3c),
-      //     reduce_add_epi32(xmm0d), reduce_add_epi32(xmm1d), reduce_add_epi32(xmm2d), reduce_add_epi32(xmm3d)
-      //   ]
-      [[maybe_unused]] auto m512_hadd128x16_interleave = [](
-        __m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3) -> __m512i {
-
-        __m512i sum01a = _mm512_unpacklo_epi32(sum0, sum1);
-        __m512i sum01b = _mm512_unpackhi_epi32(sum0, sum1);
-
-        __m512i sum23a = _mm512_unpacklo_epi32(sum2, sum3);
-        __m512i sum23b = _mm512_unpackhi_epi32(sum2, sum3);
-
-        __m512i sum01 = _mm512_add_epi32(sum01a, sum01b);
-        __m512i sum23 = _mm512_add_epi32(sum23a, sum23b);
-
-        __m512i sum0123a = _mm512_unpacklo_epi64(sum01, sum23);
-        __m512i sum0123b = _mm512_unpackhi_epi64(sum01, sum23);
-
-        return _mm512_add_epi32(sum0123a, sum0123b);
-      };
-
-      [[maybe_unused]] auto m512_haddx4 = [m512_hadd128x16_interleave](
-        __m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3, __m128i bias) -> __m128i {
-
-        __m512i sum = m512_hadd128x16_interleave(sum0, sum1, sum2, sum3);
-
-        __m256i sum256lo = _mm512_castsi512_si256(sum);
-        __m256i sum256hi = _mm512_extracti64x4_epi64(sum, 1);
-
-        sum256lo = _mm256_add_epi32(sum256lo, sum256hi);
-
-        __m128i sum128lo = _mm256_castsi256_si128(sum256lo);
-        __m128i sum128hi = _mm256_extracti128_si256(sum256lo, 1);
-
-        return _mm_add_epi32(_mm_add_epi32(sum128lo, sum128hi), bias);
-      };
-
-      [[maybe_unused]] auto m512_haddx8 = [m512_hadd128x16_interleave](
-        __m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3,
-        __m512i sum4, __m512i sum5, __m512i sum6, __m512i sum7, __m256i bias) -> __m256i {
-
-        __m512i suma = m512_hadd128x16_interleave(sum0, sum1, sum2, sum3);
-        __m512i sumb = m512_hadd128x16_interleave(sum4, sum5, sum6, sum7);
-
-        __m512i indices0 = _mm512_setr_epi64(0, 1, 8, 9, 4, 5, 12, 13);
-        __m512i indices1 = _mm512_setr_epi64(2, 3, 10, 11, 6, 7, 14, 15);
-        __m512i x = _mm512_add_epi32(
-          _mm512_permutex2var_epi64(suma, indices0, sumb),
-          _mm512_permutex2var_epi64(suma, indices1, sumb));
-
-        __m256i sum256lo = _mm512_castsi512_si256(x);
-        __m256i sum256hi = _mm512_extracti64x4_epi64(x, 1);
-
-        return _mm256_add_epi32(_mm256_add_epi32(sum256lo, sum256hi), bias);
-      };
-
-      [[maybe_unused]] auto m512_hadd256x8 =[m512_hadd128x16_interleave](
-        __m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3, __m256i bias) -> __m256i {
-
-        __m512i sum = m512_hadd128x16_interleave(sum0, sum1, sum2, sum3);
-
-        __m512i indices = _mm512_setr_epi32(
-          0, 4, 8, 12, 2, 6, 10, 14,
-          1, 5, 9, 13, 3, 7, 11, 15);
-        sum = _mm512_permutexvar_epi32(indices, sum);
-
-        __m256i sum256lo = _mm512_castsi512_si256(sum);
-        __m256i sum256hi = _mm512_extracti64x4_epi64(sum, 1);
-
-        return _mm256_add_epi32(_mm256_hadd_epi32(sum256lo, sum256hi), bias);
-      };
-
-      [[maybe_unused]] auto m512_hadd256x16 = [m512_hadd128x16_interleave](
-        __m512i sum0, __m512i sum1, __m512i sum2, __m512i sum3,
-        __m512i sum4, __m512i sum5, __m512i sum6, __m512i sum7, __m512i bias) -> __m512i {
-
-        __m512i suma = m512_hadd128x16_interleave(sum0, sum1, sum2, sum3);
-        __m512i sumb = m512_hadd128x16_interleave(sum4, sum5, sum6, sum7);
-
-        __m512i indices0 = _mm512_setr_epi64(0, 1, 8, 9, 4, 5, 12, 13);
-        __m512i indices1 = _mm512_setr_epi64(2, 3, 10, 11, 6, 7, 14, 15);
-        __m512i x = _mm512_add_epi32(
-          _mm512_permutex2var_epi64(suma, indices0, sumb),
-          _mm512_permutex2var_epi64(suma, indices1, sumb));
-
-        __m512i indices = _mm512_setr_epi32(0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15);
-        return _mm512_add_epi32(_mm512_permutexvar_epi32(indices, x), bias);
-      };
-
       [[maybe_unused]] auto m512_add_dpbusd_epi32 = [=](__m512i& acc, __m512i a, __m512i b) {
 #if defined (USE_VNNI)
         acc = _mm512_dpbusd_epi32(acc, a, b);
@@ -238,14 +149,21 @@ namespace Eval::NNUE::Layers {
 #endif
       };
 
-      [[maybe_unused]] auto m512_add_dpbusd_epi32x2 = [=](__m512i& acc, __m512i a0, __m512i b0, __m512i a1, __m512i b1) {
+      [[maybe_unused]] auto m512_add_dpbusd_epi32x4 = [=](__m512i& acc, __m512i a0, __m512i b0, __m512i a1, __m512i b1,
+                                                                        __m512i a2, __m512i b2, __m512i a3, __m512i b3) {
 #if defined (USE_VNNI)
         acc = _mm512_dpbusd_epi32(acc, a0, b0);
         acc = _mm512_dpbusd_epi32(acc, a1, b1);
+        acc = _mm512_dpbusd_epi32(acc, a2, b2);
+        acc = _mm512_dpbusd_epi32(acc, a3, b3);
 #else
         __m512i product0 = _mm512_maddubs_epi16(a0, b0);
         __m512i product1 = _mm512_maddubs_epi16(a1, b1);
-        product0 = _mm512_adds_epi16(product0, product1);
+        __m512i product2 = _mm512_maddubs_epi16(a2, b2);
+        __m512i product3 = _mm512_maddubs_epi16(a3, b3);
+        product0 = _mm512_add_epi16(product0, product1);
+        product2 = _mm512_add_epi16(product2, product3);
+        product0 = _mm512_add_epi16(product0, product2);
         product0 = _mm512_madd_epi16(product0, kOnes512);
         acc = _mm512_add_epi32(acc, product0);
 #endif
@@ -263,18 +181,6 @@ namespace Eval::NNUE::Layers {
         return _mm_cvtsi128_si32(sum128) + bias;
       };
 
-      [[maybe_unused]] auto m256_haddx4 = [](__m256i sum0, __m256i sum1, __m256i sum2, __m256i sum3, __m128i bias) -> __m128i {
-        sum0 = _mm256_hadd_epi32(sum0, sum1);
-        sum2 = _mm256_hadd_epi32(sum2, sum3);
-
-        sum0 = _mm256_hadd_epi32(sum0, sum2);
-
-        __m128i sum128lo = _mm256_castsi256_si128(sum0);
-        __m128i sum128hi = _mm256_extracti128_si256(sum0, 1);
-
-        return _mm_add_epi32(_mm_add_epi32(sum128lo, sum128hi), bias);
-      };
-
       [[maybe_unused]] auto m256_add_dpbusd_epi32 = [=](__m256i& acc, __m256i a, __m256i b) {
 #if defined (USE_VNNI)
         acc = _mm256_dpbusd_epi32(acc, a, b);
@@ -285,21 +191,27 @@ namespace Eval::NNUE::Layers {
 #endif
       };
 
-      [[maybe_unused]] auto m256_add_dpbusd_epi32x2 = [=](__m256i& acc, __m256i a0, __m256i b0, __m256i a1, __m256i b1) {
+      [[maybe_unused]] auto m256_add_dpbusd_epi32x4 = [=](__m256i& acc, __m256i a0, __m256i b0, __m256i a1, __m256i b1,
+                                                                        __m256i a2, __m256i b2, __m256i a3, __m256i b3) {
 #if defined (USE_VNNI)
         acc = _mm256_dpbusd_epi32(acc, a0, b0);
         acc = _mm256_dpbusd_epi32(acc, a1, b1);
+        acc = _mm256_dpbusd_epi32(acc, a2, b2);
+        acc = _mm256_dpbusd_epi32(acc, a3, b3);
 #else
         __m256i product0 = _mm256_maddubs_epi16(a0, b0);
         __m256i product1 = _mm256_maddubs_epi16(a1, b1);
-        product0 = _mm256_adds_epi16(product0, product1);
+        __m256i product2 = _mm256_maddubs_epi16(a2, b2);
+        __m256i product3 = _mm256_maddubs_epi16(a3, b3);
+        product0 = _mm256_add_epi16(product0, product1);
+        product2 = _mm256_add_epi16(product2, product3);
+        product0 = _mm256_add_epi16(product0, product2);
         product0 = _mm256_madd_epi16(product0, kOnes256);
         acc = _mm256_add_epi32(acc, product0);
 #endif
       };
 
 #endif
-
 #if defined (USE_SSSE3)
 
       [[maybe_unused]] const __m128i kOnes128 = _mm_set1_epi16(1);
@@ -310,25 +222,21 @@ namespace Eval::NNUE::Layers {
         return _mm_cvtsi128_si32(sum) + bias;
       };
 
-      [[maybe_unused]] auto m128_haddx4 = [](__m128i sum0, __m128i sum1, __m128i sum2, __m128i sum3, __m128i bias) -> __m128i {
-        sum0 = _mm_hadd_epi32(sum0, sum1);
-        sum2 = _mm_hadd_epi32(sum2, sum3);
-
-        sum0 = _mm_hadd_epi32(sum0, sum2);
-
-        return _mm_add_epi32(sum0, bias);
-      };
-
       [[maybe_unused]] auto m128_add_dpbusd_epi32 = [=](__m128i& acc, __m128i a, __m128i b) {
         __m128i product0 = _mm_maddubs_epi16(a, b);
         product0 = _mm_madd_epi16(product0, kOnes128);
         acc = _mm_add_epi32(acc, product0);
       };
 
-      [[maybe_unused]] auto m128_add_dpbusd_epi32x2 = [=](__m128i& acc, __m128i a0, __m128i b0, __m128i a1, __m128i b1) {
+      [[maybe_unused]] auto m128_add_dpbusd_epi32x4 = [=](__m128i& acc, __m128i a0, __m128i b0, __m128i a1, __m128i b1,
+                                                                        __m128i a2, __m128i b2, __m128i a3, __m128i b3) {
         __m128i product0 = _mm_maddubs_epi16(a0, b0);
         __m128i product1 = _mm_maddubs_epi16(a1, b1);
+        __m128i product2 = _mm_maddubs_epi16(a2, b2);
+        __m128i product3 = _mm_maddubs_epi16(a3, b3);
         product0 = _mm_adds_epi16(product0, product1);
+        product2 = _mm_adds_epi16(product2, product3);
+        product0 = _mm_adds_epi16(product0, product2);
         product0 = _mm_madd_epi16(product0, kOnes128);
         acc = _mm_add_epi32(acc, product0);
       };
@@ -336,353 +244,97 @@ namespace Eval::NNUE::Layers {
 #endif
 
 #if defined (USE_AVX512)
+      using vec_t = __m512i;
+      #define vec_setzero _mm512_setzero_si512
+      #define vec_set_32 _mm512_set1_epi32
+      auto& vec_add_dpbusd_32 = m512_add_dpbusd_epi32;
+      auto& vec_add_dpbusd_32x4 = m512_add_dpbusd_epi32x4;
+      auto& vec_hadd = m512_hadd;
+#elif defined (USE_AVX2)
+      using vec_t = __m256i;
+      #define vec_setzero _mm256_setzero_si256
+      #define vec_set_32 _mm256_set1_epi32
+      auto& vec_add_dpbusd_32 = m256_add_dpbusd_epi32;
+      auto& vec_add_dpbusd_32x4 = m256_add_dpbusd_epi32x4;
+      auto& vec_hadd = m256_hadd;
+#elif defined (USE_SSSE3)
+      using vec_t = __m128i;
+      #define vec_setzero _mm_setzero_si128
+      #define vec_set_32 _mm_set1_epi32
+      auto& vec_add_dpbusd_32 = m128_add_dpbusd_epi32;
+      auto& vec_add_dpbusd_32x4 = m128_add_dpbusd_epi32x4;
+      auto& vec_hadd = m128_hadd;
+#endif
 
-      constexpr IndexType kNumChunks512 = kPaddedInputDimensions / (kSimdWidth * 2);
-      constexpr IndexType kNumChunks256 = kPaddedInputDimensions / kSimdWidth;
+#if defined (USE_SSSE3)
 
       const auto output = reinterpret_cast<OutputType*>(buffer);
+      const auto input_vector = reinterpret_cast<const vec_t*>(input);
 
-      // Since to saturate a zmm register it takes 64 bytes we
-      // cannot use AVX512 for the smaller affine transforms.
-      // Instead we fallback to a AVX2 implementation if the
-      // kInputDimensions isn't a multiple of 64.
-      // Note that this means that for example for
-      // kInputDimensions of 96 we fallback to AVX2 even though
-      // the first 64 elements could be processed with AVX512.
-      // This is caused by mixing the __m256 and __m512 variables
-      // required to better handle that case and it would
-      // require handling more cases statically not to lose performance.
-      // This should be revisited if such input dimensions are to be considered.
-      [[maybe_unused]] const auto input_vector512 = reinterpret_cast<const __m512i*>(input);
-      [[maybe_unused]] const auto input_vector256 = reinterpret_cast<const __m256i*>(input);
+      static_assert(kOutputDimensions % kOutputSimdWidth == 0 || kOutputDimensions == 1);
 
       // kOutputDimensions is either 1 or a multiple of kSimdWidth
       // because then it is also an input dimension.
-      if constexpr (kOutputDimensions % 16 == 0 && kNumChunks256 == 1)
+      if constexpr (kOutputDimensions % kOutputSimdWidth == 0)
       {
-        for (IndexType i = 0; i < kOutputDimensions; i += 16)
-        {
-          const IndexType offset01a = (i + 0) * kPaddedInputDimensions;
-          const IndexType offset23a = (i + 2) * kPaddedInputDimensions;
-          const IndexType offset45a = (i + 4) * kPaddedInputDimensions;
-          const IndexType offset67a = (i + 6) * kPaddedInputDimensions;
-          const IndexType offset01b = (i + 8) * kPaddedInputDimensions;
-          const IndexType offset23b = (i + 10) * kPaddedInputDimensions;
-          const IndexType offset45b = (i + 12) * kPaddedInputDimensions;
-          const IndexType offset67b = (i + 14) * kPaddedInputDimensions;
-
-          const __m512i bias = *reinterpret_cast<const __m512i*>(&biases_[i]);
-          __m512i* outptr = reinterpret_cast<__m512i*>(&output[i]);
-
-          __m512i sum01a = _mm512_setzero_si512();
-          __m512i sum23a = _mm512_setzero_si512();
-          __m512i sum45a = _mm512_setzero_si512();
-          __m512i sum67a = _mm512_setzero_si512();
-          __m512i sum01b = _mm512_setzero_si512();
-          __m512i sum23b = _mm512_setzero_si512();
-          __m512i sum45b = _mm512_setzero_si512();
-          __m512i sum67b = _mm512_setzero_si512();
-
-          const auto row01a = *reinterpret_cast<const __m512i*>(&weights_[offset01a]);
-          const auto row23a = *reinterpret_cast<const __m512i*>(&weights_[offset23a]);
-          const auto row45a = *reinterpret_cast<const __m512i*>(&weights_[offset45a]);
-          const auto row67a = *reinterpret_cast<const __m512i*>(&weights_[offset67a]);
-          const auto row01b = *reinterpret_cast<const __m512i*>(&weights_[offset01b]);
-          const auto row23b = *reinterpret_cast<const __m512i*>(&weights_[offset23b]);
-          const auto row45b = *reinterpret_cast<const __m512i*>(&weights_[offset45b]);
-          const auto row67b = *reinterpret_cast<const __m512i*>(&weights_[offset67b]);
-
-          const __m256i in256 = input_vector256[0];
-          const __m512i in = _mm512_inserti64x4(_mm512_castsi256_si512(in256), in256, 1);
-
-          m512_add_dpbusd_epi32(sum01a, in, row01a);
-          m512_add_dpbusd_epi32(sum23a, in, row23a);
-          m512_add_dpbusd_epi32(sum45a, in, row45a);
-          m512_add_dpbusd_epi32(sum67a, in, row67a);
-          m512_add_dpbusd_epi32(sum01b, in, row01b);
-          m512_add_dpbusd_epi32(sum23b, in, row23b);
-          m512_add_dpbusd_epi32(sum45b, in, row45b);
-          m512_add_dpbusd_epi32(sum67b, in, row67b);
-
-          *outptr = m512_hadd256x16(
-            sum01a, sum23a, sum45a, sum67a,
-            sum01b, sum23b, sum45b, sum67b, bias);
-        }
-      }
-      else if constexpr (kOutputDimensions % 4 == 0)
-      {
-        for (IndexType i = 0; i < kOutputDimensions; i += 4)
-        {
-          const IndexType offset0 = (i + 0) * kPaddedInputDimensions;
-          const IndexType offset1 = (i + 1) * kPaddedInputDimensions;
-          const IndexType offset2 = (i + 2) * kPaddedInputDimensions;
-          const IndexType offset3 = (i + 3) * kPaddedInputDimensions;
+          constexpr IndexType kNumChunks = kPaddedInputDimensions / 4;
 
-          const __m128i bias = *reinterpret_cast<const __m128i*>(&biases_[i]);
-          __m128i* outptr = reinterpret_cast<__m128i*>(&output[i]);
+          const auto input32 = reinterpret_cast<const std::int32_t*>(input);
+          vec_t* outptr = reinterpret_cast<vec_t*>(output);
+          std::memcpy(output, biases_, kOutputDimensions * sizeof(OutputType));
 
-          if constexpr (kPaddedInputDimensions % (kSimdWidth * 2) == 0)
+          for (int i = 0; i < (int)kNumChunks - 3; i += 4)
           {
-            __m512i sum0 = _mm512_setzero_si512();
-            __m512i sum1 = _mm512_setzero_si512();
-            __m512i sum2 = _mm512_setzero_si512();
-            __m512i sum3 = _mm512_setzero_si512();
-
-            const auto row0 = reinterpret_cast<const __m512i*>(&weights_[offset0]);
-            const auto row1 = reinterpret_cast<const __m512i*>(&weights_[offset1]);
-            const auto row2 = reinterpret_cast<const __m512i*>(&weights_[offset2]);
-            const auto row3 = reinterpret_cast<const __m512i*>(&weights_[offset3]);
-
-            int j = 0;
-            if (!canSaturate16x4[i / 4])
-            {
-                for (; j < (int)kNumChunks512 - 1; j += 2)
-                {
-                    const __m512i in0 = input_vector512[j];
-                    const __m512i in1 = input_vector512[j + 1];
-
-                    m512_add_dpbusd_epi32x2(sum0, in0, row0[j], in1, row0[j + 1]);
-                    m512_add_dpbusd_epi32x2(sum1, in0, row1[j], in1, row1[j + 1]);
-                    m512_add_dpbusd_epi32x2(sum2, in0, row2[j], in1, row2[j + 1]);
-                    m512_add_dpbusd_epi32x2(sum3, in0, row3[j], in1, row3[j + 1]);
-                }
-            }
-            for (; j < (int)kNumChunks512; ++j)
-            {
-              const __m512i in = input_vector512[j];
-
-              m512_add_dpbusd_epi32(sum0, in, row0[j]);
-              m512_add_dpbusd_epi32(sum1, in, row1[j]);
-              m512_add_dpbusd_epi32(sum2, in, row2[j]);
-              m512_add_dpbusd_epi32(sum3, in, row3[j]);
-            }
-
-            *outptr = m512_haddx4(sum0, sum1, sum2, sum3, bias);
+              const vec_t in0 = vec_set_32(input32[i + 0]);
+              const vec_t in1 = vec_set_32(input32[i + 1]);
+              const vec_t in2 = vec_set_32(input32[i + 2]);
+              const vec_t in3 = vec_set_32(input32[i + 3]);
+              const auto col0 = reinterpret_cast<const vec_t*>(&weights_[(i + 0) * kOutputDimensions * 4]);
+              const auto col1 = reinterpret_cast<const vec_t*>(&weights_[(i + 1) * kOutputDimensions * 4]);
+              const auto col2 = reinterpret_cast<const vec_t*>(&weights_[(i + 2) * kOutputDimensions * 4]);
+              const auto col3 = reinterpret_cast<const vec_t*>(&weights_[(i + 3) * kOutputDimensions * 4]);
+              for (int j = 0; j * kOutputSimdWidth < kOutputDimensions; ++j)
+                  vec_add_dpbusd_32x4(outptr[j], in0, col0[j], in1, col1[j], in2, col2[j], in3, col3[j]);
           }
-          else
-          {
-            __m256i sum0 = _mm256_setzero_si256();
-            __m256i sum1 = _mm256_setzero_si256();
-            __m256i sum2 = _mm256_setzero_si256();
-            __m256i sum3 = _mm256_setzero_si256();
-
-            const auto row0 = reinterpret_cast<const __m256i*>(&weights_[offset0]);
-            const auto row1 = reinterpret_cast<const __m256i*>(&weights_[offset1]);
-            const auto row2 = reinterpret_cast<const __m256i*>(&weights_[offset2]);
-            const auto row3 = reinterpret_cast<const __m256i*>(&weights_[offset3]);
-
-            for (IndexType j = 0; j < kNumChunks256; ++j)
-            {
-              const __m256i in = input_vector256[j];
-
-              m256_add_dpbusd_epi32(sum0, in, row0[j]);
-              m256_add_dpbusd_epi32(sum1, in, row1[j]);
-              m256_add_dpbusd_epi32(sum2, in, row2[j]);
-              m256_add_dpbusd_epi32(sum3, in, row3[j]);
-            }
-
-            *outptr = m256_haddx4(sum0, sum1, sum2, sum3, bias);
-          }
-        }
+          for (int i = 0; i < canSaturate16.count; ++i)
+              output[canSaturate16.ids[i].out] += input[canSaturate16.ids[i].in] * canSaturate16.ids[i].w;
       }
       else if constexpr (kOutputDimensions == 1)
       {
-        if constexpr (kPaddedInputDimensions % (kSimdWidth * 2) == 0)
-        {
-          __m512i sum0 = _mm512_setzero_si512();
-
-          const auto row0 = reinterpret_cast<const __m512i*>(&weights_[0]);
-
-          for (IndexType j = 0; j < kNumChunks512; ++j)
-          {
-            const __m512i in = input_vector512[j];
-
-            m512_add_dpbusd_epi32(sum0, in, row0[j]);
-          }
-
-          output[0] = m512_hadd(sum0, biases_[0]);
-        }
-        else
-        {
-          __m256i sum0 = _mm256_setzero_si256();
-
-          const auto row0 = reinterpret_cast<const __m256i*>(&weights_[0]);
-
-          for (IndexType j = 0; j < kNumChunks256; ++j)
+#if defined (USE_AVX512)
+          if constexpr (kPaddedInputDimensions % (kSimdWidth * 2) != 0)
           {
-            const __m256i in = input_vector256[j];
-
-            m256_add_dpbusd_epi32(sum0, in, row0[j]);
-          }
-
-          output[0] = m256_hadd(sum0, biases_[0]);
-        }
-      }
-      else
-      {
-        // This case can never happen because kOutputDimensions
-        // is always 1 or a multiple of kSimdWidth.
-        assert(false);
-      }
-
-#elif defined (USE_AVX2)
+              constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
+              const auto input_vector256 = reinterpret_cast<const __m256i*>(input);
 
-      constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
+              __m256i sum0 = _mm256_setzero_si256();
+              const auto row0 = reinterpret_cast<const __m256i*>(&weights_[0]);
 
-      const auto output = reinterpret_cast<OutputType*>(buffer);
-      const auto input_vector = reinterpret_cast<const __m256i*>(input);
-
-      // kOutputDimensions is either 1 or a multiple of kSimdWidth
-      // because then it is also an input dimension.
-      if constexpr (kOutputDimensions % 4 == 0)
-      {
-        for (IndexType i = 0; i < kOutputDimensions; i += 4)
-        {
-          const IndexType offset0 = (i + 0) * kPaddedInputDimensions;
-          const IndexType offset1 = (i + 1) * kPaddedInputDimensions;
-          const IndexType offset2 = (i + 2) * kPaddedInputDimensions;
-          const IndexType offset3 = (i + 3) * kPaddedInputDimensions;
-
-          const __m128i bias = *reinterpret_cast<const __m128i*>(&biases_[i]);
-          __m128i* outptr = reinterpret_cast<__m128i*>(&output[i]);
-
-          __m256i sum0 = _mm256_setzero_si256();
-          __m256i sum1 = _mm256_setzero_si256();
-          __m256i sum2 = _mm256_setzero_si256();
-          __m256i sum3 = _mm256_setzero_si256();
-
-          const auto row0 = reinterpret_cast<const __m256i*>(&weights_[offset0]);
-          const auto row1 = reinterpret_cast<const __m256i*>(&weights_[offset1]);
-          const auto row2 = reinterpret_cast<const __m256i*>(&weights_[offset2]);
-          const auto row3 = reinterpret_cast<const __m256i*>(&weights_[offset3]);
-
-          int j = 0;
-          if (!canSaturate16x4[i / 4])
-          {
-              for (; j < (int)kNumChunks - 1; j += 2)
+              for (int j = 0; j < (int)kNumChunks; ++j)
               {
-                  const __m256i in0 = input_vector[j];
-                  const __m256i in1 = input_vector[j + 1];
-
-                  m256_add_dpbusd_epi32x2(sum0, in0, row0[j], in1, row0[j + 1]);
-                  m256_add_dpbusd_epi32x2(sum1, in0, row1[j], in1, row1[j + 1]);
-                  m256_add_dpbusd_epi32x2(sum2, in0, row2[j], in1, row2[j + 1]);
-                  m256_add_dpbusd_epi32x2(sum3, in0, row3[j], in1, row3[j + 1]);
+                  const __m256i in = input_vector256[j];
+                  m256_add_dpbusd_epi32(sum0, in, row0[j]);
               }
+              output[0] = m256_hadd(sum0, biases_[0]);
           }
-          for (; j < (int)kNumChunks; ++j)
+          else
+#endif
           {
-                const __m256i in = input_vector[j];
-
-                m256_add_dpbusd_epi32(sum0, in, row0[j]);
-                m256_add_dpbusd_epi32(sum1, in, row1[j]);
-                m256_add_dpbusd_epi32(sum2, in, row2[j]);
-                m256_add_dpbusd_epi32(sum3, in, row3[j]);
-          }
-
-          *outptr = m256_haddx4(sum0, sum1, sum2, sum3, bias);
-        }
-      }
-      else if constexpr (kOutputDimensions == 1)
-      {
-        __m256i sum0 = _mm256_setzero_si256();
-
-        const auto row0 = reinterpret_cast<const __m256i*>(&weights_[0]);
-
-        for (IndexType j = 0; j < kNumChunks; ++j)
-        {
-            const __m256i in = input_vector[j];
-
-            m256_add_dpbusd_epi32(sum0, in, row0[j]);
-        }
-
-        output[0] = m256_hadd(sum0, biases_[0]);
-      }
-      else
-      {
-        // This case can never happen because kOutputDimensions
-        // is always 1 or a multiple of kSimdWidth.
-        assert(false);
-      }
-
-#elif defined (USE_SSSE3)
-
-      constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
-
-      auto output = reinterpret_cast<OutputType*>(buffer);
-      const auto input_vector = reinterpret_cast<const __m128i*>(input);
+#if defined (USE_AVX512)
+              constexpr IndexType kNumChunks = kPaddedInputDimensions / (kSimdWidth * 2);
+#else
+              constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
+#endif
+              vec_t sum0 = vec_setzero();
+              const auto row0 = reinterpret_cast<const vec_t*>(&weights_[0]);
 
-      // kOutputDimensions is either 1 or a multiple of kSimdWidth
-      // because then it is also an input dimension.
-      if constexpr (kOutputDimensions % 4 == 0)
-      {
-        for (IndexType i = 0; i < kOutputDimensions; i += 4)
-        {
-          const IndexType offset0 = (i + 0) * kPaddedInputDimensions;
-          const IndexType offset1 = (i + 1) * kPaddedInputDimensions;
-          const IndexType offset2 = (i + 2) * kPaddedInputDimensions;
-          const IndexType offset3 = (i + 3) * kPaddedInputDimensions;
-
-          const __m128i bias = *reinterpret_cast<const __m128i*>(&biases_[i]);
-          __m128i* outptr = reinterpret_cast<__m128i*>(&output[i]);
-
-          __m128i sum0 = _mm_setzero_si128();
-          __m128i sum1 = _mm_setzero_si128();
-          __m128i sum2 = _mm_setzero_si128();
-          __m128i sum3 = _mm_setzero_si128();
-
-          const auto row0 = reinterpret_cast<const __m128i*>(&weights_[offset0]);
-          const auto row1 = reinterpret_cast<const __m128i*>(&weights_[offset1]);
-          const auto row2 = reinterpret_cast<const __m128i*>(&weights_[offset2]);
-          const auto row3 = reinterpret_cast<const __m128i*>(&weights_[offset3]);
-
-          int j = 0;
-          if (!canSaturate16x4[i / 4])
-          {
-              for (; j < (int)kNumChunks - 1; j += 2)
+              for (int j = 0; j < (int)kNumChunks; ++j)
               {
-                  const __m128i in0 = input_vector[j];
-                  const __m128i in1 = input_vector[j + 1];
-
-                  m128_add_dpbusd_epi32x2(sum0, in0, row0[j], in1, row0[j + 1]);
-                  m128_add_dpbusd_epi32x2(sum1, in0, row1[j], in1, row1[j + 1]);
-                  m128_add_dpbusd_epi32x2(sum2, in0, row2[j], in1, row2[j + 1]);
-                  m128_add_dpbusd_epi32x2(sum3, in0, row3[j], in1, row3[j + 1]);
+                  const vec_t in = input_vector[j];
+                  vec_add_dpbusd_32(sum0, in, row0[j]);
               }
+              output[0] = vec_hadd(sum0, biases_[0]);
           }
-          for (; j < (int)kNumChunks; ++j)
-          {
-              const __m128i in = input_vector[j];
-
-              m128_add_dpbusd_epi32(sum0, in, row0[j]);
-              m128_add_dpbusd_epi32(sum1, in, row1[j]);
-              m128_add_dpbusd_epi32(sum2, in, row2[j]);
-              m128_add_dpbusd_epi32(sum3, in, row3[j]);
-          }
-
-          *outptr = m128_haddx4(sum0, sum1, sum2, sum3, bias);
-        }
-      }
-      else if constexpr (kOutputDimensions == 1)
-      {
-        __m128i sum0 = _mm_setzero_si128();
-
-        const auto row0 = reinterpret_cast<const __m128i*>(&weights_[0]);
-
-        for (int j = 0; j < (int)kNumChunks; ++j)
-        {
-          const __m128i in = input_vector[j];
-
-          m128_add_dpbusd_epi32(sum0, in, row0[j]);
-        }
-
-        output[0] = m128_hadd(sum0, biases_[0]);
-      }
-      else
-      {
-        // This case can never happen because kOutputDimensions
-        // is always 1 or a multiple of kSimdWidth.
-        assert(false);
       }
 
 #else
@@ -693,11 +345,7 @@ namespace Eval::NNUE::Layers {
 
 #if defined(USE_SSE2)
       constexpr IndexType kNumChunks = kPaddedInputDimensions / kSimdWidth;
-#ifndef USE_SSSE3
       const __m128i kZeros = _mm_setzero_si128();
-#else
-      const __m128i kOnes = _mm_set1_epi16(1);
-#endif
       const auto input_vector = reinterpret_cast<const __m128i*>(input);
 
 #elif defined(USE_MMX)
@@ -792,12 +440,25 @@ namespace Eval::NNUE::Layers {
 
     alignas(kCacheLineSize) BiasType biases_[kOutputDimensions];
     alignas(kCacheLineSize) WeightType weights_[kOutputDimensions * kPaddedInputDimensions];
-    union {
-        uint32_t canSaturate16x4[(kOutputDimensions + 3) / 4];
-        bool canSaturate16[kOutputDimensions];
-    };
+#if defined (USE_SSSE3)
+    struct CanSaturate {
+        int count;
+        struct Entry {
+            uint16_t out;
+            uint16_t in;
+            int8_t w;
+        } ids[kPaddedInputDimensions * kOutputDimensions * 3 / 4];
+
+        void add(int i, int j, int8_t w) {
+            ids[count].out = i;
+            ids[count].in = j;
+            ids[count].w = w;
+            ++count;
+        }
+    } canSaturate16;
+#endif
   };
 
-}  // namespace Eval::NNUE::Layers
+}  // namespace Stockfish::Eval::NNUE::Layers
 
 #endif // #ifndef NNUE_LAYERS_AFFINE_TRANSFORM_H_INCLUDED
index 7f6d67bfe3b9cf5a104c64e8bdddcbdce154c2be..a10e3e482b722e919f2d0b9740090792a3c1e30b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
 
 #include "../nnue_common.h"
 
-namespace Eval::NNUE::Layers {
+namespace Stockfish::Eval::NNUE::Layers {
 
   // Clipped ReLU
   template <typename PreviousLayer>
@@ -161,6 +161,6 @@ namespace Eval::NNUE::Layers {
     PreviousLayer previous_layer_;
   };
 
-}  // namespace Eval::NNUE::Layers
+}  // namespace Stockfish::Eval::NNUE::Layers
 
 #endif // NNUE_LAYERS_CLIPPED_RELU_H_INCLUDED
index afca14c82c8ea47c646c346189661c35e8d79b5b..43b06eec5a943066b2b686b6ff27657605321e98 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
 
 #include "../nnue_common.h"
 
-namespace Eval::NNUE::Layers {
+namespace Stockfish::Eval::NNUE::Layers {
 
 // Input layer
 template <IndexType OutputDimensions, IndexType Offset = 0>
@@ -63,6 +63,6 @@ class InputSlice {
  private:
 };
 
-}  // namespace Layers
+}  // namespace Stockfish::Eval::NNUE::Layers
 
 #endif // #ifndef NNUE_LAYERS_INPUT_SLICE_H_INCLUDED
index a357d83526c89ef175e8fc10e6fe1e25b420e4bf..55fafa138fc77203b4612f2b7162ccc25a6d047b 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
 
 #include "nnue_architecture.h"
 
-namespace Eval::NNUE {
+namespace Stockfish::Eval::NNUE {
 
   // The accumulator of a StateInfo without parent is set to the INIT state
   enum AccumulatorState { EMPTY, COMPUTED, INIT };
@@ -35,6 +35,6 @@ namespace Eval::NNUE {
     AccumulatorState state[2];
   };
 
-}  // namespace Eval::NNUE
+}  // namespace Stockfish::Eval::NNUE
 
 #endif // NNUE_ACCUMULATOR_H_INCLUDED
index 91cdc4bda23158b9a418d535cb14063a3b3c2b90..1680368edb51b288f07630f1c15d24dc1d49e65a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 // Defines the network structure
 #include "architectures/halfkp_256x2-32-32.h"
 
-namespace Eval::NNUE {
+namespace Stockfish::Eval::NNUE {
 
   static_assert(kTransformedFeatureDimensions % kMaxSimdWidth == 0, "");
   static_assert(Network::kOutputDimensions == 1, "");
@@ -33,6 +33,6 @@ namespace Eval::NNUE {
   // Trigger for full calculation instead of difference calculation
   constexpr auto kRefreshTriggers = RawFeatures::kRefreshTriggers;
 
-}  // namespace Eval::NNUE
+}  // namespace Stockfish::Eval::NNUE
 
 #endif // #ifndef NNUE_ARCHITECTURE_H_INCLUDED
index f9ff2bc81ee8f919903fef0f37217379a1304262..09a152a53c90197f2c85191f169a5e13b658be2d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -43,7 +43,7 @@
 #include <arm_neon.h>
 #endif
 
-namespace Eval::NNUE {
+namespace Stockfish::Eval::NNUE {
 
   // Version of the evaluation file
   constexpr std::uint32_t kVersion = 0x7AF32F16u;
@@ -127,6 +127,6 @@ namespace Eval::NNUE {
       return result;
   }
 
-}  // namespace Eval::NNUE
+}  // namespace Stockfish::Eval::NNUE
 
 #endif // #ifndef NNUE_COMMON_H_INCLUDED
index 85bc2bc8e66cb5014cfb779e7f25e3482d1aa8a9..1e0b0e6da55112dbcddf78bddeb31668564f5e66 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
 
 #include <cstring> // std::memset()
 
-namespace Eval::NNUE {
+namespace Stockfish::Eval::NNUE {
 
   // If vector instructions are enabled, we update and refresh the
   // accumulator tile by tile such that each tile fits in the CPU's
@@ -412,6 +412,6 @@ namespace Eval::NNUE {
         WeightType weights_[kHalfDimensions * kInputDimensions];
   };
 
-}  // namespace Eval::NNUE
+}  // namespace Stockfish::Eval::NNUE
 
 #endif // #ifndef NNUE_FEATURE_TRANSFORMER_H_INCLUDED
index ed83fde72e5980d2a0cd8ff20f2df7f724b5675f..9a0610a0f53f08dcaf8a460cea629f5a7ed05300 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #include "position.h"
 #include "thread.h"
 
+namespace Stockfish {
+
 namespace {
 
   #define V Value
   #define S(mg, eg) make_score(mg, eg)
 
   // Pawn penalties
-  constexpr Score Backward      = S( 8, 25);
-  constexpr Score Doubled       = S(10, 55);
+  constexpr Score Backward      = S( 9, 22);
+  constexpr Score Doubled       = S(13, 51);
+  constexpr Score DoubledEarly  = S(20,  7);
   constexpr Score Isolated      = S( 3, 15);
-  constexpr Score WeakLever     = S( 3, 55);
-  constexpr Score WeakUnopposed = S(13, 25);
+  constexpr Score WeakLever     = S( 4, 58);
+  constexpr Score WeakUnopposed = S(13, 24);
 
   // Bonus for blocked pawns at 5th or 6th rank
-  constexpr Score BlockedPawn[2] = { S(-15, -3), S(-6, 3) };
+  constexpr Score BlockedPawn[2] = { S(-17, -6), S(-9, 2) };
 
   constexpr Score BlockedStorm[RANK_NB] = {
     S(0, 0), S(0, 0), S(75, 78), S(-8, 16), S(-6, 10), S(-6, 6), S(0, 2)
   };
 
   // Connected pawn bonus
-  constexpr int Connected[RANK_NB] = { 0, 5, 7, 11, 24, 48, 86 };
+  constexpr int Connected[RANK_NB] = { 0, 5, 7, 11, 23, 48, 87 };
 
   // Strength of pawn shelter for our king by [distance from edge][rank].
   // RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king.
@@ -69,8 +72,8 @@ namespace {
 
   // KingOnFile[semi-open Us][semi-open Them] contains bonuses/penalties
   // for king when the king is on a semi-open or open file.
-  constexpr Score KingOnFile[2][2] = {{ S(-19,12), S(-6, 7)  },
-                                     {  S(  0, 2), S( 6,-5) }};
+  constexpr Score KingOnFile[2][2] = {{ S(-21,10), S(-7, 1)  },
+                                     {  S(  0,-3), S( 9,-4) }};
 
   #undef S
   #undef V
@@ -86,6 +89,7 @@ namespace {
 
     constexpr Color     Them = ~Us;
     constexpr Direction Up   = pawn_push(Us);
+    constexpr Direction Down = -Up;
 
     Bitboard neighbours, stoppers, support, phalanx, opposed;
     Bitboard lever, leverPush, blocked;
@@ -123,6 +127,13 @@ namespace {
         phalanx    = neighbours & rank_bb(s);
         support    = neighbours & rank_bb(s - Up);
 
+        if (doubled)
+        {
+            // Additional doubled penalty if none of their pawns is fixed
+            if (!(ourPawns & shift<Down>(theirPawns | pawn_attacks_bb<Them>(theirPawns))))
+                score -= DoubledEarly;
+        }
+
         // A pawn is backward when it is behind all pawns of the same color on
         // the adjacent files and cannot safely advance.
         backward =  !(neighbours & forward_ranks_bb(Them, s + Up))
@@ -172,7 +183,7 @@ namespace {
 
         else if (backward)
             score -=  Backward
-                    + WeakUnopposed * !opposed;
+                    + WeakUnopposed * !opposed * bool(~(FileABB | FileHBB) & s);
 
         if (!support)
             score -=  Doubled * doubled
@@ -289,3 +300,5 @@ template Score Entry::do_king_safety<WHITE>(const Position& pos);
 template Score Entry::do_king_safety<BLACK>(const Position& pos);
 
 } // namespace Pawns
+
+} // namespace Stockfish
index 5499826e8d9fe5b6b78cfb0a0e880fce66388b39..124619d66a0c20805fa5d5d3f328f6167d0b6943 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
 #include "position.h"
 #include "types.h"
 
-namespace Pawns {
+namespace Stockfish::Pawns {
 
 /// Pawns::Entry contains various information about a pawn structure. A lookup
 /// to the pawn hash table (performed by calling the probe function) returns a
@@ -65,6 +65,6 @@ typedef HashTable<Entry, 131072> Table;
 
 Entry* probe(const Position& pos);
 
-} // namespace Pawns
+} // namespace Stockfish::Pawns
 
 #endif // #ifndef PAWNS_H_INCLUDED
index 13010c1a43f49571193d745a144ad92a4867bb9d..a2ee64f81cc603e6e4a03dbbfbbc00afeb863aa6 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -34,6 +34,8 @@
 
 using std::string;
 
+namespace Stockfish {
+
 namespace Zobrist {
 
   Key psq[PIECE_NB][SQUARE_NB];
@@ -249,6 +251,8 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
       set_castling_right(c, rsq);
   }
 
+  set_state(st);
+
   // 4. En passant square.
   // Ignore if square is invalid or not on side to move relative rank 6.
   bool enpassant = false;
@@ -262,12 +266,24 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
       // a) side to move have a pawn threatening epSquare
       // b) there is an enemy pawn in front of epSquare
       // c) there is no piece on epSquare or behind epSquare
+      // d) enemy pawn didn't block a check of its own color by moving forward
       enpassant = pawn_attacks_bb(~sideToMove, st->epSquare) & pieces(sideToMove, PAWN)
                && (pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove)))
-               && !(pieces() & (st->epSquare | (st->epSquare + pawn_push(sideToMove))));
+               && !(pieces() & (st->epSquare | (st->epSquare + pawn_push(sideToMove))))
+               && (   file_of(square<KING>(sideToMove)) == file_of(st->epSquare)
+                   || !(blockers_for_king(sideToMove) & (st->epSquare + pawn_push(~sideToMove))));
   }
 
-  if (!enpassant)
+  // It's necessary for st->previous to be intialized in this way because legality check relies on its existence
+  if (enpassant) {
+      st->previous = new StateInfo();
+      remove_piece(st->epSquare - pawn_push(sideToMove));
+      st->previous->checkersBB = attackers_to(square<KING>(~sideToMove)) & pieces(sideToMove);
+      st->previous->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), st->previous->pinners[BLACK]);
+      st->previous->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), st->previous->pinners[WHITE]);
+      put_piece(make_piece(~sideToMove, PAWN), st->epSquare - pawn_push(sideToMove));
+  }
+  else
       st->epSquare = SQ_NONE;
 
   // 5-6. Halfmove clock and fullmove number
@@ -279,7 +295,6 @@ Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Th
 
   chess960 = isChess960;
   thisThread = th;
-  set_state(st);
   st->accumulator.state[WHITE] = Eval::NNUE::INIT;
   st->accumulator.state[BLACK] = Eval::NNUE::INIT;
 
@@ -393,7 +408,7 @@ Position& Position::set(const string& code, Color c, StateInfo* si) {
 /// Position::fen() returns a FEN representation of the position. In case of
 /// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
 
-const string Position::fen() const {
+string Position::fen() const {
 
   int emptyCnt;
   std::ostringstream ss;
@@ -500,23 +515,11 @@ bool Position::legal(Move m) const {
   assert(color_of(moved_piece(m)) == us);
   assert(piece_on(square<KING>(us)) == make_piece(us, KING));
 
-  // En passant captures are a tricky special case. Because they are rather
-  // uncommon, we do it simply by testing whether the king is attacked after
-  // the move is made.
-  if (type_of(m) == ENPASSANT)
-  {
-      Square ksq = square<KING>(us);
-      Square capsq = to - pawn_push(us);
-      Bitboard occupied = (pieces() ^ from ^ capsq) | to;
-
-      assert(to == ep_square());
-      assert(moved_piece(m) == make_piece(us, PAWN));
-      assert(piece_on(capsq) == make_piece(~us, PAWN));
-      assert(piece_on(to) == NO_PIECE);
-
-      return   !(attacks_bb<  ROOK>(ksq, occupied) & pieces(~us, QUEEN, ROOK))
-            && !(attacks_bb<BISHOP>(ksq, occupied) & pieces(~us, QUEEN, BISHOP));
-  }
+  // st->previous->blockersForKing consider capsq as empty.
+  // If pinned, it has to move along the king ray.
+  if (type_of(m) == EN_PASSANT)
+      return   !(st->previous->blockersForKing[sideToMove] & from)
+            || aligned(from, to, square<KING>(us));
 
   // Castling moves generation does not check if the castling path is clear of
   // enemy attacks, it is delayed at a later time: now!
@@ -531,11 +534,9 @@ bool Position::legal(Move m) const {
           if (attackers_to(s) & pieces(~us))
               return false;
 
-      // In case of Chess960, verify that when moving the castling rook we do
-      // not discover some hidden checker.
+      // In case of Chess960, verify if the Rook blocks some checks
       // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
-      return   !chess960
-            || !(attacks_bb<ROOK>(to, pieces() ^ to_sq(m)) & pieces(~us, ROOK, QUEEN));
+      return !chess960 || !(blockers_for_king(us) & to_sq(m));
   }
 
   // If the moving piece is a king, check whether the destination square is
@@ -545,8 +546,8 @@ bool Position::legal(Move m) const {
 
   // A non-king move is legal if and only if it is not pinned or it
   // is moving along the ray towards or away from the king.
-  return   !(blockers_for_king(us) & from)
-        ||  aligned(from, to, square<KING>(us));
+  return !(blockers_for_king(us) & from)
+      || aligned(from, to, square<KING>(us));
 }
 
 
@@ -562,8 +563,10 @@ bool Position::pseudo_legal(const Move m) const {
   Piece pc = moved_piece(m);
 
   // Use a slower but simpler function for uncommon cases
+  // yet we skip the legality check of MoveList<LEGAL>().
   if (type_of(m) != NORMAL)
-      return MoveList<LEGAL>(*this).contains(m);
+      return checkers() ? MoveList<    EVASIONS>(*this).contains(m)
+                        : MoveList<NON_EVASIONS>(*this).contains(m);
 
   // Is not a promotion, so promotion piece must be empty
   if (promotion_type(m) - KNIGHT != NO_PIECE_TYPE)
@@ -649,31 +652,24 @@ bool Position::gives_check(Move m) const {
   case PROMOTION:
       return attacks_bb(promotion_type(m), to, pieces() ^ from) & square<KING>(~sideToMove);
 
-  // En passant capture with check? We have already handled the case
-  // of direct checks and ordinary discovered check, so the only case we
-  // need to handle is the unusual case of a discovered check through
-  // the captured pawn.
-  case ENPASSANT:
-  {
-      Square capsq = make_square(file_of(to), rank_of(from));
-      Bitboard b = (pieces() ^ from ^ capsq) | to;
+  // The double-pushed pawn blocked a check? En Passant will remove the blocker.
+  // The only discovery check that wasn't handle is through capsq and fromsq
+  // So the King must be in the same rank as fromsq to consider this possibility.
+  // st->previous->blockersForKing consider capsq as empty.
+  case EN_PASSANT:
+      return st->previous->checkersBB
+          || (   rank_of(square<KING>(~sideToMove)) == rank_of(from)
+              && st->previous->blockersForKing[~sideToMove] & from);
 
-      return  (attacks_bb<  ROOK>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK))
-            | (attacks_bb<BISHOP>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, BISHOP));
-  }
-  case CASTLING:
+  default: //CASTLING
   {
-      Square kfrom = from;
-      Square rfrom = to; // Castling is encoded as 'king captures the rook'
-      Square kto = relative_square(sideToMove, rfrom > kfrom ? SQ_G1 : SQ_C1);
-      Square rto = relative_square(sideToMove, rfrom > kfrom ? SQ_F1 : SQ_D1);
+      // Castling is encoded as 'king captures the rook'
+      Square ksq = square<KING>(~sideToMove);
+      Square rto = relative_square(sideToMove, to > from ? SQ_F1 : SQ_D1);
 
-      return   (attacks_bb<ROOK>(rto) & square<KING>(~sideToMove))
-            && (attacks_bb<ROOK>(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & square<KING>(~sideToMove));
+      return   (attacks_bb<ROOK>(rto) & ksq)
+            && (attacks_bb<ROOK>(rto, pieces() ^ from ^ to) & ksq);
   }
-  default:
-      assert(false);
-      return false;
   }
 }
 
@@ -714,7 +710,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
   Square from = from_sq(m);
   Square to = to_sq(m);
   Piece pc = piece_on(from);
-  Piece captured = type_of(m) == ENPASSANT ? make_piece(them, PAWN) : piece_on(to);
+  Piece captured = type_of(m) == EN_PASSANT ? make_piece(them, PAWN) : piece_on(to);
 
   assert(color_of(pc) == us);
   assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
@@ -740,7 +736,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
       // update non-pawn material.
       if (type_of(captured) == PAWN)
       {
-          if (type_of(m) == ENPASSANT)
+          if (type_of(m) == EN_PASSANT)
           {
               capsq -= pawn_push(us);
 
@@ -767,7 +763,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
       // Update board and piece lists
       remove_piece(capsq);
 
-      if (type_of(m) == ENPASSANT)
+      if (type_of(m) == EN_PASSANT)
           board[capsq] = NO_PIECE;
 
       // Update material hash key and prefetch access to materialTable
@@ -813,7 +809,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
   // If the moving piece is a pawn do some special extra work
   if (type_of(pc) == PAWN)
   {
-      // Set en-passant square if the moved pawn can be captured
+      // Set en passant square if the moved pawn can be captured
       if (   (int(to) ^ int(from)) == 16
           && (pawn_attacks_bb(us, to - pawn_push(us)) & pieces(them, PAWN)))
       {
@@ -936,7 +932,7 @@ void Position::undo_move(Move m) {
       {
           Square capsq = to;
 
-          if (type_of(m) == ENPASSANT)
+          if (type_of(m) == EN_PASSANT)
           {
               capsq -= pawn_push(us);
 
@@ -1015,7 +1011,7 @@ void Position::do_null_move(StateInfo& newSt) {
   }
 
   st->key ^= Zobrist::side;
-  prefetch(TT.first_entry(st->key));
+  prefetch(TT.first_entry(key()));
 
   ++st->rule50;
   st->pliesFromNull = 0;
@@ -1040,7 +1036,7 @@ void Position::undo_null_move() {
 
 /// Position::key_after() computes the new hash key after the given move. Needed
 /// for speculative prefetch. It doesn't recognize special moves like castling,
-/// en-passant and promotions.
+/// en passant and promotions.
 
 Key Position::key_after(Move m) const {
 
@@ -1065,7 +1061,7 @@ bool Position::see_ge(Move m, Value threshold) const {
 
   assert(is_ok(m));
 
-  // Only deal with normal moves, assume others pass a simple see
+  // Only deal with normal moves, assume others pass a simple SEE
   if (type_of(m) != NORMAL)
       return VALUE_ZERO >= threshold;
 
@@ -1342,3 +1338,5 @@ bool Position::pos_is_ok() const {
 
   return true;
 }
+
+} // namespace Stockfish
index 02156448ea782ecdc8c7eca74f63bf3795019d6f..a7654aa1a547f9f4646157bf3a9cba1e4c5c6c72 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
 #include "bitboard.h"
 #include "evaluate.h"
+#include "psqt.h"
 #include "types.h"
 
 #include "nnue/nnue_accumulator.h"
 
+namespace Stockfish {
 
 /// StateInfo struct stores information needed to restore a Position object to
 /// its previous state when we retract a move. Whenever a move is made on the
@@ -86,7 +88,7 @@ public:
   // FEN string input/output
   Position& set(const std::string& fenStr, bool isChess960, StateInfo* si, Thread* th);
   Position& set(const std::string& code, Color c, StateInfo* si);
-  const std::string fen() const;
+  std::string fen() const;
 
   // Position representation
   Bitboard pieces(PieceType pt) const;
@@ -113,7 +115,7 @@ public:
   Bitboard blockers_for_king(Color c) const;
   Bitboard check_squares(PieceType pt) const;
   Bitboard pinners(Color c) const;
-  bool is_discovery_check_on_king(Color c, Move m) const;
+  bool is_discovered_check_on_king(Color c, Move m) const;
 
   // Attacks to/from a given square
   Bitboard attackers_to(Square s) const;
@@ -200,10 +202,6 @@ private:
   bool chess960;
 };
 
-namespace PSQT {
-  extern Score psq[PIECE_NB][SQUARE_NB];
-}
-
 extern std::ostream& operator<<(std::ostream& os, const Position& pos);
 
 inline Color Position::side_to_move() const {
@@ -304,7 +302,7 @@ inline Bitboard Position::check_squares(PieceType pt) const {
   return st->checkSquares[pt];
 }
 
-inline bool Position::is_discovery_check_on_king(Color c, Move m) const {
+inline bool Position::is_discovered_check_on_king(Color c, Move m) const {
   return st->blockersForKing[c] & from_sq(m);
 }
 
@@ -314,7 +312,7 @@ inline bool Position::pawn_passed(Color c, Square s) const {
 
 inline bool Position::advanced_pawn_push(Move m) const {
   return   type_of(moved_piece(m)) == PAWN
-        && relative_rank(sideToMove, to_sq(m)) > RANK_5;
+        && relative_rank(sideToMove, to_sq(m)) > RANK_6;
 }
 
 inline int Position::pawns_on_same_color_squares(Color c, Square s) const {
@@ -322,7 +320,8 @@ inline int Position::pawns_on_same_color_squares(Color c, Square s) const {
 }
 
 inline Key Position::key() const {
-  return st->key;
+  return st->rule50 < 14 ? st->key
+                         : st->key ^ make_key((st->rule50 - 14) / 8);
 }
 
 inline Key Position::pawn_key() const {
@@ -371,7 +370,7 @@ inline bool Position::capture_or_promotion(Move m) const {
 inline bool Position::capture(Move m) const {
   assert(is_ok(m));
   // Castling is encoded as "king captures rook"
-  return (!empty(to_sq(m)) && type_of(m) != CASTLING) || type_of(m) == ENPASSANT;
+  return (!empty(to_sq(m)) && type_of(m) != CASTLING) || type_of(m) == EN_PASSANT;
 }
 
 inline Piece Position::captured_piece() const {
@@ -425,4 +424,6 @@ inline StateInfo* Position::state() const {
   return st;
 }
 
+} // namespace Stockfish
+
 #endif // #ifndef POSITION_H_INCLUDED
index eb36e75e903689d2f8c64f7f17190cd2f91dded4..33a3e00c91da45d96c9885f2a06d9beca3a15ae7 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+
+#include "psqt.h"
+
 #include <algorithm>
 
-#include "types.h"
 #include "bitboard.h"
+#include "types.h"
+
+namespace Stockfish {
 
-namespace PSQT {
+namespace
+{
 
-#define S(mg, eg) make_score(mg, eg)
+auto constexpr S = make_score;
 
-// Bonus[PieceType][Square / 2] contains Piece-Square scores. For each piece
-// type on a given square a (middlegame, endgame) score pair is assigned. Table
-// is defined for files A..D and white side: it is symmetric for black side and
-// second half of the files.
+// 'Bonus' contains Piece-Square parameters.
+// Scores are explicit for files A to D, implicitly mirrored for E to H.
 constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
   { },
   { },
@@ -43,14 +47,14 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
    { S(-201,-100), S(-83,-88), S(-56,-56), S(-26,-17) }
   },
   { // Bishop
-   { S(-53,-57), S( -5,-30), S( -8,-37), S(-23,-12) },
-   { S(-15,-37), S(  8,-13), S( 19,-17), S(  4,  1) },
-   { S( -7,-16), S( 21, -1), S( -5, -2), S( 17, 10) },
-   { S( -5,-20), S( 11, -6), S( 25,  0), S( 39, 17) },
-   { S(-12,-17), S( 29, -1), S( 22,-14), S( 31, 15) },
-   { S(-16,-30), S(  6,  6), S(  1,  4), S( 11,  6) },
-   { S(-17,-31), S(-14,-20), S(  5, -1), S(  0,  1) },
-   { S(-48,-46), S(  1,-42), S(-14,-37), S(-23,-24) }
+   { S(-37,-40), S(-4 ,-21), S( -6,-26), S(-16, -8) },
+   { S(-11,-26), S(  6, -9), S( 13,-12), S(  3,  1) },
+   { S(-5 ,-11), S( 15, -1), S( -4, -1), S( 12,  7) },
+   { S(-4 ,-14), S(  8, -4), S( 18,  0), S( 27, 12) },
+   { S(-8 ,-12), S( 20, -1), S( 15,-10), S( 22, 11) },
+   { S(-11,-21), S(  4,  4), S(  1,  3), S(  8,  4) },
+   { S(-12,-22), S(-10,-14), S(  4, -1), S(  0,  1) },
+   { S(-34,-32), S(  1,-29), S(-10,-26), S(-16,-17) }
   },
   { // Rook
    { S(-31, -9), S(-20,-13), S(-14,-10), S(-5, -9) },
@@ -64,13 +68,13 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
   },
   { // Queen
    { S( 3,-69), S(-5,-57), S(-5,-47), S( 4,-26) },
-   { S(-3,-55), S( 5,-31), S( 8,-22), S(12, -4) },
+   { S(-3,-54), S( 5,-31), S( 8,-22), S(12, -4) },
    { S(-3,-39), S( 6,-18), S(13, -9), S( 7,  3) },
    { S( 4,-23), S( 5, -3), S( 9, 13), S( 8, 24) },
    { S( 0,-29), S(14, -6), S(12,  9), S( 5, 21) },
-   { S(-4,-38), S(10,-18), S( 6,-12), S( 8,  1) },
+   { S(-4,-38), S(10,-18), S( 6,-11), S( 8,  1) },
    { S(-5,-50), S( 6,-27), S(10,-24), S( 8, -8) },
-   { S(-2,-75), S(-2,-52), S( 1,-43), S(-2,-36) }
+   { S(-2,-74), S(-2,-52), S( 1,-43), S(-2,-34) }
   },
   { // King
    { S(271,  1), S(327, 45), S(271, 85), S(198, 76) },
@@ -87,18 +91,21 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
 constexpr Score PBonus[RANK_NB][FILE_NB] =
   { // Pawn (asymmetric distribution)
    { },
-   { S(  3,-10), S(  3, -6), S( 10, 10), S( 19,  0), S( 16, 14), S( 19,  7), S(  7, -5), S( -5,-19) },
-   { S( -9,-10), S(-15,-10), S( 11,-10), S( 15,  4), S( 32,  4), S( 22,  3), S(  5, -6), S(-22, -4) },
-   { S( -4,  6), S(-23, -2), S(  6, -8), S( 20, -4), S( 40,-13), S( 17,-12), S(  4,-10), S( -8, -9) },
-   { S( 13, 10), S(  0,  5), S(-13,  4), S(  1, -5), S( 11, -5), S( -2, -5), S(-13, 14), S(  5,  9) },
-   { S(  5, 28), S(-12, 20), S( -7, 21), S( 22, 28), S( -8, 30), S( -5,  7), S(-15,  6), S( -8, 13) },
-   { S( -7,  0), S(  7,-11), S( -3, 12), S(-13, 21), S(  5, 25), S(-16, 19), S( 10,  4), S( -8,  7) }
+   { S(  2, -8), S(  4, -6), S( 11,  9), S( 18,  5), S( 16, 16), S( 21,  6), S(  9, -6), S( -3,-18) },
+   { S( -9, -9), S(-15, -7), S( 11,-10), S( 15,  5), S( 31,  2), S( 23,  3), S(  6, -8), S(-20, -5) },
+   { S( -3,  7), S(-20,  1), S(  8, -8), S( 19, -2), S( 39,-14), S( 17,-13), S(  2,-11), S( -5, -6) },
+   { S( 11, 12), S( -4,  6), S(-11,  2), S(  2, -6), S( 11, -5), S(  0, -4), S(-12, 14), S(  5,  9) },
+   { S(  3, 27), S(-11, 18), S( -6, 19), S( 22, 29), S( -8, 30), S( -5,  9), S(-14,  8), S(-11, 14) },
+   { S( -7, -1), S(  6,-14), S( -2, 13), S(-11, 22), S(  4, 24), S(-14, 17), S( 10,  7), S( -9,  7) }
   };
 
-#undef S
+} // namespace
 
-Score psq[PIECE_NB][SQUARE_NB];
 
+namespace PSQT
+{
+
+Score psq[PIECE_NB][SQUARE_NB];
 
 // PSQT::init() initializes piece-square tables: the white halves of the tables are
 // copied from Bonus[] and PBonus[], adding the piece value, then the black halves of
@@ -107,16 +114,18 @@ void init() {
 
   for (Piece pc : {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING})
   {
-      Score score = make_score(PieceValue[MG][pc], PieceValue[EG][pc]);
-
-      for (Square s = SQ_A1; s <= SQ_H8; ++s)
-      {
-          File f = File(edge_distance(file_of(s)));
-          psq[ pc][s] = score + (type_of(pc) == PAWN ? PBonus[rank_of(s)][file_of(s)]
-                                                     : Bonus[pc][rank_of(s)][f]);
-          psq[~pc][flip_rank(s)] = -psq[pc][s];
-      }
+    Score score = make_score(PieceValue[MG][pc], PieceValue[EG][pc]);
+
+    for (Square s = SQ_A1; s <= SQ_H8; ++s)
+    {
+      File f = File(edge_distance(file_of(s)));
+      psq[ pc][s] = score + (type_of(pc) == PAWN ? PBonus[rank_of(s)][file_of(s)]
+                                                 : Bonus[pc][rank_of(s)][f]);
+      psq[~pc][flip_rank(s)] = -psq[pc][s];
+    }
   }
 }
 
 } // namespace PSQT
+
+} // namespace Stockfish
diff --git a/src/psqt.h b/src/psqt.h
new file mode 100644 (file)
index 0000000..7abb148
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+  Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
+
+  Stockfish 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.
+
+  Stockfish 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 PSQT_H_INCLUDED
+#define PSQT_H_INCLUDED
+
+
+#include "types.h"
+
+
+namespace Stockfish::PSQT
+{
+
+extern Score psq[PIECE_NB][SQUARE_NB];
+
+// Fill psqt array from a set of internally linked parameters
+extern void init();
+
+} // namespace Stockfish::PSQT
+
+
+#endif // PSQT_H_INCLUDED
index 60a002a908842da0221b0cb42db7df686b24cd8e..fa592a859947e09e1f30fcefb8bd276ccccec16f 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -35,6 +35,8 @@
 #include "uci.h"
 #include "syzygy/tbprobe.h"
 
+namespace Stockfish {
+
 namespace Search {
 
   LimitsType Limits;
@@ -62,8 +64,7 @@ namespace {
   constexpr uint64_t TtHitAverageWindow     = 4096;
   constexpr uint64_t TtHitAverageResolution = 1024;
 
-  // Razor and futility margins
-  constexpr int RazorMargin = 510;
+  // Futility margin
   Value futility_margin(Depth d, bool improving) {
     return Value(234 * (d - improving));
   }
@@ -82,10 +83,10 @@ namespace {
 
   // History and stats update bonus, based on depth
   int stat_bonus(Depth d) {
-    return d > 13 ? 29 : 17 * d * d + 134 * d - 134;
+    return d > 14 ? 66 : 6 * d * d + 231 * d - 206;
   }
 
-  // Add a small random component to draw evaluations to avoid 3fold-blindness
+  // Add a small random component to draw evaluations to avoid 3-fold blindness
   Value value_draw(Thread* thisThread) {
     return VALUE_DRAW + Value(2 * (thisThread->nodes & 1) - 1);
   }
@@ -423,7 +424,7 @@ void Thread::search() {
           while (true)
           {
               Depth adjustedDepth = std::max(1, rootDepth - failedHighCnt - searchAgainCounter);
-              bestValue = ::search<PV>(rootPos, ss, alpha, beta, adjustedDepth, false);
+              bestValue = Stockfish::search<PV>(rootPos, ss, alpha, beta, adjustedDepth, false);
 
               // Bring the best move to the front. It is critical that sorting
               // is done with a stable algorithm because all the values but the
@@ -617,6 +618,7 @@ namespace {
     moveCount = captureCount = quietCount = ss->moveCount = 0;
     bestValue = -VALUE_INFINITE;
     maxValue = VALUE_INFINITE;
+    ss->distanceFromPv = (PvNode ? 0 : ss->distanceFromPv);
 
     // Check for the available remaining time
     if (thisThread == Threads.main())
@@ -822,12 +824,6 @@ namespace {
         thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus;
     }
 
-    // Step 7. Razoring (~1 Elo)
-    if (   !rootNode // The required rootNode PV handling is not available in qsearch
-        &&  depth == 1
-        &&  eval <= alpha - RazorMargin)
-        return qsearch<NT>(pos, ss, alpha, beta);
-
     // Set up improving flag that is used in various pruning heuristics
     // We define position as improving if static evaluation of position is better
     // Than the previous static evaluation at our turn
@@ -836,20 +832,20 @@ namespace {
                ? ss->staticEval > (ss-4)->staticEval || (ss-4)->staticEval == VALUE_NONE
                : ss->staticEval > (ss-2)->staticEval;
 
-    // Step 8. Futility pruning: child node (~50 Elo)
+    // Step 7. Futility pruning: child node (~50 Elo)
     if (   !PvNode
-        &&  depth < 8
+        &&  depth < 9
         &&  eval - futility_margin(depth, improving) >= beta
         &&  eval < VALUE_KNOWN_WIN) // Do not return unproven wins
         return eval;
 
-    // Step 9. Null move search with verification search (~40 Elo)
+    // Step 8. Null move search with verification search (~40 Elo)
     if (   !PvNode
         && (ss-1)->currentMove != MOVE_NULL
-        && (ss-1)->statScore < 22977
+        && (ss-1)->statScore < 24185
         &&  eval >= beta
         &&  eval >= ss->staticEval
-        &&  ss->staticEval >= beta - 30 * depth - 28 * improving + 84 * ss->ttPv + 168
+        &&  ss->staticEval >= beta - 24 * depth - 34 * improving + 162 * ss->ttPv + 159
         && !excludedMove
         &&  pos.non_pawn_material(us)
         && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
@@ -857,7 +853,7 @@ namespace {
         assert(eval - beta >= 0);
 
         // Null move dynamic reduction based on depth and value
-        Depth R = (1015 + 85 * depth) / 256 + std::min(int(eval - beta) / 191, 3);
+        Depth R = (1062 + 68 * depth) / 256 + std::min(int(eval - beta) / 190, 3);
 
         ss->currentMove = MOVE_NULL;
         ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
@@ -893,9 +889,9 @@ namespace {
         }
     }
 
-    probCutBeta = beta + 183 - 49 * improving;
+    probCutBeta = beta + 209 - 44 * improving;
 
-    // Step 10. ProbCut (~10 Elo)
+    // Step 9. ProbCut (~10 Elo)
     // If we have a good enough capture and a reduced search returns a value
     // much above beta, we can (almost) safely prune the previous move.
     if (   !PvNode
@@ -968,7 +964,7 @@ namespace {
          ss->ttPv = ttPv;
     }
 
-    // Step 11. If the position is not in TT, decrease depth by 2
+    // Step 10. If the position is not in TT, decrease depth by 2
     if (   PvNode
         && depth >= 6
         && !ttMove)
@@ -976,6 +972,23 @@ namespace {
 
 moves_loop: // When in check, search starts from here
 
+    ttCapture = ttMove && pos.capture_or_promotion(ttMove);
+
+    // Step 11. A small Probcut idea, when we are in check
+    probCutBeta = beta + 400;
+    if (   ss->inCheck
+        && !PvNode
+        && depth >= 4
+        && ttCapture
+        && (tte->bound() & BOUND_LOWER)
+        && tte->depth() >= depth - 3
+        && ttValue >= probCutBeta
+        && abs(ttValue) <= VALUE_KNOWN_WIN
+        && abs(beta) <= VALUE_KNOWN_WIN
+       )
+        return probCutBeta;
+
+
     const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
                                           nullptr                   , (ss-4)->continuationHistory,
                                           nullptr                   , (ss-6)->continuationHistory };
@@ -992,7 +1005,6 @@ moves_loop: // When in check, search starts from here
 
     value = bestValue;
     singularQuietLMR = moveCountPruning = false;
-    ttCapture = ttMove && pos.capture_or_promotion(ttMove);
 
     // Mark this node as being searched
     ThreadHolding th(thisThread, posKey, ss->ply);
@@ -1032,6 +1044,14 @@ moves_loop: // When in check, search starts from here
       movedPiece = pos.moved_piece(move);
       givesCheck = pos.gives_check(move);
 
+      // Indicate PvNodes that will probably fail low if node was searched with non-PV search
+      // at depth equal or greater to current depth and result of this search was far below alpha
+      bool likelyFailLow =    PvNode
+                           && ttMove
+                           && (tte->bound() & BOUND_UPPER)
+                           && ttValue < alpha + 200 + 100 * depth
+                           && tte->depth() >= depth;
+
       // Calculate new depth for this move
       newDepth = depth - 1;
 
@@ -1046,8 +1066,20 @@ moves_loop: // When in check, search starts from here
           // Reduced depth of the next LMR search
           int lmrDepth = std::max(newDepth - reduction(improving, depth, moveCount), 0);
 
-          if (   !captureOrPromotion
-              && !givesCheck)
+          if (   captureOrPromotion
+              || givesCheck)
+          {
+              // Capture history based pruning when the move doesn't give check
+              if (   !givesCheck
+                  && lmrDepth < 1
+                  && captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] < 0)
+                  continue;
+
+              // SEE based pruning
+              if (!pos.see_ge(move, Value(-218) * depth)) // (~25 Elo)
+                  continue;
+          }
+          else
           {
               // Countermoves based pruning (~20 Elo)
               if (   lmrDepth < 4 + ((ss-1)->statScore > 0 || (ss-1)->moveCount == 1)
@@ -1058,29 +1090,17 @@ moves_loop: // When in check, search starts from here
               // Futility pruning: parent node (~5 Elo)
               if (   lmrDepth < 7
                   && !ss->inCheck
-                  && ss->staticEval + 266 + 170 * lmrDepth <= alpha
+                  && ss->staticEval + 174 + 157 * lmrDepth <= alpha
                   &&  (*contHist[0])[movedPiece][to_sq(move)]
                     + (*contHist[1])[movedPiece][to_sq(move)]
                     + (*contHist[3])[movedPiece][to_sq(move)]
-                    + (*contHist[5])[movedPiece][to_sq(move)] / 2 < 27376)
+                    + (*contHist[5])[movedPiece][to_sq(move)] / 3 < 28255)
                   continue;
 
               // Prune moves with negative SEE (~20 Elo)
               if (!pos.see_ge(move, Value(-(30 - std::min(lmrDepth, 18)) * lmrDepth * lmrDepth)))
                   continue;
           }
-          else
-          {
-              // Capture history based pruning when the move doesn't give check
-              if (   !givesCheck
-                  && lmrDepth < 1
-                  && captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] < 0)
-                  continue;
-
-              // SEE based pruning
-              if (!pos.see_ge(move, Value(-213) * depth)) // (~25 Elo)
-                  continue;
-          }
       }
 
       // Step 14. Extensions (~75 Elo)
@@ -1134,7 +1154,7 @@ moves_loop: // When in check, search starts from here
 
       // Check extension (~2 Elo)
       else if (    givesCheck
-               && (pos.is_discovery_check_on_king(~us, move) || pos.see_ge(move)))
+               && (pos.is_discovered_check_on_king(~us, move) || pos.see_ge(move)))
           extension = 1;
 
       // Last captures extension
@@ -1142,12 +1162,6 @@ moves_loop: // When in check, search starts from here
                && pos.non_pawn_material() <= 2 * RookValueMg)
           extension = 1;
 
-      // Late irreversible move extension
-      if (   move == ttMove
-          && pos.rule50_count() > 80
-          && (captureOrPromotion || type_of(movedPiece) == PAWN))
-          extension = 2;
-
       // Add extension to new depth
       newDepth += extension;
 
@@ -1164,15 +1178,19 @@ moves_loop: // When in check, search starts from here
       // Step 15. Make the move
       pos.do_move(move, st, givesCheck);
 
-      // Step 16. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
-      // re-searched at full depth.
+      (ss+1)->distanceFromPv = ss->distanceFromPv + moveCount - 1;
+
+      // Step 16. Late moves reduction / extension (LMR, ~200 Elo)
+      // We use various heuristics for the sons of a node after the first son has
+      // been searched. In general we would like to reduce them, but there are many
+      // cases where we extend a son if it has good chances to be "interesting".
       if (    depth >= 3
           &&  moveCount > 1 + 2 * rootNode
           && (  !captureOrPromotion
               || moveCountPruning
               || ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha
               || cutNode
-              || (!PvNode && !formerPv)
+              || (!PvNode && !formerPv && captureHistory[movedPiece][to_sq(move)][type_of(pos.captured_piece())] < 3678)
               || thisThread->ttHitAverage < 432 * TtHitAverageResolution * TtHitAverageWindow / 1024))
       {
           Depth r = reduction(improving, depth, moveCount);
@@ -1185,8 +1203,9 @@ moves_loop: // When in check, search starts from here
           if (th.marked())
               r++;
 
-          // Decrease reduction if position is or has been on the PV (~10 Elo)
-          if (ss->ttPv)
+          // Decrease reduction if position is or has been on the PV
+          // and node is not likely to fail low. (~10 Elo)
+          if (ss->ttPv && !likelyFailLow)
               r -= 2;
 
           // Increase reduction at root and non-PV nodes when the best move does not change frequently
@@ -1205,7 +1224,14 @@ moves_loop: // When in check, search starts from here
           if (singularQuietLMR)
               r--;
 
-          if (!captureOrPromotion)
+          if (captureOrPromotion)
+          {
+              // Unless giving check, this capture is likely bad
+              if (   !givesCheck
+                  && ss->staticEval + PieceValue[EG][pos.captured_piece()] + 210 * depth <= alpha)
+                  r++;
+          }
+          else
           {
               // Increase reduction if ttMove is a capture (~5 Elo)
               if (ttCapture)
@@ -1229,38 +1255,39 @@ moves_loop: // When in check, search starts from here
                              + (*contHist[0])[movedPiece][to_sq(move)]
                              + (*contHist[1])[movedPiece][to_sq(move)]
                              + (*contHist[3])[movedPiece][to_sq(move)]
-                             - 5287;
+                             - 4741;
 
               // Decrease/increase reduction by comparing opponent's stat score (~10 Elo)
-              if (ss->statScore >= -105 && (ss-1)->statScore < -103)
+              if (ss->statScore >= -89 && (ss-1)->statScore < -116)
                   r--;
 
-              else if ((ss-1)->statScore >= -122 && ss->statScore < -129)
+              else if ((ss-1)->statScore >= -112 && ss->statScore < -100)
                   r++;
 
               // Decrease/increase reduction for moves with a good/bad history (~30 Elo)
-              r -= ss->statScore / 14884;
-          }
-          else
-          {
-              // Unless giving check, this capture is likely bad
-              if (   !givesCheck
-                  && ss->staticEval + PieceValue[EG][pos.captured_piece()] + 210 * depth <= alpha)
-                  r++;
+              // If we are not in check use statScore, but if we are in check we use
+              // the sum of main history and first continuation history with an offset.
+              if (ss->inCheck)
+                  r -= (thisThread->mainHistory[us][from_to(move)]
+                     + (*contHist[0])[movedPiece][to_sq(move)] - 3833) / 16384;
+              else
+                  r -= ss->statScore / 14790;
           }
 
-          Depth d = std::clamp(newDepth - r, 1, newDepth);
+          // In general we want to cap the LMR depth search at newDepth. But for nodes
+          // close to the principal variation the cap is at (newDepth + 1), which will
+          // allow these nodes to be searched deeper than the pv (up to 4 plies deeper).
+          Depth d = std::clamp(newDepth - r, 1, newDepth + ((ss+1)->distanceFromPv <= 4));
 
           value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
 
-          doFullDepthSearch = value > alpha && d != newDepth;
-
+          // If the son is reduced and fails high it will be re-searched at full depth
+          doFullDepthSearch = value > alpha && d < newDepth;
           didLMR = true;
       }
       else
       {
           doFullDepthSearch = !PvNode || moveCount > 1;
-
           didLMR = false;
       }
 
@@ -1548,15 +1575,13 @@ moves_loop: // When in check, search starts from here
 
       moveCount++;
 
-      // Futility pruning
+      // Futility pruning and moveCount pruning
       if (    bestValue > VALUE_TB_LOSS_IN_MAX_PLY
           && !givesCheck
           &&  futilityBase > -VALUE_KNOWN_WIN
           && !pos.advanced_pawn_push(move))
       {
-          assert(type_of(move) != ENPASSANT); // Due to !pos.advanced_pawn_push
 
-          // moveCount pruning
           if (moveCount > 2)
               continue;
 
@@ -1718,8 +1743,8 @@ moves_loop: // When in check, search starts from here
     PieceType captured = type_of(pos.piece_on(to_sq(bestMove)));
 
     bonus1 = stat_bonus(depth + 1);
-    bonus2 = bestValue > beta + PawnValueMg ? bonus1               // larger bonus
-                                            : stat_bonus(depth);   // smaller bonus
+    bonus2 = bestValue > beta + PawnValueMg ? bonus1                                 // larger bonus
+                                            : std::min(bonus1, stat_bonus(depth));   // smaller bonus
 
     if (!pos.capture_or_promotion(bestMove))
     {
@@ -2009,3 +2034,5 @@ void Tablebases::rank_root_moves(Position& pos, Search::RootMoves& rootMoves) {
             m.tbRank = 0;
     }
 }
+
+} // namespace Stockfish
index 72d43c310dc6b44fbbe917db53bb044fef6d66bc..6f9fbd0527702516daf0c39ee30224b57a87d295 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -25,6 +25,8 @@
 #include "movepick.h"
 #include "types.h"
 
+namespace Stockfish {
+
 class Position;
 
 namespace Search {
@@ -47,6 +49,7 @@ struct Stack {
   Value staticEval;
   int statScore;
   int moveCount;
+  int distanceFromPv;
   bool inCheck;
   bool ttPv;
   bool ttHit;
@@ -106,4 +109,6 @@ void clear();
 
 } // namespace Search
 
+} // namespace Stockfish
+
 #endif // #ifndef SEARCH_H_INCLUDED
index 28b70a4a10714e825be6c23f893dc570daf508da..c0cd04c1d4d8bd8f30607b616ae02363cb84da69 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #include <windows.h>
 #endif
 
-using namespace Tablebases;
+using namespace Stockfish::Tablebases;
 
-int Tablebases::MaxCardinality;
+int Stockfish::Tablebases::MaxCardinality;
+
+namespace Stockfish {
 
 namespace {
 
@@ -1000,7 +1002,7 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) {
     // so that d->lowestSym[i] >= d->lowestSym[i+1] (when read as LittleEndian).
     // Starting from this we compute a base64[] table indexed by symbol length
     // and containing 64 bit values so that d->base64[i] >= d->base64[i+1].
-    // See http://www.eecs.harvard.edu/~michaelm/E210/huffman.pdf
+    // See https://en.wikipedia.org/wiki/Huffman_coding
     for (int i = d->base64.size() - 2; i >= 0; --i) {
         d->base64[i] = (d->base64[i + 1] + number<Sym, LittleEndian>(&d->lowestSym[i])
                                          - number<Sym, LittleEndian>(&d->lowestSym[i + 1])) / 2;
@@ -1141,7 +1143,7 @@ void* mapped(TBTable<Type>& e, const Position& pos) {
     if (e.ready.load(std::memory_order_acquire))
         return e.baseAddress; // Could be nullptr if file does not exist
 
-    std::unique_lock<std::mutex> lk(mutex);
+    std::scoped_lock<std::mutex> lk(mutex);
 
     if (e.ready.load(std::memory_order_relaxed)) // Recheck under lock
         return e.baseAddress;
@@ -1440,7 +1442,7 @@ WDLScore Tablebases::probe_wdl(Position& pos, ProbeState* result) {
 // If n = 100 immediately after a capture or pawn move, then the position
 // is also certainly a win, and during the whole phase until the next
 // capture or pawn move, the inequality to be preserved is
-// dtz + 50-movecounter <= 100.
+// dtz + 50-move-counter <= 100.
 //
 // In short, if a move is available resulting in dtz + 50-move-counter <= 99,
 // then do not accept moves leading to dtz + 50-move-counter == 100.
@@ -1610,3 +1612,5 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves) {
 
     return true;
 }
+
+} // namespace Stockfish
index b998989b3de1e761887dabab01d76cb553dea658..56734af9bdc6227d0bb68a7804d10b54ebb82003 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
 
 #include "../search.h"
 
-namespace Tablebases {
+namespace Stockfish::Tablebases {
 
 enum WDLScore {
     WDLLoss        = -2, // Loss
@@ -73,6 +73,6 @@ inline std::ostream& operator<<(std::ostream& os, const ProbeState v) {
     return os;
 }
 
-}
+} // namespace Stockfish::Tablebases
 
 #endif
index 2fbf745d072cd1c9f687bd1a75624ca07a554e9c..3ef73dfa322ba39250d01b784308f1d68f842b0e 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -26,6 +26,8 @@
 #include "syzygy/tbprobe.h"
 #include "tt.h"
 
+namespace Stockfish {
+
 ThreadPool Threads; // Global object
 
 
@@ -258,3 +260,5 @@ void ThreadPool::wait_for_search_finished() const {
         if (th != front())
             th->wait_for_search_finished();
 }
+
+} // namespace Stockfish
index 6a73423b2c3c6fa9f70ae3abc23ca3dddf02e412..2b3dea0d7cccdc05eb42f8c6f57476257a1032b8 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
 #include "search.h"
 #include "thread_win32_osx.h"
 
+namespace Stockfish {
 
 /// Thread class keeps together all the thread-related stuff. We use
 /// per-thread pawn and material hash tables so that once we get a
@@ -128,4 +129,6 @@ private:
 
 extern ThreadPool Threads;
 
+} // namespace Stockfish
+
 #endif // #ifndef THREAD_H_INCLUDED
index 75ef5d9a32888ccae231bc65ff849ecbd25980af..a21674cc68f0ddbefef117e2884ddf83a027a884 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -31,6 +31,8 @@
 
 #include <pthread.h>
 
+namespace Stockfish {
+
 static const size_t TH_STACK_SIZE = 8 * 1024 * 1024;
 
 template <class T, class P = std::pair<T*, void(T::*)()>>
@@ -57,10 +59,16 @@ public:
   void join() { pthread_join(thread, NULL); }
 };
 
+} // namespace Stockfish
+
 #else // Default case: use STL classes
 
+namespace Stockfish {
+
 typedef std::thread NativeThread;
 
+} // namespace Stockfish
+
 #endif
 
 #endif // #ifndef THREAD_WIN32_OSX_H_INCLUDED
index da08f12d9692994355daf9a27130637b4b871d98..f742d1e44221cd831022774a1163211812a81c56 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
 #include "timeman.h"
 #include "uci.h"
 
+namespace Stockfish {
+
 TimeManagement Time; // Our global time management object
 
 
@@ -95,3 +97,5 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
   if (Options["Ponder"])
       optimumTime += optimumTime / 4;
 }
+
+} // namespace Stockfish
index 5ad72b32ff83d6b26e91b732d37181798387c6c7..b1878d65f25fca5e77fade3c3765966296ac4e81 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
 #include "search.h"
 #include "thread.h"
 
+namespace Stockfish {
+
 /// The TimeManagement class computes the optimal time to think depending on
 /// the maximum available time, the game move number and other parameters.
 
@@ -44,4 +46,6 @@ private:
 
 extern TimeManagement Time;
 
+} // namespace Stockfish
+
 #endif // #ifndef TIMEMAN_H_INCLUDED
index dea7c712c4434f897de07c66d385df1e40a60d00..1f495ca9d12be229aaef9a8171690c5ae5d3ad73 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -26,6 +26,8 @@
 #include "tt.h"
 #include "uci.h"
 
+namespace Stockfish {
+
 TranspositionTable TT; // Our global transposition table
 
 /// TTEntry::save() populates the TTEntry with a new node's data, possibly
@@ -123,7 +125,7 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
   for (int i = 0; i < ClusterSize; ++i)
       if (tte[i].key16 == key16 || !tte[i].depth8)
       {
-          tte[i].genBound8 = uint8_t(generation8 | (tte[i].genBound8 & 0x7)); // Refresh
+          tte[i].genBound8 = uint8_t(generation8 | (tte[i].genBound8 & (GENERATION_DELTA - 1))); // Refresh
 
           return found = (bool)tte[i].depth8, &tte[i];
       }
@@ -132,11 +134,12 @@ TTEntry* TranspositionTable::probe(const Key key, bool& found) const {
   TTEntry* replace = tte;
   for (int i = 1; i < ClusterSize; ++i)
       // Due to our packed storage format for generation and its cyclic
-      // nature we add 263 (256 is the modulus plus 7 to keep the unrelated
-      // lowest three bits from affecting the result) to calculate the entry
-      // age correctly even after generation8 overflows into the next cycle.
-      if (  replace->depth8 - ((263 + generation8 - replace->genBound8) & 0xF8)
-          >   tte[i].depth8 - ((263 + generation8 -   tte[i].genBound8) & 0xF8))
+      // nature we add GENERATION_CYCLE (256 is the modulus, plus what
+      // is needed to keep the unrelated lowest n bits from affecting
+      // the result) to calculate the entry age correctly even after
+      // generation8 overflows into the next cycle.
+      if (  replace->depth8 - ((GENERATION_CYCLE + generation8 - replace->genBound8) & GENERATION_MASK)
+          >   tte[i].depth8 - ((GENERATION_CYCLE + generation8 -   tte[i].genBound8) & GENERATION_MASK))
           replace = &tte[i];
 
   return found = false, replace;
@@ -151,7 +154,9 @@ int TranspositionTable::hashfull() const {
   int cnt = 0;
   for (int i = 0; i < 1000; ++i)
       for (int j = 0; j < ClusterSize; ++j)
-          cnt += table[i].entry[j].depth8 && (table[i].entry[j].genBound8 & 0xF8) == generation8;
+          cnt += table[i].entry[j].depth8 && (table[i].entry[j].genBound8 & GENERATION_MASK) == generation8;
 
   return cnt / ClusterSize;
 }
+
+} // namespace Stockfish
index 6aa066c56503612da6afe8dad2b47e2e8863ed29..d915d92e43f545da1826e8408e148e952c90316a 100644 (file)
--- a/src/tt.h
+++ b/src/tt.h
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -22,6 +22,8 @@
 #include "misc.h"
 #include "types.h"
 
+namespace Stockfish {
+
 /// TTEntry struct is the 10 bytes transposition table entry, defined as below:
 ///
 /// key        16 bit
@@ -72,9 +74,15 @@ class TranspositionTable {
 
   static_assert(sizeof(Cluster) == 32, "Unexpected Cluster size");
 
+  // Constants used to refresh the hash table periodically
+  static constexpr unsigned GENERATION_BITS  = 3;                                // nb of bits reserved for other things
+  static constexpr int      GENERATION_DELTA = (1 << GENERATION_BITS);           // increment for generation field
+  static constexpr int      GENERATION_CYCLE = 255 + (1 << GENERATION_BITS);     // cycle length
+  static constexpr int      GENERATION_MASK  = (0xFF << GENERATION_BITS) & 0xFF; // mask to pull out generation number
+
 public:
  ~TranspositionTable() { aligned_large_pages_free(table); }
-  void new_search() { generation8 += 8; } // Lower 3 bits are used by PV flag and Bound
+  void new_search() { generation8 += GENERATION_DELTA; } // Lower bits are used for other things
   TTEntry* probe(const Key key, bool& found) const;
   int hashfull() const;
   void resize(size_t mbSize);
@@ -94,4 +102,6 @@ private:
 
 extern TranspositionTable TT;
 
+} // namespace Stockfish
+
 #endif // #ifndef TT_H_INCLUDED
index e94f67f816f03707fad8abf63b518335ab907a19..d9618efc9c7d94f6e27dcd510d214829ce300ab4 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -26,6 +26,8 @@
 
 using std::string;
 
+namespace Stockfish {
+
 bool Tune::update_on_last;
 const UCI::Option* LastOption = nullptr;
 BoolConditions Conditions;
@@ -126,6 +128,8 @@ void BoolConditions::set() {
       sync_cout << binary[i] << sync_endl;
 }
 
+} // namespace Stockfish
+
 
 // Init options with tuning session results instead of default values. Useful to
 // get correct bench signature after a tuning session or to test tuned values.
@@ -138,7 +142,11 @@ void BoolConditions::set() {
 
 #include <cmath>
 
+namespace Stockfish {
+
 void Tune::read_results() {
 
   /* ...insert your values here... */
 }
+
+} // namespace Stockfish
index 1489fa328c0d3d92a3f91dd3e0ff25e93dcdb459..c904c09dc9442b294004c4364d233347667ab3d6 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
 #include <type_traits>
 #include <vector>
 
+namespace Stockfish {
+
 typedef std::pair<int, int> Range; // Option's min-max values
 typedef Range (RangeFun) (int);
 
@@ -130,9 +132,9 @@ class Tune {
     SetRange range;
   };
 
-  // Our facilty to fill the container, each Entry corresponds to a parameter to tune.
-  // We use variadic templates to deal with an unspecified number of entries, each one
-  // of a possible different type.
+  // Our facility to fill the container, each Entry corresponds to a parameter
+  // to tune. We use variadic templates to deal with an unspecified number of
+  // entries, each one of a possible different type.
   static std::string next(std::string& names, bool pop = true);
 
   int add(const SetRange&, std::string&&) { return 0; }
@@ -190,4 +192,6 @@ public:
 #define TUNE_CONDITIONS() int UNIQUE(c, __LINE__) = (Conditions.init(__COUNTER__), 0); \
                           TUNE(Conditions, set_conditions)
 
+} // namespace Stockfish
+
 #endif // #ifndef TUNE_H_INCLUDED
index 8506b06eab0a1a900f6847d4754ce824940b1eee..efebce1a7b6f730f2b77c111bb66c6efed73fc79 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -83,6 +83,8 @@
 #  define pext(b, m) 0
 #endif
 
+namespace Stockfish {
+
 #ifdef USE_POPCNT
 constexpr bool HasPopCnt = true;
 #else
@@ -113,7 +115,7 @@ constexpr int MAX_PLY   = 246;
 /// bit  6-11: origin square (from 0 to 63)
 /// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
 /// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
-/// NOTE: EN-PASSANT bit is set only when a pawn can be captured
+/// NOTE: en passant bit is set only when a pawn can be captured
 ///
 /// Special cases are MOVE_NONE and MOVE_NULL. We can sneak these in because in
 /// any normal move destination square is always different from origin square
@@ -127,7 +129,7 @@ enum Move : int {
 enum MoveType {
   NORMAL,
   PROMOTION = 1 << 14,
-  ENPASSANT = 2 << 14,
+  EN_PASSANT = 2 << 14,
   CASTLING  = 3 << 14
 };
 
@@ -482,6 +484,8 @@ constexpr Key make_key(uint64_t seed) {
   return seed * 6364136223846793005ULL + 1442695040888963407ULL;
 }
 
+} // namespace Stockfish
+
 #endif // #ifndef TYPES_H_INCLUDED
 
 #include "tune.h" // Global visibility to tuning setup
index b63e55adc6d122450c594c1d2e7dd5cbba533aa3..051ff2e02f4a16f4fe2cb777a1c76746428b88fc 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -34,6 +34,8 @@
 
 using namespace std;
 
+namespace Stockfish {
+
 extern vector<string> setup_bench(const Position&, istream&);
 
 namespace {
@@ -275,7 +277,7 @@ void UCI::loop(int argc, char* argv[]) {
       else if (token == "d")        sync_cout << pos << sync_endl;
       else if (token == "eval")     trace_eval(pos);
       else if (token == "compiler") sync_cout << compiler_info() << sync_endl;
-      else
+      else if (!token.empty() && token[0] != '#')
           sync_cout << "Unknown command: " << cmd << sync_endl;
 
   } while (token != "quit" && argc == 1); // Command line args are one-shot
@@ -369,3 +371,5 @@ Move UCI::to_move(const Position& pos, string& str) {
 
   return MOVE_NONE;
 }
+
+} // namespace Stockfish
index eb0b390ba92254538a8c3d52b20668ec61ae1638..d3160109d6e540e7f527976ff3cbb76613e39b46 100644 (file)
--- a/src/uci.h
+++ b/src/uci.h
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
 
 #include "types.h"
 
+namespace Stockfish {
+
 class Position;
 
 namespace UCI {
@@ -78,4 +80,6 @@ Move to_move(const Position& pos, std::string& str);
 
 extern UCI::OptionsMap Options;
 
+} // namespace Stockfish
+
 #endif // #ifndef UCI_H_INCLUDED
index 7123915933b90f59d48627cd95d42dc809b07a38..5889ef6bd80e7d5ab8e69cddb1c6df0678404f8a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
-  Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+  Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -32,6 +32,8 @@
 
 using std::string;
 
+namespace Stockfish {
+
 UCI::OptionsMap Options; // Global object
 std::unique_ptr<HashProbeThread> hash_probe_thread;
 
@@ -200,3 +202,5 @@ Option& Option::operator=(const string& v) {
 }
 
 } // namespace UCI
+
+} // namespace Stockfish
index 03e9c9de093ca37fea339f144569d00bfcb01945..bfb50e94c196710680ec999f0a079e334c5f686c 100755 (executable)
@@ -39,16 +39,16 @@ case $1 in
     threads="2"
 
 cat << EOF > tsan.supp
-race:TTEntry::move
-race:TTEntry::depth
-race:TTEntry::bound
-race:TTEntry::save
-race:TTEntry::value
-race:TTEntry::eval
-race:TTEntry::is_pv
-
-race:TranspositionTable::probe
-race:TranspositionTable::hashfull
+race:Stockfish::TTEntry::move
+race:Stockfish::TTEntry::depth
+race:Stockfish::TTEntry::bound
+race:Stockfish::TTEntry::save
+race:Stockfish::TTEntry::value
+race:Stockfish::TTEntry::eval
+race:Stockfish::TTEntry::is_pv
+
+race:Stockfish::TranspositionTable::probe
+race:Stockfish::TranspositionTable::hashfull
 
 EOF