refactored to speed up calculations