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>
44 class scoped_checkout {
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 
56  ~scoped_checkout() {
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>
492  ostream& operator<<(ostream& stream, const set<T>& v) {
493  stream << casadi::str(v);
494  return stream;
495  }
496 
497  template<typename T1, typename T2>
498  ostream& operator<<(ostream& stream, const pair<T1, T2>& p) {
499  stream << casadi::str(p);
500  return stream;
501  }
502 
503  template<typename T1, typename T2>
504  ostream& operator<<(ostream& stream, const std::map<T1, T2>& p) {
505  stream << casadi::str(p);
506  return stream;
507  }
508 
509  template<typename T2>
510  ostream& operator<<(ostream& stream, const std::map<std::string, T2>& p) {
511  stream << casadi::str(p);
512  return stream;
513  }
514 
515  template<typename T>
516  bool mul_overflows(const T& a, const T& b) {
517  if (a==0 || b==0) return false;
518  return abs(std::numeric_limits<T>::max()/a) < abs(b);
519  }
520 
521 } // namespace std
522 
523 // Implementations
524 namespace casadi {
525 
526  template<typename T, typename S>
527  std::vector<T> vector_static_cast(const std::vector<S>& rhs) {
528  std::vector<T> ret;
529  ret.reserve(rhs.size());
530  for (auto e : rhs) ret.push_back(static_cast<T>(e));
531  return ret;
532  }
533 
534  template<typename T>
535  std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i) {
536  std::vector<T> ret;
537  ret.reserve(i.size());
538  for (casadi_int k=0;k<i.size();++k) {
539  casadi_int j = i[k];
540  casadi_assert(j>=0,
541  "vector_slice: Indices should be larger than zero."
542  "You have " + str(j) + " at location " + str(k) + ".");
543  casadi_assert(j<v.size(),
544  "vector_slice: Indices should be larger than zero."
545  "You have " + str(j) + " at location " + str(k) + ".");
546  ret.push_back(v[j]);
547  }
548  return ret;
549  }
550 
551  template<typename T>
552  std::vector<T> vector_select(const std::vector<T> &v, const std::vector<bool> &s, bool invert) {
553  std::vector<T> ret;
554  casadi_assert(v.size()==s.size(), "Dimension mismatch.");
555  if (invert) {
556  for (casadi_int k=0;k<s.size();++k) {
557  if (!s[k]) ret.push_back(v[k]);
558  }
559  } else {
560  for (casadi_int k=0;k<s.size();++k) {
561  if (s[k]) ret.push_back(v[k]);
562  }
563  }
564  return ret;
565  }
566 
567  template<typename T>
568  std::vector<T> vector_tail(const std::vector<T> &v) {
569  std::vector<T> ret;
570  ret.insert(ret.begin(), v.begin()+1, v.end());
571  return ret;
572  }
573 
574  template<typename T>
575  std::vector<T> vector_init(const std::vector<T> &v) {
576  std::vector<T> ret;
577  ret.insert(ret.begin(), v.begin(), v.begin()+v.size()-1);
578  return ret;
579  }
580 
581  template<typename T>
582  std::vector<T> reverse(const std::vector<T> &v) {
583  std::vector<T> ret(v.size());
584  std::reverse_copy(v.begin(), v.end(), ret.begin());
585  return ret;
586  }
587 
588  template<typename T>
589  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b) {
590  std::vector<T> ret = a;
591  ret.insert(ret.end(), b.begin(), b.end());
592  return ret;
593  }
594 
595  template<typename T>
596  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c) {
597  std::vector<T> ret = a;
598  ret.insert(ret.end(), b.begin(), b.end());
599  ret.insert(ret.end(), c.begin(), c.end());
600  return ret;
601  }
602 
603  template<typename T>
604  std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order) {
605  casadi_assert_dev(order.size()==a.size());
606  casadi_assert_dev(is_permutation(order));
607  return vector_slice(a, order);
608  }
609 
610  template<typename T>
611  std::vector<casadi_int> find(const std::vector<T> &v) {
612  std::vector<casadi_int> ret;
613  for (casadi_int i=0;i<v.size();++i) {
614  if (v[i]) ret.push_back(i);
615  }
616  return ret;
617  }
618 
619 #ifndef SWIG
620  template<class T>
621  std::vector<T> applymap(T (*f)(const T&) , const std::vector<T>& comp) {
622  std::vector<T> ret(comp.size());
623  std::transform(comp.begin(), comp.end(), ret.begin(), f);
624  return ret;
625  }
626 
627  template<class T>
628  void applymap(void (*f)(T &), std::vector<T>& comp) {
629  std::for_each(comp.begin(), comp.end(), f);
630  }
631 
632  template<class S, class D>
633  void copy_vector(const std::vector<S>& s, std::vector<D>& d) {
634  casadi_assert(s.size()==d.size(), "Dimension mismatch.");
635  std::copy(s.begin(), s.end(), d.begin());
636  }
637 
638  template<class S, class D>
639  void assign_vector(const std::vector<S>& s, std::vector<D>& d) {
640  casadi_assert(d.empty(), "Receiving vector must be empty");
641  d.resize(s.size());
642  std::copy(s.begin(), s.end(), d.begin());
643  }
644 
645  template<class S, class D>
646  void copy_vector(const S* s, std::vector<D>& d) {
647  for (casadi_int i=0;i<d.size();++i) {
648  d[i] = static_cast<D>(s[i]);
649  }
650  }
651 
652  template<class S, class D>
653  void init_vector(std::vector<S>& d, const std::vector<D>& s) {
654  d.resize(s.size());
655  std::copy(s.begin(), s.end(), d.begin());
656  }
657 #endif //SWIG
658 
659  template<typename T>
660  bool in_range(const std::vector<T> &v, casadi_int upper) {
661  return in_range(v, 0, upper);
662  }
663 
664  template<typename T>
665  bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper) {
666  if (v.empty()) return true;
667  casadi_int max = *std::max_element(v.begin(), v.end());
668  if (max >= upper) return false;
669  casadi_int min = *std::min_element(v.begin(), v.end());
670  return (min >= lower);
671  }
672 
673  template<class T, class S>
674  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
675  std::vector<S>& flat) {
676  // Count total elements in nested
677  casadi_int N = 0;
678  for (const auto& e : nested) {
679  N += e.size();
680  }
681 
682  // Populate flat, one nested section at a time
683  flat.clear();
684  flat.reserve(N);
685  for (const auto& e : nested) {
686  flat.insert(flat.end(), e.begin(), e.end());
687  }
688  }
689 
690  template<class T, class S, class I>
691  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
692  std::vector<S>& flat,
693  std::vector<I>& indices) {
694  // Delegate
695  flatten_nested_vector(nested, flat);
696 
697  // Build up indices
698  casadi_int N = nested.size();
699  indices.resize(1, 0);
700  indices.reserve(N+1);
701  casadi_int offset = 0;
702  for (const auto& e : nested) {
703  offset += e.size();
704  indices.push_back(offset);
705  }
706  }
707 
708  template<typename T>
709  bool isUnique(const std::vector<T> &v) {
710  std::set<T> s(v.begin(), v.end());
711  return v.size()==s.size();
712  }
713 
714  template<typename T>
715  bool is_increasing(const std::vector<T> &v) {
716  if (v.empty()) return true;
717  T el = v[0];
718  for (casadi_int i=1;i<v.size();++i) {
719  if (!(v[i] > el)) return false;
720  el = v[i];
721  }
722  return el==el; // nan -> false
723  }
724 
725  template<typename T>
726  bool is_decreasing(const std::vector<T> &v) {
727  if (v.empty()) return true;
728  T el = v[0];
729  for (casadi_int i=1;i<v.size();++i) {
730  if (!(v[i] < el)) return false;
731  el = v[i];
732  }
733  return el==el; // nan -> false
734  }
735 
736  template<typename T>
737  bool is_nonincreasing(const std::vector<T> &v) {
738  if (v.empty()) return true;
739  T el = v[0];
740  for (casadi_int i=1;i<v.size();++i) {
741  if (!(v[i] <= el)) return false;
742  el = v[i];
743  }
744  return el==el; // nan -> false
745  }
746 
747  template<typename T>
748  bool is_nondecreasing(const std::vector<T> &v) {
749  if (v.empty()) return true;
750  T el = v[0];
751  for (casadi_int i=1;i<v.size();++i) {
752  if (!(v[i] >= el)) return false;
753  el = v[i];
754  }
755  return el==el; // nan -> false
756  }
757 
758  template<typename T>
759  bool is_monotone(const std::vector<T> &v) {
760  return is_nondecreasing(v) || is_nonincreasing(v);
761  }
762 
763  template<typename T>
764  bool is_strictly_monotone(const std::vector<T> &v) {
765  return is_decreasing(v) || is_increasing(v);
766  }
767 
768  template<typename T>
769  bool has_negative(const std::vector<T> &v) {
770  for (std::size_t i=0; i<v.size(); ++i) {
771  if (v[i]<0) return true;
772  }
773  return false;
774  }
775 
776  template<typename T>
777  void write_matlab(std::ostream &stream, const std::vector<T> &v) {
778  std::copy(v.begin(), v.end(), std::ostream_iterator<T>(stream, " "));
779  }
780 
781  template<typename T>
782  void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v) {
783  for (casadi_uint i=0; i<v.size(); ++i) {
784  std::copy(v[i].begin(), v[i].end(), std::ostream_iterator<T>(stream, " "));
785  stream << std::endl;
786  }
787  }
788 
789  template<typename T>
790  void read_matlab(std::istream &stream, std::vector<T> &v) {
791  v.clear();
792 
793  while (!stream.eof()) {
794  T val;
795  stream >> val;
796  if (stream.fail()) {
797  stream.clear();
798  std::string s;
799  stream >> s;
800  if (s=="inf")
801  val = std::numeric_limits<T>::infinity();
802  else
803  break;
804  }
805  v.push_back(val);
806  }
807  }
808 
809  template<typename T>
810  void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v) {
811  v.clear();
812  std::string line;
813  while (!getline(file, line, '\n').eof()) {
814  std::istringstream reader(line);
815  std::vector<T> lineData;
816 
817  while (!reader.eof()) {
818  T val;
819  reader >> val;
820  if (reader.fail()) {
821  reader.clear();
822  std::string s;
823  reader >> s;
824  if (s=="inf")
825  val = std::numeric_limits<T>::infinity();
826  else
827  break;
828  }
829  lineData.push_back(val);
830  }
831  v.push_back(lineData);
832  }
833  }
834 
835  template<typename T, typename F, typename L>
836  void linspace(std::vector<T> &v, const F& first, const L& last) {
837  if (v.size()<2)
838  throw CasadiException("std::linspace: vector must contain at least two elements");
839 
840  // Increment
841  T increment = (last-first)/T(v.size()-1);
842 
843  v[0] = first;
844  for (unsigned i=1; i<v.size()-1; ++i)
845  v[i] = v[i-1] + increment;
846  v[v.size()-1] = last;
847  }
848 
849  template<typename T>
850  T* get_ptr(std::vector<T> &v) {
851  if (v.empty())
852  return nullptr;
853  else
854  return &v.front();
855  }
856 
857  template<typename T>
858  const T* get_ptr(const std::vector<T> &v) {
859  if (v.empty())
860  return nullptr;
861  else
862  return &v.front();
863  }
864 
865  // Helper class
866  template<typename T>
867  struct sortCompare {
868  const std::vector<T> &v_;
869  sortCompare(const std::vector<T> &v) : v_(v) {}
870  bool operator() (casadi_int i, casadi_int j) const { return v_[i]<v_[j];}
871  };
872 
873  template<typename T>
874  void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
875  std::vector<casadi_int> &indices, bool invert_indices) {
876  // Call recursively if indices need to be inverted
877  if (invert_indices) {
878  std::vector<casadi_int> inverted;
879  sort(values, sorted_values, inverted, false);
880  indices.resize(inverted.size());
881  for (size_t i=0; i<inverted.size(); ++i) {
882  indices[inverted[i]] = i;
883  }
884  return;
885  }
886 
887  // Create list of indices
888  indices.resize(values.size());
889  for (size_t i=0; i<indices.size(); ++i) indices[i] = i;
890 
891  // Sort this list by the values
892  std::sort(indices.begin(), indices.end(), sortCompare<T>(values));
893 
894  // Sort the values accordingly
895  sorted_values.resize(values.size());
896  for (size_t i=0; i<values.size(); ++i) {
897  sorted_values[i] = values[indices[i]];
898  }
899  }
900 
901  template<typename T>
902  T product(const std::vector<T> &values) {
903  T r = 1;
904  for (casadi_int i=0;i<values.size();++i) r*=values[i];
905  return r;
906  }
907 
908  template<typename T>
909  T sum(const std::vector<T> &values) {
910  T r = 0;
911  for (casadi_int i=0;i<values.size();++i) r+=values[i];
912  return r;
913  }
914 
915  template<typename T>
916  std::vector<T> cumsum(const std::vector<T> &values) {
917  std::vector<T> ret(values.size());
918  T acc = 0;
919  for (casadi_int i=0;i<values.size();++i) {
920  acc+= values[i];
921  ret[i] = acc;
922  }
923  return ret;
924  }
925 
926  template<typename T>
927  std::vector<T> cumsum0(const std::vector<T> &values) {
928  std::vector<T> ret(values.size()+1, 0);
929  T acc = 0;
930  for (casadi_int i=0;i<values.size();++i) {
931  acc+= values[i];
932  ret[i+1] = acc;
933  }
934  return ret;
935  }
936 
937  template<typename T>
938  std::vector<T> diff(const std::vector<T> &values) {
939  casadi_assert(!values.empty(), "Array must be non-empty");
940  std::vector<T> ret(values.size()-1);
941  for (casadi_int i=0;i<values.size()-1;++i) {
942  ret[i] = values[i+1]-values[i];
943  }
944  return ret;
945  }
946 
947  template<typename T>
948  T dot(const std::vector<T>& a, const std::vector<T>& b) {
949  T ret = 0;
950  for (casadi_int k=0; k<a.size(); ++k) {
951  ret += a[k]*b[k];
952  }
953  return ret;
954  }
955 
956  template<typename T>
957  T norm_inf(const std::vector<T>& x) {
958  T ret = 0;
959  for (casadi_int k=0; k<x.size(); ++k) {
960  ret = fmax(ret, fabs(x[k]));
961  }
962  return ret;
963  }
964 
965  template<typename T>
966  T norm_1(const std::vector<T>& x) {
967  T ret = 0;
968  for (casadi_int k=0; k<x.size(); ++k) {
969  ret += fabs(x[k]);
970  }
971  return ret;
972  }
973 
974  template<typename T>
975  T norm_2(const std::vector<T>& x) {
976  T ret = 0;
977  for (casadi_int k=0; k<x.size(); ++k) {
978  ret += x[k]*x[k];
979  }
980  return sqrt(ret);
981  }
982 
983  template<typename T>
984  bvec_t* get_bvec_t(std::vector<T>& v) {
985  casadi_assert(0, "get_bvec_t only supported for double");
986  }
987 
988  template<typename T>
989  const bvec_t* get_bvec_t(const std::vector<T>& v) {
990  casadi_assert(0, "get_bvec_t only supported for double");
991  }
992 
995  typedef std::vector<std::string> StringVector;
997 
998 } // namespace casadi
999 #endif // SWIG
1000 
1001 #endif // CASADI_MISC_HPP
The casadi namespace.
bool is_decreasing(const std::vector< T > &v)
Check if the vector is strictly decreasing.
CASADI_EXPORT std::string temporary_file(const std::string &prefix, const std::string &suffix)
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 is_increasing(const std::vector< T > &v)
Check if the vector is strictly increasing.
bool is_monotone(const std::vector< T > &v)
Check if the vector is monotone.
void write_matlab(std::ostream &stream, const std::vector< T > &v)
Print vector, matlab style.
CASADI_EXPORT void normalized_setup(std::istream &stream)
void read_matlab(std::istream &stream, std::vector< T > &v)
Read vector, matlab style.
bool is_strictly_monotone(const std::vector< T > &v)
Check if the vector is strictly monotone.
CASADI_EXPORT 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.
bool in_range(const std::vector< T > &v, casadi_int upper)
Check if for each element of v holds: v_i < upper.
bool is_nonincreasing(const std::vector< T > &v)
Check if the vector is non-increasing.
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.
int normalized_in(std::istream &stream, double &ret)
CASADI_EXPORT 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 normalized_out(std::ostream &stream, double val)