|
Intrepid
|
00001 // @HEADER 00002 // ************************************************************************ 00003 // 00004 // Intrepid Package 00005 // Copyright (2007) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 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: Alejandro Mota (amota@sandia.gov) 00038 // 00039 // ************************************************************************ 00040 // @HEADER 00041 00042 #if !defined(Intrepid_MiniTensor_Vector_i_h) 00043 #define Intrepid_MiniTensor_Vector_i_h 00044 00045 namespace Intrepid 00046 { 00047 00048 // 00049 // Default constructor 00050 // 00051 template<typename T, Index N> 00052 inline 00053 Vector<T, N>::Vector() : 00054 TensorBase<T, Store>::TensorBase() 00055 { 00056 return; 00057 } 00058 00059 // 00060 // Constructor that initializes to NaNs 00061 // 00062 template<typename T, Index N> 00063 inline 00064 Vector<T, N>::Vector(Index const dimension) : 00065 TensorBase<T, Store>::TensorBase(dimension, ORDER) 00066 { 00067 return; 00068 } 00069 00073 template<typename T, Index N> 00074 inline 00075 Vector<T, N>::Vector(Index const dimension, ComponentValue const value) : 00076 TensorBase<T, Store>::TensorBase(dimension, ORDER, value) 00077 { 00078 return; 00079 } 00080 00081 template<typename T, Index N> 00082 inline 00083 Vector<T, N>::Vector(ComponentValue const value) : 00084 TensorBase<T, Store>::TensorBase(N, ORDER, value) 00085 { 00086 return; 00087 } 00088 00089 // 00090 // Create vector from array 00091 // 00092 template<typename T, Index N> 00093 inline 00094 Vector<T, N>::Vector(Index const dimension, T const * data_ptr) : 00095 TensorBase<T, Store>::TensorBase(dimension, ORDER, data_ptr) 00096 { 00097 return; 00098 } 00099 00100 template<typename T, Index N> 00101 inline 00102 Vector<T, N>::Vector(T const * data_ptr) : 00103 TensorBase<T, Store>::TensorBase(N, ORDER, data_ptr) 00104 { 00105 return; 00106 } 00107 00108 // 00109 // Copy constructor 00110 // 00111 template<typename T, Index N> 00112 inline 00113 Vector<T, N>::Vector(Vector<T, N> const & v) : 00114 TensorBase<T, Store>::TensorBase(v) 00115 { 00116 return; 00117 } 00118 00119 // 00120 // Create vector specifying components 00121 // 00122 template<typename T, Index N> 00123 inline 00124 Vector<T, N>::Vector(T const & s0, T const & s1) 00125 { 00126 Vector<T, N> & 00127 self = (*this); 00128 00129 self.set_dimension(2); 00130 00131 self[0] = s0; 00132 self[1] = s1; 00133 00134 return; 00135 } 00136 00137 // 00138 // Create vector specifying components 00139 // 00140 template<typename T, Index N> 00141 inline 00142 Vector<T, N>::Vector(T const & s0, T const & s1, T const & s2) 00143 { 00144 Vector<T, N> & 00145 self = (*this); 00146 00147 self.set_dimension(3); 00148 00149 self[0] = s0; 00150 self[1] = s1; 00151 self[2] = s2; 00152 00153 return; 00154 } 00155 00156 // 00157 // Simple destructor 00158 // 00159 template<typename T, Index N> 00160 inline 00161 Vector<T, N>::~Vector() 00162 { 00163 return; 00164 } 00165 00166 // 00167 // Get dimension 00168 // 00169 template<typename T, Index N> 00170 inline 00171 Index 00172 Vector<T, N>::get_dimension() const 00173 { 00174 return IS_DYNAMIC == true ? TensorBase<T, Store>::get_dimension() : N; 00175 } 00176 00177 // 00178 // Set dimension 00179 // 00180 template<typename T, Index N> 00181 inline 00182 void 00183 Vector<T, N>::set_dimension(Index const dimension) 00184 { 00185 if (IS_DYNAMIC == true) { 00186 TensorBase<T, Store>::set_dimension(dimension, ORDER); 00187 } 00188 else { 00189 assert(dimension == N); 00190 } 00191 00192 return; 00193 } 00194 00195 // 00196 // Indexing for constant vector 00197 // 00198 template<typename T, Index N> 00199 inline 00200 T const & 00201 Vector<T, N>::operator()(Index const i) const 00202 { 00203 return (*this)[i]; 00204 } 00205 00206 // 00207 // Vector indexing 00208 // 00209 template<typename T, Index N> 00210 inline 00211 T & 00212 Vector<T, N>::operator()(Index const i) 00213 { 00214 return (*this)[i]; 00215 } 00216 00217 // 00218 // Vector addition 00219 // 00220 template<typename S, typename T, Index N> 00221 inline 00222 Vector<typename Promote<S, T>::type, N> 00223 operator+(Vector<S, N> const & u, Vector<T, N> const & v) 00224 { 00225 Vector<typename Promote<S, T>::type, N> 00226 w(u.get_dimension()); 00227 00228 add(u, v, w); 00229 00230 return w; 00231 } 00232 00233 // 00234 // Vector subtraction 00235 // 00236 template<typename S, typename T, Index N> 00237 inline 00238 Vector<typename Promote<S, T>::type, N> 00239 operator-(Vector<S, N> const & u, Vector<T, N> const & v) 00240 { 00241 Vector<typename Promote<S, T>::type, N> 00242 w(u.get_dimension()); 00243 00244 subtract(u, v, w); 00245 00246 return w; 00247 } 00248 00249 // 00250 // Vector minus 00251 // 00252 template<typename T, Index N> 00253 inline 00254 Vector<T, N> 00255 operator-(Vector<T, N> const & u) 00256 { 00257 Vector<T, N> 00258 v(u.get_dimension()); 00259 00260 minus(u, v); 00261 00262 return v; 00263 } 00264 00265 // 00266 // Vector dot product 00267 // 00268 template<typename S, typename T, Index N> 00269 inline 00270 typename Promote<S, T>::type 00271 operator*(Vector<S, N> const & u, Vector<T, N> const & v) 00272 { 00273 return dot(u, v); 00274 } 00275 00276 // 00277 // Vector equality tested by components 00278 // 00279 template<typename T, Index N> 00280 inline 00281 bool 00282 operator==(Vector<T, N> const & u, Vector<T, N> const & v) 00283 { 00284 return equal(u, v); 00285 } 00286 00287 // 00288 // Vector inequality tested by components 00289 // 00290 template<typename T, Index N> 00291 inline 00292 bool 00293 operator!=(Vector<T, N> const & u, Vector<T, N> const & v) 00294 { 00295 return not_equal(u, v); 00296 } 00297 00298 // 00299 // Scalar vector product 00300 // 00301 template<typename S, typename T, Index N> 00302 inline 00303 typename lazy_disable_if< order_1234<S>, apply_vector< Promote<S,T>, N> >::type 00304 operator*(S const & s, Vector<T, N> const & u) 00305 { 00306 Vector<typename Promote<S, T>::type, N> 00307 v(u.get_dimension()); 00308 00309 scale(u, s, v); 00310 00311 return v; 00312 } 00313 00314 // 00315 // Vector scalar product 00316 // 00317 template<typename S, typename T, Index N> 00318 inline 00319 typename lazy_disable_if< order_1234<S>, apply_vector< Promote<S,T>, N> >::type 00320 operator*(Vector<T, N> const & u, S const & s) 00321 { 00322 Vector<typename Promote<S, T>::type, N> 00323 v(u.get_dimension()); 00324 00325 scale(u, s, v); 00326 00327 return v; 00328 } 00329 00330 // 00331 // Vector scalar division 00332 // 00333 template<typename S, typename T, Index N> 00334 inline 00335 Vector<typename Promote<S, T>::type, N> 00336 operator/(Vector<T, N> const & u, S const & s) 00337 { 00338 Vector<typename Promote<S, T>::type, N> 00339 v(u.get_dimension()); 00340 00341 divide(u, s, v); 00342 00343 return v; 00344 } 00345 00346 // 00347 // Scalar vector division 00348 // 00349 template<typename S, typename T, Index N> 00350 inline 00351 Vector<typename Promote<S, T>::type, N> 00352 operator/(S const & s, Vector<T, N> const & u) 00353 { 00354 Vector<typename Promote<S, T>::type, N> 00355 v(u.get_dimension()); 00356 00357 split(u, s, v); 00358 00359 return v; 00360 } 00361 00362 // 00363 // Vector dot product 00364 // 00365 template<typename S, typename T, Index N> 00366 inline 00367 typename Promote<S, T>::type 00368 dot(Vector<S, N> const & u, Vector<T, N> const & v) 00369 { 00370 Index const 00371 dimension = u.get_dimension(); 00372 00373 assert(v.get_dimension() == dimension); 00374 00375 typename Promote<S, T>::type 00376 s = 0.0; 00377 00378 switch (dimension) { 00379 00380 default: 00381 for (Index i = 0; i < dimension; ++i) { 00382 s += u(i) * v(i); 00383 } 00384 break; 00385 00386 case 3: 00387 s = u(0) * v(0) + u(1) * v(1) + u(2) * v(2); 00388 break; 00389 00390 case 2: 00391 s = u(0) * v(0) + u(1) * v(1); 00392 break; 00393 00394 } 00395 00396 return s; 00397 } 00398 00399 // 00400 // Cross product only valid for R^3. 00401 // 00402 template<typename S, typename T, Index N> 00403 inline 00404 Vector<typename Promote<S, T>::type, N> 00405 cross(Vector<S, N> const & u, Vector<T, N> const & v) 00406 { 00407 Index const 00408 dimension = u.get_dimension(); 00409 00410 assert(v.get_dimension() == dimension); 00411 00412 Vector<typename Promote<S, T>::type, N> 00413 w(dimension); 00414 00415 switch (dimension) { 00416 00417 case 3: 00418 w(0) = u(1) * v(2) - u(2) * v(1); 00419 w(1) = u(2) * v(0) - u(0) * v(2); 00420 w(2) = u(0) * v(1) - u(1) * v(0); 00421 break; 00422 00423 default: 00424 std::cerr << "ERROR: " << __PRETTY_FUNCTION__; 00425 std::cerr << std::endl; 00426 std::cerr << "Cross product undefined for R^" << dimension; 00427 std::cerr << std::endl; 00428 exit(1); 00429 break; 00430 00431 } 00432 00433 return w; 00434 } 00435 00436 // 00437 // R^N vector 2-norm 00438 // \return \f$ \sqrt{u \cdot u} \f$ 00439 // 00440 template<typename T, Index N> 00441 inline 00442 T 00443 norm(Vector<T, N> const & u) 00444 { 00445 Index const 00446 dimension = u.get_dimension(); 00447 00448 T 00449 s = 0.0; 00450 00451 switch (dimension) { 00452 00453 default: 00454 s = std::sqrt(dot(u, u)); 00455 break; 00456 00457 case 3: 00458 s = std::sqrt(u(0) * u(0) + u(1) * u(1) + u(2) * u(2)); 00459 break; 00460 00461 case 2: 00462 s = std::sqrt(u(0) * u(0) + u(1) * u(1)); 00463 break; 00464 00465 } 00466 00467 return s; 00468 } 00469 00470 // 00471 // R^N vector 2-norm square for fast distance calculations. 00472 // \return \f$ u \cdot u \f$ 00473 // 00474 template<typename T, Index N> 00475 inline 00476 T 00477 norm_square(Vector<T, N> const & u) 00478 { 00479 Index const 00480 dimension = u.get_dimension(); 00481 00482 T 00483 s = 0.0; 00484 00485 switch (dimension) { 00486 00487 default: 00488 s = dot(u, u); 00489 break; 00490 00491 case 3: 00492 s = u(0) * u(0) + u(1) * u(1) + u(2) * u(2); 00493 break; 00494 00495 case 2: 00496 s = u(0) * u(0) + u(1) * u(1); 00497 break; 00498 00499 } 00500 00501 return s; 00502 } 00503 00504 // 00505 // R^N vector 1-norm 00506 // \return \f$ \sum_i |u_i| \f$ 00507 // 00508 template<typename T, Index N> 00509 inline 00510 T 00511 norm_1(Vector<T, N> const & u) 00512 { 00513 Index const 00514 dimension = u.get_dimension(); 00515 00516 T 00517 s = 0.0; 00518 00519 switch (dimension) { 00520 00521 default: 00522 for (Index i = 0; i < dimension; ++i) { 00523 s += std::abs(u(i)); 00524 } 00525 break; 00526 00527 case 3: 00528 s = std::abs(u(0)) + std::abs(u(1)) + std::abs(u(2)); 00529 break; 00530 00531 case 2: 00532 s = std::abs(u(0)) + std::abs(u(1)); 00533 break; 00534 00535 } 00536 00537 return s; 00538 } 00539 00540 // 00541 // R^N vector infinity-norm 00542 // \return \f$ \max(|u_0|,...|u_i|,...|u_N|) \f$ 00543 // 00544 template<typename T, Index N> 00545 inline 00546 T 00547 norm_infinity(Vector<T, N> const & u) 00548 { 00549 Index const 00550 dimension = u.get_dimension(); 00551 00552 T 00553 s = 0.0; 00554 00555 switch (dimension) { 00556 00557 default: 00558 for (Index i = 0; i < dimension; ++i) { 00559 s = std::max(s, std::abs(u(i))); 00560 } 00561 break; 00562 00563 case 3: 00564 s = std::max(std::max(std::abs(u(0)), std::abs(u(1))), std::abs(u(2))); 00565 break; 00566 00567 case 2: 00568 s = std::max(std::abs(u(0)), std::abs(u(1))); 00569 break; 00570 00571 } 00572 00573 return s; 00574 } 00575 00576 // 00577 // \return u / |u|, fails for |u| = 0 00578 // 00579 template<typename T, Index N> 00580 inline 00581 Vector<T, N> 00582 unit(Vector<T, N> const & u) 00583 { 00584 return u / norm(u); 00585 } 00586 00587 // 00588 // Compute Householder vector 00589 // 00590 template<typename T, Index N> 00591 std::pair<Vector<T, N>, T> 00592 house(Vector<T, N> const & x) 00593 { 00594 Vector<T, N> 00595 v = x; 00596 00597 v[0] = 1.0; 00598 00599 Index const 00600 dimension = x.get_dimension(); 00601 00602 T 00603 sigma = 0.0; 00604 00605 for (Index i = 1; i < dimension; ++i) { 00606 sigma = v[i] * v[i]; 00607 } 00608 00609 T 00610 beta = 0.0; 00611 00612 if (sigma > 0.0) { 00613 T const 00614 mu = std::sqrt(x[0] * x[0] + sigma); 00615 v[0] = x[0] > 0.0 ? -sigma / (x[0] + mu) : x[0] - mu; 00616 beta = 2.0 * v[0] * v[0] / (sigma + v[0] * v[0]); 00617 v = v / v[0]; 00618 } 00619 00620 return std::make_pair(v, beta); 00621 } 00622 00623 } // namespace Intrepid 00624 00625 #endif // Intrepid_MiniTensor_Vector_i_h
1.7.6.1