Skip to content

Commit b9dae17

Browse files
authored
Bring hot patch version 0.1.2 into main (#18)
* Remove not_null (not used anymore) * Bring version 0.1.1 into main (#12) (#13) * Add support for builtin detection * Update comments to be more eye catching * Add clang-cl and apple clang support * Fix bug with MSVC where not checking for nan * Remove msvc specific code in favor of generic approach * Prepare for 0.1.0 release. * Add doxygen docs * Finalize min/max * Add todo for later work on remquo * Cleanup main for 0.1.0 release * Bring standard back to C++17 * Minor cleanup to cmake list * Prep files for v0.1.0 release * Prepare for 0.1.0 release. * Add doxygen docs * Finalize min/max * Add todo for later work on remquo * Cleanup main for 0.1.0 release * Bring standard back to C++17 * Minor cleanup to cmake list * Prep files for v0.1.0 release * Bring everything in * Remove artifacts that mistakenly got pushed to main * Implement isgreater * Implement isgreaterequal * Implement isless * Implement islessequal * Implement islessgreater * Implement isnormal * Implement isunordered * Add test cases for all new compare functions * Add boilerplate code for future unit tests * Update progress * A lot of work done so far on log * log now far more efficient and accurate * Update readme progress * Continue work on log for double * remove unnecessary include * remove msvc section of unlikely * improve variable names * remove old log impl * Cleanup double implementation of log * cleanup of log details and add more comments. * Finalize work on log function * Update current progress * Fix bug with ±0 in log * Update test cases to cover all major edge cases * Move to correct folder * Add headers for log and log2 * Remove dependency on Threads * Initial addition of Contribution Guide * Cleanup README and add extra information * Update project version to v0.1.1 * Add top12 bits function for upcoming work * Finalize work with log function * Initial working revision of log2 * Push current work. Need to revise log2 to resolve bugs later. * Initial implementation of lerp * Fix scope bug * remove the direct use of cmath. * Update include to use cfloat instead of float.h * Cleanup macros and fix minor bugs * Fix bug where we were improperly assigning a correct value to the wrong variable * Update docs to mention not accounting for big-endian * Add comment to mention we are mirroring impl from cmath * Remove MSVC fallback that was inconsistent with every other impl * Add additional helpers for future work * Add test for static_assert support and some additional tests * Finalize implementation of log2 * Remove static_assert for now * Update README.md * Bring version 0.1.1 into main (#12) (#14) * Add support for builtin detection * Update comments to be more eye catching * Add clang-cl and apple clang support * Fix bug with MSVC where not checking for nan * Remove msvc specific code in favor of generic approach * Prepare for 0.1.0 release. * Add doxygen docs * Finalize min/max * Add todo for later work on remquo * Cleanup main for 0.1.0 release * Bring standard back to C++17 * Minor cleanup to cmake list * Prep files for v0.1.0 release * Prepare for 0.1.0 release. * Add doxygen docs * Finalize min/max * Add todo for later work on remquo * Cleanup main for 0.1.0 release * Bring standard back to C++17 * Minor cleanup to cmake list * Prep files for v0.1.0 release * Bring everything in * Remove artifacts that mistakenly got pushed to main * Implement isgreater * Implement isgreaterequal * Implement isless * Implement islessequal * Implement islessgreater * Implement isnormal * Implement isunordered * Add test cases for all new compare functions * Add boilerplate code for future unit tests * Update progress * A lot of work done so far on log * log now far more efficient and accurate * Update readme progress * Continue work on log for double * remove unnecessary include * remove msvc section of unlikely * improve variable names * remove old log impl * Cleanup double implementation of log * cleanup of log details and add more comments. * Finalize work on log function * Update current progress * Fix bug with ±0 in log * Update test cases to cover all major edge cases * Move to correct folder * Add headers for log and log2 * Remove dependency on Threads * Initial addition of Contribution Guide * Cleanup README and add extra information * Update project version to v0.1.1 * Add top12 bits function for upcoming work * Finalize work with log function * Initial working revision of log2 * Push current work. Need to revise log2 to resolve bugs later. * Initial implementation of lerp * Fix scope bug * remove the direct use of cmath. * Update include to use cfloat instead of float.h * Cleanup macros and fix minor bugs * Fix bug where we were improperly assigning a correct value to the wrong variable * Update docs to mention not accounting for big-endian * Add comment to mention we are mirroring impl from cmath * Remove MSVC fallback that was inconsistent with every other impl * Add additional helpers for future work * Add test for static_assert support and some additional tests * Finalize implementation of log2 * Remove static_assert for now * Update README.md * Update bullet points for features of library * Remove unused helpers * add float_t and double_t to monolithic header * Cleanup and minor adjustments * Update sources to remove deleted headers * Fix ambiguity bug between float and integer * Fix ambiguity issues * Implement basic benchmarking for log and log2 * Update all test suite to use the monolithic header instead of function specific header. * Setup some basic benchmark suites for log and abs * Minor cleanup * Add first class support for Intel DPC++ * Fix small bug with compiler identification * Add first class support to Nvidia HPC C++ * Having internal issues with detection of NVidia HPC C++. Removing specific section for now * Add support for Nvidia HPC and remove use of enums. * Fix minor bug with NVHPC * Re-enable static_assert for fpclassify and verify it works with CI * Re-enable static_assert for fpclassify and verify it works with CI * Add extra comment to static_assert * rename the exponent details folder to impl * Cleanup the example mains * Finish implementation of remquo * Cleanup remquo test cases * Update remquo to better handle specific edge cases * Remove unused includes * Temporarily remove problematic test cases. * Layout some future functions for long double * Implement copysign * remove deleted file from headers * Cleanup code and documentation * Add last additional functions and documentation * Cleanup implementation details * Consolidate code and reduce code fragmentation along with minor refinement of documentation * Fix missing SetComplexitN * Minor cleanup * Update README to reflect updated functions * Update version number to 0.1.2 for upcoming hot patch
1 parent 4793fe2 commit b9dae17

25 files changed

+898
-331
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.18)
22

3-
set(CCMATH_BUILD_VERSION 0.1.1)
3+
set(CCMATH_BUILD_VERSION 0.1.2)
44
set(INTERNAL_PROJ_DEFAULT_NAME ccmath)
55

66
project(${INTERNAL_PROJ_DEFAULT_NAME} VERSION ${CCMATH_BUILD_VERSION})

README.md

+101-101
Large diffs are not rendered by default.

benchmark/ccmath_benchmark_main.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ static void BM_ccm_log(bm::State& state) {
110110
for (auto _ : state) {
111111
bm::DoNotOptimize(ccm::log(state.range(0)));
112112
}
113+
state.SetComplexityN(state.range(0));
113114
}
114115
BENCHMARK(BM_ccm_log)->Arg(16)->Arg(256)->Arg(4096)->Arg(65536)->Complexity();
115116

ccmath_headers.cmake

+28-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
##########################################
2+
# Internal headers
3+
##########################################
4+
15
set(ccmath_internal_helpers_headers
26
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/helpers/bits.hpp
37
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/helpers/endian.hpp
@@ -39,7 +43,18 @@ set(ccmath_internal_headers
3943
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/version.hpp
4044
)
4145

46+
47+
##########################################
48+
# Detail headers
49+
##########################################
50+
51+
set(ccmath_detail_basic_impl_headers
52+
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/basic/impl/remquo_float_impl.hpp
53+
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/basic/impl/remquo_double_impl.hpp
54+
)
55+
4256
set(ccmath_detail_basic_headers
57+
${ccmath_detail_basic_impl_headers}
4358
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/basic/abs.hpp
4459
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/basic/fdim.hpp
4560
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/basic/fma.hpp
@@ -65,17 +80,17 @@ set(ccmath_detail_compare_headers
6580
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/compare/signbit.hpp
6681
)
6782

68-
set(ccmath_detail_exponential_details_headers
69-
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/details/log_float_impl.hpp
70-
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/details/log_double_impl.hpp
71-
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/details/log_data.hpp
72-
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/details/log2_float_impl.hpp
73-
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/details/log2_double_impl.hpp
74-
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/details/log2_data.hpp
83+
set(ccmath_detail_exponential_impl_headers
84+
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/impl/log_float_impl.hpp
85+
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/impl/log_double_impl.hpp
86+
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/impl/log_data.hpp
87+
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/impl/log2_float_impl.hpp
88+
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/impl/log2_double_impl.hpp
89+
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/impl/log2_data.hpp
7590
)
7691

7792
set(ccmath_detail_exponential_headers
78-
${ccmath_detail_exponential_details_headers}
93+
${ccmath_detail_exponential_impl_headers}
7994
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/exp.hpp
8095
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/exp2.hpp
8196
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/detail/exponential/expm1.hpp
@@ -175,6 +190,11 @@ set(ccmath_detail_headers
175190
${ccmath_detail_root_headers}
176191
)
177192

193+
194+
##########################################
195+
# Root headers
196+
##########################################
197+
178198
set(ccmath_root_headers
179199
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/basic.hpp
180200
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/compare.hpp

include/ccmath/detail/basic/abs.hpp

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#pragma once
1010

1111
#include "ccmath/detail/compare/isnan.hpp"
12-
1312
#include <limits>
1413

1514
namespace ccm

include/ccmath/detail/basic/fdim.hpp

+9-29
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,10 @@
1010

1111
#include <limits>
1212
#include <type_traits>
13-
1413
#include "ccmath/detail/compare/isnan.hpp"
1514

1615
namespace ccm
1716
{
18-
/// @cond MATH_DETAIL
19-
namespace
20-
{
21-
namespace impl
22-
{
23-
template <typename T>
24-
inline constexpr T fdim_impl(T x, T y)
25-
{
26-
if constexpr (std::is_floating_point_v<T>)
27-
{
28-
if (ccm::isnan(x)) { return x; }
29-
if (ccm::isnan(y)) { return y; }
30-
}
31-
32-
if (x <= y) { return T(+0.0); }
33-
else if ((y < T(0.0)) && (x > (std::numeric_limits<T>::max() + y))) { return std::numeric_limits<T>::infinity(); }
34-
else { return x - y; }
35-
}
36-
37-
} // namespace impl
38-
} // namespace
39-
/// @endcond
40-
4117
/**
4218
* @brief Computes the positive difference of two floating point values (max(0,x−y))
4319
* @tparam T A floating-point type.
@@ -48,7 +24,11 @@ namespace ccm
4824
template <typename T, std::enable_if_t<std::is_floating_point<T>::value, int> = 0>
4925
inline constexpr T fdim(T x, T y)
5026
{
51-
return impl::fdim_impl(x, y);
27+
if (ccm::isnan(x)) { return x; }
28+
if (ccm::isnan(y)) { return y; }
29+
if (x <= y) { return T(+0.0); }
30+
else if ((y < T(0.0)) && (x > (std::numeric_limits<T>::max() + y))) { return std::numeric_limits<T>::infinity(); }
31+
else { return x - y; }
5232
}
5333

5434
/**
@@ -66,7 +46,7 @@ namespace ccm
6646
using shared_type = std::common_type_t<T, U>;
6747

6848
// Convert the arguments to the common type
69-
return fdim(static_cast<shared_type>(x), static_cast<shared_type>(y));
49+
return fdim<shared_type>(static_cast<shared_type>(x), static_cast<shared_type>(y));
7050
}
7151

7252
/**
@@ -79,7 +59,7 @@ namespace ccm
7959
template <typename Integer, std::enable_if_t<std::is_integral<Integer>::value, int> = 0>
8060
inline constexpr double fdim(Integer x, Integer y)
8161
{
82-
return fdim(static_cast<double>(x), static_cast<double>(y));
62+
return fdim<double>(static_cast<double>(x), static_cast<double>(y));
8363
}
8464

8565
/**
@@ -90,7 +70,7 @@ namespace ccm
9070
*/
9171
inline constexpr float fdimf(float x, float y)
9272
{
93-
return fdim(x, y);
73+
return fdim<float>(x, y);
9474
}
9575

9676
/**
@@ -101,7 +81,7 @@ namespace ccm
10181
*/
10282
inline constexpr long double fdiml(long double x, long double y)
10383
{
104-
return fdim(x, y);
84+
return fdim<long double>(x, y);
10585
}
10686
} // namespace ccm
10787

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright (c) 2024-Present Ian Pike
3+
* Copyright (c) 2024-Present ccmath contributors
4+
*
5+
* This library is provided under the MIT License.
6+
* See LICENSE for more information.
7+
*/
8+
9+
#pragma once
10+
11+
#include <cstdint>
12+
#include <limits>
13+
14+
#include "ccmath/internal/helpers/bits.hpp"
15+
#include "ccmath/internal/predef/unlikely.hpp"
16+
#include "ccmath/detail/basic/abs.hpp"
17+
#include "ccmath/detail/basic/fmod.hpp"
18+
19+
namespace ccm::internal
20+
{
21+
namespace
22+
{
23+
namespace impl
24+
{
25+
inline constexpr double remquo_double_impl(double x, double y, int * quo) noexcept
26+
{
27+
std::int64_t x_i64{};
28+
std::int64_t y_i64{};
29+
std::uint64_t x_sign{};
30+
std::uint64_t quotient_sign{};
31+
int computed_quotient{};
32+
33+
x_i64 = ccm::helpers::double_to_int64(x);
34+
y_i64 = ccm::helpers::double_to_int64(y);
35+
36+
// Determine the signs of x and the quotient.
37+
x_sign = static_cast<std::uint64_t>(x_i64) & 0x8000000000000000ULL;
38+
quotient_sign = x_sign ^ (static_cast<std::uint64_t>(y_i64) & 0x8000000000000000ULL);
39+
40+
// Clear the sign bits from the int64_t representations of x and y.
41+
x_i64 &= 0x7fffffffffffffffULL;
42+
y_i64 &= 0x7fffffffffffffffULL;
43+
44+
// If y is zero.
45+
if (CCM_UNLIKELY(y_i64 == 0)) { return (x * y) / (x * y); }
46+
47+
// If x is not finite or y is NaN.
48+
if (CCM_UNLIKELY(x_i64 >= 0x7ff0000000000000ULL || y_i64 > 0x7ff0000000000000ULL)) { return (x * y) / (x * y); }
49+
50+
// b (or bit 54) represents the highest bit we can compare against for both signed and unsigned integers without causing an overflow.
51+
// Here we are checking that if y_i64 is within the range of signed 64-bit integers that can be represented without setting the MSB (i.e.,
52+
// positive or zero).
53+
if (y_i64 <= 0x7fbfffffffffffffULL)
54+
{
55+
x = ccm::fmod(x, 8 * y); // now x < (8 * y)
56+
}
57+
58+
if (CCM_UNLIKELY(x_i64 == y_i64))
59+
{
60+
*quo = quotient_sign ? -1 : 1;
61+
return 0.0 * x;
62+
}
63+
64+
x = ccm::fabs(x);
65+
y = ccm::helpers::int64_to_double(y_i64);
66+
computed_quotient = 0;
67+
68+
if (y_i64 <= 0x7fcfffffffffffffULL && x >= 4 * y)
69+
{
70+
x -= 4 * y;
71+
computed_quotient += 4;
72+
}
73+
74+
if (y_i64 <= 0x7fdfffffffffffffULL && x >= 2 * y)
75+
{
76+
x -= 2 * y;
77+
computed_quotient += 2;
78+
}
79+
80+
if (y_i64 < 0x0020000000000000ULL)
81+
{
82+
if (x + x > y)
83+
{
84+
x -= y;
85+
++computed_quotient;
86+
if (x + x >= y)
87+
{
88+
x -= y;
89+
++computed_quotient;
90+
}
91+
}
92+
}
93+
else
94+
{
95+
double y_half = 0.5 * y;
96+
if (x > y_half)
97+
{
98+
x -= y;
99+
++computed_quotient;
100+
if (x >= y_half)
101+
{
102+
x -= y;
103+
++computed_quotient;
104+
}
105+
}
106+
}
107+
108+
*quo = quotient_sign ? -computed_quotient : computed_quotient;
109+
110+
// Make sure that the correct sign of zero results in round down mode.
111+
if (x == 0.0) { x = 0.0; }
112+
if (x_sign) { x = -x; }
113+
114+
return x;
115+
}
116+
} // namespace impl
117+
} // namespace
118+
119+
template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
120+
inline constexpr T remquo_double(T x, T y, int * quo) noexcept
121+
{
122+
return static_cast<T>(impl::remquo_double_impl(x, y, quo));
123+
}
124+
} // namespace ccm::internal

0 commit comments

Comments
 (0)