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_ZEROS_INC
11 
12 namespace elem {
13 
14 // Public section
15 // ##############
16 
17 // Constructors and destructors
18 // ============================
19 
20 template<typename T>
AbstractBlockDistMatrix(const elem::Grid & g,Int root)21 AbstractBlockDistMatrix<T>::AbstractBlockDistMatrix
22 ( const elem::Grid& g, Int root )
23 : viewType_(OWNER),
24   height_(0), width_(0),
25   auxMemory_(),
26   matrix_(0,0,true),
27   colConstrained_(false), rowConstrained_(false), rootConstrained_(false),
28   blockHeight_(DefaultBlockHeight()), blockWidth_(DefaultBlockWidth()),
29   colAlign_(0), rowAlign_(0),
30   colCut_(0), rowCut_(0),
31   root_(root), grid_(&g)
32 { }
33 
34 template<typename T>
AbstractBlockDistMatrix(const elem::Grid & g,Int blockHeight,Int blockWidth,Int root)35 AbstractBlockDistMatrix<T>::AbstractBlockDistMatrix
36 ( const elem::Grid& g, Int blockHeight, Int blockWidth, Int root )
37 : viewType_(OWNER),
38   height_(0), width_(0),
39   auxMemory_(),
40   matrix_(0,0,true),
41   colConstrained_(true), rowConstrained_(true), rootConstrained_(false),
42   blockHeight_(blockHeight), blockWidth_(blockWidth),
43   colAlign_(0), rowAlign_(0),
44   colCut_(0), rowCut_(0),
45   root_(root), grid_(&g)
46 { }
47 
48 template<typename T>
AbstractBlockDistMatrix(AbstractBlockDistMatrix<T> && A)49 AbstractBlockDistMatrix<T>::AbstractBlockDistMatrix
50 ( AbstractBlockDistMatrix<T>&& A ) ELEM_NOEXCEPT
51 : viewType_(A.viewType_),
52   height_(A.height_), width_(A.width_),
53   colConstrained_(A.colConstrained_), rowConstrained_(A.rowConstrained_),
54   rootConstrained_(A.rootConstrained_),
55   blockHeight_(A.blockHeight_), blockWidth_(A.blockWidth_),
56   colAlign_(A.colAlign_), rowAlign_(A.rowAlign_),
57   colCut_(A.colCut_), rowCut_(A.rowCut_),
58   colShift_(A.colShift_), rowShift_(A.rowShift_),
59   root_(A.root_),
60   grid_(A.grid_)
61 {
62     matrix_.ShallowSwap( A.matrix_ );
63     auxMemory_.ShallowSwap( A.auxMemory_ );
64 }
65 
66 // Optional to override
67 // --------------------
68 
69 template<typename T>
~AbstractBlockDistMatrix()70 AbstractBlockDistMatrix<T>::~AbstractBlockDistMatrix() { }
71 
72 // Assignment and reconfiguration
73 // ==============================
74 
75 template<typename T>
76 AbstractBlockDistMatrix<T>&
operator =(AbstractBlockDistMatrix<T> && A)77 AbstractBlockDistMatrix<T>::operator=( AbstractBlockDistMatrix<T>&& A )
78 {
79     if( Viewing() && !A.Viewing() )
80     {
81         LogicError
82         ("Cannot move a non-view into a viewing AbstractBlockDistMatrix");
83     }
84     else
85     {
86         auxMemory_.ShallowSwap( A.auxMemory_ );
87         matrix_.ShallowSwap( A.matrix_ );
88         viewType_ = A.viewType_;
89         height_ = A.height_;
90         width_ = A.width_;
91         colConstrained_ = A.colConstrained_;
92         rowConstrained_ = A.rowConstrained_;
93         rootConstrained_ = A.rootConstrained_;
94         blockHeight_ = A.blockHeight_;
95         blockWidth_ = A.blockWidth_;
96         colAlign_ = A.colAlign_;
97         rowAlign_ = A.rowAlign_;
98         colCut_ = A.colCut_;
99         rowCut_ = A.rowCut_;
100         colShift_ = A.colShift_;
101         rowShift_ = A.rowShift_;
102         root_ = A.root_;
103         grid_ = A.grid_;
104     }
105     return *this;
106 }
107 
108 template<typename T>
109 void
Empty()110 AbstractBlockDistMatrix<T>::Empty()
111 {
112     matrix_.Empty_();
113     viewType_ = OWNER;
114     height_ = 0;
115     width_ = 0;
116     blockHeight_ = 0;
117     blockWidth_ = 0;
118     colAlign_ = 0;
119     rowAlign_ = 0;
120     colCut_ = 0;
121     rowCut_ = 0;
122     colConstrained_ = false;
123     rowConstrained_ = false;
124     rootConstrained_ = false;
125 }
126 
127 template<typename T>
128 void
EmptyData()129 AbstractBlockDistMatrix<T>::EmptyData()
130 {
131     matrix_.Empty_();
132     viewType_ = OWNER;
133     height_ = 0;
134     width_ = 0;
135 }
136 
137 template<typename T>
138 void
SetGrid(const elem::Grid & grid)139 AbstractBlockDistMatrix<T>::SetGrid( const elem::Grid& grid )
140 {
141     if( grid_ != &grid )
142     {
143         Empty();
144         grid_ = &grid;
145         SetShifts();
146     }
147 }
148 
149 template<typename T>
150 void
Resize(Int height,Int width)151 AbstractBlockDistMatrix<T>::Resize( Int height, Int width )
152 {
153     DEBUG_ONLY(
154         CallStackEntry cse("ABDM::Resize");
155         AssertNotLocked();
156     )
157     height_ = height;
158     width_ = width;
159     if( Participating() )
160         matrix_.Resize_
161         ( BlockedLength(height,ColShift(),BlockHeight(),ColCut(),ColStride()),
162           BlockedLength(width,RowShift(),BlockWidth(),RowCut(),RowStride()) );
163 }
164 
165 template<typename T>
166 void
Resize(Int height,Int width,Int ldim)167 AbstractBlockDistMatrix<T>::Resize( Int height, Int width, Int ldim )
168 {
169     DEBUG_ONLY(
170         CallStackEntry cse("ABDM::Resize");
171         AssertNotLocked();
172     )
173     height_ = height;
174     width_ = width;
175     if( Participating() )
176         matrix_.Resize_
177         ( BlockedLength(height,ColShift(),BlockHeight(),ColCut(),ColStride()),
178           BlockedLength(width,RowShift(),BlockWidth(),RowCut(),RowStride()),
179           ldim );
180 }
181 
182 template<typename T>
183 void
MakeConsistent(bool includingViewers)184 AbstractBlockDistMatrix<T>::MakeConsistent( bool includingViewers )
185 {
186     DEBUG_ONLY(CallStackEntry cse("ABDM::MakeConsistent"))
187 
188     const Int msgLength = 13;
189     Int message[msgLength];
190     if( CrossRank() == Root() )
191     {
192         message[ 0] = viewType_;
193         message[ 1] = height_;
194         message[ 2] = width_;
195         message[ 3] = colConstrained_;
196         message[ 4] = rowConstrained_;
197         message[ 5] = rootConstrained_;
198         message[ 6] = blockHeight_;
199         message[ 7] = blockWidth_;
200         message[ 8] = colAlign_;
201         message[ 9] = rowAlign_;
202         message[10] = colCut_;
203         message[11] = rowCut_;
204         message[12] = root_;
205     }
206 
207     const elem::Grid& g = *grid_;
208     if( !g.InGrid() && !includingViewers )
209         LogicError("Non-participating process called MakeConsistent");
210     if( g.InGrid() )
211     {
212         // TODO: Ensure roots are consistent within each cross communicator
213         mpi::Broadcast( message, msgLength, Root(), CrossComm() );
214     }
215     if( includingViewers )
216     {
217         const Int vcRoot = g.VCToViewingMap(0);
218         mpi::Broadcast( message, msgLength, vcRoot, g.ViewingComm() );
219     }
220     const ViewType newViewType    = static_cast<ViewType>(message[0]);
221     const Int newHeight           = message[ 1];
222     const Int newWidth            = message[ 2];
223     const bool newConstrainedCol  = message[ 3];
224     const bool newConstrainedRow  = message[ 4];
225     const bool newConstrainedRoot = message[ 5];
226     const Int newBlockHeight      = message[ 6];
227     const Int newBlockWidth       = message[ 7];
228     const Int newColAlign         = message[ 8];
229     const Int newRowAlign         = message[ 9];
230     const Int newColCut           = message[10];
231     const Int newRowCut           = message[11];
232     const Int root                = message[12];
233 
234     root_            = root;
235     viewType_        = newViewType;
236     colConstrained_  = newConstrainedCol;
237     rowConstrained_  = newConstrainedRow;
238     rootConstrained_ = newConstrainedRoot;
239     blockHeight_     = newBlockHeight;
240     blockWidth_      = newBlockWidth;
241     colAlign_        = newColAlign;
242     rowAlign_        = newRowAlign;
243     colCut_          = newColCut;
244     rowCut_          = newRowCut;
245 
246     SetShifts();
247     Resize( newHeight, newWidth );
248 }
249 
250 template<typename T>
251 void
MakeSizeConsistent(bool includingViewers)252 AbstractBlockDistMatrix<T>::MakeSizeConsistent( bool includingViewers )
253 {
254     DEBUG_ONLY(CallStackEntry cse("ABDM::MakeSizeConsistent"))
255 
256     const Int msgLength = 2;
257     Int message[msgLength];
258     if( CrossRank() == Root() )
259     {
260         message[0] = height_;
261         message[1] = width_;
262     }
263 
264     const elem::Grid& g = *grid_;
265     if( !g.InGrid() && !includingViewers )
266         LogicError("Non-participating process called MakeSizeConsistent");
267     if( g.InGrid() )
268     {
269         // TODO: Ensure roots are consistent within each cross communicator
270         mpi::Broadcast( message, msgLength, Root(), CrossComm() );
271     }
272     if( includingViewers )
273     {
274         const Int vcRoot = g.VCToViewingMap(0);
275         mpi::Broadcast( message, msgLength, vcRoot, g.ViewingComm() );
276     }
277     const Int newHeight = message[0];
278     const Int newWidth  = message[1];
279     Resize( newHeight, newWidth );
280 }
281 
282 // Realignment
283 // -----------
284 
285 template<typename T>
286 void
Align(Int blockHeight,Int blockWidth,Int colAlign,Int rowAlign,Int colCut,Int rowCut,bool constrain)287 AbstractBlockDistMatrix<T>::Align
288 ( Int blockHeight, Int blockWidth,
289   Int colAlign, Int rowAlign, Int colCut, Int rowCut, bool constrain )
290 {
291     DEBUG_ONLY(CallStackEntry cse("ABDM::Align"))
292     const bool requireChange =
293         blockHeight_ != blockHeight || blockWidth_ != blockWidth ||
294         colAlign_    != colAlign    || rowAlign_   != rowAlign   ||
295         colCut_      != colCut      || rowCut_     != rowCut;
296     DEBUG_ONLY(
297         if( Viewing() && requireChange )
298             LogicError("Tried to realign a view");
299     )
300     if( requireChange )
301         Empty();
302     if( constrain )
303     {
304         colConstrained_ = true;
305         rowConstrained_ = true;
306     }
307     blockHeight_ = blockHeight;
308     blockWidth_ = blockWidth;
309     colAlign_ = colAlign;
310     rowAlign_ = rowAlign;
311     colCut_ = colCut;
312     rowCut_ = rowCut;
313     SetShifts();
314 }
315 
316 template<typename T>
317 void
AlignCols(Int blockHeight,Int colAlign,Int colCut,bool constrain)318 AbstractBlockDistMatrix<T>::AlignCols
319 ( Int blockHeight, Int colAlign, Int colCut, bool constrain )
320 {
321     DEBUG_ONLY(CallStackEntry cse("ABDM::AlignCols"))
322     const bool requireChange =
323         blockHeight_ != blockHeight ||
324         colAlign_    != colAlign    ||
325         colCut_      != colCut;
326     DEBUG_ONLY(
327         if( Viewing() && requireChange )
328             LogicError("Tried to realign a view");
329     )
330     if( requireChange )
331         EmptyData();
332     if( constrain )
333         colConstrained_ = true;
334     blockHeight_ = blockHeight;
335     colAlign_ = colAlign;
336     colCut_ = colCut;
337     SetShifts();
338 }
339 
340 template<typename T>
341 void
AlignRows(Int blockWidth,Int rowAlign,Int rowCut,bool constrain)342 AbstractBlockDistMatrix<T>::AlignRows
343 ( Int blockWidth, Int rowAlign, Int rowCut, bool constrain )
344 {
345     DEBUG_ONLY(CallStackEntry cse("ABDM::AlignRows"))
346     const bool requireChange =
347         blockWidth_ != blockWidth ||
348         rowAlign_   != rowAlign   ||
349         rowCut_     != rowCut;
350     DEBUG_ONLY(
351         if( Viewing() && requireChange )
352             LogicError("Tried to realign a view");
353     )
354     if( requireChange )
355         EmptyData();
356     if( constrain )
357         rowConstrained_ = true;
358     blockWidth_ = blockWidth;
359     rowAlign_ = rowAlign;
360     rowCut_ = rowCut;
361     SetShifts();
362 }
363 
364 template<typename T>
365 void
FreeAlignments()366 AbstractBlockDistMatrix<T>::FreeAlignments()
367 {
368     if( !Viewing() )
369     {
370         colConstrained_ = false;
371         rowConstrained_ = false;
372         rootConstrained_ = false;
373     }
374     else
375         LogicError("Cannot free alignments of views");
376 }
377 
378 template<typename T>
379 void
SetRoot(Int root,bool constrain)380 AbstractBlockDistMatrix<T>::SetRoot( Int root, bool constrain )
381 {
382     DEBUG_ONLY(
383         CallStackEntry cse("ABDM::SetRoot");
384         if( root < 0 || root >= mpi::Size(CrossComm()) )
385             LogicError("Invalid root");
386     )
387     if( root != root_ )
388         Empty();
389     root_ = root;
390     if( constrain )
391         rootConstrained_ = true;
392 }
393 
394 template<typename T>
395 void
AlignWith(const elem::BlockDistData & data,bool constrain)396 AbstractBlockDistMatrix<T>::AlignWith
397 ( const elem::BlockDistData& data, bool constrain )
398 {
399     DEBUG_ONLY(CallStackEntry cse("ABDM::AlignWith"))
400     AlignColsWith( data, constrain );
401     AlignRowsWith( data, constrain );
402 }
403 
404 template<typename T>
405 void
AlignColsWith(const elem::BlockDistData & data,bool constrain)406 AbstractBlockDistMatrix<T>::AlignColsWith
407 ( const elem::BlockDistData& data, bool constrain )
408 {
409     DEBUG_ONLY(
410         CallStackEntry cse("ABDM::AlignColsWith");
411         if( colAlign_ != 0 )
412             LogicError("Alignment should have been zero");
413     )
414     SetGrid( *data.grid );
415 }
416 
417 template<typename T>
418 void
AlignRowsWith(const elem::BlockDistData & data,bool constrain)419 AbstractBlockDistMatrix<T>::AlignRowsWith
420 ( const elem::BlockDistData& data, bool constrain )
421 {
422     DEBUG_ONLY(
423         CallStackEntry cse("ABDM::AlignRowsWith");
424         if( rowAlign_ != 0 )
425             LogicError("Alignment should have been zero");
426     )
427     SetGrid( *data.grid );
428 }
429 
430 template<typename T>
431 void
AlignAndResize(Int blockHeight,Int blockWidth,Int colAlign,Int rowAlign,Int colCut,Int rowCut,Int height,Int width,bool force,bool constrain)432 AbstractBlockDistMatrix<T>::AlignAndResize
433 ( Int blockHeight, Int blockWidth,
434   Int colAlign, Int rowAlign, Int colCut, Int rowCut,
435   Int height, Int width, bool force, bool constrain )
436 {
437     DEBUG_ONLY(CallStackEntry cse("ABDM::AlignAndResize"))
438     if( !Viewing() )
439     {
440         if( force || !ColConstrained() )
441         {
442             blockHeight_ = blockHeight;
443             colAlign_ = colAlign;
444             colCut_ = colCut;
445             SetColShift();
446         }
447         if( force || !RowConstrained() )
448         {
449             blockWidth_ = blockWidth;
450             rowAlign_ = rowAlign;
451             rowCut_ = rowCut;
452             SetRowShift();
453         }
454     }
455     if( constrain )
456     {
457         colConstrained_ = true;
458         rowConstrained_ = true;
459     }
460     if( force &&
461         (blockHeight_ != blockHeight || blockWidth_ != blockWidth ||
462          colAlign_    != colAlign    || rowAlign_   != rowAlign   ||
463          colCut_      != colCut      || rowCut_     != rowCut) )
464         LogicError("Could not set alignments and cuts");
465     Resize( height, width );
466 }
467 
468 template<typename T>
469 void
AlignColsAndResize(Int blockHeight,Int colAlign,Int colCut,Int height,Int width,bool force,bool constrain)470 AbstractBlockDistMatrix<T>::AlignColsAndResize
471 ( Int blockHeight, Int colAlign, Int colCut, Int height, Int width,
472   bool force, bool constrain )
473 {
474     DEBUG_ONLY(CallStackEntry cse("ABDM::AlignColsAndResize"))
475     if( !Viewing() && (force || !ColConstrained()) )
476     {
477         blockHeight_ = blockHeight;
478         colAlign_ = colAlign;
479         colCut_ = colCut;
480         SetColShift();
481     }
482     if( constrain )
483         colConstrained_ = true;
484     if( force &&
485         (colAlign_ != colAlign || colCut_ != colCut ||
486          blockHeight_ != blockHeight) )
487         LogicError("Could not set col alignment and cut");
488     Resize( height, width );
489 }
490 
491 template<typename T>
492 void
AlignRowsAndResize(Int blockWidth,Int rowAlign,Int rowCut,Int height,Int width,bool force,bool constrain)493 AbstractBlockDistMatrix<T>::AlignRowsAndResize
494 ( Int blockWidth, Int rowAlign, Int rowCut, Int height, Int width,
495   bool force, bool constrain )
496 {
497     DEBUG_ONLY(CallStackEntry cse("ABDM::AlignRowsAndResize"))
498     if( !Viewing() && (force || !RowConstrained()) )
499     {
500         blockWidth_ = blockWidth;
501         rowAlign_ = rowAlign;
502         rowCut_ = rowCut;
503         SetRowShift();
504     }
505     if( constrain )
506         rowConstrained_ = true;
507     if( force &&
508         (rowAlign_ != rowAlign || rowCut_ != rowCut ||
509          blockWidth_ != blockWidth) )
510         LogicError("Could not set row alignment and cut");
511     Resize( height, width );
512 }
513 
514 // Buffer attachment
515 // -----------------
516 
517 template<typename T>
518 void
Attach(Int height,Int width,const elem::Grid & g,Int blockHeight,Int blockWidth,Int colAlign,Int rowAlign,Int colCut,Int rowCut,T * buffer,Int ldim,Int root)519 AbstractBlockDistMatrix<T>::Attach
520 ( Int height, Int width, const elem::Grid& g,
521   Int blockHeight, Int blockWidth,
522   Int colAlign, Int rowAlign, Int colCut, Int rowCut,
523   T* buffer, Int ldim, Int root )
524 {
525     DEBUG_ONLY(CallStackEntry cse("ABDM::Attach"))
526     Empty();
527 
528     grid_ = &g;
529     root_ = root;
530     height_ = height;
531     width_ = width;
532     blockHeight_ = blockHeight;
533     blockWidth_ = blockWidth;
534     colAlign_ = colAlign;
535     rowAlign_ = rowAlign;
536     colCut_ = colCut;
537     rowCut_ = rowCut;
538     colConstrained_ = true;
539     rowConstrained_ = true;
540     viewType_ = VIEW;
541     SetShifts();
542     if( Participating() )
543     {
544         Int localHeight =
545             BlockedLength(height,colShift_,blockHeight,colCut,ColStride());
546         Int localWidth =
547             BlockedLength(width,rowShift_,blockWidth,rowCut,RowStride());
548         matrix_.Attach_( localHeight, localWidth, buffer, ldim );
549     }
550 }
551 
552 template<typename T>
553 void
Attach(Int height,Int width,const elem::Grid & g,Int blockHeight,Int blockWidth,Int colAlign,Int rowAlign,Int colCut,Int rowCut,elem::Matrix<T> & A,Int root)554 AbstractBlockDistMatrix<T>::Attach
555 ( Int height, Int width, const elem::Grid& g,
556   Int blockHeight, Int blockWidth,
557   Int colAlign, Int rowAlign, Int colCut, Int rowCut, elem::Matrix<T>& A,
558   Int root )
559 {
560     // TODO: Assert that the local dimensions are correct
561     Attach
562     ( height, width, g, blockHeight, blockWidth,
563       colAlign, rowAlign, colCut, rowCut, A.Buffer(), A.LDim(), root );
564 }
565 
566 template<typename T>
567 void
LockedAttach(Int height,Int width,const elem::Grid & g,Int blockHeight,Int blockWidth,Int colAlign,Int rowAlign,Int colCut,Int rowCut,const T * buffer,Int ldim,Int root)568 AbstractBlockDistMatrix<T>::LockedAttach
569 ( Int height, Int width, const elem::Grid& g,
570   Int blockHeight, Int blockWidth,
571   Int colAlign, Int rowAlign, Int colCut, Int rowCut,
572   const T* buffer, Int ldim, Int root )
573 {
574     DEBUG_ONLY(CallStackEntry cse("ABDM::LockedAttach"))
575     Empty();
576 
577     grid_ = &g;
578     root_ = root;
579     height_ = height;
580     width_ = width;
581     blockHeight_ = blockHeight;
582     blockWidth_ = blockWidth;
583     colAlign_ = colAlign;
584     rowAlign_ = rowAlign;
585     colCut_ = colCut;
586     rowCut_ = rowCut;
587     colConstrained_ = true;
588     rowConstrained_ = true;
589     viewType_ = LOCKED_VIEW;
590     SetShifts();
591     if( Participating() )
592     {
593         Int localHeight =
594             BlockedLength(height,colShift_,blockHeight,colCut,ColStride());
595         Int localWidth =
596             BlockedLength(width,rowShift_,blockWidth,rowCut,RowStride());
597         matrix_.LockedAttach_( localHeight, localWidth, buffer, ldim );
598     }
599 }
600 
601 template<typename T>
602 void
LockedAttach(Int height,Int width,const elem::Grid & g,Int blockHeight,Int blockWidth,Int colAlign,Int rowAlign,Int colCut,Int rowCut,const elem::Matrix<T> & A,Int root)603 AbstractBlockDistMatrix<T>::LockedAttach
604 ( Int height, Int width, const elem::Grid& g,
605   Int blockHeight, Int blockWidth,
606   Int colAlign, Int rowAlign, Int colCut, Int rowCut, const elem::Matrix<T>& A,
607   Int root )
608 {
609     // TODO: Assert that the local dimensions are correct
610     LockedAttach
611     ( height, width, g, blockHeight, blockWidth,
612       colAlign, rowAlign, colCut, rowCut, A.LockedBuffer(), A.LDim(), root );
613 }
614 
615 // Basic queries
616 // =============
617 
618 // Global matrix information
619 // -------------------------
620 
621 template<typename T>
Height() const622 Int AbstractBlockDistMatrix<T>::Height() const { return height_; }
623 template<typename T>
Width() const624 Int AbstractBlockDistMatrix<T>::Width() const { return width_; }
625 
626 template<typename T>
DiagonalLength(Int offset) const627 Int AbstractBlockDistMatrix<T>::DiagonalLength( Int offset ) const
628 { return elem::DiagonalLength(height_,width_,offset); }
629 
630 template<typename T>
Viewing() const631 bool AbstractBlockDistMatrix<T>::Viewing() const
632 { return IsViewing( viewType_ ); }
633 template<typename T>
Locked() const634 bool AbstractBlockDistMatrix<T>::Locked() const
635 { return IsLocked( viewType_ ); }
636 
637 // Local matrix information
638 // ------------------------
639 
640 template<typename T>
LocalHeight() const641 Int AbstractBlockDistMatrix<T>::LocalHeight() const { return matrix_.Height(); }
642 template<typename T>
LocalWidth() const643 Int AbstractBlockDistMatrix<T>::LocalWidth() const { return matrix_.Width(); }
644 template<typename T>
LDim() const645 Int AbstractBlockDistMatrix<T>::LDim() const { return matrix_.LDim(); }
646 
647 template<typename T>
648 elem::Matrix<T>&
Matrix()649 AbstractBlockDistMatrix<T>::Matrix() { return matrix_; }
650 template<typename T>
651 const elem::Matrix<T>&
LockedMatrix() const652 AbstractBlockDistMatrix<T>::LockedMatrix() const { return matrix_; }
653 
654 template<typename T>
655 size_t
AllocatedMemory() const656 AbstractBlockDistMatrix<T>::AllocatedMemory() const
657 { return matrix_.MemorySize(); }
658 
659 template<typename T>
660 T*
Buffer()661 AbstractBlockDistMatrix<T>::Buffer() { return matrix_.Buffer(); }
662 
663 template<typename T>
664 T*
Buffer(Int iLoc,Int jLoc)665 AbstractBlockDistMatrix<T>::Buffer( Int iLoc, Int jLoc )
666 { return matrix_.Buffer(iLoc,jLoc); }
667 
668 template<typename T>
669 const T*
LockedBuffer() const670 AbstractBlockDistMatrix<T>::LockedBuffer() const
671 { return matrix_.LockedBuffer(); }
672 
673 template<typename T>
674 const T*
LockedBuffer(Int iLoc,Int jLoc) const675 AbstractBlockDistMatrix<T>::LockedBuffer( Int iLoc, Int jLoc ) const
676 { return matrix_.LockedBuffer(iLoc,jLoc); }
677 
678 // Distribution information
679 // ------------------------
680 
681 template<typename T>
Grid() const682 const elem::Grid& AbstractBlockDistMatrix<T>::Grid() const { return *grid_; }
683 
684 template<typename T>
ColConstrained() const685 bool AbstractBlockDistMatrix<T>::ColConstrained() const
686 { return colConstrained_; }
687 template<typename T>
RowConstrained() const688 bool AbstractBlockDistMatrix<T>::RowConstrained() const
689 { return rowConstrained_; }
690 template<typename T>
RootConstrained() const691 bool AbstractBlockDistMatrix<T>::RootConstrained() const
692 { return rootConstrained_; }
693 
694 template<typename T>
BlockHeight() const695 Int AbstractBlockDistMatrix<T>::BlockHeight() const { return blockHeight_; }
696 template<typename T>
BlockWidth() const697 Int AbstractBlockDistMatrix<T>::BlockWidth() const { return blockWidth_; }
698 
699 template<typename T>
ColAlign() const700 Int AbstractBlockDistMatrix<T>::ColAlign() const { return colAlign_; }
701 template<typename T>
RowAlign() const702 Int AbstractBlockDistMatrix<T>::RowAlign() const { return rowAlign_; }
703 
704 template<typename T>
ColCut() const705 Int AbstractBlockDistMatrix<T>::ColCut() const { return colCut_; }
706 template<typename T>
RowCut() const707 Int AbstractBlockDistMatrix<T>::RowCut() const { return rowCut_; }
708 
709 template<typename T>
ColShift() const710 Int AbstractBlockDistMatrix<T>::ColShift() const { return colShift_; }
711 template<typename T>
RowShift() const712 Int AbstractBlockDistMatrix<T>::RowShift() const { return rowShift_; }
713 
714 template<typename T>
715 Int
ColRank() const716 AbstractBlockDistMatrix<T>::ColRank() const
717 { return mpi::Rank(ColComm()); }
718 
719 template<typename T>
720 Int
RowRank() const721 AbstractBlockDistMatrix<T>::RowRank() const
722 { return mpi::Rank(RowComm()); }
723 
724 template<typename T>
725 Int
PartialColRank() const726 AbstractBlockDistMatrix<T>::PartialColRank() const
727 { return mpi::Rank(PartialColComm()); }
728 
729 template<typename T>
730 Int
PartialUnionColRank() const731 AbstractBlockDistMatrix<T>::PartialUnionColRank() const
732 { return mpi::Rank(PartialUnionColComm()); }
733 
734 template<typename T>
735 Int
PartialRowRank() const736 AbstractBlockDistMatrix<T>::PartialRowRank() const
737 { return mpi::Rank(PartialRowComm()); }
738 
739 template<typename T>
740 Int
PartialUnionRowRank() const741 AbstractBlockDistMatrix<T>::PartialUnionRowRank() const
742 { return mpi::Rank(PartialUnionRowComm()); }
743 
744 template<typename T>
745 Int
DistRank() const746 AbstractBlockDistMatrix<T>::DistRank() const
747 { return mpi::Rank(DistComm()); }
748 
749 template<typename T>
750 Int
CrossRank() const751 AbstractBlockDistMatrix<T>::CrossRank() const
752 { return mpi::Rank(CrossComm()); }
753 
754 template<typename T>
755 Int
RedundantRank() const756 AbstractBlockDistMatrix<T>::RedundantRank() const
757 { return mpi::Rank(RedundantComm()); }
758 
759 template<typename T>
Root() const760 Int AbstractBlockDistMatrix<T>::Root() const { return root_; }
761 
762 template<typename T>
763 bool
Participating() const764 AbstractBlockDistMatrix<T>::Participating() const
765 { return grid_->InGrid() && (CrossRank()==root_); }
766 
767 template<typename T>
768 Int
RowOwner(Int i) const769 AbstractBlockDistMatrix<T>::RowOwner( Int i ) const
770 { return (((i+ColCut())/BlockHeight())+ColAlign()) % ColStride(); }
771 
772 template<typename T>
773 Int
ColOwner(Int j) const774 AbstractBlockDistMatrix<T>::ColOwner( Int j ) const
775 { return (((j+RowCut())/BlockWidth())+RowAlign()) % RowStride(); }
776 
777 template<typename T>
778 Int
Owner(Int i,Int j) const779 AbstractBlockDistMatrix<T>::Owner( Int i, Int j ) const
780 { return RowOwner(i)+ColOwner(j)*ColStride(); }
781 
782 template<typename T>
783 Int
LocalRow(Int i) const784 AbstractBlockDistMatrix<T>::LocalRow( Int i ) const
785 {
786     DEBUG_ONLY(
787         CallStackEntry cse("ABDM::LocalRow");
788         if( !IsLocalRow(i) )
789             LogicError("Requested local index of non-local row");
790     )
791     return LocalRowOffset(i);
792 }
793 
794 template<typename T>
795 Int
LocalCol(Int j) const796 AbstractBlockDistMatrix<T>::LocalCol( Int j ) const
797 {
798     DEBUG_ONLY(
799         CallStackEntry cse("ABDM::LocalCol");
800         if( !IsLocalCol(j) )
801             LogicError("Requested local index of non-local column");
802     )
803     return LocalColOffset(j);
804 }
805 
806 template<typename T>
807 Int
LocalRowOffset(Int i) const808 AbstractBlockDistMatrix<T>::LocalRowOffset( Int i ) const
809 { return BlockedLength_
810          ( i, ColShift(), BlockHeight(), ColCut(), ColStride() ); }
811 
812 template<typename T>
813 Int
LocalColOffset(Int j) const814 AbstractBlockDistMatrix<T>::LocalColOffset( Int j ) const
815 { return BlockedLength_( j, RowShift(), BlockWidth(), RowCut(), RowStride() ); }
816 
817 template<typename T>
818 Int
GlobalRow(Int iLoc) const819 AbstractBlockDistMatrix<T>::GlobalRow( Int iLoc ) const
820 {
821     return GlobalBlockedIndex
822            (iLoc,ColShift(),BlockHeight(),ColCut(),ColStride());
823 }
824 
825 template<typename T>
826 Int
GlobalCol(Int jLoc) const827 AbstractBlockDistMatrix<T>::GlobalCol( Int jLoc ) const
828 {
829     return GlobalBlockedIndex
830            (jLoc,RowShift(),BlockWidth(),RowCut(),RowStride());
831 }
832 
833 template<typename T>
834 bool
IsLocalRow(Int i) const835 AbstractBlockDistMatrix<T>::IsLocalRow( Int i ) const
836 { return Participating() && RowOwner(i) == ColRank(); }
837 
838 template<typename T>
839 bool
IsLocalCol(Int j) const840 AbstractBlockDistMatrix<T>::IsLocalCol( Int j ) const
841 { return Participating() && ColOwner(j) == RowRank(); }
842 
843 template<typename T>
844 bool
IsLocal(Int i,Int j) const845 AbstractBlockDistMatrix<T>::IsLocal( Int i, Int j ) const
846 { return IsLocalRow(i) && IsLocalCol(j); }
847 
848 template<typename T>
849 mpi::Comm
PartialColComm() const850 AbstractBlockDistMatrix<T>::PartialColComm() const
851 { return ColComm(); }
852 
853 template<typename T>
854 mpi::Comm
PartialRowComm() const855 AbstractBlockDistMatrix<T>::PartialRowComm() const
856 { return RowComm(); }
857 
858 template<typename T>
859 mpi::Comm
PartialUnionColComm() const860 AbstractBlockDistMatrix<T>::PartialUnionColComm() const
861 { return mpi::COMM_SELF; }
862 
863 template<typename T>
864 mpi::Comm
PartialUnionRowComm() const865 AbstractBlockDistMatrix<T>::PartialUnionRowComm() const
866 { return mpi::COMM_SELF; }
867 
868 template<typename T>
869 Int
PartialColStride() const870 AbstractBlockDistMatrix<T>::PartialColStride() const
871 { return ColStride(); }
872 
873 template<typename T>
874 Int
PartialRowStride() const875 AbstractBlockDistMatrix<T>::PartialRowStride() const
876 { return RowStride(); }
877 
878 template<typename T>
879 Int
PartialUnionColStride() const880 AbstractBlockDistMatrix<T>::PartialUnionColStride() const
881 { return 1; }
882 
883 template<typename T>
884 Int
PartialUnionRowStride() const885 AbstractBlockDistMatrix<T>::PartialUnionRowStride() const
886 { return 1; }
887 
888 // Single-entry manipulation
889 // =========================
890 
891 // Global entry manipulation
892 // -------------------------
893 
894 template<typename T>
895 T
Get(Int i,Int j) const896 AbstractBlockDistMatrix<T>::Get( Int i, Int j ) const
897 {
898     DEBUG_ONLY(
899         CallStackEntry cse("ABDM::Get");
900         if( !grid_->InGrid() )
901             LogicError("Get should only be called in-grid");
902     )
903     T value;
904     if( CrossRank() == Root() )
905     {
906         const Int owner = Owner( i, j );
907         if( owner == DistRank() )
908         {
909             const Int iLoc = LocalRow(i);
910             const Int jLoc = LocalCol(j);
911             value = GetLocal( iLoc, jLoc );
912         }
913         mpi::Broadcast( value, owner, DistComm() );
914     }
915     mpi::Broadcast( value, Root(), CrossComm() );
916     return value;
917 }
918 
919 template<typename T>
920 Base<T>
GetRealPart(Int i,Int j) const921 AbstractBlockDistMatrix<T>::GetRealPart( Int i, Int j ) const
922 {
923     DEBUG_ONLY(
924         CallStackEntry cse("ABDM::GetRealPart");
925         if( !grid_->InGrid() )
926             LogicError("Get should only be called in-grid");
927     )
928     Base<T> value;
929     if( CrossRank() == Root() )
930     {
931         const Int owner = Owner( i, j );
932         if( owner == DistRank() )
933         {
934             const Int iLoc = LocalRow(i);
935             const Int jLoc = LocalCol(j);
936             value = GetLocalRealPart( iLoc, jLoc );
937         }
938         mpi::Broadcast( value, owner, DistComm() );
939     }
940     mpi::Broadcast( value, Root(), CrossComm() );
941     return value;
942 }
943 
944 template<typename T>
945 Base<T>
GetImagPart(Int i,Int j) const946 AbstractBlockDistMatrix<T>::GetImagPart( Int i, Int j ) const
947 {
948     DEBUG_ONLY(
949         CallStackEntry cse("ABDM::GetImagPart");
950         if( !grid_->InGrid() )
951             LogicError("Get should only be called in-grid");
952     )
953     Base<T> value;
954     if( IsComplex<T>::val )
955     {
956         if( CrossRank() == Root() )
957         {
958             const Int owner = Owner( i, j );
959             if( owner == DistRank() )
960             {
961                 const Int iLoc = LocalRow(i);
962                 const Int jLoc = LocalCol(j);
963                 value = GetLocalRealPart( iLoc, jLoc );
964             }
965             mpi::Broadcast( value, owner, DistComm() );
966         }
967         mpi::Broadcast( value, Root(), CrossComm() );
968     }
969     else
970         value = 0;
971     return value;
972 }
973 
974 template<typename T>
975 void
Set(Int i,Int j,T value)976 AbstractBlockDistMatrix<T>::Set( Int i, Int j, T value )
977 {
978     DEBUG_ONLY(CallStackEntry cse("ABDM::Set"))
979     if( CrossRank() == Root() )
980     {
981         const Int owner = Owner( i, j );
982         if( owner == DistRank() )
983         {
984             const Int iLoc = LocalRow(i);
985             const Int jLoc = LocalCol(j);
986             SetLocal( iLoc, jLoc, value );
987         }
988     }
989 }
990 
991 template<typename T>
992 void
SetRealPart(Int i,Int j,Base<T> value)993 AbstractBlockDistMatrix<T>::SetRealPart( Int i, Int j, Base<T> value )
994 {
995     DEBUG_ONLY(CallStackEntry cse("ABDM::SetRealPart"))
996     if( CrossRank() == Root() )
997     {
998         const Int owner = Owner( i, j );
999         if( owner == DistRank() )
1000         {
1001             const Int iLoc = LocalRow(i);
1002             const Int jLoc = LocalCol(j);
1003             SetLocalRealPart( iLoc, jLoc, value );
1004         }
1005     }
1006 }
1007 
1008 template<typename T>
1009 void
SetImagPart(Int i,Int j,Base<T> value)1010 AbstractBlockDistMatrix<T>::SetImagPart( Int i, Int j, Base<T> value )
1011 {
1012     DEBUG_ONLY(CallStackEntry cse("ABDM::SetImagPart"))
1013     if( CrossRank() == Root() )
1014     {
1015         const Int owner = Owner( i, j );
1016         if( owner == DistRank() )
1017         {
1018             const Int iLoc = LocalRow(i);
1019             const Int jLoc = LocalCol(j);
1020             SetLocalImagPart( iLoc, jLoc, value );
1021         }
1022     }
1023 }
1024 
1025 template<typename T>
1026 void
Update(Int i,Int j,T value)1027 AbstractBlockDistMatrix<T>::Update( Int i, Int j, T value )
1028 {
1029     DEBUG_ONLY(CallStackEntry cse("ABDM::Update"))
1030     if( CrossRank() == Root() )
1031     {
1032         const Int owner = Owner( i, j );
1033         if( owner == DistRank() )
1034         {
1035             const Int iLoc = LocalRow(i);
1036             const Int jLoc = LocalCol(j);
1037             UpdateLocal( iLoc, jLoc, value );
1038         }
1039     }
1040 }
1041 
1042 template<typename T>
1043 void
UpdateRealPart(Int i,Int j,Base<T> value)1044 AbstractBlockDistMatrix<T>::UpdateRealPart( Int i, Int j, Base<T> value )
1045 {
1046     DEBUG_ONLY(CallStackEntry cse("ABDM::UpdateRealPart"))
1047     if( CrossRank() == Root() )
1048     {
1049         const Int owner = Owner( i, j );
1050         if( owner == DistRank() )
1051         {
1052             const Int iLoc = LocalRow(i);
1053             const Int jLoc = LocalCol(j);
1054             UpdateLocalRealPart( iLoc, jLoc, value );
1055         }
1056     }
1057 }
1058 
1059 template<typename T>
1060 void
UpdateImagPart(Int i,Int j,Base<T> value)1061 AbstractBlockDistMatrix<T>::UpdateImagPart( Int i, Int j, Base<T> value )
1062 {
1063     DEBUG_ONLY(CallStackEntry cse("ABDM::UpdateImagPart"))
1064     if( CrossRank() == Root() )
1065     {
1066         const Int owner = Owner( i, j );
1067         if( owner == DistRank() )
1068         {
1069             const Int iLoc = LocalRow(i);
1070             const Int jLoc = LocalCol(j);
1071             UpdateLocalImagPart( iLoc, jLoc, value );
1072         }
1073     }
1074 }
1075 
1076 template<typename T>
1077 void
MakeReal(Int i,Int j)1078 AbstractBlockDistMatrix<T>::MakeReal( Int i, Int j )
1079 {
1080     DEBUG_ONLY(CallStackEntry cse("ABDM::MakeReal"))
1081     if( CrossRank() == Root() )
1082     {
1083         const Int owner = Owner( i, j );
1084         if( owner == DistRank() )
1085         {
1086             const Int iLoc = LocalRow(i);
1087             const Int jLoc = LocalCol(j);
1088             MakeLocalReal( iLoc, jLoc );
1089         }
1090     }
1091 }
1092 
1093 template<typename T>
1094 void
Conjugate(Int i,Int j)1095 AbstractBlockDistMatrix<T>::Conjugate( Int i, Int j )
1096 {
1097     DEBUG_ONLY(CallStackEntry cse("ABDM::Conjugate"))
1098     if( CrossRank() == Root() )
1099     {
1100         const Int owner = Owner( i, j );
1101         if( owner == DistRank() )
1102         {
1103             const Int iLoc = LocalRow(i);
1104             const Int jLoc = LocalCol(j);
1105             ConjugateLocal( iLoc, jLoc );
1106         }
1107     }
1108 }
1109 
1110 // Local entry manipulation
1111 // ------------------------
1112 
1113 template<typename T>
1114 T
GetLocal(Int i,Int j) const1115 AbstractBlockDistMatrix<T>::GetLocal( Int i, Int j ) const
1116 { return matrix_.Get(i,j); }
1117 
1118 template<typename T>
1119 Base<T>
GetLocalRealPart(Int iLoc,Int jLoc) const1120 AbstractBlockDistMatrix<T>::GetLocalRealPart( Int iLoc, Int jLoc ) const
1121 { return matrix_.GetRealPart(iLoc,jLoc); }
1122 
1123 template<typename T>
1124 Base<T>
GetLocalImagPart(Int iLoc,Int jLoc) const1125 AbstractBlockDistMatrix<T>::GetLocalImagPart( Int iLoc, Int jLoc ) const
1126 { return matrix_.GetImagPart(iLoc,jLoc); }
1127 
1128 template<typename T>
1129 void
SetLocal(Int iLoc,Int jLoc,T alpha)1130 AbstractBlockDistMatrix<T>::SetLocal( Int iLoc, Int jLoc, T alpha )
1131 { matrix_.Set(iLoc,jLoc,alpha); }
1132 
1133 template<typename T>
1134 void
SetLocalRealPart(Int iLoc,Int jLoc,Base<T> alpha)1135 AbstractBlockDistMatrix<T>::SetLocalRealPart
1136 ( Int iLoc, Int jLoc, Base<T> alpha )
1137 { matrix_.SetRealPart(iLoc,jLoc,alpha); }
1138 
1139 template<typename T>
1140 void
SetLocalImagPart(Int iLoc,Int jLoc,Base<T> alpha)1141 AbstractBlockDistMatrix<T>::SetLocalImagPart
1142 ( Int iLoc, Int jLoc, Base<T> alpha )
1143 { matrix_.SetImagPart(iLoc,jLoc,alpha); }
1144 
1145 template<typename T>
1146 void
UpdateLocal(Int iLoc,Int jLoc,T alpha)1147 AbstractBlockDistMatrix<T>::UpdateLocal( Int iLoc, Int jLoc, T alpha )
1148 { matrix_.Update(iLoc,jLoc,alpha); }
1149 
1150 template<typename T>
1151 void
UpdateLocalRealPart(Int iLoc,Int jLoc,Base<T> alpha)1152 AbstractBlockDistMatrix<T>::UpdateLocalRealPart
1153 ( Int iLoc, Int jLoc, Base<T> alpha )
1154 { matrix_.UpdateRealPart(iLoc,jLoc,alpha); }
1155 
1156 template<typename T>
1157 void
UpdateLocalImagPart(Int iLoc,Int jLoc,Base<T> alpha)1158 AbstractBlockDistMatrix<T>::UpdateLocalImagPart
1159 ( Int iLoc, Int jLoc, Base<T> alpha )
1160 { matrix_.UpdateImagPart(iLoc,jLoc,alpha); }
1161 
1162 template<typename T>
1163 void
MakeLocalReal(Int iLoc,Int jLoc)1164 AbstractBlockDistMatrix<T>::MakeLocalReal( Int iLoc, Int jLoc )
1165 { matrix_.MakeReal( iLoc, jLoc ); }
1166 
1167 template<typename T>
1168 void
ConjugateLocal(Int iLoc,Int jLoc)1169 AbstractBlockDistMatrix<T>::ConjugateLocal( Int iLoc, Int jLoc )
1170 { matrix_.Conjugate( iLoc, jLoc ); }
1171 
1172 // Diagonal manipulation
1173 // =====================
1174 
1175 template<typename T>
1176 void
MakeDiagonalReal(Int offset)1177 AbstractBlockDistMatrix<T>::MakeDiagonalReal( Int offset )
1178 {
1179     DEBUG_ONLY(CallStackEntry cse("ABDM::MakeDiagonalReal"))
1180     const Int height = Height();
1181     const Int localWidth = LocalWidth();
1182     for( Int jLoc=0; jLoc<localWidth; ++jLoc )
1183     {
1184         const Int j = GlobalCol(jLoc);
1185         if( j < height && IsLocal(j,j) )
1186         {
1187             const Int iLoc = LocalRow(j);
1188             MakeLocalReal( iLoc, jLoc );
1189         }
1190     }
1191 }
1192 
1193 template<typename T>
1194 void
ConjugateDiagonal(Int offset)1195 AbstractBlockDistMatrix<T>::ConjugateDiagonal( Int offset )
1196 {
1197     DEBUG_ONLY(CallStackEntry cse("ABDM::ConjugateDiagonal"))
1198     const Int height = Height();
1199     const Int localWidth = LocalWidth();
1200     for( Int jLoc=0; jLoc<localWidth; ++jLoc )
1201     {
1202         const Int j = GlobalCol(jLoc);
1203         if( j < height && IsLocal(j,j) )
1204         {
1205             const Int iLoc = LocalRow(j);
1206             ConjugateLocal( iLoc, jLoc );
1207         }
1208     }
1209 }
1210 
1211 // Arbitrary submatrix manipulation
1212 // ================================
1213 
1214 // Global submatrix manipulation
1215 // -----------------------------
1216 
1217 template<typename T>
1218 void
GetSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,DistMatrix<T,STAR,STAR> & ASub) const1219 AbstractBlockDistMatrix<T>::GetSubmatrix
1220 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1221   DistMatrix<T,STAR,STAR>& ASub ) const
1222 {
1223     DEBUG_ONLY(CallStackEntry cse("ABDM::GetSubmatrix"))
1224     const Int m = rowInd.size();
1225     const Int n = colInd.size();
1226     ASub.SetGrid( Grid() );
1227     ASub.Resize( m, n, m );
1228     Zeros( ASub, m, n );
1229     if( Participating() )
1230     {
1231         // Fill in our locally-owned entries
1232         for( Int jSub=0; jSub<n; ++jSub )
1233         {
1234             const Int j = colInd[jSub];
1235             if( IsLocalCol(j) )
1236             {
1237                 const Int jLoc = LocalCol(j);
1238                 for( Int iSub=0; iSub<m; ++iSub )
1239                 {
1240                     const Int i = rowInd[iSub];
1241                     if( IsLocalRow(i) )
1242                     {
1243                         const Int iLoc = LocalRow(i);
1244                         ASub.SetLocal( iSub, jSub, GetLocal(iLoc,jLoc) );
1245                     }
1246                 }
1247             }
1248         }
1249         // Sum over the distribution communicator
1250         mpi::AllReduce( ASub.Buffer(), m*n, DistComm() );
1251     }
1252     // Broadcast over the cross communicator
1253     mpi::Broadcast( ASub.Buffer(), m*n, Root(), CrossComm() );
1254 }
1255 
1256 template<typename T>
1257 void
GetRealPartOfSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,DistMatrix<Base<T>,STAR,STAR> & ASub) const1258 AbstractBlockDistMatrix<T>::GetRealPartOfSubmatrix
1259 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1260   DistMatrix<Base<T>,STAR,STAR>& ASub ) const
1261 {
1262     DEBUG_ONLY(CallStackEntry cse("ABDM::GetRealPartOfSubmatrix"))
1263     const Int m = rowInd.size();
1264     const Int n = colInd.size();
1265     ASub.SetGrid( Grid() );
1266     ASub.Resize( m, n, m );
1267     Zeros( ASub, m, n );
1268     if( Participating() )
1269     {
1270         // Fill in our locally-owned entries
1271         for( Int jSub=0; jSub<n; ++jSub )
1272         {
1273             const Int j = colInd[jSub];
1274             if( IsLocalCol(j) )
1275             {
1276                 const Int jLoc = LocalCol(j);
1277                 for( Int iSub=0; iSub<m; ++iSub )
1278                 {
1279                     const Int i = rowInd[iSub];
1280                     if( IsLocalRow(i) )
1281                     {
1282                         const Int iLoc = LocalRow(i);
1283                         ASub.SetLocal
1284                         ( iSub, jSub, GetLocalRealPart(iLoc,jLoc) );
1285                     }
1286                 }
1287             }
1288         }
1289         // Sum over the distribution communicator
1290         mpi::AllReduce( ASub.Buffer(), m*n, DistComm() );
1291     }
1292     // Broadcast over the cross communicator
1293     mpi::Broadcast( ASub.Buffer(), m*n, Root(), CrossComm() );
1294 }
1295 
1296 template<typename T>
1297 void
GetImagPartOfSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,DistMatrix<Base<T>,STAR,STAR> & ASub) const1298 AbstractBlockDistMatrix<T>::GetImagPartOfSubmatrix
1299 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1300   DistMatrix<Base<T>,STAR,STAR>& ASub ) const
1301 {
1302     DEBUG_ONLY(CallStackEntry cse("ABDM::GetImagPartOfSubmatrix"))
1303     const Int m = rowInd.size();
1304     const Int n = colInd.size();
1305     ASub.SetGrid( Grid() );
1306     ASub.Resize( m, n, m );
1307     Zeros( ASub, m, n );
1308     if( Participating() )
1309     {
1310         // Fill in our locally-owned entries
1311         for( Int jSub=0; jSub<n; ++jSub )
1312         {
1313             const Int j = colInd[jSub];
1314             if( IsLocalCol(j) )
1315             {
1316                 const Int jLoc = LocalCol(j);
1317                 for( Int iSub=0; iSub<m; ++iSub )
1318                 {
1319                     const Int i = rowInd[iSub];
1320                     if( IsLocalRow(i) )
1321                     {
1322                         const Int iLoc = LocalRow(i);
1323                         ASub.SetLocal
1324                         ( iSub, jSub, GetLocalImagPart(iLoc,jLoc) );
1325                     }
1326                 }
1327             }
1328         }
1329         // Sum over the distribution communicator
1330         mpi::AllReduce( ASub.Buffer(), m*n, DistComm() );
1331     }
1332     // Broadcast over the cross communicator
1333     mpi::Broadcast( ASub.Buffer(), m*n, Root(), CrossComm() );
1334 }
1335 
1336 template<typename T>
1337 DistMatrix<T,STAR,STAR>
GetSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd) const1338 AbstractBlockDistMatrix<T>::GetSubmatrix
1339 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd ) const
1340 {
1341     DEBUG_ONLY(CallStackEntry cse("ABDM::GetSubmatrix"))
1342     DistMatrix<T,STAR,STAR> ASub( Grid() );
1343     GetSubmatrix( rowInd, colInd, ASub );
1344     return ASub;
1345 }
1346 
1347 template<typename T>
1348 DistMatrix<Base<T>,STAR,STAR>
GetRealPartOfSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd) const1349 AbstractBlockDistMatrix<T>::GetRealPartOfSubmatrix
1350 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd ) const
1351 {
1352     DEBUG_ONLY(CallStackEntry cse("ABDM::GetRealPartOfSubmatrix"))
1353     DistMatrix<Base<T>,STAR,STAR> ASub( Grid() );
1354     GetRealPartOfSubmatrix( rowInd, colInd, ASub );
1355     return ASub;
1356 }
1357 
1358 template<typename T>
1359 DistMatrix<Base<T>,STAR,STAR>
GetImagPartOfSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd) const1360 AbstractBlockDistMatrix<T>::GetImagPartOfSubmatrix
1361 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd ) const
1362 {
1363     DEBUG_ONLY(CallStackEntry cse("ABDM::GetImagPartOfSubmatrix"))
1364     DistMatrix<Base<T>,STAR,STAR> ASub( Grid() );
1365     GetImagPartOfSubmatrix( rowInd, colInd, ASub );
1366     return ASub;
1367 }
1368 
1369 template<typename T>
1370 void
SetSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,const DistMatrix<T,STAR,STAR> & ASub)1371 AbstractBlockDistMatrix<T>::SetSubmatrix
1372 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1373   const DistMatrix<T,STAR,STAR>& ASub )
1374 {
1375     DEBUG_ONLY(CallStackEntry cse("ABDM::SetSubmatrix"))
1376     const Int m = rowInd.size();
1377     const Int n = colInd.size();
1378     if( Participating() )
1379     {
1380         // Fill in our locally-owned entries
1381         for( Int jSub=0; jSub<n; ++jSub )
1382         {
1383             const Int j = colInd[jSub];
1384             if( IsLocalCol(j) )
1385             {
1386                 const Int jLoc = LocalCol(j);
1387                 for( Int iSub=0; iSub<m; ++iSub )
1388                 {
1389                     const Int i = rowInd[iSub];
1390                     if( IsLocalRow(i) )
1391                     {
1392                         const Int iLoc = LocalRow(i);
1393                         SetLocal( iLoc, jLoc, ASub.GetLocal(iSub,jSub) );
1394                     }
1395                 }
1396             }
1397         }
1398     }
1399 }
1400 
1401 template<typename T>
1402 void
SetRealPartOfSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,const DistMatrix<Base<T>,STAR,STAR> & ASub)1403 AbstractBlockDistMatrix<T>::SetRealPartOfSubmatrix
1404 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1405   const DistMatrix<Base<T>,STAR,STAR>& ASub )
1406 {
1407     DEBUG_ONLY(CallStackEntry cse("ABDM::SetRealPartOfSubmatrix"))
1408     const Int m = rowInd.size();
1409     const Int n = colInd.size();
1410     if( Participating() )
1411     {
1412         // Fill in our locally-owned entries
1413         for( Int jSub=0; jSub<n; ++jSub )
1414         {
1415             const Int j = colInd[jSub];
1416             if( IsLocalCol(j) )
1417             {
1418                 const Int jLoc = LocalCol(j);
1419                 for( Int iSub=0; iSub<m; ++iSub )
1420                 {
1421                     const Int i = rowInd[iSub];
1422                     if( IsLocalRow(i) )
1423                     {
1424                         const Int iLoc = LocalRow(i);
1425                         SetLocalRealPart
1426                         ( iLoc, jLoc, ASub.GetLocal(iSub,jSub) );
1427                     }
1428                 }
1429             }
1430         }
1431     }
1432 }
1433 
1434 template<typename T>
1435 void
SetImagPartOfSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,const DistMatrix<Base<T>,STAR,STAR> & ASub)1436 AbstractBlockDistMatrix<T>::SetImagPartOfSubmatrix
1437 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1438   const DistMatrix<Base<T>,STAR,STAR>& ASub )
1439 {
1440     DEBUG_ONLY(CallStackEntry cse("ABDM::SetImagPartOfSubmatrix"))
1441     const Int m = rowInd.size();
1442     const Int n = colInd.size();
1443     if( Participating() )
1444     {
1445         // Fill in our locally-owned entries
1446         for( Int jSub=0; jSub<n; ++jSub )
1447         {
1448             const Int j = colInd[jSub];
1449             if( IsLocalCol(j) )
1450             {
1451                 const Int jLoc = LocalCol(j);
1452                 for( Int iSub=0; iSub<m; ++iSub )
1453                 {
1454                     const Int i = rowInd[iSub];
1455                     if( IsLocalRow(i) )
1456                     {
1457                         const Int iLoc = LocalRow(i);
1458                         SetLocalImagPart
1459                         ( iLoc, jLoc, ASub.GetLocal(iSub,jSub) );
1460                     }
1461                 }
1462             }
1463         }
1464     }
1465 }
1466 
1467 template<typename T>
1468 void
UpdateSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,T alpha,const DistMatrix<T,STAR,STAR> & ASub)1469 AbstractBlockDistMatrix<T>::UpdateSubmatrix
1470 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1471   T alpha, const DistMatrix<T,STAR,STAR>& ASub )
1472 {
1473     DEBUG_ONLY(CallStackEntry cse("ABDM::UpdateSubmatrix"))
1474     const Int m = rowInd.size();
1475     const Int n = colInd.size();
1476     if( Participating() )
1477     {
1478         // Modify our locally-owned entries
1479         for( Int jSub=0; jSub<n; ++jSub )
1480         {
1481             const Int j = colInd[jSub];
1482             if( IsLocalCol(j) )
1483             {
1484                 const Int jLoc = LocalCol(j);
1485                 for( Int iSub=0; iSub<m; ++iSub )
1486                 {
1487                     const Int i = rowInd[iSub];
1488                     if( IsLocalRow(i) )
1489                     {
1490                         const Int iLoc = LocalRow(i);
1491                         UpdateLocal
1492                         ( iLoc, jLoc, alpha*ASub.GetLocal(iSub,jSub) );
1493                     }
1494                 }
1495             }
1496         }
1497     }
1498 }
1499 
1500 template<typename T>
1501 void
UpdateRealPartOfSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,Base<T> alpha,const DistMatrix<Base<T>,STAR,STAR> & ASub)1502 AbstractBlockDistMatrix<T>::UpdateRealPartOfSubmatrix
1503 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1504   Base<T> alpha, const DistMatrix<Base<T>,STAR,STAR>& ASub )
1505 {
1506     DEBUG_ONLY(CallStackEntry cse("ABDM::UpdateRealPartOfSubmatrix"))
1507     const Int m = rowInd.size();
1508     const Int n = colInd.size();
1509     if( Participating() )
1510     {
1511         // Modify our locally-owned entries
1512         for( Int jSub=0; jSub<n; ++jSub )
1513         {
1514             const Int j = colInd[jSub];
1515             if( IsLocalCol(j) )
1516             {
1517                 const Int jLoc = LocalCol(j);
1518                 for( Int iSub=0; iSub<m; ++iSub )
1519                 {
1520                     const Int i = rowInd[iSub];
1521                     if( IsLocalRow(i) )
1522                     {
1523                         const Int iLoc = LocalRow(i);
1524                         UpdateLocalRealPart
1525                         ( iLoc, jLoc, alpha*ASub.GetLocal(iSub,jSub) );
1526                     }
1527                 }
1528             }
1529         }
1530     }
1531 }
1532 
1533 template<typename T>
1534 void
UpdateImagPartOfSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd,Base<T> alpha,const DistMatrix<Base<T>,STAR,STAR> & ASub)1535 AbstractBlockDistMatrix<T>::UpdateImagPartOfSubmatrix
1536 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd,
1537   Base<T> alpha, const DistMatrix<Base<T>,STAR,STAR>& ASub )
1538 {
1539     DEBUG_ONLY(CallStackEntry cse("ABDM::UpdateImagPartOfSubmatrix"))
1540     const Int m = rowInd.size();
1541     const Int n = colInd.size();
1542     if( Participating() )
1543     {
1544         // Modify our locally-owned entries
1545         for( Int jSub=0; jSub<n; ++jSub )
1546         {
1547             const Int j = colInd[jSub];
1548             if( IsLocalCol(j) )
1549             {
1550                 const Int jLoc = LocalCol(j);
1551                 for( Int iSub=0; iSub<m; ++iSub )
1552                 {
1553                     const Int i = rowInd[iSub];
1554                     if( IsLocalRow(i) )
1555                     {
1556                         const Int iLoc = LocalRow(i);
1557                         UpdateLocalImagPart
1558                         ( iLoc, jLoc, alpha*ASub.GetLocal(iSub,jSub) );
1559                     }
1560                 }
1561             }
1562         }
1563     }
1564 }
1565 
1566 template<typename T>
1567 void
MakeSubmatrixReal(const std::vector<Int> & rowInd,const std::vector<Int> & colInd)1568 AbstractBlockDistMatrix<T>::MakeSubmatrixReal
1569 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd )
1570 {
1571     DEBUG_ONLY(CallStackEntry cse("ABDM::MakeSubmatrixReal"))
1572     const Int m = rowInd.size();
1573     const Int n = colInd.size();
1574     if( Participating() )
1575     {
1576         // Modify the locally-owned entries
1577         for( Int jSub=0; jSub<n; ++jSub )
1578         {
1579             const Int j = colInd[jSub];
1580             if( IsLocalCol(j) )
1581             {
1582                 const Int jLoc = LocalCol(j);
1583                 for( Int iSub=0; iSub<m; ++iSub )
1584                 {
1585                     const Int i = rowInd[iSub];
1586                     if( IsLocalRow(i) )
1587                     {
1588                         const Int iLoc = LocalRow(i);
1589                         MakeLocalReal( iLoc, jLoc );
1590                     }
1591                 }
1592             }
1593         }
1594     }
1595 }
1596 
1597 template<typename T>
1598 void
ConjugateSubmatrix(const std::vector<Int> & rowInd,const std::vector<Int> & colInd)1599 AbstractBlockDistMatrix<T>::ConjugateSubmatrix
1600 ( const std::vector<Int>& rowInd, const std::vector<Int>& colInd )
1601 {
1602     DEBUG_ONLY(CallStackEntry cse("ABDM::ConjugateSubmatrix"))
1603     const Int m = rowInd.size();
1604     const Int n = colInd.size();
1605     if( Participating() )
1606     {
1607         // Modify the locally-owned entries
1608         for( Int jSub=0; jSub<n; ++jSub )
1609         {
1610             const Int j = colInd[jSub];
1611             if( IsLocalCol(j) )
1612             {
1613                 const Int jLoc = LocalCol(j);
1614                 for( Int iSub=0; iSub<m; ++iSub )
1615                 {
1616                     const Int i = rowInd[iSub];
1617                     if( IsLocalRow(i) )
1618                     {
1619                         const Int iLoc = LocalRow(i);
1620                         ConjugateLocal( iLoc, jLoc );
1621                     }
1622                 }
1623             }
1624         }
1625     }
1626 }
1627 
1628 // Local submatrix manipulation
1629 // ----------------------------
1630 
1631 template<typename T>
1632 void
GetLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,elem::Matrix<T> & ASub) const1633 AbstractBlockDistMatrix<T>::GetLocalSubmatrix
1634 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1635   elem::Matrix<T>& ASub ) const
1636 {
1637     DEBUG_ONLY(CallStackEntry cse("ABDM::GetLocalSubmatrix"))
1638     LockedMatrix().GetSubmatrix( rowIndLoc, colIndLoc, ASub );
1639 }
1640 
1641 template<typename T>
1642 void
GetRealPartOfLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,elem::Matrix<Base<T>> & ASub) const1643 AbstractBlockDistMatrix<T>::GetRealPartOfLocalSubmatrix
1644 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1645   elem::Matrix<Base<T>>& ASub ) const
1646 {
1647     DEBUG_ONLY(CallStackEntry cse("ABDM::GetRealPartOfLocalSubmatrix"))
1648     LockedMatrix().GetRealPartOfSubmatrix( rowIndLoc, colIndLoc, ASub );
1649 }
1650 
1651 template<typename T>
1652 void
GetImagPartOfLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,elem::Matrix<Base<T>> & ASub) const1653 AbstractBlockDistMatrix<T>::GetImagPartOfLocalSubmatrix
1654 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1655   elem::Matrix<Base<T>>& ASub ) const
1656 {
1657     DEBUG_ONLY(CallStackEntry cse("ABDM::GetImagPartOfLocalSubmatrix"))
1658     LockedMatrix().GetImagPartOfSubmatrix( rowIndLoc, colIndLoc, ASub );
1659 }
1660 
1661 template<typename T>
1662 void
SetLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,const elem::Matrix<T> & ASub)1663 AbstractBlockDistMatrix<T>::SetLocalSubmatrix
1664 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1665   const elem::Matrix<T>& ASub )
1666 {
1667     DEBUG_ONLY(CallStackEntry cse("ABDM::SetLocalSubmatrix"))
1668     Matrix().SetSubmatrix( rowIndLoc, colIndLoc, ASub );
1669 }
1670 
1671 template<typename T>
1672 void
SetRealPartOfLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,const elem::Matrix<Base<T>> & ASub)1673 AbstractBlockDistMatrix<T>::SetRealPartOfLocalSubmatrix
1674 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1675   const elem::Matrix<Base<T>>& ASub )
1676 {
1677     DEBUG_ONLY(CallStackEntry cse("ABDM::SetRealPartOfLocalSubmatrix"))
1678     Matrix().SetRealPartOfSubmatrix( rowIndLoc, colIndLoc, ASub );
1679 }
1680 
1681 template<typename T>
1682 void
SetImagPartOfLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,const elem::Matrix<Base<T>> & ASub)1683 AbstractBlockDistMatrix<T>::SetImagPartOfLocalSubmatrix
1684 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1685   const elem::Matrix<Base<T>>& ASub )
1686 {
1687     DEBUG_ONLY(CallStackEntry cse("ABDM::SetImagPartOfLocalSubmatrix"))
1688     Matrix().SetImagPartOfSubmatrix( rowIndLoc, colIndLoc, ASub );
1689 }
1690 
1691 template<typename T>
1692 void
UpdateLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,T alpha,const elem::Matrix<T> & ASub)1693 AbstractBlockDistMatrix<T>::UpdateLocalSubmatrix
1694 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1695   T alpha, const elem::Matrix<T>& ASub )
1696 {
1697     DEBUG_ONLY(CallStackEntry cse("ABDM::UpdateLocalSubmatrix"))
1698     Matrix().UpdateSubmatrix( rowIndLoc, colIndLoc, alpha, ASub );
1699 }
1700 
1701 template<typename T>
1702 void
UpdateRealPartOfLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,Base<T> alpha,const elem::Matrix<Base<T>> & ASub)1703 AbstractBlockDistMatrix<T>::UpdateRealPartOfLocalSubmatrix
1704 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1705   Base<T> alpha, const elem::Matrix<Base<T>>& ASub )
1706 {
1707     DEBUG_ONLY(CallStackEntry cse("ABDM::UpdateRealPartOfLocalSubmatrix"))
1708     Matrix().UpdateRealPartOfSubmatrix( rowIndLoc, colIndLoc, alpha, ASub );
1709 }
1710 
1711 template<typename T>
1712 void
UpdateImagPartOfLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc,Base<T> alpha,const elem::Matrix<Base<T>> & ASub)1713 AbstractBlockDistMatrix<T>::UpdateImagPartOfLocalSubmatrix
1714 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc,
1715   Base<T> alpha, const elem::Matrix<Base<T>>& ASub )
1716 {
1717     DEBUG_ONLY(CallStackEntry cse("ABDM::UpdateImagPartOfLocalSubmatrix"))
1718     Matrix().UpdateImagPartOfSubmatrix( rowIndLoc, colIndLoc, alpha, ASub );
1719 }
1720 
1721 template<typename T>
1722 void
MakeLocalSubmatrixReal(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc)1723 AbstractBlockDistMatrix<T>::MakeLocalSubmatrixReal
1724 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc )
1725 {
1726     DEBUG_ONLY(CallStackEntry cse("ABDM::MakeLocalSubmatrixReal"))
1727     Matrix().MakeSubmatrixReal( rowIndLoc, colIndLoc );
1728 }
1729 
1730 template<typename T>
1731 void
ConjugateLocalSubmatrix(const std::vector<Int> & rowIndLoc,const std::vector<Int> & colIndLoc)1732 AbstractBlockDistMatrix<T>::ConjugateLocalSubmatrix
1733 ( const std::vector<Int>& rowIndLoc, const std::vector<Int>& colIndLoc )
1734 {
1735     DEBUG_ONLY(CallStackEntry cse("ABDM::ConjugateLocalSubmatrix"))
1736     Matrix().ConjugateSubmatrix( rowIndLoc, colIndLoc );
1737 }
1738 
1739 // Sum the local matrix over a particular communicator
1740 // ===================================================
1741 // NOTE: The matrix dimensions *must* be uniform over the communicator.
1742 
1743 template<typename T>
1744 void
SumOver(mpi::Comm comm)1745 AbstractBlockDistMatrix<T>::SumOver( mpi::Comm comm )
1746 {
1747     DEBUG_ONLY(CallStackEntry cse("ABDM::SumOver"))
1748     if( !Participating() )
1749         return;
1750 
1751     const Int localHeight = LocalHeight();
1752     const Int localWidth = LocalWidth();
1753     const Int localSize = mpi::Pad( localHeight*localWidth );
1754     T* sumBuf = auxMemory_.Require( localSize );
1755 
1756     // Pack
1757     T* buf = Buffer();
1758     const Int ldim = LDim();
1759     ELEM_PARALLEL_FOR
1760     for( Int jLoc=0; jLoc<localWidth; ++jLoc )
1761     {
1762         const T* thisCol = &buf[jLoc*ldim];
1763         T* sumCol = &sumBuf[jLoc*localHeight];
1764         MemCopy( sumCol, thisCol, localHeight );
1765     }
1766 
1767     // AllReduce sum
1768     mpi::AllReduce( sumBuf, localSize, comm );
1769 
1770     // Unpack
1771     ELEM_PARALLEL_FOR
1772     for( Int jLoc=0; jLoc<localWidth; ++jLoc )
1773     {
1774         const T* sumCol = &sumBuf[jLoc*localHeight];
1775         T* thisCol = &buf[jLoc*ldim];
1776         MemCopy( thisCol, sumCol, localHeight );
1777     }
1778     auxMemory_.Release();
1779 }
1780 
1781 // Assertions
1782 // ==========
1783 
1784 template<typename T>
1785 void
ComplainIfReal() const1786 AbstractBlockDistMatrix<T>::ComplainIfReal() const
1787 {
1788     if( !IsComplex<T>::val )
1789         LogicError("Called complex-only routine with real data");
1790 }
1791 
1792 template<typename T>
1793 void
AssertNotLocked() const1794 AbstractBlockDistMatrix<T>::AssertNotLocked() const
1795 {
1796     if( Locked() )
1797         LogicError("Assertion that matrix not be a locked view failed");
1798 }
1799 
1800 template<typename T>
1801 void
AssertNotStoringData() const1802 AbstractBlockDistMatrix<T>::AssertNotStoringData() const
1803 {
1804     if( matrix_.MemorySize() > 0 )
1805         LogicError("Assertion that matrix not be storing data failed");
1806 }
1807 
1808 template<typename T>
1809 void
AssertValidEntry(Int i,Int j) const1810 AbstractBlockDistMatrix<T>::AssertValidEntry( Int i, Int j ) const
1811 {
1812     if( i < 0 || i >= Height() || j < 0 || j >= Width() )
1813         LogicError
1814         ("Entry (",i,",",j,") is out of bounds of ",Height(),
1815          " x ",Width()," matrix");
1816 }
1817 
1818 template<typename T>
1819 void
AssertValidSubmatrix(Int i,Int j,Int height,Int width) const1820 AbstractBlockDistMatrix<T>::AssertValidSubmatrix
1821 ( Int i, Int j, Int height, Int width ) const
1822 {
1823     if( i < 0 || j < 0 )
1824         LogicError("Indices of submatrix were negative");
1825     if( height < 0 || width < 0 )
1826         LogicError("Dimensions of submatrix were negative");
1827     if( (i+height) > Height() || (j+width) > Width() )
1828         LogicError
1829         ("Submatrix is out of bounds: accessing up to (",i+height-1,
1830          ",",j+width-1,") of ",Height()," x ",Width()," matrix");
1831 }
1832 
1833 template<typename T>
1834 void
AssertSameGrid(const elem::Grid & grid) const1835 AbstractBlockDistMatrix<T>::AssertSameGrid( const elem::Grid& grid ) const
1836 {
1837     if( Grid() != grid )
1838         LogicError("Assertion that grids match failed");
1839 }
1840 
1841 template<typename T>
1842 void
AssertSameSize(Int height,Int width) const1843 AbstractBlockDistMatrix<T>::AssertSameSize( Int height, Int width ) const
1844 {
1845     if( Height() != height || Width() != width )
1846         LogicError("Assertion that matrices be the same size failed");
1847 }
1848 
1849 // Private section
1850 // ###############
1851 
1852 // Exchange metadata with another matrix
1853 // =====================================
1854 
1855 template<typename T>
1856 void
ShallowSwap(AbstractBlockDistMatrix<T> & A)1857 AbstractBlockDistMatrix<T>::ShallowSwap( AbstractBlockDistMatrix<T>& A )
1858 {
1859     matrix_.ShallowSwap( A.matrix_ );
1860     auxMemory_.ShallowSwap( A.auxMemory_ );
1861     std::swap( viewType_, A.viewType_ );
1862     std::swap( height_ , A.height_ );
1863     std::swap( width_, A.width_ );
1864     std::swap( colConstrained_, A.colConstrained_ );
1865     std::swap( rowConstrained_, A.rowConstrained_ );
1866     std::swap( rootConstrained_, A.rootConstrained_ );
1867     std::swap( blockHeight_, A.blockHeight_ );
1868     std::swap( blockWidth_, A.blockWidth_ );
1869     std::swap( colAlign_, A.colAlign_ );
1870     std::swap( rowAlign_, A.rowAlign_ );
1871     std::swap( colCut_, A.colCut_ );
1872     std::swap( rowCut_, A.rowCut_ );
1873     std::swap( colShift_, A.colShift_ );
1874     std::swap( rowShift_, A.rowShift_ );
1875     std::swap( root_, A.root_ );
1876     std::swap( grid_, A.grid_ );
1877 }
1878 
1879 // Modify the distribution metadata
1880 // ================================
1881 
1882 template<typename T>
1883 void
SetShifts()1884 AbstractBlockDistMatrix<T>::SetShifts()
1885 {
1886     if( Participating() )
1887     {
1888         colShift_ = Shift(ColRank(),colAlign_,ColStride());
1889         rowShift_ = Shift(RowRank(),rowAlign_,RowStride());
1890     }
1891     else
1892     {
1893         colShift_ = 0;
1894         rowShift_ = 0;
1895     }
1896 }
1897 
1898 template<typename T>
1899 void
SetColShift()1900 AbstractBlockDistMatrix<T>::SetColShift()
1901 {
1902     if( Participating() )
1903         colShift_ = Shift(ColRank(),colAlign_,ColStride());
1904     else
1905         colShift_ = 0;
1906 }
1907 
1908 template<typename T>
1909 void
SetRowShift()1910 AbstractBlockDistMatrix<T>::SetRowShift()
1911 {
1912     if( Participating() )
1913         rowShift_ = Shift(RowRank(),rowAlign_,RowStride());
1914     else
1915         rowShift_ = 0;
1916 }
1917 
1918 // Outside of class
1919 // ----------------
1920 
1921 template<typename T>
1922 void
AssertConforming1x2(const AbstractBlockDistMatrix<T> & AL,const AbstractBlockDistMatrix<T> & AR)1923 AssertConforming1x2
1924 ( const AbstractBlockDistMatrix<T>& AL, const AbstractBlockDistMatrix<T>& AR )
1925 {
1926     if( AL.Height() != AR.Height() )
1927         LogicError
1928         ("1x2 not conformant:\n",
1929          DimsString(AL,"Left"),"\n",DimsString(AR,"Right"));
1930     if( AL.ColAlign() != AR.ColAlign() || AL.ColCut() != AR.ColCut() )
1931         LogicError("1x2 is misaligned");
1932 }
1933 
1934 template<typename T>
1935 void
AssertConforming2x1(const AbstractBlockDistMatrix<T> & AT,const AbstractBlockDistMatrix<T> & AB)1936 AssertConforming2x1
1937 ( const AbstractBlockDistMatrix<T>& AT, const AbstractBlockDistMatrix<T>& AB )
1938 {
1939     if( AT.Width() != AB.Width() )
1940         LogicError
1941         ("2x1 is not conformant:\n",
1942          DimsString(AT,"Top"),"\n",DimsString(AB,"Bottom"));
1943     if( AT.RowAlign() != AB.RowAlign() || AT.RowCut() != AB.RowCut() )
1944         LogicError("2x1 is not aligned");
1945 }
1946 
1947 template<typename T>
1948 void
AssertConforming2x2(const AbstractBlockDistMatrix<T> & ATL,const AbstractBlockDistMatrix<T> & ATR,const AbstractBlockDistMatrix<T> & ABL,const AbstractBlockDistMatrix<T> & ABR)1949 AssertConforming2x2
1950 ( const AbstractBlockDistMatrix<T>& ATL, const AbstractBlockDistMatrix<T>& ATR,
1951   const AbstractBlockDistMatrix<T>& ABL, const AbstractBlockDistMatrix<T>& ABR )
1952 {
1953     if( ATL.Width() != ABL.Width() || ATR.Width() != ABR.Width() ||
1954         ATL.Height() != ATR.Height() || ABL.Height() != ABR.Height() )
1955         LogicError
1956         ("2x2 is not conformant:\n",
1957          DimsString(ATL,"TL"),"\n",DimsString(ATR,"TR"),"\n",
1958          DimsString(ABL,"BL"),"\n",DimsString(ABR,"BR"));
1959     if( ATL.ColAlign() != ATR.ColAlign() || ATL.ColCut() != ATR.ColCut() ||
1960         ABL.ColAlign() != ABR.ColAlign() || ABL.ColCut() != ABR.ColCut() ||
1961         ATL.RowAlign() != ABL.RowAlign() || ATL.RowCut() != ABL.RowCut() ||
1962         ATR.RowAlign() != ABR.RowAlign() || ATR.RowCut() != ABR.RowCut() )
1963         LogicError("2x2 set of matrices must aligned to combine");
1964 }
1965 
1966 // Instantiations for {Int,Real,Complex<Real>} for each Real in {float,double}
1967 // ###########################################################################
1968 
1969 #ifndef ELEM_RELEASE
1970  #define PROTO(T) \
1971   template class AbstractBlockDistMatrix<T>;\
1972   template void AssertConforming1x2\
1973   ( const AbstractBlockDistMatrix<T>& AL,  \
1974     const AbstractBlockDistMatrix<T>& AR );\
1975   template void AssertConforming2x1\
1976   ( const AbstractBlockDistMatrix<T>& AT,  \
1977     const AbstractBlockDistMatrix<T>& AB );\
1978   template void AssertConforming2x2\
1979   ( const AbstractBlockDistMatrix<T>& ATL, \
1980     const AbstractBlockDistMatrix<T>& ATR, \
1981     const AbstractBlockDistMatrix<T>& ABL, \
1982     const AbstractBlockDistMatrix<T>& ABR )
1983 #else
1984  #define PROTO(T) template class AbstractBlockDistMatrix<T>
1985 #endif
1986 
1987 #ifndef ELEM_DISABLE_COMPLEX
1988  #ifndef ELEM_DISABLE_FLOAT
1989   PROTO(Int);
1990   PROTO(float);
1991   PROTO(double);
1992   PROTO(Complex<float>);
1993   PROTO(Complex<double>);
1994  #else // ifndef ELEM_DISABLE_FLOAT
1995   PROTO(Int);
1996   PROTO(double);
1997   PROTO(Complex<double>);
1998  #endif // ifndef ELEM_DISABLE_FLOAT
1999 #else // ifndef ELEM_DISABLE_COMPLEX
2000  #ifndef ELEM_DISABLE_FLOAT
2001   PROTO(Int);
2002   PROTO(float);
2003   PROTO(double);
2004  #else // ifndef ELEM_DISABLE_FLOAT
2005   PROTO(Int);
2006   PROTO(double);
2007  #endif // ifndef ELEM_DISABLE_FLOAT
2008 #endif // ifndef ELEM_DISABLE_COMPLEX
2009 
2010 } // namespace elem
2011