Rewritten and added some tests