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 
39 namespace casadi {
40 
41 #ifndef SWIG
42 
43 template<typename T>
45 public:
46  scoped_checkout(const T& proto) : proto_(proto) {
47  mem = proto_.checkout();
48  }
49 
50  scoped_checkout(scoped_checkout&& that) : mem(that.mem), proto_(that.proto_) {
51  that.mem = -1;
52  }
53 
54  scoped_checkout(const scoped_checkout& that) = delete;
55 
57  if (mem!=-1) proto_.release(mem);
58  }
59 
60  operator casadi_int() const {
61  return mem;
62  }
63 
64 private:
65  int mem;
66  const T& proto_;
67 };
68 
80  CASADI_EXPORT std::vector<casadi_int> range(casadi_int start, casadi_int stop, casadi_int step=1,
81  casadi_int len=std::numeric_limits<casadi_int>::max());
82 
86  CASADI_EXPORT bool is_range(const std::vector<casadi_int>& v,
87  casadi_int start, casadi_int stop, casadi_int step=1);
88 
89  CASADI_EXPORT std::string join(const std::vector<std::string>& l, const std::string& delim=",");
90 
92  CASADI_EXPORT bool startswith(const std::string& s, const std::string& p);
93 
95  CASADI_EXPORT std::string replace(const std::string& s,
96  const std::string& p, const std::string& r);
97 
105  CASADI_EXPORT std::vector<casadi_int> range(casadi_int stop);
106 
108  CASADI_EXPORT bool all(const std::vector<bool> &v);
110  CASADI_EXPORT bool any(const std::vector<bool> &v);
112  CASADI_EXPORT std::vector<bool> boolvec_not(const std::vector<bool> &v);
114  CASADI_EXPORT std::vector<bool> boolvec_and(const std::vector<bool> &lhs,
115  const std::vector<bool> &rhs);
117  CASADI_EXPORT std::vector<bool> boolvec_or(const std::vector<bool> &lhs,
118  const std::vector<bool> &rhs);
119 
120  CASADI_EXPORT std::vector<casadi_int> boolvec_to_index(const std::vector<bool> &v);
121 
122  CASADI_EXPORT bool is_equally_spaced(const std::vector<double> &v);
123 
125  CASADI_EXPORT std::vector<casadi_int> tensor_permute_mapping(const std::vector<casadi_int>& dims,
126  const std::vector<casadi_int>& order);
127 
128  CASADI_EXPORT int to_int(casadi_int rhs);
129  CASADI_EXPORT std::vector<int> to_int(const std::vector<casadi_int>& rhs);
130  CASADI_EXPORT std::vector< std::vector<int> > to_int(
131  const std::vector< std::vector<casadi_int> >& rhs);
132 
133  template<typename T, typename S>
134  std::vector<T> vector_static_cast(const std::vector<S>& rhs);
135 
136  CASADI_EXPORT std::string str_bvec(bvec_t v);
137 
144  template<typename T>
145  std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i);
146 
153  template<typename T>
154  std::vector<T> vector_select(const std::vector<T> &v, const std::vector<bool> &s,
155  bool invert=false);
156 
160  template<typename T>
161  std::vector<T> vector_tail(const std::vector<T> &v);
162 
166  template<typename T>
167  std::vector<T> vector_init(const std::vector<T> &v);
168 
172  template<typename T>
173  std::vector<T> reverse(const std::vector<T> &v);
174 
178  template<typename T>
179  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b);
180 
184  template<typename T>
185  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c);
186 
190  bool is_permutation(const std::vector<casadi_int> &order);
191 
195  template<typename T>
196  std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order);
197 
201  std::vector<casadi_int> invert_permutation(const std::vector<casadi_int> &a);
202 
206  template<typename T>
207  std::vector<casadi_int> find(const std::vector<T> &v);
208 
209  #endif // SWIG
210 
212  template<typename T>
213  bool in_range(const std::vector<T> &v, casadi_int upper);
214 
216  template<typename T>
217  bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper);
218 
219  // Assert that a indices are in a range
220  #define casadi_assert_in_range(v, lower, upper) \
221  casadi_assert(in_range(v, lower, upper), \
222  "Out of bounds error. Got elements in range [" \
223  + str(*std::min_element(v.begin(), v.end())) + ","\
224  + str(*std::max_element(v.begin(), v.end())) + "], which is outside the range ["\
225  + str(lower) + "," + str(upper) + ").")
226 
227  // Assert that a indices are bounded
228  #define casadi_assert_bounded(v, upper) \
229  casadi_assert(in_range(v, upper), \
230  "Out of bounds error. Got elements in range [" \
231  + str(*std::min_element(v.begin(), v.end())) + ","\
232  + str(*std::max_element(v.begin(), v.end())) + "], which exceeds the upper bound "\
233  + str(upper) + ".")
234 
242  CASADI_EXPORT std::vector<casadi_int> complement(const std::vector<casadi_int> &v,
243  casadi_int size);
244 
253  CASADI_EXPORT std::vector<casadi_int> lookupvector(const std::vector<casadi_int> &v,
254  casadi_int size);
255  CASADI_EXPORT std::vector<casadi_int> lookupvector(const std::vector<casadi_int> &v);
256 
262  template<class T, class S>
263  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
264  std::vector<S>& flat);
265 
271  template<class T, class S, class I>
272  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
273  std::vector<S>& flat,
274  std::vector<I>& indices);
275 
277 #ifndef SWIG
281  template<class T>
282  std::vector<T> applymap(T (*f)(const T&), const std::vector<T>& comp);
283 
287  template<class T>
288  void applymap(void (*f)(T&), std::vector<T>& comp);
289 #endif // SWIG
291 
292 
294  template<typename T>
295  bool is_increasing(const std::vector<T> &v);
296 
298  template<typename T>
299  bool is_decreasing(const std::vector<T> &v);
300 
302  template<typename T>
303  bool is_nonincreasing(const std::vector<T> &v);
304 
306  template<typename T>
307  bool is_nondecreasing(const std::vector<T> &v);
308 
310  template<typename T>
311  bool is_monotone(const std::vector<T> &v);
312 
314  template<typename T>
315  bool is_strictly_monotone(const std::vector<T> &v);
316 
318  template<typename T>
319  bool has_negative(const std::vector<T> &v);
320 
322  template<typename T>
323  void write_matlab(std::ostream &stream, const std::vector<T> &v);
324 
326  template<typename T>
327  void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v);
328 
330  template<typename T>
331  void read_matlab(std::istream &stream, std::vector<T> &v);
332 
334  template<typename T>
335  void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v);
336 
337 #ifndef SWIG
339  template<typename T, typename F, typename L>
340  void linspace(std::vector<T> &v, const F& first, const L& last);
341 
344  CASADI_EXPORT bvec_t* get_bvec_t(std::vector<double>& v);
345 
347  CASADI_EXPORT const bvec_t* get_bvec_t(const std::vector<double>& v);
348 
350  CASADI_EXPORT bvec_t bvec_or(const bvec_t* arg, casadi_int n);
351 
353  template<typename T>
354  bvec_t* get_bvec_t(std::vector<T>& v);
355 
357  template<typename T>
358  const bvec_t* get_bvec_t(const std::vector<T>& v);
359 
361  template<typename T>
362  T* get_ptr(std::vector<T> &v);
363 
365  template<typename T>
366  const T* get_ptr(const std::vector<T> &v);
367 
369 
378  template<typename T>
379  void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
380  std::vector<casadi_int> &indices, bool invert_indices =false);
381 
385  template<typename T>
386  T product(const std::vector<T> &values);
387 
391  template<typename T>
392  T sum(const std::vector<T> &values);
393 
397  template<typename T>
398  std::vector<T> cumsum(const std::vector<T> &values);
399 
403  template<typename T>
404  std::vector<T> diff(const std::vector<T> &values);
405 
409  template<typename T>
410  std::vector<T> cumsum0(const std::vector<T> &values);
411 #endif //SWIG
412 
414  template<typename T>
415  bool is_regular(const std::vector<T> &v) {
416  for (auto&& vk : v) {
417  if (vk!=vk || vk==std::numeric_limits<T>::infinity() ||
418  vk==-std::numeric_limits<T>::infinity()) return false;
419  }
420  return true;
421  }
422 
423  // Create a temporary file
424  CASADI_EXPORT std::string temporary_file(const std::string& prefix, const std::string& suffix);
425 
426  CASADI_EXPORT void normalized_setup(std::istream& stream);
427  CASADI_EXPORT void normalized_setup(std::ostream& stream);
428 
429  inline void normalized_out(std::ostream& stream, double val) {
430  if (val==std::numeric_limits<double>::infinity()) {
431  stream << "inf";
432  } else if (val==-std::numeric_limits<double>::infinity()) {
433  stream << "-inf";
434  } else if (val!=val) {
435  stream << "nan";
436  } else {
437  stream << val;
438  }
439  }
440  inline int normalized_in(std::istream& stream, double& ret) {
441  std::streampos start = stream.tellg();
442  stream >> ret;
443  // Failed to interpret as double?
444  if (stream.fail()) {
445  // Clear error flag
446  stream.clear();
447  // Reset stream position
448  // Need to parse e.g "-inf"
449  stream.seekg(start);
450  // Might be a inf/nan
451  std::string non_reg;
452  stream >> non_reg;
453  // Break on trailing whitespace
454  if (stream.fail()) {
455  if (stream.eof()) {
456  ret = std::numeric_limits<double>::quiet_NaN();
457  return -1; // End of stream
458  } else {
459  ret = std::numeric_limits<double>::quiet_NaN();
460  return 1; // Failed to parse to string
461  }
462  }
463  if (non_reg=="inf") {
464  ret = std::numeric_limits<double>::infinity();
465  } else if (non_reg=="-inf") {
466  ret = -std::numeric_limits<double>::infinity();
467  } else if (non_reg=="nan") {
468  ret = std::numeric_limits<double>::quiet_NaN();
469  } else {
470  ret = std::numeric_limits<double>::quiet_NaN();
471  return 2; // Failed to interpret as number
472  }
473  }
474  return 0;
475  }
476 
477 } // namespace casadi
478 
479 #ifndef SWIG
480 // In std namespace
481 namespace std {
482 
484  template<typename T>
485  ostream& operator<<(ostream& stream, const vector<T>& v) {
486  stream << casadi::str(v);
487  return stream;
488  }
489 
491  template<typename T, size_t N>
492  ostream& operator<<(ostream& stream, const array<T, N>& v) {
493  stream << casadi::str(v);
494  return stream;
495  }
496 
498  template<typename T>
499  ostream& operator<<(ostream& stream, const set<T>& v) {
500  stream << casadi::str(v);
501  return stream;
502  }
503 
504  template<typename T1, typename T2>
505  ostream& operator<<(ostream& stream, const pair<T1, T2>& p) {
506  stream << casadi::str(p);
507  return stream;
508  }
509 
510  template<typename T1, typename T2>
511  ostream& operator<<(ostream& stream, const std::map<T1, T2>& p) {
512  stream << casadi::str(p);
513  return stream;
514  }
515 
516  template<typename T2>
517  ostream& operator<<(ostream& stream, const std::map<std::string, T2>& p) {
518  stream << casadi::str(p);
519  return stream;
520  }
521 
522  template<typename T>
523  bool mul_overflows(const T& a, const T& b) {
524  if (a==0 || b==0) return false;
525  return abs(std::numeric_limits<T>::max()/a) < abs(b);
526  }
527 
528 } // namespace std
529 
530 // Implementations
531 namespace casadi {
532 
533  template<typename T, typename S>
534  std::vector<T> vector_static_cast(const std::vector<S>& rhs) {
535  std::vector<T> ret;
536  ret.reserve(rhs.size());
537  for (auto e : rhs) ret.push_back(static_cast<T>(e));
538  return ret;
539  }
540 
541  template<typename T>
542  std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i) {
543  std::vector<T> ret;
544  ret.reserve(i.size());
545  for (casadi_int k=0;k<i.size();++k) {
546  casadi_int j = i[k];
547  casadi_assert(j>=0,
548  "vector_slice: Indices should be larger than zero."
549  "You have " + str(j) + " at location " + str(k) + ".");
550  casadi_assert(j<v.size(),
551  "vector_slice: Indices should be larger than zero."
552  "You have " + str(j) + " at location " + str(k) + ".");
553  ret.push_back(v[j]);
554  }
555  return ret;
556  }
557 
558  template<typename T>
559  std::vector<T> vector_select(const std::vector<T> &v, const std::vector<bool> &s, bool invert) {
560  std::vector<T> ret;
561  casadi_assert(v.size()==s.size(), "Dimension mismatch.");
562  if (invert) {
563  for (casadi_int k=0;k<s.size();++k) {
564  if (!s[k]) ret.push_back(v[k]);
565  }
566  } else {
567  for (casadi_int k=0;k<s.size();++k) {
568  if (s[k]) ret.push_back(v[k]);
569  }
570  }
571  return ret;
572  }
573 
574  template<typename T>
575  std::vector<T> vector_tail(const std::vector<T> &v) {
576  std::vector<T> ret;
577  ret.insert(ret.begin(), v.begin()+1, v.end());
578  return ret;
579  }
580 
581  template<typename T>
582  std::vector<T> vector_init(const std::vector<T> &v) {
583  std::vector<T> ret;
584  ret.insert(ret.begin(), v.begin(), v.begin()+v.size()-1);
585  return ret;
586  }
587 
588  template<typename T>
589  std::vector<T> reverse(const std::vector<T> &v) {
590  std::vector<T> ret(v.size());
591  std::reverse_copy(v.begin(), v.end(), ret.begin());
592  return ret;
593  }
594 
595  template<typename T>
596  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b) {
597  std::vector<T> ret = a;
598  ret.insert(ret.end(), b.begin(), b.end());
599  return ret;
600  }
601 
602  template<typename T>
603  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c) {
604  std::vector<T> ret = a;
605  ret.insert(ret.end(), b.begin(), b.end());
606  ret.insert(ret.end(), c.begin(), c.end());
607  return ret;
608  }
609 
610  template<typename T>
611  std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order) {
612  casadi_assert_dev(order.size()==a.size());
613  casadi_assert_dev(is_permutation(order));
614  return vector_slice(a, order);
615  }
616 
617  template<typename T>
618  std::vector<casadi_int> find(const std::vector<T> &v) {
619  std::vector<casadi_int> ret;
620  for (casadi_int i=0;i<v.size();++i) {
621  if (v[i]) ret.push_back(i);
622  }
623  return ret;
624  }
625 
626 #ifndef SWIG
627  template<class T>
628  std::vector<T> applymap(T (*f)(const T&) , const std::vector<T>& comp) {
629  std::vector<T> ret(comp.size());
630  std::transform(comp.begin(), comp.end(), ret.begin(), f);
631  return ret;
632  }
633 
634  template<class T>
635  void applymap(void (*f)(T &), std::vector<T>& comp) {
636  std::for_each(comp.begin(), comp.end(), f);
637  }
638 
639  template<class S, class D>
640  void copy_vector(const std::vector<S>& s, std::vector<D>& d) {
641  casadi_assert(s.size()==d.size(), "Dimension mismatch.");
642  std::copy(s.begin(), s.end(), d.begin());
643  }
644 
645  template<class S, class D>
646  void assign_vector(const std::vector<S>& s, std::vector<D>& d) {
647  casadi_assert(d.empty(), "Receiving vector must be empty");
648  d.resize(s.size());
649  std::copy(s.begin(), s.end(), d.begin());
650  }
651 
652  template<class S, class D>
653  void copy_vector(const S* s, std::vector<D>& d) {
654  for (casadi_int i=0;i<d.size();++i) {
655  d[i] = static_cast<D>(s[i]);
656  }
657  }
658 
659  template<class S, class D>
660  void init_vector(std::vector<S>& d, const std::vector<D>& s) {
661  d.resize(s.size());
662  std::copy(s.begin(), s.end(), d.begin());
663  }
664 #endif //SWIG
665 
666  template<typename T>
667  bool in_range(const std::vector<T> &v, casadi_int upper) {
668  return in_range(v, 0, upper);
669  }
670 
671  template<typename T>
672  bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper) {
673  if (v.empty()) return true;
674  casadi_int max = *std::max_element(v.begin(), v.end());
675  if (max >= upper) return false;
676  casadi_int min = *std::min_element(v.begin(), v.end());
677  return (min >= lower);
678  }
679 
680  template<class T, class S>
681  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
682  std::vector<S>& flat) {
683  // Count total elements in nested
684  casadi_int N = 0;
685  for (const auto& e : nested) {
686  N += e.size();
687  }
688 
689  // Populate flat, one nested section at a time
690  flat.clear();
691  flat.reserve(N);
692  for (const auto& e : nested) {
693  flat.insert(flat.end(), e.begin(), e.end());
694  }
695  }
696 
697  template<class T, class S, class I>
698  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
699  std::vector<S>& flat,
700  std::vector<I>& indices) {
701  // Delegate
702  flatten_nested_vector(nested, flat);
703 
704  // Build up indices
705  casadi_int N = nested.size();
706  indices.resize(1, 0);
707  indices.reserve(N+1);
708  casadi_int offset = 0;
709  for (const auto& e : nested) {
710  offset += e.size();
711  indices.push_back(offset);
712  }
713  }
714 
715  template<typename T>
716  bool isUnique(const std::vector<T> &v) {
717  std::set<T> s(v.begin(), v.end());
718  return v.size()==s.size();
719  }
720 
721  template<typename T>
722  bool is_increasing(const std::vector<T> &v) {
723  if (v.empty()) return true;
724  T el = v[0];
725  for (casadi_int i=1;i<v.size();++i) {
726  if (!(v[i] > el)) return false;
727  el = v[i];
728  }
729  return el==el; // nan -> false
730  }
731 
732  template<typename T>
733  bool is_decreasing(const std::vector<T> &v) {
734  if (v.empty()) return true;
735  T el = v[0];
736  for (casadi_int i=1;i<v.size();++i) {
737  if (!(v[i] < el)) return false;
738  el = v[i];
739  }
740  return el==el; // nan -> false
741  }
742 
743  template<typename T>
744  bool is_nonincreasing(const std::vector<T> &v) {
745  if (v.empty()) return true;
746  T el = v[0];
747  for (casadi_int i=1;i<v.size();++i) {
748  if (!(v[i] <= el)) return false;
749  el = v[i];
750  }
751  return el==el; // nan -> false
752  }
753 
754  template<typename T>
755  bool is_nondecreasing(const std::vector<T> &v) {
756  if (v.empty()) return true;
757  T el = v[0];
758  for (casadi_int i=1;i<v.size();++i) {
759  if (!(v[i] >= el)) return false;
760  el = v[i];
761  }
762  return el==el; // nan -> false
763  }
764 
765  template<typename T>
766  bool is_monotone(const std::vector<T> &v) {
767  return is_nondecreasing(v) || is_nonincreasing(v);
768  }
769 
770  template<typename T>
771  bool is_strictly_monotone(const std::vector<T> &v) {
772  return is_decreasing(v) || is_increasing(v);
773  }
774 
775  template<typename T>
776  bool has_negative(const std::vector<T> &v) {
777  for (std::size_t i=0; i<v.size(); ++i) {
778  if (v[i]<0) return true;
779  }
780  return false;
781  }
782 
783  template<typename T>
784  void write_matlab(std::ostream &stream, const std::vector<T> &v) {
785  std::copy(v.begin(), v.end(), std::ostream_iterator<T>(stream, " "));
786  }
787 
788  template<typename T>
789  void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v) {
790  for (casadi_uint i=0; i<v.size(); ++i) {
791  std::copy(v[i].begin(), v[i].end(), std::ostream_iterator<T>(stream, " "));
792  stream << std::endl;
793  }
794  }
795 
796  template<typename T>
797  void read_matlab(std::istream &stream, std::vector<T> &v) {
798  v.clear();
799 
800  while (!stream.eof()) {
801  T val;
802  stream >> val;
803  if (stream.fail()) {
804  stream.clear();
805  std::string s;
806  stream >> s;
807  if (s=="inf")
808  val = std::numeric_limits<T>::infinity();
809  else
810  break;
811  }
812  v.push_back(val);
813  }
814  }
815 
816  template<typename T>
817  void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v) {
818  v.clear();
819  std::string line;
820  while (!getline(file, line, '\n').eof()) {
821  std::istringstream reader(line);
822  std::vector<T> lineData;
823 
824  while (!reader.eof()) {
825  T val;
826  reader >> val;
827  if (reader.fail()) {
828  reader.clear();
829  std::string s;
830  reader >> s;
831  if (s=="inf")
832  val = std::numeric_limits<T>::infinity();
833  else
834  break;
835  }
836  lineData.push_back(val);
837  }
838  v.push_back(lineData);
839  }
840  }
841 
842  template<typename T, typename F, typename L>
843  void linspace(std::vector<T> &v, const F& first, const L& last) {
844  if (v.size()<2)
845  throw CasadiException("std::linspace: vector must contain at least two elements");
846 
847  // Increment
848  T increment = (last-first)/T(v.size()-1);
849 
850  v[0] = first;
851  for (unsigned i=1; i<v.size()-1; ++i)
852  v[i] = v[i-1] + increment;
853  v[v.size()-1] = last;
854  }
855 
856  template<typename T>
857  T* get_ptr(std::vector<T> &v) {
858  if (v.empty())
859  return nullptr;
860  else
861  return &v.front();
862  }
863 
864  template<typename T>
865  const T* get_ptr(const std::vector<T> &v) {
866  if (v.empty())
867  return nullptr;
868  else
869  return &v.front();
870  }
871 
872  // Helper class
873  template<typename T>
874  struct sortCompare {
875  const std::vector<T> &v_;
876  sortCompare(const std::vector<T> &v) : v_(v) {}
877  bool operator() (casadi_int i, casadi_int j) const { return v_[i]<v_[j];}
878  };
879 
880  template<typename T>
881  void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
882  std::vector<casadi_int> &indices, bool invert_indices) {
883  // Call recursively if indices need to be inverted
884  if (invert_indices) {
885  std::vector<casadi_int> inverted;
886  sort(values, sorted_values, inverted, false);
887  indices.resize(inverted.size());
888  for (size_t i=0; i<inverted.size(); ++i) {
889  indices[inverted[i]] = i;
890  }
891  return;
892  }
893 
894  // Create list of indices
895  indices.resize(values.size());
896  for (size_t i=0; i<indices.size(); ++i) indices[i] = i;
897 
898  // Sort this list by the values
899  std::sort(indices.begin(), indices.end(), sortCompare<T>(values));
900 
901  // Sort the values accordingly
902  sorted_values.resize(values.size());
903  for (size_t i=0; i<values.size(); ++i) {
904  sorted_values[i] = values[indices[i]];
905  }
906  }
907 
908  template<typename T>
909  T product(const std::vector<T> &values) {
910  T r = 1;
911  for (casadi_int i=0;i<values.size();++i) r*=values[i];
912  return r;
913  }
914 
915  template<typename T>
916  T sum(const std::vector<T> &values) {
917  T r = 0;
918  for (casadi_int i=0;i<values.size();++i) r+=values[i];
919  return r;
920  }
921 
922  template<typename T>
923  std::vector<T> cumsum(const std::vector<T> &values) {
924  std::vector<T> ret(values.size());
925  T acc = 0;
926  for (casadi_int i=0;i<values.size();++i) {
927  acc+= values[i];
928  ret[i] = acc;
929  }
930  return ret;
931  }
932 
933  template<typename T>
934  std::vector<T> cumsum0(const std::vector<T> &values) {
935  std::vector<T> ret(values.size()+1, 0);
936  T acc = 0;
937  for (casadi_int i=0;i<values.size();++i) {
938  acc+= values[i];
939  ret[i+1] = acc;
940  }
941  return ret;
942  }
943 
944  template<typename T>
945  std::vector<T> diff(const std::vector<T> &values) {
946  casadi_assert(!values.empty(), "Array must be non-empty");
947  std::vector<T> ret(values.size()-1);
948  for (casadi_int i=0;i<values.size()-1;++i) {
949  ret[i] = values[i+1]-values[i];
950  }
951  return ret;
952  }
953 
954  template<typename T>
955  T dot(const std::vector<T>& a, const std::vector<T>& b) {
956  T ret = 0;
957  for (casadi_int k=0; k<a.size(); ++k) {
958  ret += a[k]*b[k];
959  }
960  return ret;
961  }
962 
963  template<typename T>
964  T norm_inf(const std::vector<T>& x) {
965  T ret = 0;
966  for (casadi_int k=0; k<x.size(); ++k) {
967  ret = fmax(ret, fabs(x[k]));
968  }
969  return ret;
970  }
971 
972  template<typename T>
973  T norm_1(const std::vector<T>& x) {
974  T ret = 0;
975  for (casadi_int k=0; k<x.size(); ++k) {
976  ret += fabs(x[k]);
977  }
978  return ret;
979  }
980 
981  template<typename T>
982  T norm_2(const std::vector<T>& x) {
983  T ret = 0;
984  for (casadi_int k=0; k<x.size(); ++k) {
985  ret += x[k]*x[k];
986  }
987  return sqrt(ret);
988  }
989 
990  template<typename T>
991  bvec_t* get_bvec_t(std::vector<T>& v) {
992  casadi_assert(0, "get_bvec_t only supported for double");
993  }
994 
995  template<typename T>
996  const bvec_t* get_bvec_t(const std::vector<T>& v) {
997  casadi_assert(0, "get_bvec_t only supported for double");
998  }
999 
1002  typedef std::vector<std::string> StringVector;
1004 
1005 } // namespace casadi
1006 #endif // SWIG
1007 
1008 #endif // CASADI_MISC_HPP
Casadi exception class.
Definition: exception.hpp:77
scoped_checkout(scoped_checkout &&that)
Definition: casadi_misc.hpp:50
scoped_checkout(const T &proto)
Definition: casadi_misc.hpp:46
scoped_checkout(const scoped_checkout &that)=delete
The casadi namespace.
Definition: archiver.cpp:28
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)
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:91
std::string temporary_file(const std::string &prefix, const std::string &suffix)
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:56
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 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 > tensor_permute_mapping(const std::vector< casadi_int > &dims, const std::vector< casadi_int > &order)
Computes a mapping for a (dense) tensor permutation.
std::vector< casadi_int > find(const std::vector< T > &v)
find nonzeros
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.
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.
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.
bool any(const std::vector< bool > &v)
Check if any arguments are true.
Definition: casadi_misc.cpp:84
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:77
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.
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)
void normalized_out(std::ostream &stream, double val)
std::vector< casadi_int > boolvec_to_index(const std::vector< bool > &v)
bool mul_overflows(const T &a, const T &b)
ostream & operator<<(ostream &stream, const vector< T > &v)
Enables flushing an std::vector to a stream (prints representation)
bool operator()(casadi_int i, casadi_int j) const
const std::vector< T > & v_
sortCompare(const std::vector< T > &v)