improvements suggested by dsaff, and added self-test