MAINT: avoid nested dispatch in numpy.core.shape_base (#13634)
MAINT: avoid nested dispatch in numpy.core.shape_base (#13634)

* MAINT: avoid nested dispatch in numpy.core.shape_base

This is a partial reprise of the optimizations from GH-13585.

The trade-offs here are about readability, performance and whether these
functions automatically work on ndarray subclasses.

You'll have to judge the readability costs for yourself, but I think this is
pretty reasonable.

Here are the performance numbers for three relevant functions with the
following IPython script:

    import numpy as np
    x = np.array([1])
    xs = [x, x, x]
    for func in [np.stack, np.vstack, np.block]:
        %timeit func(xs)

| Function | Master | This PR |
| --- | --- | --- |
| `stack` | 6.36 µs ± 175 ns | 6 µs ± 174 ns |
| `vstack` | 7.18 µs ± 186 ns | 5.43 µs ± 125 ns |
| `block` | 15.1 µs ± 141 ns | 11.3 µs ± 104 ns |

The performance benefit for `stack` is somewhat marginal (perhaps it should be
dropped), but it's much more meaningful inside `vstack`/`hstack` and `block`,
because these functions call other dispatched functions within a loop.

For automatically working on ndarray subclasses, the main concern would be that
by skipping dispatch with `concatenate`, subclasses that define `concatenate`
won't automatically get implementations for `*stack` functions. (But I don't
think we should consider ourselves obligated to guarantee these implementation
details, as I write in GH-13633.)

`block` also will not get an automatic implementation, but given that `block`
uses two different code paths depending on argument values, this is probably a
good thing, because there's no way the code path not involving `concatenate`
could automatically work (it uses `empty()`).

* MAINT: only remove internal use in np.block

* MAINT: fixup comment on np.block optimization

jakirkham/numpy,madphysicist/numpy,anntzer/numpy,charris/numpy,pizzathief/numpy,abalkin/numpy,simongibbons/numpy,mhvk/numpy,jakirkham/numpy,pizzathief/numpy,WarrenWeckesser/numpy,pbrod/numpy,seberg/numpy,pbrod/numpy,mattip/numpy,endolith/numpy,ahaldane/numpy,abalkin/numpy,ahaldane/numpy,MSeifert04/numpy,pizzathief/numpy,numpy/numpy,mattip/numpy,pdebuyl/numpy,jakirkham/numpy,WarrenWeckesser/numpy,rgommers/numpy,madphysicist/numpy,simongibbons/numpy,pizzathief/numpy,MSeifert04/numpy,MSeifert04/numpy,grlee77/numpy,WarrenWeckesser/numpy,numpy/numpy,endolith/numpy,abalkin/numpy,grlee77/numpy,ahaldane/numpy,jorisvandenbossche/numpy,pdebuyl/numpy,mhvk/numpy,madphysicist/numpy,pbrod/numpy,jorisvandenbossche/numpy,pbrod/numpy,rgommers/numpy,pizzathief/numpy,endolith/numpy,ahaldane/numpy,simongibbons/numpy,mhvk/numpy,endolith/numpy,WarrenWeckesser/numpy,charris/numpy,madphysicist/numpy,jakirkham/numpy,pbrod/numpy,grlee77/numpy,seberg/numpy,numpy/numpy,mattip/numpy,pdebuyl/numpy,jorisvandenbossche/numpy,anntzer/numpy,charris/numpy,mattip/numpy,anntzer/numpy,pdebuyl/numpy,WarrenWeckesser/numpy,numpy/numpy,rgommers/numpy,anntzer/numpy,simongibbons/numpy,jorisvandenbossche/numpy,charris/numpy,madphysicist/numpy,grlee77/numpy,seberg/numpy,simongibbons/numpy,MSeifert04/numpy,seberg/numpy,MSeifert04/numpy,jorisvandenbossche/numpy,grlee77/numpy,rgommers/numpy,mhvk/numpy,jakirkham/numpy,ahaldane/numpy,mhvk/numpy