code: def rotation_matrix_arbitrary_axis(angle, axis):
      
      axis = normalize_vector(axis)
  
      a = np.cos(angle / 2)
      b, c, d = axis * np.sin(angle / 2)
  
      e11 = np.square(a) + np.square(b) - np.square(c) - np.square(d)
      e12 = 2 * (b * c - a * d)
      e13 = 2 * (b * d + a * c)
  
      e21 = 2 * (b * c + a * d)
      e22 = np.square(a) + np.square(c) - np.square(b) - np.square(d)
      e23 = 2 * (c * d - a * b)
  
      e31 = 2 * (b * d - a * c)
      e32 = 2 * (c * d + a * b)
      e33 = np.square(a) + np.square(d) - np.square(b) - np.square(c)
  
      return np.array([[e11, e12, e13], [e21, e22, e23], [e31, e32, e33]])
docs: Return a rotation matrix of `angle` radians about `axis`.
  
      Parameters
      ----------
      angle : int or float
          The size of the rotation in radians.
  
      axis : numpy.array
          A 3 element aray which represents a vector. The vector is the
          axis about which the rotation is carried out.
  
      Returns
      -------
      numpy.array
          A 3x3 array representing a rotation matrix.