00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef Rcpp_hpp
00023 #define Rcpp_hpp
00024
00025 #include <iostream>
00026 #include <sstream>
00027 #include <string>
00028 #include <list>
00029 #include <map>
00030 #include <stdexcept>
00031 #include <vector>
00032
00033
00034 #define R_NO_REMAP
00035
00036 #include <R.h>
00037 #include <Rinternals.h>
00038
00039
00040
00041
00042 #define RcppExport extern "C"
00043
00044
00045 char *copyMessageToR(const char* const mesg);
00046
00047 class RcppDate {
00048 private:
00049 void mdy2jdn();
00050 void jdn2mdy();
00051 int month, day, year;
00052 int jdn;
00053
00054 public:
00055 static const int Jan1970Offset;
00056 static const int QLtoJan1970Offset;
00057 RcppDate() { month=1, day=1, year=1970; mdy2jdn(); }
00058 RcppDate(int Rjdn) { jdn = Rjdn+Jan1970Offset; jdn2mdy(); }
00059 RcppDate(int month_, int day_, int year_) : month(month_),
00060 day(day_),
00061 year(year_) {
00062 if (month < 1 || month > 12 || day < 1 || day > 31)
00063 throw std::range_error("RcppDate: invalid date");
00064 mdy2jdn();
00065 }
00066 int getMonth() const { return month; }
00067 int getDay() const { return day; }
00068 int getYear() const { return year; }
00069 int getJDN() const { return jdn; }
00070
00071
00072
00073
00074 friend RcppDate operator+(const RcppDate &date, int offset);
00075 friend int operator-(const RcppDate& date1, const RcppDate& date2);
00076 friend bool operator<(const RcppDate &date1, const RcppDate& date2);
00077 friend bool operator>(const RcppDate &date1, const RcppDate& date2);
00078 friend bool operator==(const RcppDate &date1, const RcppDate& date2);
00079 friend bool operator>=(const RcppDate &date1, const RcppDate& date2);
00080 friend bool operator<=(const RcppDate &date1, const RcppDate& date2);
00081
00082 friend std::ostream& operator<<(std::ostream& os, const RcppDate& date);
00083
00084
00085
00086
00087
00088 };
00089
00090 class RcppDatetime {
00091 private:
00092 double m_d;
00093 bool m_parsed;
00094 int m_us;
00095 struct tm m_tm;
00096 void parseTime() {
00097 time_t tt;
00098 tt = floor(m_d);
00099 m_us = round( (m_d - tt) * 1.0e6);
00100 m_tm = *localtime(&tt);
00101 m_parsed = true;
00102
00103 };
00104
00105 protected:
00106
00107 friend class ColDatum;
00108
00109
00110 public:
00111 RcppDatetime(void) : m_d(0), m_parsed(false), m_us(0) { };
00112 RcppDatetime(const double d) : m_d(d), m_parsed(false), m_us(0) { };
00113
00114 double getFractionalTimestamp(void) const { return m_d; }
00115
00116 int getYear(void) { if (!m_parsed) parseTime(); return m_tm.tm_year + 1900; }
00117 int getMonth(void) { if (!m_parsed) parseTime(); return m_tm.tm_mon + 1; }
00118 int getDay(void) { if (!m_parsed) parseTime(); return m_tm.tm_mday; }
00119 int getWeekday(void) { if (!m_parsed) parseTime(); return m_tm.tm_wday; }
00120 int getHour(void) { if (!m_parsed) parseTime(); return m_tm.tm_hour; }
00121 int getMinute(void) { if (!m_parsed) parseTime(); return m_tm.tm_min; }
00122 int getSecond(void) { if (!m_parsed) parseTime(); return m_tm.tm_sec; }
00123 int getMicroSec(void) { if (!m_parsed) parseTime(); return m_us; }
00124
00125 friend RcppDatetime operator+(const RcppDatetime &date, double offset) {
00126 RcppDatetime tmp(date.m_d);
00127 tmp.m_d += offset;
00128 tmp.m_parsed = false;
00129 return tmp;
00130 }
00131 friend double operator-(const RcppDatetime& dt1, const RcppDatetime& dt2) { return dt2.m_d - dt1.m_d; }
00132 friend bool operator<(const RcppDatetime &dt1, const RcppDatetime& dt2) { return dt1.m_d < dt2.m_d; }
00133 friend bool operator<=(const RcppDatetime &dt1, const RcppDatetime& dt2) { return dt1.m_d <= dt2.m_d; }
00134 friend bool operator>(const RcppDatetime &dt1, const RcppDatetime& dt2) { return dt1.m_d > dt2.m_d; }
00135 friend bool operator>=(const RcppDatetime &dt1, const RcppDatetime& dt2) { return dt1.m_d >= dt2.m_d; }
00136 friend bool operator==(const RcppDatetime &dt1, const RcppDatetime& dt2) { return dt1.m_d == dt2.m_d; }
00137
00138 friend std::ostream& operator<<(std::ostream& os, const RcppDatetime &datetime) {
00139 RcppDatetime dt(datetime);
00140 dt.parseTime();
00141 char buf[32], usec[16];
00142 strftime(buf, 31, "%Y-%m-%d %H:%M:%S", &dt.m_tm);
00143 snprintf(usec, 15, ".%.06d", dt.m_us);
00144 os << buf << usec;
00145 return os;
00146 }
00147
00148 };
00149
00150 class RcppParams {
00151 public:
00152 RcppParams(SEXP params);
00153 void checkNames(char *inputNames[], int len);
00154 bool exists(std::string name);
00155 double getDoubleValue(std::string name);
00156 int getIntValue(std::string name);
00157 std::string getStringValue(std::string name);
00158 bool getBoolValue(std::string name);
00159 RcppDate getDateValue(std::string name);
00160 RcppDatetime getDatetimeValue(std::string name);
00161 private:
00162 std::map<std::string, int> pmap;
00163 SEXP _params;
00164 };
00165
00166
00167 enum ColType { COLTYPE_DOUBLE, COLTYPE_INT, COLTYPE_STRING,
00168 COLTYPE_FACTOR, COLTYPE_LOGICAL,
00169 COLTYPE_DATE, COLTYPE_DATETIME };
00170
00171 class ColDatum {
00172 public:
00173 ColDatum() {
00174 level = 0;
00175 }
00176 ~ColDatum() {
00177 if (type == COLTYPE_FACTOR) {
00178
00179
00180
00181
00182
00183 delete [] levelNames;
00184 }
00185 }
00186 ColDatum(const ColDatum& datum) {
00187
00188
00189 s = datum.s;
00190 x = datum.x;
00191 i = datum.i;
00192 type = datum.type;
00193 level = datum.level;
00194 numLevels = datum.numLevels;
00195 d = datum.d;
00196 if (type == COLTYPE_FACTOR) {
00197 levelNames = new std::string[numLevels];
00198 for (int i = 0; i < numLevels; i++)
00199 levelNames[i] = datum.levelNames[i];
00200 }
00201 }
00202
00203 ColType getType() const { return type; }
00204
00205 void setDoubleValue(double val) { x = val; type = COLTYPE_DOUBLE; }
00206 void setIntValue(int val) { i = val; type = COLTYPE_INT; }
00207 void setLogicalValue(int val) {
00208 if (val != 0 && val != 1)
00209 throw std::range_error("ColDatum::setLogicalValue: logical values must be 0/1.");
00210 i = val; type = COLTYPE_LOGICAL;
00211 }
00212 void setStringValue(std::string val) { s = val; type = COLTYPE_STRING; }
00213 void setDateValue(RcppDate date) {
00214 d = date;
00215 type = COLTYPE_DATE;
00216 }
00217 void setDatetimeValue(RcppDatetime datetime) {
00218 x = datetime.m_d;
00219 type = COLTYPE_DATETIME;
00220 }
00221 void setFactorValue(std::string *names, int numNames, int factorLevel) {
00222 if (factorLevel < 1 || factorLevel > numNames)
00223 throw std::range_error("ColDatum::setFactorValue: factor level out of range");
00224 level = factorLevel;
00225 numLevels = numNames;
00226 levelNames = new std::string[numLevels];
00227 for (int i = 0; i < numLevels; i++)
00228 levelNames[i] = names[i];
00229 type = COLTYPE_FACTOR;
00230 }
00231
00232 double getDoubleValue() {
00233 if (type != COLTYPE_DOUBLE)
00234 throw std::range_error("ColDatum::getDoubleValue: wrong data type in getDoubleValue");
00235 return x;
00236 }
00237 int getIntValue() {
00238 if (type != COLTYPE_INT)
00239 throw std::range_error("ColDatum::getIntValue: wrong data type in getIntValue");
00240 return i;
00241 }
00242 int getLogicalValue() {
00243 if (type != COLTYPE_LOGICAL)
00244 throw std::range_error("ColDatum::getLogicalValue: wrong data type in getLogicalValue");
00245 return i;
00246 }
00247 std::string getStringValue() {
00248 if (type != COLTYPE_STRING)
00249 throw std::range_error("ColDatum::getStringValue: wrong data type in getStringValue");
00250 return s;
00251 }
00252 RcppDate getDateValue() {
00253 if (type != COLTYPE_DATE)
00254 throw std::range_error("ColDatum::getDateValue: wrong data type in getDateValue");
00255 return d;
00256 }
00257 double getDateRCode() {
00258 return (double)(d.getJDN() - RcppDate::Jan1970Offset);
00259 }
00260 RcppDatetime getDatetimeValue() {
00261 if (type != COLTYPE_DATETIME)
00262 throw std::range_error("ColDatum::getDatetimeValue: wrong data type in getDatetimeValue");
00263 return RcppDatetime(x);
00264 }
00265
00266 void checkFactorType() {
00267 if (type != COLTYPE_FACTOR)
00268 throw std::range_error("ColDatun::checkFactorType: wrong data type in getFactor...");
00269 }
00270 int getFactorNumLevels() { checkFactorType(); return numLevels; }
00271 int getFactorLevel() { checkFactorType(); return level; }
00272 std::string *getFactorLevelNames() { checkFactorType(); return levelNames; }
00273 std::string getFactorLevelName() { checkFactorType(); return levelNames[level-1];}
00274
00275 private:
00276 ColType type;
00277 std::string s;
00278 double x;
00279 int i;
00280 int level;
00281 int numLevels;
00282 std::string *levelNames;
00283 RcppDate d;
00284 };
00285
00286 class RcppFrame {
00287 std::vector<std::string> colNames;
00288 std::vector<std::vector<ColDatum> > table;
00289 public:
00290 RcppFrame(SEXP df);
00291 RcppFrame(std::vector<std::string> colNames) : colNames(colNames) {
00292 if (colNames.size() == 0)
00293 throw std::range_error("RcppFrame::RcppFrame: zero length colNames");
00294 }
00295 std::vector<std::string>& getColNames() { return colNames; }
00296 std::vector<std::vector<ColDatum> >& getTableData() { return table; }
00297 void addRow(std::vector<ColDatum> rowData) {
00298 if (rowData.size() != colNames.size())
00299 throw std::range_error("RcppFrame::addRow: incorrect row length.");
00300 if (table.size() > 0) {
00301
00302
00303
00304 for (int i = 0; i < (int)colNames.size(); i++) {
00305 if (rowData[i].getType() != table[0][i].getType()) {
00306 std::ostringstream oss;
00307 oss << "RcppFrame::addRow: incorrect data type at posn "
00308 << i;
00309 throw std::range_error(oss.str());
00310 }
00311 }
00312 }
00313 table.push_back(rowData);
00314 }
00315 int rows() { return table.size(); }
00316 int cols() { return table[0].size(); }
00317 };
00318
00319 class RcppNumList {
00320 public:
00321 RcppNumList(SEXP theList) {
00322 if (!Rf_isNewList(theList))
00323 throw std::range_error("RcppNumList: non-list passed to constructor");
00324 len = Rf_length(theList);
00325 names = Rf_getAttrib(theList, R_NamesSymbol);
00326 namedList = theList;
00327 }
00328 std::string getName(int i) {
00329 if (i < 0 || i >= len) {
00330 std::ostringstream oss;
00331 oss << "RcppNumList::getName: index out of bounds: " << i;
00332 throw std::range_error(oss.str());
00333 }
00334 return std::string(CHAR(STRING_ELT(names,i)));
00335 }
00336 double getValue(int i) {
00337 if (i < 0 || i >= len) {
00338 std::ostringstream oss;
00339 oss << "RcppNumList::getValue: index out of bounds: " << i;
00340 throw std::range_error(oss.str());
00341 }
00342 SEXP elt = VECTOR_ELT(namedList, i);
00343 if (Rf_isReal(elt))
00344 return REAL(elt)[0];
00345 else if (Rf_isInteger(elt))
00346 return (double)INTEGER(elt)[0];
00347 else
00348 throw std::range_error("RcppNumList: contains non-numeric value");
00349 return 0;
00350 }
00351 int size() { return len; }
00352 private:
00353 int len;
00354 SEXP namedList;
00355 SEXP names;
00356 };
00357
00358 template <typename T>
00359 class RcppVector {
00360 public:
00361 RcppVector(SEXP vec);
00362 RcppVector(int len);
00363 int size() { return len; }
00364 inline T& operator()(int i) {
00365 if (i < 0 || i >= len) {
00366 std::ostringstream oss;
00367 oss << "RcppVector: subscript out of range: " << i;
00368 throw std::range_error(oss.str());
00369 }
00370 return v[i];
00371 }
00372 T *cVector();
00373 std::vector<T> stlVector();
00374 private:
00375 int len;
00376 T *v;
00377 };
00378
00379 class RcppStringVector {
00380 public:
00381 RcppStringVector(SEXP vec);
00382 ~RcppStringVector() {
00383 delete [] v;
00384 }
00385 inline std::string& operator()(int i) {
00386 if (i < 0 || i >= length) {
00387 std::ostringstream oss;
00388 oss << "RcppStringVector: subscript out of range: " << i;
00389 throw std::range_error(oss.str());
00390 }
00391 return v[i];
00392 }
00393 int size() { return length; }
00394 inline std::vector<std::string> stlVector() {
00395 std::vector<std::string> tmp(length);
00396 for (int i = 0; i < length; i++)
00397 tmp[i] = v[i];
00398 return tmp;
00399 }
00400 private:
00401 std::string *v;
00402 int length;
00403 };
00404
00405 class RcppDateVector {
00406 public:
00407 RcppDateVector(SEXP vec);
00408 ~RcppDateVector() {
00409 delete [] v;
00410 }
00411 inline RcppDate& operator()(int i) {
00412 if (i < 0 || i >= length) {
00413 std::ostringstream oss;
00414 oss << "RcppDateVector: subscript out of range: " << i;
00415 throw std::range_error(oss.str());
00416 }
00417 return v[i];
00418 }
00419 int size() { return length; }
00420 private:
00421 RcppDate *v;
00422 int length;
00423 };
00424
00425 class RcppDatetimeVector {
00426 public:
00427 RcppDatetimeVector(SEXP vec);
00428 ~RcppDatetimeVector() {
00429 delete [] v;
00430 }
00431 inline RcppDatetime &operator()(int i) {
00432 if (i < 0 || i >= length) {
00433 std::ostringstream oss;
00434 oss << "RcppDatetimeVector: subscript out of range: " << i;
00435 throw std::range_error(oss.str());
00436 }
00437 return v[i];
00438 }
00439 int size() { return length; }
00440 private:
00441 RcppDatetime *v;
00442 int length;
00443 };
00444
00445 template <typename T>
00446 class RcppMatrix {
00447 public:
00448 RcppMatrix(SEXP mat);
00449 RcppMatrix(int nx, int ny);
00450 int getDim1() { return dim1; }
00451 int getDim2() { return dim2; }
00452 inline T& operator()(int i, int j) {
00453 if (i < 0 || i >= dim1 || j < 0 || j >= dim2) {
00454 std::ostringstream oss;
00455 oss << "RcppMatrix: subscripts out of range: " << i << ", " << j;
00456 throw std::range_error(oss.str());
00457 }
00458 return a[i][j];
00459 }
00460 T **cMatrix();
00461 std::vector<std::vector<T> > stlMatrix();
00462 private:
00463 int dim1, dim2;
00464 T **a;
00465 };
00466
00467
00468
00469
00470 template <typename T>
00471 class RcppVectorView {
00472 public:
00473 RcppVectorView(SEXP vec);
00474 inline int size() const { return len; }
00475 inline T operator()(int i) const {
00476 if (i < 0 || i >= len) {
00477 std::ostringstream oss;
00478 oss << "RcppVectorView: subscript out of range: " << i;
00479 throw std::range_error(oss.str());
00480 }
00481 return v[i];
00482 }
00483 private:
00484 int len;
00485 T *v;
00486 };
00487
00488 template <typename T>
00489 class RcppMatrixView {
00490 public:
00491 RcppMatrixView(SEXP mat);
00492 inline int dim1() const { return d1; }
00493 inline int dim2() const { return d2; }
00494 inline T operator()(int i, int j) const {
00495 if (i < 0 || i >= d1 || j < 0 || j >= d2) {
00496 std::ostringstream oss;
00497 oss << "RcppMatrixView: subscripts out of range: " << i << ", " << j;
00498 throw std::range_error(oss.str());
00499 }
00500 return a[i + d1 * j];
00501 }
00502 private:
00503 int d1, d2;
00504 T *a;
00505 };
00506
00507 class RcppStringVectorView {
00508 public:
00509 RcppStringVectorView(SEXP vec);
00510 inline const char *operator()(int i) {
00511 if (i < 0 || i >= length) {
00512 std::ostringstream oss;
00513 oss << "RcppStringVector: subscript out of range: " << i;
00514 throw std::range_error(oss.str());
00515 }
00516 return CHAR(STRING_ELT(v,i));
00517 }
00518 int size() { return length; }
00519 private:
00520 SEXP v;
00521 int length;
00522 };
00523
00524
00525 class RcppFunction {
00526 public:
00527 RcppFunction(SEXP fn) : fn(fn) {
00528 if (!Rf_isFunction(fn))
00529 throw std::range_error("RcppFunction: non-function where function expected");
00530 numProtected = 0;
00531 currListPosn = 0;
00532 listSize = 0;
00533 vectorArg = listArg = R_NilValue;
00534 };
00535 ~RcppFunction() {
00536 UNPROTECT(numProtected);
00537 }
00538 SEXP listCall();
00539 SEXP vectorCall();
00540 void setRVector(std::vector<double>& v);
00541 void setRListSize(int size);
00542 void appendToRList(std::string name, double value);
00543 void appendToRList(std::string name, int value);
00544 void appendToRList(std::string name, std::string value);
00545 void appendToRList(std::string name, RcppDate& date);
00546 void appendToRList(std::string name, RcppDatetime& datetime);
00547 void clearProtectionStack() {
00548 UNPROTECT(numProtected);
00549 numProtected = 0;
00550 }
00551
00552 private:
00553 SEXP fn, listArg, vectorArg;
00554 int listSize, currListPosn, numProtected;
00555 std::vector<std::string> names;
00556 };
00557
00558 class RcppResultSet {
00559 public:
00560 RcppResultSet() { numProtected = 0; }
00561 void add(std::string, double);
00562 void add(std::string, int);
00563 void add(std::string, std::string);
00564 void add(std::string, double *, int);
00565 void add(std::string, int *, int);
00566 void add(std::string, double **, int, int);
00567 void add(std::string, int **, int, int);
00568 void add(std::string, RcppDate&);
00569 void add(std::string, RcppDateVector&);
00570 void add(std::string, RcppDatetime&);
00571 void add(std::string, RcppDatetimeVector&);
00572 void add(std::string, RcppStringVector&);
00573 void add(std::string, std::vector<double>&);
00574 void add(std::string, std::vector<int>&);
00575 void add(std::string, std::vector<std::vector<double> >&);
00576 void add(std::string, std::vector<std::vector<int> >&);
00577 void add(std::string, std::vector<std::string>&);
00578 void add(std::string, RcppVector<int>&);
00579 void add(std::string, RcppVector<double>&);
00580 void add(std::string, RcppMatrix<int>&);
00581 void add(std::string, RcppMatrix<double>&);
00582 void add(std::string, RcppFrame&);
00583 void add(std::string, SEXP, bool isProtected);
00584 SEXP getReturnList();
00585 protected:
00586 int numProtected;
00587 std::list<std::pair<std::string,SEXP> > values;
00588 };
00589
00590
00591 #endif