from copy import copy
def preduce(vl, vec, pred):
- vec = copy(vec) # must not damage predicate
+ vec = copy(vec)
pred = copy(pred) # must not damage predicate
step = 1
print(" start", step, pred, vec)
print(" row", step, pred, vec)
return vec
+
def preducei(vl, vec, pred):
+ vec = copy(vec)
pred = copy(pred) # must not damage predicate
step = 1
- ix = list(range(vl))
+ ix = list(range(vl)) # indices move rather than copy data
print(" start", step, pred, vec)
while step < vl:
step *= 2
if pred[ci] and other_pred:
vec[ci] += vec[oi]
elif other_pred:
- ix[i] = oi
+ ix[i] = oi # leave data in-place, copy index instead
pred[ci] |= other_pred
print(" row", step, pred, vec, ix)
+ return vec
+
+
+def preduce_yield(vl, vec, pred):
+ pred = copy(pred) # must not damage predicate
+ step = 1
+ ix = list(range(vl))
+ while step < vl:
+ step *= 2
+ for i in range(0, vl, step):
+ other = i + step // 2
+ ci = ix[i]
+ oi = ix[other] if other < vl else None
+ other_pred = other < vl and pred[oi]
+ if pred[ci] and other_pred:
+ yield ci, oi
+ elif other_pred:
+ ix[i] = oi
+ pred[ci] |= other_pred
+
+
+def preduce_y(vl, vec, pred):
+ for i, other in preduce_yield(vl, vec, pred):
+ vec[i] += vec[other]
+
if __name__ == '__main__':
vec = [1, 2, 3, 4, 9, 5, 6]
print (vec)
res = preduce(len(vec), vec, prd)
print (res)
- preducei(len(vec), vec, prd)
+ res2 = preducei(len(vec), vec, prd)
+ print (res2)
+ print ()
+ preduce_y(len(vec), vec, prd)
+ print (vec)
+ print ()
+ assert vec == res2
+
+ vec = [1, 2, 3, 4, 9, 5, 6]
+ prd = [1, 0, 0, 1, 1, 0, 1]
+ print (vec)
+ res = preduce(len(vec), vec, prd)
+ print (res)
+ res2 = preducei(len(vec), vec, prd)
+ print (res2)
+ print ()
+ preduce_y(len(vec), vec, prd)
print (vec)
print ()
- assert vec == res
+ assert vec == res2