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.

def rotation_matrix_arbitrary_axis(angle, axis):
    """
    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.

    """
    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]])