CXXR (C++ R)
Rinlinedfuns.h
1 /*CXXR $Id: Rinlinedfuns.h 1348 2013-02-25 17:49:03Z arr $
2  *CXXR
3  *CXXR This file is part of CXXR, a project to refactor the R interpreter
4  *CXXR into C++. It may consist in whole or in part of program code and
5  *CXXR documentation taken from the R project itself, incorporated into
6  *CXXR CXXR (and possibly MODIFIED) under the terms of the GNU General Public
7  *CXXR Licence.
8  *CXXR
9  *CXXR CXXR is Copyright (C) 2008-13 Andrew R. Runnalls, subject to such other
10  *CXXR copyrights and copyright restrictions as may be stated below.
11  *CXXR
12  *CXXR CXXR is not part of the R project, and bugs and other issues should
13  *CXXR not be reported via r-bugs or other R project channels; instead refer
14  *CXXR to the CXXR website.
15  *CXXR */
16 
17 /*
18  * R : A Computer Language for Statistical Data Analysis
19  * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka
20  * Copyright (C) 1999-2007 The R Core Team.
21  *
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation; either version 2 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, a copy is available at
34  * http://www.r-project.org/Licenses/
35  */
36 
37 /* this header is always to be included from others.
38  It is only called if COMPILING_R is defined (in util.c) or
39  from GNU C systems.
40 
41  There are different conventions for inlining across compilation units.
42  See http://www.greenend.org.uk/rjk/2003/03/inline.html
43  */
44 #ifndef R_INLINES_H_
45 #define R_INLINES_H_
46 
47 #ifndef __cplusplus
48 #define RBOOL(x) x
49 #else
50 #define RBOOL(x) Rboolean(x)
51 
52 extern "C" {
53 #endif /* __cplusplus */
54 
55 /* Probably not able to use C99 semantics in gcc < 4.3.0 but who knows what
56  unofficial versions Debian or RedHat will distribute */
57 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 && defined(__GNUC_STDC_INLINE__) && !defined(C99_INLINE_SEMANTICS)
58 #define C99_INLINE_SEMANTICS 1
59 #endif
60 
61 /* Apple's gcc build >5400 (since Xcode 3.0) doesn't support GNU inline in C99 mode */
62 #if __APPLE_CC__ > 5400 && !defined(C99_INLINE_SEMANTICS) && __STDC_VERSION__ >= 199901L
63 #define C99_INLINE_SEMANTICS 1
64 #endif
65 
66 #ifdef COMPILING_R
67 /* defined only in inlined.c: this emits standalone code there */
68 # define INLINE_FUN
69 #else
70 /* This section is normally only used for versions of gcc which do not
71  support C99 semantics. __GNUC_STDC_INLINE__ is defined if
72  GCC is following C99 inline semantics by default: we
73  switch R's usage to the older GNU semantics via attributes.
74  Do this even for __GNUC_GNUC_INLINE__ to shut up warnings in 4.2.x.
75  __GNUC_STDC_INLINE__ and __GNUC_GNU_INLINE__ were added in gcc 4.2.0.
76 */
77 # if defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__)
78 # define INLINE_FUN extern __attribute__((gnu_inline)) inline
79 # else
80 # define INLINE_FUN extern R_INLINE
81 # endif
82 #endif /* ifdef COMPILING_R */
83 
84 #if C99_INLINE_SEMANTICS
85 # undef INLINE_FUN
86 # ifdef COMPILING_R
87 /* force exported copy */
88 # define INLINE_FUN extern inline
89 # else
90 /* either inline or link to extern version at compiler's choice */
91 # define INLINE_FUN inline
92 # endif /* ifdef COMPILING_R */
93 #endif /* C99_INLINE_SEMANTICS */
94 
95 
96 #include <string.h> /* for strlen, strcmp */
97 
98 /* define inline-able functions */
99 
100 
101 /* from dstruct.c */
102 
103 /* length - length of objects */
104 
105 /* In CXXR, Rf_length() is not inlined, and is back in dstruct.cpp. */
106 R_len_t Rf_length(SEXP s);
107 /* TODO: a Length(.) {say} which is length() + dispatch (S3 + S4) if needed
108  for one approach, see do_seq_along() in ../main/seq.c
109 */
110 
111 /* from list.c */
112 /* Return a dotted pair with the given CAR and CDR. */
113 /* The (R) TAG slot on the cell is set to NULL. */
114 
115 
116 /* Get the i-th element of a list */
117 INLINE_FUN SEXP Rf_elt(SEXP list, int i)
118 {
119  int j;
120  SEXP result = list;
121 
122  if ((i < 0) || (i > Rf_length(list)))
123  return R_NilValue;
124  else
125  for (j = 0; j < i; j++)
126  result = CDR(result);
127 
128  return CAR(result);
129 }
130 
131 
132 /* Return the last element of a list */
133 INLINE_FUN SEXP Rf_lastElt(SEXP list)
134 {
135  SEXP result = R_NilValue;
136  while (list != R_NilValue) {
137  result = list;
138  list = CDR(list);
139  }
140  return result;
141 }
142 
143 
144 /* Shorthands for creating small lists */
145 
146 INLINE_FUN SEXP Rf_list1(SEXP s)
147 {
148  return CONS(s, R_NilValue);
149 }
150 
151 
152 INLINE_FUN SEXP Rf_list2(SEXP s, SEXP t)
153 {
154  PROTECT(s);
155  s = CONS(s, Rf_list1(t));
156  UNPROTECT(1);
157  return s;
158 }
159 
160 
161 INLINE_FUN SEXP Rf_list3(SEXP s, SEXP t, SEXP u)
162 {
163  PROTECT(s);
164  s = CONS(s, Rf_list2(t, u));
165  UNPROTECT(1);
166  return s;
167 }
168 
169 
170 INLINE_FUN SEXP Rf_list4(SEXP s, SEXP t, SEXP u, SEXP v)
171 {
172  PROTECT(s);
173  s = CONS(s, Rf_list3(t, u, v));
174  UNPROTECT(1);
175  return s;
176 }
177 
178 INLINE_FUN SEXP Rf_list5(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w)
179 {
180  PROTECT(s);
181  s = CONS(s, Rf_list4(t, u, v, w));
182  UNPROTECT(1);
183  return s;
184 }
185 
186 
187 /* Destructive list append : See also ``append'' */
188 
189 INLINE_FUN SEXP Rf_listAppend(SEXP s, SEXP t)
190 {
191  SEXP r;
192  if (s == R_NilValue)
193  return t;
194  r = s;
195  while (CDR(r) != R_NilValue)
196  r = CDR(r);
197  SETCDR(r, t);
198  return s;
199 }
200 
201 
202 /* Language based list constructs. These are identical to the list */
203 /* constructs, but the results can be evaluated. */
204 
205 /* Return a (language) dotted pair with the given car and cdr */
206 
207 INLINE_FUN SEXP Rf_lang1(SEXP s)
208 {
209  return LCONS(s, R_NilValue);
210 }
211 
212 INLINE_FUN SEXP Rf_lang2(SEXP s, SEXP t)
213 {
214  PROTECT(s);
215  s = LCONS(s, Rf_list1(t));
216  UNPROTECT(1);
217  return s;
218 }
219 
220 INLINE_FUN SEXP Rf_lang3(SEXP s, SEXP t, SEXP u)
221 {
222  PROTECT(s);
223  s = LCONS(s, Rf_list2(t, u));
224  UNPROTECT(1);
225  return s;
226 }
227 
228 INLINE_FUN SEXP Rf_lang4(SEXP s, SEXP t, SEXP u, SEXP v)
229 {
230  PROTECT(s);
231  s = LCONS(s, Rf_list3(t, u, v));
232  UNPROTECT(1);
233  return s;
234 }
235 
236 INLINE_FUN SEXP Rf_lang5(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w)
237 {
238  PROTECT(s);
239  s = LCONS(s, Rf_list4(t, u, v, w));
240  UNPROTECT(1);
241  return s;
242 }
243 
244 INLINE_FUN SEXP Rf_lang6(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w, SEXP x)
245 {
246  PROTECT(s);
247  s = LCONS(s, Rf_list5(t, u, v, w, x));
248  UNPROTECT(1);
249  return s;
250 }
251 
252 /* from util.c */
253 
254 /* Check to see if the arrays "x" and "y" have the identical extents */
255 
256 INLINE_FUN Rboolean Rf_conformable(SEXP x, SEXP y)
257 {
258  int i, n;
259  PROTECT(x = Rf_getAttrib(x, R_DimSymbol));
260  y = Rf_getAttrib(y, R_DimSymbol);
261  UNPROTECT(1);
262  if ((n = Rf_length(x)) != Rf_length(y))
263  return FALSE;
264  for (i = 0; i < n; i++)
265  if (INTEGER(x)[i] != INTEGER(y)[i])
266  return FALSE;
267  return TRUE;
268 }
269 
270 /* NOTE: R's inherits() is based on inherits3() in ../main/objects.c
271  * Here, use char / CHAR() instead of the slower more general translateChar()
272  */
273 INLINE_FUN Rboolean Rf_inherits(SEXP s, const char *name)
274 {
275  SEXP klass;
276  int i, nclass;
277  if (OBJECT(s)) {
278  klass = Rf_getAttrib(s, R_ClassSymbol);
279  nclass = Rf_length(klass);
280  for (i = 0; i < nclass; i++) {
281  if (!strcmp(CHAR(STRING_ELT(klass, i)), name))
282  return TRUE;
283  }
284  }
285  return FALSE;
286 }
287 
288 INLINE_FUN Rboolean Rf_isValidString(SEXP x)
289 {
290  return RBOOL(TYPEOF(x) == STRSXP && LENGTH(x) > 0
291  && TYPEOF(STRING_ELT(x, 0)) != NILSXP);
292 }
293 
294 /* non-empty ("") valid string :*/
295 INLINE_FUN Rboolean Rf_isValidStringF(SEXP x)
296 {
297  return RBOOL(Rf_isValidString(x) && CHAR(STRING_ELT(x, 0))[0]);
298 }
299 
300 INLINE_FUN Rboolean Rf_isUserBinop(SEXP s)
301 {
302  if (TYPEOF(s) == SYMSXP) {
303  const char *str = CHAR(PRINTNAME(s));
304  if (strlen(str) >= 2 && str[0] == '%' && str[strlen(str)-1] == '%')
305  return TRUE;
306  }
307  return FALSE;
308 }
309 
310 INLINE_FUN Rboolean Rf_isFunction(SEXP s)
311 {
312  return RBOOL(TYPEOF(s) == CLOSXP ||
313  TYPEOF(s) == BUILTINSXP ||
314  TYPEOF(s) == SPECIALSXP);
315 }
316 
317 INLINE_FUN Rboolean Rf_isPrimitive(SEXP s)
318 {
319  return RBOOL(TYPEOF(s) == BUILTINSXP ||
320  TYPEOF(s) == SPECIALSXP);
321 }
322 
323 INLINE_FUN Rboolean Rf_isList(SEXP s)
324 {
325  return RBOOL(s == R_NilValue || TYPEOF(s) == LISTSXP);
326 }
327 
328 
329 INLINE_FUN Rboolean Rf_isNewList(SEXP s)
330 {
331  return RBOOL(s == R_NilValue || TYPEOF(s) == VECSXP);
332 }
333 
334 INLINE_FUN Rboolean Rf_isPairList(SEXP s)
335 {
336  switch (TYPEOF(s)) {
337  case NILSXP:
338  case LISTSXP:
339  case LANGSXP:
340  return TRUE;
341  default:
342  return FALSE;
343  }
344 }
345 
346 INLINE_FUN Rboolean Rf_isVectorList(SEXP s)
347 {
348  switch (TYPEOF(s)) {
349  case VECSXP:
350  case EXPRSXP:
351  return TRUE;
352  default:
353  return FALSE;
354  }
355 }
356 
357 INLINE_FUN Rboolean Rf_isVectorAtomic(SEXP s)
358 {
359  switch (TYPEOF(s)) {
360  case LGLSXP:
361  case INTSXP:
362  case REALSXP:
363  case CPLXSXP:
364  case STRSXP:
365  case RAWSXP:
366  return TRUE;
367  default: /* including NULL */
368  return FALSE;
369  }
370 }
371 
372 INLINE_FUN Rboolean Rf_isFrame(SEXP s)
373 {
374  SEXP klass;
375  int i;
376  if (OBJECT(s)) {
377  klass = Rf_getAttrib(s, R_ClassSymbol);
378  for (i = 0; i < Rf_length(klass); i++)
379  if (!strcmp(CHAR(STRING_ELT(klass, i)), "data.frame")) return TRUE;
380  }
381  return FALSE;
382 }
383 
384 INLINE_FUN Rboolean Rf_isLanguage(SEXP s)
385 {
386  return RBOOL(s == R_NilValue || TYPEOF(s) == LANGSXP);
387 }
388 
389 INLINE_FUN Rboolean Rf_isMatrix(SEXP s)
390 {
391  SEXP t;
392  if (Rf_isVector(s)) {
393  t = Rf_getAttrib(s, R_DimSymbol);
394  /* You are not supposed to be able to assign a non-integer dim,
395  although this might be possible by misuse of ATTRIB. */
396  if (TYPEOF(t) == INTSXP && LENGTH(t) == 2)
397  return TRUE;
398  }
399  return FALSE;
400 }
401 
402 INLINE_FUN Rboolean Rf_isArray(SEXP s)
403 {
404  SEXP t;
405  if (Rf_isVector(s)) {
406  t = Rf_getAttrib(s, R_DimSymbol);
407  /* You are not supposed to be able to assign a 0-length dim,
408  nor a non-integer dim */
409  if (TYPEOF(t) == INTSXP && LENGTH(t) > 0)
410  return TRUE;
411  }
412  return FALSE;
413 }
414 
415 INLINE_FUN Rboolean Rf_isTs(SEXP s)
416 {
417  return RBOOL(Rf_isVector(s) && Rf_getAttrib(s, R_TspSymbol) != R_NilValue);
418 }
419 
420 INLINE_FUN Rboolean Rf_isInteger(SEXP s)
421 {
422  return RBOOL(TYPEOF(s) == INTSXP && !Rf_inherits(s, "factor"));
423 }
424 
425 INLINE_FUN Rboolean Rf_isFactor(SEXP s)
426 {
427  return RBOOL(TYPEOF(s) == INTSXP && Rf_inherits(s, "factor"));
428 }
429 
430 INLINE_FUN int Rf_nlevels(SEXP f)
431 {
432  if (!Rf_isFactor(f))
433  return 0;
434  return LENGTH(Rf_getAttrib(f, R_LevelsSymbol));
435 }
436 
437 /* Is an object of numeric type. */
438 /* FIXME: the LGLSXP case should be excluded here
439  * (really? in many places we affirm they are treated like INTs)*/
440 
441 INLINE_FUN Rboolean Rf_isNumeric(SEXP s)
442 {
443  switch(TYPEOF(s)) {
444  case INTSXP:
445  if (Rf_inherits(s,"factor")) return FALSE;
446  case LGLSXP:
447  case REALSXP:
448  return TRUE;
449  default:
450  return FALSE;
451  }
452 }
453 
455 INLINE_FUN Rboolean Rf_isNumber(SEXP s)
456 {
457  switch(TYPEOF(s)) {
458  case INTSXP:
459  if (Rf_inherits(s,"factor")) return FALSE;
460  case LGLSXP:
461  case REALSXP:
462  case CPLXSXP:
463  return TRUE;
464  default:
465  return FALSE;
466  }
467 }
468 
469 /* As from R 2.4.0 we check that the value is allowed. */
470 INLINE_FUN SEXP Rf_ScalarLogical(int x)
471 {
472  SEXP ans = Rf_allocVector(LGLSXP, 1);
473  if (x == NA_LOGICAL) LOGICAL(ans)[0] = NA_LOGICAL;
474  else LOGICAL(ans)[0] = (x != 0);
475  return ans;
476 }
477 
478 INLINE_FUN SEXP Rf_ScalarInteger(int x)
479 {
480  SEXP ans = Rf_allocVector(INTSXP, 1);
481  INTEGER(ans)[0] = x;
482  return ans;
483 }
484 
485 INLINE_FUN SEXP Rf_ScalarReal(double x)
486 {
487  SEXP ans = Rf_allocVector(REALSXP, 1);
488  REAL(ans)[0] = x;
489  return ans;
490 }
491 
492 
493 INLINE_FUN SEXP Rf_ScalarComplex(Rcomplex x)
494 {
495  SEXP ans = Rf_allocVector(CPLXSXP, 1);
496  COMPLEX(ans)[0] = x;
497  return ans;
498 }
499 
500 INLINE_FUN SEXP Rf_ScalarString(SEXP x)
501 {
502  SEXP ans;
503  PROTECT(x);
504  ans = Rf_allocVector(STRSXP, 1);
505  SET_STRING_ELT(ans, 0, x);
506  UNPROTECT(1);
507  return ans;
508 }
509 
510 INLINE_FUN SEXP Rf_ScalarRaw(Rbyte x)
511 {
512  SEXP ans = Rf_allocVector(RAWSXP, 1);
513  RAW(ans)[0] = x;
514  return ans;
515 }
516 
517 /* Check to see if a list can be made into a vector. */
518 /* it must have every element being a vector of length 1. */
519 /* BUT it does not exclude 0! */
520 
521 INLINE_FUN Rboolean Rf_isVectorizable(SEXP s)
522 {
523  if (s == R_NilValue) return TRUE;
524  else if (Rf_isNewList(s)) {
525  int i, n;
526 
527  n = LENGTH(s);
528  for (i = 0 ; i < n; i++)
529  if (!Rf_isVector(VECTOR_ELT(s, i)) || LENGTH(VECTOR_ELT(s, i)) > 1)
530  return FALSE;
531  return TRUE;
532  }
533  else if (Rf_isList(s)) {
534  for ( ; s != R_NilValue; s = CDR(s))
535  if (!Rf_isVector(CAR(s)) || LENGTH(CAR(s)) > 1) return FALSE;
536  return TRUE;
537  }
538  else return FALSE;
539 }
540 
541 
554 INLINE_FUN SEXP mkNamed(SEXPTYPE TYP, const char **names)
555 {
556  SEXP ans, nms;
557  int i, n;
558 
559  for (n = 0; strlen(names[n]) > 0; n++) {}
560  ans = PROTECT(Rf_allocVector(TYP, n));
561  nms = PROTECT(Rf_allocVector(STRSXP, n));
562  for (i = 0; i < n; i++)
563  SET_STRING_ELT(nms, i, Rf_mkChar(names[i]));
564  Rf_setAttrib(ans, R_NamesSymbol, nms);
565  UNPROTECT(2);
566  return ans;
567 }
568 
569 
570 /* from gram.y */
571 
572 /* short cut for ScalarString(mkChar(s)) : */
573 INLINE_FUN SEXP Rf_mkString(const char *s)
574 {
575  SEXP t;
576 
577  PROTECT(t = Rf_allocVector(STRSXP, 1));
578  SET_STRING_ELT(t, 0, Rf_mkChar(s));
579  UNPROTECT(1);
580  return t;
581 }
582 
583 #ifdef __cplusplus
584 } /* extern "C" */
585 #endif
586 
587 #endif /* R_INLINES_H_ */