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