45 template <
class IU,
class NU>
48 template <
class IU,
class NU>
51 template <
class IU,
class NU>
60 template <
typename SR,
typename IU,
typename NU,
typename RHS,
typename LHS>
65 for(IU j =0; j<A.
dcsc->nzc; ++j)
67 IU colid = A.
dcsc->jc[j];
68 for(IU i = A.
dcsc->cp[j]; i< A.dcsc->
cp[j+1]; ++i)
70 IU rowid = A.
dcsc->ir[i];
74 cout <<
"the semiring returned SAID but that is not implemented. results will be incorrect." << endl;
75 throw string(
"the semiring returned SAID but that is not implemented. results will be incorrect.");
86 template <
typename SR,
typename IU,
typename NUM,
typename IVT,
typename OVT>
88 int32_t * & sendindbuf, OVT * & sendnumbuf,
int * & sdispls,
int p_c)
94 sdispls =
new int[p_c]();
95 if(A.
getnnz() > 0 && nnzx > 0)
100 int32_t nlocrows =
static_cast<int32_t
>(A.
getnrow());
101 int32_t perpiece = nlocrows / splits;
102 vector< vector< int32_t > > indy(splits);
103 vector< vector< OVT > > numy(splits);
107 #pragma omp parallel for // num_threads(6)
109 for(
int i=0; i<splits; ++i)
112 SpMXSpV_ForThreading<SR>(*(A.
GetDCSC(i)), perpiece, indx, numx, nnzx, indy[i], numy[i], i*perpiece);
114 SpMXSpV_ForThreading<SR>(*(A.
GetDCSC(i)), nlocrows - perpiece*i, indx, numx, nnzx, indy[i], numy[i], i*perpiece);
117 vector<int> accum(splits+1, 0);
118 for(
int i=0; i<splits; ++i)
119 accum[i+1] = accum[i] + indy[i].
size();
121 sendindbuf =
new int32_t[accum[splits]];
122 sendnumbuf =
new OVT[accum[splits]];
123 int32_t perproc = nlocrows / p_c;
124 int32_t last_rec = p_c-1;
128 vector<int32_t> end_recs(splits);
129 for(
int i=0; i<splits; ++i)
134 end_recs[i] = min(indy[i].back() / perproc, last_rec);
137 #pragma omp parallel for // num_threads(6)
139 for(
int i=0; i<splits; ++i)
145 int32_t beg_rec = min( indy[i].front() / perproc, last_rec);
152 while (k >= 0 && end_recs[k] == -1) k--;
155 fill(sdispls+end_recs[k]+1, sdispls+beg_rec+1, accum[i]);
160 if(beg_rec == end_recs[i])
162 transform(indy[i].begin(), indy[i].end(), indy[i].begin(), bind2nd(minus<int32_t>(), perproc*beg_rec));
163 copy(indy[i].begin(), indy[i].end(), sendindbuf+accum[i]);
164 copy(numy[i].begin(), numy[i].end(), sendnumbuf+accum[i]);
170 int end = indy[i].size();
171 for(
int cur=0; cur< end; ++cur)
173 int32_t cur_rec = min( indy[i][cur] / perproc, last_rec);
174 while(beg_rec != cur_rec)
176 sdispls[++beg_rec] = accum[i] + cur;
178 sendindbuf[ accum[i] + cur ] = indy[i][cur] - perproc*beg_rec;
179 sendnumbuf[ accum[i] + cur ] = numy[i][cur];
182 vector<int32_t>().swap(indy[i]);
183 vector<OVT>().swap(numy[i]);
184 bool lastnonzero =
true;
185 for(
int k=i+1; k < splits; ++k)
187 if(end_recs[k] != -1)
191 fill(sdispls+end_recs[i]+1, sdispls+p_c, accum[i+1]);
194 return accum[splits];
198 cout <<
"Something is wrong, splits should be nonzero for multithreaded execution" << endl;
218 template <
typename SR,
typename IU,
typename NUM,
typename IVT,
typename OVT>
220 int32_t * sendindbuf, OVT * sendnumbuf,
int * cnts,
int * dspls,
int p_c)
222 if(A.
getnnz() > 0 && nnzx > 0)
227 vector< vector<int32_t> > indy(splits);
228 vector< vector< OVT > > numy(splits);
229 int32_t nlocrows =
static_cast<int32_t
>(A.
getnrow());
230 int32_t perpiece = nlocrows / splits;
233 #pragma omp parallel for
235 for(
int i=0; i<splits; ++i)
238 SpMXSpV_ForThreading<SR>(*(A.
GetDCSC(i)), perpiece, indx, numx, nnzx, indy[i], numy[i], i*perpiece);
240 SpMXSpV_ForThreading<SR>(*(A.
GetDCSC(i)), nlocrows - perpiece*i, indx, numx, nnzx, indy[i], numy[i], i*perpiece);
243 int32_t perproc = nlocrows / p_c;
244 int32_t last_rec = p_c-1;
248 vector<int32_t> end_recs(splits);
249 for(
int i=0; i<splits; ++i)
254 end_recs[i] = min(indy[i].back() / perproc, last_rec);
257 int ** loc_rec_cnts =
new int *[splits];
259 #pragma omp parallel for
261 for(
int i=0; i<splits; ++i)
263 loc_rec_cnts[i] =
new int[p_c]();
266 int32_t cur_rec = min( indy[i].front() / perproc, last_rec);
267 int32_t lastdata = (cur_rec+1) * perproc;
268 for(
typename vector<int32_t>::iterator it = indy[i].begin(); it != indy[i].end(); ++it)
271 if( ( (*it) >= lastdata ) && cur_rec != last_rec )
273 cur_rec = min( (*it) / perproc, last_rec);
274 lastdata = (cur_rec+1) * perproc;
276 ++loc_rec_cnts[i][cur_rec];
281 #pragma omp parallel for
283 for(
int i=0; i<splits; ++i)
289 int32_t beg_rec = min( indy[i].front() / perproc, last_rec);
290 int32_t alreadysent = 0;
291 for(
int before = i-1; before >= 0; before--)
292 alreadysent += loc_rec_cnts[before][beg_rec];
294 if(beg_rec == end_recs[i])
296 transform(indy[i].begin(), indy[i].end(), indy[i].begin(), bind2nd(minus<int32_t>(), perproc*beg_rec));
297 copy(indy[i].begin(), indy[i].end(), sendindbuf + dspls[beg_rec] + alreadysent);
298 copy(numy[i].begin(), numy[i].end(), sendnumbuf + dspls[beg_rec] + alreadysent);
302 int32_t cur_rec = beg_rec;
303 int32_t lastdata = (cur_rec+1) * perproc;
304 for(
typename vector<int32_t>::iterator it = indy[i].begin(); it != indy[i].end(); ++it)
306 if( ( (*it) >= lastdata ) && cur_rec != last_rec )
308 cur_rec = min( (*it) / perproc, last_rec);
309 lastdata = (cur_rec+1) * perproc;
315 sendindbuf[ dspls[cur_rec] + alreadysent ] = (*it) - perproc*cur_rec;
316 sendnumbuf[ dspls[cur_rec] + (alreadysent++) ] = *(numy[i].begin() + (it-indy[i].begin()));
322 for(
int i=0; i< splits; ++i)
324 for(
int j=0; j< p_c; ++j)
325 cnts[j] += loc_rec_cnts[i][j];
326 delete [] loc_rec_cnts[i];
328 delete [] loc_rec_cnts;
332 cout <<
"Something is wrong, splits should be nonzero for multithreaded execution" << endl;
340 template <
typename SR,
typename MIND,
typename VIND,
typename NUM,
typename IVT,
typename OVT>
343 if(A.
getnnz() > 0 && nnzx > 0)
347 cout <<
"Call dcsc_gespmv_threaded instead" << endl;
359 template <
typename SR,
typename IU,
typename NUM,
typename IVT,
typename OVT>
361 int32_t * indy, OVT * numy,
int * cnts,
int * dspls,
int p_c,
bool indexisvalue)
363 if(A.
getnnz() > 0 && nnzx > 0)
373 int32_t localm = (int32_t) A.
getnrow();
375 SpMXSpV(*(A.
GetDCSC()), localm, indx, numx, nnzx, indy, numy, cnts, dspls, p_c, isthere);
379 SpMXSpV<SR>(*(A.
GetDCSC()), (int32_t) A.
getnrow(), indx,
numx, nnzx, indy, numy, cnts, dspls, p_c);
385 template<
typename IU>
388 A.splits = numsplits;
389 IU perpiece = A.m / A.splits;
390 vector<IU> prevcolids(A.splits, -1);
391 vector<IU> nzcs(A.splits, 0);
392 vector<IU> nnzs(A.splits, 0);
393 vector < vector < pair<IU,IU> > > colrowpairs(A.splits);
394 if(A.nnz > 0 && A.
dcsc != NULL)
396 for(IU i=0; i< A.
dcsc->nzc; ++i)
398 for(IU j = A.
dcsc->cp[i]; j< A.dcsc->
cp[i+1]; ++j)
400 IU colid = A.
dcsc->jc[i];
401 IU rowid = A.
dcsc->ir[j];
402 IU owner = min(rowid / perpiece, static_cast<IU>(A.splits-1));
403 colrowpairs[owner].push_back(make_pair(colid, rowid - owner*perpiece));
405 if(prevcolids[owner] != colid)
407 prevcolids[owner] = colid;
420 for(
int i=0; i< A.splits; ++i)
422 sort(colrowpairs[i].begin(), colrowpairs[i].end());
424 fill(A.
dcscarr[i]->numx, A.
dcscarr[i]->numx+nnzs[i], static_cast<bool>(1));
426 IU cindex = colrowpairs[i][0].first;
427 IU rindex = colrowpairs[i][0].second;
430 A.
dcscarr[i]->jc[curnzc] = cindex;
431 A.
dcscarr[i]->cp[curnzc++] = 0;
433 for(IU j=1; j<nnzs[i]; ++j)
435 cindex = colrowpairs[i][j].first;
436 rindex = colrowpairs[i][j].second;
439 if(cindex != A.
dcscarr[i]->jc[curnzc-1])
441 A.
dcscarr[i]->jc[curnzc] = cindex;
442 A.
dcscarr[i]->cp[curnzc++] = j;
445 A.
dcscarr[i]->cp[curnzc] = nnzs[i];
456 template<
class SR,
class NUO,
class IU,
class NU1,
class NU2>
460 bool clearA =
false,
bool clearB =
false)
471 Isect<IU> *isect1, *isect2, *itr1, *itr2, *cols, *rows;
474 IU kisect =
static_cast<IU
>(itr1-isect1);
485 IU cnz = SpHelper::SpCartesian< SR > (*(A.
dcsc), *(B.
dcsc), kisect, isect1, isect2, multstack);
499 template<
class SR,
class NUO,
class IU,
class NU1,
class NU2>
503 bool clearA =
false,
bool clearB =
false)
512 IU cnz = SpHelper::SpColByCol< SR > (*(A.
dcsc), *(B.
dcsc), A.n, multstack);
523 template<
class SR,
class NUO,
class IU,
class NU1,
class NU2>
527 bool clearA =
false,
bool clearB =
false)
531 cout <<
"Tuples_AtXBt function has not been implemented yet !" << endl;
536 template<
class SR,
class NUO,
class IU,
class NU1,
class NU2>
540 bool clearA =
false,
bool clearB =
false)
544 cout <<
"Tuples_AtXBn function has not been implemented yet !" << endl;
551 template<
class SR,
class IU,
class NU>
554 int hsize = ArrSpTups.size();
561 mstar = ArrSpTups[0]->m;
562 nstar = ArrSpTups[0]->n;
564 for(
int i=1; i< hsize; ++i)
566 if((mstar != ArrSpTups[i]->m) || nstar != ArrSpTups[i]->n)
568 cerr <<
"Dimensions do not match on MergeAll()" << endl;
575 tuple<IU, IU, int> * heap =
new tuple<IU, IU, int> [hsize];
576 IU * curptr =
new IU[hsize];
577 fill_n(curptr, hsize, static_cast<IU>(0));
580 for(
int i=0; i< hsize; ++i)
582 estnnz += ArrSpTups[i]->getnnz();
583 heap[i] = make_tuple(get<0>(ArrSpTups[i]->tuples[0]), get<1>(ArrSpTups[i]->tuples[0]), i);
585 make_heap(heap, heap+hsize, not2(heapcomp));
587 tuple<IU, IU, NU> * ntuples =
new tuple<IU,IU,NU>[estnnz];
592 pop_heap(heap, heap + hsize, not2(heapcomp));
593 int source = get<2>(heap[hsize-1]);
596 ((get<0>(ntuples[cnz-1]) == get<0>(heap[hsize-1])) && (get<1>(ntuples[cnz-1]) == get<1>(heap[hsize-1]))) )
598 get<2>(ntuples[cnz-1]) =
SR::add(get<2>(ntuples[cnz-1]), ArrSpTups[source]->numvalue(curptr[source]++));
602 ntuples[cnz++] = ArrSpTups[source]->tuples[curptr[source]++];
605 if(curptr[source] != ArrSpTups[source]->getnnz())
607 heap[hsize-1] = make_tuple(get<0>(ArrSpTups[source]->tuples[curptr[source]]),
608 get<1>(ArrSpTups[source]->tuples[curptr[source]]), source);
609 push_heap(heap, heap+hsize, not2(heapcomp));
621 for(
size_t i=0; i<ArrSpTups.size(); ++i)
640 template <
typename IU,
typename NU1,
typename NU2>
652 estnzc = std::min(A.
nzc, B->
nzc);
653 estnz = std::min(A.
nz, B->
nz);
666 while(i< A.
nzc && B != NULL && j<B->
nzc)
668 if(A.
jc[i] > B->
jc[j]) ++j;
669 else if(A.
jc[i] < B->
jc[j]) ++i;
675 while (ii < A.
cp[i+1] && jj < B->
cp[j+1])
677 if (A.
ir[ii] < B->
ir[jj]) ++ii;
678 else if (A.
ir[ii] > B->
ir[jj]) ++jj;
681 temp.
ir[curnz] = A.
ir[ii];
687 temp.
jc[curnzc++] = A.
jc[i];
688 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
697 while(i< A.
nzc && B != NULL && j< B->
nzc)
699 if(A.
jc[i] > B->
jc[j]) ++j;
700 else if(A.
jc[i] < B->
jc[j])
702 temp.
jc[curnzc++] = A.
jc[i++];
703 for(IU k = A.
cp[i-1]; k< A.
cp[i]; k++)
705 temp.
ir[curnz] = A.
ir[k];
708 temp.
cp[curnzc] = temp.
cp[curnzc-1] + (A.
cp[i] - A.
cp[i-1]);
715 while (ii < A.
cp[i+1] && jj < B->
cp[j+1])
717 if (A.
ir[ii] > B->
ir[jj]) ++jj;
718 else if (A.
ir[ii] < B->
ir[jj])
720 temp.
ir[curnz] = A.
ir[ii];
729 while (ii < A.
cp[i+1])
731 temp.
ir[curnz] = A.
ir[ii];
737 temp.
jc[curnzc++] = A.
jc[i];
738 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
746 temp.
jc[curnzc++] = A.
jc[i++];
747 for(IU k = A.
cp[i-1]; k< A.
cp[i]; ++k)
749 temp.
ir[curnz] = A.
ir[k];
752 temp.
cp[curnzc] = temp.
cp[curnzc-1] + (A.
cp[i] - A.
cp[i-1]);
756 temp.
Resize(curnzc, curnz);
760 template <
typename N_promote,
typename IU,
typename NU1,
typename NU2,
typename _BinaryOperation>
772 estnzc = std::min(A.
nzc, B->
nzc);
773 estnz = std::min(A.
nz, B->
nz);
786 while(i< A.
nzc && B != NULL && j<B->
nzc)
788 if(A.
jc[i] > B->
jc[j]) ++j;
789 else if(A.
jc[i] < B->
jc[j]) ++i;
795 while (ii < A.
cp[i+1] && jj < B->
cp[j+1])
797 if (A.
ir[ii] < B->
ir[jj]) ++ii;
798 else if (A.
ir[ii] > B->
ir[jj]) ++jj;
801 temp.
ir[curnz] = A.
ir[ii];
802 temp.
numx[curnz++] = __binary_op(A.
numx[ii++], B->
numx[jj++]);
807 temp.
jc[curnzc++] = A.
jc[i];
808 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
817 while(i< A.
nzc && B != NULL && j< B->
nzc)
819 if(A.
jc[i] > B->
jc[j]) ++j;
820 else if(A.
jc[i] < B->
jc[j])
822 temp.
jc[curnzc++] = A.
jc[i++];
823 for(IU k = A.
cp[i-1]; k< A.
cp[i]; k++)
825 temp.
ir[curnz] = A.
ir[k];
826 temp.
numx[curnz++] = __binary_op(A.
numx[k], defaultBVal);
828 temp.
cp[curnzc] = temp.
cp[curnzc-1] + (A.
cp[i] - A.
cp[i-1]);
835 while (ii < A.
cp[i+1] && jj < B->
cp[j+1])
837 if (A.
ir[ii] > B->
ir[jj]) ++jj;
838 else if (A.
ir[ii] < B->
ir[jj])
840 temp.
ir[curnz] = A.
ir[ii];
841 temp.
numx[curnz++] = __binary_op(A.
numx[ii++], defaultBVal);
849 while (ii < A.
cp[i+1])
851 temp.
ir[curnz] = A.
ir[ii];
852 temp.
numx[curnz++] = __binary_op(A.
numx[ii++], defaultBVal);
857 temp.
jc[curnzc++] = A.
jc[i];
858 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
866 temp.
jc[curnzc++] = A.
jc[i++];
867 for(IU k = A.
cp[i-1]; k< A.
cp[i]; ++k)
869 temp.
ir[curnz] = A.
ir[k];
870 temp.
numx[curnz++] = __binary_op(A.
numx[k], defaultBVal);
872 temp.
cp[curnzc] = temp.
cp[curnzc-1] + (A.
cp[i] - A.
cp[i-1]);
876 temp.
Resize(curnzc, curnz);
881 template<
typename IU,
typename NU1,
typename NU2>
889 if(A.nnz > 0 && B.nnz > 0)
894 else if (A.nnz > 0 && exclude)
906 template<
typename N_promote,
typename IU,
typename NU1,
typename NU2,
typename _BinaryOperation>
914 if(A.nnz > 0 && B.nnz > 0)
919 else if (A.nnz > 0 && notB)
939 template <
typename RETT,
typename IU,
typename NU1,
typename NU2,
typename _BinaryOperation,
typename _BinaryPredicate>
940 Dcsc<IU, RETT> EWiseApply(
const Dcsc<IU,NU1> * Ap,
const Dcsc<IU,NU2> * Bp, _BinaryOperation __binary_op, _BinaryPredicate do_op,
bool allowANulls,
bool allowBNulls,
const NU1& ANullVal,
const NU2& BNullVal,
const bool allowIntersect)
942 if (Ap == NULL && Bp == NULL)
945 if (Ap == NULL && Bp != NULL)
965 temp.
jc[curnzc++] = B.
jc[j-1];
966 for(IU k = B.
cp[j-1]; k< B.
cp[j]; ++k)
968 if (do_op(ANullVal, B.
numx[k],
true,
false))
970 temp.
ir[curnz] = B.
ir[k];
971 temp.
numx[curnz++] = __binary_op(ANullVal, B.
numx[k],
true,
false);
975 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
977 temp.
Resize(curnzc, curnz);
981 if (Ap != NULL && Bp == NULL)
1000 temp.
jc[curnzc++] = A.
jc[i-1];
1001 for(IU k = A.
cp[i-1]; k< A.
cp[i]; k++)
1003 if (do_op(A.
numx[k], BNullVal,
false,
true))
1005 temp.
ir[curnz] = A.
ir[k];
1006 temp.
numx[curnz++] = __binary_op(A.
numx[k], BNullVal,
false,
true);
1010 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
1012 temp.
Resize(curnzc, curnz);
1020 IU estnzc = A.
nzc + B.
nzc;
1021 IU estnz = A.
nz + B.
nz;
1029 while(i< A.
nzc && j<B.
nzc)
1031 if(A.
jc[i] > B.
jc[j])
1037 temp.
jc[curnzc++] = B.
jc[j-1];
1038 for(IU k = B.
cp[j-1]; k< B.
cp[j]; ++k)
1040 if (do_op(ANullVal, B.
numx[k],
true,
false))
1042 temp.
ir[curnz] = B.
ir[k];
1043 temp.
numx[curnz++] = __binary_op(ANullVal, B.
numx[k],
true,
false);
1047 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
1050 else if(A.
jc[i] < B.
jc[j])
1056 temp.
jc[curnzc++] = A.
jc[i-1];
1057 for(IU k = A.
cp[i-1]; k< A.
cp[i]; k++)
1059 if (do_op(A.
numx[k], BNullVal,
false,
true))
1061 temp.
ir[curnz] = A.
ir[k];
1062 temp.
numx[curnz++] = __binary_op(A.
numx[k], BNullVal,
false,
true);
1066 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
1071 temp.
jc[curnzc++] = A.
jc[i];
1075 while (ii < A.
cp[i+1] && jj < B.
cp[j+1])
1077 if (A.
ir[ii] < B.
ir[jj])
1079 if (allowBNulls && do_op(A.
numx[ii], BNullVal,
false,
true))
1081 temp.
ir[curnz] = A.
ir[ii];
1082 temp.
numx[curnz++] = __binary_op(A.
numx[ii++], BNullVal,
false,
true);
1087 else if (A.
ir[ii] > B.
ir[jj])
1089 if (allowANulls && do_op(ANullVal, B.
numx[jj],
true,
false))
1091 temp.
ir[curnz] = B.
ir[jj];
1092 temp.
numx[curnz++] = __binary_op(ANullVal, B.
numx[jj++],
true,
false);
1099 if (allowIntersect && do_op(A.
numx[ii], B.
numx[jj],
false,
false))
1101 temp.
ir[curnz] = A.
ir[ii];
1102 temp.
numx[curnz++] = __binary_op(A.
numx[ii++], B.
numx[jj++],
false,
false);
1111 while (ii < A.
cp[i+1])
1113 if (allowBNulls && do_op(A.
numx[ii], BNullVal,
false,
true))
1115 temp.
ir[curnz] = A.
ir[ii];
1116 temp.
numx[curnz++] = __binary_op(A.
numx[ii++], BNullVal,
false,
true);
1121 while (jj < B.
cp[j+1])
1123 if (allowANulls && do_op(ANullVal, B.
numx[jj],
true,
false))
1125 temp.
ir[curnz] = B.
ir[jj];
1126 temp.
numx[curnz++] = __binary_op(ANullVal, B.
numx[jj++],
true,
false);
1131 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
1136 while(allowBNulls && i< A.
nzc)
1139 temp.
jc[curnzc++] = A.
jc[i++];
1140 for(IU k = A.
cp[i-1]; k< A.
cp[i]; ++k)
1142 if (do_op(A.
numx[k], BNullVal,
false,
true))
1144 temp.
ir[curnz] = A.
ir[k];
1145 temp.
numx[curnz++] = __binary_op(A.
numx[k], BNullVal,
false,
true);
1149 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
1151 while(allowANulls && j < B.
nzc)
1154 temp.
jc[curnzc++] = B.
jc[j++];
1155 for(IU k = B.
cp[j-1]; k< B.
cp[j]; ++k)
1157 if (do_op(ANullVal, B.
numx[k],
true,
false))
1159 temp.
ir[curnz] = B.
ir[k];
1160 temp.
numx[curnz++] = __binary_op(ANullVal, B.
numx[k],
true,
false);
1164 temp.
cp[curnzc] = temp.
cp[curnzc-1] + curnz-prevnz;
1166 temp.
Resize(curnzc, curnz);
1170 template <
typename RETT,
typename IU,
typename NU1,
typename NU2,
typename _BinaryOperation,
typename _BinaryPredicate>
1171 SpDCCols<IU,RETT> EWiseApply (
const SpDCCols<IU,NU1> & A,
const SpDCCols<IU,NU2> & B, _BinaryOperation __binary_op, _BinaryPredicate do_op,
bool allowANulls,
bool allowBNulls,
const NU1& ANullVal,
const NU2& BNullVal,
const bool allowIntersect)
1176 Dcsc<IU, RETT> * tdcsc =
new Dcsc<IU, RETT>(EWiseApply<RETT>(A.
dcsc, B.
dcsc, __binary_op, do_op, allowANulls, allowBNulls, ANullVal, BNullVal, allowIntersect));