Skip to content

Commit

Permalink
Add gcc specific optimization for fma
Browse files Browse the repository at this point in the history
  • Loading branch information
Rinzii committed Apr 22, 2024
1 parent 85c50d0 commit 0590876
Showing 1 changed file with 11 additions and 3 deletions.
14 changes: 11 additions & 3 deletions include/ccmath/math/basic/fma.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

#pragma once

#include "ccmath/internal/predef/unlikely.hpp"
// #include "ccmath/internal/predef/unlikely.hpp"
#include <type_traits>
#include "ccmath/math/compare/isinf.hpp"
#include "ccmath/math/compare/isnan.hpp"
#include <type_traits>

namespace ccm
{
Expand All @@ -27,6 +27,13 @@ namespace ccm
template <typename T, std::enable_if_t<!std::is_integral_v<T>, bool> = true>
constexpr T fma(T x, T y, T z) noexcept
{
// Check for GCC 6.1 or later
#if defined(__GNUC__) && (__GNUC__ > 6 || (__GNUC__ == 6 && __GNUC_MINOR__ >= 1)) && !defined(__clang__)
if constexpr (std::is_same_v<T, float>) { return __builtin_fmaf(x, y, z); }
else if constexpr (std::is_same_v<T, double>) { return __builtin_fma(x, y, z); }
else if constexpr (std::is_same_v<T, long double>) { return __builtin_fmal(x, y, z); }
else { __builtin_fma(x, y, z); }
#else
// Handle infinity
if (CCM_UNLIKELY((x == static_cast<T>(0) && ccm::isinf(y)) || (y == T{0} && ccm::isinf(x)))) { return std::numeric_limits<T>::quiet_NaN(); }
if (CCM_UNLIKELY(x * y == std::numeric_limits<T>::infinity() && z == -std::numeric_limits<T>::infinity()))
Expand All @@ -41,8 +48,9 @@ namespace ccm
return std::numeric_limits<T>::quiet_NaN();
}

// We have to hope the compiler optimizes this. Currently there is no builtin fma that works with static_assert.
// We have to hope the compiler optimizes this. Currently, there is no builtin fma that works with static_assert.
return (x * y) + z;
#endif
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
Expand Down

0 comments on commit 0590876

Please sign in to comment.