26 #ifndef CASADI_MISC_HPP
27 #define CASADI_MISC_HPP
29 #include "exception.hpp"
30 #include "casadi_common.hpp"
45 class scoped_checkout {
47 scoped_checkout(
const T& proto) : proto_(proto) {
48 mem = proto_.checkout();
51 scoped_checkout(scoped_checkout&& that) : mem(that.mem), proto_(that.proto_) {
55 scoped_checkout(
const scoped_checkout& that) =
delete;
58 if (mem!=-1) proto_.release(mem);
61 operator casadi_int()
const {
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());
87 CASADI_EXPORT
bool is_range(
const std::vector<casadi_int>& v,
88 casadi_int start, casadi_int stop, casadi_int step=1);
90 CASADI_EXPORT std::string join(
const std::vector<std::string>& l,
const std::string& delim=
",");
93 CASADI_EXPORT
bool startswith(
const std::string& s,
const std::string& p);
96 CASADI_EXPORT std::string replace(
const std::string& s,
97 const std::string& p,
const std::string& r);
100 CASADI_EXPORT
bool version_gt(
const std::string& version_left,
101 const std::string& version_right);
104 CASADI_EXPORT
bool version_ge(
const std::string& version_left,
105 const std::string& version_right);
108 CASADI_EXPORT
bool version_lt(
const std::string& version_left,
109 const std::string& version_right);
112 CASADI_EXPORT
bool version_le(
const std::string& version_left,
113 const std::string& version_right);
122 CASADI_EXPORT std::vector<casadi_int> range(casadi_int stop);
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);
137 CASADI_EXPORT std::vector<casadi_int> boolvec_to_index(
const std::vector<bool> &v);
139 CASADI_EXPORT
bool is_equally_spaced(
const std::vector<double> &v);
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);
146 template<
typename T,
typename S>
147 std::vector<T> vector_static_cast(
const std::vector<S>& rhs);
149 CASADI_EXPORT std::string str_bvec(bvec_t v);
158 std::vector<T> vector_slice(
const std::vector<T> &v,
const std::vector<casadi_int> &i);
167 std::vector<T> vector_select(
const std::vector<T> &v,
const std::vector<bool> &s,
174 std::vector<T> vector_tail(
const std::vector<T> &v);
180 std::vector<T> vector_init(
const std::vector<T> &v);
186 std::vector<T> reverse(
const std::vector<T> &v);
192 std::vector<T> join(
const std::vector<T> &a,
const std::vector<T> &b);
198 std::vector<T> join(
const std::vector<T> &a,
const std::vector<T> &b,
const std::vector<T> &c);
203 bool is_permutation(
const std::vector<casadi_int> &order);
209 std::vector<T> permute(
const std::vector<T> &a,
const std::vector<casadi_int> &order);
214 std::vector<casadi_int> invert_permutation(
const std::vector<casadi_int> &a);
220 std::vector<casadi_int> find(
const std::vector<T> &v);
226 bool in_range(
const std::vector<T> &v, casadi_int upper);
230 bool in_range(
const std::vector<T> &v, casadi_int lower, casadi_int upper);
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) + ").")
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 "\
255 CASADI_EXPORT std::vector<casadi_int>
complement(
const std::vector<casadi_int> &v,
266 CASADI_EXPORT std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v,
268 CASADI_EXPORT std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v);
275 template<
class T,
class S>
277 std::vector<S>& flat);
284 template<
class T,
class S,
class I>
286 std::vector<S>& flat,
287 std::vector<I>& indices);
295 std::vector<T> applymap(T (*f)(
const T&),
const std::vector<T>& comp);
301 void applymap(
void (*f)(T&), std::vector<T>& comp);
340 void write_matlab(std::ostream &stream,
const std::vector<std::vector<T> > &v);
348 void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v);
352 template<
typename T,
typename F,
typename L>
353 void linspace(std::vector<T> &v,
const F& first,
const L& last);
357 CASADI_EXPORT bvec_t* get_bvec_t(std::vector<double>& v);
360 CASADI_EXPORT
const bvec_t* get_bvec_t(
const std::vector<double>& v);
363 CASADI_EXPORT bvec_t bvec_or(
const bvec_t* arg, casadi_int n);
367 bvec_t* get_bvec_t(std::vector<T>& v);
371 const bvec_t* get_bvec_t(
const std::vector<T>& v);
375 T* get_ptr(std::vector<T> &v);
379 const T* get_ptr(
const std::vector<T> &v);
392 void sort(
const std::vector<T> &values, std::vector<T> &sorted_values,
393 std::vector<casadi_int> &indices,
bool invert_indices =
false);
399 T product(
const std::vector<T> &values);
405 T sum(
const std::vector<T> &values);
411 std::vector<T> cumsum(
const std::vector<T> &values);
417 std::vector<T> diff(
const std::vector<T> &values);
423 std::vector<T> cumsum0(
const std::vector<T> &values);
429 for (
auto&& vk : v) {
430 if (vk!=vk || vk==std::numeric_limits<T>::infinity() ||
431 vk==-std::numeric_limits<T>::infinity())
return false;
438 const std::string& suffix,
439 const std::string& directory=
"");
451 std::ostream& stream_;
452 std::ios::fmtflags flags_;
453 std::streamsize precision_;
454 std::streamsize width_;
459 if (val==std::numeric_limits<double>::infinity()) {
461 }
else if (val==-std::numeric_limits<double>::infinity()) {
463 }
else if (val!=val) {
470 std::streampos start = stream.tellg();
485 ret = std::numeric_limits<double>::quiet_NaN();
488 ret = std::numeric_limits<double>::quiet_NaN();
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();
499 ret = std::numeric_limits<double>::quiet_NaN();
515 std::ostream& operator<<(std::ostream& stream,
const std::vector<T>& v) {
516 stream << casadi::str(v);
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);
529 std::ostream& operator<<(std::ostream& stream,
const std::set<T>& v) {
530 stream << casadi::str(v);
534 template<
typename T1,
typename T2>
535 std::ostream& operator<<(std::ostream& stream,
const std::pair<T1, T2>& p) {
536 stream << casadi::str(p);
540 template<
typename T1,
typename T2>
541 std::ostream& operator<<(std::ostream& stream,
const std::map<T1, T2>& p) {
542 stream << casadi::str(p);
546 template<
typename T2>
547 std::ostream& operator<<(std::ostream& stream,
const std::map<std::string, T2>& p) {
548 stream << casadi::str(p);
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);
558 template<
typename T,
typename S>
559 std::vector<T> vector_static_cast(
const std::vector<S>& rhs) {
561 ret.reserve(rhs.size());
562 for (
auto e : rhs) ret.push_back(
static_cast<T>(e));
567 std::vector<T> vector_slice(
const std::vector<T> &v,
const std::vector<casadi_int> &i) {
569 ret.reserve(i.size());
570 for (casadi_int k=0;k<i.size();++k) {
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) +
".");
584 std::vector<T> vector_select(
const std::vector<T> &v,
const std::vector<bool> &s,
bool invert) {
586 casadi_assert(v.size()==s.size(),
"Dimension mismatch.");
588 for (casadi_int k=0;k<s.size();++k) {
589 if (!s[k]) ret.push_back(v[k]);
592 for (casadi_int k=0;k<s.size();++k) {
593 if (s[k]) ret.push_back(v[k]);
600 std::vector<T> vector_tail(
const std::vector<T> &v) {
602 ret.insert(ret.begin(), v.begin()+1, v.end());
607 std::vector<T> vector_init(
const std::vector<T> &v) {
609 ret.insert(ret.begin(), v.begin(), v.begin()+v.size()-1);
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());
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());
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());
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);
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);
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);
660 void applymap(
void (*f)(T &), std::vector<T>& comp) {
661 std::for_each(comp.begin(), comp.end(), f);
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());
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");
674 std::copy(s.begin(), s.end(), d.begin());
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]);
684 template<
class S,
class D>
685 void init_vector(std::vector<S>& d,
const std::vector<D>& s) {
687 std::copy(s.begin(), s.end(), d.begin());
692 bool in_range(
const std::vector<T> &v, casadi_int upper) {
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);
705 template<
class T,
class S>
707 std::vector<S>& flat) {
710 for (
const auto& e : nested) {
717 for (
const auto& e : nested) {
718 flat.insert(flat.end(), e.begin(), e.end());
722 template<
class T,
class S,
class I>
724 std::vector<S>& flat,
725 std::vector<I>& 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) {
736 indices.push_back(offset);
741 bool isUnique(
const std::vector<T> &v) {
742 std::set<T> s(v.begin(), v.end());
743 return v.size()==s.size();
748 if (v.empty())
return true;
750 for (casadi_int i=1;i<v.size();++i) {
751 if (!(v[i] > el))
return false;
759 if (v.empty())
return true;
761 for (casadi_int i=1;i<v.size();++i) {
762 if (!(v[i] < el))
return false;
770 if (v.empty())
return true;
772 for (casadi_int i=1;i<v.size();++i) {
773 if (!(v[i] <= el))
return false;
781 if (v.empty())
return true;
783 for (casadi_int i=1;i<v.size();++i) {
784 if (!(v[i] >= el))
return false;
802 for (std::size_t i=0; i<v.size(); ++i) {
803 if (v[i]<0)
return true;
809 void write_matlab(std::ostream &stream,
const std::vector<T> &v) {
810 std::copy(v.begin(), v.end(), std::ostream_iterator<T>(stream,
" "));
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,
" "));
822 void read_matlab(std::istream &stream, std::vector<T> &v) {
825 while (!stream.eof()) {
833 val = std::numeric_limits<T>::infinity();
842 void read_matlab(std::ifstream &file, std::vector<std::vector<T> > &v) {
845 while (!getline(file, line,
'\n').eof()) {
846 std::istringstream reader(line);
847 std::vector<T> lineData;
849 while (!reader.eof()) {
857 val = std::numeric_limits<T>::infinity();
861 lineData.push_back(val);
863 v.push_back(lineData);
867 template<
typename T,
typename F,
typename L>
868 void linspace(std::vector<T> &v,
const F& first,
const L& last) {
870 throw CasadiException(
"std::linspace: vector must contain at least two elements");
873 T increment = (last-first)/
T(v.size()-1);
876 for (
unsigned i=1; i<v.size()-1; ++i)
877 v[i] = v[i-1] + increment;
878 v[v.size()-1] = last;
882 T* get_ptr(std::vector<T> &v) {
890 const T* get_ptr(
const std::vector<T> &v) {
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];}
906 void sort(
const std::vector<T> &values, std::vector<T> &sorted_values,
907 std::vector<casadi_int> &indices,
bool invert_indices) {
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;
920 indices.resize(values.size());
921 for (
size_t i=0; i<indices.size(); ++i) indices[i] = i;
924 std::sort(indices.begin(), indices.end(), sortCompare<T>(values));
927 sorted_values.resize(values.size());
928 for (
size_t i=0; i<values.size(); ++i) {
929 sorted_values[i] = values[indices[i]];
934 T product(
const std::vector<T> &values) {
936 for (casadi_int i=0;i<values.size();++i) r*=values[i];
941 T sum(
const std::vector<T> &values) {
943 for (casadi_int i=0;i<values.size();++i) r+=values[i];
948 std::vector<T> cumsum(
const std::vector<T> &values) {
949 std::vector<T> ret(values.size());
951 for (casadi_int i=0;i<values.size();++i) {
959 std::vector<T> cumsum0(
const std::vector<T> &values) {
960 std::vector<T> ret(values.size()+1, 0);
962 for (casadi_int i=0;i<values.size();++i) {
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];
980 T dot(
const std::vector<T>& a,
const std::vector<T>& b) {
982 for (casadi_int k=0; k<a.size(); ++k) {
989 T norm_inf(
const std::vector<T>& x) {
991 for (casadi_int k=0; k<x.size(); ++k) {
992 ret = fmax(ret, fabs(x[k]));
998 T norm_1(
const std::vector<T>& x) {
1000 for (casadi_int k=0; k<x.size(); ++k) {
1006 template<
typename T>
1007 T norm_2(
const std::vector<T>& x) {
1009 for (casadi_int k=0; k<x.size(); ++k) {
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");
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");
1027 typedef std::vector<std::string> StringVector;
1033 template<
typename T>
1034 inline size_t hash_value(T v) {
return size_t(v);}
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);
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]);
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());
1061 inline size_t hash_value(std::string v) {
1063 hash_combine(seed, v.c_str(), v.size());
1071 inline size_t hash_value(
double v) {
1073 std::memcpy(&u, &v,
sizeof(
double));
1075 if (
sizeof(
size_t) == 8) {
1077 return static_cast<size_t>(u);
1081 hash_combine(seed,
static_cast<std::uint32_t
>(u));
1082 hash_combine(seed,
static_cast<std::uint32_t
>(u >> 32));
StreamStateGuard(std::ostream &os)
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="")