Am 02.01.2021 um 18:46 schrieb Riccardo (Jack) Lucchetti:
 On Sat, 2 Jan 2021, Sven Schreiber wrote:
> Perhaps we should add this to 'extra' as well?
 Sure, why not. Here's a version that encompasses the present discussion:
 
Oh my god, we're both officially old and forgetful. The duplicate()
function (written by someone whose initials are J.L.) was added to
'extra' in 2018 already!
(Along with the eliminate function.)
However, there's also a use case for an efficient multiplication with
the _transpose_ of the duplication matrix (so applied to a matrix with
n^2 rows). So maybe we can extend the existing function with a boolean
parameter switch to do that - the default of course being the current
behavior. Here's a prototype of a possible algorithm that could be
integrated there:
<hansl>
function matrix dupT(const matrix A, bool trans[0])
     if trans
         n2 = rows(A)
         n = sqrt(n2)
         if n != round(n)
             funcerr "Input must have a square number of rows"
         endif
         matrix m = mshape(seq(1,n2)', n,n)
         ## first part (first of the 1s in each row)
         matrix ix = vech(m')
         # (watch transpose here, gretl's non-standard vech definition)
         matrix part1 = A[ix, ]
         ## second part (the duplicate 1s that lead to summation here)
         m[diag]  = 0
         m[lower] = 0
         ix = vech(m) 	# (again implicit transp-of-transp here!)
         matrix Azerotop = zeros(1,cols(A)) | A
         matrix part2 = Azerotop[ix + ones(rows(ix)), ]
         matrix out = part1 + part2
     else
         matrix out = duplicate(A)
     endif
     return out
end function
</hansl>
My superficial benchmarking shows that this doesn't attain your nice
100x speedup for the non-transpose case, but I do get a factor 10x
compared to explicit (but not totally naive) creation of the duplication
matrix and multiplying with the transpose.
cheers
sven