/* Example programs from the book Scientific and Engineering Programming in C++: An Introduction with Advanced Techniques and Examples, Addison-Wesley, 1994. (c) COPYRIGHT INTERNATIONAL BUSINESS MACHINES CORPORATION 1994. ALL RIGHTS RESERVED. See README file for further details. */ #include "Array/Array2d.h" #include "Array/FortranArray1d.h" #include "Array/FortranArray2d.h" #include "SciEng/CopiedObjPtr.h" #include "SciEng/Boolean.h" #include "SciEng/utils.h" #include "SciEng/SciEngEnvironment.h" template class LapackRect; template class FactoredLapackRect; template class LapackSymPosDefPacked; template class FactoredLapackSymPosDefPacked; class InvalidFactoredMatrixUse {}; // Dummy exception class template class LapackRect : public virtual Array2d { public: LapackRect(Subscript nrows, Subscript ncols); FactoredLapackRect factor(); // ... // Array interface declarations ... virtual Subscript shape(Dimension d) const; virtual Dimension dim() const; virtual Array2d& operator=(const T&); virtual Array2d& operator=(const ConstArray2d&); virtual T& operator()(Subscript,Subscript); virtual const T& operator()(Subscript,Subscript) const; virtual Array2d::ProjectionT project(Subscript, Dimension); virtual Array2d::ConstProjectionT project(Subscript, Dimension) const; private: CopiedObjPtr< FortranArray2d > ap; // Lapack A Boolean valid; // Check validity -- throw exception if not valid void checkValidity() const; }; template LapackRect::LapackRect(Subscript nrows, Subscript ncols) : valid(Boolean::true), ap(new FortranArray2d(nrows, ncols)) { } template FactoredLapackRect LapackRect::factor() { checkValidity(); valid = Boolean::false; return FactoredLapackRect( ap.releaseControl() ); } template Subscript LapackRect::shape(Dimension d) const { checkValidity(); return ap->shape(d); } template Dimension LapackRect::dim() const { checkValidity(); return 2; } template void LapackRect::checkValidity() const { if (! valid) throw InvalidFactoredMatrixUse(); } template Array2d& LapackRect::operator=(const T& rhs) { return Array2d::operator=(rhs); } template Array2d& LapackRect::operator=(const ConstArray2d& rhs) { return Array2d::operator=(rhs); } template T& LapackRect::operator()(Subscript s0, Subscript s1) { checkValidity(); return ap->operator()(s0, s1); } template const T& LapackRect::operator()(Subscript s0, Subscript s1) const { checkValidity(); return ap->operator()(s0, s1); } template Array2d::ProjectionT LapackRect::project(Subscript s, Dimension d) { checkValidity(); return ap->project(s, d); } template Array2d::ConstProjectionT LapackRect::project(Subscript s, Dimension d) const { checkValidity(); // Following code is to get back a const projection even though the // pointer is not const. const FortranArray2d& fm = *ap; return fm.project(s, d); } template class FactoredLapackRect { public: LapackRect& solve(LapackRect&); private: friend FactoredLapackRect LapackRect::factor(); FactoredLapackRect(FortranArray2d* ap); CopiedObjPtr< FortranArray2d > fmat_p; // LAPACK "A" FortranArray1d pivots; // LAPACK "IPIV" }; template FactoredLapackRect::FactoredLapackRect(FortranArray2d* ap) : fmat_p(ap), pivots( min(ap->shape(0), ap->shape(1)) ) { // Call LAPACK factoring routine ... } template LapackRect& FactoredLapackRect::solve(LapackRect& b) { // Dummy routine return b; } int main() { LapackRect a(10,10); // ... fill a ... LapackRect b(10, 1); // ... fill b ... FactoredLapackRect factored_a = a.factor(); factored_a.solve(b); // b now contains the solution try { a(1, 2) = 3.1; // Exception thrown } catch( ... ) { return 0; // Exception caught --> success } return 1; // Exception not thrown --> bad news }