Skip to content

Commit 46a4491

Browse files
author
maechler
committed
matrix(x, n,k) now warns more often when length(x) does not "match" n*k
git-svn-id: https://svn.r-project.org/R/trunk@80272 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent e403156 commit 46a4491

File tree

3 files changed

+35
-26
lines changed

3 files changed

+35
-26
lines changed

doc/NEWS.Rd

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@
1717
of \R to that provided by \samp{libcurl}.
1818
}
1919
}
20+
21+
\subsection{NEW FEATURES}{
22+
\itemize{
23+
\item \code{matrix(x, n,m)} now warns in more cases where
24+
\code{length(x)} is larger than \code{n * m}; suggested by Abby
25+
Spurdle and Wolfgang Huber in Feb.2021 on R-devel (mailing list).
26+
}
27+
}
28+
2029
\subsection{BUG FIXES}{
2130
\itemize{
2231
\item \code{qnbinom(p, size, mu)} for large \code{size/mu} is correct

src/main/array.c

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* R : A Computer Language for Statistical Data Analysis
3-
* Copyright (C) 1998-2020 The R Core Team
3+
* Copyright (C) 1998-2021 The R Core Team
44
* Copyright (C) 2002-2015 The R Foundation
55
* Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka
66
*
@@ -63,6 +63,7 @@ SEXP GetColNames(SEXP dimnames)
6363
return R_NilValue;
6464
}
6565

66+
// .Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow), missing(ncol)))
6667
SEXP attribute_hidden do_matrix(SEXP call, SEXP op, SEXP args, SEXP rho)
6768
{
6869
SEXP vals, ans, snr, snc, dimnames;
@@ -116,36 +117,33 @@ SEXP attribute_hidden do_matrix(SEXP call, SEXP op, SEXP args, SEXP rho)
116117
if (lendat > INT_MAX) error("data is too long");
117118
nr = (int) lendat;
118119
} else if (miss_nr) {
119-
if (lendat > (double) nc * INT_MAX) error("data is too long");
120-
// avoid division by zero
121-
if (nc == 0) {
122-
if (lendat) error(_("nc = 0 for non-null data"));
123-
else nr = 0;
124-
} else
120+
if (lendat > (double) nc * INT_MAX) error("data is too long"); // incl lendat > nc == 0
121+
if (nc == 0) // as lendat <= nc, have lendat == 0
122+
nr = 0;
123+
else
125124
nr = (int) ceil((double) lendat / (double) nc);
126125
} else if (miss_nc) {
127-
if (lendat > (double) nr * INT_MAX) error("data is too long");
128-
// avoid division by zero
129-
if (nr == 0) {
130-
if (lendat) error(_("nr = 0 for non-null data"));
131-
else nc = 0;
132-
} else
126+
if (lendat > (double) nr * INT_MAX) error("data is too long"); // incl lendat > nr == 0
127+
if (nr == 0) // then lendat == 0
128+
nc = 0;
129+
else
133130
nc = (int) ceil((double) lendat / (double) nr);
134131
}
135132

136-
if(lendat > 0) {
133+
if (lendat > 0) {
137134
R_xlen_t nrc = (R_xlen_t) nr * nc;
138-
if (lendat > 1 && nrc % lendat != 0) {
135+
if (lendat > 1 && (nrc % lendat) != 0) { // ==> nrc > 0
139136
if (((lendat > nr) && (lendat / nr) * nr != lendat) ||
140137
((lendat < nr) && (nr / lendat) * lendat != nr))
141138
warning(_("data length [%d] is not a sub-multiple or multiple of the number of rows [%d]"), lendat, nr);
142139
else if (((lendat > nc) && (lendat / nc) * nc != lendat) ||
143140
((lendat < nc) && (nc / lendat) * lendat != nc))
144141
warning(_("data length [%d] is not a sub-multiple or multiple of the number of columns [%d]"), lendat, nc);
142+
else if (nrc != lendat)
143+
warning(_("data length differs from size of matrix: [%d != %d x %d]"), lendat, nr, nc);
145144
}
146-
else if ((lendat > 1) && (nrc == 0)){
147-
warning(_("data length exceeds size of matrix"));
148-
}
145+
else if (lendat > 1 && nrc == 0) // for now *not* warning for e.g., matrix(NA, 0, 4)
146+
warning(_("non-empty data for zero-extent matrix"));
149147
}
150148

151149
#ifndef LONG_VECTOR_SUPPORT
@@ -289,11 +287,8 @@ SEXP allocArray(SEXPTYPE mode, SEXP dims)
289287

290288
SEXP DropDims(SEXP x)
291289
{
292-
SEXP dims, dimnames, newnames = R_NilValue;
293-
int i, n, ndims;
294-
295290
PROTECT(x);
296-
dims = getAttrib(x, R_DimSymbol);
291+
SEXP dims = getAttrib(x, R_DimSymbol);
297292

298293
/* Check that dropping will actually do something. */
299294
/* (1) Check that there is a "dim" attribute. */
@@ -302,19 +297,21 @@ SEXP DropDims(SEXP x)
302297
UNPROTECT(1); /* x */
303298
return x;
304299
}
305-
ndims = LENGTH(dims);
300+
301+
int ndims = LENGTH(dims);
306302
int *dim = INTEGER(dims); // used several times
307303

308304
/* (2) Check whether there are redundant extents */
309-
n = 0;
305+
int i, n = 0;
310306
for (i = 0; i < ndims; i++)
311307
if (dim[i] != 1) n++;
312308
if (n == ndims) {
313309
UNPROTECT(1); /* x */
314310
return x;
315311
}
316312

317-
PROTECT(dimnames = getAttrib(x, R_DimNamesSymbol));
313+
SEXP dimnames = PROTECT(getAttrib(x, R_DimNamesSymbol)),
314+
newnames = R_NilValue;
318315
if (n <= 1) {
319316
/* We have reduced to a vector result.
320317
If that has length one, it is ambiguous which dimnames to use,
@@ -811,7 +808,7 @@ static void matprod(double *x, int nrx, int ncx,
811808
F77_CALL(dgemv)(transT, &nry, &ncy, &one, y,
812809
&nry, x, &ione, &zero, z, &ione FCONE);
813810
else /* matrix-matrix or outer product */
814-
F77_CALL(dgemm)(transN, transN, &nrx, &ncy, &ncx, &one, x,
811+
F77_CALL(dgemm)(transN, transN, &nrx, &ncy, &ncx, &one, x,
815812
&nrx, y, &nry, &zero, z, &nrx FCONE FCONE);
816813
}
817814

tests/reg-tests-2.Rout.save

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,9 @@ attr(,"scaled:scale")
812812
> ## ts
813813
> # Ensure working arithmetic for 'ts' objects :
814814
> z <- ts(matrix(1:900, 100, 3), start = c(1961, 1), frequency = 12)
815+
Warning message:
816+
In matrix(1:900, 100, 3) :
817+
data length differs from size of matrix: [900 != 100 x 3]
815818
> stopifnot(z == z)
816819
> stopifnot(z-z == 0)
817820
>

0 commit comments

Comments
 (0)