@@ -30,6 +30,8 @@ class lar_term {
30
30
// the column index related to the term
31
31
lpvar m_j = -1 ;
32
32
public:
33
+
34
+
33
35
// the column index related to the term
34
36
lpvar j () const { return m_j; }
35
37
void set_j (unsigned j) {
@@ -92,8 +94,6 @@ class lar_term {
92
94
}
93
95
// constructors
94
96
lar_term () = default ;
95
- <<<<<<< HEAD
96
- =======
97
97
lar_term (lar_term&& other) noexcept = default ;
98
98
// copy assignment operator
99
99
lar_term& operator =(const lar_term& other) = default ;
@@ -106,7 +106,6 @@ class lar_term {
106
106
}
107
107
}
108
108
109
- >>>>>>> 956229fb6 (test that pivoting is correct in dioph_eq.cpp)
110
109
lar_term (const vector<std::pair<mpq, unsigned >>& coeffs) {
111
110
for (auto const & p : coeffs) {
112
111
add_monomial (p.first , p.second );
@@ -257,10 +256,9 @@ class lar_term {
257
256
m_coeffs.reset ();
258
257
}
259
258
260
- class ival {
259
+ struct ival {
261
260
lpvar m_var;
262
261
const mpq & m_coeff;
263
- public:
264
262
ival (lpvar var, const mpq & val) : m_var(var), m_coeff(val) { }
265
263
lpvar j () const { return m_var; }
266
264
lpvar var () const { return m_var; }
@@ -274,7 +272,12 @@ class lar_term {
274
272
const_iterator operator ++() { const_iterator i = *this ; m_it++; return i; }
275
273
const_iterator operator ++(int ) { m_it++; return *this ; }
276
274
const_iterator (u_map<mpq>::iterator it) : m_it(it) {}
277
- bool operator !=(const const_iterator &other) const { return m_it != other.m_it ; }
275
+ bool operator ==(const const_iterator &other) const { return m_it == other.m_it ; }
276
+ bool operator !=(const const_iterator &other) const { return !(*this == other); }
277
+ // Return a pointer to the same object returned by operator*.
278
+ const ival* operator ->() const {
279
+ return &(**this );
280
+ }
278
281
};
279
282
280
283
bool is_normalized () const {
@@ -316,5 +319,101 @@ class lar_term {
316
319
}
317
320
const_iterator begin () const { return m_coeffs.begin ();}
318
321
const_iterator end () const { return m_coeffs.end (); }
322
+ // This iterator yields all (coefficient, variable) pairs
323
+ // plus one final pair: (mpq(-1), j()).
324
+ class ext_const_iterator {
325
+ // We'll store a reference to the lar_term, and an
326
+ // iterator into m_coeffs. Once we reach end of m_coeffs,
327
+ // we'll yield exactly one extra pair, then we are done.
328
+ const lar_term& m_term;
329
+ lar_term::const_iterator m_it;
330
+ bool m_done; // Have we gone past m_coeffs?
331
+
332
+ public:
333
+ // Construct either a "begin" iterator (end=false) or "end" iterator (end=true).
334
+ ext_const_iterator (const lar_term& t, bool is_end)
335
+ : m_term(t)
336
+ , m_it(is_end ? t.end() : t.begin())
337
+ , m_done(false )
338
+ {
339
+ // If it is_end == true, we represent a genuine end-iterator.
340
+ if (is_end) {
341
+ m_done = true ;
342
+ }
343
+ }
344
+
345
+ // Compare iterators. Two iterators are equal if both are "done" or hold the same internal iterator.
346
+ bool operator ==(ext_const_iterator const &other) const {
347
+ // They are equal if they are both at the special extra pair or both at the same spot in m_coeffs.
348
+ if (m_done && other.m_done ) {
349
+ return true ;
350
+ }
351
+ return (!m_done && !other.m_done && m_it == other.m_it );
352
+ }
353
+
354
+ bool operator !=(ext_const_iterator const &other) const {
355
+ return !(*this == other);
356
+ }
357
+
358
+ // Return the element we point to:
359
+ // 1) If we haven't finished m_coeffs, yield (coefficient, var).
360
+ // 2) If we've iterated past m_coeffs exactly once, return (mpq(-1), j()).
361
+ auto operator *() const {
362
+ if (!m_done && m_it != m_term.end ()) {
363
+ // Normal monomial from m_coeffs
364
+ // Each entry is of type { m_value, m_key } in this context
365
+ return *m_it;
366
+ }
367
+ else {
368
+ // We've gone past normal entries, so return the extra pair
369
+ // (mpq(-1), j()).
370
+ return ival (m_term.j (), rational::minus_one ());
371
+ }
372
+ }
373
+
374
+ // Pre-increment
375
+ ext_const_iterator& operator ++() {
376
+ if (!m_done && m_it != m_term.end ()) {
377
+ ++m_it;
378
+ }
379
+ else {
380
+ // We were about to return that extra pair:
381
+ // after we move once more, we are done.
382
+ m_done = true ;
383
+ }
384
+ return *this ;
385
+ }
386
+
387
+ // Post-increment
388
+ ext_const_iterator operator ++(int ) {
389
+ ext_const_iterator temp (*this );
390
+ ++(*this );
391
+ return temp;
392
+ }
393
+ };
394
+
395
+ // Return the begin/end of our extended iteration.
396
+ // begin: starts at first real monomial
397
+ // end: marks a finalized end of iteration
398
+ ext_const_iterator ext_coeffs_begin () const {
399
+ return ext_const_iterator (*this , /* is_end=*/ false );
400
+ }
401
+ ext_const_iterator ext_coeffs_end () const {
402
+ return ext_const_iterator (*this , /* is_end=*/ true );
403
+ }
404
+
405
+ // Provide a small helper for "range-based for":
406
+ // for (auto & [coef, var] : myTerm.ext_coeffs()) { ... }
407
+ struct ext_range {
408
+ ext_const_iterator b, e;
409
+ ext_const_iterator begin () const { return b; }
410
+ ext_const_iterator end () const { return e; }
411
+ };
412
+
413
+ // return an object that can be used in range-based for loops
414
+ ext_range ext_coeffs () const {
415
+ return { ext_coeffs_begin (), ext_coeffs_end () };
416
+ }
417
+
319
418
};
320
419
}
0 commit comments