From 4487b988e7126a95c491ccfffd4de542a2d9a613 Mon Sep 17 00:00:00 2001 From: Crzyrndm Date: Tue, 14 Aug 2018 22:48:28 +1200 Subject: [PATCH] Define fp equality function -- Based on checks and defaults used by various testing frameworks (primarily GTest and Catch) -- Moved the header into detail where it should have been to start with (oops) --- include/xlnt/utils/serialisation_utils.hpp | 44 -------- .../header_footer/header_footer_code.cpp | 2 +- source/detail/numeric_utils.hpp | 104 ++++++++++++++++++ source/detail/serialization/xlsx_producer.cpp | 2 +- 4 files changed, 106 insertions(+), 46 deletions(-) delete mode 100644 include/xlnt/utils/serialisation_utils.hpp create mode 100644 source/detail/numeric_utils.hpp diff --git a/include/xlnt/utils/serialisation_utils.hpp b/include/xlnt/utils/serialisation_utils.hpp deleted file mode 100644 index 23bc2ada..00000000 --- a/include/xlnt/utils/serialisation_utils.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// 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 - -#pragma once - -#include -#include - -namespace xlnt { -/// -/// Takes in any nuber and outputs a string form of that number which will -/// serialise and deserialise without loss of precision -/// -template -std::string serialize_number_to_string(Number num) -{ - // more digits and excel won't match - constexpr int Excel_Digit_Precision = 15; //sf - std::stringstream ss; - ss.precision(Excel_Digit_Precision); - ss << num; - return ss.str(); -} -} diff --git a/source/detail/header_footer/header_footer_code.cpp b/source/detail/header_footer/header_footer_code.cpp index f97ef659..b678ef90 100644 --- a/source/detail/header_footer/header_footer_code.cpp +++ b/source/detail/header_footer/header_footer_code.cpp @@ -22,7 +22,7 @@ // @author: see AUTHORS file #include -#include +#include namespace xlnt { namespace detail { diff --git a/source/detail/numeric_utils.hpp b/source/detail/numeric_utils.hpp new file mode 100644 index 00000000..1ae25abd --- /dev/null +++ b/source/detail/numeric_utils.hpp @@ -0,0 +1,104 @@ +// 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 + +#pragma once + +#include +#include +#include + +namespace xlnt { +namespace detail { +/// +/// Takes in any number and outputs a string form of that number which will +/// serialise and deserialise without loss of precision +/// +template +std::string serialize_number_to_string(Number num) +{ + // more digits and excel won't match + constexpr int Excel_Digit_Precision = 15; //sf + std::stringstream ss; + ss.precision(Excel_Digit_Precision); + ss << num; + return ss.str(); +} + +/// +/// constexpr abs +/// +template +constexpr Number abs(Number val) +{ + if (val < Number{0}) + { + return -val; + } + return val; +}; + +/// +/// constexpr max +/// +template +constexpr Number max(Number lval, Number rval) +{ + if (lval < rval) + { + return rval; + } + return lval; +}; + +/// +/// Floating point equality requires a bit of fuzzingdue to the imprecise nature of fp calculation +/// +template +constexpr bool float_equals(const LNumber &lhs, const RNumber &rhs) +{ + static_assert(!std::is_integral::value && !std::is_integral::value, + "Using this function with two integers is just wasting time. Use =="); + + // NANs always compare false with themselves + if ((lhs != lhs) || (rhs != rhs)) + { + return false; + } + // a type that lhs and rhs can agree on + using common_t = std::common_type_t; + // The lower precision epsilon. + // In comparison between different types, the lower precision type must be used for epsilon + constexpr common_t epsilon = detail::max(std::numeric_limits::epsilon(), std::numeric_limits::epsilon()); + // 100 * epsilon selected as an arbitrary range + constexpr common_t fuzz = 100 * epsilon; + // the "epsilon" then needs to be scaled into the comparison range + // epsilon for numeric_limits is valid when abs(x) <1.0, scaling only needs to be upwards + // in particular, this prevents a lhs of 0 from requiring an exact comparison + common_t scaled_fuzz = fuzz * max(xlnt::detail::abs(lhs), common_t{1}); + return ((lhs + scaled_fuzz) >= rhs) && ((rhs + scaled_fuzz) >= lhs); +} + +//static_assert(0.1 != 0.1f, "Built in equality fails"); +//static_assert(float_equals(0.1, 0.1f), "fuzzy equality allows comparison between double and float"); +} // namespace detail +} // namespace xlnt diff --git a/source/detail/serialization/xlsx_producer.cpp b/source/detail/serialization/xlsx_producer.cpp index f8172c16..b4ea1aa8 100644 --- a/source/detail/serialization/xlsx_producer.cpp +++ b/source/detail/serialization/xlsx_producer.cpp @@ -33,12 +33,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include