some improvements, not well tested