refactor rand on UnitRange / AbstractArray
This is another approach to the (non-merged) refactoring part
of #8309 and #8649.
The goal is to reduce to the minimum the different code paths
taken by UnitRange and AbstractArray (UnitRange are handled
differently so that those with overflowing length still work.
In particular two rand! method are merged into one.