generalized to arbitrary dimension
add extra checks, improve error message