1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker * Copyright 2018 The Android Open Source Project
3*b9df5ad1SAndroid Build Coastguard Worker *
4*b9df5ad1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*b9df5ad1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*b9df5ad1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*b9df5ad1SAndroid Build Coastguard Worker *
8*b9df5ad1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*b9df5ad1SAndroid Build Coastguard Worker *
10*b9df5ad1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*b9df5ad1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*b9df5ad1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b9df5ad1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*b9df5ad1SAndroid Build Coastguard Worker * limitations under the License.
15*b9df5ad1SAndroid Build Coastguard Worker */
16*b9df5ad1SAndroid Build Coastguard Worker
17*b9df5ad1SAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*b9df5ad1SAndroid Build Coastguard Worker #define LOG_TAG "audio_utils_statistics_tests"
19*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/Statistics.h>
20*b9df5ad1SAndroid Build Coastguard Worker
21*b9df5ad1SAndroid Build Coastguard Worker #include <random>
22*b9df5ad1SAndroid Build Coastguard Worker #include <stdio.h>
23*b9df5ad1SAndroid Build Coastguard Worker #include <gtest/gtest.h>
24*b9df5ad1SAndroid Build Coastguard Worker
25*b9df5ad1SAndroid Build Coastguard Worker // create uniform distribution
26*b9df5ad1SAndroid Build Coastguard Worker template <typename T, typename V>
initUniform(V & data,T rangeMin,T rangeMax)27*b9df5ad1SAndroid Build Coastguard Worker static void initUniform(V& data, T rangeMin, T rangeMax) {
28*b9df5ad1SAndroid Build Coastguard Worker const size_t count = data.capacity();
29*b9df5ad1SAndroid Build Coastguard Worker std::minstd_rand gen(count);
30*b9df5ad1SAndroid Build Coastguard Worker std::uniform_real_distribution<T> dis(rangeMin, rangeMax);
31*b9df5ad1SAndroid Build Coastguard Worker
32*b9df5ad1SAndroid Build Coastguard Worker // for_each works for scalars
33*b9df5ad1SAndroid Build Coastguard Worker for (auto& datum : data) {
34*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::for_each(datum, [&](T &value) { return value = dis(gen);});
35*b9df5ad1SAndroid Build Coastguard Worker }
36*b9df5ad1SAndroid Build Coastguard Worker }
37*b9df5ad1SAndroid Build Coastguard Worker
38*b9df5ad1SAndroid Build Coastguard Worker // create gaussian distribution
39*b9df5ad1SAndroid Build Coastguard Worker template <typename T, typename V>
initNormal(V & data,T mean,T stddev)40*b9df5ad1SAndroid Build Coastguard Worker static void initNormal(V& data, T mean, T stddev) {
41*b9df5ad1SAndroid Build Coastguard Worker const size_t count = data.capacity();
42*b9df5ad1SAndroid Build Coastguard Worker std::minstd_rand gen(count);
43*b9df5ad1SAndroid Build Coastguard Worker
44*b9df5ad1SAndroid Build Coastguard Worker // values near the mean are the most likely
45*b9df5ad1SAndroid Build Coastguard Worker // standard deviation affects the dispersion of generated values from the mean
46*b9df5ad1SAndroid Build Coastguard Worker std::normal_distribution<> dis{mean, stddev};
47*b9df5ad1SAndroid Build Coastguard Worker
48*b9df5ad1SAndroid Build Coastguard Worker // for_each works for scalars
49*b9df5ad1SAndroid Build Coastguard Worker for (auto& datum : data) {
50*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::for_each(datum, [&](T &value) { return value = dis(gen);});
51*b9df5ad1SAndroid Build Coastguard Worker }
52*b9df5ad1SAndroid Build Coastguard Worker }
53*b9df5ad1SAndroid Build Coastguard Worker
54*b9df5ad1SAndroid Build Coastguard Worker // Used to create compile-time reference constants for variance testing.
55*b9df5ad1SAndroid Build Coastguard Worker template <typename T>
56*b9df5ad1SAndroid Build Coastguard Worker class ConstexprStatistics {
57*b9df5ad1SAndroid Build Coastguard Worker public:
58*b9df5ad1SAndroid Build Coastguard Worker template <size_t N>
ConstexprStatistics(const T (& a)[N])59*b9df5ad1SAndroid Build Coastguard Worker explicit constexpr ConstexprStatistics(const T (&a)[N])
60*b9df5ad1SAndroid Build Coastguard Worker : mN{N}
61*b9df5ad1SAndroid Build Coastguard Worker , mMax{android::audio_utils::max(a)}
62*b9df5ad1SAndroid Build Coastguard Worker , mMin{android::audio_utils::min(a)}
63*b9df5ad1SAndroid Build Coastguard Worker , mMean{android::audio_utils::sum(a) / mN}
64*b9df5ad1SAndroid Build Coastguard Worker , mM2{android::audio_utils::sumSqDiff(a, mMean)}
65*b9df5ad1SAndroid Build Coastguard Worker , mPopVariance{mM2 / mN}
66*b9df5ad1SAndroid Build Coastguard Worker , mPopStdDev{android::audio_utils::sqrt_constexpr(mPopVariance)}
67*b9df5ad1SAndroid Build Coastguard Worker , mVariance{mM2 / (mN - 1)}
68*b9df5ad1SAndroid Build Coastguard Worker , mStdDev{android::audio_utils::sqrt_constexpr(mVariance)}
69*b9df5ad1SAndroid Build Coastguard Worker { }
70*b9df5ad1SAndroid Build Coastguard Worker
getN() const71*b9df5ad1SAndroid Build Coastguard Worker constexpr int64_t getN() const { return mN; }
getMin() const72*b9df5ad1SAndroid Build Coastguard Worker constexpr T getMin() const { return mMin; }
getMax() const73*b9df5ad1SAndroid Build Coastguard Worker constexpr T getMax() const { return mMax; }
getWeight() const74*b9df5ad1SAndroid Build Coastguard Worker constexpr double getWeight() const { return (double)mN; }
getMean() const75*b9df5ad1SAndroid Build Coastguard Worker constexpr double getMean() const { return mMean; }
getVariance() const76*b9df5ad1SAndroid Build Coastguard Worker constexpr double getVariance() const { return mVariance; }
getStdDev() const77*b9df5ad1SAndroid Build Coastguard Worker constexpr double getStdDev() const { return mStdDev; }
getPopVariance() const78*b9df5ad1SAndroid Build Coastguard Worker constexpr double getPopVariance() const { return mPopVariance; }
getPopStdDev() const79*b9df5ad1SAndroid Build Coastguard Worker constexpr double getPopStdDev() const { return mPopStdDev; }
80*b9df5ad1SAndroid Build Coastguard Worker
81*b9df5ad1SAndroid Build Coastguard Worker private:
82*b9df5ad1SAndroid Build Coastguard Worker const size_t mN;
83*b9df5ad1SAndroid Build Coastguard Worker const T mMax;
84*b9df5ad1SAndroid Build Coastguard Worker const T mMin;
85*b9df5ad1SAndroid Build Coastguard Worker const double mMean;
86*b9df5ad1SAndroid Build Coastguard Worker const double mM2;
87*b9df5ad1SAndroid Build Coastguard Worker const double mPopVariance;
88*b9df5ad1SAndroid Build Coastguard Worker const double mPopStdDev;
89*b9df5ad1SAndroid Build Coastguard Worker const double mVariance;
90*b9df5ad1SAndroid Build Coastguard Worker const double mStdDev;
91*b9df5ad1SAndroid Build Coastguard Worker };
92*b9df5ad1SAndroid Build Coastguard Worker
93*b9df5ad1SAndroid Build Coastguard Worker class StatisticsTest : public testing::TestWithParam<const char *>
94*b9df5ad1SAndroid Build Coastguard Worker {
95*b9df5ad1SAndroid Build Coastguard Worker };
96*b9df5ad1SAndroid Build Coastguard Worker
97*b9df5ad1SAndroid Build Coastguard Worker // find power of 2 that is small enough that it doesn't add to 1. due to finite mantissa.
98*b9df5ad1SAndroid Build Coastguard Worker template <typename T>
smallp2()99*b9df5ad1SAndroid Build Coastguard Worker constexpr T smallp2() {
100*b9df5ad1SAndroid Build Coastguard Worker T smallOne{};
101*b9df5ad1SAndroid Build Coastguard Worker for (smallOne = T{1.}; smallOne + T{1.} > T{1.}; smallOne *= T(0.5));
102*b9df5ad1SAndroid Build Coastguard Worker return smallOne;
103*b9df5ad1SAndroid Build Coastguard Worker }
104*b9df5ad1SAndroid Build Coastguard Worker
105*b9df5ad1SAndroid Build Coastguard Worker // Our near expectation is 16x the bit that doesn't fit the mantissa.
106*b9df5ad1SAndroid Build Coastguard Worker // this works so long as we add values close in exponent with each other
107*b9df5ad1SAndroid Build Coastguard Worker // realizing that errors accumulate as the sqrt of N (random walk, lln, etc).
108*b9df5ad1SAndroid Build Coastguard Worker #define TEST_EXPECT_NEAR(e, v) \
109*b9df5ad1SAndroid Build Coastguard Worker EXPECT_NEAR((e), (v), abs((e) * std::numeric_limits<decltype(e)>::epsilon() * 8))
110*b9df5ad1SAndroid Build Coastguard Worker
111*b9df5ad1SAndroid Build Coastguard Worker #define PRINT_AND_EXPECT_EQ(expected, expr) { \
112*b9df5ad1SAndroid Build Coastguard Worker auto value = (expr); \
113*b9df5ad1SAndroid Build Coastguard Worker printf("(%s): %s\n", #expr, std::to_string(value).c_str()); \
114*b9df5ad1SAndroid Build Coastguard Worker if ((expected) == (expected)) { EXPECT_EQ((expected), (value)); } \
115*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ((expected) != (expected), (value) != (value)); /* nan check */\
116*b9df5ad1SAndroid Build Coastguard Worker }
117*b9df5ad1SAndroid Build Coastguard Worker
118*b9df5ad1SAndroid Build Coastguard Worker #define PRINT_AND_EXPECT_NEAR(expected, expr) { \
119*b9df5ad1SAndroid Build Coastguard Worker auto ref = (expected); \
120*b9df5ad1SAndroid Build Coastguard Worker auto value = (expr); \
121*b9df5ad1SAndroid Build Coastguard Worker printf("(%s): %s\n", #expr, std::to_string(value).c_str()); \
122*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(ref, value); \
123*b9df5ad1SAndroid Build Coastguard Worker }
124*b9df5ad1SAndroid Build Coastguard Worker
125*b9df5ad1SAndroid Build Coastguard Worker template <typename T, typename S>
verify(const T & stat,const S & refstat)126*b9df5ad1SAndroid Build Coastguard Worker static void verify(const T &stat, const S &refstat) {
127*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(refstat.getN(), stat.getN());
128*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(refstat.getMin(), stat.getMin());
129*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(refstat.getMax(), stat.getMax());
130*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(refstat.getWeight(), stat.getWeight());
131*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(refstat.getMean(), stat.getMean());
132*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(refstat.getVariance(), stat.getVariance());
133*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(refstat.getStdDev(), stat.getStdDev());
134*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(refstat.getPopVariance(), stat.getPopVariance());
135*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(refstat.getPopStdDev(), stat.getPopStdDev());
136*b9df5ad1SAndroid Build Coastguard Worker }
137*b9df5ad1SAndroid Build Coastguard Worker
138*b9df5ad1SAndroid Build Coastguard Worker // Test against fixed reference
139*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,high_precision_sums)140*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, high_precision_sums)
141*b9df5ad1SAndroid Build Coastguard Worker {
142*b9df5ad1SAndroid Build Coastguard Worker static const double simple[] = { 1., 2., 3. };
143*b9df5ad1SAndroid Build Coastguard Worker
144*b9df5ad1SAndroid Build Coastguard Worker double rssum = android::audio_utils::sum<double, double>(simple);
145*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(6., rssum);
146*b9df5ad1SAndroid Build Coastguard Worker double kssum =
147*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sum<double, android::audio_utils::KahanSum<double>>(simple);
148*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(6., kssum);
149*b9df5ad1SAndroid Build Coastguard Worker double nmsum =
150*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sum<double, android::audio_utils::NeumaierSum<double>>(simple);
151*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(6., nmsum);
152*b9df5ad1SAndroid Build Coastguard Worker
153*b9df5ad1SAndroid Build Coastguard Worker double rs{};
154*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::KahanSum<double> ks{};
155*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::NeumaierSum<double> ns{};
156*b9df5ad1SAndroid Build Coastguard Worker
157*b9df5ad1SAndroid Build Coastguard Worker // add 1.
158*b9df5ad1SAndroid Build Coastguard Worker rs += 1.;
159*b9df5ad1SAndroid Build Coastguard Worker ks += 1.;
160*b9df5ad1SAndroid Build Coastguard Worker ns += 1.;
161*b9df5ad1SAndroid Build Coastguard Worker
162*b9df5ad1SAndroid Build Coastguard Worker static constexpr double smallOne = std::numeric_limits<double>::epsilon() * 0.5;
163*b9df5ad1SAndroid Build Coastguard Worker // add lots of small values
164*b9df5ad1SAndroid Build Coastguard Worker static const int loop = 1000;
165*b9df5ad1SAndroid Build Coastguard Worker for (int i = 0; i < loop; ++i) {
166*b9df5ad1SAndroid Build Coastguard Worker rs += smallOne;
167*b9df5ad1SAndroid Build Coastguard Worker ks += smallOne;
168*b9df5ad1SAndroid Build Coastguard Worker ns += smallOne;
169*b9df5ad1SAndroid Build Coastguard Worker }
170*b9df5ad1SAndroid Build Coastguard Worker
171*b9df5ad1SAndroid Build Coastguard Worker // remove 1.
172*b9df5ad1SAndroid Build Coastguard Worker rs += -1.;
173*b9df5ad1SAndroid Build Coastguard Worker ks += -1.;
174*b9df5ad1SAndroid Build Coastguard Worker ns += -1.;
175*b9df5ad1SAndroid Build Coastguard Worker
176*b9df5ad1SAndroid Build Coastguard Worker const double totalAdded = smallOne * loop;
177*b9df5ad1SAndroid Build Coastguard Worker printf("totalAdded: %lg\n", totalAdded);
178*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(0., rs); // normal count fails
179*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(totalAdded, ks); // kahan succeeds
180*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(totalAdded, ns); // neumaier succeeds
181*b9df5ad1SAndroid Build Coastguard Worker
182*b9df5ad1SAndroid Build Coastguard Worker // test case where kahan fails and neumaier method succeeds.
183*b9df5ad1SAndroid Build Coastguard Worker static const double tricky[] = { 1e100, 1., -1e100 };
184*b9df5ad1SAndroid Build Coastguard Worker
185*b9df5ad1SAndroid Build Coastguard Worker rssum = android::audio_utils::sum<double, double>(tricky);
186*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(0., rssum);
187*b9df5ad1SAndroid Build Coastguard Worker kssum = android::audio_utils::sum<double, android::audio_utils::KahanSum<double>>(tricky);
188*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(0., kssum);
189*b9df5ad1SAndroid Build Coastguard Worker nmsum = android::audio_utils::sum<double, android::audio_utils::NeumaierSum<double>>(tricky);
190*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(1., nmsum);
191*b9df5ad1SAndroid Build Coastguard Worker }
192*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,minmax_bounds)193*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, minmax_bounds)
194*b9df5ad1SAndroid Build Coastguard Worker {
195*b9df5ad1SAndroid Build Coastguard Worker // range based min and max use iterator forms of min and max.
196*b9df5ad1SAndroid Build Coastguard Worker
197*b9df5ad1SAndroid Build Coastguard Worker static constexpr double one[] = { 1. };
198*b9df5ad1SAndroid Build Coastguard Worker
199*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::numeric_limits<double>::infinity(),
200*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::min(&one[0], &one[0]));
201*b9df5ad1SAndroid Build Coastguard Worker
202*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(-std::numeric_limits<double>::infinity(),
203*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::max(&one[0], &one[0]));
204*b9df5ad1SAndroid Build Coastguard Worker
205*b9df5ad1SAndroid Build Coastguard Worker static constexpr int un[] = { 1 };
206*b9df5ad1SAndroid Build Coastguard Worker
207*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::numeric_limits<int>::max(),
208*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::min(&un[0], &un[0]));
209*b9df5ad1SAndroid Build Coastguard Worker
210*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::numeric_limits<int>::min(),
211*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::max(&un[0], &un[0]));
212*b9df5ad1SAndroid Build Coastguard Worker
213*b9df5ad1SAndroid Build Coastguard Worker double nanarray[] = { nan(""), nan(""), nan("") };
214*b9df5ad1SAndroid Build Coastguard Worker
215*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::numeric_limits<double>::infinity(),
216*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::min(nanarray));
217*b9df5ad1SAndroid Build Coastguard Worker
218*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(-std::numeric_limits<double>::infinity(),
219*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::max(nanarray));
220*b9df5ad1SAndroid Build Coastguard Worker
221*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::Statistics<double> s(nanarray);
222*b9df5ad1SAndroid Build Coastguard Worker
223*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::numeric_limits<double>::infinity(),
224*b9df5ad1SAndroid Build Coastguard Worker s.getMin());
225*b9df5ad1SAndroid Build Coastguard Worker
226*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(-std::numeric_limits<double>::infinity(),
227*b9df5ad1SAndroid Build Coastguard Worker s.getMax());
228*b9df5ad1SAndroid Build Coastguard Worker }
229*b9df5ad1SAndroid Build Coastguard Worker
230*b9df5ad1SAndroid Build Coastguard Worker /*
231*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, sqrt_convergence)
232*b9df5ad1SAndroid Build Coastguard Worker {
233*b9df5ad1SAndroid Build Coastguard Worker union {
234*b9df5ad1SAndroid Build Coastguard Worker int i;
235*b9df5ad1SAndroid Build Coastguard Worker float f;
236*b9df5ad1SAndroid Build Coastguard Worker } u;
237*b9df5ad1SAndroid Build Coastguard Worker
238*b9df5ad1SAndroid Build Coastguard Worker for (int i = 0; i < INT_MAX; ++i) {
239*b9df5ad1SAndroid Build Coastguard Worker u.i = i;
240*b9df5ad1SAndroid Build Coastguard Worker const float f = u.f;
241*b9df5ad1SAndroid Build Coastguard Worker if (!android::audio_utils::isnan(f)) {
242*b9df5ad1SAndroid Build Coastguard Worker const float sf = android::audio_utils::sqrt(f);
243*b9df5ad1SAndroid Build Coastguard Worker if ((i & (1 << 16) - 1) == 0) {
244*b9df5ad1SAndroid Build Coastguard Worker printf("i: %d f:%f sf:%f\n", i, f, sf);
245*b9df5ad1SAndroid Build Coastguard Worker }
246*b9df5ad1SAndroid Build Coastguard Worker }
247*b9df5ad1SAndroid Build Coastguard Worker }
248*b9df5ad1SAndroid Build Coastguard Worker }
249*b9df5ad1SAndroid Build Coastguard Worker */
250*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,minmax_simple_array)251*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, minmax_simple_array)
252*b9df5ad1SAndroid Build Coastguard Worker {
253*b9df5ad1SAndroid Build Coastguard Worker static constexpr double ary[] = { -1.5, 1.5, -2.5, 2.5 };
254*b9df5ad1SAndroid Build Coastguard Worker
255*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(-2.5, android::audio_utils::min(ary));
256*b9df5ad1SAndroid Build Coastguard Worker
257*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(2.5, android::audio_utils::max(ary));
258*b9df5ad1SAndroid Build Coastguard Worker
259*b9df5ad1SAndroid Build Coastguard Worker static constexpr int ray[] = { -1, 1, -2, 2 };
260*b9df5ad1SAndroid Build Coastguard Worker
261*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(-2, android::audio_utils::min(ray));
262*b9df5ad1SAndroid Build Coastguard Worker
263*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(2, android::audio_utils::max(ray));
264*b9df5ad1SAndroid Build Coastguard Worker }
265*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,sqrt)266*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, sqrt)
267*b9df5ad1SAndroid Build Coastguard Worker {
268*b9df5ad1SAndroid Build Coastguard Worker // check doubles
269*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::numeric_limits<double>::infinity(),
270*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(std::numeric_limits<double>::infinity()));
271*b9df5ad1SAndroid Build Coastguard Worker
272*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::nan(""),
273*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(-std::numeric_limits<double>::infinity()));
274*b9df5ad1SAndroid Build Coastguard Worker
275*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(sqrt(std::numeric_limits<double>::epsilon()),
276*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(std::numeric_limits<double>::epsilon()));
277*b9df5ad1SAndroid Build Coastguard Worker
278*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(3.,
279*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(9.));
280*b9df5ad1SAndroid Build Coastguard Worker
281*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(0.,
282*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(0.));
283*b9df5ad1SAndroid Build Coastguard Worker
284*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::nan(""),
285*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(-1.));
286*b9df5ad1SAndroid Build Coastguard Worker
287*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::nan(""),
288*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(std::nan("")));
289*b9df5ad1SAndroid Build Coastguard Worker
290*b9df5ad1SAndroid Build Coastguard Worker // check floats
291*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::numeric_limits<float>::infinity(),
292*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(std::numeric_limits<float>::infinity()));
293*b9df5ad1SAndroid Build Coastguard Worker
294*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::nanf(""),
295*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(-std::numeric_limits<float>::infinity()));
296*b9df5ad1SAndroid Build Coastguard Worker
297*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(sqrtf(std::numeric_limits<float>::epsilon()),
298*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(std::numeric_limits<float>::epsilon()));
299*b9df5ad1SAndroid Build Coastguard Worker
300*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(2.f,
301*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(4.f));
302*b9df5ad1SAndroid Build Coastguard Worker
303*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(0.f,
304*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(0.f));
305*b9df5ad1SAndroid Build Coastguard Worker
306*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::nanf(""),
307*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(-1.f));
308*b9df5ad1SAndroid Build Coastguard Worker
309*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(std::nanf(""),
310*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::sqrt(std::nanf("")));
311*b9df5ad1SAndroid Build Coastguard Worker }
312*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,stat_reference)313*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, stat_reference)
314*b9df5ad1SAndroid Build Coastguard Worker {
315*b9df5ad1SAndroid Build Coastguard Worker // fixed reference compile time constants.
316*b9df5ad1SAndroid Build Coastguard Worker static constexpr double data[] = {0.1, -0.1, 0.2, -0.3};
317*b9df5ad1SAndroid Build Coastguard Worker static constexpr ConstexprStatistics<double> rstat(data); // use alpha = 1.
318*b9df5ad1SAndroid Build Coastguard Worker static constexpr android::audio_utils::Statistics<double> stat{data};
319*b9df5ad1SAndroid Build Coastguard Worker
320*b9df5ad1SAndroid Build Coastguard Worker verify(stat, rstat);
321*b9df5ad1SAndroid Build Coastguard Worker }
322*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,stat_variable_alpha)323*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, stat_variable_alpha)
324*b9df5ad1SAndroid Build Coastguard Worker {
325*b9df5ad1SAndroid Build Coastguard Worker constexpr size_t TEST_SIZE = 1 << 20;
326*b9df5ad1SAndroid Build Coastguard Worker std::vector<double> data(TEST_SIZE);
327*b9df5ad1SAndroid Build Coastguard Worker std::vector<double> alpha(TEST_SIZE);
328*b9df5ad1SAndroid Build Coastguard Worker
329*b9df5ad1SAndroid Build Coastguard Worker initUniform(data, -1., 1.);
330*b9df5ad1SAndroid Build Coastguard Worker initUniform(alpha, .95, .99);
331*b9df5ad1SAndroid Build Coastguard Worker
332*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::ReferenceStatistics<double> rstat;
333*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::Statistics<double> stat;
334*b9df5ad1SAndroid Build Coastguard Worker
335*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<decltype(stat)>::value,
336*b9df5ad1SAndroid Build Coastguard Worker "basic statistics must be trivially copyable");
337*b9df5ad1SAndroid Build Coastguard Worker
338*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < TEST_SIZE; ++i) {
339*b9df5ad1SAndroid Build Coastguard Worker rstat.setAlpha(alpha[i]);
340*b9df5ad1SAndroid Build Coastguard Worker rstat.add(data[i]);
341*b9df5ad1SAndroid Build Coastguard Worker
342*b9df5ad1SAndroid Build Coastguard Worker stat.setAlpha(alpha[i]);
343*b9df5ad1SAndroid Build Coastguard Worker stat.add(data[i]);
344*b9df5ad1SAndroid Build Coastguard Worker }
345*b9df5ad1SAndroid Build Coastguard Worker
346*b9df5ad1SAndroid Build Coastguard Worker printf("statistics: %s\n", stat.toString().c_str());
347*b9df5ad1SAndroid Build Coastguard Worker printf("ref statistics: %s\n", rstat.toString().c_str());
348*b9df5ad1SAndroid Build Coastguard Worker verify(stat, rstat);
349*b9df5ad1SAndroid Build Coastguard Worker }
350*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,stat_vector)351*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, stat_vector)
352*b9df5ad1SAndroid Build Coastguard Worker {
353*b9df5ad1SAndroid Build Coastguard Worker // for operator overloading...
354*b9df5ad1SAndroid Build Coastguard Worker using namespace android::audio_utils;
355*b9df5ad1SAndroid Build Coastguard Worker
356*b9df5ad1SAndroid Build Coastguard Worker using data_t = std::tuple<double, double>;
357*b9df5ad1SAndroid Build Coastguard Worker using covariance_t = std::tuple<double, double, double, double>;
358*b9df5ad1SAndroid Build Coastguard Worker using covariance_ut_t = std::tuple<double, double, double>;
359*b9df5ad1SAndroid Build Coastguard Worker
360*b9df5ad1SAndroid Build Coastguard Worker constexpr size_t TEST_SIZE = 1 << 20;
361*b9df5ad1SAndroid Build Coastguard Worker std::vector<data_t> data(TEST_SIZE);
362*b9df5ad1SAndroid Build Coastguard Worker // std::vector<double> alpha(TEST_SIZE);
363*b9df5ad1SAndroid Build Coastguard Worker
364*b9df5ad1SAndroid Build Coastguard Worker initUniform(data, -1., 1.);
365*b9df5ad1SAndroid Build Coastguard Worker
366*b9df5ad1SAndroid Build Coastguard Worker std::cout << "sample data[0]: " << data[0] << "\n";
367*b9df5ad1SAndroid Build Coastguard Worker
368*b9df5ad1SAndroid Build Coastguard Worker Statistics<data_t, data_t, data_t, double, double, innerProduct_scalar<data_t>> stat;
369*b9df5ad1SAndroid Build Coastguard Worker Statistics<data_t, data_t, data_t, double,
370*b9df5ad1SAndroid Build Coastguard Worker covariance_t, outerProduct_tuple<data_t>> stat_outer;
371*b9df5ad1SAndroid Build Coastguard Worker Statistics<data_t, data_t, data_t, double,
372*b9df5ad1SAndroid Build Coastguard Worker covariance_ut_t, outerProduct_UT_tuple<data_t>> stat_outer_ut;
373*b9df5ad1SAndroid Build Coastguard Worker
374*b9df5ad1SAndroid Build Coastguard Worker using pair_t = std::pair<double, double>;
375*b9df5ad1SAndroid Build Coastguard Worker std::vector<pair_t> pairs(TEST_SIZE);
376*b9df5ad1SAndroid Build Coastguard Worker initUniform(pairs, -1., 1.);
377*b9df5ad1SAndroid Build Coastguard Worker Statistics<pair_t, pair_t, pair_t, double, double, innerProduct_scalar<pair_t>> stat_pair;
378*b9df5ad1SAndroid Build Coastguard Worker
379*b9df5ad1SAndroid Build Coastguard Worker using array_t = std::array<double, 2>;
380*b9df5ad1SAndroid Build Coastguard Worker using array_covariance_ut_t = std::array<double, 3>;
381*b9df5ad1SAndroid Build Coastguard Worker std::vector<array_t> arrays(TEST_SIZE);
382*b9df5ad1SAndroid Build Coastguard Worker initUniform(arrays, -1., 1.);
383*b9df5ad1SAndroid Build Coastguard Worker Statistics<array_t, array_t, array_t, double,
384*b9df5ad1SAndroid Build Coastguard Worker double, innerProduct_scalar<array_t>> stat_array;
385*b9df5ad1SAndroid Build Coastguard Worker Statistics<array_t, array_t, array_t, double,
386*b9df5ad1SAndroid Build Coastguard Worker array_covariance_ut_t, outerProduct_UT_array<array_t>> stat_array_ut;
387*b9df5ad1SAndroid Build Coastguard Worker
388*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < TEST_SIZE; ++i) {
389*b9df5ad1SAndroid Build Coastguard Worker stat.add(data[i]);
390*b9df5ad1SAndroid Build Coastguard Worker stat_outer.add(data[i]);
391*b9df5ad1SAndroid Build Coastguard Worker stat_outer_ut.add(data[i]);
392*b9df5ad1SAndroid Build Coastguard Worker stat_pair.add(pairs[i]);
393*b9df5ad1SAndroid Build Coastguard Worker stat_array.add(arrays[i]);
394*b9df5ad1SAndroid Build Coastguard Worker stat_array_ut.add(arrays[i]);
395*b9df5ad1SAndroid Build Coastguard Worker }
396*b9df5ad1SAndroid Build Coastguard Worker
397*b9df5ad1SAndroid Build Coastguard Worker #if 0
398*b9df5ad1SAndroid Build Coastguard Worker // these aren't trivially copyable
399*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<decltype(stat)>::value,
400*b9df5ad1SAndroid Build Coastguard Worker "tuple based inner product not trivially copyable");
401*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<decltype(stat_outer)>::value,
402*b9df5ad1SAndroid Build Coastguard Worker "tuple based outer product not trivially copyable");
403*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<decltype(stat_outer_ut)>::value,
404*b9df5ad1SAndroid Build Coastguard Worker "tuple based outer product not trivially copyable");
405*b9df5ad1SAndroid Build Coastguard Worker #endif
406*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<decltype(stat_array)>::value,
407*b9df5ad1SAndroid Build Coastguard Worker "array based inner product not trivially copyable");
408*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<decltype(stat_array_ut)>::value,
409*b9df5ad1SAndroid Build Coastguard Worker "array based inner product not trivially copyable");
410*b9df5ad1SAndroid Build Coastguard Worker
411*b9df5ad1SAndroid Build Coastguard Worker // inner product variance should be same as outer product diagonal sum
412*b9df5ad1SAndroid Build Coastguard Worker const double variance = stat.getPopVariance();
413*b9df5ad1SAndroid Build Coastguard Worker EXPECT_NEAR(variance,
414*b9df5ad1SAndroid Build Coastguard Worker std::get<0>(stat_outer.getPopVariance()) +
415*b9df5ad1SAndroid Build Coastguard Worker std::get<3>(stat_outer.getPopVariance()),
416*b9df5ad1SAndroid Build Coastguard Worker variance * std::numeric_limits<double>::epsilon() * 128);
417*b9df5ad1SAndroid Build Coastguard Worker
418*b9df5ad1SAndroid Build Coastguard Worker // outer product covariance should be identical
419*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(std::get<1>(stat_outer.getPopVariance()),
420*b9df5ad1SAndroid Build Coastguard Worker std::get<2>(stat_outer.getPopVariance()));
421*b9df5ad1SAndroid Build Coastguard Worker
422*b9df5ad1SAndroid Build Coastguard Worker // upper triangular computation should be identical to outer product
423*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(std::get<0>(stat_outer.getPopVariance()),
424*b9df5ad1SAndroid Build Coastguard Worker std::get<0>(stat_outer_ut.getPopVariance()));
425*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(std::get<1>(stat_outer.getPopVariance()),
426*b9df5ad1SAndroid Build Coastguard Worker std::get<1>(stat_outer_ut.getPopVariance()));
427*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(std::get<3>(stat_outer.getPopVariance()),
428*b9df5ad1SAndroid Build Coastguard Worker std::get<2>(stat_outer_ut.getPopVariance()));
429*b9df5ad1SAndroid Build Coastguard Worker
430*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(variance, stat_pair.getPopVariance());
431*b9df5ad1SAndroid Build Coastguard Worker
432*b9df5ad1SAndroid Build Coastguard Worker EXPECT_TRUE(equivalent(stat_array_ut.getPopVariance(), stat_outer_ut.getPopVariance()));
433*b9df5ad1SAndroid Build Coastguard Worker
434*b9df5ad1SAndroid Build Coastguard Worker printf("statistics_inner: %s\n", stat.toString().c_str());
435*b9df5ad1SAndroid Build Coastguard Worker printf("statistics_outer: %s\n", stat_outer.toString().c_str());
436*b9df5ad1SAndroid Build Coastguard Worker printf("statistics_outer_ut: %s\n", stat_outer_ut.toString().c_str());
437*b9df5ad1SAndroid Build Coastguard Worker }
438*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,stat_linearfit)439*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, stat_linearfit)
440*b9df5ad1SAndroid Build Coastguard Worker {
441*b9df5ad1SAndroid Build Coastguard Worker using namespace android::audio_utils; // for operator overload
442*b9df5ad1SAndroid Build Coastguard Worker LinearLeastSquaresFit<double> fit;
443*b9df5ad1SAndroid Build Coastguard Worker
444*b9df5ad1SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<decltype(fit)>::value,
445*b9df5ad1SAndroid Build Coastguard Worker "LinearLeastSquaresFit must be trivially copyable");
446*b9df5ad1SAndroid Build Coastguard Worker
447*b9df5ad1SAndroid Build Coastguard Worker using array_t = std::array<double, 2>;
448*b9df5ad1SAndroid Build Coastguard Worker array_t data{0.0, 1.5};
449*b9df5ad1SAndroid Build Coastguard Worker
450*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < 10; ++i) {
451*b9df5ad1SAndroid Build Coastguard Worker fit.add(data);
452*b9df5ad1SAndroid Build Coastguard Worker data = data + array_t{0.1, 0.2};
453*b9df5ad1SAndroid Build Coastguard Worker }
454*b9df5ad1SAndroid Build Coastguard Worker
455*b9df5ad1SAndroid Build Coastguard Worker // check the y line equation
456*b9df5ad1SAndroid Build Coastguard Worker {
457*b9df5ad1SAndroid Build Coastguard Worker double a, b, r2;
458*b9df5ad1SAndroid Build Coastguard Worker fit.computeYLine(a, b, r2);
459*b9df5ad1SAndroid Build Coastguard Worker printf("y line - a:%lf b:%lf r2:%lf\n", a, b, r2);
460*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(1.5, a); // y intercept
461*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(2.0, b); // y slope
462*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(1.0, r2); // correlation coefficient.
463*b9df5ad1SAndroid Build Coastguard Worker
464*b9df5ad1SAndroid Build Coastguard Worker // check same as static variant
465*b9df5ad1SAndroid Build Coastguard Worker double ac, bc, r2c;
466*b9df5ad1SAndroid Build Coastguard Worker computeYLineFromStatistics(ac, bc, r2c,
467*b9df5ad1SAndroid Build Coastguard Worker std::get<0>(fit.getMean()), /* mean_x */
468*b9df5ad1SAndroid Build Coastguard Worker std::get<1>(fit.getMean()), /* mean_y */
469*b9df5ad1SAndroid Build Coastguard Worker std::get<0>(fit.getPopVariance()), /* var_x */
470*b9df5ad1SAndroid Build Coastguard Worker std::get<1>(fit.getPopVariance()), /* cov_xy */
471*b9df5ad1SAndroid Build Coastguard Worker std::get<2>(fit.getPopVariance())); /* var_y */
472*b9df5ad1SAndroid Build Coastguard Worker
473*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(a, ac);
474*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(b, bc);
475*b9df5ad1SAndroid Build Coastguard Worker EXPECT_EQ(r2, r2c);
476*b9df5ad1SAndroid Build Coastguard Worker
477*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(1.9, fit.getYFromX(0.2));
478*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(0.2, fit.getXFromY(1.9));
479*b9df5ad1SAndroid Build Coastguard Worker TEST_EXPECT_NEAR(1.0, fit.getR2());
480*b9df5ad1SAndroid Build Coastguard Worker }
481*b9df5ad1SAndroid Build Coastguard Worker
482*b9df5ad1SAndroid Build Coastguard Worker // check the x line equation
483*b9df5ad1SAndroid Build Coastguard Worker {
484*b9df5ad1SAndroid Build Coastguard Worker double a, b, r2;
485*b9df5ad1SAndroid Build Coastguard Worker fit.computeXLine(a, b, r2);
486*b9df5ad1SAndroid Build Coastguard Worker printf("x line - a:%lf b:%lf r2:%lf\n", a, b, r2);
487*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(-0.75, a); // x intercept
488*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(0.5, b); // x slope
489*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_NEAR(1.0, r2); // correlation coefficient.
490*b9df5ad1SAndroid Build Coastguard Worker }
491*b9df5ad1SAndroid Build Coastguard Worker }
492*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,stat_linearfit_noise)493*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, stat_linearfit_noise)
494*b9df5ad1SAndroid Build Coastguard Worker {
495*b9df5ad1SAndroid Build Coastguard Worker using namespace android::audio_utils; // for operator overload
496*b9df5ad1SAndroid Build Coastguard Worker using array_t = std::array<double, 2>;
497*b9df5ad1SAndroid Build Coastguard Worker LinearLeastSquaresFit<double> fit;
498*b9df5ad1SAndroid Build Coastguard Worker
499*b9df5ad1SAndroid Build Coastguard Worker // We use 1000 steps for a linear line going from (0, 0) to (1, 1) as true data for
500*b9df5ad1SAndroid Build Coastguard Worker // our linear fit.
501*b9df5ad1SAndroid Build Coastguard Worker constexpr size_t ELEMENTS = 1000;
502*b9df5ad1SAndroid Build Coastguard Worker array_t incr{1. / ELEMENTS, 1. / ELEMENTS};
503*b9df5ad1SAndroid Build Coastguard Worker
504*b9df5ad1SAndroid Build Coastguard Worker // To simulate additive noise, we use a Gaussian with stddev of 1, and then scale
505*b9df5ad1SAndroid Build Coastguard Worker // achieve the desired stddev. We precompute our noise here (1000 of them).
506*b9df5ad1SAndroid Build Coastguard Worker std::vector<array_t> noise(ELEMENTS);
507*b9df5ad1SAndroid Build Coastguard Worker initNormal(noise, 0. /* mean */, 1. /* stddev */);
508*b9df5ad1SAndroid Build Coastguard Worker
509*b9df5ad1SAndroid Build Coastguard Worker for (int i = 0; i < 30; ++i) {
510*b9df5ad1SAndroid Build Coastguard Worker // We run through 30 trials, with noise stddev ranging from 0 to 1.
511*b9df5ad1SAndroid Build Coastguard Worker // The steps increment linearly from 0.001 to 0.01, linearly from 0.01 to 0.1, and
512*b9df5ad1SAndroid Build Coastguard Worker // linearly again from 0.1 to 1.0.
513*b9df5ad1SAndroid Build Coastguard Worker // 0.001, 0.002, ... 0.009, 0.01, 0.02, ....0.09, 0.1, 0.2, .... 1.0
514*b9df5ad1SAndroid Build Coastguard Worker const double stddev = (i <= 10) ? i / 1000. : (i <= 20) ? (i - 9) / 100. : (i - 19) / 10.;
515*b9df5ad1SAndroid Build Coastguard Worker fit.reset();
516*b9df5ad1SAndroid Build Coastguard Worker
517*b9df5ad1SAndroid Build Coastguard Worker for (size_t j = 0; j < ELEMENTS; ++j) {
518*b9df5ad1SAndroid Build Coastguard Worker array_t data = j * incr + noise[j] * stddev;
519*b9df5ad1SAndroid Build Coastguard Worker fit.add(data);
520*b9df5ad1SAndroid Build Coastguard Worker }
521*b9df5ad1SAndroid Build Coastguard Worker
522*b9df5ad1SAndroid Build Coastguard Worker double a, b, r2;
523*b9df5ad1SAndroid Build Coastguard Worker fit.computeYLine(a, b, r2);
524*b9df5ad1SAndroid Build Coastguard Worker printf("stddev: %lf y line - N:%lld a:%lf b:%lf r2:%lf\n",
525*b9df5ad1SAndroid Build Coastguard Worker stddev, (long long) fit.getN(), a, b, r2);
526*b9df5ad1SAndroid Build Coastguard Worker }
527*b9df5ad1SAndroid Build Coastguard Worker }
528*b9df5ad1SAndroid Build Coastguard Worker
529*b9df5ad1SAndroid Build Coastguard Worker
TEST_P(StatisticsTest,stat_simple_char)530*b9df5ad1SAndroid Build Coastguard Worker TEST_P(StatisticsTest, stat_simple_char)
531*b9df5ad1SAndroid Build Coastguard Worker {
532*b9df5ad1SAndroid Build Coastguard Worker const char *param = GetParam();
533*b9df5ad1SAndroid Build Coastguard Worker
534*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::Statistics<char> stat(0.9);
535*b9df5ad1SAndroid Build Coastguard Worker android::audio_utils::ReferenceStatistics<char> rstat(0.9);
536*b9df5ad1SAndroid Build Coastguard Worker
537*b9df5ad1SAndroid Build Coastguard Worker // feed the string character by character to the statistics collectors.
538*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; param[i] != '\0'; ++i) {
539*b9df5ad1SAndroid Build Coastguard Worker stat.add(param[i]);
540*b9df5ad1SAndroid Build Coastguard Worker rstat.add(param[i]);
541*b9df5ad1SAndroid Build Coastguard Worker }
542*b9df5ad1SAndroid Build Coastguard Worker
543*b9df5ad1SAndroid Build Coastguard Worker printf("statistics for %s: %s\n", param, stat.toString().c_str());
544*b9df5ad1SAndroid Build Coastguard Worker printf("ref statistics for %s: %s\n", param, rstat.toString().c_str());
545*b9df5ad1SAndroid Build Coastguard Worker // verify that the statistics are the same
546*b9df5ad1SAndroid Build Coastguard Worker verify(stat, rstat);
547*b9df5ad1SAndroid Build Coastguard Worker }
548*b9df5ad1SAndroid Build Coastguard Worker
549*b9df5ad1SAndroid Build Coastguard Worker // find the variance of pet names as signed characters.
550*b9df5ad1SAndroid Build Coastguard Worker const char *pets[] = {"cat", "dog", "elephant", "mountain lion"};
551*b9df5ad1SAndroid Build Coastguard Worker INSTANTIATE_TEST_CASE_P(PetNameStatistics, StatisticsTest,
552*b9df5ad1SAndroid Build Coastguard Worker ::testing::ValuesIn(pets));
553*b9df5ad1SAndroid Build Coastguard Worker
TEST(StatisticsTest,simple_stats)554*b9df5ad1SAndroid Build Coastguard Worker TEST(StatisticsTest, simple_stats)
555*b9df5ad1SAndroid Build Coastguard Worker {
556*b9df5ad1SAndroid Build Coastguard Worker simple_stats_t ss{};
557*b9df5ad1SAndroid Build Coastguard Worker
558*b9df5ad1SAndroid Build Coastguard Worker for (const double value : { -1., 1., 3.}) {
559*b9df5ad1SAndroid Build Coastguard Worker simple_stats_log(&ss, value);
560*b9df5ad1SAndroid Build Coastguard Worker }
561*b9df5ad1SAndroid Build Coastguard Worker
562*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(3., ss.last);
563*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(1., ss.mean);
564*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(-1., ss.min);
565*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(3., ss.max);
566*b9df5ad1SAndroid Build Coastguard Worker PRINT_AND_EXPECT_EQ(3, ss.n);
567*b9df5ad1SAndroid Build Coastguard Worker
568*b9df5ad1SAndroid Build Coastguard Worker char buffer[256];
569*b9df5ad1SAndroid Build Coastguard Worker simple_stats_to_string(&ss, buffer, sizeof(buffer));
570*b9df5ad1SAndroid Build Coastguard Worker printf("simple_stats: %s", buffer);
571*b9df5ad1SAndroid Build Coastguard Worker }
572