123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- #include "bitops.h"
- #include "ymath.h"
- #include <library/cpp/testing/unittest/registar.h>
- #include <util/stream/output.h>
- #include <util/datetime/cputimer.h>
- #include <limits>
- template <class T>
- static inline T SlowClp2(T t) noexcept {
- Y_ASSERT(t > 0);
- T ret = 1;
- while (ret < t) {
- ret *= 2;
- }
- return ret;
- }
- class TMathTest: public TTestBase {
- UNIT_TEST_SUITE(TMathTest);
- UNIT_TEST(TestClp2)
- UNIT_TEST(TestClpSimple)
- UNIT_TEST(TestSqr)
- UNIT_TEST(TestLog2)
- UNIT_TEST(ValueBitCount)
- UNIT_TEST(TestErf);
- UNIT_TEST(TestLogGamma);
- UNIT_TEST(TestIsValidFloat);
- UNIT_TEST(TestAbs);
- UNIT_TEST(TestPower);
- UNIT_TEST(TestSigmoid);
- UNIT_TEST(TestCeilDiv);
- UNIT_TEST_SUITE_END();
- private:
- void TestClp2();
- void TestSqr();
- void TestErf();
- void TestLogGamma();
- void TestAbs();
- void TestPower();
- void TestSigmoid();
- void TestCeilDiv();
- inline void TestIsValidFloat() {
- UNIT_ASSERT(IsValidFloat(-Max<double>() / 2.));
- }
- inline void TestClpSimple() {
- UNIT_ASSERT_EQUAL(FastClp2<ui32>(12), 16);
- UNIT_ASSERT_EQUAL(FastClp2<ui16>(11), 16);
- UNIT_ASSERT_EQUAL(FastClp2<ui8>(10), 16);
- UNIT_ASSERT_EQUAL(FastClp2<ui32>(15), 16);
- UNIT_ASSERT_EQUAL(FastClp2<ui32>(16), 16);
- UNIT_ASSERT_EQUAL(FastClp2<ui32>(17), 32);
- }
- inline void TestLog2() {
- UNIT_ASSERT_DOUBLES_EQUAL(Log2(2.0), 1.0, 1e-10);
- UNIT_ASSERT_DOUBLES_EQUAL(Log2(2ull), 1.0, 1e-10);
- UNIT_ASSERT_DOUBLES_EQUAL(Log2(2.0f), 1.0f, 1e-7f);
- }
- inline void ValueBitCount() {
- UNIT_ASSERT_VALUES_EQUAL(GetValueBitCount(1), 1u);
- UNIT_ASSERT_VALUES_EQUAL(GetValueBitCount(2), 2u);
- UNIT_ASSERT_VALUES_EQUAL(GetValueBitCount(3), 2u);
- UNIT_ASSERT_VALUES_EQUAL(GetValueBitCount(257), 9u);
- }
- };
- UNIT_TEST_SUITE_REGISTRATION(TMathTest);
- void TMathTest::TestSqr() {
- UNIT_ASSERT_EQUAL(Sqr(2), 4);
- UNIT_ASSERT_EQUAL(Sqr(2.0), 4.0);
- }
- void TMathTest::TestClp2() {
- for (ui8 i = 1; i < 127; ++i) {
- UNIT_ASSERT_EQUAL(SlowClp2(i), FastClp2(i));
- }
- for (ui16 i = 1; i < 255; ++i) {
- UNIT_ASSERT_EQUAL(SlowClp2(i), FastClp2(i));
- }
- for (ui32 i = 1; i < 255; ++i) {
- UNIT_ASSERT_EQUAL(SlowClp2(i), FastClp2(i));
- }
- for (ui64 i = 1; i < 255; ++i) {
- UNIT_ASSERT_EQUAL(SlowClp2(i), FastClp2(i));
- }
- if (0) {
- {
- TFuncTimer timer("fast");
- size_t ret = 0;
- for (size_t i = 0; i < 10000000; ++i) {
- ret += FastClp2(i);
- }
- Cerr << ret << Endl;
- }
- {
- TFuncTimer timer("slow");
- size_t ret = 0;
- for (size_t i = 0; i < 10000000; ++i) {
- ret += SlowClp2(i);
- }
- Cerr << ret << Endl;
- }
- }
- }
- void TMathTest::TestErf() {
- static const double a = -5.0;
- static const double b = 5.0;
- static const int n = 50;
- static const double step = (b - a) / n;
- static const double values[n + 1] = {
- -1.0000000, -1.0000000, -1.0000000, -1.0000000, -1.0000000,
- -1.0000000, -0.9999999, -0.9999996, -0.9999985, -0.9999940,
- -0.9999779, -0.9999250, -0.9997640, -0.9993115, -0.9981372,
- -0.9953223, -0.9890905, -0.9763484, -0.9522851, -0.9103140,
- -0.8427008, -0.7421010, -0.6038561, -0.4283924, -0.2227026,
- 0.0000000,
- 0.2227026, 0.4283924, 0.6038561, 0.7421010, 0.8427008,
- 0.9103140, 0.9522851, 0.9763484, 0.9890905, 0.9953223,
- 0.9981372, 0.9993115, 0.9997640, 0.9999250, 0.9999779,
- 0.9999940, 0.9999985, 0.9999996, 0.9999999, 1.0000000,
- 1.0000000, 1.0000000, 1.0000000, 1.0000000, 1.0000000};
- double x = a;
- for (int i = 0; i <= n; ++i, x += step) {
- double f = Erf(x);
- UNIT_ASSERT_DOUBLES_EQUAL(f, values[i], 1e-7);
- }
- }
- void TMathTest::TestLogGamma() {
- double curVal = 0.0;
- for (int i = 1; i <= 20; i++) {
- curVal += log((double)i);
- UNIT_ASSERT_DOUBLES_EQUAL(curVal, LogGamma((double)(i + 1)), 1e-6);
- }
- curVal = log(M_PI) / 2.0;
- for (int i = 1; i <= 20; i++) {
- UNIT_ASSERT_DOUBLES_EQUAL(curVal, LogGamma(i - 0.5), 1e-6);
- curVal += log(i - 0.5);
- }
- }
- void TMathTest::TestAbs() {
- UNIT_ASSERT_VALUES_EQUAL(Abs(1), 1);
- UNIT_ASSERT_VALUES_EQUAL(Abs(-1), 1);
- UNIT_ASSERT_VALUES_EQUAL(Abs(-1000000000000ll), 1000000000000ll);
- UNIT_ASSERT_VALUES_EQUAL(Abs(0), 0);
- UNIT_ASSERT_VALUES_EQUAL(Abs(1.0), 1.0);
- UNIT_ASSERT_VALUES_EQUAL(Abs(-1.0), 1.0);
- UNIT_ASSERT_VALUES_EQUAL(Abs(0.0), 0.0);
- }
- void TMathTest::TestPower() {
- UNIT_ASSERT_VALUES_EQUAL(Power(0, 0), 1);
- UNIT_ASSERT_VALUES_EQUAL(Power(-1, 1), -1);
- UNIT_ASSERT_VALUES_EQUAL(Power(-1, 2), 1);
- UNIT_ASSERT_VALUES_EQUAL(Power(2LL, 32), 1LL << 32);
- UNIT_ASSERT_DOUBLES_EQUAL(Power(0.0, 0), 1.0, 1e-9);
- UNIT_ASSERT_DOUBLES_EQUAL(Power(0.1, 3), 1e-3, 1e-9);
- }
- void TMathTest::TestSigmoid() {
- UNIT_ASSERT_EQUAL(Sigmoid(0.f), 0.5f);
- UNIT_ASSERT_EQUAL(Sigmoid(-5000.f), 0.0f);
- UNIT_ASSERT_EQUAL(Sigmoid(5000.f), 1.0f);
- UNIT_ASSERT_EQUAL(Sigmoid(0.), 0.5);
- UNIT_ASSERT_EQUAL(Sigmoid(-5000.), 0.0);
- UNIT_ASSERT_EQUAL(Sigmoid(5000.), 1.0);
- }
- void TMathTest::TestCeilDiv() {
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<ui8>(2, 3), 1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<ui8>(3, 3), 1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<ui32>(12, 2), 6);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<ui64>(10, 3), 4);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<ui64>(0, 10), 0);
- // negative numbers
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(0, -10), 0);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(-1, 2), 0);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(-1, -2), 1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(10, -5), -2);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(-3, -4), 1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(-6, -4), 2);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(-6, 4), -1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(-13, 4), -3);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv(-14, -4), 4);
- // check values close to overflow
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<ui8>(255, 10), 26);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<ui32>(std::numeric_limits<ui32>::max() - 3, std::numeric_limits<ui32>::max()), 1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<i32>(std::numeric_limits<i32>::max() - 3, std::numeric_limits<i32>::max()), 1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<i32>(std::numeric_limits<i32>::min(), std::numeric_limits<i32>::max()), -1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<i8>(std::numeric_limits<i8>::max(), std::numeric_limits<i8>::min() + 1), -1);
- UNIT_ASSERT_VALUES_EQUAL(CeilDiv<i64>(std::numeric_limits<i64>::max() - 2, -(std::numeric_limits<i64>::min() + 1)), 1);
- }
|