1 /*
2    Copyright (c) 2009-2014, Jack Poulson
3    All rights reserved.
4 
5    This file is part of Elemental and is under the BSD 2-Clause License,
6    which can be found in the LICENSE file in the root directory, or at
7    http://opensource.org/licenses/BSD-2-Clause
8 */
9 #include "elemental-lite.hpp"
10 #include ELEM_TRANSPOSE_INC
11 #include ELEM_ZEROS_INC
12 
13 namespace elem {
14 
15 // Public section
16 // ##############
17 
18 // Constructors and destructors
19 // ============================
20 
21 template<typename T,Dist U,Dist V>
GeneralBlockDistMatrix(const elem::Grid & g,Int root)22 GeneralBlockDistMatrix<T,U,V>::GeneralBlockDistMatrix
23 ( const elem::Grid& g, Int root )
24 : AbstractBlockDistMatrix<T>(g,root)
25 { }
26 
27 template<typename T,Dist U,Dist V>
GeneralBlockDistMatrix(const elem::Grid & g,Int blockHeight,Int blockWidth,Int root)28 GeneralBlockDistMatrix<T,U,V>::GeneralBlockDistMatrix
29 ( const elem::Grid& g, Int blockHeight, Int blockWidth, Int root )
30 : AbstractBlockDistMatrix<T>(g,blockHeight,blockWidth,root)
31 { }
32 
33 template<typename T,Dist U,Dist V>
GeneralBlockDistMatrix(GeneralBlockDistMatrix<T,U,V> && A)34 GeneralBlockDistMatrix<T,U,V>::GeneralBlockDistMatrix
35 ( GeneralBlockDistMatrix<T,U,V>&& A ) ELEM_NOEXCEPT
36 : AbstractBlockDistMatrix<T>(std::move(A))
37 { }
38 
39 // Assignment and reconfiguration
40 // ==============================
41 
42 template<typename T,Dist U,Dist V>
43 GeneralBlockDistMatrix<T,U,V>&
operator =(GeneralBlockDistMatrix<T,U,V> && A)44 GeneralBlockDistMatrix<T,U,V>::operator=( GeneralBlockDistMatrix<T,U,V>&& A )
45 {
46     AbstractBlockDistMatrix<T>::operator=( std::move(A) );
47     return *this;
48 }
49 
50 template<typename T,Dist U,Dist V>
51 void
AlignColsWith(const elem::BlockDistData & data,bool constrain)52 GeneralBlockDistMatrix<T,U,V>::AlignColsWith
53 ( const elem::BlockDistData& data, bool constrain )
54 {
55     DEBUG_ONLY(CallStackEntry cse("GBDM::AlignColsWith"))
56     this->SetGrid( *data.grid );
57     this->SetRoot( data.root );
58     if( data.colDist == U || data.colDist == UPart )
59         this->AlignCols
60         ( data.blockHeight, data.colAlign, data.colCut, constrain );
61     else if( data.rowDist == U || data.rowDist == UPart )
62         this->AlignCols
63         ( data.blockWidth, data.rowAlign, data.rowCut, constrain );
64     else if( data.colDist == UScat )
65         this->AlignCols
66         ( data.blockHeight, data.colAlign % this->ColStride(), data.colCut,
67           constrain );
68     else if( data.rowDist == UScat )
69         this->AlignCols
70         ( data.blockWidth, data.rowAlign % this->ColStride(), data.rowCut,
71           constrain );
72     DEBUG_ONLY(
73         else if( U != UGath && data.colDist != UGath && data.rowDist != UGath )
74             LogicError("Nonsensical alignment");
75     )
76 }
77 
78 template<typename T,Dist U,Dist V>
79 void
AlignRowsWith(const elem::BlockDistData & data,bool constrain)80 GeneralBlockDistMatrix<T,U,V>::AlignRowsWith
81 ( const elem::BlockDistData& data, bool constrain )
82 {
83     DEBUG_ONLY(CallStackEntry cse("GBDM::AlignRowsWith"))
84     this->SetGrid( *data.grid );
85     this->SetRoot( data.root );
86     if( data.colDist == V || data.colDist == VPart )
87         this->AlignRows
88         ( data.blockHeight, data.colAlign, data.colCut, constrain );
89     else if( data.rowDist == V || data.rowDist == VPart )
90         this->AlignRows
91         ( data.blockWidth, data.rowAlign, data.rowCut, constrain );
92     else if( data.colDist == VScat )
93         this->AlignRows
94         ( data.blockHeight, data.colAlign % this->RowStride(), data.colCut,
95           constrain );
96     else if( data.rowDist == VScat )
97         this->AlignRows
98         ( data.blockWidth, data.rowAlign % this->RowStride(), data.rowCut,
99           constrain );
100     DEBUG_ONLY(
101         else if( V != VGath && data.colDist != VGath && data.rowDist != VGath )
102             LogicError("Nonsensical alignment");
103     )
104 }
105 
106 template<typename T,Dist U,Dist V>
107 void
Translate(BlockDistMatrix<T,U,V> & A) const108 GeneralBlockDistMatrix<T,U,V>::Translate( BlockDistMatrix<T,U,V>& A ) const
109 {
110     DEBUG_ONLY(CallStackEntry cse("GBDM::Translate"))
111     const Int height = this->Height();
112     const Int width = this->Width();
113     const Int blockHeight = this->BlockHeight();
114     const Int blockWidth = this->BlockWidth();
115     const Int colAlign = this->ColAlign();
116     const Int rowAlign = this->RowAlign();
117     const Int colCut = this->ColCut();
118     const Int rowCut = this->RowCut();
119     const Int root = this->Root();
120     A.SetGrid( this->Grid() );
121     if( !A.RootConstrained() )
122         A.SetRoot( root, false );
123     if( !A.ColConstrained() )
124         A.AlignCols( blockHeight, colAlign, colCut, false );
125     if( !A.RowConstrained() )
126         A.AlignRows( blockWidth, rowAlign, rowCut, false );
127     A.Resize( height, width );
128     const bool aligned =
129         blockHeight == A.BlockHeight() && blockWidth == A.BlockWidth() &&
130         colAlign    == A.ColAlign()    && rowAlign   == A.RowAlign() &&
131         colCut      == A.ColCut()      && rowCut     == A.RowCut();
132     if( aligned && root == A.Root() )
133     {
134         A.matrix_ = this->matrix_;
135     }
136     else
137     {
138         // TODO: Implement this in a more efficient manner, perhaps through
139         //       many rounds of point-to-point communication
140         // TODO: Turn this into a general routine for redistributing
141         //       between any matrix distributions supported by Elemental.
142         //       The key addition is mpi::Translate.
143         const Int distSize = A.DistSize();
144         const Int mLocal = this->LocalHeight();
145         const Int nLocal = this->LocalWidth();
146         const Int mLocalA = A.LocalHeight();
147         const Int nLocalA = A.LocalWidth();
148 
149         // Determine how much data our process sends and recvs from every
150         // other process
151         std::vector<int> sendCounts(distSize,0),
152                          recvCounts(distSize,0);
153         for( Int jLoc=0; jLoc<nLocal; ++jLoc )
154         {
155             const Int j = this->GlobalCol(jLoc);
156             for( Int iLoc=0; iLoc<mLocal; ++iLoc )
157             {
158                 const Int i = this->GlobalRow(iLoc);
159                 const Int owner = A.Owner(i,j);
160                 ++sendCounts[owner];
161             }
162         }
163         for( Int jLoc=0; jLoc<nLocalA; ++jLoc )
164         {
165             const Int j = A.GlobalCol(jLoc);
166             for( Int iLoc=0; iLoc<mLocalA; ++iLoc )
167             {
168                 const Int i = A.GlobalRow(iLoc);
169                 const Int owner = this->Owner(i,j);
170                 ++recvCounts[owner];
171             }
172         }
173 
174         // Translate the send/recv counts into displacements and allocate
175         // the send and recv buffers
176         std::vector<int> sendDispls(distSize), recvDispls(distSize);
177         int totalSend=0, totalRecv=0;
178         for( int q=0; q<distSize; ++q )
179         {
180             sendDispls[q] = totalSend;
181             recvDispls[q] = totalRecv;
182             totalSend += sendCounts[q];
183             totalRecv += recvCounts[q];
184         }
185         std::vector<T> sendBuf(totalSend), recvBuf(totalRecv);
186 
187         // Pack the send data
188         std::vector<int> offsets = sendDispls;
189         for( Int jLoc=0; jLoc<nLocal; ++jLoc )
190         {
191             const Int j = this->GlobalCol(jLoc);
192             for( Int iLoc=0; iLoc<mLocal; ++iLoc )
193             {
194                 const Int i = this->GlobalRow(iLoc);
195                 const Int owner = A.Owner(i,j);
196                 sendBuf[offsets[owner]++] = this->GetLocal(iLoc,jLoc);
197             }
198         }
199 
200         // Perform the all-to-all communication
201         mpi::AllToAll
202         ( sendBuf.data(), sendCounts.data(), sendDispls.data(),
203           recvBuf.data(), recvCounts.data(), recvDispls.data(),
204           this->DistComm() );
205         SwapClear( sendBuf );
206 
207         // Unpack the received data
208         offsets = recvDispls;
209         for( Int jLoc=0; jLoc<nLocalA; ++jLoc )
210         {
211             const Int j = A.GlobalCol(jLoc);
212             for( Int iLoc=0; iLoc<mLocalA; ++iLoc )
213             {
214                 const Int i = A.GlobalRow(iLoc);
215                 const Int owner = this->Owner(i,j);
216                 A.SetLocal( iLoc, jLoc, recvBuf[offsets[owner]++] );
217             }
218         }
219     }
220 }
221 
222 template<typename T,Dist U,Dist V>
223 void
AllGather(BlockDistMatrix<T,UGath,VGath> & A) const224 GeneralBlockDistMatrix<T,U,V>::AllGather
225 ( BlockDistMatrix<T,UGath,VGath>& A ) const
226 {
227     DEBUG_ONLY(
228         CallStackEntry cse("GBDM::AllGather");
229         this->AssertSameGrid( A.Grid() );
230     )
231     LogicError("This routine is not yet written");
232 }
233 
234 template<typename T,Dist U,Dist V>
235 void
ColAllGather(BlockDistMatrix<T,UGath,V> & A) const236 GeneralBlockDistMatrix<T,U,V>::ColAllGather
237 ( BlockDistMatrix<T,UGath,V>& A ) const
238 {
239     DEBUG_ONLY(
240         CallStackEntry cse("GBDM::ColAllGather");
241         this->AssertSameGrid( A.Grid() );
242     )
243     LogicError("This routine is not yet written");
244 }
245 
246 template<typename T,Dist U,Dist V>
247 void
RowAllGather(BlockDistMatrix<T,U,VGath> & A) const248 GeneralBlockDistMatrix<T,U,V>::RowAllGather
249 ( BlockDistMatrix<T,U,VGath>& A ) const
250 {
251     DEBUG_ONLY(
252         CallStackEntry cse("GBDM::RowAllGather");
253         this->AssertSameGrid( A.Grid() );
254     )
255     LogicError("This routine is not yet written");
256 }
257 
258 template<typename T,Dist U,Dist V>
259 void
PartialColAllGather(BlockDistMatrix<T,UPart,V> & A) const260 GeneralBlockDistMatrix<T,U,V>::PartialColAllGather
261 ( BlockDistMatrix<T,UPart,V>& A ) const
262 {
263     DEBUG_ONLY(
264         CallStackEntry cse("GBDM::PartialColAllGather");
265         this->AssertSameGrid( A.Grid() );
266     )
267     LogicError("This routine is not yet written");
268 }
269 
270 template<typename T,Dist U,Dist V>
271 void
PartialRowAllGather(BlockDistMatrix<T,U,VPart> & A) const272 GeneralBlockDistMatrix<T,U,V>::PartialRowAllGather
273 ( BlockDistMatrix<T,U,VPart>& A ) const
274 {
275     DEBUG_ONLY(
276         CallStackEntry cse("GBDM::PartialRowAllGather");
277         this->AssertSameGrid( A.Grid() );
278     )
279     LogicError("This routine is not yet written");
280 }
281 
282 template<typename T,Dist U,Dist V>
283 void
FilterFrom(const BlockDistMatrix<T,UGath,VGath> & A)284 GeneralBlockDistMatrix<T,U,V>::FilterFrom
285 ( const BlockDistMatrix<T,UGath,VGath>& A )
286 {
287     DEBUG_ONLY(
288         CallStackEntry cse("GBDM::FilterFrom");
289         this->AssertSameGrid( A.Grid() );
290     )
291     LogicError("This routine is not yet written");
292 }
293 
294 template<typename T,Dist U,Dist V>
295 void
ColFilterFrom(const BlockDistMatrix<T,UGath,V> & A)296 GeneralBlockDistMatrix<T,U,V>::ColFilterFrom
297 ( const BlockDistMatrix<T,UGath,V>& A )
298 {
299     DEBUG_ONLY(
300         CallStackEntry cse("GBDM::ColFilterFrom");
301         this->AssertSameGrid( A.Grid() );
302     )
303     LogicError("This routine is not yet written");
304 }
305 
306 template<typename T,Dist U,Dist V>
307 void
RowFilterFrom(const BlockDistMatrix<T,U,VGath> & A)308 GeneralBlockDistMatrix<T,U,V>::RowFilterFrom
309 ( const BlockDistMatrix<T,U,VGath>& A )
310 {
311     DEBUG_ONLY(
312         CallStackEntry cse("GBDM::RowFilterFrom");
313         this->AssertSameGrid( A.Grid() );
314     )
315     LogicError("This routine is not yet written");
316 }
317 
318 template<typename T,Dist U,Dist V>
319 void
PartialColFilterFrom(const BlockDistMatrix<T,UPart,V> & A)320 GeneralBlockDistMatrix<T,U,V>::PartialColFilterFrom
321 ( const BlockDistMatrix<T,UPart,V>& A )
322 {
323     DEBUG_ONLY(
324         CallStackEntry cse("GBDM::PartialColFilterFrom");
325         this->AssertSameGrid( A.Grid() );
326     )
327     LogicError("This routine is not yet written");
328 }
329 
330 template<typename T,Dist U,Dist V>
331 void
PartialRowFilterFrom(const BlockDistMatrix<T,U,VPart> & A)332 GeneralBlockDistMatrix<T,U,V>::PartialRowFilterFrom
333 ( const BlockDistMatrix<T,U,VPart>& A )
334 {
335     DEBUG_ONLY(
336         CallStackEntry cse("GBDM::PartialRowFilterFrom");
337         this->AssertSameGrid( A.Grid() );
338     )
339     LogicError("This routine is not yet written");
340 }
341 
342 template<typename T,Dist U,Dist V>
343 void
PartialColAllToAllFrom(const BlockDistMatrix<T,UPart,VScat> & A)344 GeneralBlockDistMatrix<T,U,V>::PartialColAllToAllFrom
345 ( const BlockDistMatrix<T,UPart,VScat>& A )
346 {
347     DEBUG_ONLY(
348         CallStackEntry cse("GBDM::PartialColAllToAllFrom");
349         this->AssertSameGrid( A.Grid() );
350     )
351     LogicError("This routine is not yet written");
352 }
353 
354 template<typename T,Dist U,Dist V>
355 void
PartialRowAllToAllFrom(const BlockDistMatrix<T,UScat,VPart> & A)356 GeneralBlockDistMatrix<T,U,V>::PartialRowAllToAllFrom
357 ( const BlockDistMatrix<T,UScat,VPart>& A )
358 {
359     DEBUG_ONLY(
360         CallStackEntry cse("GBDM::PartialRowAllToAllFrom");
361         this->AssertSameGrid( A.Grid() );
362     )
363     LogicError("This routine is not yet written");
364 }
365 
366 template<typename T,Dist U,Dist V>
367 void
PartialColAllToAll(BlockDistMatrix<T,UPart,VScat> & A) const368 GeneralBlockDistMatrix<T,U,V>::PartialColAllToAll
369 ( BlockDistMatrix<T,UPart,VScat>& A ) const
370 {
371     DEBUG_ONLY(
372         CallStackEntry cse("GBDM::PartialColAllToAll");
373         this->AssertSameGrid( A.Grid() );
374     )
375     LogicError("This routine is not yet written");
376 }
377 
378 template<typename T,Dist U,Dist V>
379 void
PartialRowAllToAll(BlockDistMatrix<T,UScat,VPart> & A) const380 GeneralBlockDistMatrix<T,U,V>::PartialRowAllToAll
381 ( BlockDistMatrix<T,UScat,VPart>& A ) const
382 {
383     DEBUG_ONLY(
384         CallStackEntry cse("GBDM::PartialRowAllToAll");
385         this->AssertSameGrid( A.Grid() );
386     )
387     LogicError("This routine is not yet written");
388 }
389 
390 template<typename T,Dist U,Dist V>
391 void
RowSumScatterFrom(const BlockDistMatrix<T,U,VGath> & A)392 GeneralBlockDistMatrix<T,U,V>::RowSumScatterFrom
393 ( const BlockDistMatrix<T,U,VGath>& A )
394 {
395     DEBUG_ONLY(
396         CallStackEntry cse("GBDM::RowSumScatterFrom");
397         this->AssertSameGrid( A.Grid() );
398     )
399     this->AlignColsAndResize
400     ( A.BlockHeight(), A.ColAlign(), A.ColCut(), A.Height(), A.Width(),
401       false, false );
402     // NOTE: This will be *slightly* slower than necessary due to the result
403     //       of the MPI operations being added rather than just copied
404     Zeros( this->Matrix(), this->LocalHeight(), this->LocalWidth() );
405     this->RowSumScatterUpdate( T(1), A );
406 }
407 
408 template<typename T,Dist U,Dist V>
409 void
ColSumScatterFrom(const BlockDistMatrix<T,UGath,V> & A)410 GeneralBlockDistMatrix<T,U,V>::ColSumScatterFrom
411 ( const BlockDistMatrix<T,UGath,V>& A )
412 {
413     DEBUG_ONLY(
414         CallStackEntry cse("GBDM::ColSumScatterFrom");
415         this->AssertSameGrid( A.Grid() );
416     )
417     this->AlignRowsAndResize
418     ( A.BlockWidth(), A.RowAlign(), A.RowCut(), A.Height(), A.Width(),
419       false, false );
420     // NOTE: This will be *slightly* slower than necessary due to the result
421     //       of the MPI operations being added rather than just copied
422     Zeros( this->Matrix(), this->LocalHeight(), this->LocalWidth() );
423     this->ColSumScatterUpdate( T(1), A );
424 }
425 
426 template<typename T,Dist U,Dist V>
427 void
SumScatterFrom(const BlockDistMatrix<T,UGath,VGath> & A)428 GeneralBlockDistMatrix<T,U,V>::SumScatterFrom
429 ( const BlockDistMatrix<T,UGath,VGath>& A )
430 {
431     DEBUG_ONLY(
432         CallStackEntry cse("GBDM::SumScatterFrom");
433         this->AssertSameGrid( A.Grid() );
434     )
435     this->Resize( A.Height(), A.Width() );
436     // NOTE: This will be *slightly* slower than necessary due to the result
437     //       of the MPI operations being added rather than just copied
438     Zeros( this->Matrix(), this->LocalHeight(), this->LocalWidth() );
439     this->SumScatterUpdate( T(1), A );
440 }
441 
442 template<typename T,Dist U,Dist V>
443 void
PartialRowSumScatterFrom(const BlockDistMatrix<T,U,VPart> & A)444 GeneralBlockDistMatrix<T,U,V>::PartialRowSumScatterFrom
445 ( const BlockDistMatrix<T,U,VPart>& A )
446 {
447     DEBUG_ONLY(
448         CallStackEntry cse("GBDM::PartialRowSumScatterFrom");
449         this->AssertSameGrid( A.Grid() );
450     )
451     this->AlignAndResize
452     ( A.BlockHeight(), A.BlockWidth(),
453       A.ColAlign(), A.RowAlign(), A.ColCut(), A.RowCut(),
454       A.Height(), A.Width(), false, false );
455     // NOTE: This will be *slightly* slower than necessary due to the result
456     //       of the MPI operations being added rather than just copied
457     Zeros( this->Matrix(), this->LocalHeight(), this->LocalWidth() );
458     this->PartialRowSumScatterUpdate( T(1), A );
459 }
460 
461 template<typename T,Dist U,Dist V>
462 void
PartialColSumScatterFrom(const BlockDistMatrix<T,UPart,V> & A)463 GeneralBlockDistMatrix<T,U,V>::PartialColSumScatterFrom
464 ( const BlockDistMatrix<T,UPart,V>& A )
465 {
466     DEBUG_ONLY(
467         CallStackEntry cse("GBDM::PartialColSumScatterFrom");
468         this->AssertSameGrid( A.Grid() );
469     )
470     this->AlignAndResize
471     ( A.BlockHeight(), A.BlockWidth(),
472       A.ColAlign(), A.RowAlign(), A.ColCut(), A.RowCut(),
473       A.Height(), A.Width(), false, false );
474     // NOTE: This will be *slightly* slower than necessary due to the result
475     //       of the MPI operations being added rather than just copied
476     Zeros( this->Matrix(), this->LocalHeight(), this->LocalWidth() );
477     this->PartialColSumScatterUpdate( T(1), A );
478 }
479 
480 template<typename T,Dist U,Dist V>
481 void
RowSumScatterUpdate(T alpha,const BlockDistMatrix<T,U,VGath> & A)482 GeneralBlockDistMatrix<T,U,V>::RowSumScatterUpdate
483 ( T alpha, const BlockDistMatrix<T,U,VGath>& A )
484 {
485     DEBUG_ONLY(
486         CallStackEntry cse("GBDM::RowSumScatterUpdate");
487         this->AssertNotLocked();
488         this->AssertSameGrid( A.Grid() );
489         this->AssertSameSize( A.Height(), A.Width() );
490     )
491     if( !this->Participating() )
492         return;
493 
494     LogicError("This routine is not yet written");
495 }
496 
497 template<typename T,Dist U,Dist V>
498 void
ColSumScatterUpdate(T alpha,const BlockDistMatrix<T,UGath,V> & A)499 GeneralBlockDistMatrix<T,U,V>::ColSumScatterUpdate
500 ( T alpha, const BlockDistMatrix<T,UGath,V>& A )
501 {
502     DEBUG_ONLY(
503         CallStackEntry cse("GBDM::ColSumScatterUpdate");
504         this->AssertNotLocked();
505         this->AssertSameGrid( A.Grid() );
506         this->AssertSameSize( A.Height(), A.Width() );
507     )
508     LogicError("This routine is not yet written");
509 }
510 
511 template<typename T,Dist U,Dist V>
512 void
SumScatterUpdate(T alpha,const BlockDistMatrix<T,UGath,VGath> & A)513 GeneralBlockDistMatrix<T,U,V>::SumScatterUpdate
514 ( T alpha, const BlockDistMatrix<T,UGath,VGath>& A )
515 {
516     DEBUG_ONLY(
517         CallStackEntry cse("GBDM::SumScatterUpdate");
518         this->AssertNotLocked();
519         this->AssertSameGrid( A.Grid() );
520         this->AssertSameSize( A.Height(), A.Width() );
521     )
522     if( !this->Participating() )
523         return;
524     LogicError("This routine is not yet written");
525 }
526 
527 template<typename T,Dist U,Dist V>
528 void
PartialRowSumScatterUpdate(T alpha,const BlockDistMatrix<T,U,VPart> & A)529 GeneralBlockDistMatrix<T,U,V>::PartialRowSumScatterUpdate
530 ( T alpha, const BlockDistMatrix<T,U,VPart>& A )
531 {
532     DEBUG_ONLY(
533         CallStackEntry cse("GBDM::PartialRowSumScatterUpdate");
534         this->AssertNotLocked();
535         this->AssertSameGrid( A.Grid() );
536         this->AssertSameSize( A.Height(), A.Width() );
537     )
538     if( !this->Participating() )
539         return;
540 
541     LogicError("This routine is not yet written");
542 }
543 
544 template<typename T,Dist U,Dist V>
545 void
PartialColSumScatterUpdate(T alpha,const BlockDistMatrix<T,UPart,V> & A)546 GeneralBlockDistMatrix<T,U,V>::PartialColSumScatterUpdate
547 ( T alpha, const BlockDistMatrix<T,UPart,V>& A )
548 {
549     DEBUG_ONLY(
550         CallStackEntry cse("GBDM::PartialColSumScatterUpdate");
551         this->AssertNotLocked();
552         this->AssertSameGrid( A.Grid() );
553         this->AssertSameSize( A.Height(), A.Width() );
554     )
555     if( !this->Participating() )
556         return;
557 
558     LogicError("This routine is not yet written");
559 }
560 
561 template<typename T,Dist U,Dist V>
562 void
TransposeColAllGather(BlockDistMatrix<T,V,UGath> & A,bool conjugate) const563 GeneralBlockDistMatrix<T,U,V>::TransposeColAllGather
564 ( BlockDistMatrix<T,V,UGath>& A, bool conjugate ) const
565 {
566     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposeColAllGather"))
567     BlockDistMatrix<T,V,U> ATrans( this->Grid() );
568     ATrans.AlignWith( *this );
569     ATrans.Resize( this->Width(), this->Height() );
570     Transpose( this->LockedMatrix(), ATrans.Matrix(), conjugate );
571     ATrans.RowAllGather( A );
572 }
573 
574 template<typename T,Dist U,Dist V>
575 void
TransposePartialColAllGather(BlockDistMatrix<T,V,UPart> & A,bool conjugate) const576 GeneralBlockDistMatrix<T,U,V>::TransposePartialColAllGather
577 ( BlockDistMatrix<T,V,UPart>& A, bool conjugate ) const
578 {
579     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposePartialColAllGather"))
580     BlockDistMatrix<T,V,U> ATrans( this->Grid() );
581     ATrans.AlignWith( *this );
582     ATrans.Resize( this->Width(), this->Height() );
583     Transpose( this->LockedMatrix(), ATrans.Matrix(), conjugate );
584     ATrans.PartialRowAllGather( A );
585 }
586 
587 template<typename T,Dist U,Dist V>
588 void
AdjointColAllGather(BlockDistMatrix<T,V,UGath> & A) const589 GeneralBlockDistMatrix<T,U,V>::AdjointColAllGather
590 ( BlockDistMatrix<T,V,UGath>& A ) const
591 {
592     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointRowAllGather"))
593     this->TransposeColAllGather( A, true );
594 }
595 
596 template<typename T,Dist U,Dist V>
597 void
AdjointPartialColAllGather(BlockDistMatrix<T,V,UPart> & A) const598 GeneralBlockDistMatrix<T,U,V>::AdjointPartialColAllGather
599 ( BlockDistMatrix<T,V,UPart>& A ) const
600 {
601     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointPartialColAllGather"))
602     this->TransposePartialColAllGather( A, true );
603 }
604 
605 template<typename T,Dist U,Dist V>
606 void
TransposeColFilterFrom(const BlockDistMatrix<T,V,UGath> & A,bool conjugate)607 GeneralBlockDistMatrix<T,U,V>::TransposeColFilterFrom
608 ( const BlockDistMatrix<T,V,UGath>& A, bool conjugate )
609 {
610     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposeColFilterFrom"))
611     BlockDistMatrix<T,V,U> AFilt( A.Grid() );
612     if( this->ColConstrained() )
613         AFilt.AlignRowsWith( *this, false );
614     if( this->RowConstrained() )
615         AFilt.AlignColsWith( *this, false );
616     AFilt.RowFilterFrom( A );
617     if( !this->ColConstrained() )
618         this->AlignColsWith( AFilt, false );
619     if( !this->RowConstrained() )
620         this->AlignRowsWith( AFilt, false );
621     this->Resize( A.Width(), A.Height() );
622     Transpose( AFilt.LockedMatrix(), this->Matrix(), conjugate );
623 }
624 
625 template<typename T,Dist U,Dist V>
626 void
TransposeRowFilterFrom(const BlockDistMatrix<T,VGath,U> & A,bool conjugate)627 GeneralBlockDistMatrix<T,U,V>::TransposeRowFilterFrom
628 ( const BlockDistMatrix<T,VGath,U>& A, bool conjugate )
629 {
630     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposeRowFilterFrom"))
631     BlockDistMatrix<T,V,U> AFilt( A.Grid() );
632     if( this->ColConstrained() )
633         AFilt.AlignRowsWith( *this, false );
634     if( this->RowConstrained() )
635         AFilt.AlignColsWith( *this, false );
636     AFilt.ColFilterFrom( A );
637     if( !this->ColConstrained() )
638         this->AlignColsWith( AFilt, false );
639     if( !this->RowConstrained() )
640         this->AlignRowsWith( AFilt, false );
641     this->Resize( A.Width(), A.Height() );
642     Transpose( AFilt.LockedMatrix(), this->Matrix(), conjugate );
643 }
644 
645 template<typename T,Dist U,Dist V>
646 void
TransposePartialColFilterFrom(const BlockDistMatrix<T,V,UPart> & A,bool conjugate)647 GeneralBlockDistMatrix<T,U,V>::TransposePartialColFilterFrom
648 ( const BlockDistMatrix<T,V,UPart>& A, bool conjugate )
649 {
650     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposePartialColFilterFrom"))
651     BlockDistMatrix<T,V,U> AFilt( A.Grid() );
652     if( this->ColConstrained() )
653         AFilt.AlignRowsWith( *this, false );
654     if( this->RowConstrained() )
655         AFilt.AlignColsWith( *this, false );
656     AFilt.PartialRowFilterFrom( A );
657     if( !this->ColConstrained() )
658         this->AlignColsWith( AFilt, false );
659     if( !this->RowConstrained() )
660         this->AlignRowsWith( AFilt, false );
661     this->Resize( A.Width(), A.Height() );
662     Transpose( AFilt.LockedMatrix(), this->Matrix(), conjugate );
663 }
664 
665 template<typename T,Dist U,Dist V>
666 void
TransposePartialRowFilterFrom(const BlockDistMatrix<T,VPart,U> & A,bool conjugate)667 GeneralBlockDistMatrix<T,U,V>::TransposePartialRowFilterFrom
668 ( const BlockDistMatrix<T,VPart,U>& A, bool conjugate )
669 {
670     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposePartialRowFilterFrom"))
671     BlockDistMatrix<T,V,U> AFilt( A.Grid() );
672     if( this->ColConstrained() )
673         AFilt.AlignRowsWith( *this, false );
674     if( this->RowConstrained() )
675         AFilt.AlignColsWith( *this, false );
676     AFilt.PartialColFilterFrom( A );
677     if( !this->ColConstrained() )
678         this->AlignColsWith( AFilt, false );
679     if( !this->RowConstrained() )
680         this->AlignRowsWith( AFilt, false );
681     this->Resize( A.Width(), A.Height() );
682     Transpose( AFilt.LockedMatrix(), this->Matrix(), conjugate );
683 }
684 
685 template<typename T,Dist U,Dist V>
686 void
AdjointColFilterFrom(const BlockDistMatrix<T,V,UGath> & A)687 GeneralBlockDistMatrix<T,U,V>::AdjointColFilterFrom
688 ( const BlockDistMatrix<T,V,UGath>& A )
689 {
690     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointColFilterFrom"))
691     this->TransposeColFilterFrom( A, true );
692 }
693 
694 template<typename T,Dist U,Dist V>
695 void
AdjointRowFilterFrom(const BlockDistMatrix<T,VGath,U> & A)696 GeneralBlockDistMatrix<T,U,V>::AdjointRowFilterFrom
697 ( const BlockDistMatrix<T,VGath,U>& A )
698 {
699     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointRowFilterFrom"))
700     this->TransposeRowFilterFrom( A, true );
701 }
702 
703 template<typename T,Dist U,Dist V>
704 void
AdjointPartialColFilterFrom(const BlockDistMatrix<T,V,UPart> & A)705 GeneralBlockDistMatrix<T,U,V>::AdjointPartialColFilterFrom
706 ( const BlockDistMatrix<T,V,UPart>& A )
707 {
708     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointPartialColFilterFrom"))
709     this->TransposePartialColFilterFrom( A, true );
710 }
711 
712 template<typename T,Dist U,Dist V>
713 void
AdjointPartialRowFilterFrom(const BlockDistMatrix<T,VPart,U> & A)714 GeneralBlockDistMatrix<T,U,V>::AdjointPartialRowFilterFrom
715 ( const BlockDistMatrix<T,VPart,U>& A )
716 {
717     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointPartialRowFilterFrom"))
718     this->TransposePartialRowFilterFrom( A, true );
719 }
720 
721 template<typename T,Dist U,Dist V>
722 void
TransposeColSumScatterFrom(const BlockDistMatrix<T,V,UGath> & A,bool conjugate)723 GeneralBlockDistMatrix<T,U,V>::TransposeColSumScatterFrom
724 ( const BlockDistMatrix<T,V,UGath>& A, bool conjugate )
725 {
726     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposeColSumScatterFrom"))
727     BlockDistMatrix<T,V,U> ASumFilt( A.Grid() );
728     if( this->ColConstrained() )
729         ASumFilt.AlignRowsWith( *this, false );
730     if( this->RowConstrained() )
731         ASumFilt.AlignColsWith( *this, false );
732     ASumFilt.RowSumScatterFrom( A );
733     if( !this->ColConstrained() )
734         this->AlignColsWith( ASumFilt, false );
735     if( !this->RowConstrained() )
736         this->AlignRowsWith( ASumFilt, false );
737     this->Resize( A.Width(), A.Height() );
738     Transpose( ASumFilt.LockedMatrix(), this->Matrix(), conjugate );
739 }
740 
741 template<typename T,Dist U,Dist V>
742 void
TransposePartialColSumScatterFrom(const BlockDistMatrix<T,V,UPart> & A,bool conjugate)743 GeneralBlockDistMatrix<T,U,V>::TransposePartialColSumScatterFrom
744 ( const BlockDistMatrix<T,V,UPart>& A, bool conjugate )
745 {
746     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposePartialColSumScatterFrom"))
747     BlockDistMatrix<T,V,U> ASumFilt( A.Grid() );
748     if( this->ColConstrained() )
749         ASumFilt.AlignRowsWith( *this, false );
750     if( this->RowConstrained() )
751         ASumFilt.AlignColsWith( *this, false );
752     ASumFilt.PartialRowSumScatterFrom( A );
753     if( !this->ColConstrained() )
754         this->AlignColsWith( ASumFilt, false );
755     if( !this->RowConstrained() )
756         this->AlignRowsWith( ASumFilt, false );
757     this->Resize( A.Width(), A.Height() );
758     Transpose( ASumFilt.LockedMatrix(), this->Matrix(), conjugate );
759 }
760 
761 template<typename T,Dist U,Dist V>
762 void
AdjointColSumScatterFrom(const BlockDistMatrix<T,V,UGath> & A)763 GeneralBlockDistMatrix<T,U,V>::AdjointColSumScatterFrom
764 ( const BlockDistMatrix<T,V,UGath>& A )
765 {
766     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointColSumScatterFrom"))
767     this->TransposeColSumScatterFrom( A, true );
768 }
769 
770 template<typename T,Dist U,Dist V>
771 void
AdjointPartialColSumScatterFrom(const BlockDistMatrix<T,V,UPart> & A)772 GeneralBlockDistMatrix<T,U,V>::AdjointPartialColSumScatterFrom
773 ( const BlockDistMatrix<T,V,UPart>& A )
774 {
775     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointPartialColSumScatterFrom"))
776     this->TransposePartialColSumScatterFrom( A, true );
777 }
778 
779 template<typename T,Dist U,Dist V>
780 void
TransposeColSumScatterUpdate(T alpha,const BlockDistMatrix<T,V,UGath> & A,bool conjugate)781 GeneralBlockDistMatrix<T,U,V>::TransposeColSumScatterUpdate
782 ( T alpha, const BlockDistMatrix<T,V,UGath>& A, bool conjugate )
783 {
784     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposeColSumScatterUpdate"))
785     BlockDistMatrix<T,V,U> ASumFilt( A.Grid() );
786     if( this->ColConstrained() )
787         ASumFilt.AlignRowsWith( *this, false );
788     if( this->RowConstrained() )
789         ASumFilt.AlignColsWith( *this, false );
790     ASumFilt.RowSumScatterFrom( A );
791     if( !this->ColConstrained() )
792         this->AlignColsWith( ASumFilt, false );
793     if( !this->RowConstrained() )
794         this->AlignRowsWith( ASumFilt, false );
795     // ALoc += alpha ASumFiltLoc'
796     elem::Matrix<T>& ALoc = this->Matrix();
797     const elem::Matrix<T>& BLoc = ASumFilt.LockedMatrix();
798     const Int localHeight = ALoc.Height();
799     const Int localWidth = ALoc.Width();
800     if( conjugate )
801     {
802         for( Int jLoc=0; jLoc<localWidth; ++jLoc )
803             for( Int iLoc=0; iLoc<localHeight; ++iLoc )
804                 ALoc.Update( iLoc, jLoc, alpha*Conj(BLoc.Get(jLoc,iLoc)) );
805     }
806     else
807     {
808         for( Int jLoc=0; jLoc<localWidth; ++jLoc )
809             for( Int iLoc=0; iLoc<localHeight; ++iLoc )
810                 ALoc.Update( iLoc, jLoc, alpha*BLoc.Get(jLoc,iLoc) );
811     }
812 }
813 
814 template<typename T,Dist U,Dist V>
815 void
TransposePartialColSumScatterUpdate(T alpha,const BlockDistMatrix<T,V,UPart> & A,bool conjugate)816 GeneralBlockDistMatrix<T,U,V>::TransposePartialColSumScatterUpdate
817 ( T alpha, const BlockDistMatrix<T,V,UPart>& A, bool conjugate )
818 {
819     DEBUG_ONLY(CallStackEntry cse("GBDM::TransposePartialColSumScatterUpdate"))
820     BlockDistMatrix<T,V,U> ASumFilt( A.Grid() );
821     if( this->ColConstrained() )
822         ASumFilt.AlignRowsWith( *this, false );
823     if( this->RowConstrained() )
824         ASumFilt.AlignColsWith( *this, false );
825     ASumFilt.PartialRowSumScatterFrom( A );
826     if( !this->ColConstrained() )
827         this->AlignColsWith( ASumFilt, false );
828     if( !this->RowConstrained() )
829         this->AlignRowsWith( ASumFilt, false );
830     // ALoc += alpha ASumFiltLoc'
831     elem::Matrix<T>& ALoc = this->Matrix();
832     const elem::Matrix<T>& BLoc = ASumFilt.LockedMatrix();
833     const Int localHeight = ALoc.Height();
834     const Int localWidth = ALoc.Width();
835     if( conjugate )
836     {
837         for( Int jLoc=0; jLoc<localWidth; ++jLoc )
838             for( Int iLoc=0; iLoc<localHeight; ++iLoc )
839                 ALoc.Update( iLoc, jLoc, alpha*Conj(BLoc.Get(jLoc,iLoc)) );
840     }
841     else
842     {
843         for( Int jLoc=0; jLoc<localWidth; ++jLoc )
844             for( Int iLoc=0; iLoc<localHeight; ++iLoc )
845                 ALoc.Update( iLoc, jLoc, alpha*BLoc.Get(jLoc,iLoc) );
846     }
847 }
848 
849 template<typename T,Dist U,Dist V>
850 void
AdjointColSumScatterUpdate(T alpha,const BlockDistMatrix<T,V,UGath> & A)851 GeneralBlockDistMatrix<T,U,V>::AdjointColSumScatterUpdate
852 ( T alpha, const BlockDistMatrix<T,V,UGath>& A )
853 {
854     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointColSumScatterUpdate"))
855     this->TransposeColSumScatterUpdate( alpha, A, true );
856 }
857 
858 template<typename T,Dist U,Dist V>
859 void
AdjointPartialColSumScatterUpdate(T alpha,const BlockDistMatrix<T,V,UPart> & A)860 GeneralBlockDistMatrix<T,U,V>::AdjointPartialColSumScatterUpdate
861 ( T alpha, const BlockDistMatrix<T,V,UPart>& A )
862 {
863     DEBUG_ONLY(CallStackEntry cse("GBDM::AdjointPartialColSumScatterUpdate"))
864     this->TransposePartialColSumScatterUpdate( alpha, A, true );
865 }
866 
867 // Diagonal manipulation
868 // =====================
869 template<typename T,Dist U,Dist V>
870 bool
DiagonalAlignedWith(const elem::BlockDistData & d,Int offset) const871 GeneralBlockDistMatrix<T,U,V>::DiagonalAlignedWith
872 ( const elem::BlockDistData& d, Int offset ) const
873 {
874     DEBUG_ONLY(CallStackEntry cse("GBDM::DiagonalAlignedWith"))
875     // TODO: Ensure blocksize is compatible...the blocksizes needed for a
876     //       diagonal distribution are variable except for special cases.
877     LogicError("This routine is not yet written");
878     return false;
879 }
880 
881 template<typename T,Dist U,Dist V>
882 Int
DiagonalRoot(Int offset) const883 GeneralBlockDistMatrix<T,U,V>::DiagonalRoot( Int offset ) const
884 {
885     DEBUG_ONLY(CallStackEntry cse("GBDM::DiagonalRoot"))
886     LogicError("This routine is not yet written");
887     return 0;
888 }
889 
890 template<typename T,Dist U,Dist V>
891 Int
DiagonalAlign(Int offset) const892 GeneralBlockDistMatrix<T,U,V>::DiagonalAlign( Int offset ) const
893 {
894     DEBUG_ONLY(CallStackEntry cse("GBDM::DiagonalAlign"))
895     LogicError("This routine is not yet written");
896     return 0;
897 }
898 
899 template<typename T,Dist U,Dist V>
900 void
GetDiagonal(BlockDistMatrix<T,UDiag,VDiag> & d,Int offset) const901 GeneralBlockDistMatrix<T,U,V>::GetDiagonal
902 ( BlockDistMatrix<T,UDiag,VDiag>& d, Int offset ) const
903 {
904     DEBUG_ONLY(CallStackEntry cse("GBDM::GetDiagonal"))
905     this->GetDiagonalHelper
906     ( d, offset, []( T& alpha, T beta ) { alpha = beta; } );
907 }
908 
909 template<typename T,Dist U,Dist V>
910 void
GetRealPartOfDiagonal(BlockDistMatrix<Base<T>,UDiag,VDiag> & d,Int offset) const911 GeneralBlockDistMatrix<T,U,V>::GetRealPartOfDiagonal
912 ( BlockDistMatrix<Base<T>,UDiag,VDiag>& d, Int offset ) const
913 {
914     DEBUG_ONLY(CallStackEntry cse("GBDM::GetRealPartOfDiagonal"))
915     this->GetDiagonalHelper
916     ( d, offset, []( Base<T>& alpha, T beta ) { alpha = RealPart(beta); } );
917 }
918 
919 template<typename T,Dist U,Dist V>
920 void
GetImagPartOfDiagonal(BlockDistMatrix<Base<T>,UDiag,VDiag> & d,Int offset) const921 GeneralBlockDistMatrix<T,U,V>::GetImagPartOfDiagonal
922 ( BlockDistMatrix<Base<T>,UDiag,VDiag>& d, Int offset ) const
923 {
924     DEBUG_ONLY(CallStackEntry cse("GBDM::GetImagPartOfDiagonal"))
925     this->GetDiagonalHelper
926     ( d, offset, []( Base<T>& alpha, T beta ) { alpha = ImagPart(beta); } );
927 }
928 
929 template<typename T,Dist U,Dist V>
930 auto
GetDiagonal(Int offset) const931 GeneralBlockDistMatrix<T,U,V>::GetDiagonal( Int offset ) const
932 -> BlockDistMatrix<T,UDiag,VDiag>
933 {
934     BlockDistMatrix<T,UDiag,VDiag> d( this->Grid() );
935     GetDiagonal( d, offset );
936     return d;
937 }
938 
939 template<typename T,Dist U,Dist V>
940 auto
GetRealPartOfDiagonal(Int offset) const941 GeneralBlockDistMatrix<T,U,V>::GetRealPartOfDiagonal( Int offset ) const
942 -> BlockDistMatrix<Base<T>,UDiag,VDiag>
943 {
944     BlockDistMatrix<Base<T>,UDiag,VDiag> d( this->Grid() );
945     GetRealPartOfDiagonal( d, offset );
946     return d;
947 }
948 
949 template<typename T,Dist U,Dist V>
950 auto
GetImagPartOfDiagonal(Int offset) const951 GeneralBlockDistMatrix<T,U,V>::GetImagPartOfDiagonal( Int offset ) const
952 -> BlockDistMatrix<Base<T>,UDiag,VDiag>
953 {
954     BlockDistMatrix<Base<T>,UDiag,VDiag> d( this->Grid() );
955     GetImagPartOfDiagonal( d, offset );
956     return d;
957 }
958 
959 template<typename T,Dist U,Dist V>
960 void
SetDiagonal(const BlockDistMatrix<T,UDiag,VDiag> & d,Int offset)961 GeneralBlockDistMatrix<T,U,V>::SetDiagonal
962 ( const BlockDistMatrix<T,UDiag,VDiag>& d, Int offset )
963 {
964     DEBUG_ONLY(CallStackEntry cse("GBDM::SetDiagonal"))
965     this->SetDiagonalHelper
966     ( d, offset, []( T& alpha, T beta ) { alpha = beta; } );
967 }
968 
969 template<typename T,Dist U,Dist V>
970 void
SetRealPartOfDiagonal(const BlockDistMatrix<Base<T>,UDiag,VDiag> & d,Int offset)971 GeneralBlockDistMatrix<T,U,V>::SetRealPartOfDiagonal
972 ( const BlockDistMatrix<Base<T>,UDiag,VDiag>& d, Int offset )
973 {
974     DEBUG_ONLY(CallStackEntry cse("GBDM::SetRealPartOfDiagonal"))
975     this->SetDiagonalHelper
976     ( d, offset,
977       []( T& alpha, Base<T> beta ) { elem::SetRealPart(alpha,beta); } );
978 }
979 
980 template<typename T,Dist U,Dist V>
981 void
SetImagPartOfDiagonal(const BlockDistMatrix<Base<T>,UDiag,VDiag> & d,Int offset)982 GeneralBlockDistMatrix<T,U,V>::SetImagPartOfDiagonal
983 ( const BlockDistMatrix<Base<T>,UDiag,VDiag>& d, Int offset )
984 {
985     DEBUG_ONLY(CallStackEntry cse("GBDM::SetImagPartOfDiagonal"))
986     this->SetDiagonalHelper
987     ( d, offset,
988       []( T& alpha, Base<T> beta ) { elem::SetImagPart(alpha,beta); } );
989 }
990 
991 template<typename T,Dist U,Dist V>
992 void
UpdateDiagonal(T gamma,const BlockDistMatrix<T,UDiag,VDiag> & d,Int offset)993 GeneralBlockDistMatrix<T,U,V>::UpdateDiagonal
994 ( T gamma, const BlockDistMatrix<T,UDiag,VDiag>& d, Int offset )
995 {
996     DEBUG_ONLY(CallStackEntry cse("GBDM::UpdateDiagonal"))
997     this->SetDiagonalHelper
998     ( d, offset, [gamma]( T& alpha, T beta ) { alpha += gamma*beta; } );
999 }
1000 
1001 template<typename T,Dist U,Dist V>
1002 void
UpdateRealPartOfDiagonal(Base<T> gamma,const BlockDistMatrix<Base<T>,UDiag,VDiag> & d,Int offset)1003 GeneralBlockDistMatrix<T,U,V>::UpdateRealPartOfDiagonal
1004 ( Base<T> gamma, const BlockDistMatrix<Base<T>,UDiag,VDiag>& d, Int offset )
1005 {
1006     DEBUG_ONLY(CallStackEntry cse("GBDM::UpdateRealPartOfDiagonal"))
1007     this->SetDiagonalHelper
1008     ( d, offset,
1009       [gamma]( T& alpha, Base<T> beta )
1010       { elem::UpdateRealPart(alpha,gamma*beta); } );
1011 }
1012 
1013 template<typename T,Dist U,Dist V>
1014 void
UpdateImagPartOfDiagonal(Base<T> gamma,const BlockDistMatrix<Base<T>,UDiag,VDiag> & d,Int offset)1015 GeneralBlockDistMatrix<T,U,V>::UpdateImagPartOfDiagonal
1016 ( Base<T> gamma, const BlockDistMatrix<Base<T>,UDiag,VDiag>& d, Int offset )
1017 {
1018     DEBUG_ONLY(CallStackEntry cse("GBDM::UpdateImagPartOfDiagonal"))
1019     this->SetDiagonalHelper
1020     ( d, offset,
1021       [gamma]( T& alpha, Base<T> beta )
1022       { elem::UpdateImagPart(alpha,gamma*beta); } );
1023 }
1024 
1025 // Private section
1026 // ###############
1027 
1028 // Diagonal helper functions
1029 // =========================
1030 template<typename T,Dist U,Dist V>
1031 template<typename S,class Function>
1032 void
GetDiagonalHelper(BlockDistMatrix<S,UDiag,VDiag> & d,Int offset,Function func) const1033 GeneralBlockDistMatrix<T,U,V>::GetDiagonalHelper
1034 ( BlockDistMatrix<S,UDiag,VDiag>& d, Int offset, Function func ) const
1035 {
1036     DEBUG_ONLY(CallStackEntry cse("GBDM::GetDiagonalHelper"))
1037     LogicError("This routine is not yet written");
1038 }
1039 
1040 template<typename T,Dist U,Dist V>
1041 template<typename S,class Function>
1042 void
SetDiagonalHelper(const BlockDistMatrix<S,UDiag,VDiag> & d,Int offset,Function func)1043 GeneralBlockDistMatrix<T,U,V>::SetDiagonalHelper
1044 ( const BlockDistMatrix<S,UDiag,VDiag>& d, Int offset, Function func )
1045 {
1046     DEBUG_ONLY(
1047         CallStackEntry cse("GBDM::SetDiagonalHelper");
1048         if( !this->DiagonalAlignedWith( d, offset ) )
1049             LogicError("Invalid diagonal alignment");
1050     )
1051     LogicError("This routine is not yet written");
1052 }
1053 
1054 // Instantiations for {Int,Real,Complex<Real>} for each Real in {float,double}
1055 // ###########################################################################
1056 
1057 #define DISTPROTO(T,U,V) template class GeneralBlockDistMatrix<T,U,V>
1058 
1059 #define PROTO(T)\
1060   DISTPROTO(T,CIRC,CIRC);\
1061   DISTPROTO(T,MC,  MR  );\
1062   DISTPROTO(T,MC,  STAR);\
1063   DISTPROTO(T,MD,  STAR);\
1064   DISTPROTO(T,MR,  MC  );\
1065   DISTPROTO(T,MR,  STAR);\
1066   DISTPROTO(T,STAR,MC  );\
1067   DISTPROTO(T,STAR,MD  );\
1068   DISTPROTO(T,STAR,MR  );\
1069   DISTPROTO(T,STAR,STAR);\
1070   DISTPROTO(T,STAR,VC  );\
1071   DISTPROTO(T,STAR,VR  );\
1072   DISTPROTO(T,VC,  STAR);\
1073   DISTPROTO(T,VR,  STAR);
1074 
1075 #ifndef ELEM_DISABLE_COMPLEX
1076  #ifndef ELEM_DISABLE_FLOAT
1077   PROTO(Int);
1078   PROTO(float);
1079   PROTO(double);
1080   PROTO(Complex<float>);
1081   PROTO(Complex<double>);
1082  #else // ifndef ELEM_DISABLE_FLOAT
1083   PROTO(Int);
1084   PROTO(double);
1085   PROTO(Complex<double>);
1086  #endif // ifndef ELEM_DISABLE_FLOAT
1087 #else // ifndef ELEM_DISABLE_COMPLEX
1088  #ifndef ELEM_DISABLE_FLOAT
1089   PROTO(Int);
1090   PROTO(float);
1091   PROTO(double);
1092  #else // ifndef ELEM_DISABLE_FLOAT
1093   PROTO(Int);
1094   PROTO(double);
1095  #endif // ifndef ELEM_DISABLE_FLOAT
1096 #endif // ifndef ELEM_DISABLE_COMPLEX
1097 
1098 } // namespace elem
1099