The R Project SVN R

Rev

Rev 28766 | Rev 32380 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 28766 Rev 29363
Line 122... Line 122...
122
    if (pos < 0 && length(s) != 1) {
122
    if (pos < 0 && length(s) != 1) {
123
	if (length(s) > 1)
123
	if (length(s) > 1)
124
	    error("attempt to select more than one element");
124
	    error("attempt to select more than one element");
125
	else
125
	else
126
	    error("attempt to select less than one element");
126
	    error("attempt to select less than one element");
127
    } else 
127
    } else
128
	if(pos >= length(s))
128
	if(pos >= length(s))
129
	    error("internal error in use of recursive indexing");
129
	    error("internal error in use of recursive indexing");
130
    if(pos < 0) pos = 0;
130
    if(pos < 0) pos = 0;
131
    indx = -1;
131
    indx = -1;
132
    switch (TYPEOF(s)) {
132
    switch (TYPEOF(s)) {
Line 142... Line 142...
142
	    indx = integerOneIndex((int)dblind, len);
142
	    indx = integerOneIndex((int)dblind, len);
143
	break;
143
	break;
144
    case STRSXP:
144
    case STRSXP:
145
	/* Try for exact match */
145
	/* Try for exact match */
146
	for (i = 0; i < length(names); i++)
146
	for (i = 0; i < length(names); i++)
147
	    if (streql(CHAR(STRING_ELT(names, i)), 
147
	    if (streql(CHAR(STRING_ELT(names, i)),
148
		       CHAR(STRING_ELT(s, pos)))) {
148
		       CHAR(STRING_ELT(s, pos)))) {
149
		indx = i;
149
		indx = i;
150
		break;
150
		break;
151
	    }
151
	    }
152
	/* Try for partial match */
152
	/* Try for partial match */
Line 254... Line 254...
254
    int i, ix;
254
    int i, ix;
255
    PROTECT(indx = allocVector(INTSXP, nx));
255
    PROTECT(indx = allocVector(INTSXP, nx));
256
    for (i = 0; i < nx; i++)
256
    for (i = 0; i < nx; i++)
257
	INTEGER(indx)[i] = 1;
257
	INTEGER(indx)[i] = 1;
258
    for (i = 0; i < ns; i++) {
258
    for (i = 0; i < ns; i++) {
259
	ix = INTEGER(s)[i]; 
259
	ix = INTEGER(s)[i];
260
	if (ix != 0 && ix != NA_INTEGER && -ix <= nx)
260
	if (ix != 0 && ix != NA_INTEGER && -ix <= nx)
261
	    INTEGER(indx)[-ix - 1] = 0;
261
	    INTEGER(indx)[-ix - 1] = 0;
262
    }
262
    }
263
    s = logicalSubscript(indx, nx, nx, &stretch);
263
    s = logicalSubscript(indx, nx, nx, &stretch);
264
    UNPROTECT(1);
264
    UNPROTECT(1);
Line 315... Line 315...
315
    return R_NilValue;
315
    return R_NilValue;
316
}
316
}
317
 
317
 
318
typedef SEXP (*StringEltGetter)(SEXP x, int i);
318
typedef SEXP (*StringEltGetter)(SEXP x, int i);
319
 
319
 
-
 
320
/* This uses a couple of horrible hacks in conjunction with
-
 
321
 * VectorAssign (in subassign.c).  If subscripting is used for
-
 
322
 * assignment, it is possible to extend a vector by supplying new
-
 
323
 * names, and we want to give the extended vector those names, so they
-
 
324
 * are returned as the attribute. Also, unset elements of the vector
-
 
325
 * of new names (places where a match was found) are indicated by
-
 
326
 * setting the element of the newnames vector to NULL, even though it
-
 
327
 * is a character vector.
-
 
328
*/
-
 
329
 
-
 
330
/* The original code (pre 2.0.0) used a ns x nx loop that was too
-
 
331
 * slow.  So now we hash.  Hashing is expensive on memory (up to 32nx
-
 
332
 * bytes) so it is only worth doing if ns * nx is large.  If nx is
-
 
333
 * large, then it will be too slow unless ns is very small.
-
 
334
 */
-
 
335
 
-
 
336
#define USE_HASHING 1
320
static SEXP stringSubscript(SEXP s, int ns, int nx, SEXP names,
337
static SEXP stringSubscript(SEXP s, int ns, int nx, SEXP names,
321
			    StringEltGetter strg, int *stretch)
338
			    StringEltGetter strg, int *stretch, Rboolean in)
322
{
339
{
323
    SEXP indx, indexnames;
340
    SEXP indx, indexnames;
324
    int i, j, nnames, sub, extra;
341
    int i, j, nnames, sub, extra;
325
    int canstretch = *stretch;
342
    int canstretch = *stretch;
-
 
343
#ifdef USE_HASHING
-
 
344
    Rboolean usehashing = in && (ns * nx > 1000);
-
 
345
#else
-
 
346
    Rboolean usehashing = FALSE;
-
 
347
#endif
-
 
348
 
326
    PROTECT(s);
349
    PROTECT(s);
327
    PROTECT(names);
350
    PROTECT(names);
328
    PROTECT(indx = allocVector(INTSXP, ns));
-
 
329
    PROTECT(indexnames = allocVector(STRSXP, ns));
351
    PROTECT(indexnames = allocVector(STRSXP, ns));
330
    nnames = nx;
352
    nnames = nx;
331
    extra = nnames;
353
    extra = nnames;
332
 
354
 
333
    /* Process each of the subscripts */
355
    /* Process each of the subscripts. First we compare with the names
334
    /* First we compare with the names on the vector */
356
     * on the vector and then (if there is no match) with each of the
-
 
357
     * previous subscripts, since (if assigning) we may have already
335
    /* and then (if there is no match) with each of */
358
     * added an element of that name. (If we are not assigning, any
336
    /* the previous subscripts. */
359
     * nonmatch will have given an error.)
-
 
360
     */
337
 
361
 
-
 
362
#ifdef USE_HASHING
-
 
363
    if(usehashing) {
-
 
364
	/* must be internal, so names contains a character vector */
-
 
365
	PROTECT(indx = match(names, s, 0));
-
 
366
	for (i = 0; i < ns; i++) SET_STRING_ELT(indexnames, i, R_NilValue);
-
 
367
    } else {
-
 
368
#endif
-
 
369
	PROTECT(indx = allocVector(INTSXP, ns));
338
    for (i = 0; i < ns; i++) {
370
	for (i = 0; i < ns; i++) {
339
	sub = 0;
371
	    sub = 0;
340
	if (names != R_NilValue) {
372
	    if (names != R_NilValue) {
341
	    for (j = 0; j < nnames; j++) {
373
		for (j = 0; j < nnames; j++) {
342
	        SEXP names_j = strg(names, j);
374
		    SEXP names_j = strg(names, j);
343
		if (TYPEOF(names_j) != CHARSXP)
375
		    if (!in && TYPEOF(names_j) != CHARSXP)
344
		    error("character vector element does not have type CHARSXP");
376
			error("character vector element does not have type CHARSXP");
345
		if (NonNullStringMatch(STRING_ELT(s, i), names_j)) {
377
		    if (NonNullStringMatch(STRING_ELT(s, i), names_j)) {
346
		    sub = j + 1;
378
			sub = j + 1;
347
		    SET_STRING_ELT(indexnames, i, R_NilValue);
379
			SET_STRING_ELT(indexnames, i, R_NilValue);
348
		    break;
380
			break;
-
 
381
		    }
349
		}
382
		}
350
	    }
383
	    }
-
 
384
	    INTEGER(indx)[i] = sub;
351
	}
385
	}
-
 
386
#ifdef USE_HASHING
-
 
387
    }
-
 
388
#endif
-
 
389
 
-
 
390
    for (i = 0; i < ns; i++) {
-
 
391
	sub = INTEGER(indx)[i];
352
	if (sub == 0) {
392
	if (sub == 0) {
353
	    for (j = 0 ; j < i ; j++)
393
	    for (j = 0 ; j < i ; j++)
354
		if (NonNullStringMatch(STRING_ELT(s, i), STRING_ELT(s, j))) {
394
		if (NonNullStringMatch(STRING_ELT(s, i), STRING_ELT(s, j))) {
355
		    sub = INTEGER(indx)[j];
395
		    sub = INTEGER(indx)[j];
356
/*		    SET_STRING_ELT(indexnames, i, STRING_ELT(indexnames, sub - 1));*/
-
 
357
		    SET_STRING_ELT(indexnames, i, STRING_ELT(s, j));
396
		    SET_STRING_ELT(indexnames, i, STRING_ELT(s, j));
358
		    break;
397
		    break;
359
		}
398
		}
360
	}
399
	}
361
	if (sub == 0) {
400
	if (sub == 0) {
Line 367... Line 406...
367
	}
406
	}
368
	INTEGER(indx)[i] = sub;
407
	INTEGER(indx)[i] = sub;
369
    }
408
    }
370
    /* Ghastly hack!  We attach the new names to the attribute */
409
    /* Ghastly hack!  We attach the new names to the attribute */
371
    /* slot on the returned subscript vector. */
410
    /* slot on the returned subscript vector. */
372
    if (extra != nnames) {
411
    if (extra != nnames)
373
	SET_ATTRIB(indx, indexnames);
412
	SET_ATTRIB(indx, indexnames);
374
    }
-
 
375
    if (canstretch)
413
    if (canstretch)
376
	*stretch = extra;
414
	*stretch = extra;
377
    UNPROTECT(4);
415
    UNPROTECT(4);
378
    return indx;
416
    return indx;
379
}
417
}
380
 
418
 
381
/* Array Subscripts.  
419
/* Array Subscripts.
382
    dim is the dimension (0 to k-1)
420
    dim is the dimension (0 to k-1)
383
    s is the subscript list, 
421
    s is the subscript list,
384
    dims is the dimensions of x
422
    dims is the dimensions of x
385
    dng is a function (usually getAttrib) that obtains the dimnames
423
    dng is a function (usually getAttrib) that obtains the dimnames
386
    x is the array to be subscripted. 
424
    x is the array to be subscripted.
387
*/
425
*/
388
 
426
 
389
typedef SEXP AttrGetter(SEXP x, SEXP data);
427
typedef SEXP AttrGetter(SEXP x, SEXP data);
390
 
428
 
-
 
429
static SEXP 
391
SEXP arraySubscript(int dim, SEXP s, SEXP dims, AttrGetter dng,
430
int_arraySubscript(int dim, SEXP s, SEXP dims, AttrGetter dng,
392
		    StringEltGetter strg, SEXP x)
431
		   StringEltGetter strg, SEXP x, Rboolean in)
393
{
432
{
394
    int nd, ns, stretch = 0;
433
    int nd, ns, stretch = 0;
395
    SEXP dnames, tmp;
434
    SEXP dnames, tmp;
396
    ns = length(s);
435
    ns = length(s);
397
    nd = INTEGER(dims)[dim];
436
    nd = INTEGER(dims)[dim];
Line 411... Line 450...
411
    case STRSXP:
450
    case STRSXP:
412
	dnames = dng(x, R_DimNamesSymbol);
451
	dnames = dng(x, R_DimNamesSymbol);
413
	if (dnames == R_NilValue)
452
	if (dnames == R_NilValue)
414
	    error("no dimnames attribute for array");
453
	    error("no dimnames attribute for array");
415
	dnames = VECTOR_ELT(dnames, dim);
454
	dnames = VECTOR_ELT(dnames, dim);
416
	return stringSubscript(s, ns, nd, dnames, strg, &stretch);
455
	return stringSubscript(s, ns, nd, dnames, strg, &stretch, in);
417
    case SYMSXP:
456
    case SYMSXP:
418
	if (s == R_MissingArg)
457
	if (s == R_MissingArg)
419
	    return nullSubscript(nd);
458
	    return nullSubscript(nd);
420
    default:
459
    default:
421
	error("invalid subscript");
460
	error("invalid subscript");
422
    }
461
    }
423
    return R_NilValue;
462
    return R_NilValue;
424
}
463
}
425
 
464
 
-
 
465
SEXP arraySubscript(int dim, SEXP s, SEXP dims, AttrGetter dng,
-
 
466
		    StringEltGetter strg, SEXP x)
-
 
467
{
-
 
468
    return int_arraySubscript(dim, s, dims, dng, strg, x, TRUE);
-
 
469
}
-
 
470
 
426
/* Subscript creation.  The first thing we do is check to see */
471
/* Subscript creation.  The first thing we do is check to see */
427
/* if there are any user supplied NULL's, these result in */
472
/* if there are any user supplied NULL's, these result in */
428
/* returning a vector of length 0. */
473
/* returning a vector of length 0. */
429
/* if stretch is zero on entry then the vector x cannot be
474
/* if stretch is zero on entry then the vector x cannot be
430
   "stretched",
475
   "stretched",
Line 450... Line 495...
450
/* nx is the length of the object being subscripted,
495
/* nx is the length of the object being subscripted,
451
   s is the R subscript value,
496
   s is the R subscript value,
452
   dng gets a given attrib for x, which is the object we are
497
   dng gets a given attrib for x, which is the object we are
453
   subsetting,
498
   subsetting,
454
*/
499
*/
455
 
500
 
-
 
501
static SEXP 
456
SEXP vectorSubscript(int nx, SEXP s, int *stretch, AttrGetter dng,
502
int_vectorSubscript(int nx, SEXP s, int *stretch, AttrGetter dng,
457
		     StringEltGetter strg, SEXP x) 
503
		    StringEltGetter strg, SEXP x, Rboolean in)
458
{
504
{
459
    int ns;
505
    int ns;
460
    SEXP ans=R_NilValue, tmp;
506
    SEXP ans=R_NilValue, tmp;
461
 
507
 
462
    ns = length(s);
508
    ns = length(s);
Line 489... Line 535...
489
	break;
535
	break;
490
    case STRSXP:
536
    case STRSXP:
491
    {
537
    {
492
	SEXP names = dng(x, R_NamesSymbol);
538
	SEXP names = dng(x, R_NamesSymbol);
493
	/* *stretch = 0; */
539
	/* *stretch = 0; */
494
	ans = stringSubscript(s, ns, nx, names, strg, stretch);
540
	ans = stringSubscript(s, ns, nx, names, strg, stretch, in);
495
    }
541
    }
496
    break;
542
    break;
497
    case SYMSXP:
543
    case SYMSXP:
498
	*stretch = 0;
544
	*stretch = 0;
499
	if (s == R_MissingArg) {
545
	if (s == R_MissingArg) {
Line 506... Line 552...
506
    UNPROTECT(1);
552
    UNPROTECT(1);
507
    return ans;
553
    return ans;
508
}
554
}
509
 
555
 
510
 
556
 
-
 
557
SEXP vectorSubscript(int nx, SEXP s, int *stretch, AttrGetter dng,
-
 
558
		     StringEltGetter strg, SEXP x)
-
 
559
{
-
 
560
    return int_vectorSubscript(nx, s, stretch, dng, strg, x, TRUE);
-
 
561
}
511
 
562