Refactor: Extract utility function for string reversal

Extracted `inverser_chaine` into a reusable utility function with docstring and added unit test to ensure correctness.
This commit is contained in:
Eric Coissac
2026-04-27 20:23:44 +02:00
parent e7fa60a3a2
commit ebbfe35cbc
22 changed files with 1807 additions and 62 deletions
+2
View File
@@ -5,3 +5,5 @@ data-stress
*.zst
*.zst.meta
*.pb
*.json
*.bin
+275
View File
@@ -0,0 +1,275 @@
2026-04-27T20:36:04.208955Z  INFO obikmer::cmd::partition: dereplicating...
2026-04-27T20:36:11.471489Z  INFO obikpartitionner::partition: counting kmers in partition 0/256
2026-04-27T20:36:11.471521Z  INFO obikpartitionner::partition: counting kmers in partition 128/256
2026-04-27T20:36:11.471530Z  INFO obikpartitionner::partition: counting kmers in partition 32/256
2026-04-27T20:36:11.471535Z  INFO obikpartitionner::partition: counting kmers in partition 12/256
2026-04-27T20:36:11.471551Z  INFO obikpartitionner::partition: counting kmers in partition 76/256
2026-04-27T20:36:11.471522Z  INFO obikpartitionner::partition: counting kmers in partition 2/256
2026-04-27T20:36:11.471525Z  INFO obikpartitionner::partition: counting kmers in partition 4/256
2026-04-27T20:36:11.471535Z  INFO obikpartitionner::partition: counting kmers in partition 96/256
2026-04-27T20:36:11.471535Z  INFO obikpartitionner::partition: counting kmers in partition 80/256
2026-04-27T20:36:11.471535Z  INFO obikpartitionner::partition: counting kmers in partition 10/256
2026-04-27T20:36:11.471538Z  INFO obikpartitionner::partition: counting kmers in partition 16/256
2026-04-27T20:36:11.471543Z  INFO obikpartitionner::partition: counting kmers in partition 224/256
2026-04-27T20:36:11.471537Z  INFO obikpartitionner::partition: counting kmers in partition 192/256
2026-04-27T20:36:11.471536Z  INFO obikpartitionner::partition: counting kmers in partition 64/256
2026-04-27T20:36:11.471537Z  INFO obikpartitionner::partition: counting kmers in partition 72/256
2026-04-27T20:36:11.471530Z  INFO obikpartitionner::partition: counting kmers in partition 8/256
2026-04-27T20:36:12.831739Z  INFO obikpartitionner::partition: counting kmers in partition 129/256
2026-04-27T20:36:13.555104Z  INFO obikpartitionner::partition: counting kmers in partition 9/256
2026-04-27T20:36:14.077082Z  INFO obikpartitionner::partition: counting kmers in partition 17/256
2026-04-27T20:36:14.203310Z  INFO obikpartitionner::partition: counting kmers in partition 77/256
2026-04-27T20:36:14.316403Z  INFO obikpartitionner::partition: counting kmers in partition 3/256
2026-04-27T20:36:14.415177Z  INFO obikpartitionner::partition: counting kmers in partition 33/256
2026-04-27T20:36:14.467689Z  INFO obikpartitionner::partition: counting kmers in partition 97/256
2026-04-27T20:36:14.559650Z  INFO obikpartitionner::partition: counting kmers in partition 5/256
2026-04-27T20:36:14.591431Z  INFO obikpartitionner::partition: counting kmers in partition 81/256
2026-04-27T20:36:14.606508Z  INFO obikpartitionner::partition: counting kmers in partition 193/256
2026-04-27T20:36:14.611406Z  INFO obikpartitionner::partition: counting kmers in partition 73/256
2026-04-27T20:36:14.623813Z  INFO obikpartitionner::partition: counting kmers in partition 11/256
2026-04-27T20:36:14.665058Z  INFO obikpartitionner::partition: counting kmers in partition 65/256
2026-04-27T20:36:14.666877Z  INFO obikpartitionner::partition: counting kmers in partition 1/256
2026-04-27T20:36:14.667569Z  INFO obikpartitionner::partition: counting kmers in partition 13/256
2026-04-27T20:36:14.697486Z  INFO obikpartitionner::partition: counting kmers in partition 225/256
2026-04-27T20:36:14.698441Z  INFO obikpartitionner::partition: counting kmers in partition 130/256
2026-04-27T20:36:14.998749Z  INFO obikpartitionner::partition: counting kmers in partition 14/256
2026-04-27T20:36:15.485303Z  INFO obikpartitionner::partition: counting kmers in partition 18/256
2026-04-27T20:36:15.637613Z  INFO obikpartitionner::partition: counting kmers in partition 78/256
2026-04-27T20:36:15.722825Z  INFO obikpartitionner::partition: counting kmers in partition 98/256
2026-04-27T20:36:15.831703Z  INFO obikpartitionner::partition: counting kmers in partition 112/256
2026-04-27T20:36:16.161408Z  INFO obikpartitionner::partition: counting kmers in partition 66/256
2026-04-27T20:36:16.340113Z  INFO obikpartitionner::partition: counting kmers in partition 226/256
2026-04-27T20:36:16.506407Z  INFO obikpartitionner::partition: counting kmers in partition 82/256
2026-04-27T20:36:16.542430Z  INFO obikpartitionner::partition: counting kmers in partition 74/256
2026-04-27T20:36:16.550654Z  INFO obikpartitionner::partition: counting kmers in partition 34/256
2026-04-27T20:36:16.634719Z  INFO obikpartitionner::partition: counting kmers in partition 6/256
2026-04-27T20:36:16.763833Z  INFO obikpartitionner::partition: counting kmers in partition 194/256
2026-04-27T20:36:16.813285Z  INFO obikpartitionner::partition: counting kmers in partition 131/256
2026-04-27T20:36:16.913975Z  INFO obikpartitionner::partition: counting kmers in partition 208/256
2026-04-27T20:36:16.993526Z  INFO obikpartitionner::partition: counting kmers in partition 15/256
2026-04-27T20:36:17.092998Z  INFO obikpartitionner::partition: counting kmers in partition 160/256
2026-04-27T20:36:17.114964Z  INFO obikpartitionner::partition: counting kmers in partition 88/256
2026-04-27T20:36:17.148685Z  INFO obikpartitionner::partition: counting kmers in partition 79/256
2026-04-27T20:36:17.161989Z  INFO obikpartitionner::partition: counting kmers in partition 19/256
2026-04-27T20:36:17.180022Z  INFO obikpartitionner::partition: counting kmers in partition 113/256
2026-04-27T20:36:17.397037Z  INFO obikpartitionner::partition: counting kmers in partition 67/256
2026-04-27T20:36:17.484519Z  INFO obikpartitionner::partition: counting kmers in partition 99/256
2026-04-27T20:36:17.906842Z  INFO obikpartitionner::partition: counting kmers in partition 35/256
2026-04-27T20:36:18.146262Z  INFO obikpartitionner::partition: counting kmers in partition 75/256
2026-04-27T20:36:18.247130Z  INFO obikpartitionner::partition: counting kmers in partition 7/256
2026-04-27T20:36:18.303872Z  INFO obikpartitionner::partition: counting kmers in partition 227/256
2026-04-27T20:36:18.374448Z  INFO obikpartitionner::partition: counting kmers in partition 195/256
2026-04-27T20:36:18.382279Z  INFO obikpartitionner::partition: counting kmers in partition 83/256
2026-04-27T20:36:18.428092Z  INFO obikpartitionner::partition: counting kmers in partition 104/256
2026-04-27T20:36:18.442213Z  INFO obikpartitionner::partition: counting kmers in partition 132/256
2026-04-27T20:36:18.621883Z  INFO obikpartitionner::partition: counting kmers in partition 209/256
2026-04-27T20:36:18.784307Z  INFO obikpartitionner::partition: counting kmers in partition 161/256
2026-04-27T20:36:18.796465Z  INFO obikpartitionner::partition: counting kmers in partition 114/256
2026-04-27T20:36:18.877587Z  INFO obikpartitionner::partition: counting kmers in partition 120/256
2026-04-27T20:36:18.888423Z  INFO obikpartitionner::partition: counting kmers in partition 89/256
2026-04-27T20:36:18.918340Z  INFO obikpartitionner::partition: counting kmers in partition 20/256
2026-04-27T20:36:18.985341Z  INFO obikpartitionner::partition: counting kmers in partition 100/256
2026-04-27T20:36:19.080092Z  INFO obikpartitionner::partition: counting kmers in partition 68/256
2026-04-27T20:36:19.282760Z  INFO obikpartitionner::partition: counting kmers in partition 36/256
2026-04-27T20:36:19.485079Z  INFO obikpartitionner::partition: counting kmers in partition 92/256
2026-04-27T20:36:19.692354Z  INFO obikpartitionner::partition: counting kmers in partition 24/256
2026-04-27T20:36:19.746458Z  INFO obikpartitionner::partition: counting kmers in partition 228/256
2026-04-27T20:36:20.004054Z  INFO obikpartitionner::partition: counting kmers in partition 84/256
2026-04-27T20:36:20.164510Z  INFO obikpartitionner::partition: counting kmers in partition 196/256
2026-04-27T20:36:20.277288Z  INFO obikpartitionner::partition: counting kmers in partition 105/256
2026-04-27T20:36:20.349391Z  INFO obikpartitionner::partition: counting kmers in partition 133/256
2026-04-27T20:36:20.511981Z  INFO obikpartitionner::partition: counting kmers in partition 210/256
2026-04-27T20:36:20.709583Z  INFO obikpartitionner::partition: counting kmers in partition 101/256
2026-04-27T20:36:20.715870Z  INFO obikpartitionner::partition: counting kmers in partition 69/256
2026-04-27T20:36:20.728029Z  INFO obikpartitionner::partition: counting kmers in partition 115/256
2026-04-27T20:36:20.822257Z  INFO obikpartitionner::partition: counting kmers in partition 162/256
2026-04-27T20:36:20.982131Z  INFO obikpartitionner::partition: counting kmers in partition 90/256
2026-04-27T20:36:20.990122Z  INFO obikpartitionner::partition: counting kmers in partition 21/256
2026-04-27T20:36:21.030814Z  INFO obikpartitionner::partition: counting kmers in partition 121/256
2026-04-27T20:36:21.088309Z  INFO obikpartitionner::partition: counting kmers in partition 93/256
2026-04-27T20:36:21.134904Z  INFO obikpartitionner::partition: counting kmers in partition 37/256
2026-04-27T20:36:21.196814Z  INFO obikpartitionner::partition: counting kmers in partition 25/256
2026-04-27T20:36:21.444384Z  INFO obikpartitionner::partition: counting kmers in partition 85/256
2026-04-27T20:36:21.605343Z  INFO obikpartitionner::partition: counting kmers in partition 197/256
2026-04-27T20:36:21.954010Z  INFO obikpartitionner::partition: counting kmers in partition 106/256
2026-04-27T20:36:22.026167Z  INFO obikpartitionner::partition: counting kmers in partition 229/256
2026-04-27T20:36:22.194676Z  INFO obikpartitionner::partition: counting kmers in partition 134/256
2026-04-27T20:36:22.209911Z  INFO obikpartitionner::partition: counting kmers in partition 211/256
2026-04-27T20:36:22.281984Z  INFO obikpartitionner::partition: counting kmers in partition 70/256
2026-04-27T20:36:22.440637Z  INFO obikpartitionner::partition: counting kmers in partition 163/256
2026-04-27T20:36:22.481750Z  INFO obikpartitionner::partition: counting kmers in partition 91/256
2026-04-27T20:36:22.522458Z  INFO obikpartitionner::partition: counting kmers in partition 116/256
2026-04-27T20:36:22.775669Z  INFO obikpartitionner::partition: counting kmers in partition 22/256
2026-04-27T20:36:23.095766Z  INFO obikpartitionner::partition: counting kmers in partition 102/256
2026-04-27T20:36:23.119802Z  INFO obikpartitionner::partition: counting kmers in partition 94/256
2026-04-27T20:36:23.183138Z  INFO obikpartitionner::partition: counting kmers in partition 122/256
2026-04-27T20:36:23.186904Z  INFO obikpartitionner::partition: counting kmers in partition 38/256
2026-04-27T20:36:23.196250Z  INFO obikpartitionner::partition: counting kmers in partition 86/256
2026-04-27T20:36:23.206118Z  INFO obikpartitionner::partition: counting kmers in partition 26/256
2026-04-27T20:36:23.314520Z  INFO obikpartitionner::partition: counting kmers in partition 198/256
2026-04-27T20:36:23.355959Z  INFO obikpartitionner::partition: counting kmers in partition 107/256
2026-04-27T20:36:23.526146Z  INFO obikpartitionner::partition: counting kmers in partition 230/256
2026-04-27T20:36:23.723572Z  INFO obikpartitionner::partition: counting kmers in partition 212/256
2026-04-27T20:36:23.856569Z  INFO obikpartitionner::partition: counting kmers in partition 71/256
2026-04-27T20:36:23.910613Z  INFO obikpartitionner::partition: counting kmers in partition 164/256
2026-04-27T20:36:23.945560Z  INFO obikpartitionner::partition: counting kmers in partition 135/256
2026-04-27T20:36:24.085073Z  INFO obikpartitionner::partition: counting kmers in partition 117/256
2026-04-27T20:36:24.111144Z  INFO obikpartitionner::partition: counting kmers in partition 144/256
2026-04-27T20:36:24.188547Z  INFO obikpartitionner::partition: counting kmers in partition 23/256
2026-04-27T20:36:24.573867Z  INFO obikpartitionner::partition: counting kmers in partition 103/256
2026-04-27T20:36:24.604461Z  INFO obikpartitionner::partition: counting kmers in partition 27/256
2026-04-27T20:36:24.670189Z  INFO obikpartitionner::partition: counting kmers in partition 95/256
2026-04-27T20:36:24.935767Z  INFO obikpartitionner::partition: counting kmers in partition 123/256
2026-04-27T20:36:25.031507Z  INFO obikpartitionner::partition: counting kmers in partition 39/256
2026-04-27T20:36:25.039809Z  INFO obikpartitionner::partition: counting kmers in partition 108/256
2026-04-27T20:36:25.067950Z  INFO obikpartitionner::partition: counting kmers in partition 199/256
2026-04-27T20:36:25.149100Z  INFO obikpartitionner::partition: counting kmers in partition 231/256
2026-04-27T20:36:25.272346Z  INFO obikpartitionner::partition: counting kmers in partition 213/256
2026-04-27T20:36:25.400111Z  INFO obikpartitionner::partition: counting kmers in partition 165/256
2026-04-27T20:36:25.607381Z  INFO obikpartitionner::partition: counting kmers in partition 136/256
2026-04-27T20:36:25.902415Z  INFO obikpartitionner::partition: counting kmers in partition 152/256
2026-04-27T20:36:26.055400Z  INFO obikpartitionner::partition: counting kmers in partition 118/256
2026-04-27T20:36:26.138877Z  INFO obikpartitionner::partition: counting kmers in partition 119/256
2026-04-27T20:36:26.255235Z  INFO obikpartitionner::partition: counting kmers in partition 87/256
2026-04-27T20:36:26.350364Z  INFO obikpartitionner::partition: counting kmers in partition 148/256
2026-04-27T20:36:26.465089Z  INFO obikpartitionner::partition: counting kmers in partition 145/256
2026-04-27T20:36:26.682375Z  INFO obikpartitionner::partition: counting kmers in partition 40/256
2026-04-27T20:36:26.694729Z  INFO obikpartitionner::partition: counting kmers in partition 216/256
2026-04-27T20:36:26.777197Z  INFO obikpartitionner::partition: counting kmers in partition 28/256
2026-04-27T20:36:26.802996Z  INFO obikpartitionner::partition: counting kmers in partition 124/256
2026-04-27T20:36:26.972099Z  INFO obikpartitionner::partition: counting kmers in partition 200/256
2026-04-27T20:36:27.066713Z  INFO obikpartitionner::partition: counting kmers in partition 232/256
2026-04-27T20:36:27.112569Z  INFO obikpartitionner::partition: counting kmers in partition 166/256
2026-04-27T20:36:27.156124Z  INFO obikpartitionner::partition: counting kmers in partition 214/256
2026-04-27T20:36:27.231214Z  INFO obikpartitionner::partition: counting kmers in partition 137/256
2026-04-27T20:36:27.359784Z  INFO obikpartitionner::partition: counting kmers in partition 109/256
2026-04-27T20:36:27.369743Z  INFO obikpartitionner::partition: counting kmers in partition 153/256
2026-04-27T20:36:27.668409Z  INFO obikpartitionner::partition: counting kmers in partition 204/256
2026-04-27T20:36:27.701887Z  INFO obikpartitionner::partition: counting kmers in partition 202/256
2026-04-27T20:36:27.794402Z  INFO obikpartitionner::partition: counting kmers in partition 215/256
2026-04-27T20:36:28.058391Z  INFO obikpartitionner::partition: counting kmers in partition 149/256
2026-04-27T20:36:28.192195Z  INFO obikpartitionner::partition: counting kmers in partition 217/256
2026-04-27T20:36:28.369717Z  INFO obikpartitionner::partition: counting kmers in partition 125/256
2026-04-27T20:36:28.412339Z  INFO obikpartitionner::partition: counting kmers in partition 41/256
2026-04-27T20:36:28.496068Z  INFO obikpartitionner::partition: counting kmers in partition 29/256
2026-04-27T20:36:28.693510Z  INFO obikpartitionner::partition: counting kmers in partition 167/256
2026-04-27T20:36:28.808495Z  INFO obikpartitionner::partition: counting kmers in partition 201/256
2026-04-27T20:36:28.843564Z  INFO obikpartitionner::partition: counting kmers in partition 233/256
2026-04-27T20:36:28.917920Z  INFO obikpartitionner::partition: counting kmers in partition 140/256
2026-04-27T20:36:28.940416Z  INFO obikpartitionner::partition: counting kmers in partition 138/256
2026-04-27T20:36:29.125956Z  INFO obikpartitionner::partition: counting kmers in partition 110/256
2026-04-27T20:36:29.197246Z  INFO obikpartitionner::partition: counting kmers in partition 154/256
2026-04-27T20:36:29.376894Z  INFO obikpartitionner::partition: counting kmers in partition 203/256
2026-04-27T20:36:29.491887Z  INFO obikpartitionner::partition: counting kmers in partition 176/256
2026-04-27T20:36:29.501763Z  INFO obikpartitionner::partition: counting kmers in partition 205/256
2026-04-27T20:36:29.538499Z  INFO obikpartitionner::partition: counting kmers in partition 150/256
2026-04-27T20:36:29.685646Z  INFO obikpartitionner::partition: counting kmers in partition 218/256
2026-04-27T20:36:29.874786Z  INFO obikpartitionner::partition: counting kmers in partition 126/256
2026-04-27T20:36:30.021059Z  INFO obikpartitionner::partition: counting kmers in partition 42/256
2026-04-27T20:36:30.255780Z  INFO obikpartitionner::partition: counting kmers in partition 240/256
2026-04-27T20:36:30.602468Z  INFO obikpartitionner::partition: counting kmers in partition 141/256
2026-04-27T20:36:30.696718Z  INFO obikpartitionner::partition: counting kmers in partition 234/256
2026-04-27T20:36:30.784522Z  INFO obikpartitionner::partition: counting kmers in partition 139/256
2026-04-27T20:36:31.027016Z  INFO obikpartitionner::partition: counting kmers in partition 155/256
2026-04-27T20:36:31.073326Z  INFO obikpartitionner::partition: counting kmers in partition 30/256
2026-04-27T20:36:31.137264Z  INFO obikpartitionner::partition: counting kmers in partition 111/256
2026-04-27T20:36:31.143413Z  INFO obikpartitionner::partition: counting kmers in partition 168/256
2026-04-27T20:36:31.237329Z  INFO obikpartitionner::partition: counting kmers in partition 206/256
2026-04-27T20:36:31.252908Z  INFO obikpartitionner::partition: counting kmers in partition 236/256
2026-04-27T20:36:31.306110Z  INFO obikpartitionner::partition: counting kmers in partition 177/256
2026-04-27T20:36:31.431064Z  INFO obikpartitionner::partition: counting kmers in partition 151/256
2026-04-27T20:36:31.490837Z  INFO obikpartitionner::partition: counting kmers in partition 127/256
2026-04-27T20:36:31.528815Z  INFO obikpartitionner::partition: counting kmers in partition 43/256
2026-04-27T20:36:31.790858Z  INFO obikpartitionner::partition: counting kmers in partition 219/256
2026-04-27T20:36:31.803934Z  INFO obikpartitionner::partition: counting kmers in partition 241/256
2026-04-27T20:36:32.131051Z  INFO obikpartitionner::partition: counting kmers in partition 156/256
2026-04-27T20:36:32.433342Z  INFO obikpartitionner::partition: counting kmers in partition 235/256
2026-04-27T20:36:32.459699Z  INFO obikpartitionner::partition: counting kmers in partition 142/256
2026-04-27T20:36:32.532717Z  INFO obikpartitionner::partition: counting kmers in partition 31/256
2026-04-27T20:36:32.814909Z  INFO obikpartitionner::partition: counting kmers in partition 184/256
2026-04-27T20:36:32.967090Z  INFO obikpartitionner::partition: counting kmers in partition 169/256
2026-04-27T20:36:33.062660Z  INFO obikpartitionner::partition: counting kmers in partition 178/256
2026-04-27T20:36:33.076014Z  INFO obikpartitionner::partition: counting kmers in partition 237/256
2026-04-27T20:36:33.128961Z  INFO obikpartitionner::partition: counting kmers in partition 207/256
2026-04-27T20:36:33.228734Z  INFO obikpartitionner::partition: counting kmers in partition 180/256
2026-04-27T20:36:33.228905Z  INFO obikpartitionner::partition: counting kmers in partition 143/256
2026-04-27T20:36:33.266931Z  INFO obikpartitionner::partition: counting kmers in partition 44/256
2026-04-27T20:36:33.280333Z  INFO obikpartitionner::partition: counting kmers in partition 158/256
2026-04-27T20:36:33.368740Z  INFO obikpartitionner::partition: counting kmers in partition 220/256
2026-04-27T20:36:33.373469Z  INFO obikpartitionner::partition: counting kmers in partition 179/256
2026-04-27T20:36:33.409455Z  INFO obikpartitionner::partition: counting kmers in partition 157/256
2026-04-27T20:36:33.685036Z  INFO obikpartitionner::partition: counting kmers in partition 242/256
2026-04-27T20:36:34.174714Z  INFO obikpartitionner::partition: counting kmers in partition 182/256
2026-04-27T20:36:34.255362Z  INFO obikpartitionner::partition: counting kmers in partition 146/256
2026-04-27T20:36:34.284053Z  INFO obikpartitionner::partition: counting kmers in partition 170/256
2026-04-27T20:36:34.340602Z  INFO obikpartitionner::partition: counting kmers in partition 185/256
2026-04-27T20:36:34.748830Z  INFO obikpartitionner::partition: counting kmers in partition 45/256
2026-04-27T20:36:34.894515Z  INFO obikpartitionner::partition: counting kmers in partition 172/256
2026-04-27T20:36:35.342815Z  INFO obikpartitionner::partition: counting kmers in partition 238/256
2026-04-27T20:36:35.549647Z  INFO obikpartitionner::partition: counting kmers in partition 159/256
2026-04-27T20:36:35.556431Z  INFO obikpartitionner::partition: counting kmers in partition 181/256
2026-04-27T20:36:35.579877Z  INFO obikpartitionner::partition: counting kmers in partition 188/256
2026-04-27T20:36:35.619438Z  INFO obikpartitionner::partition: counting kmers in partition 221/256
2026-04-27T20:36:35.704344Z  INFO obikpartitionner::partition: counting kmers in partition 174/256
2026-04-27T20:36:35.891634Z  INFO obikpartitionner::partition: counting kmers in partition 190/256
2026-04-27T20:36:35.893065Z  INFO obikpartitionner::partition: counting kmers in partition 239/256
2026-04-27T20:36:35.978053Z  INFO obikpartitionner::partition: counting kmers in partition 183/256
2026-04-27T20:36:35.980835Z  INFO obikpartitionner::partition: counting kmers in partition 186/256
2026-04-27T20:36:36.010364Z  INFO obikpartitionner::partition: counting kmers in partition 243/256
2026-04-27T20:36:36.084972Z  INFO obikpartitionner::partition: counting kmers in partition 171/256
2026-04-27T20:36:36.085806Z  INFO obikpartitionner::partition: counting kmers in partition 147/256
2026-04-27T20:36:36.129893Z  INFO obikpartitionner::partition: counting kmers in partition 48/256
2026-04-27T20:36:36.188339Z  INFO obikpartitionner::partition: counting kmers in partition 46/256
2026-04-27T20:36:36.281975Z  INFO obikpartitionner::partition: counting kmers in partition 173/256
2026-04-27T20:36:37.004395Z  INFO obikpartitionner::partition: counting kmers in partition 187/256
2026-04-27T20:36:37.080479Z  INFO obikpartitionner::partition: counting kmers in partition 222/256
2026-04-27T20:36:37.100573Z  INFO obikpartitionner::partition: counting kmers in partition 189/256
2026-04-27T20:36:37.422152Z  INFO obikpartitionner::partition: counting kmers in partition 248/256
2026-04-27T20:36:37.446786Z  INFO obikpartitionner::partition: counting kmers in partition 175/256
2026-04-27T20:36:37.951518Z  INFO obikpartitionner::partition: counting kmers in partition 244/256
2026-04-27T20:36:38.235613Z  INFO obikpartitionner::partition: counting kmers in partition 191/256
2026-04-27T20:36:38.259288Z  INFO obikpartitionner::partition: counting kmers in partition 47/256
2026-04-27T20:36:38.379966Z  INFO obikpartitionner::partition: counting kmers in partition 252/256
2026-04-27T20:36:38.380690Z  INFO obikpartitionner::partition: counting kmers in partition 223/256
2026-04-27T20:36:38.520398Z  INFO obikpartitionner::partition: counting kmers in partition 56/256
2026-04-27T20:36:38.598256Z  INFO obikpartitionner::partition: counting kmers in partition 49/256
2026-04-27T20:36:38.680704Z  INFO obikpartitionner::partition: counting kmers in partition 254/256
2026-04-27T20:36:38.681038Z  INFO obikpartitionner::partition: counting kmers in partition 246/256
2026-04-27T20:36:38.813533Z  INFO obikpartitionner::partition: counting kmers in partition 247/256
2026-04-27T20:36:38.820199Z  INFO obikpartitionner::partition: counting kmers in partition 60/256
2026-04-27T20:36:38.961240Z  INFO obikpartitionner::partition: counting kmers in partition 52/256
2026-04-27T20:36:39.001585Z  INFO obikpartitionner::partition: counting kmers in partition 58/256
2026-04-27T20:36:39.050047Z  INFO obikpartitionner::partition: counting kmers in partition 249/256
2026-04-27T20:36:39.076449Z  INFO obikpartitionner::partition: counting kmers in partition 57/256
2026-04-27T20:36:39.078254Z  INFO obikpartitionner::partition: counting kmers in partition 250/256
2026-04-27T20:36:39.082390Z  INFO obikpartitionner::partition: counting kmers in partition 251/256
2026-04-27T20:36:39.082697Z  INFO obikpartitionner::partition: counting kmers in partition 245/256
2026-04-27T20:36:39.250465Z  INFO obikpartitionner::partition: counting kmers in partition 50/256
2026-04-27T20:36:39.448799Z  INFO obikpartitionner::partition: counting kmers in partition 54/256
2026-04-27T20:36:39.449166Z  INFO obikpartitionner::partition: counting kmers in partition 62/256
2026-04-27T20:36:39.450954Z  INFO obikpartitionner::partition: counting kmers in partition 63/256
2026-04-27T20:36:39.766480Z  INFO obikpartitionner::partition: counting kmers in partition 253/256
2026-04-27T20:36:39.838346Z  INFO obikpartitionner::partition: counting kmers in partition 59/256
2026-04-27T20:36:39.875987Z  INFO obikpartitionner::partition: counting kmers in partition 255/256
2026-04-27T20:36:39.876798Z  INFO obikpartitionner::partition: counting kmers in partition 55/256
2026-04-27T20:36:39.877292Z  INFO obikpartitionner::partition: counting kmers in partition 51/256
2026-04-27T20:36:40.244598Z  INFO obikpartitionner::partition: counting kmers in partition 61/256
2026-04-27T20:36:40.245589Z  INFO obikpartitionner::partition: counting kmers in partition 53/256
266.84 real 3776.35 user 115.80 sys
2423504896 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
292303 page reclaims
132311 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
0 signals received
4462 voluntary context switches
1991864 involuntary context switches
54933227607056 instructions retired
11271230983971 cycles elapsed
2210777320 peak memory footprint
+44 -11
View File
@@ -1,6 +1,29 @@
# MPHF selection — analysis in progress
# MPHF selection — two-phase indexing architecture
The choice of Minimal Perfect Hash Function for phase 6 is not yet settled. Three candidates were evaluated.
## Indexing architecture
Kmer indexing per partition proceeds in two phases. The separation is necessary because the exact number of unique kmers in a partition is not known until after counting and filtering.
### Superkmer vs kmer counts
The `SKFileMeta` sidecar written by `SKFileWriter` records `instances` (unique superkmers) and `length_sum` (total nucleotides). A superkmer of length L contains L k + 1 kmers, so the kmer count per partition can be estimated as `length_sum instances × (k 1)`. This is an **overestimate** of unique kmers: two distinct superkmers (different flanking contexts, same minimizer) can share kmers. The exact count of unique kmers is only known after enumerating and deduplicating them.
Note: two superkmers sharing a kmer necessarily share the same minimizer and therefore always land in the same partition — no kmer can appear in two different partitions.
### Phase 1 — provisional index and spectrum
1. Enumerate all kmers from the dereplicated superkmers of the partition.
2. Build a provisional MPHF over this key set; capacity is pre-allocated from the sidecar estimate (slight overestimate, harmless).
3. Accumulate counts: for each kmer in each superkmer, `count[MPHF(kmer)] += sk.count()`.
4. Compute the kmer frequency spectrum (histogram: occurrences → number of kmers).
5. Apply count filter (e.g. discard singletons). After filtering, the exact number of surviving kmers is known.
6. Discard the provisional MPHF.
### Phase 2 — definitive index
Build a new MPHF over the filtered kmer set only, with the exact key count available. This is the persistent per-partition index used for all downstream operations (queries, set operations).
---
## Candidates
@@ -8,31 +31,41 @@ The choice of Minimal Perfect Hash Function for phase 6 is not yet settled. Thre
- ~3.7 bits/key; mature crate, used in production bioinformatics (Pufferfish, Piscem)
- Parallel construction; well-tested with DNA kmer data at scale
- Drawback: largest space footprint of the three
- Drawback: largest space footprint; streaming construction (no exact count needed) was its main differentiator — irrelevant here since exact count is available at phase 2
**ptr_hash** (PtrHash algorithm, Groot Koerkamp, SEA 2025):
- ~2.4 bits/key; fastest queries (≥2.1× over alternatives, 812 ns/key for u64 in tight loops) and fastest construction (≥3.1×)
- Theoretical foundation solid; paper and Rust crate from the same author
- Requires exact key count at construction — available at phase 2
- Drawback: published February 2025 — very young, no production track record
**FMPHGO** (`ph` crate, Beling, ACM JEA 2023):
- ~2.1 bits/key — most compact of the three; good query speed; parallelisable construction
- More established than ptr_hash; actively maintained
- Currently preferred candidate
- Works well with overestimated capacity → natural fit for phase 1
## MPHF choice per phase
**Phase 1** (provisional, discarded after spectrum computation): FMPHGO. Tolerates overestimated capacity, compact, no need to optimise for query speed on a temporary structure.
**Phase 2** (persistent, queried repeatedly): open between FMPHGO and ptr_hash. Exact key count is available, so both operate optimally. ptr_hash's query speed advantage (2.13.3×) is meaningful for the persistent index but carries the risk of a very young crate. FMPHGO is the conservative default; ptr_hash is worth revisiting once it has broader production use.
boomphf is effectively eliminated: its space overhead is the largest and its streaming-construction advantage does not apply here.
---
## Space at scale
For 1 024 partitions × 100 M kmers/partition:
For 1 024 partitions × 100 M kmers/partition (phase 2 index, after filtering):
| MPHF | bits/key | Total MPHF size |
|---------|----------|-----------------|
|----------|----------|-----------------|
| boomphf | 3.7 | ~47 GB |
| ptr_hash | 2.4 | ~31 GB |
| FMPHGO | 2.1 | ~27 GB |
In practice, partition sizes depend on the dataset. For a human genome at 30× coverage with p=10 (1 024 partitions), realistic partition sizes are 330 M kmers → 18 MB per MPHF, well within RAM.
For a human genome at 30× coverage with 1 024 partitions, realistic partition sizes are 330 M unique kmers → 18 MB per phase-2 MPHF, well within RAM.
## On-disk and mmap considerations
@@ -42,7 +75,7 @@ No established Rust crate provides a natively on-disk MPHF. **SSHash** (Sparse a
## Open questions
- Confirm actual partition sizes on representative metagenomic datasets before fixing the choice.
- Evaluate whether ptr_hash's query speed advantage (2.13.3×) justifies adopting a crate that is less than a year old.
- Assess rkyv integration cost for FMPHGO if true zero-copy mmap becomes necessary.
- Confirm actual partition sizes and overestimation factor on representative metagenomic datasets.
- Revisit ptr_hash for phase 2 once the crate has broader production track record.
- Assess rkyv integration cost for FMPHGO if true zero-copy mmap becomes necessary for the persistent index.
- Keep SSHash in mind if the indexing architecture is reconsidered at a higher level.
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env python3
"""Plot kmer frequency spectrum from kmer_spectrum_raw.json (log-log scale)."""
import json
import sys
import argparse
import matplotlib.pyplot as plt
def load_spectrum(path: str):
with open(path) as f:
data = json.load(f)
spectrum = data["spectrum"]
pairs = sorted((int(k), v) for k, v in spectrum.items() if v > 0)
counts = [x for x, _ in pairs]
freqs = [y for _, y in pairs]
return counts, freqs, data.get("f0"), data.get("f1")
def main():
parser = argparse.ArgumentParser(description="Log-log kmer spectrum plot")
parser.add_argument("spectrum", nargs="?", default="kmer_spectrum_raw.json",
help="Path to kmer_spectrum_raw.json")
parser.add_argument("-o", "--output", default=None,
help="Save figure to file (PNG/SVG/PDF). Omit to display interactively.")
parser.add_argument("--max-count", type=int, default=None,
help="Truncate x-axis at this count value")
args = parser.parse_args()
counts, freqs, f0, f1 = load_spectrum(args.spectrum)
if args.max_count:
pairs = [(c, f) for c, f in zip(counts, freqs) if c <= args.max_count]
counts, freqs = zip(*pairs) if pairs else ([], [])
fig, ax = plt.subplots(figsize=(9, 5))
ax.plot(counts, freqs, ".", markersize=2, linewidth=0.6, color="steelblue")
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlabel("Repetition degree (count)", fontsize=12)
ax.set_ylabel("Number of distinct k-mers", fontsize=12)
ax.set_title("K-mer frequency spectrum", fontsize=13)
info = []
if f0 is not None:
info.append(f"F₀ = {f0:,}")
if f1 is not None:
info.append(f"F₁ = {f1:,}")
if info:
ax.text(0.98, 0.97, " ".join(info), transform=ax.transAxes,
ha="right", va="top", fontsize=9, color="gray")
ax.grid(True, which="both", linestyle="--", linewidth=0.4, alpha=0.6)
fig.tight_layout()
if args.output:
fig.savefig(args.output, dpi=150)
print(f"Saved to {args.output}", file=sys.stderr)
else:
plt.show()
if __name__ == "__main__":
main()
+1137 -41
View File
File diff suppressed because it is too large Load Diff
+24
View File
@@ -0,0 +1,24 @@
use clap::Args;
use obikpartitionner::KmerPartition;
use std::path::PathBuf;
use tracing::info;
#[derive(Args)]
pub struct CountArgs {
/// Partition directory produced by the `partition` command
#[arg(short, long)]
pub partition: PathBuf,
}
pub fn run(args: CountArgs) {
let kp = KmerPartition::open(&args.partition).unwrap_or_else(|e| {
eprintln!("error: {e}");
std::process::exit(1)
});
info!("counting kmers in {}", args.partition.display());
kp.count_kmer().unwrap_or_else(|e| {
eprintln!("error: {e}");
std::process::exit(1)
});
}
+1
View File
@@ -1,2 +1,3 @@
pub mod count;
pub mod partition;
pub mod superkmer;
+1
View File
@@ -136,4 +136,5 @@ pub fn run(args: PartitionArgs) {
info!("dereplicating...");
kp.lock().unwrap().dereplicate().expect("dereplicate error");
kp.lock().unwrap().count_kmer().expect("count kmer error");
}
+3
View File
@@ -16,6 +16,8 @@ enum Commands {
Superkmer(cmd::superkmer::SuperkmerArgs),
/// Partition super-kmers on disk by minimizer
Partition(cmd::partition::PartitionArgs),
/// Count kmers from an existing dereplicated partition directory
Count(cmd::count::CountArgs),
}
fn main() {
@@ -37,6 +39,7 @@ fn main() {
match cli.command {
Commands::Superkmer(args) => cmd::superkmer::run(args),
Commands::Partition(args) => cmd::partition::run(args),
Commands::Count(args) => cmd::count::run(args),
}
#[cfg(feature = "profiling")]
+2
View File
@@ -13,3 +13,5 @@ sysinfo = "0.33"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tracing = "0.1.44"
ph = "0.11"
memmap2 = "0.9.10"
+237 -2
View File
@@ -1,8 +1,12 @@
use std::collections::HashMap;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use tracing::debug;
use tracing::{debug, info};
use memmap2::MmapMut;
use obikseq::kmer::Kmer;
use ph::fmph::GOFunction;
use sysinfo::System;
@@ -99,6 +103,42 @@ impl KmerPartition {
Ok(partition)
}
pub fn open<P: AsRef<Path>>(path: P) -> SKResult<Self> {
let root_path = path.as_ref().to_owned();
if !root_path.exists() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("{}: partition directory not found", root_path.display()),
)
.into());
}
let meta_path = root_path.join(META_FILENAME);
let meta: PartitionMeta = serde_json::from_reader(fs::File::open(&meta_path)?)
.map_err(io::Error::other)?;
let format = match meta.format.as_str() {
"gzip" => Format::Gzip,
"bzip2" => Format::Bzip,
"lzma" => Format::Lzma,
"zstd" => Format::Zstd,
_ => Format::No,
};
let level = level_from_u32(meta.level);
let n_partitions = 1usize << meta.n_bits;
let writers = (0..n_partitions).map(|_| None).collect();
Ok(Self {
root_path,
n_partitions,
partitions_mask: (1u64 << meta.n_bits) - 1,
kmer_size: meta.kmer_size,
minimizer_size: meta.minimizer_size,
writers,
format,
level,
closed: true, // read-only: writing is not allowed on an opened partition
})
}
pub fn write(&mut self, sk: &mut SuperKmer) -> SKResult<()> {
self.check_not_closed()?;
let partition = self.partition_of(sk)?;
@@ -190,6 +230,73 @@ impl KmerPartition {
Ok(())
}
/// For each partition that has a `dereplicated.{ext}` file:
/// 1. Enumerates all unique canonical kmers (two passes over the file).
/// 2. Builds a provisional MPHF (FMPHGO) over those kmers.
/// 3. Writes a flat binary count file (`counts1.bin`, one `u32` per slot,
/// memory-mapped) accumulating kmer abundances from the superkmer counts.
/// 4. Persists the MPHF to `mphf1.bin` for downstream use.
/// 5. Writes a global `kmer_spectrum_raw.json` at the partition root.
///
/// Partitions are processed in parallel via Rayon (one task per thread).
/// Peak memory per partition is ~80 MB, so n_threads partitions run simultaneously.
pub fn count_kmer(&self) -> SKResult<()> {
let ext = format_ext(self.format);
let root = &self.root_path;
let k = self.kmer_size;
let results: Vec<SKResult<()>> = (0..self.n_partitions)
.into_par_iter()
.map(|i| {
let dir = root.join(format!("part_{:05}", i));
let dedup_path = dir.join(format!("dereplicated.{ext}"));
if !dedup_path.exists() {
return Ok(());
}
info!("counting kmers in partition {}/{}", i, self.n_partitions);
count_partition(&dir, &dedup_path, k)
})
.collect();
for r in results {
r?;
}
// Aggregate per-partition spectra into a global one at the root.
let mut global_spectrum: BTreeMap<u32, u64> = BTreeMap::new();
let mut global_f0: u64 = 0;
let mut global_f1: u64 = 0;
for i in 0..self.n_partitions {
let path = root
.join(format!("part_{:05}", i))
.join("kmer_spectrum_raw.json");
if !path.exists() {
continue;
}
let v: serde_json::Value =
serde_json::from_str(&fs::read_to_string(&path)?).map_err(io::Error::other)?;
global_f0 += v["f0"].as_u64().unwrap_or(0);
global_f1 += v["f1"].as_u64().unwrap_or(0);
if let Some(obj) = v["spectrum"].as_object() {
for (c_str, freq) in obj {
if let (Ok(c), Some(f)) = (c_str.parse::<u32>(), freq.as_u64()) {
*global_spectrum.entry(c).or_insert(0) += f;
}
}
}
}
let global_spectrum_map: BTreeMap<String, u64> =
global_spectrum.iter().map(|(&c, &f)| (format!("{c:010}"), f)).collect();
serde_json::to_writer_pretty(
fs::File::create(root.join("kmer_spectrum_raw.json"))?,
&serde_json::json!({ "f0": global_f0, "f1": global_f1, "spectrum": &global_spectrum_map }),
)
.map_err(io::Error::other)?;
Ok(())
}
// ── private ───────────────────────────────────────────────────────────────
fn check_not_closed(&self) -> SKResult<()> {
@@ -289,6 +396,18 @@ fn optimal_buckets(raw_path: &Path, available_bytes: u64) -> usize {
n.next_power_of_two() as usize
}
fn level_from_u32(n: u32) -> Level {
match n {
0 => Level::Zero, 1 => Level::One, 2 => Level::Two, 3 => Level::Three,
4 => Level::Four, 5 => Level::Five, 6 => Level::Six, 7 => Level::Seven,
8 => Level::Eight, 9 => Level::Nine, 10 => Level::Ten, 11 => Level::Eleven,
12 => Level::Twelve, 13 => Level::Thirteen, 14 => Level::Fourteen,
15 => Level::Fifteen, 16 => Level::Sixteen, 17 => Level::Seventeen,
18 => Level::Eighteen, 19 => Level::Nineteen, 20 => Level::Twenty,
_ => Level::TwentyOne,
}
}
fn format_ext(format: Format) -> &'static str {
match format {
Format::Gzip => "skmer.gz",
@@ -391,6 +510,122 @@ fn flush_map(map: HashMap<SuperKmer, u64>, writer: &mut SKFileWriter) -> SKResul
Ok(())
}
/// Build the provisional MPHF and count file for one partition directory.
fn count_partition(dir: &Path, dedup_path: &Path, k: usize) -> SKResult<()> {
// Estimate number of kmers from sidecar to pre-allocate the HashSet.
let capacity = SKFileMeta::read(dedup_path)
.ok()
.flatten()
.map(|m| {
let km1 = (k as u64).saturating_sub(1);
m.length_sum.saturating_sub(m.instances.saturating_mul(km1)) as usize
})
.unwrap_or(0);
debug!("{}: sidecar capacity estimate={capacity}", dir.display());
// Pass 1: collect all unique canonical kmers.
let mut seen: HashSet<Kmer> = HashSet::with_capacity(capacity);
let mut pass1_superkmers: u64 = 0;
{
let mut reader = SKFileReader::open(dedup_path)?;
while let Some(sk) = reader.read()? {
pass1_superkmers += 1;
let seql = sk.seql();
if seql < k {
continue;
}
for pos in 0..=(seql - k) {
seen.insert(sk.kmer(pos, k).map_err(io::Error::other)?.canonical(k));
}
}
}
let kmers: Vec<Kmer> = seen.into_iter().collect();
let n_kmers = kmers.len();
debug!("{}: pass1 superkmers={pass1_superkmers} unique_kmers={n_kmers}", dir.display());
if n_kmers == 0 {
return Ok(());
}
// Build provisional MPHF.
let mphf = GOFunction::from(kmers);
debug!("{}: MPHF built len={}", dir.display(), mphf.len());
// Create memory-mapped count file (u32 per slot, zero-initialised).
let counts_path = dir.join("counts1.bin");
let counts_file = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(&counts_path)?;
counts_file.set_len((n_kmers * std::mem::size_of::<u32>()) as u64)?;
let mut mmap = unsafe { MmapMut::map_mut(&counts_file)? };
mmap.fill(0);
// Pass 2: accumulate superkmer counts into the mmap'd array.
let mut pass2_superkmers: u64 = 0;
let mut pass2_kmer_hits: u64 = 0;
let mut pass2_kmer_misses: u64 = 0;
let mut pass2_count_sum: u64 = 0;
{
let counts =
unsafe { std::slice::from_raw_parts_mut(mmap.as_mut_ptr() as *mut u32, n_kmers) };
let mut reader = SKFileReader::open(dedup_path)?;
while let Some(sk) = reader.read()? {
pass2_superkmers += 1;
let seql = sk.seql();
let sk_count = sk.count();
if pass2_superkmers <= 3 {
debug!("{}: sk#{pass2_superkmers} seql={seql} count={sk_count}", dir.display());
}
if seql < k {
continue;
}
pass2_count_sum += sk_count as u64;
for pos in 0..=(seql - k) {
let kmer = sk.kmer(pos, k).map_err(io::Error::other)?.canonical(k);
if let Some(idx) = mphf.get(&kmer) {
counts[idx as usize] = counts[idx as usize].saturating_add(sk_count);
pass2_kmer_hits += 1;
} else {
pass2_kmer_misses += 1;
}
}
}
}
debug!(
"{}: pass2 superkmers={pass2_superkmers} hits={pass2_kmer_hits} misses={pass2_kmer_misses} count_sum={pass2_count_sum}",
dir.display()
);
mmap.flush()?;
// Build kmer frequency spectrum from the count array.
let counts = unsafe { std::slice::from_raw_parts(mmap.as_ptr() as *const u32, n_kmers) };
let mut spectrum: BTreeMap<u32, u64> = BTreeMap::new();
for &c in counts {
if c > 0 {
*spectrum.entry(c).or_insert(0) += 1;
}
}
let f0 = n_kmers as u64;
let f1: u64 = spectrum.iter().map(|(&c, &f)| c as u64 * f).sum();
let spectrum_map: BTreeMap<String, u64> =
spectrum.iter().map(|(&c, &f)| (format!("{c:010}"), f)).collect();
serde_json::to_writer_pretty(
fs::File::create(dir.join("kmer_spectrum_raw.json"))?,
&serde_json::json!({ "f0": f0, "f1": f1, "spectrum": &spectrum_map }),
)
.map_err(io::Error::other)?;
// Persist MPHF to disk.
let mphf_path = dir.join("mphf1.bin");
mphf.write(&mut fs::File::create(&mphf_path)?)?;
Ok(())
}
impl Drop for KmerPartition {
fn drop(&mut self) {
let _ = self.close();
+12
View File
@@ -135,6 +135,18 @@ impl SuperKmer {
}
}
/// Deserialise from a raw 32-bit header word and packed sequence bytes.
/// Preserves the full header payload (count or minimizer_pos in bits [31:8]).
pub fn from_header_bits(bits: u32, seq: Box<[u8]>) -> Self {
let seql = (bits & 0xFF) as u8;
let len = stored_to_len(seql);
debug_assert_eq!(seq.len(), byte_len(len));
Self {
header: SuperKmerHeader(bits),
seq,
}
}
/// Returns the sequence length in nucleotides (1256).
pub fn seql(&self) -> usize {
stored_to_len(self.header.seql())
+1 -1
View File
@@ -26,7 +26,7 @@ pub(crate) fn read_superkmer<R: Read>(
let byte_len = (nt_len + 3) / 4;
seq_buf.resize(byte_len, 0);
r.read_exact(seq_buf)?;
Ok(Some(SuperKmer::new(seql_byte, seq_buf.as_slice().into())))
Ok(Some(SuperKmer::from_header_bits(bits, seq_buf.as_slice().into())))
}
#[cfg(test)]
-1
View File
@@ -1 +0,0 @@
{"rustc_fingerprint":2162534064148227772,"outputs":{"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/coissac/.rustup/toolchains/stable-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"6432102384495711296":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/coissac/.rustup/toolchains/stable-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.94.1 (e408947bf 2026-03-25)\nbinary: rustc\ncommit-hash: e408947bfd200af42db322daf0fadfe7e26d3bd1\ncommit-date: 2026-03-25\nhost: aarch64-apple-darwin\nrelease: 1.94.1\nLLVM version: 21.1.8\n","stderr":""}},"successes":{}}
@@ -1 +0,0 @@
{"rustc":17940977064402226622,"features":"[]","declared_features":"[]","target":1865439097712885860,"profile":2330448797067240312,"path":3117914143523182133,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/obikseq-4791c70657a715c0/dep-lib-obikseq","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}
@@ -1 +0,0 @@
{"rustc":17940977064402226622,"features":"[]","declared_features":"[]","target":1865439097712885860,"profile":619605765252926426,"path":3117914143523182133,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/obikseq-5cc47015be91e3b1/dep-test-lib-obikseq","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":0}