| Ruud H.G. van Tol on Tue, 10 Mar 2026 15:30:22 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| Re: increment slowdown |
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_optimizationSolving 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