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