Martin Maechler
2014-Aug-07 08:51 UTC
[Rd] RFC: diag(x, n) not preserving integer and logical x
This is not at all something new(*). As maintainer of the Matrix package, I don't like this inconsistency of base R's diag(). We have had the following -- forever, almost surely inherited from S and S+ : diag(x) preserves the storage mode of x for 'complex' and 'double' precision, but converts integer and logicals to double : > storage.mode(x <- 1i + 1:7); storage.mode(diag(x)) [1] "complex" [1] "complex" > storage.mode(x <- 0 + 1:7); storage.mode(diag(x)) [1] "double" [1] "double" > storage.mode(x <- 1:7); storage.mode(diag(x)) [1] "integer" [1] "double" > storage.mode(x <- 1:7 > 3); storage.mode(diag(x)) [1] "logical" [1] "double" and so it is actually a bit cumbersome (and a memory waste in the case of large matrices) to create a diagonal integer or logical matrix. The help page does not mention the current behavior, though you may say it alludes to the fact that logicals are treated as 0/1 implicitly (**) If I change this behavior such that logical and integer x are preserved, make check-all which includes all checks, including those of all recommended packages (including Matrix!) successfully runs through; so at least base + Recommended R never relies on the current behavior, nor should any "well programmed" R code ... Hence my proposal, somewhat tentative for now, to change this diag(.) behavior. Martin Maechler *) and possibly something we "can not" change in R, because too much code implicitely may be depending on it, but now I hope we can still... **) BTW, also including the somewhat amusing case of diag(c("A","B")).
Duncan Murdoch
2014-Aug-08 14:51 UTC
[Rd] RFC: diag(x, n) not preserving integer and logical x
On 07/08/2014, 4:51 AM, Martin Maechler wrote:> This is not at all something new(*). As maintainer of the > Matrix package, I don't like this inconsistency of base R's diag(). > We have had the following -- forever, almost surely inherited > from S and S+ : > > diag(x) preserves the storage mode of x for 'complex' and > 'double' precision, but converts integer and logicals to double : > > > storage.mode(x <- 1i + 1:7); storage.mode(diag(x)) > [1] "complex" > [1] "complex" > > storage.mode(x <- 0 + 1:7); storage.mode(diag(x)) > [1] "double" > [1] "double" > > > storage.mode(x <- 1:7); storage.mode(diag(x)) > [1] "integer" > [1] "double" > > storage.mode(x <- 1:7 > 3); storage.mode(diag(x)) > [1] "logical" > [1] "double" > > and so it is actually a bit cumbersome (and a memory waste in > the case of large matrices) to create a diagonal integer or > logical matrix. > > The help page does not mention the current behavior, though you > may say it alludes to the fact that logicals are treated as 0/1 > implicitly (**) >I think the change to preserve integer makes sense, but preserving logical does not. A diagonal matrix has zeros off the diagonal, and they are not logical. Having diag() sometimes return a matrix with FALSE off the diagonal just looks wrong. Duncan Murdoch> If I change this behavior such that logical and integer x are > preserved, > > make check-all > > which includes all checks, including those of all recommended > packages (including Matrix!) successfully runs through; so at > least base + Recommended R never relies on the current > behavior, nor should any "well programmed" R code ... > > Hence my proposal, somewhat tentative for now, > to change this diag(.) behavior. > > Martin Maechler > > *) and possibly something we "can not" change in R, because too > much code implicitely may be depending on it, but now I hope > we can still... > > **) BTW, also including the somewhat amusing case of diag(c("A","B")). > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >