Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-utils.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
38#include <gtest/gtest.h>
39#include "../ahUtils.H"
40#include <vector>
41#include <fstream>
42#include <cstdio>
43
44// Tests for is_even() and is_odd()
45TEST(AhUtilsTest, EvenOdd) {
46 EXPECT_TRUE(Aleph::is_even(0));
47 EXPECT_FALSE(Aleph::is_odd(0));
48 EXPECT_TRUE(Aleph::is_even(2));
49 EXPECT_FALSE(Aleph::is_odd(2));
50 EXPECT_FALSE(Aleph::is_even(1));
51 EXPECT_TRUE(Aleph::is_odd(1));
52 EXPECT_TRUE(Aleph::is_even(-4));
53 EXPECT_FALSE(Aleph::is_odd(-4));
54 EXPECT_FALSE(Aleph::is_even(-5));
55 EXPECT_TRUE(Aleph::is_odd(-5));
56}
57
58// Tests for nibble_to_char() and char_to_nibble()
59TEST(AhUtilsTest, NibbleConversion) {
60 for (int i = 0; i < 16; ++i) {
61 char c = Aleph::nibble_to_char(i);
62 EXPECT_EQ(i, Aleph::char_to_nibble(c));
63 }
64 EXPECT_EQ(Aleph::nibble_to_char(10), 'A');
65 EXPECT_EQ(Aleph::nibble_to_char(15), 'F');
66 EXPECT_EQ(Aleph::char_to_nibble('9'), 9);
67 EXPECT_EQ(Aleph::char_to_nibble('B'), 11);
68
69 // Assertion test (only in debug)
70 #ifndef NDEBUG
71 EXPECT_DEATH(Aleph::nibble_to_char(16), "");
72 EXPECT_DEATH(Aleph::char_to_nibble('G'), "");
73 #endif
74}
75
76// Tests for is_power_of_2() and next_power_of_2()
77TEST(AhUtilsTest, PowerOf2) {
78 EXPECT_TRUE(Aleph::is_power_of_2(1));
79 EXPECT_TRUE(Aleph::is_power_of_2(2));
80 EXPECT_TRUE(Aleph::is_power_of_2(16));
81 EXPECT_TRUE(Aleph::is_power_of_2(1024));
82 EXPECT_FALSE(Aleph::is_power_of_2(0));
83 EXPECT_FALSE(Aleph::is_power_of_2(3));
84 EXPECT_FALSE(Aleph::is_power_of_2(15));
85
86 EXPECT_EQ(Aleph::next_power_of_2(1), 1);
87 EXPECT_EQ(Aleph::next_power_of_2(2), 2);
88 EXPECT_EQ(Aleph::next_power_of_2(3), 4);
89 EXPECT_EQ(Aleph::next_power_of_2(7), 8);
90 EXPECT_EQ(Aleph::next_power_of_2(16), 16);
91 EXPECT_EQ(Aleph::next_power_of_2(17), 32);
92}
93
94// Tests for median()
95TEST(AhUtilsTest, Median) {
97 EXPECT_EQ(*Aleph::median(1, 2, 3, cmp), 2);
98 EXPECT_EQ(*Aleph::median(3, 1, 2, cmp), 2);
99 EXPECT_EQ(*Aleph::median(2, 3, 1, cmp), 2);
100 EXPECT_EQ(*Aleph::median(1, 1, 2, cmp), 1);
101 EXPECT_EQ(*Aleph::median(2, 1, 1, cmp), 1);
102 EXPECT_EQ(*Aleph::median(1, 2, 1, cmp), 1);
103 EXPECT_EQ(*Aleph::median(5, 5, 5, cmp), 5);
104
105 // Test with temporary comparator (thanks to refactoring)
106 EXPECT_EQ(*Aleph::median(10, 20, 15, Aleph::less<int>()), 15);
107}
108
109// Tests for interpolate() and extrapolate_*()
110TEST(AhUtilsTest, Interpolation) {
111 EXPECT_DOUBLE_EQ(Aleph::interpolate(0, 10, 0, 100, 5), 50.0);
112 EXPECT_DOUBLE_EQ(Aleph::interpolate(1, 2, 10, 20, 1.5), 15.0);
113 EXPECT_DOUBLE_EQ(Aleph::extrapolate_left(1, 2, 10, 20, 0), 0.0);
114 EXPECT_DOUBLE_EQ(Aleph::extrapolate_right(1, 2, 10, 20, 3), 30.0);
115
116 EXPECT_DOUBLE_EQ(Aleph::pow2(3.0), 9.0);
117 EXPECT_DOUBLE_EQ(Aleph::pow3(2.0), 8.0);
118}
119
120// Tests for are_near()
121TEST(AhUtilsTest, AreNear) {
122 EXPECT_TRUE(Aleph::are_near(1.0, 1.000001, 1e-5));
123 EXPECT_FALSE(Aleph::are_near(1.0, 1.0001, 1e-5));
124 EXPECT_TRUE(Aleph::are_near(-1.0, -1.000001, 1e-5));
125 EXPECT_FALSE(Aleph::are_near(-1.0, -1.0001, 1e-5));
126
127 // Equal values are within any non-negative tolerance.
128 EXPECT_TRUE(Aleph::are_near(2.5, 2.5, 0.0));
129 // The comparison is inclusive at the tolerance boundary (|v1 - v2| <= e).
130 EXPECT_TRUE(Aleph::are_near(1.0, 1.5, 0.5));
131 // Symmetric in its first two arguments.
132 EXPECT_EQ(Aleph::are_near(3.0, 3.4, 0.5), Aleph::are_near(3.4, 3.0, 0.5));
133
134 // are_near must stay usable in constant expressions: it is constexpr and
135 // computes the absolute difference by hand because std::fabs is not
136 // constexpr in MSVC's STL under C++20.
137 static_assert(Aleph::are_near(1.0, 1.0005, 1e-3));
138 static_assert(not Aleph::are_near(1.0, 2.0, 1e-3));
139}
140
141// Tests for u_index and l_index
142TEST(AhUtilsTest, Indices) {
143 EXPECT_EQ(Aleph::u_index(10), 5);
144 EXPECT_EQ(Aleph::u_index(11), 5);
145 EXPECT_EQ(Aleph::l_index(5), 10);
146}
147
148// Tests for demangle and CLASSNAME_TO_STRING
149struct MyTestStruct {};
150TEST(AhUtilsTest, Demangle) {
151 std::string name = Aleph::demangle(typeid(int).name());
152 EXPECT_EQ(name, "int");
153
154 MyTestStruct s;
155 std::string className = CLASSNAME_TO_STRING(&s);
156 // The exact name may vary depending on the compiler/namespace, but it must contain MyTestStruct
157 EXPECT_TRUE(className.find("MyTestStruct") != std::string::npos);
158}
159
160// Tests for exists_file
161TEST(AhUtilsTest, ExistsFile) {
162 std::string filename = "test_exists_file.tmp";
163 std::ofstream outfile(filename);
164 outfile << "test";
165 outfile.close();
166
167 EXPECT_TRUE(Aleph::exists_file(filename));
168 std::remove(filename.c_str());
169 EXPECT_FALSE(Aleph::exists_file(filename));
170}
171
172// Tests for next_value, prev_value, is_normal_number
173TEST(AhUtilsTest, FloatUtils) {
174 double val = 1.0;
175 EXPECT_GT(Aleph::next_value(val), val);
176 EXPECT_LT(Aleph::prev_value(val), val);
177
178 EXPECT_TRUE(Aleph::is_normal_number(1.0));
179 EXPECT_TRUE(Aleph::is_normal_number(0.0));
180 EXPECT_TRUE(Aleph::is_normal_number(-0.0));
181
182 double inf = std::numeric_limits<double>::infinity();
183 double nan = std::numeric_limits<double>::quiet_NaN();
184
185 EXPECT_FALSE(Aleph::is_normal_number(inf));
186 EXPECT_FALSE(Aleph::is_normal_number(nan));
187}
188
189// Tests for error_msg
190TEST(AhUtilsTest, ErrorMsg) {
191 EXPECT_DEATH(Aleph::error_msg("Test Error"), "Test Error");
192}
193
194// Mock container to test Rvector
196 std::vector<int> data;
197
198 MockContainer(std::initializer_list<int> l) : data(l) {}
199
200 const int& get_first() const { return data.front(); }
201 const int& get_last() const { return data.back(); }
202
203 struct Iterator {
204 std::vector<int>::const_iterator it;
205 std::vector<int>::const_iterator end;
206
207 Iterator(const MockContainer& c) : it(c.data.begin()), end(c.data.end()) {}
208
209 bool has_curr() const { return it != end; }
210 const int& get_curr() const { return *it; }
211 void next() { ++it; }
212 };
213
214 Iterator get_it() const { return Iterator(*this); }
215 // For the second overload of Rvector that uses get_it(1)
216 Iterator get_it(int) const { return Iterator(*this); }
217};
218
219TEST(AhUtilsTest, Rvector) {
220 MockContainer c{1, 2, 3};
221
222 std::string r1 = Aleph::Rvector("vec", c);
223 EXPECT_EQ(r1, "vec <- c(1, 2, 3)");
224
225 // Note: The second overload of Rvector uses c.get_first() as the name
226 // and c.get_it(1) to iterate. In our mock, get_first returns int,
227 // so the name will be "1".
228 std::string r2 = Aleph::Rvector(c);
229 EXPECT_EQ(r2, "1 <- c(1, 2, 3)");
230}
231
232int main(int argc, char **argv) {
233 ::testing::InitGoogleTest(&argc, argv);
234 return RUN_ALL_TESTS();
235}
#define CLASSNAME_TO_STRING(class_ptr)
Given a pointer, it returns the class name.
Definition ahUtils.H:274
int main()
#define TEST(name)
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4129
size_t l_index(const size_t i)
Map a binary heap index to the index of its left child.
Definition ahUtils.H:217
double next_value(const double val)
Return the next representable floating-point value to val
Definition ahUtils.H:437
unsigned long next_power_of_2(unsigned long x)
In x is not exact power of 2, it returns the next power of 2.
Definition ahUtils.H:238
void error_msg(const std::string &msg)
Display message and abort program execution.
Definition ahUtils.H:280
const T * median(const T &a, const T &b, const T &c, const Compare &cmp=Compare())
Return a pointer to the median value among three elements.
Definition ahUtils.H:84
constexpr bool are_near(const double v1, const double v2, const double e) noexcept
Return true if v1 is within absolute distance e of v2.
Definition ahUtils.H:460
double extrapolate_right(const double x1, const double x2, const double y1, const double y2, const double x)
Basic linear extrapolation.
Definition ahUtils.H:423
size_t u_index(const size_t &i)
Map a binary heap index to the index of its parent.
Definition ahUtils.H:203
double interpolate(const double x1, const double x2, const double y1, const double y2, const double x)
Basic linear interpolation.
Definition ahUtils.H:359
double prev_value(const double val)
Return the next representable floating-point value of val towards the smallest positive normal number...
Definition ahUtils.H:450
bool is_even(const long n)
Return true if n is even.
Definition ahUtils.H:105
bool is_odd(const long n)
Return true if n is odd.
Definition ahUtils.H:114
double pow2(const double x)
Return x^2.
Definition ahUtils.H:396
char nibble_to_char(const int i)
Convert a 4-bit nibble stored in an int to its hex character.
Definition ahUtils.H:125
bool exists_file(const std::string &name)
Return true if it exists a file of name
Definition ahUtils.H:290
int char_to_nibble(const char c)
Convert a hex character in 0..9A..F to its 4-bit nibble value.
Definition ahUtils.H:140
std::string Rvector(const std::string &name, const C &c)
Return a string with R specification of a vector with name and data stored in container c
Definition ahUtils.H:302
bool is_normal_number(const double n)
Return true if a floating-point number is normal or zero.
Definition ahUtils.H:501
std::string demangle(const char *name)
Given a linker symbol name generated by a c++ compiler, this functions decodes it into a user level n...
Definition ahUtils.H:255
double extrapolate_left(const double x1, const double x2, const double y1, const double y2, const double x)
Basic linear extrapolation.
Definition ahUtils.H:383
double pow3(const double x)
Return x^3.
Definition ahUtils.H:404
bool is_power_of_2(unsigned long x)
Taken from http://stackoverflow.com/questions/3638431/determine-if-an-int-is-a-power-of-2-or-not-in-a...
Definition ahUtils.H:228
std::vector< int >::const_iterator end
Definition ah-utils.cc:205
Iterator(const MockContainer &c)
Definition ah-utils.cc:207
std::vector< int >::const_iterator it
Definition ah-utils.cc:204
bool has_curr() const
Definition ah-utils.cc:209
const int & get_curr() const
Definition ah-utils.cc:210
Iterator get_it() const
Definition ah-utils.cc:214
const int & get_last() const
Definition ah-utils.cc:201
MockContainer(std::initializer_list< int > l)
Definition ah-utils.cc:198
std::vector< int > data
Definition ah-utils.cc:196
const int & get_first() const
Definition ah-utils.cc:200
Iterator get_it(int) const
Definition ah-utils.cc:216
DynList< int > l