@pexdoc.pcontracts.contract(<EOL>number="<STR_LIT>", frac_length="<STR_LIT>", rjust=bool<EOL>)<EOL>def peng(number, frac_length, rjust=True):
<EOL>if number == <NUM_LIT:0>:<EOL><INDENT>number = "<STR_LIT>".format(zrs="<STR_LIT:0>" * frac_length) if frac_length else "<STR_LIT:0>"<EOL>return "<STR_LIT>".format(number.rjust(<NUM_LIT:5> + frac_length)) if rjust else number<EOL><DEDENT>sign = +<NUM_LIT:1> if number >= <NUM_LIT:0> else -<NUM_LIT:1><EOL>ssign = "<STR_LIT:->" if sign == -<NUM_LIT:1> else "<STR_LIT>"<EOL>anumber = abs(number)<EOL>if anumber < <NUM_LIT>:<EOL><INDENT>anumber = <NUM_LIT><EOL>number = sign * <NUM_LIT><EOL><DEDENT>exp = <NUM_LIT> * math.floor(math.floor(math.log10(anumber)) / <NUM_LIT>)<EOL>mant = number / <NUM_LIT:10> ** exp<EOL>smant = str(mant)<EOL>ppos = smant.find("<STR_LIT:.>")<EOL>if len(smant) - ppos - <NUM_LIT:1> > frac_length:<EOL><INDENT>mant += sign * <NUM_LIT:5> * <NUM_LIT:10> ** (-frac_length - <NUM_LIT:1>)<EOL>if abs(mant) >= <NUM_LIT:1000>:<EOL><INDENT>exp += <NUM_LIT:3><EOL>mant = mant / <NUM_LIT><EOL><DEDENT>smant = str(mant)<EOL>ppos = smant.find("<STR_LIT:.>")<EOL><DEDENT>bfrac_length = bool(frac_length)<EOL>flength = ppos - (not bfrac_length) + frac_length + <NUM_LIT:1><EOL>new_mant = smant[:flength].ljust(flength, "<STR_LIT:0>")<EOL>if exp > <NUM_LIT>:<EOL><INDENT>new_mant, exp = (<EOL>"<STR_LIT>".format(sign=ssign, frac="<STR_LIT>" * frac_length),<EOL><NUM_LIT>,<EOL>)<EOL><DEDENT>new_mant = new_mant.rjust(rjust * (<NUM_LIT:4> + bfrac_length + frac_length))<EOL>num = "<STR_LIT>".format(<EOL>mant=new_mant, suffix=_POWER_TO_SUFFIX_DICT[exp] if exp else "<STR_LIT:U+0020>" * bool(rjust)<EOL>)<EOL>return num<EOL>
r"""
    Convert a number to engineering notation.

    The absolute value of the number (if it is not exactly zero) is bounded to
    the interval [1E-24, 1E+24)

    :param number: Number to convert
    :type  number: integer or float

    :param frac_length: Number of digits of fractional part
    :type  frac_length: :ref:`NonNegativeInteger`

    :param rjust: Flag that indicates whether the number is
                  right-justified (True) or not (False)
    :type  rjust: boolean

    :rtype: string

    .. [[[cog cog.out(exobj_eng.get_sphinx_autodoc()) ]]]
    .. Auto-generated exceptions documentation for
    .. putil.eng.functions.peng

    :raises:
     * RuntimeError (Argument \`frac_length\` is not valid)

     * RuntimeError (Argument \`number\` is not valid)

     * RuntimeError (Argument \`rjust\` is not valid)

    .. [[[end]]]

    The supported engineering suffixes are:

    +----------+-------+--------+
    | Exponent | Name  | Suffix |
    +==========+=======+========+
    | 1E-24    | yocto | y      |
    +----------+-------+--------+
    | 1E-21    | zepto | z      |
    +----------+-------+--------+
    | 1E-18    | atto  | a      |
    +----------+-------+--------+
    | 1E-15    | femto | f      |
    +----------+-------+--------+
    | 1E-12    | pico  | p      |
    +----------+-------+--------+
    | 1E-9     | nano  | n      |
    +----------+-------+--------+
    | 1E-6     | micro | u      |
    +----------+-------+--------+
    | 1E-3     | milli | m      |
    +----------+-------+--------+
    | 1E+0     |       |        |
    +----------+-------+--------+
    | 1E+3     | kilo  | k      |
    +----------+-------+--------+
    | 1E+6     | mega  | M      |
    +----------+-------+--------+
    | 1E+9     | giga  | G      |
    +----------+-------+--------+
    | 1E+12    | tera  | T      |
    +----------+-------+--------+
    | 1E+15    | peta  | P      |
    +----------+-------+--------+
    | 1E+18    | exa   | E      |
    +----------+-------+--------+
    | 1E+21    | zetta | Z      |
    +----------+-------+--------+
    | 1E+24    | yotta | Y      |
    +----------+-------+--------+

    For example:

        >>> import putil.eng
        >>> putil.eng.peng(1235.6789E3, 3, False)
        '1.236M'