1 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors. 2 // https://github.com/Dobiasd/FunctionalPlus 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #include <doctest/doctest.h> 8 #include <fplus/fplus.hpp> 9 #include <vector> 10 11 namespace { 12 mod2(int x)13 int mod2(int x) 14 { 15 return x % 2; 16 } 17 mod7(int x)18 int mod7(int x) 19 { 20 return x % 7; 21 } 22 string_length(const std::string & s)23 std::size_t string_length(const std::string& s) 24 { 25 return s.size(); 26 } 27 28 typedef std::vector<int> Ints; 29 typedef std::vector<float> Floats; 30 typedef std::vector<double> Doubles; 31 } 32 33 TEST_CASE("numeric_test - is_in_interval") 34 { 35 REQUIRE(fplus::is_in_interval(1, 3, 1)); 36 REQUIRE(fplus::is_in_interval(1, 3, 2)); 37 REQUIRE_FALSE(fplus::is_in_interval(1, 3, 0)); 38 REQUIRE_FALSE(fplus::is_in_interval(1, 3, 3)); 39 REQUIRE(fplus::is_in_closed_interval(1, 3, 1)); 40 REQUIRE(fplus::is_in_closed_interval(1, 3, 2)); 41 REQUIRE(fplus::is_in_closed_interval(1, 3, 3)); 42 REQUIRE_FALSE(fplus::is_in_open_interval(1, 3, 1)); 43 REQUIRE(fplus::is_in_open_interval(1, 3, 2)); 44 REQUIRE_FALSE(fplus::is_in_open_interval(1, 3, 3)); 45 REQUIRE(fplus::is_in_interval(0.09, 0.11, fplus::abs(-0.1))); 46 REQUIRE(fplus::is_in_interval(0.09, 0.11, fplus::abs( 0.1))); 47 } 48 49 TEST_CASE("numeric_test - is_in_interval_around") 50 { 51 REQUIRE_FALSE(fplus::is_in_interval_around(0.1, 2.0, 1.85)); 52 REQUIRE(fplus::is_in_interval_around(0.1, 2.0, 1.95)); 53 REQUIRE(fplus::is_in_interval_around(0.1, 2.0, 2.05)); 54 REQUIRE_FALSE(fplus::is_in_interval_around(0.1, 2.0, 2.15)); 55 56 REQUIRE(fplus::is_in_interval_around(1, 2, 1)); 57 REQUIRE_FALSE(fplus::is_in_interval_around(1, 2, 3)); 58 } 59 60 TEST_CASE("numeric_test - is_in_open_interval_around") 61 { 62 REQUIRE_FALSE(fplus::is_in_open_interval_around(0.1, 2.0, 1.85)); 63 REQUIRE(fplus::is_in_open_interval_around(0.1, 2.0, 1.95)); 64 REQUIRE(fplus::is_in_open_interval_around(0.1, 2.0, 2.05)); 65 REQUIRE_FALSE(fplus::is_in_open_interval_around(0.1, 2.0, 2.15)); 66 67 REQUIRE_FALSE(fplus::is_in_open_interval_around(1, 2, 1)); 68 REQUIRE_FALSE(fplus::is_in_open_interval_around(1, 2, 3)); 69 } 70 71 TEST_CASE("numeric_test - is_in_closed_interval_around") 72 { 73 REQUIRE_FALSE(fplus::is_in_closed_interval_around(0.1, 2.0, 1.85)); 74 REQUIRE(fplus::is_in_closed_interval_around(0.1, 2.0, 1.95)); 75 REQUIRE(fplus::is_in_closed_interval_around(0.1, 2.0, 2.05)); 76 REQUIRE_FALSE(fplus::is_in_closed_interval_around(0.1, 2.0, 2.15)); 77 78 REQUIRE(fplus::is_in_closed_interval_around(1, 2, 1)); 79 REQUIRE(fplus::is_in_closed_interval_around(1, 2, 3)); 80 } 81 82 TEST_CASE("numeric_test - is_negative") 83 { 84 REQUIRE(fplus::is_negative(-0.1)); 85 REQUIRE_FALSE(fplus::is_negative(0.1)); 86 } 87 88 TEST_CASE("numeric_test - is_positive") 89 { 90 REQUIRE(fplus::is_positive(0.1)); 91 REQUIRE_FALSE(fplus::is_positive(-0.1)); 92 } 93 94 TEST_CASE("numeric_test - is_even") 95 { 96 REQUIRE(fplus::is_even(2)); 97 REQUIRE(fplus::is_even(-2)); 98 REQUIRE_FALSE(fplus::is_even(3)); 99 REQUIRE_FALSE(fplus::is_even(-3)); 100 } 101 102 TEST_CASE("numeric_test - is_odd") 103 { 104 REQUIRE(fplus::is_odd(1)); 105 REQUIRE(fplus::is_odd(-1)); 106 REQUIRE_FALSE(fplus::is_odd(2)); 107 REQUIRE_FALSE(fplus::is_odd(-2)); 108 } 109 110 TEST_CASE("numeric_test - sign") 111 { 112 REQUIRE_EQ(fplus::sign(0.1), 1); 113 REQUIRE_EQ(fplus::sign(-0.1), -1); 114 } 115 116 TEST_CASE("numeric_test - abs_diff") 117 { 118 REQUIRE_EQ(fplus::abs_diff<signed int>(3, 5), 2); 119 REQUIRE_EQ(fplus::abs_diff<signed int>(5, 3), 2); 120 REQUIRE_EQ(fplus::abs_diff<unsigned int>(3, 5), 2); 121 REQUIRE_EQ(fplus::abs_diff<unsigned int>(5, 3), 2); 122 } 123 124 TEST_CASE("numeric_test - cyclic_value") 125 { 126 using namespace fplus; 127 REQUIRE_EQ(cyclic_value(8.0)(3), 3); 128 REQUIRE_EQ(cyclic_value(8.0)(11), 3); 129 REQUIRE_EQ(cyclic_value(8.0)(19), 3); 130 REQUIRE_EQ(cyclic_value(8.0)(-2), 6); 131 REQUIRE_EQ(cyclic_value(8.0)(-5), 3); 132 REQUIRE_EQ(cyclic_value(8.0)(-13), 3); 133 134 REQUIRE_EQ(cyclic_value(8)(3), 3); 135 REQUIRE_EQ(cyclic_value(8)(11), 3); 136 REQUIRE_EQ(cyclic_value(8)(19), 3); 137 REQUIRE_EQ(cyclic_value(8)(-2), 6); 138 REQUIRE_EQ(cyclic_value(8)(-5), 3); 139 REQUIRE_EQ(cyclic_value(8)(-13), 3); 140 141 REQUIRE_EQ(cyclic_value<unsigned int>(8)(3), 3); 142 REQUIRE_EQ(cyclic_value<unsigned int>(8)(11), 3); 143 REQUIRE_EQ(cyclic_value<unsigned int>(8)(19), 3); 144 145 REQUIRE(is_in_interval(3.19, 3.21, cyclic_value(8.1)(3.2))); 146 } 147 148 TEST_CASE("numeric_test - cyclic_difference") 149 { 150 using namespace fplus; 151 REQUIRE_EQ(cyclic_difference(100)(5, 2), 3); 152 REQUIRE_EQ(cyclic_difference(100)(2, 5), 97); 153 REQUIRE_EQ(cyclic_difference(100)(3, -2), 5); 154 REQUIRE_EQ(cyclic_difference(100)(-2, 3), 95); 155 REQUIRE_EQ(cyclic_difference(100)(90, 10), 80); 156 REQUIRE_EQ(cyclic_difference(100)(10, 90), 20); 157 158 REQUIRE_EQ(cyclic_difference<unsigned int>(100)(5, 2), 3); 159 REQUIRE_EQ(cyclic_difference<unsigned int>(100)(2, 5), 97); 160 REQUIRE_EQ(cyclic_difference<unsigned int>(100)(90, 10), 80); 161 REQUIRE_EQ(cyclic_difference<unsigned int>(100)(10, 90), 20); 162 } 163 164 TEST_CASE("numeric_test - cyclic_shortest_difference") 165 { 166 using namespace fplus; 167 REQUIRE_EQ(cyclic_shortest_difference(100)(5, 2), 3); 168 REQUIRE_EQ(cyclic_shortest_difference(100)(2, 5), -3); 169 REQUIRE_EQ(cyclic_shortest_difference(100)(3, -2), 5); 170 REQUIRE_EQ(cyclic_shortest_difference(100)(-2, 3), -5); 171 REQUIRE_EQ(cyclic_shortest_difference(100)(90, 10), -20); 172 REQUIRE_EQ(cyclic_shortest_difference(100)(10, 90), 20); 173 } 174 175 TEST_CASE("numeric_test - cyclic_distance") 176 { 177 using namespace fplus; 178 REQUIRE_EQ(cyclic_distance(100)(2, 5), 3); 179 REQUIRE_EQ(cyclic_distance(100)(5, 2), 3); 180 REQUIRE_EQ(cyclic_distance(100)(-2, 3), 5); 181 REQUIRE_EQ(cyclic_distance(100)(3, -2), 5); 182 REQUIRE_EQ(cyclic_distance(100)(10, 90), 20); 183 REQUIRE_EQ(cyclic_distance(100)(90, 10), 20); 184 185 REQUIRE_EQ(cyclic_distance<unsigned int>(100)(2, 5), 3); 186 REQUIRE_EQ(cyclic_distance<unsigned int>(100)(5, 2), 3); 187 REQUIRE_EQ(cyclic_distance<unsigned int>(100)(10, 90), 20); 188 REQUIRE_EQ(cyclic_distance<unsigned int>(100)(90, 10), 20); 189 } 190 191 TEST_CASE("numeric_test - round") 192 { 193 // using namespace fplus; // round is also defined in tgmath.h under msvc 194 REQUIRE_EQ(round(1.4), 1); 195 REQUIRE_EQ(round(1.5), 2); 196 REQUIRE_EQ(round(1.6), 2); 197 198 REQUIRE_EQ((fplus::round<double, unsigned char>(254.9)), 255); 199 REQUIRE_EQ((fplus::round<double, unsigned char>(300.0)), 255); 200 REQUIRE_EQ((fplus::round<double, unsigned char>(-0.0000001)), 0); 201 REQUIRE_EQ((fplus::round<double, unsigned char>(-5.0)), 0); 202 203 REQUIRE_EQ(fplus::round(-1.4), -1); 204 REQUIRE_EQ(fplus::round(-1.6), -2); 205 } 206 207 TEST_CASE("numeric_test - integral_cast_clamp") 208 { 209 using namespace fplus; 210 REQUIRE_EQ(integral_cast_clamp<std::uint8_t>(std::int32_t(-1)), std::uint8_t(0)); 211 REQUIRE_EQ(integral_cast_clamp<std::uint8_t>(std::int32_t(0)), std::uint8_t(0)); 212 REQUIRE_EQ(integral_cast_clamp<std::uint8_t>(std::int32_t(3)), std::uint8_t(3)); 213 REQUIRE_EQ(integral_cast_clamp<std::uint8_t>(std::int32_t(255)), std::uint8_t(255)); 214 REQUIRE_EQ(integral_cast_clamp<std::uint8_t>(std::int32_t(256)), std::uint8_t(255)); 215 216 REQUIRE_EQ(integral_cast_clamp<std::int8_t>(std::int32_t(-129)), std::int8_t(-128)); 217 REQUIRE_EQ(integral_cast_clamp<std::int8_t>(std::int32_t(-128)), std::int8_t(-128)); 218 REQUIRE_EQ(integral_cast_clamp<std::int8_t>(std::int32_t(3)), std::int8_t(3)); 219 REQUIRE_EQ(integral_cast_clamp<std::int8_t>(std::int32_t(127)), std::int8_t(127)); 220 REQUIRE_EQ(integral_cast_clamp<std::int8_t>(std::int32_t(128)), std::int8_t(127)); 221 222 REQUIRE_EQ(integral_cast_clamp<std::int8_t>(std::uint8_t(0)), std::int8_t(0)); 223 REQUIRE_EQ(integral_cast_clamp<std::int8_t>(std::uint8_t(127)), std::int8_t(127)); 224 REQUIRE_EQ(integral_cast_clamp<std::int8_t>(std::uint8_t(128)), std::int8_t(127)); 225 226 REQUIRE_EQ(integral_cast_clamp<std::uint64_t>(std::numeric_limits<std::uint16_t>::lowest()), static_cast<std::int64_t>(std::numeric_limits<std::uint16_t>::lowest())); 227 REQUIRE_EQ(integral_cast_clamp<std::uint64_t>(std::uint16_t(0)), std::uint64_t(0)); 228 REQUIRE_EQ(integral_cast_clamp<std::uint64_t>(std::numeric_limits<std::uint16_t>::max()), static_cast<std::int64_t>(std::numeric_limits<std::uint16_t>::max())); 229 230 REQUIRE_EQ(integral_cast_clamp<std::int64_t>(std::numeric_limits<std::int16_t>::lowest()), static_cast<std::int64_t>(std::numeric_limits<std::int16_t>::lowest())); 231 REQUIRE_EQ(integral_cast_clamp<std::int64_t>(std::int16_t(0)), std::int64_t(0)); 232 REQUIRE_EQ(integral_cast_clamp<std::int64_t>(std::numeric_limits<std::int16_t>::max()), static_cast<std::int64_t>(std::numeric_limits<std::int16_t>::max())); 233 } 234 235 TEST_CASE("numeric_test - ceil") 236 { 237 using namespace fplus; 238 REQUIRE_EQ(ceil(1.4), 2); 239 REQUIRE_EQ(ceil(-1.4), -1); 240 } 241 242 TEST_CASE("numeric_test - floor") 243 { 244 using namespace fplus; 245 REQUIRE_EQ(floor(1.4), 1); 246 REQUIRE_EQ(floor(-1.4), -2); 247 } 248 249 TEST_CASE("numeric_test - floor_to_int_mult") 250 { 251 using namespace fplus; 252 REQUIRE_EQ(floor_to_int_mult(2, -3), -4); 253 REQUIRE_EQ(floor_to_int_mult(2, -2), -2); 254 REQUIRE_EQ(floor_to_int_mult(2, -1), -2); 255 REQUIRE_EQ(floor_to_int_mult(2, 0), 0); 256 REQUIRE_EQ(floor_to_int_mult(2, 1), 0); 257 REQUIRE_EQ(floor_to_int_mult(2, 2), 2); 258 REQUIRE_EQ(floor_to_int_mult(2, 3), 2); 259 REQUIRE_EQ(floor_to_int_mult<unsigned char>(2, 0), 0); 260 REQUIRE_EQ(floor_to_int_mult<unsigned char>(2, 1), 0); 261 REQUIRE_EQ(floor_to_int_mult<unsigned char>(2, 2), 2); 262 REQUIRE_EQ(floor_to_int_mult<unsigned char>(2, 3), 2); 263 264 REQUIRE_EQ(floor_to_int_mult(1, -1), -1); 265 REQUIRE_EQ(floor_to_int_mult(1, 0), 0); 266 REQUIRE_EQ(floor_to_int_mult(1, 1), 1); 267 } 268 269 TEST_CASE("numeric_test - ceil_to_int_mult") 270 { 271 using namespace fplus; 272 REQUIRE_EQ(ceil_to_int_mult(2, -3), -2); 273 REQUIRE_EQ(ceil_to_int_mult(2, -2), -2); 274 REQUIRE_EQ(ceil_to_int_mult(2, -1), -0); 275 REQUIRE_EQ(ceil_to_int_mult(2, 0), 0); 276 REQUIRE_EQ(ceil_to_int_mult(2, 1), 2); 277 REQUIRE_EQ(ceil_to_int_mult(2, 2), 2); 278 REQUIRE_EQ(ceil_to_int_mult(2, 3), 4); 279 REQUIRE_EQ(ceil_to_int_mult<unsigned char>(2, 0), 0); 280 REQUIRE_EQ(ceil_to_int_mult<unsigned char>(2, 1), 2); 281 REQUIRE_EQ(ceil_to_int_mult<unsigned char>(2, 2), 2); 282 REQUIRE_EQ(ceil_to_int_mult<unsigned char>(2, 3), 4); 283 284 REQUIRE_EQ(ceil_to_int_mult(1, -1), -1); 285 REQUIRE_EQ(ceil_to_int_mult(1, 0), 0); 286 REQUIRE_EQ(ceil_to_int_mult(1, 1), 1); 287 } 288 289 TEST_CASE("numeric_test - reference_interval") 290 { 291 using namespace fplus; 292 REQUIRE_EQ(reference_interval(2, 6, 0, 4, 3), 5); 293 REQUIRE_EQ(reference_interval(2, 10, 0, 4, 3), 8); 294 REQUIRE_EQ(reference_interval(2, 6, 0, 4, -1), 1); 295 REQUIRE_EQ(reference_interval(2, 10, 0, 4, -1), 0); 296 } 297 298 TEST_CASE("numeric_test - clamp") 299 { 300 using namespace fplus; 301 REQUIRE_EQ(clamp(2, 6, 5), 5); 302 REQUIRE_EQ(clamp(2, 6, 1), 2); 303 REQUIRE_EQ(clamp(2, 6, 8), 6); 304 } 305 306 TEST_CASE("numeric_test - int_power") 307 { 308 using namespace fplus; 309 REQUIRE_EQ(int_power(3, 0), 1); 310 REQUIRE_EQ(int_power(3, 1), 3); 311 REQUIRE_EQ(int_power(3, 2), 9); 312 REQUIRE_EQ(int_power(3, 3), 27); 313 REQUIRE_EQ(int_power(3, 4), 81); 314 } 315 316 TEST_CASE("numeric_test - min_on") 317 { 318 REQUIRE_EQ(fplus::min_on(mod2)(4, 4), 4); 319 REQUIRE_EQ(fplus::min_on(mod2)(4, 3), 4); 320 REQUIRE_EQ(fplus::min_on(mod2)(4, 3, 7), 4); 321 REQUIRE_EQ(fplus::min_on(mod2)(5, 3, 7), 5); 322 REQUIRE_EQ(fplus::min_on(mod2)(5, 3, 7, 9, 2), 2); 323 REQUIRE_EQ(fplus::min_on(mod2)(5, 3, 7, 13, 19, 4), 4); 324 325 REQUIRE_EQ(fplus::min_on(mod7)(4, 4), 4); 326 REQUIRE_EQ(fplus::min_on(mod7)(4, 3), 3); 327 REQUIRE_EQ(fplus::min_on(mod7)(4, 3, 7), 7); 328 REQUIRE_EQ(fplus::min_on(mod7)(5, 3, 7, 9, 9), 7); 329 REQUIRE_EQ(fplus::min_on(mod7)(5, 3, 7, 9, 9, 6, 6, 6, 6, 6, 6), 7); 330 REQUIRE_EQ(fplus::min_on(mod7)(70, 3, 7, 9, 9, 6, 6, 6, 6, 6, 6), 70); 331 332 const std::string s1("AAA"); 333 const std::string s2("AAABB"); 334 const std::string s3("AAABBCCC"); 335 REQUIRE_EQ(fplus::min_on(string_length)(s1, s2), s1); 336 REQUIRE_EQ(fplus::min_on(string_length)(s2, s3), s2); 337 REQUIRE_EQ(fplus::min_on(string_length)(s1, s2, s3), s1); 338 REQUIRE_EQ(fplus::min_on(string_length)(s1, s3), s1); 339 340 auto l1_min_on = fplus::min_on(mod7); 341 REQUIRE_EQ(l1_min_on(1), 1); 342 REQUIRE_EQ(l1_min_on(1, 2), 1); 343 REQUIRE_EQ(l1_min_on(1, 2, 3, 7), 7); 344 REQUIRE_EQ(l1_min_on(1, 2, 3, 6, 77), 77); 345 REQUIRE_EQ(fplus::min_on(mod7)(1), 1); 346 REQUIRE_EQ(fplus::min_on(mod7)(1, 2), 1); 347 REQUIRE_EQ(fplus::min_on(mod7)(1, 2, 3, 7), 7); 348 REQUIRE_EQ(fplus::min_on(mod7)(1, 2, 3, 6, 77), 77); 349 } 350 351 TEST_CASE("numeric_test - max_on") 352 { 353 REQUIRE_EQ(fplus::max_on(mod2)(4, 4), 4); 354 REQUIRE_EQ(fplus::max_on(mod2)(4, 3), 3); 355 REQUIRE_EQ(fplus::max_on(mod2)(4, 3, 7), 3); 356 REQUIRE_EQ(fplus::max_on(mod2)(5, 3, 7), 5); 357 REQUIRE_EQ(fplus::max_on(mod2)(5, 3, 7, 9, 2), 5); 358 REQUIRE_EQ(fplus::max_on(mod2)(5, 3, 7, 13, 19, 4), 5); 359 360 REQUIRE_EQ(fplus::max_on(mod7)(4, 4), 4); 361 REQUIRE_EQ(fplus::max_on(mod7)(4, 3), 4); 362 REQUIRE_EQ(fplus::max_on(mod7)(4, 3, 7), 4); 363 REQUIRE_EQ(fplus::max_on(mod7)(5, 3, 7, 9, 9), 5); 364 REQUIRE_EQ(fplus::max_on(mod7)(5, 3, 7, 9, 9, 6, 6, 6, 6, 6, 6), 6); 365 REQUIRE_EQ(fplus::max_on(mod7)(70, 3, 7, 9, 9, 6, 6, 6, 6, 6, 6), 6); 366 367 const std::string s1("AAA"); 368 const std::string s2("AAABB"); 369 const std::string s3("AAABBCCC"); 370 REQUIRE_EQ(fplus::max_on(string_length)(s1, s2), s2); 371 REQUIRE_EQ(fplus::max_on(string_length)(s2, s3), s3); 372 REQUIRE_EQ(fplus::max_on(string_length)(s1, s2, s3), s3); 373 REQUIRE_EQ(fplus::max_on(string_length)(s1, s3), s3); 374 375 auto l1_max_on = fplus::max_on(mod7); 376 REQUIRE_EQ(l1_max_on(1), 1); 377 REQUIRE_EQ(l1_max_on(1, 2), 2); 378 REQUIRE_EQ(l1_max_on(1, 2, 3, 7), 3); 379 REQUIRE_EQ(l1_max_on(1, 2, 3, 6, 77), 6); 380 REQUIRE_EQ(fplus::max_on(mod7)(1), 1); 381 REQUIRE_EQ(fplus::max_on(mod7)(1, 2), 2); 382 REQUIRE_EQ(fplus::max_on(mod7)(1, 2, 3, 7), 3); 383 REQUIRE_EQ(fplus::max_on(mod7)(1, 2, 3, 6, 77), 6); 384 } 385 386 TEST_CASE("numeric_test - mean") 387 { 388 using namespace fplus; 389 Ints xs = {1,4,4}; 390 REQUIRE_EQ(mean<int>(xs), 3); 391 } 392 393 TEST_CASE("numeric_test - mean_obj") 394 { 395 using namespace fplus; 396 struct vec_2d 397 { 398 double x; 399 double y; operator +vec_2d400 vec_2d operator + (const vec_2d& rhs) const 401 { 402 return {x + rhs.x, y + rhs.y}; 403 }; operator /vec_2d404 vec_2d operator / (double scalar) const 405 { 406 double scalar_d = static_cast<double>(scalar); 407 return {x / scalar_d, y / scalar_d}; 408 }; operator /vec_2d409 vec_2d operator / (std::size_t scalar) const 410 { 411 return *this / static_cast<double>(scalar); 412 }; 413 }; 414 415 auto vec_2d_length_squared = [](const vec_2d& v) -> double __anon71ed84a80202(const vec_2d& v) 416 { 417 return v.x * v.x + v.y * v.y; 418 }; 419 std::vector<vec_2d> vecs = {{1,1}, {3,3}}; 420 auto mean_vec_div_double = mean_obj_div_double(vecs); 421 auto mean_vec_div_size_t = mean_obj_div_size_t(vecs); 422 double mean_vec_length_squared_dest = 2*2 + 2*2; 423 REQUIRE(is_in_interval_around(0.001, mean_vec_length_squared_dest, 424 vec_2d_length_squared(mean_vec_div_double))); 425 REQUIRE(is_in_interval_around(0.001, mean_vec_length_squared_dest, 426 vec_2d_length_squared(mean_vec_div_size_t))); 427 } 428 429 TEST_CASE("numeric_test - variadic") 430 { 431 using namespace fplus; 432 REQUIRE_EQ(min(1,2,3,4,5), 1); 433 REQUIRE_EQ(min(1.01,1.02,1.03,1.04,1.05), 1.01); 434 REQUIRE_EQ(min(-54,2,3,54,5), -54); 435 REQUIRE_EQ(min(-54.2,2.7,3,54,5), -54.2); 436 REQUIRE_EQ(min(123,123,123,124), 123); 437 REQUIRE_EQ(min(123), 123); 438 REQUIRE_EQ(min(123,123), 123); 439 REQUIRE_EQ(min(123,123,123), 123); 440 REQUIRE_EQ(min(-1), -1); 441 REQUIRE_EQ(min(-1,-2), -2); 442 REQUIRE_EQ(min(-1,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), -2); 443 REQUIRE_EQ(min('a','b','c'), 'a'); 444 445 REQUIRE_EQ(max(1,2,3,4,5), 5); 446 REQUIRE_EQ(max(1.01,1.02,1.03,1.04,1.05), 1.05); 447 REQUIRE_EQ(max(-54,2,3,54,5), 54); 448 REQUIRE_EQ(max(-54.2,2.7,3,54.85,5), 54.85); 449 REQUIRE_EQ(max(123,123,123,124), 124); 450 REQUIRE_EQ(max(123), 123); 451 REQUIRE_EQ(max(123,123), 123); 452 REQUIRE_EQ(max(123,123,123), 123); 453 REQUIRE_EQ(max(123,123,123,123), 123); 454 REQUIRE_EQ(max(123,123,123,123,123), 123); 455 REQUIRE_EQ(max(123,123,123,123,123,123), 123); 456 REQUIRE_EQ(max(-1), -1); 457 REQUIRE_EQ(max(-1,-2), -1); 458 REQUIRE_EQ(max(-1,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 0); 459 REQUIRE_EQ(max('a','b','c'), 'c'); 460 461 REQUIRE_EQ(max_2(2, 3), 3); 462 REQUIRE_EQ(min_2(2, 3), 2); 463 } 464 465 TEST_CASE("numeric_test - normalize") 466 { 467 using namespace fplus; 468 469 REQUIRE_EQ(normalize_min_max(0.0, 10.0, Doubles({1, 3, 6})), Doubles({0, 4, 10})); 470 REQUIRE_EQ(normalize_mean_stddev(3.0, 2.0, Doubles({7, 8})), Doubles({1, 5})); 471 REQUIRE_EQ(standardize(Doubles({2, 6})), Doubles({-1, 1})); 472 473 REQUIRE_EQ(normalize_min_max(0.0f, 10.0f, Floats({1, 3, 6})), Floats({0, 4, 10})); 474 REQUIRE_EQ(normalize_mean_stddev(3.0f, 2.0f, Floats({7, 8})), Floats({1, 5})); 475 REQUIRE_EQ(standardize(Floats({2, 6})), Floats({-1, 1})); 476 477 Floats xs1 = {1, 3, 6}; 478 Floats xs2 = {7, 8}; 479 Floats xs3 = {2.0, 6.0}; 480 REQUIRE_EQ(normalize_min_max(0.0f, 10.0f, xs1), Floats({0, 4, 10})); 481 REQUIRE_EQ(normalize_mean_stddev(3.0f, 2.0f, xs2), Floats({1, 5})); 482 REQUIRE_EQ(standardize(xs3), Floats({-1, 1})); 483 484 } 485 486 TEST_CASE("numeric_test - winsorize") 487 { 488 using namespace fplus; 489 490 REQUIRE_EQ(winsorize(0.1, Doubles()), Doubles()); 491 REQUIRE_EQ(winsorize(0.1, Doubles({1})), Doubles({1})); 492 REQUIRE_EQ(winsorize(0.4, Doubles({1,2})), Doubles({1,2})); 493 REQUIRE_EQ(winsorize(0.32, Doubles({1,2,3})), Doubles({1,2,3})); 494 REQUIRE_EQ(winsorize(0.34, Doubles({1,2,3})), Doubles({2,2,2})); 495 REQUIRE_EQ(winsorize(0.1, Doubles({1,3,4,4,4,4,4,4,6,8})), Doubles({3,3,4,4,4,4,4,4,6,6})); 496 REQUIRE_EQ(winsorize(-0.1, Doubles({1,3,4,4,4,4,4,4,6,8})), Doubles({1,3,4,4,4,4,4,4,6,8})); 497 REQUIRE_EQ(winsorize(0.1, Doubles({4,4,4,3,8,4,6,4,3,4})), Doubles({3,3,4,4,4,4,4,4,6,6})); 498 REQUIRE_EQ(winsorize(0, Doubles({1,3,4,4,4,4,4,4,6,8})), Doubles({1,3,4,4,4,4,4,4,6,8})); 499 500 const auto median_result = winsorize(0.6, Doubles({1,2})); 501 REQUIRE_EQ(median_result.size(), 2); 502 REQUIRE(fplus::is_in_interval_around(0.001, 1.5, median_result[0])); 503 REQUIRE(fplus::is_in_interval_around(0.001, 1.5, median_result[1])); 504 } 505 506 TEST_CASE("numeric_test - histogram") 507 { 508 using namespace fplus; 509 510 typedef std::vector<int> ints; 511 typedef std::pair<int, int> interval; 512 typedef std::vector<interval> intervals; 513 typedef std::pair<interval, std::size_t> bin; 514 typedef std::vector<bin> bins; 515 516 const ints xs = {0,1,4,5,6,7,8,9}; 517 const intervals intervals1 = {{0,4}, {4,5}, {6,8}}; 518 const bins result1 = {{{0, 4}, 2}, {{4, 5}, 1}, {{6, 8}, 2}}; 519 520 REQUIRE_EQ(histogram_using_intervals(intervals1, xs), result1); 521 } 522 523 TEST_CASE("numeric_test - generate_consecutive_intervals") 524 { 525 using namespace fplus; 526 527 typedef std::pair<int, int> interval; 528 typedef std::vector<interval> intervals; 529 530 const intervals result = {{0,2}, {2,4}, {4,6}, {6,8}}; 531 532 REQUIRE_EQ(generate_consecutive_intervals(0, 2, 4), result); 533 } 534 535 TEST_CASE("numeric_test - histogram_intervals") 536 { 537 using namespace fplus; 538 539 typedef std::vector<int> ints; 540 typedef std::pair<int, std::size_t> bin; 541 typedef std::vector<bin> bins; 542 543 const ints xs = {0,1,4,5,7,8,9}; 544 const bins result1 = {{1, 2}, {3, 0}, {5, 2}, {7, 1}}; 545 546 REQUIRE_EQ(histogram(1, 2, 4, xs), result1); 547 } 548 549 TEST_CASE("numeric_test - modulo_chain") 550 { 551 using namespace fplus; 552 typedef std::vector<int> ints; 553 REQUIRE_EQ(modulo_chain(ints({24, 60, 60}), 23), ints({0, 0, 0, 23})); 554 REQUIRE_EQ(modulo_chain(ints({24, 60, 60}), 7223), ints({0, 2, 0, 23})); 555 REQUIRE_EQ( 556 modulo_chain(ints({24, 60, 60, 1000}), 557 3 * 24 * 60 * 60 * 1000 + 558 17 * 60 * 60 * 1000 + 559 4 * 60 * 1000 + 560 31 * 1000 + 561 256), 562 ints({3, 17, 4, 31, 256})); 563 } 564 565 TEST_CASE("numeric_test - line_equation") 566 { 567 using namespace fplus; 568 569 REQUIRE(is_in_interval_around(0.001, 2.0, line_equation( 570 std::make_pair(0.0, 0.0), 571 std::make_pair(2.0, 1.0), 4.0))); 572 REQUIRE(is_in_interval_around(0.001, -2.0, line_equation( 573 std::make_pair(-1.0, 1.0), 574 std::make_pair(-2.0, 4.0), 0.0))); 575 } 576