reimplemented and generalized + TESTS!!!!!