1 mod stackvec;
2
3 use minimal_lexical::bigint::Bigint;
4 use minimal_lexical::extended_float::ExtendedFloat;
5 use minimal_lexical::num::Float;
6 use minimal_lexical::number::Number;
7 use minimal_lexical::slow;
8 use stackvec::vec_from_u32;
9
b<F: Float>(float: F) -> (u64, i32)10 fn b<F: Float>(float: F) -> (u64, i32) {
11 let fp = slow::b(float);
12 (fp.mant, fp.exp)
13 }
14
bh<F: Float>(float: F) -> (u64, i32)15 fn bh<F: Float>(float: F) -> (u64, i32) {
16 let fp = slow::bh(float);
17 (fp.mant, fp.exp)
18 }
19
20 #[test]
b_test()21 fn 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]
bh_test()40 fn 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]
slow_test()50 fn 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]
positive_digit_comp_test()97 fn 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]
negative_digit_comp_test()124 fn 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]
parse_mantissa_test()267 fn 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