<p dir="auto">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 - (<a href="https://www.ibm.com/developerworks/aix/library/aix-toolbox/alpha.html" rel="nofollow">https://www.ibm.com/developerworks/aix/library/aix-toolbox/alpha.html</a>).</p>
<p dir="auto">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).</p>
<p dir="auto">The settings I provided are:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="# export CC='gcc -lpthread -lm -lgcc -lgomp -lgfortran -maix64'
# export LDFLAGS='-lpthread -lm -lgcc -lgomp -lgfortran -maix64'
# export PATH=/opt/freeware/bin:$PATH"><pre class="notranslate"><code class="notranslate"># export CC='gcc -lpthread -lm -lgcc -lgomp -lgfortran -maix64'
# export LDFLAGS='-lpthread -lm -lgcc -lgomp -lgfortran -maix64'
# export PATH=/opt/freeware/bin:$PATH
</code></pre></div>
<p dir="auto">Once I run <code class="notranslate">python_64 setup.py install</code>, it would throw the following error message:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="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"><pre class="notranslate"><code class="notranslate">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
</code></pre></div>
<p dir="auto">This is because within this command:  <code class="notranslate">/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</code>, the specific flag - <code class="notranslate">-Wl,-rpath="/opt/OpenBLAS/lib"</code> is not valid for AIX's <code class="notranslate">ld_so_aix</code> program.</p>
<p dir="auto">I needed to include all the library flags in order for the linker to recognize the libraries for OpenBLAS among other packages.</p>
<p dir="auto">Please let me know if you need the full run log.</p>
<p dir="auto">I will continue to investigate on how we can eliminate this particular flag without breaking anything else.</p>
<p dir="auto">Special thanks to the AIX Toolkit's team to help narrow this down a bit - <a href="https://www.ibm.com/developerworks/community/forums/html/topic?id=28814b7c-93a3-4cd3-9f42-94f36620013f#547a941b-11c6-4f5b-aa6c-b8208b7b86bb" rel="nofollow">https://www.ibm.com/developerworks/community/forums/html/topic?id=28814b7c-93a3-4cd3-9f42-94f36620013f#547a941b-11c6-4f5b-aa6c-b8208b7b86bb</a></p>
<p dir="auto">Update:  Added LDFLAGS as I forgot to include that -- required for AIX to recognize gomp and other packages when linking.</p>
<p dir="auto">This is a follow up of discussions in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="495747794" data-permission-text="Title is private" data-url="https://github.com/scipy/scipy/issues/10844" data-hovercard-type="pull_request" data-hovercard-url="/scipy/scipy/pull/10844/hovercard" href="https://github.com/scipy/scipy/pull/10844">#10844</a>.</p>
<p dir="auto"><strong>Describe the solution you'd like</strong><br>
All sampling methods in <code class="notranslate">scipy.stats</code> are using <code class="notranslate">random_state</code> which is a <code class="notranslate">np.random.Generator</code> (for new code). But this <code class="notranslate">numpy</code> generator is not aware of dimensions. Also, the new <code class="notranslate">scipy.stats.qmc</code> allow to generate samples efficiently in n-dimensions. It would be nice to bridge the gap between the two.</p>
<p dir="auto">Currently there is a <code class="notranslate">qmc.MultivariateNormalQMC</code>. Instead of duplicating this for other distributions, a solution could be to make the QMC engines inherit from <code class="notranslate">np.random.BitGenerator</code>. We could then use the new QMC engines with all the existing distributions.</p>
<p dir="auto"><strong>Describe alternatives you've considered</strong></p>
<ol dir="auto">
<li>Solution using a <code class="notranslate">BitGenerator</code>: Seemingly, it must be done in Cython. Otherwise I saw that there was a wrapper around <code class="notranslate">BitGenerator</code>, but this is not available in <code class="notranslate">numpy</code>... <a href="https://bashtage.github.io/randomgen/bit_generators/userbitgenerator.html" rel="nofollow">https://bashtage.github.io/randomgen/bit_generators/userbitgenerator.html</a> from <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/bashtage/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/bashtage">@bashtage</a>. This is working but the underlying <code class="notranslate">numpy</code> code is not aware of dimensions (<a href="https://github.com/numpy/numpy/blob/e4feb7027e397925d220a10dd58b581b87ca1fec/numpy/random/_generator.pyx#L3562-L3568">https://github.com/numpy/numpy/blob/e4feb7027e397925d220a10dd58b581b87ca1fec/numpy/random/_generator.pyx#L3562-L3568</a>).</li>
</ol>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="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):
        &quot;&quot;&quot;Generate the next &quot;raw&quot; value, which is 64 bits&quot;&quot;&quot;
        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)"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">numpy</span>.<span class="pl-s1">random</span> <span class="pl-k">import</span> <span class="pl-v">Generator</span>
<span class="pl-k">from</span> <span class="pl-s1">randomgen</span> <span class="pl-k">import</span> <span class="pl-v">UserBitGenerator</span>


<span class="pl-k">class</span> <span class="pl-v">SobolNP</span>:
    <span class="pl-k">def</span> <span class="pl-en">__init__</span>(<span class="pl-s1">self</span>, <span class="pl-s1">state</span>):
        <span class="pl-s1">self</span>.<span class="pl-s1">_next_64</span> <span class="pl-c1">=</span> <span class="pl-c1">None</span>
        <span class="pl-s1">self</span>.<span class="pl-s1">engine</span> <span class="pl-c1">=</span> <span class="pl-v">Sobol</span>(<span class="pl-s1">d</span><span class="pl-c1">=</span><span class="pl-c1">1</span>, <span class="pl-s1">scramble</span><span class="pl-c1">=</span><span class="pl-c1">False</span>, <span class="pl-s1">seed</span><span class="pl-c1">=</span><span class="pl-s1">state</span>)

    <span class="pl-k">def</span> <span class="pl-en">random_raw</span>(<span class="pl-s1">self</span>):
        <span class="pl-s">"""Generate the next "raw" value, which is 64 bits"""</span>
        <span class="pl-k">return</span> <span class="pl-en">int</span>(<span class="pl-s1">self</span>.<span class="pl-s1">engine</span>.<span class="pl-en">random</span>() <span class="pl-c1">*</span> <span class="pl-c1">2</span><span class="pl-c1">**</span><span class="pl-c1">64</span>)  <span class="pl-c"># although Sobol uses 30 bits...</span>

    <span class="pl-en">@<span class="pl-s1">property</span></span>
    <span class="pl-k">def</span> <span class="pl-en">next_64</span>(<span class="pl-s1">self</span>):
        <span class="pl-k">def</span> <span class="pl-en">_next_64</span>(<span class="pl-s1">void_p</span>):
            <span class="pl-k">return</span> <span class="pl-s1">self</span>.<span class="pl-en">random_raw</span>()

        <span class="pl-s1">self</span>.<span class="pl-s1">_next_64</span> <span class="pl-c1">=</span> <span class="pl-s1">_next_64</span>
        <span class="pl-k">return</span> <span class="pl-s1">_next_64</span>


<span class="pl-c"># examples</span>
<span class="pl-s1">prng</span> <span class="pl-c1">=</span> <span class="pl-v">SobolNP</span>(<span class="pl-c1">1234</span>)
<span class="pl-s1">sobol_bit_generator</span> <span class="pl-c1">=</span> <span class="pl-v">UserBitGenerator</span>(<span class="pl-s1">prng</span>.<span class="pl-s1">next_64</span>, <span class="pl-c1">64</span>)
<span class="pl-s1">gen</span> <span class="pl-c1">=</span> <span class="pl-v">Generator</span>(<span class="pl-s1">sobol_bit_generator</span>)
<span class="pl-s1">gen</span>.<span class="pl-en">random</span>(<span class="pl-c1">8</span>)</pre></div>
<ol start="2" dir="auto">
<li>Another solution would be to mock <code class="notranslate">np.random.Generator</code>: I am using <code class="notranslate">__getattr__</code> to mock calls to the distributions. So calls like <code class="notranslate">random_state.uniform(...)</code>. Seems to be working and n-dimensions is ok too.</li>
</ol>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="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)"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">numpy</span>.<span class="pl-s1">random</span> <span class="pl-k">import</span> <span class="pl-v">Generator</span>
<span class="pl-k">import</span> <span class="pl-s1">scipy</span>.<span class="pl-s1">stats</span> <span class="pl-k">as</span> <span class="pl-s1">stats</span>
<span class="pl-k">from</span> <span class="pl-s1">functools</span> <span class="pl-k">import</span> <span class="pl-s1">partial</span>


<span class="pl-k">class</span> <span class="pl-v">ScipyGenerator</span>:

    <span class="pl-en">@<span class="pl-s1">property</span></span>
    <span class="pl-k">def</span> <span class="pl-en">__class__</span>(<span class="pl-s1">self</span>):
        <span class="pl-k">return</span> <span class="pl-v">Generator</span>

    <span class="pl-k">def</span> <span class="pl-en">__init__</span>(<span class="pl-s1">self</span>, <span class="pl-s1">d</span>):
        <span class="pl-s1">self</span>.<span class="pl-s1">qrng</span> <span class="pl-c1">=</span> <span class="pl-s1">stats</span>.<span class="pl-s1">qmc</span>.<span class="pl-v">Sobol</span>(<span class="pl-s1">d</span><span class="pl-c1">=</span><span class="pl-s1">d</span>, <span class="pl-s1">scramble</span><span class="pl-c1">=</span><span class="pl-c1">False</span>)

    <span class="pl-k">def</span> <span class="pl-en">rvs</span>(<span class="pl-s1">self</span>, <span class="pl-c1">*</span><span class="pl-s1">args</span>, <span class="pl-s1">dist</span>, <span class="pl-c1">**</span><span class="pl-s1">kwargs</span>):
        <span class="pl-s1">args</span> <span class="pl-c1">=</span> <span class="pl-en">list</span>(<span class="pl-s1">args</span>)
        <span class="pl-s1">size</span> <span class="pl-c1">=</span> <span class="pl-s1">kwargs</span>.<span class="pl-en">pop</span>(<span class="pl-s">'size'</span>, <span class="pl-c1">None</span>)
        <span class="pl-k">if</span> <span class="pl-s1">size</span> <span class="pl-c1">is</span> <span class="pl-c1">None</span>:
            <span class="pl-s1">size</span> <span class="pl-c1">=</span> <span class="pl-s1">args</span>.<span class="pl-en">pop</span>(<span class="pl-c1">0</span>)
        <span class="pl-s1">sample</span> <span class="pl-c1">=</span> <span class="pl-s1">self</span>.<span class="pl-s1">qrng</span>.<span class="pl-en">random</span>(<span class="pl-s1">size</span>)
        <span class="pl-k">return</span> <span class="pl-en">dist</span>(<span class="pl-c1">*</span><span class="pl-s1">args</span>, <span class="pl-c1">**</span><span class="pl-s1">kwargs</span>).<span class="pl-en">ppf</span>(<span class="pl-s1">sample</span>)

    <span class="pl-k">def</span> <span class="pl-en">__getattr__</span>(<span class="pl-s1">self</span>, <span class="pl-s1">attr</span>):
        <span class="pl-k">try</span>:
            <span class="pl-s1">dist</span> <span class="pl-c1">=</span> <span class="pl-en">getattr</span>(<span class="pl-s1">stats</span>, <span class="pl-s1">attr</span>)
            <span class="pl-k">return</span> <span class="pl-en">partial</span>(<span class="pl-s1">self</span>.<span class="pl-s1">rvs</span>, <span class="pl-s1">dist</span><span class="pl-c1">=</span><span class="pl-s1">dist</span>)
        <span class="pl-k">except</span> <span class="pl-v">AttributeError</span> <span class="pl-k">as</span> <span class="pl-s1">err_np</span>:
            <span class="pl-k">raise</span> <span class="pl-s1">err_np</span>


<span class="pl-c"># examples</span>
<span class="pl-s1">random_state</span> <span class="pl-c1">=</span> <span class="pl-v">ScipyGenerator</span>(<span class="pl-s1">d</span><span class="pl-c1">=</span><span class="pl-c1">2</span>)
<span class="pl-en">isinstance</span>(<span class="pl-s1">random_state</span>, <span class="pl-v">Generator</span>)
<span class="pl-s1">random_state</span>.<span class="pl-en">uniform</span>(<span class="pl-c1">8</span>)
<span class="pl-s1">random_state</span>.<span class="pl-en">gamma</span>(<span class="pl-c1">2</span>, <span class="pl-s1">size</span><span class="pl-c1">=</span><span class="pl-c1">8</span>)</pre></div>