Current task: —

E-002-first-zeros.py

Experiments: E-002 · script updated 08-17-2026

E-002-zeros-first-10000.csv — 310.4 KB, updated 08-17-2026

← prev page 14 of 20 · 500/page · 10000 rows next →
# ngamma_n
6502 6501 6818.595648109209083012592
6503 6502 6819.200378865703849334844
6504 6503 6820.389495636155036865508
6505 6504 6821.029054304978064052277
6506 6505 6821.700640049411034089968
6507 6506 6822.503719518652592051455
6508 6507 6823.687203033240147964139
6509 6508 6824.619085022734086601665
6510 6509 6825.430833430179870844623
6511 6510 6826.694558727105861093621
6512 6511 6827.215195839816884132751
6513 6512 6828.196024115884701487345
6514 6513 6829.600399880406286303913
6515 6514 6830.083027378227155650699
6516 6515 6830.870213620891468952849
6517 6516 6831.545028254602545633311
6518 6517 6832.556238235138791472374
6519 6518 6833.389260421885037647469
6520 6519 6834.177858652429410015587
6521 6520 6835.801628118651539462703
6522 6521 6836.654339308383772621754
6523 6522 6837.608007663348725496761
6524 6523 6837.961927128307276993434
6525 6524 6838.573655317860400836837
6526 6525 6840.16095915824649465828
6527 6526 6840.629444018781627922383
6528 6527 6841.652128808343942706307
6529 6528 6842.568406740923627129813
6530 6529 6843.097716812178783292417
6531 6530 6844.542069426537534636461
6532 6531 6845.395596546573883272961
6533 6532 6846.437600649347376689639
6534 6533 6847.230869124742914957928
6535 6534 6848.211314779061851932308
6536 6535 6848.775908203615052959024
6537 6536 6849.879668262096546293453
6538 6537 6850.113716574132433446071
6539 6538 6851.115911270180983140324
6540 6539 6852.988639447484518834853
6541 6540 6853.366485079110907377901
6542 6541 6854.363467096818185343228
6543 6542 6855.29249181687268588486
6544 6543 6856.2622832564456746275
6545 6544 6856.760131671617136065037
6546 6545 6858.0494118005695076857
6547 6546 6858.558429214375931473496
6548 6547 6859.922463959376645317706
6549 6548 6860.187858899368237635206
6550 6549 6861.108305661411744999326
6551 6550 6862.251552326197145827138
6552 6551 6863.661560661965656278894
6553 6552 6864.468078714367562850888
6554 6553 6865.320196229558065051713
6555 6554 6865.947533329557641254848
6556 6555 6866.60595742231603536844
6557 6556 6867.507291743346970998708
6558 6557 6868.582153641689892691857
6559 6558 6869.569127747683380050455
6560 6559 6870.024934550840447950782
6561 6560 6871.789073856701230308413
6562 6561 6872.372448382001805324957
6563 6562 6873.072723613971619286407
6564 6563 6873.934694034237886277072
6565 6564 6875.153324099613909204858
6566 6565 6876.145315861663271238945
6567 6566 6876.698117410310699919473
6568 6567 6877.23764657693294563644
6569 6568 6878.258863124613273393939
6570 6569 6879.112421812894310957125
6571 6570 6880.377942410603945153843
6572 6571 6881.688038384212993459752
6573 6572 6882.445197358525480424401
6574 6573 6882.838577211128884512892
6575 6574 6884.181301466834897459402
6576 6575 6884.70138427851658890572
6577 6576 6885.263282750261075291721
6578 6577 6886.623661119115166548712
6579 6578 6887.549968308299199001856
6580 6579 6888.250992867099980875198
6581 6580 6889.289681088247413622214
6582 6581 6889.977275509068076958842
6583 6582 6891.537372835463676604515
6584 6583 6892.182738260615848907078
6585 6584 6892.950976502117408620191
6586 6585 6893.749941560475718334651
6587 6586 6894.725796291228656645838
6588 6587 6895.61538717234814657567
6589 6588 6895.840311975508770623404
6590 6589 6897.0820032258740904012
6591 6590 6898.502343014077366874777
6592 6591 6899.560414678553368802679
6593 6592 6900.318742990244471813202
6594 6593 6900.858109754849048601413
6595 6594 6901.834315321034593849329
6596 6595 6902.578676872228000126881
6597 6596 6903.937998227294608231965
6598 6597 6904.535186364931885592946
6599 6598 6905.140661438642824209823
6600 6599 6906.094062894561701901503
6601 6600 6907.14003263043853452929
6602 6601 6908.442281898069514516034
6603 6602 6908.903089541293175105743
6604 6603 6910.472255698743774938348
6605 6604 6911.048924563071870948986
6606 6605 6911.819906831133613326371
6607 6606 6912.192144576335882508287
6608 6607 6913.303555547399906417542
6609 6608 6914.187543371084914188936
6610 6609 6915.329117315662021636725
6611 6610 6916.245063928928405584928
6612 6611 6917.216468424075303932607
6613 6612 6918.357587013807053378023
6614 6613 6918.817356663068421320371
6615 6614 6919.750351056099085958309
6616 6615 6920.967473414749140980645
6617 6616 6921.483827935222737793222
6618 6617 6922.48097399915680945318
6619 6618 6923.354034045865965630224
6620 6619 6924.145884035742862226158
6621 6620 6924.460427819388622778428
6622 6621 6926.654831366046147528325
6623 6622 6927.286797837689678381217
6624 6623 6928.071663256565796868493
6625 6624 6928.719431898000446690598
6626 6625 6929.627051913054818429964
6627 6626 6930.528890049633507650861
6628 6627 6931.345058650023064605124
6629 6628 6932.023250807393651399201
6630 6629 6933.304572524187526105755
6631 6630 6934.184535983210836824598
6632 6631 6935.045370894762329343864
6633 6632 6936.108134342433076238469
6634 6633 6936.738749030301819204667
6635 6634 6938.142460069568626878138
6636 6635 6938.676824998127832652164
6637 6636 6939.728174416738697916881
6638 6637 6940.311344603755431246581
6639 6638 6940.802649579942344480254
6640 6639 6942.049400324626645126598
6641 6640 6942.947798550565800961156
6642 6641 6944.312163919004826902139
6643 6642 6945.071500563429420712256
6644 6643 6946.311464558266439892683
6645 6644 6946.661391100811537993124
6646 6645 6947.472631963527331466994
6647 6646 6948.143968613256257509354
6648 6647 6949.584246728472921251894
6649 6648 6950.558031839320896687363
6650 6649 6950.778718800412998845153
6651 6650 6951.731756770673123294726
6652 6651 6953.170717240902670700575
6653 6652 6953.807636482948455533288
6654 6653 6955.261558551968333255341
6655 6654 6955.78844153482948375955
6656 6655 6956.546043636552543010956
6657 6656 6957.75599370388266644715
6658 6657 6958.032891659783413722645
6659 6658 6958.980843288755212139119
6660 6659 6959.816566484797288855845
6661 6660 6960.901479751520560935638
6662 6661 6962.60741206167961157872
6663 6662 6962.870225996555972474133
6664 6663 6963.68028448135813779521
6665 6664 6964.53368407905698352386
6666 6665 6965.796786754972453266536
6667 6666 6966.478635398840768136735
6668 6667 6967.140998080977025714658
6669 6668 6968.316501086579405631806
6670 6669 6968.801828338875531661153
6671 6670 6969.932237760997579291226
6672 6671 6970.535368743666095254033
6673 6672 6972.095936145753045178874
6674 6673 6973.262414596906810490534
6675 6674 6973.654656489082174651083
6676 6675 6974.591510670816890614221
6677 6676 6975.295197954234737504924
6678 6677 6976.00825766287790953231
6679 6678 6976.919054490709277216966
6680 6679 6978.181615018905786893347
6681 6680 6978.842393158954944080872
6682 6681 6979.762843417411989685044
6683 6682 6981.004332176592048615128
6684 6683 6981.97686668382443891338
6685 6684 6982.397415579583842934313
6686 6685 6983.385289848010187646977
6687 6686 6984.843874844227763375001
6688 6687 6985.151721856232827493241
6689 6688 6986.003674960956854426061
6690 6689 6986.850633675517778282308
6691 6690 6987.254126322794603962283
6692 6691 6989.031870465207835354482
6693 6692 6990.113171653688788141328
6694 6693 6990.678711334833491419495
6695 6694 6991.939520170368063273013
6696 6695 6992.275498255837934390173
6697 6696 6993.159083827505527621559
6698 6697 6994.109978417560843610407
6699 6698 6995.039339733008801510137
6700 6699 6995.819351875685794750238
6701 6700 6996.886975870423444340473
6702 6701 6997.808697348917284882906
6703 6702 6998.498795222106748099809
6704 6703 6999.68267865455648229705
6705 6704 7000.717687588804520294195
6706 6705 7001.855900890755570654066
6707 6706 7002.352835851475362796724
6708 6707 7002.691508680539825365679
6709 6708 7004.04372349932867686819
6710 6709 7005.062866174920581380344
6711 6710 7005.10056467264672156872
6712 6711 7006.739662383949113276519
6713 6712 7008.114742057394907885324
6714 6713 7008.817473633254875770749
6715 6714 7009.367750707149055190687
6716 6715 7010.354080472365113727338
6717 6716 7011.000501879778596909772
6718 6717 7012.236145978958738811774
6719 6718 7013.15843422363897724396
6720 6719 7013.706426479037484028182
6721 6720 7014.629880155081963655508
6722 6721 7015.280466924209277154661
6723 6722 7016.721610295662351076486
6724 6723 7017.835435823635604749419
6725 6724 7018.482223807743739215505
6726 6725 7019.437796946029946950439
6727 6726 7020.435877382540453774761
6728 6727 7021.023066109284517135089
6729 6728 7021.657557247157584235875
6730 6729 7022.295224444044198229068
6731 6730 7024.042832031590761085087
6732 6731 7024.455165702430643281902
6733 6732 7025.699304046243291947123
6734 6733 7026.59472373179611591584
6735 6734 7027.30830666373973199212
6736 6735 7028.454474427452097967365
6737 6736 7029.026736381393912942075
6738 6737 7030.16093781244498928007
6739 6738 7030.916480678158892928116
6740 6739 7031.735908085673076426071
6741 6740 7032.326789393164393369425
6742 6741 7033.374833299674118654219
6743 6742 7034.292019875183257064449
6744 6743 7036.04298345023581237542
6745 6744 7036.590328238250399346895
6746 6745 7037.287650971198777087892
6747 6746 7037.826378791675526335857
6748 6747 7038.892159117755580599436
6749 6748 7039.724690853086387156616
6750 6749 7040.828312058801062411157
6751 6750 7041.380467339997152728331
6752 6751 7042.367190690242418631
6753 6752 7043.660231421896634859039
6754 6753 7044.644895546271367660169
6755 6754 7044.831635317058962758289
6756 6755 7046.487185180729160945761
6757 6756 7047.225072049254600175879
6758 6757 7047.948438454179356412764
6759 6758 7048.949401863969611285888
6760 6759 7049.280272516699045923901
6761 6760 7050.297213171848727088332
6762 6761 7051.126075603252007965514
6763 6762 7052.731101998176729282516
6764 6763 7053.529831409840681781557
6765 6764 7054.229325776320041344357
6766 6765 7055.362254325911678438391
6767 6766 7055.986004943446230536618
6768 6767 7056.614758134821366306043
6769 6768 7057.640859333485475230044
6770 6769 7058.629780453728365221274
6771 6770 7059.889596893714281397903
6772 6771 7060.046570771795757338162
6773 6772 7060.897300346828624237084
6774 6773 7062.396671827488136295209
6775 6774 7063.516698792150707564449
6776 6775 7064.111543391215279601838
6777 6776 7065.149328525932623226153
6778 6777 7065.783828580669743194114
6779 6778 7066.700657475163889408694
6780 6779 7067.232275507839840038801
6781 6780 7068.407664647505675318877
6782 6781 7068.910823584890744833195
6783 6782 7070.631775541777319225173
6784 6783 7071.257549038736809348834
6785 6784 7072.437115054569182651542
6786 6785 7072.983187561458542311305
6787 6786 7073.466662994916896016415
6788 6787 7075.067136414841138448417
6789 6788 7075.890873553446810903942
6790 6789 7076.342464150185170779258
6791 6790 7077.065912471997059903153
6792 6791 7078.271618865431295067918
6793 6792 7078.931890804248127580989
6794 6793 7080.137304262413800335541
6795 6794 7081.329045567852685920668
6796 6795 7082.278642199872636600656
6797 6796 7083.024206212044799030971
6798 6797 7083.620734181047377858644
6799 6798 7084.299067796783284272815
6800 6799 7085.248728797866419573586
6801 6800 7086.306731439244993740068
6802 6801 7087.186239237289823522181
6803 6802 7088.17277564645694995857
6804 6803 7089.062481920448932894951
6805 6804 7090.042338353993702465636
6806 6805 7090.994773908901678516091
6807 6806 7091.86750387285978460227
6808 6807 7092.676342251268125351928
6809 6808 7093.502511762346160538642
6810 6809 7094.688695951538395812675
6811 6810 7095.085720383148760778823
6812 6811 7095.725602561609248705808
6813 6812 7096.634105638254003507294
6814 6813 7098.543092299949014518629
6815 6814 7099.105747706266985255324
6816 6815 7100.148609518812446672413
6817 6816 7100.374674131554192218681
6818 6817 7101.805060778171165277313
6819 6818 7102.326350494877130080179
6820 6819 7103.038586280858889406436
6821 6820 7104.510386060178508134016
6822 6821 7104.853653429335748639566
6823 6822 7105.840204617922114786654
6824 6823 7107.089407119066238538959
6825 6824 7107.734543391730367235918
6826 6825 7108.776071695753780748222
6827 6826 7110.001860578941238972889
6828 6827 7110.890294249122934820289
6829 6828 7111.196220368459286452694
6830 6829 7112.280552946116879412299
6831 6830 7112.700332233813381973888
6832 6831 7113.874906598560373110727
6833 6832 7115.004276076471146822137
6834 6833 7115.666729177026194190031
6835 6834 7117.412224324585836683264
6836 6835 7117.750925734540749607059
6837 6836 7118.533335836163064078412
6838 6837 7119.28366536074758654773
6839 6838 7120.25076905321031443517
6840 6839 7121.421516882193200158501
6841 6840 7122.20585177363482008725
6842 6841 7122.716594278005179082308
6843 6842 7123.681370582503830561581
6844 6843 7124.489058108263974324257
6845 6844 7125.915836857431560204631
6846 6845 7127.035111899373219259298
6847 6846 7127.569883237844045910357
6848 6847 7128.564326582400678445468
6849 6848 7129.114147836605343972863
6850 6849 7130.329985123599288706752
6851 6850 7130.710717138684882068212
6852 6851 7131.460814545008116453261
6853 6852 7132.874807757900636116168
6854 6853 7134.0039376570233408503
6855 6854 7134.723114154968756594295
6856 6855 7135.384622834066491496621
6857 6856 7136.640749182656053431086
6858 6857 7137.28823595350369604471
6859 6858 7138.467686063100900558422
6860 6859 7139.026902843552392658324
6861 6860 7139.857139271782894586589
6862 6861 7140.793842097438183195558
6863 6862 7141.546892189483639602461
6864 6863 7142.172195163232959826607
6865 6864 7143.971077069489133989885
6866 6865 7144.642672074679686382164
6867 6866 7145.706891491172549902577
6868 6867 7146.3858833166616090091
6869 6868 7147.152214246956161741425
6870 6869 7147.421342255999126042609
6871 6870 7149.102831303930132017795
6872 6871 7149.690649365278747702147
6873 6872 7150.675386373472028703867
6874 6873 7151.241040722670503614577
6875 6874 7152.673138348752848444344
6876 6875 7153.629414430155319317
6877 6876 7154.183565146983572594831
6878 6877 7155.223016558715971839534
6879 6878 7156.483767096551489569565
6880 6879 7157.069573699554205763815
6881 6880 7157.560009133949787809822
6882 6881 7158.479721559110827679418
6883 6882 7159.23061039288180685689
6884 6883 7160.332445434675981806948
6885 6884 7161.815172321187023652578
6886 6885 7162.637987016803280796319
6887 6886 7163.137487199212247559278
6888 6887 7164.371935918646641892116
6889 6888 7164.711987143345429787075
6890 6889 7166.042526862267983285462
6891 6890 7166.532447389484476562327
6892 6891 7167.595613911397027316955
6893 6892 7168.643915100565886511951
6894 6893 7169.192035856892491744957
6895 6894 7170.161501605523925340273
6896 6895 7171.1357059604601371867
6897 6896 7172.806744272893638600939
6898 6897 7173.355088187846074001779
6899 6898 7173.622770905666702375851
6900 6899 7174.907955975350730354382
6901 6900 7175.547478519791275039633
6902 6901 7176.38074598089150639567
6903 6902 7177.135820086710826636376
6904 6903 7178.28043826898353945645
6905 6904 7179.369326560170893493054
6906 6905 7180.557671965447806272847
6907 6906 7181.140798188647013582974
6908 6907 7181.855662361213025117336
6909 6908 7182.761647877433051120192
6910 6909 7183.850495116685954875232
6911 6910 7184.720859712183550447364
6912 6911 7185.725322573682124312946
6913 6912 7186.027941311936880519368
6914 6913 7186.689666428596897025124
6915 6914 7188.32259450883910708618
6916 6915 7189.145690499370158632135
6917 6916 7190.294612842870593035236
6918 6917 7191.067900937835491533252
6919 6918 7191.983733312583084309713
6920 6919 7192.682398727873787226175
6921 6920 7193.221050146965582294764
6922 6921 7194.053741291015091078394
6923 6922 7195.421790712331106853204
6924 6923 7196.187762765415781638489
6925 6924 7196.957814200186857687616
6926 6925 7198.143606364030357703698
6927 6926 7198.993453206823580949809
6928 6927 7199.744478634550894533283
6929 6928 7201.057149777088322462487
6930 6929 7201.577794024115792159534
6931 6930 7202.481414823114816402872
6932 6931 7203.172044686859406747175
6933 6932 7204.265486356892517034683
6934 6933 7204.764022449226842027075
6935 6934 7205.523076974799073743306
6936 6935 7207.445017114693265819869
6937 6936 7208.190170854146141914751
6938 6937 7208.92772421169013573836
6939 6938 7209.383550025775725161236
6940 6939 7210.413788577275150585949
6941 6940 7211.335323495701183315312
6942 6941 7212.363396768572118346439
6943 6942 7212.963407701593349104033
6944 6943 7213.836766767376605856034
6945 6944 7215.101957542789342262533
6946 6945 7215.532729521918295095515
6947 6946 7216.953096055171436395721
6948 6947 7217.710867056885423202804
6949 6948 7218.731285313752465339206
6950 6949 7219.713045159146933853767
6951 6950 7220.432147546481222226572
6952 6951 7220.784711972810303878527
6953 6952 7221.858048232402909752677
6954 6953 7222.538863252622004800044
6955 6954 7223.961329509093138373103
6956 6955 7224.960275793196593619317
6957 6956 7225.664637285446599001702
6958 6957 7226.826232421187236917219
6959 6958 7227.670652097844863187991
6960 6959 7228.10497343551403658518
6961 6960 7228.963984592910047737014
6962 6961 7230.578979849759592006634
6963 6962 7230.78189655717230725617
6964 6963 7231.712168225955255454004
6965 6964 7232.507337222348557661325
6966 6965 7233.305725601915946368972
6967 6966 7235.032410357939797287504
6968 6967 7235.592047601008263783915
6969 6968 7236.715293141730841199224
6970 6969 7237.292700988194176736496
6971 6970 7237.923815549652487996384
6972 6971 7239.1071383586411926037
6973 6972 7239.492824902631269042187
6974 6973 7240.744574580114092819849
6975 6974 7241.38373752291592115242
6976 6975 7242.813003428781172547067
6977 6976 7243.908367802515763733068
6978 6977 7244.194739883836286630937
6979 6978 7245.048351170916220497872
6980 6979 7246.521971661734763370775
6981 6980 7247.172743211685886603275
6982 6981 7247.980135164897968579811
6983 6982 7248.558877326029450882313
6984 6983 7249.575515820298988962944
6985 6984 7250.311306882172284723474
6986 6985 7251.235573152237103403674
6987 6986 7252.579133334387534519113
6988 6987 7253.776967720476614618576
6989 6988 7254.381581372636949382867
6990 6989 7255.040228434971738992738
6991 6990 7255.894616493427658476875
6992 6991 7256.72874250730246103849
6993 6992 7257.358809297469850226807
6994 6993 7258.88414008788831110508
6995 6994 7259.519592696918670543699
6996 6995 7259.970840182008702069288
6997 6996 7261.33379770284986595856
6998 6997 7262.4459740548641364966
6999 6998 7263.122832007638058256355
7000 6999 7264.272994053367815024451
7001 7000 7264.748248090300387315461

E-002-zeros-first-10000.json — 712 bytes, updated 08-17-2026

JSON sidecar (click to expand)
{
  "experiment": "E-002",
  "task": "0.6a",
  "description": "First 10000 nontrivial zero ordinates via mpmath.zetazero (multiprocess)",
  "script": "research/numerics/scripts/E-002-first-zeros.py",
  "parameters": {
    "n_zeros": 10000,
    "dps": 25,
    "workers": 15
  },
  "checks": {
    "strictly_monotone": true,
    "gamma_1_matches_known": true,
    "riemann_von_mangoldt_abs_error": "0.3207309991"
  },
  "gap_statistics": {
    "min_gap": "0.03769849773",
    "max_gap": "6.887314497",
    "mean_gap": "0.9864634392",
    "local_mean_spacing_at_end": "0.8536743703"
  },
  "elapsed_seconds": 0.0,
  "timestamp_utc": "2026-08-17T20:09:20.100449+00:00",
  "row_count": 10000
}

Source code

Python script (click to expand)
"""E-002 — Task 0.6a: first 10^4 nontrivial zero ordinates of zeta.

Computes γ_n = Im(ρ_n) for n = 1..N via mpmath.zetazero at dps 25.
Parallel: multiprocessing over contiguous n-blocks (zetazero(n) is
independent per n); each worker writes its own part file with per-row
flush (crash-safe), main merges. Resumable: existing complete part files
are skipped.

Sanity checks: strict monotonicity; γ_1 = 14.134725141734693790…;
Riemann–von Mangoldt N(T) agreement at T = γ_N.

Outputs: research/numerics/data/E-002-zeros-first-10000.csv (+ .json)
Parts:   research/numerics/data/E-002-parts/part-NNN.csv
Cached:  does not recompute if final CSV is complete (use --force).
"""
import json
import os
import sys
import time
from datetime import datetime, timezone
from multiprocessing import Pool
from pathlib import Path

import mpmath as mp
import numpy as np

REPO = Path(__file__).resolve().parents[3]
DATA = REPO / "research" / "numerics" / "data"
PARTS = DATA / "E-002-parts"
N_ZEROS = 10_000
DPS = 25
N_WORKERS = min(15, os.cpu_count() or 4)  # leave one core for the OS

CSV = DATA / "E-002-zeros-first-10000.csv"
JSON = DATA / "E-002-zeros-first-10000.json"


def block_bounds(n_blocks: int):
    bounds = []
    per = N_ZEROS // n_blocks
    lo = 1
    for b in range(n_blocks):
        hi = N_ZEROS if b == n_blocks - 1 else lo + per - 1
        bounds.append((lo, hi))
        lo = hi + 1
    return bounds


def part_path(lo: int) -> Path:
    return PARTS / f"part-{lo:05d}.csv"


def compute_block(lo: int, hi: int) -> str:
    mp.mp.dps = DPS
    p = part_path(lo)
    tmp = p.with_suffix(".tmp")
    with tmp.open("w", encoding="utf-8", newline="") as f:
        for n in range(lo, hi + 1):
            g = mp.im(mp.zetazero(n))
            f.write(f"{n},{mp.nstr(g, DPS)}\n")
            f.flush()  # crash-safe: no buffered loss on kill
    os.replace(tmp, p)  # atomic: complete parts only
    return str(p)


def part_complete(lo: int, hi: int) -> bool:
    p = part_path(lo)
    if not p.exists():
        return False
    with p.open(encoding="utf-8") as f:
        return sum(1 for _ in f) == hi - lo + 1


def main() -> int:
    force = "--force" in sys.argv
    if CSV.exists() and JSON.exists() and not force:
        with CSV.open(encoding="utf-8") as f:
            if sum(1 for _ in f) - 1 >= N_ZEROS:
                print(f"cached: {CSV} complete (use --force to recompute)")
                return 0
    DATA.mkdir(parents=True, exist_ok=True)
    PARTS.mkdir(parents=True, exist_ok=True)

    blocks = block_bounds(N_WORKERS)
    todo = [(lo, hi) for lo, hi in blocks
            if force or not part_complete(lo, hi)]
    print(f"blocks: {len(blocks)} total, {len(todo)} to compute "
          f"({N_WORKERS} workers)")

    t0 = time.time()
    if todo:
        with Pool(N_WORKERS) as pool:
            for i, path in enumerate(pool.starmap(compute_block, todo), 1):
                print(f"  part done {i}/{len(todo)}: {Path(path).name} "
                      f"({time.time()-t0:.0f}s)", flush=True)

    # merge
    rows = []
    for lo, hi in blocks:
        with part_path(lo).open(encoding="utf-8") as f:
            rows.extend(f.read().strip().splitlines())
    rows.sort(key=lambda r: int(r.split(",", 1)[0]))
    with CSV.open("w", encoding="utf-8", newline="") as f:
        f.write("n,gamma_n\n")
        f.write("\n".join(rows) + "\n")
    elapsed = time.time() - t0

    # sanity checks
    mp.mp.dps = DPS
    # full-precision values straight from the CSV text (not float64 reload)
    with CSV.open(encoding="utf-8") as f:
        next(f)
        gammas = [mp.mpf(line.split(",", 1)[1]) for line in f]
    mono = all(gammas[i] < gammas[i + 1] for i in range(len(gammas) - 1))
    g1_known = mp.mpf("14.134725141734693790457251983562470270784257115699")
    g1_ok = abs(gammas[0] - g1_known) < mp.mpf("1e-20")
    T = gammas[-1]
    rvm = (T / (2 * mp.pi)) * (mp.log(T / (2 * mp.pi)) - 1) + mp.mpf("0.875")
    rvm_err = abs(N_ZEROS - rvm)
    gaps = [gammas[i + 1] - gammas[i] for i in range(len(gammas) - 1)]
    stats = {
        "min_gap": mp.nstr(min(gaps), 10),
        "max_gap": mp.nstr(max(gaps), 10),
        "mean_gap": mp.nstr(sum(gaps) / len(gaps), 10),
        "local_mean_spacing_at_end": mp.nstr(2 * mp.pi / mp.log(T / (2 * mp.pi)), 10),
    }
    print(f"monotone: {mono} | g1 ok: {g1_ok} | RvM err: "
          f"{mp.nstr(rvm_err, 5)} (should be << log T = "
          f"{mp.nstr(mp.log(T), 3)})")
    print("gap stats:", stats)

    meta = {
        "experiment": "E-002",
        "task": "0.6a",
        "description": f"First {N_ZEROS} nontrivial zero ordinates via "
                       "mpmath.zetazero (multiprocess)",
        "script": "research/numerics/scripts/E-002-first-zeros.py",
        "parameters": {"n_zeros": N_ZEROS, "dps": DPS,
                       "workers": N_WORKERS},
        "checks": {
            "strictly_monotone": bool(mono),
            "gamma_1_matches_known": bool(g1_ok),
            "riemann_von_mangoldt_abs_error": mp.nstr(rvm_err, 10),
        },
        "gap_statistics": stats,
        "elapsed_seconds": round(elapsed, 1),
        "timestamp_utc": datetime.now(timezone.utc).isoformat(),
        "row_count": N_ZEROS,
    }
    JSON.write_text(json.dumps(meta, indent=2), encoding="utf-8")
    ok = mono and g1_ok and rvm_err < 2 * mp.log(T)
    print(f"wrote {CSV.name}, {JSON.name} in {elapsed:.0f}s — "
          f"{'ALL CHECKS PASS' if ok else 'CHECK FAILURE'}")
    return 0 if ok else 1


if __name__ == "__main__":
    raise SystemExit(main())