Skip to content

Commit

Permalink
Setup initial work for pow implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Rinzii committed Sep 1, 2024
1 parent f450b58 commit 28536b3
Show file tree
Hide file tree
Showing 19 changed files with 555 additions and 432 deletions.
8 changes: 1 addition & 7 deletions ccmath_core_headers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# Math Section
##############################################################################

# TODO: Remove all impls from here into the generic headers.

### Basic/Impl headers
##########################################
Expand Down Expand Up @@ -152,13 +153,6 @@ set(ccmath_detail_nearest_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/math/nearest/trunc.hpp
)

### Power/Impl headers - TODO: Remove this an instead use the generic power headers
##########################################
set(ccmath_math_power_impl_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/math/power/impl/pow_impl.hpp
)



#######################################
## Power headers
Expand Down
91 changes: 53 additions & 38 deletions ccmath_internal_headers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
# Internal Section
##############################################################################

##########################################
### Config Section
##########################################

### Config/Arch/Targets headers
##########################################
set(ccmath_internal_config_arch_targets_headers
Expand Down Expand Up @@ -56,7 +60,12 @@ set(ccmath_internal_config_headers
)


#### Math/Generic Modules ####
##########################################
### Math Section
##########################################

### Generic Module
##########################################

### Math/Generic/Func/Basic headers
##########################################
Expand All @@ -75,9 +84,13 @@ set(ccmath_internal_math_generic_func_basic_headers
### Math/Generic/Func/Expo headers
##########################################
set(ccmath_internal_math_generic_func_expo_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/expo/exp2_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/expo/exp_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/expo/expm1_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/expo/log1p_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/expo/log2_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/expo/log10_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/expo/log_gen.hpp
)


Expand Down Expand Up @@ -129,37 +142,39 @@ set(ccmath_internal_math_generic_func_nearest_headers
### Math/Generic/Func/Power headers
##########################################
set(ccmath_internal_math_generic_func_power_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/nearest/cbrt_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/nearest/hypot_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/nearest/pow_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/nearest/sqrt_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/power/cbrt_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/power/hypot_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/power/pow_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/power/pow_impl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/power/powf_impl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/power/sqrt_gen.hpp
)


### Math/Generic/Func/Special headers
##########################################
set(ccmath_internal_math_generic_func_special_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/assoc_laguerre.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/assoc_legendre.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/beta.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/comp_ellint_1.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/comp_ellint_2.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/comp_ellint_3.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/cyl_bessel_i.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/cyl_bessel_j.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/cyl_bessel_k.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/cyl_neumann.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/ellint_1.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/ellint_2.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/ellint_3.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/expint.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/hermite.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/laguerre.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/legendre.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/riemann_zeta.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/sph_bessel.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/sph_legendre.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/sph_neumann.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/assoc_laguerre_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/assoc_legendre_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/beta_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/comp_ellint_1_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/comp_ellint_2_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/comp_ellint_3_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/cyl_bessel_i_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/cyl_bessel_j_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/cyl_bessel_k_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/cyl_neumann_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/ellint_1_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/ellint_2_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/ellint_3_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/expint_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/hermite_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/laguerre_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/legendre_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/riemann_zeta_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/sph_bessel_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/sph_legendre_gen.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/generic/func/special/sph_neumann_gen.hpp
)


Expand Down Expand Up @@ -197,18 +212,17 @@ set(ccmath_internal_math_generic_headers
)



### Math/Runtime/func headers
### Math/Runtime/Func/Power headers
##########################################
set(ccmath_internal_math_runtime_func_headers
${ccmath_internal_math_runtime_func_power_headers}
set(ccmath_internal_math_runtime_func_power_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/runtime/func/power/pow_rt.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/runtime/func/power/sqrt_rt.hpp
)


### Math/Runtime headers
### Math/Runtime/Func headers
##########################################
set(ccmath_internal_math_runtime_headers
${ccmath_internal_math_runtime_func_headers}
set(ccmath_internal_math_runtime_func_headers
${ccmath_internal_math_runtime_func_power_headers}
)


Expand Down Expand Up @@ -297,6 +311,7 @@ set(ccmath_internal_math_runtime_simd_func_headers
${ccmath_internal_math_runtime_simd_func_impl_vector_size_headers}

${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/runtime/simd/func/sqrt.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/runtime/simd/func/pow.hpp
)


Expand Down Expand Up @@ -327,7 +342,8 @@ set(ccmath_internal_math_runtime_simd_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/math/runtime/simd/simd.hpp
)


### Math/Runtime headers
##########################################
set(ccmath_internal_math_runtime_headers
${ccmath_internal_math_runtime_func_headers}
${ccmath_internal_math_runtime_simd_headers}
Expand Down Expand Up @@ -480,11 +496,10 @@ set(ccmath_internal_types_headers

set(ccmath_internal_headers
${ccmath_internal_config_headers}
${ccmath_internal_generic_headers}
${ccmath_internal_math_headers}
${ccmath_internal_predef_headers}
${ccmath_internal_math_runtime_headers}
${ccmath_internal_support_headers}
${ccmath_internal_types_headers}

${CMAKE_CURRENT_SOURCE_DIR}/include/ccmath/internal/setup.hpp
)
)
56 changes: 8 additions & 48 deletions include/ccmath/internal/math/generic/func/power/pow_gen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,59 +10,19 @@

#pragma once

#include <type_traits>

#include "ccmath/math/exponential/exp2.hpp"
#include "ccmath/math/exponential/log2.hpp"

#include "ccmath/math/power/impl/pow_impl.hpp"
#include "ccmath/internal/math/generic/func/power/pow_impl.hpp"
#include "ccmath/internal/math/generic/func/power/powf_impl.hpp"

#include <type_traits>

namespace ccm
namespace ccm::gen
{
namespace internal::impl
{
template <typename T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, bool> = true>
constexpr T pow_expo_by_sqr(T base, T exp) noexcept
{
// Handle common cases
if (exp == 0) { return 1; } // Anything to the power of 0 is 1
if (exp == 1) { return base; } // Anything to the power of 1 is itself
if (exp == 2) { return base * base; } // Anything to the power of 2 is itself squared
if (base == 0) { return 0; } // 0 to any power is 0
if (base == 1) { return 1; } // 1 to any power is 1

// If the base is 2, we can use the bit shift operator to calculate the power.
if (base == 2) { return 1 << exp; }

// This is pretty fast with smaller numbers, but is slower than the standard when dealing with large numbers.
// TODO: Find a way to optimize this for larger numbers.
T result = 1;
for (;;)
{
if (exp & 1) { result *= base; }
exp >>= 1;
if (!exp) { break; }
base *= base;
}

return result;
}

template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
constexpr T pow_generic(T base, T exp) noexcept
{
// This should work on all x86 platforms but may not work with other architectures.
// For now this is more of a hold over till I have time to implement a better generic version.
return ccm::exp2(exp * ccm::log2(base));
}
} // namespace internal::impl

template <typename T>
constexpr T pow(T base, T exp) noexcept
constexpr T pow_gen(T base, T exp) noexcept
{
if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>) { return internal::impl::pow_expo_by_sqr(base, exp); }
return internal::impl::pow_generic(base, exp);
//if constexpr (std::is

return 0;
}

} // namespace ccm
32 changes: 32 additions & 0 deletions include/ccmath/internal/math/generic/func/power/pow_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) Ian Pike
* Copyright (c) CCMath contributors
*
* CCMath is provided under the Apache-2.0 License WITH LLVM-exception.
* See LICENSE for more information.
*
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#pragma once

#include <type_traits>

namespace ccm::gen::impl
{
namespace internal::impl
{
template <typename T>
constexpr T pow_impl(T base, T exp) noexcept
{
return 0;
}
}

template <typename T>
constexpr T pow_impl(T base, T exp) noexcept
{
return internal::impl::pow_impl(base, exp);
}

} // namespace ccm
32 changes: 32 additions & 0 deletions include/ccmath/internal/math/generic/func/power/powf_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) Ian Pike
* Copyright (c) CCMath contributors
*
* CCMath is provided under the Apache-2.0 License WITH LLVM-exception.
* See LICENSE for more information.
*
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#pragma once

#include <type_traits>

namespace ccm::gen::impl
{
namespace internal::impl
{
template <typename T>
constexpr T powf_impl(T base, T exp) noexcept
{
return 0;
}
}

template <typename T>
constexpr T powf_impl(T base, T exp) noexcept
{
return internal::impl::powf_impl(base, exp);
}

} // namespace ccm
73 changes: 73 additions & 0 deletions include/ccmath/internal/math/runtime/func/power/pow_rt.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) Ian Pike
* Copyright (c) CCMath contributors
*
* CCMath is provided under the Apache-2.0 License WITH LLVM-exception.
* See LICENSE for more information.
*
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#pragma once

#include "ccmath/internal/config/type_support.hpp"
#include "ccmath/internal/math/generic/func/power/pow_gen.hpp"
#include "ccmath/internal/math/runtime/simd/func/sqrt.hpp"
#include "ccmath/internal/support/always_false.hpp"
#include "ccmath/internal/support/bits.hpp"
#include "ccmath/internal/support/fenv/rounding_mode.hpp"
#include "ccmath/internal/support/fp/fp_bits.hpp"
#include "ccmath/internal/support/is_constant_evaluated.hpp"

#include <type_traits>

namespace ccm::rt::simd_impl
{
#if defined(CCM_TYPES_LONG_DOUBLE_IS_FLOAT64)
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
#else
template <typename T, std::enable_if_t<std::is_floating_point_v<T> && !std::is_same_v<T, long double>, bool> = true>
#endif
[[nodiscard]] inline T pow_simd_impl(T num) noexcept;

#ifdef CCMATH_HAS_SIMD
#if defined(CCM_TYPES_LONG_DOUBLE_IS_FLOAT64)
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool>>
#else
template <typename T, std::enable_if_t<std::is_floating_point_v<T> && !std::is_same_v<T, long double>, bool>>
#endif
[[nodiscard]] inline T pow_simd_impl(T num) noexcept
{
intrin::simd<T, intrin::abi::native> const num_m(num);
intrin::simd<T, intrin::abi::native> const sqrt_m = intrin::sqrt(num_m);
return sqrt_m.convert();
}
#endif
} // namespace ccm::rt::simd_impl

namespace ccm::rt
{
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
T pow_rt(T num)
{
#if CCM_HAS_BUILTIN(__builtin_pow) || defined(__builtin_pow) // Prefer the builtins if available.
if constexpr (std::is_same_v<T, float>) { return __builtin_powf(num); }
else if constexpr (std::is_same_v<T, double>) { return __builtin_pow(num); }
else if constexpr (std::is_same_v<T, long double>) { return __builtin_powl(num); }
else { return static_cast<T>(__builtin_powl(static_cast<long double>(num))); }
#elif defined(CCMATH_HAS_SIMD)
// In the unlikely event, the rounding mode is not the default, use the runtime implementation instead.
if (CCM_UNLIKELY(ccm::support::fenv::get_rounding_mode() != FE_TONEAREST)) { return gen::pow_gen<T>(num); }
#if !defined(CCM_TYPES_LONG_DOUBLE_IS_FLOAT64) // If long double is different from double, use the generic implementation instead.
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>) { return simd_impl::pow_simd_impl(num); }
else { return gen::pow_gen<T>(num); }
#else // If long double is the same as double, we can use the SIMD implementation instead.
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>) { return simd_impl::sqrt_simd_impl(num); }
else if constexpr (std::is_same_v<T, long double>) { return static_cast<long double>(simd_impl::sqrt_simd_impl(static_cast<double>(num))); }
else { return ccm::gen::sqrt_gen<T>(num); }
#endif
#else // If we don't have a builtin or SIMD, use the generic implementation.
return ccm::gen::pow_gen<T>(num);
#endif
}
} // namespace ccm::rt
Loading

0 comments on commit 28536b3

Please sign in to comment.