/*
   File:        choose.h
   Authors:     Moore / Schneider / Kubica / Liu
   Created:     Sat Sep 22 09:17:30 EDT 2001
   Description: Header for a cached n-choose k implementation

   Copyright 2001, The Auton Lab
   */


#ifndef CHOOSE_H
#define CHOOSE_H

#include "standard.h"
#include "ambs.h"
#include "amiv.h"
#include "amdym.h"

#define CHOOSE_MAX_SIZE  1000

/************************** Prime factorization stuff **********************/
ivec* mk_primes_less_than_n_ivec(int n);
int find_prime_exponent_that_divides_fac(int n, int p);
void mk_prime_factorization_for_fac(int n, ivec** r_factors, 
				    ivec** r_factor_exponents);
void prime_factor_ivec_grow(ivec* pf, int grow_by);
void prime_factor_ivec_make_same_shape(ivec* pf1, ivec* pf2);
void prime_factor_ivec_result_check(ivec* pf1, ivec* pf2, ivec* r_result);
void prime_factor_ivec_plus(ivec* pf1, ivec* pf2, ivec* r_result);
void prime_factor_ivec_subtract(ivec* pf1, ivec* pf2, ivec* r_result);
void mk_prime_factor_choose(int n, int k, ivec** r_factors, 
			    ivec** r_factor_exponents);

/***************************************************************************/

/* (lazily) caches all values of n choose k up to max_n and max_k.  For
   values greater than max_n and max_k, the ref function will recompute
   them every time.  Creation of the cache is based on a static size.
   When you call mk_cached_choose you should consider the size of your 
   machine in the parameters you give.  The #define above is just a 
   conservative suggestion.  You may create the cache with any size you
   think will fit on your machine.
*/

typedef struct choose_cache
{
  int max_k;
  int max_n;
  dym *cache;
} choose_cache;

choose_cache* mk_choose_cache(int max_n, int max_k);

void free_choose_cache(choose_cache* c);

double simple_choose(int n, int k);

double optimized_choose(int n, int k);

double choose_cache_ref(choose_cache* c, int n, int k);

#endif



