function [ ibeta, it, irnd, ngrd, machep, negep, iexp, minexp, ... maxexp, eps, epsneg, xmin, xmax ] = r4_machar ( ) %*****************************************************************************80 % %% R4_MACHAR determines single precision real machine constants. % % Discussion: % % This routine determines the parameters of the single 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, single precision 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, single precision 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, single precision real XMIN, the smallest non-vanishing normalized % floating-point power of the radix: % XMIN = real ( IBETA )^MINEXP % % Output, single precision 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. % % % To enforce the single precision arithmetic, we essentially have % to "declare" our real variables, by creating them with the SINGLE % function. % a = single ( 0.0 ); b = single ( 0.0 ); beta = single ( 0.0 ); betah = single ( 0.0 ); betain = single ( 0.0 ); eps = single ( 0.0 ); epsneg = single ( 0.0 ); one = single ( 0.0 ); t = single ( 0.0 ); temp = single ( 0.0 ); temp1 = single ( 0.0 ); tempa = single ( 0.0 ); two = single ( 0.0 ); xmax = single ( 0.0 ); xmin = single ( 0.0 ); y = single ( 0.0 ); z = single ( 0.0 ); zero = single ( 0.0 ); one = single ( 1 ); two = single ( one + one ); zero = single ( one - one ); % % Determine IBETA and BETA ala Malcolm. % a = single ( one ); while ( 1 ) a = single ( a + a ); temp = single ( a + one ); temp1 = single ( temp - a ); if ( single ( temp1 - one ) ~= zero ) break end end b = single ( one ); while ( 1 ) b = single ( b + b ); temp = single ( a + b ); itemp = floor ( temp - a ); if ( itemp ~= 0 ) break end end ibeta = itemp; beta = single ( ibeta ); % % Determine IT and IRND. % it = 0; b = single ( one ); while ( 1 ) it = it + 1; b = single ( b * beta ); temp = single ( b + one ); temp1 = single ( temp - b ); if ( single ( temp1 - one ) ~= zero ) break end end irnd = 0; betah = single ( beta / two ); temp = single ( a + betah ); if ( single ( temp - a ) ~= zero ) irnd = 1; end tempa = single ( a + beta ); temp = single ( tempa + betah ); if ( irnd == 0 & single ( temp - tempa ) ~= zero ) irnd = 2; end % % Determine NEGEP and EPSNEG. % negep = it + 3; betain = single ( one / beta ); a = single ( one ); for i = 1 : negep a = single ( a * betain ); end b = single ( a ); while ( 1 ) temp = single ( one - a ); if ( single ( temp - one ) ~= zero ) break end a = single ( a * beta ); negep = negep - 1; end negep = -negep; epsneg = single ( a ); if ( ibeta ~= 2 & irnd ~= 0 ) a = single ( ( a * ( one + a ) ) / two ); temp = single ( one - a ); if ( single ( temp - one ) ~= zero ) epsneg = single ( a ); end end % % Determine MACHEP and EPS. % machep = - it - 3; a = single ( b ); while ( 1 ) temp = single ( one + a ); if ( single ( temp - one ) ~= zero ) break end a = single ( a * beta ); machep = machep + 1; end eps = single ( a ); temp = single ( tempa + beta * ( one + eps ) ); if ( ibeta ~= 2 & irnd ~= 0 ) a = single ( ( a * ( one + a ) ) / two ); temp = single ( one + a ); if ( single ( temp - one ) ~= zero ) eps = a; end end % % Determine NGRD. % ngrd = 0; temp = single ( one + eps ); if ( irnd == 0 & single ( 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 = single ( betain ); t = single ( one + eps ); nxres = 0; while ( 1 ) y = single ( z ); z = single ( y * y ); a = single ( z * one ); temp = single ( z * t ); if ( single ( a + a ) == zero | y <= abs ( z ) ) break end temp1 = single ( temp * betain ); if ( single ( 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 ( 1 ) 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 ( 1 ) xmin = single ( y ); y = single ( y * betain ); a = single ( y * one ); temp = single ( y * t ); if ( single ( a + a ) == zero | xmin <= abs ( y ) ) break end k = k + 1; temp1 = single ( temp * betain ); if ( single ( temp1 * beta ) == y ) nxres = 3; xmin = single ( 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 = single ( one - epsneg ); if ( single ( xmax * one ) ~= xmax ) xmax = single ( one - beta * epsneg ); end xmax = single ( xmax / ( beta * beta * beta * xmin ) ); i = maxexp + minexp + 3; for j = 1 : i if ( ibeta == 2 ) xmax = single ( xmax + xmax ); else xmax = single ( xmax * beta ); end end return end