00001 /* @HEADER@ */ 00002 // ************************************************************************ 00003 // 00004 // Playa: Programmable Linear Algebra 00005 // Copyright 2012 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 Kevin Long (kevin.long@ttu.edu) 00038 // 00039 00040 /* @HEADER@ */ 00041 00042 #ifndef PLAYA_VECTORDECL_HPP 00043 #define PLAYA_VECTORDECL_HPP 00044 00045 #include "PlayaDefs.hpp" 00046 #include "PlayaHandle.hpp" 00047 #include "PlayaVectorBaseDecl.hpp" 00048 #include "PlayaVectorSpaceDecl.hpp" 00049 #include "PlayaVectorFunctorsDecl.hpp" 00050 #include "Teuchos_TimeMonitor.hpp" 00051 00052 namespace Playa 00053 { 00054 00055 template <class Scalar, int> class LCN; 00056 00057 /** 00058 * User-level vector class. 00059 * 00060 * <h2> Vector creation </h2> 00061 * 00062 * Ordinarily, you will never construct a Vector directly 00063 * from a derived type. Rather, the createMember() method of 00064 * VectorSpace is used to build a vector of the appropriate 00065 * type, for example, 00066 * \code 00067 * VectorType<double> vecType = new EpetraVectorType(); 00068 * int dimension = 100; 00069 * VectorSpace<double> space = vecType.createSpace(dimension); 00070 * Vector<double> x = space.createMember(); 00071 * Vector<double> y = space.createMember(); 00072 * \endcode 00073 * This hides from you all the ugly 00074 * details of creating a particular concrete type. 00075 * 00076 * You will frequently create an empty vector to be filled in later, 00077 * for example, 00078 * \code 00079 * Vector<double> y; 00080 * \endcode 00081 * Note that this vector isn't just empty, it's null. Not only does 00082 * it have no values assigned, it does not have a concrete type. An 00083 * call a method on a null vector will result in an error. What you 00084 * <it>can</it> do with a null vector is 00085 * <ul> 00086 * <li> assign another vector to it 00087 * \code 00088 * Vector<double> x = space.createVector(); 00089 * Vector<Scalar> y; 00090 * y = x.copy(); 00091 * \endcode 00092 * <li> assign the result of a vector operation to it 00093 * \code 00094 * Vector<Scalar> z = a*x + b*y; 00095 * \endcode 00096 * 00097 * <h2> Vector creation </h2> 00098 */ 00099 template <class Scalar> 00100 class Vector : public Playa::Handle<VectorBase<Scalar> > 00101 { 00102 public: 00103 /** \name Constructors, Destructors, and Assignment Operators */ 00104 //@{ 00105 HANDLE_CTORS(Vector<Scalar>, VectorBase<Scalar>); 00106 00107 /** \brief Construct a vector from an N-term LC */ 00108 template <int N> 00109 Vector<Scalar>(const LCN<Scalar, N>& x); 00110 00111 00112 /** \brief Assign a one-term LC to this vector */ 00113 Vector<Scalar>& operator=(const LCN<Scalar, 1>& x); 00114 00115 /** \brief Assign a two-term LC to this vector */ 00116 Vector<Scalar>& operator=(const LCN<Scalar, 2>& x); 00117 00118 /** \brief Assign a three-term LC to this vector */ 00119 Vector<Scalar>& operator=(const LCN<Scalar, 3>& x); 00120 00121 /** \brief Assign an N-term LC to this vector */ 00122 template <int N> 00123 Vector<Scalar>& operator=(const LCN<Scalar, N>& x); 00124 00125 //@} 00126 00127 /** \name Operators with assignment */ 00128 //@{ 00129 /** Add a vector into this vector */ 00130 Vector<Scalar>& operator+=(const Vector<Scalar>& other); 00131 00132 /** Add a one-term LC into this vector */ 00133 Vector<Scalar>& operator+=(const LCN<Scalar, 1>& x); 00134 00135 /** Add a two-term LC into this vector */ 00136 Vector<Scalar>& operator+=(const LCN<Scalar, 2>& x); 00137 00138 /** Add an N-term LC into this vector */ 00139 template <int N> 00140 Vector<Scalar>& operator+=(const LCN<Scalar, N>& x); 00141 00142 /** Subtract a vector from this vector */ 00143 Vector<Scalar>& operator-=(const Vector<Scalar>& other); 00144 00145 /** Subtract a one-term LC from this vector */ 00146 Vector<Scalar>& operator-=(const LCN<Scalar, 1>& x); 00147 00148 /** Subtract a two-term LC from this vector */ 00149 Vector<Scalar>& operator-=(const LCN<Scalar, 2>& x); 00150 00151 /** Subtract an N-term LC from this vector */ 00152 template <int N> 00153 Vector<Scalar>& operator-=(const LCN<Scalar, N>& x); 00154 00155 /** Scale by a constant */ 00156 Vector<Scalar>& operator*=(const Scalar& a); 00157 00158 /** Divide by a constant */ 00159 Vector<Scalar>& operator/=(const Scalar& a); 00160 //@} 00161 00162 /** \name Structural information */ 00163 //@{ 00164 /** \brief My space */ 00165 VectorSpace<Scalar> space() const 00166 {return this->ptr()->space();} 00167 00168 /** \brief My communicator */ 00169 const MPIComm& comm() const 00170 {return this->space().comm();} 00171 00172 /** \brief My dimension */ 00173 int dim() const 00174 { 00175 return this->ptr()->space()->dim(); 00176 } 00177 //@} 00178 00179 00180 /** \name Block operations */ 00181 //@{ 00182 /** \brief get number of blocks */ 00183 int numBlocks() const ; 00184 00185 /** \brief set the i-th block */ 00186 void setBlock(int i, const Vector<Scalar>& v); 00187 00188 /** \brief get the i-th block */ 00189 const Vector<Scalar>& getBlock(int i) const; 00190 00191 /** \brief get the i-th block */ 00192 Vector<Scalar> getNonConstBlock(int i) ; 00193 00194 /** \brief get the i-th block */ 00195 const Vector<Scalar>& getBlock(const BlockIterator<Scalar>& b) const; 00196 00197 /** \brief get the i-th block */ 00198 Vector<Scalar> getNonConstBlock(const BlockIterator<Scalar>& b); 00199 //@} 00200 00201 00202 00203 /** \name Sequential data accessors */ 00204 //@{ 00205 /** \brief Get the next chunk of values for read-only access */ 00206 ConstDataChunk<Scalar> nextConstChunk() const ; 00207 00208 /** \brief Get the next chunk of values for read-write access */ 00209 NonConstDataChunk<Scalar> nextChunk() ; 00210 00211 /** \brief Tell whether there are more chunks remaining to be accessed */ 00212 bool hasMoreChunks() const ; 00213 00214 /** \brief Reset the data stream back to a state where all chunks are 00215 * considered unread. */ 00216 void rewind() const ; 00217 //@} 00218 00219 /** \name Random access to local elements */ 00220 //@{ 00221 /** \brief const bracket operator for read-only random access to 00222 * local elements as specified by 00223 * a flat index that runs from 0 to space().numLocalElements(). 00224 * If the vector does not consist of a single contiguous data chunk, 00225 * this might be slow (worst case would be O(N), if every element 00226 * is stored in its own chunk of length 1). 00227 */ 00228 const Scalar& operator[](int localIndex) const ; 00229 00230 /** \brief non-const bracket operator for read-write random access to 00231 * local elements as specified by 00232 * a flat index that runs from 0 to space().numLocalElements(). 00233 * If the vector does not consist of a single contiguous data chunk, 00234 * this might be slow (worst case would be O(N), if every element 00235 * is stored in its own chunk of length 1). 00236 */ 00237 Scalar& operator[](int localIndex); 00238 00239 /** \brief parentheses operator for read-only random access to 00240 * local elements as specified by 00241 * a block iterator and a flat index indicating the 00242 * element's location within that block. 00243 */ 00244 const Scalar& operator()(const BlockIterator<Scalar>& b, 00245 int localIndexWithinBlock) const ; 00246 00247 /** \brief parentheses operator for read-write random access to 00248 * local elements as specified by 00249 * a block iterator and a flat index indicating the 00250 * element's location within that block. 00251 */ 00252 Scalar& operator()(const BlockIterator<Scalar>& b, 00253 int localIndexWithinBlock) ; 00254 //@} 00255 00256 /** \name Diagnostic output */ 00257 //@{ 00258 /** \brief Return a short string description of the vector */ 00259 std::string description() const ; 00260 00261 /** \brief Print the vector in some detail */ 00262 void print(std::ostream& os) const ; 00263 //@} 00264 00265 00266 /** \name Math operations */ 00267 //@{ 00268 /** \brief Multiply this vector by a constant scalar factor 00269 * \code 00270 * this = alpha * this; 00271 * \endcode 00272 */ 00273 Vector<Scalar>& scale(const Scalar& alpha); 00274 00275 /** 00276 * \brief Add a scaled vector to this vector times a constant: 00277 * \f$ this=\alpha x + \gamma \,this. \f$ 00278 */ 00279 Vector<Scalar>& update(const Scalar& alpha, const Vector<Scalar>& x, 00280 const Scalar& gamma=1.0); 00281 /** 00282 * \brief Add two scaled vectors to this vector times a constant: 00283 * \f$ this=\alpha x + \beta y + \gamma \, this. \f$ 00284 */ 00285 Vector<Scalar>& update(const Scalar& alpha, const Vector<Scalar>& x, 00286 const Scalar& beta, const Vector<Scalar>& y, 00287 const Scalar& gamma); 00288 /** 00289 * \brief Add three scaled vectors to this vector times a constant: 00290 * \f$ this=\alpha x + \beta y + \gamma x + \delta \, this. \f$ 00291 */ 00292 Vector<Scalar>& update(const Scalar& alpha, const Vector<Scalar>& x, 00293 const Scalar& beta, const Vector<Scalar>& y, 00294 const Scalar& gamma, const Vector<Scalar>& z, 00295 const Scalar& delta); 00296 00297 /** 00298 * \brief Copy the values of another vector into this vector 00299 * \code 00300 * this = x 00301 * \endcode 00302 */ 00303 Vector<Scalar>& acceptCopyOf(const Vector<Scalar>& x); 00304 00305 /** 00306 * \brief Create a new vector that is a copy of this vector 00307 */ 00308 Vector<Scalar> copy() const ; 00309 00310 /** 00311 * \brief In-place element-by-element product (Matlab dot-star operator) 00312 */ 00313 Vector<Scalar>& selfDotStar(const Vector<Scalar>& other) ; 00314 00315 /** 00316 * \brief In-place element-by-element division (Matlab dot-slash operator) 00317 */ 00318 Vector<Scalar>& selfDotSlash(const Vector<Scalar>& other) ; 00319 00320 /** 00321 * \brief Element-by-element product (Matlab dot-star operator) 00322 */ 00323 Vector<Scalar> dotStar(const Vector<Scalar>& other) const ; 00324 00325 /** 00326 * \brief Element-by-element division (Matlab dot-slash operator) 00327 */ 00328 Vector<Scalar> dotSlash(const Vector<Scalar>& other) const ; 00329 00330 /** 00331 * \brief Return element-by-element reciprocal as a new vector 00332 */ 00333 Vector<Scalar> reciprocal() const ; 00334 00335 00336 /** 00337 * \brief Return element-by-element absolute value as a new vector 00338 */ 00339 Vector<Scalar> abs() const ; 00340 00341 /** 00342 * \brief Overwrite self with element-by-element reciprocal 00343 */ 00344 Vector<Scalar>& selfReciprocal() ; 00345 00346 /** 00347 * \brief Overwrite self with element-by-element absolute value 00348 */ 00349 Vector<Scalar>& selfAbs() ; 00350 00351 /** 00352 * \brief Overwrite self with random values 00353 */ 00354 Vector<Scalar>& randomize() ; 00355 00356 /** 00357 * \brief Set all elements to a constant value 00358 */ 00359 void setToConstant(const Scalar& alpha) ; 00360 00361 00362 /** 00363 * \brief Take dot product with another vector 00364 */ 00365 Scalar dot(const Vector<Scalar>& other) const ; 00366 00367 /** 00368 * \brief Overloaded operator for dot product 00369 */ 00370 Scalar operator*(const Vector<Scalar>& other) const ; 00371 00372 /** 00373 * \brief Compute the 1-norm of this vector 00374 */ 00375 Scalar norm1() const ; 00376 00377 /** 00378 * \brief Compute the 2-norm of this vector 00379 */ 00380 Scalar norm2() const ; 00381 00382 /** 00383 * \brief Compute the weighted 2-norm of this vector 00384 */ 00385 Scalar norm2(const Vector<Scalar>& weights) const ; 00386 00387 00388 /** 00389 * \brief Compute the infinity-norm of this vector 00390 */ 00391 Scalar normInf() const ; 00392 00393 /** 00394 * \brief Set all elements to zero 00395 */ 00396 void zero(); 00397 00398 00399 /** \brief Return the max element */ 00400 Scalar max() const; 00401 00402 /** \brief Return the min element */ 00403 Scalar min()const; 00404 00405 00406 //@} 00407 00408 00409 00410 00411 /** \brief Get a stopwtach for timing vector operations */ 00412 static RCP<Time>& opTimer() 00413 { 00414 static RCP<Time> rtn 00415 = TimeMonitor::getNewTimer("Low-level vector operations"); 00416 return rtn; 00417 } 00418 00419 /** \name Functor application */ 00420 //@{ 00421 00422 /** \brief Apply a unary functor, overwriting this vector with the results */ 00423 template <class UF> 00424 Vector<Scalar>& applyUnaryFunctor(const UF& functor); 00425 00426 /** \brief Apply a unary functor to another vector, writing the results 00427 into this vector. The other vector is unchanged. */ 00428 template <class UF> 00429 Vector<Scalar>& acceptUnaryFunctor(const UF& functor, 00430 const Vector<Scalar>& other); 00431 00432 /** \brief Apply a binary functor to this vector and another vector, 00433 writing the results 00434 into this vector. The other vector is unchanged. */ 00435 template <class VF> 00436 Vector<Scalar>& applyBinaryFunctor(const VF& functor, 00437 const Vector<Scalar>& other); 00438 00439 /** \brief Apply a ternary functor to this vector and two other vectors, 00440 writing the results 00441 into this vector. The other vectors are unchanged. */ 00442 template <class VF> 00443 Vector<Scalar>& applyTernaryFunctor(const VF& functor, 00444 const Vector<Scalar>& x, const Vector<Scalar>& y); 00445 00446 /** \brief Apply a unary reduction functor */ 00447 template <class RF> 00448 typename PlayaFunctors::VectorFunctorTraits<Scalar, RF>::ReturnType 00449 applyUnaryReductionFunctor( 00450 const RF& functor) 00451 const ; 00452 00453 /** \brief Apply a binary reduction functor */ 00454 template <class RF> 00455 typename PlayaFunctors::VectorFunctorTraits<Scalar, RF>::ReturnType 00456 applyBinaryReductionFunctor(const RF& functor, const Vector<Scalar>& other) 00457 const ; 00458 00459 00460 00461 //@} 00462 00463 protected: 00464 00465 /** get a subblock as specified by a deque of indices */ 00466 const Vector<Scalar>& getBlock(const std::deque<int>& iter) const ; 00467 00468 /** get a non-const subblock as specified by a deque of indices */ 00469 Vector<Scalar> getNonConstBlock(const std::deque<int>& iter) ; 00470 00471 00472 private: 00473 00474 }; 00475 00476 00477 template <class Scalar> class LoadableVector; 00478 /** \relates Vector \brief Dynamic cast a Vector's underlying pointer to 00479 a LoadableVector. */ 00480 template <class Scalar> 00481 LoadableVector<Scalar>* loadable(Vector<Scalar> vec) ; 00482 00483 00484 /** \relates Vector \brief Return a pointer to the beginning of the vector's 00485 single data chunk. If the underlying VectorBase is not a SingleChunkVector 00486 an exception will be thrown. */ 00487 template <class Scalar> 00488 Scalar* dataPtr(Vector<Scalar> vec) ; 00489 00490 /** \relates Vector \brief Return a pointer to the beginning of the vector's 00491 single data chunk. If the underlying VectorBase is not a SingleChunkVector 00492 an exception will be thrown. */ 00493 template <class Scalar> 00494 const Scalar* dataPtr(const Vector<Scalar>& vec) ; 00495 00496 00497 } 00498 00499 template <class Scalar> inline 00500 std::ostream& operator<<(std::ostream& os, const Playa::Vector<Scalar>& x) 00501 { 00502 x.print(os); 00503 return os; 00504 } 00505 00506 00507 00508 00509 #endif