+/* --- Simple case --- *
+ *
+ * Use a fixed-sized buffer and single-precision arithmetic to pick off
+ * low-order digits. Put each digit in a buffer, working backwards from the
+ * end. If the buffer becomes full, recurse to get another one. Ensure that
+ * there are at least @z@ digits by writing leading zeroes if there aren't
+ * enough real digits.
+ */
+
+static int simple(mpw n, int radix, unsigned z,
+ const mptext_ops *ops, void *p)
+{
+ int rc = 0;
+ char buf[64];
+ unsigned i = sizeof(buf);
+ int rd = radix > 0 ? radix : -radix;
+
+ do {
+ int ch;
+ mpw x;
+
+ x = n % rd;
+ n /= rd;
+ if (radix < 0)
+ ch = x;
+ else if (x < 10)
+ ch = '0' + x;
+ else
+ ch = 'a' + x - 10;
+ buf[--i] = ch;
+ if (z)
+ z--;
+ } while (i && n);
+
+ if (n)
+ rc = simple(n, radix, z, ops, p);
+ else {
+ static const char zero[32] = "00000000000000000000000000000000";
+ while (!rc && z >= sizeof(zero)) {
+ rc = ops->put(zero, sizeof(zero), p);
+ z -= sizeof(zero);
+ }
+ if (!rc && z)
+ rc = ops->put(zero, z, p);
+ }
+ if (!rc)
+ rc = ops->put(buf + i, sizeof(buf) - i, p);
+ BURN(buf);
+ return (rc);
+}
+
+/* --- Complicated case --- *
+ *
+ * If the number is small, fall back to the simple case above. Otherwise
+ * divide and take remainder by current large power of the radix, and emit
+ * each separately. Don't emit a zero quotient. Be very careful about
+ * leading zeroes on the remainder part, because they're deeply significant.
+ */
+
+static int complicated(mp *m, int radix, mp **pr, unsigned i, unsigned z,
+ const mptext_ops *ops, void *p)
+{
+ int rc = 0;
+ mp *q = MP_NEW;
+ unsigned d = 1 << i;
+
+ if (MP_LEN(m) < 2)
+ return (simple(MP_LEN(m) ? m->v[0] : 0, radix, z, ops, p));
+
+ assert(i);
+ mp_div(&q, &m, m, pr[i]);
+ if (!MP_LEN(q))
+ d = z;
+ else {
+ if (z > d)
+ z -= d;
+ else
+ z = 0;
+ rc = complicated(q, radix, pr, i - 1, z, ops, p);
+ }
+ if (!rc)
+ rc = complicated(m, radix, pr, i - 1, d, ops, p);
+ mp_drop(q);
+ return (rc);
+}
+
+/* --- Main driver code --- */
+