Stan  2.10.0
probability, sampling & optimization
dump.hpp
Go to the documentation of this file.
1 #ifndef STAN_IO_DUMP_HPP
2 #define STAN_IO_DUMP_HPP
3 
4 #include <boost/lexical_cast.hpp>
5 #include <boost/throw_exception.hpp>
6 #include <boost/type_traits/is_floating_point.hpp>
7 #include <boost/type_traits/is_integral.hpp>
8 #include <boost/type_traits/is_arithmetic.hpp>
9 #include <boost/utility/enable_if.hpp>
10 
12 #include <stan/io/var_context.hpp>
13 #include <stan/math/prim/scal/meta/index_type.hpp>
14 #include <stan/math/prim/arr/meta/index_type.hpp>
15 #include <stan/math/prim/mat/meta/index_type.hpp>
16 
17 #include <iostream>
18 #include <limits>
19 #include <map>
20 #include <sstream>
21 #include <stdexcept>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 #include <cctype>
26 
27 namespace stan {
28  namespace io {
29 
30  using Eigen::Dynamic;
102  class dump_reader {
103  private:
104  std::string buf_;
105  std::string name_;
106  std::vector<int> stack_i_;
107  std::vector<double> stack_r_;
108  std::vector<size_t> dims_;
109  std::istream& in_;
110 
111  bool scan_single_char(char c_expected) {
112  int c = in_.peek();
113  if (in_.fail()) return false;
114  if (c != c_expected)
115  return false;
116  char c_skip;
117  in_.get(c_skip);
118  return true;
119  }
120 
121  bool scan_optional_long() {
122  if (scan_single_char('l'))
123  return true;
124  else if (scan_single_char('L'))
125  return true;
126  else
127  return false;
128  }
129 
130  bool scan_char(char c_expected) {
131  char c;
132  in_ >> c;
133  if (in_.fail()) return false;
134  if (c != c_expected) {
135  in_.putback(c);
136  return false;
137  }
138  return true;
139  }
140 
141  bool scan_name_unquoted() {
142  char c;
143  in_ >> c;
144  if (in_.fail()) return false;
145  if (!std::isalpha(c)) return false;
146  name_.push_back(c);
147  while (in_.get(c)) { // get turns off auto space skip
148  if (std::isalpha(c) || std::isdigit(c) || c == '_' || c == '.') {
149  name_.push_back(c);
150  } else {
151  in_.putback(c);
152  return true;
153  }
154  }
155  return true; // but hit eos
156  }
157 
158  bool scan_name() {
159  if (scan_char('"')) {
160  if (!scan_name_unquoted()) return false;
161  if (!scan_char('"')) return false;
162  } else if (scan_char('\'')) {
163  if (!scan_name_unquoted()) return false;
164  if (!scan_char('\'')) return false;
165  } else {
166  if (!scan_name_unquoted()) return false;
167  }
168  return true;
169  }
170 
171 
172  bool scan_chars(const char *s, bool case_sensitive = true) {
173  for (size_t i = 0; s[i]; ++i) {
174  char c;
175  if (!(in_ >> c)) {
176  for (size_t j = 1; j < i; ++j)
177  in_.putback(s[i-j]);
178  return false;
179  }
180  // all ASCII, so toupper is OK
181  if ((case_sensitive && c != s[i])
182  || (!case_sensitive && ::toupper(c) != ::toupper(s[i]))) {
183  in_.putback(c);
184  for (size_t j = 1; j < i; ++j)
185  in_.putback(s[i-j]);
186  return false;
187  }
188  }
189  return true;
190  }
191 
192  bool scan_chars(std::string s, bool case_sensitive = true) {
193  for (size_t i = 0; i < s.size(); ++i) {
194  char c;
195  if (!(in_ >> c)) {
196  for (size_t j = 1; j < i; ++j)
197  in_.putback(s[i-j]);
198  return false;
199  }
200  // all ASCII, so toupper is OK
201  if ((case_sensitive && c != s[i])
202  || (!case_sensitive && ::toupper(c) != ::toupper(s[i]))) {
203  in_.putback(c);
204  for (size_t j = 1; j < i; ++j)
205  in_.putback(s[i-j]);
206  return false;
207  }
208  }
209  return true;
210  }
211 
212  size_t scan_dim() {
213  char c;
214  buf_.clear();
215  while (in_.get(c)) {
216  if (std::isspace(c)) continue;
217  if (std::isdigit(c)) {
218  buf_.push_back(c);
219  } else {
220  in_.putback(c);
221  break;
222  }
223  }
224  scan_optional_long();
225  size_t d = 0;
226  try {
227  d = boost::lexical_cast<size_t>(buf_);
228  }
229  catch ( const boost::bad_lexical_cast &exc ) {
230  std::string msg = "value " + buf_ + " beyond array dimension range";
231  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
232  }
233  return d;
234  }
235 
236  int scan_int() {
237  char c;
238  buf_.clear();
239  while (in_.get(c)) {
240  if (std::isspace(c)) continue;
241  if (std::isdigit(c)) {
242  buf_.push_back(c);
243  } else {
244  in_.putback(c);
245  break;
246  }
247  }
248  return(get_int());
249  }
250 
251  int get_int() {
252  int n = 0;
253  try {
254  n = boost::lexical_cast<int>(buf_);
255  }
256  catch ( const boost::bad_lexical_cast &exc ) {
257  std::string msg = "value " + buf_ + " beyond int range";
258  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
259  }
260  return n;
261  }
262 
263  double scan_double() {
264  double x = 0;
265  try {
266  x = boost::lexical_cast<double>(buf_);
267  if (x == 0)
268  validate_zero_buf(buf_);
269  }
270  catch ( const boost::bad_lexical_cast &exc ) {
271  std::string msg = "value " + buf_ + " beyond numeric range";
272  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
273  }
274  return x;
275  }
276 
277 
278 
279  // scan number stores number or throws bad lexical cast exception
280  void scan_number(bool negate_val) {
281  // must take longest first!
282  if (scan_chars("Inf")) {
283  scan_chars("inity"); // read past if there
284  stack_r_.push_back(negate_val
285  ? -std::numeric_limits<double>::infinity()
286  : std::numeric_limits<double>::infinity());
287  return;
288  }
289  if (scan_chars("NaN", false)) {
290  stack_r_.push_back(std::numeric_limits<double>::quiet_NaN());
291  return;
292  }
293 
294  char c;
295  bool is_double = false;
296  buf_.clear();
297  while (in_.get(c)) {
298  if (std::isdigit(c)) { // before pre-scan || c == '-' || c == '+') {
299  buf_.push_back(c);
300  } else if (c == '.'
301  || c == 'e'
302  || c == 'E'
303  || c == '-'
304  || c == '+') {
305  is_double = true;
306  buf_.push_back(c);
307  } else {
308  in_.putback(c);
309  break;
310  }
311  }
312  if (!is_double && stack_r_.size() == 0) {
313  int n = get_int();
314  stack_i_.push_back(negate_val ? -n : n);
315  scan_optional_long();
316  } else {
317  for (size_t j = 0; j < stack_i_.size(); ++j)
318  stack_r_.push_back(static_cast<double>(stack_i_[j]));
319  stack_i_.clear();
320  double x = scan_double();
321  stack_r_.push_back(negate_val ? -x : x);
322  }
323  }
324 
325  void scan_number() {
326  char c;
327  while (in_.get(c)) {
328  if (std::isspace(c)) continue;
329  in_.putback(c);
330  break;
331  }
332  bool negate_val = scan_char('-');
333  if (!negate_val) scan_char('+'); // flush leading +
334  return scan_number(negate_val);
335  }
336 
337 
338  bool scan_seq_value() {
339  if (!scan_char('(')) return false;
340  if (scan_char(')')) {
341  dims_.push_back(0U);
342  return true;
343  }
344  scan_number(); // first entry
345  while (scan_char(',')) {
346  scan_number();
347  }
348  dims_.push_back(stack_r_.size() + stack_i_.size());
349  return scan_char(')');
350  }
351 
352  bool scan_struct_value() {
353  if (!scan_char('(')) return false;
354  if (scan_char('c')) {
355  scan_seq_value();
356  } else {
357  int start = scan_int();
358  if (!scan_char(':'))
359  return false;
360  int end = scan_int();
361  if (start <= end) {
362  for (int i = start; i <= end; ++i)
363  stack_i_.push_back(i);
364  } else {
365  for (int i = start; i >= end; --i)
366  stack_i_.push_back(i);
367  }
368  }
369  dims_.clear();
370  if (!scan_char(',')) return false;
371  if (!scan_char('.')) return false;
372  if (!scan_chars("Dim")) return false;
373  if (!scan_char('=')) return false;
374  if (scan_char('c')) {
375  if (!scan_char('(')) return false;
376  size_t dim = scan_dim();
377  dims_.push_back(dim);
378  while (scan_char(',')) {
379  dim = scan_dim();
380  dims_.push_back(dim);
381  }
382  if (!scan_char(')')) return false;
383  } else {
384  size_t start = scan_dim();
385  if (!scan_char(':'))
386  return false;
387  size_t end = scan_dim();
388  if (start < end) {
389  for (size_t i = start; i <= end; ++i)
390  dims_.push_back(i);
391  } else {
392  for (size_t i = start; i >= end; --i)
393  dims_.push_back(i);
394  }
395  }
396  if (!scan_char(')')) return false;
397  return true;
398  }
399 
400  bool scan_value() {
401  if (scan_char('c'))
402  return scan_seq_value();
403  if (scan_chars("structure"))
404  return scan_struct_value();
405  scan_number();
406  if (!scan_char(':'))
407  return true;
408  if (stack_i_.size() != 1)
409  return false;
410  scan_number();
411  if (stack_i_.size() != 2)
412  return false;
413  int start = stack_i_[0];
414  int end = stack_i_[1];
415  stack_i_.clear();
416  if (start <= end) {
417  for (int i = start; i <= end; ++i)
418  stack_i_.push_back(i);
419  } else {
420  for (int i = start; i >= end; --i)
421  stack_i_.push_back(i);
422  }
423  dims_.push_back(stack_i_.size());
424  return true;
425  }
426 
427 
428  public:
434  explicit dump_reader(std::istream& in) : in_(in) { }
435 
440 
441 
447  std::string name() {
448  return name_;
449  }
450 
457  std::vector<size_t> dims() {
458  return dims_;
459  }
460 
468  bool is_int() {
469  // return stack_i_.size() > 0;
470  return stack_r_.size() == 0;
471  }
472 
479  std::vector<int> int_values() {
480  return stack_i_;
481  }
482 
490  std::vector<double> double_values() {
491  return stack_r_;
492  }
493 
502  bool next() {
503  stack_r_.clear();
504  stack_i_.clear();
505  dims_.clear();
506  name_.erase();
507  if (!scan_name()) // set name
508  return false;
509  if (!scan_char('<')) // set <-
510  return false;
511  if (!scan_char('-'))
512  return false;
513  try {
514  bool okSyntax = scan_value(); // set stack_r_, stack_i_, dims_
515  if (!okSyntax) {
516  std::string msg = "syntax error";
517  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
518  }
519  }
520  catch (const std::invalid_argument &e) {
521  std::string msg = "data " + name_ + " " + e.what();
522  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
523  }
524  return true;
525  }
526  };
527 
528 
529 
545  class dump : public stan::io::var_context {
546  private:
547  std::map<std::string,
548  std::pair<std::vector<double>,
549  std::vector<size_t> > > vars_r_;
550  std::map<std::string,
551  std::pair<std::vector<int>,
552  std::vector<size_t> > > vars_i_;
553  std::vector<double> const empty_vec_r_;
554  std::vector<int> const empty_vec_i_;
555  std::vector<size_t> const empty_vec_ui_;
565  bool contains_r_only(const std::string& name) const {
566  return vars_r_.find(name) != vars_r_.end();
567  }
568 
569  public:
577  explicit dump(std::istream& in) {
578  dump_reader reader(in);
579  while (reader.next()) {
580  if (reader.is_int()) {
581  vars_i_[reader.name()]
582  = std::pair<std::vector<int>,
583  std::vector<size_t> >(reader.int_values(),
584  reader.dims());
585 
586  } else {
587  vars_r_[reader.name()]
588  = std::pair<std::vector<double>,
589  std::vector<size_t> >(reader.double_values(),
590  reader.dims());
591  }
592  }
593  }
594 
603  bool contains_r(const std::string& name) const {
604  return contains_r_only(name) || contains_i(name);
605  }
606 
615  bool contains_i(const std::string& name) const {
616  return vars_i_.find(name) != vars_i_.end();
617  }
618 
626  std::vector<double> vals_r(const std::string& name) const {
627  if (contains_r_only(name)) {
628  return (vars_r_.find(name)->second).first;
629  } else if (contains_i(name)) {
630  std::vector<int> vec_int = (vars_i_.find(name)->second).first;
631  std::vector<double> vec_r(vec_int.size());
632  for (size_t ii = 0; ii < vec_int.size(); ii++) {
633  vec_r[ii] = vec_int[ii];
634  }
635  return vec_r;
636  }
637  return empty_vec_r_;
638  }
639 
647  std::vector<size_t> dims_r(const std::string& name) const {
648  if (contains_r_only(name)) {
649  return (vars_r_.find(name)->second).second;
650  } else if (contains_i(name)) {
651  return (vars_i_.find(name)->second).second;
652  }
653  return empty_vec_ui_;
654  }
655 
663  std::vector<int> vals_i(const std::string& name) const {
664  if (contains_i(name)) {
665  return (vars_i_.find(name)->second).first;
666  }
667  return empty_vec_i_;
668  }
669 
677  std::vector<size_t> dims_i(const std::string& name) const {
678  if (contains_i(name)) {
679  return (vars_i_.find(name)->second).second;
680  }
681  return empty_vec_ui_;
682  }
683 
690  virtual void names_r(std::vector<std::string>& names) const {
691  names.resize(0);
692  for (std::map<std::string,
693  std::pair<std::vector<double>,
694  std::vector<size_t> > >
695  ::const_iterator it = vars_r_.begin();
696  it != vars_r_.end(); ++it)
697  names.push_back((*it).first);
698  }
699 
706  virtual void names_i(std::vector<std::string>& names) const {
707  names.resize(0);
708  for (std::map<std::string,
709  std::pair<std::vector<int>,
710  std::vector<size_t> > >
711  ::const_iterator it = vars_i_.begin();
712  it != vars_i_.end(); ++it)
713  names.push_back((*it).first);
714  }
715 
723  bool remove(const std::string& name) {
724  return (vars_i_.erase(name) > 0)
725  || (vars_r_.erase(name) > 0);
726  }
727  };
728 
729  }
730 
731 }
732 #endif
dump(std::istream &in)
Construct a dump object from the specified input stream.
Definition: dump.hpp:577
~dump_reader()
Destroy this reader.
Definition: dump.hpp:439
bool is_int()
Checks if the last item read is integer.
Definition: dump.hpp:468
Probability, optimization and sampling library.
virtual void names_r(std::vector< std::string > &names) const
Return a list of the names of the floating point variables in the dump.
Definition: dump.hpp:690
bool contains_r(const std::string &name) const
Return true if this dump contains the specified variable name is defined.
Definition: dump.hpp:603
std::vector< double > double_values()
Returns the floating point values from the last item if the last item read contained floating point v...
Definition: dump.hpp:490
virtual void names_i(std::vector< std::string > &names) const
Return a list of the names of the integer variables in the dump.
Definition: dump.hpp:706
A stream-based reader for integer, scalar, vector, matrix and array data types, with Jacobian calcula...
Definition: reader.hpp:58
bool contains_i(const std::string &name) const
Return true if this dump contains an integer valued array with the specified name.
Definition: dump.hpp:615
A var_reader reads array variables of integer and floating point type by name and dimension...
Definition: var_context.hpp:29
std::vector< size_t > dims_r(const std::string &name) const
Return the dimensions for the double variable with the specified name.
Definition: dump.hpp:647
void validate_zero_buf(const B &buf)
Throw an bad-cast exception if the specified buffer contains a digit other than 0 before an e or E...
std::vector< int > int_values()
Returns the integer values from the last item if the last item read was an integer and the empty vect...
Definition: dump.hpp:479
std::vector< double > vals_r(const std::string &name) const
Return the double values for the variable with the specified name or null.
Definition: dump.hpp:626
std::string name()
Return the name of the most recently read variable.
Definition: dump.hpp:447
std::vector< size_t > dims()
Return the dimensions of the most recently read variable.
Definition: dump.hpp:457
std::vector< int > vals_i(const std::string &name) const
Return the integer values for the variable with the specified name.
Definition: dump.hpp:663
Reads data from S-plus dump format.
Definition: dump.hpp:102
Represents named arrays with dimensions.
Definition: dump.hpp:545
bool next()
Read the next value from the input stream, returning true if successful and false if no further input...
Definition: dump.hpp:502
dump_reader(std::istream &in)
Construct a reader for the specified input stream.
Definition: dump.hpp:434
std::vector< size_t > dims_i(const std::string &name) const
Return the dimensions for the integer variable with the specified name.
Definition: dump.hpp:677

     [ Stan Home Page ] © 2011–2016, Stan Development Team.