1 /****************************************************************/ 2 /* Parallel Combinatorial BLAS Library (for Graph Computations) */ 3 /* version 1.6 -------------------------------------------------*/ 4 /* date: 6/15/2017 ---------------------------------------------*/ 5 /* authors: Ariful Azad, Aydin Buluc --------------------------*/ 6 /****************************************************************/ 7 /* 8 Copyright (c) 2010-2017, The Regents of the University of California 9 10 Permission is hereby granted, free of charge, to any person obtaining a copy 11 of this software and associated documentation files (the "Software"), to deal 12 in the Software without restriction, including without limitation the rights 13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 copies of the Software, and to permit persons to whom the Software is 15 furnished to do so, subject to the following conditions: 16 17 The above copyright notice and this permission notice shall be included in 18 all copies or substantial portions of the Software. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 THE SOFTWARE. 27 */ 28 29 30 #ifndef _SP_CCOLS_H_ 31 #define _SP_CCOLS_H_ 32 33 #include <cmath> 34 #include "SpMat.h" // Best to include the base class first 35 #include "SpHelper.h" 36 #include "csc.h" 37 38 namespace combblas { 39 40 template <class IT, class NT> 41 class SpCCols: public SpMat<IT, NT, SpCCols<IT, NT> > 42 { 43 public: 44 typedef IT LocalIT; 45 typedef NT LocalNT; 46 47 // Constructors : 48 SpCCols (); 49 SpCCols (IT size, IT nRow, IT nCol); 50 SpCCols (const SpTuples<IT,NT> & rhs, bool transpose); SpCCols(const SpDCCols<IT,NT> & rhs)51 SpCCols (const SpDCCols<IT,NT> & rhs):nnz(0), n(0), m(0), splits(0), csc(NULL) 52 { 53 SpTuples<IT,NT> tuples(rhs); 54 SpCCols<IT,NT> object(tuples, false); 55 *this = object; // its members are already initialized by the initializer list 56 } 57 58 SpCCols (const SpCCols<IT,NT> & rhs); // Actual copy constructor 59 ~SpCCols(); 60 61 // Member Functions and Operators: 62 SpCCols<IT,NT> & operator= (const SpCCols<IT, NT> & rhs); 63 SpCCols<IT,NT> & operator+= (const SpCCols<IT, NT> & rhs); 64 65 void RowSplit(int numsplits); 66 void ColSplit(int parts, std::vector< SpCCols<IT,NT> > & matrices); //!< \attention Destroys calling object (*this) 67 68 void CreateImpl(const std::vector<IT> & essentials); 69 void CreateImpl(IT size, IT nRow, IT nCol, std::tuple<IT, IT, NT> * mytuples); 70 71 Arr<IT,NT> GetArrays() const; 72 std::vector<IT> GetEssentials() const; 73 const static IT esscount; 74 getnrow()75 IT getnrow() const { return m; } getncol()76 IT getncol() const { return n; } getnnz()77 IT getnnz() const { return nnz; } getnsplit()78 int getnsplit() const { return splits; } 79 80 GetInternal()81 auto GetInternal() const { return GetCSC(); } GetInternal(int i)82 auto GetInternal(int i) const { return GetCSC(i); } 83 84 85 class SpColIter //! Iterate over (sparse) columns of the sparse matrix 86 { 87 public: 88 class NzIter //! Iterate over the nonzeros of the sparse column 89 { 90 public: rid(ir)91 NzIter(IT * ir = NULL, NT * num = NULL) : rid(ir), val(num) {} 92 93 bool operator==(const NzIter & other) 94 { 95 return(rid == other.rid); // compare pointers 96 } 97 bool operator!=(const NzIter & other) 98 { 99 return(rid != other.rid); 100 } 101 NzIter & operator++() // prefix operator 102 { 103 ++rid; 104 ++val; 105 return(*this); 106 } 107 NzIter operator++(int) // postfix operator 108 { 109 NzIter tmp(*this); 110 ++(*this); 111 return(tmp); 112 } rowid()113 IT rowid() const //!< Return the "local" rowid of the current nonzero entry. 114 { 115 return (*rid); 116 } value()117 NT & value() //!< value is returned by reference for possible updates 118 { 119 return (*val); 120 } 121 private: 122 IT * rid; 123 NT * val; 124 125 }; 126 begcptr(jc)127 SpColIter(IT * jc = NULL) : begcptr(jc), curcptr(jc) {} 128 bool operator==(const SpColIter& other) 129 { 130 return(curcptr == other.curcptr); // compare pointers 131 } 132 bool operator!=(const SpColIter& other) 133 { 134 return(curcptr != other.curcptr); 135 } 136 SpColIter& operator++() // prefix operator (different across derived classes) 137 { 138 ++curcptr; 139 return(*this); 140 } colid()141 IT colid() const //!< Return the "local" colid of the current column. 142 { 143 return (curcptr-begcptr); 144 } colptr()145 IT colptr() const // only needed internally by ::begnz() below 146 { 147 return (*curcptr); 148 } colptrnext()149 IT colptrnext() const // only needed internally by ::begnz() below 150 { 151 return (*(curcptr+1)); 152 } nnz()153 IT nnz() const 154 { 155 return (colptrnext() - colptr()); 156 } 157 private: 158 IT * begcptr; 159 IT * curcptr; 160 }; 161 begcol()162 SpColIter begcol() // serial version 163 { 164 if( nnz > 0 ) 165 return SpColIter(csc->jc); 166 else 167 return SpColIter(NULL); 168 } endcol()169 SpColIter endcol() //serial version 170 { 171 if( nnz > 0 ) 172 return SpColIter(csc->jc + n); // (csc->jc+n) should never execute because SpColIter::colptrnext() would point invalid 173 else 174 return SpColIter(NULL); 175 } 176 begcol(int i)177 SpColIter begcol(int i) // multithreaded version 178 { 179 if( cscarr[i] ) 180 return SpColIter(cscarr[i]->jc); 181 else 182 return SpColIter(NULL); 183 } endcol(int i)184 SpColIter endcol(int i) //multithreaded version 185 { 186 if( cscarr[i] ) 187 return SpColIter(cscarr[i]->jc + n); // (csc->jc+n) should never execute because SpColIter::colptrnext() would point invalid 188 else 189 return SpColIter(NULL); 190 } 191 192 begnz(const SpColIter & ccol)193 typename SpColIter::NzIter begnz(const SpColIter & ccol) //!< Return the beginning iterator for the nonzeros of the current column 194 { 195 return typename SpColIter::NzIter( csc->ir + ccol.colptr(), csc->num + ccol.colptr() ); 196 } 197 endnz(const SpColIter & ccol)198 typename SpColIter::NzIter endnz(const SpColIter & ccol) //!< Return the ending iterator for the nonzeros of the current column 199 { 200 return typename SpColIter::NzIter( csc->ir + ccol.colptrnext(), NULL ); 201 } 202 begnz(const SpColIter & ccol,int i)203 typename SpColIter::NzIter begnz(const SpColIter & ccol, int i) //!< multithreaded version 204 { 205 return typename SpColIter::NzIter( cscarr[i]->ir + ccol.colptr(), cscarr[i]->num + ccol.colptr() ); 206 } 207 endnz(const SpColIter & ccol,int i)208 typename SpColIter::NzIter endnz(const SpColIter & ccol, int i) //!< multithreaded version 209 { 210 return typename SpColIter::NzIter( cscarr[i]->ir + ccol.colptrnext(), NULL ); 211 } 212 213 void PrintInfo() const; 214 215 private: 216 217 void SubPrintInfo(Csc<IT,NT> * mycsc) const; 218 219 // Anonymous union 220 union { 221 Csc<IT, NT> * csc; 222 Csc<IT, NT> ** cscarr; 223 }; 224 225 IT m; 226 IT n; 227 IT nnz; 228 229 int splits; // for multithreading 230 231 void CopyCsc(Csc<IT,NT> * source); 232 GetCSC()233 Csc<IT, NT> * GetCSC() const // only for single threaded matrices 234 { 235 return csc; 236 } 237 GetCSC(int i)238 Csc<IT, NT> * GetCSC(int i) const // only for split (multithreaded) matrices 239 { 240 return cscarr[i]; 241 } 242 243 template <typename SR, typename IU, typename NU, typename RHS, typename LHS> 244 friend void csc_gespmv_dense (const SpCCols<IU, NU> & A, const RHS * x, LHS * y); //!< dense vector (not implemented) 245 246 //<! sparse vector version 247 template <typename SR, typename IU, typename NUM, typename DER, typename IVT, typename OVT> 248 friend int generic_gespmv_threaded (const SpMat<IU,NUM,DER> & A, const int32_t * indx, const IVT * numx, int32_t nnzx, 249 int32_t * & sendindbuf, OVT * & sendnumbuf, int * & sdispls, int p_c, PreAllocatedSPA<OVT> & SPA); 250 }; 251 252 253 // At this point, complete type of of SpCCols is known, safe to declare these specialization (but macros won't work as they are preprocessed) 254 // General case #1: When both NT is the same 255 template <class IT, class NT> struct promote_trait< SpCCols<IT,NT> , SpCCols<IT,NT> > 256 { 257 typedef SpCCols<IT,NT> T_promote; 258 }; 259 // General case #2: First is boolean the second is anything except boolean (to prevent ambiguity) 260 template <class IT, class NT> struct promote_trait< SpCCols<IT,bool> , SpCCols<IT,NT>, typename combblas::disable_if< combblas::is_boolean<NT>::value >::type > 261 { 262 typedef SpCCols<IT,NT> T_promote; 263 }; 264 // General case #3: Second is boolean the first is anything except boolean (to prevent ambiguity) 265 template <class IT, class NT> struct promote_trait< SpCCols<IT,NT> , SpCCols<IT,bool>, typename combblas::disable_if< combblas::is_boolean<NT>::value >::type > 266 { 267 typedef SpCCols<IT,NT> T_promote; 268 }; 269 template <class IT> struct promote_trait< SpCCols<IT,int> , SpCCols<IT,float> > 270 { 271 typedef SpCCols<IT,float> T_promote; 272 }; 273 274 template <class IT> struct promote_trait< SpCCols<IT,float> , SpCCols<IT,int> > 275 { 276 typedef SpCCols<IT,float> T_promote; 277 }; 278 template <class IT> struct promote_trait< SpCCols<IT,int> , SpCCols<IT,double> > 279 { 280 typedef SpCCols<IT,double> T_promote; 281 }; 282 template <class IT> struct promote_trait< SpCCols<IT,double> , SpCCols<IT,int> > 283 { 284 typedef SpCCols<IT,double> T_promote; 285 }; 286 287 288 // Capture everything of the form SpCCols<OIT, ONT> 289 // it may come as a surprise that the partial specializations can 290 // involve more template parameters than the primary template 291 template <class NIT, class NNT, class OIT, class ONT> 292 struct create_trait< SpCCols<OIT, ONT> , NIT, NNT > 293 { 294 typedef SpCCols<NIT,NNT> T_inferred; 295 }; 296 297 } 298 299 #include "SpCCols.cpp" 300 301 #endif 302