<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def map_eigenvalues( matrix: np.ndarray, func: Callable[[complex], complex], *, rtol: float = 1e-5, atol: float = 1e-8) -> np.ndarray: """Applies a function to the eigenvalues of a matrix. Given M = sum_k a_k |v_k><v_k|, returns f(M) = sum_k f(a_k) |v_k><v_k|. Args: matrix: The matrix to modify with the function. func: The function to apply to the eigenvalues of the matrix. rtol: Relative threshold used when separating eigenspaces. atol: Absolute threshold used when separating eigenspaces. Returns: The transformed matrix. """

    vals, vecs = _perp_eigendecompose(matrix,
                                      rtol=rtol,
                                      atol=atol)
    pieces = [np.outer(vec, np.conj(vec.T)) for vec in vecs]
    out_vals = np.vectorize(func)(vals.astype(complex))

    total = np.zeros(shape=matrix.shape)
    for piece, val in zip(pieces, out_vals):
        total = np.add(total, piece * val)
    return total