28 #include "casadi_misc.hpp"
29 #include "global_options.hpp"
30 #include "filesystem_impl.hpp"
32 #include "casadi_os.hpp"
35 #define CASADI_NEED_UNISTD
37 #ifdef HAVE_SIMPLE_MKSTEMPS
42 #define CASADI_NEED_UNISTD
52 #ifdef CASADI_NEED_UNISTD
56 #undef CASADI_NEED_UNISTD
61 casadi_assert(rhs<=std::numeric_limits<int>::max(),
"Integer overflow detected.");
62 casadi_assert(rhs>=std::numeric_limits<int>::min(),
"Integer overflow detected.");
66 std::vector<int>
to_int(
const std::vector<casadi_int>& rhs) {
68 ret.reserve(rhs.size());
69 for (casadi_int e : rhs) ret.push_back(
to_int(e));
73 std::vector< std::vector<int> >
to_int(
74 const std::vector< std::vector<casadi_int> >& rhs) {
75 std::vector< std::vector<int> > ret;
76 ret.reserve(rhs.size());
77 for (
const std::vector<casadi_int>& e : rhs) ret.push_back(
to_int(e));
81 bool all(
const std::vector<bool>& v) {
88 bool any(
const std::vector<bool>& v) {
95 bool is_range(
const std::vector<casadi_int>& v,
96 casadi_int start, casadi_int stop, casadi_int step) {
97 casadi_int nret = (stop-start)/step + ((stop-start)%step!=0);
98 if (v.size()!=nret)
return false;
99 casadi_int ind = start;
100 for (casadi_int e : v) {
101 if (e!=ind)
return false;
108 const std::string& fname) {
109 casadi_assert(!offset.empty() && offset.front()==0 && offset.back()==n
110 &&
is_monotone(offset), fname +
": offset " +
str(offset) +
" must start at 0, "
111 "be nondecreasing and end at " +
str(n));
115 std::vector<casadi_int>
range(casadi_int start, casadi_int stop,
116 casadi_int step, casadi_int len) {
117 start = std::min(start, len);
118 stop = std::min(stop, len);
119 casadi_int nret = (stop-start)/step + ((stop-start)%step!=0);
120 std::vector<casadi_int> ret(nret);
121 casadi_int ind = start;
122 for (std::vector<casadi_int>::iterator it=ret.begin(); it!=ret.end(); ++it) {
131 if (v.size()<=2)
return true;
134 double margin = (v.back()-v.front())*1e-14;
136 double spacing = v[1]-v[0];
137 for (
size_t i=2; i<v.size(); ++i) {
138 if (fabs(v[i]-v[i-1]-spacing)>margin)
return false;
144 std::vector<casadi_int>
range(casadi_int stop) {
145 return range(0, stop);
148 std::vector<casadi_int>
complement(
const std::vector<casadi_int> &v, casadi_int size) {
150 "complement: out of bounds. Some elements in v fall out of [0, size[");
151 std::vector<casadi_int> lookup(size, 0);
152 std::vector<casadi_int> ret;
154 for (casadi_int i=0;i<v.size();i++) {
158 for (casadi_int i=0;i<size;i++) {
159 if (lookup[i]==0) ret.push_back(i);
166 std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v, casadi_int size) {
168 "lookupvector: out of bounds. Some elements in v fall out of [0, size[");
169 std::vector<casadi_int> lookup(size, -1);
171 for (casadi_int i=0;i<v.size();i++) {
177 std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v) {
179 return lookupvector(v, (*std::max_element(v.begin(), v.end()))+1);
183 std::set<casadi_int> order_set(order.begin(), order.end());
184 return (order_set.size()==order.size()) &&
185 (*order_set.begin()==0) &&
186 (*order_set.rbegin()==order.size()-1);
191 std::vector<casadi_int> ret(a.size());
192 for (casadi_int i=0;i<a.size();++i) {
202 return reinterpret_cast<bvec_t*
>(&v.front());
211 return reinterpret_cast<const bvec_t*
>(&v.front());
215 std::string
join(
const std::vector<std::string>& l,
const std::string& delim) {
216 std::stringstream ss;
217 for (casadi_int i=0;i<l.size();++i) {
218 if (i>0) ss << delim;
224 bool startswith(
const std::string& s,
const std::string& p) {
225 if (p.size()>s.size())
return false;
226 for (casadi_int i=0;i<p.size();++i) {
227 if (s[i]!=p[i])
return false;
232 CASADI_EXPORT std::string
replace(
const std::string& s,
233 const std::string& p,
const std::string& r) {
235 std::string::size_type n = 0;
236 while ((n = ret.find(p, n)) != std::string::npos) {
237 ret.replace(n, p.size(), r);
243 bool version_gt(
const std::string& version_left,
const std::string& version_right) {
244 std::vector<casadi_int> left_parts, right_parts;
247 std::stringstream left_stream(version_left);
249 while (std::getline(left_stream, part,
'.')) {
250 left_parts.push_back(std::stoi(part));
254 std::stringstream right_stream(version_right);
255 while (std::getline(right_stream, part,
'.')) {
256 right_parts.push_back(std::stoi(part));
260 casadi_int min_size = std::min(left_parts.size(), right_parts.size());
261 for (casadi_int i = 0; i < min_size; ++i) {
262 if (left_parts[i] > right_parts[i])
return true;
263 if (left_parts[i] < right_parts[i])
return false;
267 return left_parts.size() > right_parts.size();
270 bool version_ge(
const std::string& version_left,
const std::string& version_right) {
271 std::vector<casadi_int> left_parts, right_parts;
274 std::stringstream left_stream(version_left);
276 while (std::getline(left_stream, part,
'.')) {
277 left_parts.push_back(std::stoi(part));
281 std::stringstream right_stream(version_right);
282 while (std::getline(right_stream, part,
'.')) {
283 right_parts.push_back(std::stoi(part));
287 casadi_int min_size = std::min(left_parts.size(), right_parts.size());
288 for (casadi_int i = 0; i < min_size; ++i) {
289 if (left_parts[i] > right_parts[i])
return true;
290 if (left_parts[i] < right_parts[i])
return false;
294 return left_parts.size() >= right_parts.size();
297 bool version_lt(
const std::string& version_left,
const std::string& version_right) {
298 return version_gt(version_right, version_left);
301 bool version_le(
const std::string& version_left,
const std::string& version_right) {
302 return version_ge(version_right, version_left);
305 #ifdef HAVE_SIMPLE_MKSTEMPS
306 int simple_mkstemps_fd(
const std::string& prefix,
const std::string& suffix, std::string &result) {
308 std::string chars =
"abcdefghijklmnopqrstuvwxyz0123456789";
309 int char_size =
static_cast<int>(chars.size());
312 casadi_int max_tries = std::numeric_limits<int>::max();
315 double max_tries_d =
static_cast<double>(max_tries);
316 double char_size_d =
static_cast<double>(char_size);
317 int id_size = lround(ceil(log(max_tries_d)/log(char_size_d)));
320 std::default_random_engine rng(std::chrono::system_clock::now().time_since_epoch().count());
321 std::uniform_int_distribution<> r(0, char_size-1);
323 for (casadi_int i=0;i<max_tries;++i) {
325 for (casadi_int j=0;j<id_size;++j) {
326 result += chars.at(r(rng));
331 int fd = _sopen(result.c_str(),
332 _O_BINARY | _O_CREAT | _O_EXCL | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
335 int fd = open(result.c_str(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
337 if (fd != -1)
return fd;
338 if (fd == -1 && errno != EEXIST)
return -1;
342 std::string simple_mkstemps(
const std::string& prefix,
const std::string& suffix) {
344 int fd = simple_mkstemps_fd(prefix, suffix, ret);
346 casadi_error(
"Failed to create temporary file: '" + ret +
". '"
348 "Note that CasADi needs to be compiled with WITH_GHC_FILESYSTEM=ON "
349 "for directories to be automatically created."));
362 const std::string& suffix,
363 const std::string& directory) {
370 "Unable to create the required directory for '" + temp_dir +
"'.");
375 std::string ret = temp_dir + prefix +
"XXXXXX" + suffix;
376 if (mkstemps(&ret[0],
static_cast<int>(suffix.size())) == -1) {
377 casadi_error(
"Failed to create temporary file: '" + ret +
"'. "
379 "Note that CasADi needs to be compiled with WITH_GHC_FILESYSTEM=ON "
380 "for directories to be automatically created."));
384 #ifdef HAVE_SIMPLE_MKSTEMPS
385 return simple_mkstemps(temp_dir + prefix, suffix);
387 casadi_assert(temp_dir==
"./",
"tmpnam fallback not compatible with custom temporary directory");
389 return std::string(tmpnam(
nullptr)) + suffix;
396 std::vector<bool> ret(v.size());
397 std::transform(v.begin(), v.end(), ret.begin(),
398 [](
bool v) ->
bool { return !v; });
402 std::vector<bool>
boolvec_and(
const std::vector<bool> &lhs,
const std::vector<bool> &rhs) {
403 casadi_assert(lhs.size()==rhs.size(),
"Size mismatch.");
404 std::vector<bool> ret(lhs.size());
405 std::transform(lhs.begin(), lhs.end(), rhs.begin(), ret.begin(),
406 [](
bool a,
bool b) ->
bool { return a && b; });
410 std::vector<bool>
boolvec_or(
const std::vector<bool> &lhs,
const std::vector<bool> &rhs) {
411 casadi_assert(lhs.size()==rhs.size(),
"Size mismatch.");
412 std::vector<bool> ret(lhs.size());
413 std::transform(lhs.begin(), lhs.end(), rhs.begin(), ret.begin(),
414 [](
bool a,
bool b) ->
bool { return a || b; });
420 std::vector<casadi_int> ret;
421 for (casadi_int i=0;i<v.size();++i) {
422 if (v[i]) ret.push_back(i);
428 stream.imbue(std::locale(
"C"));
432 stream.imbue(std::locale(
"C"));
433 stream << std::scientific;
434 stream << std::setprecision(std::numeric_limits<double>::digits10 + 1);
440 precision_(os.precision()),
442 locale_(os.getloc()) {}
445 stream_.flags(flags_);
446 stream_.precision(precision_);
447 stream_.width(width_);
448 stream_.imbue(locale_);
452 std::stringstream ss;
453 for (casadi_int i=0;i<
sizeof(
bvec_t)*8;++i) {
454 bool bit = v & (
bvec_t(1) << i);
455 ss << (bit ?
"1" :
"0");
466 for (casadi_int i=0;i<n;++i) {
static std::string ensure_trailing_slash(const std::string &path)
static bool ensure_directory_exists(const std::string &path)
static std::string getTempWorkDir()
StreamStateGuard(std::ostream &os)
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
bvec_t * get_bvec_t(std::vector< double > &v)
bool is_equally_spaced(const std::vector< double > &v)
std::string join(const std::vector< std::string > &l, const std::string &delim)
std::vector< casadi_int > invert_permutation(const std::vector< casadi_int > &a)
inverse a permutation vector
unsigned long long bvec_t
bool version_le(const std::string &version_left, const std::string &version_right)
Compare versions: returns true if version_left <= version_right.
bool is_range(const std::vector< casadi_int > &v, casadi_int start, casadi_int stop, casadi_int step)
Check if a vector matches a range.
bool startswith(const std::string &s, const std::string &p)
Checks if s starts with p.
int to_int(casadi_int rhs)
bool has_negative(const std::vector< T > &v)
Check if the vector has negative entries.
bool version_gt(const std::string &version_left, const std::string &version_right)
Compare versions: returns true if version_left > version_right.
CASADI_EXPORT std::string replace(const std::string &s, const std::string &p, const std::string &r)
Replace all occurences of p with r in s.
void check_offset(const std::vector< casadi_int > &offset, casadi_int n, const std::string &fname)
Assert that offset starts at 0, is nondecreasing and ends at n.
bool is_monotone(const std::vector< T > &v)
Check if the vector is monotone.
std::string str_bvec(bvec_t v)
std::vector< bool > boolvec_or(const std::vector< bool > &lhs, const std::vector< bool > &rhs)
Or operation on boolean vector.
bool version_lt(const std::string &version_left, const std::string &version_right)
Compare versions: returns true if version_left < version_right.
std::string str(const T &v)
String representation, any type.
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.
std::vector< bool > boolvec_not(const std::vector< bool > &v)
Invert all entries.
std::vector< bool > boolvec_and(const std::vector< bool > &lhs, const std::vector< bool > &rhs)
And operation on boolean vector.
bool any(const std::vector< bool > &v)
Check if any arguments are true.
void normalized_setup(std::istream &stream)
bool all(const std::vector< bool > &v)
Check if all arguments are true.
bool in_range(const std::vector< T > &v, casadi_int upper)
Check if for each element of v holds: v_i < upper.
bool is_permutation(const std::vector< casadi_int > &order)
Does the list represent a permutation?
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 version_ge(const std::string &version_left, const std::string &version_right)
Compare versions: returns true if version_left >= version_right.
bvec_t bvec_or(const bvec_t *arg, casadi_int n)
Bit-wise or operation on bvec_t array.
std::string temporary_file(const std::string &prefix, const std::string &suffix, const std::string &directory)
std::vector< casadi_int > boolvec_to_index(const std::vector< bool > &v)