Optimization improvements

Several changes have been made to make the code more readable and improve the hash function's performance:

* The hash function now uses Switch.jl package for easy to read switch/case statements
* `reinterpret` calls are removed in favor of directly using `pointer`
* All hash functions now use truncated division `div(a,b)` instead of `int(floor(a/b))` for performance improvements