@@ -185,7 +185,7 @@ cdef balanced_list_prod(L, Py_ssize_t offset, Py_ssize_t count, Py_ssize_t cutof
185
185
return balanced_list_prod(L, offset, k, cutoff) * balanced_list_prod(L, offset + k, count - k, cutoff)
186
186
187
187
188
- cpdef iterator_prod(L, z = None ):
188
+ cpdef iterator_prod(L, z = None , bint multiply = True ):
189
189
"""
190
190
Attempt to do a balanced product of an arbitrary and unknown length
191
191
sequence (such as a generator). Intermediate multiplications are always
@@ -207,11 +207,18 @@ cpdef iterator_prod(L, z=None):
207
207
sage: L = [NonAssociative(label) for label in 'abcdef']
208
208
sage: iterator_prod(L)
209
209
(((a*b)*(c*d))*(e*f))
210
+
211
+ When ``multiply=False``, the items are added up instead (however this
212
+ interface should not be used directly, use :func:`balanced_sum` instead)::
213
+
214
+ sage: iterator_prod((1..5), multiply=False)
215
+ 15
210
216
"""
211
- # TODO: declaring sub_prods as a list should speed much of this up.
217
+ cdef list sub_prods
212
218
L = iter (L)
213
219
if z is None :
214
- sub_prods = [next(L)] * 10
220
+ sub_prods = [next(L)] * 10 # only take one element from L, the rest are just placeholders
221
+ # the list size can be dynamically increased later
215
222
else :
216
223
sub_prods = [z] * 10
217
224
@@ -232,17 +239,26 @@ cpdef iterator_prod(L, z=None):
232
239
else :
233
240
# for even i we multiply the stack down
234
241
# by the number of factors of 2 in i
235
- x = sub_prods[tip] * x
242
+ if multiply:
243
+ x = sub_prods[tip] * x
244
+ else :
245
+ x = sub_prods[tip] + x
236
246
for j from 1 <= j < 64 :
237
247
if i & (1 << j):
238
248
break
239
249
tip -= 1
240
- x = sub_prods[tip] * x
250
+ if multiply:
251
+ x = sub_prods[tip] * x
252
+ else :
253
+ x = sub_prods[tip] + x
241
254
sub_prods[tip] = x
242
255
243
256
while tip > 0 :
244
257
tip -= 1
245
- sub_prods[tip] *= sub_prods[tip + 1 ]
258
+ if multiply:
259
+ sub_prods[tip] *= sub_prods[tip + 1 ]
260
+ else :
261
+ sub_prods[tip] += sub_prods[tip + 1 ]
246
262
247
263
return sub_prods[0 ]
248
264
@@ -366,14 +382,7 @@ def balanced_sum(x, z=None, Py_ssize_t recursion_cutoff=5):
366
382
if type (x) is not list and type (x) is not tuple :
367
383
368
384
if PyGen_Check(x):
369
- # lazy list, do lazy product
370
- try :
371
- sum = copy(next(x)) if z is None else z + next(x)
372
- for a in x:
373
- sum += a
374
- return sum
375
- except StopIteration :
376
- x = []
385
+ return iterator_prod(x, z, multiply = False )
377
386
else :
378
387
try :
379
388
return x.sum()
@@ -405,8 +414,8 @@ cdef balanced_list_sum(L, Py_ssize_t offset, Py_ssize_t count, Py_ssize_t cutoff
405
414
406
415
- ``L`` -- the terms (MUST be a tuple or list)
407
416
- ``off`` -- offset in the list from which to start
408
- - ``count`` -- how many terms in the sum
409
- - ``cutoff`` -- the minimum count to recurse on. Must be at least 2
417
+ - ``count`` -- how many terms in the sum. Must be positive
418
+ - ``cutoff`` -- the minimum count to recurse on. Must be at least 2
410
419
411
420
OUTPUT:
412
421
0 commit comments