• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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