The R Project SVN R

Rev

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

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