/* * Toolbox.hh * * Created on: Jun 23, 2018 * Author: benjamin */ #ifndef TOOLBOX_HH_ #define TOOLBOX_HH_ #include "ParamData.hh" namespace AMDA { namespace Parameters { namespace StatisticFunctions { template Type min(Type a, Type b) { if (!std::isfinite(a) || isNAN(a)) return b; if (!std::isfinite(b) || isNAN(b)) return a; return std::min(a, b); } template std::vector min(std::vector a, std::vector b) { std::vector res = a; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Vectors don't have the same size")); } for (unsigned int i = 0; i < a.size(); ++i) { res[i] = StatisticFunctions::min(a[i], b[i]); } return res; } template Tab2DData min(Tab2DData a, Tab2DData b) { Tab2DData res(a); if (a.getDim1Size() != b.getDim1Size() || a.getDim2Size() != b.getDim2Size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Tab2DData don't have the same dimensions")); } for (int i = 0; i < a.getDim1Size(); ++i) { for (int j = 0; j < a.getDim2Size(); ++j) { res[i][j] = StatisticFunctions::min(a[i][j], b[i][j]); } } return res; } template Type max(Type a, Type b) { if (!std::isfinite(a) || isNAN(a)) return b; if (!std::isfinite(b) || isNAN(b)) return a; return std::max(a, b); } template std::vector max(std::vector a, std::vector b) { std::vector res = a; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Vectors don't have the same size")); } for (unsigned int i = 0; i < a.size(); ++i) { res[i] = StatisticFunctions::max(a[i], b[i]); } return res; } template Tab2DData max(Tab2DData a, Tab2DData b) { Tab2DData res(a); if (a.getDim1Size() != b.getDim1Size() || a.getDim2Size() != b.getDim2Size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Tab2DData don't have the same dimensions")); } for (int i = 0; i < a.getDim1Size(); ++i) { for (int j = 0; j < a.getDim2Size(); ++j) { res[i][j] = StatisticFunctions::max(a[i][j], b[i][j]); } } return res; } template Type pow(Type a, double exp) { return std::pow(a, exp); } template std::vector pow(std::vector a, double exp) { std::vector res = a; for (unsigned int i = 0; i < a.size(); ++i) { res[i] = StatisticFunctions::pow(a[i], exp); } return res; } template Tab2DData pow(Tab2DData a, double exp) { Tab2DData res = a; for (int i = 0; i < a.getDim1Size(); ++i) { for (int j = 0; j < a.getDim2Size(); ++j) { res[i][j] = StatisticFunctions::pow(a[i][j], exp); } } return res; } template Type square(Type a) { return StatisticFunctions::pow(a, 2); } template std::vector square(std::vector a) { return StatisticFunctions::pow(a, 2); } template Tab2DData square(Tab2DData a) { return StatisticFunctions::pow(a, 2); } template Type root_square(Type a) { if (isNAN(a) || a < 0) { Type res; res << NotANumber(); return res; } return std::sqrt(a); } template std::vector root_square(std::vector a) { std::vector res = a; for (unsigned int i = 0; i < a.size(); ++i) { res[i] = StatisticFunctions::root_square(a[i]); } return res; } template Tab2DData root_square(Tab2DData a) { Tab2DData res = a; for (int i = 0; i < a.getDim1Size(); ++i) { for (int j = 0; j < a.getDim2Size(); ++j) { res[i][j] = StatisticFunctions::root_square(a[i][j]); } } return res; } template Type div(Type a, Type b) { if (isNAN(a) || isNAN(b) || (b == 0)) { Type res; res << NotANumber(); return res; } return a / b; } template std::vector div(std::vector a, std::vector b) { std::vector res = a; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Vectors don't have the same size")); } for (unsigned int i = 0; i < a.size(); ++i) { res[i] = StatisticFunctions::div(a[i], b[i]); } return res; } template Tab2DData div(Tab2DData a, Tab2DData b) { Tab2DData res(a); if (a.getDim1Size() != b.getDim1Size() || a.getDim2Size() != b.getDim2Size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Tab2DData don't have the same dimensions")); } for (int i = 0; i < a.getDim1Size(); ++i) { for (int j = 0; j < a.getDim2Size(); ++j) { res[i][j] = StatisticFunctions::div(a[i][j], b[i][j]); } } return res; } template std::pair getMean(std::list> &list) { std::pair result(0, 0); std::pair counter(0, 0); for (auto elt : list) { if (!isNAN(elt.first)) { result.first += elt.first; counter.first += 1; } if (!isNAN(elt.second)) { result.second += elt.second; counter.second += 1; } } if (counter.first != 0) result.first /= counter.first; if (counter.second != 0) result.second /= counter.second; return result; } template std::pair getStd(std::list> &list) { std::pair mean = getMean(list); std::pair result(0, 0); int counter1 = 0; int counter2 = 0; for (auto elt : list) { if (!isNAN(elt->first)) { result.first += (elt->first - mean.first)*(elt->first - mean.first); counter1 += 1; } if (!isNAN(elt->second)) { result.second += (elt->second - mean.second)*(elt->second - mean.second); counter2 += 1; } } if (counter1 != 0) { result.first /= counter1; } else { result.first << NotANumber(); } if (counter2 != 0) { result.second /= counter2; } else { result.second << NotANumber(); } return std::sqrt(result); } template std::vectorrankify(std::vector& X) { int N = X.size(); // Rank Vector std::vector Rank_X(N); for (int i = 0; i < N; i++) { int r = 1, s = 1; // Count no of smaller elements // in 0 to i-1 for (int j = 0; j < N; j++) { if (X[j] < X[i]) r++; if (X[j] == X[i] && i != j) s++; } // Count no of smaller elements // in i+1 to N-1 /** for (int j = i + 1; j < N; j++) { if (X[j] < X[i]) r++; if (X[j] == X[i]) s++; }*/ // Use Fractional Rank formula // fractional_rank = r + (n-1)/2 Rank_X[i] = (Type) r + (s - 1) * 0.5; } // Return Rank Vector return Rank_X; } template bool getCovariance(std::list> &list, Type &result) { if (list.empty()) { return false; } std::pair mean = getMean(list); result = 0; int counter = 0; for (auto elt : list) { if (!isNAN(elt.first) && !isNAN(elt.second)) { result += (elt.first - mean.first)*(elt.second - mean.second); counter += 1; } } if (counter != 0) result /= counter; return true; } template bool getPearson(std::list> &list, Type &result) { if (list.empty()) { return false; } result = 0; int counter = 0; Type sum1 = 0, sum2 = 0; Type sum1Sq = 0, sum2Sq = 0; Type sum12 = 0; for (auto elt : list) { if (!isNAN(elt.first) && !isNAN(elt.second)) { sum1 += elt.first; sum2 += elt.second; sum1Sq += elt.first * elt.first; sum2Sq += elt.second * elt.second; sum12 += elt.first * elt.second; counter += 1; } } if (counter > 0) result = (counter * sum12 - sum1 * sum2) / (std::sqrt((counter * sum1Sq - sum1 * sum1)*(counter * sum2Sq - sum2 * sum2))); return true; } template bool getSpearman(std::list> &list, Type &result) { if (list.empty()) { return false; } std::vector X, Y; for (auto elt : list) { if (!isNAN(elt.first) && !isNAN(elt.second)) { X.push_back(elt.first); Y.push_back(elt.second); } } int n = X.size(); if (n == 0) return true; std::vector rank_X = rankify(X); std::vector rank_Y = rankify(Y); std::list> rankList; for (int i = 0; i < n; i++) rankList.push_back(std::make_pair(rank_X[i], rank_Y[i])); result = 0; getPearson(rankList, result); return true; } template bool getKendall(std::list> &list, Type &result) { if (list.empty()) { return false; } result = 0; std::vector X, Y; for (auto elt : list) { if (!isNAN(elt.first) && !isNAN(elt.second)) { X.push_back(elt.first); Y.push_back(elt.second); } } int n = X.size(); if (n == 0) return true; std::vector rank_x = rankify(X); std::vector rank_y = rankify(Y); Type nc = 0; for (int i = 0; i < n; i++){ for (int j=i;j rank_x[j] && rank_y[i] > rank_y[j]) || (rank_x[i] < rank_x[j] && rank_y[i] < rank_y[j]))) nc += 1; } } result = (Type) (4*nc - n*(n-1))/(Type) (n * (n - 1)); return true; } } /* namespace StatisticFunctions */ } /* namespace Parameters */ } /* namespace AMDA */ #endif /* TOOLBOX_HH_ */