/** 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);
}
}
};