Source code

Revision control

Copy as Markdown

Other Tools

mod stackvec;
use minimal_lexical::bigint::Bigint;
use minimal_lexical::extended_float::ExtendedFloat;
use minimal_lexical::num::Float;
use minimal_lexical::number::Number;
use minimal_lexical::slow;
use stackvec::vec_from_u32;
fn b<F: Float>(float: F) -> (u64, i32) {
let fp = slow::b(float);
(fp.mant, fp.exp)
}
fn bh<F: Float>(float: F) -> (u64, i32) {
let fp = slow::bh(float);
(fp.mant, fp.exp)
}
#[test]
fn b_test() {
assert_eq!(b(1e-45_f32), (1, -149));
assert_eq!(b(5e-324_f64), (1, -1074));
assert_eq!(b(1e-323_f64), (2, -1074));
assert_eq!(b(2e-323_f64), (4, -1074));
assert_eq!(b(3e-323_f64), (6, -1074));
assert_eq!(b(4e-323_f64), (8, -1074));
assert_eq!(b(5e-323_f64), (10, -1074));
assert_eq!(b(6e-323_f64), (12, -1074));
assert_eq!(b(7e-323_f64), (14, -1074));
assert_eq!(b(8e-323_f64), (16, -1074));
assert_eq!(b(9e-323_f64), (18, -1074));
assert_eq!(b(1_f32), (8388608, -23));
assert_eq!(b(1_f64), (4503599627370496, -52));
assert_eq!(b(1e38_f32), (9860761, 103));
assert_eq!(b(1e308_f64), (5010420900022432, 971));
}
#[test]
fn bh_test() {
assert_eq!(bh(1e-45_f32), (3, -150));
assert_eq!(bh(5e-324_f64), (3, -1075));
assert_eq!(bh(1_f32), (16777217, -24));
assert_eq!(bh(1_f64), (9007199254740993, -53));
assert_eq!(bh(1e38_f32), (19721523, 102));
assert_eq!(bh(1e308_f64), (10020841800044865, 970));
}
#[test]
fn slow_test() {
// 5e-324, round-down.
let integer = b"2";
let fraction = b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999";
let num = Number {
mantissa: 2470328229206232720,
exponent: -342,
many_digits: true,
};
let fp = ExtendedFloat {
mant: 1 << 63,
exp: -63,
};
let result = slow::slow::<f64, _, _>(num.clone(), fp, integer.iter(), fraction.iter());
assert_eq!(result.mant, 0);
assert_eq!(result.exp, 0);
// 5e-324, round-up.
let fraction = b"47032822920623272088284396434110686182529901307162382212792841250337753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356595155702263922908583924491051844359318028499365361525003193704576782492193656236698636584807570015857692699037063119282795585513329278343384093519780155312465972635795746227664652728272200563740064854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355374585166611342237666786041621596804619144672918403005300575308490487653917113865916462395249126236538818796362393732804238910186723484976682350898633885879256283027559956575244555072551893136908362547791869486679949683240497058210285131854513962138377228261454376934125320985913276672363281251";
let result = slow::slow::<f64, _, _>(num.clone(), fp, integer.iter(), fraction.iter());
assert_eq!(result.mant, 1);
assert_eq!(result.exp, 0);
// 8.98846567431158e+307
let integer = b"8";
let fraction = b"9884656743115805365666807213050294962762414131308158973971342756154045415486693752413698006024096935349884403114202125541629105369684531108613657287705365884742938136589844238179474556051429647415148697857438797685859063890851407391008830874765563025951597582513936655578157348020066364210154316532161708032";
let num = Number {
mantissa: 8988465674311580536,
exponent: 289,
many_digits: true,
};
let fp = ExtendedFloat {
mant: 9223372036854776832,
exp: 2035,
};
let result = slow::slow::<f64, _, _>(num.clone(), fp, integer.iter(), fraction.iter());
assert_eq!(result.mant, 0);
assert_eq!(result.exp, 2046);
// 8.988465674311582e+307
let fraction = b"98846567431158053656668072130502949627624141313081589739713427561540454154866937524136980060240969353498844031142021255416291053696845311086136572877053658847429381365898442381794745560514296474151486978574387976858590638908514073910088308747655630259515975825139366555781573480200663642101543165321617080321";
let result = slow::slow::<f64, _, _>(num.clone(), fp, integer.iter(), fraction.iter());
assert_eq!(result.mant, 1);
assert_eq!(result.exp, 2046);
}
#[test]
fn positive_digit_comp_test() {
// 8.98846567431158e+307
let bigmant = Bigint {
data: vec_from_u32(&[
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,
0, 1024, 2147483648,
]),
};
let exponent = 307 + 1 - 308;
let result = slow::positive_digit_comp::<f64>(bigmant, exponent);
assert_eq!(result.mant, 0);
assert_eq!(result.exp, 2046);
// 8.988465674311582e+307
let bigmant = Bigint {
data: vec_from_u32(&[
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,
0, 1024, 2147483648,
]),
};
let exponent = 307 + 1 - 308;
let result = slow::positive_digit_comp::<f64>(bigmant, exponent);
assert_eq!(result.mant, 1);
assert_eq!(result.exp, 2046);
}
#[test]
fn negative_digit_comp_test() {
// 5e-324, below halfway, round-down to 0.0.
let bigmant = Bigint {
data: vec_from_u32(&[
1727738439, 330069557, 3509095598, 686205316, 156923684, 750687444, 2688855918,
28211928, 1887482096, 3222998811, 913348873, 1652282845, 1600735541, 1664240266,
84454144, 1487769792, 1855966778, 2832488299, 507030148, 1410055467, 2513359584,
3453963205, 779237894, 3456088326, 3671009895, 3094451696, 1250165638, 2682979794,
357925323, 1713890438, 3271046672, 3485897285, 3934710962, 1813530592, 199705026,
976390839, 2805488572, 2194288220, 2094065006, 2592523639, 3798974617, 586957244,
1409218821, 3442050171, 3789534764, 1380190380, 2055222457, 3535299831, 429482276,
389342206, 133558576, 721875297, 3013586570, 540178306, 2389746866, 2313334501,
422440635, 1288499129, 864978311, 842263325, 3016323856, 2282442263, 1440906063,
3931458696, 3511314276, 1884879882, 946366824, 4260548261, 1073379659, 1732329252,
3828972211, 1915607049, 3665440937, 1844358779, 3735281178, 2646335050, 1457460927,
2940016422, 1051,
]),
};
let fp = ExtendedFloat {
mant: 1 << 63,
exp: -63,
};
let exponent = -324 + 1 - 755;
let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
assert_eq!(result.mant, 0);
assert_eq!(result.exp, 0);
// 5e-324, halfway, round-down to 0.0.
let bigmant = Bigint {
data: vec_from_u32(&[
2084786877, 507136210, 2666388819, 3110242527, 3178432722, 541916566, 208847286,
3092404665, 83491860, 2893735989, 3973758097, 2600107496, 147629623, 1754010897,
4226332273, 2587058081, 942453804, 88731834, 1319061990, 173208747, 1982493283,
3808794987, 3874839738, 1854586992, 3508364323, 2021729080, 1899625710, 2420749567,
816401711, 3059730605, 1570934109, 3138812023, 1756281367, 3205859133, 2985201975,
1014588672, 3799556578, 577719905, 4052248225, 3649019757, 398935965, 56421532,
976366795, 1876047791, 3147705595, 4025764546, 1097271882, 1910500779, 2397021233,
1340419138, 2753207595, 3067328524, 2210626776, 1280440432, 3940874757, 4172726578,
1035509558, 1062145421, 1465448826, 2990139501, 1785427751, 2093931515, 4055890033,
3388365687, 2245484242, 3609657408, 3527114516, 1013577862, 2389075196, 426934091,
3237939346, 1071362463, 4070999470, 250952461, 2280067948, 1097862995, 2226250520,
221983348, 1,
]),
};
let exponent = -324 + 1 - 752;
let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
assert_eq!(result.mant, 0);
assert_eq!(result.exp, 0);
// 5e-324, above halfway, round-up to 5e-324.
let bigmant = Bigint {
data: vec_from_u32(&[
3667999587, 776394808, 894084415, 1037654204, 1719556155, 1124198371, 2088472861,
859275578, 834918607, 3167556114, 1082875312, 231271193, 1476296236, 360239786,
3608617070, 100777043, 834603454, 887318342, 305718012, 1732087473, 2645063646,
3728211506, 93691724, 1366000745, 723904866, 3037421624, 1816387920, 2732659194,
3869049819, 532534979, 2824439209, 1323349161, 382944493, 1993820262, 4082215981,
1555952134, 3635827414, 1482231762, 1867776587, 2130459211, 3989359658, 564215320,
1173733358, 1580608728, 1412284882, 1602939803, 2382784237, 1925138608, 2495375854,
519289497, 1762272177, 608514174, 631431287, 4214469733, 754041908, 3072560125,
1765160997, 2031519620, 1769586374, 4131591237, 674408332, 3759445970, 1904194670,
3818885807, 980005947, 1736835717, 911406800, 1545844036, 2415915482, 4269340915,
2314622388, 2123690045, 2055289038, 2509524619, 1325843000, 2388695363, 787668722,
2219833485, 10,
]),
};
let exponent = -324 + 1 - 753;
let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
assert_eq!(result.mant, 1);
assert_eq!(result.exp, 0);
// 1e-323, below halfway, round-down to 5e-324.
let bigmant = Bigint {
data: vec_from_u32(&[
888248023, 990208672, 1937352202, 2058615950, 470771052, 2252062332, 3771600458,
84635785, 1367478992, 1079061842, 2740046621, 661881239, 507239328, 697753503,
253362433, 168342080, 1272933039, 4202497602, 1521090445, 4230166401, 3245111456,
1771955024, 2337713684, 1778330386, 2423095095, 693420498, 3750496916, 3753972086,
1073775970, 846704018, 1223205425, 1867757265, 3214198296, 1145624482, 599115079,
2929172517, 4121498420, 2287897365, 1987227723, 3482603622, 2806989260, 1760871734,
4227656463, 1736215921, 2778669702, 4140571142, 1870700075, 2015964902, 1288446830,
1168026618, 400675728, 2165625891, 450825118, 1620534920, 2874273302, 2645036208,
1267321906, 3865497387, 2594934933, 2526789975, 459036976, 2552359495, 27750894,
3204441497, 1944008238, 1359672352, 2839100473, 4191710191, 3220138979, 902020460,
2896982042, 1451853853, 2406388220, 1238109043, 2615908943, 3644037856, 77415486,
230114675, 3155,
]),
};
let fp = ExtendedFloat {
mant: 1 << 63,
exp: -62,
};
let exponent = -324 + 1 - 755;
let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
assert_eq!(result.mant, 1);
assert_eq!(result.exp, 0);
// 1e-323, halfway, round-up to 1e-323.
let bigmant = Bigint {
data: vec_from_u32(&[
1959393335, 1521408631, 3704199161, 740792990, 945363576, 1625749700, 626541858,
687279403, 250475582, 91273375, 3331339701, 3505355194, 442888870, 967065395,
4089062228, 3466206949, 2827361413, 266195502, 3957185970, 519626241, 1652512553,
2836450370, 3034584624, 1268793682, 1935158378, 1770219946, 1403909835, 2967281406,
2449205134, 589257223, 417835033, 826501478, 973876807, 1027642808, 365671335,
3043766018, 2808735142, 1733159717, 3566810083, 2357124681, 1196807897, 169264596,
2929100385, 1333176077, 853182194, 3487359048, 3291815648, 1436535041, 2896096404,
4021257415, 3964655489, 612050981, 2336913034, 3841321297, 3232689679, 3928245144,
3106528676, 3186436263, 101379182, 380483912, 1061315959, 1986827250, 3577735508,
1575162471, 2441485432, 2239037633, 1991408958, 3040733588, 2872258292, 1280802274,
1123883446, 3214087391, 3623063818, 752857385, 2545236548, 3293588986, 2383784264,
665950045, 3,
]),
};
let exponent = -324 + 1 - 752;
let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
assert_eq!(result.mant, 2);
assert_eq!(result.exp, 0);
// 1e-323, above halfway, round-up to 1e-323.
let bigmant = Bigint {
data: vec_from_u32(&[
2414064167, 2329184426, 2682253245, 3112962612, 863701169, 3372595114, 1970451287,
2577826735, 2504755821, 912733750, 3248625938, 693813579, 133921412, 1080719359,
2235916618, 302331131, 2503810362, 2661955026, 917154036, 901295123, 3640223643,
2594699927, 281075174, 4098002235, 2171714598, 522330280, 1154196466, 3903010287,
3017214866, 1597604939, 4178350331, 3970047484, 1148833479, 1686493490, 3656713352,
372889108, 2317547651, 151727992, 1308362466, 2096410338, 3378144383, 1692645962,
3521200074, 446858888, 4236854647, 513852113, 2853385416, 1480448529, 3191160267,
1557868492, 991849235, 1825542523, 1894293861, 4053474607, 2262125726, 627745783,
1000515697, 1799591565, 1013791827, 3804839120, 2023224998, 2688403318, 1417616716,
2866722830, 2940017843, 915539855, 2734220401, 342564812, 2952779151, 4218088154,
2648899870, 2076102840, 1870899819, 3233606562, 3977529001, 2871118793, 2363006167,
2364533159, 31,
]),
};
let exponent = -324 + 1 - 753;
let result = slow::negative_digit_comp::<f64>(bigmant, fp, exponent);
assert_eq!(result.mant, 2);
assert_eq!(result.exp, 0);
}
#[test]
fn parse_mantissa_test() {
let max_digits = f64::MAX_DIGITS;
// Large number of digits.
let integer = b"2";
let fraction = b"4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999";
let (bigmant, count) = slow::parse_mantissa(integer.iter(), fraction.iter(), max_digits);
let expected = vec_from_u32(&[
1727738439, 330069557, 3509095598, 686205316, 156923684, 750687444, 2688855918, 28211928,
1887482096, 3222998811, 913348873, 1652282845, 1600735541, 1664240266, 84454144,
1487769792, 1855966778, 2832488299, 507030148, 1410055467, 2513359584, 3453963205,
779237894, 3456088326, 3671009895, 3094451696, 1250165638, 2682979794, 357925323,
1713890438, 3271046672, 3485897285, 3934710962, 1813530592, 199705026, 976390839,
2805488572, 2194288220, 2094065006, 2592523639, 3798974617, 586957244, 1409218821,
3442050171, 3789534764, 1380190380, 2055222457, 3535299831, 429482276, 389342206,
133558576, 721875297, 3013586570, 540178306, 2389746866, 2313334501, 422440635, 1288499129,
864978311, 842263325, 3016323856, 2282442263, 1440906063, 3931458696, 3511314276,
1884879882, 946366824, 4260548261, 1073379659, 1732329252, 3828972211, 1915607049,
3665440937, 1844358779, 3735281178, 2646335050, 1457460927, 2940016422, 1051,
]);
assert_eq!(&*bigmant.data, &*expected);
assert_eq!(count, 755);
// Truncation.
let integer = b"7";
let fraction = b"4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375332669816033062329967789262837";
let (bigmant, count) = slow::parse_mantissa(integer.iter(), fraction.iter(), max_digits);
let expected = vec_from_u32(&[
983641521, 2202462645, 4170685875, 1591772364, 529830014, 803977727, 126733331, 1695971390,
4089590927, 1532849076, 2705586665, 4046282448, 4076195232, 3230469892, 3059053929,
79035789, 744229654, 2026438108, 3570486781, 2818088662, 3485839733, 3653138023,
2857937689, 602717004, 3689362390, 283607819, 1783392475, 2053068939, 1888214698,
550023429, 296880187, 1046779059, 1285361259, 84614934, 1627922685, 2023868765, 1987523901,
743493573, 3897769089, 2210613570, 2261081349, 3015057659, 3949711644, 3346092916,
2433639051, 36411806, 1050442, 269209477, 2649742673, 1494221829, 2763524503, 2514491481,
2325312415, 1741242814, 2479923579, 1098250122, 2416211509, 3612906464, 403420662,
3663250314, 1993722098, 365907183, 4270226312, 3962131185, 432952495, 2963635838,
2996289227, 3200289391, 2753231690, 2780286109, 884373163, 1418533204, 3382415762,
499541562, 3369625401, 3421327641, 3526770155, 3109983188, 1157439767, 734593155,
]);
assert_eq!(&*bigmant.data, &*expected);
assert_eq!(count, max_digits + 1);
// No fraction digits.
let integer = b"74109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375332669816033062329967789262837";
let fraction = b"";
let (bigmant, count) = slow::parse_mantissa(integer.iter(), fraction.iter(), max_digits);
assert_eq!(&*bigmant.data, &*expected);
assert_eq!(count, max_digits + 1);
// Multiple of step (check we add our temporary correctly).
let integer = b"7410984687618698162648531893023320585475897039214871466383785237510132609053131277979497545424539885696948470431685765963899850655339096945981621940161728171894510697854671067917687257517734731555330779540854980960845750095811137303474765809687100959097544227100475730780971111893578483867565399878350301522805593404659373979179073872386829939581848166016912201945649993128979841136206248449867871357218035220901702390328579173252022052897402080290685402160661237554998340267130003581248647904138574340187552090159017259254714629617513415977493871857473787096164563890871811984127167305601704549300470526959016576377688490826798697257336652176556794107250876433756084600398490497214911746308553955635418864151316847843631308023759629577398300170898437533266981";
let fraction = b"";
let (bigmant, count) = slow::parse_mantissa(integer.iter(), fraction.iter(), max_digits);
let expected = vec_from_u32(&[
617018405, 396211401, 2130402383, 3812547827, 4263683770, 3918012496, 1787721490,
2493014694, 435464626, 3720854431, 2928509507, 2677932436, 369049650, 3606588290,
231237141, 2231172875, 3358152367, 95217925, 2777810007, 1016185079, 596681915, 2331711780,
593487272, 4212730845, 339602972, 4097829793, 262427536, 4182115035, 3414687403,
3711518952, 4168896929, 483727327, 1657080031, 2785588628, 1009114769, 482126749,
485376744, 1123705337, 3225501941, 2939050108, 1338451005, 2104263947, 3425461126,
1834224928, 4061025704, 792093815, 2707019125, 3610271203, 4254101529, 1026215278,
4117890107, 1748110416, 2535111606, 80965120, 3823822115, 2354910057, 590658512,
2682089507, 159300272, 1776569442, 3382166479, 3222978591, 540586210, 934713382,
2014123057, 1455555790, 4119131465, 3685912982, 3019947291, 3437891678, 2660105801,
2605860762, 394373515, 4177081532, 1616198650, 1580399082, 2017617452, 3327697130,
315505357,
]);
assert_eq!(&*bigmant.data, &*expected);
assert_eq!(count, 760);
}