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

page 1 of 20 · 500/page · 10000 rows next →
# ngamma_n
2 1 14.13472514173469379045725
3 2 21.02203963877155499262848
4 3 25.01085758014568876321379
5 4 30.4248761258595132103119
6 5 32.93506158773918969066237
7 6 37.58617815882567125721776
8 7 40.91871901214749518739813
9 8 43.32707328091499951949612
10 9 48.00515088116715972794247
11 10 49.77383247767230218191678
12 11 52.9703214777144606441473
13 12 56.44624769706339480436776
14 13 59.34704400260235307965365
15 14 60.8317785246098098442599
16 15 65.11254404808160666087505
17 16 67.07981052949417371447883
18 17 69.54640171117397925292686
19 18 72.06715767448190758252211
20 19 75.70469069908393316832692
21 20 77.14484006887480537268266
22 21 79.33737502024936792276359
23 22 82.91038085408603018316484
24 23 84.73549298051705010573531
25 24 87.42527461312522940653167
26 25 88.80911120763446542368235
27 26 92.49189927055848429625973
28 27 94.65134404051988696659793
29 28 95.87063422824530975874103
30 29 98.83119421819369223332442
31 30 101.3178510057313912287854
32 31 103.7255380404783394163984
33 32 105.4466230523260944936708
34 33 107.1686111842764075151234
35 34 111.0295355431696745246564
36 35 111.8746591769926370856121
37 36 114.3202209154527127658909
38 37 116.2266803208575543821608
39 38 118.7907828659762173229791
40 39 121.3701250024206459189455
41 40 122.9468292935525882008175
42 41 124.256818554345767184732
43 42 127.5166838795964951242793
44 43 129.578704199956050985768
45 44 131.0876885309326567235664
46 45 133.4977372029975864501305
47 46 134.7565097533738713313261
48 47 138.1160420545334432001916
49 48 139.73620895212138895045
50 49 141.1237074040211237619404
51 50 143.1118458076206327394051
52 51 146.0009824867655185474025
53 52 147.4227653425596020495212
54 53 150.0535204207848803514325
55 54 150.9252576122414667618525
56 55 153.0246938111988961982565
57 56 156.1129092942378675697502
58 57 157.5975918175940598875305
59 58 158.849988171420498724175
60 59 161.1889641375960275194373
61 60 163.030709687181987243311
62 61 165.5370691879004188300389
63 62 167.1844399781745134409578
64 63 169.0945154155688214895059
65 64 169.9119764794116989666998
66 65 173.4115365195915529598461
67 66 174.7541915233657258133788
68 67 176.4414342977104188888926
69 68 178.3774077760999772858309
70 69 179.91648402025699613934
71 70 182.207078484366461915407
72 71 184.8744678483875088009606
73 72 185.5987836777074714665277
74 73 187.2289225835018519916415
75 74 189.4161586560169370848523
76 75 192.0266563607137865472836
77 76 193.0797266038457040474022
78 77 195.2653966795292353214632
79 78 196.8764818409583169486223
80 79 198.0153096762519124249199
81 80 201.2647519437037887330161
82 81 202.4935945141405342776867
83 82 204.1896718031045543307164
84 83 205.3946972021632860252124
85 84 207.906258887806209861502
86 85 209.5765097168562598528356
87 86 211.6908625953653075639075
88 87 213.3479193597126661906391
89 88 214.5470447834914232229442
90 89 216.1695385082637002658696
91 90 219.0675963490213789856773
92 91 220.7149188393140033691156
93 92 221.4307055546933387320975
94 93 224.0070002546043352117289
95 94 224.9833246695822875037825
96 95 227.4214442796792913104614
97 96 229.3374133055253481077601
98 97 231.2501887004991647738062
99 98 231.9872352531802486037717
100 99 233.6934041789083006407045
101 100 236.5242296658162058024755
102 101 237.7698204809252040032366
103 102 239.5554775733276287402689
104 103 241.0491577962165864128379
105 104 242.8232719342226000168265
106 105 244.0708984970781582368165
107 106 247.136990074897499467551
108 107 248.1019900601484592567621
109 108 249.5736896447072091923298
110 109 251.0149477950160011429542
111 110 253.069986747999477194599
112 111 255.3062564549140227530865
113 112 256.3807136944344777893584
114 113 258.6104394915313682089831
115 114 259.8744069896780003506728
116 115 260.8050845045968701859312
117 116 263.5738939048701322330816
118 117 265.5578518388763202924773
119 118 266.6149737815010724957201
120 119 267.921915082824059440379
121 120 269.9704490239976025946935
122 121 271.4940556416449990181794
123 122 273.4596091884032870457143
124 123 275.5874926493438412487407
125 124 276.4520495031329386798873
126 125 278.2507435298419544927483
127 126 279.2292509277451892284099
128 127 282.4651147650520962330272
129 128 283.2111857332338674204938
130 129 284.8359639809047241331576
131 130 286.6674453630028842928476
132 131 287.9119205014221871552541
133 132 289.579854929218834152738
134 133 291.8462913290673958355131
135 134 293.5584341393562853567767
136 135 294.9653696192655421750664
137 136 295.5732548789582923884608
138 137 297.9792770619434152099297
139 138 299.8403260537213129600271
140 139 301.6493254621941836234701
141 140 302.6967495896069170517515
142 141 304.8643713408572977001488
143 142 305.7289126020368092892228
144 143 307.21949612817005478941
145 144 310.1094631467018988047862
146 145 311.1651415303560032709427
147 146 312.427801180600891980486
148 147 313.985285731158922979049
149 148 315.4756160894757338685961
150 149 317.7348059423701803956455
151 150 318.8531042563165979066892
152 151 321.1601343091135782919215
153 152 322.1445586724829322988374
154 153 323.466969557512050506212
155 154 324.8628660517396132649801
156 155 327.4439012619054573434693
157 156 329.0330716804809340336147
158 157 329.9532397282338663438921
159 158 331.4744675826634243756618
160 159 333.6453785248698505849617
161 160 334.2113548332443832324034
162 161 336.8418504283906847946548
163 162 338.3399928508066118862573
164 163 339.8582167253635401923266
165 164 341.0422611110465604825978
166 165 342.0548775103635854514038
167 166 344.6617029402523370441812
168 167 346.3478705660099473959365
169 168 347.2726775844204844757971
170 169 349.3162608706961441231556
171 170 350.408419349192099187672
172 171 351.8786490253592804367134
173 172 353.4889004887188067836038
174 173 356.0175749772649473179604
175 174 357.1513022520396248096029
176 175 357.9526851016322737551289
177 176 359.743754953114448799292
178 177 361.2893616958046503902913
179 178 363.3313305789738347473345
180 179 364.7360241140889937162621
181 180 366.2127102883313168610771
182 181 367.9935754817403033261833
183 182 368.9684380957343898915769
184 183 370.0509192121060003396512
185 184 373.0619283721128384491194
186 185 373.8648739109085697447564
187 186 375.8259127667393341079077
188 187 376.3240922306680521171908
189 188 378.436680249965479724091
190 189 379.8729753465323466510241
191 190 381.4844686171865249196625
192 191 383.4435294495364877043458
193 192 384.9561168148636871037516
194 193 385.861300845974229180562
195 194 387.2228902223879809759485
196 195 388.8461283542322546008094
197 196 391.4560835636380457705782
198 197 392.2450833395190967490152
199 198 393.427743844434025936699
200 199 395.5828700109937209708777
201 200 396.3818542225921869319995
202 201 397.9187362096142433869812
203 202 399.9851198761948995059173
204 203 401.8392286005332165399113
205 204 402.8619177638861141763154
206 205 404.2364418002080047402278
207 206 405.1343874599099272574863
208 207 407.581460386896182076309
209 208 408.947245502351112519634
210 209 410.5138691933666386467691
211 210 411.9722678042787506646403
212 211 413.2627360701850468862571
213 212 415.0188097551551156463192
214 213 415.4552149962945988571288
215 214 418.3877057895347792260457
216 215 419.8613648181523236878523
217 216 420.6438276250417862679747
218 217 422.0767100588267596298407
219 218 423.7165796274818186105629
220 219 425.0698824944613476143747
221 220 427.2088250840745805281429
222 221 428.1279140766166821103051
223 222 430.328745430938636669927
224 223 431.3013069307035920195051
225 224 432.1386417345885683062532
226 225 433.8892184809272253029466
227 226 436.1610064326469840718015
228 227 437.5816981676685811540132
229 228 438.621738656272196290915
230 229 439.9184422143706564102218
231 230 441.6831992011890238742044
232 231 442.9045463026094494697231
233 232 444.3193362775591559203057
234 233 446.8606226964295225288609
235 234 447.4417041944932900655269
236 235 449.1485456850233047530235
237 236 450.1269457803135240300458
238 237 451.4033084453887954621132
239 238 453.9867378066779160383668
240 239 454.9746837686167888753094
241 240 456.3284266892460512244998
242 241 457.9038930641029715746993
243 242 459.5134152811060117540099
244 243 460.0879444221758412553303
245 244 462.0653672748825309638309
246 245 464.0572869105482845762461
247 246 465.6715392113710945529666
248 247 466.5702869308262551673921
249 248 467.439046210261638856645
250 249 469.5360045591120321918191
251 250 470.7736554781016476901189
252 251 472.799174661908816658298
253 252 473.8352323451396870738055
254 253 475.6003393693757856054288
255 254 476.7690152374845208528487
256 255 478.0752637666709691998727
257 256 478.9421815346348265383171
258 257 481.8303393762865613666814
259 258 482.834782790982397306557
260 259 483.8514272124825375601882
261 260 485.5391481293560069300254
262 261 486.5287182616512443523675
263 262 488.3805670900174485271114
264 263 489.6617615779561315127809
265 264 491.3988215936630065692133
266 265 493.3144415817853009363606
267 266 493.9579978053694649095831
268 267 495.3588288221312774968341
269 268 496.4296962157591034839189
270 269 498.5807824296865420166751
271 270 500.3090849416904955393094
272 271 501.6044469651454776633325
273 272 502.2762703271182331753995
274 273 504.4997733134277371837913
275 274 505.4152317422444420295522
276 275 506.4641527095235312215261
277 276 508.8007003364678208094697
278 277 510.2642279436728344207795
279 278 511.5622897003745954604549
280 279 512.6231445314074186671013
281 280 513.6689855554736834362441
282 281 515.4350571672993772496769
283 282 517.589668572467425341358
284 283 518.2342231475501435738583
285 284 520.1063104117232559031961
286 285 521.5251934494920409677324
287 286 522.4566961777302104301444
288 287 523.9605308920158404870075
289 288 525.0773856872796221805912
290 289 527.9036416012723452296173
291 290 528.4062138522926589416089
292 291 529.806226318706900798164
293 292 530.8669178839610896443874
294 293 532.6881830282937305051264
295 294 533.7796307537687325654825
296 295 535.6643140758732246170461
297 296 537.0697590831223275883897
298 297 538.428526176247962843501
299 298 540.2131663762281333836457
300 299 540.6313902472951173601281
301 300 541.8474371212012815471191
302 301 544.3238901010052629031213
303 302 545.6368332489348182548554
304 303 547.0109120581222924636559
305 304 547.9316133644893383104512
306 305 549.4975675626613784599847
307 306 550.9700100394838890456572
308 307 552.0495722005648927925767
309 308 553.7649721191588146171498
310 309 555.7920205616825084165732
311 310 556.8994764068553512619642
312 311 557.564659172058528408524
313 312 559.3162370286821637609351
314 313 560.2408074972956682417933
315 314 562.5592076160458511081379
316 315 564.1608791107861178138795
317 316 564.506055938149835122246
318 317 566.6987876828079562415123
319 318 567.7317579011769374503347
320 319 568.9239551796293684967535
321 320 570.051114782463592038527
322 321 572.4199841324527640452769
323 322 573.614610526758129987246
324 323 575.0938860144948856074572
325 324 575.8072471409287807094293
326 325 577.0390034720982112166371
327 326 579.0988346720366074312844
328 327 580.1369593623846286727163
329 328 581.9465762659016255515061
330 329 583.2360882191672782619606
331 330 584.5617059034655283669459
332 331 585.9845632049883005741873
333 332 586.7427718912501556447719
334 333 588.1396632662479564175542
335 334 590.660397516765275631032
336 335 591.7258580650480566492224
337 336 592.5713583002255698207727
338 337 593.9747146822310292438052
339 338 595.7281536973889491770209
340 339 596.3627683283936840895791
341 340 598.4930773461647544010636
342 341 599.5456403643648539975154
343 342 601.6021367359326360517381
344 343 602.5791678863873542988227
345 344 603.625618903579160672244
346 345 604.6162184937532329146396
347 346 606.3834604221090410886743
348 347 608.4132173111873251751267
349 348 609.3895751547200805273239
350 349 610.8391629377394069267025
351 350 611.7742096208872046351684
352 351 613.5997786756371194051865
353 352 614.6462378722326215255531
354 353 615.5385633694070278534743
355 354 618.1128313664423733825402
356 355 619.1844825979536342490281
357 356 620.2728936722275219190856
358 357 621.7092945279486229572986
359 358 622.3750027397790092178815
360 359 624.2699000181778808347729
361 360 626.0192834276543821983362
362 361 627.2683968507830207519976
363 362 628.3258623594603619359438
364 363 630.4738874382920458706066
365 364 630.8057809271975326418717
366 365 632.2251411671159519521547
367 366 633.5468582522517774841971
368 367 635.5238003106054538105256
369 368 637.3971931598373071737481
370 369 637.9255139808225810934288
371 370 638.9279382668567701937727
372 371 640.6947946688256676231875
373 372 641.9454996657052945453785
374 373 643.2788837813978893611434
375 374 644.9905782297480025124437
376 375 646.3481915955015920338809
377 376 647.7617530042888837937668
378 377 648.7864008887824407710801
379 378 650.1975193452564590832539
380 379 650.6686838913959825305606
381 380 653.6495716053946919020869
382 381 654.3019205863193422754706
383 382 655.7094630223556363160267
384 383 656.9640845994606174228699
385 384 658.1756144186053997448798
386 385 659.6638459729641078311652
387 386 660.7167325952792700521589
388 387 662.2965864311004106443783
389 388 664.2446046522730134498903
390 389 665.3427630955990405427882
391 390 666.5151477041729605487751
392 391 667.1484948945554299410692
393 392 668.9758488202351314061923
394 393 670.3235852058625840344296
395 394 672.4581835841697341813651
396 395 673.043578286147645770131
397 396 674.3558978101231678961563
398 397 676.1396743636267482031781
399 398 677.2301806687639732478548
400 399 677.8004447462213349189388
401 400 679.7421978825282177195259
402 401 681.8949915331518891094524
403 402 682.6027350197505454875408
404 403 684.0135498138695052361941
405 404 684.9726298620984525457367
406 405 686.163223587727949603473
407 406 687.9615431847036484827963
408 407 689.3689413622723684232552
409 408 690.4747350323503976939431
410 409 692.4516844155208488498467
411 410 693.1769700606018248456231
412 411 694.5339086998731400156307
413 412 695.7263359209267301678014
414 413 696.6260699003456149709028
415 414 699.1320954760135067108162
416 415 700.2967391321434945680122
417 416 701.3017429546461556851739
418 417 702.2273431457605001194353
419 418 704.0338392955253093226531
420 419 705.1258139546192276668675
421 420 706.184654799517919025811
422 421 708.269070885109899995269
423 422 709.2295885702843007090347
424 423 711.1302741796854315654749
425 424 711.9002899143753120389151
426 425 712.7493834701012902546106
427 426 714.0827718206693930769245
428 427 716.112396454052110148182
429 428 717.4825697031001907144419
430 429 718.7427865454858939884492
431 430 719.697100988365665132691
432 431 721.3511622185364171283862
433 432 722.2775049756742373403761
434 433 723.8458210451284155116719
435 434 724.5626138903790795922462
436 435 727.0564032300493816176484
437 436 728.4054815889340600347444
438 437 728.7587497956142685661306
439 438 730.416482122756434709944
440 439 731.4173549185985250807494
441 440 732.8180527144998492085675
442 441 734.7896432523779942523125
443 442 735.7654592085783210769322
444 443 737.0529289122653080423105
445 444 738.5804211713738225217055
446 445 739.909523674041944029701
447 446 740.573807447295010515036
448 447 741.7573355729416732758612
449 448 743.8950131424736593815501
450 449 745.3449895506118743256405
451 450 746.499305899432329509605
452 451 747.6745636242695283595694
453 452 748.2427544650845478685033
454 453 750.6559503621242998668074
455 454 750.9663810666508372684584
456 455 752.8876215672023747495077
457 456 754.3223704717126726851031
458 457 755.8393089760378298727924
459 458 756.7682484399509307201332
460 459 758.1017292464125834114898
461 460 758.9002382248923747674354
462 461 760.2823669835120645318696
463 462 762.700033249691054728069
464 463 763.5930661728372229969732
465 464 764.3075227241802217362512
466 465 766.0875400998362053944225
467 466 767.2184721555395140824994
468 467 768.2814618065092308234567
469 468 769.6934072526244243250067
470 469 771.0708393136783163211872
471 470 772.9616175657570243378292
472 471 774.1177446279405074021419
473 472 775.047847096580508050017
474 473 775.9997119631714424777316
475 474 777.299748529592564816511
476 475 779.1570769491890040639245
477 476 780.3489250041816705381278
478 477 782.1376643908120947543177
479 478 782.5979439460735398661665
480 479 784.2888226124655014631461
481 480 785.7390897007150518406462
482 481 786.4611474505062774598968
483 482 787.4684638159100383814735
484 483 790.059092364119564294946
485 484 790.8316204679210350190829
486 485 792.4277076086045268663911
487 486 792.8886525626225880422428
488 487 794.4837918698931644813184
489 488 795.6065961561624126279126
490 489 797.2634700380355849161917
491 490 798.707570166296211309692
492 491 799.6543362108976327728269
493 492 801.6042464629820559666766
494 493 802.5419848784181496624171
495 494 803.2430962042701941902262
496 495 804.7622391126617639515958
497 496 805.8616356670948028368032
498 497 808.1518149359937473923559
499 498 809.1977833633007103877196
500 499 810.0818048864070998915247
501 500 811.1843588465062603378843

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