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 8 of 20 · 500/page · 10000 rows next →
# ngamma_n
3502 3501 4025.583199026725424130326
3503 3502 4026.602759101599393676236
3504 3503 4027.866297571924415222028
3505 3504 4028.247172919727479772781
3506 3505 4029.195557080540315202186
3507 3506 4030.383280199061820269064
3508 3507 4030.916107786028135695007
3509 3508 4031.654311715944818680877
3510 3509 4033.374476877376963248457
3511 3510 4034.520820162190739997837
3512 3511 4035.105599029920828107329
3513 3512 4036.079389601862977614691
3514 3513 4037.12601457102600998306
3515 3514 4038.290698859279128482785
3516 3515 4038.948310434303325260566
3517 3516 4039.85781922225609501172
3518 3517 4040.940563221796225392227
3519 3518 4041.464677644774374591638
3520 3519 4042.702480396315250223669
3521 3520 4044.322287003434570728901
3522 3521 4045.055147387290924543977
3523 3522 4046.214784829124031157552
3524 3523 4046.738210817314325220196
3525 3524 4047.468044325976916231362
3526 3525 4048.3807098275631774212
3527 3526 4049.97370468657634263341
3528 3527 4050.43139062420435775513
3529 3528 4051.38437955123379965668
3530 3529 4052.997625981506260337193
3531 3530 4053.566272077934283238615
3532 3531 4054.69071287025434405187
3533 3532 4055.477852503357040339605
3534 3533 4056.996361903224402555211
3535 3534 4057.428904233524567290512
3536 3535 4057.993493539175552801319
3537 3536 4059.085428288183095249539
3538 3537 4060.048996006782810556855
3539 3538 4061.743933049635338111238
3540 3539 4062.850288692900517428533
3541 3540 4063.157725455432651574807
3542 3541 4064.358380196390134897714
3543 3542 4065.178475192899321860068
3544 3543 4066.109592650519313339877
3545 3544 4067.07410686881256402971
3546 3545 4068.083223826024383359971
3547 3546 4068.969297626075607360698
3548 3547 4070.281912569777939834099
3549 3548 4070.603677649607697782275
3550 3549 4072.705128706193108975219
3551 3550 4073.12645017239200941089
3552 3551 4074.087681133033709606809
3553 3552 4074.817064510665765360646
3554 3553 4075.7413466700905149609
3555 3554 4076.719781863792053895874
3556 3555 4077.413345484527613144467
3557 3556 4078.922771360211755044523
3558 3557 4080.10830448120156709593
3559 3558 4081.066083420945756238523
3560 3559 4081.698568431797951076366
3561 3560 4082.588348141119579174655
3562 3561 4083.630042860071034148531
3563 3562 4084.942883202912307965411
3564 3563 4085.515370585825626100419
3565 3564 4086.379221074612250775797
3566 3565 4086.967478975275949354806
3567 3566 4088.781881483158054732788
3568 3567 4089.730285637656534801653
3569 3568 4090.591265910278965240063
3570 3569 4091.910846159219193728449
3571 3570 4092.297206464624930645753
3572 3571 4093.248362229124430532951
3573 3572 4093.905911945289125719314
3574 3573 4095.137930751253504173635
3575 3574 4096.510847296560407744544
3576 3575 4097.063684460353298960775
3577 3576 4098.475186448155724798996
3578 3577 4099.244845293626992475848
3579 3578 4100.10753413051964458167
3580 3579 4101.578447921560121188951
3581 3580 4102.037362535125580759718
3582 3581 4102.825941825781477258174
3583 3582 4104.14133120219216683307
3584 3583 4104.613098579828915562507
3585 3584 4105.512852569224958931843
3586 3585 4107.327219355882225463535
3587 3586 4108.624233430278305581599
3588 3587 4108.852443160772494844638
3589 3588 4109.710931285796126200828
3590 3589 4110.634319886721141688497
3591 3590 4111.85984544507771752754
3592 3591 4112.667206018722375299999
3593 3592 4113.485989227036601044632
3594 3593 4114.687567837158964554347
3595 3594 4115.615773798477103160711
3596 3595 4116.813980891257400122515
3597 3596 4117.600710739797161461922
3598 3597 4118.974352669458241314399
3599 3598 4119.596332883649645452586
3600 3599 4120.634210584368994290793
3601 3600 4121.348656802788074646363
3602 3601 4121.79465878504165755021
3603 3602 4123.240086669544312935074
3604 3603 4124.648829380197273769667
3605 3604 4125.592128452605104292504
3606 3605 4126.378063880529021693135
3607 3606 4127.593370808397083110957
3608 3607 4128.298166699678466670728
3609 3608 4128.777675202575931135012
3610 3609 4130.466763780259752689342
3611 3610 4131.136979899321969923271
3612 3611 4131.928002432784459591087
3613 3612 4132.724451307376544964537
3614 3613 4134.050648828269375848315
3615 3614 4135.441760021328964841198
3616 3615 4136.396688873409519754223
3617 3616 4136.974853483482130959067
3618 3617 4137.962941379643079206237
3619 3618 4138.838339555502391832491
3620 3619 4139.46409915523830814269
3621 3620 4140.89283011563274133838
3622 3621 4141.373775320128172181064
3623 3622 4143.347062500451133645172
3624 3623 4143.897624856071481705998
3625 3624 4144.603298798390414941052
3626 3625 4145.564792568009009431861
3627 3626 4147.07192227952515161419
3628 3627 4147.595069547505049210598
3629 3628 4148.652520778808441897268
3630 3629 4149.069451050763133346981
3631 3630 4150.445097952485151815959
3632 3631 4151.14685150949820531548
3633 3632 4152.768725265643344251899
3634 3633 4153.839146745052127530374
3635 3634 4154.630899005978987952583
3636 3635 4155.334787261632335144408
3637 3636 4156.296304962837572624788
3638 3637 4156.913907991741328997442
3639 3638 4158.129334413811242054685
3640 3639 4159.480461698979829257665
3641 3640 4159.921665840759389187155
3642 3641 4161.096281182124803241373
3643 3642 4162.377914593377240624758
3644 3643 4163.278853050829165149389
3645 3644 4164.135351440631472027915
3646 3645 4165.139162955595756411904
3647 3646 4166.078428062398829525613
3648 3647 4166.984173408356866620242
3649 3648 4167.509875345772868354443
3650 3649 4168.303453625533487017353
3651 3650 4170.482806110564012300463
3652 3651 4170.875114381647877879611
3653 3652 4172.130758051546532436257
3654 3653 4172.876966851703883987534
3655 3654 4173.416864022804521257207
3656 3655 4174.873181874607245529232
3657 3656 4175.512052252207840572435
3658 3657 4176.643071920197626255344
3659 3658 4177.322188624039802964908
3660 3659 4178.530304183175522793938
3661 3660 4179.574699430186857067778
3662 3661 4180.503181765203083578957
3663 3662 4181.922493184464297243543
3664 3663 4182.850792879099913259103
3665 3664 4183.377504371781905551951
3666 3665 4183.846344459319153619836
3667 3666 4185.312727675292838292472
3668 3667 4185.957936687376979078368
3669 3668 4187.200718846234245244589
3670 3669 4188.419977240156833977673
3671 3670 4189.615279793395058432437
3672 3671 4190.233269290908713869094
3673 3672 4190.985912225671671007786
3674 3673 4192.109712345712517225071
3675 3674 4193.175851165785098973545
3676 3675 4194.092245882131889272253
3677 3676 4194.89901388826094143015
3678 3677 4195.541351655143766551063
3679 3678 4196.604548355804795180037
3680 3679 4198.425989112479249027807
3681 3680 4199.33519263116430486193
3682 3681 4199.63300282963642188751
3683 3682 4200.997463466575706570067
3684 3683 4201.827002236684127009665
3685 3684 4202.416698746014430959619
3686 3685 4203.280813660139269368756
3687 3686 4204.736011073341322481789
3688 3687 4205.627365267385813391126
3689 3688 4206.870191888257310638902
3690 3689 4207.354542104387760672383
3691 3690 4208.734782098327231020671
3692 3691 4209.642902759412553684941
3693 3692 4210.549793194042952990353
3694 3693 4211.527980700039128152744
3695 3694 4212.170228129721352672328
3696 3695 4212.967293233469157664978
3697 3696 4214.11768658357798081054
3698 3697 4215.179293281830773860739
3699 3698 4216.832135763850230669007
3700 3699 4217.495524251771119977699
3701 3700 4218.230788626875563450353
3702 3701 4219.086410356289667962014
3703 3702 4219.672061531219570365814
3704 3703 4221.306739710483433395472
3705 3704 4222.12667144104502890088
3706 3705 4222.507243705137996463231
3707 3706 4223.901179992220450204451
3708 3707 4225.282365846362951643513
3709 3708 4225.722307332870217758055
3710 3709 4227.210630501786314844797
3711 3710 4227.984705072136280418118
3712 3711 4228.980834106910106534888
3713 3712 4229.533411497629163706475
3714 3713 4230.657847975155365009749
3715 3714 4231.008079754503101277579
3716 3715 4232.66032737878244951324
3717 3716 4234.137260750954802005681
3718 3717 4234.672186485428209507774
3719 3718 4235.502814784649530559824
3720 3719 4236.708778081333553093361
3721 3720 4237.343105088598700865966
3722 3721 4238.581562429219524081949
3723 3722 4239.083355091352149427037
3724 3723 4240.609223276219873907117
3725 3724 4241.104024290079786471209
3726 3725 4241.783753083254786295423
3727 3726 4243.573652494019625857323
3728 3727 4244.575822632996718442186
3729 3728 4245.621059995546743796043
3730 3729 4246.010961501898300903152
3731 3730 4247.050666369494432725971
3732 3731 4247.882863620120972745711
3733 3732 4248.798229920726097730432
3734 3733 4249.842360550784185109188
3735 3734 4251.024571916935894702453
3736 3735 4252.063770376692823471219
3737 3736 4253.452157043094974709763
3738 3737 4253.641943495415197993416
3739 3738 4254.606741244740830906058
3740 3739 4256.25397791507811694364
3741 3740 4256.903916379891303848817
3742 3741 4257.398426070860373553049
3743 3742 4258.412309498923805528628
3744 3743 4259.219971503959149237882
3745 3744 4260.828780400028577525829
3746 3745 4261.801316153905304146513
3747 3746 4262.83491775881813127138
3748 3747 4263.851070090161653157231
3749 3748 4264.326484097472780808815
3750 3749 4265.197753530233854891574
3751 3750 4266.17552629782877859772
3752 3751 4267.375018115874995308067
3753 3752 4268.223032063958135627934
3754 3753 4269.31196338319825631651
3755 3754 4270.228945852237268113279
3756 3755 4271.219357724018474298507
3757 3756 4272.62654668278855186395
3758 3757 4273.266070375791575275658
3759 3758 4274.006198485267499036548
3760 3759 4275.106732633899628078354
3761 3760 4275.863648070410039299644
3762 3761 4276.733176340385498092673
3763 3762 4277.420042959429433607477
3764 3763 4279.548867188124268064958
3765 3764 4280.161625524678237395263
3766 3765 4280.973787692787184731096
3767 3766 4281.587159761130006834057
3768 3767 4282.943479138628317707634
3769 3768 4283.493728632652311983602
3770 3769 4284.844965401470749190127
3771 3770 4285.629053648214923857741
3772 3771 4286.158107286907703681665
3773 3772 4287.680518179438382678241
3774 3773 4288.504766274432492112422
3775 3774 4289.812145760645530074644
3776 3775 4290.683826357642490280546
3777 3776 4291.674919393785886227071
3778 3777 4292.726444975231376542164
3779 3778 4292.817263390514137590153
3780 3779 4293.813814959747385625628
3781 3780 4295.348211448381976546637
3782 3781 4296.247687553782203307885
3783 3782 4297.269668492699212990583
3784 3783 4298.663179089635915853876
3785 3784 4299.054947282909573301277
3786 3785 4300.089148378121238996799
3787 3786 4301.012050609301536271816
3788 3787 4302.145194882383666534142
3789 3788 4303.183384178737349694454
3790 3789 4303.534636903585180282736
3791 3790 4304.617528001025212884031
3792 3791 4305.613823712048145777578
3793 3792 4307.449077599055896908371
3794 3793 4307.998991754306450218425
3795 3794 4309.172964976841508301835
3796 3795 4309.358615069695703461874
3797 3796 4310.632176097218701787277
3798 3797 4311.66200724392219714877
3799 3798 4312.22643012379073703269
3800 3799 4313.401370258528985403015
3801 3800 4314.799283160255336209699
3802 3801 4315.573741805210985077861
3803 3802 4316.464656306923669271655
3804 3803 4317.356190740262700661577
3805 3804 4318.867542854213184133238
3806 3805 4319.406828392035801867569
3807 3806 4320.162243602362299355047
3808 3807 4321.074891627432100607293
3809 3808 4322.076165190021617270543
3810 3809 4322.664566486274587618776
3811 3810 4324.546748008150745772116
3812 3811 4325.293085728018140886251
3813 3812 4326.350118583584828390076
3814 3813 4327.394690703758969781658
3815 3814 4327.700362559461280728399
3816 3815 4328.615769054413532147354
3817 3816 4330.02783591525437061736
3818 3817 4330.890065791732079745339
3819 3818 4331.851915622106296327659
3820 3819 4332.303902286719461748326
3821 3820 4334.020581083662575845289
3822 3821 4335.063147370884527300447
3823 3822 4335.606667165305049524088
3824 3823 4337.13366260566910682678
3825 3824 4337.451842980883658531344
3826 3825 4338.719122162573600501807
3827 3826 4339.027061506978881932941
3828 3827 4340.087832540901234235183
3829 3828 4341.413050962383796875536
3830 3829 4342.901618174997644426798
3831 3830 4343.563201207074485598529
3832 3831 4344.334641491140474885633
3833 3832 4345.249657154565037228925
3834 3833 4346.242896210363647367794
3835 3834 4347.628030072289640801638
3836 3835 4347.788735321778720109309
3837 3836 4348.97543085198228259119
3838 3837 4350.013922105545571685437
3839 3838 4350.871384355095550698161
3840 3839 4351.952516632844799693284
3841 3840 4353.70018973244653194803
3842 3841 4354.220757625007382864286
3843 3842 4354.724596590270922342909
3844 3843 4355.893110782247816934124
3845 3844 4356.482766408338403412125
3846 3845 4357.587591693042281689688
3847 3846 4358.755643132420286909673
3848 3847 4359.500185597816646770188
3849 3848 4361.191076817522249291911
3850 3849 4361.486734502675719096008
3851 3850 4362.761583185764398272975
3852 3851 4363.525581318882122838953
3853 3852 4364.546908846036685299828
3854 3853 4365.671997008556408897273
3855 3854 4366.527307542686969731941
3856 3855 4367.000511849069285656955
3857 3856 4367.711048429534312843732
3858 3857 4369.537964927337176457344
3859 3858 4370.734627509905661621589
3860 3859 4371.362633022014821645633
3861 3860 4372.22790650743243853776
3862 3861 4373.433178290921766909451
3863 3862 4373.863804411418442674221
3864 3863 4374.695096160702237207782
3865 3864 4376.083223911225390966263
3866 3865 4376.982953296759940307459
3867 3866 4377.768463362284683833961
3868 3867 4379.103315875457539430989
3869 3868 4379.759864529332484282788
3870 3869 4381.09102830986457228257
3871 3870 4382.125949498676589289295
3872 3871 4382.875748523263969008889
3873 3872 4383.46642731829730740101
3874 3873 4384.419601139081317074497
3875 3874 4385.57988632890391049312
3876 3875 4386.083678707494445686014
3877 3876 4387.756260025841354659622
3878 3877 4389.029478391509339602711
3879 3878 4389.719630868887908314812
3880 3879 4390.351108275227104076492
3881 3880 4391.021213066960059009494
3882 3881 4392.574337674838886637326
3883 3882 4393.358662552606143626062
3884 3883 4394.028511126825552842023
3885 3884 4395.060893844163135236424
3886 3885 4395.951097930616234479962
3887 3886 4397.223222687317357301357
3888 3887 4398.451719633069752663285
3889 3888 4399.177467304123480436705
3890 3889 4400.270180039160398612286
3891 3890 4401.175471547632582621853
3892 3891 4401.533574080142021232284
3893 3892 4402.808234516906255163677
3894 3893 4403.239569924188559173443
3895 3894 4405.218604639987692369683
3896 3895 4405.832303993915803938759
3897 3896 4406.706876416488763458973
3898 3897 4407.973180939619009282754
3899 3898 4408.623707863404237262145
3900 3899 4409.666097134110426045845
3901 3900 4410.491141982205285855204
3902 3901 4411.715201530781930130456
3903 3902 4412.237247490713238199236
3904 3903 4413.216561165380747114459
3905 3904 4413.934044512484839559242
3906 3905 4415.850961826549950549669
3907 3906 4416.59399902948133121558
3908 3907 4417.580116975685104299894
3909 3908 4418.241556472837749396494
3910 3909 4418.971524790858100014503
3911 3910 4419.922457573363702114283
3912 3911 4421.141217996643738328363
3913 3912 4421.904701207757415642196
3914 3913 4422.790749620976987837023
3915 3914 4424.339666554156858748551
3916 3915 4425.244909574641610322781
3917 3916 4425.495648732297991529238
3918 3917 4427.164720656212138236376
3919 3918 4428.073175842685664942564
3920 3919 4428.881802431637943049585
3921 3920 4429.488009566998485873495
3922 3921 4430.247448795439337919052
3923 3922 4431.424340483088057362397
3924 3923 4432.575627454585165453853
3925 3924 4434.029253195875076186016
3926 3925 4434.779104836070688680723
3927 3926 4435.529083292576743800182
3928 3927 4436.423737983623331374407
3929 3928 4437.394173677606044650917
3930 3929 4437.976869628506697839688
3931 3930 4439.557560714414832325527
3932 3931 4440.107585509010946069663
3933 3932 4441.064996264988783477651
3934 3933 4441.98494857835778628387
3935 3934 4443.365941871083814756236
3936 3935 4444.564424110313409079007
3937 3936 4445.238338540593880076851
3938 3937 4445.772758248951021434027
3939 3938 4447.26309601679314724237
3940 3939 4447.732962461683127222024
3941 3940 4448.301901068324509768316
3942 3941 4449.635268124367618071226
3943 3942 4451.098120800309180893734
3944 3943 4452.18808370513297160544
3945 3944 4452.680702066041694395023
3946 3945 4453.734551271115639049577
3947 3946 4454.462905440249533815014
3948 3947 4455.762657972554838530365
3949 3948 4456.703250193513507286086
3950 3949 4457.245826339942973539429
3951 3950 4458.188749330669113489268
3952 3951 4459.171279016140607208855
3953 3952 4460.548529287535826298853
3954 3953 4461.404140478537193489077
3955 3954 4462.734622194915687919673
3956 3955 4463.647648067206901185866
3957 3956 4464.038523256990129282452
3958 3957 4464.812716127626601098113
3959 3958 4465.805997569222651444357
3960 3959 4467.228532883001554745029
3961 3960 4467.739817015275730229265
3962 3961 4469.170662737410317484138
3963 3962 4469.978032831733946790411
3964 3963 4471.361757252287805366446
3965 3964 4471.550195590352033532132
3966 3965 4472.959272015182274969513
3967 3966 4474.186277577406440361309
3968 3967 4474.317091778977771744419
3969 3968 4475.80111093175964025797
3970 3969 4476.246519157506198531337
3971 3970 4477.015857063332257867041
3972 3971 4479.269423276334162344969
3973 3972 4479.730664772092819520358
3974 3973 4480.533629739235561810049
3975 3974 4481.41004022113804777577
3976 3975 4482.366885688958295640715
3977 3976 4483.238277466884327438975
3978 3977 4484.123623369348991498488
3979 3978 4485.052226103624408763139
3980 3979 4486.32721916294134417896
3981 3980 4487.084191427811448102813
3982 3981 4488.070667249015175844498
3983 3982 4489.240895547541078523971
3984 3983 4490.295506994854455665865
3985 3984 4491.218481252422990785755
3986 3985 4492.008277878969253039674
3987 3986 4492.638034669212676935225
3988 3987 4493.533634735208371961568
3989 3988 4494.493755901568357037465
3990 3989 4495.810018029897351327214
3991 3990 4496.893451767265072729332
3992 3991 4498.107112046466237971667
3993 3992 4498.778394072472857396016
3994 3993 4499.585223107458145042813
3995 3994 4500.164602396069653262386
3996 3995 4501.627186643984574882362
3997 3996 4502.673855553594221841988
3998 3997 4503.329854345718332643124
3999 3998 4503.715555681810678935499
4000 3999 4505.458867093072674442996
4001 4000 4506.311496728824972433

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