mirror of
https://github.com/exaloop/codon.git
synced 2025-06-03 15:03:52 +08:00
1597 lines
64 KiB
Python
1597 lines
64 KiB
Python
# Copyright (C) 2022-2025 Exaloop Inc. <https://exaloop.io>
|
|
|
|
import util
|
|
|
|
_DIGIT_MODE_UNIQUE: Static[int] = 0
|
|
_DIGIT_MODE_EXACT: Static[int] = 1
|
|
|
|
_CUTOFF_MODE_TOTAL_LENGTH: Static[int] = 0
|
|
_CUTOFF_MODE_FRACTION_LENGTH: Static[int] = 1
|
|
|
|
_TRIM_MODE_NONE: Static[int] = 0
|
|
_TRIM_MODE_LEAVE_ONE_ZERO: Static[int] = 1
|
|
_TRIM_MODE_ZEROS: Static[int] = 2
|
|
_TRIM_MODE_DPT_ZEROS: Static[int] = 3
|
|
|
|
def _bitmask_u64(n):
|
|
return ~(~u64(0) << u64(n))
|
|
|
|
def _bitmask_u32(n):
|
|
return ~(~u32(0) << u32(n))
|
|
|
|
@pure
|
|
@llvm
|
|
def _log_tab(idx: u32) -> u32:
|
|
@data = private unnamed_addr constant [256 x i8] c"\00\00\01\01\02\02\02\02\03\03\03\03\03\03\03\03\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\04\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\05\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\06\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07\07"
|
|
%i = zext i32 %idx to i64
|
|
%p = getelementptr inbounds [256 x i8], ptr @data, i64 0, i64 %i
|
|
%x = load i8, ptr %p, align 1
|
|
%y = zext i8 %x to i32
|
|
ret i32 %y
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_tab(idx: u32) -> u32:
|
|
@data = private unnamed_addr constant [8 x i32] [i32 1, i32 10, i32 100, i32 1000, i32 10000, i32 100000, i32 1000000, i32 10000000], align 16
|
|
%i = zext i32 %idx to i64
|
|
%p = getelementptr inbounds [8 x i32], ptr @data, i64 0, i64 %i
|
|
%x = load i32, ptr %p, align 4
|
|
ret i32 %x
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_8_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [1 x i32] [i32 100000000], align 4
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_16_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [2 x i32] [i32 1874919424, i32 2328306], align 4
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_32_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [4 x i32] [i32 0, i32 -2052264063, i32 762134875, i32 1262], align 16
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_64_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [7 x i32] [i32 0, i32 0, i32 -1083564287, i32 1849224548, i32 -626550803, i32 -381683212, i32 1593091], align 16
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_128_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [14 x i32] [i32 0, i32 0, i32 0, i32 0, i32 781532673, i32 64985353, i32 253049085, i32 594863151, i32 -741345812, i32 -1006314488, i32 -1127370534, i32 -1506574567, i32 -383834621, i32 590], align 16
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_256_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [27 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 -1741784063, i32 -1093433509, i32 -656826510, i32 303378311, i32 1809731782, i32 -817205648, i32 -711600113, i32 649228654, i32 -1379506512, i32 487929380, i32 1011012442, i32 1677677582, i32 -866815040, i32 1710878487, i32 1438394610, i32 -2133014537, i32 -194056740, i32 1608314830, i32 349175], align 16
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_512_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [54 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 -59967487, i32 2012377703, i32 -1886042404, i32 1570150255, i32 -1204122985, i32 -1021437223, i32 1187251475, i32 -1796843705, i32 -930515263, i32 1148564857, i32 687371067, i32 -1440898625, i32 1883165473, i32 505794538, i32 -1306906846, i32 -1135477970, i32 -1763618979, i32 -1079775828, i32 849106862, i32 -402886317, i32 -1006893419, i32 -2052515548, i32 -111189154, i32 -1299149088, i32 -1817465372, i32 325481258, i32 -1807124644, i32 1774082830, i32 1933815724, i32 -1332102015, i32 1168579910, i32 -1570138296, i32 -1934593277, i32 -1978982637, i32 -1934914921, i32 -1043187495, i32 1664357844, i32 28], align 16
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_1024_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [107 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 689565697, i32 -178574478, i32 1853628763, i32 516071302, i32 -1726198137, i32 365238920, i32 336250165, i32 1283268122, i32 -869476327, i32 248595470, i32 -1989790482, i32 2111925499, i32 507770399, i32 -1613855875, i32 589114268, i32 591287751, i32 1708941527, i32 -196009589, i32 475844916, i32 -916235898, i32 -1842627681, i32 -1477929935, i32 -1616958969, i32 1656645978, i32 -1911536956, i32 73103988, i32 448667107, i32 -1965546843, i32 -1170947055, i32 -669731579, i32 -1086333261, i32 -1882908138, i32 -1313302852, i32 -177344788, i32 838560765, i32 -1225497269, i32 270153238, i32 1802868219, i32 -602257410, i32 -2133229431, i32 -2135054939, i32 -1709168510, i32 837488486, i32 -57729136, i32 -1754647792, i32 -496338050, i32 -546818422, i32 1021550776, i32 -1908251954, i32 1973637538, i32 1823520457, i32 1146713475, i32 833971519, i32 -1017715830, i32 905620390, i32 26278816, i32 -1614484142, i32 -2000926437, i32 373297482, i32 5996609, i32 -185392290, i32 512575049, i32 917036550, i32 1942311753, i32 -1478050518, i32 -1046046964, i32 1192784020, i32 -757380625, i32 -1838399653, i32 -1369306668, i32 759380297, i32 888447942, i32 -735027820, i32 -640280059, i32 805], align 16
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_2048_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [213 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 322166785, i32 -485922715, i32 -1300411073, i32 1239584207, i32 -332511455, i32 -293084332, i32 -1241090684, i32 915114683, i32 -1511677551, i32 785739093, i32 -41781389, i32 -363802302, i32 1370983858, i32 -1741411170, i32 -934225220, i32 -2039556367, i32 422849554, i32 -1837545081, i32 -755471934, i32 1720790602, i32 1908931983, i32 1470596141, i32 592794347, i32 -75502132, i32 -209314592, i32 941661409, i32 -1760316343, i32 885063988, i32 -1939057442, i32 -1482151780, i32 767256131, i32 -473209613, i32 -2139816191, i32 -477548823, i32 281116564, i32 -1460572270, i32 -1473765674, i32 -1770341453, i32 1511330880, i32 -1722614803, i32 330571332, i32 -1343878717, i32 -1564695530, i32 -250510817, i32 -82680652, i32 -1850029708, i32 -691546453, i32 -1907818699, i32 1142537539, i32 -995731867, i32 1751012624, i32 861228086, i32 -1421244777, i32 230498814, i32 1023297821, i32 -1741839258, i32 -873837401, i32 -1643049861, i32 2042981258, i32 1606787143, i32 -2066215378, i32 447345732, i32 1930371132, i32 1784132011, i32 -682428506, i32 -2019042206, i32 -1807399425, i32 1080427616, i32 2009179183, i32 -911460515, i32 -395913233, i32 1950782960, i32 -2126345083, i32 -1577292906, i32 -678331269, i32 2079341593, i32 1530129217, i32 1461057425, i32 -1888702881, i32 -620295939, i32 -1322931058, i32 2019354295, i32 1455849819, i32 1866918619, i32 1324269294, i32 424891864, i32 -1572544964, i32 -1653372480, i32 1400249021, i32 -812003303, i32 -560020917, i32 225889849, i32 1891545473, i32 777383150, i32 -705142663, i32 -177365685, i32 -74938629, i32 334453379, i32 1083130821, i32 1060342180, i32 -86804157, i32 1489826908, i32 -131205050, i32 1096580926, i32 689301528, i32 -1958912780, i32 1782865703, i32 -119818886, i32 -896597904, i32 -1965554708, i32 -1293386700, i32 59740741, i32 -1092777364, i32 -943071520, i32 246185302, i32 718535188, i32 -522319808, i32 -143300740, i32 -239269163, i32 -1833033186, i32 -2013651015, i32 -828570460, i32 -758943831, i32 1064267812, i32 -1339510942, i32 -1871161874, i32 -667006506, i32 1325057500, i32 -418047317, i32 2009959531, i32 175455101, i32 184092852, i32 -1936181725, i32 -451989465, i32 -1809701007, i32 487121622, i32 -135714586, i32 -219259738, i32 459389244, i32 300652075, i32 -1773620708, i32 -835990623, i32 888631636, i32 2076098096, i32 -450452711, i32 -1931269716, i32 -565545774, i32 -1243851819, i32 649395], align 16
|
|
ret ptr @data
|
|
|
|
@pure
|
|
@llvm
|
|
def _pow10_4096_blocks() -> Ptr[u32]:
|
|
@data = private unnamed_addr constant [426 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 711442433, i32 -730706291, i32 -1895925017, i32 -124117360, i32 -284671721, i32 1423987028, i32 330414929, i32 1349249065, i32 -81153678, i32 -442935474, i32 -254123706, i32 -2140401965, i32 -1200953922, i32 1159028371, i32 -1067901758, i32 2115927092, i32 2085102554, i32 488590542, i32 -1685347864, i32 -692068491, i32 -482230768, i32 -1025528200, i32 23816114, i32 253984538, i32 1035905997, i32 -1351998092, i32 -894179625, i32 338562688, i32 1637191975, i32 740509713, i32 -2030004479, i32 -884213374, i32 -132735868, i32 -2012926068, i32 1759373012, i32 -1139599519, i32 -16054011, i32 1420532801, i32 1981002276, i32 438054990, i32 1006507643, i32 1142697287, i32 1332538012, i32 2029019521, i32 -345661512, i32 818392641, i32 -1803678450, i32 -1578382633, i32 -646081194, i32 556814413, i32 444795339, i32 -223554297, i32 1066321706, i32 -41797830, i32 -1784134980, i32 672091442, i32 -211711296, i32 -2128982268, i32 1841538484, i32 -745113061, i32 364431512, i32 -587319153, i32 1162785440, i32 -2026325751, i32 281340310, i32 735693841, i32 848809228, i32 1700785200, i32 -1375263311, i32 -200732952, i32 58530286, i32 965505005, i32 1000010347, i32 -913005488, i32 -1254877373, i32 1973852082, i32 -1403995711, i32 1019960210, i32 -2072059, i32 -1473079455, i32 -538291646, i32 -343684389, i32 -409096713, i32 1008791145, i32 503998487, i32 1881258362, i32 1949332730, i32 392996726, i32 2012973814, i32 -324953109, i32 -1833242146, i32 -1352419566, i32 -566900597, i32 -1528066164, i32 -516434455, i32 1085564064, i32 -2016293400, i32 1116879805, i32 -846241025, i32 774279411, i32 157211670, i32 1506320155, i32 531168605, i32 1362654525, i32 956967721, i32 -2146095336, i32 769186085, i32 -108734402, i32 2055679604, i32 -1046601809, i32 -313699283, i32 -319179312, i32 -1805456779, i32 -985920801, i32 212771124, i32 933418041, i32 -923128182, i32 562115198, i32 1853601831, i32 757336096, i32 1354633440, i32 1486083256, i32 -1422840903, i32 522920738, i32 1141587749, i32 -1084064034, i32 1926940553, i32 -1240942443, i32 2021162538, i32 -2032225296, i32 1877899947, i32 -1147964428, i32 669840763, i32 -136792706, i32 -56464737, i32 1023731922, i32 -908127285, i32 829588074, i32 -845247108, i32 -1459824416, i32 -1295805289, i32 813056473, i32 482949569, i32 638108879, i32 -1227765825, i32 1026714238, i32 -290514458, i32 -1911299489, i32 -295489493, i32 771648919, i32 630660440, i32 -467845948, i32 176185980, i32 -1416776294, i32 -1628817464, i32 -385156233, i32 -1865803313, i32 -1629276884, i32 907266128, i32 -25635198, i32 2022665808, i32 1527122180, i32 -1222913628, i32 1072477492, i32 -1288944372, i32 549664855, i32 -1494626342, i32 37352654, i32 1212772743, i32 -1583686763, i32 -1265439350, i32 -1783847256, i32 1305308377, i32 -820305072, i32 -68636374, i32 442988428, i32 954940108, i32 -1020419197, i32 -82679119, i32 -1606467416, i32 -312740538, i32 -372357340, i32 1279948029, i32 1939943640, i32 -644477395, i32 -1561602367, i32 -1800704021, i32 1864579964, i32 1225941120, i32 -1904502157, i32 1267503249, i32 -761726567, i32 904410805, i32 -1452417281, i32 -1777231055, i32 1796069820, i32 -959692915, i32 673539835, i32 1924694759, i32 -696869061, i32 -1502333891, i32 16535707, i32 -591431799, i32 -702125505, i32 -1365884419, i32 1317622811, i32 294990855, i32 1396706563, i32 -1911695526, i32 -441109691, i32 277813677, i32 277580220, i32 1101318484, i32 -532993181, i32 1132150143, i32 -1750274674, i32 -875141520, i32 743770306, i32 1695464553, i32 1548693232, i32 -1873807681, i32 -1719295265, i32 -1615995490, i32 1591267897, i32 626546738, i32 -471524167, i32 267710932, i32 1455435162, i32 -1940981756, i32 -1046443501, i32 335348168, i32 -422414735, i32 -1480444684, i32 -1660848436, i32 -791200270, i32 1301019273, i32 1414467789, i32 722985138, i32 -1224057731, i32 -41484727, i32 -550027455, i32 558142907, i32 -2065147907, i32 13833173, i32 77003966, i32 -1531295932, i32 -389363326, i32 -1362977170, i32 -2014547912, i32 1879090457, i32 -1360121029, i32 -10034132, i32 -1963103451, i32 62191163, i32 -1116106276, i32 1522063815, i32 785672270, i32 1215568492, i32 -1358523379, i32 802972489, i32 -1338147123, i32 -378234513, i32 -1401395207, i32 1391232801, i32 -1126326966, i32 -1898107648, i32 894950918, i32 1103583736, i32 961991865, i32 -1487664654, i32 305977505, i32 -1240461397, i32 1048256994, i32 781017659, i32 -1835688542, i32 -1130143881, i32 537658277, i32 905753687, i32 464963300, i32 -145835736, i32 1029507924, i32 -2016666335, i32 1231291503, i32 414073408, i32 -664227211, i32 -1949125482, i32 475358196, i32 -1036723979, i32 -127342224, i32 -116056065, i32 -1367612254, i32 655438830, i32 -1156589278, i32 623200562, i32 -1509253184, i32 273403236, i32 807993669, i32 98], align 16
|
|
ret ptr @data
|
|
|
|
def _pow10_blocks(i: u32):
|
|
if i == u32(0):
|
|
return (1, _pow10_8_blocks())
|
|
elif i == u32(1):
|
|
return (2, _pow10_16_blocks())
|
|
elif i == u32(2):
|
|
return (4, _pow10_32_blocks())
|
|
elif i == u32(3):
|
|
return (7, _pow10_64_blocks())
|
|
elif i == u32(4):
|
|
return (14, _pow10_128_blocks())
|
|
elif i == u32(5):
|
|
return (27, _pow10_256_blocks())
|
|
elif i == u32(6):
|
|
return (54, _pow10_512_blocks())
|
|
elif i == u32(7):
|
|
return (107, _pow10_1024_blocks())
|
|
elif i == u32(8):
|
|
return (213, _pow10_2048_blocks())
|
|
elif i == u32(9):
|
|
return (426, _pow10_4096_blocks())
|
|
else:
|
|
return (0, Ptr[u32]())
|
|
|
|
def _log_base2_32(val: u32):
|
|
temp = val >> u32(24)
|
|
if temp:
|
|
return u32(24) + _log_tab(temp)
|
|
|
|
temp = val >> u32(16)
|
|
if temp:
|
|
return u32(16) + _log_tab(temp)
|
|
|
|
temp = val >> u32(8)
|
|
if temp:
|
|
return u32(8) + _log_tab(temp)
|
|
|
|
return _log_tab(val)
|
|
|
|
def _log_base2_64(val: u64):
|
|
temp = val >> u64(32)
|
|
if temp:
|
|
return u64(32) + util.zext(_log_base2_32(util.itrunc(temp, u32)), u64)
|
|
|
|
return util.zext(_log_base2_32(util.itrunc(val, u32)), u64)
|
|
|
|
def _log_base2_128(hi: u64, lo: u64):
|
|
if hi:
|
|
return u64(64) + _log_base2_64(hi)
|
|
|
|
return _log_base2_64(lo)
|
|
|
|
_BIGINT_MAX_BLOCKS: Static[int] = 1023
|
|
_BIGINT_DRAGON4_GROUPSIZE: Static[int] = 7
|
|
|
|
class BigInt:
|
|
length: int
|
|
blocks: Ptr[u32]
|
|
|
|
def __init__(self, length: int, blocks: Ptr[u32]):
|
|
self.length = length
|
|
self.blocks = blocks
|
|
|
|
def __init__(self):
|
|
self.__init__(0, Ptr[u32](_BIGINT_MAX_BLOCKS))
|
|
|
|
def __str__(self):
|
|
return f'BigInt: len={len(self)} blocks=[{", ".join(str(self[i]) for i in range(len(self)))}]'
|
|
|
|
def make_pow10(i: u32):
|
|
return BigInt(*_pow10_blocks(i))
|
|
|
|
def copy(self, dst: BigInt):
|
|
length = len(self)
|
|
srcp = self.blocks
|
|
dstp = dst.blocks
|
|
while srcp != self.blocks + length:
|
|
dstp[0] = srcp[0]
|
|
dstp += 1
|
|
srcp += 1
|
|
dst.length = length
|
|
|
|
def __getitem__(self, idx: int):
|
|
return self.blocks[idx]
|
|
|
|
def __setitem__(self, idx: int, val: u32):
|
|
self.blocks[idx] = val
|
|
|
|
def __setitem__(self, idx: int, val: u64):
|
|
self.blocks[idx] = util.itrunc(val, u32)
|
|
|
|
def __len__(self):
|
|
return self.length
|
|
|
|
def __bool__(self):
|
|
return self.length != 0
|
|
|
|
def set(self, val: u64):
|
|
if val > _bitmask_u64(32):
|
|
self[0] = val & _bitmask_u64(32)
|
|
self[1] = (val >> u64(32)) & _bitmask_u64(32)
|
|
self.length = 2
|
|
elif val:
|
|
self[0] = val & _bitmask_u64(32)
|
|
self.length = 1
|
|
else:
|
|
self.length = 0
|
|
|
|
def set(self, hi: u64, lo: u64):
|
|
if hi > _bitmask_u64(32):
|
|
self.length = 4
|
|
elif hi:
|
|
self.length = 3
|
|
elif lo > _bitmask_u64(32):
|
|
self.length = 2
|
|
elif lo:
|
|
self.length = 1
|
|
else:
|
|
self.length = 0
|
|
|
|
n = self.length
|
|
|
|
if n >= 4:
|
|
self[3] = (hi >> u64(32)) & _bitmask_u64(32)
|
|
if n >= 3:
|
|
self[2] = hi & _bitmask_u64(32)
|
|
if n >= 2:
|
|
self[1] = (lo >> u64(32)) & _bitmask_u64(32)
|
|
if n >= 1:
|
|
self[0] = lo & _bitmask_u64(32)
|
|
|
|
def set(self, val: u32):
|
|
if val:
|
|
self[0] = val
|
|
self.length = 1
|
|
else:
|
|
self.length = 0
|
|
|
|
@property
|
|
def even(self):
|
|
return len(self) == 0 or (self[0] % u32(2) == u32(0))
|
|
|
|
def compare(self, rhs: BigInt):
|
|
lhs = self
|
|
ldiff = len(lhs) - len(rhs)
|
|
if ldiff != 0:
|
|
return ldiff
|
|
|
|
i = len(lhs) - 1
|
|
while i >= 0:
|
|
if lhs[i] == rhs[i]:
|
|
i -= 1
|
|
elif lhs[i] > rhs[i]:
|
|
return 1
|
|
else:
|
|
return -1
|
|
return 0
|
|
|
|
def __eq__(self, other: BigInt):
|
|
return self.compare(other) == 0
|
|
|
|
def __ne__(self, other: BigInt):
|
|
return self.compare(other) != 0
|
|
|
|
def __lt__(self, other: BigInt):
|
|
return self.compare(other) < 0
|
|
|
|
def __le__(self, other: BigInt):
|
|
return self.compare(other) <= 0
|
|
|
|
def __gt__(self, other: BigInt):
|
|
return self.compare(other) > 0
|
|
|
|
def __ge__(self, other: BigInt):
|
|
return self.compare(other) >= 0
|
|
|
|
def add(self, lhs: BigInt, rhs: BigInt):
|
|
result = self
|
|
if len(lhs) < len(rhs):
|
|
small = lhs
|
|
large = rhs
|
|
else:
|
|
small = rhs
|
|
large = lhs
|
|
|
|
result.length = len(large)
|
|
|
|
large_cur = large.blocks
|
|
large_end = large_cur + len(large)
|
|
small_cur = small.blocks
|
|
small_end = small_cur + len(small)
|
|
result_cur = result.blocks
|
|
carry = u64(0)
|
|
|
|
while small_cur != small_end:
|
|
s = carry + util.zext(large_cur[0], u64) + util.zext(small_cur[0], u64)
|
|
carry = s >> u64(32)
|
|
result_cur[0] = util.itrunc(s & _bitmask_u64(32), u32)
|
|
large_cur += 1
|
|
small_cur += 1
|
|
result_cur += 1
|
|
|
|
while large_cur != large_end:
|
|
s = carry + util.zext(large_cur[0], u64)
|
|
carry = s >> u64(32)
|
|
result_cur[0] = util.itrunc(s & _bitmask_u64(32), u32)
|
|
large_cur += 1
|
|
result_cur += 1
|
|
|
|
if carry:
|
|
result_cur[0] = u32(1)
|
|
result.length = len(large) + 1
|
|
else:
|
|
result.length = len(large)
|
|
|
|
def mul(self, lhs: BigInt, rhs: BigInt):
|
|
result = self
|
|
if len(lhs) < len(rhs):
|
|
small = lhs
|
|
large = rhs
|
|
else:
|
|
small = rhs
|
|
large = lhs
|
|
|
|
max_result_len = len(large) + len(small)
|
|
cur = result.blocks
|
|
end = cur + max_result_len
|
|
while cur != end:
|
|
cur[0] = u32(0)
|
|
cur += 1
|
|
|
|
result_start = result.blocks
|
|
small_cur = small.blocks
|
|
|
|
while small_cur != small.blocks + len(small):
|
|
multiplier = small_cur[0]
|
|
if multiplier:
|
|
large_cur = large.blocks
|
|
result_cur = result_start
|
|
carry = u64(0)
|
|
while True:
|
|
product = (util.zext(result_cur[0], u64) +
|
|
(util.zext(large_cur[0], u64) *
|
|
util.zext(multiplier, u64)) + carry)
|
|
carry = product >> u64(32)
|
|
result_cur[0] = util.itrunc(product & _bitmask_u64(32), u32)
|
|
large_cur += 1
|
|
result_cur += 1
|
|
|
|
if large_cur == large.blocks + len(large):
|
|
break
|
|
|
|
result_cur[0] = util.itrunc(carry & _bitmask_u64(32), u32)
|
|
|
|
small_cur += 1
|
|
result_start += 1
|
|
|
|
if max_result_len > 0 and not result[max_result_len - 1]:
|
|
result.length = max_result_len - 1
|
|
else:
|
|
result.length = max_result_len
|
|
|
|
def mul(self, lhs: BigInt, rhs: u32):
|
|
result = self
|
|
carry = u32(0)
|
|
result_cur = result.blocks
|
|
p_lhs_cur = lhs.blocks
|
|
p_lhs_end = lhs.blocks + len(lhs)
|
|
|
|
while p_lhs_cur != p_lhs_end:
|
|
product = (util.zext(p_lhs_cur[0], u64) *
|
|
util.zext(rhs, u64) +
|
|
util.zext(carry, u64))
|
|
result_cur[0] = util.itrunc(product & _bitmask_u64(32), u32)
|
|
carry = util.itrunc(product >> u64(32), u32)
|
|
p_lhs_cur += 1
|
|
result_cur += 1
|
|
|
|
if carry:
|
|
result_cur[0] = carry
|
|
result.length = len(lhs) + 1
|
|
else:
|
|
result.length = len(lhs)
|
|
|
|
def mul2(self, in_: BigInt):
|
|
result = self
|
|
carry = u32(0)
|
|
result_cur = result.blocks
|
|
p_lhs_cur = in_.blocks
|
|
p_lhs_end = in_.blocks + len(in_)
|
|
|
|
while p_lhs_cur != p_lhs_end:
|
|
cur = p_lhs_cur[0]
|
|
result_cur[0] = (cur << u32(1)) | carry
|
|
carry = cur >> u32(31)
|
|
p_lhs_cur += 1
|
|
result_cur += 1
|
|
|
|
if carry:
|
|
result_cur[0] = carry
|
|
result.length = len(in_) + 1
|
|
else:
|
|
result.length = len(in_)
|
|
|
|
def mul2(self):
|
|
result = self
|
|
carry = u32(0)
|
|
cur = result.blocks
|
|
end = result.blocks + len(result)
|
|
|
|
while cur != end:
|
|
tmpcur = cur[0]
|
|
cur[0] = (tmpcur << u32(1)) | carry
|
|
carry = tmpcur >> u32(31)
|
|
cur += 1
|
|
|
|
if carry:
|
|
cur[0] = carry
|
|
result.length = len(result) + 1
|
|
|
|
def mul10(self):
|
|
result = self
|
|
carry = u64(0)
|
|
cur = result.blocks
|
|
end = result.blocks + len(result)
|
|
|
|
while cur != end:
|
|
product = util.zext(cur[0], u64) * u64(10) + carry
|
|
cur[0] = util.itrunc(product & _bitmask_u64(32), u32)
|
|
carry = product >> u64(32)
|
|
cur += 1
|
|
|
|
if carry:
|
|
cur[0] = util.itrunc(carry, u32)
|
|
result.length = len(result) + 1
|
|
|
|
def pow10(self, exponent: u32, temp: BigInt):
|
|
result = self
|
|
cur_temp = result
|
|
p_next_temp = temp
|
|
table_idx = u32(0)
|
|
|
|
small_exponent = exponent & _bitmask_u32(3)
|
|
cur_temp.set(_pow10_tab(small_exponent))
|
|
exponent >>= u32(3)
|
|
|
|
while exponent:
|
|
if exponent & u32(1):
|
|
p_next_temp.mul(cur_temp, BigInt.make_pow10(table_idx))
|
|
p_swap = cur_temp
|
|
cur_temp = p_next_temp
|
|
p_next_temp = p_swap
|
|
|
|
table_idx += u32(1)
|
|
exponent >>= u32(1)
|
|
|
|
if cur_temp is not result:
|
|
cur_temp.copy(result)
|
|
|
|
def mul_pow10(self, exponent: u32, temp: BigInt):
|
|
in_ = self
|
|
table_idx = u32(0)
|
|
|
|
small_exponent = exponent & _bitmask_u32(3)
|
|
if small_exponent:
|
|
temp.mul(in_, _pow10_tab(small_exponent))
|
|
cur_temp = temp
|
|
p_next_temp = in_
|
|
else:
|
|
cur_temp = in_
|
|
p_next_temp = temp
|
|
|
|
exponent >>= u32(3)
|
|
|
|
while exponent:
|
|
if exponent & u32(1):
|
|
p_next_temp.mul(cur_temp, BigInt.make_pow10(table_idx))
|
|
p_swap = cur_temp
|
|
cur_temp = p_next_temp
|
|
p_next_temp = p_swap
|
|
|
|
table_idx += u32(1)
|
|
exponent >>= u32(1)
|
|
|
|
if cur_temp is not in_:
|
|
cur_temp.copy(in_)
|
|
|
|
def pow2(self, exponent: u32):
|
|
result = self
|
|
block_idx = int(exponent) >> 5
|
|
|
|
for i in range(block_idx + 1):
|
|
result[i] = u32(0)
|
|
result.length = block_idx + 1
|
|
|
|
bit_idx = int(exponent) & (32 - 1)
|
|
self[block_idx] |= (u32(1) << u32(bit_idx))
|
|
|
|
def div_with_rem_maxq9(self, divisor: BigInt):
|
|
dividend = self
|
|
length = len(divisor)
|
|
if len(dividend) < len(divisor):
|
|
return u32(0)
|
|
|
|
final_divisor_block = divisor.blocks + (length - 1)
|
|
final_dividend_block = dividend.blocks + (length - 1)
|
|
quotient = final_dividend_block[0] // (final_divisor_block[0] + u32(1))
|
|
|
|
if quotient:
|
|
divisor_cur = divisor.blocks
|
|
dividend_cur = dividend.blocks
|
|
borrow = u64(0)
|
|
carry = u64(0)
|
|
|
|
while True:
|
|
product = util.zext(divisor_cur[0], u64) * util.zext(quotient, u64) + carry
|
|
carry = product >> u64(32)
|
|
|
|
difference = util.zext(dividend_cur[0], u64) - (product & _bitmask_u64(32)) - borrow
|
|
borrow = (difference >> u64(32)) & u64(1)
|
|
|
|
dividend_cur[0] = util.itrunc(difference & _bitmask_u64(32), u32)
|
|
divisor_cur += 1
|
|
dividend_cur += 1
|
|
|
|
if divisor_cur > final_divisor_block:
|
|
break
|
|
|
|
while length > 0 and dividend[length - 1] == u32(0):
|
|
length -= 1
|
|
|
|
dividend.length = length
|
|
|
|
if dividend >= divisor:
|
|
divisor_cur = divisor.blocks
|
|
dividend_cur = dividend.blocks
|
|
borrow = u64(0)
|
|
|
|
quotient += u32(1)
|
|
|
|
while True:
|
|
difference = util.zext(dividend_cur[0], u64) - util.zext(divisor_cur[0], u64) - borrow
|
|
borrow = (difference >> u64(32)) & u64(1)
|
|
|
|
dividend_cur[0] = util.itrunc(difference & _bitmask_u64(32), u32)
|
|
divisor_cur += 1
|
|
dividend_cur += 1
|
|
|
|
if divisor_cur > final_divisor_block:
|
|
break
|
|
|
|
while length > 0 and dividend[length - 1] == u32(0):
|
|
length -= 1
|
|
|
|
dividend.length = length
|
|
|
|
return quotient
|
|
|
|
def lshift(self, shift: u32):
|
|
result = self
|
|
shift_blocks = int(shift // u32(32))
|
|
shift_bits = int(shift % u32(32))
|
|
|
|
p_in_blocks = result.blocks
|
|
in_length = len(result)
|
|
|
|
if not shift_bits:
|
|
p_in_cur = result.blocks + len(result)
|
|
p_out_cur = p_in_cur + shift_blocks
|
|
while p_in_cur >= p_in_blocks:
|
|
p_out_cur[0] = p_in_cur[0]
|
|
p_in_cur -= 1
|
|
p_out_cur -= 1
|
|
|
|
for i in range(shift_blocks):
|
|
result[i] = u32(0)
|
|
|
|
result.length += shift_blocks
|
|
else:
|
|
in_block_idx = in_length - 1
|
|
out_block_idx = in_length + shift_blocks
|
|
|
|
low_bits_shift = u32(32 - shift_bits)
|
|
high_bits = u32(0)
|
|
block = result[in_block_idx]
|
|
low_bits = block >> low_bits_shift
|
|
|
|
result.length = out_block_idx + 1
|
|
|
|
while in_block_idx > 0:
|
|
result[out_block_idx] = high_bits | low_bits
|
|
high_bits = block << u32(shift_bits)
|
|
in_block_idx -= 1
|
|
out_block_idx -= 1
|
|
block = result[in_block_idx]
|
|
low_bits = block >> low_bits_shift
|
|
|
|
result[out_block_idx] = high_bits | low_bits
|
|
result[out_block_idx - 1] = block << u32(shift_bits)
|
|
|
|
for i in range(shift_blocks):
|
|
result[i] = u32(0)
|
|
|
|
if result[len(result) - 1] == u32(0):
|
|
result.length -= 1
|
|
|
|
def dragon4(bigints,
|
|
exponent: i32,
|
|
mantissa_bit: u32,
|
|
has_unequal_margins: bool,
|
|
digit_mode: int,
|
|
cutoff_mode: int,
|
|
cutoff_max: int,
|
|
cutoff_min: int,
|
|
out_buffer: cobj,
|
|
buffer_size: int,
|
|
out_exponent: Ptr[i32]):
|
|
|
|
cur_digit = out_buffer
|
|
mantissa = bigints[0]
|
|
scale = bigints[1]
|
|
scaled_value = bigints[2]
|
|
scaled_margin_low = bigints[3]
|
|
optional_margin_high = bigints[4]
|
|
temp1 = bigints[5]
|
|
temp2 = bigints[6]
|
|
|
|
log10_2 = 0.30102999566398119521373889472449
|
|
is_even = mantissa.even
|
|
|
|
if not mantissa:
|
|
cur_digit[0] = byte(48)
|
|
out_exponent[0] = i32(0)
|
|
return 1
|
|
|
|
mantissa.copy(scaled_value)
|
|
exponent_u32 = util.bitcast(exponent, u32)
|
|
|
|
if has_unequal_margins:
|
|
if exponent > i32(0):
|
|
scaled_value.lshift(exponent_u32 + u32(2))
|
|
scale.set(u32(4))
|
|
scaled_margin_low.pow2(exponent_u32)
|
|
optional_margin_high.pow2(exponent_u32 + u32(1))
|
|
else:
|
|
scaled_value.lshift(u32(2))
|
|
scale.pow2(util.bitcast(-exponent + i32(2), u32))
|
|
scaled_margin_low.set(u32(1))
|
|
optional_margin_high.set(u32(2))
|
|
|
|
scaled_margin_high = optional_margin_high
|
|
else:
|
|
if exponent > i32(0):
|
|
scaled_value.lshift(exponent_u32 + u32(1))
|
|
scale.set(u32(2))
|
|
scaled_margin_low.pow2(exponent_u32)
|
|
else:
|
|
scaled_value.lshift(u32(1))
|
|
scale.pow2(util.bitcast(-exponent + i32(1), u32))
|
|
scaled_margin_low.set(u32(1))
|
|
|
|
scaled_margin_high = scaled_margin_low
|
|
|
|
digit_exponent = util.fptosi(util.ceil64(util.sitofp(util.bitcast(mantissa_bit, i32) + exponent, float) * log10_2 - 0.69), int)
|
|
|
|
if cutoff_max >= 0 and cutoff_mode == _CUTOFF_MODE_FRACTION_LENGTH and digit_exponent <= -cutoff_max:
|
|
digit_exponent = -cutoff_max + 1
|
|
|
|
if digit_exponent > 0:
|
|
scale.mul_pow10(u32(digit_exponent), temp1)
|
|
elif digit_exponent < 0:
|
|
temp = temp1
|
|
pow10 = temp2
|
|
pow10.pow10(u32(-digit_exponent), temp)
|
|
|
|
temp.mul(scaled_value, pow10)
|
|
temp.copy(scaled_value)
|
|
|
|
temp.mul(scaled_margin_low, pow10)
|
|
temp.copy(scaled_margin_low)
|
|
|
|
if scaled_margin_high is not scaled_margin_low:
|
|
scaled_margin_high.mul2(scaled_margin_low)
|
|
|
|
if scaled_value >= scale:
|
|
digit_exponent += 1
|
|
else:
|
|
scaled_value.mul10()
|
|
scaled_margin_low.mul10()
|
|
if scaled_margin_high is not scaled_margin_low:
|
|
scaled_margin_high.mul2(scaled_margin_low)
|
|
|
|
cutoff_max_exponent = digit_exponent - buffer_size
|
|
if cutoff_max >= 0:
|
|
if cutoff_mode == _CUTOFF_MODE_TOTAL_LENGTH:
|
|
desired_cutoff_exponent = digit_exponent - cutoff_max
|
|
if desired_cutoff_exponent > cutoff_max_exponent:
|
|
cutoff_max_exponent = desired_cutoff_exponent
|
|
else:
|
|
desired_cutoff_exponent = -cutoff_max
|
|
if desired_cutoff_exponent > cutoff_max_exponent:
|
|
cutoff_max_exponent = desired_cutoff_exponent
|
|
|
|
cutoff_min_exponent = digit_exponent
|
|
if cutoff_min >= 0:
|
|
if cutoff_mode == _CUTOFF_MODE_TOTAL_LENGTH:
|
|
desired_cutoff_exponent = digit_exponent - cutoff_min
|
|
if desired_cutoff_exponent < cutoff_min_exponent:
|
|
cutoff_min_exponent = desired_cutoff_exponent
|
|
else:
|
|
desired_cutoff_exponent = -cutoff_min
|
|
if desired_cutoff_exponent < cutoff_min_exponent:
|
|
cutoff_min_exponent = desired_cutoff_exponent
|
|
|
|
out_exponent[0] = i32(digit_exponent - 1)
|
|
low = False
|
|
high = False
|
|
output_digit = u32(0)
|
|
|
|
hi_block = scale[len(scale) - 1]
|
|
if hi_block < u32(8) or hi_block > u32(429496729):
|
|
hi_block_log2 = _log_base2_32(hi_block)
|
|
shift = (u32(32) + u32(27) - hi_block_log2) % u32(32)
|
|
|
|
scale.lshift(shift)
|
|
scaled_value.lshift(shift)
|
|
scaled_margin_low.lshift(shift)
|
|
if scaled_margin_high is not scaled_margin_low:
|
|
scaled_margin_high.mul2(scaled_margin_low)
|
|
|
|
if digit_mode == _DIGIT_MODE_UNIQUE:
|
|
while True:
|
|
scaled_value_high = temp1
|
|
digit_exponent -= 1
|
|
output_digit = scaled_value.div_with_rem_maxq9(scale)
|
|
|
|
scaled_value_high.add(scaled_value, scaled_margin_high)
|
|
comp = scaled_value.compare(scaled_margin_low)
|
|
low = (comp <= 0) if is_even else (comp < 0)
|
|
comp = scaled_value_high.compare(scale)
|
|
high = (comp >= 0) if is_even else (comp > 0)
|
|
|
|
if (((low or high) and (digit_exponent <= cutoff_min_exponent)) or
|
|
digit_exponent == cutoff_max_exponent):
|
|
break
|
|
|
|
cur_digit[0] = byte(48 + int(output_digit))
|
|
cur_digit += 1
|
|
|
|
scaled_value.mul10()
|
|
scaled_margin_low.mul10()
|
|
if scaled_margin_high is not scaled_margin_low:
|
|
scaled_margin_high.mul2(scaled_margin_low)
|
|
else:
|
|
while True:
|
|
digit_exponent -= 1
|
|
output_digit = scaled_value.div_with_rem_maxq9(scale)
|
|
|
|
if len(scaled_value) == 0 or digit_exponent == cutoff_max_exponent:
|
|
break
|
|
|
|
cur_digit[0] = byte(48 + int(output_digit))
|
|
cur_digit += 1
|
|
|
|
scaled_value.mul10()
|
|
|
|
round_down = low
|
|
if low == high:
|
|
scaled_value.mul2()
|
|
compare = scaled_value.compare(scale)
|
|
round_down = (compare < 0)
|
|
|
|
if compare == 0:
|
|
round_down = (output_digit & u32(1) == u32(0))
|
|
|
|
if round_down:
|
|
cur_digit[0] = byte(48 + int(output_digit))
|
|
cur_digit += 1
|
|
else:
|
|
if output_digit == u32(9):
|
|
while True:
|
|
if cur_digit == out_buffer:
|
|
cur_digit[0] = byte(48 + 1)
|
|
cur_digit += 1
|
|
out_exponent[0] += i32(1)
|
|
break
|
|
|
|
cur_digit -= 1
|
|
if cur_digit[0] != byte(48 + 9):
|
|
cur_digit[0] = byte(int(cur_digit[0]) + 1)
|
|
cur_digit += 1
|
|
break
|
|
else:
|
|
cur_digit[0] = byte(48 + int(output_digit) + 1)
|
|
cur_digit += 1
|
|
|
|
output_len = cur_digit - out_buffer
|
|
return output_len
|
|
|
|
def format_positional(buffer: cobj,
|
|
buffer_size: int,
|
|
mantissa,
|
|
exponent: i32,
|
|
signbit: byte,
|
|
mantissa_bit: u32,
|
|
has_unequal_margins: bool,
|
|
digit_mode: int,
|
|
cutoff_mode: int,
|
|
precision: i32,
|
|
min_digits: i32,
|
|
trim_mode: int,
|
|
digits_left: int,
|
|
digits_right: int):
|
|
num_whole_digits = 0
|
|
has_sign = 0
|
|
max_print_len = buffer_size - 1
|
|
pos = 0
|
|
num_fraction_digits = 0
|
|
print_exponent = i32(0)
|
|
|
|
if signbit == byte(43) and pos < max_print_len: # '+'
|
|
buffer[pos] = byte(43)
|
|
pos += 1
|
|
has_sign = 1
|
|
elif signbit == byte(45) and pos < max_print_len: # '-'
|
|
buffer[pos] = byte(45)
|
|
pos += 1
|
|
has_sign = 1
|
|
|
|
num_digits = dragon4(mantissa, exponent, mantissa_bit,
|
|
has_unequal_margins, digit_mode,
|
|
cutoff_mode, int(precision), int(min_digits),
|
|
buffer + has_sign, max_print_len - has_sign,
|
|
__ptr__(print_exponent))
|
|
|
|
if print_exponent >= i32(0):
|
|
num_whole_digits = int(print_exponent) + 1
|
|
if num_digits <= num_whole_digits:
|
|
count = num_whole_digits - num_digits
|
|
pos += num_digits
|
|
|
|
if pos + count > max_print_len:
|
|
count = max_print_len - pos
|
|
|
|
num_digits += count
|
|
while count > 0:
|
|
buffer[pos] = byte(48)
|
|
pos += 1
|
|
count -= 1
|
|
elif num_digits > num_whole_digits:
|
|
num_fraction_digits = num_digits - num_whole_digits
|
|
max_fraction_digits = max_print_len - num_whole_digits - 1 - pos
|
|
if num_fraction_digits > max_fraction_digits:
|
|
num_fraction_digits = max_fraction_digits
|
|
|
|
str.memmove(buffer + pos + num_whole_digits + 1,
|
|
buffer + pos + num_whole_digits,
|
|
num_fraction_digits)
|
|
pos += num_whole_digits
|
|
buffer[pos] = byte(46) # '.'
|
|
num_digits = num_whole_digits + 1 + num_fraction_digits
|
|
pos += 1 + num_fraction_digits
|
|
else:
|
|
num_fraction_zeros = 0
|
|
if pos + 2 < max_print_len:
|
|
max_fraction_zeros = max_print_len - 2 - pos
|
|
num_fraction_zeros = -(int(print_exponent) + 1)
|
|
if num_fraction_zeros > max_fraction_zeros:
|
|
num_fraction_zeros = max_fraction_zeros
|
|
|
|
digits_start_idx = 2 + num_fraction_zeros
|
|
num_fraction_digits = num_digits
|
|
max_fraction_digits = max_print_len - digits_start_idx - pos
|
|
if num_fraction_digits > max_fraction_digits:
|
|
num_fraction_digits = max_fraction_digits
|
|
|
|
str.memmove(buffer + pos + digits_start_idx,
|
|
buffer + pos,
|
|
num_fraction_digits)
|
|
|
|
for i in range(2, digits_start_idx):
|
|
buffer[pos + i] = byte(48)
|
|
|
|
num_fraction_digits += num_fraction_zeros
|
|
num_digits = num_fraction_digits
|
|
|
|
if pos + 1 < max_print_len:
|
|
buffer[pos + 1] = byte(46) # '.'
|
|
|
|
if pos < max_print_len:
|
|
buffer[pos] = byte(48)
|
|
num_digits += 1
|
|
|
|
num_whole_digits = 1
|
|
pos += 2 + num_fraction_digits
|
|
|
|
if (trim_mode != _TRIM_MODE_DPT_ZEROS and
|
|
num_fraction_digits == 0 and pos < max_print_len):
|
|
buffer[pos] = byte(46) # '.'
|
|
pos += 1
|
|
|
|
add_digits = int(min_digits if digit_mode == _DIGIT_MODE_UNIQUE else precision)
|
|
desired_fractional_digits = 0 if add_digits < 0 else add_digits
|
|
if cutoff_mode == _CUTOFF_MODE_TOTAL_LENGTH:
|
|
desired_fractional_digits = add_digits - num_whole_digits
|
|
|
|
if trim_mode == _TRIM_MODE_LEAVE_ONE_ZERO:
|
|
if num_fraction_digits == 0 and pos < max_print_len:
|
|
buffer[pos] = byte(48)
|
|
pos += 1
|
|
num_fraction_digits += 1
|
|
elif (trim_mode == _TRIM_MODE_NONE and
|
|
desired_fractional_digits > num_fraction_digits and
|
|
pos < max_print_len):
|
|
count = desired_fractional_digits - num_fraction_digits
|
|
if pos + count > max_print_len:
|
|
count = max_print_len - pos
|
|
num_fraction_digits += count
|
|
|
|
while count > 0:
|
|
buffer[pos] = byte(48)
|
|
pos += 1
|
|
count -= 1
|
|
|
|
if trim_mode != _TRIM_MODE_NONE and num_fraction_digits > 0:
|
|
while buffer[pos - 1] == byte(48):
|
|
pos -= 1
|
|
num_fraction_digits -= 1
|
|
|
|
if buffer[pos - 1] == byte(46): # '.'
|
|
if trim_mode == _TRIM_MODE_LEAVE_ONE_ZERO:
|
|
buffer[pos] = byte(48)
|
|
pos += 1
|
|
num_fraction_digits += 1
|
|
elif trim_mode == _TRIM_MODE_DPT_ZEROS:
|
|
pos -= 1
|
|
|
|
if digits_right >= num_fraction_digits:
|
|
count = digits_right - num_fraction_digits
|
|
|
|
if (trim_mode == _TRIM_MODE_DPT_ZEROS and
|
|
num_fraction_digits == 0 and
|
|
pos < max_print_len):
|
|
buffer[pos] = byte(32) # ' '
|
|
pos += 1
|
|
|
|
if pos + count > max_print_len:
|
|
count = max_print_len - pos
|
|
|
|
while count > 0:
|
|
buffer[pos] = byte(32) # ' '
|
|
pos += 1
|
|
count -= 1
|
|
|
|
if digits_left > num_whole_digits + has_sign:
|
|
shift = digits_left - (num_whole_digits + has_sign)
|
|
count = pos
|
|
|
|
if count + shift > max_print_len:
|
|
count = max_print_len - shift
|
|
|
|
if count > 0:
|
|
str.memmove(buffer + shift, buffer, count)
|
|
|
|
pos = shift + count
|
|
while shift > 0:
|
|
buffer[shift - 1] = byte(32) # ' '
|
|
shift -= 1
|
|
|
|
# buffer[pos] = byte(0)
|
|
return pos
|
|
|
|
def format_scientific(buffer: cobj,
|
|
buffer_size: int,
|
|
mantissa,
|
|
exponent: i32,
|
|
signbit: byte,
|
|
mantissa_bit: u32,
|
|
has_unequal_margins: bool,
|
|
digit_mode: int,
|
|
precision: i32,
|
|
min_digits: i32,
|
|
trim_mode: int,
|
|
digits_left: int,
|
|
exp_digits: int):
|
|
cur_out = buffer
|
|
leftchars = 1 + int(signbit == byte(43) or signbit == byte(45)) # '+'/'-'
|
|
print_exponent = i32(0)
|
|
|
|
if digits_left > leftchars:
|
|
i = 0
|
|
while i < digits_left - leftchars and buffer_size > 1:
|
|
cur_out[0] = byte(32) # ' '
|
|
cur_out += 1
|
|
buffer_size -= 1
|
|
i += 1
|
|
|
|
if signbit == byte(43) and buffer_size > 1: # '+'
|
|
cur_out[0] = byte(43)
|
|
cur_out += 1
|
|
buffer_size -= 1
|
|
elif signbit == byte(45) and buffer_size > 1: # '-'
|
|
cur_out[0] = byte(45)
|
|
cur_out += 1
|
|
buffer_size -= 1
|
|
|
|
num_digits = dragon4(mantissa, exponent, mantissa_bit, has_unequal_margins,
|
|
digit_mode, _CUTOFF_MODE_TOTAL_LENGTH,
|
|
-1 if precision < i32(0) else int(precision) + 1,
|
|
-1 if min_digits < i32(0) else int(min_digits) + 1,
|
|
cur_out, buffer_size, __ptr__(print_exponent))
|
|
|
|
if buffer_size > 1:
|
|
cur_out += 1
|
|
buffer_size -= 1
|
|
|
|
num_fraction_digits = num_digits - 1
|
|
if num_fraction_digits > 0 and buffer_size > 1:
|
|
max_fraction_digits = buffer_size - 2
|
|
if num_fraction_digits > max_fraction_digits:
|
|
num_fraction_digits = max_fraction_digits
|
|
|
|
str.memmove(cur_out + 1, cur_out, num_fraction_digits)
|
|
cur_out[0] = byte(46) # '.'
|
|
cur_out += 1 + num_fraction_digits
|
|
buffer_size -= 1 + num_fraction_digits
|
|
|
|
if (trim_mode != _TRIM_MODE_DPT_ZEROS and
|
|
num_fraction_digits == 0 and
|
|
buffer_size > 1):
|
|
cur_out[0] = byte(46) # '.'
|
|
cur_out += 1
|
|
buffer_size -= 1
|
|
|
|
add_digits = int(min_digits) if digit_mode == _DIGIT_MODE_UNIQUE else int(precision)
|
|
add_digits = 0 if add_digits < 0 else add_digits
|
|
if trim_mode == _TRIM_MODE_LEAVE_ONE_ZERO:
|
|
if num_fraction_digits == 0 and buffer_size > 1:
|
|
cur_out[0] = byte(48)
|
|
cur_out += 1
|
|
buffer_size -= 1
|
|
num_fraction_digits += 1
|
|
elif trim_mode == _TRIM_MODE_NONE:
|
|
if add_digits > num_fraction_digits:
|
|
num_zeros = add_digits - num_fraction_digits
|
|
|
|
if num_zeros > buffer_size - 1:
|
|
num_zeros = buffer_size - 1
|
|
|
|
end = cur_out + num_zeros
|
|
while cur_out < end:
|
|
cur_out[0] = byte(48)
|
|
num_fraction_digits += 1
|
|
cur_out += 1
|
|
|
|
if trim_mode != _TRIM_MODE_NONE and num_fraction_digits > 0:
|
|
cur_out -= 1
|
|
while cur_out[0] == byte(48):
|
|
cur_out -= 1
|
|
buffer_size += 1
|
|
num_fraction_digits -= 1
|
|
|
|
if trim_mode == _TRIM_MODE_LEAVE_ONE_ZERO and cur_out[0] == byte(46):
|
|
cur_out += 1
|
|
cur_out[0] = byte(48)
|
|
buffer_size -= 1
|
|
num_fraction_digits += 1
|
|
|
|
cur_out += 1
|
|
|
|
if buffer_size > 1:
|
|
exponent_buffer_t = (byte(0),) * 7
|
|
digits_t = (i32(0),) * 5
|
|
exponent_buffer = __ptr__(exponent_buffer_t).as_byte()
|
|
digits = Ptr[i32](__ptr__(digits_t).as_byte())
|
|
|
|
if exp_digits > 5:
|
|
exp_digits = 5
|
|
if exp_digits < 0:
|
|
exp_digits = 2
|
|
|
|
exponent_buffer[0] = byte(101) # 'e'
|
|
if print_exponent >= i32(0):
|
|
exponent_buffer[1] = byte(43) # '+'
|
|
else:
|
|
exponent_buffer[1] = byte(45) # '-'
|
|
print_exponent = -print_exponent
|
|
|
|
for i in range(5):
|
|
digits[i] = print_exponent % i32(10)
|
|
print_exponent //= i32(10)
|
|
|
|
i = 5
|
|
while i > exp_digits and digits[i - 1] == i32(0):
|
|
i -= 1
|
|
exp_size = i
|
|
|
|
while i > 0:
|
|
exponent_buffer[2 + (exp_size - i)] = byte(48 + int(digits[i - 1]))
|
|
i -= 1
|
|
|
|
count = exp_size + 2
|
|
if count > buffer_size - 1:
|
|
count = buffer_size - 1
|
|
|
|
str.memcpy(cur_out, exponent_buffer, count)
|
|
cur_out += count
|
|
buffer_size -= count
|
|
|
|
# cur_out[0] = byte(0)
|
|
return cur_out - buffer
|
|
|
|
def print_inf_nan(buffer: cobj,
|
|
buffer_size: int,
|
|
mantissa: u64,
|
|
mantissa_hex_width: int,
|
|
signbit: byte):
|
|
max_print_len = buffer_size - 1
|
|
pos = 0
|
|
|
|
if mantissa == u64(0):
|
|
if signbit == byte(43): # '+'
|
|
if pos < max_print_len - 1:
|
|
buffer[pos] = byte(43)
|
|
pos += 1
|
|
elif signbit == byte(45): # '-'
|
|
if pos < max_print_len - 1:
|
|
buffer[pos] = byte(45)
|
|
pos += 1
|
|
|
|
print_len = 3 if 3 < max_print_len - pos else max_print_len - pos
|
|
str.memcpy(buffer + pos, "inf".ptr, print_len)
|
|
# buffer[pos + print_len] = byte(0)
|
|
return pos + print_len
|
|
else:
|
|
print_len = 3 if 3 < max_print_len - pos else max_print_len - pos
|
|
str.memcpy(buffer + pos, "nan".ptr, print_len)
|
|
# buffer[pos + print_len] = byte(0)
|
|
return pos + print_len
|
|
|
|
def format_float_bits(buffer: cobj,
|
|
buffer_size: int,
|
|
mantissa,
|
|
exponent: i32,
|
|
signbit: byte,
|
|
mantissa_bit: u32,
|
|
has_unequal_margins: bool,
|
|
scientific: bool,
|
|
digit_mode: int,
|
|
cutoff_mode: int,
|
|
precision: i32,
|
|
min_digits: i32,
|
|
sign: bool,
|
|
trim_mode: int,
|
|
digits_left: int,
|
|
digits_right: int,
|
|
exp_digits: int):
|
|
if scientific:
|
|
return format_scientific(buffer, buffer_size, mantissa, exponent,
|
|
signbit, mantissa_bit, has_unequal_margins,
|
|
digit_mode, precision, min_digits, trim_mode,
|
|
digits_left, exp_digits)
|
|
else:
|
|
return format_positional(buffer, buffer_size, mantissa, exponent,
|
|
signbit, mantissa_bit, has_unequal_margins,
|
|
digit_mode, cutoff_mode, precision, min_digits,
|
|
trim_mode, digits_left, digits_right)
|
|
|
|
def _trim_mode_code(trim_mode: str):
|
|
if trim_mode == 'k':
|
|
return _TRIM_MODE_NONE
|
|
elif trim_mode == '0':
|
|
return _TRIM_MODE_LEAVE_ONE_ZERO
|
|
elif trim_mode == '.':
|
|
return _TRIM_MODE_ZEROS
|
|
elif trim_mode == '-':
|
|
return _TRIM_MODE_DPT_ZEROS
|
|
else:
|
|
raise ValueError(f"if supplied, trim must be 'k', '.', '0' or '-' found `{trim_mode}`")
|
|
|
|
def _from_buffer(buffer: cobj, n: int):
|
|
p = cobj(n)
|
|
str.memcpy(p, buffer, n)
|
|
return str(p, n)
|
|
|
|
# Buffer size that can hold any float128 string
|
|
# TODO: Make this smaller for other float types
|
|
_BUFFER_SIZE: Static[int] = 16384
|
|
|
|
def format_ieee16(value: float16,
|
|
scientific: bool = False,
|
|
unique: bool = True,
|
|
fractional: bool = True,
|
|
precision: int = -1,
|
|
min_digits: int = -1,
|
|
sign: bool = False,
|
|
trim_mode: str = 'k',
|
|
digits_left: int = -1,
|
|
digits_right: int = -1,
|
|
exp_digits: int = -1):
|
|
bigint_data = __array__[u32](_BIGINT_DRAGON4_GROUPSIZE * _BIGINT_MAX_BLOCKS)
|
|
scratch = __array__[byte](_BUFFER_SIZE)
|
|
buffer = scratch.ptr
|
|
blocks = bigint_data.ptr
|
|
bigints = tuple(BigInt(0, blocks + (i * _BIGINT_MAX_BLOCKS))
|
|
for i in staticrange(_BIGINT_DRAGON4_GROUPSIZE))
|
|
|
|
signbit = byte(0)
|
|
digit_mode = _DIGIT_MODE_UNIQUE if unique else _DIGIT_MODE_EXACT
|
|
cutoff_mode = _CUTOFF_MODE_FRACTION_LENGTH if fractional else _CUTOFF_MODE_TOTAL_LENGTH
|
|
|
|
integer = util.zext(util.bitcast(value, u16), u32)
|
|
float_mantissa = integer & _bitmask_u32(10)
|
|
float_exponent = (integer >> u32(10)) & _bitmask_u32(5)
|
|
float_sign = integer >> u32(15)
|
|
|
|
if float_sign:
|
|
signbit = byte(45) # '-'
|
|
elif sign:
|
|
signbit = byte(43) # '+'
|
|
|
|
if float_exponent == _bitmask_u32(5):
|
|
n = print_inf_nan(buffer, _BUFFER_SIZE, util.zext(float_mantissa, u64), 3, signbit)
|
|
return _from_buffer(buffer, n)
|
|
|
|
mantissa = u32(0)
|
|
exponent = i32(0)
|
|
mantissa_bit = u32(0)
|
|
has_unequal_margins = False
|
|
|
|
if float_exponent:
|
|
mantissa = (u32(1) << u32(10)) | float_mantissa
|
|
exponent = util.bitcast(float_exponent, i32) - i32(15) - i32(10)
|
|
mantissa_bit = u32(10)
|
|
has_unequal_margins = (float_exponent != u32(1)) and (float_mantissa == u32(0))
|
|
else:
|
|
mantissa = float_mantissa
|
|
exponent = i32(1 - 15 - 10)
|
|
mantissa_bit = _log_base2_32(mantissa)
|
|
has_unequal_margins = False
|
|
|
|
bigints[0].set(mantissa)
|
|
n = format_float_bits(buffer,
|
|
_BUFFER_SIZE,
|
|
bigints,
|
|
exponent,
|
|
signbit,
|
|
mantissa_bit,
|
|
has_unequal_margins,
|
|
scientific,
|
|
digit_mode,
|
|
cutoff_mode,
|
|
i32(precision),
|
|
i32(min_digits),
|
|
sign,
|
|
_trim_mode_code(trim_mode),
|
|
digits_left,
|
|
digits_right,
|
|
exp_digits)
|
|
return _from_buffer(buffer, n)
|
|
|
|
def format_ieee32(value: float32,
|
|
scientific: bool = False,
|
|
unique: bool = True,
|
|
fractional: bool = True,
|
|
precision: int = -1,
|
|
min_digits: int = -1,
|
|
sign: bool = False,
|
|
trim_mode: str = 'k',
|
|
digits_left: int = -1,
|
|
digits_right: int = -1,
|
|
exp_digits: int = -1):
|
|
bigint_data = __array__[u32](_BIGINT_DRAGON4_GROUPSIZE * _BIGINT_MAX_BLOCKS)
|
|
scratch = __array__[byte](_BUFFER_SIZE)
|
|
buffer = scratch.ptr
|
|
blocks = bigint_data.ptr
|
|
bigints = tuple(BigInt(0, blocks + (i * _BIGINT_MAX_BLOCKS))
|
|
for i in staticrange(_BIGINT_DRAGON4_GROUPSIZE))
|
|
|
|
signbit = byte(0)
|
|
digit_mode = _DIGIT_MODE_UNIQUE if unique else _DIGIT_MODE_EXACT
|
|
cutoff_mode = _CUTOFF_MODE_FRACTION_LENGTH if fractional else _CUTOFF_MODE_TOTAL_LENGTH
|
|
|
|
integer = util.bitcast(value, u32)
|
|
float_mantissa = integer & _bitmask_u32(23)
|
|
float_exponent = (integer >> u32(23)) & _bitmask_u32(8)
|
|
float_sign = integer >> u32(31)
|
|
|
|
if float_sign:
|
|
signbit = byte(45) # '-'
|
|
elif sign:
|
|
signbit = byte(43) # '+'
|
|
|
|
if float_exponent == _bitmask_u32(8):
|
|
n = print_inf_nan(buffer, _BUFFER_SIZE, util.zext(float_mantissa, u64), 6, signbit)
|
|
return _from_buffer(buffer, n)
|
|
|
|
mantissa = u32(0)
|
|
exponent = i32(0)
|
|
mantissa_bit = u32(0)
|
|
has_unequal_margins = False
|
|
|
|
if float_exponent:
|
|
mantissa = (u32(1) << u32(23)) | float_mantissa
|
|
exponent = util.bitcast(float_exponent, i32) - i32(127) - i32(23)
|
|
mantissa_bit = u32(23)
|
|
has_unequal_margins = (float_exponent != u32(1)) and (float_mantissa == u32(0))
|
|
else:
|
|
mantissa = float_mantissa
|
|
exponent = i32(1 - 127 - 23)
|
|
mantissa_bit = _log_base2_32(mantissa)
|
|
has_unequal_margins = False
|
|
|
|
bigints[0].set(mantissa)
|
|
n = format_float_bits(buffer,
|
|
_BUFFER_SIZE,
|
|
bigints,
|
|
exponent,
|
|
signbit,
|
|
mantissa_bit,
|
|
has_unequal_margins,
|
|
scientific,
|
|
digit_mode,
|
|
cutoff_mode,
|
|
i32(precision),
|
|
i32(min_digits),
|
|
sign,
|
|
_trim_mode_code(trim_mode),
|
|
digits_left,
|
|
digits_right,
|
|
exp_digits)
|
|
return _from_buffer(buffer, n)
|
|
|
|
def format_ieee64(value: float,
|
|
scientific: bool = False,
|
|
unique: bool = True,
|
|
fractional: bool = True,
|
|
precision: int = -1,
|
|
min_digits: int = -1,
|
|
sign: bool = False,
|
|
trim_mode: str = 'k',
|
|
digits_left: int = -1,
|
|
digits_right: int = -1,
|
|
exp_digits: int = -1):
|
|
bigint_data = __array__[u32](_BIGINT_DRAGON4_GROUPSIZE * _BIGINT_MAX_BLOCKS)
|
|
scratch = __array__[byte](_BUFFER_SIZE)
|
|
buffer = scratch.ptr
|
|
blocks = bigint_data.ptr
|
|
bigints = tuple(BigInt(0, blocks + (i * _BIGINT_MAX_BLOCKS))
|
|
for i in staticrange(_BIGINT_DRAGON4_GROUPSIZE))
|
|
|
|
signbit = byte(0)
|
|
digit_mode = _DIGIT_MODE_UNIQUE if unique else _DIGIT_MODE_EXACT
|
|
cutoff_mode = _CUTOFF_MODE_FRACTION_LENGTH if fractional else _CUTOFF_MODE_TOTAL_LENGTH
|
|
|
|
integer = util.bitcast(value, u64)
|
|
float_mantissa = integer & _bitmask_u64(52)
|
|
float_exponent = util.itrunc(integer >> u64(52), u32) & _bitmask_u32(11)
|
|
float_sign = integer >> u64(63)
|
|
|
|
if float_sign:
|
|
signbit = byte(45) # '-'
|
|
elif sign:
|
|
signbit = byte(43) # '+'
|
|
|
|
if float_exponent == _bitmask_u32(11):
|
|
n = print_inf_nan(buffer, _BUFFER_SIZE, float_mantissa, 13, signbit)
|
|
return _from_buffer(buffer, n)
|
|
|
|
mantissa = u64(0)
|
|
exponent = i32(0)
|
|
mantissa_bit = u32(0)
|
|
has_unequal_margins = False
|
|
|
|
if float_exponent:
|
|
mantissa = (u64(1) << u64(52)) | float_mantissa
|
|
exponent = util.bitcast(float_exponent, i32) - i32(1023) - i32(52)
|
|
mantissa_bit = u32(52)
|
|
has_unequal_margins = (float_exponent != u32(1)) and (float_mantissa == u64(0))
|
|
else:
|
|
mantissa = float_mantissa
|
|
exponent = i32(1 - 1023 - 52)
|
|
mantissa_bit = util.itrunc(_log_base2_64(mantissa), u32)
|
|
has_unequal_margins = False
|
|
|
|
bigints[0].set(mantissa)
|
|
n = format_float_bits(buffer,
|
|
_BUFFER_SIZE,
|
|
bigints,
|
|
exponent,
|
|
signbit,
|
|
mantissa_bit,
|
|
has_unequal_margins,
|
|
scientific,
|
|
digit_mode,
|
|
cutoff_mode,
|
|
i32(precision),
|
|
i32(min_digits),
|
|
sign,
|
|
_trim_mode_code(trim_mode),
|
|
digits_left,
|
|
digits_right,
|
|
exp_digits)
|
|
return _from_buffer(buffer, n)
|
|
|
|
def format_ieee128(value: float128,
|
|
scientific: bool = False,
|
|
unique: bool = True,
|
|
fractional: bool = True,
|
|
precision: int = -1,
|
|
min_digits: int = -1,
|
|
sign: bool = False,
|
|
trim_mode: str = 'k',
|
|
digits_left: int = -1,
|
|
digits_right: int = -1,
|
|
exp_digits: int = -1):
|
|
bigint_data = __array__[u32](_BIGINT_DRAGON4_GROUPSIZE * _BIGINT_MAX_BLOCKS)
|
|
scratch = __array__[byte](_BUFFER_SIZE)
|
|
buffer = scratch.ptr
|
|
blocks = bigint_data.ptr
|
|
bigints = tuple(BigInt(0, blocks + (i * _BIGINT_MAX_BLOCKS))
|
|
for i in staticrange(_BIGINT_DRAGON4_GROUPSIZE))
|
|
|
|
signbit = byte(0)
|
|
digit_mode = _DIGIT_MODE_UNIQUE if unique else _DIGIT_MODE_EXACT
|
|
cutoff_mode = _CUTOFF_MODE_FRACTION_LENGTH if fractional else _CUTOFF_MODE_TOTAL_LENGTH
|
|
|
|
integer = util.bitcast(value, u128)
|
|
val_hi = util.itrunc(integer >> u128(64), u64)
|
|
val_lo = util.itrunc(integer & ((u128(1) << u128(64)) - u128(1)), u64)
|
|
mantissa_hi = val_hi & _bitmask_u64(48)
|
|
mantissa_lo = val_lo
|
|
|
|
float_exponent = util.itrunc(val_hi >> u64(48), u32) & _bitmask_u32(15)
|
|
float_sign = util.itrunc(val_hi >> u64(63), u32)
|
|
|
|
if float_sign:
|
|
signbit = byte(45) # '-'
|
|
elif sign:
|
|
signbit = byte(43) # '+'
|
|
|
|
if float_exponent == _bitmask_u32(15):
|
|
mantissa_zero = u64(1 if mantissa_hi or mantissa_lo else 0)
|
|
n = print_inf_nan(buffer, _BUFFER_SIZE, mantissa_zero, 16, signbit)
|
|
return _from_buffer(buffer, n)
|
|
|
|
exponent = i32(0)
|
|
mantissa_bit = u32(0)
|
|
has_unequal_margins = False
|
|
|
|
if float_exponent:
|
|
mantissa_hi = (u64(1) << u64(48)) | mantissa_hi
|
|
exponent = util.bitcast(float_exponent, i32) - i32(16383) - i32(112)
|
|
mantissa_bit = u32(112)
|
|
has_unequal_margins = (float_exponent != u32(1)) and (mantissa_hi == u64(0)) and (mantissa_lo == u64(0))
|
|
else:
|
|
exponent = i32(1 - 16383 - 112)
|
|
mantissa_bit = util.itrunc(_log_base2_128(mantissa_hi, mantissa_lo), u32)
|
|
has_unequal_margins = False
|
|
|
|
bigints[0].set(mantissa_hi, mantissa_lo)
|
|
n = format_float_bits(buffer,
|
|
_BUFFER_SIZE,
|
|
bigints,
|
|
exponent,
|
|
signbit,
|
|
mantissa_bit,
|
|
has_unequal_margins,
|
|
scientific,
|
|
digit_mode,
|
|
cutoff_mode,
|
|
i32(precision),
|
|
i32(min_digits),
|
|
sign,
|
|
_trim_mode_code(trim_mode),
|
|
digits_left,
|
|
digits_right,
|
|
exp_digits)
|
|
return _from_buffer(buffer, n)
|
|
|
|
def format_float(value,
|
|
scientific: bool = False,
|
|
unique: bool = True,
|
|
fractional: bool = True,
|
|
precision: int = -1,
|
|
min_digits: int = -1,
|
|
sign: bool = False,
|
|
trim_mode: str = 'k',
|
|
digits_left: int = -1,
|
|
digits_right: int = -1,
|
|
exp_digits: int = -1):
|
|
if isinstance(value, float16):
|
|
return format_ieee16(value,
|
|
scientific=scientific,
|
|
unique=unique,
|
|
fractional=fractional,
|
|
precision=precision,
|
|
min_digits=min_digits,
|
|
sign=sign,
|
|
trim_mode=trim_mode,
|
|
digits_left=digits_left,
|
|
digits_right=digits_right,
|
|
exp_digits=exp_digits)
|
|
|
|
if isinstance(value, float32):
|
|
return format_ieee32(value,
|
|
scientific=scientific,
|
|
unique=unique,
|
|
fractional=fractional,
|
|
precision=precision,
|
|
min_digits=min_digits,
|
|
sign=sign,
|
|
trim_mode=trim_mode,
|
|
digits_left=digits_left,
|
|
digits_right=digits_right,
|
|
exp_digits=exp_digits)
|
|
|
|
if isinstance(value, float):
|
|
return format_ieee64(value,
|
|
scientific=scientific,
|
|
unique=unique,
|
|
fractional=fractional,
|
|
precision=precision,
|
|
min_digits=min_digits,
|
|
sign=sign,
|
|
trim_mode=trim_mode,
|
|
digits_left=digits_left,
|
|
digits_right=digits_right,
|
|
exp_digits=exp_digits)
|
|
|
|
if isinstance(value, float128):
|
|
return format_ieee128(value,
|
|
scientific=scientific,
|
|
unique=unique,
|
|
fractional=fractional,
|
|
precision=precision,
|
|
min_digits=min_digits,
|
|
sign=sign,
|
|
trim_mode=trim_mode,
|
|
digits_left=digits_left,
|
|
digits_right=digits_right,
|
|
exp_digits=exp_digits)
|
|
|
|
compile_error("cannot format non-float value")
|
|
|
|
def _none_or_positive_arg(x: Optional[int], name: str) -> int:
|
|
if x is None:
|
|
return -1
|
|
if x < 0:
|
|
raise ValueError(f"{name} must be >= 0")
|
|
return x
|
|
|
|
def format_float_positional(x,
|
|
precision: Optional[int] = None,
|
|
unique: bool = True,
|
|
fractional: bool = True,
|
|
trim: str = 'k',
|
|
sign: bool = False,
|
|
pad_left: Optional[int] = None,
|
|
pad_right: Optional[int] = None,
|
|
min_digits: Optional[int] = None):
|
|
precision = _none_or_positive_arg(precision, "precision")
|
|
pad_left = _none_or_positive_arg(pad_left, "pad_left")
|
|
pad_right = _none_or_positive_arg(pad_right, "pad_right")
|
|
min_digits = _none_or_positive_arg(min_digits, "min_digits")
|
|
|
|
if not fractional and precision == 0:
|
|
raise ValueError("precision must be greater than 0 if "
|
|
"fractional=False")
|
|
|
|
if min_digits > 0 and precision > 0 and min_digits > precision:
|
|
raise ValueError("min_digits must be less than or equal to precision")
|
|
|
|
return format_float(x, scientific=False, precision=precision, unique=unique,
|
|
fractional=fractional, trim_mode=trim, sign=sign, digits_left=pad_left,
|
|
digits_right=pad_right, min_digits=min_digits)
|
|
|
|
def format_float_scientific(x,
|
|
precision: Optional[int] = None,
|
|
unique: bool = True,
|
|
trim: str = 'k',
|
|
sign: bool = False,
|
|
pad_left: Optional[int] = None,
|
|
exp_digits: Optional[int] = None,
|
|
min_digits: Optional[int] = None):
|
|
precision = _none_or_positive_arg(precision, "precision")
|
|
pad_left = _none_or_positive_arg(pad_left, "pad_left")
|
|
exp_digits = _none_or_positive_arg(exp_digits, "exp_digits")
|
|
min_digits = _none_or_positive_arg(min_digits, "min_digits")
|
|
|
|
if min_digits > 0 and precision > 0 and min_digits > precision:
|
|
raise ValueError("min_digits must be less than or equal to precision")
|
|
|
|
return format_float(x, scientific=True, precision=precision, unique=unique,
|
|
trim_mode=trim, sign=sign, digits_left=pad_left,
|
|
exp_digits=exp_digits, min_digits=min_digits)
|