I would like for example uint
types to hit 0 rather than wrap-around on subtraction - is it possible to alter this behaviour from python without writing a new c-type? (For example for subtracting two uint8
numpy arrays) ?
There is no integer overflow/underflow detection in Numpy, but you could test for this yourself either before or after the calculation. m0
does this after the calculation, as shown below.
import numpy as np
import timeit
a = np.arange(0, 251, 50, dtype=np.uint8)
b = np.array(a[::-1])
def m0(a, b):
x = (a-b)
x[b>a] = 0
def m1(a, b):
c = (a.astype(np.int16) - b).clip(0, 255).astype(np.uint8)
m0(a, b)
m1(a, b)
a = np.array(a.repeat(1000)) # repeat and copy (copy since I don't remember whether repeat is an indexing trick)
b = np.array(b.repeat(1000))
N = 1000000
print timeit.timeit("m0(a, b)", setup="from __main__ import m0, m1, a, b", number=N)
# 1.7734951973
print timeit.timeit("m1(a, b)", setup="from __main__ import m0, m1, a, b", number=N)
# 3.6973798275
I also compare the times to @Qlaus's approach, which is also good, and they are comparable (you shouldn't take the 50% speed gain here very seriously, but instead test them both for your specific application). On the other hand, the subtraction itself takes about 0.6
of the times above, so with this removed, the m0
solution is about 3x faster. But on the other hand, usually if you do one operation that will underflow or overflow you will be doing several, and for those cases, using int16
wil likely be fastest. In the end, testing for your actual case will be the best approach to optimizing.
Numpy does not do overflow handling on array types. See this discussion or this related question.
If you do not care about speed so much you could save your results in an int16
first and then clip it and write it back to an uint8
array.
import numpy as np
a = np.arange(5, dtype=np.uint8)
b = np.ones(5, dtype=np.uint8) * 2
print(a-b) # [254 255 0 1 2]
c = (a.astype(np.int16) - b).clip(0, 255).astype(np.uint8)
print(c) # [0, 0, 0, 1, 2]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With