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>
45 class scoped_checkout {
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 
57  ~scoped_checkout() {
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 
90  CASADI_EXPORT std::string join(const std::vector<std::string>& l, const std::string& delim=",");
91 
93  CASADI_EXPORT bool startswith(const std::string& s, const std::string& p);
94 
96  CASADI_EXPORT std::string replace(const std::string& s,
97  const std::string& p, const std::string& r);
98 
100  CASADI_EXPORT bool version_gt(const std::string& version_left,
101  const std::string& version_right);
102 
104  CASADI_EXPORT bool version_ge(const std::string& version_left,
105  const std::string& version_right);
106 
108  CASADI_EXPORT bool version_lt(const std::string& version_left,
109  const std::string& version_right);
110 
112  CASADI_EXPORT bool version_le(const std::string& version_left,
113  const std::string& version_right);
114 
122  CASADI_EXPORT std::vector<casadi_int> range(casadi_int stop);
123 
125  CASADI_EXPORT bool all(const std::vector<bool> &v);
127  CASADI_EXPORT bool any(const std::vector<bool> &v);
129  CASADI_EXPORT std::vector<bool> boolvec_not(const std::vector<bool> &v);
131  CASADI_EXPORT std::vector<bool> boolvec_and(const std::vector<bool> &lhs,
132  const std::vector<bool> &rhs);
134  CASADI_EXPORT std::vector<bool> boolvec_or(const std::vector<bool> &lhs,
135  const std::vector<bool> &rhs);
136 
137  CASADI_EXPORT std::vector<casadi_int> boolvec_to_index(const std::vector<bool> &v);
138 
139  CASADI_EXPORT bool is_equally_spaced(const std::vector<double> &v);
140 
141  CASADI_EXPORT int to_int(casadi_int rhs);
142  CASADI_EXPORT std::vector<int> to_int(const std::vector<casadi_int>& rhs);
143  CASADI_EXPORT std::vector< std::vector<int> > to_int(
144  const std::vector< std::vector<casadi_int> >& rhs);
145 
146  template<typename T, typename S>
147  std::vector<T> vector_static_cast(const std::vector<S>& rhs);
148 
149  CASADI_EXPORT std::string str_bvec(bvec_t v);
150 
157  template<typename T>
158  std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i);
159 
166  template<typename T>
167  std::vector<T> vector_select(const std::vector<T> &v, const std::vector<bool> &s,
168  bool invert=false);
169 
173  template<typename T>
174  std::vector<T> vector_tail(const std::vector<T> &v);
175 
179  template<typename T>
180  std::vector<T> vector_init(const std::vector<T> &v);
181 
185  template<typename T>
186  std::vector<T> reverse(const std::vector<T> &v);
187 
191  template<typename T>
192  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b);
193 
197  template<typename T>
198  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c);
199 
203  bool is_permutation(const std::vector<casadi_int> &order);
204 
208  template<typename T>
209  std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order);
210 
214  std::vector<casadi_int> invert_permutation(const std::vector<casadi_int> &a);
215 
219  template<typename T>
220  std::vector<casadi_int> find(const std::vector<T> &v);
221 
222  #endif // SWIG
223 
225  template<typename T>
226  bool in_range(const std::vector<T> &v, casadi_int upper);
227 
229  template<typename T>
230  bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper);
231 
232  // Assert that a indices are in a range
233  #define casadi_assert_in_range(v, lower, upper) \
234  casadi_assert(in_range(v, lower, upper), \
235  "Out of bounds error. Got elements in range [" \
236  + str(*std::min_element(v.begin(), v.end())) + ","\
237  + str(*std::max_element(v.begin(), v.end())) + "], which is outside the range ["\
238  + str(lower) + "," + str(upper) + ").")
239 
240  // Assert that a indices are bounded
241  #define casadi_assert_bounded(v, upper) \
242  casadi_assert(in_range(v, upper), \
243  "Out of bounds error. Got elements in range [" \
244  + str(*std::min_element(v.begin(), v.end())) + ","\
245  + str(*std::max_element(v.begin(), v.end())) + "], which exceeds the upper bound "\
246  + str(upper) + ".")
247 
255  CASADI_EXPORT std::vector<casadi_int> complement(const std::vector<casadi_int> &v,
256  casadi_int size);
257 
266  CASADI_EXPORT std::vector<casadi_int> lookupvector(const std::vector<casadi_int> &v,
267  casadi_int size);
268  CASADI_EXPORT std::vector<casadi_int> lookupvector(const std::vector<casadi_int> &v);
269 
275  template<class T, class S>
276  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
277  std::vector<S>& flat);
278 
284  template<class T, class S, class I>
285  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
286  std::vector<S>& flat,
287  std::vector<I>& indices);
288 
290 #ifndef SWIG
294  template<class T>
295  std::vector<T> applymap(T (*f)(const T&), const std::vector<T>& comp);
296 
300  template<class T>
301  void applymap(void (*f)(T&), std::vector<T>& comp);
302 #endif // SWIG
304 
305 
307  template<typename T>
308  bool is_increasing(const std::vector<T> &v);
309 
311  template<typename T>
312  bool is_decreasing(const std::vector<T> &v);
313 
315  template<typename T>
316  bool is_nonincreasing(const std::vector<T> &v);
317 
319  template<typename T>
320  bool is_nondecreasing(const std::vector<T> &v);
321 
323  template<typename T>
324  bool is_monotone(const std::vector<T> &v);
325 
327  template<typename T>
328  bool is_strictly_monotone(const std::vector<T> &v);
329 
331  template<typename T>
332  bool has_negative(const std::vector<T> &v);
333 
335  template<typename T>
336  void write_matlab(std::ostream &stream, const std::vector<T> &v);
337 
339  template<typename T>
340  void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v);
341 
343  template<typename T>
344  void read_matlab(std::istream &stream, std::vector<T> &v);
345 
347  template<typename T>
348  void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v);
349 
350 #ifndef SWIG
352  template<typename T, typename F, typename L>
353  void linspace(std::vector<T> &v, const F& first, const L& last);
354 
357  CASADI_EXPORT bvec_t* get_bvec_t(std::vector<double>& v);
358 
360  CASADI_EXPORT const bvec_t* get_bvec_t(const std::vector<double>& v);
361 
363  CASADI_EXPORT bvec_t bvec_or(const bvec_t* arg, casadi_int n);
364 
366  template<typename T>
367  bvec_t* get_bvec_t(std::vector<T>& v);
368 
370  template<typename T>
371  const bvec_t* get_bvec_t(const std::vector<T>& v);
372 
374  template<typename T>
375  T* get_ptr(std::vector<T> &v);
376 
378  template<typename T>
379  const T* get_ptr(const std::vector<T> &v);
380 
382 
391  template<typename T>
392  void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
393  std::vector<casadi_int> &indices, bool invert_indices =false);
394 
398  template<typename T>
399  T product(const std::vector<T> &values);
400 
404  template<typename T>
405  T sum(const std::vector<T> &values);
406 
410  template<typename T>
411  std::vector<T> cumsum(const std::vector<T> &values);
412 
416  template<typename T>
417  std::vector<T> diff(const std::vector<T> &values);
418 
422  template<typename T>
423  std::vector<T> cumsum0(const std::vector<T> &values);
424 #endif //SWIG
425 
427  template<typename T>
428  bool is_regular(const std::vector<T> &v) {
429  for (auto&& vk : v) {
430  if (vk!=vk || vk==std::numeric_limits<T>::infinity() ||
431  vk==-std::numeric_limits<T>::infinity()) return false;
432  }
433  return true;
434  }
435 
436  // Create a temporary file
437  CASADI_EXPORT std::string temporary_file(const std::string& prefix,
438  const std::string& suffix,
439  const std::string& directory="");
440 
441  CASADI_EXPORT void normalized_setup(std::istream& stream);
442  CASADI_EXPORT void normalized_setup(std::ostream& stream);
443 
444 
445  class CASADI_EXPORT StreamStateGuard {
446  public:
447  explicit StreamStateGuard(std::ostream& os);
449 
450  private:
451  std::ostream& stream_;
452  std::ios::fmtflags flags_;
453  std::streamsize precision_;
454  std::streamsize width_;
455  std::locale locale_;
456  };
457 
458  inline void normalized_out(std::ostream& stream, double val) {
459  if (val==std::numeric_limits<double>::infinity()) {
460  stream << "inf";
461  } else if (val==-std::numeric_limits<double>::infinity()) {
462  stream << "-inf";
463  } else if (val!=val) {
464  stream << "nan";
465  } else {
466  stream << val;
467  }
468  }
469  inline int normalized_in(std::istream& stream, double& ret) {
470  std::streampos start = stream.tellg();
471  stream >> ret;
472  // Failed to interpret as double?
473  if (stream.fail()) {
474  // Clear error flag
475  stream.clear();
476  // Reset stream position
477  // Need to parse e.g "-inf"
478  stream.seekg(start);
479  // Might be a inf/nan
480  std::string non_reg;
481  stream >> non_reg;
482  // Break on trailing whitespace
483  if (stream.fail()) {
484  if (stream.eof()) {
485  ret = std::numeric_limits<double>::quiet_NaN();
486  return -1; // End of stream
487  } else {
488  ret = std::numeric_limits<double>::quiet_NaN();
489  return 1; // Failed to parse to string
490  }
491  }
492  if (non_reg=="inf") {
493  ret = std::numeric_limits<double>::infinity();
494  } else if (non_reg=="-inf") {
495  ret = -std::numeric_limits<double>::infinity();
496  } else if (non_reg=="nan" || non_reg=="-nan") {
497  ret = std::numeric_limits<double>::quiet_NaN();
498  } else {
499  ret = std::numeric_limits<double>::quiet_NaN();
500  return 2; // Failed to interpret as number
501  }
502  }
503  return 0;
504  }
505 
506 } // namespace casadi
507 
508 #ifndef SWIG
509 
510 // Implementations
511 namespace casadi {
512 
514  template<typename T>
515  std::ostream& operator<<(std::ostream& stream, const std::vector<T>& v) {
516  stream << casadi::str(v);
517  return stream;
518  }
519 
521  template<typename T, size_t N>
522  std::ostream& operator<<(std::ostream& stream, const std::array<T, N>& v) {
523  stream << casadi::str(v);
524  return stream;
525  }
526 
528  template<typename T>
529  std::ostream& operator<<(std::ostream& stream, const std::set<T>& v) {
530  stream << casadi::str(v);
531  return stream;
532  }
533 
534  template<typename T1, typename T2>
535  std::ostream& operator<<(std::ostream& stream, const std::pair<T1, T2>& p) {
536  stream << casadi::str(p);
537  return stream;
538  }
539 
540  template<typename T1, typename T2>
541  std::ostream& operator<<(std::ostream& stream, const std::map<T1, T2>& p) {
542  stream << casadi::str(p);
543  return stream;
544  }
545 
546  template<typename T2>
547  std::ostream& operator<<(std::ostream& stream, const std::map<std::string, T2>& p) {
548  stream << casadi::str(p);
549  return stream;
550  }
551 
552  template<typename T>
553  bool mul_overflows(const T& a, const T& b) {
554  if (a==0 || b==0) return false;
555  return std::abs(std::numeric_limits<T>::max()/a) < std::abs(b);
556  }
557 
558  template<typename T, typename S>
559  std::vector<T> vector_static_cast(const std::vector<S>& rhs) {
560  std::vector<T> ret;
561  ret.reserve(rhs.size());
562  for (auto e : rhs) ret.push_back(static_cast<T>(e));
563  return ret;
564  }
565 
566  template<typename T>
567  std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i) {
568  std::vector<T> ret;
569  ret.reserve(i.size());
570  for (casadi_int k=0;k<i.size();++k) {
571  casadi_int j = i[k];
572  casadi_assert(j>=0,
573  "vector_slice: Indices should be larger than zero."
574  "You have " + str(j) + " at location " + str(k) + ".");
575  casadi_assert(j<v.size(),
576  "vector_slice: Indices should be larger than zero."
577  "You have " + str(j) + " at location " + str(k) + ".");
578  ret.push_back(v[j]);
579  }
580  return ret;
581  }
582 
583  template<typename T>
584  std::vector<T> vector_select(const std::vector<T> &v, const std::vector<bool> &s, bool invert) {
585  std::vector<T> ret;
586  casadi_assert(v.size()==s.size(), "Dimension mismatch.");
587  if (invert) {
588  for (casadi_int k=0;k<s.size();++k) {
589  if (!s[k]) ret.push_back(v[k]);
590  }
591  } else {
592  for (casadi_int k=0;k<s.size();++k) {
593  if (s[k]) ret.push_back(v[k]);
594  }
595  }
596  return ret;
597  }
598 
599  template<typename T>
600  std::vector<T> vector_tail(const std::vector<T> &v) {
601  std::vector<T> ret;
602  ret.insert(ret.begin(), v.begin()+1, v.end());
603  return ret;
604  }
605 
606  template<typename T>
607  std::vector<T> vector_init(const std::vector<T> &v) {
608  std::vector<T> ret;
609  ret.insert(ret.begin(), v.begin(), v.begin()+v.size()-1);
610  return ret;
611  }
612 
613  template<typename T>
614  std::vector<T> reverse(const std::vector<T> &v) {
615  std::vector<T> ret(v.size());
616  std::reverse_copy(v.begin(), v.end(), ret.begin());
617  return ret;
618  }
619 
620  template<typename T>
621  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b) {
622  std::vector<T> ret = a;
623  ret.insert(ret.end(), b.begin(), b.end());
624  return ret;
625  }
626 
627  template<typename T>
628  std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c) {
629  std::vector<T> ret = a;
630  ret.insert(ret.end(), b.begin(), b.end());
631  ret.insert(ret.end(), c.begin(), c.end());
632  return ret;
633  }
634 
635  template<typename T>
636  std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order) {
637  casadi_assert_dev(order.size()==a.size());
638  casadi_assert_dev(is_permutation(order));
639  return vector_slice(a, order);
640  }
641 
642  template<typename T>
643  std::vector<casadi_int> find(const std::vector<T> &v) {
644  std::vector<casadi_int> ret;
645  for (casadi_int i=0;i<v.size();++i) {
646  if (v[i]) ret.push_back(i);
647  }
648  return ret;
649  }
650 
651 #ifndef SWIG
652  template<class T>
653  std::vector<T> applymap(T (*f)(const T&) , const std::vector<T>& comp) {
654  std::vector<T> ret(comp.size());
655  std::transform(comp.begin(), comp.end(), ret.begin(), f);
656  return ret;
657  }
658 
659  template<class T>
660  void applymap(void (*f)(T &), std::vector<T>& comp) {
661  std::for_each(comp.begin(), comp.end(), f);
662  }
663 
664  template<class S, class D>
665  void copy_vector(const std::vector<S>& s, std::vector<D>& d) {
666  casadi_assert(s.size()==d.size(), "Dimension mismatch.");
667  std::copy(s.begin(), s.end(), d.begin());
668  }
669 
670  template<class S, class D>
671  void assign_vector(const std::vector<S>& s, std::vector<D>& d) {
672  casadi_assert(d.empty(), "Receiving vector must be empty");
673  d.resize(s.size());
674  std::copy(s.begin(), s.end(), d.begin());
675  }
676 
677  template<class S, class D>
678  void copy_vector(const S* s, std::vector<D>& d) {
679  for (casadi_int i=0;i<d.size();++i) {
680  d[i] = static_cast<D>(s[i]);
681  }
682  }
683 
684  template<class S, class D>
685  void init_vector(std::vector<S>& d, const std::vector<D>& s) {
686  d.resize(s.size());
687  std::copy(s.begin(), s.end(), d.begin());
688  }
689 #endif //SWIG
690 
691  template<typename T>
692  bool in_range(const std::vector<T> &v, casadi_int upper) {
693  return in_range(v, 0, upper);
694  }
695 
696  template<typename T>
697  bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper) {
698  if (v.empty()) return true;
699  casadi_int max = *std::max_element(v.begin(), v.end());
700  if (max >= upper) return false;
701  casadi_int min = *std::min_element(v.begin(), v.end());
702  return (min >= lower);
703  }
704 
705  template<class T, class S>
706  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
707  std::vector<S>& flat) {
708  // Count total elements in nested
709  casadi_int N = 0;
710  for (const auto& e : nested) {
711  N += e.size();
712  }
713 
714  // Populate flat, one nested section at a time
715  flat.clear();
716  flat.reserve(N);
717  for (const auto& e : nested) {
718  flat.insert(flat.end(), e.begin(), e.end());
719  }
720  }
721 
722  template<class T, class S, class I>
723  void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
724  std::vector<S>& flat,
725  std::vector<I>& indices) {
726  // Delegate
727  flatten_nested_vector(nested, flat);
728 
729  // Build up indices
730  casadi_int N = nested.size();
731  indices.resize(1, 0);
732  indices.reserve(N+1);
733  casadi_int offset = 0;
734  for (const auto& e : nested) {
735  offset += e.size();
736  indices.push_back(offset);
737  }
738  }
739 
740  template<typename T>
741  bool isUnique(const std::vector<T> &v) {
742  std::set<T> s(v.begin(), v.end());
743  return v.size()==s.size();
744  }
745 
746  template<typename T>
747  bool is_increasing(const std::vector<T> &v) {
748  if (v.empty()) return true;
749  T el = v[0];
750  for (casadi_int i=1;i<v.size();++i) {
751  if (!(v[i] > el)) return false;
752  el = v[i];
753  }
754  return el==el; // nan -> false
755  }
756 
757  template<typename T>
758  bool is_decreasing(const std::vector<T> &v) {
759  if (v.empty()) return true;
760  T el = v[0];
761  for (casadi_int i=1;i<v.size();++i) {
762  if (!(v[i] < el)) return false;
763  el = v[i];
764  }
765  return el==el; // nan -> false
766  }
767 
768  template<typename T>
769  bool is_nonincreasing(const std::vector<T> &v) {
770  if (v.empty()) return true;
771  T el = v[0];
772  for (casadi_int i=1;i<v.size();++i) {
773  if (!(v[i] <= el)) return false;
774  el = v[i];
775  }
776  return el==el; // nan -> false
777  }
778 
779  template<typename T>
780  bool is_nondecreasing(const std::vector<T> &v) {
781  if (v.empty()) return true;
782  T el = v[0];
783  for (casadi_int i=1;i<v.size();++i) {
784  if (!(v[i] >= el)) return false;
785  el = v[i];
786  }
787  return el==el; // nan -> false
788  }
789 
790  template<typename T>
791  bool is_monotone(const std::vector<T> &v) {
792  return is_nondecreasing(v) || is_nonincreasing(v);
793  }
794 
795  template<typename T>
796  bool is_strictly_monotone(const std::vector<T> &v) {
797  return is_decreasing(v) || is_increasing(v);
798  }
799 
800  template<typename T>
801  bool has_negative(const std::vector<T> &v) {
802  for (std::size_t i=0; i<v.size(); ++i) {
803  if (v[i]<0) return true;
804  }
805  return false;
806  }
807 
808  template<typename T>
809  void write_matlab(std::ostream &stream, const std::vector<T> &v) {
810  std::copy(v.begin(), v.end(), std::ostream_iterator<T>(stream, " "));
811  }
812 
813  template<typename T>
814  void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v) {
815  for (casadi_uint i=0; i<v.size(); ++i) {
816  std::copy(v[i].begin(), v[i].end(), std::ostream_iterator<T>(stream, " "));
817  stream << std::endl;
818  }
819  }
820 
821  template<typename T>
822  void read_matlab(std::istream &stream, std::vector<T> &v) {
823  v.clear();
824 
825  while (!stream.eof()) {
826  T val;
827  stream >> val;
828  if (stream.fail()) {
829  stream.clear();
830  std::string s;
831  stream >> s;
832  if (s=="inf")
833  val = std::numeric_limits<T>::infinity();
834  else
835  break;
836  }
837  v.push_back(val);
838  }
839  }
840 
841  template<typename T>
842  void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v) {
843  v.clear();
844  std::string line;
845  while (!getline(file, line, '\n').eof()) {
846  std::istringstream reader(line);
847  std::vector<T> lineData;
848 
849  while (!reader.eof()) {
850  T val;
851  reader >> val;
852  if (reader.fail()) {
853  reader.clear();
854  std::string s;
855  reader >> s;
856  if (s=="inf")
857  val = std::numeric_limits<T>::infinity();
858  else
859  break;
860  }
861  lineData.push_back(val);
862  }
863  v.push_back(lineData);
864  }
865  }
866 
867  template<typename T, typename F, typename L>
868  void linspace(std::vector<T> &v, const F& first, const L& last) {
869  if (v.size()<2)
870  throw CasadiException("std::linspace: vector must contain at least two elements");
871 
872  // Increment
873  T increment = (last-first)/T(v.size()-1);
874 
875  v[0] = first;
876  for (unsigned i=1; i<v.size()-1; ++i)
877  v[i] = v[i-1] + increment;
878  v[v.size()-1] = last;
879  }
880 
881  template<typename T>
882  T* get_ptr(std::vector<T> &v) {
883  if (v.empty())
884  return nullptr;
885  else
886  return &v.front();
887  }
888 
889  template<typename T>
890  const T* get_ptr(const std::vector<T> &v) {
891  if (v.empty())
892  return nullptr;
893  else
894  return &v.front();
895  }
896 
897  // Helper class
898  template<typename T>
899  struct sortCompare {
900  const std::vector<T> &v_;
901  sortCompare(const std::vector<T> &v) : v_(v) {}
902  bool operator() (casadi_int i, casadi_int j) const { return v_[i]<v_[j];}
903  };
904 
905  template<typename T>
906  void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
907  std::vector<casadi_int> &indices, bool invert_indices) {
908  // Call recursively if indices need to be inverted
909  if (invert_indices) {
910  std::vector<casadi_int> inverted;
911  sort(values, sorted_values, inverted, false);
912  indices.resize(inverted.size());
913  for (size_t i=0; i<inverted.size(); ++i) {
914  indices[inverted[i]] = i;
915  }
916  return;
917  }
918 
919  // Create list of indices
920  indices.resize(values.size());
921  for (size_t i=0; i<indices.size(); ++i) indices[i] = i;
922 
923  // Sort this list by the values
924  std::sort(indices.begin(), indices.end(), sortCompare<T>(values));
925 
926  // Sort the values accordingly
927  sorted_values.resize(values.size());
928  for (size_t i=0; i<values.size(); ++i) {
929  sorted_values[i] = values[indices[i]];
930  }
931  }
932 
933  template<typename T>
934  T product(const std::vector<T> &values) {
935  T r = 1;
936  for (casadi_int i=0;i<values.size();++i) r*=values[i];
937  return r;
938  }
939 
940  template<typename T>
941  T sum(const std::vector<T> &values) {
942  T r = 0;
943  for (casadi_int i=0;i<values.size();++i) r+=values[i];
944  return r;
945  }
946 
947  template<typename T>
948  std::vector<T> cumsum(const std::vector<T> &values) {
949  std::vector<T> ret(values.size());
950  T acc = 0;
951  for (casadi_int i=0;i<values.size();++i) {
952  acc+= values[i];
953  ret[i] = acc;
954  }
955  return ret;
956  }
957 
958  template<typename T>
959  std::vector<T> cumsum0(const std::vector<T> &values) {
960  std::vector<T> ret(values.size()+1, 0);
961  T acc = 0;
962  for (casadi_int i=0;i<values.size();++i) {
963  acc+= values[i];
964  ret[i+1] = acc;
965  }
966  return ret;
967  }
968 
969  template<typename T>
970  std::vector<T> diff(const std::vector<T> &values) {
971  casadi_assert(!values.empty(), "Array must be non-empty");
972  std::vector<T> ret(values.size()-1);
973  for (casadi_int i=0;i<values.size()-1;++i) {
974  ret[i] = values[i+1]-values[i];
975  }
976  return ret;
977  }
978 
979  template<typename T>
980  T dot(const std::vector<T>& a, const std::vector<T>& b) {
981  T ret = 0;
982  for (casadi_int k=0; k<a.size(); ++k) {
983  ret += a[k]*b[k];
984  }
985  return ret;
986  }
987 
988  template<typename T>
989  T norm_inf(const std::vector<T>& x) {
990  T ret = 0;
991  for (casadi_int k=0; k<x.size(); ++k) {
992  ret = fmax(ret, fabs(x[k]));
993  }
994  return ret;
995  }
996 
997  template<typename T>
998  T norm_1(const std::vector<T>& x) {
999  T ret = 0;
1000  for (casadi_int k=0; k<x.size(); ++k) {
1001  ret += fabs(x[k]);
1002  }
1003  return ret;
1004  }
1005 
1006  template<typename T>
1007  T norm_2(const std::vector<T>& x) {
1008  T ret = 0;
1009  for (casadi_int k=0; k<x.size(); ++k) {
1010  ret += x[k]*x[k];
1011  }
1012  return sqrt(ret);
1013  }
1014 
1015  template<typename T>
1016  bvec_t* get_bvec_t(std::vector<T>& v) {
1017  casadi_assert(0, "get_bvec_t only supported for double");
1018  }
1019 
1020  template<typename T>
1021  const bvec_t* get_bvec_t(const std::vector<T>& v) {
1022  casadi_assert(0, "get_bvec_t only supported for double");
1023  }
1024 
1027  typedef std::vector<std::string> StringVector;
1029 
1033  template<typename T>
1034  inline size_t hash_value(T v) { return size_t(v);}
1035 
1039  template<typename T>
1040  inline void hash_combine(std::size_t& seed, T v) {
1041  seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1042  }
1043 
1047  template<typename T>
1048  inline void hash_combine(std::size_t& seed, const T* v, std::size_t sz) {
1049  for (casadi_int i=0; i<sz; ++i) hash_combine(seed, v[i]);
1050  }
1051 
1055  template<typename T>
1056  inline void hash_combine(std::size_t& seed, const std::vector<T>& v) {
1057  hash_combine(seed, get_ptr(v), v.size());
1058  }
1059 
1060  template<>
1061  inline size_t hash_value(std::string v) {
1062  size_t seed = 0;
1063  hash_combine(seed, v.c_str(), v.size());
1064  return seed;
1065  }
1066 
1070  template<>
1071  inline size_t hash_value(double v) {
1072  std::uint64_t u;
1073  std::memcpy(&u, &v, sizeof(double));
1074 
1075  if (sizeof(size_t) == 8) {
1076  // 64-bit: keep all bits
1077  return static_cast<size_t>(u);
1078  } else {
1079  // 32-bit: fold with hash_combine
1080  size_t seed = 0;
1081  hash_combine(seed, static_cast<std::uint32_t>(u));
1082  hash_combine(seed, static_cast<std::uint32_t>(u >> 32));
1083  return seed;
1084  }
1085  }
1086 
1087 } // namespace casadi
1088 #endif // SWIG
1089 
1090 #endif // CASADI_MISC_HPP
StreamStateGuard(std::ostream &os)
The casadi namespace.
Definition: archiver.hpp:32
bool is_decreasing(const std::vector< T > &v)
Check if the vector is strictly decreasing.
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)
CASADI_EXPORT std::string temporary_file(const std::string &prefix, const std::string &suffix, const std::string &directory="")