f279d245ec1932006111e3b18f42d448ccfaf0b8
[scilab.git] / scilab / modules / ast / includes / types / sparse.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010-2010 - 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
16 #ifndef __SPARSE_HH__
17 #define __SPARSE_HH__
18
19 //#include <Eigen/Sparse>
20 #include <complex>
21 #include "double.hxx"
22 #include "bool.hxx"
23 #include "keepForSparse.hxx"
24
25 #define SPARSE_CONST
26
27 namespace Eigen
28 {
29 template<typename _Scalar, int _Flags, typename _Index>  class SparseMatrix;
30 }
31
32 namespace types
33 {
34 /* Utility function to create a new var on the heap from another type
35  */
36 template<typename Dest, typename Arg>
37 Dest* create_new(Arg const&);
38
39 struct SparseBool;
40
41 /**
42    Sparse is a wrapper over Eigen sparse matrices templates for either double or std::complex<double> values.
43  */
44 struct EXTERN_AST Sparse : GenericType
45 {
46     virtual ~Sparse();
47     /* @param src: Double matrix to copy into a new sparse matrix
48     **/
49     Sparse(Double SPARSE_CONST& src);
50     /* @param src : Double matrix to copy into a new sparse matrix
51        @param idx : Double matrix to use as indexes to get values from the src
52     **/
53     Sparse(Double SPARSE_CONST& src, Double SPARSE_CONST& idx);
54     /* @param src : Double matrix to copy into a new sparse matrix
55        @param idx : Double matrix to use as indexes to get values from the src
56        @param dims : Double matrix containing the dimensions of the new matrix
57     **/
58     Sparse(Double SPARSE_CONST& src, Double SPARSE_CONST& idx, Double SPARSE_CONST& dims);
59     /*
60       @param rows : nb of rows of the new matrix
61       @param rows : nb of columns of the new matrix
62       @param cplx : if the new matrix contains complex numbers
63     **/
64     Sparse(int rows, int cols, bool cplx = false);
65     Sparse(Sparse const& o);
66     /* cf. adj2sp()
67       @param xadj : adjacency matrix for the new matrix
68       @param adjncy : adjacency matrix (row indexes) for the new matrix
69       @param src : data for the new matrix
70       @param r : nb of rows for the new matrix
71       @param c : nb of columns for the new matrix
72     **/
73     Sparse(Double SPARSE_CONST& xadj, Double SPARSE_CONST& adjncy, Double SPARSE_CONST& src, std::size_t r, std::size_t c);
74
75     //constructor to create a sparse from value extract to another ( save / load operation typically)
76     Sparse(int rows, int cols, int nonzeros, int* inner, int* outer, double* real, double* img);
77
78     bool isSparse()
79     {
80         return true;
81     }
82     void finalize();
83
84     /*data management member function defined for compatibility with the Double API*/
85     Sparse* set(int _iRows, int _iCols, double _dblReal, bool _bFinalize = true);
86     Sparse* set(int _iIndex, double _dblReal, bool _bFinalize = true)
87     {
88         return set(_iIndex % m_iRows, _iIndex / m_iRows, _dblReal, _bFinalize);
89     }
90
91     Sparse* set(int _iRows, int _iCols, std::complex<double> v, bool _bFinalize = true);
92     Sparse* set(int _iIndex, std::complex<double> v, bool _bFinalize = true)
93     {
94         return set(_iIndex % m_iRows, _iIndex / m_iRows, v, _bFinalize);
95     }
96     /*
97       set non zero values to 1.
98     **/
99     bool one_set();
100     /* get real value at coords (r,c)
101     **/
102     double getReal(int r, int c) const;
103     double getReal(int _iIndex) const
104     {
105         return getReal(_iIndex % m_iRows, _iIndex / m_iRows);
106     }
107
108     double* get();
109     double get(int r, int c) const;
110     double get(int _iIndex) const
111     {
112         return get(_iIndex % m_iRows, _iIndex / m_iRows);
113     }
114
115     std::complex<double>* getImg();
116     std::complex<double> getImg(int r, int c) const;
117     std::complex<double> getImg(int _iIndex) const
118     {
119         return getImg(_iIndex % m_iRows, _iIndex / m_iRows);
120     }
121
122     /* return true if matrix contains complex numbers, false otherwise.
123     **/
124     bool isComplex() const;
125     // overload of GenericType methode.
126     bool isComplex()
127     {
128         // force const to call isComplex const method.
129         const Sparse* sp = this;
130         return sp->isComplex();
131     }
132
133     inline bool isScalar()
134     {
135         return (getRows() == 1 && getCols() == 1);
136     }
137     /* clear all the values of the matrix to 0. (or 0.+0.i if complex)
138     **/
139     bool zero_set();
140
141     /*
142       Config management and GenericType methods overrides
143     */
144     void whoAmI() SPARSE_CONST;
145     bool isExtract() const;
146     Sparse* clone(void) const;
147     Sparse* clone(void)
148     {
149         return const_cast<Sparse const*>(this)->clone();
150     }
151     bool toString(std::wostringstream& ostr) const;
152     bool toString(std::wostringstream& ostr)
153     {
154         return const_cast<Sparse const*>(this)->toString(ostr);
155     }
156
157     /* post condition: dimensions are at least _iNewRows, _iNewCols
158        preserving existing data.
159        If dimensions where already >=, this is a no-op.
160
161        @param _iNewRows new minimum nb of rows
162        @param _iNewCols new minimum nb of cols
163        @return true upon succes, false otherwise.
164      */
165     Sparse* resize(int _iNewRows, int _iNewCols);
166     /* post condition: new total size must be equal to the old size.
167                        Two dimensions maximum.
168
169        @param _iNewRows new nb of rows
170        @param _iNewCols new nb of cols
171        @param _piNewDims new nb of dimension
172        @param _iNewDims new size for each dimension
173        @return true upon succes, false otherwise.
174     */
175     Sparse* reshape(int* _piNewDims, int _iNewDims);
176     Sparse* reshape(int _iNewRows, int _iNewCols);
177     /*
178       insert _iSeqCount elements from _poSource at coords given by _piSeqCoord (max in _piMaxDim).
179       coords are considered 1D if _bAsVector, 2D otherwise.
180       @param _iSeqCount nb of elts to insert
181       @param _piSeqCoord dest coords
182       @param _poSource src
183       @param  _bAsVector if _piSeqCoord contains 1D coords.
184      */
185     Sparse* insert(typed_list* _pArgs, InternalType* _pSource);
186
187     GenericType* remove(typed_list* _pArgs);
188
189     GenericType* insertNew(typed_list* _pArgs);
190
191     /* append _poSource from coords _iRows, _iCols
192        @param _iRows row to append from
193        @param _iCols col to append from
194        @param _poSource src data to append
195      */
196     Sparse* append(int r, int c, types::Sparse SPARSE_CONST* src);
197
198     /*
199       extract a submatrix
200       @param _iSeqCount nb of elts to extract
201       @param _piSeqCoord src coords
202       @param _piMaxDim max coords
203       @param _piDimSize size of the extracted matrix
204       @param  _bAsVector if _piSeqCoord contains 1D coords.
205
206      */
207     GenericType* extract(typed_list* _pArgs);
208     Sparse* extract(int _iSeqCount, int* _piSeqCoord, int* _piMaxDim, int* _piDimSize, bool _bAsVector) SPARSE_CONST;
209     virtual bool invoke(typed_list & in, optional_list & /*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e);
210     virtual bool isInvokable() const;
211     virtual bool hasInvokeOption() const;
212     virtual int getInvokeNbIn();
213     virtual int getInvokeNbOut();
214
215     /*
216        change the sign (inplace).
217      */
218     void opposite();
219
220     /*
221       compares with an other value for equality (same nb of elts, with same values)
222       TODO: should it handle other types ?
223      */
224     bool operator==(const InternalType& it) SPARSE_CONST;
225     /*
226       compares with an other value for inequality (same nb of elts, with same values)
227       TODO: should it handle other types ?
228      */
229     bool operator!=(const InternalType& it) SPARSE_CONST
230     {
231         return !(*this == it);
232     }
233
234
235     /* return type as string ( double, int, cell, list, ... )*/
236     virtual std::wstring         getTypeStr() SPARSE_CONST {return std::wstring(L"sparse");}
237     /* return type as short string ( s, i, ce, l, ... ), as in overloading macros*/
238     virtual std::wstring         getShortTypeStr() SPARSE_CONST {return std::wstring(L"sp");}
239
240     /* create a new sparse matrix containing the result of an addition
241        @param o other matrix to add
242        @return ptr to the new matrix, 0 in case of failure
243      */
244     Sparse* add(Sparse const& o) const;
245
246     /* create a new sparse matrix containing the result of an addition
247        @param d scalar to add
248        @return ptr to the new matrix, 0 in case of failure
249      */
250     Double* add(double d) const;
251
252     /* create a new sparse matrix containing the result of an addition
253        @param c complex  to add
254        @return ptr to the new matrix, 0 in case of failure
255      */
256     Double* add(std::complex<double> c) const;
257
258
259
260
261     /* create a new sparse matrix containing the result of a substraction
262        @param o other matrix to substract
263        @return ptr to the new matrix, 0 in case of failure
264      */
265     Sparse* substract(Sparse const& o) const;
266
267     /* create a new sparse matrix containing the result of an subtraction
268        @param d scalar to subtract
269        @return ptr to the new matrix, 0 in case of failure
270      */
271     Double* substract(double d) const;
272
273     /* create a new sparse matrix containing the result of an subtraction
274        @param c scalar to subtract
275        @return ptr to the new matrix, 0 in case of failure
276      */
277     Double* substract(std::complex<double> c) const;
278
279
280     /* create a new sparse matrix containing the result of a multiplication
281        @param o other matrix to substract
282        @return ptr to the new matrix, 0 in case of failure
283      */
284     Sparse* multiply(Sparse const& o) const;
285
286     /* create a new sparse matrix containing the result of an multiplication
287        @param s scalar to multiply by
288        @return ptr to the new matrix, 0 in case of failure
289      */
290     Sparse* multiply(double s) const;
291
292     /* create a new sparse matrix containing the result of an multiplication
293        @param c scalar to subtract
294        @return ptr to the new matrix, 0 in case of failure
295      */
296     Sparse* multiply(std::complex<double> c) const;
297
298     /* create a new matrix containing the result of an .*
299        @param o sparse matrix to .*
300        @return ptr to the new matrix, 0 in case of failure
301      */
302     Sparse* dotMultiply(Sparse SPARSE_CONST& o) const;
303
304     /* create a new matrix containing the result of an ./
305       @param o sparse matrix to ./
306       @return ptr to the new matrix, 0 in case of failure
307     */
308     Sparse* dotDivide(Sparse SPARSE_CONST& o) const;
309
310     bool neg(InternalType *& out);
311
312     bool transpose(InternalType *& out);
313     bool adjoint(InternalType *& out);
314     int newCholLLT(Sparse** permut, Sparse** factor) const;
315
316     /** create a new sparse matrix containing the non zero values set to 1.
317        equivalent but faster than calling one_set() on a new copy of the
318        current matrix.
319        @return ptr to the new matrix, 0 in case of failure
320      */
321     Sparse* newOnes() const;
322
323     Sparse* newReal() const;
324     /** @return the nb of non zero values.
325      */
326     std::size_t nonZeros() const;
327
328     /* @param i row of the current sparse matrix
329        @return the nb of non zero values in row i
330      */
331     std::size_t nonZeros(std::size_t i) const;
332
333     int* getNbItemByRow(int* _piNbItemByRows);
334     int* getColPos(int* _piColPos);
335     int* getInnerPtr(int* count);
336     int* getOuterPtr(int* count);
337
338
339     /**
340        "in-place" cast into a sparse matrix of comlpex values
341      */
342     void toComplex();
343
344     /* coefficient wise relational operator < between *this sparse matrix and an other.
345        Matrices must have the same dimensions except if one of them is of size (1,1)
346        (i.e. a scalar) : it is then treated as a constant matrix of thre required dimensions.
347
348        @param o other sparse matrix
349
350        @return ptr to a new Sparse matrix where each element is the result of the logical operator
351         '<' between the elements of *this and those of o.
352      */
353     SparseBool* newLessThan(Sparse &o);
354
355     /* coefficient wise relational operator != between *this sparse matrix and an other.
356        Matrices must have the same dimensions except if one of them is of size (1,1)
357        (i.e. a scalar) : it is then treated as a constant matrix of thre required dimensions.
358
359        @param o other sparse matrix
360
361        @return ptr to a new Sparse matrix where each element is the result of the logical operator
362         '!=' between the elements of *this and those of o.
363      */
364     SparseBool* newNotEqualTo(Sparse const&o) const;
365
366     /* coefficient wise relational operator <= between *this sparse matrix and an other.
367        Matrices must have the same dimensions except if one of them is of size (1,1)
368        (i.e. a scalar) : it is then treated as a constant matrix of thre required dimensions.
369
370        Do not use this function is possible as the result will be dense because
371        0. <= 0. is true, hence the result matrix will hold a non default value (i.e. true)
372        for each pair of default values (0.) of the sparse arguments !
373
374        @param o other sparse matrix
375
376        @return ptr to a new Sparse matrix where each element is the result of the logical operator
377         '<=' between the elements of *this and those of o.
378      */
379     SparseBool* newLessOrEqual(Sparse &o);
380
381     /* coefficient wise relational operator == between *this sparse matrix and an other.
382        Matrices must have the same dimensions except if one of them is of size (1,1)
383        (i.e. a scalar) : it is then treated as a constant matrix of thre required dimensions.
384
385        Do not use this function is possible as the result will be dense because
386        0. == 0. is true, hence the result matrix will hold a non default value (i.e. true)
387        for each pair of default values (0.) of the sparse arguments !
388
389        @param o other sparse matrix
390
391        @return ptr to a new Sparse matrix where each element is the result of the logical operator
392         '==' between the elements of *this and those of o.
393      */
394     SparseBool* newEqualTo(Sparse &o);
395
396     /**
397        output 1-base column numbers of the non zero elements
398        @param out : ptr used as an output iterator over double values
399        @return past-the-end output iterator after ouput is done
400      */
401     double* outputCols(double* out) const;
402
403     /**
404        output real and imaginary values of the non zero elements
405        @param outReal : ptr used as an output iterator over double values for real values
406        @param outImag : ptr used as an output iterator over double values for imaginary values if any
407        @return pair of past-the-end output iterators after ouput is done
408      */
409     std::pair<double*, double*> outputValues(double* outReal, double* outImag)const;
410
411     /**
412        ouput rows and afterwards columns of the non zero elements
413        @param out : ptr used as an output iterator over double values
414        @return past-the-end output iterators after ouput is done
415      */
416     int* outputRowCol(int* out)const;
417
418     /**
419        @param dest Double to be filled with values from the current sparse matrix.
420      */
421     void fill(Double& dest, int r = 0, int c = 0) SPARSE_CONST;
422
423
424     inline ScilabType  getType(void) SPARSE_CONST
425     {
426         return ScilabSparse;
427     }
428
429     inline ScilabId    getId(void) SPARSE_CONST
430     {
431         if (isComplex())
432         {
433             return IdSparseComplex;
434         }
435         return IdSparse;
436     }
437
438
439
440     SparseBool* newLesserThan(Sparse const&o);
441
442     typedef Eigen::SparseMatrix<double, 0x1, int>                   RealSparse_t;
443     typedef Eigen::SparseMatrix<std::complex<double>, 0x1, int>     CplxSparse_t;
444     /**
445        One and only one of the args should be 0.
446        @param realSp ptr to an Eigen sparse matrix of double values
447        @param cplxSp ptr to an Eigen sparse matrix of std::complex<double> elements
448      */
449     Sparse(RealSparse_t* realSp, CplxSparse_t* cplxSp);
450
451     RealSparse_t* matrixReal;
452     CplxSparse_t* matrixCplx;
453
454 protected :
455 private :
456
457     /** utility function used by constructors
458         @param rows : nb of rows
459         @param cols : nb of columns
460         @param src : Double matrix data source
461         @param : iterator (cf MatrixIterator.hxx) with indices
462         @param n : nb of elements to copy from data source.
463      */
464     template<typename DestIter>
465     void create(int rows, int cols, Double SPARSE_CONST& src, DestIter o, std::size_t n);
466     void create2(int rows, int cols, Double SPARSE_CONST& src, Double SPARSE_CONST& idx);
467
468     /** utility function used by insert functions conceptually : sp[destTrav]= src[srcTrav]
469         @param src : data source
470         @param SrcTrav : iterator over the data source
471         @param n : nb of elements to copy
472         @param sp : sparse destination matrix
473         @param destTrav : iterator over the data sink (i.e. sp)
474      */
475     template<typename Src, typename SrcTraversal, typename Sz, typename DestTraversal>
476     static bool copyToSparse(Src SPARSE_CONST& src, SrcTraversal srcTrav, Sz n, Sparse& sp, DestTraversal destTrav);
477
478     Sparse* insert(typed_list* _pArgs, Sparse* _pSource);
479 };
480
481 template<typename T>
482 void neg(const int r, const int c, const T * const in, Eigen::SparseMatrix<bool, 1, int> * const out);
483
484
485 /*
486   Implement sparse boolean matrix
487  */
488 struct EXTERN_AST SparseBool : GenericType
489 {
490     virtual ~SparseBool();
491     /* @param src: Bool matrix to copy into a new sparse matrix
492     **/
493     SparseBool(Bool SPARSE_CONST& src);
494     /* @param src : Bool matrix to copy into a new sparse matrix
495        @param idx : Double matrix to use as indexes to get values from the src
496     **/
497     SparseBool(Bool SPARSE_CONST& src, Double SPARSE_CONST& idx);
498     /* @param src : Bool matrix to copy into a new sparse matrix
499        @param idx : Double matrix to use as indexes to get values from the src
500        @param dims : Double matrix containing the dimensions of the new matrix
501     **/
502     SparseBool(Bool SPARSE_CONST& src, Double SPARSE_CONST& idx, Double SPARSE_CONST& dims);
503     /*
504        @param rows : nb of rows of the new matrix
505        @param rows : nb of columns of the new matrix
506     */
507     SparseBool(int rows, int cols);
508
509     SparseBool(SparseBool const& o);
510
511     //constructor to create a sparse from value extract to another ( save / load operation typically)
512     SparseBool(int rows, int cols, int trues, int* inner, int* outer);
513
514     bool isSparseBool()
515     {
516         return true;
517     }
518     void finalize();
519
520     bool toString(std::wostringstream& ostr) const;
521     bool toString(std::wostringstream& ostr)
522     {
523         return const_cast<SparseBool const*>(this)->toString(ostr);
524     }
525
526     /* Config management and GenericType methods overrides */
527     SparseBool* clone(void) const;
528     SparseBool* clone(void)
529     {
530         return const_cast<SparseBool const*>(this)->clone();
531     }
532
533     SparseBool* resize(int _iNewRows, int _iNewCols);
534     SparseBool* reshape(int* _piNewDims, int _iNewDims);
535     SparseBool* reshape(int _iNewRows, int _iNewCols);
536     SparseBool* insert(typed_list* _pArgs, InternalType* _pSource);
537     SparseBool* append(int _iRows, int _iCols, SparseBool SPARSE_CONST* _poSource);
538
539     GenericType* remove(typed_list* _pArgs);
540     GenericType* insertNew(typed_list* _pArgs);
541     GenericType* extract(typed_list* _pArgs);
542
543     SparseBool* extract(int _iSeqCount, int* _piSeqCoord, int* _piMaxDim, int* _piDimSize, bool _bAsVector) SPARSE_CONST;
544
545     virtual bool invoke(typed_list & in, optional_list &/*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e);
546     virtual bool isInvokable() const;
547     virtual bool hasInvokeOption() const;
548     virtual int getInvokeNbIn();
549     virtual int getInvokeNbOut();
550
551     bool transpose(InternalType *& out);
552
553     /** @return the nb of non zero values.
554      */
555     std::size_t nbTrue() const;
556     /* @param i row of the current sparse matrix
557        @return the nb of non zero values in row i
558      */
559     std::size_t nbTrue(std::size_t i) const;
560
561     void setTrue(bool finalize = true);
562     void setFalse(bool finalize = true);
563
564     int* getNbItemByRow(int* _piNbItemByRows);
565     int* getColPos(int* _piColPos);
566     int* getInnerPtr(int* count);
567     int* getOuterPtr(int* count);
568     /**
569        output 1-base column numbers of the non zero elements
570        @param out : ptr used as an output iterator over double values
571        @return past-the-end output iterator after ouput is done
572      */
573
574     int* outputRowCol(int* out)const;
575
576     bool operator==(const InternalType& it) SPARSE_CONST;
577     bool operator!=(const InternalType& it) SPARSE_CONST;
578
579     /* return type as string ( double, int, cell, list, ... )*/
580     virtual std::wstring getTypeStr() SPARSE_CONST {return std::wstring(L"boolean sparse");}
581     /* return type as short string ( s, i, ce, l, ... )*/
582     virtual std::wstring getShortTypeStr() SPARSE_CONST {return std::wstring(L"spb");}
583
584     inline ScilabType getType(void) SPARSE_CONST
585     {
586         return ScilabSparseBool;
587     }
588
589     inline ScilabId getId(void) SPARSE_CONST
590     {
591         return IdSparseBool;
592     }
593
594     inline bool isScalar()
595     {
596         return (getRows() == 1 && getCols() == 1);
597     }
598
599     bool isTrue()
600     {
601         if (static_cast<int>(nbTrue()) == m_iSize)
602         {
603             return true;
604         }
605         return false;
606     }
607
608     bool neg(InternalType *& out)
609     {
610         SparseBool * _out = new SparseBool(getRows(), getCols());
611         types::neg(getRows(), getCols(), matrixBool, _out->matrixBool);
612         _out->finalize();
613         out = _out;
614         return true;
615     }
616
617     void whoAmI() SPARSE_CONST;
618
619     bool* get();
620     bool get(int r, int c) SPARSE_CONST;
621     bool get(int _iIndex) SPARSE_CONST
622     {
623         return get(_iIndex % m_iRows, _iIndex / m_iRows);
624     }
625
626     SparseBool* set(int r, int c, bool b, bool _bFinalize = true) SPARSE_CONST;
627     SparseBool* set(int _iIndex, bool b, bool _bFinalize = true) SPARSE_CONST
628     {
629         return set(_iIndex % m_iRows, _iIndex / m_iRows, b, _bFinalize);
630     }
631
632     void fill(Bool& dest, int r = 0, int c = 0) SPARSE_CONST;
633
634     Sparse* newOnes() const;
635     SparseBool* newNotEqualTo(SparseBool const&o) const;
636     SparseBool* newEqualTo(SparseBool& o);
637
638     SparseBool* newLogicalOr(SparseBool const&o) const;
639     SparseBool* newLogicalAnd(SparseBool const&o) const;
640
641     typedef Eigen::SparseMatrix<bool, 0x1, int> BoolSparse_t;
642     SparseBool(BoolSparse_t* o);
643     BoolSparse_t* matrixBool;
644
645 private:
646     void create2(int rows, int cols, Bool SPARSE_CONST& src, Double SPARSE_CONST& idx);
647     SparseBool* insert(typed_list* _pArgs, SparseBool* _pSource);
648 };
649
650 template<typename T>
651 struct SparseTraits
652 {
653     typedef types::Sparse type;
654 };
655 template<>
656 struct SparseTraits<types::Bool>
657 {
658     typedef types::SparseBool type;
659 };
660 template<>
661 struct SparseTraits<types::SparseBool>
662 {
663     typedef types::SparseBool type;
664 };
665
666 }
667
668 #endif /* !__SPARSE_HH__ */