1mod stackvec;
2
3use minimal_lexical::bigint::Bigint;
4use minimal_lexical::extended_float::ExtendedFloat;
5use minimal_lexical::num::Float;
6use minimal_lexical::number::Number;
7use minimal_lexical::slow;
8use stackvec::vec_from_u32;
9
10fn b<F: Float>(float: F) -> (u64, i32) {
11    let fp = slow::b(float);
12    (fp.mant, fp.exp)
13}
14
15fn bh<F: Float>(float: F) -> (u64, i32) {
16    let fp = slow::bh(float);
17    (fp.mant, fp.exp)
18}
19
20#[test]
21fn b_test() {
22    assert_eq!(b(1e-45_f32), (1, -149));
23    assert_eq!(b(5e-324_f64), (1, -1074));
24    assert_eq!(b(1e-323_f64), (2, -1074));
25    assert_eq!(b(2e-323_f64), (4, -1074));
26    assert_eq!(b(3e-323_f64), (6, -1074));
27    assert_eq!(b(4e-323_f64), (8, -1074));
28    assert_eq!(b(5e-323_f64), (10, -1074));
29    assert_eq!(b(6e-323_f64), (12, -1074));
30    assert_eq!(b(7e-323_f64), (14, -1074));
31    assert_eq!(b(8e-323_f64), (16, -1074));
32    assert_eq!(b(9e-323_f64), (18, -1074));
33    assert_eq!(b(1_f32), (8388608, -23));
34    assert_eq!(b(1_f64), (4503599627370496, -52));
35    assert_eq!(b(1e38_f32), (9860761, 103));
36    assert_eq!(b(1e308_f64), (5010420900022432, 971));
37}
38
39#[test]
40fn bh_test() {
41    assert_eq!(bh(1e-45_f32), (3, -150));
42    assert_eq!(bh(5e-324_f64), (3, -1075));
43    assert_eq!(bh(1_f32), (16777217, -24));
44    assert_eq!(bh(1_f64), (9007199254740993, -53));
45    assert_eq!(bh(1e38_f32), (19721523, 102));
46    assert_eq!(bh(1e308_f64), (10020841800044865, 970));
47}
48
49#[test]
50fn slow_test() {
51    // 5e-324, round-down.
52    let integer = b"2";
53    let fraction = b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999";
54    let num = Number {
55        mantissa: 2470328229206232720,
56        exponent: -342,
57        many_digits: true,
58    };
59    let fp = ExtendedFloat {
60        mant: 1 << 63,
61        exp: -63,
62    };
63    let result = slow::slow::<f64, _, _>(num.clone(), fp, integer.iter(), fraction.iter());
64    assert_eq!(result.mant, 0);
65    assert_eq!(result.exp, 0);
66
67    // 5e-324, round-up.
68    let fraction = b"47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251";
69    let result = slow::slow::<f64, _, _>(num.clone(), fp, integer.iter(), fraction.iter());
70    assert_eq!(result.mant, 1);
71    assert_eq!(result.exp, 0);
72
73    // 8.98846567431158e+307
74    let integer = b"8";
75    let fraction = b"9884656743115805365666807213050294962762414131308158973971342756154045415486693752413698006024096935349884403114202125541629105369684531108613657287705365884742938136589844238179474556051429647415148697857438797685859063890851407391008830874765563025951597582513936655578157348020066364210154316532161708032";
76    let num = Number {
77        mantissa: 8988465674311580536,
78        exponent: 289,
79        many_digits: true,
80    };
81    let fp = ExtendedFloat {
82        mant: 9223372036854776832,
83        exp: 2035,
84    };
85    let result = slow::slow::<f64, _, _>(num.clone(), fp, integer.iter(), fraction.iter());
86    assert_eq!(result.mant, 0);
87    assert_eq!(result.exp, 2046);
88
89    // 8.988465674311582e+307
90    let fraction = b"98846567431158053656668072130502949627624141313081589739713427561540454154866937524136980060240969353498844031142021255416291053696845311086136572877053658847429381365898442381794745560514296474151486978574387976858590638908514073910088308747655630259515975825139366555781573480200663642101543165321617080321";
91    let result = slow::slow::<f64, _, _>(num.clone(), fp, integer.iter(), fraction.iter());
92    assert_eq!(result.mant, 1);
93    assert_eq!(result.exp, 2046);
94}
95
96#[test]
97fn positive_digit_comp_test() {
98    // 8.98846567431158e+307
99    let bigmant = Bigint {
100        data: vec_from_u32(&[
101            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102            0, 1024, 2147483648,
103        ]),
104    };
105    let exponent = 307 + 1 - 308;
106    let result = slow::positive_digit_comp::<f64>(bigmant, exponent);
107    assert_eq!(result.mant, 0);
108    assert_eq!(result.exp, 2046);
109
110    // 8.988465674311582e+307
111    let bigmant = Bigint {
112        data: vec_from_u32(&[
113            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114            0, 1024, 2147483648,
115        ]),
116    };
117    let exponent = 307 + 1 - 308;
118    let result = slow::positive_digit_comp::<f64>(bigmant, exponent);
119    assert_eq!(result.mant, 1);
120    assert_eq!(result.exp, 2046);
121}
122
123#[test]
124fn negative_digit_comp_test() {
125    // 5e-324, below halfway, round-down to 0.0.
126    let bigmant = Bigint {
127        data: vec_from_u32(&[
128            1727738439, 330069557, 3509095598, 686205316, 156923684, 750687444, 2688855918,
129            28211928, 1887482096, 3222998811, 913348873, 1652282845, 1600735541, 1664240266,
130            84454144, 1487769792, 1855966778, 2832488299, 507030148, 1410055467, 2513359584,
131            3453963205, 779237894, 3456088326, 3671009895, 3094451696, 1250165638, 2682979794,
132            357925323, 1713890438, 3271046672, 3485897285, 3934710962, 1813530592, 199705026,
133            976390839, 2805488572, 2194288220, 2094065006, 2592523639, 3798974617, 586957244,
134            1409218821, 3442050171, 3789534764, 1380190380, 2055222457, 3535299831, 429482276,
135            389342206, 133558576, 721875297, 3013586570, 540178306, 2389746866, 2313334501,
136            422440635, 1288499129, 864978311, 842263325, 3016323856, 2282442263, 1440906063,
137            3931458696, 3511314276, 1884879882, 946366824, 4260548261, 1073379659, 1732329252,
138            3828972211, 1915607049, 3665440937, 1844358779, 3735281178, 2646335050, 1457460927,
139            2940016422, 1051,
140        ]),
141    };
142    let fp = ExtendedFloat {
143        mant: 1 << 63,
144        exp: -63,
145    };
146    let exponent = -324 + 1 - 755;
147    let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
148    assert_eq!(result.mant, 0);
149    assert_eq!(result.exp, 0);
150
151    // 5e-324, halfway, round-down to 0.0.
152    let bigmant = Bigint {
153        data: vec_from_u32(&[
154            2084786877, 507136210, 2666388819, 3110242527, 3178432722, 541916566, 208847286,
155            3092404665, 83491860, 2893735989, 3973758097, 2600107496, 147629623, 1754010897,
156            4226332273, 2587058081, 942453804, 88731834, 1319061990, 173208747, 1982493283,
157            3808794987, 3874839738, 1854586992, 3508364323, 2021729080, 1899625710, 2420749567,
158            816401711, 3059730605, 1570934109, 3138812023, 1756281367, 3205859133, 2985201975,
159            1014588672, 3799556578, 577719905, 4052248225, 3649019757, 398935965, 56421532,
160            976366795, 1876047791, 3147705595, 4025764546, 1097271882, 1910500779, 2397021233,
161            1340419138, 2753207595, 3067328524, 2210626776, 1280440432, 3940874757, 4172726578,
162            1035509558, 1062145421, 1465448826, 2990139501, 1785427751, 2093931515, 4055890033,
163            3388365687, 2245484242, 3609657408, 3527114516, 1013577862, 2389075196, 426934091,
164            3237939346, 1071362463, 4070999470, 250952461, 2280067948, 1097862995, 2226250520,
165            221983348, 1,
166        ]),
167    };
168    let exponent = -324 + 1 - 752;
169    let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
170    assert_eq!(result.mant, 0);
171    assert_eq!(result.exp, 0);
172
173    // 5e-324, above halfway, round-up to 5e-324.
174    let bigmant = Bigint {
175        data: vec_from_u32(&[
176            3667999587, 776394808, 894084415, 1037654204, 1719556155, 1124198371, 2088472861,
177            859275578, 834918607, 3167556114, 1082875312, 231271193, 1476296236, 360239786,
178            3608617070, 100777043, 834603454, 887318342, 305718012, 1732087473, 2645063646,
179            3728211506, 93691724, 1366000745, 723904866, 3037421624, 1816387920, 2732659194,
180            3869049819, 532534979, 2824439209, 1323349161, 382944493, 1993820262, 4082215981,
181            1555952134, 3635827414, 1482231762, 1867776587, 2130459211, 3989359658, 564215320,
182            1173733358, 1580608728, 1412284882, 1602939803, 2382784237, 1925138608, 2495375854,
183            519289497, 1762272177, 608514174, 631431287, 4214469733, 754041908, 3072560125,
184            1765160997, 2031519620, 1769586374, 4131591237, 674408332, 3759445970, 1904194670,
185            3818885807, 980005947, 1736835717, 911406800, 1545844036, 2415915482, 4269340915,
186            2314622388, 2123690045, 2055289038, 2509524619, 1325843000, 2388695363, 787668722,
187            2219833485, 10,
188        ]),
189    };
190    let exponent = -324 + 1 - 753;
191    let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
192    assert_eq!(result.mant, 1);
193    assert_eq!(result.exp, 0);
194
195    // 1e-323, below halfway, round-down to 5e-324.
196    let bigmant = Bigint {
197        data: vec_from_u32(&[
198            888248023, 990208672, 1937352202, 2058615950, 470771052, 2252062332, 3771600458,
199            84635785, 1367478992, 1079061842, 2740046621, 661881239, 507239328, 697753503,
200            253362433, 168342080, 1272933039, 4202497602, 1521090445, 4230166401, 3245111456,
201            1771955024, 2337713684, 1778330386, 2423095095, 693420498, 3750496916, 3753972086,
202            1073775970, 846704018, 1223205425, 1867757265, 3214198296, 1145624482, 599115079,
203            2929172517, 4121498420, 2287897365, 1987227723, 3482603622, 2806989260, 1760871734,
204            4227656463, 1736215921, 2778669702, 4140571142, 1870700075, 2015964902, 1288446830,
205            1168026618, 400675728, 2165625891, 450825118, 1620534920, 2874273302, 2645036208,
206            1267321906, 3865497387, 2594934933, 2526789975, 459036976, 2552359495, 27750894,
207            3204441497, 1944008238, 1359672352, 2839100473, 4191710191, 3220138979, 902020460,
208            2896982042, 1451853853, 2406388220, 1238109043, 2615908943, 3644037856, 77415486,
209            230114675, 3155,
210        ]),
211    };
212    let fp = ExtendedFloat {
213        mant: 1 << 63,
214        exp: -62,
215    };
216    let exponent = -324 + 1 - 755;
217    let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
218    assert_eq!(result.mant, 1);
219    assert_eq!(result.exp, 0);
220
221    // 1e-323, halfway, round-up to 1e-323.
222    let bigmant = Bigint {
223        data: vec_from_u32(&[
224            1959393335, 1521408631, 3704199161, 740792990, 945363576, 1625749700, 626541858,
225            687279403, 250475582, 91273375, 3331339701, 3505355194, 442888870, 967065395,
226            4089062228, 3466206949, 2827361413, 266195502, 3957185970, 519626241, 1652512553,
227            2836450370, 3034584624, 1268793682, 1935158378, 1770219946, 1403909835, 2967281406,
228            2449205134, 589257223, 417835033, 826501478, 973876807, 1027642808, 365671335,
229            3043766018, 2808735142, 1733159717, 3566810083, 2357124681, 1196807897, 169264596,
230            2929100385, 1333176077, 853182194, 3487359048, 3291815648, 1436535041, 2896096404,
231            4021257415, 3964655489, 612050981, 2336913034, 3841321297, 3232689679, 3928245144,
232            3106528676, 3186436263, 101379182, 380483912, 1061315959, 1986827250, 3577735508,
233            1575162471, 2441485432, 2239037633, 1991408958, 3040733588, 2872258292, 1280802274,
234            1123883446, 3214087391, 3623063818, 752857385, 2545236548, 3293588986, 2383784264,
235            665950045, 3,
236        ]),
237    };
238    let exponent = -324 + 1 - 752;
239    let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
240    assert_eq!(result.mant, 2);
241    assert_eq!(result.exp, 0);
242
243    // 1e-323, above halfway, round-up to 1e-323.
244    let bigmant = Bigint {
245        data: vec_from_u32(&[
246            2414064167, 2329184426, 2682253245, 3112962612, 863701169, 3372595114, 1970451287,
247            2577826735, 2504755821, 912733750, 3248625938, 693813579, 133921412, 1080719359,
248            2235916618, 302331131, 2503810362, 2661955026, 917154036, 901295123, 3640223643,
249            2594699927, 281075174, 4098002235, 2171714598, 522330280, 1154196466, 3903010287,
250            3017214866, 1597604939, 4178350331, 3970047484, 1148833479, 1686493490, 3656713352,
251            372889108, 2317547651, 151727992, 1308362466, 2096410338, 3378144383, 1692645962,
252            3521200074, 446858888, 4236854647, 513852113, 2853385416, 1480448529, 3191160267,
253            1557868492, 991849235, 1825542523, 1894293861, 4053474607, 2262125726, 627745783,
254            1000515697, 1799591565, 1013791827, 3804839120, 2023224998, 2688403318, 1417616716,
255            2866722830, 2940017843, 915539855, 2734220401, 342564812, 2952779151, 4218088154,
256            2648899870, 2076102840, 1870899819, 3233606562, 3977529001, 2871118793, 2363006167,
257            2364533159, 31,
258        ]),
259    };
260    let exponent = -324 + 1 - 753;
261    let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
262    assert_eq!(result.mant, 2);
263    assert_eq!(result.exp, 0);
264}
265
266#[test]
267fn parse_mantissa_test() {
268    let max_digits = f64::MAX_DIGITS;
269
270    // Large number of digits.
271    let integer = b"2";
272    let fraction = b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999";
273    let (bigmant, count) = slow::parse_mantissa(integer.iter(), fraction.iter(), max_digits);
274    let expected = vec_from_u32(&[
275        1727738439, 330069557, 3509095598, 686205316, 156923684, 750687444, 2688855918, 28211928,
276        1887482096, 3222998811, 913348873, 1652282845, 1600735541, 1664240266, 84454144,
277        1487769792, 1855966778, 2832488299, 507030148, 1410055467, 2513359584, 3453963205,
278        779237894, 3456088326, 3671009895, 3094451696, 1250165638, 2682979794, 357925323,
279        1713890438, 3271046672, 3485897285, 3934710962, 1813530592, 199705026, 976390839,
280        2805488572, 2194288220, 2094065006, 2592523639, 3798974617, 586957244, 1409218821,
281        3442050171, 3789534764, 1380190380, 2055222457, 3535299831, 429482276, 389342206,
282        133558576, 721875297, 3013586570, 540178306, 2389746866, 2313334501, 422440635, 1288499129,
283        864978311, 842263325, 3016323856, 2282442263, 1440906063, 3931458696, 3511314276,
284        1884879882, 946366824, 4260548261, 1073379659, 1732329252, 3828972211, 1915607049,
285        3665440937, 1844358779, 3735281178, 2646335050, 1457460927, 2940016422, 1051,
286    ]);
287    assert_eq!(&*bigmant.data, &*expected);
288    assert_eq!(count, 755);
289
290    // Truncation.
291    let integer = b"7";
292    let fraction = b"4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375332669816033062329967789262837";
293    let (bigmant, count) = slow::parse_mantissa(integer.iter(), fraction.iter(), max_digits);
294    let expected = vec_from_u32(&[
295        983641521, 2202462645, 4170685875, 1591772364, 529830014, 803977727, 126733331, 1695971390,
296        4089590927, 1532849076, 2705586665, 4046282448, 4076195232, 3230469892, 3059053929,
297        79035789, 744229654, 2026438108, 3570486781, 2818088662, 3485839733, 3653138023,
298        2857937689, 602717004, 3689362390, 283607819, 1783392475, 2053068939, 1888214698,
299        550023429, 296880187, 1046779059, 1285361259, 84614934, 1627922685, 2023868765, 1987523901,
300        743493573, 3897769089, 2210613570, 2261081349, 3015057659, 3949711644, 3346092916,
301        2433639051, 36411806, 1050442, 269209477, 2649742673, 1494221829, 2763524503, 2514491481,
302        2325312415, 1741242814, 2479923579, 1098250122, 2416211509, 3612906464, 403420662,
303        3663250314, 1993722098, 365907183, 4270226312, 3962131185, 432952495, 2963635838,
304        2996289227, 3200289391, 2753231690, 2780286109, 884373163, 1418533204, 3382415762,
305        499541562, 3369625401, 3421327641, 3526770155, 3109983188, 1157439767, 734593155,
306    ]);
307    assert_eq!(&*bigmant.data, &*expected);
308    assert_eq!(count, max_digits + 1);
309
310    // No fraction digits.
311    let integer = b"74109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375332669816033062329967789262837";
312    let fraction = b"";
313    let (bigmant, count) = slow::parse_mantissa(integer.iter(), fraction.iter(), max_digits);
314    assert_eq!(&*bigmant.data, &*expected);
315    assert_eq!(count, max_digits + 1);
316
317    // Multiple of step (check we add our temporary correctly).
318    let integer = b"7410984687618698162648531893023320585475897039214871466383785237510132609053131277979497545424539885696948470431685765963899850655339096945981621940161728171894510697854671067917687257517734731555330779540854980960845750095811137303474765809687100959097544227100475730780971111893578483867565399878350301522805593404659373979179073872386829939581848166016912201945649993128979841136206248449867871357218035220901702390328579173252022052897402080290685402160661237554998340267130003581248647904138574340187552090159017259254714629617513415977493871857473787096164563890871811984127167305601704549300470526959016576377688490826798697257336652176556794107250876433756084600398490497214911746308553955635418864151316847843631308023759629577398300170898437533266981";
319    let fraction = b"";
320    let (bigmant, count) = slow::parse_mantissa(integer.iter(), fraction.iter(), max_digits);
321    let expected = vec_from_u32(&[
322        617018405, 396211401, 2130402383, 3812547827, 4263683770, 3918012496, 1787721490,
323        2493014694, 435464626, 3720854431, 2928509507, 2677932436, 369049650, 3606588290,
324        231237141, 2231172875, 3358152367, 95217925, 2777810007, 1016185079, 596681915, 2331711780,
325        593487272, 4212730845, 339602972, 4097829793, 262427536, 4182115035, 3414687403,
326        3711518952, 4168896929, 483727327, 1657080031, 2785588628, 1009114769, 482126749,
327        485376744, 1123705337, 3225501941, 2939050108, 1338451005, 2104263947, 3425461126,
328        1834224928, 4061025704, 792093815, 2707019125, 3610271203, 4254101529, 1026215278,
329        4117890107, 1748110416, 2535111606, 80965120, 3823822115, 2354910057, 590658512,
330        2682089507, 159300272, 1776569442, 3382166479, 3222978591, 540586210, 934713382,
331        2014123057, 1455555790, 4119131465, 3685912982, 3019947291, 3437891678, 2660105801,
332        2605860762, 394373515, 4177081532, 1616198650, 1580399082, 2017617452, 3327697130,
333        315505357,
334    ]);
335    assert_eq!(&*bigmant.data, &*expected);
336    assert_eq!(count, 760);
337}
338