rewritten with new algorithm and 3.10 compatibility