This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [gfortran] I/O of large integer and real kinds, round 2


On Thu, Jun 09, 2005 at 12:50:04AM +0200, FX Coudert wrote:
> +      while (x > 1e100L)
> +      {
> +        result += 100;
> +        x /= 1e100L;
> +      }
> +      while (x > 1e10L)
> +      {
> +        result += 10;
> +        x /= 1e10L;
> +      }

You don't have to work this hard.  IEEE double has a dynamic range of
1e308, or so.  Since we're falling back to log10 for evaluation of the
significand, there's no point in reducing the value below DBL_MAX.

Now, real(10) doesn't have *any* more dynamic range, just extra
precision.  So in that case you might as well pass on to log10
immediately and do nothing else.

For real(16), the dynamic range is 1e4932 or so.  In that case,
reducing by 1e100 is going to take quite a long time, and be remarkably
inaccurate.  While you could adjust your scheme to reduce by 1e1000,
it seems like 

long double log10l (long double x)
{
#if LDBL_MAX_EXP > DBL_MAX_EXP
  if (x > DBL_MAX)
    {
      int p2_result = 0;
      if (x >= 0x1p16384L) { p2_result += 16384; x /= 0x1p16384L; }
      if (x >= 0x1p8192L) { p2_result += 8192; x /= 0x1p8192L; }
      if (x >= 0x1p4096L) { p2_result += 4096; x /= 0x1p4096L; }
      if (x >= 0x1p2048L) { p2_result += 2048; x /= 0x1p2048L; }
      if (x >= 0x1p1024L) { p2_result += 1024; x /= 0x1p1024L; }
      return log10 (x) + p2_result * .30102999566398119521373889472449302L;
    }
  else
#endif
    return log10 (x);
}

would be a whole lot faster and be more accurate.  This takes into
account knowledge that real(16) has 4 bits more exponent than real(8),
and specifically targets those four bits for reduction.  The last
reduction (0x1p1024L) is so that something just a bit larger than
DBL_MAX (e.g. DBL_MAX+0x1p912L) doesn't get rounded up to +Inf.


r~


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]