/* File: dmnum_tri.c */

/* Purpose: Digital mean numerator triangle generator */

#include <stdio.h>
#include <gmp.h>

/*
 * Calculate the digital mean numerator M for arbitrary B and N
 */
static void mpz_digmean_num(mpz_t m, const mpz_t b, const mpz_t n)
{
	mpz_t q, r;

	/* Initialize */
	mpz_set_ui(m, 0);
	mpz_init_set(q, n);
	mpz_init(r);

	/* Calculate digital mean numerator */
	while (mpz_cmp_ui(q, 0))
	{
		/* Divide by base */
		mpz_tdiv_qr(q, r, q, b);

		/* Scale remainder */
		mpz_mul_ui(r, r, 2);

		/* Subtract base */
		mpz_sub(r, r, b);

		/* Correct */
		mpz_add_ui(r, r, 1);

		/* Accumulate */
		mpz_add(m, m, r);
	}

	/* Finalize */
	mpz_clear(r);
	mpz_clear(q);
}

int main(void)
{
	mpz_t b, n, m;

	/* Initialize */
	mpz_init_set_ui(n, 2);
	mpz_init(b);
	mpz_init(m);

	while (1)
	{
		/* Extract maximum number of characters per number */
		const int len = mpz_sizeinbase(n, 10) + 2;

		/* Display the current row */
		for (mpz_set_ui(b, 2); mpz_cmp(b, n) <= 0; mpz_add_ui(b, b, 1))
		{
			/* Calculate numerator */
			mpz_digmean_num(m, b, n);

			/* Display */
			gmp_printf("%*Zd ", len, m);
		}

		/* Terminate */
		printf("\n");

		/* Advance */
		mpz_add_ui(n, n, 1);
	}

	/* Finalize */
	mpz_clear(m);
	mpz_clear(b);
	mpz_clear(n);
}

/* End: dmnum_tri.c */