/*
 * baseout.cpp: handle all forms of output which ultimately come down
 * to representing a number in ordinary positional notation, with or
 * without a scientific-notation exponent, and with all kinds of
 * top-level formatting (e.g. as a decimal string or an IEEE bit
 * pattern).
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <string>
#include <map>

#include "spigot.h"
#include "error.h"
#include "funcs.h"
#include "cr.h"
#include "baseout.h"

/* ----------------------------------------------------------------------
 * Low-level utility stuff.
 */

char digitchar(int d, char a = 'a')
{
    return (d >= 10 ? a-10 : '0') + d;
}

/*
 * Small helper class to handle intervals of integers, with rigorous
 * attention paid to open/closed endpoints.
 */
struct Interval {
    bigint lo, hi;
    bool lo_open, hi_open;
    bool lo_inf, hi_inf;

    void init(bigint alo, bigint ahi, bool alo_open, bool ahi_open,
              bool alo_inf = false, bool ahi_inf = false) {
        lo = alo;
        hi = ahi;
        lo_open = alo_open;
        hi_open = ahi_open;
        lo_inf = alo_inf;
        hi_inf = ahi_inf;
    }

    Interval()
        : lo(0), hi(0), lo_open(true), hi_open(true),
          lo_inf(false), hi_inf(false) {}

    Interval(bigint alo, bigint ahi, bool alo_open, bool ahi_open)
        : lo(alo), hi(ahi), lo_open(alo_open), hi_open(ahi_open),
          lo_inf(false), hi_inf(false) {}

    Interval(const Interval &a)
        : lo(a.lo), hi(a.hi), lo_open(a.lo_open), hi_open(a.hi_open),
          lo_inf(a.lo_inf), hi_inf(a.hi_inf) {}

    const Interval &operator=(const Interval &a) {
        init(a.lo, a.hi, a.lo_open, a.hi_open, a.lo_inf, a.hi_inf);
        return *this;
    }

    Interval intersect(const Interval &b) const {
        Interval ret;
        int s;

        s = (lo_inf ?
             (b.lo_inf ? 0 : -1) :
             (b.lo_inf ? +1 : bigint_sign(lo - b.lo)));
        if (s > 0) {
            ret.lo = lo;
            ret.lo_open = lo_open;
            ret.lo_inf = lo_inf;
        } else if (s < 0) {
            ret.lo = b.lo;
            ret.lo_open = b.lo_open;
            ret.lo_inf = b.lo_inf;
        } else {
            ret.lo = b.lo;
            ret.lo_open = lo_open || b.lo_open;
            ret.lo_inf = b.lo_inf;
        }

        s = (hi_inf ?
             (b.hi_inf ? 0 : +1) :
             (b.hi_inf ? -1 : bigint_sign(hi - b.hi)));
        if (s < 0) {
            ret.hi = hi;
            ret.hi_open = hi_open;
            ret.hi_inf = hi_inf;
        } else if (s > 0) {
            ret.hi = b.hi;
            ret.hi_open = b.hi_open;
            ret.hi_inf = b.hi_inf;
        } else {
            ret.hi = b.hi;
            ret.hi_open = hi_open || b.hi_open;
            ret.hi_inf = b.hi_inf;
        }

        return ret;
    }

    bool empty() const {
        return !lo_inf && !hi_inf &&
            (lo > hi || (lo == hi && (lo_open || hi_open)));
    }

    void translate(bigint origin) {
        lo += origin;
        hi += origin;
    }

    void scale(bigint scale) {
        lo *= scale;
        hi *= scale;
    }

    void remove_lower_bound() {
        lo_inf = true;
    }
    bool has_lower_bound() const {
        return !lo_inf;
    }
};

static int floor_log(bigint i, int base, bool *exact)
{
    /*
     * Helper function for deciding on exponents. Returns the integer
     * part (literally, floor) part of the log of i to the base base,
     * which must be 2 or 10. Input must be positive.
     */

    /*
     * We start by finding a rational approximation to 1/log2(base).
     * Since we have spigot available to compute these for us, that's
     * how we do it!
     */
    bigint lognum, logdenom;
    if ((base & (base-1)) == 0) {
        // Special case: base is a power of 2, so its log is an
        // integer.
        lognum = 1;
        logdenom = 0;
        for (int b = base; b > 1; b >>= 1)
            ++logdenom;
    } else {
        // Memoise the approximate logarithm we get, so we can reuse
        // it if called on again to generate output in the same base.
        typedef std::map<int,std::pair<bigint,bigint> > our_map_t;
        static our_map_t log2s;
        our_map_t::iterator it = log2s.find(base);

        if (it != log2s.end()) {
            lognum = it->second.first;
            logdenom = it->second.second;
        } else {
            Spigot *sp = spigot_reciprocal(spigot_log2(spigot_integer(base)));
            ConvergentsGenerator convs(sp);
            while (1) {
                /*
                 * We need to err on the low side, which means taking
                 * only every other convergent. (They oscillate
                 * between erring high and low, starting with the
                 * integer part which is always low.)
                 */
                convs.get_convergent(&lognum, &logdenom);
                if (logdenom > 200)
                    break;
                convs.get_convergent(&lognum, &logdenom);
            }
            log2s[base] = std::pair<bigint,bigint>(lognum, logdenom);
        }
    }

    assert(i > 0);

    int ret = bigint_approxlog2(i) * lognum / logdenom;
    bigint power = bigint_power(base, ret);
    *exact = (i % power == 0);
    bigint residual = i / power;
    while (residual >= base) {
        if (residual % (unsigned)base != 0)
            *exact = false;
        residual /= base;
        ret++;
    }
    return ret;
}

static RoundingMode signedify(RoundingMode rmode, int sign)
{
    if (sign < 0) {
        return (rmode == ROUND_UP ? ROUND_TOWARD_ZERO :
                rmode == ROUND_DOWN ? ROUND_AWAY_FROM_ZERO :
                rmode == ROUND_TO_NEAREST_UP ?
                ROUND_TO_NEAREST_TOWARD_ZERO :
                rmode == ROUND_TO_NEAREST_DOWN ?
                ROUND_TO_NEAREST_AWAY_FROM_ZERO :
                rmode);
    } else {
        return (rmode == ROUND_UP ? ROUND_AWAY_FROM_ZERO :
                rmode == ROUND_DOWN ? ROUND_TOWARD_ZERO :
                rmode == ROUND_TO_NEAREST_UP ?
                ROUND_TO_NEAREST_AWAY_FROM_ZERO :
                rmode == ROUND_TO_NEAREST_DOWN ?
                ROUND_TO_NEAREST_TOWARD_ZERO :
                rmode);
    }
}

static bool is_directed(RoundingMode rmode)
{
    return (rmode == ROUND_UP ||
            rmode == ROUND_TOWARD_ZERO ||
            rmode == ROUND_DOWN ||
            rmode == ROUND_AWAY_FROM_ZERO);
}

/* ----------------------------------------------------------------------
 * Abstract base class for formatters.
 */

/*
 * 'Formatter' is an abstract base class for things which accept a
 * stream of data in the form (sign, exponent, digit, digit, ...) and
 * turn it into a string.
 *
 * Formatters provide information on the base they want to use (for
 * exponent and digit), and whether they have a digit limit. They
 * receive digits _after_ rounding, so they can concentrate entirely
 * on gluing them into strings.
 */
class Formatter {
    std::string text;
  protected:
    void write(char c) {
        text.push_back(c);
    }
    void write(std::string s) {
        text += s;
    }
  public:
    Formatter() : text("") {}
    virtual ~Formatter() {}
    std::string current_text() const {
        return text;
    }
    void consume_text(size_t nchars) {
        text.erase(0, nchars);
    }

    /*
     * Return the desired number bases for exponent and digits.
     *
     * Constraints: 2 <= ebase <= dbase.
     *
     * The semantics will be that the exponent will be returned as the
     * largest power of ebase less than or equal to the number. Hence,
     * setting ebase < dbase means that not every non-zero digit can
     * occur in the leading position.
     *
     * (So if you implement printf("%a") by setting ebase=2 and
     * dbase=16, that gives you output in which the leading digit is
     * always 1. Of course if you wanted the version with the exponent
     * always a multiple of 4 and all leading digits possible, you
     * could do that just as easily by using ebase=16 and quadrupling
     * the received exponent.)
     *
     * If you were to set ebase > dbase, that would have to mean that
     * more than one digit was required before the point in some
     * situations (e.g. ebase=10 and dbase=2 would have to represent
     * 975, say, as 1001.11 * 10^2), which would complicate the
     * formatting interface (you'd have to communicate where the point
     * went, _separately_ from what the exponent was!) and so I'm
     * comfortable with disallowing that until I hear of a reason why
     * it's needed.
     */
    virtual unsigned ebase() = 0;
    virtual unsigned dbase() = 0;

    /*
     * Indicate whether this formatter has a lower limit on the
     * exponent it can accept. Some will take any exponent; others
     * find it easier to cap the exponent below, so as not to have to
     * faff around with inventing lots of leading zeroes.
     */
    virtual bool has_min_exp() = 0;
    virtual int min_exp() = 0;

    /*
     * Called by the generator to provide the sign and exponent, then
     * the digits. sign_exp() is called once, then digit() repeatedly,
     * and done() once we've finished outputting digits (if we ever
     * do). The argument to done() indicates whether we've stopped
     * outputting digits because the representation in the target base
     * turned out to be exact (in which case we pass 'true') or just
     * because we reached the digit limit ('false').
     */
    virtual void sign_exp(int s, int e) = 0;
    virtual void digit(unsigned d) = 0;
    virtual void done(bool exact) = 0;

    /*
     * Called by the generator in place of sign_exp() and digit(), if
     * an exact zero needs to be formatted.
     *
     * In case it makes a difference, the formatter should respond to
     * this by preparing enough text to use as tentative output
     * representing a potential zero, and to the subsequent done() by
     * appending the rest of the text to make a full and complete
     * output (e.g. a trailing exponent).
     */
    virtual void exact_zero() = 0;

    /*
     * Indicate whether this formatter has a finite number of digits
     * remaining to output. Some can keep going for ever; others
     * impose a limit, at which rounding takes place.
     */
    virtual bool has_digit_limit() = 0;
    virtual unsigned digits_left() = 0;

    /*
     * Indicates whether this formatter has prematurely decided on its
     * entire output. This can happen in the case of IEEE overflow.
     */
    virtual bool complete() { return false; }

    /*
     * Tweaks which permit the formatter to scale up the first digit,
     * or to round at a partial digit position.
     */
    virtual bigint first_digit_scale() { return 1; }
    virtual bigint round_digit_scale() { return 1; }

    /*
     * Formatters constantly have to be copied, because in situations
     * where the input number is taking a while to decide which side
     * of a digit boundary it's on, we run multiple formatters in
     * parallel for the various possibilities.
     */
    virtual Formatter *clone() = 0;
};

/* ----------------------------------------------------------------------
 * The main core of base output.
 */

/*
 * BaseOutputGenerator is the place where the top-level work happens.
 * At one end, this retrieves data from an input spigot by being a
 * subclass of Generator; at the other end, it maintains a number of
 * currently active Formatters with partially constructed strings, and
 * outputs digits whenever they all agree on what comes next. In
 * between, it does sign and exponent finding, and rounding.
 */
class BaseOutputGenerator : public OutputGenerator {
    Formatter *mainfmt;
    struct CurrFmt {
        /*
         * This structure defines a currently active formatter, and
         * all the things BaseOutputGenerator needs to know to
         * remember how and when to pass it further digits.
         */
        Formatter *fmt;

        /*
         * The first digit has an unusual range of possibilities, so
         * remember if this is it or not. Also, the range of
         * possibilities depends on whether we're outputting the
         * formatter's minimum exponent (because that's when a leading
         * zero digit is permitted).
         */
        bool at_first_digit, at_min_exp;

        /* How to convert the spigot's current scale to output digits:
         * you compute (value-base)/(2*halfscale). */
        bigint base;
        bigint halfscale;

        /*
         * Record the running parity of the number so far, for RTE/RTO.
         *
         * In an even (digit) base, 'round to even/odd' can be
         * regarded as simply rounding to whichever answer has an even
         * or odd _last digit_. But if the base is odd, that doesn't
         * make sense - e.g. what if you're in base 7, and stuck
         * between outputting a digit 6 or rounding up to 0? _Both_
         * are even, so round-to-even has two choices that it still
         * can't decide between, and round-to-odd has none.
         *
         * The answer is to stop thinking about the last digit, and
         * start thinking about the whole number. Rounding to even/odd
         * should properly be seen as rounding so that the _entire
         * number output_ is an even or odd multiple of the last place
         * value. (In particular, if you're rounding to the nearest
         * _integer_, you want to break ties by picking the even or
         * odd _integer_ out of the options.)
         *
         * In an even base, of course, the two notions are the same.
         * But in an odd base, it means we have to track the parity of
         * the whole number so far, which handily is easy because the
         * parity of a number in an odd base is equal to the parity of
         * the sum of the digits, or the parity of the number of odd
         * digits, or other equivalent formulations including the
         * parity of the XOR of the digits.
         *
         * 'parity' does this tracking, as we step along the number.
         * Only its low bit is meaningful.
         */
        unsigned parity;

        /*
         * 'done' is true if this formatter has output its rounding
         * digit and hence finished. In that situation, 'base' always
         * points at the rounding boundary separating us from the
         * other formatter, and the other two booleans here indicate
         * which side of that boundary this formatter expects to be
         * on, and whether an exact tie counts as valid.
         */
        bool done;
        bool round_down;        // if true, we expect to be < base
        bool round_open;        // if false, = counts as the right side

        /*
         * Remember what exponent this formatter started off with, and
         * whether either end of its interval is an exponent boundary,
         * so that we can recognise the case later on when a rounding
         * decision is being made between two numbers of different
         * exponents.
         */
        int exponent;
        bool just_below_exponent_boundary, just_above_exponent_boundary;

        int digits_since_done;
    } currfmts[2], newfmts[2];
    int n_currfmts;
    unsigned ebase, dbase;
    bool has_min_exp;
    int min_exp;
    RoundingMode rmode;
    bool exponent_finding_phase;
    bool done;
    int crState;                 // for coroutine-structured progress()
    int sign, exponent;
    int scale;
    void dump_formatters(const char *prefix);
  private:
    int compute_exponent(int sign, int eadj, const bigint &i,
                         bool add_epsilon, bool maximum);
  public:
    BaseOutputGenerator(Coreable *acore, Formatter *fmt, RoundingMode armode);
    ~BaseOutputGenerator();
    void progress();
    bool get_definite_output(std::string &out);
    bool get_tentative_output(std::string &out, int *digits);
};

BaseOutputGenerator::BaseOutputGenerator(Coreable *acore, Formatter *fmt,
                                         RoundingMode armode)
    : OutputGenerator(acore),
      mainfmt(fmt),
      n_currfmts(0),
      rmode(armode),
      exponent_finding_phase(true),
      done(false),
      crState(-1)
{
    dprint("hello BaseOutputGenerator %p", acore);
}

BaseOutputGenerator::~BaseOutputGenerator()
{
    delete mainfmt;
    while (n_currfmts-- > 0)
        delete currfmts[n_currfmts].fmt;
}

void BaseOutputGenerator::dump_formatters(const char *prefix)
{
    if (!debugging)
        return;

    for (int i = 0; i < n_currfmts; ++i) {
        if (currfmts[i].done) {
            dprint("%s: formatter %d: done base=%b rdown=%B ropen=%B \"%s\"",
                   prefix, i,
                   &currfmts[i].base,
                   currfmts[i].round_down,
                   currfmts[i].round_open,
                   currfmts[i].fmt->current_text().c_str());
        } else {
            dprint("%s: formatter %d: base=%b scale=2*%b parity=%d"
                   " \"%s\" (%d digits)",
                   prefix, i,
                   &currfmts[i].base,
                   &currfmts[i].halfscale,
                   (int)(currfmts[i].parity & 1),
                   currfmts[i].fmt->current_text().c_str(),
                   (!currfmts[i].fmt->has_digit_limit() ? 9999 :
                    currfmts[i].fmt->digits_left()));
        }
    }
}

int BaseOutputGenerator::compute_exponent(int sign, int eadj, const bigint &i,
                                          bool add_epsilon, bool maximum)
{
    assert(i >= 0);
    bool exact;
    int e = floor_log(i, ebase, &exact);

    if (exact) {
        /*
         * If the number is an _exact_ power of ebase, then there is
         * only one possible exponent for it, irrespective of rounding.
         */
        if (!add_epsilon)
            return e;

        /*
         * If the number is epsilon less than an exact power of ebase,
         * then we should consider its exponent to be one lower.
         */
        if (maximum)
            e--;
    }

    bool special_case = false;
    RoundingMode real_rmode = signedify(rmode, sign);
    if (ebase == 2 && is_directed(real_rmode)) {
        Formatter *fmt = mainfmt->clone();
        fmt->sign_exp(sign, eadj + e);
        special_case = (fmt->has_digit_limit() && fmt->digits_left() == 1);
        delete fmt;
    }
    if (special_case) {
        return real_rmode == ROUND_TOWARD_ZERO ? e : e+1;
    }

    if (maximum) {
        bigint threshold = bigint_power(ebase, e+1);
        if (dbase > 2) {
            threshold = fdiv(threshold * (dbase-1), dbase);
        } else {
            threshold = fdiv(threshold * 3, 4);
        }
        if (i >= threshold) {
            e++;
        }
    }

    return e;
}

void BaseOutputGenerator::progress() {
    bigint lo, hi;

    crBegin;

    ebase = mainfmt->ebase();
    dbase = mainfmt->dbase();
    has_min_exp = mainfmt->has_min_exp();
    min_exp = mainfmt->min_exp();
    assert(ebase <= dbase);

    dprint("ebase=%d dbase=%d", (int)ebase, (int)dbase);
    if (has_min_exp)
        dprint("min_exp=%d", (int)min_exp);
    else
        dprint("no min_exp");

    /*
     * Start by determining the sign and exponent, which we do by
     * iterating the input spigot until the two ends of its interval
     * have the same sign and differ by at most a factor of ebase.
     *
     * While we do this, we arrange for a formatter to be active and
     * contain an exact representation of zero, so that that can be
     * used as tentative output if the exponent search drags on.
     */
    n_currfmts = 1;
    currfmts[0].fmt = mainfmt->clone();
    currfmts[0].fmt->exact_zero();
    currfmts[0].fmt->done(true);

    exponent = 0;
    while (1) {
        bool lo_open, hi_open;
        iterate_to_bounds(&lo, &hi, &lo_open, &hi_open, 0, NULL, true);

        dprint("exponent-finding: got (%b,%b)", &lo, &hi);

        int e1, e2;

        if (lo > 0 &&
            (e1 = compute_exponent(+1, exponent, lo, lo_open, false),
             e2 = compute_exponent(+1, exponent, hi, hi_open, true),
             e2 - e1 <= 1)) {
            /*
             * Positive number.
             */
            sign = +1;
            scale = e2;
            dprint("positive, scale=%d", (int)scale);
            break;
        } else if (hi < 0 &&
                   (e1 = compute_exponent(-1, exponent, -hi, hi_open, false),
                    e2 = compute_exponent(-1, exponent, -lo, lo_open, true),
                    e2 - e1 <= 1)) {
            /*
             * Negative number.
             */
            sign = -1;
            scale = e2;
            dprint("negative, scale=%d", (int)scale);
            break;
        } else if (hi == 0 && lo == 0) {
            /*
             * The number is exactly zero, so the temporary formatter
             * we set up for that possibility has in fact got the
             * right answer already, so just leave it there and finish.
             */
            dprint("exact zero");
            exponent_finding_phase = false;
            done = true;
            crReturnV;
            assert(!"Called again after completing an exact zero");
        } else if (hi - lo <= 2) {
            /*
             * If the interval has narrowed as far as we can
             * reasonably expect it to, but none of the above cases
             * has yielded a useful result, then the exponent is
             * probably too small (or else the number is
             * _non-obviously_ zero). Premultiply a matrix that zooms
             * in, remember that we've done so, and keep trying.
             */
            if (has_min_exp && exponent <= min_exp) {
                /*
                 * An exception is if we're already at the formatter's
                 * lower exponent limit, in which case we must stop
                 * zooming in and just start generating zero digits
                 * anyway.
                 *
                 * Well, almost. Actually we still have to go round
                 * this loop until the _sign_ is available, but after
                 * that we can start generating digits.
                 */
                if (lo > 0 || (lo == 0 && lo_open)) {
                    dprint("min exp limit reached, positive");
                    sign = +1;
                    scale = 0;
                    break;
                } else if (hi < 0 || (hi == 0 && hi_open)) {
                    dprint("min exp limit reached, negative");
                    sign = -1;
                    scale = 0;
                    break;
                }
            }
            bigint matrix[4];
            matrix[0] = ebase;
            matrix[1] = matrix[2] = 0;
            matrix[3] = 1;
            dprint("premultiplying exponent-finding zoom %4m", matrix);
            core->premultiply(matrix);
            exponent--;
            dprint("zoomed in, decremented exponent to %d", exponent);
        }

        /*
         * Return from the coroutine every time we go round this loop,
         * so that we're conveniently interruptible.
         */
        crReturnV;
    }

    dprint("exponent found: exponent=%d scale=%d sign=%d",
           exponent, scale, sign);
    if (has_min_exp && exponent + scale < min_exp) {
        scale = min_exp - exponent;
        dprint("adjusted for min exp %d: exponent=%d scale=%d sign=%d",
               min_exp, exponent, scale, sign);
    }

    /*
     * Do sign-dependent processing, now we know the sign: translate
     * signed roundings (towards +inf or -inf) into sign-independent
     * ones (towards or away from zero), and premultiply a negation
     * matrix if the number is negative.
     */
    if (sign < 0) {
        bigint matrix[4];
        matrix[0] = -1;
        matrix[1] = matrix[2] = 0;
        matrix[3] = 1;
        dprint("premultiplying negation %4m", matrix);
        core->premultiply(matrix);
    }
    rmode = signedify(rmode, sign);

    /*
     * Discard our temporary zero formatter.
     */
    delete currfmts[0].fmt;
    exponent_finding_phase = false;

    /*
     * Find the overall exponent, by combining the log of the
     * integer-part interval we got back with the number of times
     * we've already zoomed in.
     */
    exponent += (int)scale;
    dprint("final exponent=%d", exponent);

    /*
     * If the integer part was large, start by zooming back out. Also
     * zoom if we need to scale up the first digit.
     */
    {
        bigint matrix[4];
        matrix[0] = mainfmt->first_digit_scale();
        matrix[1] = matrix[2] = 0;
        matrix[3] = bigint_power(ebase, scale);
        if (matrix[0] != matrix[3]) {
            dprint("premultiplying initial zoom %4m", matrix);
            core->premultiply(matrix);
        }
    }

    /*
     * We've now zoomed the spigot so that ebase^exponent in the scale
     * of the output number is represented by 1 here. But we're going
     * to worry about the exponent one below that, so we must zoom in
     * by ebase again; also we zoom in by an extra factor of 2 so that
     * we can get intervals at half-digit granularity.
     */
    {
        bigint matrix[4];
        matrix[0] = ebase*2;
        matrix[1] = matrix[2] = 0;
        matrix[3] = 1;
        dprint("premultiplying pre-main-loop zoom %4m", matrix);
        core->premultiply(matrix);
    }

    /*
     * Now we know the number's sign, and we've got its exponent to
     * within a range of two possibilities. Begin our main loop by
     * initialising one formatter to each of the exponent choices.
     *
     * Our formatters are in sorted order always, from smallest to
     * largest.
     */
    n_currfmts = 0;

    if (!has_min_exp || exponent > min_exp) { // omit this exponent if too low
        currfmts[n_currfmts].fmt = mainfmt->clone();
        currfmts[n_currfmts].done = false;
        currfmts[n_currfmts].fmt->sign_exp(sign, exponent - 1);
        currfmts[n_currfmts].base = 0;
        currfmts[n_currfmts].halfscale = 1;
        currfmts[n_currfmts].parity = 0;
        currfmts[n_currfmts].at_first_digit = true;
        currfmts[n_currfmts].at_min_exp = (has_min_exp &&
                                           exponent-1 == min_exp);
        currfmts[n_currfmts].exponent = exponent - 1;
        currfmts[n_currfmts].just_below_exponent_boundary = true;
        currfmts[n_currfmts].just_above_exponent_boundary = false;
        currfmts[n_currfmts].digits_since_done = 0;
        n_currfmts++;
    }

    currfmts[n_currfmts].fmt = mainfmt->clone();
    currfmts[n_currfmts].done = false;
    currfmts[n_currfmts].fmt->sign_exp(sign, exponent);
    currfmts[n_currfmts].base = 0;
    currfmts[n_currfmts].halfscale = ebase;
    currfmts[n_currfmts].parity = 0;
    currfmts[n_currfmts].at_first_digit = true;
    currfmts[n_currfmts].at_min_exp = (has_min_exp &&
                                       exponent == min_exp);
    currfmts[n_currfmts].exponent = exponent;
    currfmts[n_currfmts].just_below_exponent_boundary = false;
    currfmts[n_currfmts].just_above_exponent_boundary = (n_currfmts > 0);
    currfmts[n_currfmts].digits_since_done = 0;
    n_currfmts++;

    while (1) {
        dump_formatters("digit loop");

        /*
         * Fetch enough data to narrow down to the next digit
         * position, no matter which formatter's scale we're working
         * at.
         */
        bool lo_open, hi_open;
        bool force_refine;
        force_refine = false;

        {
            assert(n_currfmts > 0);
            bigint min_halfscale = currfmts[0].halfscale;
            if (n_currfmts > 1 && min_halfscale > currfmts[1].halfscale)
                min_halfscale = currfmts[1].halfscale;

            while (1) {
                iterate_to_bounds(&lo, &hi, &lo_open, &hi_open, 0, NULL,
                                  force_refine);
                /*
                 * We make the termination condition of this loop as
                 * carefully loose as possible, to get the maximum
                 * output in cases where limited data is available
                 * (e.g. FileReaders).
                 *
                 * We need our interval to overlap at most two
                 * possible digits' catchment areas. For this, it has
                 * to be contained in either a closed interval between
                 * two exact digit boundaries (which are at least
                 * 2*min_halfscale apart), or a closed interval
                 * between two points exactly midway between digit
                 * boundaries. That will get us what we want
                 * regardless of the rounding mode.
                 *
                 * Also, we don't want it to be the full width of one
                 * of those intervals _and_ be closed at both ends.
                 * (Because that raises the possibility that we might
                 * manage to overlap three digit catchment intervals,
                 * in the case where each endpoint of the width-2
                 * closed interval would round-to-even outwards.)
                 */
                bigint tmp_lo = fdiv(lo, min_halfscale);
                bool tmp_lo_open = lo_open || (tmp_lo * min_halfscale != lo);
                bigint tmp_hi = fdiv(hi + min_halfscale-1, min_halfscale);
                bool tmp_hi_open = hi_open || (tmp_hi * min_halfscale != hi);

                int s = bigint_sign(tmp_hi - tmp_lo - 2);
                if (s < 0 || (s == 0 && (tmp_lo_open || tmp_hi_open)))
                    break;
                force_refine = true;
            }
        }

        dprint("digit loop: got %s%b,%b%s",
               lo_open?"(":"[", &lo, &hi, hi_open?")":"]");

        /*
         * Iterate over all active formatters, and see what each one
         * makes of this new piece of data.
         */
        int n_newfmts;
        n_newfmts = 0;
        for (int i = 0; i < n_currfmts; ++i) {
            CurrFmt &cfmt = currfmts[i];

            if (cfmt.done) {
                /*
                 * This formatter is a static entry in the list
                 * representing a successfully rounded output. Check
                 * whether the number has been shown to be on the
                 * wrong side of the rounding boundary; if so, discard
                 * this formatter, and otherwise, just propagate it
                 * into the newfmts list without change.
                 */
                int sign;
                bool open;

                bigint base;
                if (i > 0 && cfmt.just_above_exponent_boundary) {
                    base = currfmts[i-1].base;
                } else {
                    base = cfmt.base;
                }

                if (cfmt.round_down) {
                    sign = bigint_sign(lo - base);
                    open = lo_open;
                } else {
                    sign = bigint_sign(base - hi);
                    open = hi_open;
                }
                dprint("check done formatter %d, sign=%d", i, sign);
                if (sign < 0 || (sign == 0 && !cfmt.round_open && !open)) {
                    cfmt.digits_since_done++;
                    newfmts[n_newfmts++] = cfmt;
                    cfmt.fmt = NULL;       // prevent deletion later
                }
                continue;
            }

            bool rounding = (cfmt.fmt->has_digit_limit() &&
                             cfmt.fmt->digits_left() == 1);

            bigint this_scale = cfmt.halfscale;
            bigint digit_scale = 1;
            if (rounding) {
                digit_scale = cfmt.fmt->round_digit_scale();
                this_scale *= digit_scale;
                dprint("rounding this digit with scale %b", &digit_scale);
            } else {
                dprint("not rounding this digit");
            }

            bigint this_lo = fdiv(lo - cfmt.base, this_scale);
            bool this_lo_open = lo_open || (this_lo * this_scale != lo - cfmt.base);
            bigint this_hi = fdiv(hi - cfmt.base + this_scale-1,
                                  this_scale);
            bool this_hi_open = hi_open || (this_hi * this_scale != hi - cfmt.base);

            /*
             * If there's any possibility of this number being rounded
             * up to slightly more than its current value at a later
             * digit position, then we must presume that it could
             * round up to the high end of our current interval, i.e.
             * we must treat the interval as closed at the top end for
             * the purposes of this formatter.
             *
             * Rounding up is a possibility if we're not in
             * round-toward-zero mode, and have a nonzero digit limit
             * which we haven't yet reached.
             */
            if (rmode != ROUND_TOWARD_ZERO &&
                cfmt.fmt->has_digit_limit() &&
                cfmt.fmt->digits_left() > 1)
                this_hi_open = false;

            Interval curr_int(this_lo, this_hi, this_lo_open, this_hi_open);
            dprint("formatter %d: scaled interval %s%b,%b%s", i,
                   this_lo_open?"(":"[", &this_lo,
                   &this_hi, this_hi_open?")":"]");

            /*
             * If the interval we're now sitting on is _exactly_ zero,
             * then we've output all the digits of a terminating base
             * representation, and we should notify the formatter.
             */
            if (this_lo == 0 && this_hi == 0) {
                dprint("formatter %d: marking as exact", i);
                cfmt.done = true;
                cfmt.digits_since_done = 0;
                cfmt.fmt->done(true);
                newfmts[n_newfmts++] = cfmt;
                cfmt.fmt = NULL;       // prevent deletion later
                continue;
            }

            /*
             * Enumerate the possible next digits that might go to
             * this formatter, based on the number's interval.
             */
            bigint dmin = this_lo / 2U, dmax = (this_hi + 1) / 2U;
            bool potentially_still_above_exponent_boundary = false;
            bool potentially_still_below_exponent_boundary = false;
            if (cfmt.at_first_digit) {
                bigint first_digit_scale =
                    cfmt.fmt->first_digit_scale() / digit_scale;
                bigint first_digit_min = (cfmt.at_min_exp ? (bigint)0 :
                                          first_digit_scale);
                bigint first_digit_max = ebase * first_digit_scale;
                if (dmax >= first_digit_max)
                    dmax = first_digit_max - 1;
                if (dmin < first_digit_min)
                    dmin = first_digit_min;
                if (cfmt.just_above_exponent_boundary &&
                    !cfmt.at_min_exp && dmin == first_digit_scale)
                    potentially_still_above_exponent_boundary = true;
                if (cfmt.just_below_exponent_boundary &&
                    dmax == first_digit_max - 1)
                    potentially_still_below_exponent_boundary = true;
            } else {
                bigint scaled_dbase = (bigint)dbase / digit_scale;
                if (dmax >= scaled_dbase)
                    dmax = scaled_dbase - 1;
                if (dmin < 0)
                    dmin = 0;
                if (cfmt.just_above_exponent_boundary &&
                    !cfmt.at_min_exp && dmin == 0)
                    potentially_still_above_exponent_boundary = true;
                if (cfmt.just_below_exponent_boundary &&
                    dmax == scaled_dbase - 1)
                    potentially_still_below_exponent_boundary = true;
            }

            dprint("formatter %d: digit range [%b,%b]", i, &dmin, &dmax);

            for (bigint d = dmin; d <= dmax; ++d) {
                assert(d >= 0);
                assert(d < (bigint)dbase);
                /*
                 * Determine the catchment interval for this digit.
                 * Usually this is just [d,d+1), unless we're at the
                 * rounding point right now, in which case the shape
                 * of the catchment interval varies a lot depending on
                 * rounding mode.
                 */
                Interval catchment;
                if (!rounding || rmode == ROUND_TOWARD_ZERO) {
                    catchment.init(d*2, d*2+2, false, true);
                } else if (rmode == ROUND_AWAY_FROM_ZERO) {
                    catchment.init(d*2-2, d*2, true, false);
                } else {
                    bool cmin_open, cmax_open;
                    switch (rmode) {
                      case ROUND_TO_NEAREST_EVEN:
                        /*
                         * If the number is the last digit of an even
                         * multiple of this place value, its catchment
                         * interval is closed at both ends, otherwise
                         * it's open at both ends.
                         */
                        cmin_open = cmax_open =
                            (((unsigned)d ^ cfmt.parity) & 1) != 0;
                        break;
                      case ROUND_TO_NEAREST_ODD:
                        /*
                         * Exact reverse of ROUND_TO_NEAREST_EVEN, of
                         * course.
                         */
                        cmin_open = cmax_open =
                            (((unsigned)d ^ cfmt.parity) & 1) == 0;
                        break;
                      case ROUND_TO_NEAREST_TOWARD_ZERO:
                        cmin_open = true;
                        cmax_open = false;
                        break;
                      default /*case ROUND_TO_NEAREST_AWAY_FROM_ZERO */ :
                        cmin_open = false;
                        cmax_open = true;
                        break;
                    }
                    catchment.init(d*2-1, d*2+1, cmin_open, cmax_open);
                }

                /*
                 * If this formatter is just above an exponent
                 * boundary, and there's one recorded just below it
                 * which is just below the same boundary, then we
                 * discard the lower bound on this catchment area,
                 * because only the next formatter down can correctly
                 * compute the rounding boundary between exponents.
                 */
                if (potentially_still_above_exponent_boundary && d == dmin &&
                    n_newfmts > 0 &&
                    newfmts[n_newfmts-1].just_below_exponent_boundary)
                    catchment.remove_lower_bound();

                if (rounding) {
                    if (catchment.has_lower_bound()) {
                        dprint("catchment interval for digit %b: %s%b,%b%s", &d,
                               catchment.lo_open?"(":"[",
                               &catchment.lo,
                               &catchment.hi,
                               catchment.hi_open?")":"]");
                    } else {
                        dprint("catchment interval for digit %b: (-inf,%b%s",&d,
                               &catchment.hi,
                               catchment.hi_open?")":"]");
                    }
                }

                /*
                 * Intersect, and if the resulting interval is
                 * non-empty, create a new formatter for the next
                 * digit which has the right parameters.
                 */
                Interval out = curr_int.intersect(catchment);
                if (!out.empty()) {
                    /*
                     * Special case: there's one situation in which we
                     * might find ourselves attempting to produce a
                     * third formatter, which is if we've just crossed
                     * an exponent boundary and the lower-exponent
                     * formatter had two possibilities already.
                     *
                     * In that situation, we discard the current
                     * option: it's only included due to unwillingness
                     * to trust the lower bound of a formatter just
                     * above an exponent boundary, and the fact that
                     * the next formatter down is still considering a
                     * digit lower than 9 (or more generally dmax) is
                     * enough to show that we can't really be in this
                     * exponent's catchment area.
                     */
                    if (n_newfmts == 2 &&
                        potentially_still_above_exponent_boundary &&
                        d == dmin &&
                        newfmts[n_newfmts-1].exponent != cfmt.exponent) {
                        dprint("formatter %d: would output digit %d, but "
                               "deferring to lower exponent", i, (int)d);
                        continue;
                    }

                    dprint("formatter %d: output digit %d", i, (int)d);

                    assert(n_newfmts < 2);

                    CurrFmt &newfmt = newfmts[n_newfmts];
                    n_newfmts++;

                    newfmt.fmt = cfmt.fmt->clone();
                    newfmt.fmt->digit(d * digit_scale);
                    newfmt.at_first_digit = false;
                    newfmt.exponent = cfmt.exponent;
                    newfmt.just_above_exponent_boundary =
                        potentially_still_above_exponent_boundary && d == dmin;
                    newfmt.just_below_exponent_boundary =
                        potentially_still_below_exponent_boundary && d == dmax;
                    newfmt.at_min_exp = cfmt.at_min_exp;

                    if (rounding) {
                        /*
                         * This formatter is now 'done', meaning that
                         * we've sent it all the digits we're going
                         * to. However, that's conditional on the
                         * number turning out to be in the right
                         * interval for this formatter after all - in
                         * some cases we can have two formatters in
                         * the done state, representing what will be
                         * output if the number ends up rounded down
                         * and up respectively, and then we have to
                         * keep processing until we find out which one
                         * is out of range, at which point we discard
                         * it and return just the other one.
                         */
                        newfmt.done = true;
                        newfmt.digits_since_done = 0;
                        newfmt.fmt->done(false);
                        if (n_newfmts == 1) {
                            newfmt.base = catchment.hi * this_scale + cfmt.base;
                            newfmt.round_down = true;
                            newfmt.round_open = catchment.hi_open;
                        } else {
                            newfmt.base = catchment.lo * this_scale + cfmt.base;
                            newfmt.round_down = false;
                            newfmt.round_open = catchment.lo_open;
                        }
                        newfmt.halfscale = cfmt.halfscale;
                    } else {
                        newfmt.done = false;
                        newfmt.base = cfmt.base + d*2*cfmt.halfscale;
                        newfmt.halfscale = cfmt.halfscale;
                        /* Fold the just-generated digit in to 'parity',
                         * if we're in an odd base; keep parity set to
                         * even, in an even base. Bit-twiddling to do
                         * this without any serious arithmetic. */
                        newfmt.parity = cfmt.parity ^ ((unsigned)d & dbase);
                    }
                }

                /*
                 * Loop on to the next possible digit.
                 */
            }
        }

        /*
         * Replace the old set of live formatters with the new set.
         */
        while (n_currfmts > 0) {
            --n_currfmts;
            if (currfmts[n_currfmts].fmt)
                delete currfmts[n_currfmts].fmt;
        }
        while (n_currfmts < n_newfmts) {
            currfmts[n_currfmts] = newfmts[n_currfmts];
            n_currfmts++;
        }

        assert(n_currfmts > 0);

        /*
         * End condition: if all formatters are done and have the same
         * string in them, we really have finished. (Usually this
         * occurs because there's only one formatter left, but in the
         * special case of IEEE overflow we can find we have two
         * formatters marked as done and agreeing on all their text
         * despite not having even figured out which of their
         * exponents is live yet.)
         */
        done = true;
        for (int i = 0; i < n_currfmts; ++i) {
            if (!currfmts[i].done && !currfmts[i].fmt->complete()) {
                done = false;
                break;
            }
        }
        if (done) {
            for (int i = 1; i < n_currfmts; ++i) {
                if (currfmts[0].fmt->current_text() !=
                    currfmts[i].fmt->current_text()) {
                    done = false;
                    break;
                }
            }
        }

        if (done) {
            crReturnV;
            assert(!"Called again after finishing output");
        }

        /*
         * Premultiply in a translation and scaling matrix, and scale
         * up all the formatters' intervals and bases.
         */
        {
            bigint newbase = currfmts[0].base;

            for (int i = 0; i < n_currfmts; ++i) {
                CurrFmt &cfmt = currfmts[i];
                cfmt.base = (cfmt.base - newbase) * dbase;
            }

            bigint matrix[4];
            matrix[0] = dbase;
            matrix[1] = -newbase * dbase;
            matrix[2] = 0;
            matrix[3] = 1;
            dprint("premultiplying post-digit zoom %4m", matrix);
            core->premultiply(matrix);
        }

        crReturnV;
    }

    crEnd;
}

bool BaseOutputGenerator::get_definite_output(std::string &out)
{
    if (done)
        return false;

    progress();
    assert(n_currfmts > 0);

    dump_formatters("output check");

    if (exponent_finding_phase) {
        /*
         * Special case: during exponent-finding, we only have one
         * CurrFmt active and yet we never generate definite output.
         */
        out = "";
        dprint("no output available");
        return true;
    } else if (n_currfmts == 1) {
        /*
         * If there's only one formatter live, then everything it's
         * produced is the only possible option and hence definite
         * output.
         */
        out = currfmts[0].fmt->current_text();
        dprint("unilateral \"%s\"", out.c_str());
        currfmts[0].fmt->consume_text(out.size());
        return true;
    } else {
        /*
         * With two formatters, we can only output what they agree on.
         */
        assert(n_currfmts == 2);
        std::string out0 = currfmts[0].fmt->current_text();
        std::string out1 = currfmts[1].fmt->current_text();
        size_t len = 0;
        while (len < out0.size() && len < out1.size() && out0[len] == out1[len])
            ++len;
        out = out0.substr(0, len);
        dprint("bilateral \"%s\"", out.c_str());
        currfmts[0].fmt->consume_text(len);
        currfmts[1].fmt->consume_text(len);
        return true;
    }
}

bool BaseOutputGenerator::get_tentative_output(std::string &out, int *digits)
{
    if (done)
        return false;

    if (exponent_finding_phase) {
        /*
         * Special case: during exponent-finding, we have exactly one
         * CurrFmt active and its output is all tentative.
         */
        assert(n_currfmts == 1);
        out = currfmts[0].fmt->current_text();
        char buf[256];
        sprintf(buf, " (%u^%d)", ebase, exponent);
        *digits = -exponent;
        out += buf;
        return true;
    } else if (n_currfmts == 2) {
        /*
         * Multiple live formatters are precisely the condition under
         * which we generate tentative output.
         *
         * If we haven't rounded yet, then the upper one of the two
         * formatters must contain what the answer might turn out to
         * exactly be; if we have, then we pick whichever formatter
         * has its rounding boundary closed.
         */
        int which, zeroes = 0;
        for (which = 0; which < 2; ++which)
            if (currfmts[which].done && !currfmts[which].round_open) {
                zeroes = currfmts[which].digits_since_done;
                break;                 // found a closed done formatter
            }
        if (which == 2)
            which = 1;                 // otherwise just go with #1
        out = currfmts[which].fmt->current_text();

        size_t last_nonzero = out.size();
        /*
         * Trim trailing zeroes from the upper formatter, and count
         * them, to use as our accuracy indicator.
         */
        while (last_nonzero > 0 && out[last_nonzero-1] == '0')
            last_nonzero--;
        zeroes += out.size() - last_nonzero;
        /*
         * Also trim a decimal point, if that's now the last thing in
         * the string, because it's ugly to print it unnecessarily.
         */
        if (last_nonzero > 0 && out[last_nonzero-1] == '.')
            last_nonzero--;
        out.resize(last_nonzero);
        char buf[256];
        sprintf(buf, " (%u^-%d)", dbase, zeroes);
        *digits = zeroes;
        out += buf;

        return true;
    } else {
        return false;
    }
}

/* ----------------------------------------------------------------------
 * Formatter for spigot's default output mode: just plain positional
 * notation, with a point if necessary but no exponent.
 */

class BaseFormatter : public Formatter {
    unsigned base;
    char a;                            // either 'a' or 'A'
    bool started, written_point;
    int our_min_exp;
    unsigned int_digits;
    unsigned min_int_digits;
    bool has_dlimit;
    unsigned digits;
  public:
    BaseFormatter(int abase, char aa, bool ahas_dlimit,
                  unsigned adigits, unsigned amin_int_digits) : Formatter() {
        base = abase;
        a = aa;
        started = written_point = false;
        int_digits = 0;
        has_dlimit = ahas_dlimit;
        digits = adigits;
        min_int_digits = amin_int_digits;
        if (min_int_digits < 1)
            min_int_digits = 1;

        /*
         * Minimum exponent: if we've been asked for a minimum number
         * of integer digits, the easiest way to achieve that is by
         * increasing the minimum exponent. Also, if we're rounding to
         * a position above the decimal point, that too is most easily
         * achieved by increasing the min exp.
         */
        our_min_exp = 0;
        if (our_min_exp < (int)min_int_digits-1)
            our_min_exp = (int)min_int_digits-1;
        if (our_min_exp < -(int)digits)
            our_min_exp = -(int)digits;
    }
    virtual BaseFormatter *clone() { return new BaseFormatter(*this); }

    virtual unsigned ebase() { return base; }
    virtual unsigned dbase() { return base; }

    virtual bool has_min_exp() { return true; }
    virtual int min_exp() { return our_min_exp; }

    virtual void sign_exp(int s, int e) {
        if (s < 0)
            write('-');

        int_digits = e+1;
        digits += int_digits;
    }
    virtual void digit(unsigned d) {
        // Skip this digit if it's a leading zero that we don't want
        if (started || int_digits <= min_int_digits || d != 0) {
            started = true;
            if (!written_point && int_digits == 0) {
                write('.');
                written_point = true;
            }
            write(digitchar(d, a));
        }
        if (int_digits > 0)
            --int_digits;
        --digits;
    }
    virtual void done(bool) {
        while (int_digits > 0)
            digit(0);
    }

    virtual void exact_zero() {
        sign_exp(0, our_min_exp);
        digit(0);
    }

    virtual bool has_digit_limit() { return has_dlimit; }
    virtual unsigned digits_left() { return digits; }
};

OutputGenerator *base_format(Spigot *spig, int base, int uppercase,
                             bool has_digitlimit, int digitlimit,
                             RoundingMode rmode, int minintdigits)
{
    return new BaseOutputGenerator
        (spig, new BaseFormatter(base, uppercase?'A':'a',
                                 has_digitlimit, digitlimit,
                                 minintdigits), rmode);
}

/* ----------------------------------------------------------------------
 * Formatter for hex bit patterns of IEEE 754-style floats, with
 * optional extra exponent digits.
 */

class IEEEFormatter : public Formatter {
    int expscale, signexpdigits;
    int mantdigits_left;
    unsigned expbias;
    int last_expdigit;
    bool seen_first_digit;
    bool has_dlimit;
    unsigned digits;
    unsigned roundscale;
    bool overflow;
  public:
    IEEEFormatter(int abits, bool ahas_dlimit, int adigits,
                  bool parity_rounding) : Formatter() {
        int expbits;

        expbits = (abits == 16 ? 5 :
                   abits == 32 ? 8 :
                   abits == 64 ? 11 :
                   abits == 128 ? 15 :
                   -1);
        expbias = (1 << (expbits-1)) - 1;

        if (ahas_dlimit) {
            /*
             * Enforce that negative digit limits don't get too
             * excessive. In most rounding modes, we can cope with up
             * to the number of mantissa bits (i.e. removing all but
             * the implicit leading 1), so -S -d-23, or -D -d-52. But
             * in parity-based rounding modes (i.e. tie-breaking to
             * even or odd), we decrease that by one, because at that
             * extreme _all_ numbers count as even and so we can't
             * round sensibly.
             */
            int most_neg_dlimit = -(abits - expbits - 1);
            if (parity_rounding)
                most_neg_dlimit++;
            if (adigits < most_neg_dlimit)
                throw spigot_error("minimum -d value in this mode is %d",
                                   most_neg_dlimit);
        }

        signexpdigits = (expbits + 1 + 3) / 4;
        expscale = 1 << (signexpdigits*4 - expbits - 1);
        mantdigits_left = (abits / 4) - signexpdigits;
        seen_first_digit = false;

        has_dlimit = ahas_dlimit;
        if (has_dlimit) {
            digits = (bigint)mantdigits_left + fdiv((bigint)adigits + 3, 4);
            roundscale = 1 << (3U & -adigits);
        } else {
            digits = 0;
            roundscale = 1;
        }

        overflow = false;
    }
    virtual IEEEFormatter *clone() { return new IEEEFormatter(*this); }

    virtual unsigned ebase() { return 2; }
    virtual unsigned dbase() { return 16; }

    virtual bool has_min_exp() { return true; }
    virtual int min_exp() { return -(expbias - 1); }

    virtual void sign_exp(int s, int e) {
        assert(e > -(int)expbias);
        unsigned biasexp = e + expbias;
        assert(biasexp > 0);
        unsigned signexp = biasexp * expscale;
        if (signexp >= (1U << (4*signexpdigits - 1)) - expscale) {
            /*
             * Overflow case.
             */
            signexp = (1 << (4*signexpdigits-1)) - expscale;
            if (s < 0)
                signexp |= 1 << (4*signexpdigits-1);
            for (int i = signexpdigits - 1; i >= 0; i--) {
                write(digitchar((signexp >> (4*i)) & 0xF));
            }
            for (int i = mantdigits_left; i-- > 0 ;) {
                write('0');
            }

            overflow = true;
            return;
        }
        if (s < 0)
            signexp |= 1 << (4*signexpdigits - 1);

        /*
         * We have to decide whether to print the final exponent
         * digit, or defer it. It must be deferred if any bits of
         * mantissa live in the same nibble, and also if there's a
         * possibility of denormalisation. Otherwise we can write it
         * out now.
         */
        bool print_last_expdigit_now = (biasexp > 1 && expscale == 1);
        int last_expdigit_to_print = print_last_expdigit_now ? 0 : 1;
        for (int i = signexpdigits - 1; i >= last_expdigit_to_print; i--) {
            write(digitchar((signexp >> (4*i)) & 0xF));
        }
        if (print_last_expdigit_now) {
            last_expdigit = -1;      // means we've already printed it
        } else {
            last_expdigit = signexp & 0xF;
        }
        // The mantissa digit that ends up combined with the exponent
        // must still be counted in our digit counts.
        mantdigits_left++;
        digits++;
    }
    virtual void digit(unsigned d) {
        if (overflow)
            return;

        if (!seen_first_digit) {
            seen_first_digit = true;
            /*
             * The first digit is a special case. It will either need
             * to be combined with the last digit of the exponent
             * field, or else just dropped completely.
             */
            if (last_expdigit >= 0) {
                if ((int)d < expscale) {
                    /*
                     * Denormalisation. In this case the exponent
                     * vanishes completely, so we ignore last_expdigit
                     * and just print d unchanged.
                     */
                } else {
                    /*
                     * Otherwise, trim the leading bit from d and then
                     * combine it with the remaining exponent bits.
                     */
                    d = (d & ~expscale) | last_expdigit;
                }
            } else {
                /*
                 * In the case where we elide the leading digit
                 * completely, we expect that it's always just the
                 * leading 1 bit. If it's bigger than that, then we
                 * should have folded it into the last exponent digit;
                 * if it's smaller, we should have adjusted the
                 * exponent field for denormalisation; either way, we
                 * ought not to be in this case.
                 */
                assert(d == 1);
                mantdigits_left--;
                digits--;
                return;                // do not output anything
            }
        }
        if (mantdigits_left >= 0 && mantdigits_left-- == 0)
            write('.');      // print a point before the mantissa extension
        write(digitchar(d));
        digits--;
    }
    virtual void done(bool) {
        while (mantdigits_left-- > 0)
            write('0');
    }

    virtual void exact_zero() {
        sign_exp(+1, -(expbias - 1));
        while (mantdigits_left-- > 0)
            write('0');
    }

    virtual bool complete() { return overflow; }

    virtual bool has_digit_limit() { return has_dlimit; }
    virtual unsigned digits_left() { return digits; }

    virtual bigint first_digit_scale() { return expscale; }
    virtual bigint round_digit_scale() { return roundscale; }
};

OutputGenerator *ieee_format(Spigot *spig, int bits,
                             bool has_digitlimit, int digitlimit,
                             RoundingMode rmode)
{
    return new BaseOutputGenerator
        (spig, new IEEEFormatter(bits, has_digitlimit, digitlimit,
                                 (rmode == ROUND_TO_NEAREST_EVEN ||
                                  rmode == ROUND_TO_NEAREST_ODD)), rmode);
}

/* ----------------------------------------------------------------------
 * Formatter for all 'printf'-style output.
 */

class PrintfFormatter : public Formatter {
    bool hashflag;
    size_t fieldwidth;
    int precision;
    int intdigits, mindigits;
    enum { E_MODE, F_MODE, G_MODE } mode;
    enum { SPACE_BEFORE, ZERO_MIDDLE, SPACE_AFTER } padmode;
    int expbase, expmult, digitbase;
    char expchr, poschr, a;
    std::string prefix, expstr, digits;
    bool output_started, finished;
    bool seen_point, stripzeroes;
    size_t padlen;
    int saved_zeroes;
    bool has_dlimit;
    int dlimit;
  public:
    PrintfFormatter(int width, int aprecision,
                    int flags, int specifier, bool nibble_mode) {
        precision = aprecision;
        hashflag = (flags & 8);        // '#' modifier

        fieldwidth = (width > 0 ? width : 0);
        if (flags & 1)                 // '-' modifier
            padmode = SPACE_AFTER;
        else if (flags & 16)           // '0' modifier
            padmode = ZERO_MIDDLE;
        else
            padmode = SPACE_BEFORE;

        bool uppercase = isupper(specifier);

        if (strchr("aA", specifier)) {
            if (nibble_mode) {
                expbase = 16;
                expmult = 4;
            } else {
                expbase = 2;
                expmult = 1;
            }
            digitbase = 16;
            prefix = (uppercase ? "0X" : "0x");
            expchr = (uppercase ? 'P' : 'p');
            a = (uppercase ? 'A' : 'a');
            mode = E_MODE;             // %a is just a hex version of %e
        } else {
            expbase = digitbase = 10;
            expmult = 1;
            expchr = (uppercase ? 'E' : 'e');
            if (precision < 0)
                precision = 6;
            mode = (strchr("gG", specifier) ? G_MODE :
                    strchr("fF", specifier) ? F_MODE : E_MODE);
        }

        if (flags & 2)                 // '+' modifier
            poschr = '+';
        else if (flags & 4)            // ' ' modifier
            poschr = ' ';
        else
            poschr = '\0';

        output_started = false;
        seen_point = false;
        saved_zeroes = 0;
        finished = false;
        stripzeroes = false;
    }
    virtual PrintfFormatter *clone() { return new PrintfFormatter(*this); }

    virtual unsigned ebase() { return expbase; };
    virtual unsigned dbase() { return digitbase; };

    virtual bool has_min_exp() { return (mode == F_MODE); }
    virtual int min_exp() { return 0; }

    virtual void sign_exp(int sign, int exponent) {
        exponent *= expmult;

        if (mode == G_MODE) {
            /*
             * Change into F_MODE or E_MODE depending on exponent.
             */
            int P = (precision == 0 ? 1 : precision);
            int X = exponent;
            if (P > X && X >= -4) {
                mode = F_MODE;
                precision = P - (X + 1);
            } else {
                mode = E_MODE;
                precision = P - 1;
            }
            if (!hashflag)
                stripzeroes = true;
        }

        if (sign < 0) {
            prefix = "-" + prefix;
        } else if (poschr) {
            prefix = poschr + prefix;
        }

        // Initialise 'mindigits' to a temporary value, to prevent
        // undefined behaviour when digit() looks at it. We'll set it
        // to the proper value further on.
        mindigits = 0;

        if (mode == F_MODE) {
            // In 'f' mode, we don't start counting precision digits
            // until after the decimal point, so adjust for that.
            intdigits = (exponent > 0 ? exponent : 0) + 1;
            if (precision >= 0)
                precision += intdigits;

            // If the exponent is negative, output some leading
            // zeroes. (This can't happen in _real_ 'f' mode, because
            // we set min_exp in that case, but it can happen if we
            // just converted 'g' mode into 'f' mode above).
            while (exponent < 0) {
                digit(0);
                exponent++;
                precision--;
                assert(precision > 0);
            }
        } else {
            // In non-'f' mode, we print an exponent suffix.
            char expbuf[256];
#if defined _MSC_VER
#define snprintf _snprintf
#endif
            snprintf(expbuf, sizeof(expbuf), "%c%+.*d", expchr,
                     expbase==10 ? 2 : 1,   // min 2 digits for decimal exp
                     exponent);
            expstr = expbuf;
            intdigits = 1;
            if (precision >= 0)
                precision++;      // this doesn't include the int part
        }

        mindigits = precision;

        if (precision >= 0) {
            has_dlimit = true;
            dlimit = precision;
        } else {
            has_dlimit = false;
        }
    }

  private:
    void putstr(std::string s) {
        for (size_t i = 0; i < s.length(); ++i)
            write(s[i]);
    }
    size_t length_so_far() {
        return prefix.length() + expstr.length() + digits.length();
    }
    void start_output() {
        size_t len = length_so_far();
        padlen = (fieldwidth > len ? fieldwidth - len : 0);

        if (padmode == SPACE_BEFORE)
            for (size_t i = 0; i < padlen; i++)
                write(' ');

        putstr(prefix);

        if (padmode == ZERO_MIDDLE)
            for (size_t i = 0; i < padlen; i++)
                write('0');

        putstr(digits);

        output_started = true;
    }
    void putch_inner(char c) {
        if (output_started) {
            write(c);
        } else {
            digits.push_back(c);
            if (length_so_far() >= fieldwidth)
                start_output();
        }
    }
    void putch_middle(char c) {
        if (!hashflag && !seen_point && intdigits <= 0) {
            putch_inner('.');
            seen_point = true;
        }

        putch_inner(c);
        if (mindigits > 0)
            mindigits--;
        if (!seen_point)
            intdigits--;

        if (hashflag && !seen_point && intdigits <= 0) {
            putch_inner('.');
            seen_point = true;
        }
    }
    virtual void putch(char c) {
        if (stripzeroes && c == '0' && intdigits <= 0) {
            saved_zeroes++;
        } else {
            while (saved_zeroes > 0) {
                putch_middle('0');
                saved_zeroes--;
            }
            putch_middle(c);
        }
    }

  public:
    virtual void digit(unsigned d) {
        putch(digitchar(d, a));
        dlimit--;
    }
    virtual void done(bool) {
        for (int i = mindigits; i > 0; i--)
            putch('0');

        if (!output_started)
            start_output();

        putstr(expstr);

        if (padmode == SPACE_AFTER)
            for (size_t i = 0; i < padlen; i++)
                write(' ');

        finished = true;
    }

    virtual void exact_zero() {
        sign_exp(0, 0);
        digit(0);
    }

    virtual bool has_digit_limit() { return has_dlimit; }
    virtual unsigned digits_left() { return dlimit; }
};

OutputGenerator *printf_format(Spigot *spig, RoundingMode rmode,
                               int width, int precision,
                               int flags, int specifier,
                               bool nibble_mode)
{
    return new BaseOutputGenerator
        (spig, new PrintfFormatter(width, precision, flags,
                                   specifier, nibble_mode), rmode);
}
