function [ ibeta, it, irnd, ngrd, machep, negep, iexp, minexp, ...
  maxexp, eps, epsneg, xmin, xmax ] = r8_machar ( )

%*****************************************************************************80
%
%% R8_MACHAR determines double precision real machine constants.
%
%  Discussion:
%
%    This routine determines the parameters of the double precision
%    real arithmetic system.  The determination of the first
%    three uses an extension of an algorithm due to Malcolm,
%    incorporating some of the improvements suggested by Gentleman and
%    Marovich.
%
%    This routine appeared as ACM algorithm 665.
%
%    An earlier version of this program was published in Cody and Waite.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 October 2011
%
%  Author:
%
%    Original FORTRAN77 version by William Cody.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    William Cody,
%    ACM Algorithm 665, MACHAR, a routine to dynamically determine
%    machine parameters,
%    ACM Transactions on Mathematical Software,
%    Volume 14, Number 4, pages 303-311, 1988.
%
%    William Cody, William Waite,
%    Software Manual for the Elementary Functions,
%    Prentice Hall, 1980.
%
%    Morvern Gentleman, Scott Marovich,
%    Communications of the ACM,
%    Volume 17, pages 276-277, 1974.
%
%    Michael Malcolm,
%    Communications of the ACM,
%    Volume 15, pages 949-951, 1972.
%
%  Parameters:
%
%    Output, integer IBETA, the radix for the floating-point representation.
%
%    Output, integer IT, the number of base IBETA digits in the floating-point
%    significand.
%
%    Output, integer IRND:
%    0, if floating-point addition chops.
%    1, if floating-point addition rounds, but not in the IEEE style.
%    2, if floating-point addition rounds in the IEEE style.
%    3, if floating-point addition chops, and there is partial underflow.
%    4, if floating-point addition rounds, but not in the IEEE style, and
%      there is partial underflow.
%    5, if floating-point addition rounds in the IEEE style, and there is
%      partial underflow.
%
%    Output, integer NGRD, the number of guard digits for multiplication with
%    truncating arithmetic.  It is
%    0, if floating-point arithmetic rounds, or if it truncates and only
%      IT base IBETA digits participate in the post-normalization shift of the
%      floating-point significand in multiplication;
%    1, if floating-point arithmetic truncates and more than IT base IBETA
%      digits participate in the post-normalization shift of the floating-point
%      significand in multiplication.
%
%    Output, integer MACHEP, the largest negative integer such that
%      1.0 < 1.0 + real ( IBETA )^MACHEP,
%    except that MACHEP is bounded below by - ( IT + 3 ).
%
%    Output, integer NEGEPS, the largest negative integer such that
%      1.0 - real ( IBETA )^NEGEPS < 1.0,
%    except that NEGEPS is bounded below by - ( IT + 3 ).
%
%    Output, integer IEXP, the number of bits (decimal places if IBETA = 10)
%    reserved for the representation of the exponent (including the bias or
%    sign) of a floating-point number.
%
%    Output, integer MINEXP, the largest in magnitude negative integer such
%    that
%      real ( IBETA )^MINEXP
%    is positive and normalized.
%
%    Output, integer MAXEXP, the smallest positive power of BETA that overflows.
%
%    Output, real EPS, the smallest positive floating-point number
%    such that
%      1.0 + EPS ~= 1.0.
%    in particular, if either IBETA = 2  or IRND = 0,
%      EPS = real ( IBETA )^MACHEP.
%    Otherwise,
%      EPS = ( real ( IBETA )^MACHEP ) / 2.
%
%    Output, real EPSNEG, a small positive floating-point number
%    such that
%      1.0 - EPSNEG < 1.0.
%    In particular, if IBETA = 2 or IRND = 0,
%      EPSNEG = real ( IBETA )^NEGEPS.
%    Otherwise,
%      EPSNEG = ( real ( IBETA )^NEGEPS ) / 2.
%    Because NEGEPS is bounded below by - ( IT + 3 ), EPSNEG might not be the
%    smallest number that can alter 1.0 by subtraction.
%
%    Output, real XMIN, the smallest non-vanishing normalized
%    floating-point power of the radix:
%      XMIN = real ( IBETA )^MINEXP
%
%    Output, real XMAX, the largest finite floating-point number.
%    In particular,
%      XMAX = ( 1.0 - EPSNEG ) * real ( IBETA )^MAXEXP
%    On some machines, the computed value of XMAX will be only the second,
%    or perhaps third, largest number, being too small by 1 or 2 units in
%    the last digit of the significand.
%
  one = 1;
  two = one + one;
  zero = one - one;
%
%  Determine IBETA and BETA ala Malcolm.
%
  a = one;

  while ( true )

    a = a + a;
    temp = a + one;
    temp1 = temp - a;

    if ( temp1 - one ~= zero )
      break
    end

  end

  b = one;

  while ( true )

    b = b + b;
    temp = a + b;
    itemp = floor ( temp - a );

    if ( itemp ~= 0 )
      break
    end

  end

  ibeta = itemp;
  beta = ibeta;
%
%  Determine IT and IRND.
%
  it = 0;
  b = one;

  while ( true )

    it = it + 1;
    b = b * beta;
    temp = b + one;
    temp1 = temp - b;

    if ( temp1 - one ~= zero )
      break
    end

  end

  irnd = 0;
  betah = beta / two;
  temp = a + betah;

  if ( temp - a ~= zero )
    irnd = 1;
  end

  tempa = a + beta;
  temp = tempa + betah;

  if ( irnd == 0 && temp - tempa ~= zero )
    irnd = 2;
  end
%
%  Determine NEGEP and EPSNEG.
%
  negep = it + 3;
  betain = one / beta;
  a = one;
  for i = 1 : negep
    a = a * betain;
  end

  b = a;

  while ( true )

    temp = one - a;

    if ( temp - one ~= zero )
      break
    end

    a = a * beta;
    negep = negep - 1;

  end

  negep = -negep;
  epsneg = a;

  if ( ibeta ~= 2 && irnd ~= 0 )

    a = ( a * ( one + a ) ) / two;
    temp = one - a;

    if ( temp - one ~= zero )
      epsneg = a;
    end

  end
%
%  Determine MACHEP and EPS.
%
  machep = -it - 3;
  a = b;

  while ( true )

    temp = one + a;

    if ( temp - one ~= zero ) 
      break
    end

    a = a * beta;
    machep = machep + 1;

  end

  eps = a;
  temp = tempa + beta * ( one + eps );

  if ( ibeta ~= 2 && irnd ~= 0 )

    a = ( a * ( one + a ) ) / two;
    temp = one + a;

    if ( temp - one ~= zero )
      eps = a;
    end

  end
%
%  Determine NGRD.
%
  ngrd = 0;
  temp = one + eps;

  if ( irnd == 0 && temp * one - one ~= zero )
    ngrd = 1;
  end
%
%  Determine IEXP, MINEXP and XMIN.
%
%  Loop to determine largest I and K = 2^I such that (1/BETA)^(2^(I))
%  does not underflow.  Exit from loop is signaled by an underflow.
%
  i = 0;
  k = 1;
  z = betain;
  t = one + eps;
  nxres = 0;

  while ( true )

    y = z;
    z = y * y;

    a = z * one;
    temp = z * t;

    if ( a + a == zero || y <= abs ( z ) )
      break
    end

    temp1 = temp * betain;

    if ( temp1 * beta == z )
      break
    end

    i = i + 1;
    k = k + k;

  end
%
%  This segment is for nondecimal machines.
%
  if ( ibeta ~= 10 )

    iexp = i + 1;
    mx = k + k;
%
%  This segment is for decimal machines only.
%
  else

    iexp = 2;
    iz = ibeta;

    while ( true )

      if ( k < iz )
        break
      end

      iz = iz * ibeta;
      iexp = iexp + 1;

    end

    mx = iz + iz - 1;

  end
%
%  Loop to determine MINEXP, XMIN.
%  Exit from loop is signaled by an underflow.
%
  while ( true )

    xmin = y;
    y = y * betain;

    a = y * one;
    temp = y * t;

    if ( a + a == zero || xmin <= abs ( y ) )
      break
    end

    k = k + 1;
    temp1 = temp * betain;

    if ( temp1 * beta == y )
      nxres = 3;
      xmin = y;
      break
    end

  end

  minexp = - k;
%
%  Determine MAXEXP and XMAX.
%
  if ( mx <= k + k - 3 && ibeta ~= 10 )
    mx = mx + mx;
    iexp = iexp + 1;
  end

  maxexp = mx + minexp;
%
%  Adjust IRND to reflect partial underflow.
%
  irnd = irnd + nxres;
%
%  Adjust for IEEE-style machines.
%
  if ( irnd == 2 || irnd == 5 )
    maxexp = maxexp - 2;
  end
%
%  Adjust for non-IEEE machines with partial underflow.
%
  if ( irnd == 3 || irnd == 4 )
    maxexp = maxexp - it;
  end
%
%  Adjust for machines with implicit leading bit in binary significand,
%  and machines with radix point at extreme right of significand.
%
  i = maxexp + minexp;

  if ( ibeta == 2 && i == 0 )
    maxexp = maxexp - 1;
  end

  if ( 20 < i )
    maxexp = maxexp - 1;
  end

  if ( a ~= y )
    maxexp = maxexp - 2;
  end

  xmax = one - epsneg;

  if ( xmax * one ~= xmax )
    xmax = one - beta * epsneg;
  end

  xmax = xmax / ( beta * beta * beta * xmin );

  i = maxexp + minexp + 3;

  for j = 1 : i

    if ( ibeta == 2 )
      xmax = xmax + xmax;
    else
      xmax = xmax * beta;
    end

  end

  return
end
