/****************************************************************************/
/* Cálculo del número combinatorio m sobre n. Para enteros de tamaño        */
/* arbitrario. Usa LIP.                                                     */
/*                                                                          */
/* Jaime Suarez <mcripto@bigfoot.com> 2003                                  */
/* en http://elparaiso.mat.uned.es                                            */
/****************************************************************************/

#include "lip.h"
#include <stdio.h>

int comb(long m, long n, verylong *x);
int fact(long n, verylong *x);

main(int argc, char *argv[])
{
	verylong x=0;
	long m,n;
	
	if (argc!=3) {
		printf("%s <m> <n> calcula el numero combinatorio m sobre n\n",
				argv[0]);
		return 1;
	}

	m=atol(argv[1]);
	n=atol(argv[2]);
	comb(m,n,&x);
	printf("%ld sobre %ld = ",m,n); 
	zwriteln(x);
	return 0;
}

int comb(long m, long n, verylong *x)
{
	verylong a=0,b=0,c=0,d=0,e=0;

	if (m<n || m==0 || n==0) return 1;
	
	fact(m,&a);
	fact(n,&b);
	fact(m-n,&c);
	zmul(b,c,&d);
	zdiv(a,d,x,&e);	/* e, el resto debería ser 0 */
	return 0;
}

int fact(long n, verylong *x)
{
	verylong fact=0, tmp=0, uno=0;
	
	if (n<0) return -1;
	if (n==0) { zone(x); return 0;}

	zone(&fact);
	zone(&uno);
	while(n >1) {
		zsmul(fact,n--,&tmp);
		zcopy(tmp, &fact);
	}
	
	zcopy(fact, x);
	return 0;
}