casadi_misc.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #ifndef CASADI_MISC_HPP
27 #define CASADI_MISC_HPP
28 
29 #include "exception.hpp"
30 #include "casadi_common.hpp"
31 #include <cstring>
32 
40 namespace casadi {
41 
42 #ifndef SWIG
43 
44 template<typename T>
46 public:
47  scoped_checkout(const T& proto) : proto_(proto) {
48  mem = proto_.checkout();
49  }
50 
51  scoped_checkout(scoped_checkout&& that) : mem(that.mem), proto_(that.proto_) {
52  that.mem = -1;
53  }
54 
55  scoped_checkout(const scoped_checkout& that) = delete;
56 
58  if (mem!=-1) proto_.release(mem);
59  }
60 
61  operator casadi_int() const {
62  return mem;
63  }
64 
65 private:
66  int mem;
67  const T& proto_;
68 };
69 
81  CASADI_EXPORT std::vector<casadi_int> range(casadi_int start, casadi_int stop, casadi_int step=1,
82  casadi_int len=std::numeric_limits<casadi_int>::max());
83 
87  CASADI_EXPORT bool is_range(const std::vector<casadi_int>& v,
88  casadi_int start, casadi_int stop, casadi_int step=1);
89 
91  CASADI_EXPORT void check_offset(const std::vector<casadi_int>& offset, casadi_int n,
92  const std::string& fname);
93 
94  CASADI_EXPORT std::string join(const std::vector<std::string>& l, const std::string& delim=",");
95 
97  CASADI_EXPORT bool startswith(const std::string& s, const std::string& p);
98 
100  CASADI_EXPORT std::string replace(const std::string& s,
101  const std::string& p, const std::string& r);
102 
104  CASADI_EXPORT bool version_gt(const std::string& version_left,
105  const std::string& version_right);
106 
108  CASADI_EXPORT bool version_ge(const std::string& version_left,
109  const std::string& version_right);
110 
112  CASADI_EXPORT bool version_lt(const std::string& version_left,
113  const std::string& version_right);
114 
116  CASADI_EXPORT bool version_le(const std::string& version_left,
117  const std::string& version_right);
118 
126  CASADI_EXPORT std::vector<casadi_int> range(casadi_int stop);
127 
129  CASADI_EXPORT bool all(const std::vector<bool> &v);
131  CASADI_EXPORT bool any(const std::vector<bool> &v);
133  CASADI_EXPORT std::vector<bool> boolvec_not(const std::vector<bool> &v);
135  CASADI_EXPORT std::vector<bool> boolvec_and(const std::vector<bool> &lhs,
136  const std::vector<bool> &rhs);
138  CASADI_EXPORT std::vector<bool> boolvec_or(const std::vector<bool> &lhs,
139  const std::vector<bool> &rhs);
140 
141  CASADI_EXPORT std::vector<casadi_int> boolvec_to_index(const std::vector<bool> &v);
142 
143  CASADI_EXPORT bool is_equally_spaced(const std::vector<double> &v);
144 
145  CASADI_EXPORT int to_int(casadi_int rhs);
146  CASADI_EXPORT std::vector<int> to_int(const std::vector<casadi_int>& rhs);
147  CASADI_EXPORT std::vector< std::vector<int> > to_int(
148  const std::vector< std::vector<casadi_int> >& rhs);
149 
150  template<typename T, typename S>
151  std::vector<T> vector_static_cast(const std::vector<S>& rhs);
152 
153  CASADI_EXPORT std::string str_bvec(bvec_t v);
154 
161  template<typename T>
162  std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i);
163 
170  template<typename T>
171  std::vector<T> vector_select(const std::vector<T> &v, const std::vector<bool> &s,
172  bool invert=false);
173 
177  template<typename T>
178  std::vector<T> vector_tail(const std::vector<T> &v);
179 
183  template<typename T>
184  std::vector<T> vector_init(const std::vector<T> &v);
185 
189  template<typename T>
190  std::vector<T> reverse(const std::vector<T> &v);
191 
195  template<typename T>
196  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b);
197 
201  template<typename T>
202  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c);
203 
207  bool is_permutation(const std::vector<casadi_int> &order);
208 
212  template<typename T>
213  std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order);
214 
218  std::vector<casadi_int> invert_permutation(const std::vector<casadi_int> &a);
219 
223  template<typename T>
224  std::vector<casadi_int> find(const std::vector<T> &v);
225 
226  #endif // SWIG
227 
229  template<typename T>
230  bool in_range(const std::vector<T> &v, casadi_int upper);
231 
233  template<typename T>
234  bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper);
235 
236  // Assert that a indices are in a range
237  #define casadi_assert_in_range(v, lower, upper) \
238  casadi_assert(in_range(v, lower, upper), \
239  "Out of bounds error. Got elements in range [" \
240  + str(*std::min_element(v.begin(), v.end())) + ","\
241  + str(*std::max_element(v.begin(), v.end())) + "], which is outside the range ["\
242  + str(lower) + "," + str(upper) + ").")
243 
244  // Assert that a indices are bounded
245  #define casadi_assert_bounded(v, upper) \
246  casadi_assert(in_range(v, upper), \
247  "Out of bounds error. Got elements in range [" \
248  + str(*std::min_element(v.begin(), v.end())) + ","\
249  + str(*std::max_element(v.begin(), v.end())) + "], which exceeds the upper bound "\
250  + str(upper) + ".")
251 
259  CASADI_EXPORT std::vector<casadi_int> complement(const std::vector<casadi_int> &v,
260  casadi_int size);
261 
270  CASADI_EXPORT std::vector<casadi_int> lookupvector(const std::vector<casadi_int> &v,
271  casadi_int size);
272  CASADI_EXPORT std::vector<casadi_int> lookupvector(const std::vector<casadi_int> &v);
273 
279  template<class T, class S>
280  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
281  std::vector<S>& flat);
282 
288  template<class T, class S, class I>
289  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
290  std::vector<S>& flat,
291  std::vector<I>& indices);
292 
294 #ifndef SWIG
298  template<class T>
299  std::vector<T> applymap(T (*f)(const T&), const std::vector<T>& comp);
300 
304  template<class T>
305  void applymap(void (*f)(T&), std::vector<T>& comp);
306 #endif // SWIG
308 
309 
311  template<typename T>
312  bool is_increasing(const std::vector<T> &v);
313 
315  template<typename T>
316  bool is_decreasing(const std::vector<T> &v);
317 
319  template<typename T>
320  bool is_nonincreasing(const std::vector<T> &v);
321 
323  template<typename T>
324  bool is_nondecreasing(const std::vector<T> &v);
325 
327  template<typename T>
328  bool is_monotone(const std::vector<T> &v);
329 
331  template<typename T>
332  bool is_strictly_monotone(const std::vector<T> &v);
333 
335  template<typename T>
336  bool has_negative(const std::vector<T> &v);
337 
339  template<typename T>
340  void write_matlab(std::ostream &stream, const std::vector<T> &v);
341 
343  template<typename T>
344  void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v);
345 
347  template<typename T>
348  void read_matlab(std::istream &stream, std::vector<T> &v);
349 
351  template<typename T>
352  void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v);
353 
354 #ifndef SWIG
356  template<typename T, typename F, typename L>
357  void linspace(std::vector<T> &v, const F& first, const L& last);
358 
361  CASADI_EXPORT bvec_t* get_bvec_t(std::vector<double>& v);
362 
364  CASADI_EXPORT const bvec_t* get_bvec_t(const std::vector<double>& v);
365 
367  CASADI_EXPORT bvec_t bvec_or(const bvec_t* arg, casadi_int n);
368 
370  template<typename T>
371  bvec_t* get_bvec_t(std::vector<T>& v);
372 
374  template<typename T>
375  const bvec_t* get_bvec_t(const std::vector<T>& v);
376 
378  template<typename T>
379  T* get_ptr(std::vector<T> &v);
380 
382  template<typename T>
383  const T* get_ptr(const std::vector<T> &v);
384 
386 
395  template<typename T>
396  void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
397  std::vector<casadi_int> &indices, bool invert_indices =false);
398 
402  template<typename T>
403  T product(const std::vector<T> &values);
404 
408  template<typename T>
409  T sum(const std::vector<T> &values);
410 
414  template<typename T>
415  std::vector<T> cumsum(const std::vector<T> &values);
416 
420  template<typename T>
421  std::vector<T> diff(const std::vector<T> &values);
422 
426  template<typename T>
427  std::vector<T> cumsum0(const std::vector<T> &values);
428 #endif //SWIG
429 
431  template<typename T>
432  bool is_regular(const std::vector<T> &v) {
433  for (auto&& vk : v) {
434  if (vk!=vk || vk==std::numeric_limits<T>::infinity() ||
435  vk==-std::numeric_limits<T>::infinity()) return false;
436  }
437  return true;
438  }
439 
440  // Create a temporary file
441  CASADI_EXPORT std::string temporary_file(const std::string& prefix,
442  const std::string& suffix,
443  const std::string& directory="");
444 
445  CASADI_EXPORT void normalized_setup(std::istream& stream);
446  CASADI_EXPORT void normalized_setup(std::ostream& stream);
447 
448 
449  class CASADI_EXPORT StreamStateGuard {
450  public:
451  explicit StreamStateGuard(std::ostream& os);
452  ~StreamStateGuard();
453 
454  private:
455  std::ostream& stream_;
456  std::ios::fmtflags flags_;
457  std::streamsize precision_;
458  std::streamsize width_;
459  std::locale locale_;
460  };
461 
462  inline void normalized_out(std::ostream& stream, double val) {
463  if (val==std::numeric_limits<double>::infinity()) {
464  stream << "inf";
465  } else if (val==-std::numeric_limits<double>::infinity()) {
466  stream << "-inf";
467  } else if (val!=val) {
468  stream << "nan";
469  } else {
470  stream << val;
471  }
472  }
473  inline int normalized_in(std::istream& stream, double& ret) {
474  std::streampos start = stream.tellg();
475  stream >> ret;
476  // Failed to interpret as double?
477  if (stream.fail()) {
478  // Clear error flag
479  stream.clear();
480  // Reset stream position
481  // Need to parse e.g "-inf"
482  stream.seekg(start);
483  // Might be a inf/nan
484  std::string non_reg;
485  stream >> non_reg;
486  // Break on trailing whitespace
487  if (stream.fail()) {
488  if (stream.eof()) {
489  ret = std::numeric_limits<double>::quiet_NaN();
490  return -1; // End of stream
491  } else {
492  ret = std::numeric_limits<double>::quiet_NaN();
493  return 1; // Failed to parse to string
494  }
495  }
496  if (non_reg=="inf") {
497  ret = std::numeric_limits<double>::infinity();
498  } else if (non_reg=="-inf") {
499  ret = -std::numeric_limits<double>::infinity();
500  } else if (non_reg=="nan" || non_reg=="-nan") {
501  ret = std::numeric_limits<double>::quiet_NaN();
502  } else {
503  ret = std::numeric_limits<double>::quiet_NaN();
504  return 2; // Failed to interpret as number
505  }
506  }
507  return 0;
508  }
509 
510 } // namespace casadi
511 
512 #ifndef SWIG
513 
514 // Implementations
515 namespace casadi {
516 
518  template<typename T>
519  std::ostream& operator<<(std::ostream& stream, const std::vector<T>& v) {
520  stream << casadi::str(v);
521  return stream;
522  }
523 
525  template<typename T, size_t N>
526  std::ostream& operator<<(std::ostream& stream, const std::array<T, N>& v) {
527  stream << casadi::str(v);
528  return stream;
529  }
530 
532  template<typename T>
533  std::ostream& operator<<(std::ostream& stream, const std::set<T>& v) {
534  stream << casadi::str(v);
535  return stream;
536  }
537 
538  template<typename T1, typename T2>
539  std::ostream& operator<<(std::ostream& stream, const std::pair<T1, T2>& p) {
540  stream << casadi::str(p);
541  return stream;
542  }
543 
544  template<typename T1, typename T2>
545  std::ostream& operator<<(std::ostream& stream, const std::map<T1, T2>& p) {
546  stream << casadi::str(p);
547  return stream;
548  }
549 
550  template<typename T2>
551  std::ostream& operator<<(std::ostream& stream, const std::map<std::string, T2>& p) {
552  stream << casadi::str(p);
553  return stream;
554  }
555 
556  template<typename T>
557  bool mul_overflows(const T& a, const T& b) {
558  if (a==0 || b==0) return false;
559  return std::abs(std::numeric_limits<T>::max()/a) < std::abs(b);
560  }
561 
562  template<typename T, typename S>
563  std::vector<T> vector_static_cast(const std::vector<S>& rhs) {
564  std::vector<T> ret;
565  ret.reserve(rhs.size());
566  for (auto e : rhs) ret.push_back(static_cast<T>(e));
567  return ret;
568  }
569 
570  template<typename T>
571  std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i) {
572  std::vector<T> ret;
573  ret.reserve(i.size());
574  for (casadi_int k=0;k<i.size();++k) {
575  casadi_int j = i[k];
576  casadi_assert(j>=0,
577  "vector_slice: Indices should be larger than zero."
578  "You have " + str(j) + " at location " + str(k) + ".");
579  casadi_assert(j<v.size(),
580  "vector_slice: Indices should be larger than zero."
581  "You have " + str(j) + " at location " + str(k) + ".");
582  ret.push_back(v[j]);
583  }
584  return ret;
585  }
586 
587  template<typename T>
588  std::vector<T> vector_select(const std::vector<T> &v, const std::vector<bool> &s, bool invert) {
589  std::vector<T> ret;
590  casadi_assert(v.size()==s.size(), "Dimension mismatch.");
591  if (invert) {
592  for (casadi_int k=0;k<s.size();++k) {
593  if (!s[k]) ret.push_back(v[k]);
594  }
595  } else {
596  for (casadi_int k=0;k<s.size();++k) {
597  if (s[k]) ret.push_back(v[k]);
598  }
599  }
600  return ret;
601  }
602 
603  template<typename T>
604  std::vector<T> vector_tail(const std::vector<T> &v) {
605  std::vector<T> ret;
606  ret.insert(ret.begin(), v.begin()+1, v.end());
607  return ret;
608  }
609 
610  template<typename T>
611  std::vector<T> vector_init(const std::vector<T> &v) {
612  std::vector<T> ret;
613  ret.insert(ret.begin(), v.begin(), v.begin()+v.size()-1);
614  return ret;
615  }
616 
617  template<typename T>
618  std::vector<T> reverse(const std::vector<T> &v) {
619  std::vector<T> ret(v.size());
620  std::reverse_copy(v.begin(), v.end(), ret.begin());
621  return ret;
622  }
623 
624  template<typename T>
625  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b) {
626  std::vector<T> ret = a;
627  ret.insert(ret.end(), b.begin(), b.end());
628  return ret;
629  }
630 
631  template<typename T>
632  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c) {
633  std::vector<T> ret = a;
634  ret.insert(ret.end(), b.begin(), b.end());
635  ret.insert(ret.end(), c.begin(), c.end());
636  return ret;
637  }
638 
639  template<typename T>
640  std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order) {
641  casadi_assert_dev(order.size()==a.size());
642  casadi_assert_dev(is_permutation(order));
643  return vector_slice(a, order);
644  }
645 
646  template<typename T>
647  std::vector<casadi_int> find(const std::vector<T> &v) {
648  std::vector<casadi_int> ret;
649  for (casadi_int i=0;i<v.size();++i) {
650  if (v[i]) ret.push_back(i);
651  }
652  return ret;
653  }
654 
655 #ifndef SWIG
656  template<class T>
657  std::vector<T> applymap(T (*f)(const T&) , const std::vector<T>& comp) {
658  std::vector<T> ret(comp.size());
659  std::transform(comp.begin(), comp.end(), ret.begin(), f);
660  return ret;
661  }
662 
663  template<class T>
664  void applymap(void (*f)(T &), std::vector<T>& comp) {
665  std::for_each(comp.begin(), comp.end(), f);
666  }
667 
668  template<class S, class D>
669  void copy_vector(const std::vector<S>& s, std::vector<D>& d) {
670  casadi_assert(s.size()==d.size(), "Dimension mismatch.");
671  std::copy(s.begin(), s.end(), d.begin());
672  }
673 
674  template<class S, class D>
675  void assign_vector(const std::vector<S>& s, std::vector<D>& d) {
676  casadi_assert(d.empty(), "Receiving vector must be empty");
677  d.resize(s.size());
678  std::copy(s.begin(), s.end(), d.begin());
679  }
680 
681  template<class S, class D>
682  void copy_vector(const S* s, std::vector<D>& d) {
683  for (casadi_int i=0;i<d.size();++i) {
684  d[i] = static_cast<D>(s[i]);
685  }
686  }
687 
688  template<class S, class D>
689  void init_vector(std::vector<S>& d, const std::vector<D>& s) {
690  d.resize(s.size());
691  std::copy(s.begin(), s.end(), d.begin());
692  }
693 #endif //SWIG
694 
695  template<typename T>
696  bool in_range(const std::vector<T> &v, casadi_int upper) {
697  return in_range(v, 0, upper);
698  }
699 
700  template<typename T>
701  bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper) {
702  if (v.empty()) return true;
703  casadi_int max = *std::max_element(v.begin(), v.end());
704  if (max >= upper) return false;
705  casadi_int min = *std::min_element(v.begin(), v.end());
706  return (min >= lower);
707  }
708 
709  template<class T, class S>
710  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
711  std::vector<S>& flat) {
712  // Count total elements in nested
713  casadi_int N = 0;
714  for (const auto& e : nested) {
715  N += e.size();
716  }
717 
718  // Populate flat, one nested section at a time
719  flat.clear();
720  flat.reserve(N);
721  for (const auto& e : nested) {
722  flat.insert(flat.end(), e.begin(), e.end());
723  }
724  }
725 
726  template<class T, class S, class I>
727  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
728  std::vector<S>& flat,
729  std::vector<I>& indices) {
730  // Delegate
731  flatten_nested_vector(nested, flat);
732 
733  // Build up indices
734  casadi_int N = nested.size();
735  indices.resize(1, 0);
736  indices.reserve(N+1);
737  casadi_int offset = 0;
738  for (const auto& e : nested) {
739  offset += e.size();
740  indices.push_back(offset);
741  }
742  }
743 
744  template<typename T>
745  bool isUnique(const std::vector<T> &v) {
746  std::set<T> s(v.begin(), v.end());
747  return v.size()==s.size();
748  }
749 
750  template<typename T>
751  bool is_increasing(const std::vector<T> &v) {
752  if (v.empty()) return true;
753  T el = v[0];
754  for (casadi_int i=1;i<v.size();++i) {
755  if (!(v[i] > el)) return false;
756  el = v[i];
757  }
758  return el==el; // nan -> false
759  }
760 
761  template<typename T>
762  bool is_decreasing(const std::vector<T> &v) {
763  if (v.empty()) return true;
764  T el = v[0];
765  for (casadi_int i=1;i<v.size();++i) {
766  if (!(v[i] < el)) return false;
767  el = v[i];
768  }
769  return el==el; // nan -> false
770  }
771 
772  template<typename T>
773  bool is_nonincreasing(const std::vector<T> &v) {
774  if (v.empty()) return true;
775  T el = v[0];
776  for (casadi_int i=1;i<v.size();++i) {
777  if (!(v[i] <= el)) return false;
778  el = v[i];
779  }
780  return el==el; // nan -> false
781  }
782 
783  template<typename T>
784  bool is_nondecreasing(const std::vector<T> &v) {
785  if (v.empty()) return true;
786  T el = v[0];
787  for (casadi_int i=1;i<v.size();++i) {
788  if (!(v[i] >= el)) return false;
789  el = v[i];
790  }
791  return el==el; // nan -> false
792  }
793 
794  template<typename T>
795  bool is_monotone(const std::vector<T> &v) {
796  return is_nondecreasing(v) || is_nonincreasing(v);
797  }
798 
799  template<typename T>
800  bool is_strictly_monotone(const std::vector<T> &v) {
801  return is_decreasing(v) || is_increasing(v);
802  }
803 
804  template<typename T>
805  bool has_negative(const std::vector<T> &v) {
806  for (std::size_t i=0; i<v.size(); ++i) {
807  if (v[i]<0) return true;
808  }
809  return false;
810  }
811 
812  template<typename T>
813  void write_matlab(std::ostream &stream, const std::vector<T> &v) {
814  std::copy(v.begin(), v.end(), std::ostream_iterator<T>(stream, " "));
815  }
816 
817  template<typename T>
818  void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v) {
819  for (casadi_uint i=0; i<v.size(); ++i) {
820  std::copy(v[i].begin(), v[i].end(), std::ostream_iterator<T>(stream, " "));
821  stream << std::endl;
822  }
823  }
824 
825  template<typename T>
826  void read_matlab(std::istream &stream, std::vector<T> &v) {
827  v.clear();
828 
829  while (!stream.eof()) {
830  T val;
831  stream >> val;
832  if (stream.fail()) {
833  stream.clear();
834  std::string s;
835  stream >> s;
836  if (s=="inf")
837  val = std::numeric_limits<T>::infinity();
838  else
839  break;
840  }
841  v.push_back(val);
842  }
843  }
844 
845  template<typename T>
846  void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v) {
847  v.clear();
848  std::string line;
849  while (!getline(file, line, '\n').eof()) {
850  std::istringstream reader(line);
851  std::vector<T> lineData;
852 
853  while (!reader.eof()) {
854  T val;
855  reader >> val;
856  if (reader.fail()) {
857  reader.clear();
858  std::string s;
859  reader >> s;
860  if (s=="inf")
861  val = std::numeric_limits<T>::infinity();
862  else
863  break;
864  }
865  lineData.push_back(val);
866  }
867  v.push_back(lineData);
868  }
869  }
870 
871  template<typename T, typename F, typename L>
872  void linspace(std::vector<T> &v, const F& first, const L& last) {
873  if (v.size()<2)
874  throw CasadiException("std::linspace: vector must contain at least two elements");
875 
876  // Increment
877  T increment = (last-first)/T(v.size()-1);
878 
879  v[0] = first;
880  for (unsigned i=1; i<v.size()-1; ++i)
881  v[i] = v[i-1] + increment;
882  v[v.size()-1] = last;
883  }
884 
885  template<typename T>
886  T* get_ptr(std::vector<T> &v) {
887  if (v.empty())
888  return nullptr;
889  else
890  return &v.front();
891  }
892 
893  template<typename T>
894  const T* get_ptr(const std::vector<T> &v) {
895  if (v.empty())
896  return nullptr;
897  else
898  return &v.front();
899  }
900 
901  // Helper class
902  template<typename T>
903  struct sortCompare {
904  const std::vector<T> &v_;
905  sortCompare(const std::vector<T> &v) : v_(v) {}
906  bool operator() (casadi_int i, casadi_int j) const { return v_[i]<v_[j];}
907  };
908 
909  template<typename T>
910  void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
911  std::vector<casadi_int> &indices, bool invert_indices) {
912  // Call recursively if indices need to be inverted
913  if (invert_indices) {
914  std::vector<casadi_int> inverted;
915  sort(values, sorted_values, inverted, false);
916  indices.resize(inverted.size());
917  for (size_t i=0; i<inverted.size(); ++i) {
918  indices[inverted[i]] = i;
919  }
920  return;
921  }
922 
923  // Create list of indices
924  indices.resize(values.size());
925  for (size_t i=0; i<indices.size(); ++i) indices[i] = i;
926 
927  // Sort this list by the values
928  std::sort(indices.begin(), indices.end(), sortCompare<T>(values));
929 
930  // Sort the values accordingly
931  sorted_values.resize(values.size());
932  for (size_t i=0; i<values.size(); ++i) {
933  sorted_values[i] = values[indices[i]];
934  }
935  }
936 
937  template<typename T>
938  T product(const std::vector<T> &values) {
939  T r = 1;
940  for (casadi_int i=0;i<values.size();++i) r*=values[i];
941  return r;
942  }
943 
944  template<typename T>
945  T sum(const std::vector<T> &values) {
946  T r = 0;
947  for (casadi_int i=0;i<values.size();++i) r+=values[i];
948  return r;
949  }
950 
951  template<typename T>
952  std::vector<T> cumsum(const std::vector<T> &values) {
953  std::vector<T> ret(values.size());
954  T acc = 0;
955  for (casadi_int i=0;i<values.size();++i) {
956  acc+= values[i];
957  ret[i] = acc;
958  }
959  return ret;
960  }
961 
962  template<typename T>
963  std::vector<T> cumsum0(const std::vector<T> &values) {
964  std::vector<T> ret(values.size()+1, 0);
965  T acc = 0;
966  for (casadi_int i=0;i<values.size();++i) {
967  acc+= values[i];
968  ret[i+1] = acc;
969  }
970  return ret;
971  }
972 
973  template<typename T>
974  std::vector<T> diff(const std::vector<T> &values) {
975  casadi_assert(!values.empty(), "Array must be non-empty");
976  std::vector<T> ret(values.size()-1);
977  for (casadi_int i=0;i<values.size()-1;++i) {
978  ret[i] = values[i+1]-values[i];
979  }
980  return ret;
981  }
982 
983  template<typename T>
984  T dot(const std::vector<T>& a, const std::vector<T>& b) {
985  T ret = 0;
986  for (casadi_int k=0; k<a.size(); ++k) {
987  ret += a[k]*b[k];
988  }
989  return ret;
990  }
991 
992  template<typename T>
993  T norm_inf(const std::vector<T>& x) {
994  T ret = 0;
995  for (casadi_int k=0; k<x.size(); ++k) {
996  ret = fmax(ret, fabs(x[k]));
997  }
998  return ret;
999  }
1000 
1001  template<typename T>
1002  T norm_1(const std::vector<T>& x) {
1003  T ret = 0;
1004  for (casadi_int k=0; k<x.size(); ++k) {
1005  ret += fabs(x[k]);
1006  }
1007  return ret;
1008  }
1009 
1010  template<typename T>
1011  T norm_2(const std::vector<T>& x) {
1012  T ret = 0;
1013  for (casadi_int k=0; k<x.size(); ++k) {
1014  ret += x[k]*x[k];
1015  }
1016  return sqrt(ret);
1017  }
1018 
1019  template<typename T>
1020  bvec_t* get_bvec_t(std::vector<T>& v) {
1021  casadi_assert(0, "get_bvec_t only supported for double");
1022  }
1023 
1024  template<typename T>
1025  const bvec_t* get_bvec_t(const std::vector<T>& v) {
1026  casadi_assert(0, "get_bvec_t only supported for double");
1027  }
1028 
1031  typedef std::vector<std::string> StringVector;
1033 
1037  template<typename T>
1038  inline size_t hash_value(T v) { return size_t(v);}
1039 
1043  template<typename T>
1044  inline void hash_combine(std::size_t& seed, T v) {
1045  seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1046  }
1047 
1051  template<typename T>
1052  inline void hash_combine(std::size_t& seed, const T* v, std::size_t sz) {
1053  for (casadi_int i=0; i<sz; ++i) hash_combine(seed, v[i]);
1054  }
1055 
1059  template<typename T>
1060  inline void hash_combine(std::size_t& seed, const std::vector<T>& v) {
1061  hash_combine(seed, get_ptr(v), v.size());
1062  }
1063 
1064  template<>
1065  inline size_t hash_value(std::string v) {
1066  size_t seed = 0;
1067  hash_combine(seed, v.c_str(), v.size());
1068  return seed;
1069  }
1070 
1074  template<>
1075  inline size_t hash_value(double v) {
1076  std::uint64_t u;
1077  std::memcpy(&u, &v, sizeof(double));
1078 
1079  if (sizeof(size_t) == 8) {
1080  // 64-bit: keep all bits
1081  return static_cast<size_t>(u);
1082  } else {
1083  // 32-bit: fold with hash_combine
1084  size_t seed = 0;
1085  hash_combine(seed, static_cast<std::uint32_t>(u));
1086  hash_combine(seed, static_cast<std::uint32_t>(u >> 32));
1087  return seed;
1088  }
1089  }
1090 
1091 } // namespace casadi
1092 #endif // SWIG
1093 
1094 #endif // CASADI_MISC_HPP
Casadi exception class.
Definition: exception.hpp:77
scoped_checkout(scoped_checkout &&that)
Definition: casadi_misc.hpp:51
scoped_checkout(const T &proto)
Definition: casadi_misc.hpp:47
scoped_checkout(const scoped_checkout &that)=delete
The casadi namespace.
Definition: archiver.cpp:28
bool mul_overflows(const T &a, const T &b)
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
bvec_t * get_bvec_t(std::vector< double > &v)
bool is_equally_spaced(const std::vector< double > &v)
T product(const std::vector< T > &values)
product
std::vector< T > vector_tail(const std::vector< T > &v)
Return all but the first element of a vector.
std::string join(const std::vector< std::string > &l, const std::string &delim)
bool is_decreasing(const std::vector< T > &v)
Check if the vector is strictly decreasing.
std::vector< casadi_int > invert_permutation(const std::vector< casadi_int > &a)
inverse a permutation vector
void assign_vector(const std::vector< S > &s, std::vector< D > &d)
T norm_1(const std::vector< T > &x)
unsigned long long bvec_t
void init_vector(std::vector< S > &d, const std::vector< D > &s)
T norm_inf(const std::vector< T > &x)
bool version_le(const std::string &version_left, const std::string &version_right)
Compare versions: returns true if version_left <= version_right.
void copy_vector(const std::vector< S > &s, std::vector< D > &d)
bool is_range(const std::vector< casadi_int > &v, casadi_int start, casadi_int stop, casadi_int step)
Check if a vector matches a range.
Definition: casadi_misc.cpp:95
bool startswith(const std::string &s, const std::string &p)
Checks if s starts with p.
int to_int(casadi_int rhs)
Definition: casadi_misc.cpp:60
void flatten_nested_vector(const std::vector< std::vector< T > > &nested, std::vector< S > &flat)
Flatten a nested std::vector tot a single flattened vector.
bool has_negative(const std::vector< T > &v)
Check if the vector has negative entries.
bool isUnique(const std::vector< T > &v)
bool version_gt(const std::string &version_left, const std::string &version_right)
Compare versions: returns true if version_left > version_right.
bool is_increasing(const std::vector< T > &v)
Check if the vector is strictly increasing.
CASADI_EXPORT std::string replace(const std::string &s, const std::string &p, const std::string &r)
Replace all occurences of p with r in s.
void sort(const std::vector< T > &values, std::vector< T > &sorted_values, std::vector< casadi_int > &indices, bool invert_indices=false)
Sort the data in a vector.
std::vector< casadi_int > find(const std::vector< T > &v)
find nonzeros
void check_offset(const std::vector< casadi_int > &offset, casadi_int n, const std::string &fname)
Assert that offset starts at 0, is nondecreasing and ends at n.
bool is_monotone(const std::vector< T > &v)
Check if the vector is monotone.
std::string str_bvec(bvec_t v)
std::vector< bool > boolvec_or(const std::vector< bool > &lhs, const std::vector< bool > &rhs)
Or operation on boolean vector.
bool version_lt(const std::string &version_left, const std::string &version_right)
Compare versions: returns true if version_left < version_right.
void linspace(std::vector< T > &v, const F &first, const L &last)
Matlab's linspace.
std::string str(const T &v)
String representation, any type.
std::vector< casadi_int > lookupvector(const std::vector< casadi_int > &v, casadi_int size)
Returns a vector for quickly looking up entries of supplied list.
void write_matlab(std::ostream &stream, const std::vector< T > &v)
Print vector, matlab style.
std::vector< T > vector_static_cast(const std::vector< S > &rhs)
std::vector< bool > boolvec_not(const std::vector< bool > &v)
Invert all entries.
void hash_combine(std::size_t &seed, T v)
Generate a hash value incrementally (function taken from boost)
std::vector< std::string > StringVector
std::vector< T > cumsum(const std::vector< T > &values)
cumulative sum
std::vector< bool > boolvec_and(const std::vector< bool > &lhs, const std::vector< bool > &rhs)
And operation on boolean vector.
size_t hash_value(T v)
Hash value of an integer.
bool any(const std::vector< bool > &v)
Check if any arguments are true.
Definition: casadi_misc.cpp:88
void normalized_setup(std::istream &stream)
void read_matlab(std::istream &stream, std::vector< T > &v)
Read vector, matlab style.
T dot(const std::vector< T > &a, const std::vector< T > &b)
bool all(const std::vector< bool > &v)
Check if all arguments are true.
Definition: casadi_misc.cpp:81
std::ostream & operator<<(std::ostream &stream, const std::vector< T > &v)
Enables flushing an std::vector to a stream (prints representation)
bool is_strictly_monotone(const std::vector< T > &v)
Check if the vector is strictly monotone.
std::vector< T > diff(const std::vector< T > &values)
diff
std::vector< T > vector_select(const std::vector< T > &v, const std::vector< bool > &s, bool invert=false)
Select subset of vector.
std::vector< T > vector_slice(const std::vector< T > &v, const std::vector< casadi_int > &i)
Slicing vector.
std::vector< T > vector_init(const std::vector< T > &v)
Return all but the last element of a vector.
std::vector< T > applymap(T(*f)(const T &), const std::vector< T > &comp)
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
T norm_2(const std::vector< T > &x)
std::vector< T > cumsum0(const std::vector< T > &values)
cumulative sum, starting with zero
bool in_range(const std::vector< T > &v, casadi_int upper)
Check if for each element of v holds: v_i < upper.
bool is_permutation(const std::vector< casadi_int > &order)
Does the list represent a permutation?
bool is_nonincreasing(const std::vector< T > &v)
Check if the vector is non-increasing.
std::vector< casadi_int > complement(const std::vector< casadi_int > &v, casadi_int size)
Returns the list of all i in [0, size[ not found in supplied list.
std::vector< T > permute(const std::vector< T > &a, const std::vector< casadi_int > &order)
permute a list
T sum(const std::vector< T > &values)
sum
std::vector< T > reverse(const std::vector< T > &v)
Reverse a list.
bool is_regular(const std::vector< T > &v)
Checks if array does not contain NaN or Inf.
bool is_nondecreasing(const std::vector< T > &v)
Check if the vector is non-decreasing.
bool version_ge(const std::string &version_left, const std::string &version_right)
Compare versions: returns true if version_left >= version_right.
bvec_t bvec_or(const bvec_t *arg, casadi_int n)
Bit-wise or operation on bvec_t array.
int normalized_in(std::istream &stream, double &ret)
std::string temporary_file(const std::string &prefix, const std::string &suffix, const std::string &directory)
void normalized_out(std::ostream &stream, double val)
std::vector< casadi_int > boolvec_to_index(const std::vector< bool > &v)
bool operator()(casadi_int i, casadi_int j) const
const std::vector< T > & v_
sortCompare(const std::vector< T > &v)