code: def rotate(a, th):
      
      return np.sum(a[..., np.newaxis] * R_rot(th), axis=-2)
docs: Return cartesian vectors, after rotation by specified angles about
      each degree of freedom.
  
      Parameters
      ----------
      a: array, shape (n, d)
          Input d-dimensional cartesian vectors, left unchanged.
      th: array, shape (n, m)
          Angles by which to rotate about each m rotational degree of freedom
          (m=1 in 2 dimensions, m=3 in 3 dimensions).
  
      Returns
      -------
      ar: array, shape of a
          Rotated cartesian vectors.