>>>>> Radford Neal <radf...@cs.toronto.edu> >>>>> on Mon, 23 Jun 2014 11:24:35 -0400 writes:
> A new version of pqR is now available at pqR-project.org, which fixes > several bugs that are also present in the latest R Core patch release > (r66002). A number of bugs found previously during pqR development > are also unfixed in the latest R Core release. Here is the list of > these bugs that are unfixed in r66002 (including documentation > deficiencies), taken from the pqR bug fix and documentation update > sections of the pqR NEWS file (pqR-project.org/NEWS.txt): Duncan Murdoch has already mentioned that "unfixed bugs" is a strong wording... I'm commenting on one subtopic only: [.........] > o Fixed the following bug (also present in R-2.15.0 and R-3.0.2): > x <- t(5) > print (x %*% c(3,4)) > print (crossprod(5,c(3,4))) > The call of crossprod produced an error, whereas the > corresponding use of %*% does not. > In pqR-2013-12-29, this bug also affected the expression t(5) %*% > c(3,4), since it is converted to the equivalent of > crossprod(5,c(3,4)). (I'm not getting this last para... but that may be unimportant) [........] > o Fixed the following bug (also present in R-2.15.0 and R-3.0.2): > v <- c(1,2) > m <- matrix(c(3,4),1,2) > print(t(m)%*%v) > print(crossprod(m,v)) > in which crossprod gave an error rather than produce the answer > for the corresponding use of %*%. Both cases above concern %*%, crossprod() {and also tcrossprod()}, and always when one at least one operand is a vector... As S and R's terminology has always been mathematically correct and "knows" that a vector is not a 1-row matrix or 1-column matrix (which some people call row-vector and column-vector), R has indeed much more freedom to be lenient in how to promote vectors to matrices, and it has always done so tolerantly for some cases of "%*%", but even there is room for discussion, see below. Since about January, I have a corresponding entry in the TODO file of the Matrix package (which I maintain), and I (at least partly) agree with you, that we should *consider* changing the current behavior. The following is from my corresponding R script : ### NOTA BENE: vector %*% Matrix _and_ Matrix %*% vector : ### --------- ----------------- ----------------- ## The k-vector is treated as (1,k)-matrix *or* (k,1)-matrix ## on both sides whenever it "helps fit" the matrix dimensions: and one kind of reasoning would go to say that crossprod() and tcrossprod() should do the same. This would even make more cases work than (I think) your proposal. However, one can argue that the current behavior is quite consistent {there is more than one kind of consistency here; in this case it's the consistency of underlying C code IIRC}, and not strictly a bug. It is something which I am grateful you bring up for discussion, and I'm happy to settle here. Note that the Matrix package and many other packages that implement matrix multiplication methods, should then also follow the new semantic, and so this is typically rather for R-devel than R-patched. Note that from your first case example, one could also argue -- at least from my 'NOTA BENE' rule above -- that 5 %*% 3:4 should work, since 5 %*% rbind(3:4) does work, but 5 %*% cbind(3:4) does not. So you see, there are quite a few cases one could discuss, and have reasons pro and contra some of the changes. I will be too busy till the end of 'useR! 2014' and would want quite a bit of further thoughts before making a quick decision, notably about the cases I have in the appended products.Rout Martin Maechler, (ETH Zurich and R Core team) ---------------
### NOTA BENE: vector %*% Matrix _and_ Matrix %*% vector : ### --------- ----------------- ----------------- ## The k-vector is treated as (1,k)-matrix *or* (k,1)-matrix ## on both sides whenever it "helps fit" the matrix dimensions: ## --------------- %*% --------------------------------------------- ## --------- v . v ----------------------------- ## We *could* consider allowing more even here: could argue ## from the 'NOTA BENE' above that > 5 %*% 3:4 ## should work, since > 5 %*% rbind(3:4) ## does work, but > 5 %*% cbind(3:4) ## does not. ## --------- v . M ----------------------------- > 1:3 %*% matrix(1:12, 3,4) ## (1, n) if n == nrow(.) [,1] [,2] [,3] [,4] [1,] 14 32 50 68 > 1:4 %*% matrix(1:12, 3,4) Error in 1:4 %*% matrix(1:12, 3, 4) : non-conformable arguments No suitable frames for recover() > 1:4 %*% matrix(1:5, 1,5) ## (n, 1) if nrow(.) == 1 [,1] [,2] [,3] [,4] [,5] [1,] 1 2 3 4 5 [2,] 2 4 6 8 10 [3,] 3 6 9 12 15 [4,] 4 8 12 16 20 ## --------- M . v ----------------------------- > matrix(1:4, 3,4) %*% 1:4 ## (n, 1) if n == ncol(.) [,1] [1,] 26 [2,] 28 [3,] 26 > matrix(1:4, 3,4) %*% 1:3 Error in matrix(1:4, 3, 4) %*% 1:3 : non-conformable arguments No suitable frames for recover() > matrix(1:3, 3,1) %*% 1:3 ## (1, n) if ncol(.) == 1 [,1] [,2] [,3] [1,] 1 2 3 [2,] 2 4 6 [3,] 3 6 9 > ## --------------- crossprod ------------------------------------- ## --------- M . v ----------------------------- > crossprod(matrix(1:4, 3,4), 1:3) ## (n, 1) if n == nrow(.) [,1] [1,] 14 [2,] 12 [3,] 14 [4,] 20 > crossprod(matrix(1:4, 3,4), 1:4) Error in crossprod(matrix(1:4, 3, 4), 1:4) : non-conformable arguments > m <- matrix(1:2, 1,2); v <- 1:3 > crossprod(m,v) ##>>> *could* be nice and use (1,n) as nrow(.)==1 <<< Error in crossprod(m, v) : non-conformable arguments ##>> after all, crossprod(m,v) "should"== t(m) %*% v and that does work: > t(m) %*% v [,1] [,2] [,3] [1,] 1 2 3 [2,] 2 4 6 > ## --------- v . M ----------------------------- > crossprod(1:3, matrix(1:4, 3,4)) ## (1, n) if n == nrow(.) [,1] [,2] [,3] [,4] [1,] 14 12 14 20 > crossprod(1:4, matrix(1:4, 3,4)) Error in crossprod(1:4, matrix(1:4, 3, 4)) : non-conformable arguments > crossprod(1:3, matrix(1:3, 1,3)) ##>>> *could* be nice and use (n,1) as > nrow(.)==1 <<< Error in crossprod(1:3, matrix(1:3, 1, 3)) : non-conformable arguments > crossprod(v,m) Error in crossprod(v, m) : non-conformable arguments ##>> "as" v %*% m does work and v could have been A[1,] instead of A[1, , drop=TRUE] > ## --------------- tcrossprod ------------------------------------- ## --------- M . v ----------------------------- > tcrossprod(matrix(1:4, 3,4), 1:3) Error in tcrossprod(matrix(1:4, 3, 4), 1:3) : non-conformable arguments > tcrossprod(matrix(1:4, 3,4), 1:4) Error in tcrossprod(matrix(1:4, 3, 4), 1:4) : non-conformable arguments > tcrossprod(matrix(1:4, 1,4), 1:4)##>>> *could* be nice and use (n,1) as > ncol(.) == 1 <<< Error in tcrossprod(matrix(1:4, 1, 4), 1:4) : non-conformable arguments ##>> "as" m %*% v does work and v could have been A[1,] instead of A[1, , drop=TRUE] > matrix(1:4, 1,4) %*% 1:4 [,1] [1,] 30 > tcrossprod(matrix(1:2, 2,1), 1:5) # v -> c(1, n) as ncol(.) == 1 [,1] [,2] [,3] [,4] [,5] [1,] 1 2 3 4 5 [2,] 2 4 6 8 10 > ## --------- v . M ----------------------------- > tcrossprod(1:4, matrix(1:4, 3,4)) # v -> c(1, n) as n == ncol(.) [,1] [,2] [,3] [1,] 26 28 26 > tcrossprod(1:3, matrix(1:4, 3,4)) Error in tcrossprod(1:3, matrix(1:4, 3, 4)) : non-conformable arguments > tcrossprod(1:3, matrix(1:3, 3,1)) # v -> c(n, 1) as ncol(.) == 1 [,1] [,2] [,3] [1,] 1 2 3 [2,] 2 4 6 [3,] 3 6 9 > ##--------------------------- vector x vector ----------------- > 1:3 %*% 1:3 ## must have same n [,1] [1,] 14 > crossprod(1:3, 1:3) ## must have same n [,1] [1,] 14 > tcrossprod(1:3, 1:4) ## can have different length [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 2 4 6 8 [3,] 3 6 9 12
______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel