Stan  2.13.1
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 
6 #include <stan/math/prim/mat.hpp>
7 #include <boost/lexical_cast.hpp>
8 #include <boost/throw_exception.hpp>
9 #include <boost/type_traits/is_floating_point.hpp>
10 #include <boost/type_traits/is_integral.hpp>
11 #include <boost/type_traits/is_arithmetic.hpp>
12 #include <boost/utility/enable_if.hpp>
13 #include <iostream>
14 #include <limits>
15 #include <map>
16 #include <sstream>
17 #include <stdexcept>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 #include <cctype>
22 
23 namespace stan {
24  namespace io {
25 
26  using Eigen::Dynamic;
98  class dump_reader {
99  private:
100  std::string buf_;
101  std::string name_;
102  std::vector<int> stack_i_;
103  std::vector<double> stack_r_;
104  std::vector<size_t> dims_;
105  std::istream& in_;
106 
107  bool scan_single_char(char c_expected) {
108  int c = in_.peek();
109  if (in_.fail()) return false;
110  if (c != c_expected)
111  return false;
112  char c_skip;
113  in_.get(c_skip);
114  return true;
115  }
116 
117  bool scan_optional_long() {
118  if (scan_single_char('l'))
119  return true;
120  else if (scan_single_char('L'))
121  return true;
122  else
123  return false;
124  }
125 
126  bool scan_char(char c_expected) {
127  char c;
128  in_ >> c;
129  if (in_.fail()) return false;
130  if (c != c_expected) {
131  in_.putback(c);
132  return false;
133  }
134  return true;
135  }
136 
137  bool scan_name_unquoted() {
138  char c;
139  in_ >> c;
140  if (in_.fail()) return false;
141  if (!std::isalpha(c)) return false;
142  name_.push_back(c);
143  while (in_.get(c)) { // get turns off auto space skip
144  if (std::isalpha(c) || std::isdigit(c) || c == '_' || c == '.') {
145  name_.push_back(c);
146  } else {
147  in_.putback(c);
148  return true;
149  }
150  }
151  return true; // but hit eos
152  }
153 
154  bool scan_name() {
155  if (scan_char('"')) {
156  if (!scan_name_unquoted()) return false;
157  if (!scan_char('"')) return false;
158  } else if (scan_char('\'')) {
159  if (!scan_name_unquoted()) return false;
160  if (!scan_char('\'')) return false;
161  } else {
162  if (!scan_name_unquoted()) return false;
163  }
164  return true;
165  }
166 
167 
168  bool scan_chars(const char *s, bool case_sensitive = true) {
169  for (size_t i = 0; s[i]; ++i) {
170  char c;
171  if (!(in_ >> c)) {
172  for (size_t j = 1; j < i; ++j)
173  in_.putback(s[i-j]);
174  return false;
175  }
176  // all ASCII, so toupper is OK
177  if ((case_sensitive && c != s[i])
178  || (!case_sensitive && ::toupper(c) != ::toupper(s[i]))) {
179  in_.putback(c);
180  for (size_t j = 1; j < i; ++j)
181  in_.putback(s[i-j]);
182  return false;
183  }
184  }
185  return true;
186  }
187 
188  bool scan_chars(std::string s, bool case_sensitive = true) {
189  for (size_t i = 0; i < s.size(); ++i) {
190  char c;
191  if (!(in_ >> c)) {
192  for (size_t j = 1; j < i; ++j)
193  in_.putback(s[i-j]);
194  return false;
195  }
196  // all ASCII, so toupper is OK
197  if ((case_sensitive && c != s[i])
198  || (!case_sensitive && ::toupper(c) != ::toupper(s[i]))) {
199  in_.putback(c);
200  for (size_t j = 1; j < i; ++j)
201  in_.putback(s[i-j]);
202  return false;
203  }
204  }
205  return true;
206  }
207 
208  size_t scan_dim() {
209  char c;
210  buf_.clear();
211  while (in_.get(c)) {
212  if (std::isspace(c)) continue;
213  if (std::isdigit(c)) {
214  buf_.push_back(c);
215  } else {
216  in_.putback(c);
217  break;
218  }
219  }
220  scan_optional_long();
221  size_t d = 0;
222  try {
223  d = boost::lexical_cast<size_t>(buf_);
224  }
225  catch ( const boost::bad_lexical_cast &exc ) {
226  std::string msg = "value " + buf_ + " beyond array dimension range";
227  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
228  }
229  return d;
230  }
231 
232  int scan_int() {
233  char c;
234  buf_.clear();
235  while (in_.get(c)) {
236  if (std::isspace(c)) continue;
237  if (std::isdigit(c)) {
238  buf_.push_back(c);
239  } else {
240  in_.putback(c);
241  break;
242  }
243  }
244  return(get_int());
245  }
246 
247  int get_int() {
248  int n = 0;
249  try {
250  n = boost::lexical_cast<int>(buf_);
251  }
252  catch ( const boost::bad_lexical_cast &exc ) {
253  std::string msg = "value " + buf_ + " beyond int range";
254  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
255  }
256  return n;
257  }
258 
259  double scan_double() {
260  double x = 0;
261  try {
262  x = boost::lexical_cast<double>(buf_);
263  if (x == 0)
264  validate_zero_buf(buf_);
265  }
266  catch ( const boost::bad_lexical_cast &exc ) {
267  std::string msg = "value " + buf_ + " beyond numeric range";
268  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
269  }
270  return x;
271  }
272 
273 
274 
275  // scan number stores number or throws bad lexical cast exception
276  void scan_number(bool negate_val) {
277  // must take longest first!
278  if (scan_chars("Inf")) {
279  scan_chars("inity"); // read past if there
280  stack_r_.push_back(negate_val
281  ? -std::numeric_limits<double>::infinity()
282  : std::numeric_limits<double>::infinity());
283  return;
284  }
285  if (scan_chars("NaN", false)) {
286  stack_r_.push_back(std::numeric_limits<double>::quiet_NaN());
287  return;
288  }
289 
290  char c;
291  bool is_double = false;
292  buf_.clear();
293  while (in_.get(c)) {
294  if (std::isdigit(c)) { // before pre-scan || c == '-' || c == '+') {
295  buf_.push_back(c);
296  } else if (c == '.'
297  || c == 'e'
298  || c == 'E'
299  || c == '-'
300  || c == '+') {
301  is_double = true;
302  buf_.push_back(c);
303  } else {
304  in_.putback(c);
305  break;
306  }
307  }
308  if (!is_double && stack_r_.size() == 0) {
309  int n = get_int();
310  stack_i_.push_back(negate_val ? -n : n);
311  scan_optional_long();
312  } else {
313  for (size_t j = 0; j < stack_i_.size(); ++j)
314  stack_r_.push_back(static_cast<double>(stack_i_[j]));
315  stack_i_.clear();
316  double x = scan_double();
317  stack_r_.push_back(negate_val ? -x : x);
318  }
319  }
320 
321  void scan_number() {
322  char c;
323  while (in_.get(c)) {
324  if (std::isspace(c)) continue;
325  in_.putback(c);
326  break;
327  }
328  bool negate_val = scan_char('-');
329  if (!negate_val) scan_char('+'); // flush leading +
330  return scan_number(negate_val);
331  }
332 
333 
334  bool scan_seq_value() {
335  if (!scan_char('(')) return false;
336  if (scan_char(')')) {
337  dims_.push_back(0U);
338  return true;
339  }
340  scan_number(); // first entry
341  while (scan_char(',')) {
342  scan_number();
343  }
344  dims_.push_back(stack_r_.size() + stack_i_.size());
345  return scan_char(')');
346  }
347 
348  bool scan_struct_value() {
349  if (!scan_char('(')) return false;
350  if (scan_char('c')) {
351  scan_seq_value();
352  } else {
353  int start = scan_int();
354  if (!scan_char(':'))
355  return false;
356  int end = scan_int();
357  if (start <= end) {
358  for (int i = start; i <= end; ++i)
359  stack_i_.push_back(i);
360  } else {
361  for (int i = start; i >= end; --i)
362  stack_i_.push_back(i);
363  }
364  }
365  dims_.clear();
366  if (!scan_char(',')) return false;
367  if (!scan_char('.')) return false;
368  if (!scan_chars("Dim")) return false;
369  if (!scan_char('=')) return false;
370  if (scan_char('c')) {
371  if (!scan_char('(')) return false;
372  size_t dim = scan_dim();
373  dims_.push_back(dim);
374  while (scan_char(',')) {
375  dim = scan_dim();
376  dims_.push_back(dim);
377  }
378  if (!scan_char(')')) return false;
379  } else {
380  size_t start = scan_dim();
381  if (!scan_char(':'))
382  return false;
383  size_t end = scan_dim();
384  if (start < end) {
385  for (size_t i = start; i <= end; ++i)
386  dims_.push_back(i);
387  } else {
388  for (size_t i = start; i >= end; --i)
389  dims_.push_back(i);
390  }
391  }
392  if (!scan_char(')')) return false;
393  return true;
394  }
395 
396  bool scan_value() {
397  if (scan_char('c'))
398  return scan_seq_value();
399  if (scan_chars("structure"))
400  return scan_struct_value();
401  scan_number();
402  if (!scan_char(':'))
403  return true;
404  if (stack_i_.size() != 1)
405  return false;
406  scan_number();
407  if (stack_i_.size() != 2)
408  return false;
409  int start = stack_i_[0];
410  int end = stack_i_[1];
411  stack_i_.clear();
412  if (start <= end) {
413  for (int i = start; i <= end; ++i)
414  stack_i_.push_back(i);
415  } else {
416  for (int i = start; i >= end; --i)
417  stack_i_.push_back(i);
418  }
419  dims_.push_back(stack_i_.size());
420  return true;
421  }
422 
423 
424  public:
430  explicit dump_reader(std::istream& in) : in_(in) { }
431 
436 
437 
443  std::string name() {
444  return name_;
445  }
446 
453  std::vector<size_t> dims() {
454  return dims_;
455  }
456 
464  bool is_int() {
465  // return stack_i_.size() > 0;
466  return stack_r_.size() == 0;
467  }
468 
475  std::vector<int> int_values() {
476  return stack_i_;
477  }
478 
486  std::vector<double> double_values() {
487  return stack_r_;
488  }
489 
498  bool next() {
499  stack_r_.clear();
500  stack_i_.clear();
501  dims_.clear();
502  name_.erase();
503  if (!scan_name()) // set name
504  return false;
505  if (!scan_char('<')) // set <-
506  return false;
507  if (!scan_char('-'))
508  return false;
509  try {
510  bool okSyntax = scan_value(); // set stack_r_, stack_i_, dims_
511  if (!okSyntax) {
512  std::string msg = "syntax error";
513  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
514  }
515  }
516  catch (const std::invalid_argument &e) {
517  std::string msg = "data " + name_ + " " + e.what();
518  BOOST_THROW_EXCEPTION(std::invalid_argument(msg));
519  }
520  return true;
521  }
522  };
523 
524 
525 
541  class dump : public stan::io::var_context {
542  private:
543  std::map<std::string,
544  std::pair<std::vector<double>,
545  std::vector<size_t> > > vars_r_;
546  std::map<std::string,
547  std::pair<std::vector<int>,
548  std::vector<size_t> > > vars_i_;
549  std::vector<double> const empty_vec_r_;
550  std::vector<int> const empty_vec_i_;
551  std::vector<size_t> const empty_vec_ui_;
561  bool contains_r_only(const std::string& name) const {
562  return vars_r_.find(name) != vars_r_.end();
563  }
564 
565  public:
573  explicit dump(std::istream& in) {
574  dump_reader reader(in);
575  while (reader.next()) {
576  if (reader.is_int()) {
577  vars_i_[reader.name()]
578  = std::pair<std::vector<int>,
579  std::vector<size_t> >(reader.int_values(),
580  reader.dims());
581 
582  } else {
583  vars_r_[reader.name()]
584  = std::pair<std::vector<double>,
585  std::vector<size_t> >(reader.double_values(),
586  reader.dims());
587  }
588  }
589  }
590 
599  bool contains_r(const std::string& name) const {
600  return contains_r_only(name) || contains_i(name);
601  }
602 
611  bool contains_i(const std::string& name) const {
612  return vars_i_.find(name) != vars_i_.end();
613  }
614 
622  std::vector<double> vals_r(const std::string& name) const {
623  if (contains_r_only(name)) {
624  return (vars_r_.find(name)->second).first;
625  } else if (contains_i(name)) {
626  std::vector<int> vec_int = (vars_i_.find(name)->second).first;
627  std::vector<double> vec_r(vec_int.size());
628  for (size_t ii = 0; ii < vec_int.size(); ii++) {
629  vec_r[ii] = vec_int[ii];
630  }
631  return vec_r;
632  }
633  return empty_vec_r_;
634  }
635 
643  std::vector<size_t> dims_r(const std::string& name) const {
644  if (contains_r_only(name)) {
645  return (vars_r_.find(name)->second).second;
646  } else if (contains_i(name)) {
647  return (vars_i_.find(name)->second).second;
648  }
649  return empty_vec_ui_;
650  }
651 
659  std::vector<int> vals_i(const std::string& name) const {
660  if (contains_i(name)) {
661  return (vars_i_.find(name)->second).first;
662  }
663  return empty_vec_i_;
664  }
665 
673  std::vector<size_t> dims_i(const std::string& name) const {
674  if (contains_i(name)) {
675  return (vars_i_.find(name)->second).second;
676  }
677  return empty_vec_ui_;
678  }
679 
686  virtual void names_r(std::vector<std::string>& names) const {
687  names.resize(0);
688  for (std::map<std::string,
689  std::pair<std::vector<double>,
690  std::vector<size_t> > >
691  ::const_iterator it = vars_r_.begin();
692  it != vars_r_.end(); ++it)
693  names.push_back((*it).first);
694  }
695 
702  virtual void names_i(std::vector<std::string>& names) const {
703  names.resize(0);
704  for (std::map<std::string,
705  std::pair<std::vector<int>,
706  std::vector<size_t> > >
707  ::const_iterator it = vars_i_.begin();
708  it != vars_i_.end(); ++it)
709  names.push_back((*it).first);
710  }
711 
719  bool remove(const std::string& name) {
720  return (vars_i_.erase(name) > 0)
721  || (vars_r_.erase(name) > 0);
722  }
723  };
724 
725  }
726 
727 }
728 #endif
dump(std::istream &in)
Construct a dump object from the specified input stream.
Definition: dump.hpp:573
bool contains_r(const std::string &name) const
Return true if this dump contains the specified variable name is defined.
Definition: dump.hpp:599
~dump_reader()
Destroy this reader.
Definition: dump.hpp:435
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:673
bool is_int()
Checks if the last item read is integer.
Definition: dump.hpp:464
Probability, optimization and sampling library.
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:486
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:686
A stream-based reader for integer, scalar, vector, matrix and array data types, with Jacobian calcula...
Definition: reader.hpp:35
A var_reader reads array variables of integer and floating point type by name and dimension...
Definition: var_context.hpp:29
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< size_t > dims_r(const std::string &name) const
Return the dimensions for the double variable with the specified name.
Definition: dump.hpp:643
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:475
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:702
std::vector< int > vals_i(const std::string &name) const
Return the integer values for the variable with the specified name.
Definition: dump.hpp:659
std::string name()
Return the name of the most recently read variable.
Definition: dump.hpp:443
std::vector< size_t > dims()
Return the dimensions of the most recently read variable.
Definition: dump.hpp:453
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:611
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:622
Reads data from S-plus dump format.
Definition: dump.hpp:98
Represents named arrays with dimensions.
Definition: dump.hpp:541
bool next()
Read the next value from the input stream, returning true if successful and false if no further input...
Definition: dump.hpp:498
dump_reader(std::istream &in)
Construct a reader for the specified input stream.
Definition: dump.hpp:430

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