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