refactor and add untested cuda support