1 /* Sparse_Row class declaration.
2    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3    Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_Sparse_Row_defs_hh
25 #define PPL_Sparse_Row_defs_hh 1
26 
27 #include "Sparse_Row_types.hh"
28 
29 #include "CO_Tree_defs.hh"
30 #include "Coefficient_defs.hh"
31 #include "Dense_Row_types.hh"
32 
33 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
34 //! A finite sparse sequence of coefficients.
35 /*! \ingroup PPL_CXX_interface
36   This class is implemented using a CO_Tree. See the documentation of CO_Tree
37   for details on the implementation and the performance.
38 
39   This class is a drop-in replacement of Dense_Row, meaning that code
40   using Dense_Row can be ported to Sparse_Row changing only the type.
41   The resulting code will work, but probably needs more CPU and memory (it
42   does not exploit the sparse representation yet).
43 
44   To take advantage of the sparse representation, the client code must then be
45   modified to use methods which can have a faster implementation on sparse
46   data structures.
47 
48   The main changes are the replacement of calls to operator[] with calls to
49   find(), lower_bound() or insert(), using hint iterators when possible.
50   Sequential scanning of rows should probably be implemented using iterators
51   rather than indexes, to improve performance.
52   reset() should be called to zero elements.
53 
54   \see Sparse_Matrix
55   \see CO_Tree
56 */
57 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
58 class Parma_Polyhedra_Library::Sparse_Row {
59 
60 public:
61 
62   //! An %iterator on the row elements
63   /*!
64     This %iterator skips non-stored zeroes.
65     \see CO_Tree::iterator
66   */
67   typedef CO_Tree::iterator iterator;
68 
69   //! A const %iterator on the row elements
70   /*!
71     This %iterator skips non-stored zeroes.
72     \see CO_Tree::const_iterator
73   */
74   typedef CO_Tree::const_iterator const_iterator;
75 
76   //! Constructs a row with the specified size.
77   /*!
78     \param n
79     The size for the new row.
80 
81     The row will contain only non-stored zeroes.
82 
83     This constructor takes \f$O(1)\f$ time.
84   */
85   explicit Sparse_Row(dimension_type n = 0);
86 
87   //! Constructs a row with the specified size.
88   /*!
89     \param n
90     The size for the new row.
91 
92     \param capacity
93     It is ignored. This parameter is needed for compatibility with Dense_Row.
94 
95     The row will contain only non-stored zeroes.
96 
97     This constructor takes \f$O(1)\f$ time.
98   */
99   Sparse_Row(dimension_type n, dimension_type capacity);
100 
101   //! Copy constructor with specified capacity.
102   /*!
103     It is assumed that \p capacity is greater than or equal to
104     the size of \p y.
105   */
106   Sparse_Row(const Sparse_Row& y, dimension_type capacity);
107 
108   //! Copy constructor with specified size and capacity.
109   /*!
110     It is assumed that \p sz is less than or equal to \p capacity.
111   */
112   Sparse_Row(const Sparse_Row& y, dimension_type sz, dimension_type capacity);
113 
114   //! Constructor from a Dense_Row.
115   /*!
116     \param row
117     The row that will be copied into *this.
118 
119     This constructor takes \f$O(n)\f$ time. Note that constructing of a row of
120     zeroes and then inserting n elements costs \f$O(n*\log^2 n)\f$ time.
121   */
122   explicit Sparse_Row(const Dense_Row& row);
123 
124   //! Copy constructor from a Dense_Row with specified size and capacity.
125   /*!
126     It is assumed that \p sz is less than or equal to \p capacity.
127   */
128   Sparse_Row(const Dense_Row& y, dimension_type sz, dimension_type capacity);
129 
130   Sparse_Row& operator=(const Dense_Row& row);
131 
132   //! Swaps *this and x.
133   /*!
134     \param x
135     The row that will be swapped with *this.
136 
137     This method takes \f$O(1)\f$ time.
138   */
139   void m_swap(Sparse_Row& x);
140 
141   //! Returns the size of the row.
142   /*!
143     This method takes \f$O(1)\f$ time.
144   */
145   dimension_type size() const;
146 
147   //! Returns the number of elements explicitly stored in the row.
148   /*!
149     This is equivalent to std::distance(begin(), end()), but it's much faster.
150 
151     This method takes \f$O(1)\f$ time.
152   */
153   dimension_type num_stored_elements() const;
154 
155   //! Resizes the row to the specified size.
156   /*!
157     \param n
158     The new size for the row.
159 
160     This method takes \f$O(k*\log^2 n)\f$ amortized time when shrinking the
161     row and removing the trailing k elements.
162     It takes \f$O(1)\f$ time when enlarging the row.
163   */
164   void resize(dimension_type n);
165 
166   //! Resizes the row to size \p n.
167   /*!
168     \param n
169     The new size for the row.
170 
171     This method, with this signature, is needed for compatibility with
172     Dense_Row.
173 
174     This method takes \f$O(1)\f$ time.
175   */
176   void expand_within_capacity(dimension_type n);
177 
178   //! Resizes the row to size \p n.
179   /*!
180     \param n
181     The new size for the row.
182 
183     This method, with this signature, is needed for compatibility with
184     Dense_Row.
185 
186     This method takes \f$O(k*\log^2 n)\f$ amortized time where k is the number
187     of removed elements.
188   */
189   void shrink(dimension_type n);
190 
191   /*!
192     \brief Deletes the i-th element from the row, shifting the next elements
193            to the left.
194 
195     \param i
196     The index of the element that will be deleted.
197 
198     The size of the row is decreased by 1.
199 
200     This operation invalidates existing iterators.
201 
202     This method takes \f$O(k+\log^2 n)\f$ amortized time, where k is the
203     number of elements with index greater than i.
204   */
205   void delete_element_and_shift(dimension_type i);
206 
207   //! Adds \p n zeroes before index \p i.
208   /*!
209     \param n
210     The number of non-stored zeroes that will be added to the row.
211 
212     \param i
213     The index of the element before which the zeroes will be added.
214 
215     Existing elements with index greater than or equal to \p i are shifted to
216     the right by \p n positions. The size is increased by \p n.
217 
218     Existing iterators are not invalidated, but are shifted to the right
219     by \p n if they pointed at or after index \p i (i.e., they point to
220     the same, possibly shifted, values as before).
221 
222     This method takes \f$O(k + \log m)\f$ expected time, where \f$k\f$ is
223     the number of elements with index greater than or equal to \p i and
224     \f$m\f$ the number of stored elements.
225   */
226   void add_zeroes_and_shift(dimension_type n, dimension_type i);
227 
228   //! Returns an %iterator that points at the first stored element.
229   /*!
230     This method takes \f$O(1)\f$ time.
231   */
232   iterator begin();
233 
234   //! Returns an %iterator that points after the last stored element.
235   /*!
236     This method always returns a reference to the same internal %iterator,
237     that is kept valid.
238     Client code can keep a const reference to that %iterator instead of
239     keep updating a local %iterator.
240 
241     This method takes \f$O(1)\f$ time.
242   */
243   const iterator& end();
244 
245   //! Equivalent to <CODE>cbegin()</CODE>.
246   const_iterator begin() const;
247 
248   //! Equivalent to <CODE>cend()</CODE>.
249   const const_iterator& end() const;
250 
251   //! Returns an %iterator that points at the first element.
252   /*!
253     This method takes \f$O(1)\f$ time.
254   */
255   const_iterator cbegin() const;
256 
257   //! Returns an %iterator that points after the last element.
258   /*!
259     This method always returns a reference to the same internal %iterator,
260     that is updated at each operation that modifies the structure.
261     Client code can keep a const reference to that %iterator instead of
262     keep updating a local %iterator.
263 
264     This method takes \f$O(1)\f$ time.
265   */
266   const const_iterator& cend() const;
267 
268   //! Returns the size() of the largest possible Sparse_Row.
269   static dimension_type max_size();
270 
271   //! Resets all the elements of this row.
272   /*!
273     This method takes \f$O(n)\f$ time.
274   */
275   void clear();
276 
277   //! Gets a reference to the i-th element.
278   /*!
279     \param i
280     The index of the desired element.
281 
282     For read-only access it's better to use get(), that avoids allocating
283     space for zeroes.
284 
285     If possible, use the insert(), find() or lower_bound() methods with
286     a hint instead of this, to improve performance.
287 
288     This operation invalidates existing iterators.
289 
290     This method takes \f$O(\log n)\f$ amortized time when there is already an
291     element with index \p i, and \f$O(\log^2 n)\f$ otherwise.
292   */
293   Coefficient& operator[](dimension_type i);
294 
295   //! Equivalent to <CODE>get(i)</CODE>, provided for convenience.
296   /*!
297     This method takes \f$O(\log n)\f$ time.
298   */
299   Coefficient_traits::const_reference operator[](dimension_type i) const;
300 
301   //! Gets the i-th element in the sequence.
302   /*!
303     \param i
304     The index of the desired element.
305 
306     If possible, use the insert(), find() or lower_bound() methods with
307     a hint instead of this, to improve performance.
308 
309     This method takes \f$O(\log n)\f$ time.
310   */
311   Coefficient_traits::const_reference get(dimension_type i) const;
312 
313   //! Looks for an element with index i.
314   /*!
315     \param i
316     The index of the desired element.
317 
318     If possible, use the find() method that takes a hint %iterator, to improve
319     performance.
320 
321     This method takes \f$O(\log n)\f$ time.
322   */
323   iterator find(dimension_type i);
324 
325   //! Looks for an element with index i.
326   /*!
327     \param i
328     The index of the desired element.
329 
330     \param itr
331     It is used as a hint. This method will be faster if the searched element
332     is near to \p itr.
333 
334     The value of \p itr does not affect the result of this method, as long it
335     is a valid %iterator for this row. \p itr may even be end().
336 
337     This method takes \f$O(\log n)\f$ time.
338     If the distance between \p itr and the searched position is \f$O(1)\f$,
339     this method takes \f$O(1)\f$ time.
340   */
341   iterator find(iterator itr, dimension_type i);
342 
343   //! Looks for an element with index i.
344   /*!
345     \param i
346     The index of the desired element.
347 
348     If possible, use the find() method that takes a hint %iterator, to improve
349     performance.
350 
351     This method takes \f$O(\log n)\f$ time.
352   */
353   const_iterator find(dimension_type i) const;
354 
355   //! Looks for an element with index i.
356   /*!
357     \param i
358     The index of the desired element.
359 
360     \param itr
361     It is used as a hint. This method will be faster if the searched element
362     is near to \p itr.
363 
364     The value of \p itr does not affect the result of this method, as long it
365     is a valid %iterator for this row. \p itr may even be end().
366 
367     This method takes \f$O(\log n)\f$ time.
368     If the distance between \p itr and the searched position is \f$O(1)\f$,
369     this method takes \f$O(1)\f$ time.
370   */
371   const_iterator find(const_iterator itr, dimension_type i) const;
372 
373   //! Lower bound of index i.
374   /*!
375     \param i
376     The index of the desired element.
377 
378     \returns an %iterator to the first element with index greater than or
379              equal to i.
380              If there are no such elements, returns end().
381 
382     If possible, use the find() method that takes a hint %iterator, to improve
383     performance.
384 
385     This method takes \f$O(\log n)\f$ time.
386   */
387   iterator lower_bound(dimension_type i);
388 
389   //! Lower bound of index i.
390   /*!
391     \param i
392     The index of the desired element.
393 
394     \param itr
395     It is used as a hint. This method will be faster if the searched element
396     is near to \p itr.
397 
398     \returns an %iterator to the first element with index greater than or
399              equal to i.
400              If there are no such elements, returns end().
401 
402     The value of \p itr does not affect the result of this method, as long it
403     is a valid %iterator for this row. \p itr may even be end().
404 
405     This method takes \f$O(\log n)\f$ time.
406     If the distance between \p itr and the searched position is \f$O(1)\f$,
407     this method takes \f$O(1)\f$ time.
408   */
409   iterator lower_bound(iterator itr, dimension_type i);
410 
411   //! Lower bound of index i.
412   /*!
413 
414     \param i
415     The index of the desired element.
416 
417     \returns an %iterator to the first element with index greater than or
418              equal to i.
419              If there are no such elements, returns end().
420 
421     If possible, use the find() method that takes a hint %iterator, to improve
422     performance.
423 
424     This method takes \f$O(\log n)\f$ time.
425   */
426   const_iterator lower_bound(dimension_type i) const;
427 
428   //! Lower bound of index i.
429   /*!
430     \param i
431     The index of the desired element.
432 
433     \param itr
434     It is used as a hint. This method will be faster if the searched element
435     is near to \p itr.
436 
437     \returns an %iterator to the first element with index greater than or
438              equal to i.
439              If there are no such elements, returns end().
440 
441     The value of \p itr does not affect the result of this method, as long it
442     is a valid %iterator for this row. \p itr may even be end().
443 
444     This method takes \f$O(\log n)\f$ time.
445     If the distance between \p itr and the searched position is \f$O(1)\f$,
446     this method takes \f$O(1)\f$ time.
447   */
448   const_iterator lower_bound(const_iterator itr, dimension_type i) const;
449 
450   //! Equivalent to <CODE>(*this)[i] = x; find(i)</CODE>, but faster.
451   /*!
452     \param i
453     The index of the desired element.
454 
455     \param x
456     The value that will be associated to the element.
457 
458     If possible, use versions of this method that take a hint, to improve
459     performance.
460 
461     This operation invalidates existing iterators.
462 
463     This method takes \f$O(\log^2 n)\f$ amortized time.
464   */
465   iterator insert(dimension_type i, Coefficient_traits::const_reference x);
466 
467   //! Equivalent to <CODE>(*this)[i] = x; find(i)</CODE>, but faster.
468   /*!
469     \param i
470     The index of the desired element.
471 
472     \param x
473     The value that will be associated to the element.
474 
475     \param itr
476     It is used as a hint. This method will be faster if the searched element
477     is near to \p itr, even faster than <CODE>(*this)[i] = x</CODE>.
478 
479     The value of \p itr does not affect the result of this method, as long it
480     is a valid %iterator for this row. \p itr may even be end().
481 
482     This operation invalidates existing iterators.
483 
484     This method takes \f$O(\log^2 n)\f$ amortized time. If the distance
485     between \p itr and the searched position is \f$O(1)\f$ and the row already
486     contains an element with this index, this method takes \f$O(1)\f$ time.
487   */
488   iterator insert(iterator itr, dimension_type i,
489                   Coefficient_traits::const_reference x);
490 
491   //! Equivalent to <CODE>(*this)[i]; find(i)</CODE>, but faster.
492   /*!
493     \param i
494     The index of the desired element.
495 
496     If possible, use versions of this method that take a hint, to improve
497     performance.
498 
499     This operation invalidates existing iterators.
500 
501     This method takes \f$O(\log^2 n)\f$ amortized time.
502   */
503   iterator insert(dimension_type i);
504 
505   //! Equivalent to <CODE>(*this)[i]; find(i)</CODE>, but faster.
506   /*!
507     \param i
508     The index of the desired element.
509 
510     \param itr
511     It is used as a hint. This method will be faster if the searched element
512     is near to \p itr, even faster than <CODE>(*this)[i]</CODE>.
513 
514     The value of \p itr does not affect the result of this method, as long it
515     is a valid %iterator for this row. \p itr may even be end().
516 
517     This operation invalidates existing iterators.
518 
519     This method takes \f$O(\log^2 n)\f$ amortized time. If the distance
520     between \p itr and the searched position is \f$O(1)\f$ and the row already
521     contains an element with this index, this method takes \f$O(1)\f$ time.
522   */
523   iterator insert(iterator itr, dimension_type i);
524 
525   //! Swaps the i-th element with the j-th element.
526   /*!
527     \param i
528     The index of an element.
529 
530     \param j
531     The index of another element.
532 
533     This operation invalidates existing iterators.
534 
535     This method takes \f$O(\log^2 n)\f$ amortized time.
536   */
537   void swap_coefficients(dimension_type i, dimension_type j);
538 
539   //! Equivalent to swap(i,itr.index()), but it assumes that
540   //! lower_bound(i)==itr.
541   /*!
542     Iterators that pointed to the itr.index()-th element remain valid
543     but now point to the i-th element. Other iterators are unaffected.
544 
545     This method takes \f$O(1)\f$ time.
546   */
547   void fast_swap(dimension_type i, iterator itr);
548 
549   //! Swaps the element pointed to by i with the element pointed to by j.
550   /*!
551     \param i
552     An %iterator pointing to an element.
553 
554     \param j
555     An %iterator pointing to another element.
556 
557     This method takes \f$O(1)\f$ time.
558   */
559   void swap_coefficients(iterator i, iterator j);
560 
561   //! Resets to zero the value pointed to by i.
562   /*!
563     \param i
564     An %iterator pointing to the element that will be reset (not stored
565     anymore).
566 
567     By calling this method instead of getting a reference to the value and
568     setting it to zero, the element will no longer be stored.
569 
570     This operation invalidates existing iterators.
571 
572     This method takes \f$O(\log^2 n)\f$ amortized time.
573   */
574   iterator reset(iterator i);
575 
576   //! Resets to zero the values in the range [first,last).
577   /*!
578     \param first
579     An %iterator pointing to the first element to reset.
580 
581     \param last
582     An %iterator pointing after the last element to reset.
583 
584     By calling this method instead of getting a reference to the values and
585     setting them to zero, the elements will no longer be stored.
586 
587     This operation invalidates existing iterators.
588 
589     This method takes \f$O(k*\log^2 n)\f$ amortized time, where k is the
590     number of elements in [first,last).
591   */
592   iterator reset(iterator first, iterator last);
593 
594   //! Resets to zero the i-th element.
595   /*!
596     \param i
597     The index of the element to reset.
598 
599     By calling this method instead of getting a reference to the value and
600     setting it to zero, the element will no longer be stored.
601 
602     This operation invalidates existing iterators.
603 
604     This method takes \f$O(\log^2 n)\f$ amortized time.
605   */
606   void reset(dimension_type i);
607 
608   //! Resets to zero the elements with index greater than or equal to i.
609   /*!
610     \param i
611     The index of the first element to reset.
612 
613     By calling this method instead of getting a reference to the values and
614     setting them to zero, the elements will no longer be stored.
615 
616     This operation invalidates existing iterators.
617 
618     This method takes \f$O(k*\log^2 n)\f$ amortized time, where k is the
619     number of elements with index greater than or equal to i.
620   */
621   void reset_after(dimension_type i);
622 
623   //! Normalizes the modulo of coefficients so that they are mutually prime.
624   /*!
625     Computes the Greatest Common Divisor (GCD) among the elements of the row
626     and normalizes them by the GCD itself.
627 
628     This method takes \f$O(n)\f$ time.
629   */
630   void normalize();
631 
632   //! Calls g(x[i],y[i]), for each i.
633   /*!
634     \param y
635     The row that will be combined with *this.
636 
637     \param f
638     A functor that should take a Coefficient&.
639     f(c1) must be equivalent to g(c1, 0).
640 
641     \param g
642     A functor that should take a Coefficient& and a
643     Coefficient_traits::const_reference.
644     g(c1, c2) must do nothing when c1 is zero.
645 
646     This method takes \f$O(n*\log^2 n)\f$ time.
647 
648     \note
649     The functors will only be called when necessary, assuming the requested
650     properties hold.
651 
652     \see combine_needs_second
653     \see combine
654   */
655   template <typename Func1, typename Func2>
656   void combine_needs_first(const Sparse_Row& y,
657                            const Func1& f, const Func2& g);
658 
659   //! Calls g(x[i],y[i]), for each i.
660   /*!
661     \param y
662     The row that will be combined with *this.
663 
664     \param g
665     A functor that should take a Coefficient& and a
666     Coefficient_traits::const_reference.
667     g(c1, 0) must do nothing, for every c1.
668 
669     \param h
670     A functor that should take a Coefficient& and a
671     Coefficient_traits::const_reference.
672     h(c1, c2) must be equivalent to g(c1, c2) when c1 is zero.
673 
674     This method takes \f$O(n*\log^2 n)\f$ time.
675 
676     \note
677     The functors will only be called when necessary, assuming the requested
678     properties hold.
679 
680     \see combine_needs_first
681     \see combine
682   */
683   template <typename Func1, typename Func2>
684   void combine_needs_second(const Sparse_Row& y,
685                             const Func1& g, const Func2& h);
686 
687   //! Calls g(x[i],y[i]), for each i.
688   /*!
689     \param y
690     The row that will be combined with *this.
691 
692     \param f
693     A functor that should take a Coefficient&.
694     f(c1) must be equivalent to g(c1, 0).
695 
696     \param g
697     A functor that should take a Coefficient& and a
698     Coefficient_traits::const_reference.
699     g(c1, c2) must do nothing when both c1 and c2 are zero.
700 
701     \param h
702     A functor that should take a Coefficient& and a
703     Coefficient_traits::const_reference.
704     h(c1, c2) must be equivalent to g(c1, c2) when c1 is zero.
705 
706     This method takes \f$O(n*\log^2 n)\f$ time.
707 
708     \note
709     The functors will only be called when necessary, assuming the requested
710     properties hold.
711 
712     \see combine_needs_first
713     \see combine_needs_second
714   */
715   template <typename Func1, typename Func2, typename Func3>
716   void combine(const Sparse_Row& y,
717                const Func1& f, const Func2& g, const Func3& h);
718 
719   //! Executes <CODE>(*this)[i] = (*this)[i]*coeff1 + y[i]*coeff2</CODE>, for
720   //! each i.
721   /*!
722     \param y
723     The row that will be combined with *this.
724 
725     \param coeff1
726     The coefficient used for elements of *this.
727     This must not be 0.
728 
729     \param coeff2
730     The coefficient used for elements of y.
731     This must not be 0.
732 
733     This method takes \f$O(n*\log^2 n)\f$ time.
734 
735     \note
736     The functors will only be called when necessary.
737     This method can be implemented in user code, too. It is provided for
738     convenience only.
739 
740     \see combine_needs_first
741     \see combine_needs_second
742     \see combine
743   */
744   void linear_combine(const Sparse_Row& y,
745                       Coefficient_traits::const_reference coeff1,
746                       Coefficient_traits::const_reference coeff2);
747 
748   //! Equivalent to <CODE>(*this)[i] = (*this)[i] * c1 + y[i] * c2</CODE>,
749   //! for each i in [start, end).
750   /*!
751     This method, unlike the other linear_combine() method, detects when
752     coeff1==1 and/or coeff2==1 or coeff2==-1 in order to save some work.
753   */
754   void linear_combine(const Sparse_Row& y,
755                       Coefficient_traits::const_reference c1,
756                       Coefficient_traits::const_reference c2,
757                       dimension_type start, dimension_type end);
758 
759   PPL_OUTPUT_DECLARATIONS
760 
761   //! Loads the row from an ASCII representation generated using ascii_dump().
762   /*!
763     \param s
764     The stream from which the ASCII representation will be loaded.
765   */
766   bool ascii_load(std::istream& s);
767 
768   //! Returns the size in bytes of the memory managed by \p *this.
769   /*!
770     This method takes \f$O(n)\f$ time.
771   */
772   memory_size_type external_memory_in_bytes() const;
773 
774   //! Returns the size in bytes of the memory managed by \p *this.
775   /*!
776     This method is provided for compatibility with Dense_Row.
777 
778     This method takes \f$O(n)\f$ time.
779 
780     \param capacity
781     This parameter is ignored.
782   */
783   memory_size_type external_memory_in_bytes(dimension_type capacity) const;
784 
785   //! Returns the size in bytes of the memory managed by \p *this.
786   /*!
787     This method takes \f$O(n)\f$ time.
788   */
789   memory_size_type total_memory_in_bytes() const;
790 
791   //! Returns the size in bytes of the memory managed by \p *this.
792   /*!
793     This method is provided for compatibility with Dense_Row.
794 
795     This method takes \f$O(n)\f$ time.
796 
797     \param capacity
798     This parameter is ignored.
799   */
800   memory_size_type total_memory_in_bytes(dimension_type capacity) const;
801 
802   //! Checks the invariant.
803   bool OK() const;
804 
805   //! Checks the invariant.
806   /*!
807     This method is provided for compatibility with Dense_Row.
808 
809     \param capacity
810     This parameter is ignored.
811   */
812   bool OK(dimension_type capacity) const;
813 
814 private:
815   //! The tree used to store the elements.
816   CO_Tree tree;
817 
818   //! The size of the row.
819   /*!
820     The elements contained in this row have indexes that are less than size_.
821   */
822   dimension_type size_;
823 };
824 
825 
826 namespace Parma_Polyhedra_Library {
827 
828 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
829 //! Swaps \p x with \p y.
830 /*! \relates Sparse_Row */
831 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
832 void swap(Parma_Polyhedra_Library::Sparse_Row& x,
833           Parma_Polyhedra_Library::Sparse_Row& y);
834 
835 void swap(Parma_Polyhedra_Library::Sparse_Row& x,
836           Parma_Polyhedra_Library::Dense_Row& y);
837 
838 void swap(Parma_Polyhedra_Library::Dense_Row& x,
839           Parma_Polyhedra_Library::Sparse_Row& y);
840 
841 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
842 //! Returns <CODE>true</CODE> if and only if \p x and \p y are equal.
843 /*! \relates Sparse_Row */
844 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
845 bool operator==(const Sparse_Row& x, const Sparse_Row& y);
846 
847 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
848 //! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
849 /*! \relates Sparse_Row */
850 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
851 bool operator!=(const Sparse_Row& x, const Sparse_Row& y);
852 
853 bool operator==(const Dense_Row& x, const Sparse_Row& y);
854 bool operator!=(const Dense_Row& x, const Sparse_Row& y);
855 
856 bool operator==(const Sparse_Row& x, const Dense_Row& y);
857 bool operator!=(const Sparse_Row& x, const Dense_Row& y);
858 
859 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
860 //! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
861 //! for each i in [start, end).
862 /*! \relates Sparse_Row */
863 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
864 void linear_combine(Sparse_Row& x, const Dense_Row& y,
865                     Coefficient_traits::const_reference coeff1,
866                     Coefficient_traits::const_reference coeff2);
867 
868 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
869 //! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
870 //! for each i in [start, end).
871 /*! \relates Sparse_Row
872   This function detects when coeff1==1 and/or coeff2==1 or coeff2==-1 in
873   order to save some work.
874 */
875 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
876 void linear_combine(Sparse_Row& x, const Dense_Row& y,
877                     Coefficient_traits::const_reference c1,
878                     Coefficient_traits::const_reference c2,
879                     dimension_type start, dimension_type end);
880 
881 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
882 //! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
883 //! for each i in [start, end).
884 /*! \relates Sparse_Row */
885 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
886 void linear_combine(Dense_Row& x, const Sparse_Row& y,
887                     Coefficient_traits::const_reference coeff1,
888                     Coefficient_traits::const_reference coeff2);
889 
890 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
891 //! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
892 //! for each i in [start, end).
893 /*! \relates Sparse_Row
894   This function detects when coeff1==1 and/or coeff2==1 or coeff2==-1 in
895   order to save some work.
896 */
897 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
898 void linear_combine(Dense_Row& x, const Sparse_Row& y,
899                     Coefficient_traits::const_reference c1,
900                     Coefficient_traits::const_reference c2,
901                     dimension_type start, dimension_type end);
902 
903 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
904 //! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
905 //! for each i in [start, end).
906 /*! \relates Sparse_Row */
907 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
908 void linear_combine(Sparse_Row& x, const Sparse_Row& y,
909                     Coefficient_traits::const_reference coeff1,
910                     Coefficient_traits::const_reference coeff2);
911 
912 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
913 //! Equivalent to <CODE>x[i] = x[i] * c1 + y[i] * c2</CODE>,
914 //! for each i in [start, end).
915 /*! \relates Sparse_Row
916   This function detects when coeff1==1 and/or coeff2==1 or coeff2==-1 in
917   order to save some work.
918 */
919 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
920 void linear_combine(Sparse_Row& x, const Sparse_Row& y,
921                     Coefficient_traits::const_reference c1,
922                     Coefficient_traits::const_reference c2,
923                     dimension_type start, dimension_type end);
924 
925 } // namespace Parma_Polyhedra_Library
926 
927 #include "Sparse_Row_inlines.hh"
928 #include "Sparse_Row_templates.hh"
929 
930 #endif // !defined(PPL_Sparse_Row_defs_hh)
931