|
Tpetra Matrix/Vector Services Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Tpetra: Templated Linear Algebra Services Package 00005 // Copyright (2008) Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // ************************************************************************ 00040 // @HEADER 00041 00042 #ifndef __MatrixMarket_util_hpp 00043 #define __MatrixMarket_util_hpp 00044 00045 #include <Teuchos_as.hpp> 00046 #include <string> 00047 00048 namespace Tpetra { 00049 namespace MatrixMarket { 00050 00051 namespace details { 00052 00076 template<class Scalar> 00077 class SetScientific { 00078 public: 00080 typedef Scalar scalar_type; 00081 00086 SetScientific (std::ostream& out) : 00087 out_ (out), originalFlags_ (out.flags()) 00088 { 00089 typedef Teuchos::ScalarTraits<scalar_type> STS; 00090 typedef typename STS::magnitudeType magnitude_type; 00091 typedef Teuchos::ScalarTraits<magnitude_type> STM; 00092 00093 // Print floating-point values in scientific notation. 00094 out << std::scientific; 00095 00096 // We're writing decimal digits, so compute the number of 00097 // digits we need to get reasonable accuracy when reading 00098 // values back in. 00099 // 00100 // There is actually an algorithm, due to Guy Steele (yes, 00101 // Java's Guy Steele) et al., for idempotent printing of 00102 // finite-length floating-point values. We should actually 00103 // implement that algorithm, but I don't have time for that 00104 // now. Currently, I just print no more than (one decimal 00105 // digit more than (the number of decimal digits justified 00106 // by the precision of magnitude_type)). 00107 // 00108 // We need to use STM's log10() rather than (say) std::log10 00109 // here, because STM::base() returns a magnitude_type, not 00110 // one of C++'s standard integer types. 00111 const magnitude_type numDecDigits = STM::t() * STM::log10 (STM::base()); 00112 00113 // Round and add one. The cast to int should not overflow 00114 // unless STM::t() is _extremely_ large, so we don't need to 00115 // check for that case here. 00116 const magnitude_type one = STM::one(); 00117 const magnitude_type two = one + one; 00118 // Cast from magnitude_type to int, since std::ostream's 00119 // precision() method expects an int input. 00120 const int prec = 1 + Teuchos::as<int> ((two*numDecDigits + one) / two); 00121 00122 // Set the number of (decimal) digits after the decimal 00123 // point to print. 00124 out.precision (prec); 00125 } 00126 00132 ~SetScientific () { 00133 out_.flags (originalFlags_); 00134 } 00135 00136 private: 00138 std::ostream& out_; 00139 00141 std::ios_base::fmtflags originalFlags_; 00142 }; 00143 00144 // We define a class because template functions can't (in the 00145 // current C++ standard) have default template parameters. 00146 template<class Scalar, bool isComplex=Teuchos::ScalarTraits<Scalar>::isComplex> 00147 class ScalarAssigner { 00148 public: 00149 static void 00150 assign (Scalar& val, 00151 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType& real, 00152 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType& imag); 00153 }; 00154 00155 template<class RealType> 00156 class ScalarAssigner<RealType, false> { 00157 public: 00158 static void 00159 assign (RealType& val, 00160 const typename Teuchos::ScalarTraits<RealType>::magnitudeType& real, 00161 const typename Teuchos::ScalarTraits<RealType>::magnitudeType& imag) 00162 { 00163 // imag had better be zero. We're ignoring it regardless. 00164 (void) imag; 00165 val = real; 00166 } 00167 }; 00168 00169 #ifdef HAVE_TEUCHOS_COMPLEX 00170 template<class MagType> 00171 class ScalarAssigner<std::complex<MagType>, true> { 00172 public: 00173 static void 00174 assign (std::complex<MagType>& val, 00175 const typename Teuchos::ScalarTraits<std::complex<MagType> >::magnitudeType& real, 00176 const typename Teuchos::ScalarTraits<std::complex<MagType> >::magnitudeType& imag) 00177 { 00178 val = std::complex<MagType> (real, imag); 00179 } 00180 }; 00181 #endif // HAVE_TEUCHOS_COMPLEX 00182 00183 // \fn assignScalar 00184 // \brief val = S(real, imag). 00185 // 00186 // We have to template it because we don't know that S is a 00187 // complex type; if we write S(real,imag), the compiler will 00188 // complain if S is a real type. 00189 template<class Scalar> 00190 void 00191 assignScalar (Scalar& val, 00192 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType& real, 00193 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType& imag) 00194 { 00195 ScalarAssigner<Scalar>::assign (val, real, imag); 00196 } 00197 00198 } // namespace details 00199 00200 00201 namespace { 00202 bool isSkew (const std::string& symmType) { 00203 return symmType.size() >= 4 && symmType.substr(0,4) == "skew"; 00204 } 00205 00206 bool isConj (const std::string& symmType) { 00207 return std::string::npos != symmType.find ("hermitian"); 00208 } 00209 00210 bool needsSymmetrization (const std::string& symmType) { 00211 return symmType != "general"; 00212 } 00213 } // namespace (anonymous) 00214 00233 template<class AdderType> 00234 class SymmetrizingAdder { 00235 public: 00237 typedef typename AdderType::index_type index_type; 00239 typedef typename AdderType::value_type value_type; 00240 00247 SymmetrizingAdder (const Teuchos::RCP<AdderType>& adder, 00248 const std::string& symmType) : 00249 adder_ (adder), 00250 symmetrize_ (needsSymmetrization (symmType)), 00251 conjugate_ (isConj (symmType)), 00252 skew_ (isSkew (symmType)) 00253 {} 00254 00256 void 00257 operator() (const index_type i, 00258 const index_type j, 00259 const value_type& Aij) 00260 { 00261 AdderType& theAdder = *adder_; 00262 00263 theAdder (i, j, Aij); 00264 if (symmetrize_ && i != j) { 00265 typedef Teuchos::ScalarTraits<value_type> STS; 00266 const value_type Aji = skew_ ? 00267 -(conjugate_ ? STS::conjugate(Aij) : Aij) : 00268 (conjugate_ ? STS::conjugate(Aij) : Aij); 00269 theAdder (j, i, Aji); 00270 } 00271 } 00272 00276 Teuchos::RCP<AdderType> getAdder() const { 00277 return adder_; 00278 } 00279 00280 private: 00282 Teuchos::RCP<AdderType> adder_; 00284 bool symmetrize_; 00286 bool conjugate_; 00288 bool skew_; 00289 }; 00290 00291 } // namespace MatrixMarket 00292 } // namespace Tpetra 00293 00294 #endif // __MatrixMarket_util_hpp
1.7.4