Your add works for this calculation, but it needs to be reused, so non-zero values propagate. I don’t see how your calculation is generated [ 1. 1. 2. 1. 3. 1. 4. 1. 5. 1.] .
In [619]: fib=np.zeros(10,int);fib[:2]=1 In [620]: for _ in range(10): ...: np.add(fib[:-2], fib[1:-1], out=fib[2:]) ...: print(fib) ...: [1 1 2 1 0 0 0 0 0 0] # ** [1 1 2 3 3 1 0 0 0 0] [1 1 2 3 5 6 4 1 0 0] [ 1 1 2 3 5 8 11 10 5 1] [ 1 1 2 3 5 8 13 19 21 15] ...
(edit - Note that the first np.add acts as if it were fully buffered. Compare the result with ** with both objects and floating point arrays. I am using version 1.13.1 on Py3.)
Or to highlight good values at every step
In [623]: fib=np.zeros(20,int);fib[:2]=1 In [624]: for i in range(10): ...: np.add(fib[:-2], fib[1:-1], out=fib[2:]) ...: print(fib[:(i+2)]) ...: [1 1] [1 1 2] [1 1 2 3] [1 1 2 3 5] [1 1 2 3 5 8] [ 1 1 2 3 5 8 13] [ 1 1 2 3 5 8 13 21] [ 1 1 2 3 5 8 13 21 34] [ 1 1 2 3 5 8 13 21 34 55] [ 1 1 2 3 5 8 13 21 34 55 89]
fib[2:] = fib[:-2]+fib[1:-1] does the same.
As described in the documentation for ufunc.at , operations like np.add use buffering, even with the out parameter. Therefore, while they interact in level C code, they do not accumulate; that is, the results of step ith not used in step i+1 .
add.at can be used to execute unbuffered a[i] += b . This is useful when indexes contain duplicates. but this does not allow feedback from the changed values a to b . Therefore, it is not useful here.
There is also add.accumulate (aka np.cumsum ), which may be useful for certain iterative definitions. But it is difficult to apply in general cases.
cumprod (multiply accumulation) can work with qmatrix approach
Numpy matrix_power function gives incorrect results for large exponents
Use np.matrix to define qmatrix , so * multiply means matrix product (as opposed to elementary):
In [647]: qmatrix = numpy.matrix([[1, 1], [1, 0]])
Fill the matrix of objects with copies (actually pointers) to this matrix.
In [648]: M = np.empty(10, object) In [649]: M[:] = [qmatrix for _ in range(10)]
Apply cumprod and extract one element from each matrix.
In [650]: m1=np.cumprod(M) In [651]: m1 Out[651]: array([matrix([[1, 1], [1, 0]]), matrix([[2, 1], [1, 1]]), matrix([[3, 2], [2, 1]]), matrix([[5, 3], [3, 2]]), matrix([[8, 5], [5, 3]]), matrix([[13, 8], [ 8, 5]]), matrix([[21, 13], [13, 8]]), matrix([[34, 21], [21, 13]]), matrix([[55, 34], [34, 21]]), matrix([[89, 55], [55, 34]])], dtype=object) In [652]: [x[0,1] for x in m1] Out[652]: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
The linked answer uses numpy.linalg.matrix_power , which also runs duplicate matrix products. For one power, matrix_power is faster, but for an entire power range, cumprod is faster.