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 11 of 20 · 500/page · 10000 rows next →
# ngamma_n
5002 5001 5448.90841328642824189342
5003 5002 5449.42763016759129583346
5004 5003 5451.309407660432125976804
5005 5004 5451.666775612691957231143
5006 5005 5452.330950202066110156709
5007 5006 5453.276425897145941987107
5008 5007 5454.232766091015700279671
5009 5008 5454.94855551058488961658
5010 5009 5455.867963982944480094372
5011 5010 5457.254335831568652792661
5012 5011 5458.715645086830449457823
5013 5012 5459.06218261065924044654
5014 5013 5459.714513943352429284716
5015 5014 5460.815544164755402516794
5016 5015 5461.68296883086899744093
5017 5016 5462.745000549540524954532
5018 5017 5463.764554543696861775823
5019 5018 5464.243875226838746157218
5020 5019 5465.083241509825381488945
5021 5020 5466.418306245839049400991
5022 5021 5467.790444992022355936776
5023 5022 5468.244535553760817960949
5024 5023 5469.480888387572601162165
5025 5024 5470.220068672416494293048
5026 5025 5471.082873141512531510347
5027 5026 5471.76086691968778111104
5028 5027 5472.26403769318866333983
5029 5028 5473.925204188394557794511
5030 5029 5474.871452901578204762369
5031 5030 5475.749436824135198743958
5032 5031 5476.748893801358884412116
5033 5032 5477.671940618743160709514
5034 5033 5478.463436457820085883122
5035 5034 5479.396814759793017054696
5036 5035 5480.654805801402197904381
5037 5036 5480.956733202192205045022
5038 5037 5481.993734077743723989894
5039 5038 5483.066851689781061488604
5040 5039 5483.473148968389999875177
5041 5040 5485.379530334925227567753
5042 5041 5486.250958078564070012627
5043 5042 5487.158642325720149215523
5044 5043 5487.81444820313140106988
5045 5044 5488.239469786524493973266
5046 5045 5489.539886310044147101117
5047 5046 5490.606477202431895121978
5048 5047 5491.198488461752068057985
5049 5048 5492.137050601373727394787
5050 5049 5493.792469126766004568311
5051 5050 5494.038480583097445162615
5052 5051 5495.28087546248379091876
5053 5052 5496.089727275413839022715
5054 5053 5497.373490396218552377307
5055 5054 5498.174123945101110650223
5056 5055 5498.633565305225435982512
5057 5056 5499.612797508678841744319
5058 5057 5500.353983645932026026775
5059 5058 5501.331224223354398320132
5060 5059 5503.211694478846152759319
5061 5060 5503.522536239298818653726
5062 5061 5504.579491040506799129541
5063 5062 5505.57193582868611933858
5064 5063 5506.330011485518841144611
5065 5064 5506.908179898227209764992
5066 5065 5508.017009501102573272185
5067 5066 5509.291230676581301411901
5068 5067 5509.945930302345558844656
5069 5068 5510.544264813349547674907
5070 5069 5511.757773875190808297182
5071 5070 5513.10995805623856557325
5072 5071 5514.00184870436628385958
5073 5072 5514.844462098076174414831
5074 5073 5515.501482955429397539925
5075 5074 5516.629656666066695866062
5076 5075 5517.161633410805628385935
5077 5076 5517.948299556428166448735
5078 5077 5519.095837607030514022834
5079 5078 5520.215397938825219816758
5080 5079 5521.614204753150253779042
5081 5080 5522.249630994144620749776
5082 5081 5522.970046465706315956736
5083 5082 5523.601350977461962001926
5084 5083 5525.23978235029661096868
5085 5084 5525.717122329117077026834
5086 5085 5526.662765223687380131313
5087 5086 5527.355332468716428027666
5088 5087 5528.1664125017809604781
5089 5088 5529.660934020356724164109
5090 5089 5530.203159249181133052209
5091 5090 5531.929612602777589937167
5092 5091 5532.461117364642881455585
5093 5092 5533.275825277342791940392
5094 5093 5533.953358476204396379097
5095 5094 5534.810789007363286927881
5096 5095 5535.656868324537494745956
5097 5096 5536.899525056139120403256
5098 5097 5537.790908369000483765339
5099 5098 5538.74072731824015904083
5100 5099 5539.814585079014230814096
5101 5100 5540.694583143287033613635
5102 5101 5541.576351543939162329654
5103 5102 5542.764646056709399124875
5104 5103 5543.113256672817102589146
5105 5104 5544.515208608563964565311
5106 5105 5545.192999163192276821482
5107 5106 5545.667895222008550121208
5108 5107 5546.53530457845434356906
5109 5108 5548.523919661123326398694
5110 5109 5549.358839814484364552583
5111 5110 5549.834823142450606360474
5112 5111 5550.807899778982554614577
5113 5112 5551.929911749658370976531
5114 5113 5552.207947116757286823839
5115 5114 5553.659789785949267580705
5116 5115 5554.238599943795348611454
5117 5116 5555.402430795447668282311
5118 5117 5556.199245743833326954564
5119 5118 5557.363922456235952347588
5120 5119 5558.202004496687585688907
5121 5120 5559.248178602726214133933
5122 5121 5560.367211776969279173537
5123 5122 5561.310135213797164418699
5124 5123 5561.791548798032326009059
5125 5124 5562.261884446336975349367
5126 5125 5563.637870900838938690779
5127 5126 5564.430162550764755876349
5128 5127 5565.566217326974068499982
5129 5128 5566.912177257101726559759
5130 5129 5567.644318652243764447228
5131 5130 5568.798580122037866842874
5132 5131 5568.912933770419058191511
5133 5132 5570.006356173319980960918
5134 5133 5571.437867776981014085126
5135 5134 5572.175581208444873872128
5136 5135 5572.58602422567817044518
5137 5136 5573.899529405042665529494
5138 5137 5574.441283883400029895676
5139 5138 5576.064762432888624291087
5140 5139 5577.183679281282722886192
5141 5140 5577.672276828444520869372
5142 5141 5578.644644373745654154278
5143 5142 5579.495916492832559297791
5144 5143 5580.333270376427692034488
5145 5144 5581.025573783574737992243
5146 5145 5581.822277193782992762807
5147 5146 5583.389191418452475045085
5148 5147 5584.323740890818679399604
5149 5148 5585.244570955993298591951
5150 5149 5585.708717008199229657892
5151 5150 5587.160081274639041719357
5152 5151 5587.886525281240674325869
5153 5152 5588.751061185498474269435
5154 5153 5589.69172717109069251214
5155 5154 5590.385173138886275215746
5156 5155 5591.400963623905634426358
5157 5156 5591.925240792589814647446
5158 5157 5593.555617029214751268755
5159 5158 5594.574594282586987408894
5160 5159 5595.711374711911892291798
5161 5160 5596.227736682097490442653
5162 5161 5596.856616829598348633577
5163 5162 5597.841768955218611280852
5164 5163 5598.606006812810798568627
5165 5164 5600.162150309786951017647
5166 5165 5600.549747047590455224716
5167 5166 5601.300750966579683034509
5168 5167 5603.081362651794675636512
5169 5168 5603.564840050677412380454
5170 5169 5604.347254349504406183905
5171 5170 5605.644654187447337852899
5172 5171 5606.542579545898783944713
5173 5172 5607.273178719413434051518
5174 5173 5608.005403503109645636695
5175 5174 5608.695582163807052646593
5176 5175 5609.563895924981947351752
5177 5176 5611.146743753712648256921
5178 5177 5612.157114643562103650552
5179 5178 5613.121400281543652931306
5180 5179 5613.727896996746259758119
5181 5180 5614.492287916933749963376
5182 5181 5615.741026437992921610597
5183 5182 5616.254524796164835547684
5184 5183 5617.320271437551893897452
5185 5184 5618.289089574102520421958
5186 5185 5619.268082017288301358316
5187 5186 5619.902394519334819884399
5188 5187 5621.023391660963442411651
5189 5188 5622.48860414226709302504
5190 5189 5623.413625843145743184608
5191 5190 5623.777120106693860786742
5192 5191 5624.755579135306360112507
5193 5192 5625.592184743385317971101
5194 5193 5626.502242711864952413837
5195 5194 5627.213187208193468521757
5196 5195 5628.348462444158723325625
5197 5196 5629.890648797948390792413
5198 5197 5630.380502229843031130062
5199 5198 5631.520288039644122252897
5200 5199 5632.197465155438906171047
5201 5200 5632.847100005567177781528
5202 5201 5634.370016211938756011193
5203 5202 5635.016250807584053286651
5204 5203 5635.929470274486806685965
5205 5204 5636.236694481527156578672
5206 5205 5637.490237062518195585102
5207 5206 5638.788714457923167039247
5208 5207 5640.134252591616466017377
5209 5208 5640.385710966421894391979
5210 5209 5641.872250768496859684193
5211 5210 5642.463399097842273429982
5212 5211 5643.093319440582164512786
5213 5212 5643.663127487791554150013
5214 5213 5645.328117414937829046654
5215 5214 5645.769016095280873127025
5216 5215 5647.16157657346779993949
5217 5216 5647.857206976795513976477
5218 5217 5648.974462993070656535167
5219 5218 5649.800756925361340628433
5220 5219 5650.839075232864965331172
5221 5220 5651.883418462845097299427
5222 5221 5652.345479579187370214127
5223 5222 5653.407356205339511171091
5224 5223 5654.192151373508913093296
5225 5224 5655.000372762493339316597
5226 5225 5655.819252623684267069731
5227 5226 5657.866738715883688992495
5228 5227 5658.411247459894845506872
5229 5228 5658.921215888583878865465
5230 5229 5659.894412872658961533012
5231 5230 5660.630422802744392989956
5232 5231 5661.929696761165335274251
5233 5232 5662.457451148033282618742
5234 5233 5663.557248248997338684861
5235 5234 5664.33670825630043706983
5236 5235 5665.460459801875874409218
5237 5236 5666.472615778431504818829
5238 5237 5667.31617046271900636043
5239 5238 5668.525315609320491593277
5240 5239 5669.472767900275489795876
5241 5240 5669.978563813660367628044
5242 5241 5671.149659068222141102106
5243 5242 5671.479959154304941402194
5244 5243 5672.290954890888229692088
5245 5244 5673.937158397051192416932
5246 5245 5674.814995125544637517978
5247 5246 5675.707528740345457711473
5248 5247 5676.972536522759571779833
5249 5248 5677.385026082539975719732
5250 5249 5678.34790888179564535805
5251 5250 5679.113903984791819851631
5252 5251 5680.339045053083798827966
5253 5252 5681.241565137187091423574
5254 5253 5682.099169924707567237334
5255 5254 5682.288150146846667815348
5256 5255 5683.970509043295656614716
5257 5256 5685.123793484791522880694
5258 5257 5686.093541225542155404112
5259 5258 5687.024519731124854665528
5260 5259 5687.481856548010748342217
5261 5260 5688.363844470026801576857
5262 5261 5689.508631787297226627041
5263 5262 5689.95269506155268460801
5264 5263 5691.140945770724161628701
5265 5264 5692.205217958837326821907
5266 5265 5693.589608697248632625695
5267 5266 5694.311966528280060980174
5268 5267 5694.60921746829710680557
5269 5268 5696.031917372012645389957
5270 5269 5697.172049668285156523556
5271 5270 5697.902079625018692251187
5272 5271 5698.374747827996621386441
5273 5272 5699.372993196989247968354
5274 5273 5700.481014348115871099103
5275 5274 5700.983872395575744793176
5276 5275 5702.732811445348827682917
5277 5276 5703.616227811558333025198
5278 5277 5704.50584061041598463156
5279 5278 5705.1779271079964809123
5280 5279 5706.077414326690228269528
5281 5280 5706.596075748012358306604
5282 5281 5707.768652251343638872783
5283 5282 5709.039424443666172856997
5284 5283 5709.520369132196748682914
5285 5284 5710.601740934770900940704
5286 5285 5711.559224969293482043326
5287 5286 5712.815871228328833947367
5288 5287 5713.793844101061114969934
5289 5288 5714.099754695891407873202
5290 5289 5715.633644358693091273263
5291 5290 5716.333560485883523383702
5292 5291 5716.750279152261250317811
5293 5292 5717.771496602875770142625
5294 5293 5718.472339581721182159343
5295 5294 5720.363389999227951899577
5296 5295 5721.050534731965750810034
5297 5296 5721.964323486251642018492
5298 5297 5722.591357947802587252624
5299 5298 5723.779045993776154340036
5300 5299 5724.163357935434107931365
5301 5300 5725.671140915321036730485
5302 5301 5726.233386878947283804258
5303 5302 5726.988743535994042457646
5304 5303 5728.120700254256982335179
5305 5304 5729.152376853109992944151
5306 5305 5729.883193187224891516614
5307 5306 5731.347862115284190177812
5308 5307 5732.34118914718544975148
5309 5308 5732.882093179836952855524
5310 5309 5733.599967910076694184101
5311 5310 5734.289092686585503338995
5312 5311 5735.448992420156071714272
5313 5312 5736.325416947508278247278
5314 5313 5737.255261080919404679076
5315 5314 5738.609819841823763011252
5316 5315 5739.569634432319716541775
5317 5316 5740.311894799231977336542
5318 5317 5740.865372181460909674224
5319 5318 5742.146698513288067832531
5320 5319 5743.006062922092945731854
5321 5320 5743.891993555737296493287
5322 5321 5744.857530427187239946216
5323 5322 5745.316395042860773787116
5324 5323 5746.105037293983012005453
5325 5324 5747.944351267191170391137
5326 5325 5748.737621328780804293649
5327 5326 5749.840045598376904353837
5328 5327 5750.072418941113829837471
5329 5328 5751.510678657523590443897
5330 5329 5752.022580454234660167371
5331 5330 5752.725353414598731595788
5332 5331 5753.688438232309051725562
5333 5332 5755.267001495403222702716
5334 5333 5755.666768504421132705632
5335 5334 5756.764768471898807845246
5336 5335 5757.942007977970633658119
5337 5336 5758.475340726917995667907
5338 5337 5759.896683465309303615352
5339 5338 5760.646107948371680574713
5340 5339 5761.131645054408015731308
5341 5340 5762.451906741179293546297
5342 5341 5762.733907455103630723509
5343 5342 5763.832280946394398969328
5344 5343 5764.963556715087977995018
5345 5344 5766.305389090200659537026
5346 5345 5767.382918922687772602391
5347 5346 5767.9850958060815304803
5348 5347 5768.708111307268919065501
5349 5348 5769.21737948994303158372
5350 5349 5770.681886992372902291036
5351 5350 5771.717742972695575731357
5352 5351 5772.11031091359072954759
5353 5352 5773.085986223199354222302
5354 5353 5774.269143736220661543144
5355 5354 5775.404901666433818278955
5356 5355 5776.052509870957899689569
5357 5356 5777.400076385150515545742
5358 5357 5778.091121756383535906698
5359 5358 5779.005201100713353865249
5360 5359 5779.661555490872897389028
5361 5360 5780.378597203566201271768
5362 5361 5781.253921951085908136206
5363 5362 5782.400466794728555080461
5364 5363 5784.048432518079013471019
5365 5364 5784.46846731567479663052
5366 5365 5785.212894534429495234771
5367 5366 5786.493575401431618244114
5368 5367 5787.13487880005665674431
5369 5368 5787.969440944723517186612
5370 5369 5788.985799825034779679283
5371 5370 5789.954351321143773807671
5372 5371 5790.692267030690145747487
5373 5372 5791.546976217493472034628
5374 5373 5792.289593635210603059267
5375 5374 5794.301907788139006739433
5376 5375 5794.668781596151989993945
5377 5376 5795.563939737832121437037
5378 5377 5796.419040669174737459122
5379 5378 5797.217839236136158011893
5380 5379 5797.884282193431830567902
5381 5380 5798.93966425474410547313
5382 5381 5800.041030274365183981505
5383 5382 5800.71927732053811324297
5384 5383 5802.371718407209981003052
5385 5384 5802.781136074599940416402
5386 5385 5803.871206258075695266035
5387 5386 5804.409409031705795632005
5388 5387 5805.820188753753056985783
5389 5388 5806.798661008811025866962
5390 5389 5807.373949619648276407196
5391 5390 5807.786383388401621854181
5392 5391 5808.950049546973894976844
5393 5392 5810.033203191335043551269
5394 5393 5811.356821178595812194159
5395 5394 5812.204788290976828290477
5396 5395 5813.345051566531392872399
5397 5396 5813.946414929016704501297
5398 5397 5814.499327315379878099512
5399 5398 5815.62471424982586074488
5400 5399 5816.29567020282267772757
5401 5400 5817.687141955804285187926
5402 5401 5818.292158757065279715283
5403 5402 5819.263873660719762581278
5404 5403 5820.323072483646427188574
5405 5404 5821.199580317665381706397
5406 5405 5822.554932361928656708973
5407 5406 5823.160120590071735066813
5408 5407 5824.034446196029884459186
5409 5408 5824.644070750254689379011
5410 5409 5826.022417685476873322211
5411 5410 5826.437166473171039774961
5412 5411 5826.894313623182376754275
5413 5412 5828.890322956993345007063
5414 5413 5829.884397342048155838998
5415 5414 5830.591034346443479022732
5416 5415 5831.348619828558170377338
5417 5416 5832.010437995125382265489
5418 5417 5833.320748987730534766236
5419 5418 5834.000771326140774909834
5420 5419 5834.935242018621244281217
5421 5420 5835.952597527724674241907
5422 5421 5836.409775793470024378632
5423 5422 5837.694816937440399112045
5424 5423 5838.887811770638554178019
5425 5424 5839.657148889604894256085
5426 5425 5840.870745780082286406709
5427 5426 5841.773244696567850755427
5428 5427 5842.257347261062416821684
5429 5428 5843.00401616360113136137
5430 5429 5843.745504057074496105935
5431 5430 5845.0435407788509694096
5432 5431 5846.122346475740794687959
5433 5432 5846.858967153620422882036
5434 5433 5848.182987415376076096368
5435 5434 5848.996958343328399552968
5436 5435 5849.66151737555267767474
5437 5436 5850.489268138529995088268
5438 5437 5851.711059759895363358223
5439 5438 5852.668145588459682197783
5440 5439 5853.095554594940911715182
5441 5440 5854.191539972039291841986
5442 5441 5854.715491772939334213866
5443 5442 5856.094228893924657411096
5444 5443 5857.843809341438855552547
5445 5444 5858.083358309463994750872
5446 5445 5858.833953060091339910781
5447 5446 5859.861397251982080191228
5448 5447 5860.64938299976398628785
5449 5448 5861.434868985917139226727
5450 5449 5862.557428297671930266213
5451 5450 5863.094038513300203641087
5452 5451 5864.65676360640008444086
5453 5452 5865.522792510626343111959
5454 5453 5866.040235324606145055414
5455 5454 5867.201546981377919799185
5456 5455 5868.543660974694386843041
5457 5456 5868.986917034966458883421
5458 5457 5870.008991855740832579327
5459 5458 5870.718884647864672142004
5460 5459 5871.419724497563173919427
5461 5460 5872.402794856289760871374
5462 5461 5873.387593706414782849602
5463 5462 5874.881588208323431755264
5464 5463 5875.798358154291255036175
5465 5464 5876.37496362147243623329
5466 5465 5877.609748606668303847735
5467 5466 5877.93329391948930497387
5468 5467 5878.676214478654668335145
5469 5468 5880.463284726764016018723
5470 5469 5880.709560927625161895173
5471 5470 5881.825024120581472572267
5472 5471 5882.270516172437724716164
5473 5472 5884.03282624493641843835
5474 5473 5884.684250047966716213021
5475 5474 5885.744730540396178807063
5476 5475 5886.621191165030699231089
5477 5476 5887.486300388680372319839
5478 5477 5888.387576534156828877771
5479 5478 5888.845470521668698166067
5480 5479 5889.698291834789962472542
5481 5480 5890.842689357557413608915
5482 5481 5892.22584829350913314817
5483 5482 5893.121091670048429159863
5484 5483 5894.085613219848942205882
5485 5484 5894.544410863417662980612
5486 5485 5895.557133651959274946813
5487 5486 5896.814625874133130051643
5488 5487 5897.52850839518075329734
5489 5488 5898.04561559284613771815
5490 5489 5899.335294403183385260123
5491 5490 5900.026130768220366436945
5492 5491 5900.832883795790770636653
5493 5492 5902.160660214254045193416
5494 5493 5903.45910433616580797294
5495 5494 5904.359224850042737927089
5496 5495 5904.786649649029349879913
5497 5496 5905.377904296964183014586
5498 5497 5906.654294834346700621759
5499 5498 5907.305604481369755337803
5500 5499 5908.304130378044936438292
5501 5500 5909.432316004653369888103

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())