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 double getDoubleValue(std::string name);
00155 int getIntValue(std::string name);
00156 std::string getStringValue(std::string name);
00157 bool getBoolValue(std::string name);
00158 RcppDate getDateValue(std::string name);
00159 RcppDatetime getDatetimeValue(std::string name);
00160 private:
00161 std::map<std::string, int> pmap;
00162 SEXP _params;
00163 };
00164
00165
00166 enum ColType { COLTYPE_DOUBLE, COLTYPE_INT, COLTYPE_STRING,
00167 COLTYPE_FACTOR, COLTYPE_LOGICAL,
00168 COLTYPE_DATE, COLTYPE_DATETIME };
00169
00170 class ColDatum {
00171 public:
00172 ColDatum() {
00173 level = 0;
00174 }
00175 ~ColDatum() {
00176 if (type == COLTYPE_FACTOR) {
00177
00178
00179
00180
00181
00182 delete [] levelNames;
00183 }
00184 }
00185 ColDatum(const ColDatum& datum) {
00186
00187
00188 s = datum.s;
00189 x = datum.x;
00190 i = datum.i;
00191 type = datum.type;
00192 level = datum.level;
00193 numLevels = datum.numLevels;
00194 d = datum.d;
00195 if (type == COLTYPE_FACTOR) {
00196 levelNames = new std::string[numLevels];
00197 for (int i = 0; i < numLevels; i++)
00198 levelNames[i] = datum.levelNames[i];
00199 }
00200 }
00201
00202 ColType getType() const { return type; }
00203
00204 void setDoubleValue(double val) { x = val; type = COLTYPE_DOUBLE; }
00205 void setIntValue(int val) { i = val; type = COLTYPE_INT; }
00206 void setLogicalValue(int val) {
00207 if (val != 0 && val != 1)
00208 throw std::range_error("ColDatum::setLogicalValue: logical values must be 0/1.");
00209 i = val; type = COLTYPE_LOGICAL;
00210 }
00211 void setStringValue(std::string val) { s = val; type = COLTYPE_STRING; }
00212 void setDateValue(RcppDate date) {
00213 d = date;
00214 type = COLTYPE_DATE;
00215 }
00216 void setDatetimeValue(RcppDatetime datetime) {
00217 x = datetime.m_d;
00218 type = COLTYPE_DATETIME;
00219 }
00220 void setFactorValue(std::string *names, int numNames, int factorLevel) {
00221 if (factorLevel < 1 || factorLevel > numNames)
00222 throw std::range_error("ColDatum::setFactorValue: factor level out of range");
00223 level = factorLevel;
00224 numLevels = numNames;
00225 levelNames = new std::string[numLevels];
00226 for (int i = 0; i < numLevels; i++)
00227 levelNames[i] = names[i];
00228 type = COLTYPE_FACTOR;
00229 }
00230
00231 double getDoubleValue() {
00232 if (type != COLTYPE_DOUBLE)
00233 throw std::range_error("ColDatum::getDoubleValue: wrong data type in getDoubleValue");
00234 return x;
00235 }
00236 int getIntValue() {
00237 if (type != COLTYPE_INT)
00238 throw std::range_error("ColDatum::getIntValue: wrong data type in getIntValue");
00239 return i;
00240 }
00241 int getLogicalValue() {
00242 if (type != COLTYPE_LOGICAL)
00243 throw std::range_error("ColDatum::getLogicalValue: wrong data type in getLogicalValue");
00244 return i;
00245 }
00246 std::string getStringValue() {
00247 if (type != COLTYPE_STRING)
00248 throw std::range_error("ColDatum::getStringValue: wrong data type in getStringValue");
00249 return s;
00250 }
00251 RcppDate getDateValue() {
00252 if (type != COLTYPE_DATE)
00253 throw std::range_error("ColDatum::getDateValue: wrong data type in getDateValue");
00254 return d;
00255 }
00256 double getDateRCode() {
00257 return (double)(d.getJDN() - RcppDate::Jan1970Offset);
00258 }
00259 RcppDatetime getDatetimeValue() {
00260 if (type != COLTYPE_DATETIME)
00261 throw std::range_error("ColDatum::getDatetimeValue: wrong data type in getDatetimeValue");
00262 return RcppDatetime(x);
00263 }
00264
00265 void checkFactorType() {
00266 if (type != COLTYPE_FACTOR)
00267 throw std::range_error("ColDatun::checkFactorType: wrong data type in getFactor...");
00268 }
00269 int getFactorNumLevels() { checkFactorType(); return numLevels; }
00270 int getFactorLevel() { checkFactorType(); return level; }
00271 std::string *getFactorLevelNames() { checkFactorType(); return levelNames; }
00272 std::string getFactorLevelName() { checkFactorType(); return levelNames[level-1];}
00273
00274 private:
00275 ColType type;
00276 std::string s;
00277 double x;
00278 int i;
00279 int level;
00280 int numLevels;
00281 std::string *levelNames;
00282 RcppDate d;
00283 };
00284
00285 class RcppFrame {
00286 std::vector<std::string> colNames;
00287 std::vector<std::vector<ColDatum> > table;
00288 public:
00289 RcppFrame(SEXP df);
00290 RcppFrame(std::vector<std::string> colNames) : colNames(colNames) {
00291 if (colNames.size() == 0)
00292 throw std::range_error("RcppFrame::RcppFrame: zero length colNames");
00293 }
00294 std::vector<std::string>& getColNames() { return colNames; }
00295 std::vector<std::vector<ColDatum> >& getTableData() { return table; }
00296 void addRow(std::vector<ColDatum> rowData) {
00297 if (rowData.size() != colNames.size())
00298 throw std::range_error("RcppFrame::addRow: incorrect row length.");
00299 if (table.size() > 0) {
00300
00301
00302
00303 for (int i = 0; i < (int)colNames.size(); i++) {
00304 if (rowData[i].getType() != table[0][i].getType()) {
00305 std::ostringstream oss;
00306 oss << "RcppFrame::addRow: incorrect data type at posn "
00307 << i;
00308 throw std::range_error(oss.str());
00309 }
00310 }
00311 }
00312 table.push_back(rowData);
00313 }
00314 int rows() { return table.size(); }
00315 int cols() { return table[0].size(); }
00316 };
00317
00318 class RcppNumList {
00319 public:
00320 RcppNumList(SEXP theList) {
00321 if (!Rf_isNewList(theList))
00322 throw std::range_error("RcppNumList: non-list passed to constructor");
00323 len = Rf_length(theList);
00324 names = Rf_getAttrib(theList, R_NamesSymbol);
00325 namedList = theList;
00326 }
00327 std::string getName(int i) {
00328 if (i < 0 || i >= len) {
00329 std::ostringstream oss;
00330 oss << "RcppNumList::getName: index out of bounds: " << i;
00331 throw std::range_error(oss.str());
00332 }
00333 return std::string(CHAR(STRING_ELT(names,i)));
00334 }
00335 double getValue(int i) {
00336 if (i < 0 || i >= len) {
00337 std::ostringstream oss;
00338 oss << "RcppNumList::getValue: index out of bounds: " << i;
00339 throw std::range_error(oss.str());
00340 }
00341 SEXP elt = VECTOR_ELT(namedList, i);
00342 if (Rf_isReal(elt))
00343 return REAL(elt)[0];
00344 else if (Rf_isInteger(elt))
00345 return (double)INTEGER(elt)[0];
00346 else
00347 throw std::range_error("RcppNumList: contains non-numeric value");
00348 return 0;
00349 }
00350 int size() { return len; }
00351 private:
00352 int len;
00353 SEXP namedList;
00354 SEXP names;
00355 };
00356
00357 template <typename T>
00358 class RcppVector {
00359 public:
00360 RcppVector(SEXP vec);
00361 RcppVector(int len);
00362 int size() { return len; }
00363 inline T& operator()(int i) {
00364 if (i < 0 || i >= len) {
00365 std::ostringstream oss;
00366 oss << "RcppVector: subscript out of range: " << i;
00367 throw std::range_error(oss.str());
00368 }
00369 return v[i];
00370 }
00371 T *cVector();
00372 std::vector<T> stlVector();
00373 private:
00374 int len;
00375 T *v;
00376 };
00377
00378 class RcppStringVector {
00379 public:
00380 RcppStringVector(SEXP vec);
00381 ~RcppStringVector() {
00382 delete [] v;
00383 }
00384 inline std::string& operator()(int i) {
00385 if (i < 0 || i >= length) {
00386 std::ostringstream oss;
00387 oss << "RcppStringVector: subscript out of range: " << i;
00388 throw std::range_error(oss.str());
00389 }
00390 return v[i];
00391 }
00392 int size() { return length; }
00393 inline std::vector<std::string> stlVector() {
00394 std::vector<std::string> tmp(length);
00395 for (int i = 0; i < length; i++)
00396 tmp[i] = v[i];
00397 return tmp;
00398 }
00399 private:
00400 std::string *v;
00401 int length;
00402 };
00403
00404 class RcppDateVector {
00405 public:
00406 RcppDateVector(SEXP vec);
00407 ~RcppDateVector() {
00408 delete [] v;
00409 }
00410 inline RcppDate& operator()(int i) {
00411 if (i < 0 || i >= length) {
00412 std::ostringstream oss;
00413 oss << "RcppDateVector: subscript out of range: " << i;
00414 throw std::range_error(oss.str());
00415 }
00416 return v[i];
00417 }
00418 int size() { return length; }
00419 private:
00420 RcppDate *v;
00421 int length;
00422 };
00423
00424 class RcppDatetimeVector {
00425 public:
00426 RcppDatetimeVector(SEXP vec);
00427 ~RcppDatetimeVector() {
00428 delete [] v;
00429 }
00430 inline RcppDatetime &operator()(int i) {
00431 if (i < 0 || i >= length) {
00432 std::ostringstream oss;
00433 oss << "RcppDatetimeVector: subscript out of range: " << i;
00434 throw std::range_error(oss.str());
00435 }
00436 return v[i];
00437 }
00438 int size() { return length; }
00439 private:
00440 RcppDatetime *v;
00441 int length;
00442 };
00443
00444 template <typename T>
00445 class RcppMatrix {
00446 public:
00447 RcppMatrix(SEXP mat);
00448 RcppMatrix(int nx, int ny);
00449 int getDim1() { return dim1; }
00450 int getDim2() { return dim2; }
00451 inline T& operator()(int i, int j) {
00452 if (i < 0 || i >= dim1 || j < 0 || j >= dim2) {
00453 std::ostringstream oss;
00454 oss << "RcppMatrix: subscripts out of range: " << i << ", " << j;
00455 throw std::range_error(oss.str());
00456 }
00457 return a[i][j];
00458 }
00459 T **cMatrix();
00460 std::vector<std::vector<T> > stlMatrix();
00461 private:
00462 int dim1, dim2;
00463 T **a;
00464 };
00465
00466
00467
00468
00469 template <typename T>
00470 class RcppVectorView {
00471 public:
00472 RcppVectorView(SEXP vec);
00473 inline int size() const { return len; }
00474 inline T operator()(int i) const {
00475 if (i < 0 || i >= len) {
00476 std::ostringstream oss;
00477 oss << "RcppVectorView: subscript out of range: " << i;
00478 throw std::range_error(oss.str());
00479 }
00480 return v[i];
00481 }
00482 private:
00483 int len;
00484 T *v;
00485 };
00486
00487 template <typename T>
00488 class RcppMatrixView {
00489 public:
00490 RcppMatrixView(SEXP mat);
00491 inline int dim1() const { return d1; }
00492 inline int dim2() const { return d2; }
00493 inline T operator()(int i, int j) const {
00494 if (i < 0 || i >= d1 || j < 0 || j >= d2) {
00495 std::ostringstream oss;
00496 oss << "RcppMatrixView: subscripts out of range: " << i << ", " << j;
00497 throw std::range_error(oss.str());
00498 }
00499 return a[i + d1 * j];
00500 }
00501 private:
00502 int d1, d2;
00503 T *a;
00504 };
00505
00506 class RcppStringVectorView {
00507 public:
00508 RcppStringVectorView(SEXP vec);
00509 inline const char *operator()(int i) {
00510 if (i < 0 || i >= length) {
00511 std::ostringstream oss;
00512 oss << "RcppStringVector: subscript out of range: " << i;
00513 throw std::range_error(oss.str());
00514 }
00515 return CHAR(STRING_ELT(v,i));
00516 }
00517 int size() { return length; }
00518 private:
00519 SEXP v;
00520 int length;
00521 };
00522
00523
00524 class RcppFunction {
00525 public:
00526 RcppFunction(SEXP fn) : fn(fn) {
00527 if (!Rf_isFunction(fn))
00528 throw std::range_error("RcppFunction: non-function where function expected");
00529 numProtected = 0;
00530 currListPosn = 0;
00531 listSize = 0;
00532 vectorArg = listArg = R_NilValue;
00533 };
00534 ~RcppFunction() {
00535 UNPROTECT(numProtected);
00536 }
00537 SEXP listCall();
00538 SEXP vectorCall();
00539 void setRVector(std::vector<double>& v);
00540 void setRListSize(int size);
00541 void appendToRList(std::string name, double value);
00542 void appendToRList(std::string name, int value);
00543 void appendToRList(std::string name, std::string value);
00544 void appendToRList(std::string name, RcppDate& date);
00545 void appendToRList(std::string name, RcppDatetime& datetime);
00546 void clearProtectionStack() {
00547 UNPROTECT(numProtected);
00548 numProtected = 0;
00549 }
00550
00551 private:
00552 SEXP fn, listArg, vectorArg;
00553 int listSize, currListPosn, numProtected;
00554 std::vector<std::string> names;
00555 };
00556
00557 class RcppResultSet {
00558 public:
00559 RcppResultSet() { numProtected = 0; }
00560 void add(std::string, double);
00561 void add(std::string, int);
00562 void add(std::string, std::string);
00563 void add(std::string, double *, int);
00564 void add(std::string, int *, int);
00565 void add(std::string, double **, int, int);
00566 void add(std::string, int **, int, int);
00567 void add(std::string, RcppDate&);
00568 void add(std::string, RcppDateVector&);
00569 void add(std::string, RcppDatetime&);
00570 void add(std::string, RcppDatetimeVector&);
00571 void add(std::string, RcppStringVector&);
00572 void add(std::string, std::vector<double>&);
00573 void add(std::string, std::vector<int>&);
00574 void add(std::string, std::vector<std::vector<double> >&);
00575 void add(std::string, std::vector<std::vector<int> >&);
00576 void add(std::string, std::vector<std::string>&);
00577 void add(std::string, RcppVector<int>&);
00578 void add(std::string, RcppVector<double>&);
00579 void add(std::string, RcppMatrix<int>&);
00580 void add(std::string, RcppMatrix<double>&);
00581 void add(std::string, RcppFrame&);
00582 void add(std::string, SEXP, bool isProtected);
00583 SEXP getReturnList();
00584 protected:
00585 int numProtected;
00586 std::list<std::pair<std::string,SEXP> > values;
00587 };
00588
00589
00590 #endif