NAME
    printf - formatted print to standard output

SYNOPSIS
    printf(fmt, x_1, x_2, ...)

TYPES
    fmt                 string
    x_1, x_2, ...       any

    return              null

DESCRIPTION
    The function printf() is similar to the C function with the same name.
    The most significant difference is that there is no requirement
    that the types of values of the arguments x_i match the
    corresponding format specifier in fmt.  Thus, whatever the
    format specifier, a number is printed as a number, a string as
    a string, a list as a list, a matrix as a matrix, an xx-object
    as an xx-object, etc.

    Except when a '%' is encountered, characters of the string fmt are
    printed in succession to the standard output.  Occurrence of
    a '%' indicates the intention to build a format specifier.
    This is completed by a succession of characters as follows:

            an optional '-'
            zero or more decimal digits
            an optional '. followed by zero or more decimal digits
            an optional 'l'
            one of the letters: d, s, c, f, e, g, r, o, x, b,

    If any other character is read, the '%' and any characters
    between '%' and the character are ignored and no specifier is
    formed.  E.g. "%+f" prints as if only "f" were read; "% 10s"
    prints as "10s", "%X" prints as "X", "%%" prints as "%".

    The characters in a format specifier are interpreted as follows:

            a minus sign sets the right-pad flag;
            the first group of digits determines the width w;
                    w = 0 if there are no digits
            a dot indicates the precision is to be read from the
                    following digits; if there is no dot,
                    precision = config("display").
            any digits following the . determines the precision p;
                    p = 0 if there are no digits
            any 'l' before the final letter is ignored
            the final letter determines the mode as follows:

            d, s, c             current config("mode")
            f           real (decimal, floating point)
            e           exponential
            g           general format (real or exponential)
            r           fractional
            o           octal
            x           hexadecimal
            b           binary

    If the number of arguments after fmt is less than the number
    of format specifiers in fmt, the "missing" arguments may be
    taken to be null values - these contribute nothing to the output;
    if a positive width w has been specified, the effect is to
    produce w spaces, e.g., printf("abc%6dxyz") prints "abc      xyz".

    Control charters may be given in fmt by escaping them with
    the \ character.  The following control charter escape
    sequences are recognized:

        \a      audible bell    byte 0x07 in ASCII encoding
        \b      backspace       byte 0x08 in ASCII encoding
        \f      form feed       byte 0x0c in ASCII encoding
        \n      newline         byte 0x0b in ASCII encoding
        \r      return          byte 0x0a in ASCII encoding
        \t      tab             byte 0x0d in ASCII encoding
        \v      vertical tab    byte 0x09 in ASCII encoding

    If i <= the number of specifiers in fmt, the value of argument
    x_i is printed in the format specified by the i-th specifier.
    If a positive width w has been specified and normal printing
    of x_i does not include a '\n' character, what is printed will
    if necessary be padded with spaces so that the length of the
    printed output is at least the w.  Note that control characters
    (e.g., '\a', '\b', '\f', '\n', '\r', '\t', '\n') count as one
    character.  If the 'right-pad' flag has been set, the padding
    is on the right; otherwise it is on the left.

    If i > the number of specifiers in fmt, the value of argument x_i
    does not contribute to the printing.  However, as all arguments
    are evaluated before printing occurs, side-effects of the
    evaluation of x_i might affect the result.

    If the i-th specifier is of numerical type, any numbers in the
    printing of x_i will be printed in the specified format, unless
    this is modified by the printing procedure for x_i's type.  Any
    specified precision will be ignored except for floating-point
    mode.

    The (g) general format will print the as real (f) (decimal or
    floating point) or as an exponential (e) depending on the
    configuration parameter "display".

    In the case of floating-point (f) format, and the (g) general
    format, the precision determines the maximum number of decimal
    places to be displayed.  Other aspects of this printing may be
    affected by the configuration parameters "outround", "tilde",
    "fullzero", "leadzero".

    IMPORTANT NOTES:

    In calc, %d formats in base 10 according to the current
    config("mode").  Therefore this will print the entire
    "1.2345" value:

        ; printf("%d\n", 1.2345);
        1.2345


    assuming printing of 4 or more digits is allowed by the current
    value of display().

    See also:

        ; help printf
        ; help display
        ; help mode

    In calc, %x formats in base 16.  A non-integer numeric values such
    as 1/3 is represented as a fraction.  When fractions are printed
    in %x format, both the numerator and denominator are printed
    as is mode("fraction"):

        ; printf("%x\n", 1.2345);
        0x9a5/0x7d0

    See also:

        ; help printf
        ; help display
        ; help mode


    Because calc is capable of of printing very large values, some
    people may be surprised when this does not print the entire
    value of M(23209):

        fprintf(fd, "%d\n", 2^23209-1);
        /* the entire value may not be printed yet */

    Because I/O is usually buffered to files, the above fprintf()
    may print only the initial 4096 characters.  One needs to also
    flush (or close the stream) to be sure that the entire
    value as been printed to the file:

        ; fflush(fd);

    A similar problem an arise when printing many digits after
    the decimal point:

        ; display(10000),;
        ; fprintf(fd, "%d\n", pi(1e-10000));
        ; fflush(fd);

    The buffer will also be flushed during a call to fclose():

        ; fclose(fd);

EXAMPLE
    ; config("epsilon", 1e-6),;
    : config("display", 6),;
    ; config("tilde", 1),;
    ; config("outround", 0),;
    ; config("fullzero", 0),;
    ; fmt = "%f,%10f,%-10f,%10.4f,%.4f,%.f.\n";
    ; a = sqrt(3);
    ; printf(fmt,a,a,a,a,a,a);
    1.732051,  1.732051,1.732051  ,   ~1.7320,~1.7320,~1.

    ; fd = fopen("/tmp/test.txt", "w+");
    ; fprintf(fd, "%d\n", 2^23209-1);

    ; ## one must flush to be buffered output is written

    ; fflush(fd);
    ; display(10000),;
    ; fprintf(fd, "%d\n", pi(1e-10000));

    ; ## closing the file will also flush the buffer

    ; fclose(fd);

    ; printf("%x\n", 1.2345);
    0x9a5/0x7d0

    ; config("display", 5),;
    : config("tilde", 0),;
    ; printf("%f\n", pi());
    3.1416
    ; config("display", 10),;
    ; printf("%f\n", pi());
    3.141592654

    ; config("tilde", 0),;
    : config("outround",24),;
    ; config("fullzero", 1),;
    ; printf(fmt,a,a,a,a,a,a);
    1.732051,  1.732051,1.732051  ,    1.7321,1.7321,2.

    ; mat A[4] = {sqrt(2), 3/7, "undefined", null()};
    ; printf("%f%r",A,A);
    mat [4] (4 elements, 4 nonzero):
      [0] = 1.414214
      [1] = 0.428571
      [2] = "undefined"
      [3] = NULL

    mat [4] (4 elements, 4 nonzero):
      [0] = 707107/500000
      [1] = 3/7
      [2] = "undefined"
      [3] = NULL

    ; config("display", 50),;
    ; printf("%g %g\n%g %g\n", 1e5, 1e49, 1e50, 1e500);
    100000 100000000000000000000000000000000000000000000000000
    1e50 1e500

    ; config("display", 10),;
    : config("tilde", 0),;
    ; printf("%f %f %f\n%f %f %f\n",
             exp(1), exp(2), exp(3), exp(4), exp(5), exp(6));
    2.7182818285 7.3890560989 20.0855369232
    54.5981500331 148.4131591026 403.4287934927
    ; printf("%e %e %e\n%e %e %e\n",
             exp(1), exp(2), exp(3), exp(4), exp(5), exp(6));
    2.7182818285 7.3890560989 2.0085536923e1
    5.4598150033e1 1.4841315910e2 4.0342879349e2
    ; printf("%g %g %g\n%g %g %g\n",
             exp(1), exp(2), exp(3), exp(4), exp(5), exp(6));
    2.718281828 7.389056099 20.08553692
    54.59815003 148.4131591 403.4287935

    ; config("display", 10),;
    ; config("tilde", 0),;
    ; printf("%f %f %f\n%f %f %f\n",
             exp(20), exp(21), exp(22), exp(23), exp(24), exp(25));
    485165195.4097902780 1318815734.4832146972 3584912846.1315915617
    9744803446.2489026000 26489122129.8434722941 72004899337.3858725242`
    ; printf("%e %e %e\n%e %e %e\n",
             exp(20), exp(21), exp(22), exp(23), exp(24), exp(25));
    4.8516519541e8 1.3188157345e9 3.5849128461e9
    9.7448034462e9 2.6489122130e10 7.2004899337e10
    ; printf("%g %g %g\n%g %g %g\n",
             exp(20), exp(21), exp(22), exp(23), exp(24), exp(25));
    485165195.4 1318815734 3584912846
    9744803446 2.648912213e10 7.200489934e10

    ; /*
       * NOTE: When displaying many digits after the decimal point
       *       be sure to set display(digits) (see 'help display') to
       *       large enough AND to set epsilon(eps) (see 'help epsilon')
       *       small enough (or if the function has a esp argument,
       *       give a eps argument that is small enough) to display
       *       the value correctly.
       */
    ; config("tilde", 1),;

    ; ## NOTE: display has too few digits and epsilon is not small enough

    ; display(12),;
    ; printf("%f\n", pi(1e-10));
    3.1415926536
    ; epsilon(1e-10),;
    ; printf("%f\n", pi());
    3.1415926536

    ; ## NOTE: display has too few digits yet epsilon is small enough

    ; display(12),;
    ; printf("%f\n", pi(1e-72));
    ~3.141592653590
    ; epsilon(1e-72),;
    ; printf("%f\n", pi());
    ~3.141592653590

    ; ## NOTE: display has enough digits but epsilon is not small enough

    ; display(72),;
    ; printf("%f\n", pi(1e-10));
    3.1415926536
    ; epsilon(1e-10),;
    ; printf("%f\n", pi());
    3.1415926536

    ; ## NOTE: display has enough digits and epsilon is small enough

    ; display(72),;
    ; printf("%f\n", pi(1e-72));
    3.141592653589793238462643383279502884197169399375105820974944592307816406
    ; epsilon(1e-72),;
    ; printf("%f\n", pi());
    3.141592653589793238462643383279502884197169399375105820974944592307816406

LIMITS
    The number of arguments of printf() is not to exceed 1024.

LINK LIBRARY
    none

SEE ALSO
    config, display, epsilon, fclose, fflush, fopen, fprintf, strprintf

## Copyright (C) 1999-2006,2018,2021  Landon Curt Noll
##
## Calc is open software; you can redistribute it and/or modify it under
## the terms of the version 2.1 of the GNU Lesser General Public License
## as published by the Free Software Foundation.
##
## Calc is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
## Public License for more details.
##
## A copy of version 2.1 of the GNU Lesser General Public License is
## distributed with calc under the filename COPYING-LGPL.  You should have
## received a copy with calc; if not, write to Free Software Foundation, Inc.
## 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
##
## Under source code control:   1996/03/12 22:50:41
## File existed as early as:    1996
##
## chongo <was here> /\oo/\     http://www.isthe.com/chongo/
## Share and enjoy!  :-)        http://www.isthe.com/chongo/tech/comp/calc/
