28 #include "casadi_misc.hpp"
29 #include "casadi_os.hpp"
31 #define CASADI_NEED_UNISTD
33 #ifdef HAVE_SIMPLE_MKSTEMPS
38 #define CASADI_NEED_UNISTD
48 #ifdef CASADI_NEED_UNISTD
52 #undef CASADI_NEED_UNISTD
57 casadi_assert(rhs<=std::numeric_limits<int>::max(),
"Integer overflow detected.");
58 casadi_assert(rhs>=std::numeric_limits<int>::min(),
"Integer overflow detected.");
62 std::vector<int>
to_int(
const std::vector<casadi_int>& rhs) {
64 ret.reserve(rhs.size());
65 for (casadi_int e : rhs) ret.push_back(
to_int(e));
69 std::vector< std::vector<int> >
to_int(
70 const std::vector< std::vector<casadi_int> >& rhs) {
71 std::vector< std::vector<int> > ret;
72 ret.reserve(rhs.size());
73 for (
const std::vector<casadi_int>& e : rhs) ret.push_back(
to_int(e));
77 bool all(
const std::vector<bool>& v) {
84 bool any(
const std::vector<bool>& v) {
91 bool is_range(
const std::vector<casadi_int>& v,
92 casadi_int start, casadi_int stop, casadi_int step) {
93 casadi_int nret = (stop-start)/step + ((stop-start)%step!=0);
94 if (v.size()!=nret)
return false;
95 casadi_int ind = start;
96 for (casadi_int e : v) {
97 if (e!=ind)
return false;
104 std::vector<casadi_int>
range(casadi_int start, casadi_int stop,
105 casadi_int step, casadi_int len) {
106 start = std::min(start, len);
107 stop = std::min(stop, len);
108 casadi_int nret = (stop-start)/step + ((stop-start)%step!=0);
109 std::vector<casadi_int> ret(nret);
110 casadi_int ind = start;
111 for (std::vector<casadi_int>::iterator it=ret.begin(); it!=ret.end(); ++it) {
120 if (v.size()<=2)
return true;
123 double margin = (v.back()-v.front())*1e-14;
125 double spacing = v[1]-v[0];
126 for (
size_t i=2; i<v.size(); ++i) {
127 if (fabs(v[i]-v[i-1]-spacing)>margin)
return false;
133 std::vector<casadi_int>
range(casadi_int stop) {
134 return range(0, stop);
137 std::vector<casadi_int>
complement(
const std::vector<casadi_int> &v, casadi_int size) {
139 "complement: out of bounds. Some elements in v fall out of [0, size[");
140 std::vector<casadi_int> lookup(size, 0);
141 std::vector<casadi_int> ret;
143 for (casadi_int i=0;i<v.size();i++) {
147 for (casadi_int i=0;i<size;i++) {
148 if (lookup[i]==0) ret.push_back(i);
155 std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v, casadi_int size) {
157 "lookupvector: out of bounds. Some elements in v fall out of [0, size[");
158 std::vector<casadi_int> lookup(size, -1);
160 for (casadi_int i=0;i<v.size();i++) {
166 std::vector<casadi_int>
lookupvector(
const std::vector<casadi_int> &v) {
168 return lookupvector(v, (*std::max_element(v.begin(), v.end()))+1);
172 std::set<casadi_int> order_set(order.begin(), order.end());
173 return (order_set.size()==order.size()) &&
174 (*order_set.begin()==0) &&
175 (*order_set.rbegin()==order.size()-1);
180 std::vector<casadi_int> ret(a.size());
181 for (casadi_int i=0;i<a.size();++i) {
189 const std::vector<casadi_int>& order) {
193 casadi_int n = dims.size();
195 if (N==0)
return std::vector<casadi_int>();
198 if (n==1)
return range(N);
201 std::vector<casadi_int> mapping(N);
203 if (n==0)
return mapping;
207 std::vector<casadi_int> cumprod(n+1, 1);
208 for (casadi_int k=1;k<dims.size();++k) cumprod[k]=cumprod[k-1]*dims[k-1];
211 casadi_int stride = cumprod[order[0]];
214 casadi_int N_inner = dims[order[0]];
215 casadi_int N_outer = N/N_inner;
218 std::vector<casadi_int> new_dims(n-1), new_cumprod(n-1, 1);
219 for (casadi_int k=0;k<n-1;++k) {
220 new_dims[k] = dims[order[k+1]];
221 new_cumprod[k] = cumprod[order[k+1]];
225 std::vector<casadi_int> index_counters(n-1);
228 casadi_int m_ind = 0;
230 for (casadi_int i=0;i<N_outer;++i) {
233 for (casadi_int k=0;k<n-1;++k) ind+=index_counters[k]*new_cumprod[k];
236 for (casadi_int j=0;j<N_inner;++j) {
237 mapping.at(m_ind++) = ind;
245 for (casadi_int k=0;k<n-2;++k) {
246 if (index_counters[k]==new_dims[k]) {
247 index_counters[k] = 0;
248 index_counters[k+1]++;
259 return reinterpret_cast<bvec_t*
>(&v.front());
268 return reinterpret_cast<const bvec_t*
>(&v.front());
272 std::string
join(
const std::vector<std::string>& l,
const std::string& delim) {
273 std::stringstream ss;
274 for (casadi_int i=0;i<l.size();++i) {
275 if (i>0) ss << delim;
281 bool startswith(
const std::string& s,
const std::string& p) {
282 if (p.size()>s.size())
return false;
283 for (casadi_int i=0;i<p.size();++i) {
284 if (s[i]!=p[i])
return false;
289 CASADI_EXPORT std::string
replace(
const std::string& s,
290 const std::string& p,
const std::string& r) {
292 std::string::size_type n = 0;
293 while ((n = ret.find(p, n)) != std::string::npos) {
294 ret.replace(n, p.size(), r);
300 #ifdef HAVE_SIMPLE_MKSTEMPS
301 int simple_mkstemps_fd(
const std::string& prefix,
const std::string& suffix, std::string &result) {
303 std::string chars =
"abcdefghijklmnopqrstuvwxyz0123456789";
304 int char_size =
static_cast<int>(chars.size());
307 casadi_int max_tries = std::numeric_limits<int>::max();
310 double max_tries_d =
static_cast<double>(max_tries);
311 double char_size_d =
static_cast<double>(char_size);
312 int id_size = lround(ceil(log(max_tries_d)/log(char_size_d)));
315 std::default_random_engine rng(std::chrono::system_clock::now().time_since_epoch().count());
316 std::uniform_int_distribution<> r(0, char_size-1);
318 for (casadi_int i=0;i<max_tries;++i) {
320 for (casadi_int j=0;j<id_size;++j) {
321 result += chars.at(r(rng));
326 int fd = _sopen(result.c_str(),
327 _O_BINARY | _O_CREAT | _O_EXCL | _O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
330 int fd = open(result.c_str(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
332 if (fd != -1)
return fd;
333 if (fd == -1 && errno != EEXIST)
return -1;
337 std::string simple_mkstemps(
const std::string& prefix,
const std::string& suffix) {
339 int fd = simple_mkstemps_fd(prefix, suffix, ret);
341 casadi_error(
"Failed to create temporary file: '" + ret +
"'");
353 std::string
temporary_file(
const std::string& prefix,
const std::string& suffix) {
356 std::string ret = prefix +
"XXXXXX" + suffix;
357 if (mkstemps(&ret[0],
static_cast<int>(suffix.size())) == -1) {
358 casadi_error(
"Failed to create temporary file: '" + ret +
"'");
362 #ifdef HAVE_SIMPLE_MKSTEMPS
363 return simple_mkstemps(prefix, suffix);
366 return prefix + std::string(tmpnam(
nullptr)) + suffix;
373 std::vector<bool> ret(v.size());
374 std::transform(v.begin(), v.end(), ret.begin(),
375 [](
bool v) ->
bool { return !v; });
379 std::vector<bool>
boolvec_and(
const std::vector<bool> &lhs,
const std::vector<bool> &rhs) {
380 casadi_assert(lhs.size()==rhs.size(),
"Size mismatch.");
381 std::vector<bool> ret(lhs.size());
382 std::transform(lhs.begin(), lhs.end(), rhs.begin(), ret.begin(),
383 [](
bool a,
bool b) ->
bool { return a && b; });
387 std::vector<bool>
boolvec_or(
const std::vector<bool> &lhs,
const std::vector<bool> &rhs) {
388 casadi_assert(lhs.size()==rhs.size(),
"Size mismatch.");
389 std::vector<bool> ret(lhs.size());
390 std::transform(lhs.begin(), lhs.end(), rhs.begin(), ret.begin(),
391 [](
bool a,
bool b) ->
bool { return a || b; });
397 std::vector<casadi_int> ret;
398 for (casadi_int i=0;i<v.size();++i) {
399 if (v[i]) ret.push_back(i);
405 stream.imbue(std::locale(
"C"));
409 stream.imbue(std::locale(
"C"));
410 stream << std::scientific;
411 stream << std::setprecision(std::numeric_limits<double>::digits10 + 1);
416 std::stringstream ss;
417 for (casadi_int i=0;i<
sizeof(
bvec_t)*8;++i) {
418 bool bit = v & (
bvec_t(1) << i);
419 ss << (bit ?
"1" :
"0");
430 for (casadi_int i=0;i<n;++i) {
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)
T product(const std::vector< T > &values)
product
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 is_range(const std::vector< casadi_int > &v, casadi_int start, casadi_int stop, casadi_int step)
Check if a vector matches a range.
std::string temporary_file(const std::string &prefix, const std::string &suffix)
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.
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::vector< casadi_int > tensor_permute_mapping(const std::vector< casadi_int > &dims, const std::vector< casadi_int > &order)
Computes a mapping for a (dense) tensor permutation.
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.
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.
bvec_t bvec_or(const bvec_t *arg, casadi_int n)
Bit-wise or operation on bvec_t array.
std::vector< casadi_int > boolvec_to_index(const std::vector< bool > &v)