adding nogil to computationally intensive parts

I believe Python's Global Interpreter Lock (GIL) is not required for heavy computation parts. So here's a modification with some `nogil`s, and it works perfectly fine in my use case with `joblib` and `backend = 'threading'`