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 std::vector<casadi_int>
range(casadi_int start, casadi_int stop,
109 casadi_int step, casadi_int len) {
110 start = std::min(start, len);
111 stop = std::min(stop, len);
112 casadi_int nret = (stop-start)/step + ((stop-start)%step!=0);
113 std::vector<casadi_int> ret(nret);
114 casadi_int ind = start;
115 for (std::vector<casadi_int>::iterator it=ret.begin(); it!=ret.end(); ++it) {
124 if (v.size()<=2)
return true;
127 double margin = (v.back()-v.front())*1e-14;
129 double spacing = v[1]-v[0];
130 for (
size_t i=2; i<v.size(); ++i) {
131 if (fabs(v[i]-v[i-1]-spacing)>margin)
return false;
137 std::vector<casadi_int>
range(casadi_int stop) {
138 return range(0, stop);
141 std::vector<casadi_int>
complement(
const std::vector<casadi_int> &v, casadi_int size) {
143 "complement: out of bounds. Some elements in v fall out of [0, size[");
144 std::vector<casadi_int> lookup(size, 0);
145 std::vector<casadi_int> ret;
147 for (casadi_int i=0;i<v.size();i++) {
151 for (casadi_int i=0;i<size;i++) {
152 if (lookup[i]==0) ret.push_back(i);
159 std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v, casadi_int size) {
161 "lookupvector: out of bounds. Some elements in v fall out of [0, size[");
162 std::vector<casadi_int> lookup(size, -1);
164 for (casadi_int i=0;i<v.size();i++) {
170 std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v) {
172 return lookupvector(v, (*std::max_element(v.begin(), v.end()))+1);
176 std::set<casadi_int> order_set(order.begin(), order.end());
177 return (order_set.size()==order.size()) &&
178 (*order_set.begin()==0) &&
179 (*order_set.rbegin()==order.size()-1);
184 std::vector<casadi_int> ret(a.size());
185 for (casadi_int i=0;i<a.size();++i) {
195 return reinterpret_cast<bvec_t*
>(&v.front());
204 return reinterpret_cast<const bvec_t*
>(&v.front());
208 std::string
join(
const std::vector<std::string>& l,
const std::string& delim) {
209 std::stringstream ss;
210 for (casadi_int i=0;i<l.size();++i) {
211 if (i>0) ss << delim;
217 bool startswith(
const std::string& s,
const std::string& p) {
218 if (p.size()>s.size())
return false;
219 for (casadi_int i=0;i<p.size();++i) {
220 if (s[i]!=p[i])
return false;
225 CASADI_EXPORT std::string
replace(
const std::string& s,
226 const std::string& p,
const std::string& r) {
228 std::string::size_type n = 0;
229 while ((n = ret.find(p, n)) != std::string::npos) {
230 ret.replace(n, p.size(), r);
236 bool version_gt(
const std::string& version_left,
const std::string& version_right) {
237 std::vector<casadi_int> left_parts, right_parts;
240 std::stringstream left_stream(version_left);
242 while (std::getline(left_stream, part,
'.')) {
243 left_parts.push_back(std::stoi(part));
247 std::stringstream right_stream(version_right);
248 while (std::getline(right_stream, part,
'.')) {
249 right_parts.push_back(std::stoi(part));
253 casadi_int min_size = std::min(left_parts.size(), right_parts.size());
254 for (casadi_int i = 0; i < min_size; ++i) {
255 if (left_parts[i] > right_parts[i])
return true;
256 if (left_parts[i] < right_parts[i])
return false;
260 return left_parts.size() > right_parts.size();
263 bool version_ge(
const std::string& version_left,
const std::string& version_right) {
264 std::vector<casadi_int> left_parts, right_parts;
267 std::stringstream left_stream(version_left);
269 while (std::getline(left_stream, part,
'.')) {
270 left_parts.push_back(std::stoi(part));
274 std::stringstream right_stream(version_right);
275 while (std::getline(right_stream, part,
'.')) {
276 right_parts.push_back(std::stoi(part));
280 casadi_int min_size = std::min(left_parts.size(), right_parts.size());
281 for (casadi_int i = 0; i < min_size; ++i) {
282 if (left_parts[i] > right_parts[i])
return true;
283 if (left_parts[i] < right_parts[i])
return false;
287 return left_parts.size() >= right_parts.size();
290 bool version_lt(
const std::string& version_left,
const std::string& version_right) {
291 return version_gt(version_right, version_left);
294 bool version_le(
const std::string& version_left,
const std::string& version_right) {
295 return version_ge(version_right, version_left);
298 #ifdef HAVE_SIMPLE_MKSTEMPS
299 int simple_mkstemps_fd(
const std::string& prefix,
const std::string& suffix, std::string &result) {
301 std::string chars =
"abcdefghijklmnopqrstuvwxyz0123456789";
302 int char_size =
static_cast<int>(chars.size());
305 casadi_int max_tries = std::numeric_limits<int>::max();
308 double max_tries_d =
static_cast<double>(max_tries);
309 double char_size_d =
static_cast<double>(char_size);
310 int id_size = lround(ceil(log(max_tries_d)/log(char_size_d)));
313 std::default_random_engine rng(std::chrono::system_clock::now().time_since_epoch().count());
314 std::uniform_int_distribution<> r(0, char_size-1);
316 for (casadi_int i=0;i<max_tries;++i) {
318 for (casadi_int j=0;j<id_size;++j) {
319 result += chars.at(r(rng));
324 int fd = _sopen(result.c_str(),
325 _O_BINARY | _O_CREAT | _O_EXCL | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
328 int fd = open(result.c_str(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
330 if (fd != -1)
return fd;
331 if (fd == -1 && errno != EEXIST)
return -1;
335 std::string simple_mkstemps(
const std::string& prefix,
const std::string& suffix) {
337 int fd = simple_mkstemps_fd(prefix, suffix, ret);
339 casadi_error(
"Failed to create temporary file: '" + ret +
". '"
341 "Note that CasADi needs to be compiled with WITH_GHC_FILESYSTEM=ON "
342 "for directories to be automatically created."));
355 const std::string& suffix,
356 const std::string& directory) {
363 "Unable to create the required directory for '" + temp_dir +
"'.");
368 std::string ret = temp_dir + prefix +
"XXXXXX" + suffix;
369 if (mkstemps(&ret[0],
static_cast<int>(suffix.size())) == -1) {
370 casadi_error(
"Failed to create temporary file: '" + ret +
"'. "
372 "Note that CasADi needs to be compiled with WITH_GHC_FILESYSTEM=ON "
373 "for directories to be automatically created."));
377 #ifdef HAVE_SIMPLE_MKSTEMPS
378 return simple_mkstemps(temp_dir + prefix, suffix);
380 casadi_assert(temp_dir==
"./",
"tmpnam fallback not compatible with custom temporary directory");
382 return std::string(tmpnam(
nullptr)) + suffix;
389 std::vector<bool> ret(v.size());
390 std::transform(v.begin(), v.end(), ret.begin(),
391 [](
bool v) ->
bool { return !v; });
395 std::vector<bool>
boolvec_and(
const std::vector<bool> &lhs,
const std::vector<bool> &rhs) {
396 casadi_assert(lhs.size()==rhs.size(),
"Size mismatch.");
397 std::vector<bool> ret(lhs.size());
398 std::transform(lhs.begin(), lhs.end(), rhs.begin(), ret.begin(),
399 [](
bool a,
bool b) ->
bool { return a && b; });
403 std::vector<bool>
boolvec_or(
const std::vector<bool> &lhs,
const std::vector<bool> &rhs) {
404 casadi_assert(lhs.size()==rhs.size(),
"Size mismatch.");
405 std::vector<bool> ret(lhs.size());
406 std::transform(lhs.begin(), lhs.end(), rhs.begin(), ret.begin(),
407 [](
bool a,
bool b) ->
bool { return a || b; });
413 std::vector<casadi_int> ret;
414 for (casadi_int i=0;i<v.size();++i) {
415 if (v[i]) ret.push_back(i);
421 stream.imbue(std::locale(
"C"));
425 stream.imbue(std::locale(
"C"));
426 stream << std::scientific;
427 stream << std::setprecision(std::numeric_limits<double>::digits10 + 1);
433 precision_(os.precision()),
435 locale_(os.getloc()) {}
438 stream_.flags(flags_);
439 stream_.precision(precision_);
440 stream_.width(width_);
441 stream_.imbue(locale_);
445 std::stringstream ss;
446 for (casadi_int i=0;i<
sizeof(
bvec_t)*8;++i) {
447 bool bit = v & (
bvec_t(1) << i);
448 ss << (bit ?
"1" :
"0");
459 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.
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::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)