The R Project SVN R

Rev

Rev 63181 | Rev 63635 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 r 1
/*
1016 maechler 2
 *  R : A Computer Language for Statistical Data Analysis
2 r 3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
59046 ripley 4
 *  Copyright (C) 1997--2012  The R Core Team
2 r 5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
42307 ripley 17
 *  along with this program; if not, a copy is available at
18
 *  http://www.r-project.org/Licenses/
47040 maechler 19
 *
20
 * EXPORTS:
21
 *
22
 *  OneIndex()        -- used for "[[<-" in ./subassign.c
23
 *  get1index()       -- used for "[["   in ./subassign.c & subset.c
63166 luke 24
 *  vectorIndex()     -- used for "[[" and "[[<-" with a vector arg
47040 maechler 25
 
26
 *  mat2indsub()      -- for "mat[i]"     "    "            "
27
 
49592 murdoch 28
 *  makeSubscript()   -- for "[" and "[<-" in ./subset.c and ./subassign.c,
29
 *			 and "[[<-" with a scalar in ./subassign.c
47040 maechler 30
 *  vectorSubscript() -- for makeSubscript()   {currently unused externally}
31
 *  arraySubscript()  -- for "[i,j,..." and "[<-..." in ./subset.c, ./subassign.c
2 r 32
 */
33
 
5187 hornik 34
#ifdef HAVE_CONFIG_H
7701 hornik 35
#include <config.h>
5187 hornik 36
#endif
37
 
41686 ripley 38
#include <Defn.h>
2 r 39
 
41686 ripley 40
/* We might get a call with R_NilValue from subassignment code */
41
#define ECALL(call, yy) if(call == R_NilValue) error(yy); else errorcall(call, yy);
42
 
59113 ripley 43
/* This allows for the unusual case where x is of length 2,
44
   and x[[-m]] selects one element for m = 1, 2.
45
   So 'len' is only used if it is 2 and i is negative.
46
*/
47
static R_INLINE int integerOneIndex(int i, R_xlen_t len, SEXP call)
41680 ripley 48
{
10921 maechler 49
    int indx = -1;
4562 pd 50
 
59113 ripley 51
    if (i > 0) /* a regular 1-based index from R */
10921 maechler 52
	indx = i - 1;
41686 ripley 53
    else if (i == 0 || len < 2) {
54
	ECALL(call, _("attempt to select less than one element"));
55
    } else if (len == 2 && i > -3)
10921 maechler 56
	indx = 2 + i;
41686 ripley 57
    else {
58
	ECALL(call, _("attempt to select more than one element"));
59
    }
59113 ripley 60
    return indx;
4562 pd 61
}
62
 
47040 maechler 63
/* Utility used (only in) do_subassign2_dflt(), i.e. "[[<-" in ./subassign.c : */
59057 ripley 64
R_xlen_t attribute_hidden
59113 ripley 65
OneIndex(SEXP x, SEXP s, R_xlen_t len, int partial, SEXP *newname, 
59095 ripley 66
	 int pos, SEXP call)
1839 ihaka 67
{
68
    SEXP names;
59057 ripley 69
    R_xlen_t i, indx, nx;
63181 ripley 70
    const void *vmax;
2 r 71
 
41686 ripley 72
    if (pos < 0 && length(s) > 1) {
73
	ECALL(call, _("attempt to select more than one element"));
74
    }
75
    if (pos < 0 && length(s) < 1) {
76
	ECALL(call, _("attempt to select less than one element"));
77
    }
45446 ripley 78
 
22883 ripley 79
    if(pos < 0) pos = 0;
1839 ihaka 80
 
10921 maechler 81
    indx = -1;
1839 ihaka 82
    *newname = R_NilValue;
83
    switch(TYPEOF(s)) {
84
    case LGLSXP:
85
    case INTSXP:
41680 ripley 86
	indx = integerOneIndex(INTEGER(s)[pos], len, call);
1839 ihaka 87
	break;
88
    case REALSXP:
59095 ripley 89
	indx = integerOneIndex((int)REAL(s)[pos], len, call);
1839 ihaka 90
	break;
91
    case STRSXP:
63181 ripley 92
	vmax = vmaxget();
59057 ripley 93
	nx = xlength(x);
1839 ihaka 94
	names = getAttrib(x, R_NamesSymbol);
95
	if (names != R_NilValue) {
96
	    /* Try for exact match */
43389 ripley 97
	    for (i = 0; i < nx; i++) {
98
		const char *tmp = translateChar(STRING_ELT(names, i));
99
		if (!tmp[0]) continue;
100
		if (streql(tmp, translateChar(STRING_ELT(s, pos)))) {
10921 maechler 101
		    indx = i;
1839 ihaka 102
		    break;
103
		}
43389 ripley 104
	    }
1839 ihaka 105
	    /* Try for partial match */
10921 maechler 106
	    if (partial && indx < 0) {
59096 ripley 107
		size_t l = strlen(translateChar(STRING_ELT(s, pos)));
1839 ihaka 108
		for(i = 0; i < nx; i++) {
43389 ripley 109
		    const char *tmp = translateChar(STRING_ELT(names, i));
110
		    if (!tmp[0]) continue;
59096 ripley 111
		    if(!strncmp(tmp, translateChar(STRING_ELT(s, pos)), l)) {
10921 maechler 112
			if(indx == -1 )
113
			    indx = i;
1839 ihaka 114
			else
10921 maechler 115
			    indx = -2;
1839 ihaka 116
		    }
117
		}
118
	    }
119
	}
10921 maechler 120
	if (indx == -1)
121
	    indx = nx;
22883 ripley 122
	*newname = STRING_ELT(s, pos);
63181 ripley 123
	vmaxset(vmax);
1839 ihaka 124
	break;
125
    case SYMSXP:
63181 ripley 126
	vmax = vmaxget();
59057 ripley 127
	nx = xlength(x);
1839 ihaka 128
	names = getAttrib(x, R_NamesSymbol);
129
	if (names != R_NilValue) {
130
	    for (i = 0; i < nx; i++)
40705 ripley 131
		if (streql(translateChar(STRING_ELT(names, i)),
132
			   translateChar(PRINTNAME(s)))) {
10921 maechler 133
		    indx = i;
1839 ihaka 134
		    break;
135
		}
136
	}
10921 maechler 137
	if (indx == -1)
138
	    indx = nx;
22883 ripley 139
	*newname = STRING_ELT(s, pos);
63181 ripley 140
	vmaxset(vmax);
1839 ihaka 141
	break;
142
    default:
41686 ripley 143
	if (call == R_NilValue)
144
	    error(_("invalid subscript type '%s'"), type2char(TYPEOF(s)));
145
	else
45446 ripley 146
	    errorcall(call, _("invalid subscript type '%s'"),
41686 ripley 147
		      type2char(TYPEOF(s)));
1839 ihaka 148
    }
10921 maechler 149
    return indx;
1839 ihaka 150
}
151
 
59113 ripley 152
/* used here and in subset.c and subassign.c */
59057 ripley 153
R_xlen_t attribute_hidden
59095 ripley 154
get1index(SEXP s, SEXP names, R_xlen_t len, int pok, int pos, SEXP call)
10718 maechler 155
{
59113 ripley 156
/* Get a single index for the [[ and [[<- operators.
157
   Checks that only one index is being selected.
158
   Returns -1 for no match.
159
 
160
   s is the subscript
161
   len is the length of the object or dimension, with names its (dim)names.
162
   pos is len-1 or -1 for [[, -1 for [[<-
163
     -1 means use the only element of length-1 s.
10718 maechler 164
   pok : is "partial ok" ?
59113 ripley 165
	 if pok is -1, warn if partial matching occurs, but allow.
10718 maechler 166
*/
59057 ripley 167
    int  warn_pok = 0;
41784 ripley 168
    const char *ss, *cur_name;
59057 ripley 169
    R_xlen_t indx;
63181 ripley 170
    const void *vmax;
2 r 171
 
41670 rgentlem 172
    if (pok == -1) {
45446 ripley 173
	pok = 1;
174
	warn_pok = 1;
41670 rgentlem 175
    }
176
 
22883 ripley 177
    if (pos < 0 && length(s) != 1) {
41686 ripley 178
	if (length(s) > 1) {
179
	    ECALL(call, _("attempt to select more than one element"));
180
	} else {
181
	    ECALL(call, _("attempt to select less than one element"));
182
	}
29363 ripley 183
    } else
41686 ripley 184
	if(pos >= length(s)) {
185
	    ECALL(call, _("internal error in use of recursive indexing"));
186
	}
22883 ripley 187
    if(pos < 0) pos = 0;
10921 maechler 188
    indx = -1;
1839 ihaka 189
    switch (TYPEOF(s)) {
190
    case LGLSXP:
191
    case INTSXP:
59057 ripley 192
    {
193
	int i = INTEGER(s)[pos];
59113 ripley 194
	if (i != NA_INTEGER)
195
	    indx = integerOneIndex(i, len, call);
1839 ihaka 196
	break;
59057 ripley 197
    }
1839 ihaka 198
    case REALSXP:
59057 ripley 199
    {
200
	double dblind = REAL(s)[pos];
201
	if(!ISNAN(dblind)) {
59113 ripley 202
	    /* see comment above integerOneIndex */
203
	    if (dblind > 0) indx = (R_xlen_t)(dblind - 1);
59057 ripley 204
	    else if (dblind == 0 || len < 2) {
205
		ECALL(call, _("attempt to select less than one element"));
206
	    } else if (len == 2 && dblind > -3)
59113 ripley 207
		indx = (R_xlen_t)(2 + dblind);
59057 ripley 208
	    else {
209
		ECALL(call, _("attempt to select more than one element"));
210
	    }
211
	}
1839 ihaka 212
	break;
59057 ripley 213
    }
1839 ihaka 214
    case STRSXP:
40705 ripley 215
	/* NA matches nothing */
216
	if(STRING_ELT(s, pos) == NA_STRING) break;
43389 ripley 217
	/* "" matches nothing: see names.Rd */
218
	if(!CHAR(STRING_ELT(s, pos))[0]) break;
45446 ripley 219
 
1839 ihaka 220
	/* Try for exact match */
63181 ripley 221
	vmax = vmaxget();
40705 ripley 222
	ss = translateChar(STRING_ELT(s, pos));
59057 ripley 223
	for (R_xlen_t i = 0; i < xlength(names); i++)
40705 ripley 224
	    if (STRING_ELT(names, i) != NA_STRING) {
225
		if (streql(translateChar(STRING_ELT(names, i)), ss)) {
35796 ripley 226
		    indx = i;
227
		    break;
228
		}
1839 ihaka 229
	    }
230
	/* Try for partial match */
10921 maechler 231
	if (pok && indx < 0) {
59095 ripley 232
	    size_t len = strlen(ss);
59057 ripley 233
	    for(R_xlen_t i = 0; i < xlength(names); i++) {
40705 ripley 234
		if (STRING_ELT(names, i) != NA_STRING) {
45446 ripley 235
		    cur_name = translateChar(STRING_ELT(names, i));
41670 rgentlem 236
		    if(!strncmp(cur_name, ss, len)) {
237
			if(indx == -1) {/* first one */
35796 ripley 238
			    indx = i;
45446 ripley 239
			    if (warn_pok) {
41686 ripley 240
				if (call == R_NilValue)
241
				    warning(_("partial match of '%s' to '%s'"),
41674 ripley 242
					    ss, cur_name);
41686 ripley 243
				else
45446 ripley 244
				    warningcall(call,
41686 ripley 245
						_("partial match of '%s' to '%s'"),
246
						ss, cur_name);
247
			    }
45446 ripley 248
			}
41670 rgentlem 249
			else {
35796 ripley 250
			    indx = -2;/* more than one partial match */
45446 ripley 251
			    if (warn_pok) /* already given context */
252
				warningcall(R_NilValue,
41680 ripley 253
					    _("further partial match of '%s' to '%s'"),
41674 ripley 254
					    ss, cur_name);
45446 ripley 255
			    break;
256
			}
35796 ripley 257
		    }
544 pd 258
		}
1839 ihaka 259
	    }
2 r 260
	}
63181 ripley 261
	vmaxset(vmax);
1839 ihaka 262
	break;
263
    case SYMSXP:
63181 ripley 264
	vmax = vmaxget();
59057 ripley 265
	for (R_xlen_t i = 0; i < xlength(names); i++)
35796 ripley 266
	    if (STRING_ELT(names, i) != NA_STRING &&
45446 ripley 267
		streql(translateChar(STRING_ELT(names, i)),
40705 ripley 268
		       CHAR(PRINTNAME(s)))) {
10921 maechler 269
		indx = i;
63181 ripley 270
		vmaxset(vmax);
1839 ihaka 271
		break;
272
	    }
273
    default:
41686 ripley 274
	if (call == R_NilValue)
275
	    error(_("invalid subscript type '%s'"), type2char(TYPEOF(s)));
276
	else
45446 ripley 277
	    errorcall(call, _("invalid subscript type '%s'"),
41686 ripley 278
		      type2char(TYPEOF(s)));
1839 ihaka 279
    }
10921 maechler 280
    return indx;
2 r 281
}
282
 
59113 ripley 283
/* This is used for [[ and [[<- with a vector of indices of length > 1 .
284
   x is a list or pairlist, and it is indexed recusively from 
285
   level start to level stop-1.  ( 0...len-1 or 0..len-2 then len-1).
63166 luke 286
   For [[<- it needs to duplicate if substructure has NAMED > 1.
59113 ripley 287
 */
49597 ripley 288
SEXP attribute_hidden
63166 luke 289
vectorIndex(SEXP x, SEXP thesub, int start, int stop, int pok, SEXP call,
290
	    Rboolean dup) 
49592 murdoch 291
{
59095 ripley 292
    int i;
293
    R_xlen_t offset;
63166 luke 294
    SEXP cx;
49592 murdoch 295
 
63166 luke 296
    /* sanity check */
297
    if (dup && NAMED(x) > 1)
298
	error("should only be called in an assignment context.");
299
 
49592 murdoch 300
    for(i = start; i < stop; i++) {
52828 ripley 301
	if(!isVectorList(x) && !isPairList(x)) {
302
	    if (i)
303
		errorcall(call, _("recursive indexing failed at level %d\n"), i+1);
304
	    else
305
		errorcall(call, _("attempt to select more than one element"));
306
	}
49592 murdoch 307
	offset = get1index(thesub, getAttrib(x, R_NamesSymbol),
59113 ripley 308
		           xlength(x), pok, i, call);
59095 ripley 309
	if(offset < 0 || offset >= xlength(x))
49592 murdoch 310
	    errorcall(call, _("no such index at level %d\n"), i+1);
311
	if(isPairList(x)) {
59123 ripley 312
#ifdef LONG_VECTOR_SUPPORT
59118 ripley 313
	    if (offset > R_SHORT_LEN_MAX)
59095 ripley 314
		error("invalid subscript for pairlist");
59123 ripley 315
#endif
63166 luke 316
	    cx = nthcdr(x, (int) offset);
317
	    x = CAR(cx);
318
	    if (dup && NAMED(x) > 1) {
319
		x = duplicate(x);
63185 luke 320
		SETCAR(cx, x);
63166 luke 321
	    }
49592 murdoch 322
	} else {
63166 luke 323
	    cx = x;
49592 murdoch 324
	    x = VECTOR_ELT(x, offset);
63166 luke 325
	    if (dup && NAMED(x) > 1) {
326
		x = duplicate(x);
327
		SET_VECTOR_ELT(cx, offset, x);
328
	    }
49592 murdoch 329
    	}
330
    }
331
    return x;
332
}
333
 
60312 ripley 334
/* Special Matrix Subscripting: Handles the case x[i] where
335
   x is an n-way array and i is a matrix with n columns.
336
   This code returns a vector containing the subscripts
337
   to be extracted when x is regarded as unravelled.
2 r 338
 
60312 ripley 339
   Negative indices are not allowed.
59057 ripley 340
 
60312 ripley 341
   A zero/NA anywhere in a row will cause a zero/NA in the same
342
   position in the result.
343
*/
344
 
345
 
41680 ripley 346
SEXP attribute_hidden mat2indsub(SEXP dims, SEXP s, SEXP call)
2 r 347
{
60312 ripley 348
    int nrs = nrows(s);
59057 ripley 349
    R_xlen_t NR = nrs;
1839 ihaka 350
    SEXP rvec;
2 r 351
 
41686 ripley 352
    if (ncols(s) != LENGTH(dims)) {
353
	ECALL(call, _("incorrect number of columns in matrix subscript"));
354
    }
45446 ripley 355
 
59095 ripley 356
#ifdef LONG_VECTOR_SUPPORT
60312 ripley 357
    /* Check if it is a long vector we need to index */
60314 ripley 358
    R_xlen_t len = 1;
60312 ripley 359
    for (int j = 0; j < LENGTH(dims); j++)  len *= INTEGER(dims)[j];
2 r 360
 
60312 ripley 361
    if(len > R_SHORT_LEN_MAX) {
59095 ripley 362
	PROTECT(rvec = allocVector(REALSXP, nrs));
60312 ripley 363
	double *rv = REAL(rvec);
364
	for (int i = 0; i < nrs; i++) rv[i] = 1.; // 1-based.
365
	if (TYPEOF(s) == REALSXP) {
366
	    for (int i = 0; i < nrs; i++) {
367
		R_xlen_t tdim = 1;
368
		for (int j = 0; j < LENGTH(dims); j++) {
369
		    double k = REAL(s)[i + j * NR];
370
		    if(ISNAN(k)) {rv[i] = NA_REAL; break;}
371
		    if(k < 0) {
372
			ECALL(call, _("negative values are not allowed in a matrix subscript"));
373
		    }
374
		    if(k == 0.) {rv[i] = 0.; break;}
375
		    if (k > INTEGER(dims)[j]) {
376
			ECALL(call, _("subscript out of bounds"));
377
		    }
378
		    rv[i] += (k - 1.) * tdim;
379
		    tdim *= INTEGER(dims)[j];
59095 ripley 380
		}
60312 ripley 381
	    }
382
	} else {
383
	    s = coerceVector(s, INTSXP);
384
	    for (int i = 0; i < nrs; i++) {
385
		R_xlen_t tdim = 1;
386
		for (int j = 0; j < LENGTH(dims); j++) {
387
		    int k = INTEGER(s)[i + j * NR];
388
		    if(k == NA_INTEGER) {rv[i] = NA_REAL; break;}
389
		    if(k < 0) {
390
			ECALL(call, _("negative values are not allowed in a matrix subscript"));
391
		    }
392
		    if(k == 0) {rv[i] = 0.; break;}
393
		    if (k > INTEGER(dims)[j]) {
394
			ECALL(call, _("subscript out of bounds"));
395
		    }
396
		    rv[i] += (double) ((k - 1) * tdim);
397
		    tdim *= INTEGER(dims)[j];
59095 ripley 398
		}
1839 ihaka 399
	    }
59095 ripley 400
	}
401
    } else
402
#endif
403
    {
404
	PROTECT(rvec = allocVector(INTSXP, nrs));
60312 ripley 405
	int *iv = INTEGER(rvec);
406
	for (int i = 0; i < nrs; i++) iv[i] = 1; // 1-based.
59095 ripley 407
	s = coerceVector(s, INTSXP);
60312 ripley 408
	for (int i = 0; i < nrs; i++) {
59095 ripley 409
	    int tdim = 1;
60312 ripley 410
	    for (int j = 0; j < LENGTH(dims); j++) {
411
		int k = INTEGER(s)[i + j * NR];
412
		if(k == NA_INTEGER) {iv[i] = NA_INTEGER; break;}
59095 ripley 413
		if(k < 0) {
414
		    ECALL(call, _("negative values are not allowed in a matrix subscript"));
415
		}
60312 ripley 416
		if(k == 0) {iv[i] = 0; break;}
59095 ripley 417
		if (k > INTEGER(dims)[j]) {
418
		    ECALL(call, _("subscript out of bounds"));
419
		}
60312 ripley 420
		iv[i] += (k - 1) * tdim;
59095 ripley 421
		tdim *= INTEGER(dims)[j];
41686 ripley 422
	    }
2 r 423
	}
1839 ihaka 424
    }
59095 ripley 425
 
1839 ihaka 426
    UNPROTECT(1);
60312 ripley 427
    return rvec;
2 r 428
}
429
 
50896 falcon 430
/*
431
Special Matrix Subscripting: For the case x[i] where x is an n-way
432
array and i is a character matrix with n columns, this code converts i
433
to an integer matrix by matching against the dimnames of x. NA values
434
in any row of i propagate to the result.  Unmatched entries result in
435
a subscript out of bounds error.  */
436
 
437
SEXP attribute_hidden strmat2intmat(SEXP s, SEXP dnamelist, SEXP call)
438
{
439
    /* XXX: assumes all args are protected */
59057 ripley 440
    int nr = nrows(s), i, j, v;
441
    R_xlen_t idx, NR = nr;
50896 falcon 442
    SEXP dnames, snames, si, sicol, s_elt;
443
    PROTECT(snames = allocVector(STRSXP, nr));
59057 ripley 444
    PROTECT(si = allocVector(INTSXP, xlength(s)));
50896 falcon 445
    dimgets(si, getAttrib(s, R_DimSymbol));
446
    for (i = 0; i < length(dnamelist); i++) {
447
        dnames = VECTOR_ELT(dnamelist, i);
59095 ripley 448
        for (j = 0; j < nr; j++)
59057 ripley 449
            SET_STRING_ELT(snames, j, STRING_ELT(s, j + (i * NR)));
50896 falcon 450
        PROTECT(sicol = match(dnames, snames, 0));
451
        for (j = 0; j < nr; j++) {
452
            v = INTEGER(sicol)[j];
59057 ripley 453
            idx = j + (i * NR);
50896 falcon 454
            s_elt = STRING_ELT(s, idx);
455
            if (s_elt == NA_STRING) v = NA_INTEGER;
456
            if (!CHAR(s_elt)[0]) v = 0; /* disallow "" match */
457
            if (v == 0) errorcall(call, _("subscript out of bounds"));
458
            INTEGER(si)[idx] = v;
459
        }
460
        UNPROTECT(1);
461
    }
462
    UNPROTECT(2);
463
    return si;
464
}
465
 
59097 ripley 466
static SEXP nullSubscript(R_xlen_t n)
2 r 467
{
10921 maechler 468
    SEXP indx;
59097 ripley 469
#ifdef LONG_VECTOR_SUPPORT
59118 ripley 470
    if (n > R_SHORT_LEN_MAX) {
59097 ripley 471
 	indx = allocVector(REALSXP, n);
472
	for (R_xlen_t i = 0; i < n; i++)
473
	    REAL(indx)[i] = (double)(i + 1);
474
    } else 
475
#endif
476
    {
477
	indx = allocVector(INTSXP, n);
478
	for (int i = 0; i < n; i++)
479
	    INTEGER(indx)[i] = i + 1;
480
    }
10921 maechler 481
    return indx;
2 r 482
}
483
 
59088 ripley 484
 
59046 ripley 485
static SEXP 
59095 ripley 486
logicalSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, R_xlen_t *stretch, SEXP call)
2 r 487
{
59046 ripley 488
    R_xlen_t count, i, nmax;
489
    int canstretch;
10921 maechler 490
    SEXP indx;
59097 ripley 491
    canstretch = *stretch > 0;
41686 ripley 492
    if (!canstretch && ns > nx) {
493
	ECALL(call, _("(subscript) logical subscript too long"));
494
    }
4288 ihaka 495
    nmax = (ns > nx) ? ns : nx;
496
    *stretch = (ns > nx) ? ns : 0;
59065 ripley 497
    if (ns == 0) return(allocVector(INTSXP, 0));
498
#ifdef LONG_VECTOR_SUPPORT
59118 ripley 499
    if (nmax > R_SHORT_LEN_MAX) {
59065 ripley 500
	count = 0;
59097 ripley 501
	for (R_xlen_t i = 0; i < nmax; i++)
59065 ripley 502
	    if (LOGICAL(s)[i%ns]) count++;
59573 luke 503
	indx = allocVector(REALSXP, count);
59065 ripley 504
	count = 0;
505
	for (i = 0; i < nmax; i++)
506
	    if (LOGICAL(s)[i%ns]) {
507
		if (LOGICAL(s)[i%ns] == NA_LOGICAL)
508
		    REAL(indx)[count++] = NA_REAL;
509
		else
59097 ripley 510
		    REAL(indx)[count++] = (double)(i + 1);
59065 ripley 511
	    }
512
	return indx;
513
    }
514
#endif
1839 ihaka 515
    count = 0;
5603 ihaka 516
    for (i = 0; i < nmax; i++)
59065 ripley 517
	if (LOGICAL(s)[i%ns]) count++;
10921 maechler 518
    indx = allocVector(INTSXP, count);
1839 ihaka 519
    count = 0;
27383 rgentlem 520
    for (i = 0; i < nmax; i++)
521
	if (LOGICAL(s)[i%ns]) {
522
	    if (LOGICAL(s)[i%ns] == NA_LOGICAL)
523
		INTEGER(indx)[count++] = NA_INTEGER;
524
	    else
59097 ripley 525
		INTEGER(indx)[count++] = (int)(i + 1);
27383 rgentlem 526
	}
10921 maechler 527
    return indx;
2 r 528
}
529
 
59046 ripley 530
static SEXP negativeSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, SEXP call)
2 r 531
{
27383 rgentlem 532
    SEXP indx;
59095 ripley 533
    R_xlen_t stretch = 0;
59046 ripley 534
    R_xlen_t i;
38545 ripley 535
    PROTECT(indx = allocVector(LGLSXP, nx));
1839 ihaka 536
    for (i = 0; i < nx; i++)
38545 ripley 537
	LOGICAL(indx)[i] = 1;
28762 pd 538
    for (i = 0; i < ns; i++) {
59095 ripley 539
	int ix = INTEGER(s)[i];
28762 pd 540
	if (ix != 0 && ix != NA_INTEGER && -ix <= nx)
38545 ripley 541
	    LOGICAL(indx)[-ix - 1] = 0;
28762 pd 542
    }
41680 ripley 543
    s = logicalSubscript(indx, nx, nx, &stretch, call);
1839 ihaka 544
    UNPROTECT(1);
545
    return s;
2 r 546
}
547
 
59046 ripley 548
static SEXP positiveSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx)
2 r 549
{
10921 maechler 550
    SEXP indx;
59046 ripley 551
    R_xlen_t i, zct = 0;
59057 ripley 552
    for (i = 0; i < ns; i++) if (INTEGER(s)[i] == 0) zct++;
1839 ihaka 553
    if (zct) {
27383 rgentlem 554
	indx = allocVector(INTSXP, (ns - zct));
555
	for (i = 0, zct = 0; i < ns; i++)
556
	    if (INTEGER(s)[i] != 0)
557
		INTEGER(indx)[zct++] = INTEGER(s)[i];
558
	return indx;
59065 ripley 559
 
59057 ripley 560
    } else return s;
2 r 561
}
562
 
59046 ripley 563
static SEXP 
59095 ripley 564
integerSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, R_xlen_t *stretch, SEXP call)
2 r 565
{
59046 ripley 566
    R_xlen_t i;
567
    int ii, min, max, canstretch;
28766 ripley 568
    Rboolean isna = FALSE;
59097 ripley 569
    canstretch = *stretch > 0;
1839 ihaka 570
    *stretch = 0;
27383 rgentlem 571
    min = 0;
1839 ihaka 572
    max = 0;
573
    for (i = 0; i < ns; i++) {
27383 rgentlem 574
	ii = INTEGER(s)[i];
575
	if (ii != NA_INTEGER) {
576
	    if (ii < min)
577
		min = ii;
578
	    if (ii > max)
579
		max = ii;
28766 ripley 580
	} else isna = TRUE;
1839 ihaka 581
    }
582
    if (max > nx) {
27383 rgentlem 583
	if(canstretch) *stretch = max;
41686 ripley 584
	else {
585
	    ECALL(call, _("subscript out of bounds"));
586
	}
1839 ihaka 587
    }
588
    if (min < 0) {
41680 ripley 589
	if (max == 0 && !isna) return negativeSubscript(s, ns, nx, call);
41686 ripley 590
	else {
591
	    ECALL(call, _("only 0's may be mixed with negative subscripts"));
592
	}
1839 ihaka 593
    }
27383 rgentlem 594
    else return positiveSubscript(s, ns, nx);
595
    return R_NilValue;
2 r 596
}
597
 
59065 ripley 598
static SEXP 
59095 ripley 599
realSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, R_xlen_t *stretch, SEXP call)
59065 ripley 600
{
601
    R_xlen_t i;
602
    int canstretch;
603
    double ii, min, max;
604
    Rboolean isna = FALSE;
59097 ripley 605
    canstretch = *stretch > 0;
59065 ripley 606
    *stretch = 0;
607
    min = 0;
608
    max = 0;
609
    for (i = 0; i < ns; i++) {
610
	ii = REAL(s)[i];
611
	if (R_FINITE(ii)) {
612
	    if (ii < min) min = ii;
613
	    if (ii > max) max = ii;
614
	} else isna = TRUE;
615
    }
616
    if (max > nx) {
60200 ripley 617
#ifndef LONG_VECTOR_SUPPORT
618
	if (max > INT_MAX) {
59065 ripley 619
	    ECALL(call, _("subscript too large for 32-bit R"));
620
	}
621
#endif
59095 ripley 622
	if(canstretch) *stretch = (R_xlen_t) max;
59065 ripley 623
	else {
624
	    ECALL(call, _("subscript out of bounds"));
625
	}
626
    }
627
    if (min < 0) {
628
	if (max == 0 && !isna) {
629
	    SEXP indx;
59095 ripley 630
	    R_xlen_t stretch = 0;
59065 ripley 631
	    double dx;
632
	    R_xlen_t i, ix;
633
	    PROTECT(indx = allocVector(LGLSXP, nx));
634
	    for (i = 0; i < nx; i++) LOGICAL(indx)[i] = 1;
635
	    for (i = 0; i < ns; i++) {
636
		dx = REAL(s)[i];
637
		if (R_FINITE(dx) && dx != 0  && -dx <= nx) {
59097 ripley 638
		    ix = (int)(-dx - 1);
59065 ripley 639
		    LOGICAL(indx)[ix] = 0;
59080 ripley 640
		}
59065 ripley 641
	    }
642
	    s = logicalSubscript(indx, nx, nx, &stretch, call);
643
	    UNPROTECT(1);
644
	    return s;
645
	} else {
646
	    ECALL(call, _("only 0's may be mixed with negative subscripts"));
647
	}
648
    } else {
649
	/* Only return a REALSXP index if we need to */
650
	SEXP indx;
651
	R_xlen_t i, cnt = 0;
652
	Rboolean int_ok = TRUE;
59080 ripley 653
	/* NB, indices will be truncated eventually,
654
	   so need to do that to take '0' into account */
59065 ripley 655
	for (i = 0; i < ns; i++) {
656
	    double ds = REAL(s)[i];
59574 luke 657
#ifdef OLDCODE_LONG_VECTOR
59065 ripley 658
	    if (!R_FINITE(ds)) {
59123 ripley 659
		if (ds > INT_MAX) int_ok = FALSE;
59065 ripley 660
		cnt++;
59080 ripley 661
	    } else if ((R_xlen_t) ds != 0) cnt++;
59574 luke 662
#else
663
	    if (R_FINITE(ds) && ds > INT_MAX) 
664
		int_ok = FALSE;
665
	    if ((R_xlen_t) ds != 0) cnt++;
666
#endif
59065 ripley 667
	}
668
	if (int_ok) {
669
	    indx = allocVector(INTSXP, cnt);
670
	    for (i = 0, cnt = 0; i < ns; i++) {
671
		double ds = REAL(s)[i];
59080 ripley 672
		int ia;
673
		if (!R_FINITE(ds)) ia = NA_INTEGER;
59097 ripley 674
		else ia = (int) ds;
59080 ripley 675
		if (ia != 0) INTEGER(indx)[cnt++] = ia;
59065 ripley 676
	    }
677
	} else {
678
	    indx = allocVector(REALSXP, cnt);
59080 ripley 679
	    for (i = 0, cnt = 0; i < ns; i++) {
59097 ripley 680
		R_xlen_t ia = (R_xlen_t) REAL(s)[i];
59080 ripley 681
		if (ia != 0) REAL(indx)[cnt++] = REAL(s)[i];
682
	    }
59065 ripley 683
	}
684
	return indx;
685
    }
686
    return R_NilValue;
687
}
688
 
29363 ripley 689
/* This uses a couple of horrible hacks in conjunction with
690
 * VectorAssign (in subassign.c).  If subscripting is used for
691
 * assignment, it is possible to extend a vector by supplying new
692
 * names, and we want to give the extended vector those names, so they
51067 ripley 693
 * are returned as the use.names attribute. Also, unset elements of the vector
29363 ripley 694
 * of new names (places where a match was found) are indicated by
51067 ripley 695
 * setting the element of the newnames vector to NULL.
29363 ripley 696
*/
697
 
698
/* The original code (pre 2.0.0) used a ns x nx loop that was too
699
 * slow.  So now we hash.  Hashing is expensive on memory (up to 32nx
700
 * bytes) so it is only worth doing if ns * nx is large.  If nx is
701
 * large, then it will be too slow unless ns is very small.
702
 */
703
 
41680 ripley 704
static SEXP
59046 ripley 705
stringSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, SEXP names,
59095 ripley 706
		R_xlen_t *stretch, SEXP call)
2 r 707
{
10921 maechler 708
    SEXP indx, indexnames;
59088 ripley 709
    R_xlen_t i, j, nnames, extra, sub;
59097 ripley 710
    int canstretch = *stretch > 0;
39595 murdoch 711
    /* product may overflow, so check factors as well. */
59066 ripley 712
    Rboolean usehashing = ( ((ns > 1000 && nx) || (nx > 1000 && ns)) || (ns * nx > 15*nx + ns) );
29363 ripley 713
 
1839 ihaka 714
    PROTECT(s);
715
    PROTECT(names);
51067 ripley 716
    PROTECT(indexnames = allocVector(VECSXP, ns));
1839 ihaka 717
    nnames = nx;
718
    extra = nnames;
2 r 719
 
29363 ripley 720
    /* Process each of the subscripts. First we compare with the names
721
     * on the vector and then (if there is no match) with each of the
722
     * previous subscripts, since (if assigning) we may have already
723
     * added an element of that name. (If we are not assigning, any
724
     * nonmatch will have given an error.)
725
     */
2 r 726
 
29363 ripley 727
    if(usehashing) {
728
	/* must be internal, so names contains a character vector */
35796 ripley 729
	/* NB: this does not behave in the same way with respect to ""
730
	   and NA names: they will match */
29363 ripley 731
	PROTECT(indx = match(names, s, 0));
35796 ripley 732
	/* second pass to correct this */
733
	for (i = 0; i < ns; i++)
734
	    if(STRING_ELT(s, i) == NA_STRING || !CHAR(STRING_ELT(s, i))[0])
735
		INTEGER(indx)[i] = 0;
51067 ripley 736
	for (i = 0; i < ns; i++) SET_VECTOR_ELT(indexnames, i, R_NilValue);
29363 ripley 737
    } else {
738
	PROTECT(indx = allocVector(INTSXP, ns));
739
	for (i = 0; i < ns; i++) {
740
	    sub = 0;
741
	    if (names != R_NilValue) {
742
		for (j = 0; j < nnames; j++) {
59066 ripley 743
		    SEXP names_j = STRING_ELT(names, j);
29363 ripley 744
		    if (NonNullStringMatch(STRING_ELT(s, i), names_j)) {
745
			sub = j + 1;
51067 ripley 746
			SET_VECTOR_ELT(indexnames, i, R_NilValue);
29363 ripley 747
			break;
748
		    }
1839 ihaka 749
		}
27383 rgentlem 750
	    }
59097 ripley 751
	    INTEGER(indx)[i] = (int) sub;
2 r 752
	}
29363 ripley 753
    }
754
 
47460 ripley 755
 
29363 ripley 756
    for (i = 0; i < ns; i++) {
757
	sub = INTEGER(indx)[i];
1839 ihaka 758
	if (sub == 0) {
759
	    for (j = 0 ; j < i ; j++)
10172 luke 760
		if (NonNullStringMatch(STRING_ELT(s, i), STRING_ELT(s, j))) {
10921 maechler 761
		    sub = INTEGER(indx)[j];
51067 ripley 762
		    SET_VECTOR_ELT(indexnames, i, STRING_ELT(s, j));
1839 ihaka 763
		    break;
764
		}
765
	}
766
	if (sub == 0) {
41686 ripley 767
	    if (!canstretch) {
768
		ECALL(call, _("subscript out of bounds"));
769
	    }
1839 ihaka 770
	    extra += 1;
771
	    sub = extra;
51067 ripley 772
	    SET_VECTOR_ELT(indexnames, i, STRING_ELT(s, i));
1839 ihaka 773
	}
59097 ripley 774
	INTEGER(indx)[i] = (int) sub;
1839 ihaka 775
    }
38655 ripley 776
    /* We return the new names as the names attribute of the returned
777
       subscript vector. */
29363 ripley 778
    if (extra != nnames)
51067 ripley 779
	setAttrib(indx, R_UseNamesSymbol, indexnames);
8505 pd 780
    if (canstretch)
781
	*stretch = extra;
10718 maechler 782
    UNPROTECT(4);
10921 maechler 783
    return indx;
2 r 784
}
785
 
29363 ripley 786
/* Array Subscripts.
14913 rgentlem 787
    dim is the dimension (0 to k-1)
29363 ripley 788
    s is the subscript list,
14913 rgentlem 789
    dims is the dimensions of x
790
    dng is a function (usually getAttrib) that obtains the dimnames
29363 ripley 791
    x is the array to be subscripted.
14913 rgentlem 792
*/
2 r 793
 
59086 ripley 794
attribute_hidden SEXP
59066 ripley 795
int_arraySubscript(int dim, SEXP s, SEXP dims, SEXP x, SEXP call)
2 r 796
{
59095 ripley 797
    int nd, ns;
798
    R_xlen_t stretch = 0;
14913 rgentlem 799
    SEXP dnames, tmp;
1839 ihaka 800
    ns = length(s);
801
    nd = INTEGER(dims)[dim];
2 r 802
 
1839 ihaka 803
    switch (TYPEOF(s)) {
804
    case NILSXP:
805
	return allocVector(INTSXP, 0);
806
    case LGLSXP:
41680 ripley 807
	return logicalSubscript(s, ns, nd, &stretch, call);
1839 ihaka 808
    case INTSXP:
41680 ripley 809
	return integerSubscript(s, ns, nd, &stretch, call);
1839 ihaka 810
    case REALSXP:
59118 ripley 811
	/* We don't yet allow subscripts > R_SHORT_LEN_MAX */
45446 ripley 812
	PROTECT(tmp = coerceVector(s, INTSXP));
41680 ripley 813
	tmp = integerSubscript(tmp, ns, nd, &stretch, call);
45446 ripley 814
	UNPROTECT(1);
2504 pd 815
	return tmp;
1839 ihaka 816
    case STRSXP:
59066 ripley 817
	dnames = getAttrib(x, R_DimNamesSymbol);
41686 ripley 818
	if (dnames == R_NilValue) {
819
	    ECALL(call, _("no 'dimnames' attribute for array"));
820
	}
10172 luke 821
	dnames = VECTOR_ELT(dnames, dim);
59066 ripley 822
	return stringSubscript(s, ns, nd, dnames, &stretch, call);
1839 ihaka 823
    case SYMSXP:
824
	if (s == R_MissingArg)
825
	    return nullSubscript(nd);
826
    default:
41686 ripley 827
	if (call == R_NilValue)
828
	    error(_("invalid subscript type '%s'"), type2char(TYPEOF(s)));
829
	else
45446 ripley 830
	    errorcall(call, _("invalid subscript type '%s'"),
41686 ripley 831
		      type2char(TYPEOF(s)));
1839 ihaka 832
    }
833
    return R_NilValue;
2 r 834
}
835
 
59066 ripley 836
/* This is used by packages arules, cba, proxy and seriation. */
837
typedef SEXP AttrGetter(SEXP x, SEXP data);
838
typedef SEXP (*StringEltGetter)(SEXP x, int i);
839
 
38676 ripley 840
SEXP
36990 ripley 841
arraySubscript(int dim, SEXP s, SEXP dims, AttrGetter dng,
842
	       StringEltGetter strg, SEXP x)
29363 ripley 843
{
59066 ripley 844
    return int_arraySubscript(dim, s, dims, x, R_NilValue);
29363 ripley 845
}
846
 
1839 ihaka 847
/* Subscript creation.  The first thing we do is check to see */
848
/* if there are any user supplied NULL's, these result in */
849
/* returning a vector of length 0. */
15317 rgentlem 850
/* if stretch is zero on entry then the vector x cannot be
851
   "stretched",
852
   otherwise, stretch returns the new required length for x
853
*/
2 r 854
 
59066 ripley 855
static SEXP 
59095 ripley 856
vectorSubscript(R_xlen_t nx, SEXP s, R_xlen_t *stretch, SEXP x, SEXP call);
59066 ripley 857
 
59095 ripley 858
SEXP attribute_hidden 
859
makeSubscript(SEXP x, SEXP s, R_xlen_t *stretch, SEXP call)
2 r 860
{
15317 rgentlem 861
    SEXP ans;
2 r 862
 
1839 ihaka 863
    ans = R_NilValue;
864
    if (isVector(x) || isList(x) || isLanguage(x)) {
59066 ripley 865
	ans = vectorSubscript(xlength(x), s, stretch, x, call);
59046 ripley 866
    } else {
41686 ripley 867
	ECALL(call, _("subscripting on non-vector"));
868
    }
15317 rgentlem 869
    return ans;
870
 
871
}
872
 
873
/* nx is the length of the object being subscripted,
59066 ripley 874
   s is the R subscript value.
15317 rgentlem 875
*/
29363 ripley 876
 
45446 ripley 877
static SEXP
59095 ripley 878
vectorSubscript(R_xlen_t nx, SEXP s, R_xlen_t *stretch, SEXP x, SEXP call)
15317 rgentlem 879
{
59065 ripley 880
    SEXP ans = R_NilValue;
15317 rgentlem 881
 
59046 ripley 882
    R_xlen_t ns = xlength(s);
15317 rgentlem 883
    /* special case for simple indices -- does not duplicate */
884
    if (ns == 1 && TYPEOF(s) == INTSXP && ATTRIB(s) == R_NilValue) {
885
	int i = INTEGER(s)[0];
886
	if (0 < i && i <= nx) {
10782 luke 887
	    *stretch = 0;
888
	    return s;
889
	}
15317 rgentlem 890
    }
38655 ripley 891
    PROTECT(s = duplicate(s));
15317 rgentlem 892
    SET_ATTRIB(s, R_NilValue);
38952 ripley 893
    SET_OBJECT(s, 0);
15317 rgentlem 894
    switch (TYPEOF(s)) {
895
    case NILSXP:
896
	*stretch = 0;
897
	ans = allocVector(INTSXP, 0);
898
	break;
899
    case LGLSXP:
41680 ripley 900
	ans = logicalSubscript(s, ns, nx, stretch, call);
15317 rgentlem 901
	break;
902
    case INTSXP:
42414 ripley 903
	ans = integerSubscript(s, ns, nx, stretch, call);
904
	break;
15317 rgentlem 905
    case REALSXP:
59065 ripley 906
	ans = realSubscript(s, ns, nx, stretch, call);
15317 rgentlem 907
	break;
908
    case STRSXP:
909
    {
59066 ripley 910
	SEXP names = getAttrib(x, R_NamesSymbol);
15317 rgentlem 911
	/* *stretch = 0; */
59066 ripley 912
	ans = stringSubscript(s, ns, nx, names, stretch, call);
15317 rgentlem 913
    }
914
    break;
915
    case SYMSXP:
916
	*stretch = 0;
917
	if (s == R_MissingArg) {
918
	    ans = nullSubscript(nx);
1839 ihaka 919
	    break;
2 r 920
	}
15317 rgentlem 921
    default:
41686 ripley 922
	if (call == R_NilValue)
923
	    error(_("invalid subscript type '%s'"), type2char(TYPEOF(s)));
924
	else
45446 ripley 925
	    errorcall(call, _("invalid subscript type '%s'"),
41686 ripley 926
		      type2char(TYPEOF(s)));
1839 ihaka 927
    }
15317 rgentlem 928
    UNPROTECT(1);
1839 ihaka 929
    return ans;
2 r 930
}