added sparse matrix version