On 03/08/2012 05:40 PM, Janne Blomqvist wrote:

Hi,## Advertising

the attached patch implements some improvements for formatted writes of floating point values. Currently libgfortran uses snprintf() to fill a buffer with a fixed amount of digits, regardless of the digits required, and then rounding or zero extending as needed. The patch changes this to first figure out the number of digits needed, then using snprintf() to fill the buffer with exactly the needed amount of digits (except when a ROUND= specifier is used, in that case more digits are generated). This has a few advantages: - As the performance cost of snprintf() increases roughly linearly with more digits (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38199#c13 ), we needlessly waste cycles when we don't need all the digits. The attached write-many.f90 benchmark is almost twice as fast; best of five timings with current trunk: real 0m2.055s with patch: real 0m1.268s - Although we generate enough digits to be able to get back the original value exactly when reading, there are some (valid?) usecases where more digits are needed. Exhibit 1 is dyadic.f90 which prints a couple dyadic fractions which are exact both in binary and character representations. With current trunk: $ ./dyadic_f .000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

000000000000000000000000000000000000000000000000000000000000000000000000000000

.99999999999999988897769753748434595763683000000000000 With patch: $ ./dyadic_f .0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000494065645841246544176568792868221372365059802614324 76442558568250067550727020875186529983636163599237979656469544571773092665671035593979639877479601078187812630071319031140452 78458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566 86768187039560310624931945271591492455329305456544401127480129709999541931989409080416563324524757147869014726780159355238611 55013480352649347201937902681071074917033322268447533357208324319360923828934583680601060115061698097530783422773183292479049 82524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993 664809941164205702637090279242767544565229087538682506419718265533447265625 .99999999999999988897769753748434595763683319091796875 For another example, Bob Corbett recently posted boz_corbett.f90 on c.l.f. With trunk: $ ./boz_corbett .67242062862241870125253556346435045576786000...E-4931 where "..." is a very long string of zeros. With patch: $ ./boz_corbett .672420628622418701252535563464350455767864674589043138777375863685283014882452413061808444374167...E-4931 where "..." is a very long string of digits. - With the patch, for the vast majority of Fortran programs which don't use the F2003 ROUND= specifier, we let snprintf() do the rounding (as we generate the correct number of digits to begin with). Thus isolating the user from potential bugs in the rounding logic in libgfortran, as well as the performance impacts of that same code. Note that GFortran previously did roundTiesToAway, whereas at least glibc snprintf() does roundTiesToEven, so some change in behavior is expected. Anyway, this is IMHO for the better, as it avoids biasing the magnitude upwards in some common cases. Also, roundTiesToAway is the default rounding mode for arithmetic. Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

`I like the idea behind this patch. I confess, I have not studied the two test`

`cases that you are modifying, but the changes seem to stick out with too many`

`digits there. Is this really correct?`

`When I get another moment, I will look closer. Maybe you can explain the need`

`for this change a little more. Sorry if I am being to careful. Its been many`

`months since I delved into the formatting code.`

Best regards, Jerry