|
STK++ 1.0
|
00001 /*--------------------------------------------------------------------*/ 00002 /* Copyright (C) 2004-2007 Serge Iovleff 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as 00006 published by the Free Software Foundation; either version 2 of the 00007 License, or (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public 00015 License along with this program; if not, write to the 00016 Free Software Foundation, Inc., 00017 59 Temple Place, 00018 Suite 330, 00019 Boston, MA 02111-1307 00020 USA 00021 00022 Contact : Serge.Iovleff@stkpp.org 00023 */ 00024 00025 /* 00026 * Project: stkpp::Algebra 00027 * Purpose: Define 1D Linear Algebra methods with Real Containers 00028 * Author: Serge Iovleff, serge.iovleff@stkpp.org 00029 * 00030 **/ 00031 00037 #ifndef STK_LINALGEBRA1D_H 00038 #define STK_LINALGEBRA1D_H 00039 00040 #include "../../STKernel/include/STK_Real.h" 00041 #include "../../STKernel/include/STK_Misc.h" 00042 00043 #include "../../Sdk/include/STK_ITContainer1D.h" 00044 00045 namespace STK 00046 { 00047 00057 template<class Container1D> 00058 Real sum( ITContainer1D<Real, Container1D> const& x) 00059 { 00060 // get dimensions 00061 const Integer first = x.first(), last = x.last(); 00062 // compute the sum 00063 Real sum = 0.0; 00064 for (Integer i=first; i<=last; i++) 00065 sum += x[i]; 00066 return (sum); 00067 } 00068 00079 template<class Container1D1, class Container1D2> 00080 Real weightedSum( ITContainer1D<Real, Container1D1> const& x 00081 , ITContainer1D<Real, Container1D2> const& w 00082 ) 00083 { 00084 #ifdef STK_DEBUG 00085 if (!x.range().isIn(w.range())) 00086 throw runtime_error("In weightedSum(x, w) " 00087 "x.range() not include in w.range()"); 00088 #endif 00089 // dimensions 00090 const Integer first = x.first(), last = x.last(); 00091 // compute the weighted sum 00092 Real sum = 0.0; 00093 for (Integer i=first; i<=last; i++) 00094 sum += w[i] * x[i]; 00095 return (sum); 00096 } 00097 00106 template<class Container1D> 00107 Real normInf( ITContainer1D<Real, Container1D> const& x) 00108 { 00109 // get dimensions 00110 const Integer first = x.first(), last = x.last(); 00111 // compute the maxmal value 00112 Real scale = 0.0; 00113 for (Integer i=first; i<=last; i++) 00114 scale = max(scale, abs(x[i])); 00115 return (scale); 00116 } 00117 00127 template<class Container1D1, class Container1D2> 00128 Real weightedNormInf( ITContainer1D<Real, Container1D1> const& x 00129 , ITContainer1D<Real, Container1D2> const& w 00130 ) 00131 { 00132 #ifdef STK_DEBUG 00133 if (!x.range().isIn(w.range())) 00134 throw runtime_error("In weightedNormInf(x, w) " 00135 "x.range() not include in w.range()"); 00136 #endif 00137 // get dimensions 00138 const Integer first = x.first(), last = x.last(); 00139 // compute weighted norm inf 00140 Real scale = 0.0; 00141 for (Integer i=first; i<=last; i++) 00142 scale = max(scale, abs(w[i]*x[i])); 00143 return (scale); 00144 } 00145 00154 template<class Container1D> 00155 Real normTwo( ITContainer1D<Real, Container1D> const& x) 00156 { 00157 // compute the maximal value of x 00158 Real scale =normInf(x), norm =0.0; 00159 if (scale) 00160 { 00161 // get dimensions 00162 const Integer first = x.first(), last = x.last(); 00163 // sum squared normalized values 00164 for (Integer i = first; i<=last; i++) 00165 { 00166 const Real aux = x[i]/scale; 00167 norm += aux * aux; 00168 } 00169 } 00170 // rescale sum 00171 return (Real(sqrt(double(norm)))*scale); 00172 } 00173 00183 template<class Container1D1, class Container1D2> 00184 Real weightedNormTwo( ITContainer1D<Real, Container1D1> const& x 00185 , ITContainer1D<Real, Container1D2> const& w 00186 ) 00187 { 00188 #ifdef STK_DEBUG 00189 if (!x.range().isIn(w.range())) 00190 throw runtime_error("In weightedNormTwo(x, w) " 00191 "x.range() not include in w.range()"); 00192 #endif 00193 // compute the maximal value of x 00194 Real scale = weightedNormInf(x, w), norm2 =0.0; 00195 if (scale) 00196 { 00197 // get dimensions 00198 const Integer first = x.first(), last = x.last(); 00199 // compute norm2 00200 for (Integer i = first; i<=last; i++) 00201 { 00202 const Real aux = (w[i]*x[i])/scale; 00203 norm2 += aux * aux; 00204 } 00205 } 00206 // rescale sum 00207 return (Real(sqrt(double(norm2)))*scale); 00208 } 00209 00218 template<class Container1D> 00219 Real normTwo2( ITContainer1D<Real, Container1D> const& x) 00220 { 00221 Real scale =normInf(x), norm =0.0; 00222 if (scale) 00223 { 00224 // get dimensions 00225 const Integer first = x.first(), last = x.last(); 00226 // sum squared normalized values 00227 for (Integer i = first; i<=last; i++) 00228 { 00229 Real aux = x[i]/scale; 00230 norm += aux * aux; 00231 } 00232 } 00233 // scale result 00234 return (norm*scale*scale); 00235 } 00236 00247 template<class Container1D1, class Container1D2> 00248 Real weightedNormTwo2( ITContainer1D<Real, Container1D1> const& x 00249 , ITContainer1D<Real, Container1D2> const& w 00250 ) 00251 { 00252 #ifdef STK_DEBUG 00253 if (!x.range().isIn(w.range())) 00254 throw runtime_error("In weightedNormTwo2(x, w) " 00255 "x.range() not include in w.range()"); 00256 #endif 00257 Real scale =weightedNormInf(x, w), norm =0.0; 00258 if (scale) 00259 { 00260 // get dimensions 00261 const Integer first = x.first(), last = x.last(); 00262 // compute norm2 00263 for (Integer i = first; i <= last; i++) 00264 { 00265 const Real aux = x[i]/scale; 00266 norm += w[i] * aux * aux; 00267 } 00268 } 00269 // scale result 00270 return (norm*scale*scale); 00271 } 00272 00285 template<class Container1D1, class Container1D2> 00286 Real dot( ITContainer1D<Real, Container1D1> const& x 00287 , ITContainer1D<Real, Container1D2> const& y 00288 ) 00289 { 00290 // compute the valid range 00291 const Integer first = max(x.first(), y.first()) , last = min(x.last(), y.last()); 00292 // compute the sum product 00293 Real sum=0.0; 00294 Integer i; 00295 for (i = first; i<last; i+=2) 00296 sum += x[i] * y[i] + x[i+1] * y[i+1]; 00297 // check if the number of element is odd 00298 if (i==last) sum+=x[last]*y[last]; 00299 return (sum); 00300 } 00301 00315 template<class Container1D1, class Container1D2, class Container1D3> 00316 Real weightedDot( ITContainer1D<Real, Container1D1> const& x 00317 , ITContainer1D<Real, Container1D2> const& y 00318 , ITContainer1D<Real, Container1D3> const& w 00319 ) 00320 { 00321 // compute the valid range 00322 const Integer first = max(x.first(), y.first()) , last = min(x.last(), y.last()); 00323 #ifdef STK_DEBUG 00324 if (!Range(first,last).isIn(w.range())) 00325 throw runtime_error("In weightedDot(x, w) " 00326 "Range(first,last) not include in w.range()"); 00327 #endif 00328 // compute the sum product 00329 Real sum=0.0; 00330 Integer i; 00331 for (i = first; i<last; i+=2) 00332 sum += w[i]*x[i] * y[i] + w[i+1]*x[i+1] * y[i+1]; 00333 // check if last is odd 00334 if (i == last) sum += w[last]*x[last]*y[last]; 00335 return (sum); 00336 } 00337 00351 template<class Container1D1, class Container1D2> 00352 Real dist( ITContainer1D<Real, Container1D1> const& x 00353 , ITContainer1D<Real, Container1D2> const& y 00354 ) 00355 { 00356 // compute the valid range 00357 const Integer first = max(x.first(), y.first()) , last = min(x.last(), y.last()); 00358 // compute the maximal difference 00359 Real scale = 0.; 00360 for (Integer i = first; i<=last; i++) 00361 scale = max(scale, abs(x[i] - y[i])); 00362 // Compute the norm 00363 Real norm2 = 0.; 00364 if (scale) 00365 { // comp the norm^2 00366 for (Integer i = first; i<=last; i++) 00367 { 00368 const Real aux = (x[i]-y[i])/scale; 00369 norm2 += aux * aux; 00370 } 00371 } 00372 // rescale sum 00373 return (Real(sqrt(double(norm2)))*scale); 00374 } 00375 00390 template<class Container1D1, class Container1D2, class Container1D3> 00391 Real weightedDist( ITContainer1D<Real, Container1D1> const& x 00392 , ITContainer1D<Real, Container1D2> const& y 00393 , ITContainer1D<Real, Container1D3> const& w 00394 ) 00395 { 00396 // compute the valid range 00397 const Integer first = max(x.first(), y.first()) , last = min(x.last(), y.last()); 00398 #ifdef STK_DEBUG 00399 if (!Range(first,last).isIn(w.range())) 00400 throw runtime_error("In weightedDist(x, w) " 00401 "Range(first,last) not include in w.range()"); 00402 #endif 00403 // compute the maximal difference 00404 Real scale = 0., norm2= 0.; 00405 for (Integer i = first; i<=last; i++) 00406 scale = max(scale, abs(w[i]*(x[i] - y[i]))); 00407 // Compute the norm 00408 if (scale) 00409 { // comp the norm^2 00410 for (Integer i = first; i<=last; i++) 00411 { 00412 const Real aux = (x[i]-y[i])/scale; 00413 norm2 += w[i]*aux * aux; 00414 } 00415 } 00416 // rescale sum 00417 return (Real(sqrt(double(norm2)))*scale); 00418 } 00419 00430 template<class Container1D1, class Container1D2> 00431 void add(ITContainer1D<Real, Container1D1> const& x, ITContainer1D<Real, Container1D2>& y) 00432 { 00433 // compute the valid range 00434 const Integer first = max(x.first(), y.first()) , last = min(x.last(), y.last()); 00435 for (Integer i = first; i<=last; i++) 00436 { 00437 y[i] += x[i]; 00438 } 00439 } 00440 00452 template<class Container1D1, class Container1D2, class Container1D3> 00453 void add( ITContainer1D<Real, Container1D1> const& x 00454 , ITContainer1D<Real, Container1D2> const& y 00455 , ITContainer1D<Real, Container1D3>& z 00456 ) 00457 { 00458 // compute the valid range 00459 const Integer first = max(x.first(), y.first()) , last = min(x.last(), y.last()); 00460 z.resize(Range(first, last)); 00461 for (Integer i = first; i<=last; i++) 00462 { 00463 z[i] = x[i] + y[i]; 00464 } 00465 } 00466 00477 template<class Container1D1, class Container1D2> 00478 void diff(ITContainer1D<Real, Container1D1> const& x, ITContainer1D<Real, Container1D2>& y) 00479 { 00480 // compute the valid range 00481 const Integer first = max(x.first(), y.first()) , last = min(x.last(), y.last()); 00482 for (Integer i = first; i<=last; i++) 00483 { 00484 y[i] -= x[i]; 00485 } 00486 } 00487 00499 template<class Container1D1, class Container1D2, class Container1D3> 00500 void diff( ITContainer1D<Real, Container1D1> const& x 00501 , ITContainer1D<Real, Container1D2> const& y 00502 , ITContainer1D<Real, Container1D3>& z 00503 ) 00504 { 00505 // compute the valid range 00506 const Integer first = max(x.first(), y.first()) , last = min(x.last(), y.last()); 00507 z.resize(Range(first, last)); 00508 for (Integer i = first; i<=last; i++) 00509 { 00510 z[i] = x[i] - y[i]; 00511 } 00512 } 00513 00514 00515 } // Namespace STK 00516 00517 #endif // STK_LINALGEBRA1D_H