Scythe-1.0.3
|
00001 /* 00002 * Scythe Statistical Library Copyright (C) 2000-2002 Andrew D. Martin 00003 * and Kevin M. Quinn; 2002-present Andrew D. Martin, Kevin M. Quinn, 00004 * and Daniel Pemstein. All Rights Reserved. 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify under the terms of the GNU General Public License as 00008 * published by Free Software Foundation; either version 2 of the 00009 * License, or (at your option) any later version. See the text files 00010 * COPYING and LICENSE, distributed with this source code, for further 00011 * information. 00012 * -------------------------------------------------------------------- 00013 * scythestat/stat.h 00014 * 00015 */ 00016 00028 #ifndef SCYTHE_STAT_H 00029 #define SCYTHE_STAT_H 00030 00031 #ifdef SCYTHE_COMPILE_DIRECT 00032 #include "matrix.h" 00033 #include "algorithm.h" 00034 #include "error.h" 00035 #else 00036 #include "scythestat/matrix.h" 00037 #include "scythestat/algorithm.h" 00038 #include "scythestat/error.h" 00039 #endif 00040 00041 #include <numeric> 00042 #include <set> 00043 00044 00045 namespace scythe { 00046 00047 namespace { 00048 typedef unsigned int uint; 00049 } 00050 00051 /* A macro for defining column versions of a function. That is, 00052 * when expanded, this macro produces general and default template 00053 * functions that compute function NAME on each column in a matrix and 00054 * return a row vector with the results. We use this to generate 00055 * column versions of every function in this header file. 00056 */ 00057 #define SCYTHE_STATMETH_COL(NAME) \ 00058 template <matrix_order RO, matrix_style RS, typename T, \ 00059 matrix_order PO, matrix_style PS> \ 00060 Matrix<T,RO,RS> \ 00061 NAME ## c (const Matrix<T,PO,PS>& A) \ 00062 { \ 00063 Matrix<T,RO,RS> res (1, A.cols(), false); \ 00064 \ 00065 for (uint j = 0; j < A.cols(); ++j) \ 00066 res[j] = NAME(A(_, j)); \ 00067 \ 00068 return res; \ 00069 } \ 00070 \ 00071 template <typename T, matrix_order O, matrix_style S> \ 00072 Matrix<T,O,Concrete> \ 00073 NAME ## c (const Matrix<T,O,S>& A) \ 00074 { \ 00075 return NAME ## c<O,Concrete>(A); \ 00076 } 00077 00078 00079 /* Calculate the sum of a Matrix */ 00080 00095 template <typename T, matrix_order PO, matrix_style PS> 00096 T 00097 sum (const Matrix<T,PO,PS> &A) 00098 { 00099 return (std::accumulate(A.begin_f(), A.end_f(), (T) 0)); 00100 } 00101 00102 /* Calculate the sum of each column in a Matrix */ 00103 00118 SCYTHE_STATMETH_COL(sum) 00119 00120 /* Calculate the product of a Matrix */ 00121 00122 00135 template <typename T, matrix_order PO, matrix_style PS> 00136 T 00137 prod (const Matrix<T,PO,PS> &A) 00138 { 00139 return std::accumulate(A.begin_f(), A.end_f(), (T) 1, 00140 std::multiplies<T> ()); 00141 } 00142 00143 /* Calculate the product of each column of a matrix */ 00144 00159 SCYTHE_STATMETH_COL(prod) 00160 00161 /* Calculate the mean of a Matrix */ 00162 00163 00178 template <typename T, matrix_order PO, matrix_style PS> 00179 T 00180 mean (const Matrix<T,PO,PS> &A) 00181 { 00182 return (std::accumulate(A.begin_f(), A.end_f(), (T) 0) / A.size()); 00183 } 00184 00185 /* Calculate the mean of each column of a Matrix */ 00186 00203 SCYTHE_STATMETH_COL(mean) 00204 00205 /* Calculate the median of a matrix. Uses a sort but I'll implement 00206 * the randomized alg when I figure out how to generalize it to 00207 * even-length lists 00208 */ 00209 00210 00223 template <typename T, matrix_order PO, matrix_style PS> 00224 T 00225 median (const Matrix<T,PO,PS> &A) 00226 { 00227 Matrix<T, PO, Concrete> temp(A); 00228 uint n = temp.size(); 00229 00230 sort(temp.begin(), temp.end()); 00231 if (n % 2 == 0) 00232 return ((temp[n / 2] + temp[n / 2 - 1]) / 2); 00233 else 00234 return temp[(uint) ::floor(n / 2)]; 00235 } 00236 00237 /* Calculate the median of each column of a matrix */ 00238 00253 SCYTHE_STATMETH_COL(median) 00254 00255 /* Calculate the mode of a matrix */ 00256 00257 00270 template <typename T, matrix_order PO, matrix_style PS> 00271 T 00272 mode (const Matrix<T,PO,PS> &A) 00273 { 00274 Matrix<T, PO, Concrete> temp(A); 00275 00276 sort(temp.begin(), temp.end()); 00277 00278 T last = temp[0]; 00279 uint cnt = 1; 00280 T cur_max = temp[0]; 00281 uint max_cnt = 1; 00282 00283 for (uint i = 1; i < temp.size(); ++i) { 00284 if (last == temp[i]) { 00285 ++cnt; 00286 } else { 00287 last = temp[i]; 00288 cnt = 1; 00289 } 00290 if (cnt > max_cnt) { 00291 max_cnt = cnt; 00292 cur_max = temp[i]; 00293 } 00294 } 00295 00296 return cur_max; 00297 } 00298 00313 SCYTHE_STATMETH_COL(mode) 00314 00315 /* Calculate the variance of a Matrix */ 00316 00317 /* A functor that encapsulates a single variance calculation step. 00318 * Also used by skew and kurtosis. */ 00319 namespace { 00320 template <typename T, typename T2> 00321 struct var_step : std::binary_function<T, T, T> 00322 { 00323 T constant_; 00324 T2 divisor_; 00325 T exponent_; 00326 var_step (T c, T2 d, T e) : constant_ (c), divisor_ (d), 00327 exponent_ (e) {} 00328 T operator() (T last, T x) const 00329 { 00330 return (last + std::pow(constant_ - x, exponent_) / divisor_); 00331 } 00332 }; 00333 } 00334 00347 template <typename T, matrix_order PO, matrix_style PS> 00348 T 00349 var (const Matrix<T,PO,PS> &A) 00350 { 00351 return var(A, mean(A)); 00352 } 00353 00354 /* Calculate the variances of each column of a Matrix. */ 00355 00369 SCYTHE_STATMETH_COL(var) 00370 00371 00385 template <typename T, matrix_order PO, matrix_style PS> 00386 T 00387 var (const Matrix<T,PO,PS> &A, T mu) 00388 { 00389 return std::accumulate(A.begin_f(), A.end_f(), (T) 0, 00390 var_step<T, uint> (mu, A.size() - 1, 2)); 00391 } 00392 00393 /* Calculate the standard deviation of a Matrix (not std cause of namespace std:: */ 00394 00408 template <typename T, matrix_order PO, matrix_style PS> 00409 T 00410 sd (const Matrix<T,PO,PS> &A) 00411 { 00412 return std::sqrt(var(A)); 00413 } 00414 00415 /* Calculate the standard deviation of each column of a Matrix */ 00428 SCYTHE_STATMETH_COL(sd) 00429 00430 00444 template <typename T, matrix_order PO, matrix_style PS> 00445 T 00446 sd (const Matrix<T,PO,PS> &A, T mu) 00447 { 00448 return std::sqrt(var(A, mu)); 00449 } 00450 00451 /* Calculate the skew of a Matrix */ 00452 00464 template <typename T, matrix_order PO, matrix_style PS> 00465 T 00466 skew (const Matrix<T,PO,PS> &A) 00467 { 00468 T mu = mean(A); 00469 T sde = sd(A, mu); 00470 return std::accumulate(A.begin_f(), A.end_f(), (T) 0, 00471 var_step<T, T> (mu, A.size() * std::pow(sde, 3), 3)); 00472 } 00473 00474 /* Calculate the skew of each column of a Matrix. */ 00475 00487 SCYTHE_STATMETH_COL(skew) 00488 00489 /* Calculate the kurtosis of a Matrix */ 00490 00491 00501 template <typename T, matrix_order PO, matrix_style PS> 00502 T 00503 kurtosis (const Matrix<T,PO,PS> &A) 00504 { 00505 T mu = mean(A); 00506 T sde = sd(A, mu); 00507 return (std::accumulate(A.begin_f(), A.end_f(), (T) 0, 00508 var_step<T, T> (mu, A.size() * std::pow(sde, 4), 4)) 00509 - 3); 00510 } 00511 00512 /* Calculate the kurtosis of each column of a Matrix. */ 00513 00525 SCYTHE_STATMETH_COL(kurtosis) 00526 00527 /* Calculates the maximum element in a Matrix */ 00540 template <typename T, matrix_order PO, matrix_style PS> 00541 T 00542 max (const Matrix<T,PO,PS> &A) 00543 { 00544 return *(max_element(A.begin_f(), A.end_f())); 00545 } 00546 00558 SCYTHE_STATMETH_COL(max) 00559 00560 /* Calculates the minimum element in a Matrix */ 00561 00562 00572 template <typename T, matrix_order PO, matrix_style PS> 00573 T 00574 min (const Matrix<T,PO,PS> &A) 00575 { 00576 return *(min_element(A.begin_f(), A.end_f())); 00577 } 00578 00590 SCYTHE_STATMETH_COL(min) 00591 00592 /* Find the index of the max element */ 00593 00605 template <typename T, matrix_order PO, matrix_style PS> 00606 unsigned int 00607 maxind (const Matrix<T,PO,PS> &A) 00608 { 00609 return (max_element(A.begin_f(), A.end_f())).get_index(); 00610 } 00611 00623 SCYTHE_STATMETH_COL(maxind) 00624 00625 /* Find the index of the min element */ 00626 00627 00638 template <typename T, matrix_order PO, matrix_style PS> 00639 unsigned int 00640 minind (const Matrix<T,PO,PS> &A) 00641 { 00642 return (min_element(A.begin_f(), A.end_f())).get_index(); 00643 } 00644 00655 SCYTHE_STATMETH_COL(minind) 00656 00657 } // end namespace scythe 00658 00659 00660 #endif /* SCYTHE_STAT_H */