/*
 * spigot.h: Declare the base classes for spigot-based exact real
 * arithmetic.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "bigint.h"

#define lenof(x) (sizeof(x)/sizeof(*(x)))

#if defined HAVE_FDOPEN && defined HAVE_TCSETATTR
/*
 * The code which permits expressions to contain atoms of the form
 * 'base10fd:3' and 'cfracfd:4', identifying a Unix file descriptor
 * from which to read a number formatted in a particular way, is
 * conditionalised on autoconf having told us we've got the necessary
 * API functions available. This should remove one obstacle to
 * compiling this program on non-Unix.
 */
#define HAVE_FDS
#endif

#include <stdio.h>
#include <stdarg.h>

#include <string>

/*
 * Below are the main class definitions for the central parts of the
 * spigot algorithm.
 *
 * There are three basic components, which I've called Source, Core
 * and Generator.
 *
 * A Source is something which delivers a description of a specific
 * real number, in the spigot representation of a stream of matrices
 * and a starting interval.
 *
 * The Generator base class contains the top-level loop of the main
 * spigot algorithm, which checks to see if it has enough information
 * to produce some output, and if so, produces it and premultiplies in
 * a matrix representing the extraction of that output, and otherwise,
 * fetches more stuff from the Source. A derived class of Generator
 * exists for each possible format the output might be needed in:
 * digits in a base-n positional system, continued fraction terms,
 * random queries useful to clients doing further computation on the
 * numbers, and there's also a special-purpose Generator which
 * reconstitutes the number as a Source again so that it can be fed to
 * further computations.
 *
 * But Generator doesn't contain the whole spigot algorithm. About
 * half of it is separated out into the Core class. The interface
 * between Generator and Core consists of three key methods: Generator
 * can ask Core where the current endpoints of its output interval lie
 * (in a form rich enough to also spot things like constant functions
 * and poles), it can tell Core to go and absorb more data from its
 * Source to refine those endpoints, and it can pass a matrix back to
 * Core to premultiply in when it's extracting output.
 *
 * Splitting the algorithm up at that point turns out to be a good
 * idea purely on legibility grounds, but the main purpose is to
 * permit alternative Cores. The primary default Core takes a single
 * Source, but this system also permits a two-input Core to be slotted
 * in in place of the default one, to do arithmetic on two input
 * numbers, without having to affect the Generator side of the
 * mechanism.
 */

class Debuggable {
    /*
     * Everything in this hierarchy derives from Debuggable, but
     * that's not very interesting; it's only there to provide a
     * convenient means of doing diagnostic print statements which all
     * automatically include their 'this' pointer.
     *
     * All the diagnostics are disabled completely (and hence should
     * be optimised away at all their call sites) unless you change
     * the #if 0 below to #if 1; and even then, nothing will be
     * printed unless you call enable_debug() on some particular
     * object.
     */
  protected:
    bool debugging;
  public:
    Debuggable();
    virtual ~Debuggable();
    void dprintv(const char *fmt, va_list ap);
#if 0
    void enable_debug() { debugging = true; }
    void dprint(const char *fmt, ...) {
        if (!debugging)
            return;
        va_list ap;
        va_start(ap, fmt);
        dprintv(fmt, ap);
        va_end(ap);
    }
#else
    inline void enable_debug() { }
    inline void dprint(const char * /*fmt*/, ...) { }
#endif
};

class Core;
class Source;
class BaseSource;
class CfracSource;

class Coreable : public Debuggable {
    /*
     * Cores and Sources are more or less interchangeable, because any
     * Source is easily turned into a Core by putting a Core1 on the
     * front (the default one-source core, defined in spigot.cpp), and
     * conversely any Core can be turned back into a Source by putting
     * a SourceGenOuter on the front (also in spigot.cpp). Hence, we
     * define this common base class of Core and Source which makes
     * that interchangeability explicit; in each descendant, one of
     * toCore and toSource just returns 'this' and the other puts an
     * appropriate shim on the front.
     */
  public:
    virtual Coreable *clone() = 0;
    virtual Core *toCore() = 0;
    virtual Source *toSource() = 0;

    /*
     * Lots of parts of this program can do something more useful if
     * they *know* a number is rational. Hence, all Cores and Sources
     * provide this virtual function, which will give their rational
     * value if they're known to have one.
     */
    virtual bool is_rational(bigint *n, bigint *d);
};

/*
 * 'Coreable' is a sensible name in terms of how the above class fits
 * into the complicated structure. But this is also the type that most
 * of the actual function implementations will be passing around all
 * over the place, so I'm giving it the alias name 'Spigot'. (Partly
 * because historically that's what the big main class was called, so
 * it's easier not to have to change it throughout the code; but also
 * I think it's realistically the best candidate for the primary
 * class.)
 */
typedef Coreable Spigot;

class Core : public Coreable {
    /*
     * Ancestor of all Core classes. The boilerplate toCore and
     * toSource methods are filled in here, but all the routines for
     * doing interesting work are left to the concrete descendant.
     */
  public:
    virtual Core *clone() = 0;
    virtual void premultiply(const bigint matrix[4]) = 0;
    virtual void refine() = 0;
    virtual int max_endpoints() = 0;
    virtual int endpoints(bigint *endpoints) = 0;

    virtual Core *toCore();
    virtual Source *toSource();
};

class Source : public Coreable {
    /*
     * Ancestor of all Source classes. The boilerplate toCore and
     * toSource methods are filled in here, but all the routines for
     * doing interesting work are left to the concrete descendant.
     *
     * You can override this class and fill in the three pure virtual
     * methods, or some still-abstract descendants are provided below
     * in case that's easier.
     */
  public:
    virtual Source *clone() = 0;
    virtual bool gen_interval(bigint *low, bigint *high) = 0;
    virtual bool gen_matrix(bigint *matrix) = 0;
    virtual Core *toCore();
    virtual Source *toSource();
};

class BaseSource : public Source {
    /*
     * Abstract base class for turning a stream of digits in a
     * specified base into a Source. Override this class and fill in
     * gen_digit() (and clone() from the parent).
     */
    bool first_digit;
    bigint base;
    bool negate;
  public:
    BaseSource(bigint base, bool negate);
    virtual bool gen_digit(bigint *digit) = 0;

    virtual bool gen_interval(bigint *low, bigint *high);
    virtual bool gen_matrix(bigint *matrix);
};

class CfracSource : public Source {
    /*
     * Abstract base class for turning a stream of continued fraction
     * terms into a Source. Override this class and fill in
     * gen_term() (and clone() from the parent).
     */
  public:
    virtual bool gen_term(bigint *term) = 0;

    virtual bool gen_interval(bigint *low, bigint *high);
    virtual bool gen_matrix(bigint *matrix);
};

class BinaryIntervalSource : public Source {
    /*
     * Abstract base class for turning a stream of binary intervals
     * (that is, intervals of rationals with a power-of-2 denominator)
     * into a Source. Override this class and fill in
     * gen_bin_interval() (and clone() from the parent).
     */
    bigint lo, hi;
    unsigned bits;
    bool started;
  public:
    BinaryIntervalSource();
    virtual void gen_bin_interval(bigint *lo, bigint *hi, unsigned *bits) = 0;

    virtual bool gen_interval(bigint *low, bigint *high);
    virtual bool gen_matrix(bigint *matrix);
};

class Generator : public Debuggable {
    /*
     * Ancestor of all Generator classes. This base class contains the
     * main function iterate_spigot_algorithm that everything ends up
     * coming back to, but exposes no way to get the results out. So
     * it's conceptually an abstract base class, even though it
     * doesn't happen to have any pure virtual methods; regardless of
     * that, you have to override it to get anything useful done,
     * because you have to add public methods that produce output.
     *
     * Generator objects have the common feature that you pass them a
     * Core (or at least Coreable) at construction time, and they take
     * ownership of it - they expect it to have been be dynamically
     * allocated, and they will delete it when destructed.
     */
    bool started;
    bool we_are_now_constant;
    int max_endpoints;
    bigint *endpoints;
  private:
    int iterate_spigot_algorithm(bool force);
  protected:
    Core *core;
    void ensure_started();
    void iterate_to_bounds(bigint *rlo, bigint *rhi,
                           bool *rlo_open, bool *rhi_open,
                           int minwidth, const bigint *scale,
                           bool force_refine);
    bool iterate_to_floor_or_inf(bigint *rfloor, bool *rconstant = NULL);
    bigint iterate_to_floor(bool *constant = NULL);
  public:
    Generator(Coreable *acore);
    virtual ~Generator();
};

class CfracGenerator : public Generator {
    /*
     * Generator that produces continued fraction terms of the number.
     * The first call to get_term() returns the integer part;
     * subsequent calls return the following terms.
     *
     * No special handling is done for negative numbers. So the
     * integer part returned will always be floor of the actual
     * number, and the next term has positive sense, i.e. if the
     * numbers returned are a, b, c, ... then the actual number is
     * equal to
     *
     *   a + 1
     *       -----------
     *       b + 1
     *           -------
     *           c + 1
     *               ---
     *               ...
     */
    bool done;
  public:
    CfracGenerator(Coreable *acore);
    bool get_term(bigint *retterm);
};

class ConvergentsGenerator {
    /*
     * Class that returns continued-fraction _convergents_ to the
     * number, i.e. the actual rational numbers resulting from
     * successive truncations of the continued fraction.
     *
     * This class _looks_ like a generator, and you can treat it as
     * one for all practical purposes, but it isn't actually descended
     * from the Generator base class because I need to ensure that
     * nobody accidentally calls get_term() on the CfracGenerator it's
     * based on. (Otherwise a term will be missed by the tracker in
     * this class, and all the subsequent convergents will come out
     * wrong). Therefore, it _has_ a CfracGenerator rather than being
     * one.
     *
     * (I suppose that makes the class's name a misnomer - but it
     * would surely be even uglier to call it something like
     * ConvergentsNotReallyAGenerator.)
     */
    CfracGenerator cfg;
    bigint cvn, pcvn, cvd, pcvd;

  public:
    ConvergentsGenerator(Coreable *acore);
    bool get_convergent(bigint *n, bigint *d);
};

class BracketingGenerator : public Generator {
    /*
     * Class that returns pairs of increasingly precise rational
     * numbers over a common denominator bracketing the target number,
     * but which avoids exactness hazards by not insisting that they
     * be the very best rationals for a given denominator.
     *
     * The denominators are always powers of two, and at your option
     * you can receive them as bigints (via get_bracket) or as plain
     * bit-shift counts (get_bracket_shift).
     */
    unsigned bits, prevbits;
    bool started;

  public:
    BracketingGenerator(Coreable *acore);
    void get_bracket(bigint *nlo, bigint *nhi, bigint *d);
    void get_bracket_shift(bigint *nlo, bigint *nhi, unsigned *dbits);
    void set_denominator_lower_bound(bigint d);
    void set_denominator_lower_bound_shift(unsigned dbits);
};

class StaticGenerator : public Generator {
    /*
     * This generator never premultiplies anything into its core,
     * unless explicitly told to. Therefore, its various methods can
     * safely be called in any interleaving without interfering with
     * one another; the only one that modifies state is the
     * premultiply() method, and you know when you're calling that.
     */
  public:
    StaticGenerator(Coreable *acore);
    bigint get_floor(bool *constant);
    bigint get_approximate_approximant(const bigint &d);
    virtual int get_sign();         /* +1, -1, or 0 if exactly zero */
    virtual int try_get_sign();     /* +1, -1, or 0 if not yet sure */
    void premultiply(const bigint matrix[4]);
    /* Also, in this derived class we expose iterate_to_bounds() as public. */
    using Generator::iterate_to_bounds;
};

/*
 * Abstract base class of the various generators used in main() to
 * produce spigot's final output.
 */
class OutputGenerator : public Generator {
  protected:
    OutputGenerator(Coreable *acore) : Generator(acore) {}
  public:
    virtual ~OutputGenerator() {};
    virtual bool get_definite_output(std::string &out) = 0;
    virtual bool get_tentative_output(std::string &out, int *digits) = 0;
};

/*
 * Function called periodically during the inner loop of
 * iterate_spigot_algorithm, which can check for an interruption of
 * some sort and handle it by throwing a C++ exception to terminate
 * the iteration.
 */
void spigot_check_exception();

/*
 * Functions in misc.cpp.
 */
void bigint_print_nl(const bigint &a);
void debug_printv(FILE *fp, const char *fmt, va_list ap);
void dprint(const char *fmt, ...);
/* Exact sign test. Will take ownership of x and deletes it. */
int get_sign(Spigot *x);
/* Tries to find the sign of one of x1,x2, whichever gets there first.
 * Returns +1 or -1 if the sign is of x1, or +2 or -2 if it's x2. Will
 * take ownership of both x1,x2 and delete them. */
int parallel_sign_test(Spigot *x1, Spigot *x2);
bigint gcd(bigint a, bigint b);
