general algorithm