Por que a função diag é tão lenta? [no R 3.2.0 ou anterior]

Eu estava olhando para os benchmarks emesta respostae queria compará-los comdiag (usado em uma resposta diferente). Infelizmente, parece quediag leva idades:

nc  <- 1e4
set.seed(1)
m <- matrix(sample(letters,nc^2,replace=TRUE), ncol = nc)

microbenchmark(
  diag = diag(m),
  cond = m[row(m)==col(m)],
  vec  = m[(1:nc-1L)*nc+1:nc],
  mat  = m[cbind(1:nc,1:nc)],
times=10)

Comentários: Eu testei estes comidentical. Peguei "cond" de uma das respostas paraesta pergunta de lição de casa. Os resultados são semelhantes com uma matriz de números inteiros,1:26 ao invés deletters.

Resultados:

Unit: microseconds
 expr         min          lq         mean       median          uq         max neval
 diag  604343.469  629819.260  710371.3320  706842.3890  793144.019  837115.504    10
 cond 3862039.512 3985784.025 4175724.0390 4186317.5260 4312493.742 4617117.706    10
  vec     317.088     329.017     432.9099     350.1005     629.460     651.376    10
  mat     272.147     292.953     441.7045     345.9400     637.506     706.860    10

É apenas uma operação de subconjunto de matrizes, então não sei por que há tanta sobrecarga. Olhando dentro da função, vejo algumas verificações e depoisc(m)[v], Ondev é o mesmo vetor usado no benchmark "vec". Cronometrando esses dois ...

v <- (1:nc-1L)*nc+1:nc
microbenchmark(diaglike=c(m)[v],vec=m[v])
# Unit: microseconds
#      expr        min          lq        mean     median          uq        max neval
#  diaglike 579224.436 664853.7450 720372.8105 712649.706 767281.5070 931976.707   100
#       vec    334.843    339.8365    568.7808    646.799    663.5825   1445.067   100

... parece que encontrei meu culpado. Então, a nova variação na minha pergunta é:Por que existe uma aparentemente desnecessária e muito demoradac nodiag?

questionAnswers(1)

yourAnswerToTheQuestion