@@ -2294,4 +2294,139 @@ contract FixedPointMathLibTest is SoladyTest {
22942294 function mul (uint256 x , uint256 y ) public pure returns (uint256 ) {
22952295 return x * y;
22962296 }
2297+
2298+ function testMulSqrtSmall (uint256 x , uint256 y ) public {
2299+ x = _bound (x, 0 , 2 ** 128 - 1 );
2300+ y = _bound (y, 0 , 2 ** 128 - 1 );
2301+ assertEq (FixedPointMathLib.mulSqrt (x, y), FixedPointMathLib.sqrt (x * y));
2302+ }
2303+
2304+ function testMulSqrt (uint256 x , uint256 y ) public {
2305+ if (x == y) {
2306+ assertEq (FixedPointMathLib.mulSqrt (x, y), x);
2307+ return ;
2308+ }
2309+ uint256 z = FixedPointMathLib.mulSqrt (x, y);
2310+
2311+ emit LogUint ("z " , z);
2312+ (uint256 p0 , uint256 p1 ) = _fullMul (x, y);
2313+ (uint256 z0 , uint256 z1 ) = _fullMul (z, z);
2314+
2315+ if (z == type (uint256 ).max) return ;
2316+ (uint256 zp0 , uint256 zp1 ) = _fullMul (z + 1 , z + 1 );
2317+
2318+ assertTrue ((z1 < p1) || (z1 == p1 && z0 <= p0));
2319+ assertTrue ((p1 < zp1) || (p1 == zp1 && p0 < zp0));
2320+ }
2321+
2322+ function _fullMul (uint256 x , uint256 y ) internal pure returns (uint256 p0 , uint256 p1 ) {
2323+ /// @solidity memory-safe-assembly
2324+ assembly {
2325+ p0 := mul (x, y)
2326+ let mm := mulmod (x, y, not (0 ))
2327+ p1 := sub (mm, add (p0, lt (mm, p0)))
2328+ }
2329+ }
2330+
2331+ function _testMulSqrt (uint256 x , uint256 y , uint256 z ) public {
2332+ assertEq (FixedPointMathLib.mulSqrt (x, y), z);
2333+ assertEq (FixedPointMathLib.mulSqrt (y, x), z);
2334+ }
2335+
2336+ function testMulSqrtDifferential (uint256 x , uint256 y ) public {
2337+ assertEq (FixedPointMathLib.mulSqrt (x, y), _mulSqrtOriginal (x, y));
2338+ }
2339+
2340+ function _mulSqrtOriginal (uint256 x , uint256 y ) internal pure returns (uint256 z ) {
2341+ if (x == 0 || y == 0 ) return 0 ;
2342+ if (x == y) return x;
2343+ uint256 p = FixedPointMathLib.rawMul (x, y);
2344+ if (y == p / x) return FixedPointMathLib.sqrt (p);
2345+ uint256 sqrtX = FixedPointMathLib.sqrt (x);
2346+ uint256 sqrtY = FixedPointMathLib.sqrt (y);
2347+ for (z = FixedPointMathLib.saturatingMul (sqrtX + 1 , sqrtY + 1 );;) {
2348+ uint256 zNext = FixedPointMathLib.fullMulDivUnchecked (x, y, z);
2349+ zNext = FixedPointMathLib.avg (z, zNext);
2350+ if (zNext >= z) break ;
2351+ z = zNext;
2352+ }
2353+ }
2354+
2355+ function testMulSqrt () public {
2356+ // forgefmt: disable-start
2357+ this ._testMulSqrt (1 ,40899 ,202 );
2358+ this ._testMulSqrt (2 ,126475466778170 ,15904431 );
2359+ this ._testMulSqrt (1 ,7531755327269063297785 ,86785686188 );
2360+ this ._testMulSqrt (4 ,1145375910940206129316611151348 ,2140444730368159 );
2361+ this ._testMulSqrt (1 ,6000249325576079771745702731971550324701397394 ,77461276297102668974080 );
2362+ this ._testMulSqrt (19990973968927499539515487029982657202480 ,351588509 ,2651150077078442553440984 );
2363+ this ._testMulSqrt (884589532366 ,8944067071329830864412327072945291263924221217993 ,2812797203510731992653280306277 );
2364+ this ._testMulSqrt (6 ,231793030923641024945144526163927788762812410599871060107884767317 ,1179304110711841006457676781313383 );
2365+ this ._testMulSqrt (7 ,25918817354934577870911410398594504620656949910895919963803454597218 ,13469659293558320924081748803885430 );
2366+ this ._testMulSqrt (2 ,6184767715379885918995468503098991544649672240672289523626396828206377 ,111218413182169488449746241587513722 );
2367+ this ._testMulSqrt (11262102866604455182725961449733527925032397745743648245810757 ,2289531243 ,160576886179084819940315039841174360 );
2368+ this ._testMulSqrt (2 ,386128680208745785717489332755004235996307094856550925460526784315796445 ,878781747885953518587400193470685282 );
2369+ this ._testMulSqrt (20 ,133823397008372075942399557492827432876972721009673572412945073431794356 ,1635991424234076331806369976651119304 );
2370+ this ._testMulSqrt (64385011511148092020199840672969561808819251747679314637 ,16788189010063055495896874 ,32877161414335023454300652451233783772805 );
2371+ this ._testMulSqrt (307695058396291282867900569126929438472472421745 ,16650777576165153239643978609535636374 ,2263484477225720726470604509270073120374679 );
2372+ this ._testMulSqrt (37369048817028070 ,403547546041382623075657545097967233546021171804178222743888832459267032 ,122801416718262293521136665081803979269652981 );
2373+ this ._testMulSqrt (108757921013865829718776238158835403990222487425921424856119171941423640 ,311530010377180825 ,184068889989727037643726419490138992138431758 );
2374+ this ._testMulSqrt (71968390915585988831780603371197224690006783200448692196810504 ,1317434458380206291313344071812603846743105529396590981616 ,307918232825485645925260268942424415111262027158036186068393 );
2375+ this ._testMulSqrt (169786846411291950176086783315992030432326301383306594102503280 ,262091314248283560844199184902391093238338514869222967307939442153535 ,210949419809600269188992711762466980237552872839406150493359215238 );
2376+ this ._testMulSqrt (13125530490447682132624267118512105994743022946653752643039816341671957523 ,2703992648396778482623576839914577810228120087337379417522074085943689092 ,5957460696679273501196497896950129901097275853419042552123499864438199223 );
2377+ this ._testMulSqrt (759343816572101418250144283506759951951139556413747077593352856047453741042 ,5783606897390246194179048291049046711192537808438654462819097925235107871790 ,2095649334935842670420229418803511179917932829424728325651967137561547960515 );
2378+ this ._testMulSqrt (1453693402301034209593542434097237131647588800659364354488100189009468111235 ,3021095182839377497836893600683197190212994171204262758821708252445961887922 ,2095649334935842670420229418803511179917932829424728325651967137561547960515 );
2379+ this ._testMulSqrt (1500322080289732537847477243966572315817180906638531006084846839970956040737 ,2927202227250387439989971689119336628619848415002314520835497068418776903816 ,2095649334935842670420229418803511179917932829424728325651967137561547960515 );
2380+ this ._testMulSqrt (1418188734037590650038894298784738194557827267133881612919761886151138174982 ,3096728968163296409290287978802863257249612545684811929660405453902456993799 ,2095649334935842670420229418803511179917932829424728325651967137561547960515 );
2381+ this ._testMulSqrt (72649803940522399886719930058523700039023197833404875144131115786317960957502 ,1058032812382543109188733542274803566994606781443813721786480120922367936989 ,8767318654082973239818507301503235653779978250722724160009440005060322575671 );
2382+ this ._testMulSqrt (5373922104039726654109199686576171393319670483688158333460332678277457737472 ,29698357225200387337129817970745776673739254860209898274723677280893657304883 ,12633157101301807356759851956784431867751428103301339039224348881394628761742 );
2383+ this ._testMulSqrt (4110435947028096136332171788401813256200194295940648314773165026203401589664 ,47629135145959642265403944627116611572745368779360562832098585565036412006720 ,13992015910147179362140946267238865150610331346635053034797342180359096262561 );
2384+ this ._testMulSqrt (6670439349065019066867111962665902305718250536829827331422008770563721526834 ,23925958995271068490107533294147958150213516645841822380228819548185161301331 ,12633157101301807356759851956784431867751428103301339039224348881394628761742 );
2385+ this ._testMulSqrt (2969132035655378982552797810065716750184480456087472143547576763384185040150 ,65937286344558903530415649738599306075672958462949062884739418323163356428267 ,13992015910147179362140946267238865150610331346635053034797342180359096262561 );
2386+ this ._testMulSqrt (7491404489992521390184991330802592986343520371455692604718960104437178752665 ,21303970244748005562096092471791804290084308713402287738808276131330039069727 ,12633157101301807356759851956784431867751428103301339039224348881394628761742 );
2387+ this ._testMulSqrt (6121895596657181220666267444651436648237333295237933576541838582595521000977 ,70855413278339511916656827078592824537105782268733407488004367896456997184904 ,20827132364970253561103779902092578934359252280464989168083476470668469620748 );
2388+ this ._testMulSqrt (9663464530001823655566072879594302677711586601817760096066022478590461523681 ,44887570208519155988166566051306580252890388816305191368753991821976222373501 ,20827132364970253561103779902092578934359252280464989168083476470668469620748 );
2389+ this ._testMulSqrt (3146233082020622571934575333002634745373987161876939823151669615808091349575 ,62225685168905914639685682949327855631601195004914029384687573254167511859580 ,13992015910147179362140946267238865150610331346635053034797342180359096262561 );
2390+ this ._testMulSqrt (81292148375414543538357432189784118864691517292040335173170009268459477601704 ,2516741501174680293198396542611706642053439931235618117323066049365884914216 ,14303542342233117118521903523784342299628960478384746102119577025303325649767 );
2391+ this ._testMulSqrt (6235952310590095577242208648287326629803669887249954646740971273060426215074 ,86267974483515850745154997335441073241510839437043584529161844505392388495406 ,23194028861118718470348997581404528819309525163067296635449034115712705381145 );
2392+ this ._testMulSqrt (8202270509291188368161098479682643484535231613691719026429761609950890177708 ,110093889479585348411203054124693950081761292952495296567025182505398163143046 ,30050288899302887082115267696735954136708432495128508248566789198018211109331 );
2393+ this ._testMulSqrt (58567595367007003434029003100140382325611053031291395486564269268008176012515 ,58567595367007003434029003100140382325611053031291395486564269268008176012528 ,58567595367007003434029003100140382325611053031291395486564269268008176012521 );
2394+ this ._testMulSqrt (66674750232480974592958260963213523118377591895163248013022969308057159666106 ,66674750232480974592958260963213523118377591895163248013022969308057159666106 ,66674750232480974592958260963213523118377591895163248013022969308057159666106 );
2395+ this ._testMulSqrt (33585912866580500017428740937261524277391765196007489833430561956127819834566 ,52199687981615271967060816285063413507671559301970565963089267667884242865491 ,41870922753304826754657295225348362266441633929084405750532911003697653673376 );
2396+ this ._testMulSqrt (67059371761480772870120378810526551624172903367552398549958050667166366320070 ,18204720352041367142096118905131984188387648432760494796813976946511020703864 ,34939907124967249547474326305667618125822338407481424538436068764138475863743 );
2397+ this ._testMulSqrt (91758599666022652235931878429035236115420549503042702161402892861112704213437 ,91758599666022652235931878429035236115420549503042702161402892861112704213446 ,91758599666022652235931878429035236115420549503042702161402892861112704213441 );
2398+ this ._testMulSqrt (57643576768106877450231061433780292981040727232162059949268652098179482795200 ,25879261867897264383063632807223059137462762609820894729277419678914890663158 ,38623480140765111324896240658186465312359836452286369356057144242747750076434 );
2399+ this ._testMulSqrt (97780904848435401688577228945316029068942540304391356583531299677110827351347 ,97780904848435401688577228945316029068942540304391356583531299677110827351347 ,97780904848435401688577228945316029068942540304391356583531299677110827351347 );
2400+ this ._testMulSqrt (39125312885387593452616334467597728868299242980364796136151236474971873470685 ,86828779128818620639494340617473793523235661436852771257233255355108198117255 ,58285531230925917668113509553487197292966405880544341575100636208705254025063 );
2401+ this ._testMulSqrt (28103463145585940293035771056326313713678024127581863885732629790555352610632 ,76815787111206973955699536219912347630679580756295209504314028436731758019833 ,46462776951867402066001606132202385212266391791890179377014155917534178988307 );
2402+ this ._testMulSqrt (55085887312063313304662947434367535525632525671759520071608379009942981796106 ,82800294118819938958395766683447025163837791408331540436336605895422829072207 ,67536121233270524981094905764087840435055016173869770891190734091029911998939 );
2403+ this ._testMulSqrt (11374112687571915868904337573234209429066724575146519193518714103220820309055 ,38136552227230499196160353868270595333171776294556651442476000096535825394060 ,20827132364970253561103779902092578934359252280464989168083476470668469620748 );
2404+ this ._testMulSqrt (58730317605090576282758883651000593881824017604589031401161423874294761362545 ,58730317605090576282758883651000593881824017604589031401161423874294761362556 ,58730317605090576282758883651000593881824017604589031401161423874294761362550 );
2405+ this ._testMulSqrt (50831499485199945339590926255329493296549952108872771415944026608406615545066 ,50831499485199945339590926255329493296549952108872771415944026608406615545075 ,50831499485199945339590926255329493296549952108872771415944026608406615545070 );
2406+ this ._testMulSqrt (85172087893546842302544308826796315864783084900992147451076334534702648635115 ,85172087893546842302544308826796315864783084900992147451076334534702648635115 ,85172087893546842302544308826796315864783084900992147451076334534702648635115 );
2407+ this ._testMulSqrt (65565054857983221818976561024613786630057794203730058177227059603745603013729 ,65565054857983221818976561024613786630057794203730058177227059603745603013729 ,65565054857983221818976561024613786630057794203730058177227059603745603013729 );
2408+ this ._testMulSqrt (55911495894251782213187662010802819104143247543461889936919543738942314665456 ,55911495894251782213187662010802819104143247543461889936919543738942314665463 ,55911495894251782213187662010802819104143247543461889936919543738942314665459 );
2409+ this ._testMulSqrt (17879363847304668652748901453932635872715480532463893033011272860213208357255 ,30088485217079270634851249038350032152097092409273038120371466325762898598320 ,23194028861118718470348997581404528819309525163067296635449034115712705381145 );
2410+ this ._testMulSqrt (22574079799238893389795996210248534007844658027018240720384507454263215868089 ,23831003504672027024172723977212295224054264531333207324229467512231849039503 ,23194028861118718470348997581404528819309525163067296635449034115712705381145 );
2411+ this ._testMulSqrt (10611306079283782718696192094919244168932152831659131747498031131196511452379 ,15040246427133913011360593741211490257502964477997080664156994032702222657211 ,12633157101301807356759851956784431867751428103301339039224348881394628761742 );
2412+ this ._testMulSqrt (73858585336675259861717749966041474360396794822352124567893338971277971476418 ,73858585336675259861717749966041474360396794822352124567893338971277971476418 ,73858585336675259861717749966041474360396794822352124567893338971277971476418 );
2413+ this ._testMulSqrt (93493926051444437853990951601184659120548710831844470529111733337613793165495 ,54214116350546943146180291574636539900604297425564498997024649792129389692208 ,71194737059858860760008503832934929635934877910339827282451164211383009505882 );
2414+ this ._testMulSqrt (31741633454414803277828892614935784705765176373701489896871054927885458857680 ,31741633454414803277828892614935784705765176373701489896871054927885458857683 ,31741633454414803277828892614935784705765176373701489896871054927885458857681 );
2415+ this ._testMulSqrt (73131310464141944405157343302384814531452681906375563388541324773631263794690 ,73131310464141944405157343302384814531452681906375563388541324773631263794693 ,73131310464141944405157343302384814531452681906375563388541324773631263794691 );
2416+ this ._testMulSqrt (65455015498287996254702939291233980776874205016778705952818114191323439048349 ,65455015498287996254702939291233980776874205016778705952818114191323439048349 ,65455015498287996254702939291233980776874205016778705952818114191323439048349 );
2417+ this ._testMulSqrt (81462032043753857067983762687246123130574773932537561797650535926862438796461 ,81462032043753857067983762687246123130574773932537561797650535926862438796478 ,81462032043753857067983762687246123130574773932537561797650535926862438796469 );
2418+ this ._testMulSqrt (78209457813515644067726265623499202575598482171839000555604704620897437284905 ,78209457813515644067726265623499202575598482171839000555604704620897437284905 ,78209457813515644067726265623499202575598482171839000555604704620897437284905 );
2419+ this ._testMulSqrt (13412474850080548643225312277495789264111309375181229577549786099110203380624 ,40109150684236126557038510591608000846411423768057235283250658763488731560550 ,23194028861118718470348997581404528819309525163067296635449034115712705381145 );
2420+ this ._testMulSqrt (40011146698470653129691243350367280704077684991355208240666470591824566065223 ,40011146698470653129691243350367280704077684991355208240666470591824566065236 ,40011146698470653129691243350367280704077684991355208240666470591824566065229 );
2421+ this ._testMulSqrt (84469863776974389618863256801434264209320466806351315058376170339221016552781 ,105252699476938925947685053655574147531645177588390239327939130772357535593314 ,94290408775102118898547330988195929704226272047925587806802926560630963930928 );
2422+ this ._testMulSqrt (30101390199343843269859768555851977933764901751609935209985867350357455919180 ,112858679561759692460068611865224624921408338260436569801949431998683320106122 ,58285531230925917668113509553487197292966405880544341575100636208705254025063 );
2423+ this ._testMulSqrt (49252281286569566201714256790755535986103544271522937010444395775245383022031 ,103313582627134147756455088718855511170155287731084491962378585746899181375663 ,71333229509639179283943164935234626333287573837435931792829607795291911850054 );
2424+ this ._testMulSqrt (103203975778750389840486623148704163858899099747818966282132716369708045200084 ,103203975778750389840486623148704163858899099747818966282132716369708045200084 ,103203975778750389840486623148704163858899099747818966282132716369708045200084 );
2425+ this ._testMulSqrt (107596843987355231847546681774981365988735519046298392541656481902159008087733 ,107596843987355231847546681774981365988735519046298392541656481902159008087733 ,107596843987355231847546681774981365988735519046298392541656481902159008087733 );
2426+ this ._testMulSqrt (102830484155533021557704227144831932637592583365851544616380718131012301176108 ,102830484155533021557704227144831932637592583365851544616380718131012301176108 ,102830484155533021557704227144831932637592583365851544616380718131012301176108 );
2427+ this ._testMulSqrt (115780671983614014435071450400947059939097134791386840528286481782155947852587 ,115780671983614014435071450400947059939097134791386840528286481782155947852608 ,115780671983614014435071450400947059939097134791386840528286481782155947852597 );
2428+ this ._testMulSqrt (102599946188735338018377241438053351371953655256423785960693281164040632229692 ,113977391922349753717143966833940674036437676311140700292665530749893373322354 ,108139143134969783777522484667256465358316928947625235238969806848330075092141 );
2429+ this ._testMulSqrt (104750355640940008131284436009813329129514270958235948287118057008845178828468 ,111637561575924997019627058419809811559908173308145846004665185899087410950352 ,108139143134969783777522484667256465358316928947625235238969806848330075092141 );
2430+ // forgefmt: disable-end
2431+ }
22972432}
0 commit comments