Karim Belabas on Tue, 24 Jun 2025 14:03:52 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: a remark / feature request about listpop


* M. F. Hasler [2025-06-20 23:55]:
> Allowing negative indices to get elements counted from the back would
> also be a -- probably even better -- alternative, of course.

This would slow down all accesses to GP array elements, as well as
making obvious mistakes (non-positive array indices) harder to detect.

The use case is not important enough for this.

> [I sometimes saw (and maybe even used, unofficially) a construction like
> v[-1..-1][1], but I think that's terrible and really looks desperate.
> It could for example be motivated if you don't have the vector stored in a
> variable v, but just, e.g., the result of a function, like
> computeSolution(args)[-1..-1][1]  to get just the last element. But yes,
> it's terrible, I agree.]

I'm happy to report that v[-1..-1][1] is about 35% slower than v[#v].
Don't use that, ever. :-)

About not storing the return value in a variable, you have a point.

But (unless you're extra careful) chances are the GP memory model are
already forcing copies of that return value somewhere in the function body.
The best place to handle such concerns is currently computeSolution() itself:

  computeSolution(args, only_last = 0)

etc.

Cheers,

    K.B.

P.S. To have an idea of what GP is *really* doing behind the scenes, you
can have fun with

  install(closure_disassemble, vG);

For instance, these two trivial routines are functionally equivalent:

  weightedmean(x, y)=
  { my(N = sum(i=1,#y, y[i]));
    sum(i=1,#x, x[i]*y[i]) / N * 1.;
  }
  weightedmean2(x, y)=
    sum(i=1,#x, x[i]*y[i]) / sum(i=1,#y, y[i]) * 1.;

But the GP compiler currently handles the second one in a (marginally) more
efficient way:

? closure_disassemble(weightedmean2)
00001	getargs		2
00002	pushstoi	1
00003	pushlex		-2
00004	calllong	#_
00005	stoi
00006	pushgen		1
00007	pushlong	0
00008	callgen		sum
00009	pushstoi	1
00010	pushlex		-1
00011	calllong	#_
00012	stoi
00013	pushgen		2
00014	pushlong	0
00015	callgen		sum
00016	callgen2	_/_
00017	pushreal	3
00018	callgen2	_*_

? closure_disassemble(weightedmean)
00001	getargs		2
00002	newframe	1      \\ extra
00003	pushstoi	1
00004	pushlex		-2
00005	calllong	#_
00006	stoi
00007	pushgen		1
00008	pushlong	0
00009	callgen		sum
00010	storelex	-1     \\ extra
00011	pushstoi	1
00012	pushlex		-3
00013	calllong	#_
00014	stoi
00015	pushgen		2
00016	pushlong	0
00017	callgen		sum
00018	pushlex		-1     \\ extra
00019	callgen2	_/_
00020	pushreal	3
00021	callgen2	_*_

-- 
Pr. Karim Belabas, U. Bordeaux, Vice-président en charge du Numérique
Institut de Mathématiques de Bordeaux UMR 5251 - (+33) 05 40 00 29 77
http://www.math.u-bordeaux.fr/~kbelabas/