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(float: F) -> (u64, i32) { let fp = slow::b(float); (fp.mant, fp.exp) } fn bh(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::(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::(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::(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::(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::(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::(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::(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::(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::(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::(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::(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::(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); }