rewritten to use GCD, not fully tested!