Much faster and generic algorithm.