26 #ifndef CASADI_MISC_HPP
27 #define CASADI_MISC_HPP
29 #include "exception.hpp"
30 #include "casadi_common.hpp"
44 class scoped_checkout {
46 scoped_checkout(
const T& proto) : proto_(proto) {
47 mem = proto_.checkout();
50 scoped_checkout(scoped_checkout&& that) : mem(that.mem), proto_(that.proto_) {
54 scoped_checkout(
const scoped_checkout& that) =
delete;
57 if (mem!=-1) proto_.release(mem);
60 operator casadi_int()
const {
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());
86 CASADI_EXPORT
bool is_range(
const std::vector<casadi_int>& v,
87 casadi_int start, casadi_int stop, casadi_int step=1);
89 CASADI_EXPORT std::string join(
const std::vector<std::string>& l,
const std::string& delim=
",");
92 CASADI_EXPORT
bool startswith(
const std::string& s,
const std::string& p);
95 CASADI_EXPORT std::string replace(
const std::string& s,
96 const std::string& p,
const std::string& r);
105 CASADI_EXPORT std::vector<casadi_int> range(casadi_int stop);
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);
120 CASADI_EXPORT std::vector<casadi_int> boolvec_to_index(
const std::vector<bool> &v);
122 CASADI_EXPORT
bool is_equally_spaced(
const std::vector<double> &v);
125 CASADI_EXPORT std::vector<casadi_int> tensor_permute_mapping(
const std::vector<casadi_int>& dims,
126 const std::vector<casadi_int>& order);
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);
133 template<
typename T,
typename S>
134 std::vector<T> vector_static_cast(
const std::vector<S>& rhs);
136 CASADI_EXPORT std::string str_bvec(bvec_t v);
145 std::vector<T> vector_slice(
const std::vector<T> &v,
const std::vector<casadi_int> &i);
151 std::vector<T> vector_tail(
const std::vector<T> &v);
157 std::vector<T> reverse(
const std::vector<T> &v);
163 std::vector<T> join(
const std::vector<T> &a,
const std::vector<T> &b);
169 std::vector<T> join(
const std::vector<T> &a,
const std::vector<T> &b,
const std::vector<T> &c);
174 bool is_permutation(
const std::vector<casadi_int> &order);
180 std::vector<T> permute(
const std::vector<T> &a,
const std::vector<casadi_int> &order);
185 std::vector<casadi_int> invert_permutation(
const std::vector<casadi_int> &a);
191 std::vector<casadi_int> find(
const std::vector<T> &v);
197 bool in_range(
const std::vector<T> &v, casadi_int upper);
201 bool in_range(
const std::vector<T> &v, casadi_int lower, casadi_int upper);
204 #define casadi_assert_in_range(v, lower, upper) \
205 casadi_assert(in_range(v, lower, upper), \
206 "Out of bounds error. Got elements in range [" \
207 + str(*std::min_element(v.begin(), v.end())) + ","\
208 + str(*std::max_element(v.begin(), v.end())) + "], which is outside the range ["\
209 + str(lower) + "," + str(upper) + ").")
212 #define casadi_assert_bounded(v, upper) \
213 casadi_assert(in_range(v, upper), \
214 "Out of bounds error. Got elements in range [" \
215 + str(*std::min_element(v.begin(), v.end())) + ","\
216 + str(*std::max_element(v.begin(), v.end())) + "], which exceeds the upper bound "\
226 CASADI_EXPORT std::vector<casadi_int>
complement(
const std::vector<casadi_int> &v,
237 CASADI_EXPORT std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v,
239 CASADI_EXPORT std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v);
246 template<
class T,
class S>
248 std::vector<S>& flat);
255 template<
class T,
class S,
class I>
257 std::vector<S>& flat,
258 std::vector<I>& indices);
266 std::vector<T> applymap(T (*f)(
const T&),
const std::vector<T>& comp);
272 void applymap(
void (*f)(T&), std::vector<T>& comp);
311 void write_matlab(std::ostream &stream,
const std::vector<std::vector<T> > &v);
319 void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v);
323 template<
typename T,
typename F,
typename L>
324 void linspace(std::vector<T> &v,
const F& first,
const L& last);
328 CASADI_EXPORT bvec_t* get_bvec_t(std::vector<double>& v);
331 CASADI_EXPORT
const bvec_t* get_bvec_t(
const std::vector<double>& v);
334 CASADI_EXPORT bvec_t bvec_or(
const bvec_t* arg, casadi_int n);
338 bvec_t* get_bvec_t(std::vector<T>& v);
342 const bvec_t* get_bvec_t(
const std::vector<T>& v);
346 T* get_ptr(std::vector<T> &v);
350 const T* get_ptr(
const std::vector<T> &v);
363 void sort(
const std::vector<T> &values, std::vector<T> &sorted_values,
364 std::vector<casadi_int> &indices,
bool invert_indices =
false);
370 T product(
const std::vector<T> &values);
376 T sum(
const std::vector<T> &values);
382 std::vector<T> cumsum(
const std::vector<T> &values);
388 std::vector<T> diff(
const std::vector<T> &values);
394 std::vector<T> cumsum0(
const std::vector<T> &values);
400 for (
auto&& vk : v) {
401 if (vk!=vk || vk==std::numeric_limits<T>::infinity() ||
402 vk==-std::numeric_limits<T>::infinity())
return false;
408 CASADI_EXPORT std::string
temporary_file(
const std::string& prefix,
const std::string& suffix);
414 if (val==std::numeric_limits<double>::infinity()) {
416 }
else if (val==-std::numeric_limits<double>::infinity()) {
418 }
else if (val!=val) {
425 std::streampos start = stream.tellg();
440 ret = std::numeric_limits<double>::quiet_NaN();
443 ret = std::numeric_limits<double>::quiet_NaN();
447 if (non_reg==
"inf") {
448 ret = std::numeric_limits<double>::infinity();
449 }
else if (non_reg==
"-inf") {
450 ret = -std::numeric_limits<double>::infinity();
451 }
else if (non_reg==
"nan") {
452 ret = std::numeric_limits<double>::quiet_NaN();
454 ret = std::numeric_limits<double>::quiet_NaN();
469 ostream& operator<<(ostream& stream,
const vector<T>& v) {
470 stream << casadi::str(v);
476 ostream& operator<<(ostream& stream,
const set<T>& v) {
477 stream << casadi::str(v);
481 template<
typename T1,
typename T2>
482 ostream& operator<<(ostream& stream,
const pair<T1, T2>& p) {
483 stream << casadi::str(p);
487 template<
typename T1,
typename T2>
488 ostream& operator<<(ostream& stream,
const std::map<T1, T2>& p) {
489 stream << casadi::str(p);
493 template<
typename T2>
494 ostream& operator<<(ostream& stream,
const std::map<std::string, T2>& p) {
495 stream << casadi::str(p);
500 bool mul_overflows(
const T& a,
const T& b) {
501 if (a==0 || b==0)
return false;
502 return abs(std::numeric_limits<T>::max()/a) < abs(b);
510 template<
typename T,
typename S>
511 std::vector<T> vector_static_cast(
const std::vector<S>& rhs) {
513 ret.reserve(rhs.size());
514 for (
auto e : rhs) ret.push_back(
static_cast<T
>(e));
519 std::vector<T> vector_slice(
const std::vector<T> &v,
const std::vector<casadi_int> &i) {
521 ret.reserve(i.size());
522 for (casadi_int k=0;k<i.size();++k) {
525 "vector_slice: Indices should be larger than zero."
526 "You have " + str(j) +
" at location " + str(k) +
".");
527 casadi_assert(j<v.size(),
528 "vector_slice: Indices should be larger than zero."
529 "You have " + str(j) +
" at location " + str(k) +
".");
536 std::vector<T> vector_tail(
const std::vector<T> &v) {
538 ret.insert(ret.begin(), v.begin()+1, v.end());
543 std::vector<T> reverse(
const std::vector<T> &v) {
544 std::vector<T> ret(v.size());
545 std::reverse_copy(v.begin(), v.end(), ret.begin());
550 std::vector<T> join(
const std::vector<T> &a,
const std::vector<T> &b) {
551 std::vector<T> ret = a;
552 ret.insert(ret.end(), b.begin(), b.end());
557 std::vector<T> join(
const std::vector<T> &a,
const std::vector<T> &b,
const std::vector<T> &c) {
558 std::vector<T> ret = a;
559 ret.insert(ret.end(), b.begin(), b.end());
560 ret.insert(ret.end(), c.begin(), c.end());
565 std::vector<T> permute(
const std::vector<T> &a,
const std::vector<casadi_int> &order) {
566 casadi_assert_dev(order.size()==a.size());
567 casadi_assert_dev(is_permutation(order));
568 return vector_slice(a, order);
572 std::vector<casadi_int> find(
const std::vector<T> &v) {
573 std::vector<casadi_int> ret;
574 for (casadi_int i=0;i<v.size();++i) {
575 if (v[i]) ret.push_back(i);
582 std::vector<T> applymap(T (*f)(
const T&) ,
const std::vector<T>& comp) {
583 std::vector<T> ret(comp.size());
584 std::transform(comp.begin(), comp.end(), ret.begin(), f);
589 void applymap(
void (*f)(T &), std::vector<T>& comp) {
590 std::for_each(comp.begin(), comp.end(), f);
593 template<
class S,
class D>
594 void copy_vector(
const std::vector<S>& s, std::vector<D>& d) {
595 casadi_assert(s.size()==d.size(),
"Dimension mismatch.");
596 std::copy(s.begin(), s.end(), d.begin());
599 template<
class S,
class D>
600 void assign_vector(
const std::vector<S>& s, std::vector<D>& d) {
601 casadi_assert(d.empty(),
"Receiving vector must be empty");
603 std::copy(s.begin(), s.end(), d.begin());
606 template<
class S,
class D>
607 void copy_vector(
const S* s, std::vector<D>& d) {
608 for (casadi_int i=0;i<d.size();++i) {
609 d[i] =
static_cast<D
>(s[i]);
613 template<
class S,
class D>
614 void init_vector(std::vector<S>& d,
const std::vector<D>& s) {
616 std::copy(s.begin(), s.end(), d.begin());
621 bool in_range(
const std::vector<T> &v, casadi_int upper) {
626 bool in_range(
const std::vector<T> &v, casadi_int lower, casadi_int upper) {
627 if (v.empty())
return true;
628 casadi_int max = *std::max_element(v.begin(), v.end());
629 if (max >= upper)
return false;
630 casadi_int min = *std::min_element(v.begin(), v.end());
631 return (min >= lower);
634 template<
class T,
class S>
636 std::vector<S>& flat) {
639 for (
const auto& e : nested) {
646 for (
const auto& e : nested) {
647 flat.insert(flat.end(), e.begin(), e.end());
651 template<
class T,
class S,
class I>
653 std::vector<S>& flat,
654 std::vector<I>& indices) {
659 casadi_int N = nested.size();
660 indices.resize(1, 0);
661 indices.reserve(N+1);
662 casadi_int offset = 0;
663 for (
const auto& e : nested) {
665 indices.push_back(offset);
670 bool isUnique(
const std::vector<T> &v) {
671 std::set<T> s(v.begin(), v.end());
672 return v.size()==s.size();
677 if (v.empty())
return true;
679 for (casadi_int i=1;i<v.size();++i) {
680 if (!(v[i] > el))
return false;
688 if (v.empty())
return true;
690 for (casadi_int i=1;i<v.size();++i) {
691 if (!(v[i] < el))
return false;
699 if (v.empty())
return true;
701 for (casadi_int i=1;i<v.size();++i) {
702 if (!(v[i] <= el))
return false;
710 if (v.empty())
return true;
712 for (casadi_int i=1;i<v.size();++i) {
713 if (!(v[i] >= el))
return false;
731 for (std::size_t i=0; i<v.size(); ++i) {
732 if (v[i]<0)
return true;
738 void write_matlab(std::ostream &stream,
const std::vector<T> &v) {
739 std::copy(v.begin(), v.end(), std::ostream_iterator<T>(stream,
" "));
743 void write_matlab(std::ostream &stream,
const std::vector<std::vector<T> > &v) {
744 for (casadi_uint i=0; i<v.size(); ++i) {
745 std::copy(v[i].begin(), v[i].end(), std::ostream_iterator<T>(stream,
" "));
751 void read_matlab(std::istream &stream, std::vector<T> &v) {
754 while (!stream.eof()) {
762 val = std::numeric_limits<T>::infinity();
771 void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v) {
774 while (!getline(file, line,
'\n').eof()) {
775 std::istringstream reader(line);
776 std::vector<T> lineData;
778 while (!reader.eof()) {
786 val = std::numeric_limits<T>::infinity();
790 lineData.push_back(val);
792 v.push_back(lineData);
796 template<
typename T,
typename F,
typename L>
797 void linspace(std::vector<T> &v,
const F& first,
const L& last) {
799 throw CasadiException(
"std::linspace: vector must contain at least two elements");
802 T increment = (last-first)/T(v.size()-1);
805 for (
unsigned i=1; i<v.size()-1; ++i)
806 v[i] = v[i-1] + increment;
807 v[v.size()-1] = last;
811 T* get_ptr(std::vector<T> &v) {
819 const T* get_ptr(
const std::vector<T> &v) {
829 const std::vector<T> &v_;
830 sortCompare(
const std::vector<T> &v) : v_(v) {}
831 bool operator() (casadi_int i, casadi_int j)
const {
return v_[i]<v_[j];}
835 void sort(
const std::vector<T> &values, std::vector<T> &sorted_values,
836 std::vector<casadi_int> &indices,
bool invert_indices) {
838 if (invert_indices) {
839 std::vector<casadi_int> inverted;
840 sort(values, sorted_values, inverted,
false);
841 indices.resize(inverted.size());
842 for (
size_t i=0; i<inverted.size(); ++i) {
843 indices[inverted[i]] = i;
849 indices.resize(values.size());
850 for (
size_t i=0; i<indices.size(); ++i) indices[i] = i;
853 std::sort(indices.begin(), indices.end(), sortCompare<T>(values));
856 sorted_values.resize(values.size());
857 for (
size_t i=0; i<values.size(); ++i) {
858 sorted_values[i] = values[indices[i]];
863 T product(
const std::vector<T> &values) {
865 for (casadi_int i=0;i<values.size();++i) r*=values[i];
870 T sum(
const std::vector<T> &values) {
872 for (casadi_int i=0;i<values.size();++i) r+=values[i];
877 std::vector<T> cumsum(
const std::vector<T> &values) {
878 std::vector<T> ret(values.size());
880 for (casadi_int i=0;i<values.size();++i) {
888 std::vector<T> cumsum0(
const std::vector<T> &values) {
889 std::vector<T> ret(values.size()+1, 0);
891 for (casadi_int i=0;i<values.size();++i) {
899 std::vector<T> diff(
const std::vector<T> &values) {
900 casadi_assert(!values.empty(),
"Array must be non-empty");
901 std::vector<T> ret(values.size()-1);
902 for (casadi_int i=0;i<values.size()-1;++i) {
903 ret[i] = values[i+1]-values[i];
909 T dot(
const std::vector<T>& a,
const std::vector<T>& b) {
911 for (casadi_int k=0; k<a.size(); ++k) {
918 T norm_inf(
const std::vector<T>& x) {
920 for (casadi_int k=0; k<x.size(); ++k) {
921 ret = fmax(ret, fabs(x[k]));
927 T norm_1(
const std::vector<T>& x) {
929 for (casadi_int k=0; k<x.size(); ++k) {
936 T norm_2(
const std::vector<T>& x) {
938 for (casadi_int k=0; k<x.size(); ++k) {
945 bvec_t* get_bvec_t(std::vector<T>& v) {
946 casadi_assert(0,
"get_bvec_t only supported for double");
950 const bvec_t* get_bvec_t(
const std::vector<T>& v) {
951 casadi_assert(0,
"get_bvec_t only supported for double");
956 typedef std::vector<std::string> StringVector;
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)