#include "factorial_gmp.hpp" 

namespace Factorial {

mpz_class iterative ( const mpz_class n ) {
  if ( n < 0 ) { throw std::invalid_argument ( "Parameter must be a non-negative integer." ) ; }
  mpz_class total ( 1 ) ;
  for ( unsigned int i = 2 ; i <= n ; ++i ) { total *= i ; }
  return total ;
}

mpz_class recursive ( const mpz_class n ) {
  if ( n < 0 ) { throw std::invalid_argument ( "Parameter must be a non-negative integer." ) ; }
  return ( n < 2 ) ? mpz_class ( 1 ) : n * recursive ( n - 1 ) ;
}

mpz_class tailRecursive_iterate ( const mpz_class n , const mpz_class result ) {
  return ( n < 2 ) ? result : tailRecursive_iterate ( n - 1 , result * n ) ;
}

mpz_class tailRecursive ( const mpz_class n ) {
  if ( n < 0 ) { throw std::invalid_argument ( "Parameter must be a non-negative integer." ) ; }
  return ( n < 2 ) ? mpz_class ( 1 ) : tailRecursive_iterate ( n , mpz_class ( 1 ) ) ;
}


} // namespace Factorial
