/* ****************************************************************************** * * * 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 ******************************************************************************/ // // #ifndef LIBND4J_PLATFORM_MATH_H #define LIBND4J_PLATFORM_MATH_H #include #include #include #include #ifdef __CUDACC__ #ifdef HAS_BFLOAT16 #include #endif #ifdef HAS_FLOAT16 #include #endif #ifdef HAS_BFLOAT16 union BPAIR { struct { bfloat16 H; bfloat16 L; } B; int W; SD_HOST_DEVICE BPAIR(){}; SD_HOST_DEVICE ~BPAIR(){}; }; #endif #if CUDA_VERSION_MAJOR == 8 typedef union { struct { half H; half L; } B; int W; } PAIR; #else struct HALFS { half H; half L; SD_HOST_DEVICE HALFS(){}; SD_HOST_DEVICE ~HALFS(){}; }; union PAIR { HALFS B; int W; SD_HOST_DEVICE PAIR(){}; SD_HOST_DEVICE ~PAIR() {} }; #endif // cuda_9 #else #ifdef HAS_FLOAT16 #include #endif #endif // Include SD_PRINT_MATH_FUNC and SD_PRINT_MATH_FUNC2 macros #ifdef SD_PRINT_MATH #include #include // Include for fixed-width integer types // New sd_print_math2 functions for functions with two inputs #define PRINT_IF_NECESSARY(funcName) \ const char* envFuncName = std::getenv("PRINT_MATH_FUNCTION_NAME"); \ if (envFuncName != nullptr && std::string(envFuncName) != "" && (funcName != nullptr && std::string(funcName) != "") && std::string(envFuncName) == (funcName)) { \ StackTrace st; \ st.load_here(); \ Printer p; \ p.print(st); \ } template SD_INLINE SD_HOST void sd_print_math2(const char* func_name, T input1, T input2, T output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %f, input2 = %f, output = %f\n", func_name, static_cast(input1), static_cast(input2), static_cast(output)); fflush(stdout); } #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, double input1, double input2, double output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %f, input2 = %f, output = %f\n", func_name, static_cast(input1), static_cast(input2), static_cast(output)); fflush(stdout); } #endif #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, float input1, float input2, float output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %f, input2 = %f, output = %f\n", func_name, static_cast(input1), static_cast(input2), static_cast(output)); fflush(stdout); } #endif #ifdef HAS_UINT16 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, uint16_t input1, uint16_t input2, uint16_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %d, input2 = %d, output = %d\n", func_name, input1, input2, output); fflush(stdout); } #endif // Specializations for integer types #ifdef HAS_INT32 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, int input1, int input2, int output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %d, input2 = %d, output = %d\n", func_name, input1, input2, output); fflush(stdout); } #endif #ifdef HAS_UINT32 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, uint32_t input1, uint32_t input2, uint32_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %d, input2 = %d, output = %d\n", func_name, input1, input2, output); fflush(stdout); } #endif #ifdef HAS_FLOAT16 SD_INLINE SD_HOST void sd_print_math(const char* func_name, float16 input, float16 output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %f, output = %f\n", func_name, static_cast(input), static_cast(output)); fflush(stdout); } #endif #ifdef HAS_BFLOAT16 SD_INLINE SD_HOST void sd_print_math(const char* func_name, bfloat16 input, bfloat16 output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %f, output = %f\n", func_name, static_cast(input), static_cast(output)); fflush(stdout); } #endif template SD_INLINE SD_HOST void sd_print_math(const char* func_name, T input, T output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %f, output = %f\n", func_name, static_cast(input), static_cast(output)); fflush(stdout); } // Specializations for integer types #ifdef HAS_INT32 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, int input, int output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %d, output = %d\n", func_name, input, output); fflush(stdout); } #endif #ifdef HAS_LONG template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, long input, long output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %ld, output = %ld\n", func_name, input, output); fflush(stdout); } #endif #ifdef HAS_UINT64 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, unsigned long input, unsigned long output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %lu, output = %lu\n", func_name, input, output); fflush(stdout); } template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, long long input, long long output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %lld, output = %lld\n", func_name, input, output); fflush(stdout); } template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, unsigned long long input, unsigned long long output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %llu, output = %llu\n", func_name, input, output); fflush(stdout); } #endif #ifdef HAS_INT16 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, int16_t input, int16_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %d, output = %d\n", func_name, input, output); fflush(stdout); } #endif #ifdef HAS_UINT16 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, uint16_t input, uint16_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %u, output = %u\n", func_name, input, output); fflush(stdout); } #endif #ifdef HAS_INT8 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, int8_t input, int8_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %d, output = %d\n", func_name, input, output); fflush(stdout); } #endif #ifdef HAS_UINT8 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, uint8_t input, uint8_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %u, output = %u\n", func_name, input, output); fflush(stdout); } #endif #ifdef HAS_UINT32 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, uint32_t input, uint32_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %u, output = %u\n", func_name, input, output); fflush(stdout); } #endif // Specializations for float16 #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, float16 input, float16 output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %f, output = %f\n", func_name, static_cast(input), static_cast(output)); fflush(stdout); } #endif // Specializations for bfloat16 #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, bfloat16 input, bfloat16 output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %f, output = %f\n", func_name, static_cast(input), static_cast(output)); fflush(stdout); } #endif // Specialization for bool #ifdef HAS_BOOL template <> SD_INLINE SD_HOST void sd_print_math(const char* func_name, bool input, bool output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input = %s, output = %s\n", func_name, input ? "true" : "false", output ? "true" : "false"); fflush(stdout); } #endif #ifdef HAS_UINT64 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, uint64_t input1, uint64_t input2, uint64_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %ld, input2 = %ld, output = %ld\n", func_name, input1, input2, output); fflush(stdout); } #endif #ifdef HAS_LONG template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, long input1, long input2, long output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %ld, input2 = %ld, output = %ld\n", func_name, input1, input2, output); fflush(stdout); } template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, long long input1, long long input2, long long output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %lld, input2 = %lld, output = %lld\n", func_name, input1, input2, output); fflush(stdout); } #endif #ifdef HAS_UINT64 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, unsigned long long input1, unsigned long long input2, unsigned long long output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %llu, input2 = %llu, output = %llu\n", func_name, input1, input2, output); fflush(stdout); } #endif #ifdef HAS_INT16 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, int16_t input1, int16_t input2, int16_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %d, input2 = %d, output = %d\n", func_name, input1, input2, output); fflush(stdout); } #endif #ifdef HAS_INT8 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, int8_t input1, int8_t input2, int8_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %d, input2 = %d, output = %d\n", func_name, input1, input2, output); fflush(stdout); } #endif #ifdef HAS_UINT8 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, uint8_t input1, uint8_t input2, uint8_t output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %u, input2 = %u, output = %u\n", func_name, input1, input2, output); fflush(stdout); } #endif // Specializations for float16 #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST void sd_print_math2(const char* func_name, float16 input1, float16 input2, float16 output) { #if defined(SD_GCC_FUNCTRACE) PRINT_IF_NECESSARY(func_name); #endif printf("%s: input1 = %f, input2 = %f, output = %f\n", func_name, static_cast(input1), static_cast(input2), static_cast(output)); fflush(stdout); } #endif #define SD_PRINT_MATH_FUNC(func_name, input, output,type) \ sd_print_math(func_name, input, output); #define SD_PRINT_MATH_FUNC2(func_name, input1, input2, output,type) \ sd_print_math2(func_name, input1,input2, output); #else #define SD_PRINT_MATH_FUNC(func_name, input, output,type) #define SD_PRINT_MATH_FUNC2(func_name, input1, input2, output,type) #endif namespace sd { namespace math { template SD_INLINE SD_HOST_DEVICE T p_exp(T value); template SD_INLINE SD_HOST_DEVICE T p_log(T value); template SD_INLINE SD_HOST_DEVICE T p_log2(T value); template SD_INLINE SD_HOST_DEVICE T p_floor(T value); template SD_INLINE SD_HOST_DEVICE T p_ceil(T value); template SD_INLINE SD_HOST_DEVICE T p_round(T value); template SD_INLINE SD_HOST_DEVICE T p_round_prefer_ceil(T value); template SD_INLINE SD_HOST_DEVICE T p_round_prefer_floor(T value); template SD_INLINE SD_HOST_DEVICE T p_cos(T value); template SD_INLINE SD_HOST_DEVICE T p_cosh(T value); template SD_INLINE SD_HOST_DEVICE T p_acos(T value); template SD_INLINE SD_HOST_DEVICE T p_acosh(T value); template SD_INLINE SD_HOST_DEVICE T p_sin(T value); template SD_INLINE SD_HOST_DEVICE T p_sinh(T value); template SD_INLINE SD_HOST_DEVICE T p_asin(T value); template SD_INLINE SD_HOST_DEVICE T p_sqrt(T value); template SD_INLINE SD_HOST_DEVICE T p_tanh(T value); template SD_INLINE SD_HOST_DEVICE T p_erf(T value); template SD_INLINE SD_HOST_DEVICE T p_erfc(T value); template SD_INLINE SD_HOST_DEVICE T p_atan(T value); template SD_INLINE SD_HOST_DEVICE T p_tan(T value); template SD_INLINE SD_HOST_DEVICE T p_atanh(T value); template SD_INLINE SD_HOST_DEVICE T p_rint(T value); template SD_INLINE SD_HOST_DEVICE T p_rotl(T value, T shift); template SD_INLINE SD_HOST_DEVICE T p_rotr(T value, T shift); template SD_INLINE SD_HOST_DEVICE T p_remainder(T val1, T val2); template SD_INLINE SD_HOST_DEVICE T p_fmod(T val1, T val2); template SD_INLINE SD_HOST_DEVICE T p_pow(T value, T power); template SD_INLINE SD_HOST_DEVICE T p_atan2(T val1, T val2); // Function implementations with SD_PRINT_MATH_FUNC added // p_exp #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_exp(float value) { float result = expf(value); SD_PRINT_MATH_FUNC("p_exp", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_exp(float16 val) { #ifdef SD_NATIVE_HALFS float16 result = hexp(val.data); #else float16 result = static_cast(expf((float)val)); #endif SD_PRINT_MATH_FUNC("p_exp", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_exp(bfloat16 val) { bfloat16 result = static_cast(expf((float)val)); SD_PRINT_MATH_FUNC("p_exp", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_exp(double value) { double result = exp(value); SD_PRINT_MATH_FUNC("p_exp", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_exp(T value) { T result = static_cast(expf(static_cast(value))); SD_PRINT_MATH_FUNC("p_exp", value, result,T); return result; } // p_pow #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_pow(float16 value, float16 power) { float16 result = static_cast(powf(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_pow", value, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_pow(bfloat16 value, bfloat16 power) { bfloat16 result = static_cast(powf(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_pow", value, result,bfloat16); return result; } #endif #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_pow(float value, float power) { float result = powf(value, power); SD_PRINT_MATH_FUNC("p_pow", value, result,float); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_pow(double value, double power) { double result = pow(value, power); SD_PRINT_MATH_FUNC("p_pow", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_pow(T value, T power) { T result = static_cast(powf(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_pow", value, result,T); return result; } // p_fmod #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_fmod(float16 value, float16 power) { float16 result = static_cast(fmodf(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_fmod", value, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_fmod(bfloat16 value, bfloat16 power) { bfloat16 result = static_cast(fmodf(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_fmod", value, result,bfloat16); return result; } #endif #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_fmod(float value, float power) { float result = fmodf(value, power); SD_PRINT_MATH_FUNC("p_fmod", value, result,float); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_fmod(double value, double power) { double result = fmod(value, power); SD_PRINT_MATH_FUNC("p_fmod", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_fmod(T value, T power) { T result = static_cast(fmodf(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_fmod", value, result,T); return result; } // p_atan2 #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_atan2(float16 value, float16 power) { float16 result = static_cast(atan2f(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_atan2", value, result,float16); return result; } #endif #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_atan2(float value, float power) { float result = atan2f(value, power); SD_PRINT_MATH_FUNC("p_atan2", value, result,float); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_atan2(double value, double power) { double result = atan2(value, power); SD_PRINT_MATH_FUNC("p_atan2", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_atan2(T value, T power) { T result = static_cast(atan2f(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_atan2", value, result,float); return result; } // p_remainder #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_remainder(float16 value, float16 power) { float16 result = static_cast(remainderf(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_remainder", value, result,float16); return result; } #endif #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_remainder(float value, float power) { float result = remainderf(value, power); SD_PRINT_MATH_FUNC("p_remainder", value, result,float); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_remainder(double value, double power) { double result = remainder(value, power); SD_PRINT_MATH_FUNC("p_remainder", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_remainder(T value, T power) { T result = static_cast(remainderf(static_cast(value), static_cast(power))); SD_PRINT_MATH_FUNC("p_remainder", value, result,T); return result; } // p_log #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_log(float value) { if (value == 0.0f) value = SD_EPSILON; float result = logf(value); SD_PRINT_MATH_FUNC("p_log", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_log(float16 val) { #ifdef SD_NATIVE_HALFS if ((float)val == 0.0f) val = static_cast(SD_EPSILON); float16 result = hlog(val.data); #else if (val == 0.0f) val = static_cast(SD_EPSILON); float16 result = static_cast(logf((float)val)); #endif SD_PRINT_MATH_FUNC("p_log", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_log(bfloat16 val) { if (val == 0.0f) val = static_cast(SD_EPSILON); bfloat16 result = static_cast(logf((float)val)); SD_PRINT_MATH_FUNC("p_log", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_log(double value) { if (value == 0.0) value = SD_EPSILON; double result = log(value); SD_PRINT_MATH_FUNC("p_log", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_log(T value) { if (value == static_cast(0.0f)) value = static_cast(SD_EPSILON); T result = static_cast(logf(static_cast(value))); SD_PRINT_MATH_FUNC("p_log", value, result,T); return result; } // p_log2 #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_log2(float value) { if (value == 0.0f) value = SD_EPSILON; float result = log2f(value); SD_PRINT_MATH_FUNC("p_log2", value, result,float); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_log2(double value) { if (value == 0.0) value = SD_EPSILON; double result = log2(value); SD_PRINT_MATH_FUNC("p_log2", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_log2(T value) { if (value == static_cast(0.0f)) value = static_cast(SD_EPSILON); T result = static_cast(log2f(static_cast(value))); SD_PRINT_MATH_FUNC("p_log2", value, result,float); return result; } // p_floor #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_floor(float value) { float result = floorf(value); SD_PRINT_MATH_FUNC("p_floor", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_floor(float16 val) { #ifdef SD_NATIVE_HALFS float16 result = hfloor(val.data); #else float16 result = static_cast(floorf((float)val)); #endif SD_PRINT_MATH_FUNC("p_floor", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_floor(bfloat16 val) { bfloat16 result = static_cast(floorf((float)val)); SD_PRINT_MATH_FUNC("p_floor", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_floor(double value) { double result = floor(value); SD_PRINT_MATH_FUNC("p_floor", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_floor(T value) { SD_PRINT_MATH_FUNC("p_floor", value, value,T); return value; } // p_ceil #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_ceil(float value) { float result = ceilf(value); SD_PRINT_MATH_FUNC("p_ceil", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_ceil(float16 val) { #ifdef SD_NATIVE_HALFS float16 result = hceil(val.data); #else float16 result = static_cast(ceilf((float)val)); #endif SD_PRINT_MATH_FUNC("p_ceil", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_ceil(bfloat16 val) { bfloat16 result = static_cast(ceilf((float)val)); SD_PRINT_MATH_FUNC("p_ceil", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_ceil(double value) { double result = ceil(value); SD_PRINT_MATH_FUNC("p_ceil", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_ceil(T value) { SD_PRINT_MATH_FUNC("p_ceil", value, value,T); return value; } // p_round #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_round(float value) { float result = roundf(value); SD_PRINT_MATH_FUNC("p_round", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_round(float16 val) { float16 result = static_cast(roundf((float)val)); SD_PRINT_MATH_FUNC("p_round", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_round(bfloat16 val) { bfloat16 result = static_cast(roundf((float)val)); SD_PRINT_MATH_FUNC("p_round", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_round(double value) { double result = round(value); SD_PRINT_MATH_FUNC("p_round", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_round(T value) { SD_PRINT_MATH_FUNC("p_round", value, value,T); return value; } // p_round_prefer_ceil #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_round_prefer_ceil(float value) { float result = roundf(value); SD_PRINT_MATH_FUNC("p_round_prefer_ceil", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_round_prefer_ceil(float16 val) { float16 result = static_cast(roundf((float)val)); SD_PRINT_MATH_FUNC("p_round_prefer_ceil", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_round_prefer_ceil(bfloat16 val) { bfloat16 result = static_cast(roundf((float)val)); SD_PRINT_MATH_FUNC("p_round_prefer_ceil", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_round_prefer_ceil(double value) { double result = round(value); SD_PRINT_MATH_FUNC("p_round_prefer_ceil", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_round_prefer_ceil(T value) { SD_PRINT_MATH_FUNC("p_round_prefer_ceil", value, value,T); return value; } // p_round_prefer_floor #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_round_prefer_floor(float value) { float result; if (value == static_cast(value) + 0.5f) { result = floorf(value); } else { result = roundf(value); } SD_PRINT_MATH_FUNC("p_round_prefer_floor", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_round_prefer_floor(float16 val) { float float_val = static_cast(val); float16 result; if (float_val == static_cast(float_val) + 0.5f) { result = static_cast(floorf(float_val)); } else { result = static_cast(roundf(float_val)); } SD_PRINT_MATH_FUNC("p_round_prefer_floor", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_round_prefer_floor(bfloat16 val) { float float_val = static_cast(val); bfloat16 result; if (float_val == static_cast(float_val) + 0.5f) { result = static_cast(floorf(float_val)); } else { result = static_cast(roundf(float_val)); } SD_PRINT_MATH_FUNC("p_round_prefer_floor", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_round_prefer_floor(double value) { double result; if (value == static_cast(value) + 0.5) { result = floor(value); } else { result = round(value); } SD_PRINT_MATH_FUNC("p_round_prefer_floor", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_round_prefer_floor(T value) { SD_PRINT_MATH_FUNC("p_round_prefer_floor", value, value,T); return value; } // p_rint #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_rint(float value) { float result = rintf(value); SD_PRINT_MATH_FUNC("p_rint", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_rint(float16 val) { #ifdef SD_NATIVE_HALFS float16 result = hrint(val.data); #else float16 result = static_cast(rintf((float)val)); #endif SD_PRINT_MATH_FUNC("p_rint", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_rint(bfloat16 val) { bfloat16 result = static_cast(rintf((float)val)); SD_PRINT_MATH_FUNC("p_rint", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_rint(double value) { double result = rint(value); SD_PRINT_MATH_FUNC("p_rint", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_rint(T value) { SD_PRINT_MATH_FUNC("p_rint", value, value,T); return value; } // p_cos #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_cos(float value) { float result = cosf(value); SD_PRINT_MATH_FUNC("p_cos", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_cos(float16 val) { #ifdef SD_NATIVE_HALFS float16 result = hcos(val.data); #else float16 result = static_cast(cosf((float)val)); #endif SD_PRINT_MATH_FUNC("p_cos", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_cos(bfloat16 val) { bfloat16 result = static_cast(cosf((float)val)); SD_PRINT_MATH_FUNC("p_cos", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_cos(double value) { double result = cos(value); SD_PRINT_MATH_FUNC("p_cos", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_cos(T value) { T result = static_cast(cosf(static_cast(value))); SD_PRINT_MATH_FUNC("p_cos", value, result,T); return result; } // p_sin #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_sin(float value) { float result = sinf(value); SD_PRINT_MATH_FUNC("p_sin", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_sin(float16 val) { #ifdef SD_NATIVE_HALFS float16 result = hsin(val.data); #else float16 result = static_cast(sinf((float)val)); #endif SD_PRINT_MATH_FUNC("p_sin", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_sin(bfloat16 val) { bfloat16 result = static_cast(sinf((float)val)); SD_PRINT_MATH_FUNC("p_sin", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_sin(double value) { double result = sin(value); SD_PRINT_MATH_FUNC("p_sin", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_sin(T value) { T result = static_cast(sinf(static_cast(value))); SD_PRINT_MATH_FUNC("p_sin", value, result,T); return result; } // p_sqrt #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_sqrt(float value) { float result = sqrtf(value); SD_PRINT_MATH_FUNC("p_sqrt", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_sqrt(float16 val) { #ifdef SD_NATIVE_HALFS float16 result = hsqrt(val.data); #else float16 result = static_cast(sqrtf((float)val)); #endif SD_PRINT_MATH_FUNC("p_sqrt", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_sqrt(bfloat16 val) { bfloat16 result = static_cast(sqrtf((float)val)); SD_PRINT_MATH_FUNC("p_sqrt", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_sqrt(double value) { double result = sqrt(value); SD_PRINT_MATH_FUNC("p_sqrt", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_sqrt(T value) { T result = static_cast(sqrtf(static_cast(value))); SD_PRINT_MATH_FUNC("p_sqrt", value, result,T); return result; } // p_tanh #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_tanh(float value) { float result = tanhf(value); SD_PRINT_MATH_FUNC("p_tanh", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_tanh(float16 val) { float16 result = static_cast(tanhf((float)val)); SD_PRINT_MATH_FUNC("p_tanh", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_tanh(bfloat16 val) { bfloat16 result = static_cast(tanhf((float)val)); SD_PRINT_MATH_FUNC("p_tanh", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_tanh(double value) { double result = tanh(value); SD_PRINT_MATH_FUNC("p_tanh", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_tanh(T value) { T result = static_cast(tanhf(static_cast(value))); SD_PRINT_MATH_FUNC("p_tanh", value, result,T); return result; } // p_erf #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_erf(float value) { float result = erff(value); SD_PRINT_MATH_FUNC("p_erf", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_erf(float16 val) { float16 result = static_cast(erff((float)val)); SD_PRINT_MATH_FUNC("p_erf", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_erf(bfloat16 val) { bfloat16 result = static_cast(erff((float)val)); SD_PRINT_MATH_FUNC("p_erf", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_erf(double value) { double result = erf(value); SD_PRINT_MATH_FUNC("p_erf", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_erf(T value) { T result = static_cast(erff(static_cast(value))); SD_PRINT_MATH_FUNC("p_erf", value, result,T); return result; } // p_erfc #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_erfc(float value) { float result = erfcf(value); SD_PRINT_MATH_FUNC("p_erfc", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_erfc(float16 val) { float16 result = static_cast(erfcf((float)val)); SD_PRINT_MATH_FUNC("p_erfc", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_erfc(bfloat16 val) { bfloat16 result = static_cast(erfcf((float)val)); SD_PRINT_MATH_FUNC("p_erfc", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_erfc(double value) { double result = erfc(value); SD_PRINT_MATH_FUNC("p_erfc", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_erfc(T value) { T result = static_cast(erfcf(static_cast(value))); SD_PRINT_MATH_FUNC("p_erfc", value, result,T); return result; } // p_acos #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_acos(float value) { float result = acosf(value); SD_PRINT_MATH_FUNC("p_acos", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_acos(float16 val) { float16 result = static_cast(acosf((float)val)); SD_PRINT_MATH_FUNC("p_acos", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_acos(bfloat16 val) { bfloat16 result = static_cast(acosf((float)val)); SD_PRINT_MATH_FUNC("p_acos", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_acos(double value) { double result = acos(value); SD_PRINT_MATH_FUNC("p_acos", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_acos(T value) { T result = static_cast(acosf(static_cast(value))); SD_PRINT_MATH_FUNC("p_acos", value, result,T); return result; } // p_cosh #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_cosh(float value) { float result = coshf(value); SD_PRINT_MATH_FUNC("p_cosh", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_cosh(float16 val) { float16 result = static_cast(coshf((float)val)); SD_PRINT_MATH_FUNC("p_cosh", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_cosh(bfloat16 val) { bfloat16 result = static_cast(coshf((float)val)); SD_PRINT_MATH_FUNC("p_cosh", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_cosh(double value) { double result = cosh(value); SD_PRINT_MATH_FUNC("p_cosh", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_cosh(T value) { T result = static_cast(coshf(static_cast(value))); SD_PRINT_MATH_FUNC("p_cosh", value, result,T); return result; } // p_acosh #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_acosh(float value) { float result = acoshf(value); SD_PRINT_MATH_FUNC("p_acosh", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_acosh(float16 val) { float16 result = static_cast(acoshf((float)val)); SD_PRINT_MATH_FUNC("p_acosh", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_acosh(bfloat16 val) { bfloat16 result = static_cast(acoshf((float)val)); SD_PRINT_MATH_FUNC("p_acosh", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_acosh(double value) { double result = acosh(value); SD_PRINT_MATH_FUNC("p_acosh", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_acosh(T value) { T result = static_cast(acoshf(static_cast(value))); SD_PRINT_MATH_FUNC("p_acosh", value, result,T); return result; } // p_sinh #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_sinh(float value) { float result = sinhf(value); SD_PRINT_MATH_FUNC("p_sinh", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_sinh(float16 val) { float16 result = static_cast(sinhf((float)val)); SD_PRINT_MATH_FUNC("p_sinh", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_sinh(bfloat16 val) { bfloat16 result = static_cast(sinhf((float)val)); SD_PRINT_MATH_FUNC("p_sinh", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_sinh(double value) { double result = sinh(value); SD_PRINT_MATH_FUNC("p_sinh", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_sinh(T value) { T result = static_cast(sinhf(static_cast(value))); SD_PRINT_MATH_FUNC("p_sinh", value, result,T); return result; } // p_asin #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_asin(float value) { float result = asinf(value); SD_PRINT_MATH_FUNC("p_asin", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_asin(float16 val) { float16 result = static_cast(asinf((float)val)); SD_PRINT_MATH_FUNC("p_asin", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_asin(bfloat16 val) { bfloat16 result = static_cast(asinf((float)val)); SD_PRINT_MATH_FUNC("p_asin", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_asin(double value) { double result = asin(value); SD_PRINT_MATH_FUNC("p_asin", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_asin(T value) { T result = static_cast(asinf(static_cast(value))); SD_PRINT_MATH_FUNC("p_asin", value, result,T); return result; } // p_atan #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_atan(float value) { float result = atanf(value); SD_PRINT_MATH_FUNC("p_atan", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_atan(float16 val) { float16 result = static_cast(atanf((float)val)); SD_PRINT_MATH_FUNC("p_atan", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_atan(bfloat16 val) { bfloat16 result = static_cast(atanf((float)val)); SD_PRINT_MATH_FUNC("p_atan", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_atan(double value) { double result = atan(value); SD_PRINT_MATH_FUNC("p_atan", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_atan(T value) { T result = static_cast(atanf(static_cast(value))); SD_PRINT_MATH_FUNC("p_atan", value, result,T); return result; } // p_tan #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_tan(float value) { float result = tanf(value); SD_PRINT_MATH_FUNC("p_tan", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_tan(float16 val) { float16 result = static_cast(tanf((float)val)); SD_PRINT_MATH_FUNC("p_tan", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_tan(bfloat16 val) { bfloat16 result = static_cast(tanf((float)val)); SD_PRINT_MATH_FUNC("p_tan", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_tan(double value) { double result = tan(value); SD_PRINT_MATH_FUNC("p_tan", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_tan(T value) { T result = static_cast(tanf(static_cast(value))); SD_PRINT_MATH_FUNC("p_tan", value, result,T); return result; } // p_atanh #ifdef HAS_FLOAT32 template <> SD_INLINE SD_HOST_DEVICE float p_atanh(float value) { float result = atanhf(value); SD_PRINT_MATH_FUNC("p_atanh", value, result,float); return result; } #endif #ifdef HAS_FLOAT16 template <> SD_INLINE SD_HOST_DEVICE float16 p_atanh(float16 val) { float16 result = static_cast(atanhf((float)val)); SD_PRINT_MATH_FUNC("p_atanh", val, result,float16); return result; } #endif #ifdef HAS_BFLOAT16 template <> SD_INLINE SD_HOST_DEVICE bfloat16 p_atanh(bfloat16 val) { bfloat16 result = static_cast(atanhf((float)val)); SD_PRINT_MATH_FUNC("p_atanh", val, result,bfloat16); return result; } #endif #ifdef HAS_DOUBLE template <> SD_INLINE SD_HOST_DEVICE double p_atanh(double value) { double result = atanh(value); SD_PRINT_MATH_FUNC("p_atanh", value, result,double); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_atanh(T value) { T result = static_cast(atanhf(static_cast(value))); SD_PRINT_MATH_FUNC("p_atanh", value, result,T); return result; } // Rotational functions template SD_INLINE SD_HOST_DEVICE T _rotate_left(T value, T shift); template SD_INLINE SD_HOST_DEVICE T _rotate_right(T value, T shift); // Bool specializations (rotation of a single bit is a no-op) #ifdef HAS_BOOL template <> SD_INLINE SD_HOST_DEVICE bool _rotate_left(bool value, bool shift) { SD_PRINT_MATH_FUNC("_rotate_left", value, value, bool); return value; } template <> SD_INLINE SD_HOST_DEVICE bool _rotate_right(bool value, bool shift) { SD_PRINT_MATH_FUNC("_rotate_right", value, value, bool); return value; } #endif #ifdef HAS_INT8 template <> SD_INLINE SD_HOST_DEVICE int8_t _rotate_left(int8_t value, int8_t shift) { int8_t result = value << shift | value >> (8 - shift); SD_PRINT_MATH_FUNC("_rotate_left", value, result,int8_t); return result; } template <> SD_INLINE SD_HOST_DEVICE int8_t _rotate_right(int8_t value, int8_t shift) { int8_t result = value >> shift | value << (8 - shift); SD_PRINT_MATH_FUNC("_rotate_right", value, result,int8_t); return result; } #endif #ifdef HAS_UINT8 template <> SD_INLINE SD_HOST_DEVICE uint8_t _rotate_left(uint8_t value, uint8_t shift) { uint8_t result = value << shift | value >> (8 - shift); SD_PRINT_MATH_FUNC("_rotate_left", value, result,uint8_t); return result; } template <> SD_INLINE SD_HOST_DEVICE uint8_t _rotate_right(uint8_t value, uint8_t shift) { uint8_t result = value >> shift | value << (8 - shift); SD_PRINT_MATH_FUNC("_rotate_right", value, result,uint8_t); return result; } #include // for CHAR_BIT // Ensure 8-bit char environment static_assert(CHAR_BIT == 8, "rotate assumes 8-bit char."); template <> SD_INLINE SD_HOST_DEVICE char _rotate_left(char value, char shift) { // Normalize shift to [0,7] and operate on unsigned to avoid sign-extended shifts const unsigned char v = static_cast(value); const unsigned int s = static_cast(shift) & 7u; const unsigned char r = static_cast((v << s) | (v >> ((8u - s) & 7u))); const char result = static_cast(r); SD_PRINT_MATH_FUNC("_rotate_left", value, result, char); return result; } template <> SD_INLINE SD_HOST_DEVICE char _rotate_right(char value, char shift) { const unsigned char v = static_cast(value); const unsigned int s = static_cast(shift) & 7u; const unsigned char r = static_cast((v >> s) | (v << ((8u - s) & 7u))); const char result = static_cast(r); SD_PRINT_MATH_FUNC("_rotate_right", value, result, char); return result; } #endif #ifdef HAS_INT16 template <> SD_INLINE SD_HOST_DEVICE int16_t _rotate_left(int16_t value, int16_t shift) { int16_t result = value << shift | value >> (16 - shift); SD_PRINT_MATH_FUNC("_rotate_left", value, result,int16_t); return result; } template <> SD_INLINE SD_HOST_DEVICE int16_t _rotate_right(int16_t value, int16_t shift) { int16_t result = value >> shift | value << (16 - shift); SD_PRINT_MATH_FUNC("_rotate_right", value, result,int16_t); return result; } #endif #ifdef HAS_UINT16 template <> SD_INLINE SD_HOST_DEVICE uint16_t _rotate_left(uint16_t value, uint16_t shift) { uint16_t result = value << shift | value >> (16 - shift); SD_PRINT_MATH_FUNC("_rotate_left", value, result,uint16_t); return result; } template <> SD_INLINE SD_HOST_DEVICE uint16_t _rotate_right(uint16_t value, uint16_t shift) { uint16_t result = value >> shift | value << (16 - shift); SD_PRINT_MATH_FUNC("_rotate_right", value, result,uint16_t); return result; } #endif #ifdef HAS_INT32 template <> SD_INLINE SD_HOST_DEVICE int _rotate_left(int value, int shift) { int result = value << shift | value >> (32 - shift); SD_PRINT_MATH_FUNC("_rotate_left", value, result,int); return result; } template <> SD_INLINE SD_HOST_DEVICE int _rotate_right(int value, int shift) { int result = value >> shift | value << (32 - shift); SD_PRINT_MATH_FUNC("_rotate_right", value, result,int); return result; } #endif #ifdef HAS_UINT32 template <> SD_INLINE SD_HOST_DEVICE uint32_t _rotate_left(uint32_t value, uint32_t shift) { uint32_t result = value << shift | value >> (32 - shift); SD_PRINT_MATH_FUNC("_rotate_left", value, result,uint32_t); return result; } template <> SD_INLINE SD_HOST_DEVICE uint32_t _rotate_right(uint32_t value, uint32_t shift) { uint32_t result = value >> shift | value << (32 - shift); SD_PRINT_MATH_FUNC("_rotate_right", value, result,uint32_t); return result; } #endif #ifdef HAS_INT64 template <> SD_INLINE SD_HOST_DEVICE sd::LongType _rotate_left(sd::LongType value, sd::LongType shift) { sd::LongType result = value << shift | value >> (64 - shift); SD_PRINT_MATH_FUNC("_rotate_left", value, result,sd::LongType); return result; } template <> SD_INLINE SD_HOST_DEVICE sd::LongType _rotate_right(sd::LongType value, sd::LongType shift) { sd::LongType result = value >> shift | value << (64 - shift); SD_PRINT_MATH_FUNC("_rotate_right", value, result,sd::LongType); return result; } #endif #ifdef HAS_UINT64 template <> SD_INLINE SD_HOST_DEVICE uint64_t _rotate_left(unsigned long value, unsigned long shift) { #ifdef SD_ARM_BUILD // TODO: eventually remove this once gcc fixes the bug sd::LongType val = _rotate_left(*reinterpret_cast(&value), *reinterpret_cast(&shift)); uint64_t result = *reinterpret_cast(&val); #else uint64_t result = value << shift | value >> (64 - shift); #endif SD_PRINT_MATH_FUNC("_rotate_left", value, result,unsigned long); return result; } template <> SD_INLINE SD_HOST_DEVICE unsigned long _rotate_right(unsigned long value, unsigned long shift) { #ifdef SD_ARM_BUILD // TODO: eventually remove this once gcc fixes the bug sd::LongType val = _rotate_right(*reinterpret_cast(&value), *reinterpret_cast(&shift)); uint64_t result = *reinterpret_cast(&val); #else uint64_t result = value >> shift | value << (64 - shift); #endif SD_PRINT_MATH_FUNC("_rotate_right", value, result,unsigned long); return result; } // Add specializations for unsigned long long (sd::UnsignedLong typedef) template <> SD_INLINE SD_HOST_DEVICE unsigned long long _rotate_left(unsigned long long value, unsigned long long shift) { unsigned long long result = value << shift | value >> (64 - shift); SD_PRINT_MATH_FUNC("_rotate_left", value, result, unsigned long long); return result; } template <> SD_INLINE SD_HOST_DEVICE unsigned long long _rotate_right(unsigned long long value, unsigned long long shift) { unsigned long long result = value >> shift | value << (64 - shift); SD_PRINT_MATH_FUNC("_rotate_right", value, result, unsigned long long); return result; } #endif template SD_INLINE SD_HOST_DEVICE T p_rotl(T value, T shift) { T result = _rotate_left(value, shift); SD_PRINT_MATH_FUNC("p_rotl", value, result,T); return result; } template SD_INLINE SD_HOST_DEVICE T p_rotr(T value, T shift) { T result = _rotate_right(value, shift); SD_PRINT_MATH_FUNC("p_rotr", value, result,T); return result; } } // namespace math } // namespace sd #endif // LIBND4J_PLATFORM_MATH_H