OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-cogutil / tests / util / numericUTest.cxxtest

237 lines · cxxtest ref:
/** numericUTest.cxxtest ---
 *
 * Copyright (C) 2010 OpenCog Foundation
 *
 * Author: Nil Geisweiller <ngeiswei@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <iomanip>
#include <opencog/util/numeric.h>

using namespace std;
using namespace opencog;

class numericUTest : public CxxTest::TestSuite
{
public:

    void test_is_approx_eq_ulp()
    {
        double d1 = 0.1,
               d2 = 3,
               d3 = 0.3,
               d4 = d1 * d2;

        cout << "\n";
        cout << "test_is_approx_eq_ulp:\n";
        cout << setprecision(32) << "d1: " << d1 << endl
                                 << "d2: " << d2 << endl
                                 << "d3: " << d3 << endl
                                 << "d4: " << d4 << endl;
        TS_ASSERT(not (d3 == d4))

// Allow as many as 24 bits to be different.
#define COMPARE_ULPS 24
        TS_ASSERT(is_approx_eq_ulp(d3, d4, COMPARE_ULPS))

        double d5 = -0.0000000000000000000000000000001,
               d6 =  0.0000000000000000000000000000001;

        TS_ASSERT(not is_approx_eq_ulp(d5, d6, COMPARE_ULPS))
        TS_ASSERT(not is_approx_eq_ulp(d5, 0.0, COMPARE_ULPS))
    }

    void test_integer_log2()
    {
        unsigned
            res_0 = integer_log2(0),
            res_1 = integer_log2(1),
            res_2 = integer_log2(2),
            res_3 = integer_log2(3),
            res_4 = integer_log2(4),
            res_5 = integer_log2(5);

        cout << "test_integer_log2: ";
        cout << res_0 << " " << res_1 << " " << res_2 << " "
             << res_3 << " " << res_4 << " " << res_5 << endl;

        TS_ASSERT_EQUALS(res_0, 0);
        TS_ASSERT_EQUALS(res_1, 0);
        TS_ASSERT_EQUALS(res_2, 1);
        TS_ASSERT_EQUALS(res_3, 1);
        TS_ASSERT_EQUALS(res_4, 2);
        TS_ASSERT_EQUALS(res_5, 2);
    }

    void test_next_power_of_two()
    {
        TS_ASSERT_THROWS_ANYTHING(next_power_of_two(0));

        unsigned
            res_1 = next_power_of_two(1),
            res_2 = next_power_of_two(2),
            res_3 = next_power_of_two(3),
            res_4 = next_power_of_two(4),
            res_5 = next_power_of_two(5),
            res_50 = next_power_of_two(50),
            res_255 = next_power_of_two(255),
            res_256 = next_power_of_two(256),
            res_257 = next_power_of_two(257);

        cout << "test_next_power_of_two: ";
        cout << res_1 << " " << res_2 << " " << res_3 << " "
             << res_4 << " " << res_5 << " "
             << res_50 << " " << res_255 << " "
             << res_256 << " " << res_257 << endl;

        TS_ASSERT_EQUALS(res_1, 1);
        TS_ASSERT_EQUALS(res_2, 2);
        TS_ASSERT_EQUALS(res_3, 4);
        TS_ASSERT_EQUALS(res_4, 4);
        TS_ASSERT_EQUALS(res_5, 8);
        TS_ASSERT_EQUALS(res_50, 64);
        TS_ASSERT_EQUALS(res_255, 256);
        TS_ASSERT_EQUALS(res_256, 256);
        TS_ASSERT_EQUALS(res_257, 512);
    }

    void test_nbits_to_pack()
    {
        TS_ASSERT_THROWS_ANYTHING(nbits_to_pack(0));
        unsigned
            res_1 = nbits_to_pack(1),
            res_2 = nbits_to_pack(2),
            res_3 = nbits_to_pack(3),
            res_4 = nbits_to_pack(4),
            res_5 = nbits_to_pack(5),
            res_50 = nbits_to_pack(50),
            res_257 = nbits_to_pack(257);

        cout << "test_nbits_to_pack: ";
        cout << res_1 << " " << res_2 << " " << res_3 << " "
             << res_4 << " " << res_5 << " "
             << res_50 << " " << res_257 << endl;

        TS_ASSERT_EQUALS(res_1, 1);
        TS_ASSERT_EQUALS(res_2, 1);
        TS_ASSERT_EQUALS(res_3, 2);
        TS_ASSERT_EQUALS(res_4, 2);
        TS_ASSERT_EQUALS(res_5, 4);
        TS_ASSERT_EQUALS(res_50, 8);
        TS_ASSERT_EQUALS(res_257, 16);
    }

    void test_tanimoto_distance()
    {
        typedef vector<float> Vec;
        // test max distance
        {
            Vec a = {1, 0, 1, 0, 1, 0, 1},
                b = {0, 1, 0, 1, 0, 1, 0};

            float dst = tanimoto_distance<Vec, float>(a, b);
            TS_ASSERT_EQUALS(dst, 1);
        }

        // test min distance
        {
            Vec a = {1, 0, 1, 0, 1, 0, 1},
                b = {1, 0, 1, 0, 1, 0, 1};

            float dst = tanimoto_distance<Vec, float>(a, b);
            TS_ASSERT_EQUALS(dst, 0);
        }

        // test in between distance
        {
            Vec a = {0, 1, 1, 1, 1, 1, 0},
                b = {1, 0, 1, 0, 1, 0, 1};

            float dst = tanimoto_distance<Vec, float>(a, b);
            TS_ASSERT_DELTA(dst, 1 - 2.0/7.0, 0.00001);
        }

        // test in between distance float
        {
            Vec a = {0, .1, .1, .1, .1, .1, 0},
                b = {.1, 0, .1,  0, .1, 0, .1};

            float dst = tanimoto_distance<Vec, float>(a, b);
            TS_ASSERT_DELTA(dst, 1 - 0.02/0.07, 0.00001);
        }

        // test null case
        {
            Vec a = {0, 0, 0, 0, 0, 0, 0},
                b = {0, 0, 0, 0, 0, 0, 0};

            float dst = tanimoto_distance<Vec, float>(a, b);
            TS_ASSERT_DELTA(dst, 0, 0.000001);
        }
    }

    void test_angular_distance()
    {
        typedef vector<float> Vec;
        // test max distance
        {
            Vec a = {1, 0, 1, 0, 1, 0, 1},
                b = {0, 1, 0, 1, 0, 1, 0};

            float dst = angular_distance<Vec, float>(a, b, false);
            TS_ASSERT_EQUALS(dst, 1);
        }

        // test min distance
        {
            Vec a = {1, 0, 1, 0, 1, 0, 1},
                b = {1, 0, 1, 0, 1, 0, 1};

            float dst = angular_distance<Vec, float>(a, b, false);
            TS_ASSERT_EQUALS(dst, 0);
        }

        // test in between distance
        {
            Vec a = {0, 1, 1, 1, 1, 1, 0},
                b = {1, 0, 1, 0, 1, 0, 1};

            float dst = angular_distance<Vec, float>(a, b, false);
            TS_ASSERT_DELTA(dst, 2 * acos(2.0 / (sqrt(5 * 4))) / M_PI, 0.00001);
        }

        // test in between distance float
        {
            Vec a = {0, .1, .1, .1, .1, .1, 0},
                b = {.1, 0, .1, 0, .1, 0, .1};

            float dst = angular_distance<Vec, float>(a, b, false);
            TS_ASSERT_DELTA(dst, 2 * acos(.02 / (sqrt(.05 * .04))) / M_PI, 0.00001);
        }

        // test null case
        {
            Vec a = {0, 0, 0, 0, 0, 0, 0},
                b = {0, 0, 0, 0, 0, 0, 0};

                float dst = angular_distance<Vec, float>(a, b, false);
            TS_ASSERT_EQUALS(dst, 0);
        }
    }
};