object Factorial_S {
  val one = new BigInt ( java.math.BigInteger.ONE )
  def iterative ( n : BigInt ) : BigInt = {
    assume ( n >= 0 , "Parameter must be a non-negative integer." )
    var i = n
    var result = one
    while ( i > 0 ) {
      result = result * i
      i = i - 1
    }
    result
  }
  def recursive ( n : BigInt ) : BigInt = {
    assume ( n >= 0 , "Parameter must be a non-negative integer." )
    if ( n < 2 ) 1
    else n * recursive ( n - 1 )
  }
  def tailRecursive ( n : BigInt ) : BigInt = {
    assume ( n >= 0 , "Parameter must be a non-negative integer." )
    if ( n < 2 ) 1
    else {
      def iterate ( x : BigInt , result : BigInt ) : BigInt =
        if ( x > n ) result
        else iterate ( x + 1 , result * x )
      iterate ( 1 , 1 )
    }
  }
  def applicative ( n : BigInt ) : BigInt = {
    one to n reduceLeft ( _ * _ )
  }
}

