Issue 1:
We are using SciPy 1.1.0 main branch source code release on AIX 7.1 using AIX Toolkit packages for GCC and related packages - (https://www.ibm.com/developerworks/aix/library/aix-toolbox/alpha.html).

We have to use the AIX's linker (ld) as GCC's linker is not compatible with AIX at this time. There is a limitation with AIX linker that causes an issue with the build when compiling in 64 bit mode (using Python_64 2.7.15, and -maix64 flags).

The settings I provided are:

# export CC='gcc -lpthread -lm -lgcc -lgomp -lgfortran -maix64'
# export LDFLAGS='-lpthread -lm -lgcc -lgomp -lgfortran -maix64'
# export PATH=/opt/freeware/bin:$PATH

Once I run python_64 setup.py install, it would throw the following error message:

ld: 0706-012 The -p flag is not recognized.
ld: 0706-012 The -a flag is not recognized.
ld: 0706-012 The -t flag is not recognized.
ld: 0706-012 The -h flag is not recognized.
ld: 0706-012 The -= flag is not recognized.
ld: 0706-012 The -/ flag is not recognized.
collect2: error: ld returned 255 exit status

This is because within this command: /opt/freeware/lib64/python2.7/config/ld_so_aix /opt/freeware/bin/gfortran -Wall -maix64 -g -bI:/opt/freeware/lib64/python2.7/config/python.exp -lpthread -lm -lgcc -lgomp -lgfortran -maix64 build/temp.aix-7.1-2.7/scipy/integrate/_quadpackmodule.o -L/opt/OpenBLAS/lib -L/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/6.3.0/ppc64 -L/opt/freeware/lib64 -Lbuild/temp.aix-7.1-2.7 -Wl,-rpath="/opt/OpenBLAS/lib" -lquadpack -lmach -lopenblas -lopenblas -lgfortran -o build/lib.aix-7.1-2.7/scipy/integrate/_quadpack.so, the specific flag - -Wl,-rpath="/opt/OpenBLAS/lib" is not valid for AIX's ld_so_aix program.

I needed to include all the library flags in order for the linker to recognize the libraries for OpenBLAS among other packages.

Please let me know if you need the full run log.

I will continue to investigate on how we can eliminate this particular flag without breaking anything else.

Special thanks to the AIX Toolkit's team to help narrow this down a bit - https://www.ibm.com/developerworks/community/forums/html/topic?id=28814b7c-93a3-4cd3-9f42-94f36620013f#547a941b-11c6-4f5b-aa6c-b8208b7b86bb

Update: Added LDFLAGS as I forgot to include that -- required for AIX to recognize gomp and other packages when linking.

Issue 2:
This is a follow up of discussions in #10844.

Describe the solution you'd like

All sampling methods in scipy.stats are using random_state which is a np.random.Generator (for new code). But this numpy generator is not aware of dimensions. Also, the new scipy.stats.qmc allow to generate samples efficiently in n-dimensions. It would be nice to bridge the gap between the two.

Currently there is a qmc.MultivariateNormalQMC. Instead of duplicating this for other distributions, a solution could be to make the QMC engines inherit from np.random.BitGenerator. We could then use the new QMC engines with all the existing distributions.

Describe alternatives you've considered

Solution using a BitGenerator: Seemingly, it must be done in Cython. Otherwise I saw that there was a wrapper around BitGenerator, but this is not available in numpy... https://bashtage.github.io/randomgen/bit_generators/userbitgenerator.html from @bashtage. This is working but the underlying numpy code is not aware of dimensions (https://github.com/numpy/numpy/blob/e4feb7027e397925d220a10dd58b581b87ca1fec/numpy/random/_generator.pyx#L3562-L3568).

from numpy.random import Generator
from randomgen import UserBitGenerator

class SobolNP:
def __init__(self, state):
self._next_64 = None
self.engine = Sobol(d=1, scramble=False, seed=state)

def random_raw(self):
"""Generate the next "raw" value, which is 64 bits"""
return int(self.engine.random() * 2**64) # although Sobol uses 30 bits...

@property
def next_64(self):
def _next_64(void_p):
return self.random_raw()

self._next_64 = _next_64
return _next_64

# examples
prng = SobolNP(1234)
sobol_bit_generator = UserBitGenerator(prng.next_64, 64)
gen = Generator(sobol_bit_generator)
gen.random(8)

Another solution would be to mock np.random.Generator: I am using __getattr__ to mock calls to the distributions. So calls like random_state.uniform(...). Seems to be working and n-dimensions is ok too.

from numpy.random import Generator
import scipy.stats as stats
from functools import partial

class ScipyGenerator:

@property
def __class__(self):
return Generator

def __init__(self, d):
self.qrng = stats.qmc.Sobol(d=d, scramble=False)

def rvs(self, *args, dist, **kwargs):
args = list(args)
size = kwargs.pop('size', None)
if size is None:
size = args.pop(0)
sample = self.qrng.random(size)
return dist(*args, **kwargs).ppf(sample)

def __getattr__(self, attr):
try:
dist = getattr(stats, attr)
return partial(self.rvs, dist=dist)
except AttributeError as err_np:
raise err_np

# examples
random_state = ScipyGenerator(d=2)
isinstance(random_state, Generator)
random_state.uniform(8)
random_state.gamma(2, size=8)