Fix strtod multiple-precision division bug (bug 26137).

Bug 26137 reports spurious "inexact" exceptions from strtod, on 32-bit
systems only, for a decimal argument that is exactly 1 + 2^-32.  In
fact the same issue also appears for 1 + 2^-64 and 1 + 2^-96 as
arguments to strtof128 on 32-bit systems, and 1 + 2^-64 as an argument
to strtof128 on 64-bit systems.  In FE_DOWNWARD or FE_TOWARDZERO mode,
the return value is also incorrect.

The problem is in the multiple-precision division logic used in the
case of dividing by a denominator that occupies at least three GMP
limbs.  There was a comment "The division does not work if the upper
limb of the two-limb mumerator is greater than the denominator.", but
in fact there were problems for the case of equality (that is, where
the high limbs are equal, offset by some multiple of the GMP limb
size) as well.  In such cases, the code used "quot = ~(mp_limb_t) 0;"
(with subsequent correction if that is an overestimate), because
udiv_qrnnd does not support the case of equality, but it's possible
for the shifted numerator to be greater than or equal to the
denominator, in which case that is an underestimate.  To avoid that,
this patch changes the ">" condition to ">=", meaning the first
division is done with a zero high word.

The tests added are all 1 + 2^-n for n from 1 to 113 except for those
that were already present in tst-strtod-round-data.

Tested for x86_64 and x86.
This commit is contained in:
Joseph Myers 2020-06-30 23:04:06 +00:00
parent 5f40e4b1ba
commit 09555b9721
3 changed files with 3577 additions and 2 deletions

View File

@ -1648,8 +1648,8 @@ ____STRTOF_INTERNAL (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group,
d1 = den[densize - 2];
/* The division does not work if the upper limb of the two-limb
numerator is greater than the denominator. */
if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0)
numerator is greater or equal to than the denominator. */
if (__mpn_cmp (num, &den[densize - numsize], numsize) >= 0)
num[numsize++] = 0;
if (numsize < densize)

View File

@ -155,3 +155,113 @@
-179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215
-1189731495357231765085759326628007130763444687096510237472674821233261358180483686904488595472612039915115437484839309258897667381308687426274524698341565006080871634366004897522143251619531446845952345709482135847036647464830984784714280967845614138476044338404886122905286855313236158695999885790106357018120815363320780964323712757164290613406875202417365323950267880089067517372270610835647545755780793431622213451903817859630690311343850657539360649645193283178291767658965405285113556134369793281725888015908414675289832538063419234888599898980623114025121674472051872439321323198402942705341366951274739014593816898288994445173400364617928377138074411345791848573595077170437644191743889644885377684738322240608239079061399475675334739784016491742621485229014847672335977897158397334226349734811441653077758250988926030894789604676153104257260141806823027588003441951455327701598071281589597169413965608439504983171255062282026626200048042149808200002060993433681237623857880627479727072877482838438705048034164633337013385405998040701908662387301605018188262573723766279240798931717708807901740265407930976419648877869604017517691938687988088008944251258826969688364194133945780157844364946052713655454906327187428531895100278695119323496808703630436193927592692344820812834297364478686862064169042458555136532055050508189891866846863799917647547291371573500701015197559097453040033031520683518216494195636696077748110598284901343611469214274121810495077979275556645164983850062051066517084647369464036640569339464837172183352956873912042640003611618789278195710052094562761306703551840330110645101995435167626688669627763820604342480357906415354212732946756073006907088870496125050068156659252761297664065498347492661798824062312210409274584565587264846417650160123175874034726261957289081466197651553830744424709698634753627770356227126145052549125229448040149114795681359875968512808575244271871455454084894986155020794806980939215658055319165641681105966454159951476908583129721503298816585142073061480888021769818338417129396878371459575846052583142928447249703698548125295775920936450022651427249949580708203966082847550921891152133321048011973883636577825533325988852156325439335021315312134081390451021255363707903495916963125924201167877190108935255914539488216897117943269373608639074472792751116715127106396425081353553137213552890539802602978645319795100976432939091924660228878912900654210118287298298707382159717184569540515403029173307292454391789568674219640761451173600617752186991913366837033887201582071625868247133104513315097274713442728340606642890406496636104443217752811227470029162858093727701049646499540220983981932786613204254226464243689610107429923197638681545837561773535568984536053627234424277105760924864023781629665526314910906960488073475217005121136311870439925762508666032566213750416695719919674223210606724721373471234021613540712188239909701971943944347480314217903886317767779921539892177334344368907550318800833546852344370327089284147501640589448482001254237386680074457341910933774891959681016516069106149905572425810895586938833067490204900368624166301968553005687040285095450484840073528643826570403767157286512380255109954518857013476588189300004138849715883139866071547574816476727635116435462804401112711392529180570794193422686818353212799068972247697191474268157912195973794192807298886952361100880264258801320928040011928153970801130741339550003299015924978259936974358726286143980520112454369271114083747919007803406596321353417004068869443405472140675963640997405009225803505672726465095506267339268892424364561897661906898424186770491035344080399248327097911712881140170384182058601614758284200750183500329358499691864066590539660709069537381601887679046657759654588001937117771344698326428792622894338016112445533539447087462049763409147542099248815521395929388007711172017894897793706604273480985161028815458787911160979113422433557549170905442026397275695283207305331845419990749347810524006194197200591652147867193696254337864981603833146354201700628817947177518115217674352016511172347727727075220056177748218928597158346744541337107358427757919660562583883823262178961691787226118865632764934288772405859754877759869235530653929937901193611669007472354746360764601872442031379944139824366828698790212922996174192728625891720057612509349100482545964152046477925114446500732164109099345259799455690095576788686397487061948854749024863607921857834205793797188834779656273479112388585706424836379072355410286787018527401653934219888361061949671961055068686961468019035629749424086587195041004404915266476272761070511568387063401264136517237211409916458796347624949215904533937210937520465798300175408017538862312719042361037129338896586028150046596078872444365564480545689033575955702988396719744528212984142578483954005084264327730840985420021409069485412320805268520094146798876110414583170390473982488899228091818213934288295679717369943152460447027290669964066815
+0x.80000000000000000000000000000001p1025
1.5
1.25
1.125
1.0625
1.03125
1.015625
1.0078125
1.00390625
1.001953125
1.0009765625
1.00048828125
1.000244140625
1.0001220703125
1.00006103515625
1.000030517578125
1.0000152587890625
1.00000762939453125
1.000003814697265625
1.0000019073486328125
1.00000095367431640625
1.000000476837158203125
1.0000000298023223876953125
1.00000001490116119384765625
1.000000007450580596923828125
1.0000000037252902984619140625
1.00000000186264514923095703125
1.000000000931322574615478515625
1.0000000004656612873077392578125
1.00000000023283064365386962890625
1.000000000116415321826934814453125
1.0000000000582076609134674072265625
1.00000000002910383045673370361328125
1.000000000014551915228366851806640625
1.0000000000072759576141834259033203125
1.00000000000363797880709171295166015625
1.000000000001818989403545856475830078125
1.0000000000009094947017729282379150390625
1.00000000000045474735088646411895751953125
1.000000000000227373675443232059478759765625
1.0000000000001136868377216160297393798828125
1.00000000000005684341886080801486968994140625
1.000000000000028421709430404007434844970703125
1.0000000000000142108547152020037174224853515625
1.00000000000000710542735760100185871124267578125
1.000000000000003552713678800500929355621337890625
1.0000000000000017763568394002504646778106689453125
1.00000000000000088817841970012523233890533447265625
1.000000000000000444089209850062616169452667236328125
1.0000000000000002220446049250313080847263336181640625
1.00000000000000011102230246251565404236316680908203125
1.000000000000000055511151231257827021181583404541015625
1.0000000000000000277555756156289135105907917022705078125
1.00000000000000001387778780781445675529539585113525390625
1.000000000000000006938893903907228377647697925567626953125
1.0000000000000000034694469519536141888238489627838134765625
1.00000000000000000173472347597680709441192448139190673828125
1.000000000000000000867361737988403547205962240695953369140625
1.0000000000000000004336808689942017736029811203479766845703125
1.00000000000000000021684043449710088680149056017398834228515625
1.000000000000000000108420217248550443400745280086994171142578125
1.0000000000000000000542101086242752217003726400434970855712890625
1.00000000000000000002710505431213761085018632002174854278564453125
1.000000000000000000013552527156068805425093160010874271392822265625
1.0000000000000000000067762635780344027125465800054371356964111328125
1.00000000000000000000338813178901720135627329000271856784820556640625
1.000000000000000000001694065894508600678136645001359283924102783203125
1.0000000000000000000008470329472543003390683225006796419620513916015625
1.00000000000000000000042351647362715016953416125033982098102569580078125
1.000000000000000000000211758236813575084767080625169910490512847900390625
1.0000000000000000000001058791184067875423835403125849552452564239501953125
1.00000000000000000000005293955920339377119177015629247762262821197509765625
1.000000000000000000000026469779601696885595885078146238811314105987548828125
1.0000000000000000000000132348898008484427979425390731194056570529937744140625
1.00000000000000000000000661744490042422139897126953655970282852649688720703125
1.000000000000000000000003308722450212110699485634768279851414263248443603515625
1.0000000000000000000000016543612251060553497428173841399257071316242218017578125
1.00000000000000000000000082718061255302767487140869206996285356581211090087890625
1.000000000000000000000000413590306276513837435704346034981426782906055450439453125
1.0000000000000000000000002067951531382569187178521730174907133914530277252197265625
1.00000000000000000000000010339757656912845935892608650874535669572651386260986328125
1.000000000000000000000000051698788284564229679463043254372678347863256931304931640625
1.0000000000000000000000000258493941422821148397315216271863391739316284656524658203125
1.00000000000000000000000001292469707114105741986576081359316958696581423282623291015625
1.000000000000000000000000006462348535570528709932880406796584793482907116413116455078125
1.0000000000000000000000000032311742677852643549664402033982923967414535582065582275390625
1.00000000000000000000000000161558713389263217748322010169914619837072677910327911376953125
1.000000000000000000000000000807793566946316088741610050849573099185363389551639556884765625
1.0000000000000000000000000004038967834731580443708050254247865495926816947758197784423828125
1.00000000000000000000000000020194839173657902218540251271239327479634084738790988922119140625
1.000000000000000000000000000100974195868289511092701256356196637398170423693954944610595703125
1.0000000000000000000000000000504870979341447555463506281780983186990852118469774723052978515625
1.00000000000000000000000000002524354896707237777317531408904915934954260592348873615264892578125
1.000000000000000000000000000012621774483536188886587657044524579674771302961744368076324462890625
1.0000000000000000000000000000063108872417680944432938285222622898373856514808721840381622314453125
1.00000000000000000000000000000315544362088404722164691426113114491869282574043609201908111572265625
1.000000000000000000000000000001577721810442023610823457130565572459346412870218046009540557861328125
1.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625
1.00000000000000000000000000000039443045261050590270586428264139311483660321755451150238513946533203125
1.000000000000000000000000000000197215226305252951352932141320696557418301608777255751192569732666015625
1.0000000000000000000000000000000986076131526264756764660706603482787091508043886278755962848663330078125
1.00000000000000000000000000000004930380657631323783823303533017413935457540219431393779814243316650390625
1.000000000000000000000000000000024651903288156618919116517665087069677287701097156968899071216583251953125
1.0000000000000000000000000000000123259516440783094595582588325435348386438505485784844495356082916259765625
1.00000000000000000000000000000000616297582203915472977912941627176741932192527428924222476780414581298828125
1.000000000000000000000000000000003081487911019577364889564708135883709660962637144621112383902072906494140625
1.0000000000000000000000000000000015407439555097886824447823540679418548304813185723105561919510364532470703125
1.00000000000000000000000000000000077037197775489434122239117703397092741524065928615527809597551822662353515625
1.000000000000000000000000000000000385185988877447170611195588516985463707620329643077639047987759113311767578125
1.0000000000000000000000000000000001925929944387235853055977942584927318538101648215388195239938795566558837890625
1.00000000000000000000000000000000009629649721936179265279889712924636592690508241076940976199693977832794189453125

File diff suppressed because it is too large Load Diff