Files
2026-07-13 12:47:05 +08:00

561 lines
46 KiB
C++

/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
#pragma once
#ifndef BINARY_OP_MACROS_H_
#define BINARY_OP_MACROS_H_
#include "op_types.h"
#include <math/templatemath.h>
namespace simdOps {
// =============================================================================
// STANDARD BINARY OPERATION MACROS
// =============================================================================
/**
* @brief Declares a standard binary operation with proper SIMD handling
*/
#define DECLARE_STANDARD_BINARY_OP(OP_NAME, OPERATION) \
template <typename X, typename Y, typename Z> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE Z op_logic(X d1, Y d2) { \
return OPERATION; \
} \
\
SD_HOST_DEVICE SD_INLINE Z op_logic(X d1, Y d2, Z* params) { \
return OPERATION; \
} \
\
SD_HOST_DEVICE SD_INLINE Z op_logic(X d1) { \
return static_cast<Z>(d1); \
} \
\
SD_HOST_DEVICE SD_INLINE Z op_logic(X d1, Y* params) { \
return OPERATION##_WITH_PARAMS; \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_safe<TZ, TX, TY> op_simd(TX d1, TY d2) { \
return op_logic(d1, d2); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_unsafe<TZ, TX, TY> op_simd(TX d1, TY d2) { \
return op_logic(d1, d2); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_safe<TZ, TX, TY> op_simd(TX d1, TY d2, TZ* params) { \
return op_logic(d1, d2, params); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_unsafe<TZ, TX, TY> op_simd(TX d1, TY d2, TZ* params) { \
return op_logic(d1, d2, params); \
} \
\
template<typename TX = X, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_safe<TZ, TX> op_simd(TX d1) { \
return op_logic(d1); \
} \
\
template<typename TX = X, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_unsafe<TZ, TX> op_simd(TX d1) { \
return op_logic(d1); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_safe<TZ, TX, TY> op_simd(TX d1, TY* params) { \
return op_logic(d1, params); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_unsafe<TZ, TX, TY> op_simd(TX d1, TY* params) { \
return op_logic(d1, params); \
} \
\
public: \
SD_HOST_DEVICE SD_INLINE Z op(X d1, Y d2) { \
DISPATCH_SIMD_BINARY(Z, X, Y, op_simd(d1, d2), op_logic(d1, d2)) \
} \
\
SD_HOST_DEVICE SD_INLINE Z op(X d1, Y d2, Z* params) { \
DISPATCH_SIMD_BINARY(Z, X, Y, op_simd(d1, d2, params), op_logic(d1, d2, params)) \
} \
\
SD_HOST_DEVICE SD_INLINE Z op(X d1) { \
DISPATCH_SIMD_UNARY(Z, X, op_simd(d1), op_logic(d1)) \
} \
\
SD_HOST_DEVICE SD_INLINE Z op(X d1, Y* params) { \
DISPATCH_SIMD_BINARY(Z, X, Y, op_simd(d1, params), op_logic(d1, params)) \
} \
\
SD_HOST_DEVICE SD_INLINE static X startingValue() { return static_cast<X>(0.f); } \
};
/**
* @brief Declares a binary math operation with proper SIMD handling
*/
#define DECLARE_BINARY_MATH_OP(OP_NAME, MATH_FUNC) \
template <typename X, typename Y, typename Z, \
typename std::enable_if< \
std::is_arithmetic<X>::value && \
std::is_arithmetic<Y>::value && \
std::is_arithmetic<Z>::value, int>::type = 0> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2) { return sd::math::MATH_FUNC<X COMMA Y COMMA Z>(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2, Z* params) { return sd::math::MATH_FUNC<X COMMA Y COMMA Z>(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1) { return static_cast<Z>(d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y* params) { return sd::math::MATH_FUNC<X COMMA Y COMMA Z>(d1, params[0]); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2) { return op_logic(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2, Z* params) { return op_logic(d1, d2, params); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1) { return op_logic(d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y* params) { return op_logic(d1, params); } \
\
public: \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value || \
simdOps::is_simd_unsupported_argument_type<Y>::value) return op_logic(d1, d2); \
else return op_simd(d1, d2); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2, Z* params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value || \
simdOps::is_simd_unsupported_argument_type<Y>::value) return op_logic(d1, d2, params); \
else return op_simd(d1, d2, params); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value) return op_logic(d1); \
else return op_simd(d1); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y* params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value || \
simdOps::is_simd_unsupported_argument_type<Y>::value) return op_logic(d1, params); \
else return op_simd(d1, params); \
} \
SD_HOST_DEVICE SD_INLINE static X startingValue() { return static_cast<X>(1.f); } \
};
// =============================================================================
// COMPARISON OPERATION MACROS
// =============================================================================
/**
* @brief Declares a comparison operation with proper SIMD handling
*/
#define DECLARE_COMPARISON_OP(OP_NAME, COMPARISON) \
template <typename X, typename Z> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, X d2) { return d1 COMPARISON d2; } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, X d2, X* params) { return op_logic(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, X* params) { return d1; } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, X d2) { return op_logic(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, X d2, X* params) { return op_logic(d1, d2, params); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, X* params) { return op_logic(d1, params); } \
\
public: \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, X d2) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value) return op_logic(d1, d2); \
else return op_simd(d1, d2); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, X d2, X* params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value) return op_logic(d1, d2, params); \
else return op_simd(d1, d2, params); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, X* params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value) return op_logic(d1, params); \
else return op_simd(d1, params); \
} \
};
// =============================================================================
// REVERSE BINARY MATH OPERATION MACROS
// =============================================================================
/**
* @brief Declares a reverse binary math operation with proper SIMD handling
*/
#define DECLARE_REVERSE_BINARY_MATH_OP(OP_NAME, MATH_FUNC, START_VAL) \
template <typename X, typename Y, typename Z> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2) { return sd::math::MATH_FUNC<Y COMMA X COMMA Z>(d2, d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2, Z* params) { return sd::math::MATH_FUNC<Y COMMA X COMMA Z>(d2, d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1) { return static_cast<Z>(d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y* params) { return sd::math::MATH_FUNC<Y COMMA X COMMA Z>(params[0], d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2) { return op_logic(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2, Z* params) { return op_logic(d1, d2, params); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1) { return op_logic(d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y* params) { return op_logic(d1, params); } \
\
public: \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value || \
simdOps::is_simd_unsupported_argument_type<Y>::value) return op_logic(d1, d2); \
else return op_simd(d1, d2); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2, Z* params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value || \
simdOps::is_simd_unsupported_argument_type<Y>::value) return op_logic(d1, d2, params); \
else return op_simd(d1, d2, params); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value) return op_logic(d1); \
else return op_simd(d1); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y* params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value || \
simdOps::is_simd_unsupported_argument_type<Y>::value) return op_logic(d1, params); \
else return op_simd(d1, params); \
} \
SD_HOST_DEVICE SD_INLINE static X startingValue() { return static_cast<X>(START_VAL); } \
};
// =============================================================================
// SQUARED OPERATION MACROS
// =============================================================================
/**
* @brief Declares a squared binary operation with proper SIMD handling
*/
#define DECLARE_SQUARED_BINARY_OP(OP_NAME, OPERATION) \
template <typename X, typename Y, typename Z> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE Z op_logic(X d1, Y d2) { \
Z diff = OPERATION; \
return sd::math::sd_multiply<Z, Z, Z>(diff, diff); \
} \
\
SD_HOST_DEVICE SD_INLINE Z op_logic(X d1, Y d2, Z* params) { \
Z diff = OPERATION; \
return sd::math::sd_multiply<Z, Z, Z>(diff, diff); \
} \
\
SD_HOST_DEVICE SD_INLINE Z op_logic(X d1) { \
return static_cast<Z>(d1); \
} \
\
SD_HOST_DEVICE SD_INLINE Z op_logic(X d1, Y* params) { \
Z diff = OPERATION##_PARAMS; \
return sd::math::sd_multiply<Z, Z, Z>(diff, diff); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_safe<TZ, TX, TY> op_simd(TX d1, TY d2) { \
return op_logic(d1, d2); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_unsafe<TZ, TX, TY> op_simd(TX d1, TY d2) { \
return op_logic(d1, d2); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_safe<TZ, TX, TY> op_simd(TX d1, TY d2, TZ* params) { \
return op_logic(d1, d2, params); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_unsafe<TZ, TX, TY> op_simd(TX d1, TY d2, TZ* params) { \
return op_logic(d1, d2, params); \
} \
\
template<typename TX = X, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_safe<TZ, TX> op_simd(TX d1) { \
return op_logic(d1); \
} \
\
template<typename TX = X, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_unsafe<TZ, TX> op_simd(TX d1) { \
return op_logic(d1); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_safe<TZ, TX, TY> op_simd(TX d1, TY* params) { \
return op_logic(d1, params); \
} \
\
template<typename TX = X, typename TY = Y, typename TZ = Z> \
SD_HOST_DEVICE SD_INLINE enable_if_simd_unsafe<TZ, TX, TY> op_simd(TX d1, TY* params) { \
return op_logic(d1, params); \
} \
\
public: \
SD_HOST_DEVICE SD_INLINE Z op(X d1, Y d2) { \
DISPATCH_SIMD_BINARY(Z, X, Y, op_simd(d1, d2), op_logic(d1, d2)) \
} \
\
SD_HOST_DEVICE SD_INLINE Z op(X d1, Y d2, Z* params) { \
DISPATCH_SIMD_BINARY(Z, X, Y, op_simd(d1, d2, params), op_logic(d1, d2, params)) \
} \
\
SD_HOST_DEVICE SD_INLINE Z op(X d1) { \
DISPATCH_SIMD_UNARY(Z, X, op_simd(d1), op_logic(d1)) \
} \
\
SD_HOST_DEVICE SD_INLINE Z op(X d1, Y* params) { \
DISPATCH_SIMD_BINARY(Z, X, Y, op_simd(d1, params), op_logic(d1, params)) \
} \
\
SD_HOST_DEVICE SD_INLINE static X startingValue() { return static_cast<X>(0.f); } \
};
#define DECLARE_BINARY_COPY_OP(OP_NAME, BINARY_OP, BINARY_PARAM_OP, UNARY_OP, PARAM_OP) \
template <typename X, typename Y, typename Z> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2) { \
if constexpr (std::is_arithmetic<X>::value && std::is_arithmetic<Y>::value && std::is_arithmetic<Z>::value) { \
return BINARY_OP; \
} else { \
return UNARY_OP; \
} \
} \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2, Z *params) { \
if constexpr (std::is_arithmetic<X>::value && std::is_arithmetic<Y>::value && std::is_arithmetic<Z>::value) { \
return BINARY_PARAM_OP; \
} else { \
return UNARY_OP; \
} \
} \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1) { return UNARY_OP; } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y *params) { \
if constexpr (std::is_arithmetic<X>::value && std::is_arithmetic<Y>::value && std::is_arithmetic<Z>::value) { \
return PARAM_OP; \
} else { \
return UNARY_OP; \
} \
} \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2) { return op_logic(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2, Z *params) { return op_logic(d1, d2, params); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1) { return op_logic(d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y *params) { return op_logic(d1, params); } \
\
public: \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2) { \
if constexpr(any_non_simd<X,Y,Z>) \
return op_logic(d1, d2); \
else return op_simd(d1, d2); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2, Z *params) { \
if constexpr(any_non_simd<X,Y,Z>) \
return op_logic(d1, d2, params); \
else return op_simd(d1, d2, params); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value) \
return op_logic(d1); \
else return op_simd(d1); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y *params) { \
if constexpr(any_non_simd<X,Y,Z>) \
return op_logic(d1, params); \
else return op_simd(d1, params); \
} \
};
// =============================================================================
// BINARY PARAMETER OPERATION MACROS
// =============================================================================
/**
* @brief Declares a binary operation with parameters only
*/
#define DECLARE_BINARY_PARAM_OP(OP_NAME, OPERATION, BOILERPLATE) \
template <typename X, typename Y, typename Z> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2, Z* params) { \
if constexpr (any_my_string_v<X, Y, Z>) { \
return static_cast<Z>(d1); \
} else { \
return OPERATION; \
} \
} \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2, Z* params) { \
return op_logic(d1, d2, params); \
} \
\
public: \
BOILERPLATE; \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2, Z* params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value || \
simdOps::is_simd_unsupported_argument_type<Y>::value) \
return op_logic(d1, d2, params); \
else \
return op_simd(d1, d2, params); \
} \
};
/**
* @brief Declares a binary math operation with different input/output types
*/
#define DECLARE_BINARY_MATH_OP_XZ(OP_NAME, MATH_FUNC) \
template <typename X, typename Y, typename Z> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2) { return sd::math::MATH_FUNC<X COMMA Z>(d1, static_cast<X>(d2)); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2, Z* params) { return sd::math::MATH_FUNC<X COMMA Z>(d1, static_cast<X>(d2)); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1) { return static_cast<Z>(d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y* params) { return sd::math::MATH_FUNC<X COMMA Z>(d1, static_cast<X>(params[0])); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2) { return op_logic(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2, Z* params) { return op_logic(d1, d2, params); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1) { return op_logic(d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y* params) { return op_logic(d1, params); } \
\
public: \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value || \
simdOps::is_simd_unsupported_argument_type<Y>::value) \
return op_logic(d1, d2); \
else \
return op_simd(d1, d2); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2, Z* params) { \
if constexpr (any_my_string_v<X, Y, Z>) \
return d1; \
return op_simd(d1, d2, params); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value) \
return op_logic(d1); \
else \
return op_simd(d1); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y* params) { \
if constexpr (any_my_string_v<X, Y, Z>) \
return d1; \
return op_simd(d1, params); \
} \
SD_HOST_DEVICE SD_INLINE static X startingValue() { return static_cast<X>(1.f); } \
};
/**
* @brief Declares a binary math operation with custom starting value
*/
#define DECLARE_BINARY_MATH_OP_WITH_STARTING(OP_NAME, BINARY_OP, UNARY_OP, PARAM_OP, STARTING_VAL) \
template <typename X, typename Y, typename Z> \
class OP_NAME { \
private: \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2) { return BINARY_OP; } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y d2, Z *params) { return op_logic(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1) { return UNARY_OP; } \
SD_HOST_DEVICE SD_INLINE static Z op_logic(X d1, Y *params) { return PARAM_OP; } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2) { return op_logic(d1, d2); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y d2, Z *params) { return op_logic(d1, d2, params); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1) { return op_logic(d1); } \
SD_HOST_DEVICE SD_INLINE static Z op_simd(X d1, Y *params) { return op_logic(d1, params); } \
\
public: \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2) { \
if constexpr(any_non_simd<X,Y,Z>) \
return op_logic(d1, d2); \
else return op_simd(d1, d2); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y d2, Z *params) { \
if constexpr(any_non_simd<X,Y,Z>) \
return op_logic(d1, d2, params); \
else return op_simd(d1, d2, params); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1) { \
if constexpr (simdOps::is_simd_unsupported_return_type<Z>::value || \
simdOps::is_simd_unsupported_argument_type<X>::value) \
return op_logic(d1); \
else return op_simd(d1); \
} \
SD_HOST_DEVICE SD_INLINE static Z op(X d1, Y *params) { \
if constexpr(any_non_simd<X,Y,Z>) \
return op_logic(d1, params); \
else return op_simd(d1, params); \
} \
SD_HOST_DEVICE SD_INLINE static X startingValue() { return STARTING_VAL; } \
};
#define DECLARE_SIMPLE_BINARY_OP(OP_NAME, OPERATION) \
template <typename X> \
class OP_NAME { \
private: \
static SD_INLINE X op_logic(X d1, X d2) { return OPERATION; } \
static SD_INLINE X op_logic(X d1, X d2, X *params) { return op_logic(d1, d2); } \
static SD_INLINE SD_HOST_DEVICE X op_simd(X d1, X d2) { return op_logic(d1, d2); } \
static SD_INLINE SD_HOST_DEVICE X op_simd(X d1, X d2, X *params) { return op_logic(d1, d2, params); } \
\
public: \
static SD_INLINE SD_HOST_DEVICE X op(X d1, X d2) { \
if constexpr (simdOps::is_simd_unsupported_return_type<X>::value) \
return op_logic(d1, d2); \
else return op_simd(d1, d2); \
} \
static SD_INLINE SD_HOST_DEVICE X op(X d1, X d2, X *params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<X>::value) \
return op_logic(d1, d2, params); \
else return op_simd(d1, d2, params); \
} \
};
#define DECLARE_SIMPLE_BINARY_TEMPLATE_OP(OP_NAME, OPERATION) \
template <typename X> \
class OP_NAME { \
private: \
static SD_HOST_DEVICE SD_INLINE X op_logic(X d1, X d2) { return OPERATION; } \
static SD_HOST_DEVICE SD_INLINE X op_logic(X d1, X d2, X *params) { return op_logic(d1, d2); } \
static SD_HOST_DEVICE SD_INLINE X op_simd(X d1, X d2) { return op_logic(d1, d2); } \
static SD_HOST_DEVICE SD_INLINE X op_simd(X d1, X d2, X *params) { return op_logic(d1, d2, params); } \
\
public: \
static SD_HOST_DEVICE SD_INLINE X op(X d1, X d2) { \
if constexpr (simdOps::is_simd_unsupported_return_type<X>::value) { \
return op_logic(d1, d2); \
} else { \
return op_simd(d1, d2); \
} \
} \
static SD_HOST_DEVICE SD_INLINE X op(X d1, X d2, X *params) { \
if constexpr (simdOps::is_simd_unsupported_return_type<X>::value) { \
return op_logic(d1, d2, params); \
} else { \
return op_simd(d1, d2, params); \
} \
} \
};
}
#endif