#include <stdio.h>
struct ratio
	{
	int over;
	int under;
	};

main(int argc, char *argv[])
	{
	struct ratio diamond[29][29];
	struct ratio one_one;
	int relation[29];
	int i, k;
	int limit;
	
	if(argc < 2)
		{
		fprintf(stderr, "To produce Incipient Tonality Diamonds, enter the tonal relation along a side.\n");
		fprintf(stderr, "(See Harry Partch, \"Genesis of a Music\", Chapters 7 and 8).\n"); 
		fprintf(stderr, "The untonalities will form one side of the diamond and the otonalities the other\n");
		fprintf(stderr, "and the rest get filled in from there.\n\n");
		fprintf(stderr, "For example, try entering [%s 4 5 6]  (the ordinary triad relations)\n", argv[0]);
		fprintf(stderr, "to see the septimal just scale,\n", argv[0]);
		fprintf(stderr, "or [%s 4 5 6 7 8 9 10 11]  to see Partch's 11 limit \n",
argv[0]);
		fprintf(stderr, "as laid out on the Diamond Marimba\n");
		exit(-1);
		}
	if(argc > 30)
		{
		fprintf(stderr, "Hard coded maximum of 29\n");
		exit(-1);
		}
	limit = argc - 1;	
	for(i = 1; i < argc; i++)
		relation[i-1] = atoi(argv[i]);	
	
	one_one.over = one_one.under = 1;
	for(i = 0; i < limit; i++)
		{
		orelate(&diamond[i][0], &one_one, relation[i]);
		for(k = 1; k < limit; k++)
		        /* into diamond[i][k] put diamond[i][0] * relation[k]/1 */
			urelate(&diamond[i][k], &diamond[i][0], relation[k]);
		}
	
	for(i = 0; i < limit; i++)
		{
		for(k = 0; k < limit; k++)
			 {
			 printf("%3d/%-3d ",  diamond[i][k].over, diamond[i][k].under);
			 }
		printf("\n\n");
		}			
	}
	
orelate(struct ratio *cell,  struct ratio *base,  int relation)
	{
	struct ratio multiplier;
	
	multiplier.under = 1;
	multiplier.over = relation;
	ratio_multiply_cpy(cell,  base, &multiplier);
	}


urelate(struct ratio *cell,  struct ratio *base,  int relation)
	{
	struct ratio multiplier;
	
	multiplier.over = 1;
	multiplier.under = relation;
	ratio_multiply_cpy(cell,  base, &multiplier);
	}

ratio_multiply_cpy(struct ratio *cell,  struct ratio *base,  struct ratio *multiplier)
	{
	cell->over = multiplier->over * base->over;
	cell->under = multiplier->under * base->under;
	normalize(cell);
	}	
	
normalize(struct ratio *cell)
	{
	prime_reduce(cell);
	if(cell->over == cell->under)
		{
		cell->over = cell->under = 1;
		return;
		}
	if(cell->over < cell->under)
		{
		if(cell->under%2 == 0)
			{
			cell->under /= 2;
			normalize(cell);
			return;
			}
		else
			{
			cell->over *= 2;
			normalize(cell);
			return;
			}
		}	
	if(cell->under < cell->over)
		{
		if(cell->over/2 < cell->under)
			return;
		if(cell->over%2 == 0)
			{
			cell->over /= 2;
			normalize(cell);
			return;
			}
		else
			{
			cell->under *= 2;
			normalize(cell);
			return;
			}
		}	
	}
	
prime_reduce(struct ratio *cell)
	{
	static int prime[] = { 29, 23, 19, 17, 13, 11, 7, 5, 3, 2, 0 };
	int i;
	
	for(i = 0; prime[i] != 0; i++)
		{
		if(cell->under%prime[i] == 0 && cell->over%prime[i] == 0)
			{
			cell->under /= prime[i];
			cell->over  /= prime[i];
			prime_reduce(cell);
			}
		}
	return;
	}	
		
