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 7 of 20 · 500/page · 10000 rows next →
# ngamma_n
3002 3001 3534.06258828016997260639
3003 3002 3535.772576943416588436442
3004 3003 3536.633250705505307203467
3005 3004 3537.708013056178211576798
3006 3005 3538.500568907352958726009
3007 3006 3539.089936526597997395583
3008 3007 3540.456758807154447477662
3009 3008 3541.357522375370674696041
3010 3009 3542.340883917586681125542
3011 3010 3543.322306535336406728243
3012 3011 3543.816796286908503061975
3013 3012 3545.699212171315652050241
3014 3013 3546.864134595260489504879
3015 3014 3547.31478139648583677958
3016 3015 3548.351252963577545927833
3017 3016 3549.458356776357443813342
3018 3017 3550.065059225519704829118
3019 3018 3550.853298372029498401217
3020 3019 3552.080209750381069015604
3021 3020 3553.84068059702097097986
3022 3021 3554.165034789487061627343
3023 3022 3555.534145071897488093946
3024 3023 3556.065234535611866863888
3025 3024 3557.427102352920707684813
3026 3025 3558.349345038406358629044
3027 3026 3559.265664699892158720735
3028 3027 3560.019248823558045713607
3029 3028 3560.776183334352187103418
3030 3029 3562.162435082827542793858
3031 3030 3563.215121485676151024066
3032 3031 3564.760770714007353843945
3033 3032 3565.396422886999811355662
3034 3033 3566.284910776263374697552
3035 3034 3566.916683895457835276768
3036 3035 3567.733251749069523470616
3037 3036 3569.343132086432282350638
3038 3037 3570.008671364950081203457
3039 3038 3570.822916554615170910433
3040 3039 3572.513965627941474489582
3041 3040 3573.079804301269415462486
3042 3041 3574.100016308942958429884
3043 3042 3575.493155747453303677675
3044 3043 3575.955379643794348696925
3045 3044 3577.20528398563208568807
3046 3045 3577.981184110552278139248
3047 3046 3578.410382618929418994226
3048 3047 3579.75010261459774163889
3049 3048 3581.585338241799590748924
3050 3049 3582.394916619829274666787
3051 3050 3582.92304218550771493122
3052 3051 3583.945574774916280124236
3053 3052 3585.206278712881179287057
3054 3053 3585.684448661568814930473
3055 3054 3586.840745006095897797447
3056 3055 3587.968813667965440760057
3057 3056 3588.859444520462213313781
3058 3057 3589.745006545045819187021
3059 3058 3590.983471293056933506471
3060 3059 3592.405889080009609201423
3061 3060 3593.028558839785969099466
3062 3061 3594.227274785490695903371
3063 3062 3594.469272698104701522324
3064 3063 3595.77906375388261092731
3065 3064 3596.421772540065402957321
3066 3065 3597.80264129457512180314
3067 3066 3598.948560206193670061421
3068 3067 3600.166323796782349381541
3069 3068 3601.104013685447015925494
3070 3069 3601.791282751961631642039
3071 3070 3602.418894262688351563839
3072 3071 3604.248053633486021662463
3073 3072 3604.754984017813335219091
3074 3073 3605.494474971794832198848
3075 3074 3606.359317624099887487465
3076 3075 3607.574809645374461166551
3077 3076 3609.283333034273279729623
3078 3077 3609.700266168917677083748
3079 3078 3611.101631551564917511766
3080 3079 3611.91099467675687163894
3081 3080 3612.324192687339622630824
3082 3081 3613.549021241040446879335
3083 3082 3614.327814642186299074565
3084 3083 3615.606268124633568375793
3085 3084 3616.840689133504104243759
3086 3085 3617.802842397040907467178
3087 3086 3618.452558515970061806495
3088 3087 3619.88572350701106480393
3089 3088 3620.705570449877443237983
3090 3089 3621.886132366144136256102
3091 3090 3622.179274502217610453354
3092 3091 3623.558468473039696030237
3093 3092 3624.437503556840806249904
3094 3093 3624.881726597741555589643
3095 3094 3627.060315519066668849686
3096 3095 3627.949114790735445303616
3097 3096 3628.610375056135944810536
3098 3097 3629.407217611507167841407
3099 3098 3630.36342504544031737514
3100 3099 3631.30868428878177873434
3101 3100 3632.478178336013750108352
3102 3101 3633.440157775448833615541
3103 3102 3634.056193093004974106547
3104 3103 3635.673633427948447650607
3105 3104 3636.439638357045251172991
3106 3105 3637.54065771794929291555
3107 3106 3638.553707679430567169114
3108 3107 3639.679806517767157831346
3109 3108 3640.3629764942696737966
3110 3109 3641.010538146349407549987
3111 3110 3641.707123241174429619248
3112 3111 3643.479573648180924715069
3113 3112 3644.403358341780687500525
3114 3113 3645.632116643506368662373
3115 3114 3646.45089436983169477722
3116 3115 3647.28426168040381318837
3117 3116 3648.15845468551884992962
3118 3117 3649.166164131527840828171
3119 3118 3650.302043571159495448604
3120 3119 3651.253106163416819112181
3121 3120 3651.783523374765972068805
3122 3121 3653.0883261963893382595
3123 3122 3654.211437502704305114433
3124 3123 3655.905726441463279154078
3125 3124 3656.334529766239875427286
3126 3125 3656.892829633305812628482
3127 3126 3658.129372193821133813405
3128 3127 3658.921689551014202970974
3129 3128 3659.907500747567182275982
3130 3129 3660.735665814957187837187
3131 3130 3662.368949297409952120119
3132 3131 3663.448288854976732378083
3133 3132 3664.00200710459123173989
3134 3133 3664.878137729471867913497
3135 3134 3666.237025972965733036639
3136 3135 3667.307339233034196928439
3137 3136 3667.735638945522655375564
3138 3137 3669.030191157441767073147
3139 3138 3669.423746308953714569587
3140 3139 3670.73199726917752378923
3141 3140 3672.349351294876327432124
3142 3141 3673.159176144118690156885
3143 3142 3674.08760895614379026615
3144 3143 3675.262610129655987978376
3145 3144 3675.662484245629679923733
3146 3145 3676.368938137253659678922
3147 3146 3677.893295662794792812478
3148 3147 3678.847783056964556828699
3149 3148 3679.818311649508081213857
3150 3149 3680.583983908414981853057
3151 3150 3682.418731435667305881968
3152 3151 3682.571730549068099259862
3153 3152 3683.971024203510371870598
3154 3153 3684.859893088268220097353
3155 3154 3685.9744421424271559224
3156 3155 3686.271337180935382280408
3157 3156 3687.538413759765544286981
3158 3157 3688.177027971996118448671
3159 3158 3690.184258111030655673127
3160 3159 3691.039162252974917217844
3161 3160 3691.756939721431318257151
3162 3161 3692.64765392734599683236
3163 3162 3693.370984735038681316839
3164 3163 3694.791126717894572904107
3165 3164 3695.672790133180585511249
3166 3165 3696.121982633589127833368
3167 3166 3697.585963644991890736851
3168 3167 3698.547362766514283974448
3169 3168 3699.430292630649955282931
3170 3169 3700.838316759630356721498
3171 3170 3702.050756987914500006264
3172 3171 3702.460155933212898287441
3173 3172 3703.347476075603680339226
3174 3173 3704.209894382999447377713
3175 3174 3705.129228187902331167877
3176 3175 3706.294721355962656966036
3177 3176 3707.579055361439022674417
3178 3177 3708.658452868782083203093
3179 3178 3709.58227172335331479811
3180 3179 3710.371491776773358952412
3181 3180 3711.404818176416529613018
3182 3181 3712.17013946661263764367
3183 3182 3713.583581050868824719829
3184 3183 3714.424676839815995053202
3185 3184 3714.739333589796615304511
3186 3185 3715.846459034948509976498
3187 3186 3717.751095917050867352058
3188 3187 3718.49835547448697701785
3189 3188 3719.483495399308027780935
3190 3189 3720.182048932696292736718
3191 3190 3721.296040000338288020235
3192 3191 3722.058836768195941442757
3193 3192 3722.627320552538586028316
3194 3193 3724.388127501142136826468
3195 3194 3724.88231999030137704156
3196 3195 3726.517718264919253019633
3197 3196 3727.105295973327673110174
3198 3197 3727.938465955540360751555
3199 3198 3729.472791701951074776019
3200 3199 3730.187320676354296573146
3201 3200 3731.075159248372698021596
3202 3201 3731.652937302642750380325
3203 3202 3732.847475613411832532746
3204 3203 3733.67169680712566332331
3205 3204 3735.007644637012569080075
3206 3205 3736.462855616984139736731
3207 3206 3737.426702784950265240634
3208 3207 3737.847779331928765593776
3209 3208 3738.588055467694012039051
3210 3209 3739.831690660130602365702
3211 3210 3740.875153687163953311191
3212 3211 3741.925079348680116886
3213 3212 3742.485013546845301411154
3214 3213 3743.8596162116295294552
3215 3214 3744.846671965053909675215
3216 3215 3746.135972512802586811324
3217 3216 3746.840953103113868383243
3218 3217 3747.997127044578351478381
3219 3218 3748.752860722956767740346
3220 3219 3749.672707911018502176603
3221 3220 3750.303158431205408860629
3222 3221 3751.164644510357872194106
3223 3222 3753.186449129888108423387
3224 3223 3753.946989066386061833094
3225 3224 3754.507321882974734646272
3226 3225 3755.922818842412856307956
3227 3226 3756.524972712017124694798
3228 3227 3757.481439849810206029108
3229 3228 3758.696426296329949512239
3230 3229 3759.35921667557811069465
3231 3230 3760.582729132616577522183
3232 3231 3761.085334951762833969329
3233 3232 3762.475079096339359998986
3234 3233 3763.999842697677547614192
3235 3234 3764.64428016998528347418
3236 3235 3765.746026064096287925552
3237 3236 3766.45596753182066766396
3238 3237 3766.872421484277807982004
3239 3238 3768.338640155954434175085
3240 3239 3769.293394313006448933759
3241 3240 3770.105497899101135000531
3242 3241 3771.728992761721378791089
3243 3242 3772.512331217439890354918
3244 3243 3773.467327740988558121926
3245 3244 3773.941580304984973160346
3246 3245 3775.752711840115427011112
3247 3246 3776.258807342244331680619
3248 3247 3777.143244333655944718417
3249 3248 3777.833370602115823136256
3250 3249 3778.839373785258593011575
3251 3250 3780.226486450645759017995
3252 3251 3781.668646123160835271265
3253 3252 3782.390575661851609147435
3254 3253 3783.126649463720346253487
3255 3254 3784.265550345229671223881
3256 3255 3784.865105099824619410066
3257 3256 3785.791018600925516608884
3258 3257 3786.935697906059179416738
3259 3258 3788.263664870251948365252
3260 3259 3788.800050331939493490617
3261 3260 3790.04177667257351735608
3262 3261 3791.020914404688758905329
3263 3262 3792.560247671588549843729
3264 3263 3792.872479501939546382562
3265 3264 3793.790990276485509246234
3266 3265 3795.021653416458419218212
3267 3266 3795.808588147873639874756
3268 3267 3796.139177933295054438861
3269 3268 3797.854055842943754012007
3270 3269 3799.298497077311899317849
3271 3270 3800.132426403406501340251
3272 3271 3800.877635578880027708031
3273 3272 3801.590617175651922173093
3274 3273 3802.640239732521012673481
3275 3274 3803.829200465714550227491
3276 3275 3804.790840393653911424342
3277 3276 3805.434646754817842957088
3278 3277 3806.29789675533174648491
3279 3278 3808.093049896331448327699
3280 3279 3808.459507836561145046834
3281 3280 3809.874248312906201412991
3282 3281 3811.184712334396695954801
3283 3282 3811.428221764781090041118
3284 3283 3812.544754398986000934845
3285 3284 3812.978308901785566377618
3286 3285 3814.327017461777310197761
3287 3286 3815.531819858070988219514
3288 3287 3816.602598127822443356568
3289 3288 3817.76870791430830528339
3290 3289 3818.505533965585731785908
3291 3290 3819.414498547847187907506
3292 3291 3820.43831336925376087111
3293 3292 3821.438059666772819288133
3294 3293 3822.371913385551814133467
3295 3294 3823.148110407561065568762
3296 3295 3824.418553124508024529808
3297 3296 3824.541037159350616548714
3298 3297 3826.947627237762543773336
3299 3298 3827.576335685668821836103
3300 3299 3828.339520519640936296906
3301 3300 3829.144810486888796983926
3302 3301 3830.161823923041355831512
3303 3302 3831.034679119847849960474
3304 3303 3831.932487129554814399597
3305 3304 3832.941548849468677729272
3306 3305 3834.353094561193438030767
3307 3306 3835.220398724040018392704
3308 3307 3836.022881981186403109276
3309 3308 3837.238847224151315504301
3310 3309 3838.084058667460074643025
3311 3310 3839.426268466037812101604
3312 3311 3839.974002766309188837546
3313 3312 3840.504678748195229727496
3314 3313 3841.682344812185417988821
3315 3314 3842.678532636432437496322
3316 3315 3844.403553213034847711515
3317 3316 3844.897010964168201914892
3318 3317 3846.487475476057548300695
3319 3318 3846.747301182658958025836
3320 3319 3847.681749670896746927453
3321 3320 3848.415301005862612205502
3322 3321 3850.170201814830045633846
3323 3322 3850.603920438379459569436
3324 3323 3851.410102460568819907334
3325 3324 3852.703102475248649119429
3326 3325 3853.860293845638106751829
3327 3326 3854.902586332991800713887
3328 3327 3855.955254473828766428056
3329 3328 3856.70386739588545985536
3330 3329 3857.610583014921081546048
3331 3330 3858.448586235992104362787
3332 3331 3859.285738177006220721896
3333 3332 3860.09300850517269031875
3334 3333 3861.852719325409005757585
3335 3334 3862.983783666956998704307
3336 3335 3863.658286019181994770722
3337 3336 3864.150190996822989940639
3338 3337 3865.565077205411726895091
3339 3338 3866.82240411328656480261
3340 3339 3866.972328124997318237581
3341 3340 3868.412859073881031955221
3342 3341 3869.144666921011526224389
3343 3342 3870.114034539457829775286
3344 3343 3871.291750189439619128089
3345 3344 3872.666546572794402382462
3346 3345 3873.810208380673396369433
3347 3346 3874.229614843760682187707
3348 3347 3875.105197584665997060837
3349 3348 3876.17374068980673678916
3350 3349 3876.657964937792977933507
3351 3350 3878.256174941054693397915
3352 3351 3879.110338709994588311542
3353 3352 3880.08221359744173948184
3354 3353 3881.540350511397796503673
3355 3354 3882.116845259779487145414
3356 3355 3882.899992550470255746599
3357 3356 3884.209799207988744030342
3358 3357 3885.10996308611235529453
3359 3358 3886.225209766245638375857
3360 3359 3886.451289790500395195687
3361 3360 3887.352013760036825957001
3362 3361 3889.155346344496094431651
3363 3362 3890.309181969027112201886
3364 3363 3891.086883002408645857237
3365 3364 3891.929936985990490856285
3366 3365 3893.001131076967069568567
3367 3366 3893.407062083334096652158
3368 3367 3894.783730288917097304988
3369 3368 3895.56793127391507423357
3370 3369 3896.64263227513428481865
3371 3370 3897.870750291093003286008
3372 3371 3898.65196179455533617567
3373 3372 3899.623743455614739939906
3374 3373 3901.007764610422026171522
3375 3374 3902.077427042258698973027
3376 3375 3902.411160510889354972783
3377 3376 3903.351543073145757339838
3378 3377 3904.379191304120937170268
3379 3378 3905.344851666203596742621
3380 3379 3906.119319111883894096798
3381 3380 3908.188165438193626058368
3382 3381 3908.606362666069931891751
3383 3382 3909.465847404125029024338
3384 3383 3910.63271685653970475102
3385 3384 3910.91143823615837912082
3386 3385 3912.642948598512348959961
3387 3386 3913.259137861760987569145
3388 3387 3914.219923269218954272575
3389 3388 3914.949001244906410445094
3390 3389 3916.176538559951340385457
3391 3390 3917.658165953608366624569
3392 3391 3918.443052987650145674963
3393 3392 3919.222740960692518655605
3394 3393 3920.540431095450587398867
3395 3394 3921.152570240051835609908
3396 3395 3921.652560348288666438551
3397 3396 3922.665203224202656174952
3398 3397 3924.193310525357618908077
3399 3398 3925.247119257293025393085
3400 3399 3926.176083583575326687154
3401 3400 3927.080517370093174300389
3402 3401 3928.142218295294467209548
3403 3402 3928.886559206820356147826
3404 3403 3930.099281280357436125852
3405 3404 3930.891086382284810202274
3406 3405 3931.745217360564949425984
3407 3406 3932.624568087019042320622
3408 3407 3933.51688184203785228182
3409 3408 3934.938347808599447019202
3410 3409 3936.443286119626161131968
3411 3410 3936.974234313655024427792
3412 3411 3937.905380853557401362538
3413 3412 3938.21461653686463249095
3414 3413 3939.775186811875467466087
3415 3414 3940.434637596688948586773
3416 3415 3941.630029648000720129957
3417 3416 3942.352722187778191036608
3418 3417 3944.03036280692911648478
3419 3418 3944.650915652395713949201
3420 3419 3945.333063668887094366058
3421 3420 3946.878983570570298787006
3422 3421 3947.703864074578611833287
3423 3422 3948.434192200487546591539
3424 3423 3949.313705822149646069943
3425 3424 3950.132375511085209322725
3426 3425 3950.859466439663037494352
3427 3426 3952.942870156917175169827
3428 3427 3953.356526591264831061221
3429 3428 3954.778621164596996670021
3430 3429 3955.176546372732661583086
3431 3430 3956.420217191614135622826
3432 3431 3957.019901776542639870501
3433 3432 3957.954717947092253546075
3434 3433 3959.470755505529516744654
3435 3434 3960.071028756977266031136
3436 3435 3960.770534614479359708466
3437 3436 3962.168461926687971607771
3438 3437 3963.470348861256275151684
3439 3438 3964.312649523208256814248
3440 3439 3965.13270709891233338617
3441 3440 3966.138714993044403933861
3442 3441 3966.753894106404171408075
3443 3442 3967.818761421170713090338
3444 3443 3968.48465360789603325114
3445 3444 3969.914600219660540069449
3446 3445 3971.318070212216399377305
3447 3446 3972.115760264560262036847
3448 3447 3973.010681503585877369284
3449 3448 3973.457014783824321923667
3450 3449 3974.893413368283160052264
3451 3450 3976.066183195673826166205
3452 3451 3976.731418901192373990986
3453 3452 3977.113908694971600065015
3454 3453 3978.686119979256594878194
3455 3454 3979.497341176278255104251
3456 3455 3980.844099782236250536174
3457 3456 3982.048502086845775326892
3458 3457 3982.764068116537151659485
3459 3458 3983.749795369122902311835
3460 3459 3984.227435181156851577244
3461 3460 3985.098725242399498989392
3462 3461 3986.516179038180407271527
3463 3462 3987.230709154775459031745
3464 3463 3988.719449264675649709891
3465 3464 3989.352175808955517196716
3466 3465 3990.481409607346073668663
3467 3466 3991.570890985175510498294
3468 3467 3992.33110509982246180572
3469 3468 3993.293163731767162155101
3470 3469 3994.39587399845226471107
3471 3470 3995.168459723067387720868
3472 3471 3995.797813413111165863464
3473 3472 3996.689040233028031629828
3474 3473 3998.809292299706732014203
3475 3474 3999.519248285303142180907
3476 3475 4000.017285178770817525017
3477 3476 4001.144258634627438509415
3478 3477 4002.112349427714343895922
3479 3478 4002.695719414773562292036
3480 3479 4004.022451394682446505104
3481 3480 4004.80673102867447586364
3482 3481 4005.876737437339064100626
3483 3482 4006.931920817723560603115
3484 3483 4008.142030891384439156352
3485 3484 4008.689596252476207075287
3486 3485 4010.361019023809560450906
3487 3486 4010.983311280304647997889
3488 3487 4011.663881541786930039466
3489 3488 4012.568916000892392478724
3490 3489 4013.233688805466681017985
3491 3490 4014.657294818277420413329
3492 3491 4015.657651051640921343151
3493 3492 4016.968938010016809797996
3494 3493 4018.029268458575597729829
3495 3494 4018.776951600020067438075
3496 3495 4019.106065040812167909245
3497 3496 4020.57077310366363936028
3498 3497 4021.628014217374502305405
3499 3498 4022.380106437604588096577
3500 3499 4023.428504974205280282145
3501 3500 4023.905151400087167641985

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