COMBINATORIAL_BLAS 1.6
 
Loading...
Searching...
No Matches
SpTuples.cpp
Go to the documentation of this file.
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#include "SpTuples.h"
31#include "SpParHelper.h"
32#include <iomanip>
33
34namespace combblas {
35
36template <class IT,class NT>
37SpTuples<IT,NT>::SpTuples(int64_t size, IT nRow, IT nCol)
38:m(nRow), n(nCol), nnz(size)
39{
40 if(nnz > 0)
41 {
42 tuples = new std::tuple<IT, IT, NT>[nnz];
43 }
44 else
45 {
46 tuples = NULL;
47 }
48 isOperatorNew = false;
49}
50
51template <class IT,class NT>
52SpTuples<IT,NT>::SpTuples (int64_t size, IT nRow, IT nCol, std::tuple<IT, IT, NT> * mytuples, bool sorted, bool isOpNew)
53:tuples(mytuples), m(nRow), n(nCol), nnz(size), isOperatorNew(isOpNew)
54{
55 if(!sorted)
56 {
57 SortColBased();
58 }
59
60}
61
69template <class IT, class NT>
70SpTuples<IT,NT>::SpTuples (int64_t maxnnz, IT nRow, IT nCol, std::vector<IT> & edges, bool removeloops):m(nRow), n(nCol)
71{
72 if(maxnnz > 0)
73 {
74 tuples = new std::tuple<IT, IT, NT>[maxnnz];
75 }
76 for(int64_t i=0; i<maxnnz; ++i)
77 {
78 rowindex(i) = edges[2*i+0];
79 colindex(i) = edges[2*i+1];
80 numvalue(i) = (NT) 1;
81 }
82 std::vector<IT>().swap(edges); // free memory for edges
83
84 nnz = maxnnz; // for now (to sort)
85 SortColBased();
86
87 int64_t cnz = 0;
88 int64_t dup = 0; int64_t self = 0;
89 nnz = 0;
90 while(cnz < maxnnz)
91 {
92 int64_t j=cnz+1;
93 while(j < maxnnz && rowindex(cnz) == rowindex(j) && colindex(cnz) == colindex(j))
94 {
95 numvalue(cnz) += numvalue(j);
96 numvalue(j++) = 0; // mark for deletion
97 ++dup;
98 }
99 if(removeloops && rowindex(cnz) == colindex(cnz))
100 {
101 numvalue(cnz) = 0;
102 --nnz;
103 ++self;
104 }
105 ++nnz;
106 cnz = j;
107 }
108
109 std::tuple<IT, IT, NT> * ntuples = new std::tuple<IT,IT,NT>[nnz];
110 int64_t j = 0;
111 for(int64_t i=0; i<maxnnz; ++i)
112 {
113 if(numvalue(i) != 0)
114 {
115 ntuples[j++] = tuples[i];
116 }
117 }
118 assert(j == nnz);
119
120 delete [] tuples;
121 tuples = ntuples;
122 isOperatorNew = false;
123}
124
125
131template <class IT, class NT>
132SpTuples<IT,NT>::SpTuples (int64_t size, IT nRow, IT nCol, StackEntry<NT, std::pair<IT,IT> > * & multstack)
133:m(nRow), n(nCol), nnz(size)
134{
135 isOperatorNew = false;
136 if(nnz > 0)
137 {
138 tuples = new std::tuple<IT, IT, NT>[nnz];
139 }
140 for(int64_t i=0; i<nnz; ++i)
141 {
142 colindex(i) = multstack[i].key.first;
143 rowindex(i) = multstack[i].key.second;
144 numvalue(i) = multstack[i].value;
145 }
146 delete [] multstack;
147}
148
149
150template <class IT,class NT>
151SpTuples<IT,NT>::~SpTuples()
152{
153 // This tuples_deleted member is a temporary patch to avoid memory leak from MemEfficietnSpGEMM3D
154 if((nnz > 0) && (tuples_deleted != true))
155 {
156 if(isOperatorNew)
157 ::operator delete(tuples);
158 else
159 delete [] tuples;
160 }
161}
162
168template <class IT,class NT>
169SpTuples<IT,NT>::SpTuples(const SpTuples<IT,NT> & rhs): m(rhs.m), n(rhs.n), nnz(rhs.nnz)
170{
171 tuples = new std::tuple<IT, IT, NT>[nnz];
172 isOperatorNew = false;
173 for(IT i=0; i< nnz; ++i)
174 {
175 tuples[i] = rhs.tuples[i];
176 }
177}
178
180template <class IT,class NT>
181SpTuples<IT,NT>::SpTuples (const SpDCCols<IT,NT> & rhs): m(rhs.m), n(rhs.n), nnz(rhs.nnz)
182{
183 if(nnz > 0)
184 {
185 FillTuples(rhs.dcsc);
186 }
187 isOperatorNew = false;
188}
189
190
191
192template <class IT, class NT>
193SpTuples<IT, NT>::SpTuples (const SpCCols<IT, NT> &rhs) :
194 m(rhs.m), n(rhs.n), nnz(rhs.nnz)
195{
196 isOperatorNew = false;
197 if (nnz > 0)
198 {
199 tuples = new std::tuple<IT, IT, NT>[nnz];
200 Csc<IT, NT> *csc = rhs.csc;
201 IT k = 0;
202 for (IT i = 0; i < csc->n; ++i)
203 {
204 for (IT j = csc->jc[i]; j < csc->jc[i + 1]; ++j)
205 {
206 colindex(k) = i;
207 rowindex(k) = csc->ir[j];
208 numvalue(k++) = csc->num[j];
209 }
210 }
211 }
212}
213
214
215
216template <class IT,class NT>
217inline void SpTuples<IT,NT>::FillTuples (Dcsc<IT,NT> * mydcsc)
218{
219 tuples = new std::tuple<IT, IT, NT>[nnz];
220 IT k = 0;
221 for(IT i = 0; i< mydcsc->nzc; ++i)
222 {
223 for(IT j = mydcsc->cp[i]; j< mydcsc->cp[i+1]; ++j)
224 {
225 colindex(k) = mydcsc->jc[i];
226 rowindex(k) = mydcsc->ir[j];
227 numvalue(k++) = mydcsc->numx[j];
228 }
229 }
230}
231
232
233// Hint1: The assignment operator (operates on an existing object)
234// Hint2: The assignment operator is the only operator that is not inherited.
235// Make sure that base class data are also updated during assignment
236template <class IT,class NT>
237SpTuples<IT,NT> & SpTuples<IT,NT>::operator=(const SpTuples<IT,NT> & rhs)
238{
239 if(this != &rhs) // "this" pointer stores the address of the class instance
240 {
241 if(nnz > 0)
242 {
243 // make empty
244 if(isOperatorNew)
245 ::operator delete(tuples);
246 else
247 delete [] tuples;
248 }
249 m = rhs.m;
250 n = rhs.n;
251 nnz = rhs.nnz;
252 isOperatorNew = false;
253
254 if(nnz> 0)
255 {
256 tuples = new std::tuple<IT, IT, NT>[nnz];
257 for(IT i=0; i< nnz; ++i)
258 {
259 tuples[i] = rhs.tuples[i];
260 }
261 }
262 }
263 return *this;
264}
265
269template <class IT,class NT>
270template <typename BINFUNC>
271void SpTuples<IT,NT>::RemoveDuplicates(BINFUNC BinOp)
272{
273 if(nnz > 0)
274 {
275 std::vector< std::tuple<IT, IT, NT> > summed;
276 summed.push_back(tuples[0]);
277
278 for(IT i=1; i< nnz; ++i)
279 {
280 if((joker::get<0>(summed.back()) == joker::get<0>(tuples[i])) && (joker::get<1>(summed.back()) == joker::get<1>(tuples[i])))
281 {
282 joker::get<2>(summed.back()) = BinOp(joker::get<2>(summed.back()), joker::get<2>(tuples[i]));
283 }
284 else
285 {
286 summed.push_back(tuples[i]);
287
288 }
289 }
290 if(isOperatorNew)
291 ::operator delete(tuples);
292 else
293 delete [] tuples;
294 tuples = new std::tuple<IT, IT, NT>[summed.size()];
295 isOperatorNew = false;
296 std::copy(summed.begin(), summed.end(), tuples);
297 nnz = summed.size();
298 }
299}
300
301
304template <class IT,class NT>
305std::ifstream& SpTuples<IT,NT>::getstream (std::ifstream& infile)
306{
307 std::cout << "Getting... SpTuples" << std::endl;
308 IT cnz = 0;
309 if (infile.is_open())
310 {
311 while ( (!infile.eof()) && cnz < nnz)
312 {
313 infile >> rowindex(cnz) >> colindex(cnz) >> numvalue(cnz); // row-col-value
314
315 rowindex(cnz) --;
316 colindex(cnz) --;
317
318 if((rowindex(cnz) > m) || (colindex(cnz) > n))
319 {
320 std::cerr << "supplied matrix indices are beyond specified boundaries, aborting..." << std::endl;
321 }
322 ++cnz;
323 }
324 assert(nnz == cnz);
325 }
326 else
327 {
328 std::cerr << "input file is not open!" << std::endl;
329 }
330 return infile;
331}
332
335template <class IT,class NT>
336std::ofstream& SpTuples<IT,NT>::putstream(std::ofstream& outfile) const
337{
338 outfile << m <<"\t"<< n <<"\t"<< nnz<<std::endl;
339 for (IT i = 0; i < nnz; ++i)
340 {
341 outfile << rowindex(i)+1 <<"\t"<< colindex(i)+1 <<"\t"
342 << numvalue(i) << std::endl;
343 }
344 return outfile;
345}
346
347template <class IT,class NT>
348void SpTuples<IT,NT>::PrintInfo()
349{
350 std::cout << "This is a SpTuples class" << std::endl;
351
352 std::cout << "m: " << m ;
353 std::cout << ", n: " << n ;
354 std::cout << ", nnz: "<< nnz << std::endl;
355
356 for(IT i=0; i< nnz; ++i)
357 {
358 if(rowindex(i) < 0 || colindex(i) < 0)
359 {
360 std::cout << "Negative index at " << i << std::endl;
361 return;
362 }
363 else if(rowindex(i) >= m || colindex(i) >= n)
364 {
365 std::cout << "Index " << i << " too big with values (" << rowindex(i) << ","<< colindex(i) << ")" << std::endl;
366 }
367 }
368
369 if(m < 8 && n < 8) // small enough to print
370 {
371 NT ** A = SpHelper::allocate2D<NT>(m,n);
372 for(IT i=0; i< m; ++i)
373 for(IT j=0; j<n; ++j)
374 A[i][j] = 0.0;
375
376 for(IT i=0; i< nnz; ++i)
377 {
378 A[rowindex(i)][colindex(i)] = numvalue(i);
379 }
380 for(IT i=0; i< m; ++i)
381 {
382 for(IT j=0; j<n; ++j)
383 {
384 std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(2) << A[i][j];
385 std::cout << " ";
386 }
387 std::cout << std::endl;
388 }
389 SpHelper::deallocate2D(A,m);
390 }
391}
392
393}
int64_t IT
double NT
int size
Definition common.h:20
long int64_t
Definition compat.h:21
double A