The R Project SVN R

Rev

Rev 29864 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 29864 Rev 30691
1
/*
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
4
 *  Copyright (C) 1998-2001   The R Development Core Team
4
 *  Copyright (C) 1998-2001   The R Development Core Team
5
 *  Copyright (C) 2002--2004  The R Foundation
5
 *  Copyright (C) 2002--2004  The R Foundation
6
 *
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
10
 *  (at your option) any later version.
11
 *
11
 *
12
 *  This program is distributed in the hope that it will be useful,
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
15
 *  GNU General Public License for more details.
16
 *
16
 *
17
 *  A copy of the GNU General Public License is available via WWW at
17
 *  A copy of the GNU General Public License is available via WWW at
18
 *  http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
18
 *  http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
19
 *  writing to the Free Software Foundation, Inc., 59 Temple Place,
19
 *  writing to the Free Software Foundation, Inc., 59 Temple Place,
20
 *  Suite 330, Boston, MA  02111-1307  USA.
20
 *  Suite 330, Boston, MA  02111-1307  USA.
21
 */
21
 */
22
 
22
 
23
#ifdef HAVE_CONFIG_H
23
#ifdef HAVE_CONFIG_H
24
#include <config.h>
24
#include <config.h>
25
#endif
25
#endif
26
 
26
 
27
#include <Defn.h>
27
#include <Defn.h>
28
#include <Rmath.h>
28
#include <Rmath.h>
29
#include <R_ext/RS.h>
29
#include <R_ext/RS.h>
30
#include <R_ext/Applic.h> /* for dgemm */
30
#include <R_ext/Applic.h> /* for dgemm */
31
 
31
 
32
/* "GetRowNames" and "GetColNames" are utility routines which
32
/* "GetRowNames" and "GetColNames" are utility routines which
33
 * locate and return the row names and column names from the
33
 * locate and return the row names and column names from the
34
 * dimnames attribute of a matrix.  They are useful because
34
 * dimnames attribute of a matrix.  They are useful because
35
 * old versions of R used pair-based lists for dimnames
35
 * old versions of R used pair-based lists for dimnames
36
 * whereas recent versions use vector based lists.
36
 * whereas recent versions use vector based lists.
37
 
37
 
38
 * These are now very old, plus
38
 * These are now very old, plus
39
 * ``When the "dimnames" attribute is
39
 * ``When the "dimnames" attribute is
40
 *   grabbed off an array it is always adjusted to be a vector.''
40
 *   grabbed off an array it is always adjusted to be a vector.''
41
*/
41
*/
42
SEXP GetRowNames(SEXP dimnames)
42
SEXP GetRowNames(SEXP dimnames)
43
{
43
{
44
    if (TYPEOF(dimnames) == VECSXP)
44
    if (TYPEOF(dimnames) == VECSXP)
45
	return VECTOR_ELT(dimnames, 0);
45
	return VECTOR_ELT(dimnames, 0);
46
    else
46
    else
47
	return R_NilValue;
47
	return R_NilValue;
48
}
48
}
49
 
49
 
50
SEXP GetColNames(SEXP dimnames)
50
SEXP GetColNames(SEXP dimnames)
51
{
51
{
52
    if (TYPEOF(dimnames) == VECSXP)
52
    if (TYPEOF(dimnames) == VECSXP)
53
	return VECTOR_ELT(dimnames, 1);
53
	return VECTOR_ELT(dimnames, 1);
54
    else
54
    else
55
	return R_NilValue;
55
	return R_NilValue;
56
}
56
}
57
 
57
 
58
SEXP do_matrix(SEXP call, SEXP op, SEXP args, SEXP rho)
58
SEXP do_matrix(SEXP call, SEXP op, SEXP args, SEXP rho)
59
{
59
{
60
    SEXP vals, snr, snc;
60
    SEXP vals, snr, snc;
61
    int nr, nc, byrow, lendat;
61
    int nr, nc, byrow, lendat;
62
 
62
 
63
    checkArity(op, args);
63
    checkArity(op, args);
64
    vals = CAR(args);
64
    vals = CAR(args);
65
    snr = CADR(args);
65
    snr = CADR(args);
66
    snc = CADDR(args);
66
    snc = CADDR(args);
67
    byrow = asInteger(CADR(CDDR(args)));
67
    byrow = asInteger(CADR(CDDR(args)));
68
 
68
 
69
    /* R wrapper does as.vector
69
    /* R wrapper does as.vector
70
    if (isVector(vals) || isList(vals)) {
70
    if (isVector(vals) || isList(vals)) {
71
	if (length(vals) < 0)  (sic! cannot happen)
71
	if (length(vals) < 0)  (sic! cannot happen)
72
	   errorcall(call, "argument has length zero");
72
	   errorcall(call, "argument has length zero");
73
    }
73
    }
74
    else errorcall(call, "invalid matrix element type"); */
74
    else errorcall(call, "invalid matrix element type"); */
75
 
75
 
76
    if (!isNumeric(snr) || !isNumeric(snc))
76
    if (!isNumeric(snr) || !isNumeric(snc))
77
	error("non-numeric matrix extent");
77
	error("non-numeric matrix extent");
78
 
78
 
79
    lendat = length(vals);
79
    lendat = length(vals);
80
    nr = asInteger(snr);
80
    nr = asInteger(snr);
81
    if (nr == NA_INTEGER) /* This is < 0 */
81
    if (nr == NA_INTEGER) /* This is < 0 */
82
	error("matrix: invalid nrow value (too large or NA)");
82
	error("matrix: invalid nrow value (too large or NA)");
83
    if (nr < 0)
83
    if (nr < 0)
84
	error("matrix: invalid nrow value (< 0)");
84
	error("matrix: invalid nrow value (< 0)");
85
    nc = asInteger(snc);
85
    nc = asInteger(snc);
86
    if (nc < 0)
86
    if (nc < 0)
87
	error("matrix: invalid ncol value (< 0)");
87
	error("matrix: invalid ncol value (< 0)");
88
    if (nc == NA_INTEGER)
88
    if (nc == NA_INTEGER)
89
	error("matrix: invalid ncol value (too large or NA)");
89
	error("matrix: invalid ncol value (too large or NA)");
90
    if (nc < 0)
90
    if (nc < 0)
91
	error("matrix: invalid ncol value (< 0)");
91
	error("matrix: invalid ncol value (< 0)");
92
 
92
 
93
    if(lendat > 0 ) {
93
    if(lendat > 0 ) {
94
	if (lendat > 1 && (nr * nc) % lendat != 0) {
94
	if (lendat > 1 && (nr * nc) % lendat != 0) {
95
	    if (((lendat > nr) && (lendat / nr) * nr != lendat) ||
95
	    if (((lendat > nr) && (lendat / nr) * nr != lendat) ||
96
		((lendat < nr) && (nr / lendat) * lendat != nr))
96
		((lendat < nr) && (nr / lendat) * lendat != nr))
97
		warning("data length [%d] is not a sub-multiple or multiple of the number of rows [%d] in matrix", lendat, nr);
97
		warning("data length [%d] is not a sub-multiple or multiple of the number of rows [%d] in matrix", lendat, nr);
98
	    else if (((lendat > nc) && (lendat / nc) * nc != lendat) ||
98
	    else if (((lendat > nc) && (lendat / nc) * nc != lendat) ||
99
		     ((lendat < nc) && (nc / lendat) * lendat != nc))
99
		     ((lendat < nc) && (nc / lendat) * lendat != nc))
100
		warning("data length [%d] is not a sub-multiple or multiple of the number of columns [%d] in matrix", lendat, nc);
100
		warning("data length [%d] is not a sub-multiple or multiple of the number of columns [%d] in matrix", lendat, nc);
101
	}
101
	}
102
	else if ((lendat > 1) && (nr * nc == 0)){
102
	else if ((lendat > 1) && (nr * nc == 0)){
103
	    warning("data length exceeds size of matrix");
103
	    warning("data length exceeds size of matrix");
104
	}
104
	}
105
    }
105
    }
106
 
106
 
107
    if ((double)nr * (double)nc > INT_MAX)
107
    if ((double)nr * (double)nc > INT_MAX)
108
	error("matrix: too many elements specified");
108
	error("matrix: too many elements specified");
109
 
109
 
110
    PROTECT(snr = allocMatrix(TYPEOF(vals), nr, nc));
110
    PROTECT(snr = allocMatrix(TYPEOF(vals), nr, nc));
111
    if(lendat) {
111
    if(lendat) {
112
	if (isVector(vals))
112
	if (isVector(vals))
113
	    copyMatrix(snr, vals, byrow);
113
	    copyMatrix(snr, vals, byrow);
114
	else
114
	else
115
	    copyListMatrix(snr, vals, byrow);
115
	    copyListMatrix(snr, vals, byrow);
116
    } else if (isVector(vals)) { /* fill with NAs */
116
    } else if (isVector(vals)) { /* fill with NAs */
117
	int i, j;
117
	int i, j;
118
	switch(TYPEOF(vals)) {
118
	switch(TYPEOF(vals)) {
119
	case STRSXP:
119
	case STRSXP:
120
	    for (i = 0; i < nr; i++)
120
	    for (i = 0; i < nr; i++)
121
		for (j = 0; j < nc; j++)
121
		for (j = 0; j < nc; j++)
122
		    SET_STRING_ELT(snr, i + j * nr, NA_STRING);
122
		    SET_STRING_ELT(snr, i + j * nr, NA_STRING);
123
	    break;
123
	    break;
124
	case LGLSXP:
124
	case LGLSXP:
125
	    for (i = 0; i < nr; i++)
125
	    for (i = 0; i < nr; i++)
126
		for (j = 0; j < nc; j++)
126
		for (j = 0; j < nc; j++)
127
		    LOGICAL(snr)[i + j * nr] = NA_LOGICAL;
127
		    LOGICAL(snr)[i + j * nr] = NA_LOGICAL;
128
	    break;
128
	    break;
129
	case INTSXP:
129
	case INTSXP:
130
	    for (i = 0; i < nr; i++)
130
	    for (i = 0; i < nr; i++)
131
		for (j = 0; j < nc; j++)
131
		for (j = 0; j < nc; j++)
132
		    INTEGER(snr)[i + j * nr] = NA_INTEGER;
132
		    INTEGER(snr)[i + j * nr] = NA_INTEGER;
133
	    break;
133
	    break;
134
	case REALSXP:
134
	case REALSXP:
135
	    for (i = 0; i < nr; i++)
135
	    for (i = 0; i < nr; i++)
136
		for (j = 0; j < nc; j++)
136
		for (j = 0; j < nc; j++)
137
		    REAL(snr)[i + j * nr] = NA_REAL;
137
		    REAL(snr)[i + j * nr] = NA_REAL;
138
	    break;
138
	    break;
139
	case CPLXSXP:
139
	case CPLXSXP:
140
	    {
140
	    {
141
		Rcomplex na_cmplx;
141
		Rcomplex na_cmplx;
142
		na_cmplx.r = NA_REAL;
142
		na_cmplx.r = NA_REAL;
143
		na_cmplx.i = 0;
143
		na_cmplx.i = 0;
144
		for (i = 0; i < nr; i++)
144
		for (i = 0; i < nr; i++)
145
		    for (j = 0; j < nc; j++)
145
		    for (j = 0; j < nc; j++)
146
			COMPLEX(snr)[i + j * nr] = na_cmplx;
146
			COMPLEX(snr)[i + j * nr] = na_cmplx;
147
	    }
147
	    }
148
	    break;
148
	    break;
-
 
149
	case RAWSXP:
-
 
150
	    for (i = 0; i < nr; i++)
-
 
151
		for (j = 0; j < nc; j++)
-
 
152
		    RAW(snr)[i + j * nr] = 0;
-
 
153
	    break;
149
	}
154
	}
150
    }
155
    }
151
    UNPROTECT(1);
156
    UNPROTECT(1);
152
    return snr;
157
    return snr;
153
}
158
}
154
 
159
 
155
 
160
 
156
SEXP allocMatrix(SEXPTYPE mode, int nrow, int ncol)
161
SEXP allocMatrix(SEXPTYPE mode, int nrow, int ncol)
157
{
162
{
158
    SEXP s, t;
163
    SEXP s, t;
159
    int n;
164
    int n;
160
 
165
 
161
    if (nrow < 0 || ncol < 0)
166
    if (nrow < 0 || ncol < 0)
162
	error("negative extents to matrix");
167
	error("negative extents to matrix");
163
    if ((double)nrow * (double)ncol > INT_MAX)
168
    if ((double)nrow * (double)ncol > INT_MAX)
164
	error("allocMatrix: too many elements specified");
169
	error("allocMatrix: too many elements specified");
165
    n = nrow * ncol;
170
    n = nrow * ncol;
166
    PROTECT(s = allocVector(mode, n));
171
    PROTECT(s = allocVector(mode, n));
167
    PROTECT(t = allocVector(INTSXP, 2));
172
    PROTECT(t = allocVector(INTSXP, 2));
168
    INTEGER(t)[0] = nrow;
173
    INTEGER(t)[0] = nrow;
169
    INTEGER(t)[1] = ncol;
174
    INTEGER(t)[1] = ncol;
170
    setAttrib(s, R_DimSymbol, t);
175
    setAttrib(s, R_DimSymbol, t);
171
    UNPROTECT(2);
176
    UNPROTECT(2);
172
    return s;
177
    return s;
173
}
178
}
174
 
179
 
175
 
180
 
176
SEXP allocArray(SEXPTYPE mode, SEXP dims)
181
SEXP allocArray(SEXPTYPE mode, SEXP dims)
177
{
182
{
178
    SEXP array;
183
    SEXP array;
179
    int i, n;
184
    int i, n;
180
    double dn;
185
    double dn;
181
 
186
 
182
    dn = n = 1;
187
    dn = n = 1;
183
    for (i = 0; i < LENGTH(dims); i++) {
188
    for (i = 0; i < LENGTH(dims); i++) {
184
	dn *= INTEGER(dims)[i];
189
	dn *= INTEGER(dims)[i];
185
	if(dn > INT_MAX)
190
	if(dn > INT_MAX)
186
	    error("allocArray: too many elements specified by dims");
191
	    error("allocArray: too many elements specified by dims");
187
	n *= INTEGER(dims)[i];
192
	n *= INTEGER(dims)[i];
188
    }
193
    }
189
 
194
 
190
    PROTECT(dims = duplicate(dims));
195
    PROTECT(dims = duplicate(dims));
191
    PROTECT(array = allocVector(mode, n));
196
    PROTECT(array = allocVector(mode, n));
192
    setAttrib(array, R_DimSymbol, dims);
197
    setAttrib(array, R_DimSymbol, dims);
193
    UNPROTECT(2);
198
    UNPROTECT(2);
194
    return array;
199
    return array;
195
}
200
}
196
 
201
 
197
/* DropDims strips away redundant dimensioning information. */
202
/* DropDims strips away redundant dimensioning information. */
198
/* If there is an appropriate dimnames attribute the correct */
203
/* If there is an appropriate dimnames attribute the correct */
199
/* element is extracted and attached to the vector as a names */
204
/* element is extracted and attached to the vector as a names */
200
/* attribute.  Note that this function mutates x. */
205
/* attribute.  Note that this function mutates x. */
201
/* Duplication should occur before this is called. */
206
/* Duplication should occur before this is called. */
202
 
207
 
203
SEXP DropDims(SEXP x)
208
SEXP DropDims(SEXP x)
204
{
209
{
205
    SEXP q, dims, dimnames, newnames = R_NilValue;
210
    SEXP q, dims, dimnames, newnames = R_NilValue;
206
    int i, n, ndims;
211
    int i, n, ndims;
207
 
212
 
208
    PROTECT(x);
213
    PROTECT(x);
209
    dims = getAttrib(x, R_DimSymbol);
214
    dims = getAttrib(x, R_DimSymbol);
210
    dimnames = getAttrib(x, R_DimNamesSymbol);
215
    dimnames = getAttrib(x, R_DimNamesSymbol);
211
 
216
 
212
    /* Check that dropping will actually do something. */
217
    /* Check that dropping will actually do something. */
213
    /* (1) Check that there is a "dim" attribute. */
218
    /* (1) Check that there is a "dim" attribute. */
214
 
219
 
215
    if (dims == R_NilValue) {
220
    if (dims == R_NilValue) {
216
	UNPROTECT(1);
221
	UNPROTECT(1);
217
	return x;
222
	return x;
218
    }
223
    }
219
    ndims = LENGTH(dims);
224
    ndims = LENGTH(dims);
220
 
225
 
221
    /* (2) Check whether there are redundant extents */
226
    /* (2) Check whether there are redundant extents */
222
    n = 0;
227
    n = 0;
223
    for (i = 0; i < ndims; i++)
228
    for (i = 0; i < ndims; i++)
224
	if (INTEGER(dims)[i] != 1) n++;
229
	if (INTEGER(dims)[i] != 1) n++;
225
    if (n == ndims) {
230
    if (n == ndims) {
226
	UNPROTECT(1);
231
	UNPROTECT(1);
227
	return x;
232
	return x;
228
    }
233
    }
229
 
234
 
230
    if (n <= 1) {
235
    if (n <= 1) {
231
	/* We have reduced to a vector result. */
236
	/* We have reduced to a vector result. */
232
	if (dimnames != R_NilValue) {
237
	if (dimnames != R_NilValue) {
233
	    n = length(dims);
238
	    n = length(dims);
234
	    if (TYPEOF(dimnames) == VECSXP) {
239
	    if (TYPEOF(dimnames) == VECSXP) {
235
		for (i = 0; i < n; i++) {
240
		for (i = 0; i < n; i++) {
236
		    if (INTEGER(dims)[i] != 1) {
241
		    if (INTEGER(dims)[i] != 1) {
237
			newnames = VECTOR_ELT(dimnames, i);
242
			newnames = VECTOR_ELT(dimnames, i);
238
			break;
243
			break;
239
		    }
244
		    }
240
		}
245
		}
241
	    }
246
	    }
242
	    else {
247
	    else {
243
		q = dimnames;
248
		q = dimnames;
244
		for (i = 0; i < n; i++) {
249
		for (i = 0; i < n; i++) {
245
		    if (INTEGER(dims)[i] != 1) {
250
		    if (INTEGER(dims)[i] != 1) {
246
			newnames = CAR(q);
251
			newnames = CAR(q);
247
			break;
252
			break;
248
		    }
253
		    }
249
		    q = CDR(q);
254
		    q = CDR(q);
250
		}
255
		}
251
	    }
256
	    }
252
	}
257
	}
253
	PROTECT(newnames);
258
	PROTECT(newnames);
254
	setAttrib(x, R_DimNamesSymbol, R_NilValue);
259
	setAttrib(x, R_DimNamesSymbol, R_NilValue);
255
	setAttrib(x, R_DimSymbol, R_NilValue);
260
	setAttrib(x, R_DimSymbol, R_NilValue);
256
	setAttrib(x, R_NamesSymbol, newnames);
261
	setAttrib(x, R_NamesSymbol, newnames);
257
	UNPROTECT(1);
262
	UNPROTECT(1);
258
    }
263
    }
259
    else {
264
    else {
260
	/* We have a lower dimensional array. */
265
	/* We have a lower dimensional array. */
261
	SEXP newdims, dnn, newnamesnames = R_NilValue;
266
	SEXP newdims, dnn, newnamesnames = R_NilValue;
262
	dnn = getAttrib(dimnames, R_NamesSymbol);
267
	dnn = getAttrib(dimnames, R_NamesSymbol);
263
	PROTECT(newdims = allocVector(INTSXP, n));
268
	PROTECT(newdims = allocVector(INTSXP, n));
264
	for (i = 0, n = 0; i < ndims; i++)
269
	for (i = 0, n = 0; i < ndims; i++)
265
	    if (INTEGER(dims)[i] != 1)
270
	    if (INTEGER(dims)[i] != 1)
266
		INTEGER(newdims)[n++] = INTEGER(dims)[i];
271
		INTEGER(newdims)[n++] = INTEGER(dims)[i];
267
	if (!isNull(dimnames)) {
272
	if (!isNull(dimnames)) {
268
	    int havenames = 0;
273
	    int havenames = 0;
269
	    for (i = 0; i < ndims; i++)
274
	    for (i = 0; i < ndims; i++)
270
		if (INTEGER(dims)[i] != 1 &&
275
		if (INTEGER(dims)[i] != 1 &&
271
		    VECTOR_ELT(dimnames, i) != R_NilValue)
276
		    VECTOR_ELT(dimnames, i) != R_NilValue)
272
		    havenames = 1;
277
		    havenames = 1;
273
	    if (havenames) {
278
	    if (havenames) {
274
		PROTECT(newnames = allocVector(VECSXP, n));
279
		PROTECT(newnames = allocVector(VECSXP, n));
275
		PROTECT(newnamesnames = allocVector(STRSXP, n));
280
		PROTECT(newnamesnames = allocVector(STRSXP, n));
276
		for (i = 0, n = 0; i < ndims; i++) {
281
		for (i = 0, n = 0; i < ndims; i++) {
277
		    if (INTEGER(dims)[i] != 1) {
282
		    if (INTEGER(dims)[i] != 1) {
278
			if(!isNull(dnn))
283
			if(!isNull(dnn))
279
			    SET_STRING_ELT(newnamesnames, n,
284
			    SET_STRING_ELT(newnamesnames, n,
280
					   STRING_ELT(dnn, i));
285
					   STRING_ELT(dnn, i));
281
			SET_VECTOR_ELT(newnames, n++, VECTOR_ELT(dimnames, i));
286
			SET_VECTOR_ELT(newnames, n++, VECTOR_ELT(dimnames, i));
282
		    }
287
		    }
283
		}
288
		}
284
	    }
289
	    }
285
	    else dimnames = R_NilValue;
290
	    else dimnames = R_NilValue;
286
	}
291
	}
287
	PROTECT(dimnames);
292
	PROTECT(dimnames);
288
	setAttrib(x, R_DimNamesSymbol, R_NilValue);
293
	setAttrib(x, R_DimNamesSymbol, R_NilValue);
289
	setAttrib(x, R_DimSymbol, newdims);
294
	setAttrib(x, R_DimSymbol, newdims);
290
	if (dimnames != R_NilValue)
295
	if (dimnames != R_NilValue)
291
	{
296
	{
292
	    if(!isNull(dnn))
297
	    if(!isNull(dnn))
293
		setAttrib(newnames, R_NamesSymbol, newnamesnames);
298
		setAttrib(newnames, R_NamesSymbol, newnamesnames);
294
	    setAttrib(x, R_DimNamesSymbol, newnames);
299
	    setAttrib(x, R_DimNamesSymbol, newnames);
295
	    UNPROTECT(2);
300
	    UNPROTECT(2);
296
	}
301
	}
297
	UNPROTECT(2);
302
	UNPROTECT(2);
298
    }
303
    }
299
    UNPROTECT(1);
304
    UNPROTECT(1);
300
    return x;
305
    return x;
301
}
306
}
302
 
307
 
303
SEXP do_drop(SEXP call, SEXP op, SEXP args, SEXP rho)
308
SEXP do_drop(SEXP call, SEXP op, SEXP args, SEXP rho)
304
{
309
{
305
    SEXP x, xdims;
310
    SEXP x, xdims;
306
    int i, n, shorten;
311
    int i, n, shorten;
307
 
312
 
308
    checkArity(op, args);
313
    checkArity(op, args);
309
    x = CAR(args);
314
    x = CAR(args);
310
    if ((xdims = getAttrib(x, R_DimSymbol)) != R_NilValue) {
315
    if ((xdims = getAttrib(x, R_DimSymbol)) != R_NilValue) {
311
	n = LENGTH(xdims);
316
	n = LENGTH(xdims);
312
	shorten = 0;
317
	shorten = 0;
313
	for (i = 0; i < n; i++)
318
	for (i = 0; i < n; i++)
314
	    if (INTEGER(xdims)[i] == 1) shorten = 1;
319
	    if (INTEGER(xdims)[i] == 1) shorten = 1;
315
	if (shorten) {
320
	if (shorten) {
316
	    if (NAMED(x)) x = duplicate(x);
321
	    if (NAMED(x)) x = duplicate(x);
317
	    x = DropDims(x);
322
	    x = DropDims(x);
318
	}
323
	}
319
    }
324
    }
320
    return x;
325
    return x;
321
}
326
}
322
 
327
 
323
/* Length of Primitive Objects */
328
/* Length of Primitive Objects */
324
 
329
 
325
SEXP do_length(SEXP call, SEXP op, SEXP args, SEXP rho)
330
SEXP do_length(SEXP call, SEXP op, SEXP args, SEXP rho)
326
{
331
{
327
    SEXP ans;
332
    SEXP ans;
328
    R_len_t len;
333
    R_len_t len;
329
 
334
 
330
    if (length(args) != 1)
335
    if (length(args) != 1)
331
	error("incorrect number of args to length");
336
	error("incorrect number of args to length");
332
 
337
 
333
    if( isObject(CAR(args)) && DispatchOrEval(call, op, "length", args,
338
    if( isObject(CAR(args)) && DispatchOrEval(call, op, "length", args,
334
					      rho, &ans, 0, 1))
339
					      rho, &ans, 0, 1))
335
      return(ans);
340
      return(ans);
336
 
341
 
337
    ans = allocVector(INTSXP, 1);
342
    ans = allocVector(INTSXP, 1);
338
    len = length(CAR(args));
343
    len = length(CAR(args));
339
    INTEGER(ans)[0] = (len < INT_MAX) ? len : NA_INTEGER;
344
    INTEGER(ans)[0] = (len < INT_MAX) ? len : NA_INTEGER;
340
    return ans;
345
    return ans;
341
}
346
}
342
 
347
 
343
 
348
 
344
SEXP do_rowscols(SEXP call, SEXP op, SEXP args, SEXP rho)
349
SEXP do_rowscols(SEXP call, SEXP op, SEXP args, SEXP rho)
345
{
350
{
346
    SEXP ans;
351
    SEXP ans;
347
    int i, j, nr, nc;
352
    int i, j, nr, nc;
348
 
353
 
349
    if (length(args) != 1)
354
    if (length(args) != 1)
350
	error("incorrect number of args to row/col");
355
	error("incorrect number of args to row/col");
351
    if (!isMatrix(CAR(args)))
356
    if (!isMatrix(CAR(args)))
352
	error("a matrix is required as arg to row/col");
357
	error("a matrix is required as arg to row/col");
353
 
358
 
354
    nr = nrows(CAR(args));
359
    nr = nrows(CAR(args));
355
    nc = ncols(CAR(args));
360
    nc = ncols(CAR(args));
356
 
361
 
357
    ans = allocMatrix(INTSXP, nr, nc);
362
    ans = allocMatrix(INTSXP, nr, nc);
358
 
363
 
359
    switch (PRIMVAL(op)) {
364
    switch (PRIMVAL(op)) {
360
    case 1:
365
    case 1:
361
	for (i = 0; i < nr; i++)
366
	for (i = 0; i < nr; i++)
362
	    for (j = 0; j < nc; j++)
367
	    for (j = 0; j < nc; j++)
363
		INTEGER(ans)[i + j * nr] = i + 1;
368
		INTEGER(ans)[i + j * nr] = i + 1;
364
	break;
369
	break;
365
    case 2:
370
    case 2:
366
	for (i = 0; i < nr; i++)
371
	for (i = 0; i < nr; i++)
367
	    for (j = 0; j < nc; j++)
372
	    for (j = 0; j < nc; j++)
368
		INTEGER(ans)[i + j * nr] = j + 1;
373
		INTEGER(ans)[i + j * nr] = j + 1;
369
	break;
374
	break;
370
    }
375
    }
371
    return ans;
376
    return ans;
372
}
377
}
373
 
378
 
374
static void matprod(double *x, int nrx, int ncx,
379
static void matprod(double *x, int nrx, int ncx,
375
		    double *y, int nry, int ncy, double *z)
380
		    double *y, int nry, int ncy, double *z)
376
{
381
{
377
    char *transa = "N", *transb = "N";
382
    char *transa = "N", *transb = "N";
378
    int i,  j, k;
383
    int i,  j, k;
379
    double one = 1.0, zero = 0.0, sum;
384
    double one = 1.0, zero = 0.0, sum;
380
    Rboolean have_na = FALSE;
385
    Rboolean have_na = FALSE;
381
 
386
 
382
    if (nrx > 0 && ncx > 0 && nry > 0 && ncy > 0) {
387
    if (nrx > 0 && ncx > 0 && nry > 0 && ncy > 0) {
383
	/* Don't trust the BLAS to handle NA/NaNs correctly: PR#4582
388
	/* Don't trust the BLAS to handle NA/NaNs correctly: PR#4582
384
	 * The test is only O(n) here
389
	 * The test is only O(n) here
385
	 */
390
	 */
386
	for (i = 0; i < nrx*ncx; i++)
391
	for (i = 0; i < nrx*ncx; i++)
387
	    if (ISNAN(x[i])) {have_na = TRUE; break;}
392
	    if (ISNAN(x[i])) {have_na = TRUE; break;}
388
	if (!have_na) 
393
	if (!have_na) 
389
	    for (i = 0; i < nry*ncy; i++)
394
	    for (i = 0; i < nry*ncy; i++)
390
		if (ISNAN(y[i])) {have_na = TRUE; break;}
395
		if (ISNAN(y[i])) {have_na = TRUE; break;}
391
	if (have_na) {
396
	if (have_na) {
392
	    for (i = 0; i < nrx; i++)
397
	    for (i = 0; i < nrx; i++)
393
		for (k = 0; k < ncy; k++) {
398
		for (k = 0; k < ncy; k++) {
394
		    sum = 0.0;
399
		    sum = 0.0;
395
		    for (j = 0; j < ncx; j++)
400
		    for (j = 0; j < ncx; j++)
396
			sum += x[i + j * nrx] * y[j + k * nry];
401
			sum += x[i + j * nrx] * y[j + k * nry];
397
		    z[i + k * nrx] = sum;
402
		    z[i + k * nrx] = sum;
398
		}
403
		}
399
	} else
404
	} else
400
	    F77_CALL(dgemm)(transa, transb, &nrx, &ncy, &ncx, &one,
405
	    F77_CALL(dgemm)(transa, transb, &nrx, &ncy, &ncx, &one,
401
			    x, &nrx, y, &nry, &zero, z, &nrx);
406
			    x, &nrx, y, &nry, &zero, z, &nrx);
402
    } else /* zero-extent operations should return zeroes */
407
    } else /* zero-extent operations should return zeroes */
403
	for(i = 0; i < nrx*ncy; i++) z[i] = 0;
408
	for(i = 0; i < nrx*ncy; i++) z[i] = 0;
404
}
409
}
405
 
410
 
406
#ifdef HAVE_DOUBLE_COMPLEX
411
#ifdef HAVE_DOUBLE_COMPLEX
407
/* ZGEMM - perform one of the matrix-matrix operations    */
412
/* ZGEMM - perform one of the matrix-matrix operations    */
408
/* C := alpha*op( A )*op( B ) + beta*C */
413
/* C := alpha*op( A )*op( B ) + beta*C */
409
extern void
414
extern void
410
F77_NAME(zgemm)(const char *transa, const char *transb, const int *m,
415
F77_NAME(zgemm)(const char *transa, const char *transb, const int *m,
411
		const int *n, const int *k, const Rcomplex *alpha,
416
		const int *n, const int *k, const Rcomplex *alpha,
412
		const Rcomplex *a, const int *lda,
417
		const Rcomplex *a, const int *lda,
413
		const Rcomplex *b, const int *ldb,
418
		const Rcomplex *b, const int *ldb,
414
		const Rcomplex *beta, Rcomplex *c, const int *ldc);
419
		const Rcomplex *beta, Rcomplex *c, const int *ldc);
415
#endif
420
#endif
416
 
421
 
417
static void cmatprod(Rcomplex *x, int nrx, int ncx,
422
static void cmatprod(Rcomplex *x, int nrx, int ncx,
418
		     Rcomplex *y, int nry, int ncy, Rcomplex *z)
423
		     Rcomplex *y, int nry, int ncy, Rcomplex *z)
419
{
424
{
420
#ifdef HAVE_DOUBLE_COMPLEX
425
#ifdef HAVE_DOUBLE_COMPLEX
421
    char *transa = "N", *transb = "N";
426
    char *transa = "N", *transb = "N";
422
    int i;
427
    int i;
423
    Rcomplex one, zero;
428
    Rcomplex one, zero;
424
 
429
 
425
    one.r = 1.0; one.i = zero.r = zero.i = 0.0;
430
    one.r = 1.0; one.i = zero.r = zero.i = 0.0;
426
    if (nrx > 0 && ncx > 0 && nry > 0 && ncy > 0) {
431
    if (nrx > 0 && ncx > 0 && nry > 0 && ncy > 0) {
427
        F77_CALL(zgemm)(transa, transb, &nrx, &ncy, &ncx, &one,
432
        F77_CALL(zgemm)(transa, transb, &nrx, &ncy, &ncx, &one,
428
			x, &nrx, y, &nry, &zero, z, &nrx);
433
			x, &nrx, y, &nry, &zero, z, &nrx);
429
    } else { /* zero-extent operations should return zeroes */
434
    } else { /* zero-extent operations should return zeroes */
430
	for(i = 0; i < nrx*ncy; i++) z[i].r = z[i].i = 0;
435
	for(i = 0; i < nrx*ncy; i++) z[i].r = z[i].i = 0;
431
    }
436
    }
432
#else
437
#else
433
    int i, j, k;
438
    int i, j, k;
434
    double xij_r, xij_i, yjk_r, yjk_i, sum_i, sum_r;
439
    double xij_r, xij_i, yjk_r, yjk_i, sum_i, sum_r;
435
 
440
 
436
    for (i = 0; i < nrx; i++)
441
    for (i = 0; i < nrx; i++)
437
	for (k = 0; k < ncy; k++) {
442
	for (k = 0; k < ncy; k++) {
438
	    z[i + k * nrx].r = NA_REAL;
443
	    z[i + k * nrx].r = NA_REAL;
439
	    z[i + k * nrx].i = NA_REAL;
444
	    z[i + k * nrx].i = NA_REAL;
440
	    sum_r = 0.0;
445
	    sum_r = 0.0;
441
	    sum_i = 0.0;
446
	    sum_i = 0.0;
442
	    for (j = 0; j < ncx; j++) {
447
	    for (j = 0; j < ncx; j++) {
443
		xij_r = x[i + j * nrx].r;
448
		xij_r = x[i + j * nrx].r;
444
		xij_i = x[i + j * nrx].i;
449
		xij_i = x[i + j * nrx].i;
445
		yjk_r = y[j + k * nry].r;
450
		yjk_r = y[j + k * nry].r;
446
		yjk_i = y[j + k * nry].i;
451
		yjk_i = y[j + k * nry].i;
447
		if (ISNAN(xij_r) || ISNAN(xij_i)
452
		if (ISNAN(xij_r) || ISNAN(xij_i)
448
		    || ISNAN(yjk_r) || ISNAN(yjk_i))
453
		    || ISNAN(yjk_r) || ISNAN(yjk_i))
449
		    goto next_ik;
454
		    goto next_ik;
450
		sum_r += (xij_r * yjk_r - xij_i * yjk_i);
455
		sum_r += (xij_r * yjk_r - xij_i * yjk_i);
451
		sum_i += (xij_r * yjk_i + xij_i * yjk_r);
456
		sum_i += (xij_r * yjk_i + xij_i * yjk_r);
452
	    }
457
	    }
453
	    z[i + k * nrx].r = sum_r;
458
	    z[i + k * nrx].r = sum_r;
454
	    z[i + k * nrx].i = sum_i;
459
	    z[i + k * nrx].i = sum_i;
455
	next_ik:
460
	next_ik:
456
	    ;
461
	    ;
457
	}
462
	}
458
#endif
463
#endif
459
}
464
}
460
 
465
 
461
static void symcrossprod(double *x, int nr, int nc, double *z)
466
static void symcrossprod(double *x, int nr, int nc, double *z)
462
{
467
{
463
    char *trans = "T", *uplo = "U";
468
    char *trans = "T", *uplo = "U";
464
    double one = 1.0, zero = 0.0;
469
    double one = 1.0, zero = 0.0;
465
    int i, j;
470
    int i, j;
466
    if (nr > 0 && nc > 0) {
471
    if (nr > 0 && nc > 0) {
467
        F77_CALL(dsyrk)(uplo, trans, &nc, &nr, &one, x, &nr, &zero, z, &nc);
472
        F77_CALL(dsyrk)(uplo, trans, &nc, &nr, &one, x, &nr, &zero, z, &nc);
468
	for (i = 1; i < nc; i++)
473
	for (i = 1; i < nc; i++)
469
	    for (j = 0; j < i; j++) z[i + nc *j] = z[j + nc * i];
474
	    for (j = 0; j < i; j++) z[i + nc *j] = z[j + nc * i];
470
    } else { /* zero-extent operations should return zeroes */
475
    } else { /* zero-extent operations should return zeroes */
471
	for(i = 0; i < nc*nc; i++) z[i] = 0;
476
	for(i = 0; i < nc*nc; i++) z[i] = 0;
472
    }
477
    }
473
 
478
 
474
}
479
}
475
 
480
 
476
static void crossprod(double *x, int nrx, int ncx,
481
static void crossprod(double *x, int nrx, int ncx,
477
		      double *y, int nry, int ncy, double *z)
482
		      double *y, int nry, int ncy, double *z)
478
{
483
{
479
    char *transa = "T", *transb = "N";
484
    char *transa = "T", *transb = "N";
480
    double one = 1.0, zero = 0.0;
485
    double one = 1.0, zero = 0.0;
481
    if (nrx > 0 && ncx > 0 && nry > 0 && ncy > 0) {
486
    if (nrx > 0 && ncx > 0 && nry > 0 && ncy > 0) {
482
        F77_CALL(dgemm)(transa, transb, &ncx, &ncy, &nrx, &one,
487
        F77_CALL(dgemm)(transa, transb, &ncx, &ncy, &nrx, &one,
483
			x, &nrx, y, &nry, &zero, z, &ncx);
488
			x, &nrx, y, &nry, &zero, z, &ncx);
484
    }
489
    }
485
    else { /* zero-extent operations should return zeroes */
490
    else { /* zero-extent operations should return zeroes */
486
	int i;
491
	int i;
487
	for(i = 0; i < ncx*ncy; i++) z[i] = 0;
492
	for(i = 0; i < ncx*ncy; i++) z[i] = 0;
488
    }
493
    }
489
}
494
}
490
 
495
 
491
static void ccrossprod(Rcomplex *x, int nrx, int ncx,
496
static void ccrossprod(Rcomplex *x, int nrx, int ncx,
492
		       Rcomplex *y, int nry, int ncy, Rcomplex *z)
497
		       Rcomplex *y, int nry, int ncy, Rcomplex *z)
493
{
498
{
494
    char *transa = "T", *transb = "N";
499
    char *transa = "T", *transb = "N";
495
    Rcomplex one, zero;
500
    Rcomplex one, zero;
496
 
501
 
497
    one.r = 1.0; one.i = zero.r = zero.i = 0.0;
502
    one.r = 1.0; one.i = zero.r = zero.i = 0.0;
498
    if (nrx > 0 && ncx > 0 && nry > 0 && ncy > 0) {
503
    if (nrx > 0 && ncx > 0 && nry > 0 && ncy > 0) {
499
        F77_CALL(zgemm)(transa, transb, &ncx, &ncy, &nrx, &one,
504
        F77_CALL(zgemm)(transa, transb, &ncx, &ncy, &nrx, &one,
500
			x, &nrx, y, &nry, &zero, z, &ncx);
505
			x, &nrx, y, &nry, &zero, z, &ncx);
501
    }
506
    }
502
    else { /* zero-extent operations should return zeroes */
507
    else { /* zero-extent operations should return zeroes */
503
	int i;
508
	int i;
504
	for(i = 0; i < ncx*ncy; i++) z[i].r = z[i].i = 0;
509
	for(i = 0; i < ncx*ncy; i++) z[i].r = z[i].i = 0;
505
    }
510
    }
506
}
511
}
507
/* "%*%" (op = 0)  or  crossprod (op = 1) : */
512
/* "%*%" (op = 0)  or  crossprod (op = 1) : */
508
SEXP do_matprod(SEXP call, SEXP op, SEXP args, SEXP rho)
513
SEXP do_matprod(SEXP call, SEXP op, SEXP args, SEXP rho)
509
{
514
{
510
    int ldx, ldy, nrx, ncx, nry, ncy, mode;
515
    int ldx, ldy, nrx, ncx, nry, ncy, mode;
511
    SEXP x = CAR(args), y = CADR(args), xdims, ydims, ans;
516
    SEXP x = CAR(args), y = CADR(args), xdims, ydims, ans;
512
    Rboolean sym;
517
    Rboolean sym;
513
 
518
 
514
    if(R_has_methods(op)) {
519
    if(R_has_methods(op)) {
515
      SEXP value;
520
      SEXP value;
516
      value = R_possible_dispatch(call, op, args, rho);
521
      value = R_possible_dispatch(call, op, args, rho);
517
      if(value) return value;
522
      if(value) return value;
518
    }
523
    }
519
 
524
 
520
    sym = isNull(y);
525
    sym = isNull(y);
521
    if (sym && (PRIMVAL(op) == 1)) y = x;
526
    if (sym && (PRIMVAL(op) == 1)) y = x;
522
    if ( !(isNumeric(x) || isComplex(x)) || !(isNumeric(y) || isComplex(y)) )
527
    if ( !(isNumeric(x) || isComplex(x)) || !(isNumeric(y) || isComplex(y)) )
523
	errorcall(call, "requires numeric matrix/vector arguments");
528
	errorcall(call, "requires numeric matrix/vector arguments");
524
 
529
 
525
    xdims = getAttrib(x, R_DimSymbol);
530
    xdims = getAttrib(x, R_DimSymbol);
526
    ydims = getAttrib(y, R_DimSymbol);
531
    ydims = getAttrib(y, R_DimSymbol);
527
    ldx = length(xdims);
532
    ldx = length(xdims);
528
    ldy = length(ydims);
533
    ldy = length(ydims);
529
 
534
 
530
    if (ldx != 2 && ldy != 2) {		/* x and y non-matrices */
535
    if (ldx != 2 && ldy != 2) {		/* x and y non-matrices */
531
	if (PRIMVAL(op) == 0) {
536
	if (PRIMVAL(op) == 0) {
532
	    nrx = 1;
537
	    nrx = 1;
533
	    ncx = LENGTH(x);
538
	    ncx = LENGTH(x);
534
	}
539
	}
535
	else {
540
	else {
536
	    nrx = LENGTH(x);
541
	    nrx = LENGTH(x);
537
	    ncx = 1;
542
	    ncx = 1;
538
	}
543
	}
539
	nry = LENGTH(y);
544
	nry = LENGTH(y);
540
	ncy = 1;
545
	ncy = 1;
541
    }
546
    }
542
    else if (ldx != 2) {		/* x not a matrix */
547
    else if (ldx != 2) {		/* x not a matrix */
543
	nry = INTEGER(ydims)[0];
548
	nry = INTEGER(ydims)[0];
544
	ncy = INTEGER(ydims)[1];
549
	ncy = INTEGER(ydims)[1];
545
	nrx = 0;
550
	nrx = 0;
546
	ncx = 0;
551
	ncx = 0;
547
	if (PRIMVAL(op) == 0) {
552
	if (PRIMVAL(op) == 0) {
548
	    if (LENGTH(x) == nry) {	/* x as row vector */
553
	    if (LENGTH(x) == nry) {	/* x as row vector */
549
		nrx = 1;
554
		nrx = 1;
550
		ncx = LENGTH(x);
555
		ncx = LENGTH(x);
551
	    }
556
	    }
552
	    else if (nry == 1) {	/* x as col vector */
557
	    else if (nry == 1) {	/* x as col vector */
553
		nrx = LENGTH(x);
558
		nrx = LENGTH(x);
554
		ncx = 1;
559
		ncx = 1;
555
	    }
560
	    }
556
	}
561
	}
557
	else {
562
	else {
558
	    if (LENGTH(x) == nry) {	/* x is a row vector */
563
	    if (LENGTH(x) == nry) {	/* x is a row vector */
559
		nrx = LENGTH(x);
564
		nrx = LENGTH(x);
560
		ncx = 1;
565
		ncx = 1;
561
	    }
566
	    }
562
	}
567
	}
563
    }
568
    }
564
    else if (ldy != 2) {		/* y not a matrix */
569
    else if (ldy != 2) {		/* y not a matrix */
565
	nrx = INTEGER(xdims)[0];
570
	nrx = INTEGER(xdims)[0];
566
	ncx = INTEGER(xdims)[1];
571
	ncx = INTEGER(xdims)[1];
567
	nry = 0;
572
	nry = 0;
568
	ncy = 0;
573
	ncy = 0;
569
	if (PRIMVAL(op) == 0) {
574
	if (PRIMVAL(op) == 0) {
570
	    if (LENGTH(y) == ncx) {	/* y as col vector */
575
	    if (LENGTH(y) == ncx) {	/* y as col vector */
571
		nry = LENGTH(y);
576
		nry = LENGTH(y);
572
		ncy = 1;
577
		ncy = 1;
573
	    }
578
	    }
574
	    else if (ncx == 1) {	/* y as row vector */
579
	    else if (ncx == 1) {	/* y as row vector */
575
		nry = 1;
580
		nry = 1;
576
		ncy = LENGTH(y);
581
		ncy = LENGTH(y);
577
	    }
582
	    }
578
	}
583
	}
579
	else {
584
	else {
580
	    if (LENGTH(y) == nrx) {	/* y is a row vector */
585
	    if (LENGTH(y) == nrx) {	/* y is a row vector */
581
		nry = LENGTH(y);
586
		nry = LENGTH(y);
582
		ncy = 1;
587
		ncy = 1;
583
	    }
588
	    }
584
	}
589
	}
585
    }
590
    }
586
    else {				/* x and y matrices */
591
    else {				/* x and y matrices */
587
	nrx = INTEGER(xdims)[0];
592
	nrx = INTEGER(xdims)[0];
588
	ncx = INTEGER(xdims)[1];
593
	ncx = INTEGER(xdims)[1];
589
	nry = INTEGER(ydims)[0];
594
	nry = INTEGER(ydims)[0];
590
	ncy = INTEGER(ydims)[1];
595
	ncy = INTEGER(ydims)[1];
591
    }
596
    }
592
 
597
 
593
    if (PRIMVAL(op) == 0) {
598
    if (PRIMVAL(op) == 0) {
594
	if (ncx != nry)
599
	if (ncx != nry)
595
	    errorcall(call, "non-conformable arguments");
600
	    errorcall(call, "non-conformable arguments");
596
    }
601
    }
597
    else {
602
    else {
598
	if (nrx != nry)
603
	if (nrx != nry)
599
	    errorcall(call, "non-conformable arguments");
604
	    errorcall(call, "non-conformable arguments");
600
    }
605
    }
601
 
606
 
602
    if (isComplex(CAR(args)) || isComplex(CADR(args)))
607
    if (isComplex(CAR(args)) || isComplex(CADR(args)))
603
	mode = CPLXSXP;
608
	mode = CPLXSXP;
604
    else
609
    else
605
	mode = REALSXP;
610
	mode = REALSXP;
606
    SETCAR(args, coerceVector(CAR(args), mode));
611
    SETCAR(args, coerceVector(CAR(args), mode));
607
    SETCADR(args, coerceVector(CADR(args), mode));
612
    SETCADR(args, coerceVector(CADR(args), mode));
608
 
613
 
609
    if (PRIMVAL(op) == 0) {		       	/* op == 0 : matprod() */
614
    if (PRIMVAL(op) == 0) {		       	/* op == 0 : matprod() */
610
 
615
 
611
	PROTECT(ans = allocMatrix(mode, nrx, ncy));
616
	PROTECT(ans = allocMatrix(mode, nrx, ncy));
612
	if (mode == CPLXSXP)
617
	if (mode == CPLXSXP)
613
	    cmatprod(COMPLEX(CAR(args)), nrx, ncx,
618
	    cmatprod(COMPLEX(CAR(args)), nrx, ncx,
614
		     COMPLEX(CADR(args)), nry, ncy, COMPLEX(ans));
619
		     COMPLEX(CADR(args)), nry, ncy, COMPLEX(ans));
615
	else
620
	else
616
	    matprod(REAL(CAR(args)), nrx, ncx,
621
	    matprod(REAL(CAR(args)), nrx, ncx,
617
		    REAL(CADR(args)), nry, ncy, REAL(ans));
622
		    REAL(CADR(args)), nry, ncy, REAL(ans));
618
 
623
 
619
	PROTECT(xdims = getAttrib(CAR(args), R_DimNamesSymbol));
624
	PROTECT(xdims = getAttrib(CAR(args), R_DimNamesSymbol));
620
	PROTECT(ydims = getAttrib(CADR(args), R_DimNamesSymbol));
625
	PROTECT(ydims = getAttrib(CADR(args), R_DimNamesSymbol));
621
 
626
 
622
	if (xdims != R_NilValue || ydims != R_NilValue) {
627
	if (xdims != R_NilValue || ydims != R_NilValue) {
623
	    SEXP dimnames, dimnamesnames, dn;
628
	    SEXP dimnames, dimnamesnames, dn;
624
	    PROTECT(dimnames = allocVector(VECSXP, 2));
629
	    PROTECT(dimnames = allocVector(VECSXP, 2));
625
	    PROTECT(dimnamesnames = allocVector(STRSXP, 2));
630
	    PROTECT(dimnamesnames = allocVector(STRSXP, 2));
626
	    if (xdims != R_NilValue) {
631
	    if (xdims != R_NilValue) {
627
		if (ldx == 2 || ncx ==1) {
632
		if (ldx == 2 || ncx ==1) {
628
		    dn = getAttrib(xdims, R_NamesSymbol);
633
		    dn = getAttrib(xdims, R_NamesSymbol);
629
		    SET_VECTOR_ELT(dimnames, 0, VECTOR_ELT(xdims, 0));
634
		    SET_VECTOR_ELT(dimnames, 0, VECTOR_ELT(xdims, 0));
630
		    if(!isNull(dn))
635
		    if(!isNull(dn))
631
			SET_STRING_ELT(dimnamesnames, 0, STRING_ELT(dn, 0));
636
			SET_STRING_ELT(dimnamesnames, 0, STRING_ELT(dn, 0));
632
		}
637
		}
633
	    }
638
	    }
634
	    if (ydims != R_NilValue) {
639
	    if (ydims != R_NilValue) {
635
		if (ldy == 2 ){
640
		if (ldy == 2 ){
636
		    dn = getAttrib(ydims, R_NamesSymbol);
641
		    dn = getAttrib(ydims, R_NamesSymbol);
637
		    SET_VECTOR_ELT(dimnames, 1, VECTOR_ELT(ydims, 1));
642
		    SET_VECTOR_ELT(dimnames, 1, VECTOR_ELT(ydims, 1));
638
		    if(!isNull(dn))
643
		    if(!isNull(dn))
639
			SET_STRING_ELT(dimnamesnames, 1, STRING_ELT(dn, 1));
644
			SET_STRING_ELT(dimnamesnames, 1, STRING_ELT(dn, 1));
640
		} else if (nry == 1) {
645
		} else if (nry == 1) {
641
		    dn = getAttrib(ydims, R_NamesSymbol);
646
		    dn = getAttrib(ydims, R_NamesSymbol);
642
		    SET_VECTOR_ELT(dimnames, 1, VECTOR_ELT(ydims, 0));
647
		    SET_VECTOR_ELT(dimnames, 1, VECTOR_ELT(ydims, 0));
643
		    if(!isNull(dn))
648
		    if(!isNull(dn))
644
			SET_STRING_ELT(dimnamesnames, 1, STRING_ELT(dn, 0));
649
			SET_STRING_ELT(dimnamesnames, 1, STRING_ELT(dn, 0));
645
		}
650
		}
646
	    }
651
	    }
647
	    setAttrib(dimnames, R_NamesSymbol, dimnamesnames);
652
	    setAttrib(dimnames, R_NamesSymbol, dimnamesnames);
648
	    setAttrib(ans, R_DimNamesSymbol, dimnames);
653
	    setAttrib(ans, R_DimNamesSymbol, dimnames);
649
	    UNPROTECT(2);
654
	    UNPROTECT(2);
650
	}
655
	}
651
    }
656
    }
652
 
657
 
653
    else {					/* op == 1: crossprod() */
658
    else {					/* op == 1: crossprod() */
654
 
659
 
655
	PROTECT(ans = allocMatrix(mode, ncx, ncy));
660
	PROTECT(ans = allocMatrix(mode, ncx, ncy));
656
	if (mode == CPLXSXP)
661
	if (mode == CPLXSXP)
657
	    if(sym)
662
	    if(sym)
658
		ccrossprod(COMPLEX(CAR(args)), nrx, ncx,
663
		ccrossprod(COMPLEX(CAR(args)), nrx, ncx,
659
			   COMPLEX(CAR(args)), nry, ncy, COMPLEX(ans));
664
			   COMPLEX(CAR(args)), nry, ncy, COMPLEX(ans));
660
	    else
665
	    else
661
		ccrossprod(COMPLEX(CAR(args)), nrx, ncx,
666
		ccrossprod(COMPLEX(CAR(args)), nrx, ncx,
662
			   COMPLEX(CADR(args)), nry, ncy, COMPLEX(ans));
667
			   COMPLEX(CADR(args)), nry, ncy, COMPLEX(ans));
663
	else {
668
	else {
664
	    if(sym)
669
	    if(sym)
665
		symcrossprod(REAL(CAR(args)), nrx, ncx, REAL(ans));
670
		symcrossprod(REAL(CAR(args)), nrx, ncx, REAL(ans));
666
	    else
671
	    else
667
		crossprod(REAL(CAR(args)), nrx, ncx,
672
		crossprod(REAL(CAR(args)), nrx, ncx,
668
			  REAL(CADR(args)), nry, ncy, REAL(ans));
673
			  REAL(CADR(args)), nry, ncy, REAL(ans));
669
	}
674
	}
670
 
675
 
671
	PROTECT(xdims = getAttrib(CAR(args), R_DimNamesSymbol));
676
	PROTECT(xdims = getAttrib(CAR(args), R_DimNamesSymbol));
672
	if (sym)
677
	if (sym)
673
	    PROTECT(ydims = xdims);
678
	    PROTECT(ydims = xdims);
674
	else
679
	else
675
	    PROTECT(ydims = getAttrib(CADR(args), R_DimNamesSymbol));
680
	    PROTECT(ydims = getAttrib(CADR(args), R_DimNamesSymbol));
676
 
681
 
677
	if (xdims != R_NilValue || ydims != R_NilValue) {
682
	if (xdims != R_NilValue || ydims != R_NilValue) {
678
	    SEXP dimnames, dimnamesnames, dnx=R_NilValue, dny=R_NilValue;
683
	    SEXP dimnames, dimnamesnames, dnx=R_NilValue, dny=R_NilValue;
679
 
684
 
680
	    /* allocate dimnames and dimnamesnames */
685
	    /* allocate dimnames and dimnamesnames */
681
 
686
 
682
	    PROTECT(dimnames = allocVector(VECSXP, 2));
687
	    PROTECT(dimnames = allocVector(VECSXP, 2));
683
	    PROTECT(dimnamesnames = allocVector(STRSXP, 2));
688
	    PROTECT(dimnamesnames = allocVector(STRSXP, 2));
684
 
689
 
685
            /* There was a bug here.  The second element of a */
690
            /* There was a bug here.  The second element of a */
686
            /* dimnames list was being accessed for a 1-d array. */
691
            /* dimnames list was being accessed for a 1-d array. */
687
            /* I have just excluded the use of dimnames in this */
692
            /* I have just excluded the use of dimnames in this */
688
            /* case. - ihaka Sep 30, 2003. */
693
            /* case. - ihaka Sep 30, 2003. */
689
 
694
 
690
	    if (xdims != R_NilValue) {
695
	    if (xdims != R_NilValue) {
691
                if (ldx == 2) {
696
                if (ldx == 2) {
692
		    dnx = getAttrib(xdims, R_NamesSymbol);
697
		    dnx = getAttrib(xdims, R_NamesSymbol);
693
		    SET_VECTOR_ELT(dimnames, 0, VECTOR_ELT(xdims, 1));
698
		    SET_VECTOR_ELT(dimnames, 0, VECTOR_ELT(xdims, 1));
694
		    if(!isNull(dnx))
699
		    if(!isNull(dnx))
695
			SET_STRING_ELT(dimnamesnames, 0, STRING_ELT(dnx, 1));
700
			SET_STRING_ELT(dimnamesnames, 0, STRING_ELT(dnx, 1));
696
		}
701
		}
697
	    }
702
	    }
698
 
703
 
699
	    if (ydims != R_NilValue) {
704
	    if (ydims != R_NilValue) {
700
                if (ldy == 2) {
705
                if (ldy == 2) {
701
		    dny = getAttrib(ydims, R_NamesSymbol);
706
		    dny = getAttrib(ydims, R_NamesSymbol);
702
		    SET_VECTOR_ELT(dimnames, 1, VECTOR_ELT(ydims, 1));
707
		    SET_VECTOR_ELT(dimnames, 1, VECTOR_ELT(ydims, 1));
703
		    if(!isNull(dny))
708
		    if(!isNull(dny))
704
			SET_STRING_ELT(dimnamesnames, 1, STRING_ELT(dny, 1));
709
			SET_STRING_ELT(dimnamesnames, 1, STRING_ELT(dny, 1));
705
		}
710
		}
706
	    }
711
	    }
707
 
712
 
708
            /* We sometimes attach a dimnames attribute */
713
            /* We sometimes attach a dimnames attribute */
709
            /* whose elements are all NULL ... */
714
            /* whose elements are all NULL ... */
710
            /* Thus is ugly but causes no real damage. */
715
            /* Thus is ugly but causes no real damage. */
711
	    
716
	    
712
	    if (!isNull(dnx) || !isNull(dny))
717
	    if (!isNull(dnx) || !isNull(dny))
713
		setAttrib(dimnames, R_NamesSymbol, dimnamesnames);
718
		setAttrib(dimnames, R_NamesSymbol, dimnamesnames);
714
	    setAttrib(ans, R_DimNamesSymbol, dimnames);
719
	    setAttrib(ans, R_DimNamesSymbol, dimnames);
715
	    UNPROTECT(2);
720
	    UNPROTECT(2);
716
	}
721
	}
717
    }
722
    }
718
    UNPROTECT(3);
723
    UNPROTECT(3);
719
    return ans;
724
    return ans;
720
}
725
}
721
 
726
 
722
SEXP do_transpose(SEXP call, SEXP op, SEXP args, SEXP rho)
727
SEXP do_transpose(SEXP call, SEXP op, SEXP args, SEXP rho)
723
{
728
{
724
    SEXP a, r, dims, dimnames, dimnamesnames=R_NilValue,
729
    SEXP a, r, dims, dimnames, dimnamesnames=R_NilValue,
725
	ndimnamesnames, rnames, cnames;
730
	ndimnamesnames, rnames, cnames;
726
    int i, len = 0, ncol=0, nrow=0;
731
    int i, len = 0, ncol=0, nrow=0;
727
 
732
 
728
    checkArity(op, args);
733
    checkArity(op, args);
729
    a = CAR(args);
734
    a = CAR(args);
730
 
735
 
731
    if (isVector(a)) {
736
    if (isVector(a)) {
732
	dims = getAttrib(a, R_DimSymbol);
737
	dims = getAttrib(a, R_DimSymbol);
733
	rnames = R_NilValue;
738
	rnames = R_NilValue;
734
	cnames = R_NilValue;
739
	cnames = R_NilValue;
735
	switch(length(dims)) {
740
	switch(length(dims)) {
736
	case 0:
741
	case 0:
737
	    nrow = len = length(a);
742
	    nrow = len = length(a);
738
	    ncol = 1;
743
	    ncol = 1;
739
	    rnames = getAttrib(a, R_NamesSymbol);
744
	    rnames = getAttrib(a, R_NamesSymbol);
740
	    break;
745
	    break;
741
	case 1:
746
	case 1:
742
	    nrow = len = length(a);
747
	    nrow = len = length(a);
743
	    ncol = 1;
748
	    ncol = 1;
744
	    rnames = getAttrib(a, R_DimNamesSymbol);
749
	    rnames = getAttrib(a, R_DimNamesSymbol);
745
	    if (rnames != R_NilValue)
750
	    if (rnames != R_NilValue)
746
		rnames = VECTOR_ELT(rnames, 0);
751
		rnames = VECTOR_ELT(rnames, 0);
747
	    break;
752
	    break;
748
	case 2:
753
	case 2:
749
	    ncol = ncols(a);
754
	    ncol = ncols(a);
750
	    nrow = nrows(a);
755
	    nrow = nrows(a);
751
	    len = length(a);
756
	    len = length(a);
752
	    dimnames = getAttrib(a, R_DimNamesSymbol);
757
	    dimnames = getAttrib(a, R_DimNamesSymbol);
753
	    if (dimnames != R_NilValue) {
758
	    if (dimnames != R_NilValue) {
754
		rnames = VECTOR_ELT(dimnames, 0);
759
		rnames = VECTOR_ELT(dimnames, 0);
755
		cnames = VECTOR_ELT(dimnames, 1);
760
		cnames = VECTOR_ELT(dimnames, 1);
756
		dimnamesnames = getAttrib(dimnames, R_NamesSymbol);
761
		dimnamesnames = getAttrib(dimnames, R_NamesSymbol);
757
	    }
762
	    }
758
	    break;
763
	    break;
759
	default:
764
	default:
760
	    goto not_matrix;
765
	    goto not_matrix;
761
	}
766
	}
762
    }
767
    }
763
    else
768
    else
764
	goto not_matrix;
769
	goto not_matrix;
765
    PROTECT(r = allocVector(TYPEOF(a), len));
770
    PROTECT(r = allocVector(TYPEOF(a), len));
766
    switch (TYPEOF(a)) {
771
    switch (TYPEOF(a)) {
767
    case LGLSXP:
772
    case LGLSXP:
768
    case INTSXP:
773
    case INTSXP:
769
	for (i = 0; i < len; i++)
774
	for (i = 0; i < len; i++)
770
	    INTEGER(r)[i] = INTEGER(a)[(i / ncol) + (i % ncol) * nrow];
775
	    INTEGER(r)[i] = INTEGER(a)[(i / ncol) + (i % ncol) * nrow];
771
	break;
776
	break;
772
    case REALSXP:
777
    case REALSXP:
773
	for (i = 0; i < len; i++)
778
	for (i = 0; i < len; i++)
774
	    REAL(r)[i] = REAL(a)[(i / ncol) + (i % ncol) * nrow];
779
	    REAL(r)[i] = REAL(a)[(i / ncol) + (i % ncol) * nrow];
775
	break;
780
	break;
776
    case CPLXSXP:
781
    case CPLXSXP:
777
	for (i = 0; i < len; i++)
782
	for (i = 0; i < len; i++)
778
	    COMPLEX(r)[i] = COMPLEX(a)[(i / ncol) + (i % ncol) * nrow];
783
	    COMPLEX(r)[i] = COMPLEX(a)[(i / ncol) + (i % ncol) * nrow];
779
	break;
784
	break;
780
    case STRSXP:
785
    case STRSXP:
781
	for (i = 0; i < len; i++)
786
	for (i = 0; i < len; i++)
782
	    SET_STRING_ELT(r, i,
787
	    SET_STRING_ELT(r, i,
783
			   STRING_ELT(a, (i / ncol) + (i % ncol) * nrow));
788
			   STRING_ELT(a, (i / ncol) + (i % ncol) * nrow));
784
	break;
789
	break;
785
    case VECSXP:
790
    case VECSXP:
786
	for (i = 0; i < len; i++)
791
	for (i = 0; i < len; i++)
787
	    SET_VECTOR_ELT(r, i,
792
	    SET_VECTOR_ELT(r, i,
788
			   VECTOR_ELT(a, (i / ncol) + (i % ncol) * nrow));
793
			   VECTOR_ELT(a, (i / ncol) + (i % ncol) * nrow));
789
	break;
794
	break;
-
 
795
    case RAWSXP:
-
 
796
	for (i = 0; i < len; i++)
-
 
797
	    RAW(r)[i] = RAW(a)[(i / ncol) + (i % ncol) * nrow];
-
 
798
	break;
790
    default:
799
    default:
791
	goto not_matrix;
800
	goto not_matrix;
792
    }
801
    }
793
    PROTECT(dims = allocVector(INTSXP, 2));
802
    PROTECT(dims = allocVector(INTSXP, 2));
794
    INTEGER(dims)[0] = ncol;
803
    INTEGER(dims)[0] = ncol;
795
    INTEGER(dims)[1] = nrow;
804
    INTEGER(dims)[1] = nrow;
796
    setAttrib(r, R_DimSymbol, dims);
805
    setAttrib(r, R_DimSymbol, dims);
797
    UNPROTECT(1);
806
    UNPROTECT(1);
798
    if(rnames != R_NilValue || cnames != R_NilValue) {
807
    if(rnames != R_NilValue || cnames != R_NilValue) {
799
	PROTECT(dimnames = allocVector(VECSXP, 2));
808
	PROTECT(dimnames = allocVector(VECSXP, 2));
800
	SET_VECTOR_ELT(dimnames, 0, cnames);
809
	SET_VECTOR_ELT(dimnames, 0, cnames);
801
	SET_VECTOR_ELT(dimnames, 1, rnames);
810
	SET_VECTOR_ELT(dimnames, 1, rnames);
802
	if(!isNull(dimnamesnames)) {
811
	if(!isNull(dimnamesnames)) {
803
	    PROTECT(ndimnamesnames = allocVector(VECSXP, 2));
812
	    PROTECT(ndimnamesnames = allocVector(VECSXP, 2));
804
	    SET_STRING_ELT(ndimnamesnames, 1, STRING_ELT(dimnamesnames, 0));
813
	    SET_STRING_ELT(ndimnamesnames, 1, STRING_ELT(dimnamesnames, 0));
805
	    SET_STRING_ELT(ndimnamesnames, 0, STRING_ELT(dimnamesnames, 1));
814
	    SET_STRING_ELT(ndimnamesnames, 0, STRING_ELT(dimnamesnames, 1));
806
	    setAttrib(dimnames, R_NamesSymbol, ndimnamesnames);
815
	    setAttrib(dimnames, R_NamesSymbol, ndimnamesnames);
807
	    UNPROTECT(1);
816
	    UNPROTECT(1);
808
	}
817
	}
809
	setAttrib(r, R_DimNamesSymbol, dimnames);
818
	setAttrib(r, R_DimNamesSymbol, dimnames);
810
	UNPROTECT(1);
819
	UNPROTECT(1);
811
    }
820
    }
812
    copyMostAttrib(a, r);
821
    copyMostAttrib(a, r);
813
    UNPROTECT(1);
822
    UNPROTECT(1);
814
    return r;
823
    return r;
815
 not_matrix:
824
 not_matrix:
816
    errorcall(call, "argument is not a matrix");
825
    errorcall(call, "argument is not a matrix");
817
    return call;/* never used; just for -Wall */
826
    return call;/* never used; just for -Wall */
818
}
827
}
819
 
828
 
820
/*
829
/*
821
 New version of aperm, using strides for speed.
830
 New version of aperm, using strides for speed.
822
 Jonathan Rougier <J.C.Rougier@durham.ac.uk>
831
 Jonathan Rougier <J.C.Rougier@durham.ac.uk>
823
 
832
 
824
 v1.0 30.01.01
833
 v1.0 30.01.01
825
 
834
 
826
 M.Maechler : expanded	all ../include/Rdefines.h macros
835
 M.Maechler : expanded	all ../include/Rdefines.h macros
827
 */
836
 */
828
 
837
 
829
/* this increments iip and sets j using strides */
838
/* this increments iip and sets j using strides */
830
 
839
 
831
#define CLICKJ						\
840
#define CLICKJ						\
832
    for (itmp=0; itmp<n; itmp++)			\
841
    for (itmp=0; itmp<n; itmp++)			\
833
	if (iip[itmp] == INTEGER(dimsr)[itmp]-1)	\
842
	if (iip[itmp] == INTEGER(dimsr)[itmp]-1)	\
834
	    iip[itmp] = 0;				\
843
	    iip[itmp] = 0;				\
835
	else {						\
844
	else {						\
836
	    iip[itmp]++;				\
845
	    iip[itmp]++;				\
837
	    break;					\
846
	    break;					\
838
	}						\
847
	}						\
839
    for (j=0, itmp=0; itmp<n; itmp++)			\
848
    for (j=0, itmp=0; itmp<n; itmp++)			\
840
	j += iip[itmp] * stride[itmp];
849
	j += iip[itmp] * stride[itmp];
841
 
850
 
842
/* aperm (a, perm, resize = TRUE) */
851
/* aperm (a, perm, resize = TRUE) */
843
SEXP do_aperm(SEXP call, SEXP op, SEXP args, SEXP rho)
852
SEXP do_aperm(SEXP call, SEXP op, SEXP args, SEXP rho)
844
{
853
{
845
    SEXP a, perm, resize, r, dimsa, dimsr, dna;
854
    SEXP a, perm, resize, r, dimsa, dimsr, dna;
846
    int i, j, n, len, itmp;
855
    int i, j, n, len, itmp;
847
    int *pp, *iip, *stride;
856
    int *pp, *iip, *stride;
848
    char *vmax;
857
    char *vmax;
849
 
858
 
850
    checkArity(op, args);
859
    checkArity(op, args);
851
 
860
 
852
    a = CAR(args);
861
    a = CAR(args);
853
    if (!isArray(a))
862
    if (!isArray(a))
854
	errorcall(call,"invalid first argument, must be an array");
863
	errorcall(call,"invalid first argument, must be an array");
855
 
864
 
856
    PROTECT(dimsa = getAttrib(a, R_DimSymbol));
865
    PROTECT(dimsa = getAttrib(a, R_DimSymbol));
857
    n = LENGTH(dimsa);
866
    n = LENGTH(dimsa);
858
 
867
 
859
    /* check the permutation */
868
    /* check the permutation */
860
 
869
 
861
    PROTECT(perm = coerceVector(CADR(args), INTSXP));
870
    PROTECT(perm = coerceVector(CADR(args), INTSXP));
862
    vmax = vmaxget();
871
    vmax = vmaxget();
863
    pp = (int *) R_alloc(n, sizeof(int));
872
    pp = (int *) R_alloc(n, sizeof(int));
864
    if (length(perm) == 0) {
873
    if (length(perm) == 0) {
865
	for (i=0; i<n; i++)
874
	for (i=0; i<n; i++)
866
	    pp[i] = n-1-i;
875
	    pp[i] = n-1-i;
867
    } else if (length(perm) == n) {
876
    } else if (length(perm) == n) {
868
	for (i=0; i<n; i++)
877
	for (i=0; i<n; i++)
869
	    pp[i] = INTEGER(perm)[i] - 1; /* no offset! */
878
	    pp[i] = INTEGER(perm)[i] - 1; /* no offset! */
870
    } else
879
    } else
871
	errorcall(call, "`perm' is of wrong length");
880
	errorcall(call, "`perm' is of wrong length");
872
 
881
 
873
    iip = (int *) R_alloc(n, sizeof(int));
882
    iip = (int *) R_alloc(n, sizeof(int));
874
    for (i=0; i<n; iip[i++] = 0);
883
    for (i=0; i<n; iip[i++] = 0);
875
    for (i=0; i<n; i++)
884
    for (i=0; i<n; i++)
876
	if (pp[i] >= 0 && pp[i] < n)
885
	if (pp[i] >= 0 && pp[i] < n)
877
	    iip[pp[i]]++;
886
	    iip[pp[i]]++;
878
	else
887
	else
879
	    errorcall(call, "value of out range in `perm'");
888
	    errorcall(call, "value of out range in `perm'");
880
    for (i=0; i<n; i++)
889
    for (i=0; i<n; i++)
881
	if (iip[i]==0)
890
	if (iip[i]==0)
882
	    errorcall(call, "invalid permutation (`perm')");
891
	    errorcall(call, "invalid permutation (`perm')");
883
 
892
 
884
    /* create the stride object and permute */
893
    /* create the stride object and permute */
885
 
894
 
886
    stride = (int *) R_alloc(n, sizeof(int));
895
    stride = (int *) R_alloc(n, sizeof(int));
887
 
896
 
888
    for (iip[0] = 1, i = 1; i<n; i++)
897
    for (iip[0] = 1, i = 1; i<n; i++)
889
	iip[i] = iip[i-1] * INTEGER(dimsa)[i-1];
898
	iip[i] = iip[i-1] * INTEGER(dimsa)[i-1];
890
 
899
 
891
    for (i=0; i<n; i++)
900
    for (i=0; i<n; i++)
892
	stride[i] = iip[pp[i]];
901
	stride[i] = iip[pp[i]];
893
 
902
 
894
    /* also need to have the dimensions of r */
903
    /* also need to have the dimensions of r */
895
 
904
 
896
    PROTECT(dimsr = allocVector(INTSXP,n));
905
    PROTECT(dimsr = allocVector(INTSXP,n));
897
    for (i=0; i<n; i++)
906
    for (i=0; i<n; i++)
898
	INTEGER(dimsr)[i] = INTEGER(dimsa)[pp[i]];
907
	INTEGER(dimsr)[i] = INTEGER(dimsa)[pp[i]];
899
 
908
 
900
    /* and away we go! iip will hold the incrementer */
909
    /* and away we go! iip will hold the incrementer */
901
 
910
 
902
    len = LENGTH(a);
911
    len = LENGTH(a);
903
    len = length(a);
912
    len = length(a);
904
    PROTECT(r = allocVector(TYPEOF(a), len));
913
    PROTECT(r = allocVector(TYPEOF(a), len));
905
 
914
 
906
    for (i=0; i<n; iip[i++] = 0);
915
    for (i=0; i<n; iip[i++] = 0);
907
 
916
 
908
    switch (TYPEOF(a)) {
917
    switch (TYPEOF(a)) {
909
 
918
 
910
    case INTSXP:
919
    case INTSXP:
911
    case LGLSXP:
920
    case LGLSXP:
912
	for (j=0, i=0; i<len; i++) {
921
	for (j=0, i=0; i<len; i++) {
913
	    INTEGER(r)[i] = INTEGER(a)[j];
922
	    INTEGER(r)[i] = INTEGER(a)[j];
914
	    CLICKJ;
923
	    CLICKJ;
915
	}
924
	}
916
	break;
925
	break;
917
 
926
 
918
    case REALSXP:
927
    case REALSXP:
919
	for (j=0, i=0; i<len; i++) {
928
	for (j=0, i=0; i<len; i++) {
920
	    REAL(r)[i] = REAL(a)[j];
929
	    REAL(r)[i] = REAL(a)[j];
921
	    CLICKJ;
930
	    CLICKJ;
922
	}
931
	}
923
	break;
932
	break;
924
 
933
 
925
    case CPLXSXP:
934
    case CPLXSXP:
926
	for (j=0, i=0; i<len; i++) {
935
	for (j=0, i=0; i<len; i++) {
927
	    COMPLEX(r)[i].r = COMPLEX(a)[j].r;
936
	    COMPLEX(r)[i].r = COMPLEX(a)[j].r;
928
	    COMPLEX(r)[i].i = COMPLEX(a)[j].i;
937
	    COMPLEX(r)[i].i = COMPLEX(a)[j].i;
929
	    CLICKJ;
938
	    CLICKJ;
930
	}
939
	}
931
	break;
940
	break;
932
 
941
 
933
    case STRSXP:
942
    case STRSXP:
934
	for (j=0, i=0; i<len; i++) {
943
	for (j=0, i=0; i<len; i++) {
935
	    SET_STRING_ELT(r, i, STRING_ELT(a, j));
944
	    SET_STRING_ELT(r, i, STRING_ELT(a, j));
936
	    CLICKJ;
945
	    CLICKJ;
937
	}
946
	}
938
	break;
947
	break;
939
 
948
 
940
    case VECSXP:
949
    case VECSXP:
941
	for (j=0, i=0; i<len; i++) {
950
	for (j=0, i=0; i<len; i++) {
942
	    SET_VECTOR_ELT(r, i, VECTOR_ELT(a, j));
951
	    SET_VECTOR_ELT(r, i, VECTOR_ELT(a, j));
943
	    CLICKJ;
952
	    CLICKJ;
-
 
953
	}
-
 
954
	break;
-
 
955
 
-
 
956
    case RAWSXP:
-
 
957
	for (j=0, i=0; i<len; i++) {
-
 
958
	    RAW(r)[i] = RAW(a)[j];
-
 
959
	    CLICKJ;
944
	}
960
	}
945
	break;
961
	break;
946
 
962
 
947
    default:
963
    default:
948
	errorcall(call, "unsupported type of array");
964
	errorcall(call, "unsupported type of array");
949
    }
965
    }
950
 
966
 
951
    /* handle the resize */
967
    /* handle the resize */
952
    PROTECT(resize = coerceVector(CADDR(args), INTSXP));
968
    PROTECT(resize = coerceVector(CADDR(args), INTSXP));
953
    if (LOGICAL(resize)[0])
969
    if (LOGICAL(resize)[0])
954
	setAttrib(r, R_DimSymbol, dimsr);
970
	setAttrib(r, R_DimSymbol, dimsr);
955
    else
971
    else
956
	setAttrib(r, R_DimSymbol, dimsa);
972
	setAttrib(r, R_DimSymbol, dimsa);
957
 
973
 
958
    /* and handle the dimnames */
974
    /* and handle the dimnames */
959
 
975
 
960
    PROTECT(dna = getAttrib(a, R_DimNamesSymbol));
976
    PROTECT(dna = getAttrib(a, R_DimNamesSymbol));
961
 
977
 
962
    if (LOGICAL(resize)[0] && dna != R_NilValue) {
978
    if (LOGICAL(resize)[0] && dna != R_NilValue) {
963
 
979
 
964
	SEXP dnna, dnr, dnnr;
980
	SEXP dnna, dnr, dnnr;
965
 
981
 
966
	PROTECT(dnna = getAttrib(dna, R_NamesSymbol));
982
	PROTECT(dnna = getAttrib(dna, R_NamesSymbol));
967
	PROTECT(dnnr = allocVector(STRSXP,n));
983
	PROTECT(dnnr = allocVector(STRSXP,n));
968
	PROTECT(dnr  = allocVector(VECSXP,n));
984
	PROTECT(dnr  = allocVector(VECSXP,n));
969
 
985
 
970
	for (i=0; i<n; i++) {
986
	for (i=0; i<n; i++) {
971
	    SET_VECTOR_ELT(dnr, i, VECTOR_ELT(dna, pp[i]));
987
	    SET_VECTOR_ELT(dnr, i, VECTOR_ELT(dna, pp[i]));
972
	    if (dnna != R_NilValue)
988
	    if (dnna != R_NilValue)
973
		SET_STRING_ELT(dnnr, i, STRING_ELT(dnna, pp[i]));
989
		SET_STRING_ELT(dnnr, i, STRING_ELT(dnna, pp[i]));
974
	}
990
	}
975
 
991
 
976
	if (dnna != R_NilValue)
992
	if (dnna != R_NilValue)
977
	    setAttrib(dnr, R_NamesSymbol, dnnr);
993
	    setAttrib(dnr, R_NamesSymbol, dnnr);
978
	setAttrib(r, R_DimNamesSymbol, dnr);
994
	setAttrib(r, R_DimNamesSymbol, dnr);
979
	UNPROTECT(3); /* dnna, dnr, dnnr */
995
	UNPROTECT(3); /* dnna, dnr, dnnr */
980
    }
996
    }
981
    /* free temporary memory */
997
    /* free temporary memory */
982
    vmaxset(vmax);
998
    vmaxset(vmax);
983
 
999
 
984
    UNPROTECT(6); /* dimsa, perm, r, dimsr, resize, dna */
1000
    UNPROTECT(6); /* dimsa, perm, r, dimsr, resize, dna */
985
    return r;
1001
    return r;
986
}
1002
}
987
 
1003
 
988
/* colSums(x, n, p, na.rm) and friends */
1004
/* colSums(x, n, p, na.rm) and friends */
989
SEXP do_colsum(SEXP call, SEXP op, SEXP args, SEXP rho)
1005
SEXP do_colsum(SEXP call, SEXP op, SEXP args, SEXP rho)
990
{
1006
{
991
    SEXP x, ans = R_NilValue;
1007
    SEXP x, ans = R_NilValue;
992
    int OP, n, p, cnt = 0, i, j, type;
1008
    int OP, n, p, cnt = 0, i, j, type;
993
    Rboolean NaRm, keepNA;
1009
    Rboolean NaRm, keepNA;
994
    int *ix;
1010
    int *ix;
995
    double *rx, sum = 0.0;
1011
    double *rx, sum = 0.0;
996
 
1012
 
997
    checkArity(op, args);
1013
    checkArity(op, args);
998
    x = CAR(args); args = CDR(args);
1014
    x = CAR(args); args = CDR(args);
999
    n = asInteger(CAR(args)); args = CDR(args);
1015
    n = asInteger(CAR(args)); args = CDR(args);
1000
    p = asInteger(CAR(args)); args = CDR(args);
1016
    p = asInteger(CAR(args)); args = CDR(args);
1001
    NaRm = asLogical(CAR(args));
1017
    NaRm = asLogical(CAR(args));
1002
    if (n == NA_INTEGER || n <= 0)
1018
    if (n == NA_INTEGER || n <= 0)
1003
	errorcall(call, "invalid value of n");
1019
	errorcall(call, "invalid value of n");
1004
    if (p == NA_INTEGER || p <= 0)
1020
    if (p == NA_INTEGER || p <= 0)
1005
	errorcall(call, "invalid value of p");
1021
	errorcall(call, "invalid value of p");
1006
    if (NaRm == NA_LOGICAL) errorcall(call, "invalid value of na.rm");
1022
    if (NaRm == NA_LOGICAL) errorcall(call, "invalid value of na.rm");
1007
    keepNA = !NaRm;
1023
    keepNA = !NaRm;
1008
 
1024
 
1009
    OP = PRIMVAL(op);
1025
    OP = PRIMVAL(op);
1010
    switch (type = TYPEOF(x)) {
1026
    switch (type = TYPEOF(x)) {
1011
    case LGLSXP: break;
1027
    case LGLSXP: break;
1012
    case INTSXP: break;
1028
    case INTSXP: break;
1013
    case REALSXP: break;
1029
    case REALSXP: break;
1014
    default:
1030
    default:
1015
	errorcall(call, "`x' must be numeric");
1031
	errorcall(call, "`x' must be numeric");
1016
    }
1032
    }
1017
 
1033
 
1018
    if (OP == 0 || OP == 1) { /* columns */
1034
    if (OP == 0 || OP == 1) { /* columns */
1019
	cnt = n;
1035
	cnt = n;
1020
	PROTECT(ans = allocVector(REALSXP, p));
1036
	PROTECT(ans = allocVector(REALSXP, p));
1021
	for (j = 0; j < p; j++) {
1037
	for (j = 0; j < p; j++) {
1022
	    switch (type) {
1038
	    switch (type) {
1023
	    case REALSXP:
1039
	    case REALSXP:
1024
		rx = REAL(x) + n*j;
1040
		rx = REAL(x) + n*j;
1025
		if (keepNA)
1041
		if (keepNA)
1026
		    for (sum = 0., i = 0; i < n; i++) sum += *rx++;
1042
		    for (sum = 0., i = 0; i < n; i++) sum += *rx++;
1027
		else {
1043
		else {
1028
		    for (cnt = 0, sum = 0., i = 0; i < n; i++, rx++)
1044
		    for (cnt = 0, sum = 0., i = 0; i < n; i++, rx++)
1029
			if (!ISNAN(*rx)) {cnt++; sum += *rx;}
1045
			if (!ISNAN(*rx)) {cnt++; sum += *rx;}
1030
			else if (keepNA) {sum = NA_REAL; break;}
1046
			else if (keepNA) {sum = NA_REAL; break;}
1031
		}
1047
		}
1032
		break;
1048
		break;
1033
	    case INTSXP:
1049
	    case INTSXP:
1034
		ix = INTEGER(x) + n*j;
1050
		ix = INTEGER(x) + n*j;
1035
		for (cnt = 0, sum = 0., i = 0; i < n; i++, ix++)
1051
		for (cnt = 0, sum = 0., i = 0; i < n; i++, ix++)
1036
		    if (*ix != NA_INTEGER) {cnt++; sum += *ix;}
1052
		    if (*ix != NA_INTEGER) {cnt++; sum += *ix;}
1037
		    else if (keepNA) {sum = NA_REAL; break;}
1053
		    else if (keepNA) {sum = NA_REAL; break;}
1038
		break;
1054
		break;
1039
	    case LGLSXP:
1055
	    case LGLSXP:
1040
		ix = LOGICAL(x) + n*j;
1056
		ix = LOGICAL(x) + n*j;
1041
		for (cnt = 0, sum = 0., i = 0; i < n; i++, ix++)
1057
		for (cnt = 0, sum = 0., i = 0; i < n; i++, ix++)
1042
		    if (*ix != NA_LOGICAL) {cnt++; sum += *ix;}
1058
		    if (*ix != NA_LOGICAL) {cnt++; sum += *ix;}
1043
		    else if (keepNA) {sum = NA_REAL; break;}
1059
		    else if (keepNA) {sum = NA_REAL; break;}
1044
		break;
1060
		break;
1045
	    }
1061
	    }
1046
	    if (OP == 1) {
1062
	    if (OP == 1) {
1047
		if (cnt > 0) sum /= cnt; else sum = NA_REAL;
1063
		if (cnt > 0) sum /= cnt; else sum = NA_REAL;
1048
	    }
1064
	    }
1049
	    REAL(ans)[j] = sum;
1065
	    REAL(ans)[j] = sum;
1050
	}
1066
	}
1051
    }
1067
    }
1052
 
1068
 
1053
    if (OP == 2 || OP == 3) { /* rows */
1069
    if (OP == 2 || OP == 3) { /* rows */
1054
	cnt = p;
1070
	cnt = p;
1055
	PROTECT(ans = allocVector(REALSXP, n));
1071
	PROTECT(ans = allocVector(REALSXP, n));
1056
 
1072
 
1057
	/* reverse summation order to improve cache hits */
1073
	/* reverse summation order to improve cache hits */
1058
	if (type == REALSXP) {
1074
	if (type == REALSXP) {
1059
	    double *rans = REAL(ans), *ra = rans, *cnt = NULL, *c;
1075
	    double *rans = REAL(ans), *ra = rans, *cnt = NULL, *c;
1060
	    rx = REAL(x);
1076
	    rx = REAL(x);
1061
	    if (!keepNA && OP == 3) cnt = Calloc(n, double);
1077
	    if (!keepNA && OP == 3) cnt = Calloc(n, double);
1062
	    for (ra = rans, i = 0; i < n; i++) *ra++ = 0.0;
1078
	    for (ra = rans, i = 0; i < n; i++) *ra++ = 0.0;
1063
	    for (j = 0; j < p; j++) {
1079
	    for (j = 0; j < p; j++) {
1064
		ra = rans;
1080
		ra = rans;
1065
		if (keepNA)
1081
		if (keepNA)
1066
		    for (i = 0; i < n; i++) *ra++ += *rx++;
1082
		    for (i = 0; i < n; i++) *ra++ += *rx++;
1067
		else
1083
		else
1068
		    for (c = cnt, i = 0; i < n; i++, ra++, rx++, c++)
1084
		    for (c = cnt, i = 0; i < n; i++, ra++, rx++, c++)
1069
			if (!ISNAN(*rx)) {
1085
			if (!ISNAN(*rx)) {
1070
			    *ra += *rx;
1086
			    *ra += *rx;
1071
			    if (OP == 3) (*c)++;
1087
			    if (OP == 3) (*c)++;
1072
			}
1088
			}
1073
	    }
1089
	    }
1074
	    if (OP == 3) {
1090
	    if (OP == 3) {
1075
		if (keepNA)
1091
		if (keepNA)
1076
		    for (ra = rans, i = 0; i < n; i++)
1092
		    for (ra = rans, i = 0; i < n; i++)
1077
			*ra++ /= p;
1093
			*ra++ /= p;
1078
		else {
1094
		else {
1079
		    for (ra = rans, c = cnt, i = 0; i < n; i++, c++)
1095
		    for (ra = rans, c = cnt, i = 0; i < n; i++, c++)
1080
			if (*c > 0) *ra++ /= *c; else *ra++ = NA_REAL;
1096
			if (*c > 0) *ra++ /= *c; else *ra++ = NA_REAL;
1081
		    Free(cnt);
1097
		    Free(cnt);
1082
		}
1098
		}
1083
	    }
1099
	    }
1084
	    UNPROTECT(1);
1100
	    UNPROTECT(1);
1085
	    return ans;
1101
	    return ans;
1086
	}
1102
	}
1087
 
1103
 
1088
	for (i = 0; i < n; i++) {
1104
	for (i = 0; i < n; i++) {
1089
	    switch (type) {
1105
	    switch (type) {
1090
	    case REALSXP: /* this cannot be reached */
1106
	    case REALSXP: /* this cannot be reached */
1091
		rx = REAL(x) + i;
1107
		rx = REAL(x) + i;
1092
		if (keepNA)
1108
		if (keepNA)
1093
		    for (sum = 0., j = 0; j < p; j++, rx += n) sum += *rx;
1109
		    for (sum = 0., j = 0; j < p; j++, rx += n) sum += *rx;
1094
		else {
1110
		else {
1095
		    for (cnt = 0, sum = 0., j = 0; j < p; j++, rx += n)
1111
		    for (cnt = 0, sum = 0., j = 0; j < p; j++, rx += n)
1096
			if (!ISNAN(*rx)) {cnt++; sum += *rx;}
1112
			if (!ISNAN(*rx)) {cnt++; sum += *rx;}
1097
			else if (keepNA) {sum = NA_REAL; break;}
1113
			else if (keepNA) {sum = NA_REAL; break;}
1098
		}
1114
		}
1099
		break;
1115
		break;
1100
	    case INTSXP:
1116
	    case INTSXP:
1101
		ix = INTEGER(x) + i;
1117
		ix = INTEGER(x) + i;
1102
		for (cnt = 0, sum = 0., j = 0; j < p; j++, ix += n)
1118
		for (cnt = 0, sum = 0., j = 0; j < p; j++, ix += n)
1103
		    if (*ix != NA_INTEGER) {cnt++; sum += *ix;}
1119
		    if (*ix != NA_INTEGER) {cnt++; sum += *ix;}
1104
		    else if (keepNA) {sum = NA_REAL; break;}
1120
		    else if (keepNA) {sum = NA_REAL; break;}
1105
		break;
1121
		break;
1106
	    case LGLSXP:
1122
	    case LGLSXP:
1107
		ix = LOGICAL(x) + i;
1123
		ix = LOGICAL(x) + i;
1108
		for (cnt = 0, sum = 0., j = 0; j < p; j++, ix += n)
1124
		for (cnt = 0, sum = 0., j = 0; j < p; j++, ix += n)
1109
		    if (*ix != NA_LOGICAL) {cnt++; sum += *ix;}
1125
		    if (*ix != NA_LOGICAL) {cnt++; sum += *ix;}
1110
		    else if (keepNA) {sum = NA_REAL; break;}
1126
		    else if (keepNA) {sum = NA_REAL; break;}
1111
		break;
1127
		break;
1112
	    }
1128
	    }
1113
	    if (OP == 3) {
1129
	    if (OP == 3) {
1114
		if (cnt > 0) sum /= cnt; else sum = NA_REAL;
1130
		if (cnt > 0) sum /= cnt; else sum = NA_REAL;
1115
	    }
1131
	    }
1116
	    REAL(ans)[i] = sum;
1132
	    REAL(ans)[i] = sum;
1117
	}
1133
	}
1118
    }
1134
    }
1119
 
1135
 
1120
    UNPROTECT(1);
1136
    UNPROTECT(1);
1121
    return ans;
1137
    return ans;
1122
}
1138
}