The R Project SVN R

Rev

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

Rev Author Line No. Line
37087 ripley 1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
59198 ripley 4
 *  Copyright (C) 1999-2012  The R Core Team.
37087 ripley 5
 *
6
 *  This program is free software; you can redistribute it and/or modify
38988 ripley 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
37087 ripley 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 Lesser General Public License for more details.
15
 *
38988 ripley 16
 *  You should have received a copy of the GNU General Public License
42308 ripley 17
 *  along with this program; if not, a copy is available at
18
 *  http://www.r-project.org/Licenses/
37087 ripley 19
 */
20
 
21
/* this header is always to be included from others.
22
   It is only called if COMPILING_R is defined (in util.c) or
23
   from GNU C systems.
24
 
40855 ripley 25
   There are different conventions for inlining across compilation units.
41631 ripley 26
   See http://www.greenend.org.uk/rjk/2003/03/inline.html
37087 ripley 27
 */
28
#ifndef R_INLINES_H_
29
#define R_INLINES_H_
30
 
59035 ripley 31
/* Probably not able to use C99 semantics in gcc < 4.3.0 */
41636 ripley 32
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 && defined(__GNUC_STDC_INLINE__) && !defined(C99_INLINE_SEMANTICS)
41631 ripley 33
#define C99_INLINE_SEMANTICS 1
34
#endif
35
 
41648 urbaneks 36
/* Apple's gcc build >5400 (since Xcode 3.0) doesn't support GNU inline in C99 mode */
43219 urbaneks 37
#if __APPLE_CC__ > 5400 && !defined(C99_INLINE_SEMANTICS) && __STDC_VERSION__ >= 199901L
41648 urbaneks 38
#define C99_INLINE_SEMANTICS 1
39
#endif
40
 
41631 ripley 41
#ifdef COMPILING_R
41637 ripley 42
/* defined only in inlined.c: this emits standalone code there */
41631 ripley 43
# define INLINE_FUN
44
#else
41838 ripley 45
/* This section is normally only used for versions of gcc which do not
46
   support C99 semantics.  __GNUC_STDC_INLINE__ is defined if
40870 ripley 47
   GCC is following C99 inline semantics by default: we
41838 ripley 48
   switch R's usage to the older GNU semantics via attributes.
49
   Do this even for __GNUC_GNUC_INLINE__ to shut up warnings in 4.2.x.
50
   __GNUC_STDC_INLINE__ and __GNUC_GNU_INLINE__ were added in gcc 4.2.0.
51
*/
41623 ripley 52
# if defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__)
40870 ripley 53
#  define INLINE_FUN extern __attribute__((gnu_inline)) inline
54
# else
55
#  define INLINE_FUN extern R_INLINE
56
# endif
41631 ripley 57
#endif /* ifdef COMPILING_R */
37087 ripley 58
 
41636 ripley 59
#if C99_INLINE_SEMANTICS
41631 ripley 60
# undef INLINE_FUN
61
# ifdef COMPILING_R
62
/* force exported copy */
63
#  define INLINE_FUN extern inline
64
# else
65
/* either inline or link to extern version at compiler's choice */
66
#  define INLINE_FUN inline
67
# endif /* ifdef COMPILING_R */
68
#endif /* C99_INLINE_SEMANTICS */
69
 
70
 
42397 ripley 71
#include <string.h> /* for strlen, strcmp */
41631 ripley 72
 
37087 ripley 73
/* define inline-able functions */
74
 
37088 ripley 75
 
76
/* from dstruct.c */
77
 
78
/*  length - length of objects  */
79
 
38662 ripley 80
int Rf_envlength(SEXP rho);
37088 ripley 81
 
48980 maechler 82
/* TODO: a  Length(.) {say} which is  length() + dispatch (S3 + S4) if needed
83
         for one approach, see do_seq_along() in ../main/seq.c
84
*/
37088 ripley 85
INLINE_FUN R_len_t length(SEXP s)
86
{
87
    int i;
88
    switch (TYPEOF(s)) {
89
    case NILSXP:
90
	return 0;
91
    case LGLSXP:
92
    case INTSXP:
93
    case REALSXP:
94
    case CPLXSXP:
95
    case STRSXP:
96
    case CHARSXP:
97
    case VECSXP:
98
    case EXPRSXP:
99
    case RAWSXP:
100
	return LENGTH(s);
101
    case LISTSXP:
102
    case LANGSXP:
103
    case DOTSXP:
104
	i = 0;
105
	while (s != NULL && s != R_NilValue) {
106
	    i++;
107
	    s = CDR(s);
108
	}
109
	return i;
110
    case ENVSXP:
38662 ripley 111
	return Rf_envlength(s);
37088 ripley 112
    default:
113
	return 1;
114
    }
115
}
116
 
59009 ripley 117
INLINE_FUN R_xlen_t xlength(SEXP s)
118
{
119
    int i;
120
    switch (TYPEOF(s)) {
121
    case NILSXP:
122
	return 0;
123
    case LGLSXP:
124
    case INTSXP:
125
    case REALSXP:
126
    case CPLXSXP:
127
    case STRSXP:
128
    case CHARSXP:
129
    case VECSXP:
130
    case EXPRSXP:
131
    case RAWSXP:
132
	return XLENGTH(s);
133
    case LISTSXP:
134
    case LANGSXP:
135
    case DOTSXP:
136
	i = 0;
137
	while (s != NULL && s != R_NilValue) {
138
	    i++;
139
	    s = CDR(s);
140
	}
141
	return i;
142
    case ENVSXP:
143
	return Rf_envlength(s);
144
    default:
145
	return 1;
146
    }
147
}
37088 ripley 148
 
59009 ripley 149
 
37088 ripley 150
/* from list.c */
151
/* Return a dotted pair with the given CAR and CDR. */
152
/* The (R) TAG slot on the cell is set to NULL. */
153
 
154
 
155
/* Get the i-th element of a list */
156
INLINE_FUN SEXP elt(SEXP list, int i)
157
{
158
    int j;
159
    SEXP result = list;
160
 
161
    if ((i < 0) || (i > length(list)))
162
	return R_NilValue;
163
    else
164
	for (j = 0; j < i; j++)
165
	    result = CDR(result);
166
 
167
    return CAR(result);
168
}
169
 
170
 
171
/* Return the last element of a list */
172
INLINE_FUN SEXP lastElt(SEXP list)
173
{
174
    SEXP result = R_NilValue;
175
    while (list != R_NilValue) {
176
	result = list;
177
	list = CDR(list);
178
    }
179
    return result;
180
}
181
 
182
 
183
/* Shorthands for creating small lists */
184
 
185
INLINE_FUN SEXP list1(SEXP s)
186
{
187
    return CONS(s, R_NilValue);
188
}
189
 
190
 
191
INLINE_FUN SEXP list2(SEXP s, SEXP t)
192
{
193
    PROTECT(s);
194
    s = CONS(s, list1(t));
195
    UNPROTECT(1);
196
    return s;
197
}
198
 
199
 
200
INLINE_FUN SEXP list3(SEXP s, SEXP t, SEXP u)
201
{
202
    PROTECT(s);
203
    s = CONS(s, list2(t, u));
204
    UNPROTECT(1);
205
    return s;
206
}
207
 
208
 
209
INLINE_FUN SEXP list4(SEXP s, SEXP t, SEXP u, SEXP v)
210
{
211
    PROTECT(s);
212
    s = CONS(s, list3(t, u, v));
213
    UNPROTECT(1);
214
    return s;
215
}
216
 
51659 maechler 217
INLINE_FUN SEXP list5(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w)
218
{
219
    PROTECT(s);
220
    s = CONS(s, list4(t, u, v, w));
221
    UNPROTECT(1);
222
    return s;
223
}
37088 ripley 224
 
51659 maechler 225
 
37088 ripley 226
/* Destructive list append : See also ``append'' */
227
 
228
INLINE_FUN SEXP listAppend(SEXP s, SEXP t)
229
{
230
    SEXP r;
231
    if (s == R_NilValue)
232
	return t;
233
    r = s;
234
    while (CDR(r) != R_NilValue)
235
	r = CDR(r);
236
    SETCDR(r, t);
237
    return s;
238
}
239
 
240
 
241
/* Language based list constructs.  These are identical to the list */
242
/* constructs, but the results can be evaluated. */
243
 
244
/* Return a (language) dotted pair with the given car and cdr */
245
 
246
INLINE_FUN SEXP lcons(SEXP car, SEXP cdr)
247
{
248
    SEXP e = cons(car, cdr);
249
    SET_TYPEOF(e, LANGSXP);
250
    return e;
251
}
252
 
253
INLINE_FUN SEXP lang1(SEXP s)
254
{
255
    return LCONS(s, R_NilValue);
256
}
257
 
258
INLINE_FUN SEXP lang2(SEXP s, SEXP t)
259
{
260
    PROTECT(s);
261
    s = LCONS(s, list1(t));
262
    UNPROTECT(1);
263
    return s;
264
}
265
 
266
INLINE_FUN SEXP lang3(SEXP s, SEXP t, SEXP u)
267
{
268
    PROTECT(s);
269
    s = LCONS(s, list2(t, u));
270
    UNPROTECT(1);
271
    return s;
272
}
273
 
274
INLINE_FUN SEXP lang4(SEXP s, SEXP t, SEXP u, SEXP v)
275
{
276
    PROTECT(s);
277
    s = LCONS(s, list3(t, u, v));
278
    UNPROTECT(1);
279
    return s;
280
}
281
 
51659 maechler 282
INLINE_FUN SEXP lang5(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w)
283
{
284
    PROTECT(s);
285
    s = LCONS(s, list4(t, u, v, w));
286
    UNPROTECT(1);
287
    return s;
288
}
289
 
290
INLINE_FUN SEXP lang6(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w, SEXP x)
291
{
292
    PROTECT(s);
293
    s = LCONS(s, list5(t, u, v, w, x));
294
    UNPROTECT(1);
295
    return s;
296
}
297
 
37088 ripley 298
/* from util.c */
299
 
37087 ripley 300
/* Check to see if the arrays "x" and "y" have the identical extents */
301
 
302
INLINE_FUN Rboolean conformable(SEXP x, SEXP y)
303
{
304
    int i, n;
305
    PROTECT(x = getAttrib(x, R_DimSymbol));
306
    y = getAttrib(y, R_DimSymbol);
307
    UNPROTECT(1);
308
    if ((n = length(x)) != length(y))
309
	return FALSE;
310
    for (i = 0; i < n; i++)
311
	if (INTEGER(x)[i] != INTEGER(y)[i])
312
	    return FALSE;
313
    return TRUE;
314
}
315
 
52431 maechler 316
/* NOTE: R's inherits() is based on inherits3() in ../main/objects.c
317
 * Here, use char / CHAR() instead of the slower more general translateChar()
318
 */
41781 ripley 319
INLINE_FUN Rboolean inherits(SEXP s, const char *name)
37087 ripley 320
{
39863 duncan 321
    SEXP klass;
37087 ripley 322
    int i, nclass;
41636 ripley 323
    if (OBJECT(s)) {
39863 duncan 324
	klass = getAttrib(s, R_ClassSymbol);
325
	nclass = length(klass);
37087 ripley 326
	for (i = 0; i < nclass; i++) {
39863 duncan 327
	    if (!strcmp(CHAR(STRING_ELT(klass, i)), name))
37087 ripley 328
		return TRUE;
329
	}
330
    }
331
    return FALSE;
332
}
333
 
334
INLINE_FUN Rboolean isValidString(SEXP x)
335
{
41636 ripley 336
    return TYPEOF(x) == STRSXP && LENGTH(x) > 0 && TYPEOF(STRING_ELT(x, 0)) != NILSXP;
37087 ripley 337
}
338
 
339
/* non-empty ("") valid string :*/
340
INLINE_FUN Rboolean isValidStringF(SEXP x)
341
{
342
    return isValidString(x) && CHAR(STRING_ELT(x, 0))[0];
343
}
344
 
345
INLINE_FUN Rboolean isUserBinop(SEXP s)
346
{
41636 ripley 347
    if (TYPEOF(s) == SYMSXP) {
41777 ripley 348
	const char *str = CHAR(PRINTNAME(s));
37087 ripley 349
	if (strlen(str) >= 2 && str[0] == '%' && str[strlen(str)-1] == '%')
350
	    return TRUE;
351
    }
352
    return FALSE;
353
}
354
 
355
INLINE_FUN Rboolean isFunction(SEXP s)
356
{
357
    return (TYPEOF(s) == CLOSXP ||
358
	    TYPEOF(s) == BUILTINSXP ||
359
	    TYPEOF(s) == SPECIALSXP);
360
}
361
 
362
INLINE_FUN Rboolean isPrimitive(SEXP s)
363
{
364
    return (TYPEOF(s) == BUILTINSXP ||
365
	    TYPEOF(s) == SPECIALSXP);
366
}
367
 
368
INLINE_FUN Rboolean isList(SEXP s)
369
{
370
    return (s == R_NilValue || TYPEOF(s) == LISTSXP);
371
}
372
 
373
 
374
INLINE_FUN Rboolean isNewList(SEXP s)
375
{
376
    return (s == R_NilValue || TYPEOF(s) == VECSXP);
377
}
378
 
379
INLINE_FUN Rboolean isPairList(SEXP s)
380
{
381
    switch (TYPEOF(s)) {
382
    case NILSXP:
383
    case LISTSXP:
384
    case LANGSXP:
385
	return TRUE;
386
    default:
387
	return FALSE;
388
    }
389
}
390
 
391
INLINE_FUN Rboolean isVectorList(SEXP s)
392
{
393
    switch (TYPEOF(s)) {
394
    case VECSXP:
395
    case EXPRSXP:
396
	return TRUE;
397
    default:
398
	return FALSE;
399
    }
400
}
401
 
402
INLINE_FUN Rboolean isVectorAtomic(SEXP s)
403
{
404
    switch (TYPEOF(s)) {
405
    case LGLSXP:
406
    case INTSXP:
407
    case REALSXP:
408
    case CPLXSXP:
409
    case STRSXP:
410
    case RAWSXP:
411
	return TRUE;
412
    default: /* including NULL */
413
	return FALSE;
414
    }
415
}
416
 
417
INLINE_FUN Rboolean isVector(SEXP s)/* === isVectorList() or isVectorAtomic() */
418
{
419
    switch(TYPEOF(s)) {
420
    case LGLSXP:
421
    case INTSXP:
422
    case REALSXP:
423
    case CPLXSXP:
424
    case STRSXP:
425
    case RAWSXP:
426
 
427
    case VECSXP:
428
    case EXPRSXP:
429
	return TRUE;
430
    default:
431
	return FALSE;
432
    }
433
}
434
 
435
INLINE_FUN Rboolean isFrame(SEXP s)
436
{
39863 duncan 437
    SEXP klass;
37087 ripley 438
    int i;
41636 ripley 439
    if (OBJECT(s)) {
39863 duncan 440
	klass = getAttrib(s, R_ClassSymbol);
441
	for (i = 0; i < length(klass); i++)
442
	    if (!strcmp(CHAR(STRING_ELT(klass, i)), "data.frame")) return TRUE;
37087 ripley 443
    }
444
    return FALSE;
445
}
446
 
447
INLINE_FUN Rboolean isLanguage(SEXP s)
448
{
449
    return (s == R_NilValue || TYPEOF(s) == LANGSXP);
450
}
451
 
452
INLINE_FUN Rboolean isMatrix(SEXP s)
453
{
454
    SEXP t;
455
    if (isVector(s)) {
456
	t = getAttrib(s, R_DimSymbol);
40675 ripley 457
	/* You are not supposed to be able to assign a non-integer dim,
458
	   although this might be possible by misuse of ATTRIB. */
37087 ripley 459
	if (TYPEOF(t) == INTSXP && LENGTH(t) == 2)
460
	    return TRUE;
461
    }
462
    return FALSE;
463
}
464
 
465
INLINE_FUN Rboolean isArray(SEXP s)
466
{
467
    SEXP t;
468
    if (isVector(s)) {
469
	t = getAttrib(s, R_DimSymbol);
40675 ripley 470
	/* You are not supposed to be able to assign a 0-length dim,
471
	 nor a non-integer dim */
37087 ripley 472
	if (TYPEOF(t) == INTSXP && LENGTH(t) > 0)
473
	    return TRUE;
474
    }
475
    return FALSE;
476
}
477
 
478
INLINE_FUN Rboolean isTs(SEXP s)
479
{
480
    return (isVector(s) && getAttrib(s, R_TspSymbol) != R_NilValue);
481
}
482
 
483
 
484
INLINE_FUN Rboolean isInteger(SEXP s)
485
{
486
    return (TYPEOF(s) == INTSXP && !inherits(s, "factor"));
487
}
488
 
489
INLINE_FUN Rboolean isFactor(SEXP s)
490
{
491
    return (TYPEOF(s) == INTSXP  && inherits(s, "factor"));
492
}
493
 
494
INLINE_FUN int nlevels(SEXP f)
495
{
496
    if (!isFactor(f))
497
	return 0;
498
    return LENGTH(getAttrib(f, R_LevelsSymbol));
499
}
500
 
501
/* Is an object of numeric type. */
502
/* FIXME:  the LGLSXP case should be excluded here
503
 * (really? in many places we affirm they are treated like INTs)*/
504
 
505
INLINE_FUN Rboolean isNumeric(SEXP s)
506
{
507
    switch(TYPEOF(s)) {
508
    case INTSXP:
509
	if (inherits(s,"factor")) return FALSE;
510
    case LGLSXP:
511
    case REALSXP:
512
	return TRUE;
513
    default:
514
	return FALSE;
515
    }
516
}
517
 
49903 maechler 518
/** Is an object "Numeric" or  complex */
519
INLINE_FUN Rboolean isNumber(SEXP s)
520
{
521
    switch(TYPEOF(s)) {
522
    case INTSXP:
523
	if (inherits(s,"factor")) return FALSE;
524
    case LGLSXP:
525
    case REALSXP:
526
    case CPLXSXP:
527
	return TRUE;
528
    default:
529
	return FALSE;
530
    }
531
}
532
 
38064 ripley 533
/* As from R 2.4.0 we check that the value is allowed. */
37087 ripley 534
INLINE_FUN SEXP ScalarLogical(int x)
535
{
59086 ripley 536
    SEXP ans = allocVector(LGLSXP, (R_xlen_t)1);
38547 ripley 537
    if (x == NA_LOGICAL) LOGICAL(ans)[0] = NA_LOGICAL;
538
    else LOGICAL(ans)[0] = (x != 0);
37087 ripley 539
    return ans;
540
}
541
 
542
INLINE_FUN SEXP ScalarInteger(int x)
543
{
59086 ripley 544
    SEXP ans = allocVector(INTSXP, (R_xlen_t)1);
37087 ripley 545
    INTEGER(ans)[0] = x;
546
    return ans;
547
}
548
 
549
INLINE_FUN SEXP ScalarReal(double x)
550
{
59086 ripley 551
    SEXP ans = allocVector(REALSXP, (R_xlen_t)1);
37087 ripley 552
    REAL(ans)[0] = x;
553
    return ans;
554
}
555
 
556
 
557
INLINE_FUN SEXP ScalarComplex(Rcomplex x)
558
{
59086 ripley 559
    SEXP ans = allocVector(CPLXSXP, (R_xlen_t)1);
37087 ripley 560
    COMPLEX(ans)[0] = x;
561
    return ans;
562
}
563
 
564
INLINE_FUN SEXP ScalarString(SEXP x)
565
{
566
    SEXP ans;
567
    PROTECT(x);
59086 ripley 568
    ans = allocVector(STRSXP, (R_xlen_t)1);
569
    SET_STRING_ELT(ans, (R_xlen_t)0, x);
37087 ripley 570
    UNPROTECT(1);
571
    return ans;
572
}
573
 
574
INLINE_FUN SEXP ScalarRaw(Rbyte x)
575
{
59086 ripley 576
    SEXP ans = allocVector(RAWSXP, (R_xlen_t)1);
37087 ripley 577
    RAW(ans)[0] = x;
578
    return ans;
579
}
580
 
581
/* Check to see if a list can be made into a vector. */
582
/* it must have every element being a vector of length 1. */
583
/* BUT it does not exclude 0! */
584
 
585
INLINE_FUN Rboolean isVectorizable(SEXP s)
586
{
41636 ripley 587
    if (s == R_NilValue) return TRUE;
37087 ripley 588
    else if (isNewList(s)) {
59086 ripley 589
	R_xlen_t i, n;
37087 ripley 590
 
59086 ripley 591
	n = XLENGTH(s);
37087 ripley 592
	for (i = 0 ; i < n; i++)
59086 ripley 593
	    if (!isVector(VECTOR_ELT(s, i)) || XLENGTH(VECTOR_ELT(s, i)) > 1)
37087 ripley 594
		return FALSE;
595
	return TRUE;
596
    }
597
    else if (isList(s)) {
598
	for ( ; s != R_NilValue; s = CDR(s))
599
	    if (!isVector(CAR(s)) || LENGTH(CAR(s)) > 1) return FALSE;
600
	return TRUE;
601
    }
602
    else return FALSE;
603
}
604
 
605
 
48980 maechler 606
/**
607
 * Create a named vector of type TYP
608
 *
48981 maechler 609
 * @example const char *nms[] = {"xi", "yi", "zi", ""};
49020 maechler 610
 *          mkNamed(VECSXP, nms);  =~= R  list(xi=, yi=, zi=)
48981 maechler 611
 *
48980 maechler 612
 * @param TYP a vector SEXP type (e.g. REALSXP)
613
 * @param names names of list elements with null string appended
614
 *
615
 * @return (pointer to a) named vector of type TYP
616
 */
51659 maechler 617
INLINE_FUN SEXP mkNamed(SEXPTYPE TYP, const char **names)
48980 maechler 618
{
619
    SEXP ans, nms;
59086 ripley 620
    R_xlen_t i, n;
48980 maechler 621
 
622
    for (n = 0; strlen(names[n]) > 0; n++) {}
623
    ans = PROTECT(allocVector(TYP, n));
624
    nms = PROTECT(allocVector(STRSXP, n));
625
    for (i = 0; i < n; i++)
626
	SET_STRING_ELT(nms, i, mkChar(names[i]));
627
    setAttrib(ans, R_NamesSymbol, nms);
628
    UNPROTECT(2);
629
    return ans;
630
}
631
 
632
 
37088 ripley 633
/* from gram.y */
37087 ripley 634
 
48822 maechler 635
/* short cut for  ScalarString(mkChar(s)) : */
37088 ripley 636
INLINE_FUN SEXP mkString(const char *s)
637
{
638
    SEXP t;
639
 
59086 ripley 640
    PROTECT(t = allocVector(STRSXP, (R_xlen_t)1));
641
    SET_STRING_ELT(t, (R_xlen_t)0, mkChar(s));
37088 ripley 642
    UNPROTECT(1);
643
    return t;
644
}
645
 
37087 ripley 646
#endif /* R_INLINES_H_ */