fus 2.4.1
import "./main" all

approxEquals'export: (num, x) -> Math..approxEquals(num.valueOf(), x)
approxGreaterThan'export: (num, x) -> Math..approxGreaterThan(num.valueOf(), x)
approxLessThan'export: (num, x) -> Math..approxLessThan(num.valueOf(), x)

pad'export: (num, integerSize, fractionalSize) ->
    num.valueOf()..format{
        integerSize: integerSize
        fractionalSize: fractionalSize
    }

format'export: (num, options) ->
    o: Object..absorb(Object..clone(options ifvoid {}), {
        integerSize: 1
        fractionalSize: 0
        forcesSign: false
        radix: 10
        integerGroupEnabled: false
        integerGroupSeparator: ","
        integerGroupSize: 3
        fractionalGroupEnabled: false
        fractionalGroupSeparator: " "
        fractionalGroupSize: 3
    })
    if o.radix ≠ 10
        o.fractionalSize: 0
    x: num.valueOf()
    if o.integerSize > 80 or o.fractionalSize > 20 or x ≥ 1e21 or x ≤ -1e21
    or o.integerGroupSize < 1 or o.fractionalGroupSize < 1
        fail("Number or argument out of range")
    s:
        if o.radix = 10
            t: Math..roundDecimal(x, o.fractionalSize).toString()
            ePos: t.indexOf("e")
            if ePos = -1
                t
            else
                if t.(ePos + 1) = "+"
                    fail("Number too large") # Redundant but needed to be robust
                else
                    # JavaScript shows any number < 0.000001 in exponential form, so we
                    # use `toFixed` to disable the exponential form.
                    # But `toFixed` can't be used for all cases, because
                    # `(12345678901.2).toFixed(6)` will give "12345678901.200001",
                    # which looks ugly.
                    x.toFixed(o.fractionalSize)
        else
            Math.round(x).toString(o.radix)
    isNegative: s.0 = "-"
    if s.0 = "+" or s.0 = "-"
        s: s..remove(0)
    do --
        pos: s.indexOf(".")
        rawIntegerSize: pos = -1 ? s.length | pos
        integerMissing: Math.max(o.integerSize - rawIntegerSize, 0)
        rawFractionalSize: pos = -1 ? 0 | s.length - 1 - pos
        fractionalMissing: o.fractionalSize - rawFractionalSize

        # For truncating. If `fractionalMissing` is negative then truncate, otherwise it
        # will remain unchanged.
        s: s.substr(0, s.length + fractionalMissing)
        if s.(s.length - 1) = "."
            s: s.substr(0, s.length - 1)

        if pos = -1 and o.fractionalSize > 0
            s: self + "."
        s: "0".repeat(integerMissing) + s + "0".repeat(Math.max(fractionalMissing, 0))
    if o.integerGroupEnabled or o.fractionalGroupEnabled then do --
        pos: s.indexOf(".")

        # All these inserts must be from bottom to top, otherwise it will be harder
        # to locate the position to insert to.
        if o.fractionalGroupEnabled
            fractionalStart: (pos = -1 ? s.length | pos) + 1 + o.fractionalGroupSize
            repeat{fractionalStart to s.length - 1 by o.fractionalGroupSize}
            ..reverse()
            .forEach(i -> s: s..insert(i, o.fractionalGroupSeparator))
        if o.integerGroupEnabled
            integerStart: (pos = -1 ? s.length | pos) - o.integerGroupSize
            repeat{integerStart to 1 by -o.integerGroupSize}
            .forEach(i -> s: s..insert(i, o.integerGroupSeparator))
    if o.forcesSign
        if isNegative
            s: "-" + s
        else
            s: "+" + s
    else
        if isNegative
            s: "-" + s
    s
