27 #include "casadi_misc.hpp"
28 #include "serializing_stream.hpp"
32 Slice::Slice() : start(0), stop(
std::numeric_limits<casadi_int>::max()), step(1) {
35 Slice::Slice(casadi_int i,
bool ind1) : start(i-ind1), stop(i-ind1+1), step(1) {
36 casadi_assert(!(ind1 && i<=0),
37 "Matlab is 1-based, but requested index " +
38 str(i) +
". Note that negative slices are"
39 " disabled in the Matlab interface. "
40 "Possibly you may want to use 'end'.");
41 if (i==-1)
stop = std::numeric_limits<casadi_int>::max();
45 start(start), stop(stop), step(step) { }
47 Slice::Slice(
int start,
int stop,
int step) : start(start), stop(stop), step(step) {
49 Slice::Slice(
int start, casadi_int stop,
int step) : start(start), stop(stop), step(step) {
51 Slice::Slice(casadi_int start,
int stop,
int step) : start(start), stop(stop), step(step) {
56 stop==std::numeric_limits<casadi_int>::max() ?
stop :
stop-i,
62 stop==std::numeric_limits<casadi_int>::max() ?
stop :
stop*i,
68 if (start==std::numeric_limits<casadi_int>::min()) {
74 if (stop==std::numeric_limits<casadi_int>::max()) {
80 casadi_assert(
stop<=len,
82 +
") out of bounds with supplied length of " +
str(len));
83 casadi_assert(
start>=0,
85 +
") out of bounds with start<0.");
91 casadi_assert(
start!=std::numeric_limits<casadi_int>::min(),
"Need a length");
92 casadi_assert(
stop!=std::numeric_limits<casadi_int>::max(),
"Need a length");
95 (stop<=start && step>0))
return std::vector<casadi_int>();
100 std::vector<casadi_int>
Slice::all(casadi_int len,
bool ind1)
const {
105 casadi_assert(
start!=std::numeric_limits<casadi_int>::min() &&
106 stop!=std::numeric_limits<casadi_int>::max(),
107 "Cannot determine numel of slice.");
108 return all(std::numeric_limits<casadi_int>::max()).size();
116 bool from_beginning =
start == 0;
117 bool till_end =
stop == std::numeric_limits<casadi_int>::max();
118 bool skip_none =
step==1;
122 if (!from_beginning) stream <<
start;
124 if (!till_end) stream <<
stop;
125 if (!skip_none) stream <<
":" <<
step;
130 std::vector<casadi_int> ret;
131 for (casadi_int i=outer.
start; i!=outer.
stop; i+=outer.
step) {
140 casadi_int
start = std::min(this->start, len);
141 casadi_int
stop = std::min(this->stop, len);
148 casadi_assert(
start >= -len &&
start < len,
"Slice::getScalar: out of bounds");
154 casadi_assert(
is_slice(v, ind1),
"Cannot be represented as a Slice");
158 }
else if (v.size()==1) {
159 r.
start = v.front()-ind1;
170 bool CASADI_EXPORT
is_slice(
const std::vector<casadi_int>& v,
bool ind1) {
172 casadi_int last_v = -1;
173 for (casadi_int i=0; i<v.size(); ++i) {
174 casadi_assert(!(ind1 && v[i]<=0),
175 "Matlab is 1-based, but requested index " +
str(v[i]) +
". "
176 "Note that negative slices are disabled in the Matlab interface. "
177 "Possibly you may want to use 'end'.");
178 if (v[i]-ind1<=last_v)
return false;
183 if (v.size()<2)
return true;
186 if (v.size()==2)
return v[0]!=v[1];
189 casadi_int start = v[0]-ind1;
190 casadi_int step = v[1]-v[0];
194 for (casadi_int i=2; i<v.size(); ++i) {
195 if (v[i]-ind1!=start+i*step)
return false;
202 bool CASADI_EXPORT
is_slice2(
const std::vector<casadi_int>& v) {
207 casadi_int last_v = -1;
208 for (casadi_int i=0; i<v.size(); ++i) {
209 if (v[i]<=last_v)
return false;
214 casadi_int start_outer = 0;
215 casadi_int step_outer = -1;
216 casadi_int start_inner = v.front();
217 casadi_int step_inner = v[1]-v[0];
218 casadi_int stop_inner = -1;
219 for (casadi_int i=2; i<v.size(); ++i) {
220 casadi_int predicted_v = start_inner+i*step_inner;
221 if (v[i]!=predicted_v) {
222 stop_inner = predicted_v;
223 step_outer = v[i] - start_inner;
227 casadi_assert_dev(stop_inner>=0);
230 casadi_int stop_outer = v.back();
232 if (step_outer>0) stop_outer++;
234 }
while (stop_outer % step_outer!=0);
237 std::vector<casadi_int>::const_iterator it=v.begin();
238 for (casadi_int i=start_outer; i!=stop_outer; i+=step_outer) {
239 for (casadi_int j=i+start_inner; j!=i+stop_inner; j+=step_inner) {
241 if (it==v.end())
return false;
244 if (*it++ != j)
return false;
249 if (it!=v.end())
return false;
255 std::pair<Slice, Slice> CASADI_EXPORT
to_slice2(
const std::vector<casadi_int>& v) {
256 casadi_assert(
is_slice2(v),
"Cannot be represented as a nested Slice");
264 return std::make_pair(inner, outer);
270 inner.
start = v.front();
271 inner.
step = v[1]-v[0];
273 for (casadi_int i=2; i<v.size(); ++i) {
274 casadi_int predicted_v = inner.
start+i*inner.
step;
275 if (v[i]!=predicted_v) {
276 inner.
stop = predicted_v;
283 outer.
stop = v.back();
287 }
while (outer.
stop % outer.
step!=0);
288 return std::make_pair(inner, outer);
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
Class representing a Slice.
void serialize(SerializingStream &s) const
Serialize an object.
Slice operator-(casadi_int i) const
Substract.
size_t size() const
Get number of elements.
casadi_int scalar(casadi_int len) const
Get scalar (if is_scalar)
bool is_empty() const
Check if slice is empty.
Slice apply(casadi_int len, bool ind1=false) const
Apply concrete length.
casadi_int stop
stop value: use std::numeric_limits<casadi_int>::max() to indicate unboundedness
Slice()
Default constructor - all elements.
void disp(std::ostream &stream, bool more=false) const
Print a description of the object.
static Slice deserialize(DeserializingStream &s)
Deserialize without type information.
Slice operator*(casadi_int i) const
std::vector< casadi_int > all() const
Get a vector of indices.
bool is_scalar(casadi_int len) const
Is the slice a scalar.
casadi_int start
start value: negative values will get added to length
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
bool CASADI_EXPORT is_slice(const IM &x, bool ind1=false)
Is the IM a Slice.
bool CASADI_EXPORT is_slice2(const std::vector< casadi_int > &v)
Check if an index vector can be represented more efficiently as two nested slices.
std::string str(const T &v)
String representation, any type.
std::pair< Slice, Slice > CASADI_EXPORT to_slice2(const std::vector< casadi_int > &v)
Construct nested slices from an index vector (requires is_slice2(v) to be true)
Slice CASADI_EXPORT to_slice(const IM &x, bool ind1=false)
Convert IM to Slice.