1 /*
2  *    This file is part of CasADi.
3  *
4  *    CasADi -- A symbolic framework for dynamic optimization.
5  *    Copyright (C) 2010-2014 Joel Andersson, Joris Gillis, Moritz Diehl,
6  *                            K.U. 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 
32 /** \brief Convenience tools for C++ Standard Library vectors
33     \author Joel Andersson
34     \date 2010-2011
35 */
36 
37 namespace casadi {
38 
39 #ifndef SWIG
40 
41 template<typename T>
42 class scoped_checkout {
43 public:
scoped_checkout(const T & proto)44   scoped_checkout(const T& proto) : proto_(proto) {
45     mem = proto_.checkout();
46   }
47 
scoped_checkout(scoped_checkout && that)48   scoped_checkout(scoped_checkout&& that) : mem(that.mem), proto_(that.proto_) {
49     that.mem = -1;
50   }
51 
52   scoped_checkout(const scoped_checkout& that) = delete;
53 
~scoped_checkout()54   ~scoped_checkout() {
55     if (mem!=-1) proto_.release(mem);
56   }
57 
operator casadi_int() const58   operator casadi_int() const {
59     return mem;
60   }
61 
62 private:
63   int mem;
64   const T& proto_;
65 };
66 
67   /**  \brief Range function
68   * \param start
69   * \param stop
70   * \param step
71   * \param len
72   *
73   * Consider a infinitely long list [start, start+step, start+2*step, ...]
74   * Elements larger than or equal to stop are chopped off.
75   *
76   */
77   CASADI_EXPORT std::vector<casadi_int> range(casadi_int start, casadi_int stop, casadi_int step=1,
78                                             casadi_int len=std::numeric_limits<casadi_int>::max());
79 
80   /** \brief Check if a vector matches a range
81    *
82    */
83   CASADI_EXPORT bool is_range(const std::vector<casadi_int>& v,
84     casadi_int start, casadi_int stop, casadi_int step=1);
85 
86   CASADI_EXPORT std::string join(const std::vector<std::string>& l, const std::string& delim=",");
87 
88   /// Checsks if s starts with p
89   CASADI_EXPORT bool startswith(const std::string& s, const std::string& p);
90   /**  \brief Range function
91   * \param stop
92   *
93   * \return list [0, 1, 2...stop-1]
94   */
95   CASADI_EXPORT std::vector<casadi_int> range(casadi_int stop);
96 
97   /// Check if all arguments are true
98   CASADI_EXPORT bool all(const std::vector<bool> &v);
99   /// Check if any arguments are true
100   CASADI_EXPORT bool any(const std::vector<bool> &v);
101   /// Invert all entries
102   CASADI_EXPORT std::vector<bool> boolvec_not(const std::vector<bool> &v);
103   /// And operation on boolean vector
104   CASADI_EXPORT std::vector<bool> boolvec_and(const std::vector<bool> &lhs,
105       const std::vector<bool> &rhs);
106   /// Or operation on boolean vector
107   CASADI_EXPORT std::vector<bool> boolvec_or(const std::vector<bool> &lhs,
108       const std::vector<bool> &rhs);
109 
110   CASADI_EXPORT std::vector<casadi_int> boolvec_to_index(const std::vector<bool> &v);
111 
112   CASADI_EXPORT bool is_equally_spaced(const std::vector<double> &v);
113 
114   /// Computes a mapping for a (dense) tensor permutation
115   CASADI_EXPORT std::vector<casadi_int> tensor_permute_mapping(const std::vector<casadi_int>& dims,
116       const std::vector<casadi_int>& order);
117 
118   CASADI_EXPORT int to_int(casadi_int rhs);
119   CASADI_EXPORT std::vector<int> to_int(const std::vector<casadi_int>& rhs);
120   CASADI_EXPORT std::vector< std::vector<int> > to_int(
121     const std::vector< std::vector<casadi_int> >& rhs);
122 
123   template<typename T, typename S>
124   std::vector<T> vector_static_cast(const std::vector<S>& rhs);
125 
126   CASADI_EXPORT std::string str_bvec(bvec_t v);
127 
128   /**  \brief Slicing vector
129   *  \param v Vector to slice
130   *  \param i List of indices
131   */
132   template<typename T>
133   std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i);
134 
135   /** \brief Reverse a list
136   */
137   template<typename T>
138   std::vector<T> reverse(const std::vector<T> &v);
139 
140   /** \brief Join two lists
141   */
142   template<typename T>
143   std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b);
144 
145   /** \brief Join three lists
146   */
147   template<typename T>
148   std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c);
149 
150   /** \brief permute a list
151   */
152   template<typename T>
153   std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order);
154 
155   /** \brief find nonzeros */
156   template<typename T>
157   std::vector<casadi_int> find(const std::vector<T> &v);
158 
159   #endif // SWIG
160 
161   /// Check if for each element of v holds: v_i < upper
162   template<typename T>
163   bool in_range(const std::vector<T> &v, casadi_int upper);
164 
165   /// Check if for each element of v holds: lower <= v_i < upper
166   template<typename T>
167   bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper);
168 
169   // Assert that a indices are in a range
170   #define casadi_assert_in_range(v, lower, upper) \
171    casadi_assert(in_range(v, lower, upper), \
172     "Out of bounds error. Got elements in range [" \
173     + str(*std::min_element(v.begin(), v.end())) + ","\
174     + str(*std::max_element(v.begin(), v.end())) + "], which is outside the range ["\
175     + str(lower) + "," + str(upper) + ").")
176 
177     // Assert that a indices are bounded
178     #define casadi_assert_bounded(v, upper) \
179      casadi_assert(in_range(v, upper), \
180       "Out of bounds error. Got elements in range [" \
181       + str(*std::min_element(v.begin(), v.end())) + ","\
182       + str(*std::max_element(v.begin(), v.end())) + "], which exceeds the upper bound "\
183       + str(upper) + ".")
184 
185   /** \brief Returns the list of all i in [0, size[ not found in supplied list
186   *
187   * The supplied vector may contain duplicates and may be non-monotonous
188   * The supplied vector will be checked for bounds
189   * The result vector is guaranteed to be monotonously increasing
190   */
191   CASADI_EXPORT std::vector<casadi_int> complement(const std::vector<casadi_int> &v,
192                                                     casadi_int size);
193 
194   /** \brief Returns a vector for quickly looking up entries of supplied list
195   *
196   *  lookupvector[i]!=-1     <=>  v contains i
197   *  v[lookupvector[i]] == i <=>  v contains i
198   *
199   *  Duplicates are treated by looking up last occurrence
200   */
201   CASADI_EXPORT std::vector<casadi_int> lookupvector(const std::vector<casadi_int> &v,
202                                                      casadi_int size);
203   CASADI_EXPORT std::vector<casadi_int> lookupvector(const std::vector<casadi_int> &v);
204 
205   /** \brief Flatten a nested std::vector tot a single flattened vector
206    *
207    * Contents of nested[i] ends up in flat[indices[i]]..flat[indices[i+1]-1]
208    */
209   template<class T, class S>
210   void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
211                             std::vector<S>& flat);
212 
213   /** \brief Flatten a nested std::vector tot a single flattened vector
214    *
215    * Contents of nested[i] ends up in flat[indices[i]]..flat[indices[i+1]-1]
216    */
217   template<class T, class S, class I>
218   void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
219                             std::vector<S>& flat,
220                             std::vector<I>& indices);
221 
222   /// \cond INTERNAL
223 #ifndef SWIG
224   /**
225   Apply a function f to each element in a vector
226   */
227   template<class T>
228   std::vector<T> applymap(T (*f)(const T&), const std::vector<T>& comp);
229 
230   /**
231   Apply a function f to each element in a vector
232   */
233   template<class T>
234   void applymap(void (*f)(T&), std::vector<T>& comp);
235 #endif // SWIG
236   /// \endcond
237 
238 
239   /// Check if the vector is strictly increasing
240   template<typename T>
241   bool is_increasing(const std::vector<T> &v);
242 
243   /// Check if the vector is strictly decreasing
244   template<typename T>
245   bool is_decreasing(const std::vector<T> &v);
246 
247   /// Check if the vector is non-increasing
248   template<typename T>
249   bool is_nonincreasing(const std::vector<T> &v);
250 
251   /// Check if the vector is non-decreasing
252   template<typename T>
253   bool is_nondecreasing(const std::vector<T> &v);
254 
255   /// Check if the vector is monotone
256   template<typename T>
257   bool is_monotone(const std::vector<T> &v);
258 
259   /// Check if the vector is strictly monotone
260   template<typename T>
261   bool is_strictly_monotone(const std::vector<T> &v);
262 
263   /// Check if the vector has negative entries
264   template<typename T>
265   bool has_negative(const std::vector<T> &v);
266 
267   /// Print vector, matlab style
268   template<typename T>
269   void write_matlab(std::ostream &stream, const std::vector<T> &v);
270 
271   /// Print matrix, matlab style
272   template<typename T>
273   void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v);
274 
275   /// Read vector, matlab style
276   template<typename T>
277   void read_matlab(std::istream &stream, std::vector<T> &v);
278 
279   /// Read matrix, matlab style
280   template<typename T>
281   void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v);
282 
283 #ifndef SWIG
284   /// Matlab's linspace
285   template<typename T, typename F, typename L>
286   void linspace(std::vector<T> &v, const F& first, const L& last);
287 
288   /// \cond INTERNAL
289   /// Get an pointer of sets of booleans from a double vector
290   CASADI_EXPORT bvec_t* get_bvec_t(std::vector<double>& v);
291 
292   /// Get an pointer of sets of booleans from a double vector
293   CASADI_EXPORT const bvec_t* get_bvec_t(const std::vector<double>& v);
294 
295   /// Bit-wise or operation on bvec_t array
296   CASADI_EXPORT bvec_t bvec_or(const bvec_t* arg, casadi_int n);
297 
298   /// Get an pointer of sets of booleans from a double vector
299   template<typename T>
300   bvec_t* get_bvec_t(std::vector<T>& v);
301 
302   /// Get an pointer of sets of booleans from a double vector
303   template<typename T>
304   const bvec_t* get_bvec_t(const std::vector<T>& v);
305 
306   /// Get a pointer to the data contained in the vector
307   template<typename T>
308   T* get_ptr(std::vector<T> &v);
309 
310   /// Get a pointer to the data contained in the vector
311   template<typename T>
312   const T* get_ptr(const std::vector<T> &v);
313 
314   /// \endcond
315 
316   /** \brief Sort the data in a vector
317   *
318   * \param[in]  values the vector that needs sorting
319   * \param[out] sorted_values the sorted vector
320   * \param[out] indices The indices such that 'sorted_values= values[indices]'
321   * \param[in] invert_indices Output indices such that 'sorted_values[indices=values'
322   **/
323   template<typename T>
324   void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
325             std::vector<casadi_int> &indices, bool invert_indices =false);
326 
327   /** \brief product
328   *
329   */
330   template<typename T>
331   T product(const std::vector<T> &values);
332 
333   /** \brief sum
334   *
335   */
336   template<typename T>
337   T sum(const std::vector<T> &values);
338 
339   /** \brief cumulative sum
340   *
341   */
342   template<typename T>
343   std::vector<T> cumsum(const std::vector<T> &values);
344 
345   /** \brief diff
346   *
347   */
348   template<typename T>
349   std::vector<T> diff(const std::vector<T> &values);
350 
351   /** \brief cumulative sum, starting with zero
352   *
353   */
354   template<typename T>
355   std::vector<T> cumsum0(const std::vector<T> &values);
356 #endif //SWIG
357 
358   /// Checks if array does not contain NaN or Inf
359   template<typename T>
is_regular(const std::vector<T> & v)360   bool is_regular(const std::vector<T> &v) {
361     for (auto&& vk : v) {
362       if (vk!=vk || vk==std::numeric_limits<T>::infinity() ||
363           vk==-std::numeric_limits<T>::infinity()) return false;
364     }
365     return true;
366   }
367 
368   // Create a temporary file
369   CASADI_EXPORT std::string temporary_file(const std::string& prefix, const std::string& suffix);
370 
371   CASADI_EXPORT void normalized_setup(std::istream& stream);
372   CASADI_EXPORT void normalized_setup(std::ostream& stream);
373 
normalized_out(std::ostream & stream,double val)374   inline void normalized_out(std::ostream& stream, double val) {
375     if (val==std::numeric_limits<double>::infinity()) {
376       stream << "inf";
377     } else if (val==-std::numeric_limits<double>::infinity()) {
378       stream << "-inf";
379     } else if (val!=val) {
380       stream << "nan";
381     } else {
382       stream << val;
383     }
384   }
normalized_in(std::istream & stream,double & ret)385   inline int normalized_in(std::istream& stream, double& ret) {
386     std::streampos start = stream.tellg();
387     stream >> ret;
388     // Failed to interpret as double?
389     if (stream.fail()) {
390       // Clear error flag
391       stream.clear();
392       // Reset stream position
393       // Need to parse e.g "-inf"
394       stream.seekg(start);
395       // Might be a inf/nan
396       std::string non_reg;
397       stream >> non_reg;
398       // Break on trailing whitespace
399       if (stream.fail()) {
400         if (stream.eof()) {
401           ret = std::numeric_limits<double>::quiet_NaN();
402           return -1; // End of stream
403         } else {
404           ret = std::numeric_limits<double>::quiet_NaN();
405           return 1; // Failed to parse to string
406         }
407       }
408       if (non_reg=="inf") {
409         ret = std::numeric_limits<double>::infinity();
410       } else if (non_reg=="-inf") {
411         ret = -std::numeric_limits<double>::infinity();
412       } else if (non_reg=="nan") {
413         ret = std::numeric_limits<double>::quiet_NaN();
414       } else {
415         ret = std::numeric_limits<double>::quiet_NaN();
416         return 2; // Failed to interpretas number
417       }
418     }
419     return 0;
420   }
421 
422 } // namespace casadi
423 
424 #ifndef SWIG
425 // In std namespace
426 namespace std {
427 
428   /// Enables flushing an std::vector to a stream (prints representation)
429   template<typename T>
operator <<(ostream & stream,const vector<T> & v)430   ostream& operator<<(ostream& stream, const vector<T>& v) {
431     stream << casadi::str(v);
432     return stream;
433   }
434 
435   /// Enables flushing an std::set to a stream (prints representation)
436   template<typename T>
operator <<(ostream & stream,const set<T> & v)437   ostream& operator<<(ostream& stream, const set<T>& v) {
438     stream << casadi::str(v);
439     return stream;
440   }
441 
442   template<typename T1, typename T2>
operator <<(ostream & stream,const pair<T1,T2> & p)443   ostream& operator<<(ostream& stream, const pair<T1, T2>& p) {
444     stream << casadi::str(p);
445     return stream;
446   }
447 
448   template<typename T1, typename T2>
operator <<(ostream & stream,const std::map<T1,T2> & p)449   ostream& operator<<(ostream& stream, const std::map<T1, T2>& p) {
450     stream << casadi::str(p);
451     return stream;
452   }
453 
454   template<typename T2>
operator <<(ostream & stream,const std::map<std::string,T2> & p)455   ostream& operator<<(ostream& stream, const std::map<std::string, T2>& p) {
456     stream << casadi::str(p);
457     return stream;
458   }
459 
460   template<typename T>
mul_overflows(const T & a,const T & b)461   bool mul_overflows(const T& a, const T& b) {
462     if (a==0 || b==0) return false;
463     return abs(std::numeric_limits<T>::max()/a) < abs(b);
464   }
465 
466 } // namespace std
467 
468 // Implementations
469 namespace casadi {
470 
471   template<typename T, typename S>
vector_static_cast(const std::vector<S> & rhs)472   std::vector<T> vector_static_cast(const std::vector<S>& rhs) {
473     std::vector<T> ret;
474     ret.reserve(rhs.size());
475     for (auto e : rhs) ret.push_back(static_cast<T>(e));
476     return ret;
477   }
478 
479   template<typename T>
vector_slice(const std::vector<T> & v,const std::vector<casadi_int> & i)480   std::vector<T> vector_slice(const std::vector<T> &v, const std::vector<casadi_int> &i) {
481     std::vector<T> ret;
482     ret.reserve(i.size());
483     for (casadi_int k=0;k<i.size();++k) {
484        casadi_int j = i[k];
485        casadi_assert(j>=0,
486          "vector_slice: Indices should be larger than zero."
487          "You have " + str(j) + " at location " + str(k) + ".");
488        casadi_assert(j<v.size(),
489          "vector_slice: Indices should be larger than zero."
490          "You have " + str(j) + " at location " + str(k) + ".");
491        ret.push_back(v[j]);
492     }
493     return ret;
494   }
495 
496   template<typename T>
reverse(const std::vector<T> & v)497   std::vector<T> reverse(const std::vector<T> &v) {
498     std::vector<T> ret(v.size());
499     std::reverse_copy(v.begin(), v.end(), ret.begin());
500     return ret;
501   }
502 
503   template<typename T>
join(const std::vector<T> & a,const std::vector<T> & b)504   std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b) {
505     std::vector<T> ret = a;
506     ret.insert(ret.end(), b.begin(), b.end());
507     return ret;
508   }
509 
510   template<typename T>
join(const std::vector<T> & a,const std::vector<T> & b,const std::vector<T> & c)511   std::vector<T> join(const std::vector<T> &a, const std::vector<T> &b, const std::vector<T> &c) {
512     std::vector<T> ret = a;
513     ret.insert(ret.end(), b.begin(), b.end());
514     ret.insert(ret.end(), c.begin(), c.end());
515     return ret;
516   }
517 
518   template<typename T>
permute(const std::vector<T> & a,const std::vector<casadi_int> & order)519   std::vector<T> permute(const std::vector<T> &a, const std::vector<casadi_int> &order) {
520     casadi_assert_dev(order.size()==a.size());
521     std::set<casadi_int> order_set(order.begin(), order.end());
522     casadi_assert_dev(order_set.size()==a.size());
523     casadi_assert_dev(*order_set.begin()==0);
524     casadi_assert_dev(*order_set.rbegin()==a.size()-1);
525     return vector_slice(a, order);
526   }
527 
528   template<typename T>
find(const std::vector<T> & v)529   std::vector<casadi_int> find(const std::vector<T> &v) {
530     std::vector<casadi_int> ret;
531     for (casadi_int i=0;i<v.size();++i) {
532       if (v[i]) ret.push_back(i);
533     }
534     return ret;
535   }
536 
537 #ifndef SWIG
538   template<class T>
applymap(T (* f)(const T &),const std::vector<T> & comp)539   std::vector<T> applymap(T (*f)(const T&) , const std::vector<T>& comp) {
540     std::vector<T> ret(comp.size());
541     std::transform(comp.begin(), comp.end(), ret.begin(), f);
542     return ret;
543   }
544 
545   template<class T>
applymap(void (* f)(T &),std::vector<T> & comp)546   void applymap(void (*f)(T &), std::vector<T>& comp) {
547     std::for_each(comp.begin(), comp.end(), f);
548   }
549 
550   template<class S, class D>
copy_vector(const std::vector<S> & s,std::vector<D> & d)551   void copy_vector(const std::vector<S>& s, std::vector<D>& d) {
552     casadi_assert(s.size()==d.size(), "Dimension mismatch.");
553     std::copy(s.begin(), s.end(), d.begin());
554   }
555 
556   template<class S, class D>
assign_vector(const std::vector<S> & s,std::vector<D> & d)557   void assign_vector(const std::vector<S>& s, std::vector<D>& d) {
558     casadi_assert(d.empty(), "Receiving vector must be empty");
559     d.resize(s.size());
560     std::copy(s.begin(), s.end(), d.begin());
561   }
562 
563   template<class S, class D>
copy_vector(const S * s,std::vector<D> & d)564   void copy_vector(const S* s, std::vector<D>& d) {
565     for (casadi_int i=0;i<d.size();++i) {
566       d[i] = static_cast<D>(s[i]);
567     }
568   }
569 
570   template<class S, class D>
init_vector(std::vector<S> & d,const std::vector<D> & s)571   void init_vector(std::vector<S>& d, const std::vector<D>& s) {
572     d.resize(s.size());
573     std::copy(s.begin(), s.end(), d.begin());
574   }
575 #endif //SWIG
576 
577   template<typename T>
in_range(const std::vector<T> & v,casadi_int upper)578   bool in_range(const std::vector<T> &v, casadi_int upper) {
579     return in_range(v, 0, upper);
580   }
581 
582   template<typename T>
in_range(const std::vector<T> & v,casadi_int lower,casadi_int upper)583   bool in_range(const std::vector<T> &v, casadi_int lower, casadi_int upper) {
584     if (v.empty()) return true;
585     casadi_int max = *std::max_element(v.begin(), v.end());
586     if (max >= upper) return false;
587     casadi_int min = *std::min_element(v.begin(), v.end());
588     return (min >= lower);
589   }
590 
591   template<class T, class S>
flatten_nested_vector(const std::vector<std::vector<T>> & nested,std::vector<S> & flat)592   void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
593                              std::vector<S>& flat) {
594     // Count total elements in nested
595     casadi_int N = 0;
596     for (const auto& e : nested) {
597       N += e.size();
598     }
599 
600     // Populate flat, one nested section at a time
601     flat.clear();
602     flat.reserve(N);
603     for (const auto& e : nested) {
604       flat.insert(flat.end(), e.begin(), e.end());
605     }
606   }
607 
608   template<class T, class S, class I>
flatten_nested_vector(const std::vector<std::vector<T>> & nested,std::vector<S> & flat,std::vector<I> & indices)609   void flatten_nested_vector(const std::vector< std::vector<T> >& nested,
610                              std::vector<S>& flat,
611                              std::vector<I>& indices) {
612     // Delegate
613     flatten_nested_vector(nested, flat);
614 
615     // Build up indices
616     casadi_int N = nested.size();
617     indices.resize(1, 0);
618     indices.reserve(N+1);
619     casadi_int offset = 0;
620     for (const auto& e : nested) {
621       offset += e.size();
622       indices.push_back(offset);
623     }
624   }
625 
626   template<typename T>
isUnique(const std::vector<T> & v)627   bool isUnique(const std::vector<T> &v) {
628     std::set<T> s(v.begin(), v.end());
629     return v.size()==s.size();
630   }
631 
632   template<typename T>
is_increasing(const std::vector<T> & v)633   bool is_increasing(const std::vector<T> &v) {
634     if (v.empty()) return true;
635     T el = v[0];
636     for (casadi_int i=1;i<v.size();++i) {
637       if (!(v[i] > el)) return false;
638       el = v[i];
639     }
640     return el==el; // nan -> false
641   }
642 
643   template<typename T>
is_decreasing(const std::vector<T> & v)644   bool is_decreasing(const std::vector<T> &v) {
645     if (v.empty()) return true;
646     T el = v[0];
647     for (casadi_int i=1;i<v.size();++i) {
648       if (!(v[i] < el)) return false;
649       el = v[i];
650     }
651     return el==el; // nan -> false
652   }
653 
654   template<typename T>
is_nonincreasing(const std::vector<T> & v)655   bool is_nonincreasing(const std::vector<T> &v) {
656     if (v.empty()) return true;
657     T el = v[0];
658     for (casadi_int i=1;i<v.size();++i) {
659       if (!(v[i] <= el)) return false;
660       el = v[i];
661     }
662     return el==el; // nan -> false
663   }
664 
665   template<typename T>
is_nondecreasing(const std::vector<T> & v)666   bool is_nondecreasing(const std::vector<T> &v) {
667     if (v.empty()) return true;
668     T el = v[0];
669     for (casadi_int i=1;i<v.size();++i) {
670       if (!(v[i] >= el)) return false;
671       el = v[i];
672     }
673     return el==el; // nan -> false
674   }
675 
676   template<typename T>
is_monotone(const std::vector<T> & v)677   bool is_monotone(const std::vector<T> &v) {
678     return is_nondecreasing(v) || is_nonincreasing(v);
679   }
680 
681   template<typename T>
is_strictly_monotone(const std::vector<T> & v)682   bool is_strictly_monotone(const std::vector<T> &v) {
683     return is_decreasing(v) || is_increasing(v);
684   }
685 
686   template<typename T>
has_negative(const std::vector<T> & v)687   bool has_negative(const std::vector<T> &v) {
688     for (std::size_t i=0; i<v.size(); ++i) {
689       if (v[i]<0) return true;
690     }
691     return false;
692   }
693 
694   template<typename T>
write_matlab(std::ostream & stream,const std::vector<T> & v)695   void write_matlab(std::ostream &stream, const std::vector<T> &v) {
696     std::copy(v.begin(), v.end(), std::ostream_iterator<T>(stream, " "));
697   }
698 
699   template<typename T>
write_matlab(std::ostream & stream,const std::vector<std::vector<T>> & v)700   void write_matlab(std::ostream &stream, const std::vector<std::vector<T> > &v) {
701     for (casadi_uint i=0; i<v.size(); ++i) {
702       std::copy(v[i].begin(), v[i].end(), std::ostream_iterator<T>(stream, " "));
703       stream << std::endl;
704     }
705   }
706 
707   template<typename T>
read_matlab(std::istream & stream,std::vector<T> & v)708   void read_matlab(std::istream &stream, std::vector<T> &v) {
709     v.clear();
710 
711     while (!stream.eof()) {
712       T val;
713       stream >> val;
714       if (stream.fail()) {
715         stream.clear();
716         std::string s;
717         stream >> s;
718         if (s=="inf")
719           val = std::numeric_limits<T>::infinity();
720         else
721           break;
722       }
723       v.push_back(val);
724     }
725   }
726 
727   template<typename T>
read_matlab(std::ifstream & file,std::vector<std::vector<T>> & v)728   void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v) {
729     v.clear();
730     std::string line;
731     while (!getline(file, line, '\n').eof()) {
732       std::istringstream reader(line);
733       std::vector<T> lineData;
734 
735       while (!reader.eof()) {
736         T val;
737         reader >> val;
738         if (reader.fail()) {
739           reader.clear();
740           std::string s;
741           reader >> s;
742           if (s=="inf")
743             val = std::numeric_limits<T>::infinity();
744           else
745             break;
746         }
747         lineData.push_back(val);
748       }
749       v.push_back(lineData);
750     }
751   }
752 
753   template<typename T, typename F, typename L>
linspace(std::vector<T> & v,const F & first,const L & last)754   void linspace(std::vector<T> &v, const F& first, const L& last) {
755     if (v.size()<2)
756         throw CasadiException("std::linspace: vector must contain at least two elements");
757 
758     // Increment
759     T increment = (last-first)/T(v.size()-1);
760 
761     v[0] = first;
762     for (unsigned i=1; i<v.size()-1; ++i)
763       v[i] = v[i-1] + increment;
764     v[v.size()-1] = last;
765   }
766 
767   template<typename T>
get_ptr(std::vector<T> & v)768   T* get_ptr(std::vector<T> &v) {
769     if (v.empty())
770       return nullptr;
771     else
772       return &v.front();
773   }
774 
775   template<typename T>
get_ptr(const std::vector<T> & v)776   const T* get_ptr(const std::vector<T> &v) {
777     if (v.empty())
778       return nullptr;
779     else
780       return &v.front();
781   }
782 
783   // Helper class
784   template<typename T>
785   struct sortCompare {
786     const std::vector<T> &v_;
sortComparecasadi::sortCompare787     sortCompare(const std::vector<T> &v) : v_(v) {}
operator ()casadi::sortCompare788     bool operator() (casadi_int i, casadi_int j) const { return v_[i]<v_[j];}
789   };
790 
791   template<typename T>
sort(const std::vector<T> & values,std::vector<T> & sorted_values,std::vector<casadi_int> & indices,bool invert_indices)792   void sort(const std::vector<T> &values, std::vector<T> &sorted_values,
793             std::vector<casadi_int> &indices, bool invert_indices) {
794     // Call recursively if indices need to be inverted
795     if (invert_indices) {
796       std::vector<casadi_int> inverted;
797       sort(values, sorted_values, inverted, false);
798       indices.resize(inverted.size());
799       for (size_t i=0; i<inverted.size(); ++i) {
800         indices[inverted[i]] = i;
801       }
802       return;
803     }
804 
805     // Create list of indices
806     indices.resize(values.size());
807     for (size_t i=0; i<indices.size(); ++i) indices[i] = i;
808 
809     // Sort this list by the values
810     std::sort(indices.begin(), indices.end(), sortCompare<T>(values));
811 
812     // Sort the values accordingly
813     sorted_values.resize(values.size());
814     for (size_t i=0; i<values.size(); ++i) {
815       sorted_values[i] = values[indices[i]];
816     }
817   }
818 
819   template<typename T>
product(const std::vector<T> & values)820   T product(const std::vector<T> &values) {
821     T r = 1;
822     for (casadi_int i=0;i<values.size();++i) r*=values[i];
823     return r;
824   }
825 
826   template<typename T>
sum(const std::vector<T> & values)827   T sum(const std::vector<T> &values) {
828     T r = 0;
829     for (casadi_int i=0;i<values.size();++i) r+=values[i];
830     return r;
831   }
832 
833   template<typename T>
cumsum(const std::vector<T> & values)834   std::vector<T> cumsum(const std::vector<T> &values) {
835     std::vector<T> ret(values.size());
836     T acc = 0;
837     for (casadi_int i=0;i<values.size();++i) {
838       acc+= values[i];
839       ret[i] = acc;
840     }
841     return ret;
842   }
843 
844   template<typename T>
cumsum0(const std::vector<T> & values)845   std::vector<T> cumsum0(const std::vector<T> &values) {
846     std::vector<T> ret(values.size()+1, 0);
847     T acc = 0;
848     for (casadi_int i=0;i<values.size();++i) {
849       acc+= values[i];
850       ret[i+1] = acc;
851     }
852     return ret;
853   }
854 
855   template<typename T>
diff(const std::vector<T> & values)856   std::vector<T> diff(const std::vector<T> &values) {
857     casadi_assert(!values.empty(), "Array must be non-empty");
858     std::vector<T> ret(values.size()-1);
859     for (casadi_int i=0;i<values.size()-1;++i) {
860       ret[i] = values[i+1]-values[i];
861     }
862     return ret;
863   }
864 
865   template<typename T>
dot(const std::vector<T> & a,const std::vector<T> & b)866   T dot(const std::vector<T>& a, const std::vector<T>& b) {
867     T ret = 0;
868     for (casadi_int k=0; k<a.size(); ++k) {
869       ret += a[k]*b[k];
870     }
871     return ret;
872   }
873 
874   template<typename T>
norm_inf(const std::vector<T> & x)875   T norm_inf(const std::vector<T>& x) {
876     T ret = 0;
877     for (casadi_int k=0; k<x.size(); ++k) {
878       ret = fmax(ret, fabs(x[k]));
879     }
880     return ret;
881   }
882 
883   template<typename T>
norm_1(const std::vector<T> & x)884   T norm_1(const std::vector<T>& x) {
885     T ret = 0;
886     for (casadi_int k=0; k<x.size(); ++k) {
887       ret += fabs(x[k]);
888     }
889     return ret;
890   }
891 
892   template<typename T>
norm_2(const std::vector<T> & x)893   T norm_2(const std::vector<T>& x) {
894     T ret = 0;
895     for (casadi_int k=0; k<x.size(); ++k) {
896       ret += x[k]*x[k];
897     }
898     return sqrt(ret);
899   }
900 
901   template<typename T>
get_bvec_t(std::vector<T> & v)902   bvec_t* get_bvec_t(std::vector<T>& v) {
903     casadi_assert(0, "get_bvec_t only supported for double");
904   }
905 
906   template<typename T>
get_bvec_t(const std::vector<T> & v)907   const bvec_t* get_bvec_t(const std::vector<T>& v) {
908     casadi_assert(0, "get_bvec_t only supported for double");
909   }
910 
911   ///@{
912   /// Readability typedefs
913   typedef std::vector<std::string> StringVector;
914   ///@}
915 
916 } // namespace casadi
917 #endif // SWIG
918 
919 #endif // CASADI_MISC_HPP
920