mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
Adding tests for xlnt::detail::float_equals
-- Plenty of comments which should be useful if it becomes useful to tweak the comparison
This commit is contained in:
parent
a28f3fb7a9
commit
9565377963
|
@ -15,6 +15,7 @@ if(STATIC_CRT)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(GLOB CELL_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/cell/*.cpp)
|
file(GLOB CELL_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/cell/*.cpp)
|
||||||
|
file(GLOB DETAIL_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/detail/*.cpp)
|
||||||
file(GLOB PACKAGING_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/packaging/*.cpp)
|
file(GLOB PACKAGING_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/packaging/*.cpp)
|
||||||
file(GLOB STYLES_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/styles/*.cpp)
|
file(GLOB STYLES_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/styles/*.cpp)
|
||||||
file(GLOB UTILS_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/utils/*.cpp)
|
file(GLOB UTILS_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/utils/*.cpp)
|
||||||
|
@ -23,6 +24,7 @@ file(GLOB WORKSHEET_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/worksheet/*.cpp)
|
||||||
|
|
||||||
set(TESTS
|
set(TESTS
|
||||||
${CELL_TESTS}
|
${CELL_TESTS}
|
||||||
|
${DETAIL_TESTS}
|
||||||
${PACKAGING_TESTS}
|
${PACKAGING_TESTS}
|
||||||
${STYLES_TESTS}
|
${STYLES_TESTS}
|
||||||
${UTILS_TESTS}
|
${UTILS_TESTS}
|
||||||
|
@ -59,6 +61,7 @@ endif()
|
||||||
source_group(helpers FILES ${HELPERS})
|
source_group(helpers FILES ${HELPERS})
|
||||||
source_group(runner FILES ${RUNNER})
|
source_group(runner FILES ${RUNNER})
|
||||||
source_group(tests\\cell FILES ${CELL_TESTS})
|
source_group(tests\\cell FILES ${CELL_TESTS})
|
||||||
|
source_group(tests\\detail FILES ${DETAIL_TESTS})
|
||||||
source_group(tests\\packaging FILES ${PACKAGING_TESTS})
|
source_group(tests\\packaging FILES ${PACKAGING_TESTS})
|
||||||
source_group(tests\\serialization FILES ${SERIALIZATION_TESTS})
|
source_group(tests\\serialization FILES ${SERIALIZATION_TESTS})
|
||||||
source_group(tests\\styles FILES ${STYLES_TESTS})
|
source_group(tests\\styles FILES ${STYLES_TESTS})
|
||||||
|
|
112
tests/detail/numeric_util_test_suite.cpp
Normal file
112
tests/detail/numeric_util_test_suite.cpp
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
// Copyright (c) 2014-2018 Thomas Fussell
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE
|
||||||
|
//
|
||||||
|
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||||
|
// @author: see AUTHORS file
|
||||||
|
|
||||||
|
#include "../../source/detail/numeric_utils.hpp"
|
||||||
|
#include <helpers/test_suite.hpp>
|
||||||
|
|
||||||
|
class numeric_test_suite : public test_suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
numeric_test_suite()
|
||||||
|
{
|
||||||
|
register_test(test_float_equals_zero);
|
||||||
|
register_test(test_float_equals_large);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_float_equals_zero()
|
||||||
|
{
|
||||||
|
// comparing relatively small numbers (2.3e-6) with 0 will be true by default
|
||||||
|
const float comp_val = 2.3e-6; // about the largest difference allowed by default
|
||||||
|
xlnt_assert(0.f != comp_val); // fail because not exactly equal
|
||||||
|
xlnt_assert(xlnt::detail::float_equals(0.0, comp_val));
|
||||||
|
xlnt_assert(xlnt::detail::float_equals(0.0, -comp_val));
|
||||||
|
// fail because diff is out of bounds for fuzzy equality
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals(0.0, comp_val + 0.1e-6));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals(0.0, -(comp_val + 0.1e-6)));
|
||||||
|
// if the bounds of comparison are too loose, there are two tweakable knobs to tighten the comparison up
|
||||||
|
//==========================================================
|
||||||
|
// #1: reduce the epsilon_scale (default is 20)
|
||||||
|
// This can bring the range down to FLT_EPSILON (scale factor of 1)
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals(0.0, comp_val, 10));
|
||||||
|
const float closer_comp_val = 1.1e-6;
|
||||||
|
xlnt_assert(xlnt::detail::float_equals(0.0, closer_comp_val, 10));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals(0.0, closer_comp_val + 0.1e-6, 10));
|
||||||
|
xlnt_assert(xlnt::detail::float_equals(0.0, -closer_comp_val, 10));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals(0.0, -(closer_comp_val + 0.1e-6), 10));
|
||||||
|
//==========================================================
|
||||||
|
// #2: specify the epsilon source as a higher precision type (e.g. double)
|
||||||
|
// This makes the epsilon range quite significantly less
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, comp_val));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, closer_comp_val));
|
||||||
|
const float tiny_comp_val = 4.4e-15;
|
||||||
|
xlnt_assert(xlnt::detail::float_equals<double>(0.0, tiny_comp_val));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, tiny_comp_val + 0.1e-15));
|
||||||
|
xlnt_assert(xlnt::detail::float_equals<double>(0.0, -tiny_comp_val));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, -(tiny_comp_val + 0.1e-15)));
|
||||||
|
//==========================================================
|
||||||
|
// #3: combine #1 & #2
|
||||||
|
// for the tightest default precision, double with a scale of 1
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, comp_val, 1));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, closer_comp_val, 1));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, tiny_comp_val, 1));
|
||||||
|
const float really_tiny_comp_val = 2.2e-16; // the limit is +/- std::numeric_limits<double>::epsilon()
|
||||||
|
xlnt_assert(xlnt::detail::float_equals<double>(0.0, really_tiny_comp_val, 1));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, really_tiny_comp_val + 0.1e-16, 1));
|
||||||
|
xlnt_assert(xlnt::detail::float_equals<double>(0.0, -really_tiny_comp_val, 1));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals<double>(0.0, -(really_tiny_comp_val + 0.1e-16), 1));
|
||||||
|
//==========================================================
|
||||||
|
// in the world of floats, 2.2e-16 is still significantly different to 0.f (smallest representable float is around 1e-38)
|
||||||
|
// if comparisons are known to involve extremely small numbers (such that +/- 2.2e-16 is too large a band),
|
||||||
|
// a type that specialises std::numeric_limits::epsilon may be passed as the first template parameter
|
||||||
|
// the type itself doesn't actually need to have any behaviour as it is only used as the source for epsilon
|
||||||
|
// struct super_precise{};
|
||||||
|
// namespace std {
|
||||||
|
// template<> numeric_limits<super_precise> {
|
||||||
|
// double epsilon() {
|
||||||
|
// return 1e-30;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// float_equals<double>(0.0, 2e-30, 1); // returns true
|
||||||
|
// float_equals<super_precise>(0.0, 2e-30, 1); // returns false
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_float_equals_large()
|
||||||
|
{
|
||||||
|
const float compare_to = 20e6;
|
||||||
|
// fp math with arguments of different magnitudes is wierd
|
||||||
|
xlnt_assert(compare_to == compare_to + 1); // x == x + 1 ...
|
||||||
|
xlnt_assert(compare_to != compare_to + 10); // x != x + 10
|
||||||
|
xlnt_assert(compare_to != compare_to - 10); // x != x - 10
|
||||||
|
// if the same epsilon was used for comparison of large values as the values around one
|
||||||
|
// we'd have all the issues around zero again
|
||||||
|
xlnt_assert(xlnt::detail::float_equals(compare_to, compare_to + 49));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals(compare_to, compare_to + 50));
|
||||||
|
xlnt_assert(xlnt::detail::float_equals(compare_to, compare_to - 49));
|
||||||
|
xlnt_assert(!xlnt::detail::float_equals(compare_to, compare_to - 50));
|
||||||
|
// float_equals also scales epsilon up to match the magnitude of its arguments
|
||||||
|
// all the same options are available for increasing/decreasing the precision of the comparison
|
||||||
|
// however the the epsilon source should always be of equal or lesser precision than the arguments when away from zero
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static numeric_test_suite x;
|
Loading…
Reference in New Issue
Block a user