Re: increment slowdown
"Ruud H.G. van Tol" <[email protected]> Tue, 10 Mar 2026 15:30:12 +0100
| Newsgroups | gmane.comp.mathematics.pari.user |
|---|---|
| Message-ID | <[email protected]> |
On 2026-03-10 14:58, Bill Allombert wrote: > On Tue, Mar 10, 2026 at 02:05:38PM +0100, Ruud H.G. van Tol wrote: >> oeis.A005228: >> >> ? lista1(len)= my(r=List(1), d=1); while(#r<len, setsearch(r, d++) && d++; >> listput(~r, r[#r]+d)); Vec(r); >> [...] >> >> ? lista2(len)= my(r=List(1), d=1); while(#r<len, d++; setsearch(r, d) && >> d++; listput(~r, r[#r]+d)); Vec(r); >> [...] >> >> The first variant has the d++ inside the setsearch() call, and is much >> slower. > > Yes, this is a known limitation of the copy optimiser. > It is not able to check that d++ does not modify r, so it copies r. > > Imagine this example > r=[1,1,2];vecsearch(r,r[1]--) > the correct result is 0. > but > ? r=[1,1,2];r[1]--;vecsearch(r,r[1]) > %14 = 1 > > In general, to avoid this limitation, do not use the return values of x++ and > x+= , x-= , x*= etc. Understood. That is indeed a tricky one to optimize for. Maybe https://en.wikipedia.org/wiki/Peephole_optimization Solving this, would make existing code run considerably faster, so is a nice challenge. Another slightly faster variant: ? lista4(len)= my(d=1, r=List([1])); while(#r<len, setsearch(r, d+1) && d++; listput(~r, r[#r]+d++)); Vec(r); ? lista4(10001)[-10..-1] cpu time = 11 ms, real time = 11 ms. %20 = [50793733, 50803858, 50813984, 50824111, 50834239, 50844368, 50854498, 50864629, 50874761, 50884894] And a variant that sets d only once per iteration: ? lista5(len)= my(d=1, r=List([1])); while(#r<len, d+=2-!setsearch(r, d+1); listput(~r, r[#r]+d)); Vec(r); ? lista5(10001)[-10..-1] cpu time = 12 ms, real time = 12 ms. %30 = [50793733, 50803858, 50813984, 50824111, 50834239, 50844368, 50854498, 50864629, 50874761, 50884894] A way out might also be to support setsearch(~r, ...). -- Ruud