code: def knot_removal_kv(knotvector, span, r):
      
      # Edge case
      if r < 1:
          return knotvector
  
      # Create a deep copy of the input knot  vector
      kv_updated = deepcopy(knotvector)
  
      # Shift knots
      for k in range(span + 1, len(knotvector)):
          kv_updated[k - r] = knotvector[k]
  
      # Slice to get the new knot vector
      kv_updated = kv_updated[0:-r]
  
      # Return the new knot vector
      return kv_updated
docs: Computes the knot vector of the rational/non-rational spline after knot removal.
  
      Part of Algorithm A5.8 of The NURBS Book by Piegl & Tiller, 2nd Edition.
  
      :param knotvector: knot vector
      :type knotvector: list, tuple
      :param span: knot span
      :type span: int
      :param r: number of knot removals
      :type r: int
      :return: updated knot vector
      :rtype: list