Reimplemented using C++ for better performance