1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - Bernard HUGUENEY
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15 #ifndef MATRIXITERATORS_HXX
16 #define MATRIXITERATORS_HXX
17 
18 #include <complex>
19 #include <utility>
20 #include <iterator>
21 
22 #include <Eigen/Sparse>
23 #include "double.hxx"
24 #include "sparse.hxx"
25 
26 
27 /*
28   In order to reuse code for the various Matrix Classes, we need some uniform API to access elements.
29   We cannot use runtime polymorphism (with dynamic dispatching) because of the runtime cost so we have to
30   use compile-time polymorphism with templates.
31 
32   The provided free function templates get<>() and set<>() provide such an uniform API.
33 
34   In order to perform element-wise operations on Matrices (copy, partial or total assignments, etc.),
35   we provide an iterator. To enable reading (with get<>()) or writiting (with set<>()) we provide an Accessor<> proxy.
36 
37   As is it common to iterate over a sub-matrix according to indices given by a Scilab variable (Double) we provide
38   an iterator created from such a variable (IteratorFromVar).
39  */
40 template<typename T>
41 struct UndefinedAccessorForType {};
42 
43 /**
44    This free function overloads perform read access into a 2D container, using 0-based indices.
45    @param s the 2D structure used to fetch a value of type V.
46    @param r : the row (0 based)
47    @param c : the column (0 based)
48    @return : the value of type V at row r and column c of structure s
49 */
50 
51 template<typename V, typename S> V get(S SPARSE_CONST&, int, int)
52 {
53     return UndefinedAccessorForType<S>();
54 }
55 
get(types::Double SPARSE_CONST & d,int r,int c)56 template<> double get(types::Double SPARSE_CONST& d, int r, int c)
57 {
58     return d.getReal(r, c);
59 }
get(types::Double SPARSE_CONST & d,int r,int c)60 template<> std::complex<double> get(types::Double SPARSE_CONST& d, int r, int c)
61 {
62     return std::complex<double>(d.getReal(r, c), d.getImg(r, c));
63 }
64 
get(types::Bool SPARSE_CONST & d,int r,int c)65 template<> bool get(types::Bool SPARSE_CONST& d, int r, int c)
66 {
67     return d.get(r, c) == 1;
68 }
get(types::Bool SPARSE_CONST & d,int r,int c)69 template<> int get(types::Bool SPARSE_CONST& d, int r, int c)
70 {
71     return d.get(r, c);
72 }
get(types::SparseBool SPARSE_CONST & d,int r,int c)73 template<> bool get(types::SparseBool SPARSE_CONST& d, int r, int c)
74 {
75     return d.get(r, c);
76 }
get(types::SparseBool SPARSE_CONST & d,int r,int c)77 template<> int get(types::SparseBool SPARSE_CONST& d, int r, int c)
78 {
79     return d.get(r, c);
80 }
81 
get(types::Sparse SPARSE_CONST & s,int r,int c)82 template<> double get(types::Sparse SPARSE_CONST& s, int r, int c)
83 {
84     return s.getReal(r, c);
85 }
get(types::Sparse SPARSE_CONST & s,int r,int c)86 template<> std::complex<double> get(types::Sparse SPARSE_CONST& s, int r, int c)
87 {
88     return s.get(r, c);
89 }
90 
get(types::Sparse::RealSparse_t SPARSE_CONST & s,int r,int c)91 template<> double get(types::Sparse::RealSparse_t SPARSE_CONST&s, int r, int c)
92 {
93     return s.coeff(r, c);
94 }
get(types::Sparse::RealSparse_t SPARSE_CONST & s,int r,int c)95 template<> std::complex<double> get(types::Sparse::RealSparse_t SPARSE_CONST&s, int r, int c)
96 {
97     return std::complex<double>(s.coeff(r, c), 0.);
98 }
99 
get(types::SparseBool::BoolSparse_t SPARSE_CONST & d,int r,int c)100 template<> bool get(types::SparseBool::BoolSparse_t SPARSE_CONST& d, int r, int c)
101 {
102     return d.coeff(r, c);
103 }
104 
get(types::Sparse::CplxSparse_t SPARSE_CONST & s,int r,int c)105 template<> double get(types::Sparse::CplxSparse_t SPARSE_CONST&s, int r, int c)
106 {
107     return s.coeff(r, c).real();
108 }
get(types::Sparse::CplxSparse_t SPARSE_CONST & s,int r,int c)109 template<> std::complex<double> get(types::Sparse::CplxSparse_t SPARSE_CONST&s, int r, int c)
110 {
111     return s.coeff(r, c);
112 }
113 
114 
115 /**
116    This free function overloads perform write access into a 2D container, using 0-based indices.
117    @param s the 2D structure used to fetch a value of type V.
118    @param r : the row (0 based)
119    @param c : the column (0 based)
120    @param v : the value of type V to set at row r and column c of structure s
121    @return : true iff everything went ok (should throw otherwise anyway).
122 */
123 
124 
set(S &,int,int,V)125 template<typename S, typename V> bool set(S &, int, int, V)
126 {
127     return UndefinedAccessorForType<S>();
128 }
129 
set(types::Double & d,int r,int c,double v)130 template<> bool set(types::Double & d, int r, int c, double v)
131 {
132     return d.set(r, c, v);
133 }
set(types::Double & d,int r,int c,std::complex<double> v)134 template<> bool set(types::Double & d, int r, int c, std::complex<double> v)
135 {
136     return d.set(r, c, v.real()) && d.setImg(r, c, v.imag());
137 }
138 
set(types::Sparse & s,int r,int c,double v)139 template<> bool set(types::Sparse & s, int r, int c, double v)
140 {
141     return s.set(r, c, v);
142 }
set(types::Sparse & s,int r,int c,std::complex<double> v)143 template<> bool set(types::Sparse & s, int r, int c, std::complex<double> v)
144 {
145     return s.set(r, c, v);
146 }
set(types::Bool & d,int r,int c,bool v)147 template<> bool set(types::Bool & d, int r, int c, bool v)
148 {
149     return d.set(r, c, v);
150 }
set(types::SparseBool & d,int r,int c,bool v)151 template<> bool set(types::SparseBool & d, int r, int c, bool v)
152 {
153     return d.set(r, c, v);
154 }
set(types::Bool & d,int r,int c,int v)155 template<> bool set(types::Bool & d, int r, int c, int v)
156 {
157     return d.set(r, c, v);
158 }
set(types::SparseBool & d,int r,int c,int v)159 template<> bool set(types::SparseBool & d, int r, int c, int v)
160 {
161     return d.set(r, c, v != 0);
162 }
163 
set(types::Sparse::RealSparse_t & s,int r,int c,double v)164 template<> bool set(types::Sparse::RealSparse_t& s, int r, int c, double v)
165 {
166     if (v != 0.)
167     {
168         if (s.isCompressed() && s.coeff(r, c) == 0)
169         {
170             s.reserve(s.nonZeros() + 1);
171         }
172 
173         s.coeffRef(r, c) = v;
174     }
175     return true;
176 }
177 
set(types::Sparse::RealSparse_t & s,int r,int c,std::complex<double> v)178 template<> bool set(types::Sparse::RealSparse_t& s, int r, int c, std::complex<double> v)
179 {
180     if ( v.real() != 0.)
181     {
182         if (s.isCompressed() && s.coeff(r, c) == 0)
183         {
184             s.reserve(s.nonZeros() + 1);
185         }
186 
187         s.coeffRef(r, c) = v.real();
188     }
189     return  true;
190 }
191 // should we make this a compile error ?
set(types::Sparse::CplxSparse_t & s,int r,int c,double v)192 template<> bool set(types::Sparse::CplxSparse_t& s, int r, int c, double v)
193 {
194     if (v != 0.)
195     {
196         if (s.isCompressed() && s.coeff(r, c) == 0.)
197         {
198             s.reserve(s.nonZeros() + 1);
199         }
200 
201         s.coeffRef(r, c) = std::complex<double>(v);
202     }
203     return true;
204 }
205 
206 namespace
207 {
208 }
set(types::Sparse::CplxSparse_t & s,int r,int c,std::complex<double> v)209 template<> bool set(types::Sparse::CplxSparse_t& s, int r, int c, std::complex<double> v)
210 {
211     if (v != 0.)
212     {
213         if (s.isCompressed() && s.coeff(r, c) == 0.)
214         {
215             s.reserve(s.nonZeros() + 1);
216         }
217 
218         s.coeffRef(r, c) = v;
219     }
220     return true;
221 }
222 
set(types::SparseBool::BoolSparse_t & s,int r,int c,bool v)223 template<> bool set(types::SparseBool::BoolSparse_t& s, int r, int c, bool v)
224 {
225     if (v)
226     {
227         if (s.isCompressed() && s.coeff(r, c) == false)
228         {
229             s.reserve(s.nonZeros() + 1);
230         }
231 
232         s.coeffRef(r, c) = v;
233     }
234     return true;
235 }
236 
237 
238 
239 
rows(S SPARSE_CONST & s)240 template<typename S> inline int rows(S SPARSE_CONST&s)
241 {
242     return s.rows();
243 }
cols(S SPARSE_CONST & s)244 template<typename S> inline int cols(S SPARSE_CONST&s)
245 {
246     return s.cols();
247 }
248 
rows(types::Double SPARSE_CONST & d)249 template<> inline int rows(types::Double SPARSE_CONST&d)
250 {
251     return d.getRows();
252 }
cols(types::Double SPARSE_CONST & d)253 template<> inline int cols(types::Double SPARSE_CONST&d)
254 {
255     return d.getCols();
256 }
rows(types::Sparse SPARSE_CONST & s)257 template<> inline int rows(types::Sparse SPARSE_CONST&s)
258 {
259     return s.getRows();
260 }
cols(types::Sparse SPARSE_CONST & s)261 template<> inline int cols(types::Sparse SPARSE_CONST&s)
262 {
263     return s.getCols();
264 }
rows(types::Bool SPARSE_CONST & s)265 template<> inline int rows(types::Bool SPARSE_CONST&s)
266 {
267     return s.getRows();
268 }
cols(types::Bool SPARSE_CONST & s)269 template<> inline int cols(types::Bool SPARSE_CONST&s)
270 {
271     return s.getCols();
272 }
rows(types::SparseBool SPARSE_CONST & s)273 template<> inline int rows(types::SparseBool SPARSE_CONST&s)
274 {
275     return s.getRows();
276 }
cols(types::SparseBool SPARSE_CONST & s)277 template<> inline int cols(types::SparseBool SPARSE_CONST&s)
278 {
279     return s.getCols();
280 }
281 
282 
283 
284 /**
285   These free function overloads handle nb of rows size queries for 2D containers
286    wrapping the corresponding member function.
287    @param s : 2D structure to query
288    @return : nb of rows
289 */
290 template<typename S> inline int rows(S SPARSE_CONST&s);
291 template<> inline int rows(types::Double SPARSE_CONST&d);
292 
293 /**
294   These free function overloads handle nb of cols size queries for 2D containers
295    wrapping the corresponding member function.
296    @param s : 2D structure to query
297    @return : nb of cols
298 */
299 template<typename S> inline int cols(S SPARSE_CONST&s);
300 template<> inline int cols(types::Double SPARSE_CONST&d);
301 
302 /* this proxy struct provides read and write access (using set and get)
303    with the usual operators (operator*() and operator=() )*/
304 template<typename S, typename V> struct Accessor
305 {
306     /**
307        @param s_ : 2D structure to access
308        @param r_ : row to access
309        @param c_ ; column to access
310     */
AccessorAccessor311     Accessor(S& s_, int r_, int c_): s(s_), r(r_), c(c_) {}
312     /**
313        read accessor as a casting operator
314        @return : value of s at (r,c)
315      */
operator VAccessor316     operator V() SPARSE_CONST
317     {
318         //        std::cerr<<"reading "<<get<S,V>(s, r, c)<<" @("<<r<<","<<c<<")\n";
319         return ::get<V>(s, r, c);
320     }
321     /**
322        write accessor as an assignment operator
323        @param v : value to set at (r,c) in s.
324     */
325     template<typename Sa, typename Va>
operator =Accessor326     Accessor& operator=(Accessor<Sa, Va> const& a)
327     {
328         //        std::cerr<<"writing "<<( Va(const_cast<Accessor<Sa, Va>&>(a)))<<" @("<<r<<","<<c<<")\n";
329         //        Va tmp=const_cast<Accessor<Sa, Va>&>(a);
330         //        ::set<S,V>(s, r, c, tmp);
331         ::set<S, V>(s, r, c, Va(const_cast<Accessor<Sa, Va>&>(a)));
332         return *this;
333     }
334 
operator =Accessor335     Accessor& operator=(Accessor const& a)
336     {
337         //        std::cerr<<"writing "<<( V(const_cast<Accessor&>(a)))<<" @("<<r<<","<<c<<")\n";
338         ::set<S, V>(s, r, c, V(const_cast<Accessor&>(a)));
339         return *this;
340     }
operator =Accessor341     Accessor& operator=(V const& v)
342     {
343         //        std::cerr<<"writing "<<v<<" @("<<r<<","<<c<<")\n";
344         ::set<S, V>(s, r, c, v);
345         return *this;
346     }
347 private:
348     S& s;
349     int r, c;
350 };
351 
352 /* convenient typedef for pairs of (row, column) int values used as 2D coords */
353 typedef std::pair<int, int> Coords2D;
354 /* convenient typedef for iterator over pairs of (row, column) int values used as 2D coords */
355 typedef std::iterator<std::forward_iterator_tag, Coords2D > Coords2DIterator;
356 /**
357    Iterator over coords making a full row-wise traversal wrapping around when reaching
358    the end of the 2D container.
359  */
360 struct RowWiseFullIterator : Coords2DIterator
361 {
362     /**
363        @param cMax : size of the 2D structure
364      */
RowWiseFullIteratorRowWiseFullIterator365     RowWiseFullIterator(Coords2D cMax): c(0, 0), cMax(cMax)
366     {
367     }
368     /**
369        @param cMax : size of the 2D structure
370        @param cInit : starting coords of the traversal.
371      */
RowWiseFullIteratorRowWiseFullIterator372     RowWiseFullIterator(Coords2D cMax, Coords2D cInit): c(cInit), cMax(cMax)
373     {
374     }
375     /**
376        @param rm : nb of rows of the 2D structure
377        @param cm : nb of column of the 2D structure
378      */
RowWiseFullIteratorRowWiseFullIterator379     RowWiseFullIterator(int rm, int cm): c(0, 0), cMax(rm, cm)
380     {
381     }
382     /**
383        @param rm : nb of rows of the 2D structure
384        @param cm : nb of column of the 2D structure
385        @param rInit : starting row of the traversal
386        @param cInit : starting column of the traversal
387      */
RowWiseFullIteratorRowWiseFullIterator388     RowWiseFullIterator(int rm, int cm, int rInit, int cInit): c(rInit, cInit), cMax(rm, cm)
389     {
390     }
operator ++RowWiseFullIterator391     RowWiseFullIterator& operator++()
392     {
393         if (++c.first == cMax.first)
394         {
395             c.first = 0;
396             if (++c.second == cMax.second)
397             {
398                 /* wrap around */
399                 c.first = c.second = 0;
400             }
401         }
402         return *this;
403     }
operator ++RowWiseFullIterator404     RowWiseFullIterator operator++(int)
405     {
406         RowWiseFullIterator tmp(*this);
407         ++(*this);
408         return tmp;
409     }
operator *RowWiseFullIterator410     std::pair<int, int> operator*() const
411     {
412         return c;
413     }
414 private:
415     Coords2D c;
416     Coords2D const cMax;
417 };
418 
419 /**
420    Iterator over coords making a row-wise traversal of non zero elements of an Eigen Sparse Matrix
421  */
422 template<typename Sp>
423 struct RowWiseSparseIterator : Coords2DIterator
424 {
425     /**
426        @param sp: sparse matrix for non zero elements traversal
427      */
RowWiseSparseIteratorRowWiseSparseIterator428     RowWiseSparseIterator(Sp const& sp): sp(sp), outerIdx(0), innerIt(sp, 0)
429     {
430     }
operator ++RowWiseSparseIterator431     RowWiseSparseIterator& operator++()
432     {
433         ++innerIt;
434         if (!innerIt)
435         {
436             if (++outerIdx >= sp.outerSize())
437             {
438                 outerIdx = 0;
439             }
440             new (&innerIt) typename Sp::InnerIterator(sp, outerIdx);// innerIt= typename Sp::InnerIterator(sp, outerIdx) when Eigen will be fixed
441         }
442         return *this;
443     }
operator ++RowWiseSparseIterator444     RowWiseSparseIterator operator++(int)
445     {
446         RowWiseFullIterator tmp(*this);
447         ++(*this);
448         return tmp;
449     }
operator *RowWiseSparseIterator450     std::pair<int, int> operator*() const
451     {
452         //        std::cerr<<"sparse it r="<<innerIt.row()<<" c="<<innerIt.col()<<std::endl;
453         return std::pair<int, int>(innerIt.row(), innerIt.col());
454     }
455 private:
456     Sp const& sp;
457     typename Eigen::internal::traits<Sp>::Index outerIdx;
458     typename Sp::InnerIterator innerIt;
459 };
460 
461 /**
462    translate an iterator
463  */
464 template<typename C2DIter>
465 struct TranslatedIterator : Coords2DIterator
466 {
467     /**
468        @param C2DIter: translation as a vector of (rows, cols)
469        @param tr: translation as a vector of (rows, cols)
470      */
TranslatedIteratorTranslatedIterator471     TranslatedIterator(C2DIter const& c2dIter, Coords2D tr): it(c2dIter), tr(tr)
472     {
473     }
operator ++TranslatedIterator474     TranslatedIterator& operator++()
475     {
476         ++it;
477         return *this;
478     }
operator ++TranslatedIterator479     TranslatedIterator operator++(int)
480     {
481         TranslatedIterator tmp(*this);
482         ++(*this);
483         return tmp;
484     }
operator *TranslatedIterator485     std::pair<int, int> operator*() const
486     {
487         std::pair<int, int>res(*it);
488         res.first += tr.first;
489         res.second += tr.second;
490         //        std::cerr<<"translated it r="<< res.first<<" c="<<res.second<<std::endl;
491 
492         return res;
493     }
494 private:
495     C2DIter it;
496     Coords2D const tr;
497 };
498 
499 /**
500  * Template for iterator over 2D coords from an int*.
501  * Could handle wrap around with a length arg (i.e. to recycle values instead of raising
502  * "error 15 Submatrix incorrectly defined."
503  */
504 template<bool AsVector = false> struct Coords : Coords2DIterator
505 {
CoordsCoords506     Coords(int SPARSE_CONST* coords, int unused = 0): coords(coords), unused(unused)
507     {
508     }
509 
operator ++Coords510     Coords& operator++()
511     {
512         coords += 2;
513         return *this;
514     }
515 
operator ++Coords516     Coords& operator++(int)
517     {
518         Coords tmp(*this);
519         ++(*this);
520         return tmp;
521     }
522 
operator *Coords523     Coords2D operator*()const
524     {
525         return Coords2D(coords[0] - 1, coords[1] - 1);
526     }
527 
528 private:
529     int const* coords;
530     int unused;
531 };
532 /**
533    explicit specialization for 2D from 1D int* sequences
534    (The 2D strcture is considered as a vector)
535  */
536 template<> struct Coords<true> : Coords2DIterator
537 {
CoordsCoords538     Coords(int SPARSE_CONST* coords, int rMax): coords(coords), rMax(rMax)
539     {
540     }
541 
operator ++Coords542     Coords& operator++()
543     {
544         ++coords;
545         return *this;
546     }
547 
operator ++Coords548     Coords operator++(int)
549     {
550         Coords tmp(*this);
551         ++(*this);
552         return tmp;
553     }
554 
operator *Coords555     Coords2D operator*()const
556     {
557         return Coords2D((coords[0] - 1) % rMax, (coords[0] - 1) / rMax);
558     }
559 
560 private:
561     int const* coords;
562     int const rMax;
563 };
564 /* This 'iterator' class allows traverses the 2D containers, either
565 Rowwisefull traversal
566 or with 2D coords from another matrix
567 or with 1D coords from another vector (1x) matrix
568 to respect Double insert() API, we take int* and a bool
569 */
570 template<typename S, typename V, typename Iter>
571 struct MatrixIterator : std::iterator<std::forward_iterator_tag, V>
572 {
MatrixIteratorMatrixIterator573     MatrixIterator(S& s_, Iter i_): s(s_), i(i_)
574     {
575     }
operator ++MatrixIterator576     MatrixIterator& operator++()
577     {
578         ++i;
579         return *this;
580     }
operator ++MatrixIterator581     MatrixIterator operator++(int)
582     {
583         MatrixIterator tmp(*this);
584         ++i;
585         return tmp;
586     }
operator *MatrixIterator587     Accessor<S, V> operator*()
588     {
589         return Accessor<S, V>(s, (*i).first, (*i).second);
590     }
591 private:
592     S& s;
593     Iter i;
594 };
595 template<typename V, typename S, typename Iter>
makeMatrixIterator(S & s,Iter i)596 MatrixIterator<S, V, Iter> makeMatrixIterator(S& s, Iter i)
597 {
598     return MatrixIterator<S, V, Iter>(s, i);
599 }
600 
601 template<typename S> struct IteratorFromVar;
602 
603 template<typename S> IteratorFromVar<S> makeIteratorFromVar(S& s);
604 
605 struct Adjacency
606 {
AdjacencyAdjacency607     Adjacency(double const* x, double const*a): xadj(x), adjncy(a) {}
608     double const* xadj;
609     double const* adjncy;
610 };
611 
612 template<typename In, typename Sz, typename Out>
mycopy_n(In i,Sz n,Out o)613 Out mycopy_n(In i, Sz n, Out o)
614 {
615     for (; n; --n, ++i, ++o)
616     {
617         *o = *i;
618     }
619     return o;
620 }
621 
nonZeros(T SPARSE_CONST & t)622 template<typename T> std::size_t nonZeros(T SPARSE_CONST& t)
623 {
624     return t.getSize();
625 }
nonZeros(types::Sparse SPARSE_CONST & sp)626 template<> std::size_t nonZeros(types::Sparse SPARSE_CONST& sp)
627 {
628     return sp.nonZeros();
629 }
nonZeros(Eigen::SparseMatrix<Scalar,Options,Index> SPARSE_CONST & sp)630 template<typename Scalar, int Options, typename Index> std::size_t nonZeros(Eigen::SparseMatrix<Scalar, Options, Index> SPARSE_CONST& sp)
631 {
632     return sp.nonZeros();
633 }
634 
635 
636 /* Default for dense matrix Scilab matrix types
637  */
makeNonZerosIterator(D SPARSE_CONST & d)638 template<typename D> RowWiseFullIterator makeNonZerosIterator(D SPARSE_CONST& d)
639 {
640     return RowWiseFullIterator(d.getRows(), d.getCols());
641 }
makeNonZerosIterator(Eigen::SparseMatrix<Scalar,Options,Index> SPARSE_CONST & sp)642 template<typename Scalar, int Options, typename Index> RowWiseSparseIterator<Eigen::SparseMatrix<Scalar, Options, Index> > makeNonZerosIterator(Eigen::SparseMatrix<Scalar, Options, Index> SPARSE_CONST& sp)
643 {
644     return RowWiseSparseIterator<Eigen::SparseMatrix<Scalar, Options, Index> >(sp);
645 }
makeTranslatedIterator(Iter const & it,Coords2D const & tr)646 template<typename Iter> TranslatedIterator<Iter> makeTranslatedIterator(Iter const& it, Coords2D const& tr)
647 {
648     return TranslatedIterator<Iter>(it, tr);
649 }
650 
651 
652 
653 template<typename S> struct IteratorFromVar { };
654 
655 template<> struct IteratorFromVar<types::Double> : Coords2DIterator
656 {
IteratorFromVarIteratorFromVar657     IteratorFromVar(types::Double& d_): d(d_), r(0)
658     {
659         // check dimension ?
660     }
661 
operator ++IteratorFromVar662     IteratorFromVar& operator++()
663     {
664         ++r;
665         return *this;
666     }
operator ++IteratorFromVar667     IteratorFromVar operator++(int)
668     {
669         IteratorFromVar tmp(*this);
670         ++r;
671         return tmp;
672     }
operator *IteratorFromVar673     Coords2D operator*()
674     {
675         return std::pair<int, int>(static_cast<int>(d.getReal(r, 0) - 1), static_cast<int>(d.getReal(r, 1) - 1));
676     }
677 private:
678     types::Double& d;
679     int r;
680 };
681 
682 /*
683   iterator from adjacency matrices :
684  */
685 template<> struct IteratorFromVar<Adjacency> : Coords2DIterator
686 {
IteratorFromVarIteratorFromVar687     IteratorFromVar(Adjacency& a): xadj(a.xadj), adjncy(a.adjncy), c(1), nb(1)
688     {
689         update();
690     }
691 
operator ++IteratorFromVar692     IteratorFromVar& operator++()
693     {
694         ++nb;
695         update();
696         ++adjncy;
697         return *this;
698     }
operator ++IteratorFromVar699     IteratorFromVar operator++(int)
700     {
701         IteratorFromVar tmp(*this);
702         ++nb;
703         update();
704         ++adjncy;
705         return tmp;
706     }
operator *IteratorFromVar707     std::pair<int, int> operator*()
708     {
709         return std::pair<int, int>(static_cast<int>(*adjncy) - 1, c - 1);
710     }
711 private:
updateIteratorFromVar712     void update()
713     {
714         for (; xadj[1] <= nb; ++c, ++xadj)
715         {
716         }
717     }
718     double const* xadj;
719     double const* adjncy;
720     int c;
721     std::size_t nb;
722 };
723 
makeIteratorFromVar(S & s)724 template<typename S> IteratorFromVar<S> makeIteratorFromVar(S& s)
725 {
726     return IteratorFromVar<S>(s);
727 }
728 
729 #endif
730