The R Project SVN R

Rev

Rev 89130 | 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
87891 ripley 3
 *  Copyright (C) 1997--2025  The R Core Team
2 r 4
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
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
68947 ripley 18
 *  https://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]"     "    "            "
81258 maechler 27
 *  strmat2intmat()   -- for "mat[<ch>]"  "    "            "
47040 maechler 28
 
49592 murdoch 29
 *  makeSubscript()   -- for "[" and "[<-" in ./subset.c and ./subassign.c,
30
 *			 and "[[<-" with a scalar in ./subassign.c
47040 maechler 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
 
67645 urbaneks 40
#include <R_ext/Itermacros.h>
41
 
42
/* interval at which to check interrupts, a guess (~subsecond on current hw) */
43
#define NINTERRUPT 10000000
44
 
41686 ripley 45
/* We might get a call with R_NilValue from subassignment code */
69576 maechler 46
#define ECALL(call, yy)     if(call == R_NilValue) error(yy);    else errorcall(call, yy);
47
#define ECALL3(call, yy, A) if(call == R_NilValue) error(yy, A); else errorcall(call, yy, A);
81258 maechler 48
#define ECALL4(call, yy, A, B) if(call == R_NilValue) error(yy, A, B); else errorcall(call, yy, A, B);
41686 ripley 49
 
83454 ripley 50
NORET static void ECALL_OutOfBounds(SEXP x, int subscript,
81144 luke 51
				    R_xlen_t index, SEXP call)
52
{
53
    if (call == R_NilValue)
54
	call = R_CurrentExpression; /* default behaves like error() */
55
    SEXP sindex = ScalarReal((double) index);
56
    PROTECT(sindex);
57
    SEXP cond = R_makeOutOfBoundsError(x, subscript, sindex, call, NULL);
58
    PROTECT(cond);
59
    R_signalErrorCondition(cond, call);
60
    UNPROTECT(2); /* sindex, cond; not reached */
61
}
62
 
83454 ripley 63
NORET static void ECALL_MissingSubs(SEXP call) // no x
82544 maechler 64
{
65
    if (call == R_NilValue)
66
	call = R_CurrentExpression;
67
    SEXP cond = R_makeMissingSubscriptError1(call);
68
    PROTECT(cond);
69
    R_signalErrorCondition(cond, call);
70
    UNPROTECT(1); /* cond; not reached */
71
}
72
 
83454 ripley 73
NORET static void ECALL_OutOfBoundsCHAR(SEXP x, int subscript,
81144 luke 74
					SEXP sindex, SEXP call)
75
{
76
    if (call == R_NilValue)
77
	call = R_CurrentExpression; /* default behaves like error() */
78
    sindex = ScalarString(sindex);
79
    PROTECT(sindex);
80
    SEXP cond = R_makeOutOfBoundsError(x, subscript, sindex, call, NULL);
81
    PROTECT(cond);
82
    R_signalErrorCondition(cond, call);
83
    UNPROTECT(2); /* sindex, cond; not reached */
84
}
85
 
59113 ripley 86
/* This allows for the unusual case where x is of length 2,
87
   and x[[-m]] selects one element for m = 1, 2.
88
   So 'len' is only used if it is 2 and i is negative.
89
*/
90
static R_INLINE int integerOneIndex(int i, R_xlen_t len, SEXP call)
41680 ripley 91
{
10921 maechler 92
    int indx = -1;
4562 pd 93
 
59113 ripley 94
    if (i > 0) /* a regular 1-based index from R */
10921 maechler 95
	indx = i - 1;
41686 ripley 96
    else if (i == 0 || len < 2) {
69576 maechler 97
	ECALL3(call, _("attempt to select less than one element in %s"), "integerOneIndex");
41686 ripley 98
    } else if (len == 2 && i > -3)
10921 maechler 99
	indx = 2 + i;
41686 ripley 100
    else {
69576 maechler 101
	ECALL3(call, _("attempt to select more than one element in %s"), "integerOneIndex");
41686 ripley 102
    }
59113 ripley 103
    return indx;
4562 pd 104
}
105
 
47040 maechler 106
/* Utility used (only in) do_subassign2_dflt(), i.e. "[[<-" in ./subassign.c : */
87901 ripley 107
attribute_hidden R_xlen_t
74145 maechler 108
OneIndex(SEXP x, SEXP s, R_xlen_t nx, int partial, SEXP *newname,
59095 ripley 109
	 int pos, SEXP call)
1839 ihaka 110
{
111
    SEXP names;
74145 maechler 112
    R_xlen_t i, indx;
63181 ripley 113
    const void *vmax;
2 r 114
 
41686 ripley 115
    if (pos < 0 && length(s) > 1) {
69576 maechler 116
	ECALL3(call, _("attempt to select more than one element in %s"), "OneIndex");
41686 ripley 117
    }
118
    if (pos < 0 && length(s) < 1) {
69576 maechler 119
	ECALL3(call, _("attempt to select less than one element in %s"), "OneIndex");
41686 ripley 120
    }
45446 ripley 121
 
22883 ripley 122
    if(pos < 0) pos = 0;
1839 ihaka 123
 
10921 maechler 124
    indx = -1;
1839 ihaka 125
    *newname = R_NilValue;
126
    switch(TYPEOF(s)) {
127
    case LGLSXP:
128
    case INTSXP:
74145 maechler 129
	indx = integerOneIndex(INTEGER_ELT(s, pos), nx, call);
1839 ihaka 130
	break;
131
    case REALSXP:
79295 maechler 132
    {
133
	double dblind = REAL_ELT(s, pos);
134
	if(!ISNAN(dblind)) {
135
	    /* see comment above integerOneIndex */
81380 maechler 136
	    if (dblind >= 1) indx = (R_xlen_t)(dblind - 1);
137
	    else if (dblind > -1 || nx < 2) {
79295 maechler 138
		ECALL3(call, _("attempt to select less than one element in %s"), "OneIndex <real>");
139
	    } else if (nx == 2 && dblind > -3)
81380 maechler 140
		indx = 2 + (R_xlen_t) dblind;
79295 maechler 141
	    else {
142
		ECALL3(call, _("attempt to select more than one element in %s"), "OneIndex <real>");
143
	    }
144
	}
1839 ihaka 145
	break;
79295 maechler 146
    }
1839 ihaka 147
    case STRSXP:
63181 ripley 148
	vmax = vmaxget();
74145 maechler 149
	names = getAttrib(x, R_NamesSymbol);
1839 ihaka 150
	if (names != R_NilValue) {
74145 maechler 151
	    PROTECT(names);
1839 ihaka 152
	    /* Try for exact match */
43389 ripley 153
	    for (i = 0; i < nx; i++) {
154
		const char *tmp = translateChar(STRING_ELT(names, i));
155
		if (!tmp[0]) continue;
156
		if (streql(tmp, translateChar(STRING_ELT(s, pos)))) {
10921 maechler 157
		    indx = i;
1839 ihaka 158
		    break;
159
		}
43389 ripley 160
	    }
73114 maechler 161
	    // Try for partial match -- not ever used in current R (partial is 0)
10921 maechler 162
	    if (partial && indx < 0) {
59096 ripley 163
		size_t l = strlen(translateChar(STRING_ELT(s, pos)));
1839 ihaka 164
		for(i = 0; i < nx; i++) {
43389 ripley 165
		    const char *tmp = translateChar(STRING_ELT(names, i));
166
		    if (!tmp[0]) continue;
59096 ripley 167
		    if(!strncmp(tmp, translateChar(STRING_ELT(s, pos)), l)) {
10921 maechler 168
			if(indx == -1 )
169
			    indx = i;
1839 ihaka 170
			else
10921 maechler 171
			    indx = -2;
1839 ihaka 172
		    }
173
		}
174
	    }
74145 maechler 175
	    UNPROTECT(1); /* names */
1839 ihaka 176
	}
10921 maechler 177
	if (indx == -1)
178
	    indx = nx;
22883 ripley 179
	*newname = STRING_ELT(s, pos);
63181 ripley 180
	vmaxset(vmax);
1839 ihaka 181
	break;
182
    case SYMSXP:
63181 ripley 183
	vmax = vmaxget();
1839 ihaka 184
	names = getAttrib(x, R_NamesSymbol);
185
	if (names != R_NilValue) {
68392 luke 186
	    PROTECT(names);
1839 ihaka 187
	    for (i = 0; i < nx; i++)
40705 ripley 188
		if (streql(translateChar(STRING_ELT(names, i)),
85209 luke 189
			   CHAR(PRINTNAME(s)))) {
10921 maechler 190
		    indx = i;
1839 ihaka 191
		    break;
192
		}
68392 luke 193
	    UNPROTECT(1); /* names */
1839 ihaka 194
	}
10921 maechler 195
	if (indx == -1)
196
	    indx = nx;
73521 luke 197
	*newname = PRINTNAME(s);
63181 ripley 198
	vmaxset(vmax);
1839 ihaka 199
	break;
200
    default:
85146 luke 201
	ECALL3(call, _("invalid subscript type '%s'"), R_typeToChar(s));
1839 ihaka 202
    }
10921 maechler 203
    return indx;
1839 ihaka 204
}
205
 
59113 ripley 206
/* used here and in subset.c and subassign.c */
87901 ripley 207
attribute_hidden R_xlen_t
59095 ripley 208
get1index(SEXP s, SEXP names, R_xlen_t len, int pok, int pos, SEXP call)
10718 maechler 209
{
59113 ripley 210
/* Get a single index for the [[ and [[<- operators.
211
   Checks that only one index is being selected.
212
   Returns -1 for no match.
213
 
214
   s is the subscript
215
   len is the length of the object or dimension, with names its (dim)names.
216
   pos is len-1 or -1 for [[, -1 for [[<-
217
     -1 means use the only element of length-1 s.
10718 maechler 218
   pok : is "partial ok" ?
59113 ripley 219
	 if pok is -1, warn if partial matching occurs, but allow.
10718 maechler 220
*/
41784 ripley 221
    const char *ss, *cur_name;
63181 ripley 222
    const void *vmax;
2 r 223
 
78184 maechler 224
    int warn_pok = (pok == -1);
225
    if (warn_pok)
45446 ripley 226
	pok = 1;
41670 rgentlem 227
 
22883 ripley 228
    if (pos < 0 && length(s) != 1) {
41686 ripley 229
	if (length(s) > 1) {
69576 maechler 230
	    ECALL3(call, _("attempt to select more than one element in %s"), "get1index");
41686 ripley 231
	} else {
69576 maechler 232
	    ECALL3(call, _("attempt to select less than one element in %s"), "get1index");
41686 ripley 233
	}
78184 maechler 234
    } else if(pos >= length(s)) {
235
	ECALL(call, _("internal error in use of recursive indexing"));
236
    }
22883 ripley 237
    if(pos < 0) pos = 0;
78184 maechler 238
    R_xlen_t indx = -1;
1839 ihaka 239
    switch (TYPEOF(s)) {
240
    case LGLSXP:
241
    case INTSXP:
59057 ripley 242
    {
73567 luke 243
	int i = INTEGER_ELT(s, pos);
59113 ripley 244
	if (i != NA_INTEGER)
245
	    indx = integerOneIndex(i, len, call);
1839 ihaka 246
	break;
59057 ripley 247
    }
1839 ihaka 248
    case REALSXP:
59057 ripley 249
    {
73567 luke 250
	double dblind = REAL_ELT(s, pos);
59057 ripley 251
	if(!ISNAN(dblind)) {
59113 ripley 252
	    /* see comment above integerOneIndex */
81380 maechler 253
	    if (dblind >= 1) {
78184 maechler 254
		if(R_FINITE(dblind)) indx = (R_xlen_t)(dblind - 1);
81380 maechler 255
	    } else if (dblind > -1 || len < 2) {
78184 maechler 256
		ECALL3(call,
81380 maechler 257
		       (dblind <= -1) ? _("invalid negative subscript in %s")
80533 maechler 258
		       : _("attempt to select less than one element in %s"),
78184 maechler 259
		       "get1index <real>");
260
	    } else if (len == 2 && dblind > -3) // dblind = -2 or -1 {why exception ?}
81380 maechler 261
		indx = 2 + (R_xlen_t) dblind;
59057 ripley 262
	    else {
78184 maechler 263
		ECALL3(call,
81380 maechler 264
		       (dblind <= -1) ? _("invalid negative subscript in %s")
80533 maechler 265
		       : _("attempt to select more than one element in %s"),
78184 maechler 266
		       "get1index <real>");
59057 ripley 267
	    }
268
	}
1839 ihaka 269
	break;
59057 ripley 270
    }
1839 ihaka 271
    case STRSXP:
40705 ripley 272
	/* NA matches nothing */
273
	if(STRING_ELT(s, pos) == NA_STRING) break;
43389 ripley 274
	/* "" matches nothing: see names.Rd */
275
	if(!CHAR(STRING_ELT(s, pos))[0]) break;
45446 ripley 276
 
1839 ihaka 277
	/* Try for exact match */
63181 ripley 278
	vmax = vmaxget();
40705 ripley 279
	ss = translateChar(STRING_ELT(s, pos));
59057 ripley 280
	for (R_xlen_t i = 0; i < xlength(names); i++)
40705 ripley 281
	    if (STRING_ELT(names, i) != NA_STRING) {
282
		if (streql(translateChar(STRING_ELT(names, i)), ss)) {
35796 ripley 283
		    indx = i;
284
		    break;
285
		}
1839 ihaka 286
	    }
287
	/* Try for partial match */
10921 maechler 288
	if (pok && indx < 0) {
59095 ripley 289
	    size_t len = strlen(ss);
59057 ripley 290
	    for(R_xlen_t i = 0; i < xlength(names); i++) {
40705 ripley 291
		if (STRING_ELT(names, i) != NA_STRING) {
45446 ripley 292
		    cur_name = translateChar(STRING_ELT(names, i));
41670 rgentlem 293
		    if(!strncmp(cur_name, ss, len)) {
294
			if(indx == -1) {/* first one */
35796 ripley 295
			    indx = i;
45446 ripley 296
			    if (warn_pok) {
41686 ripley 297
				if (call == R_NilValue)
298
				    warning(_("partial match of '%s' to '%s'"),
41674 ripley 299
					    ss, cur_name);
41686 ripley 300
				else
45446 ripley 301
				    warningcall(call,
41686 ripley 302
						_("partial match of '%s' to '%s'"),
303
						ss, cur_name);
304
			    }
45446 ripley 305
			}
41670 rgentlem 306
			else {
35796 ripley 307
			    indx = -2;/* more than one partial match */
45446 ripley 308
			    if (warn_pok) /* already given context */
309
				warningcall(R_NilValue,
41680 ripley 310
					    _("further partial match of '%s' to '%s'"),
41674 ripley 311
					    ss, cur_name);
45446 ripley 312
			    break;
313
			}
35796 ripley 314
		    }
544 pd 315
		}
1839 ihaka 316
	    }
2 r 317
	}
63181 ripley 318
	vmaxset(vmax);
1839 ihaka 319
	break;
320
    case SYMSXP:
82544 maechler 321
	if (s == R_MissingArg) {
322
	    ECALL_MissingSubs(call);
323
	}
63181 ripley 324
	vmax = vmaxget();
59057 ripley 325
	for (R_xlen_t i = 0; i < xlength(names); i++)
35796 ripley 326
	    if (STRING_ELT(names, i) != NA_STRING &&
45446 ripley 327
		streql(translateChar(STRING_ELT(names, i)),
40705 ripley 328
		       CHAR(PRINTNAME(s)))) {
10921 maechler 329
		indx = i;
63181 ripley 330
		vmaxset(vmax);
1839 ihaka 331
		break;
332
	    }
72958 maechler 333
	break;
1839 ihaka 334
    default:
85146 luke 335
	ECALL3(call, _("invalid subscript type '%s'"), R_typeToChar(s));
1839 ihaka 336
    }
10921 maechler 337
    return indx;
2 r 338
}
339
 
59113 ripley 340
/* This is used for [[ and [[<- with a vector of indices of length > 1 .
68754 maechler 341
   x is a list or pairlist, and it is indexed recusively from
59113 ripley 342
   level start to level stop-1.  ( 0...len-1 or 0..len-2 then len-1).
65021 luke 343
   For [[<- it needs to duplicate if substructure might be shared.
59113 ripley 344
 */
83446 ripley 345
attribute_hidden SEXP
63166 luke 346
vectorIndex(SEXP x, SEXP thesub, int start, int stop, int pok, SEXP call,
68754 maechler 347
	    Rboolean dup)
49592 murdoch 348
{
63166 luke 349
    /* sanity check */
65021 luke 350
    if (dup && MAYBE_SHARED(x))
63166 luke 351
	error("should only be called in an assignment context.");
352
 
87184 maechler 353
    for(int i = start; i < stop; i++) {
52828 ripley 354
	if(!isVectorList(x) && !isPairList(x)) {
355
	    if (i)
356
		errorcall(call, _("recursive indexing failed at level %d\n"), i+1);
357
	    else
69576 maechler 358
		errorcall(call, _("attempt to select more than one element in %s"), "vectorIndex");
52828 ripley 359
	}
68250 luke 360
	PROTECT(x);
87184 maechler 361
	SEXP cx, names = PROTECT(getAttrib(x, R_NamesSymbol));
362
	R_xlen_t offset = get1index(thesub, names, xlength(x), pok, i, call);
68250 luke 363
	UNPROTECT(2); /* x, names */
59095 ripley 364
	if(offset < 0 || offset >= xlength(x))
49592 murdoch 365
	    errorcall(call, _("no such index at level %d\n"), i+1);
366
	if(isPairList(x)) {
59123 ripley 367
#ifdef LONG_VECTOR_SUPPORT
59118 ripley 368
	    if (offset > R_SHORT_LEN_MAX)
59095 ripley 369
		error("invalid subscript for pairlist");
59123 ripley 370
#endif
63166 luke 371
	    cx = nthcdr(x, (int) offset);
74021 luke 372
	    RAISE_NAMED(CAR(x), NAMED(x));
63166 luke 373
	    x = CAR(cx);
65021 luke 374
	    if (dup && MAYBE_SHARED(x)) {
72506 kalibera 375
		PROTECT(cx);
64970 luke 376
		x = shallow_duplicate(x);
63185 luke 377
		SETCAR(cx, x);
72506 kalibera 378
		UNPROTECT(1); /* cx */
63166 luke 379
	    }
49592 murdoch 380
	} else {
63166 luke 381
	    cx = x;
49592 murdoch 382
	    x = VECTOR_ELT(x, offset);
74021 luke 383
	    RAISE_NAMED(x, NAMED(cx));
65021 luke 384
	    if (dup && MAYBE_SHARED(x)) {
72506 kalibera 385
		PROTECT(cx);
64970 luke 386
		x = shallow_duplicate(x);
63166 luke 387
		SET_VECTOR_ELT(cx, offset, x);
72506 kalibera 388
		UNPROTECT(1); /* cx */
63166 luke 389
	    }
68923 ripley 390
	}
49592 murdoch 391
    }
392
    return x;
393
}
394
 
60312 ripley 395
/* Special Matrix Subscripting: Handles the case x[i] where
396
   x is an n-way array and i is a matrix with n columns.
397
   This code returns a vector containing the subscripts
398
   to be extracted when x is regarded as unravelled.
2 r 399
 
60312 ripley 400
   Negative indices are not allowed.
59057 ripley 401
 
60312 ripley 402
   A zero/NA anywhere in a row will cause a zero/NA in the same
403
   position in the result.
404
*/
81380 maechler 405
/*
406
  Called from `[`   VectorSubset()    ./subset.c	and
407
              `[<-` VectorSubassign() ./subassign.c
60312 ripley 408
 
81380 maechler 409
  only if(isMatrix(s) && isArray(x) && ncols(s) == "length(dim(x))"),
410
  where dims = getAttrib(x, R_DimSymbol);
411
*/
83446 ripley 412
attribute_hidden SEXP mat2indsub(SEXP dims, SEXP s, SEXP call, SEXP x)
2 r 413
{
60312 ripley 414
    int nrs = nrows(s);
59057 ripley 415
    R_xlen_t NR = nrs;
1839 ihaka 416
    SEXP rvec;
73567 luke 417
    int ndim = LENGTH(dims);
73729 luke 418
    const int *pdims = INTEGER_RO(dims);
2 r 419
 
73567 luke 420
    if (ncols(s) != ndim) {
41686 ripley 421
	ECALL(call, _("incorrect number of columns in matrix subscript"));
422
    }
45446 ripley 423
 
59095 ripley 424
#ifdef LONG_VECTOR_SUPPORT
60312 ripley 425
    /* Check if it is a long vector we need to index */
60314 ripley 426
    R_xlen_t len = 1;
73567 luke 427
    for (int j = 0; j < ndim; j++)  len *= pdims[j];
2 r 428
 
60312 ripley 429
    if(len > R_SHORT_LEN_MAX) {
59095 ripley 430
	PROTECT(rvec = allocVector(REALSXP, nrs));
60312 ripley 431
	double *rv = REAL(rvec);
432
	for (int i = 0; i < nrs; i++) rv[i] = 1.; // 1-based.
433
	if (TYPEOF(s) == REALSXP) {
434
	    for (int i = 0; i < nrs; i++) {
435
		R_xlen_t tdim = 1;
73729 luke 436
		const double *ps = REAL_RO(s);
73567 luke 437
		for (int j = 0; j < ndim; j++) {
438
		    double k = ps[i + j * NR];
60312 ripley 439
		    if(ISNAN(k)) {rv[i] = NA_REAL; break;}
81380 maechler 440
		    k = trunc(k); // = "as.integer(k)" for large k
60312 ripley 441
		    if(k < 0) {
442
			ECALL(call, _("negative values are not allowed in a matrix subscript"));
443
		    }
444
		    if(k == 0.) {rv[i] = 0.; break;}
73567 luke 445
		    if (k > pdims[j]) {
81186 ripley 446
			ECALL_OutOfBounds(x, j, (R_xlen_t)k, call);
60312 ripley 447
		    }
87184 maechler 448
		    rv[i] += (k - 1.) * (double)tdim;
73567 luke 449
		    tdim *= pdims[j];
59095 ripley 450
		}
60312 ripley 451
	    }
452
	} else {
453
	    s = coerceVector(s, INTSXP);
73729 luke 454
	    const int *ps = INTEGER_RO(s);
60312 ripley 455
	    for (int i = 0; i < nrs; i++) {
456
		R_xlen_t tdim = 1;
73567 luke 457
		for (int j = 0; j < ndim; j++) {
458
		    int k = ps[i + j * NR];
60312 ripley 459
		    if(k == NA_INTEGER) {rv[i] = NA_REAL; break;}
460
		    if(k < 0) {
461
			ECALL(call, _("negative values are not allowed in a matrix subscript"));
462
		    }
463
		    if(k == 0) {rv[i] = 0.; break;}
73567 luke 464
		    if (k > pdims[j]) {
81144 luke 465
			ECALL_OutOfBounds(x, j, k, call);
60312 ripley 466
		    }
467
		    rv[i] += (double) ((k - 1) * tdim);
73567 luke 468
		    tdim *= pdims[j];
59095 ripley 469
		}
1839 ihaka 470
	    }
59095 ripley 471
	}
472
    } else
473
#endif
474
    {
475
	PROTECT(rvec = allocVector(INTSXP, nrs));
60312 ripley 476
	int *iv = INTEGER(rvec);
477
	for (int i = 0; i < nrs; i++) iv[i] = 1; // 1-based.
59095 ripley 478
	s = coerceVector(s, INTSXP);
73567 luke 479
	int *ps = INTEGER(s);
60312 ripley 480
	for (int i = 0; i < nrs; i++) {
59095 ripley 481
	    int tdim = 1;
73567 luke 482
	    for (int j = 0; j < ndim; j++) {
483
		int k = ps[i + j * NR];
60312 ripley 484
		if(k == NA_INTEGER) {iv[i] = NA_INTEGER; break;}
59095 ripley 485
		if(k < 0) {
486
		    ECALL(call, _("negative values are not allowed in a matrix subscript"));
487
		}
60312 ripley 488
		if(k == 0) {iv[i] = 0; break;}
73567 luke 489
		if (k > pdims[j]) {
81144 luke 490
		    ECALL_OutOfBounds(x, j, k, call);
59095 ripley 491
		}
60312 ripley 492
		iv[i] += (k - 1) * tdim;
73567 luke 493
		tdim *= pdims[j];
41686 ripley 494
	    }
2 r 495
	}
1839 ihaka 496
    }
59095 ripley 497
 
1839 ihaka 498
    UNPROTECT(1);
60312 ripley 499
    return rvec;
2 r 500
}
501
 
50896 falcon 502
/*
503
Special Matrix Subscripting: For the case x[i] where x is an n-way
504
array and i is a character matrix with n columns, this code converts i
505
to an integer matrix by matching against the dimnames of x. NA values
506
in any row of i propagate to the result.  Unmatched entries result in
507
a subscript out of bounds error.  */
81258 maechler 508
/*
509
  Called from `[`   VectorSubset()    ./subset.c	and
510
              `[<-` VectorSubassign() ./subassign.c
81261 maechler 511
 
512
  only if(isMatrix(s) && isArray(x) && ncols(s) == "length(dim(x))"),
81258 maechler 513
  where dnamelist = PROTECT(GetArrayDimnames(x))
514
 */
83446 ripley 515
attribute_hidden SEXP strmat2intmat(SEXP s, SEXP dnamelist, SEXP call, SEXP x)
50896 falcon 516
{
517
    /* XXX: assumes all args are protected */
81258 maechler 518
    SEXP dim = getAttrib(s, R_DimSymbol);
519
    int nr = INTEGER(dim)[0], // = nrow(s)
520
	nc = INTEGER(dim)[1]; // = ncol(s)
521
    if(isNull(dnamelist)) { // && nr > 0)
522
#if 1
523
	ECALL(call, _("no 'dimnames' attribute for array")); // as in  arraySubscript()
524
#else
525
	ECALL4(call,
526
          _("%d x %d character matrix subscript illegal for NULL dimnames"),
527
	       nr, nc);
528
#endif
529
    }
81261 maechler 530
#if 0 /* unneeded as only called  if (length(dnamelist) == nc) : */
81258 maechler 531
    if(length(dnamelist) != nc) {
532
	ECALL4(call,
533
          _("subscripting by character matrix of %d columns does not match length(dimnames(x)) == %d"),
534
	       nc, length(dnamelist));
535
    }
536
#endif
537
    SEXP snames = PROTECT(allocVector(STRSXP, nr));
538
    // result si := an integer matrix of same dimension as 's'
539
    SEXP si = PROTECT(allocVector(INTSXP, xlength(s)));
540
    dimgets(si, dim);
73567 luke 541
    int *psi = INTEGER(si);
87180 kalibera 542
    if (XLENGTH(si))
543
	memset(psi, 0, XLENGTH(si) * sizeof(int));
81258 maechler 544
    for (int i = 0; i < nc; i++) {
545
	R_xlen_t iNR = i * (R_xlen_t) nr;
546
	for (int j = 0; j < nr; j++)
547
	    SET_STRING_ELT(snames, j, STRING_ELT(s, j + iNR));
548
	SEXP dnames = VECTOR_ELT(dnamelist, i);
549
	SEXP sicol = PROTECT(match(dnames, snames, 0));
550
	for (int j = 0; j < nr; j++) {
551
	    int v = INTEGER_ELT(sicol, j);
552
	    R_xlen_t idx = j + iNR;
553
	    SEXP s_elt = STRING_ELT(s, idx);
68923 ripley 554
	    if (s_elt == NA_STRING) v = NA_INTEGER;
81258 maechler 555
	    else if (!CHAR(s_elt)[0]) v = 0; /* disallow "" match */
81144 luke 556
	    if (v == 0) ECALL_OutOfBoundsCHAR(x, i, s_elt, call);
73567 luke 557
	    psi[idx] = v;
68923 ripley 558
	}
559
	UNPROTECT(1);
50896 falcon 560
    }
561
    UNPROTECT(2);
562
    return si;
563
}
564
 
59097 ripley 565
static SEXP nullSubscript(R_xlen_t n)
2 r 566
{
10921 maechler 567
    SEXP indx;
59097 ripley 568
#ifdef LONG_VECTOR_SUPPORT
59118 ripley 569
    if (n > R_SHORT_LEN_MAX) {
68923 ripley 570
	indx = allocVector(REALSXP, n);
73567 luke 571
	double *pindx = REAL(indx);
59097 ripley 572
	for (R_xlen_t i = 0; i < n; i++)
73567 luke 573
	    pindx[i] = (double)(i + 1);
68754 maechler 574
    } else
59097 ripley 575
#endif
576
    {
577
	indx = allocVector(INTSXP, n);
73567 luke 578
	int *pindx = INTEGER(indx);
59097 ripley 579
	for (int i = 0; i < n; i++)
73567 luke 580
	    pindx[i] = i + 1;
59097 ripley 581
    }
10921 maechler 582
    return indx;
2 r 583
}
584
 
59088 ripley 585
 
68754 maechler 586
static SEXP
59095 ripley 587
logicalSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, R_xlen_t *stretch, SEXP call)
2 r 588
{
89130 maechler 589
    bool canstretch = *stretch > 0;
41686 ripley 590
    if (!canstretch && ns > nx) {
591
	ECALL(call, _("(subscript) logical subscript too long"));
592
    }
4288 ihaka 593
    *stretch = (ns > nx) ? ns : 0;
59065 ripley 594
    if (ns == 0) return(allocVector(INTSXP, 0));
89130 maechler 595
    R_xlen_t count, i, i1, i2,
596
	nmax = (ns > nx) ? ns : nx;
597
    SEXP indx; // result
598
 
73729 luke 599
    const int *ps = LOGICAL_RO(s);    /* Calling LOCICAL_RO here may force a
600
					 large allocation, but no larger than
601
					 the one made by R_alloc below. This
602
					 could use rewriting to better handle
603
					 a sparse logical index. */
59065 ripley 604
#ifdef LONG_VECTOR_SUPPORT
59118 ripley 605
    if (nmax > R_SHORT_LEN_MAX) {
68923 ripley 606
	if (ns == nmax) { /* no recycling - use fast single-index code */
68754 maechler 607
	    const void *vmax = vmaxget();
608
	    double *buf = (double *) R_alloc(nmax, sizeof(double));
609
	    count = 0;
73567 luke 610
	    R_ITERATE_CHECK(NINTERRUPT, nmax, i,
611
		if (ps[i]) {
612
		    if (ps[i] == NA_LOGICAL)
613
			buf[count++] = NA_REAL;
614
		    else
615
			buf[count++] = (double)(i + 1);
68754 maechler 616
		});
68923 ripley 617
	    PROTECT(indx = allocVector(REALSXP, count));
87180 kalibera 618
	    if (count)
619
		memcpy(REAL(indx), buf, sizeof(double) * count);
68923 ripley 620
	    vmaxset(vmax);
621
	    UNPROTECT(1);
622
	    return indx;
623
	}
59065 ripley 624
	count = 0;
67645 urbaneks 625
	/* we only need to scan s once even if we recycle,
626
	   just remember the total count as well as
627
	   the count for the last incomplete chunk (if any) */
628
	i1 = (ns < nmax) ? (nmax % ns) : 0;
68754 maechler 629
	if (i1 > 0) { /* last recycling chunk is incomplete -
67645 urbaneks 630
			 we have to get the truncated count as well */
631
	    R_xlen_t rem = 0;
632
	    for (i = 0; i < ns; i++) {
633
		if (i == i1) rem = count;
73567 luke 634
		if (ps[i]) count++;
67645 urbaneks 635
	    }
636
	    count = count * (nmax / ns) + rem;
637
	} else { /* nested recycling, total is sufficient */
638
	    for (i = 0; i < ns; i++)
73567 luke 639
		if (ps[i]) count++;
67645 urbaneks 640
	    count *= nmax / ns;
641
	}
68187 luke 642
	PROTECT(indx = allocVector(REALSXP, count));
73567 luke 643
	double *pindx = REAL(indx);
59065 ripley 644
	count = 0;
73567 luke 645
	MOD_ITERATE_CHECK(NINTERRUPT, nmax, ns, nmax, i, i1, i2,
646
	    if (ps[i1]) {
647
		if (ps[i1] == NA_LOGICAL)
648
		    pindx[count++] = NA_REAL;
649
		else
650
		    pindx[count++] = (double)(i + 1);
68923 ripley 651
	    });
67645 urbaneks 652
 
68187 luke 653
	UNPROTECT(1);
59065 ripley 654
	return indx;
655
    }
656
#endif
68754 maechler 657
// else --- the same code for  non-long vectors --------------------------
658
    if (ns == nmax) {  /* no recycling - use fast single-index code */
659
	const void *vmax = vmaxget();
660
	int *buf = (int *) R_alloc(nmax, sizeof(int));
661
	count = 0;
73567 luke 662
	R_ITERATE_CHECK(NINTERRUPT, nmax, i,
663
	    if (ps[i]) {
664
		if (ps[i] == NA_LOGICAL)
665
		    buf[count++] = NA_INTEGER;
666
		else
667
		    buf[count++] = (int)(i + 1);
68754 maechler 668
	    });
669
	PROTECT(indx = allocVector(INTSXP, count));
87180 kalibera 670
	if (count)
671
	    memcpy(INTEGER(indx), buf, sizeof(int) * count);
68754 maechler 672
	vmaxset(vmax);
673
	UNPROTECT(1);
674
	return indx;
675
    }
676
 
1839 ihaka 677
    count = 0;
67645 urbaneks 678
    /* we only need to scan s once even if we recycle,
679
       just remember the total count as well as
680
       the count for the last incomplete chunk (if any) */
681
    i1 = (ns < nmax) ? (nmax % ns) : 0;
68754 maechler 682
    if (i1 > 0) { /* last recycling chunk is incomplete -
67645 urbaneks 683
		     we have to get the truncated count as well */
684
	R_xlen_t rem = 0;
685
	for (i = 0; i < ns; i++) {
686
	    if (i == i1) rem = count;
73567 luke 687
	    if (ps[i]) count++;
67645 urbaneks 688
	}
689
	count = count * (nmax / ns) + rem;
68754 maechler 690
    } else { /* nested recycling, total is sufficient */
67645 urbaneks 691
	for (i = 0; i < ns; i++)
73567 luke 692
	    if (ps[i]) count++;
67645 urbaneks 693
	count *= nmax / ns;
694
    }
68187 luke 695
    PROTECT(indx = allocVector(INTSXP, count));
73567 luke 696
    int *pindx = INTEGER(indx);
1839 ihaka 697
    count = 0;
73567 luke 698
    MOD_ITERATE_CHECK(NINTERRUPT, nmax, ns, nmax, i, i1, i2,
699
	if (ps[i1]) {
700
	    if (ps[i1] == NA_LOGICAL)
701
		pindx[count++] = NA_INTEGER;
702
	    else
703
		pindx[count++] = (int)(i + 1);
68923 ripley 704
	});
67645 urbaneks 705
 
68187 luke 706
    UNPROTECT(1);
10921 maechler 707
    return indx;
2 r 708
}
709
 
59046 ripley 710
static SEXP negativeSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, SEXP call)
2 r 711
{
89130 maechler 712
    SEXP indx = PROTECT(allocVector(LGLSXP, nx));
713
    int *pindx = LOGICAL(indx);
59046 ripley 714
    R_xlen_t i;
1839 ihaka 715
    for (i = 0; i < nx; i++)
73567 luke 716
	pindx[i] = 1;
73729 luke 717
    const int *ps = INTEGER_RO(s);
28762 pd 718
    for (i = 0; i < ns; i++) {
73567 luke 719
	int ix = ps[i];
28762 pd 720
	if (ix != 0 && ix != NA_INTEGER && -ix <= nx)
73567 luke 721
	    pindx[-ix - 1] = 0;
28762 pd 722
    }
89130 maechler 723
    R_xlen_t stretch = 0;
41680 ripley 724
    s = logicalSubscript(indx, nx, nx, &stretch, call);
1839 ihaka 725
    UNPROTECT(1);
726
    return s;
2 r 727
}
728
 
59046 ripley 729
static SEXP positiveSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx)
2 r 730
{
59046 ripley 731
    R_xlen_t i, zct = 0;
73729 luke 732
    const int *ps = INTEGER_RO(s);
73567 luke 733
    for (i = 0; i < ns; i++) if (ps[i] == 0) zct++;
1839 ihaka 734
    if (zct) {
89130 maechler 735
	SEXP indx = allocVector(INTSXP, (ns - zct));
73567 luke 736
	int *pindx = INTEGER(indx);
27383 rgentlem 737
	for (i = 0, zct = 0; i < ns; i++)
73567 luke 738
	    if (ps[i] != 0)
739
		pindx[zct++] = ps[i];
27383 rgentlem 740
	return indx;
59065 ripley 741
 
59057 ripley 742
    } else return s;
2 r 743
}
744
 
68754 maechler 745
static SEXP
81144 luke 746
integerSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, R_xlen_t *stretch,
89928 luke 747
		 SEXP call, SEXP x, int dim)
2 r 748
{
89130 maechler 749
    bool isna = false, neg = false,
750
	canstretch = *stretch > 0;
1839 ihaka 751
    *stretch = 0;
89130 maechler 752
    int max = 0;
73729 luke 753
    const int *ps = INTEGER_RO(s);
89130 maechler 754
    for (R_xlen_t i = 0; i < ns; i++) {
755
	int ii = ps[i];
73694 luke 756
	if (ii < 0) {
757
	    if (ii == NA_INTEGER)
87891 ripley 758
		isna = true;
73694 luke 759
	    else
87891 ripley 760
		neg = true;
73694 luke 761
	}
762
	else if (ii > max)
763
	    max = ii;
1839 ihaka 764
    }
765
    if (max > nx) {
27383 rgentlem 766
	if(canstretch) *stretch = max;
41686 ripley 767
	else {
89928 luke 768
	    ECALL_OutOfBounds(x, dim, max, call);
41686 ripley 769
	}
1839 ihaka 770
    }
73694 luke 771
    if (neg) {
41680 ripley 772
	if (max == 0 && !isna) return negativeSubscript(s, ns, nx, call);
41686 ripley 773
	else {
774
	    ECALL(call, _("only 0's may be mixed with negative subscripts"));
775
	}
1839 ihaka 776
    }
27383 rgentlem 777
    else return positiveSubscript(s, ns, nx);
778
    return R_NilValue;
2 r 779
}
780
 
68754 maechler 781
static SEXP
81144 luke 782
realSubscript(SEXP s, R_xlen_t ns, R_xlen_t nx, R_xlen_t *stretch,
783
	      SEXP call, SEXP x)
59065 ripley 784
{
89130 maechler 785
    bool canstretch = *stretch > 0;
59065 ripley 786
    *stretch = 0;
81380 maechler 787
    double min = 0, max = 0;
73729 luke 788
    const double *ps = REAL_RO(s);
87891 ripley 789
    bool isna = false;
81380 maechler 790
    for (R_xlen_t i = 0; i < ns; i++) {
791
	double ii = ps[i];
59065 ripley 792
	if (R_FINITE(ii)) {
793
	    if (ii < min) min = ii;
794
	    if (ii > max) max = ii;
87891 ripley 795
	} else isna = true;
59065 ripley 796
    }
87184 maechler 797
    if (max >= (double)nx+1.) {
60200 ripley 798
#ifndef LONG_VECTOR_SUPPORT
799
	if (max > INT_MAX) {
59065 ripley 800
	    ECALL(call, _("subscript too large for 32-bit R"));
801
	}
802
#endif
59095 ripley 803
	if(canstretch) *stretch = (R_xlen_t) max;
59065 ripley 804
	else {
81144 luke 805
	    ECALL_OutOfBounds(x, -1, (R_xlen_t) max, call);
59065 ripley 806
	}
807
    }
81380 maechler 808
    if (min <= -1) {
809
	if (max < 1 && !isna) {
810
	    R_xlen_t i, stretch = 0;
811
	    SEXP indx = PROTECT(allocVector(LGLSXP, nx));
73567 luke 812
	    int *pindx = LOGICAL(indx);
813
	    for (i = 0; i < nx; i++) pindx[i] = 1;
59065 ripley 814
	    for (i = 0; i < ns; i++) {
81380 maechler 815
		double dx = ps[i];
87184 maechler 816
		if (R_FINITE(dx) && dx <= -1  && -dx < (double)nx+1.) {
81380 maechler 817
		    R_xlen_t ix = (R_xlen_t)(-dx - 1);
73567 luke 818
		    pindx[ix] = 0;
59080 ripley 819
		}
59065 ripley 820
	    }
821
	    s = logicalSubscript(indx, nx, nx, &stretch, call);
822
	    UNPROTECT(1);
823
	    return s;
824
	} else {
825
	    ECALL(call, _("only 0's may be mixed with negative subscripts"));
826
	}
827
    } else {
828
	/* Only return a REALSXP index if we need to */
829
	SEXP indx;
830
	R_xlen_t i, cnt = 0;
87891 ripley 831
	bool int_ok = true;
59080 ripley 832
	/* NB, indices will be truncated eventually,
833
	   so need to do that to take '0' into account */
59065 ripley 834
	for (i = 0; i < ns; i++) {
73567 luke 835
	    double ds = ps[i];
59574 luke 836
#ifdef OLDCODE_LONG_VECTOR
59065 ripley 837
	    if (!R_FINITE(ds)) {
87891 ripley 838
		if (ds > INT_MAX) int_ok = false;
59065 ripley 839
		cnt++;
59080 ripley 840
	    } else if ((R_xlen_t) ds != 0) cnt++;
59574 luke 841
#else
87891 ripley 842
	    if (R_FINITE(ds) && ds > INT_MAX) int_ok = false;
64252 ripley 843
	    if (!R_FINITE(ds) || (R_xlen_t) ds != 0) cnt++;
59574 luke 844
#endif
59065 ripley 845
	}
846
	if (int_ok) {
847
	    indx = allocVector(INTSXP, cnt);
73567 luke 848
	    int *pindx = INTEGER(indx);
59065 ripley 849
	    for (i = 0, cnt = 0; i < ns; i++) {
73567 luke 850
		double ds = ps[i];
59080 ripley 851
		int ia;
852
		if (!R_FINITE(ds)) ia = NA_INTEGER;
59097 ripley 853
		else ia = (int) ds;
73567 luke 854
		if (ia != 0) pindx[cnt++] = ia;
59065 ripley 855
	    }
856
	} else {
857
	    indx = allocVector(REALSXP, cnt);
73567 luke 858
	    double *pindx = REAL(indx);
59080 ripley 859
	    for (i = 0, cnt = 0; i < ns; i++) {
73567 luke 860
		double ds = ps[i];
861
		if (!R_FINITE(ds) || (R_xlen_t) ds != 0) pindx[cnt++] = ds;
59080 ripley 862
	    }
59065 ripley 863
	}
864
	return indx;
865
    }
866
    return R_NilValue;
867
}
868
 
29363 ripley 869
/* This uses a couple of horrible hacks in conjunction with
870
 * VectorAssign (in subassign.c).  If subscripting is used for
871
 * assignment, it is possible to extend a vector by supplying new
872
 * names, and we want to give the extended vector those names, so they
51067 ripley 873
 * are returned as the use.names attribute. Also, unset elements of the vector
29363 ripley 874
 * of new names (places where a match was found) are indicated by
51067 ripley 875
 * setting the element of the newnames vector to NULL.
29363 ripley 876
*/
877
 
878
/* The original code (pre 2.0.0) used a ns x nx loop that was too
879
 * slow.  So now we hash.  Hashing is expensive on memory (up to 32nx
880
 * bytes) so it is only worth doing if ns * nx is large.  If nx is
881
 * large, then it will be too slow unless ns is very small.
882
 */
883
 
41680 ripley 884
static SEXP
89130 maechler 885
stringSubscript(SEXP s, R_xlen_t ns /* = xlength(s) */, R_xlen_t nx /* = xlength(x) */,
886
		SEXP names,
81144 luke 887
		R_xlen_t *stretch, SEXP call, SEXP x, int dim)
2 r 888
{
39595 murdoch 889
    /* product may overflow, so check factors as well. */
87891 ripley 890
    bool usehashing = ( ((ns > 1000 && nx) || (nx > 1000 && ns)) || (ns * nx > 15*nx + ns) );
78127 kalibera 891
    int nprotect = 0;
1839 ihaka 892
    PROTECT(s);
893
    PROTECT(names);
78127 kalibera 894
    nprotect += 2;
2 r 895
 
89130 maechler 896
    SEXP indx, indexnames = R_NilValue;
897
    bool canstretch = *stretch > 0;
898
    *stretch = 0;
899
    R_xlen_t i, sub,
900
	nnames = nx,
901
	extra = nnames;
902
 
29363 ripley 903
    /* Process each of the subscripts. First we compare with the names
904
     * on the vector and then (if there is no match) with each of the
905
     * previous subscripts, since (if assigning) we may have already
906
     * added an element of that name. (If we are not assigning, any
907
     * nonmatch will have given an error.)
908
     */
2 r 909
 
29363 ripley 910
    if(usehashing) {
911
	/* must be internal, so names contains a character vector */
35796 ripley 912
	/* NB: this does not behave in the same way with respect to ""
913
	   and NA names: they will match */
73729 luke 914
	PROTECT(indx = match(names, s, 0)); /**** guaranteed to be fresh???*/
78127 kalibera 915
	nprotect++;
35796 ripley 916
	/* second pass to correct this */
73567 luke 917
	int *pindx = INTEGER(indx);
35796 ripley 918
	for (i = 0; i < ns; i++)
919
	    if(STRING_ELT(s, i) == NA_STRING || !CHAR(STRING_ELT(s, i))[0])
78184 maechler 920
		pindx[i] = 0;
29363 ripley 921
    } else {
922
	PROTECT(indx = allocVector(INTSXP, ns));
78127 kalibera 923
	nprotect++;
73567 luke 924
	int *pindx = INTEGER(indx);
29363 ripley 925
	for (i = 0; i < ns; i++) {
926
	    sub = 0;
927
	    if (names != R_NilValue) {
89130 maechler 928
		for (R_xlen_t j = 0; j < nnames; j++) {
59066 ripley 929
		    SEXP names_j = STRING_ELT(names, j);
29363 ripley 930
		    if (NonNullStringMatch(STRING_ELT(s, i), names_j)) {
931
			sub = j + 1;
932
			break;
933
		    }
1839 ihaka 934
		}
27383 rgentlem 935
	    }
73567 luke 936
	    pindx[i] = (int) sub;
2 r 937
	}
29363 ripley 938
    }
939
 
73567 luke 940
    int *pindx = INTEGER(indx);
74660 lawrence 941
    SEXP sindx = NULL;
29363 ripley 942
    for (i = 0; i < ns; i++) {
73567 luke 943
	sub = pindx[i];
1839 ihaka 944
	if (sub == 0) {
74660 lawrence 945
	    if (sindx == NULL) {
946
		sindx = PROTECT(match(s, s, 0));
947
		indexnames = PROTECT(allocVector(VECSXP, ns));
78127 kalibera 948
		nprotect += 2;
74660 lawrence 949
		for (int z = 0; z < ns; z++)
950
		    SET_VECTOR_ELT(indexnames, z, R_NilValue);
951
	    }
952
	    int j = INTEGER(sindx)[i] - 1;
953
	    if(STRING_ELT(s, i) != NA_STRING && CHAR(STRING_ELT(s, i))[0]) {
954
		sub = pindx[j];
955
		SET_VECTOR_ELT(indexnames, i, STRING_ELT(s, j));
956
	    }
1839 ihaka 957
	}
958
	if (sub == 0) {
41686 ripley 959
	    if (!canstretch) {
81144 luke 960
		ECALL_OutOfBoundsCHAR(x, dim, STRING_ELT(s, i), call);
41686 ripley 961
	    }
1839 ihaka 962
	    extra += 1;
963
	    sub = extra;
51067 ripley 964
	    SET_VECTOR_ELT(indexnames, i, STRING_ELT(s, i));
1839 ihaka 965
	}
73567 luke 966
	pindx[i] = (int) sub;
1839 ihaka 967
    }
38655 ripley 968
    /* We return the new names as the names attribute of the returned
969
       subscript vector. */
89130 maechler 970
    if (extra != nnames) {
51067 ripley 971
	setAttrib(indx, R_UseNamesSymbol, indexnames);
89130 maechler 972
	if (canstretch)
973
	    *stretch = extra;
974
    }
78127 kalibera 975
    UNPROTECT(nprotect);
10921 maechler 976
    return indx;
2 r 977
}
978
 
29363 ripley 979
/* Array Subscripts.
14913 rgentlem 980
    dim is the dimension (0 to k-1)
29363 ripley 981
    s is the subscript list,
14913 rgentlem 982
    dims is the dimensions of x
983
    dng is a function (usually getAttrib) that obtains the dimnames
29363 ripley 984
    x is the array to be subscripted.
14913 rgentlem 985
*/
2 r 986
 
59086 ripley 987
attribute_hidden SEXP
59066 ripley 988
int_arraySubscript(int dim, SEXP s, SEXP dims, SEXP x, SEXP call)
2 r 989
{
59095 ripley 990
    int nd, ns;
991
    R_xlen_t stretch = 0;
14913 rgentlem 992
    SEXP dnames, tmp;
1839 ihaka 993
    ns = length(s);
73567 luke 994
    nd = INTEGER_ELT(dims, dim);
2 r 995
 
1839 ihaka 996
    switch (TYPEOF(s)) {
997
    case NILSXP:
998
	return allocVector(INTSXP, 0);
999
    case LGLSXP:
41680 ripley 1000
	return logicalSubscript(s, ns, nd, &stretch, call);
1839 ihaka 1001
    case INTSXP:
89928 luke 1002
	return integerSubscript(s, ns, nd, &stretch, call, x, dim);
1839 ihaka 1003
    case REALSXP:
59118 ripley 1004
	/* We don't yet allow subscripts > R_SHORT_LEN_MAX */
45446 ripley 1005
	PROTECT(tmp = coerceVector(s, INTSXP));
89928 luke 1006
	tmp = integerSubscript(tmp, ns, nd, &stretch, call, x, dim);
45446 ripley 1007
	UNPROTECT(1);
2504 pd 1008
	return tmp;
1839 ihaka 1009
    case STRSXP:
59066 ripley 1010
	dnames = getAttrib(x, R_DimNamesSymbol);
41686 ripley 1011
	if (dnames == R_NilValue) {
1012
	    ECALL(call, _("no 'dimnames' attribute for array"));
1013
	}
10172 luke 1014
	dnames = VECTOR_ELT(dnames, dim);
81144 luke 1015
	return stringSubscript(s, ns, nd, dnames, &stretch, call, x, dim);
1839 ihaka 1016
    case SYMSXP:
1017
	if (s == R_MissingArg)
1018
	    return nullSubscript(nd);
1019
    default:
85146 luke 1020
	ECALL3(call, _("invalid subscript type '%s'"), R_typeToChar(s));
1839 ihaka 1021
    }
1022
    return R_NilValue;
2 r 1023
}
1024
 
59066 ripley 1025
/* This is used by packages arules, cba, proxy and seriation. */
1026
typedef SEXP AttrGetter(SEXP x, SEXP data);
1027
typedef SEXP (*StringEltGetter)(SEXP x, int i);
1028
 
86648 luke 1029
attribute_hidden SEXP
36990 ripley 1030
arraySubscript(int dim, SEXP s, SEXP dims, AttrGetter dng,
1031
	       StringEltGetter strg, SEXP x)
29363 ripley 1032
{
59066 ripley 1033
    return int_arraySubscript(dim, s, dims, x, R_NilValue);
29363 ripley 1034
}
1035
 
1839 ihaka 1036
/* Subscript creation.  The first thing we do is check to see */
1037
/* if there are any user supplied NULL's, these result in */
1038
/* returning a vector of length 0. */
15317 rgentlem 1039
/* if stretch is zero on entry then the vector x cannot be
1040
   "stretched",
1041
   otherwise, stretch returns the new required length for x
1042
*/
2 r 1043
 
83446 ripley 1044
attribute_hidden SEXP
59095 ripley 1045
makeSubscript(SEXP x, SEXP s, R_xlen_t *stretch, SEXP call)
2 r 1046
{
63630 luke 1047
    if (! (isVector(x) || isList(x) || isLanguage(x))) {
41686 ripley 1048
	ECALL(call, _("subscripting on non-vector"));
1049
    }
15317 rgentlem 1050
 
63630 luke 1051
    R_xlen_t nx = xlength(x);
15317 rgentlem 1052
 
1053
    /* special case for simple indices -- does not duplicate */
73567 luke 1054
    if (IS_SCALAR(s, INTSXP)) {
1055
	int i = SCALAR_IVAL(s);
1056
	if (0 < i && i <= nx) {
1057
	    *stretch = 0;
1058
	    return s;
10782 luke 1059
	}
73567 luke 1060
    }
1061
    else if (IS_SCALAR(s, REALSXP)) {
1062
	double di = SCALAR_DVAL(s);
1063
	if (1 <= di && di <= nx) {
1064
	    *stretch = 0;
1065
	    /* We could only return a REALSXP if the value is too
1066
	       large for an INTSXP, but, as the calling code can
1067
	       handle REALSXP indices, returning the REALSXP
1068
	       avoids an allocation. */
1069
	    return s;
63630 luke 1070
	}
15317 rgentlem 1071
    }
63630 luke 1072
 
73567 luke 1073
    R_xlen_t ns = xlength(s);
63630 luke 1074
    SEXP ans = R_NilValue;
15317 rgentlem 1075
    switch (TYPEOF(s)) {
1076
    case NILSXP:
1077
	*stretch = 0;
1078
	ans = allocVector(INTSXP, 0);
1079
	break;
1080
    case LGLSXP:
41680 ripley 1081
	ans = logicalSubscript(s, ns, nx, stretch, call);
15317 rgentlem 1082
	break;
1083
    case INTSXP:
89928 luke 1084
	ans = integerSubscript(s, ns, nx, stretch, call, x, -1);
42414 ripley 1085
	break;
15317 rgentlem 1086
    case REALSXP:
81144 luke 1087
	ans = realSubscript(s, ns, nx, stretch, call, x);
15317 rgentlem 1088
	break;
1089
    case STRSXP:
1090
    {
75532 kalibera 1091
	SEXP names = PROTECT(getAttrib(x, R_NamesSymbol));
81144 luke 1092
	ans = stringSubscript(s, ns, nx, names, stretch, call, x, -1);
75532 kalibera 1093
	UNPROTECT(1); /* names */
63630 luke 1094
	break;
15317 rgentlem 1095
    }
1096
    case SYMSXP:
1097
	*stretch = 0;
1098
	if (s == R_MissingArg) {
1099
	    ans = nullSubscript(nx);
1839 ihaka 1100
	    break;
2 r 1101
	}
15317 rgentlem 1102
    default:
85146 luke 1103
	ECALL3(call, _("invalid subscript type '%s'"), R_typeToChar(s));
1839 ihaka 1104
    }
1105
    return ans;
2 r 1106
}