reductions are so freakishly slow :(
the any() code takes 12 us, while a median of 5000 doubles takes 55us in total (including all the weighted partition stuff)

using count_nonzero is better for large q, but still slower than the python loop for len(q) < 10
nonzero wins if len(q) > 10, while median does not get much more expensive, I guess a threshold could make sense

```
In [3]: q = np.array([0.5])
In [4]: %timeit  ((q < 0).any() or (q > 1).any())
100000 loops, best of 3: 12.1 µs per loop

In [5]: %timeit  ((q < 0) | (q > 1)).any()
100000 loops, best of 3: 8.79 µs per loop

In [6]: %timeit  np.count_nonzero((q < 0) | (q > 1))
100000 loops, best of 3: 4.8 µs per loop


In [7]: def f(q):
   ...:     for i in range(q.size):
   ...:        if q[i] < 0. or q[i] > 100.:
   ...:           pass
   ...: 

In [8]: %timeit f(q)
1000000 loops, best of 3: 841 ns per loop
```