stable but too slow and a bit sloppy; needs caching