INTERFACEAFmtBufF ;
friends
interface for the FmtBuf
interface that reveals
internal types and procedures.
IMPORT Fmt, FmtBuf, RealFloat, LongFloat, ExtendedFloat; TYPE Class = { NaN, Inf, Number, Zero }; IEEEKind = { Single, Double, Extended };The
Class
type is a coarse-grained and precision-independent
representation of the class of an IEEE floating-point number.
The NaN
class includes both quiet and signalling NaN's. The
Number
class includes both normal and denormal numbers.
The IEEEKind
type enumerates the three IEEE floating-point
precisions.
CONST ClassMapReal = ARRAY RealFloat.IEEEClass OF Class{ Class.NaN, Class.NaN, Class.Inf, Class.Number, Class.Number, Class.Zero}; ClassMapLong = ARRAY LongFloat.IEEEClass OF Class{ Class.NaN, Class.NaN, Class.Inf, Class.Number, Class.Number, Class.Zero}; ClassMapExtd = ARRAY ExtendedFloat.IEEEClass OF Class{ Class.NaN, Class.NaN, Class.Inf, Class.Number, Class.Number, Class.Zero};The
ClassMapReal
, ClassMapLong
, and ClassMapExtd
arrays
are maps from the appropriate IEEEClass
type to the corresponding
precision-independent Class
type.
TYPE NumAttr = RECORD class: Class; kind: IEEEKind; sign: [0..1]; maxExpDigits: CARDINAL; len: CARDINAL; exp: INTEGER; errorSign: [-1..1]; END; Digits = ARRAY OF [0..9];This interface represents a floating point number by a pair of values
(num, digits)
in the set NumAttr x Digits
. num
contains attributes
of the number, and digits
contains the digits of the number. The
first four fields of num
are defined by:
"class" denotes the class of the number, "kind" denotes the precision of the number, "sign" is the sign bit of the number (0 = positive, 1 = negative), and "maxExpDigits" is the maximum number of base-10 exponent digits required by "kind"-precision real numbersIf
num.class = Class.Number
, then the other fields of num
are the same as those in the DecimalApprox
structure produced
by the ToDecimal
procedure in instantiations of the Float
interface. A Digits
value contains the same digits as the digits
field of the DecimalApprox
record; this field has been removed from
the record so it can be passed READONLY on the stack for efficiency.
TYPE FmtRec = RECORD style: Fmt.Style; prec: CARDINAL; literal: BOOLEAN; END;A
FmtRec
bundles together the three formatting parameters that
determine how a floating-point value should be formatted.
PROCEDURE Float( VAR (*OUT*) b: FmtBuf.T; READONLY num: NumAttr; VAR (*IN*) digits: Digits; READONLY fmt: FmtRec) : CARDINAL;
Format the number(num, digits)
into the bufferb
to precisionfmt.prec
according to formatting stylefmt.style
andfmt.literal
as defined in theFmt
interface. Returns the number of characters written into the bufferb
. It is a checked run-time error forb
not to be large enough to hold the result. The contents ofdigits
is undefined on return.
The caller must guarantee that the buffer
b
passed to Float
is
sufficiently large. The tricky question is to decide how large the
buffer needs to be. Our goal here is to develop an upper-bound that
is easy to compute. We proceed by a case analysis.
We need not consider the Style.Auto
style, since the width of a
number produced with Style.Auto
is at most the maximum of the width
produced using Style.Sci
and Style.Fix
.
A number of type T
rendered to prec
digits of precision with
Style.Sci
will normally produce a text of length 5 + prec +
T.MaxExpDigits
(the 5 extra characters are for the leading sign,
leading digit, decimal point, exponent character, and exponent sign).
However, in the case that prec = 0
, the width will be 1 larger if
literal = TRUE
and 1 smaller otherwise. Also, in the case where
literal = TRUE
, the special values Nan
and Infinity
require 8
characters in the single-precision case and 12 characters in the
double- and extended-precision cases. Hence, some good upper-bounds
for Style.Sci
are:
literal = FALSE: width <= 5 + prec + T.MaxExpDigits literal = TRUE: width <= MAX(5 + MAX(prec, 1) + T.MaxExpDigits, 12)The width of a number rendered according to
Style.Fix
is a bit more
difficult to bound. Independent of the literal
parameter, the values
NaN
and Infinity
require at most 12 characters, and the value zero
requires at most MAX(prec, 1) + 5
characters. A non-zero fixpoint
number is formatted to have the form [-]DD***D.PP***P[(d|x)0]
. There
are exactly prec
digits after the decimal, but the number of digits
before the decimal depends on the magnitude of the number. Suppose the
base-10 exponent of the number, if rendered in scientific notation, is
exp
. Then the number of digits before the decimal is given by
MAX(exp, 1)
. Hence, the maximum width for each class of number
rendered in Style.Fix
is:
Nan, Infinity: width <= 12 Zero: width <= 5 + MAX(prec, 1) All others: width <= 4 + MAX(prec, 1) + MAX(exp, 1)Hence, an overall cautious upper-bound is given by the following formula, where
exp
is defined to be zero in the Nan
, Infinity
,
and Zero
cases:
Style.Fix: width <= MAX(4 + MAX(prec, 1) + MAX(exp, 1), 12)END FmtBufF.