File: r_coerce.h

package info (click to toggle)
rcpp 1.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,480 kB
  • sloc: cpp: 27,436; ansic: 7,778; sh: 53; makefile: 2
file content (301 lines) | stat: -rw-r--r-- 8,448 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
/* :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1: */
//
// r_coerce.h: Rcpp R/C++ interface class library -- coercion
//
// Copyright (C) 2010 - 2013 Dirk Eddelbuettel, Romain Francois, and Kevin Ushey
//
// This file is part of Rcpp.
//
// Rcpp is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Rcpp is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.

#ifndef Rcpp__internal__r_coerce__h
#define Rcpp__internal__r_coerce__h

namespace Rcpp{
namespace internal{

template <int FROM, int TO>
typename ::Rcpp::traits::storage_type<TO>::type
r_coerce( typename ::Rcpp::traits::storage_type<FROM>::type from ) ;

template <>
inline int r_coerce<INTSXP,INTSXP>(int from) { return from ; }

template <>
inline int r_coerce<LGLSXP,LGLSXP>(int from) { return from ; }

template <>
inline double r_coerce<REALSXP,REALSXP>(double from) { return from ; }

template <>
inline Rcomplex r_coerce<CPLXSXP,CPLXSXP>(Rcomplex from) { return from ; }

template <>
inline Rbyte r_coerce<RAWSXP,RAWSXP>(Rbyte from) { return from ; }

// -> INTSXP
template <>
inline int r_coerce<LGLSXP,INTSXP>(int from){
	return (from==NA_LOGICAL) ? NA_INTEGER : from ;
}
template <>
inline int r_coerce<REALSXP,INTSXP>(double from){
	if (Rcpp_IsNA(from)) {
		return NA_INTEGER;
	} else if (from > INT_MAX || from <= INT_MIN ) {
		return NA_INTEGER;
	}
	return static_cast<int>(from);

}
template <>
inline int r_coerce<CPLXSXP,INTSXP>(Rcomplex from){
	return r_coerce<REALSXP,INTSXP>(from.r) ;
}
template <>
inline int r_coerce<RAWSXP,INTSXP>(Rbyte from){
	return static_cast<int>(from);
}

// -> REALSXP
template <>
inline double r_coerce<LGLSXP,REALSXP>(int from){
	return from == NA_LOGICAL ? NA_REAL : static_cast<double>(from) ;
}
template <>
inline double r_coerce<INTSXP,REALSXP>(int from){
	return from == NA_INTEGER ? NA_REAL : static_cast<double>(from) ;
}
template <>
inline double r_coerce<CPLXSXP,REALSXP>(Rcomplex from){
	return from.r ;
}
template <>
inline double r_coerce<RAWSXP,REALSXP>(Rbyte from){
	return static_cast<double>(from) ;
}

// -> LGLSXP
template <>
inline int r_coerce<REALSXP,LGLSXP>(double from){
	return Rcpp_IsNA(from) ? NA_LOGICAL : (from!=0.0);
}

template <>
inline int r_coerce<INTSXP,LGLSXP>(int from){
	return ( from == NA_INTEGER ) ? NA_LOGICAL : (from!=0);
}

template <>
inline int r_coerce<CPLXSXP,LGLSXP>(Rcomplex from){
	if( Rcpp_IsNA(from.r) ) return NA_LOGICAL ;
	if( from.r == 0.0 || from.i == 0.0 ) return FALSE ;
	return TRUE ;
}

template <>
inline int r_coerce<RAWSXP,LGLSXP>(Rbyte from){
	if( from != static_cast<Rbyte>(0) ) return TRUE ;
	return FALSE ;
}

// -> RAWSXP
template <>
inline Rbyte r_coerce<INTSXP,RAWSXP>(int from){
	return (from < 0 || from > 255) ? static_cast<Rbyte>(0) : static_cast<Rbyte>(from) ;
}

template <>
inline Rbyte r_coerce<REALSXP,RAWSXP>(double from){
	if( Rcpp_IsNA(from) ) return static_cast<Rbyte>(0) ;
	return r_coerce<INTSXP,RAWSXP>(static_cast<int>(from)) ;
}

template <>
inline Rbyte r_coerce<CPLXSXP,RAWSXP>(Rcomplex from){
	 return r_coerce<REALSXP,RAWSXP>(from.r) ;
}

template <>
inline Rbyte r_coerce<LGLSXP,RAWSXP>(int from){
	return static_cast<Rbyte>(from == TRUE) ;
}

// -> CPLXSXP
template <>
inline Rcomplex r_coerce<REALSXP,CPLXSXP>(double from){
	Rcomplex c ;
	if( Rcpp_IsNA(from) ){
		c.r = NA_REAL;
		c.i = NA_REAL;
	} else{
		c.r = from ;
		c.i = 0.0 ;
	}
	return c ;
}

template <>
inline Rcomplex r_coerce<INTSXP,CPLXSXP>(int from){
	Rcomplex c ;
	if( from == NA_INTEGER ){
		c.r = NA_REAL;
		c.i = NA_REAL;
	} else{
		c.r = static_cast<double>(from) ;
		c.i = 0.0 ;
	}
	return c ;
}

template <>
inline Rcomplex r_coerce<RAWSXP,CPLXSXP>(Rbyte from){
	Rcomplex c ;
	c.r = static_cast<double>(from);
	c.i = 0.0 ;
	return c ;
}

template <>
inline Rcomplex r_coerce<LGLSXP,CPLXSXP>(int from){
	Rcomplex c ;
	if( from == TRUE ){
		c.r = 1.0 ; c.i = 0.0 ;
	} else if( from == FALSE ){
		c.r = c.i = 0.0 ;
	} else { /* NA */
		c.r = c.i = NA_REAL;
	}
	return c ;
}

// -> STRSXP
template <int RTYPE>
const char* coerce_to_string( typename ::Rcpp::traits::storage_type<RTYPE>::type from ) ;

inline const char* dropTrailing0(char *s, char cdec) {
    /* Note that  's'  is modified */
    char *p = s;
    for (p = s; *p; p++) {
        if(*p == cdec) {
            char *replace = p++;
            while ('0' <= *p  &&  *p <= '9')
            if(*(p++) != '0')
                replace = p;
            if(replace != p)
                while((*(replace++) = *(p++))) ;
            break;
        }
    }
    return s;
}

inline int integer_width( int n ){
    return n < 0 ? ( (int) ( ::log10( -n+0.5) + 2 ) ) : ( (int) ( ::log10( n+0.5) + 1 ) ) ;
}

template <>
inline const char* coerce_to_string<CPLXSXP>(Rcomplex x){
	//int wr, dr, er, wi, di, ei;
    //Rf_formatComplex(&x, 1, &wr, &dr, &er, &wi, &di, &ei, 0);
    // we are no longer allowed to use this:
    //     Rf_EncodeComplex(x, wr, dr, er, wi, di, ei, '.' );
    // so approximate it poorly as
    static char tmp1[128], tmp2[128], tmp3[256];
    //snprintf(tmp, 127, "%*.*f+%*.*fi", wr, dr, x.r, wi, di, x.i);
    //snprintf(tmp, 127, "%f+%fi", x.r, x.i); // FIXEM: barebones default formatting
    snprintf(tmp1, 127, "%f", x.r);
    snprintf(tmp2, 127, "%f", x.i);
    snprintf(tmp3, 255, "%s+%si", dropTrailing0(tmp1, '.'), dropTrailing0(tmp2, '.'));
    return tmp3;
}
template <>
inline const char* coerce_to_string<REALSXP>(double x){
	//int w,d,e ;
    // cf src/main/format.c in R's sources:
    //   The return values are
    //     w : the required field width
    //     d : use %w.df in fixed format, %#w.de in scientific format
    //     e : use scientific format if != 0, value is number of exp digits - 1
    //
    //   nsmall specifies the minimum number of decimal digits in fixed format:
    //   it is 0 except when called from do_format.
    //Rf_formatReal( &x, 1, &w, &d, &e, 0 ) ;
    // we are no longer allowed to use this:
    //     char* tmp = const_cast<char*>( Rf_EncodeReal(x, w, d, e, '.') );
    // so approximate it poorly as

    static char tmp[128];
    snprintf(tmp, 127, "%f", x);
    if (strcmp( dropTrailing0(tmp, '.'), "-0") == 0) return "0";
    else return dropTrailing0(tmp, '.');
}
#define NB 1000
template <>
inline const char* coerce_to_string<INTSXP >(int from) {
	static char buffer[NB] ;
    snprintf(buffer, NB, "%*d", integer_width(from), from);
    return buffer ;
}
template <>
inline const char* coerce_to_string<RAWSXP >(Rbyte from){
	static char buff[3];
    snprintf(buff, 3, "%02x", from);
    return buff;
}
template <>
inline const char* coerce_to_string<LGLSXP >(int from){
	return from == 0 ? "FALSE" : "TRUE" ;
}

#undef NB
template <>
inline SEXP r_coerce<STRSXP ,STRSXP>(SEXP from){
	return from ;
}
template <>
inline SEXP r_coerce<CPLXSXP,STRSXP>(Rcomplex from) {
	return Rcpp::traits::is_na<CPLXSXP>(from) ? NA_STRING : Rf_mkChar( coerce_to_string<CPLXSXP>( from ) ) ;
}
template <>
inline SEXP r_coerce<REALSXP,STRSXP>(double from){

  // handle some special values explicitly
  if (Rcpp_IsNaN(from)) return Rf_mkChar("NaN");
  else if (from == R_PosInf) return Rf_mkChar("Inf");
  else if (from == R_NegInf) return Rf_mkChar("-Inf");
  else return Rcpp::traits::is_na<REALSXP>(from) ? NA_STRING :Rf_mkChar( coerce_to_string<REALSXP>( from ) ) ;
}
template <>
inline SEXP r_coerce<INTSXP ,STRSXP>(int from){
	return Rcpp::traits::is_na<INTSXP>(from) ? NA_STRING :Rf_mkChar( coerce_to_string<INTSXP>( from ) ) ;
}
template <>
inline SEXP r_coerce<RAWSXP ,STRSXP>(Rbyte from){
	return Rf_mkChar( coerce_to_string<RAWSXP>(from));
}
template <>
inline SEXP r_coerce<LGLSXP ,STRSXP>(int from){
	return Rcpp::traits::is_na<LGLSXP>(from) ? NA_STRING :Rf_mkChar( coerce_to_string<LGLSXP>(from));
}
template <>
inline SEXP r_coerce<SYMSXP ,STRSXP>(SEXP from){
	return Rf_ScalarString( PRINTNAME(from) ) ;
}

} // internal
} // Rcpp

#endif