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