text: '''THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE
  DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY,
  WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.'''
  
  # Bitcoin Cash (BCH)   qpz32c4lg7x7lnk9jg6qg7s4uavdce89myax5v5nuk
  # Ether (ETH) -        0x843d3DEC2A4705BD4f45F674F641cE2D0022c9FB
  # Litecoin (LTC) -     Lfk5y4F7KZa9oRxpazETwjQnHszEPvqPvu
  # Bitcoin (BTC) -      34L8qWiQyKr8k4TnHDacfjbaSqQASbBtTd
  
  # contact :- github@jamessawyer.co.uk
  
  
  
  # fibonacci.py
  """
  1. Calculates the iterative fibonacci sequence
  
  2. Calculates the fibonacci sequence with a formula
      an = [ Phin - (phi)n ]/Sqrt[5]
      reference-->Su, Francis E., et al. "Fibonacci Number Formula." Math Fun Facts. <http://www.math.hmc.edu/funfacts>
  """
  import math
  import functools
  import time
  from decimal import getcontext, Decimal
  
  getcontext().prec = 100
  
  
  def timer_decorator(func):
      @functools.wraps(func)
      def timer_wrapper(*args, **kwargs):
          start = time.time()
          func(*args, **kwargs)
          end = time.time()
          if int(end - start) > 0:
              print(f"Run time for {func.__name__}: {(end - start):0.2f}s")
          else:
              print(f"Run time for {func.__name__}: {(end - start)*1000:0.2f}ms")
          return func(*args, **kwargs)
  
      return timer_wrapper
  
  
  # define Python user-defined exceptions
  class Error(Exception):
      """Base class for other exceptions"""
  
  
  class ValueTooLargeError(Error):
      """Raised when the input value is too large"""
  
  
  class ValueTooSmallError(Error):
      """Raised when the input value is not greater than one"""
  
  
  class ValueLessThanZero(Error):
      """Raised when the input value is less than zero"""
  
  
  def _check_number_input(n, min_thresh, max_thresh=None):
      """
      :param n: single integer
      :type n: int
      :param min_thresh: min threshold, single integer
      :type min_thresh: int
      :param max_thresh: max threshold, single integer
      :type max_thresh: int
      :return: boolean
      """
      try:
          if n >= min_thresh and max_thresh is None:
              return True
          elif min_thresh <= n <= max_thresh:
              return True
          elif n < 0:
              raise ValueLessThanZero
          elif n < min_thresh:
              raise ValueTooSmallError
          elif n > max_thresh:
              raise ValueTooLargeError
      except ValueLessThanZero:
          print("Incorrect Input: number must not be less than 0")
      except ValueTooSmallError:
          print(
              f"Incorrect Input: input number must be > {min_thresh} for the recursive calculation"
          )
      except ValueTooLargeError:
          print(
              f"Incorrect Input: input number must be < {max_thresh} for the recursive calculation"
          )
      return False
  
  
  @timer_decorator
  def fib_iterative(n):
      """
      :param n: calculate Fibonacci to the nth integer
      :type n:int
      :return: Fibonacci sequence as a list
      """
      n = int(n)
      if _check_number_input(n, 2):
          seq_out = [0, 1]
          a, b = 0, 1
          for _ in range(n - len(seq_out)):
              a, b = b, a + b
              seq_out.append(b)
          return seq_out
  
  
  @timer_decorator
  def fib_formula(n):
      """
      :param n: calculate Fibonacci to the nth integer
      :type n:int
      :return: Fibonacci sequence as a list
      """
      seq_out = [0, 1]
      n = int(n)
      if _check_number_input(n, 2, 1000000):
          sqrt = Decimal(math.sqrt(5))
          phi_1 = Decimal(1 + sqrt) / Decimal(2)
          phi_2 = Decimal(1 - sqrt) / Decimal(2)
          for i in range(2, n):
              temp_out = ((phi_1 ** Decimal(i)) - (phi_2 ** Decimal(i))) * (
                  Decimal(sqrt) ** Decimal(-1)
              )
              seq_out.append(int(temp_out))
          return seq_out
  
  
  if __name__ == "__main__":
      num = 20
      # print(f'{fib_recursive(num)}\n')
      # print(f'{fib_iterative(num)}\n')
      # print(f'{fib_formula(num)}\n')
      fib_iterative(num)
      fib_formula(num)
  