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 numbers
   If 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 bufferbto precisionfmt.precaccording to formatting stylefmt.styleandfmt.literalas defined in theFmtinterface. Returns the number of characters written into the bufferb. It is a checked run-time error forbnot to be large enough to hold the result. The contents ofdigitsis 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.