| 75 | */ |
| 76 | template <typename InputIterator1, typename InputIterator2> |
| 77 | TStatTestResult MannWhitneyWithSign(InputIterator1 xBegin, InputIterator1 xEnd, InputIterator2 yBegin, InputIterator2 yEnd, bool useContinuity) { |
| 78 | const size_t MINIMUM_NUMBER_ELEMENTS_NORMAL_APPROXIMATION = 20; |
| 79 | |
| 80 | typedef typename std::iterator_traits<InputIterator1>::value_type ValueType; |
| 81 | typedef typename std::iterator_traits<InputIterator2>::value_type AnotherValueType; |
| 82 | static_assert((std::is_same<ValueType, AnotherValueType>::value), "expect (std::is_same<ValueType, AnotherValueType>::value)"); |
| 83 | static_assert(std::is_floating_point<ValueType>::value, "expect std::is_floating_point<ValueType>::value"); |
| 84 | |
| 85 | typedef TVector<std::pair<ValueType, bool>> TMWVector; |
| 86 | |
| 87 | ValueType xSize = static_cast<ValueType>(std::distance(xBegin, xEnd)); |
| 88 | ValueType ySize = static_cast<ValueType>(std::distance(yBegin, yEnd)); |
| 89 | |
| 90 | if (xSize < MINIMUM_NUMBER_ELEMENTS_NORMAL_APPROXIMATION || ySize < MINIMUM_NUMBER_ELEMENTS_NORMAL_APPROXIMATION) { |
| 91 | return TStatTestResult(static_cast<ValueType>(1), 0); |
| 92 | } |
| 93 | |
| 94 | TMWVector xy; |
| 95 | for (InputIterator1 it = xBegin; it != xEnd; ++it) { |
| 96 | xy.push_back(std::make_pair(*it, false)); |
| 97 | } |
| 98 | for (InputIterator2 it = yBegin; it != yEnd; ++it) { |
| 99 | xy.push_back(std::make_pair(*it, true)); |
| 100 | } |
| 101 | |
| 102 | Sort(xy.begin(), xy.end()); |
| 103 | NDetail::MWStatistics<ValueType> statistics = NDetail::GetMWStatistics<ValueType>(xy.begin(), xy.end()); |
| 104 | |
| 105 | ValueType nx = statistics.xIndicesSum > statistics.yIndicesSum ? xSize : ySize; |
| 106 | ValueType u = xSize * ySize + nx * (nx + 1) / 2 - Max(statistics.xIndicesSum, statistics.yIndicesSum); |
| 107 | statistics.modifier /= (xSize + ySize) * (Sqr(xSize + ySize) - 1); |
| 108 | statistics.modifier = sqrt(1 - statistics.modifier); |
| 109 | |
| 110 | if (statistics.modifier < std::numeric_limits<double>::epsilon()) { |
| 111 | return TStatTestResult(static_cast<ValueType>(1.), 0); |
| 112 | } |
| 113 | |
| 114 | const ValueType mean = xSize * ySize / 2.0; |
| 115 | const ValueType stdDeviation = sqrt(xSize * ySize * (xSize + ySize + 1) / 12); |
| 116 | double res = Phi(mean, stdDeviation * statistics.modifier, u, useContinuity); |
| 117 | if (res < 0.5) { |
| 118 | res = 1 - res; |
| 119 | } |
| 120 | ValueType xUStatistic = statistics.xIndicesSum - xSize * (xSize + 1) / 2; |
| 121 | ValueType yUStatistic = statistics.yIndicesSum - ySize * (ySize + 1) / 2; |
| 122 | int sign = xUStatistic > yUStatistic ? 1 : xUStatistic < yUStatistic ? -1 : 0; |
| 123 | return TStatTestResult((1 - res) * 2, sign); |
| 124 | } |
| 125 | |
| 126 | //! Mann-Whitney test. |
| 127 | /*! More details on: http://en.wikipedia.org/wiki/Mann–Whitney_U */ |