decimal-scaled 0.5.0

Const-generic base-10 fixed-point decimals (D18/D38/D76/D153/D307 and the half-width tiers up to D1232) with integer-only transcendentals correctly rounded to within 0.5 ULP — exact at the type's last representable place. Deterministic across every platform; no_std-friendly.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
// SPDX-FileCopyrightText: 2026 John Moxley
// SPDX-License-Identifier: MIT OR Apache-2.0

//! Tier-generic surface over the per-tier wide guard-digit cores.
//!
//! Each wide decimal tier (D57 .. D1232) carries a guard-digit
//! transcendental core, emitted by `decl_wide_transcendental!` into a
//! `wide_trig_<tier>` module against a tier-specific work integer `W`
//! (e.g. `Int<16>` for D307) and tier-specific constant tables. The
//! per-family wide-tier kernels (`algos::{exp,ln,trig}::wide_kernel`)
//! run through six generic `*_series` functions ([`exp_series`],
//! [`ln_series`], [`sin_series`], [`cos_series`], [`tan_series`],
//! [`atan_series`]) instead of one thin `*_strict_<tier>` wrapper per tier
//! per function.
//!
//! [`WideTrigCore`] is the trait that backs those six generic functions.
//! `W` and the storage integer cannot be computed from a single const
//! parameter on stable rust (`W = Int<2N>` needs `generic_const_exprs`),
//! so each tier binds them as **associated types** on a per-tier `Core`
//! marker; `select`/routing is unchanged, only the call target moves
//! from the per-tier wrapper to `*_series::<Core, SCALE>`. This is the
//! same work-width-threading pattern the `sqrt` pilot uses, expressed as
//! a trait because the core surface (not just one work width) is shared.
//!
//! # Layering
//!
//! The `*_series` functions are **algorithm functions**: they call only
//! the trait surface (which forwards *down* into the per-tier core's
//! kernels) and the width-free `near_pole_tan` helper. They never call a
//! method on their own decimal type — the type's `*_strict` methods
//! delegate *down* through the policy dispatch to here.
//!
//! # Per-tier impls
//!
//! The trait is implemented once per tier by `decl_wide_transcendental!`
//! (the `impl WideTrigCore for Core` block it emits): each method
//! forwards to the sibling free function the macro already emits in the
//! per-tier core module (`$core::exp_fixed`, `$core::round_to_storage_*`,
//! …). Collapsing those per-tier bodies themselves to one `BigInt`-
//! generic implementation (the `exp_generic` precedent in
//! `crate::macros::wide_transcendental`) is a separate, later step — the
//! trait surface here is what makes that collapse a local change rather
//! than a routing change.

use crate::int::types::traits::BigInt;
use crate::support::rounding::RoundingMode;

/// Tier-generic surface over a wide guard-digit transcendental core.
///
/// Implemented once per wide tier by `decl_wide_transcendental!` on a
/// per-tier zero-sized `Core` marker, binding the tier's work integer
/// [`Self::W`] and storage integer [`Self::Storage`] as associated
/// types. The six `*_series` free functions in this module are generic
/// over `C: WideTrigCore` and drive the whole wide-tier strict
/// transcendental surface through it.
pub(crate) trait WideTrigCore {
    /// The tier's guard-digit work integer: a value `x` is held as the
    /// `W` integer `x · 10^w` at a working scale `w`.
    type W: BigInt + Copy + PartialEq;
    /// The next-wider work integer used by the large-result `exp` path
    /// (`exp_fixed_wide`). Aliases [`Self::W`] on the widest tier. Not
    /// consumed by the `*_series` functions directly; threaded so a
    /// later `BigInt`-generic core lift has the binding available.
    type Wexp: BigInt + Copy + PartialEq;
    /// The wide composition / AGM work integer (the two-core split): the
    /// compositions + the AGM run on `Wagm` so a narrowed primitive
    /// [`Self::W`] cannot clip their precision. Aliases [`Self::W`] until
    /// the primitive `$Work` is narrowed.
    type Wagm: BigInt + Copy + PartialEq;
    /// The tier's storage integer (`x · 10^SCALE`).
    type Storage: BigInt + Copy + PartialEq;

    /// Guard digits added below the storage scale on the strict path.
    const GUARD: u32;

    // ── value zero / small constants in `Storage` and `W` ──────────────

    /// The storage `0`.
    fn storage_zero() -> Self::Storage;
    /// The storage representation of `1` at scale `SCALE` (`10^SCALE`).
    fn storage_one(scale: u32) -> Self::Storage;
    /// The storage `MAX` / `MIN` (the tier's representable bounds). Supplied to
    /// the work-rung narrowing range check (`round_to_storage_*_g`): `MAX`/`MIN`
    /// are inherent consts on `Int<N>`, NOT on `BigInt`, so a tier-generic
    /// kernel sources them through the `Core` here rather than `Self::Storage::MAX`.
    fn storage_max() -> Self::Storage;
    /// See [`Self::storage_max`].
    fn storage_min() -> Self::Storage;
    /// The work-integer `0`.
    fn zero() -> Self::W;

    // ── working-scale lift / narrow ────────────────────────────────────

    /// Builds a working-scale `W` from raw storage, scaling by
    /// `10^working_digits` (raw is `value · 10^SCALE`).
    fn to_work_scaled(raw: Self::Storage, working_digits: u32) -> Self::W;
    /// Builds a working-scale `W` from raw storage at the const `GUARD`.
    fn to_work(raw: Self::Storage) -> Self::W;
    /// Rounds a working-scale `W` value at scale `w` to scale `target`
    /// under `mode` and narrows to storage.
    fn round_to_storage_with(
        v: Self::W,
        w: u32,
        target: u32,
        mode: RoundingMode,
    ) -> Self::Storage;
    /// `Wagm` storage-bridge: lift raw storage to the wide composition work
    /// integer (the `Wagm` sibling of [`Self::to_work_scaled`]).
    fn to_work_scaled_agm(raw: Self::Storage, working_digits: u32) -> Self::Wagm;
    /// `Wagm` storage-bridge: narrow a `Wagm` composition value at scale `w`
    /// to scale `target` under `mode` (the `Wagm` sibling of
    /// [`Self::round_to_storage_with`]).
    fn round_to_storage_with_agm(
        v: Self::Wagm,
        w: u32,
        target: u32,
        mode: RoundingMode,
    ) -> Self::Storage;
    /// Directed-rounding narrowing with Ziv escalation. `recompute(g)`
    /// returns the kernel value computed with `g` guard digits.
    fn round_to_storage_directed(
        base_guard: u32,
        target: u32,
        mode: RoundingMode,
        recompute: &mut dyn FnMut(u32) -> Self::W,
    ) -> Self::Storage;
    /// Directed-rounding narrowing for a kernel whose true result is **never
    /// exactly representable** at the storage scale — a non-zero-argument
    /// transcendental (`exp`), irrational by Lindemann–Weierstrass and so
    /// always strictly between two storage grid lines. Identical to
    /// [`Self::round_to_storage_directed`] except a working residual of exactly
    /// zero is treated as a genuine sub-resolution positive residual (Ceiling
    /// rounds up, Floor / Trunc keep the floor, nearest is unaffected) — the
    /// only correctly-rounded answer when the deciding residual sits below the
    /// work integer's resolution (e.g. `exp(-10^-S)` just under `1.0`). The
    /// caller MUST pin its algebraic-exact inputs (`exp 0`) before this.
    fn round_to_storage_directed_never_exact(
        base_guard: u32,
        target: u32,
        mode: RoundingMode,
        recompute: &mut dyn FnMut(u32) -> Self::W,
    ) -> Self::Storage;

    // ── the per-tier guard-digit kernels ──────────────────────────────

    /// `e^v` for a working-scale value `v` at scale `w`. `SCALE`
    /// const-folds the internal `ln 2` — see [`Self::ln_fixed`].
    fn exp_fixed<const SCALE: u32>(v_w: Self::W, w: u32) -> Self::W;
    /// Natural log of a positive working-scale value at scale `w`.
    ///
    /// `SCALE` is the decimal layer's own storage scale: on the common
    /// path `w == SCALE + GUARD`, so the kernel reads its `ln 2`
    /// constant from the compile-time baked `WideConst<SCALE>` rather
    /// than re-deriving it at runtime; any other `w` (Ziv escalation)
    /// falls to the runtime const. Bit-identical either way.
    fn ln_fixed<const SCALE: u32>(v_w: Self::W, w: u32) -> Self::W;
    /// Sine of a working-scale value at scale `w`. `SCALE` const-folds
    /// the internal `π` — see [`Self::ln_fixed`].
    fn sin_fixed<const SCALE: u32>(v_w: Self::W, w: u32) -> Self::W;
    /// Cosine of a working-scale value at scale `w`. `SCALE` const-folds
    /// the internal `π` — see [`Self::ln_fixed`].
    fn cos_fixed<const SCALE: u32>(v_w: Self::W, w: u32) -> Self::W;
    /// Joint sine + cosine of a working-scale value at scale `w`. `SCALE`
    /// const-folds the internal `π` — see [`Self::ln_fixed`].
    fn sin_cos_fixed<const SCALE: u32>(v_w: Self::W, w: u32) -> (Self::W, Self::W);
    /// Arctangent of a working-scale value at scale `w`. `SCALE`
    /// const-folds the internal `π/2` — see [`Self::ln_fixed`].
    fn atan_fixed<const SCALE: u32>(v_w: Self::W, w: u32) -> Self::W;

    // ── working-scale helpers the tan kernel needs ────────────────────

    /// `(a · 10^w) / b`, rounded half-to-even.
    fn div(a: Self::W, b: Self::W, w: u32) -> Self::W;
    /// `(a · b) / 10^w`, rounded half-to-even — the plain work-int
    /// multiply. Needed by the inverse / inverse-hyperbolic schoolbooks
    /// (`x^2`, `inv^2`, `t*(t+2)`).
    fn mul(a: Self::W, b: Self::W, w: u32) -> Self::W;
    /// Integer square root of a non-negative working-scale value at
    /// scale `w` (`sqrt(v / 10^w) * 10^w`). The leaf asin/acos/asinh/
    /// acosh schoolbooks need it (`asin = atan(x / sqrt(1 - x^2))`).
    /// Dispatches down to the work-int root.
    fn sqrt_fixed(v: Self::W, w: u32) -> Self::W;
    /// `ln(1 + t)` at working scale `w`, accurate for small `t` — the
    /// near-1 branch of the acosh schoolbook (avoids the `v^2 - 1`
    /// cancellation as `v -> 1`).
    fn log1p_fixed(t: Self::W, w: u32) -> Self::W;
    /// Bit length of `|v|` (0 for zero).
    fn bit_length(v: Self::W) -> u32;

    // hyperbolic exp-identity kernels (sinh/cosh/tanh schoolbooks)

    /// The `ceil(|x| * log10(e))` integer-digit lift for the large-arg
    /// `e^x` reassembly, used to set the base guard so a big `sinh`/
    /// `cosh` stays sub-storage-ULP. `mag_at_scale` is `x * 10^scale`.
    fn exp_result_int_digits(mag_at_scale: Self::W, scale: u32) -> u32;
    /// `sinh(|x|)` at working scale `w` via the `(e^x - e^-x)/2`
    /// identity (composed in the wider [`Self::Wexp`]); caller reapplies
    /// the sign. `SCALE` const-folds the internal `ln 2` (via
    /// `exp_fixed`) — see [`Self::ln_fixed`].
    fn sinh_pos_wide<const SCALE: u32>(av_w: Self::W, w: u32) -> Self::W;
    /// `cosh(|x|)` at working scale `w` via the `(e^x + e^-x)/2`
    /// identity. `SCALE` const-folds the internal `ln 2` — see
    /// [`Self::sinh_pos_wide`].
    fn cosh_pos_wide<const SCALE: u32>(av_w: Self::W, w: u32) -> Self::W;
    /// `tanh(|x|)` at working scale `w` via the
    /// `(e^x - e^-x)/(e^x + e^-x)` identity; caller reapplies the sign.
    /// `SCALE` const-folds the internal `ln 2` — see
    /// [`Self::sinh_pos_wide`].
    fn tanh_pos_wide<const SCALE: u32>(av_w: Self::W, w: u32) -> Self::W;

    /// Tang/Series-ROUTED working-scale natural log on the wide
    /// composition integer [`Self::Wagm`] — the per-tier
    /// `ln_fixed_routed_agm` (Tang where `policy::ln::is_tang` routes
    /// it, Series otherwise; the per-tier Tang CAP is a macro literal,
    /// which is why this is a trait binding rather than a free generic).
    /// Consumed by the acosh / atanh canonical kernels.
    fn ln_fixed_routed_agm<const SCALE: u32>(v_w: Self::Wagm, w: u32) -> Self::Wagm;

    /// Directed-rounding narrowing with Ziv escalation, forcing a
    /// confirm recompute even in nearest modes — the acosh / atanh
    /// near-special path (the residual can sit on a rounding boundary).
    fn round_to_storage_directed_near_special(
        base_guard: u32,
        target: u32,
        mode: RoundingMode,
        recompute: &mut dyn FnMut(u32) -> Self::W,
    ) -> Self::Storage;

    // ── working-scale helpers the Tang lookup kernels need ─────────────

    /// The work-integer `1` at working scale `w` (`10^w`), cached.
    fn one(w: u32) -> Self::W;
    /// The work-integer literal `n` (small unsigned).
    fn lit(n: u128) -> Self::W;
    /// `ln 2` at working scale `w`, const-folded at the layer's own
    /// `SCALE` (the baked `WideConst<SCALE>` on the common
    /// `w == SCALE + GUARD` path) — see [`Self::ln_fixed`].
    fn ln2<const SCALE: u32>(w: u32) -> Self::W;
    /// `(a · 10^w) / b`, rounded half-to-even, with a precomputed
    /// `10^w` numerator factor (loop-friendly).
    fn div_cached(a: Self::W, b: Self::W, pow10_w: Self::W) -> Self::W;
    /// Rounds a working-scale value to the nearest integer (ties away
    /// from zero); the range-reduction quotient for the Tang exp kernel.
    fn round_to_nearest_int(v: Self::W, w: u32) -> i128;
    /// `10^n` in the work integer (the un-cached power; used to widen by
    /// `extra` digits in the Tang exp reassembly).
    fn pow10(n: u32) -> Self::W;
    /// `Self::W::BITS` — the work integer's bit width.
    fn w_bits() -> u32;

    /// The `ln(1 + i/M)` Tang table slot at working scale `w` (table
    /// size `M = 128`; the `i = 0` slot is `0`, the `i = M` slot is
    /// `ln 2`). Recomputed on the stack per call; `SCALE` const-folds
    /// the internal `ln 2` — see [`Self::ln_fixed`].
    fn ln_table_entry<const SCALE: u32>(w: u32, idx: usize) -> Self::W;

    /// The Tang exp table slot `exp(j · ln2 / M)` at working scale `w`
    /// for table size `M`. Recomputed on the stack per call; `SCALE`
    /// const-folds the internal `ln 2` — see [`Self::ln_fixed`].
    fn exp_table_entry<const SCALE: u32>(w: u32, idx: usize, m: u32) -> Self::W;

    // ── π constants + the sincos Tang table (the sincos Tang kernel) ───

    /// `π` at working scale `w`, const-folded at the layer's own `SCALE`
    /// (the baked `WideConst<SCALE>` on the common `w == SCALE + GUARD`
    /// path) — see [`Self::ln_fixed`].
    fn pi<const SCALE: u32>(w: u32) -> Self::W;
    /// `π/2` at working scale `w`, const-folded at the layer's own
    /// `SCALE` — see [`Self::pi`].
    fn half_pi<const SCALE: u32>(w: u32) -> Self::W;

    /// `180/π` (degrees per radian) at working scale `w`, const-folded at
    /// the layer's own `SCALE` — see [`Self::pi`]. The exact angle-scale
    /// factor the `to_degrees` `MulPiRatio` kernel multiplies by (`x *
    /// 180/π`), replacing the runtime divide-by-`π`.
    fn deg_per_rad<const SCALE: u32>(w: u32) -> Self::W;
    /// `π/180` (radians per degree) at working scale `w`, const-folded at
    /// the layer's own `SCALE` — see [`Self::pi`]. The exact angle-scale
    /// factor the `to_radians` `MulPiRatio` kernel multiplies by (`x *
    /// π/180`).
    fn rad_per_deg<const SCALE: u32>(w: u32) -> Self::W;

    /// The sincos Tang table slot `(sin(c_j), cos(c_j))` at working
    /// scale `w` for table size `m`, where `c_j = j · π / (4·m)` and
    /// `j ∈ [0, m]` (the `j = m` slot is `(sin π/4, cos π/4)`, needed
    /// because rounding can lift a residual to the table boundary).
    /// Recomputed on the stack per call; `SCALE` const-folds the
    /// internal `π` — see [`Self::ln_fixed`].
    fn sincos_table_entry<const SCALE: u32>(w: u32, idx: usize, m: u32) -> (Self::W, Self::W);
}

/// Near-min analytic pin for `exp`. When `|v| < 10^(-SCALE/2)` the deviation
/// `e^v − (1 + v) = v²/2 + …` is provably below half a storage ULP, and `e^v > 1 + v`
/// strictly (exp is convex), so the correctly-rounded result is exactly `1 + v` for
/// every mode except `Ceiling`, which the positive deviation — however deep it
/// sits — rounds up by one ULP.
/// This short-circuits the widening: at these tiny inputs its `s >> n` range reduction
/// loses bits (the working guard carries fewer factors of 2 than `n`), and the
/// resulting sub-ULP deficit borrows into the result digit at the `…999000` /
/// `1.000…` grid line — a deciding digit past the work integer's reach, so the
/// escalation can't recover it. Returns `None` (defer to the normal path) otherwise.
/// The cheap bit-length pre-filter exits before the `pow10` for every non-tiny input,
/// so the hot path is unaffected.
#[inline]
fn exp_near_min_pin<C: WideTrigCore, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> Option<C::Storage> {
    let half = SCALE / 2;
    let zero = C::storage_zero();
    if half == 0 || raw == zero {
        return None;
    }
    let absr = if raw < zero { zero - raw } else { raw };
    // `10^half` has ≈ half·log2(10) bits; skip the pow10 unless |raw| is plausibly
    // below it (true only for genuinely tiny inputs — every normal call exits here).
    // A value of bit-length `bl` is at least `2^(bl−1)`, so the exit is certain
    // only once `2^(bl−1) >= 10^half` ⟺ `(bl−1)·log10(2) >= half` — comparing
    // `bl` itself (not `bl−1`) silently dropped the top quarter of the band.
    let bl = <C::Storage as BigInt>::BITS - absr.leading_zeros();
    if ((bl - 1) as u64) * 100_000 >= (half as u64) * 332_193 {
        return None;
    }
    // Exact: |raw| < 10^half ⟺ v²/2 < ½ ULP and the deviation sits past the scale.
    if absr >= crate::consts::pow10::dispatch::<C::Storage>(half) {
        return None;
    }
    let g = C::storage_one(SCALE) + raw; // (1 + v), exact since |v| < 1
    Some(match mode {
        RoundingMode::Ceiling => g + <C::Storage as BigInt>::from_i128(1),
        _ => g,
    })
}

/// `exp_strict` for a wide tier — generic over the tier `C`.
///
/// `raw == 0` short-circuits to the type's `ONE` raw (`10^SCALE`) rather
/// than running the Taylor series. Replaces the per-tier
/// `exp_strict_<tier>` wrappers.
#[inline]
#[must_use]
pub(crate) fn exp_series<C: WideTrigCore, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    <C::Wexp as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    if raw == C::storage_zero() {
        return C::storage_one(SCALE);
    }
    if let Some(r) = exp_near_min_pin::<C, SCALE>(raw, mode) {
        return r;
    }
    // `exp(x)` for `x != 0` is transcendental (Lindemann–Weierstrass), so its
    // true value is never exactly on a storage grid line — a zero working
    // residual is a sub-resolution artifact, not a true zero. The `never_exact`
    // rule makes Ceiling round up (Floor stays) on inputs whose deciding
    // residual sits below the work-int resolution (`exp(-10^-S)` just under
    // `1.0`). `raw == 0` (the one exact case) is pinned above.
    //
    // Two-width near-min widening: near `x ≈ 0` the half-ULP tie of
    // `exp(±10^-k)` is decided by the `x³/6` term at digit ≈ `1.5·SCALE`, beyond
    // the tier work integer's escalation reach at mid/high scales; retry at
    // `C::Wexp` when the deciding digit is unreachable in `C::W`. Deep ties past
    // the precision horizon stay exact ties.
    round_to_storage_widening_g::<C::Storage, C::W, C::Wexp>(
        C::GUARD,
        SCALE,
        mode,
        true,
        C::storage_max(),
        C::storage_min(),
        |guard| C::exp_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard),
        |guard| {
            crate::algos::exp::exp_generic::exp_fixed::<C::Wexp>(
                to_work_scaled_g::<C::Storage, C::Wexp>(raw, guard),
                SCALE + guard,
            )
        },
    )
}

/// Rung-generic `exp_strict` — the Series exp kernel run at an
/// arbitrary work rung `Wk` (decoupled from `C::W`; mirrors
/// [`sin_series_g`]). Identical pins ([`exp_near_min_pin`], the zero
/// pin) and the identical two-width near-min widening as
/// [`exp_series`], with the PRIMARY width swapped from `C::W` to the
/// rung: each Ziv probe regime-splits on the exact
/// [`crate::algos::exp::exp_generic::exp_peak_fits`] model (the same
/// gate the per-tier `exp_fixed` routes `exp_fixed_wide` with) — the
/// fast path runs `exp_fixed::<Wk>`, a probe whose internal
/// squaring/`2^k` peak outgrows the rung lifts to the tier's `C::Wexp`
/// and narrows the (always-rung-representable) probe VALUE back. The
/// widening RETRY stays at `C::Wexp`, unchanged: a near-tie unresolved
/// at the rung's smaller cap retries there, reaching at least the
/// tier's resolution depth. The policy gate bounds `|x|` (the
/// result-magnitude axis, `work_rung::EXP_ARG_BUDGET`) so the everyday
/// region stays on the rung's fast path.
#[cfg(feature = "_wide-support")]
#[inline]
#[must_use]
pub(crate) fn exp_series_g<C: WideTrigCore, Wk: BigInt, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    Wk::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    <C::Wexp as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    use crate::algos::exp::exp_generic as eg;
    if raw == C::storage_zero() {
        return C::storage_one(SCALE);
    }
    if let Some(r) = exp_near_min_pin::<C, SCALE>(raw, mode) {
        return r;
    }
    round_to_storage_widening_g::<C::Storage, Wk, C::Wexp>(
        C::GUARD,
        SCALE,
        mode,
        true,
        C::storage_max(),
        C::storage_min(),
        |guard| {
            let w = SCALE + guard;
            let v = to_work_scaled_g::<C::Storage, Wk>(raw, guard);
            if eg::exp_peak_fits::<Wk>(v, w) {
                eg::exp_fixed::<Wk>(v, w)
            } else {
                eg::resize_or_panic::<C::Wexp, Wk>(eg::exp_fixed::<C::Wexp>(
                    to_work_scaled_g::<C::Storage, C::Wexp>(raw, guard),
                    w,
                ))
            }
        },
        |guard| {
            eg::exp_fixed::<C::Wexp>(
                to_work_scaled_g::<C::Storage, C::Wexp>(raw, guard),
                SCALE + guard,
            )
        },
    )
}

/// `ln_strict` for a wide tier — generic over the tier `C`. Panics if
/// `raw <= 0`. Replaces the per-tier `ln_strict_<tier>` wrappers.
#[inline]
#[must_use]
pub(crate) fn ln_series<C: WideTrigCore, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    ln_series_g::<C, C::W, SCALE>(raw, mode)
}

/// Rung-generic `ln_series` — the Brent-reduction wide-ln kernel run at an
/// arbitrary work rung `Wk` (decoupled from `C::W`), so the policy can
/// run / bench Series at its minimal valid work width
/// (mirrors [`crate::algos::ln::ln_tang::ln_tang_g`]; [`ln_series`] is the
/// `Wk = C::W` alias, bit-identical). Calls the already-work-int-generic
/// `exp_generic::ln_fixed::<Wk>` directly (bypassing the fixed-`C::W` trait
/// method `C::ln_fixed`), with `ln 2` const-folded at the base working scale on
/// the hot path — value-identical to the per-tier `ln2_cf::<SCALE>`.
#[inline]
#[must_use]
pub(crate) fn ln_series_g<C: WideTrigCore, Wk: BigInt, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    <Wk as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    if raw <= C::storage_zero() {
        panic!("wide-tier ln: argument must be positive");
    }
    round_to_storage_directed_g::<C::Storage, Wk>(
        C::GUARD,
        SCALE,
        mode,
        C::storage_max(),
        C::storage_min(),
        |guard| {
            let w = SCALE + guard;
            let ln2 = if w == SCALE + C::GUARD {
                crate::consts::ln2_by_scale::<Wk>(w, crate::support::rounding::DEFAULT_ROUNDING_MODE)
            } else {
                crate::consts::ln2_by_working_scale::<Wk>(
                    w,
                    crate::support::rounding::DEFAULT_ROUNDING_MODE,
                )
            };
            crate::algos::exp::exp_generic::ln_fixed::<Wk>(
                to_work_scaled_g::<C::Storage, Wk>(raw, guard),
                w,
                ln2,
            )
        },
    )
}

/// `sin_strict` for a wide tier — generic over the tier `C`. Replaces
/// the per-tier `sin_strict_<tier>` wrappers.
#[inline]
#[must_use]
pub(crate) fn sin_series<C: WideTrigCore, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    // Linear-band analytic directed decision (relocated DOWN from the policy
    // layer so the bare tier kernel and the rung-dispatched path agree): the
    // cubic deciding digit sits below the work integer's Ziv reach AND the
    // const-table provisioning, so only the analytic sign resolves it.
    if let Some(v) = tiny_x_linear_directed::<C::Storage, SCALE>(raw, mode, false) {
        return v;
    }
    let (r, decided) = round_to_storage_directed_decided_g::<C::Storage, C::W>(
        C::GUARD,
        SCALE,
        mode,
        C::storage_max(),
        C::storage_min(),
        |guard| C::sin_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard),
    );
    // Deep sub-resolution band (deciding `x^{j*}`, `j* ≥ 5`): the walker is
    // mode-blind (`decided == false`); the sign is analytic (`sin` alternates).
    let r = tiny_x_deep_directed_adjust::<C::Storage, SCALE>(r, decided, raw, mode, true, <C::W as BigInt>::BITS);
    adjust_bounded_extremum::<C, SCALE>(r, raw, mode)
}

/// `cos_strict` for a wide tier — generic over the tier `C`. Standalone
/// `cos_fixed` path (cofunction identity, one `sin_fixed`, no sqrt).
/// Replaces the per-tier `cos_strict_<tier>` wrappers.
#[inline]
#[must_use]
pub(crate) fn cos_series<C: WideTrigCore, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage {
    let r = C::round_to_storage_directed(C::GUARD, SCALE, mode, &mut |guard| {
        C::cos_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard)
    });
    adjust_bounded_extremum::<C, SCALE>(r, raw, mode)
}

/// Directed-rounding post-adjust for `sin`/`cos` near an extremum the
/// working-scale kernel cannot resolve.
///
/// `sin`/`cos` lie STRICTLY inside `(−1, 1)` for every representable
/// non-special argument: `cos = +1` only at the already-pinned `raw == 0`,
/// and `cos = −1` / `sin = ±1` occur only at arguments (`π`, `π/2 + kπ`) that
/// are never exactly representable. But for an argument within the input
/// granularity of an extremum the deviation `δ²/2` from `±1` can sit far below
/// any REACHABLE working scale — e.g. ~`10⁻³⁴⁷` at D462 s346, against a
/// ~462-digit work-integer ceiling — so the kernel rounds to exactly
/// `±10^SCALE` and a DIRECTED mode then lands on the wrong side of the grid
/// line (the value is interior, but the kernel saw it AS the extremum).
///
/// Because the true value is strictly interior, the directed side is known a
/// priori with no extra precision:
/// - just below `+1` (`result == +one`): Floor / Trunc step down one LSB to
///   `one − 1`; Ceiling keeps `one`.
/// - just above `−1` (`result == −one`): Ceiling / Trunc step toward zero to
///   `−one + 1`; Floor keeps `−one`.
///
/// Nearest modes are unaffected (rounding to `±1` IS correct to nearest there).
/// A no-op unless the directed result is exactly `±10^SCALE` and `raw != 0`, so
/// reachable cells (already resolved off the grid line) and the exact
/// `cos(0) = 1` point pass through untouched. The rule is continuous over the
/// whole near-extremum region, not fitted to one benched cell.
#[inline]
pub(crate) fn adjust_bounded_extremum<C: WideTrigCore, const SCALE: u32>(
    result: C::Storage,
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage {
    if crate::support::rounding::is_nearest_mode(mode) || raw == C::storage_zero() {
        return result;
    }
    let one = C::storage_one(SCALE);
    let neg_one = C::storage_zero() - one;
    if result == one {
        match mode {
            RoundingMode::Floor | RoundingMode::Trunc => one - <C::Storage as BigInt>::ONE,
            _ => result,
        }
    } else if result == neg_one {
        match mode {
            RoundingMode::Ceiling | RoundingMode::Trunc => neg_one + <C::Storage as BigInt>::ONE,
            _ => result,
        }
    } else {
        result
    }
}

/// Analytic directed rounding for the tiny-argument linear band of the odd
/// forward/inverse trig functions whose Maclaurin series is
/// `f(x) = x + c·x³ + …` with `|c| ≤ 1/3` (`sin`, `tan`, `atan`, `asin`).
///
/// For `|x| < 10^(−⌈SCALE/3⌉)` — i.e. `|raw| ≤ 10^(SCALE − ⌈SCALE/3⌉)` in
/// storage units — the cubic correction `|c·x³|` stays below half a storage
/// ULP, so `f(x)` rounds to exactly `x` (= `raw`) under the nearest modes
/// while sitting a STRICTLY-signed sub-ULP cubic tail off the grid line: the
/// directed result is then determined analytically by the tail's sign,
/// EXPANDING (`|f| > |x|`: `tan` `+x³/3`, `asin` `+x³/6`) or COMPRESSING
/// (`|f| < |x|`: `sin` `−x³/6`, `atan` `−x³/3`).
///
/// This is the wide-tier sibling of the narrow tier's
/// `small_x_linear_threshold` + [`tiny_odd_expanding_directed`] /
/// [`tiny_odd_compressing_directed`] pair
/// (`crate::support::rounding`). At a wide tier the cubic deciding digit
/// sits at fractional depth `≈ 3·SCALE`, far beyond the work integer's Ziv
/// escalation reach, so the directed walker cannot resolve it and falls to a
/// mode-blind grid value (the comprehensive-gate wrong-mode find: `tan`/`sin`
/// of `1e-117`/`3e-60`-class arguments at D153/D307/D616). The analytic
/// decision is the only correct source there. Returns `Some(result)` for a
/// directed mode with `raw` inside the band; `None` otherwise (nearest modes,
/// `SCALE == 0`, `raw == 0`, or `|raw|` outside the band) — the caller then
/// runs its normal kernel, unchanged.
#[inline]
pub(crate) fn tiny_x_linear_directed<St: BigInt, const SCALE: u32>(
    raw: St,
    mode: RoundingMode,
    expanding: bool,
) -> Option<St> {
    // Only the directed modes are at risk; the nearest modes round to `raw`,
    // which the kernel already produces in-band. `SCALE == 0` has no sub-unit
    // linear band (only `x = 0` is "tiny", and that is the kernel's exact pin).
    if crate::support::rounding::is_nearest_mode(mode) || SCALE == 0 {
        return None;
    }
    let zero = <St as BigInt>::ZERO;
    if raw == zero {
        return None; // f(0) is the kernel's exact-zero pin
    }
    let absr = if raw < zero { zero - raw } else { raw };
    // The small-x linear band exponent, conservative by one digit (matches the
    // narrow `small_x_linear_threshold`): `|raw| ≤ 10^(SCALE − ⌈SCALE/3⌉)`.
    let thresh_exp = SCALE - SCALE.div_ceil(3);
    // One table-read + one compare exits for every normal-magnitude argument.
    if absr > crate::consts::pow10::dispatch::<St>(thresh_exp) {
        return None;
    }
    // `one` is ONE STORAGE ULP (the integer `1`), the step the directed
    // decision adds/drops — NOT `10^SCALE` (the value 1.0).
    let one = <St as BigInt>::ONE;
    Some(if expanding {
        crate::support::rounding::tiny_odd_expanding_directed(raw, zero, one, mode)
    } else {
        crate::support::rounding::tiny_odd_compressing_directed(raw, zero, one, mode)
    })
}

/// Upper bound on the deciding Taylor-term index `j*` that the deep-band
/// directed post-adjust ([`tiny_x_deep_directed_adjust`]) handles. `j* ≤ JMAX`
/// is equivalent to `|x| < 10^(−SCALE/JMAX)` — a CONTINUOUS tiny-argument band
/// (Class I), not a per-cell fit: a smaller `|x|` raises the leading-digit
/// position `k`, which lowers `j*`. The bound keeps the post-adjust off NON-tiny
/// arguments (whose `k = 1` gives `j* ≈ SCALE`, far above `JMAX`) so a rare
/// deep Table-Maker tie at an ordinary magnitude is never mistaken for the
/// analytic tiny-`x` regime. `41` spans every deep sub-resolution cell the
/// odd-series trig kernels reach (the comprehensive-gate find is `j* = 7`),
/// with wide headroom; the `decided == false` gate (below) is the real
/// validity wall, this only excludes the non-tiny corner.
const TINY_X_DEEP_JMAX: u32 = 41;

/// Analytic directed post-adjust for the DEEP sub-resolution band of the odd
/// forward/inverse trig functions — the generalisation of
/// [`tiny_x_linear_directed`] past its `j* = 3` (cubic) reach.
///
/// For a tiny `x = m·10^(−k)` whose LEADING odd Taylor terms terminate exactly
/// on the storage grid (so `f(x)` rounds to a grid value `G` under nearest),
/// the directed side is decided by the first SUB-resolution odd term `x^{j*}`
/// (`j* =` smallest odd `j` with `j·k > SCALE`). Its sign is analytically
/// certain: `sin`/`atan` alternate (`+` for `j* ≡ 1 (mod 4)`, `−` for `j* ≡ 3`),
/// `tan`/`asin` are always `+` (every coefficient positive). At a wide tier
/// `x^{j*}` sits at fractional depth `j*·k`, BEYOND both the work integer's Ziv
/// reach AND the const-table provisioning, so the directed walker returns the
/// mode-blind grid value `G` (`decided == false`) — the `±3·10^(−120)` @ D616
/// s615 find, deciding `x⁷` at depth ~841.
///
/// TWO conditions must hold for the adjust to fire — and they are independent:
/// 1. `decided == false`: the walker gave up at its escalation cap.
/// 2. `j*·k > reach`: the deciding term sits BEYOND the walker's reach
///    (`reach = work_bits/8 − 8`, the directed `BITS/8` cap with the
///    bounded-result trig `int_digits = 0`). This is the load-bearing test:
///    `decided == false` ALONE is not "mode-blind" — the walker can RESOLVE
///    the deciding term correctly yet still report `decided == false` when its
///    CONFIRM probe lands on the cap-clamped (`tainted`) rung. Only when the
///    term is genuinely past `reach` is `r` the mode-blind grid value `G`.
///
/// When both hold the value is on the grid (`r == G`, every above-scale term
/// terminated — an off-grid value's non-terminating tail is at depth `~SCALE`,
/// well WITHIN `reach`, so the walker resolves it and `j*·k ≤ reach` keeps this
/// off). The result is `G ± 1 ULP` per the deciding sign via the same
/// [`tiny_odd_expanding_directed`] / [`tiny_odd_compressing_directed`] step the
/// linear band uses. `alternating` selects the sign rule (`true` = `sin`/`atan`,
/// `false` = `tan`/`asin`); `work_bits` is the tier work integer's `BITS`
/// (`C::W` — the deepest width the widening walker reaches). A no-op for nearest
/// modes, `decided == true`, `raw == 0`, `SCALE == 0`, `|x| ≥ 1`, `j*` outside
/// `[5, JMAX]`, or `j*·k ≤ reach`.
#[inline]
pub(crate) fn tiny_x_deep_directed_adjust<St: BigInt, const SCALE: u32>(
    r: St,
    decided: bool,
    raw: St,
    mode: RoundingMode,
    alternating: bool,
    work_bits: u32,
) -> St {
    if decided || crate::support::rounding::is_nearest_mode(mode) || SCALE == 0 {
        return r;
    }
    let zero = <St as BigInt>::ZERO;
    if raw == zero {
        return r;
    }
    let absr = if raw < zero { zero - raw } else { raw };
    // Leading-digit position `k`: `|x| = |raw|·10^(−SCALE)` and `|x| ≈ 10^(−k)`,
    // so `k = SCALE − digits(|raw|) + 1`. `|x| ≥ 1` (digits > SCALE) is not tiny.
    let digits = dec_digits_g::<St>(absr);
    if digits == 0 || digits > SCALE {
        return r;
    }
    let k = SCALE - digits + 1;
    if k == 0 {
        return r;
    }
    // `j*` = smallest ODD `j` with `j·k > SCALE`. `floor(SCALE/k)+1` is the
    // smallest integer with the property (`(⌊SCALE/k⌋+1)·k = ⌊SCALE/k⌋·k + k >
    // SCALE` since `k > SCALE mod k`); round up to the next odd.
    let j_min = SCALE / k + 1;
    let j_star = if j_min % 2 == 1 { j_min } else { j_min + 1 };
    // `j* = 3` is the linear band's [`tiny_x_linear_directed`] pre-empt; only the
    // deeper terms reach here. The upper bound excludes the non-tiny corner.
    if !(5..=TINY_X_DEEP_JMAX).contains(&j_star) {
        return r;
    }
    // The deciding term must be BEYOND the walker's reach (else it RESOLVED `r`
    // correctly — see the doc). `j*·k` is its fractional depth.
    let reach = (work_bits / 8).saturating_sub(8);
    if j_star.saturating_mul(k) <= reach {
        return r;
    }
    let expanding = if alternating { j_star % 4 == 1 } else { true };
    let one = <St as BigInt>::ONE;
    if expanding {
        crate::support::rounding::tiny_odd_expanding_directed(r, zero, one, mode)
    } else {
        crate::support::rounding::tiny_odd_compressing_directed(r, zero, one, mode)
    }
}

/// Directed-rounding post-adjust for `ln` very near `x = 1`.
///
/// Concavity gives `ln(x) < x − 1` STRICTLY for every `x ≠ 1`, and `ln(x)`
/// is transcendental for algebraic `x ≠ 1`, so it never lands exactly on a
/// storage grid line. For `x` within the input granularity of 1 the deficit
/// `(x − 1) − ln(x) ≈ (x − 1)²/2` can sit far below any REACHABLE working
/// scale (e.g. `x = 1 + 10⁻ˢ` leaves the deficit ~`10⁻²ˢ`), so the kernel
/// rounds to exactly the linear term `δ = raw − 10^SCALE` and a downward
/// mode then keeps `δ` though the true value is strictly below it. Because
/// `ln(x) < x − 1`, a CORRECT downward result can never equal `δ`, so
/// `result == δ` is unambiguously the sub-resolution overshoot — step down
/// one LSB. `ln(1) = 0` is exact (`raw == one`) and excluded; nearest modes
/// (frac ≈ 1⁻, rounds to `δ`) and `Ceiling` (`δ` IS the correct ceiling)
/// are already right. `Floor` steps down for both signs; `Trunc` (toward
/// zero) steps down only for `x > 1` (positive value). A no-op unless the
/// result is exactly `δ`, so reachable cells pass untouched. Mirrors
/// [`adjust_bounded_extremum`] / [`adjust_cosh_near_min`].
#[inline]
pub(crate) fn adjust_ln_near_one<C: WideTrigCore, const SCALE: u32>(
    result: C::Storage,
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage {
    if crate::support::rounding::is_nearest_mode(mode) {
        return result;
    }
    let one = C::storage_one(SCALE);
    if raw == one {
        return result; // ln(1) = 0 is exact
    }
    let delta = raw - one; // (x − 1) at storage scale (signed)
    if result != delta {
        return result; // only the sub-resolution linear-term overshoot
    }
    match mode {
        RoundingMode::Floor => result - <C::Storage as BigInt>::ONE,
        RoundingMode::Trunc if raw > one => result - <C::Storage as BigInt>::ONE,
        _ => result,
    }
}

/// `tan_strict` for a wide tier — generic over the tier `C`. Panics at
/// odd multiples of π/2 where the cosine is zero. Ports the near-pole
/// recompute (`near_pole_tan::tan_extra_digits`, width-free). Replaces
/// the per-tier `tan_strict_<tier>` wrappers.
#[inline]
#[must_use]
pub(crate) fn tan_series<C: WideTrigCore, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    if raw == C::storage_zero() {
        return C::storage_zero(); // tan(0) = 0, the sole exact point
    }
    // Analytic tiny-`x` directed decision (relocated from the policy layer) —
    // `tan(x) = x + x³/3 + …` EXPANDS (every Taylor coefficient is positive).
    if let Some(v) = tiny_x_linear_directed::<C::Storage, SCALE>(raw, mode, true) {
        return v;
    }
    let w0 = SCALE + C::GUARD;
    let (sin0, cos0) = C::sin_cos_fixed::<SCALE>(C::to_work(raw), w0);
    if cos0 == C::zero() {
        panic!("wide-tier tan: cosine is zero (argument is an odd multiple of pi/2)");
    }
    let probe = C::div(sin0, cos0, w0);
    let extra = crate::algos::trig::near_pole_tan::tan_extra_digits(C::bit_length(probe), w0)
        .saturating_sub(C::GUARD);
    if extra == 0 {
        // Near-tie escape: a fixed-w single shot cannot see a deciding
        // digit below w (`tan(x) = x + x^3/3 + ...` lands an exact
        // rational partial on a boundary with the deciding tail deeper -
        // the asin(3e-60) family). Clear-of-band residuals keep the
        // single-shot cost; the band escalates through the walker.
        if let Some(st) = round_to_storage_clear_of_tie_g::<C::Storage, C::W>(
            probe, w0, SCALE, mode, C::storage_max(), C::storage_min(),
        ) {
            return st;
        }
        return tan_walker::<C, SCALE>(raw, C::GUARD, mode);
    }
    let w = w0 + extra;
    let (sin_w, cos_w) = C::sin_cos_fixed::<SCALE>(C::to_work_scaled(raw, C::GUARD + extra), w);
    let r = C::div(sin_w, cos_w, w);
    if let Some(st) = round_to_storage_clear_of_tie_g::<C::Storage, C::W>(
        r, w, SCALE, mode, C::storage_max(), C::storage_min(),
    ) {
        return st;
    }
    tan_walker::<C, SCALE>(raw, C::GUARD + extra, mode)
}

/// The tier-width Ziv walker for `tan` near a rounding boundary: the
/// ratio recomputed per probe at `w = SCALE + guard`, escalating from
/// the (near-pole-lifted) `base_guard`. Reached only from the near-tie
/// band of the single-shot terminals above / in the rung kernel.
fn tan_walker<C: WideTrigCore, const SCALE: u32>(
    raw: C::Storage,
    base_guard: u32,
    mode: RoundingMode,
) -> C::Storage
where
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    let (r, decided) = round_to_storage_directed_decided_g::<C::Storage, C::W>(
        base_guard,
        SCALE,
        mode,
        C::storage_max(),
        C::storage_min(),
        |guard| {
            let w = SCALE + guard;
            let (s, c) = C::sin_cos_fixed::<SCALE>(C::to_work_scaled(raw, guard), w);
            if c == C::zero() {
                panic!("wide-tier tan: cosine is zero (argument is an odd multiple of pi/2)");
            }
            C::div(s, c, w)
        },
    );
    // Deep sub-resolution tiny-`x` band (`j* ≥ 5`): `tan` always EXPANDS.
    // A near-pole tie (`|x| ≈ π/2`, not tiny) has `j*` far above `JMAX`, so
    // the adjust is a no-op there.
    tiny_x_deep_directed_adjust::<C::Storage, SCALE>(r, decided, raw, mode, false, <C::W as BigInt>::BITS)
}

/// `atan_strict` for a wide tier — generic over the tier `C`. Result in
/// `(−π/2, π/2)`. Replaces the per-tier `atan_strict_<tier>` wrappers.
#[inline]
#[must_use]
pub(crate) fn atan_series<C: WideTrigCore, const SCALE: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    // Analytic tiny-`x` directed decision (relocated from the policy layer) —
    // `atan` alternates like `sin` (`atan(x) = x − x³/3 + x⁵/5 − …`).
    if let Some(v) = tiny_x_linear_directed::<C::Storage, SCALE>(raw, mode, false) {
        return v;
    }
    let (r, decided) = round_to_storage_directed_decided_g::<C::Storage, C::W>(
        C::GUARD,
        SCALE,
        mode,
        C::storage_max(),
        C::storage_min(),
        |guard| C::atan_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard),
    );
    tiny_x_deep_directed_adjust::<C::Storage, SCALE>(r, decided, raw, mode, true, <C::W as BigInt>::BITS)
}

/// Narrow-`GUARD` single-shot `atan_strict` for a wide tier — generic
/// over the tier `C`, the decimal `SCALE`, and the band's narrow guard
/// `GUARD`. Routes the canonical [`WideTrigCore::atan_fixed`] kernel
/// through `w = SCALE + GUARD` and narrows once with
/// [`WideTrigCore::round_to_storage_with`] (no Ziv escalation — the band
/// guards leave the working error many orders of magnitude below half a
/// storage ULP). Replaces the per-tier atan narrow wrappers.
#[inline]
#[must_use]
pub(crate) fn atan_narrow<C: WideTrigCore, const SCALE: u32, const GUARD: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage {
    // Ziv-escalated narrowing from the band guard (NOT a single shot):
    // `atan(x) = x - x^3/3 + ...` lands an exact rational partial on a
    // rounding boundary with the deciding tail below the band's fixed
    // working scale (the asin(3e-60) family). The walker's base probe is
    // the same single evaluation; clear-of-band inputs exit there.
    C::round_to_storage_directed(GUARD, SCALE, mode, &mut |guard| {
        C::atan_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard)
    })
}

/// Rung-generic `sin_strict` — the forward-trig Series kernel run at an
/// arbitrary work rung `Wk` (decoupled from `C::W`), so the policy can
/// run it at the minimal valid work width for low-scale cells (mirrors
/// [`ln_series_g`]; the tier-width [`sin_series`] keeps the trait-bound
/// realisation, value-identical — the integer ops are width-agnostic, so
/// the only divergence surface is the Ziv cap `Wk::BITS/8`, budgeted by
/// `policy::work_rung::trig_rung`). `GUARD` is the base guard: the tier
/// `GUARD` (30) on the Series cells, the band guard (8/10) on the
/// narrow-GUARD band cells — one kernel serves both shapes (the explicit
/// `raw == 0` pin is value-identical to the unpinned tier path: the
/// kernel computes the exact grid value either way).
///
/// `π` at the rung comes from the same per-scale constant table as the
/// per-tier `pi_cf` (`pi_by_scale` keyed on the const `SCALE + GUARD` on
/// the hot path — value-identical to `pi_by_working_scale` at the same
/// scale, only the const-fold seam differs).
#[cfg(feature = "_wide-support")]
#[inline]
#[must_use]
pub(crate) fn sin_series_g<C: WideTrigCore, Wk: BigInt, const SCALE: u32, const GUARD: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    Wk::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    if raw == C::storage_zero() {
        return C::storage_zero();
    }
    // Analytic tiny-`x` directed decision — the SAME pre-empt the tier
    // [`sin_series`] carries (relocated from the policy layer), so this
    // rung-dispatched path and the bare tier kernel agree.
    if let Some(v) = tiny_x_linear_directed::<C::Storage, SCALE>(raw, mode, false) {
        return v;
    }
    // Two-width fall-up: an unresolved-at-rung-cap near-tie reruns the
    // walker at the tier work width `C::W` (the recompute closure is the
    // tier kernel's, verbatim), so the conclusion is never weaker than
    // the tier path's — see `round_to_storage_directed_widening_g`.
    let (r, decided) = round_to_storage_directed_widening_decided_g::<C::Storage, Wk, C::W>(
        GUARD,
        SCALE,
        mode,
        C::storage_max(),
        C::storage_min(),
        |guard| {
            let w = SCALE + guard;
            crate::algos::trig::trig_generic::sin_fixed::<Wk>(
                to_work_scaled_g::<C::Storage, Wk>(raw, guard),
                w,
                pi_at_rung::<Wk>(w, SCALE + GUARD),
            )
        },
        |guard| C::sin_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard),
    );
    let r = tiny_x_deep_directed_adjust::<C::Storage, SCALE>(r, decided, raw, mode, true, <C::W as BigInt>::BITS);
    adjust_bounded_extremum::<C, SCALE>(r, raw, mode)
}

/// Rung-generic `cos_strict` — see [`sin_series_g`]. Standalone
/// `cos_fixed` path (cofunction identity, one `sin_fixed`, no sqrt).
#[cfg(feature = "_wide-support")]
#[inline]
#[must_use]
pub(crate) fn cos_series_g<C: WideTrigCore, Wk: BigInt, const SCALE: u32, const GUARD: u32>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    Wk::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    if raw == C::storage_zero() {
        return C::storage_one(SCALE);
    }
    // Two-width fall-up — see [`sin_series_g`].
    let r = round_to_storage_directed_widening_g::<C::Storage, Wk, C::W>(
        GUARD,
        SCALE,
        mode,
        C::storage_max(),
        C::storage_min(),
        |guard| {
            let w = SCALE + guard;
            crate::algos::trig::trig_generic::cos_fixed::<Wk>(
                to_work_scaled_g::<C::Storage, Wk>(raw, guard),
                w,
                pi_at_rung::<Wk>(w, SCALE + GUARD),
            )
        },
        |guard| C::cos_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard),
    );
    adjust_bounded_extremum::<C, SCALE>(r, raw, mode)
}

/// Rung-generic `tan_strict` — see [`sin_series_g`]. One kernel covers
/// the two existing tan shapes, preserved bit-for-bit per call site:
///
/// - `NEAR_POLE = true, SUB_GUARD = true` — the tier-`GUARD` Series
///   shape ([`tan_series`]): the base probe sizes a per-call lift
///   (`near_pole_tan::tan_extra_digits`) MINUS the guard already paid.
/// - `NEAR_POLE = true, SUB_GUARD = false` — the narrow-band shape
///   (`sincos_narrow::tan_narrow_with_taylor` with its probe): the full
///   per-call lift on top of the band guard.
/// - `NEAR_POLE = false` — the band shape without the probe (the band
///   guard already covers the worst case): one divide + one narrowing.
///
/// The rare near-pole recompute (`extra > 0`) runs at the TIER work
/// width `C::W` — capacity for the unbounded per-call lift is exactly
/// what the tier `$Work` is sized for, and the probe value (hence
/// `extra`) is bit-identical at the rung, so the recompute reproduces
/// the tier path exactly.
#[cfg(feature = "_wide-support")]
#[inline]
#[must_use]
pub(crate) fn tan_series_g<
    C: WideTrigCore,
    Wk: BigInt,
    const SCALE: u32,
    const GUARD: u32,
    const NEAR_POLE: bool,
    const SUB_GUARD: bool,
>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    Wk::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    use crate::algos::exp::exp_generic as eg;

    if raw == C::storage_zero() {
        return C::storage_zero();
    }
    // Analytic tiny-`x` directed decision — the SAME pre-empt the tier
    // [`tan_series`] carries (relocated from the policy layer).
    if let Some(v) = tiny_x_linear_directed::<C::Storage, SCALE>(raw, mode, true) {
        return v;
    }
    let w0 = SCALE + GUARD;
    let (sin0, cos0) = crate::algos::trig::trig_generic::sin_cos_fixed::<Wk>(
        to_work_scaled_g::<C::Storage, Wk>(raw, GUARD),
        w0,
        pi_at_rung::<Wk>(w0, w0),
    );
    if cos0 == eg::zero::<Wk>() {
        panic!("wide-tier tan: cosine is zero (argument is an odd multiple of pi/2)");
    }
    let probe = eg::div::<Wk>(sin0, cos0, w0);
    if !NEAR_POLE {
        // Near-tie escape — see [`tan_series`]: clear-of-band residuals
        // keep the single-shot cost; the band escalates (rung first,
        // tier fall-up).
        if let Some(st) = round_to_storage_clear_of_tie_g::<C::Storage, Wk>(
            probe, w0, SCALE, mode, C::storage_max(), C::storage_min(),
        ) {
            return st;
        }
        return tan_walker_rung_g::<C, Wk, SCALE>(raw, GUARD, mode);
    }
    let extra_raw =
        crate::algos::trig::near_pole_tan::tan_extra_digits(eg::bit_length::<Wk>(probe), w0);
    let extra = if SUB_GUARD { extra_raw.saturating_sub(GUARD) } else { extra_raw };
    if extra == 0 {
        if let Some(st) = round_to_storage_clear_of_tie_g::<C::Storage, Wk>(
            probe, w0, SCALE, mode, C::storage_max(), C::storage_min(),
        ) {
            return st;
        }
        return tan_walker_rung_g::<C, Wk, SCALE>(raw, GUARD, mode);
    }
    // Near-pole recompute at the tier work width (the `w` here is off the
    // hot `SCALE + GUARD` path, so π comes from the runtime-keyed table —
    // exactly the per-tier `pi_cf` fallback the tier path takes).
    let w = w0 + extra;
    let (sin_w, cos_w) = crate::algos::trig::trig_generic::sin_cos_fixed::<C::W>(
        to_work_scaled_g::<C::Storage, C::W>(raw, GUARD + extra),
        w,
        crate::consts::pi_by_working_scale::<C::W>(
            w,
            crate::support::rounding::DEFAULT_ROUNDING_MODE,
        ),
    );
    let r = eg::div::<C::W>(sin_w, cos_w, w);
    if let Some(st) = round_to_storage_clear_of_tie_g::<C::Storage, C::W>(
        r, w, SCALE, mode, C::storage_max(), C::storage_min(),
    ) {
        return st;
    }
    tan_walker::<C, SCALE>(raw, GUARD + extra, mode)
}

/// Two-width near-tie walker for the rung `tan` shapes: the ratio
/// recomputed per probe at the rung `Wk` (π from the same per-scale
/// table), an unresolved-at-rung-cap walk falling up to the tier-width
/// [`tan_walker`] closure. Reached only from the near-tie band.
#[cfg(feature = "_wide-support")]
fn tan_walker_rung_g<C: WideTrigCore, Wk: BigInt, const SCALE: u32>(
    raw: C::Storage,
    base_guard: u32,
    mode: RoundingMode,
) -> C::Storage
where
    Wk::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    use crate::algos::exp::exp_generic as eg;
    let base_w = SCALE + base_guard;
    let (r, decided) = round_to_storage_directed_widening_decided_g::<C::Storage, Wk, C::W>(
        base_guard,
        SCALE,
        mode,
        C::storage_max(),
        C::storage_min(),
        |guard| {
            let w = SCALE + guard;
            let (s, c) = crate::algos::trig::trig_generic::sin_cos_fixed::<Wk>(
                to_work_scaled_g::<C::Storage, Wk>(raw, guard),
                w,
                pi_at_rung::<Wk>(w, base_w),
            );
            if c == eg::zero::<Wk>() {
                panic!("wide-tier tan: cosine is zero (argument is an odd multiple of pi/2)");
            }
            eg::div::<Wk>(s, c, w)
        },
        |guard| {
            let w = SCALE + guard;
            let (s, c) = C::sin_cos_fixed::<SCALE>(C::to_work_scaled(raw, guard), w);
            if c == C::zero() {
                panic!("wide-tier tan: cosine is zero (argument is an odd multiple of pi/2)");
            }
            C::div(s, c, w)
        },
    );
    // Deep sub-resolution tiny-`x` band (`j* ≥ 5`): `tan` always EXPANDS.
    tiny_x_deep_directed_adjust::<C::Storage, SCALE>(r, decided, raw, mode, false, <C::W as BigInt>::BITS)
}

/// Rung-generic `atan_strict` — the inverse-tangent kernel run at an
/// arbitrary work rung `Wk` (decoupled from `C::W`; mirrors
/// [`sin_series_g`]). One kernel covers the two existing tier shapes,
/// preserved value-for-value per call site:
///
/// - `DIRECTED = true` — the tier-`GUARD` Ziv shape ([`atan_series`]):
///   directed narrowing with escalation at the rung.
/// - `DIRECTED = false` — the narrow-band single-shot shape
///   ([`atan_narrow`], band `GUARD` 10/12): one kernel evaluation at
///   `w = SCALE + GUARD`, one narrowing, no escalation (the band guard
///   leaves the working error far below half a storage ULP).
///
/// `π` at the rung comes from the same per-scale constant table as the
/// per-tier `pi_cf` (`pi_by_scale` keyed on the const `SCALE + GUARD` on
/// the hot path) — and only its `π/2` half is consumed, by the `|x| > 1`
/// reciprocal-fold complement. Unlike sin/cos there is NO precision loss
/// proportional to `digits(|x|)` (no mod-τ cancellation); the `|x|` axis
/// is purely the lift's representation capacity, gated by the policy
/// (`forward_rung::atan_strict`).
#[cfg(feature = "_wide-support")]
#[inline]
#[must_use]
pub(crate) fn atan_series_g<
    C: WideTrigCore,
    Wk: BigInt,
    const SCALE: u32,
    const GUARD: u32,
    const DIRECTED: bool,
>(
    raw: C::Storage,
    mode: RoundingMode,
) -> C::Storage
where
    Wk::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    <C::W as BigInt>::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    // Analytic tiny-`x` directed decision — the SAME pre-empt the tier
    // [`atan_series`] carries (relocated from the policy layer).
    if let Some(v) = tiny_x_linear_directed::<C::Storage, SCALE>(raw, mode, false) {
        return v;
    }
    let (r, decided) = if DIRECTED {
        // Two-width fall-up — see [`sin_series_g`].
        round_to_storage_directed_widening_decided_g::<C::Storage, Wk, C::W>(
            GUARD,
            SCALE,
            mode,
            C::storage_max(),
            C::storage_min(),
            |guard| {
                let w = SCALE + guard;
                crate::algos::trig::trig_generic::atan_fixed::<Wk>(
                    to_work_scaled_g::<C::Storage, Wk>(raw, guard),
                    w,
                    pi_at_rung::<Wk>(w, SCALE + GUARD),
                )
            },
            |guard| C::atan_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard),
        )
    } else {
        // Band shape: same Ziv-escalated two-width walker, from the band
        // guard (the single-shot it replaces could not see a deciding
        // digit below the band's fixed working scale — see
        // [`atan_narrow`]). `DIRECTED` still selects the policy-side
        // out-of-budget fallback kernel; the narrowing machinery is one.
        let base_w = SCALE + GUARD;
        round_to_storage_directed_widening_decided_g::<C::Storage, Wk, C::W>(
            GUARD,
            SCALE,
            mode,
            C::storage_max(),
            C::storage_min(),
            |guard| {
                let w = SCALE + guard;
                crate::algos::trig::trig_generic::atan_fixed::<Wk>(
                    to_work_scaled_g::<C::Storage, Wk>(raw, guard),
                    w,
                    pi_at_rung::<Wk>(w, base_w),
                )
            },
            |guard| C::atan_fixed::<SCALE>(C::to_work_scaled(raw, guard), SCALE + guard),
        )
    };
    // Deep sub-resolution band (`j* ≥ 5`): `atan` alternates like `sin`.
    tiny_x_deep_directed_adjust::<C::Storage, SCALE>(r, decided, raw, mode, true, <C::W as BigInt>::BITS)
}

/// `π` at working scale `w` in the rung integer `Wk`: the per-scale
/// constant table keyed on the CONST base working scale on the hot path
/// (`w == base_w`, const-folds per monomorphisation — the rung sibling
/// of the per-tier `pi_cf`), the runtime-keyed lookup on the Ziv
/// escalation path. Value-identical either way (same table entry).
#[cfg(feature = "_wide-support")]
#[inline]
pub(crate) fn pi_at_rung<Wk: BigInt>(w: u32, base_w: u32) -> Wk {
    if w == base_w {
        crate::consts::pi_by_scale::<Wk>(base_w, crate::support::rounding::DEFAULT_ROUNDING_MODE)
    } else {
        crate::consts::pi_by_working_scale::<Wk>(
            w,
            crate::support::rounding::DEFAULT_ROUNDING_MODE,
        )
    }
}

// ─── Work-int-generic narrowing / lift free fns (the SCALE-derived work-rung
//     surface) ─────────────────────────────────────────────────────────────
//
// Hoisted out of the per-tier `decl_wide_transcendental!` macro so a
// tier-generic kernel (e.g. `ln_tang_g<C, Wk>`) can lift/narrow at an
// arbitrary work rung `Wk` WITHOUT a per-tier module path and WITHOUT a new
// trait method (free-fn hoist, no trait-surface growth).
// `St` (storage) appears only as the input/output type + the range-check
// bounds; `St` has no trait-level `MAX`/`MIN`, so the caller supplies them
// (`st_max`/`st_min`). The per-tier macro forwards pass `<$Storage>::MAX/MIN`
// (bit-identical to the prior inline bodies); a tier-generic caller passes
// `C::storage_max()/storage_min()`. The `÷10^shift` divides are already
// width-generic (`div_wide_pow10::<S>` / `dispatch_wide_pow10::<S>`).

/// Work-int-generic lift-up: widen storage `St` into the work integer `S` and
/// scale by `10^working_digits`. Storage-generic sibling of the per-tier
/// `to_work_scaled`; sources `10^d` from the width-generic `exp_generic::pow10`.
#[inline]
pub(crate) fn to_work_scaled_g<St: BigInt, S: BigInt>(raw: St, working_digits: u32) -> S
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    // `10^d` first: the truncated-low schoolbook (`mul_low_fixed`) skips the
    // zero limbs of its FIRST operand, and `10^d` is the sparse one (a guard
    // of <= 38 digits spans 1-2 limbs while the lifted value spans the whole
    // storage width), so the lift costs one inner row per `10^d` limb instead
    // of one per value limb. The wrapping low product is commutative —
    // bit-identical to the previous `resize * pow10` order.
    crate::algos::exp::exp_generic::pow10::<S>(working_digits) * BigInt::resize_to::<S>(raw)
}

/// Narrow a working-scale `signed` value (in the work int `S`) to storage
/// `St`, panicking when it exceeds the storage range. When `S` is NARROWER
/// than `St` (the work-rung case — a rung below the storage width admitted
/// by the trig magnitude gate) every `S`-representable value fits the wider
/// storage, so the bounds check is vacuously true and skipped — `st_max` /
/// `st_min` cannot even be represented in `S` (a down-resize would truncate
/// their magnitude into garbage bounds). The `LIMBS` compare const-folds per
/// monomorphisation.
#[inline]
fn narrow_range_checked_g<St: BigInt + Copy, S: BigInt>(signed: S, st_max: St, st_min: St) -> St
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    if <S as BigInt>::LIMBS >= <St as BigInt>::LIMBS {
        let max_w = BigInt::resize_to::<S>(st_max);
        let min_w = BigInt::resize_to::<S>(st_min);
        if signed > max_w || signed < min_w {
            panic!("wide-tier strict transcendental: result out of range");
        }
    }
    // Down-resize through `S`'s EXACT scratch (`unpack_mag` +
    // `from_mag_sign_u64`), not the width-erased `resize_to` blanket: the
    // narrow default build sizes that blanket's `MAX_U128_LIMB` buffer to
    // its 2-limb storage, below the `Int<24>` work integer the narrow
    // near-tie walkers run in. The up-resizes above are from the SMALLER
    // `St` (its own width bounds the blanket buffer), so they stay.
    let neg = signed < <S as BigInt>::ZERO;
    let mag = if neg { -signed } else { signed };
    let mut buf =
        <S::Scratch as crate::int::types::compute_limbs::ComputeLimbs>::single_u64();
    crate::algos::exp::exp_generic::unpack_mag(mag, buf.as_mut());
    St::from_mag_sign_u64(buf.as_ref(), neg)
}

/// Work-int-generic narrowing of a working-scale value `v` (at scale `w`) down
/// to storage scale `target`, rounded under `mode`, into storage `St`.
/// `st_max`/`st_min` are `St::MAX`/`MIN`, caller-supplied.
#[inline]
pub(crate) fn round_to_storage_with_g<St: BigInt + Copy, S: BigInt>(
    v: S,
    w: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
) -> St
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    let shift = w - target;
    let rounded = if shift == 0 {
        v
    } else if shift <= 38 {
        crate::algos::support::mg_divide::div_wide_pow10::<S>(v, shift, mode)
    } else {
        crate::algos::support::rescale::dispatch_wide_pow10::<S>(v, shift, mode)
    };
    narrow_range_checked_g::<St, S>(rounded, st_max, st_min)
}

/// Absolute floor (`10^4` work-integer units) separating a genuine deciding-
/// digit SIGNAL from the kernel's own working-scale rounding NOISE. The strict
/// kernels compute to a few-ULP working accuracy (≈10²–10³ work units of
/// error); a residual-to-boundary distance above this is a real deciding digit,
/// below it is noise. Once a deciding term is representable its signal grows
/// 10× per extra working digit, so it clears the floor within a handful of
/// digits. Using an ABSOLUTE floor (not a relative `divisor/1000`, which scales
/// with the working scale and so never fires for a near-min input) is what lets
/// the loop tell "resolved" from "spinning on kernel noise" — and so return the
/// clean exact-tie base narrowing instead of a noise-driven deep misround.
const ZIV_RESOLVE_FLOOR_POW10: u32 = 4;

/// How deep the Ziv escalations may PROBE, in working-scale digits. A
/// near-tie whose deciding term lies beyond this is unverifiable (the widest
/// shipped tier, D1232 / `Int<64>` storage, carries ~1232 significant digits,
/// and the golden data is generated to match), so the escalation stops and
/// falls to its unresolved endgame — the near-min resolver then applies the
/// never-exact sub-resolution rule (a strictly positive tail under the
/// computed digits) instead of trusting a kernel-noise-driven deep narrowing.
const ZIV_PRECISION_HORIZON: u32 = 1264;

/// Exact decimal digit count of a non-negative work value (`v > 0`).
/// Bit-length estimate (`digits <= floor(bl·log10 2) + 1`, at most one high),
/// refined by a single `pow10` compare. Cold-path helper for the positional
/// cross-depth confirmation below.
fn dec_digits_g<S: BigInt>(v: S) -> u32 {
    let bl = <S as BigInt>::BITS - v.leading_zeros();
    let mut d = ((bl as u64 * 30_103) / 100_000) as u32 + 1;
    if d > 1 && v < crate::consts::pow10::dispatch::<S>(d - 1) {
        d -= 1;
    }
    d
}

/// Single-width near-min escalation for `cosh` / `exp`, returning
/// `(value, resolved)`. A near-tie's deciding term (`cosh`'s `x⁴/24`,
/// `exp`'s `x³/6`) is trusted only once it clears the absolute kernel-noise
/// floor AND a probe at a DIFFERENT depth reproduces its position and side —
/// the kernels' working-scale error can far exceed the floor (measured
/// ~10^12 units at some depths), but noise always sits in the bottom digits
/// of whatever `w` produced it, while a genuine deciding term keeps a
/// depth-independent fractional position. `resolved == false` means the cap
/// (the work integer's capacity, never past [`ZIV_PRECISION_HORIZON`]) was
/// reached without a confirmed deciding term: the value is then the BASE
/// probe SNAPPED to its nearest grid line (absorbing the kernel's sub-floor
/// noise) with the `never_exact` sub-resolution rule applied on top — the
/// true value carries a strictly positive tail below the computed digits, so
/// Ceiling (positive result) / Floor (negative) nudge one ULP off the grid
/// line and an unresolved half-ULP boundary rounds as ABOVE half for the
/// nearest modes. A widening caller may still retry at a wider integer.
/// `recompute` is a `&mut dyn FnMut` trait object, NOT an `impl FnMut`
/// generic: the walker body is large and every distinct closure type would
/// mint a full copy of it per call site (the dominant IR-volume entry at
/// the wide gate builds), while a trait object keeps ONE instantiation per
/// `(St, S)` pair. The dyn indirection is perf-acceptable — each
/// `recompute` call evaluates a whole transcendental kernel at the probed
/// guard, and the walker itself sits on the rare Ziv escalation path (the
/// hot path narrows single-shot and never enters it) — and it matches the
/// `WideTrigCore` trait surface, which already passes `&mut dyn FnMut`.
#[allow(clippy::too_many_arguments)]
fn near_min_resolve_g<St: BigInt + Copy, S: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    never_exact: bool,
    st_max: St,
    st_min: St,
    recompute: &mut dyn FnMut(u32) -> S,
) -> (St, bool)
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    use crate::support::rounding::{is_nearest_mode, should_bump, RoundingMode};
    let lit = |n: i128| <S as BigInt>::from_i128(n);
    let pow10 = |n: u32| crate::consts::pow10::dispatch::<S>(n);
    let bit_length = |v: S| -> u32 {
        let m = if v < <S as BigInt>::ZERO { -v } else { v };
        <S as BigInt>::BITS - m.leading_zeros()
    };
    let floor = pow10(ZIV_RESOLVE_FLOOR_POW10);
    // The kernels' error is value-RELATIVE (~an ULP of the value at the
    // working scale), so a result carrying `int_digits` integer digits has a
    // noise floor of ~10^int_digits WORKING UNITS regardless of `w`: a
    // fractional digit at depth `p` only clears that noise once
    // `w > p + int_digits`. The probe horizon therefore extends by
    // `int_digits` (the width cap already subtracts them, protecting the
    // kernel's internal headroom).
    let max_guard_for = |int_digits: u32| -> u32 {
        let cap = (<S>::BITS / 8).saturating_sub(int_digits + 8);
        cap.saturating_sub(target)
            .min((ZIV_PRECISION_HORIZON + int_digits).saturating_sub(target))
            .max(base_guard)
    };
    let int_digits_of = |v: St| -> u32 {
        let n = BigInt::resize_to::<S>(v);
        let m = if n < lit(0) { -n } else { n };
        ((bit_length(m) as u64 * 30103 / 100_000) as u32 + 1).saturating_sub(target)
    };
    let range_check = |signed: S| -> St { narrow_range_checked_g::<St, S>(signed, st_max, st_min) };
    let finish = |neg: bool, q: S, bump: bool| -> St {
        let q_mag = if bump { q + lit(1) } else { q };
        range_check(if neg { -q_mag } else { q_mag })
    };
    // Leading fractional-digit position of the deciding residual `dist`
    // (working units at scale `target + g`) — the cross-depth confirmation
    // key: a genuine deciding term keeps this position across depths.
    let pos_of = |dist: S, g: u32| -> u32 { target + g - dec_digits_g::<S>(dist) + 1 };
    // One working-scale probe: `(neg, q, rem, divisor)` of the recomputed
    // value at guard `g`, magnitude split at the storage grid.
    let mut probe = |g: u32| -> (bool, S, S, S) {
        let v = recompute(g);
        let neg = v < lit(0);
        let mag = if neg { -v } else { v };
        let divisor = pow10(g);
        // Exact per-width Knuth scratch (the narrow build's blanket is sized
        // to its 2-limb storage; the walkers probe in `Int<24>`).
        let (q, rem) = crate::algos::exp::exp_generic::div_rem_exact(mag, divisor);
        (neg, q, rem, divisor)
    };

    if is_nearest_mode(mode) {
        // Nearest rounding of a probe, by the true `rem` vs `half` ordering.
        let round_half = |neg: bool, q: S, rem: S, divisor: S| -> St {
            let half = divisor / lit(2);
            let cmp_r = if rem < half {
                ::core::cmp::Ordering::Less
            } else if rem == half {
                ::core::cmp::Ordering::Equal
            } else {
                ::core::cmp::Ordering::Greater
            };
            finish(neg, q, should_bump(mode, cmp_r, q.bit(0), !neg))
        };
        let (neg0, q0, rem0, div0) = probe(base_guard);
        let half0 = div0 / lit(2);
        let dist0 = if rem0 < half0 { half0 - rem0 } else { rem0 - half0 };
        if dist0 > pow10(base_guard) / lit(1000) {
            return (round_half(neg0, q0, rem0, div0), true); // not near a half-ULP tie
        }
        let lo = round_half(neg0, q0, rem0, div0);
        let max_guard = max_guard_for(int_digits_of(lo));
        // Cross-depth confirmation: the kernels' working-scale error can reach
        // well past the absolute noise floor (measured ~10^12 units at some
        // depths), but noise always sits in the BOTTOM digits of whatever `w`
        // produced it, while a genuine deciding term keeps a depth-independent
        // fractional position. A probe's signal `(position, side)` is therefore
        // trusted only once a probe at a DIFFERENT depth reproduces it.
        let mut pending: Option<(u32, bool)> = if dist0 > floor {
            Some((pos_of(dist0, base_guard), rem0 > half0))
        } else {
            None
        };
        let mut guard = base_guard;
        loop {
            if guard >= max_guard {
                // Cap reached without a confirmed deciding term. An unconfirmed
                // signal from the deepest probe gets ONE shifted confirm probe
                // (real positions reproduce; noise tracks the bottom of `w`).
                if let Some((pp, ps)) = pending {
                    let back = ZIV_RESOLVE_FLOOR_POW10 + 3;
                    if max_guard > base_guard + back {
                        let g_c = max_guard - back;
                        let (neg, q, rem, div) = probe(g_c);
                        let half = div / lit(2);
                        let dist = if rem < half { half - rem } else { rem - half };
                        if dist > floor {
                            let p = pos_of(dist, g_c);
                            if (rem > half) == ps && p.abs_diff(pp) <= 1 {
                                return (round_half(neg, q, rem, div), true);
                            }
                        }
                    }
                }
                // Still unresolved: the deciding term sits below every probed
                // depth. With the never-exact rule the half boundary carries a
                // strictly positive sub-resolution tail — the residual is
                // ABOVE half, so every nearest mode rounds away from the kept
                // value; otherwise keep the clean base narrowing. Either way
                // the widening caller may retry at a wider integer.
                if never_exact {
                    return (finish(neg0, q0, true), false);
                }
                return (lo, false);
            }
            let step = (target + base_guard).max(base_guard);
            let next_guard = guard.saturating_add(step).min(max_guard);
            let (neg, q, rem, div) = probe(next_guard);
            let half = div / lit(2);
            let hi_dist = if rem < half { half - rem } else { rem - half };
            if hi_dist > floor {
                let p = pos_of(hi_dist, next_guard);
                let above = rem > half;
                if let Some((pp, ps)) = pending {
                    if above == ps && p.abs_diff(pp) <= 1 {
                        // Confirmed deciding digit — trustworthy.
                        return (round_half(neg, q, rem, div), true);
                    }
                }
                pending = Some((p, above));
            }
            guard = next_guard;
        }
    }

    // directed
    // Directed semantics: any nonzero residual (or the `never_exact`
    // sub-resolution rule) nudges Ceiling/Floor by the result's sign.
    let dir_round = |neg: bool, q: S, rem: S| -> St {
        let result_positive = !neg;
        let residual_present = rem != lit(0) || never_exact;
        let bump = residual_present
            && match mode {
                RoundingMode::Trunc => false,
                RoundingMode::Floor => !result_positive,
                RoundingMode::Ceiling => result_positive,
                _ => unreachable!(),
            };
        finish(neg, q, bump)
    };
    let (neg0, q0, rem0, div0) = probe(base_guard);
    let dist0 = if rem0 < div0 - rem0 { rem0 } else { div0 - rem0 };
    if dist0 > pow10(base_guard) / lit(1000) {
        return (dir_round(neg0, q0, rem0), true); // clear of a grid line
    }
    let base = dir_round(neg0, q0, rem0);
    let max_guard = max_guard_for(int_digits_of(base));
    // Cross-depth confirmation — see the nearest branch: a probe's signal
    // `(position, side)` is trusted only once a probe at a different depth
    // reproduces it (noise tracks the bottom of `w`; real digits do not move).
    let mut pending: Option<(u32, bool)> = if dist0 > floor {
        Some((pos_of(dist0, base_guard), rem0 < div0 - rem0))
    } else {
        None
    };
    let mut guard = base_guard;
    loop {
        if guard >= max_guard {
            // Cap reached without a confirmed deciding term. An unconfirmed
            // signal from the deepest probe gets ONE shifted confirm probe.
            if let Some((pp, ps)) = pending {
                let back = ZIV_RESOLVE_FLOOR_POW10 + 3;
                if max_guard > base_guard + back {
                    let g_c = max_guard - back;
                    let (neg, q, rem, div) = probe(g_c);
                    let dist = if rem < div - rem { rem } else { div - rem };
                    if dist > floor {
                        let p = pos_of(dist, g_c);
                        if (rem < div - rem) == ps && p.abs_diff(pp) <= 1 {
                            return (dir_round(neg, q, rem), true);
                        }
                    }
                }
            }
            // Still unresolved: the deciding digit is beyond reach. SNAP the
            // base probe to its nearest grid line — the sub-floor remainder is
            // kernel noise around it (the undershoot that would otherwise
            // leave the narrowing one ULP short) — then apply the
            // `never_exact` sub-resolution rule on the grid value: the true
            // value carries a strictly positive tail below the computed
            // digits, so Ceiling (positive result) / Floor (negative) nudge
            // one ULP off the line; Trunc keeps it. A non-`never_exact`
            // caller keeps the bare grid line.
            let q_grid = if rem0 > div0 / lit(2) { q0 + lit(1) } else { q0 };
            let tail_bump = never_exact
                && match mode {
                    RoundingMode::Trunc => false,
                    RoundingMode::Floor => neg0,
                    RoundingMode::Ceiling => !neg0,
                    _ => unreachable!(),
                };
            return (finish(neg0, q_grid, tail_bump), false);
        }
        let step = (target + base_guard).max(base_guard);
        let next_guard = guard.saturating_add(step).min(max_guard);
        let (neg, q, rem, div) = probe(next_guard);
        let hi_dist = if rem < div - rem { rem } else { div - rem };
        if hi_dist > floor {
            let p = pos_of(hi_dist, next_guard);
            let above = rem < div - rem;
            if let Some((pp, ps)) = pending {
                if above == ps && p.abs_diff(pp) <= 1 {
                    // Confirmed deciding digit — trustworthy.
                    return (dir_round(neg, q, rem), true);
                }
            }
            pending = Some((p, above));
        }
        guard = next_guard;
    }
}

/// Two-width near-min narrowing for `cosh` / `exp`: resolve the near-tie at the
/// tier work integer `S1`; if its deciding digit was unreachable there (and a
/// wider integer would reach further, i.e. `S1` is below the precision
/// horizon), retry at the next-wider `S2`. A tie unresolved at both widths
/// falls to the never-exact endgame (the sub-resolution positive tail).
/// `never_exact` mirrors the `exp` sub-resolution rule.
#[inline]
#[allow(clippy::too_many_arguments)]
pub(crate) fn round_to_storage_widening_g<St: BigInt + Copy, S1: BigInt, S2: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    never_exact: bool,
    st_max: St,
    st_min: St,
    mut recompute1: impl FnMut(u32) -> S1,
    mut recompute2: impl FnMut(u32) -> S2,
) -> St
where
    S1::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    S2::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    let (v1, resolved1) = near_min_resolve_g::<St, S1>(
        base_guard, target, mode, never_exact, st_max, st_min, &mut recompute1,
    );
    // `S1` only proves a residual is past the probe horizon when its width
    // actually reaches it — and a result carrying integer digits raises both
    // the horizon AND the noise floor by that count (see the resolver), so
    // the reach test must include them.
    let int_digits = {
        let m = if v1 < <St as BigInt>::ZERO { -v1 } else { v1 };
        let bl = <St as BigInt>::BITS - m.leading_zeros();
        ((bl as u64 * 30103 / 100_000) as u32 + 1).saturating_sub(target)
    };
    if resolved1 || (<S1>::BITS / 8) >= ZIV_PRECISION_HORIZON + int_digits {
        return v1;
    }
    near_min_resolve_g::<St, S2>(
        base_guard, target, mode, never_exact, st_max, st_min, &mut recompute2,
    )
    .0
}

/// Single-shot narrowing with a NEAR-TIE escape hatch. Rounds a
/// working-scale value `v` (at scale `w`) to storage exactly as
/// [`round_to_storage_with_g`] would — PROVIDED the sub-storage residual
/// is clear of the mode's deciding boundary (the half-ULP line for the
/// nearest modes, the grid line for the directed ones) by more than the
/// near-tie band (`divisor/1000`, the shared Ziv escalate trigger).
/// Returns `None` when the residual sits inside the band: the value's
/// TRUE deciding digit may then lie below `w`'s resolution (the
/// `asin(3·10⁻⁶⁰)` family — an exact rational partial sum landing
/// exactly ON a boundary with a transcendental tail below the fixed
/// working scale), and the caller must escalate through the full Ziv
/// walker instead of concluding from this single shot. One `div_rem` —
/// the clear path costs what the plain narrowing cost.
#[inline]
pub(crate) fn round_to_storage_clear_of_tie_g<St: BigInt + Copy, S: BigInt>(
    v: S,
    w: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
) -> Option<St>
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    use crate::support::rounding::{is_nearest_mode, should_bump};
    let lit = |n: i128| <S as BigInt>::from_i128(n);
    let shift = w - target;
    if shift == 0 {
        // Already at storage scale: the value IS the answer (no residual).
        return Some(narrow_range_checked_g::<St, S>(v, st_max, st_min));
    }
    let neg = v < lit(0);
    let mag = if neg { -v } else { v };
    let divisor = crate::consts::pow10::dispatch::<S>(shift);
    let (q, rem) = mag.div_rem(divisor);
    let band = if shift >= 3 {
        crate::consts::pow10::dispatch::<S>(shift - 3)
    } else {
        lit(0)
    };
    let bump = if is_nearest_mode(mode) {
        // Distance to the half-ULP boundary (divisor is even for shift >= 1).
        let half = divisor >> 1;
        let dist = if rem < half { half - rem } else { rem - half };
        if dist <= band {
            return None;
        }
        rem != lit(0)
            && should_bump(mode, rem.cmp(&(divisor - rem)), q.bit(0), !neg)
    } else {
        // Distance to the grid line.
        let dist = if rem < divisor - rem { rem } else { divisor - rem };
        if dist <= band {
            return None;
        }
        rem != lit(0)
            && match mode {
                RoundingMode::Trunc => false,
                RoundingMode::Floor => neg,
                RoundingMode::Ceiling => !neg,
                _ => unreachable!(),
            }
    };
    let q_mag = if bump { q + lit(1) } else { q };
    let signed = if neg { -q_mag } else { q_mag };
    Some(narrow_range_checked_g::<St, S>(signed, st_max, st_min))
}

/// Work-int-generic directed-rounding narrowing with Ziv escalation. `St` =
/// storage output, `S` = work integer (a rung `Wk` or the tier `W`).
#[inline]
pub(crate) fn round_to_storage_directed_g<St: BigInt + Copy, S: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
    mut recompute: impl FnMut(u32) -> S,
) -> St
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    round_to_storage_directed_impl_g::<St, S>(
        base_guard, target, mode, false, false, st_max, st_min, &mut recompute,
    )
    .0
}

/// As [`round_to_storage_directed_g`] but RETAINS the walker's `decided`
/// verdict (`false` once it gives up at the escalation cap — mode-blind). The
/// odd forward/inverse trig kernels read it to drive
/// [`tiny_x_deep_directed_adjust`]; every other caller keeps the `.0`-only
/// wrapper. Bit-identical narrowing — only the discarded boolean differs.
#[inline]
pub(crate) fn round_to_storage_directed_decided_g<St: BigInt + Copy, S: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
    mut recompute: impl FnMut(u32) -> S,
) -> (St, bool)
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    round_to_storage_directed_impl_g::<St, S>(
        base_guard, target, mode, false, false, st_max, st_min, &mut recompute,
    )
}

/// `never_exact` directed narrowing (an irrational-valued kernel, e.g. `exp`):
/// a zero working residual is a sub-resolution positive residual.
#[inline]
pub(crate) fn round_to_storage_directed_never_exact_g<St: BigInt + Copy, S: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
    mut recompute: impl FnMut(u32) -> S,
) -> St
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    round_to_storage_directed_impl_g::<St, S>(
        base_guard, target, mode, false, true, st_max, st_min, &mut recompute,
    )
    .0
}

/// Near-special-point directed narrowing (`acosh` at 1, `atanh` at ±1):
/// force a confirm recompute even in nearest modes.
#[inline]
pub(crate) fn round_to_storage_directed_near_special_g<St: BigInt + Copy, S: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
    mut recompute: impl FnMut(u32) -> S,
) -> St
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    round_to_storage_directed_impl_g::<St, S>(
        base_guard, target, mode, true, false, st_max, st_min, &mut recompute,
    )
    .0
}

/// Two-width directed narrowing for the SCALE-derived work rungs: resolve
/// at the rung `S1`; if the walker reaches `S1`'s escalation cap
/// UNRESOLVED (the deciding digit lies beyond the rung's reach but
/// possibly within the tier's), rerun the WHOLE walker at the wider tier
/// work integer `S2`, so the conclusion is never weaker than the tier
/// path's. The directed/nearest twin of the exp near-min
/// [`round_to_storage_widening_g`] retry, and the rung families' fix for
/// the at-cap base-narrowing endgame: an unresolved-at-rung tie that
/// concludes from the rung's probes can, under a DIRECTED mode, land
/// one ULP on the wrong side of a sub-rung-resolution residual the tier
/// width resolves (the `sin_d307_s153` Trunc defect — `sin(x) = x − x³/6`
/// with the cube term between the two caps). A resolved-at-rung value is
/// a CONFIRMED deciding digit the tier walker would find identically (the
/// rung cap never exceeds the tier cap), and an unresolved cell reruns
/// the tier walker verbatim — so the result is bit-identical to the tier
/// path in every case, with the (overwhelmingly common) resolved fast
/// path unchanged.
#[inline]
#[allow(clippy::too_many_arguments)]
pub(crate) fn round_to_storage_directed_widening_g<St: BigInt + Copy, S1: BigInt, S2: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
    mut recompute1: impl FnMut(u32) -> S1,
    mut recompute2: impl FnMut(u32) -> S2,
) -> St
where
    S1::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    S2::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    let (v, resolved) = round_to_storage_directed_impl_g::<St, S1>(
        base_guard, target, mode, false, false, st_max, st_min, &mut recompute1,
    );
    if resolved || <S1 as BigInt>::BITS >= <S2 as BigInt>::BITS {
        return v;
    }
    round_to_storage_directed_impl_g::<St, S2>(
        base_guard, target, mode, false, false, st_max, st_min, &mut recompute2,
    )
    .0
}

/// As [`round_to_storage_directed_widening_g`] but RETAINS the final `decided`
/// verdict (the rung's when it resolves or is the widest, else the tier
/// fall-up's). The odd forward/inverse trig rung kernels read it for
/// [`tiny_x_deep_directed_adjust`]. Bit-identical narrowing.
#[inline]
#[allow(clippy::too_many_arguments)]
pub(crate) fn round_to_storage_directed_widening_decided_g<St: BigInt + Copy, S1: BigInt, S2: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
    mut recompute1: impl FnMut(u32) -> S1,
    mut recompute2: impl FnMut(u32) -> S2,
) -> (St, bool)
where
    S1::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    S2::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    let (v, resolved) = round_to_storage_directed_impl_g::<St, S1>(
        base_guard, target, mode, false, false, st_max, st_min, &mut recompute1,
    );
    if resolved || <S1 as BigInt>::BITS >= <S2 as BigInt>::BITS {
        return (v, resolved);
    }
    round_to_storage_directed_impl_g::<St, S2>(
        base_guard, target, mode, false, false, st_max, st_min, &mut recompute2,
    )
}

/// Near-special two-width narrowing — the `force_confirm` sibling of
/// [`round_to_storage_directed_widening_g`] (`acosh` at 1, `atanh` at
/// ±1): an at-cap unconfirmed walk at the rung `S1` reruns at the tier
/// `S2`, never concluding shallower than the tier path.
#[inline]
#[allow(clippy::too_many_arguments)]
pub(crate) fn round_to_storage_directed_near_special_widening_g<
    St: BigInt + Copy,
    S1: BigInt,
    S2: BigInt,
>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    st_max: St,
    st_min: St,
    mut recompute1: impl FnMut(u32) -> S1,
    mut recompute2: impl FnMut(u32) -> S2,
) -> St
where
    S1::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
    S2::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    let (v, resolved) = round_to_storage_directed_impl_g::<St, S1>(
        base_guard, target, mode, true, false, st_max, st_min, &mut recompute1,
    );
    if resolved || <S1 as BigInt>::BITS >= <S2 as BigInt>::BITS {
        return v;
    }
    round_to_storage_directed_impl_g::<St, S2>(
        base_guard, target, mode, true, false, st_max, st_min, &mut recompute2,
    )
    .0
}

/// `recompute` is a `&mut dyn FnMut` trait object, NOT an `impl FnMut`
/// generic — see [`near_min_resolve_g`]: one walker instantiation per
/// `(St, S)` instead of one per call-site closure type. Perf-acceptable
/// because the walker is the RARE Ziv escalation machinery (the hot path
/// narrows single-shot; each `recompute` call is a whole kernel
/// evaluation, dwarfing the indirect call), and it matches the
/// `WideTrigCore` trait surface, which already passes `&mut dyn FnMut`.
#[allow(clippy::too_many_arguments)]
fn round_to_storage_directed_impl_g<St: BigInt + Copy, S: BigInt>(
    base_guard: u32,
    target: u32,
    mode: RoundingMode,
    force_confirm: bool,
    never_exact: bool,
    st_max: St,
    st_min: St,
    recompute: &mut dyn FnMut(u32) -> S,
) -> (St, bool)
where
    S::Scratch: crate::int::types::compute_limbs::ComputeLimbs,
{
    use crate::support::rounding::{is_nearest_mode, RoundingMode};

    let lit = |n: i128| <S as BigInt>::from_i128(n);
    let pow10 = |n: u32| crate::consts::pow10::dispatch::<S>(n);
    let bit_length = |v: S| -> u32 {
        let m = if v < <S as BigInt>::ZERO { -v } else { v };
        <S as BigInt>::BITS - m.leading_zeros()
    };
    let floor = pow10(ZIV_RESOLVE_FLOOR_POW10);
    // The near-tie band at guard `g` is `divisor/1000 = 10^(g-3)` — a table
    // lookup, not a work-integer divide (the divisor is always `10^g`).
    let band_of = |g: u32| -> S { if g >= 3 { pow10(g - 3) } else { lit(0) } };
    if is_nearest_mode(mode) {
        // Round to nearest at a working scale `target + guard`, reporting the
        // sub-storage residual's distance to the half-ULP boundary
        // (`dist_half`). A round-to-nearest decision is trustworthy only once
        // `dist_half` exceeds the ABSOLUTE kernel-noise floor — a genuine
        // deciding digit (`exp(1e-14)`'s `x³/6`, `cosh(1e-28)`'s `x⁴/24`, both
        // just past an exact half). While `dist_half` sits inside the floor the
        // residual is the kernel's own working-scale rounding noise, not a real
        // deciding digit, so the narrowing is a Table-Maker's-Dilemma tie.
        // ONE `div_rem` per narrowing: the quotient + remainder of the same
        // division yield BOTH the correctly-rounded value (the standard
        // `r` vs `m − r` comparison through `should_bump`, exactly
        // [`round_mag_with_mode`]'s rule — bit-identical to routing through
        // `round_to_storage_with`) AND the `dist_half` tie distance. The
        // previous shape divided twice (once inside `round_to_storage_with`,
        // once for the remainder) plus a divide-by-two for `half` — measured
        // at >50% of a wide `sin(0)` call (the bbc trig-s0 cluster).
        let mut nearest_narrow = |guard: u32| -> (St, S, S) {
            let v = recompute(guard);
            let neg = v < lit(0);
            let mag = if neg { -v } else { v };
            let divisor = pow10(guard);
            // Exact per-width Knuth scratch (the narrow build's blanket is sized
            // to its 2-limb storage; the walkers probe in `Int<24>`).
            let (q, rem) = crate::algos::exp::exp_generic::div_rem_exact(mag, divisor);
            let q_mag = if rem != lit(0) {
                let comp = divisor - rem;
                let bump = crate::support::rounding::should_bump(
                    mode,
                    rem.cmp(&comp),
                    q.bit(0),
                    !neg,
                );
                if bump { q + lit(1) } else { q }
            } else {
                q
            };
            let signed = if neg { -q_mag } else { q_mag };
            let narrowed = narrow_range_checked_g::<St, S>(signed, st_max, st_min);
            // `divisor = 10^guard` is even for every guard >= 1 (and the
            // guard-0 degenerate `1/2 == 1 >> 1 == 0`), so the half-ULP
            // boundary is an exact one-bit shift — not a divide.
            let half = divisor >> 1;
            let dist_half = if rem < half { half - rem } else { rem - half };
            (narrowed, dist_half, divisor)
        };
        let (lo, dist0, _divisor0) = nearest_narrow(base_guard);
        // Ordinary input — residual clear of the half boundary by more than the
        // (generous) `divisor/1000` near-tie band — keep the single base
        // narrowing (bit-identical to the prior single-shot path). The escalate
        // trigger stays the wide band; the absolute `floor` below is only the
        // STOP test (signal vs noise), not the escalate trigger.
        if !force_confirm && dist0 > band_of(base_guard) {
            return (lo, true);
        }
        let int_digits = {
            let n = BigInt::resize_to::<S>(lo);
            let m = if n < lit(0) { -n } else { n };
            let bl = bit_length(m);
            let storage_digits = (bl as u64 * 30103 / 100_000) as u32 + 1;
            storage_digits.saturating_sub(target)
        };
        let cap_digits = (<S>::BITS / 8).saturating_sub(int_digits + 8);
        let max_guard = cap_digits
            .saturating_sub(target)
            .min(ZIV_PRECISION_HORIZON.saturating_sub(target))
            .max(base_guard);
        let mut guard = base_guard;
        let mut best = lo;
        loop {
            if guard >= max_guard {
                // Cap reached without clearing the noise floor. `force_confirm`
                // (acosh/atanh) trusts its last stable narrowing; otherwise the
                // deciding digit is below the work integer's / the crate's reach
                // — return the CLEAN base narrowing (the exact-tie answer the
                // finite-precision oracle agrees with), NOT the deepest
                // narrowing (which is dominated by kernel noise at this depth).
                return (if force_confirm { best } else { lo }, false);
            }
            let step = (target + base_guard).max(base_guard);
            let unclamped = guard.saturating_add(step);
            let next_guard = unclamped.min(max_guard);
            // A probe whose depth was CLAMPED by this width's escalation cap
            // diverges from the canonical (tier-width) probe sequence — any
            // conclusion drawn from it is reported UNRESOLVED so a two-width
            // caller falls up to the tier walker instead of trusting a
            // cap-limited reading (e.g. a zero remainder that is only the
            // deciding term underflowing at the clamped working scale).
            let tainted = unclamped > max_guard;
            let (hi, hi_dist, _) = nearest_narrow(next_guard);
            if force_confirm {
                if hi == best {
                    return (best, !tainted);
                }
            } else if hi_dist > floor {
                // Deciding digit is now a clear signal above the noise floor —
                // this narrowing is trustworthy (at an unclamped, canonical
                // probe depth).
                return (hi, !tainted);
            }
            guard = next_guard;
            best = hi;
        }
    }

    let mut directed_narrow = |guard: u32| -> (S, S, S) {
        let w = target + guard;
        let v = recompute(guard);
        let shift = w - target;
        let neg = v < lit(0);
        let mag = if neg { -v } else { v };
        let divisor = pow10(shift);
        // Exact per-width Knuth scratch (the narrow build's blanket is sized
        // to its 2-limb storage; the walkers probe in `Int<24>`).
        let (q, rem) = crate::algos::exp::exp_generic::div_rem_exact(mag, divisor);
        let result_positive = !neg;
        let residual_present = rem != lit(0) || never_exact;
        let bump = residual_present
            && match mode {
                RoundingMode::Trunc => false,
                RoundingMode::Floor => !result_positive,
                RoundingMode::Ceiling => result_positive,
                _ => unreachable!(),
            };
        let q_mag = if bump { q + lit(1) } else { q };
        let signed = if neg { -q_mag } else { q_mag };
        let dist = if rem < divisor - rem {
            rem
        } else {
            divisor - rem
        };
        (signed, dist, divisor)
    };

    let (mut lo, dist0, _divisor0) = directed_narrow(base_guard);

    let band0 = band_of(base_guard);
    let near_grid = force_confirm || dist0 <= band0;

    let (signed, decided) = if !near_grid {
        (lo, true)
    } else {
        // The clean base narrowing — the unresolved endgame's answer (see
        // the cap break below). Captured BEFORE the loop starts rolling
        // `lo` through the deeper probes.
        let base = lo;
        let int_digits = {
            let m = if lo < lit(0) { -lo } else { lo };
            let bl = bit_length(m);
            let storage_digits = (bl as u64 * 30103 / 100_000) as u32 + 1;
            storage_digits.saturating_sub(target)
        };
        // DELIBERATELY the bare `BITS/8` work-integer cap — NOT `.min(
        // ZIV_PRECISION_HORIZON)` like the nearest branch above. The two
        // boundaries serve different masters: nearest gives up at the horizon
        // because a half-ULP tie past the shipped ~1232-digit oracle is
        // unverifiable, and giving up early still yields the correct nearest
        // answer (snap to the grid value `G`). A DIRECTED sub-resolution
        // residual past the horizon is the opposite — its SIGN still decides
        // `G` vs `G ± 1`, and that decision is owned by the analytic
        // [`tiny_x_deep_directed_adjust`], which fires exactly when the
        // deciding term lies beyond `reach = work_bits/8 − 8` — the EXACT
        // complement of this `cap_digits` (bounded trig ⇒ `int_digits = 0`).
        // So the walker MUST own every deciding term up to `BITS/8`: clamping
        // here to the horizon would lower the give-up boundary below `reach`,
        // leaving cells with `j*·k ∈ (horizon, reach]` reported mode-blind
        // (`decided == false`) yet UN-adjusted by the helper (its `j*·k ≤
        // reach` returns `r` unchanged) — a directed mis-round. `BITS/8` is
        // also the const-table-safe cap (`pi`/`ln2`/`sincos` are provisioned
        // per width to ≈`BITS/8`), so probing to it never requests a const
        // past the generated table.
        let cap_digits = (<S>::BITS / 8).saturating_sub(int_digits + 8);
        let max_guard = cap_digits.saturating_sub(target).max(base_guard);

        let mut guard = base_guard;
        // Whether the LAST probe's grid-line distance cleared the absolute
        // noise floor — a genuine, representable deciding digit (a real
        // residual only GROWS with depth, so a final floor-clearing probe is
        // signal even without a second confirming probe; the asin(1e-38)
        // D38<38> Ceiling deviation `x³/6` at ULP-depth 77 first becomes
        // visible exactly at the rung's cap-clamped probe).
        let mut last_resolved = false;
        loop {
            if guard >= max_guard {
                // Cap reached. `force_confirm` (acosh/atanh) trusts its
                // last stable narrowing. A walk whose FINAL probe resolved
                // (cleared the noise floor) but had no deeper probe left to
                // confirm against trusts that probe — discarding it for the
                // base would invert a deciding digit first visible at the
                // cap. Otherwise — no probe ever cleared the floor (the
                // Table-Maker's-Dilemma residue) — return the CLEAN BASE
                // narrowing, mirroring the nearest branch's endgame: never
                // an unresolved deepest probe, which at this depth is
                // dominated by kernel noise, and at the cap-CLAMPED working
                // scale can even be a wrapped kernel value (the deep-
                // underflow `exp` probe's internal squaring peak tops the
                // work integer's sign bit, handing the walker a NEGATIVE
                // "e^x" that inverts the directed bump — the
                // exp(-62.175…) D38 s17–19 Ceiling/Floor inversion).
                break (if force_confirm || last_resolved { lo } else { base }, false);
            }
            let step = (target + base_guard).max(base_guard);
            let unclamped = guard.saturating_add(step);
            let next_guard = unclamped.min(max_guard);
            // See the nearest branch: a cap-clamped probe departs from the
            // canonical probe sequence, so its conclusion is reported
            // UNRESOLVED for the two-width fall-up.
            let tainted = unclamped > max_guard;
            let (hi, hi_dist, _hi_div) = directed_narrow(next_guard);
            // A deciding digit is a genuine SIGNAL once its distance to the
            // grid line clears the ABSOLUTE kernel-noise floor — the same
            // rule the nearest branch applies to its half-boundary
            // distance. A relative `divisor/1000` band would scale with
            // the working scale, so a SUB-RESOLUTION residual (e.g. a
            // deep-underflow `exp`, value ≪ 1 storage ULP) could never
            // clear it and every such walk would run to the cap — where the
            // deepest probe, not the clean base, would be trusted.
            // Resolution still demands two consecutive probes agree on the
            // narrowing (`hi == lo`), a stricter consistency requirement
            // than the nearest branch's single floor-clearing probe.
            //
            // `hi_dist == lit(0)`: a probe landing EXACTLY on a grid line
            // (working-scale remainder == 0) at a depth ABOVE the true
            // deviation also counts as resolved when paired with `hi == lo`.
            // `directed_narrow` already handles the zero remainder correctly
            // (`residual_present = rem != lit(0) || never_exact` keeps the
            // directed bump active when `never_exact` is set), so `hi` IS
            // the right directed answer; `hi == lo` confirms a second,
            // independent depth reached the same conclusion. This is sound
            // for every CURRENT ladder: the step formula (`target +
            // base_guard`, ≥68 digits in the wide tiers) spans a 10^68×
            // depth gap, making coincidental paired exact-zero remainders
            // impossible unless the residual is genuinely sub-resolution to
            // the ZIV_PRECISION_HORIZON. A future ladder with a stride SHORT
            // enough to straddle a genuine residual would be pathological —
            // canonical form: stride k digits, true deviation at depth D+k,
            // so depth-D and depth-(D+k) both produce exact-zero remainders
            // while depth-(D+2k) would show the genuine non-zero residual;
            // the hi==lo+dist==0 pair would then fire early on an answer
            // that a proper confirming probe would overturn.
            let resolved = hi_dist == lit(0) || hi_dist > floor;
            if hi == lo && resolved {
                break (hi, !tainted);
            }
            guard = next_guard;
            lo = hi;
            last_resolved = resolved;
        }
    };

    (narrow_range_checked_g::<St, S>(signed, st_max, st_min), decided)
}

// Directed-walker contract tests: a strictly positive SUB-RESOLUTION
// residual (value ≪ 1 storage ULP — the deep-underflow `exp` shape) must
// round Ceiling → 1 ULP and Floor/Trunc/nearest → 0 under the
// `never_exact` walker, even when the deepest (cap-clamped) probe is
// POISONED — the stand-in for a work-integer-wrapped kernel value (the
// generic exp kernel's internal squaring peak can top the work integer's
// sign bit at the cap-clamped working scale, handing the walker a
// NEGATIVE "e^x"). Before the fix the directed branch could never resolve
// a sub-resolution residual (the relative `divisor/1000` stop band scales
// with the working scale) and at the cap trusted the DEEPEST probe — so
// the poisoned probe inverted Ceiling to 0 and Floor to -1.
#[cfg(test)]
mod directed_walker_contract {
    use super::*;
    use crate::int::types::Int;
    use crate::support::rounding::RoundingMode;

    type S = Int<24>;
    type St = Int<2>;
    const BASE_GUARD: u32 = 30;
    const TARGET: u32 = 17;

    const ALL_MODES: [RoundingMode; 6] = [
        RoundingMode::HalfToEven,
        RoundingMode::HalfAwayFromZero,
        RoundingMode::HalfTowardZero,
        RoundingMode::Ceiling,
        RoundingMode::Floor,
        RoundingMode::Trunc,
    ];

    fn run(mode: RoundingMode, recompute: impl FnMut(u32) -> S) -> i128 {
        round_to_storage_directed_never_exact_g::<St, S>(
            BASE_GUARD,
            TARGET,
            mode,
            St::MAX,
            St::MIN,
            recompute,
        )
        .as_i128()
    }

    /// Negated probe value — the wrapped-kernel stand-in. Any probe at
    /// guard >= 150 is past every canonical (unclamped) depth for this
    /// `(TARGET, BASE_GUARD)`, i.e. only the cap-clamped probe lands
    /// there; poisoning the whole tail keeps the test robust if the
    /// step arithmetic ever changes.
    const POISON_FROM: u32 = 150;

    // A genuine sub-resolution positive (≈9.95e-28 storage ULPs): its
    // grid-line distance clears the ABSOLUTE kernel-noise floor at the
    // first escalation probe, so the walk resolves at a canonical depth
    // and the poisoned tail is never consulted.
    #[test]
    fn sub_resolution_positive_resolves_correctly_despite_poisoned_tail() {
        for mode in ALL_MODES {
            let got = run(mode, |g| {
                let v = <S as BigInt>::from_i128(995)
                    * crate::consts::pow10::dispatch::<S>(g - BASE_GUARD);
                if g >= POISON_FROM { -v } else { v }
            });
            let want = if mode == RoundingMode::Ceiling { 1 } else { 0 };
            assert_eq!(got, want, "sub-resolution positive, mode={mode:?}");
        }
    }

    // A residual at kernel-noise scale (5 work units, below the resolve
    // floor at EVERY depth — the Table-Maker's-Dilemma stand-in): the walk
    // runs to the cap unresolved, and the endgame must return the CLEAN
    // BASE narrowing (never-exact: Ceiling → 1, others → 0), never the
    // deepest probe's — which here is poisoned negative and would invert
    // Ceiling to 0 and Floor to -1.
    #[test]
    fn unresolved_cap_returns_clean_base_not_deepest_probe() {
        for mode in ALL_MODES {
            let got = run(mode, |g| {
                let v = <S as BigInt>::from_i128(5);
                if g >= POISON_FROM { -v } else { v }
            });
            let want = if mode == RoundingMode::Ceiling { 1 } else { 0 };
            assert_eq!(got, want, "noise-scale residual at cap, mode={mode:?}");
        }
    }

    // A deciding digit first visible ONLY at the cap-clamped final probe —
    // the asin(1e-38) D38<38> shape (CI fallout of the cap-endgame fix):
    // value = 1 ULP + 1.667e-77 ULPs, walked at the D57 borrow path's
    // Int<16> rung (max_guard = 128 − 8 − 38 = 82, first probe 30+68 = 98
    // clamped to 82). The base probe lands EXACTLY on grid (the deviation
    // is below w = 68's resolution); the single cap-clamped probe shows the
    // genuine residual (1.667e5 work units, above the noise floor) — the
    // endgame must TRUST that resolved final probe (Ceiling → 2), not
    // discard it for the on-grid base (Ceiling → 1, the wrong answer).
    #[test]
    fn deciding_digit_first_visible_at_cap_probe_is_trusted() {
        type Rung = Int<16>;
        for (mode, want) in [
            (RoundingMode::Ceiling, 2_i128),
            (RoundingMode::Floor, 1),
            (RoundingMode::Trunc, 1),
            (RoundingMode::HalfToEven, 1),
        ] {
            let got = round_to_storage_directed_g::<St, Rung>(
                BASE_GUARD,
                TARGET_ASIN,
                mode,
                St::MAX,
                St::MIN,
                |g| {
                    // 10^g + ⌊1.667·10^(g−77)⌋ — the deviation appears at
                    // ULP-depth 77 (asin's x³/6 for x = 1e-38).
                    let one = crate::consts::pow10::dispatch::<Rung>(g);
                    if g >= 80 {
                        one + <Rung as BigInt>::from_i128(1667)
                            * crate::consts::pow10::dispatch::<Rung>(g - 80)
                    } else {
                        one
                    }
                },
            )
            .as_i128();
            assert_eq!(got, want, "late-visible deciding digit, mode={mode:?}");
        }
    }

    /// The asin-shape test's storage scale (D38<38>).
    const TARGET_ASIN: u32 = 38;
}

/// Wide-tier tiny-x DIRECTED rounding pins (the comprehensive-gate
/// wrong-mode find): for a sub-resolution-cubic argument the deciding
/// cubic digit sits at fractional depth `≈ 3·SCALE`, past the work
/// integer's Ziv reach, so the directed result is the analytic
/// [`tiny_x_linear_directed`] decision — EXPANDING (`tan`/`asin`,
/// `|f| > |x|`) pushes the magnitude OUT by one ULP, COMPRESSING
/// (`sin`/`atan`, `|f| < |x|`) pulls it IN — NOT the mode-blind grid value
/// the pre-fix narrowing returned. The three nearest modes round to `x`.
/// Covers both the Tang band (D153<76>) and the Series band (D153<152>),
/// each side of zero, through the public strict path.
#[cfg(all(test, any(feature = "d153", feature = "wide")))]
mod tiny_x_directed_pins {
    use crate::int::types::{traits::BigInt, Int};
    use crate::support::rounding::RoundingMode::{
        Ceiling, Floor, HalfAwayFromZero, HalfToEven, HalfTowardZero, Trunc,
    };

    const ULP: Int<8> = <Int<8> as BigInt>::ONE;

    /// Pin all six modes for one wide-tier `D153<SCALE>` function at the
    /// tiny argument `±3·10^(−KNEG)` (raw `±3·10^(SCALE−KNEG)`, built
    /// directly — the parser takes no scientific notation). `expanding`
    /// selects the cubic-tail direction: EXPANDING (`|f| > |x|`,
    /// `tan`/`asin`) pushes the magnitude OUT by one ULP only under the
    /// away-from-`x` directed mode (Ceiling for `+x`, Floor for `−x`);
    /// COMPRESSING (`|f| < |x|`, `sin`/`atan`) pulls it IN by one ULP under
    /// the toward-zero directed modes. The three nearest modes round to `x`.
    macro_rules! pin {
        ($scale:literal, $kneg:literal, $f:ident, $expanding:expr, $label:literal) => {{
            let r = Int::<8>::from_i128(3)
                * crate::consts::pow10::dispatch::<Int<8>>($scale - $kneg);
            let x = crate::D::<Int<8>, $scale>(r);
            let nr = -r;
            let nx = crate::D::<Int<8>, $scale>(nr);
            for m in [HalfToEven, HalfAwayFromZero, HalfTowardZero] {
                assert_eq!(x.$f(m).0, r, "{} (+x) {:?}", $label, m);
                assert_eq!(nx.$f(m).0, nr, "{} (−x) {:?}", $label, m);
            }
            if $expanding {
                assert_eq!(x.$f(Ceiling).0, r + ULP, "{} (+x) Ceiling", $label);
                assert_eq!(x.$f(Floor).0, r, "{} (+x) Floor", $label);
                assert_eq!(x.$f(Trunc).0, r, "{} (+x) Trunc", $label);
                assert_eq!(nx.$f(Floor).0, nr - ULP, "{} (−x) Floor", $label);
                assert_eq!(nx.$f(Ceiling).0, nr, "{} (−x) Ceiling", $label);
                assert_eq!(nx.$f(Trunc).0, nr, "{} (−x) Trunc", $label);
            } else {
                assert_eq!(x.$f(Floor).0, r - ULP, "{} (+x) Floor", $label);
                assert_eq!(x.$f(Trunc).0, r - ULP, "{} (+x) Trunc", $label);
                assert_eq!(x.$f(Ceiling).0, r, "{} (+x) Ceiling", $label);
                assert_eq!(nx.$f(Ceiling).0, nr + ULP, "{} (−x) Ceiling", $label);
                assert_eq!(nx.$f(Trunc).0, nr + ULP, "{} (−x) Trunc", $label);
                assert_eq!(nx.$f(Floor).0, nr, "{} (−x) Floor", $label);
            }
        }};
    }

    #[test]
    fn tan_expanding_d153_tang_and_series_bands() {
        // 3e-60 @ s76 → Tang band (70..=82); 3e-120 @ s152 → Series band —
        // both sit in the linear band so the analytic decision applies.
        pin!(76, 60, tan_strict_with, true, "tan s76");
        pin!(152, 120, tan_strict_with, true, "tan s152");
    }

    #[test]
    fn sin_compressing_d153_tang_and_series_bands() {
        pin!(76, 60, sin_strict_with, false, "sin s76");
        pin!(152, 120, sin_strict_with, false, "sin s152");
    }

    #[test]
    fn atan_compressing_d153_series_band() {
        pin!(152, 120, atan_strict_with, false, "atan s152");
    }

    #[test]
    fn asin_expanding_d153_series_band() {
        pin!(152, 120, asin_strict_with, true, "asin s152");
    }
}

/// Wide-tier DEEP-band tiny-x DIRECTED rounding pins — the generalisation past
/// the linear ([`tiny_x_directed_pins`]) band, where the LEADING odd Taylor
/// terms terminate exactly on the grid and a DEEPER odd term (`x⁷`, `j* = 7`)
/// decides. The comprehensive-gate find: `±3·10⁻¹²⁰` @ D616 s615 (the `x⁷`
/// digit sits at fractional depth ~841, past the `Int<96>` work integer's reach
/// AND the const tables, so the directed walker is mode-blind and only the
/// analytic [`tiny_x_deep_directed_adjust`] sign resolves it). This pins the
/// DIRECTED adjustment RELATIVE to the nearest grid value `G` (`G ≠ x` here, the
/// deep-band signature — asserted explicitly); `G`'s own accuracy is the golden
/// gate's job. EXPANDING (`tan`/`asin`, `j* ≡ 1 mod 4` for the alternating pair)
/// pushes OUT, COMPRESSING (`sin`/`atan`, `j* = 7 ≡ 3 mod 4`) pulls IN.
#[cfg(all(test, any(feature = "d616", feature = "x-wide")))]
mod tiny_x_deep_directed_pins {
    use crate::int::types::{traits::BigInt, Int};
    use crate::support::rounding::RoundingMode::{
        Ceiling, Floor, HalfAwayFromZero, HalfToEven, HalfTowardZero, Trunc,
    };

    const ULP: Int<32> = <Int<32> as BigInt>::ONE;

    /// Pin all six modes for one `D616<SCALE>` function at `±3·10^(−KNEG)`
    /// (raw `±3·10^(SCALE−KNEG)`). `G` is the crate's own NEAREST result (the
    /// terminating partial sum, `≠ x`); the directed modes must be `G ± 1 ULP`
    /// per the deciding term's sign.
    macro_rules! pin_deep {
        ($scale:literal, $kneg:literal, $f:ident, $expanding:expr, $label:literal) => {{
            let r = Int::<32>::from_i128(3)
                * crate::consts::pow10::dispatch::<Int<32>>($scale - $kneg);
            let x = crate::D::<Int<32>, $scale>(r);
            let nx = crate::D::<Int<32>, $scale>(-r);
            let g = x.$f(HalfToEven).0; // the on-grid nearest value
            let ng = nx.$f(HalfToEven).0;
            // Deep-band signature: the nearest value is the terminating partial
            // sum, strictly off the raw linear term `x`.
            assert_ne!(g, r, "{}: expected the DEEP band (G != x)", $label);
            for m in [HalfToEven, HalfAwayFromZero, HalfTowardZero] {
                assert_eq!(x.$f(m).0, g, "{} (+x) {:?}", $label, m);
                assert_eq!(nx.$f(m).0, ng, "{} (−x) {:?}", $label, m);
            }
            if $expanding {
                assert_eq!(x.$f(Ceiling).0, g + ULP, "{} (+x) Ceiling", $label);
                assert_eq!(x.$f(Floor).0, g, "{} (+x) Floor", $label);
                assert_eq!(x.$f(Trunc).0, g, "{} (+x) Trunc", $label);
                assert_eq!(nx.$f(Floor).0, ng - ULP, "{} (−x) Floor", $label);
                assert_eq!(nx.$f(Ceiling).0, ng, "{} (−x) Ceiling", $label);
                assert_eq!(nx.$f(Trunc).0, ng, "{} (−x) Trunc", $label);
            } else {
                assert_eq!(x.$f(Floor).0, g - ULP, "{} (+x) Floor", $label);
                assert_eq!(x.$f(Trunc).0, g - ULP, "{} (+x) Trunc", $label);
                assert_eq!(x.$f(Ceiling).0, g, "{} (+x) Ceiling", $label);
                assert_eq!(nx.$f(Ceiling).0, ng + ULP, "{} (−x) Ceiling", $label);
                assert_eq!(nx.$f(Trunc).0, ng + ULP, "{} (−x) Trunc", $label);
                assert_eq!(nx.$f(Floor).0, ng, "{} (−x) Floor", $label);
            }
        }};
    }

    #[test]
    fn sin_atan_compressing_d616_s615_deep() {
        pin_deep!(615, 120, sin_strict_with, false, "sin s615");
        pin_deep!(615, 120, atan_strict_with, false, "atan s615");
    }

    #[test]
    fn tan_asin_expanding_d616_s615_deep() {
        pin_deep!(615, 120, tan_strict_with, true, "tan s615");
        pin_deep!(615, 120, asin_strict_with, true, "asin s615");
    }
}