code: def derivatives_ctrlpts(**kwargs):
          
          # r1 - minimum span, r2 - maximum span
          r1 = kwargs.get('r1')
          r2 = kwargs.get('r2')
          deriv_order = kwargs.get('deriv_order')
          degree = kwargs.get('degree')
          knotvector = kwargs.get('knotvector')
          ctrlpts = kwargs.get('ctrlpts')
          dimension = kwargs.get('dimension')
  
          # Algorithm A3.3
          r = r2 - r1
          PK = [[[None for _ in range(dimension)] for _ in range(r + 1)] for _ in range(deriv_order + 1)]
          for i in range(0, r + 1):
              PK[0][i][:] = [elem for elem in ctrlpts[r1 + i]]
  
          for k in range(1, deriv_order + 1):
              tmp = degree - k + 1
              for i in range(0, r - k + 1):
                  PK[k][i][:] = [tmp * (elem1 - elem2) /
                                 (knotvector[r1 + i + degree + 1] - knotvector[r1 + i + k]) for elem1, elem2
                                 in zip(PK[k - 1][i + 1], PK[k - 1][i])]
  
          # Return a 2-dimensional list of control points
          return PK
docs: Computes the control points of all derivative curves up to and including the {degree}-th derivative.
  
          Implementation of Algorithm A3.3 from The NURBS Book by Piegl & Tiller.
  
          Output is PK[k][i], i-th control point of the k-th derivative curve where 0 <= k <= degree and r1 <= i <= r2-k.