chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:47:05 +08:00
commit 4f3b7da785
7394 changed files with 2005594 additions and 0 deletions
+615
View File
@@ -0,0 +1,615 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
/*
Intel bfloat16 data type, based on
https://software.intel.com/sites/default/files/managed/40/8b/bf16-hardware-numerics-definition-white-paper.pdf
*/
#ifndef __UTIL_TYPES_BFLOAT16__H__
#define __UTIL_TYPES_BFLOAT16__H__
#include <system/common.h>
#include <cfloat>
#include <iosfwd>
#include <iostream>
#include <type_traits>
#include <limits>
#include <cmath>
// Forward declarations to avoid circular dependencies
struct float16;
// Type trait for SIMD safety
template<typename T>
struct is_simd_native {
static constexpr bool value = std::is_same<T, float>::value ||
std::is_same<T, double>::value ||
std::is_integral<T>::value;
};
template<typename T>
struct is_bfloat16_type {
static constexpr bool value = false;
};
template <typename T>
struct isNumericType {
static bool constexpr value = std::is_same<double, T>::value || std::is_same<float, T>::value ||
std::is_same<int, T>::value || std::is_same<unsigned int, T>::value ||
std::is_same<long long, T>::value || std::is_same<unsigned long long, T>::value ||
std::is_same<long int, T>::value || std::is_same<long unsigned int, T>::value ||
std::is_same<int8_t, T>::value || std::is_same<uint8_t, T>::value ||
std::is_same<int16_t, T>::value || std::is_same<uint16_t, T>::value ||
std::is_same<bool, T>::value ||
std::is_same<signed char, T>::value || std::is_same<unsigned char, T>::value ||
std::is_same<char, T>::value;
};
// Forward declaration
struct bfloat16;
// Specialization for bfloat16
template<>
struct is_bfloat16_type<bfloat16> {
static constexpr bool value = true;
};
struct alignas(2) bfloat16 {
public:
constexpr bfloat16(const bfloat16&) = default;
constexpr bfloat16& operator=(const bfloat16&) = default;
uint16_t _data;
// Default constructor
SD_INLINE SD_HOST_DEVICE constexpr bfloat16() : _data(0) {}
// Constructor from raw bits
SD_INLINE SD_HOST_DEVICE constexpr explicit bfloat16(uint16_t raw_bits) : _data(raw_bits) {}
// Constructor for atomic operations compatibility
SD_INLINE SD_HOST_DEVICE bfloat16(int16_t raw_bits) : _data(static_cast<uint16_t>(raw_bits)) {}
// Comprehensive constructors for all numeric types
// Double constructor
SD_INLINE SD_HOST_DEVICE bfloat16(double value) : _data(0) {
*this = static_cast<float>(value);
}
// Float constructor
SD_INLINE SD_HOST_DEVICE bfloat16(float value) : _data(0) {
*this = value;
}
// Integer constructors
SD_INLINE SD_HOST_DEVICE bfloat16(int value) : _data(0) {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE bfloat16(unsigned int value) : _data(0) {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE bfloat16(long long value) : _data(0) {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE bfloat16(unsigned long long value) : _data(0) {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE bfloat16(long int value) : _data(0) {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE bfloat16(long unsigned int value) : _data(0) {
*this = static_cast<float>(value);
}
// Fixed-width integer constructors
SD_INLINE SD_HOST_DEVICE bfloat16(int8_t value) : _data(0) {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE bfloat16(uint8_t value) : _data(0) {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE bfloat16(char value) : _data(0) {
*this = static_cast<float>(value);
}
// Boolean constructor
SD_INLINE SD_HOST_DEVICE bfloat16(bool value) : _data(0) {
*this = value ? 1.0f : 0.0f;
}
// float16 constructor - DECLARATION ONLY (defined in types_impl.h)
SD_INLINE SD_HOST_DEVICE explicit bfloat16(const float16& value);
// Float conversion
SD_INLINE SD_HOST_DEVICE operator float() const {
union {
uint32_t i;
float f;
} u;
u.i = static_cast<uint32_t>(_data) << 16;
return u.f;
}
SD_INLINE SD_HOST_DEVICE explicit operator bool() const { return this->_data != 0; }
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value &&
!std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE explicit operator T() const {
return static_cast<T>(static_cast<float>(*this));
}
SD_INLINE SD_HOST_DEVICE bfloat16& operator=(const bool rhs) {
*this = rhs ? 1.0f : 0.0f;
return *this;
}
// Add these assignment operators to the bfloat16 struct
SD_INLINE SD_HOST_DEVICE bfloat16& operator=(const char rhs) {
return operator=(static_cast<float>(rhs));
}
SD_INLINE SD_HOST_DEVICE bfloat16& operator=(const unsigned char rhs) {
return operator=(static_cast<float>(rhs));
}
SD_INLINE SD_HOST_DEVICE bfloat16& operator=(const float& rhs) {
#if defined(__CUDA_ARCH__)
if (isnan(rhs)) {
_data = 0x7FC0;
return *this;
}
#else
if (std::isnan(rhs)) {
_data = 0x7FC0;
return *this;
}
#endif
union {
float f;
uint32_t i;
} u;
u.f = rhs;
uint32_t lsb = (u.i >> 16) & 1;
uint32_t rounding_bias = 0x7fff + lsb;
u.i += rounding_bias;
this->_data = static_cast<uint16_t>(u.i >> 16);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value &&
!std::is_same<T, float>::value &&
!std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE bfloat16& operator=(const T& rhs) {
return operator=(static_cast<float>(rhs));
}
// Comparison operators
SD_INLINE SD_HOST_DEVICE friend bool operator==(const bfloat16& a, const bfloat16& b) {
if ((a._data & 0x7F80) == 0x7F80 && (a._data & 0x007F) != 0) return false;
if ((b._data & 0x7F80) == 0x7F80 && (b._data & 0x007F) != 0) return false;
return static_cast<float>(a) == static_cast<float>(b);
}
SD_INLINE SD_HOST_DEVICE friend bool operator!=(const bfloat16& a, const bfloat16& b) {
return !(a == b);
}
SD_INLINE SD_HOST_DEVICE friend bool operator<(const bfloat16& a, const bfloat16& b) {
return static_cast<float>(a) < static_cast<float>(b);
}
SD_INLINE SD_HOST_DEVICE friend bool operator>(const bfloat16& a, const bfloat16& b) {
return static_cast<float>(a) > static_cast<float>(b);
}
SD_INLINE SD_HOST_DEVICE friend bool operator<=(const bfloat16& a, const bfloat16& b) {
return static_cast<float>(a) <= static_cast<float>(b);
}
SD_INLINE SD_HOST_DEVICE friend bool operator>=(const bfloat16& a, const bfloat16& b) {
return static_cast<float>(a) >= static_cast<float>(b);
}
// Arithmetic operators
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator+(const bfloat16& a, const bfloat16& b) {
return bfloat16(static_cast<float>(a) + static_cast<float>(b));
}
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator-(const bfloat16& a, const bfloat16& b) {
return bfloat16(static_cast<float>(a) - static_cast<float>(b));
}
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator*(const bfloat16& a, const bfloat16& b) {
return bfloat16(static_cast<float>(a) * static_cast<float>(b));
}
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator/(const bfloat16& a, const bfloat16& b) {
return bfloat16(static_cast<float>(a) / static_cast<float>(b));
}
// Mixed type operators
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator+(const bfloat16& a, const T& b) {
return bfloat16(static_cast<float>(a) + static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator+(const T& a, const bfloat16& b) {
return bfloat16(static_cast<float>(a) + static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator-(const bfloat16& a, const T& b) {
return bfloat16(static_cast<float>(a) - static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator-(const T& a, const bfloat16& b) {
return bfloat16(static_cast<float>(a) - static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator*(const bfloat16& a, const T& b) {
return bfloat16(static_cast<float>(a) * static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator*(const T& a, const bfloat16& b) {
return bfloat16(static_cast<float>(a) * static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator/(const bfloat16& a, const T& b) {
return bfloat16(static_cast<float>(a) / static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bfloat16 operator/(const T& a, const bfloat16& b) {
return bfloat16(static_cast<float>(a) / static_cast<float>(b));
}
// Mixed type comparison operators
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator==(const bfloat16& a, const T& b) {
return static_cast<float>(a) == static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator==(const T& a, const bfloat16& b) {
return static_cast<float>(a) == static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator!=(const bfloat16& a, const T& b) {
return static_cast<float>(a) != static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator!=(const T& a, const bfloat16& b) {
return static_cast<float>(a) != static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator<(const bfloat16& a, const T& b) {
return static_cast<float>(a) < static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator<(const T& a, const bfloat16& b) {
return static_cast<float>(a) < static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator>(const bfloat16& a, const T& b) {
return static_cast<float>(a) > static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator>(const T& a, const bfloat16& b) {
return static_cast<float>(a) > static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator<=(const bfloat16& a, const T& b) {
return static_cast<float>(a) <= static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator<=(const T& a, const bfloat16& b) {
return static_cast<float>(a) <= static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator>=(const bfloat16& a, const T& b) {
return static_cast<float>(a) >= static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator>=(const T& a, const bfloat16& b) {
return static_cast<float>(a) >= static_cast<float>(b);
}
// Compound assignment operators
SD_INLINE SD_HOST_DEVICE bfloat16& operator+=(const bfloat16& rhs) {
*this = static_cast<float>(*this) + static_cast<float>(rhs);
return *this;
}
SD_INLINE SD_HOST_DEVICE bfloat16& operator-=(const bfloat16& rhs) {
*this = static_cast<float>(*this) - static_cast<float>(rhs);
return *this;
}
SD_INLINE SD_HOST_DEVICE bfloat16& operator*=(const bfloat16& rhs) {
*this = static_cast<float>(*this) * static_cast<float>(rhs);
return *this;
}
SD_INLINE SD_HOST_DEVICE bfloat16& operator/=(const bfloat16& rhs) {
*this = static_cast<float>(*this) / static_cast<float>(rhs);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE bfloat16& operator+=(const T& rhs) {
*this = static_cast<float>(*this) + static_cast<float>(rhs);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE bfloat16& operator-=(const T& rhs) {
*this = static_cast<float>(*this) - static_cast<float>(rhs);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE bfloat16& operator*=(const T& rhs) {
*this = static_cast<float>(*this) * static_cast<float>(rhs);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, float16>::value
>::type>
SD_INLINE SD_HOST_DEVICE bfloat16& operator/=(const T& rhs) {
*this = static_cast<float>(*this) / static_cast<float>(rhs);
return *this;
}
// Increment/decrement operators
SD_INLINE SD_HOST_DEVICE bfloat16& operator++() {
*this = static_cast<float>(*this) + 1.0f;
return *this;
}
SD_INLINE SD_HOST_DEVICE bfloat16& operator--() {
*this = static_cast<float>(*this) - 1.0f;
return *this;
}
SD_INLINE SD_HOST_DEVICE bfloat16 operator++(int) {
bfloat16 tmp = *this;
*this = static_cast<float>(*this) + 1.0f;
return tmp;
}
SD_INLINE SD_HOST_DEVICE bfloat16 operator--(int) {
bfloat16 tmp = *this;
*this = static_cast<float>(*this) - 1.0f;
return tmp;
}
SD_INLINE SD_HOST_DEVICE bfloat16 operator-() const {
bfloat16 result;
result._data = _data ^ 0x8000;
return result;
}
// Static utility methods
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 min() {
return bfloat16(static_cast<uint16_t>(0x0080));
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 lowest() {
return bfloat16(static_cast<uint16_t>(0xFF7F));
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 max() {
return bfloat16(static_cast<uint16_t>(0x7F7F));
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 epsilon() {
return bfloat16(static_cast<uint16_t>(0x3C00));
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 round_error() {
return bfloat16(static_cast<uint16_t>(0x3F00));
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 infinity() {
return bfloat16(static_cast<uint16_t>(0x7F80));
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 quiet_NaN() {
return bfloat16(static_cast<uint16_t>(0x7FC0));
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 signaling_NaN() {
return bfloat16(static_cast<uint16_t>(0x7FA0));
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 denorm_min() {
return bfloat16(static_cast<uint16_t>(0x0001));
}
// Legacy aliases
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 eps() {
return epsilon();
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 inf() {
return infinity();
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 nan() {
return quiet_NaN();
}
SD_INLINE SD_HOST_DEVICE static constexpr bfloat16 min_positive() {
return denorm_min();
}
// Helper methods
SD_INLINE SD_HOST_DEVICE static float as_float(const bfloat16& bf16) {
return static_cast<float>(bf16);
}
SD_INLINE SD_HOST_DEVICE static bfloat16 from_float(float f) {
return bfloat16(f);
}
};
// Ensure proper alignment
static_assert(sizeof(bfloat16) == 2, "bfloat16 must be 2 bytes");
static_assert(alignof(bfloat16) >= 2, "bfloat16 must be at least 2-byte aligned");
namespace std {
template<>
struct is_arithmetic<bfloat16> : std::true_type {};
template<>
struct is_floating_point<bfloat16> : std::true_type {};
template<>
struct numeric_limits<bfloat16> {
static constexpr bool is_specialized = true;
static constexpr bool is_signed = true;
static constexpr bool is_integer = false;
static constexpr bool is_exact = false;
static constexpr bool has_infinity = true;
static constexpr bool has_quiet_NaN = true;
static constexpr bool has_signaling_NaN = true;
static constexpr float_denorm_style has_denorm = denorm_present;
static constexpr bool has_denorm_loss = false;
static constexpr float_round_style round_style = round_to_nearest;
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
static constexpr int digits = 8;
static constexpr int digits10 = 2;
static constexpr int max_digits10 = 4;
static constexpr int radix = 2;
static constexpr int min_exponent = -125;
static constexpr int min_exponent10 = -37;
static constexpr int max_exponent = 128;
static constexpr int max_exponent10 = 38;
static constexpr bfloat16 min() noexcept { return bfloat16::min(); }
static constexpr bfloat16 lowest() noexcept { return bfloat16::lowest(); }
static constexpr bfloat16 max() noexcept { return bfloat16::max(); }
static constexpr bfloat16 epsilon() noexcept { return bfloat16::epsilon(); }
static constexpr bfloat16 round_error() noexcept { return bfloat16::round_error(); }
static constexpr bfloat16 infinity() noexcept { return bfloat16::infinity(); }
static constexpr bfloat16 quiet_NaN() noexcept { return bfloat16::quiet_NaN(); }
static constexpr bfloat16 signaling_NaN() noexcept { return bfloat16::signaling_NaN(); }
static constexpr bfloat16 denorm_min() noexcept { return bfloat16::denorm_min(); }
};
#ifdef __CUDACC__
SD_INLINE SD_HOST_DEVICE bool isnan(const bfloat16& bf) {
return (bf._data & 0x7F80) == 0x7F80 && (bf._data & 0x007F) != 0;
}
SD_INLINE SD_HOST_DEVICE bool isinf(const bfloat16& bf) {
return (bf._data & 0x7F80) == 0x7F80 && (bf._data & 0x007F) == 0;
}
SD_INLINE SD_HOST_DEVICE bool isfinite(const bfloat16& bf) {
return (bf._data & 0x7F80) != 0x7F80;
}
#endif
}
#endif
+821
View File
@@ -0,0 +1,821 @@
/* ******************************************************************************
*
*
* 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_FLOAT16_H
#define LIBND4J_FLOAT16_H
#include <system/common.h>
#include <cfloat>
#include <iosfwd>
#include <iostream>
#include <type_traits>
#include <limits>
#if defined(__INTEL_COMPILER) || defined(SD_F16C)
#include <immintrin.h>
#endif
// Forward declarations to avoid circular dependencies
struct bfloat16;
#if defined(__CUDACC__)
#include <cuda_fp16.h>
#if CUDA_VERSION_MAJOR != 8
// CUDA_9 and above
struct ihalf : public __half {
public:
SD_HOST_DEVICE ihalf() : __half() {
//
}
SD_INLINE SD_HOST_DEVICE unsigned short* getXP() { return &this->__x; }
SD_INLINE SD_HOST_DEVICE unsigned short getX() const { return this->__x; }
SD_INLINE SD_HOST_DEVICE void assign(const __half f) { this->__x = ((__half_raw*)&f)->x; }
};
#else
struct ihalf : public __half {
public:
SD_HOST_DEVICE ihalf() : __half() {
//
}
SD_INLINE SD_HOST_DEVICE unsigned short* getXP() { return &this->x; }
SD_INLINE SD_HOST_DEVICE unsigned short getX() const { return this->x; }
SD_INLINE SD_HOST_DEVICE void assign(const __half f) { this->x = ((__half*)&f)->x; }
};
#endif // CUDA_8
#else
struct alignas(2) __half {
public:
unsigned short x;
inline unsigned short* getXP() { return &this->x; }
inline unsigned short getX() const { return this->x; }
};
typedef __half half;
typedef __half ihalf;
#endif // CUDA
static SD_INLINE SD_HOST_DEVICE int ishnan_(unsigned short h) { return (h & 0x7c00U) == 0x7c00U && (h & 0x03ffU) != 0; }
static SD_INLINE SD_HOST_DEVICE int ishinf_(unsigned short h) { return (h & 0x7c00U) == 0x7c00U && (h & 0x03ffU) == 0; }
static SD_INLINE SD_HOST_DEVICE int ishequ_(unsigned short x, unsigned short y) {
return ishnan_(x) == 0 && ishnan_(y) == 0 && x == y;
}
static SD_INLINE SD_HOST_DEVICE unsigned short hneg(unsigned short h) {
h ^= 0x8000U;
return h;
}
#if defined(__INTEL_COMPILER) || defined(SD_F16C)
//_Pragma("omp declare simd") inline
SD_INLINE SD_HOST_DEVICE float cpu_ihalf2float(ihalf h) { return _cvtsh_ss(h.getX()); }
#else
SD_INLINE SD_HOST_DEVICE float cpu_ihalf2float(ihalf h) {
unsigned sign = ((h.getX() >> 15) & 1);
unsigned exponent = ((h.getX() >> 10) & 0x1f);
unsigned mantissa = ((h.getX() & 0x3ff) << 13);
if (exponent == 0x1f) { /* NaN or Inf */
mantissa = (mantissa ? (sign = 0, 0x7fffff) : 0);
exponent = 0xff;
} else if (!exponent) { /* Denorm or Zero */
if (mantissa) {
unsigned int msb;
exponent = 0x71;
do {
msb = (mantissa & 0x400000);
mantissa <<= 1; /* normalize */
--exponent;
} while (!msb);
mantissa &= 0x7fffff; /* 1.mantissa is implicit */
}
} else {
exponent += 0x70;
}
union {
int i;
float f;
} u;
u.i = ((sign << 31) | (exponent << 23) | mantissa);
return u.f;
}
#endif
#if defined(__INTEL_COMPILER) || defined(SD_F16C)
//_Pragma("omp declare simd") inline
SD_INLINE SD_HOST_DEVICE ihalf cpu_float2ihalf_rn(float f) {
ihalf ret;
ret.x = _cvtss_sh(f, 0);
return ret;
}
#else
SD_INLINE SD_HOST_DEVICE ihalf cpu_float2ihalf_rn(float f) {
ihalf ret;
union {
float f;
int i;
} u;
u.f = f;
unsigned x = u.i;
unsigned u_val = (x & 0x7fffffff), remainder, shift, lsb, lsb_s1, lsb_m1;
unsigned sign, exponent, mantissa;
// Get rid of +NaN/-NaN case first.
if (u_val > 0x7f800000) {
*ret.getXP() = 0x7fffU;
return ret;
}
sign = ((x >> 16) & 0x8000);
// Get rid of +Inf/-Inf, +0/-0.
if (u_val > 0x477fefff) {
*ret.getXP() = sign | 0x7c00U;
return ret;
}
if (u_val < 0x33000001) {
*ret.getXP() = (sign | 0x0000);
return ret;
}
exponent = ((u_val >> 23) & 0xff);
mantissa = (u_val & 0x7fffff);
if (exponent > 0x70) {
shift = 13;
exponent -= 0x70;
} else {
shift = 0x7e - exponent;
exponent = 0;
mantissa |= 0x800000;
}
lsb = (1 << shift);
lsb_s1 = (lsb >> 1);
lsb_m1 = (lsb - 1);
// Round to nearest even.
remainder = (mantissa & lsb_m1);
mantissa >>= shift;
if (remainder > lsb_s1 || (remainder == lsb_s1 && (mantissa & 0x1))) {
++mantissa;
if (!(mantissa & 0x3ff)) {
++exponent;
mantissa = 0;
}
}
*ret.getXP() = (sign | (exponent << 10) | mantissa);
return ret;
}
#endif
struct alignas(2) float16 {
private:
template <typename T>
struct isNumericType {
static bool const value = std::is_same<double, T>::value || std::is_same<float, T>::value ||
std::is_same<int, T>::value || std::is_same<unsigned int, T>::value ||
std::is_same<long long, T>::value || std::is_same<unsigned long long, T>::value ||
std::is_same<long int, T>::value || std::is_same<long unsigned int, T>::value ||
std::is_same<int8_t, T>::value || std::is_same<uint8_t, T>::value ||
std::is_same<int16_t, T>::value || std::is_same<uint16_t, T>::value ||
std::is_same<bool, T>::value;
};
public:
float16(const float16&) = default;
float16& operator=(const float16&) = default;
ihalf data;
// Default constructor
SD_INLINE SD_HOST_DEVICE float16() : data{} {
#ifndef __CUDACC__
*data.getXP() = 0;
#endif
}
// Constructor from raw bits
SD_INLINE SD_HOST_DEVICE explicit float16(unsigned short raw_bits) : data{} {
*data.getXP() = raw_bits;
}
// Comprehensive constructors for all numeric types
// Double constructor
SD_INLINE SD_HOST_DEVICE float16(double value) : data{} {
*this = static_cast<float>(value);
}
// Float constructor
SD_INLINE SD_HOST_DEVICE float16(float value) : data{} {
*this = value;
}
// Integer constructors
SD_INLINE SD_HOST_DEVICE float16(int value) : data{} {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE float16(unsigned int value) : data{} {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE float16(long long value) : data{} {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE float16(unsigned long long value) : data{} {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE float16(long int value) : data{} {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE float16(long unsigned int value) : data{} {
*this = static_cast<float>(value);
}
// Fixed-width integer constructors
SD_INLINE SD_HOST_DEVICE float16(int8_t value) : data{} {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE float16(uint8_t value) : data{} {
*this = static_cast<float>(value);
}
SD_INLINE SD_HOST_DEVICE float16(int16_t value) : data{} {
*this = static_cast<float>(value);
}
// Boolean constructor
SD_INLINE SD_HOST_DEVICE float16(bool value) : data{} {
*this = value ? 1.0f : 0.0f;
}
// bfloat16 constructor - DECLARATION ONLY (defined in types_impl.h)
SD_INLINE SD_HOST_DEVICE explicit float16(const bfloat16& value);
SD_INLINE SD_HOST_DEVICE float16(const half& rhs) : data{} {
#ifdef __CUDACC__
data.assign(rhs);
#endif
}
SD_INLINE SD_HOST_DEVICE operator float() const {
#if defined(__CUDA_ARCH__)
return __half2float(data);
#else
return cpu_ihalf2float(data);
#endif
}
SD_INLINE SD_HOST_DEVICE float16 operator|(int rhs) const {
float16 result;
*result.data.getXP() = static_cast<unsigned short>(this->data.getX() | static_cast<unsigned short>(rhs));
return result;
}
SD_INLINE SD_HOST_DEVICE float16 operator|(const float16& rhs) const {
float16 result;
*result.data.getXP() = static_cast<unsigned short>(this->data.getX() | rhs.data.getX());
return result;
}
SD_INLINE SD_HOST_DEVICE friend float16 operator|(int lhs, const float16& rhs) {
float16 result;
*result.data.getXP() = static_cast<unsigned short>(static_cast<unsigned short>(lhs) | rhs.data.getX());
return result;
}
SD_INLINE SD_HOST_DEVICE explicit operator bool() const { return static_cast<float>(*this) != 0.0f; }
SD_INLINE SD_HOST_DEVICE explicit operator half() const { return data; }
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE explicit operator T() const {
return static_cast<T>(static_cast<float>(*this));
}
SD_INLINE SD_HOST_DEVICE float16& operator=(const float& rhs) {
#if defined(__CUDA_ARCH__)
auto t = __float2half_rn(rhs);
auto b = *(data.getXP());
#if CUDA_VERSION_MAJOR == 8
*(data.getXP()) = t;
#else
data.assign(t);
#endif
#else
data = cpu_float2ihalf_rn(rhs);
#endif
return *this;
}
SD_INLINE SD_HOST_DEVICE float16 operator&(const float16& rhs) const {
float16 result;
*result.data.getXP() = static_cast<unsigned short>(this->data.getX() & rhs.data.getX());
return result;
}
SD_INLINE SD_HOST_DEVICE float16 operator&(int rhs) const {
float16 result;
*result.data.getXP() = static_cast<unsigned short>(this->data.getX() & static_cast<unsigned short>(rhs));
return result;
}
SD_INLINE SD_HOST_DEVICE float16& operator=(const unsigned short rhs) {
*data.getXP() = rhs;
return *this;
}
SD_INLINE SD_HOST_DEVICE float16& operator=(const bool rhs) {
*this = rhs ? 1.0f : 0.0f;
return *this;
}
// Add these assignment operators to the float16 struct
SD_INLINE SD_HOST_DEVICE float16& operator=(const char rhs) {
return operator=(static_cast<float>(rhs));
}
SD_INLINE SD_HOST_DEVICE float16& operator=(const unsigned char rhs) {
return operator=(static_cast<float>(rhs));
}
SD_INLINE SD_HOST_DEVICE float16& operator=(const ihalf& rhs) {
*data.getXP() = ((ihalf)rhs).getX();
return *this;
}
#if defined(__CUDACC__)
SD_INLINE SD_HOST_DEVICE float16& operator=(const half& rhs) {
data.assign(rhs);
return *this;
}
#endif
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value &&
!std::is_same<T, float>::value &&
!std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE float16& operator=(const T& rhs) {
return operator=(static_cast<float>(rhs));
}
#ifdef SD_NATIVE_HALFS
SD_INLINE SD_HOST_DEVICE friend bool operator==(const float16& a, const float16& b) { return __hequ(a.data, b.data); }
#else
SD_INLINE SD_HOST_DEVICE friend bool operator==(const float16& a, const float16& b) {
return ishequ_(((ihalf)a.data).getX(), ((ihalf)b.data).getX());
}
#endif
#ifdef SD_NATIVE_HALFS
SD_INLINE SD_HOST_DEVICE friend bool operator!=(const float16& a, const float16& b) {
return !(__hequ(a.data, b.data));
}
#else
SD_INLINE SD_HOST_DEVICE friend bool operator!=(const float16& a, const float16& b) { return !(a == b); }
#endif
#ifdef SD_NATIVE_HALFS
SD_INLINE SD_HOST_DEVICE friend bool operator<(const float16& a, const float16& b) { return __hlt(a.data, b.data); }
#else
SD_INLINE SD_HOST_DEVICE friend bool operator<(const float16& a, const float16& b) { return static_cast<float>(a) < static_cast<float>(b); }
#endif
#ifdef SD_NATIVE_HALFS
SD_INLINE SD_HOST_DEVICE friend bool operator>(const float16& a, const float16& b) { return __hgt(a.data, b.data); }
#else
SD_INLINE SD_HOST_DEVICE friend bool operator>(const float16& a, const float16& b) { return static_cast<float>(a) > static_cast<float>(b); }
#endif
#ifdef SD_NATIVE_HALFS
SD_INLINE SD_HOST_DEVICE friend bool operator<=(const float16& a, const float16& b) { return __hle(a.data, b.data); }
#else
SD_INLINE SD_HOST_DEVICE friend bool operator<=(const float16& a, const float16& b) { return static_cast<float>(a) <= static_cast<float>(b); }
#endif
#ifdef SD_NATIVE_HALFS
SD_INLINE SD_HOST_DEVICE friend bool operator>=(const float16& a, const float16& b) { return __hge(a.data, b.data); }
#else
SD_INLINE SD_HOST_DEVICE friend bool operator>=(const float16& a, const float16& b) { return static_cast<float>(a) >= static_cast<float>(b); }
#endif
#ifdef SD_NATIVE_HALFS
SD_INLINE SD_HOST_DEVICE friend float16 operator+(const float16& a, const float16& b) {
return __hadd(a.data, b.data);
}
SD_INLINE SD_HOST_DEVICE friend float16 operator-(const float16& a, const float16& b) {
return __hsub(a.data, b.data);
}
SD_INLINE SD_HOST_DEVICE friend float16 operator*(const float16& a, const float16& b) {
return __hmul(a.data, b.data);
}
SD_INLINE SD_HOST_DEVICE friend float16 operator/(const float16& a, const float16& b) {
#if CUDA_VERSION_MAJOR == 8
return hdiv(a.data, b.data);
#else
return __hdiv(a.data, b.data);
#endif
}
#else
SD_INLINE SD_HOST_DEVICE friend float16 operator+(const float16& a, const float16& b) {
return float16(static_cast<float>(a) + static_cast<float>(b));
}
SD_INLINE SD_HOST_DEVICE friend float16 operator-(const float16& a, const float16& b) {
return float16(static_cast<float>(a) - static_cast<float>(b));
}
SD_INLINE SD_HOST_DEVICE friend float16 operator*(const float16& a, const float16& b) {
return float16(static_cast<float>(a) * static_cast<float>(b));
}
SD_INLINE SD_HOST_DEVICE friend float16 operator/(const float16& a, const float16& b) {
return float16(static_cast<float>(a) / static_cast<float>(b));
}
#endif
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend float16 operator+(const float16& a, const T& b) {
return float16(static_cast<float>(a) + static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend float16 operator+(const T& a, const float16& b) {
return float16(static_cast<float>(a) + static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend float16 operator-(const float16& a, const T& b) {
return float16(static_cast<float>(a) - static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend float16 operator-(const T& a, const float16& b) {
return float16(static_cast<float>(a) - static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend float16 operator*(const float16& a, const T& b) {
return float16(static_cast<float>(a) * static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend float16 operator*(const T& a, const float16& b) {
return float16(static_cast<float>(a) * static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend float16 operator/(const float16& a, const T& b) {
return float16(static_cast<float>(a) / static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend float16 operator/(const T& a, const float16& b) {
return float16(static_cast<float>(a) / static_cast<float>(b));
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator==(const float16& a, const T& b) {
return static_cast<float>(a) == static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator==(const T& a, const float16& b) {
return static_cast<float>(a) == static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator!=(const float16& a, const T& b) {
return static_cast<float>(a) != static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator!=(const T& a, const float16& b) {
return static_cast<float>(a) != static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator<(const float16& a, const T& b) {
return static_cast<float>(a) < static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator<(const T& a, const float16& b) {
return static_cast<float>(a) < static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator>(const float16& a, const T& b) {
return static_cast<float>(a) > static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator>(const T& a, const float16& b) {
return static_cast<float>(a) > static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator<=(const float16& a, const T& b) {
return static_cast<float>(a) <= static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator<=(const T& a, const float16& b) {
return static_cast<float>(a) <= static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator>=(const float16& a, const T& b) {
return static_cast<float>(a) >= static_cast<float>(b);
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE friend bool operator>=(const T& a, const float16& b) {
return static_cast<float>(a) >= static_cast<float>(b);
}
// Compound assignment operators
SD_INLINE SD_HOST_DEVICE float16& operator+=(const float16& rhs) {
*this = static_cast<float>(*this) + static_cast<float>(rhs);
return *this;
}
SD_INLINE SD_HOST_DEVICE float16& operator-=(const float16& rhs) {
*this = static_cast<float>(*this) - static_cast<float>(rhs);
return *this;
}
SD_INLINE SD_HOST_DEVICE float16& operator*=(const float16& rhs) {
*this = static_cast<float>(*this) * static_cast<float>(rhs);
return *this;
}
SD_INLINE SD_HOST_DEVICE float16& operator/=(const float16& rhs) {
*this = static_cast<float>(*this) / static_cast<float>(rhs);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE float16& operator+=(const T& rhs) {
*this = static_cast<float>(*this) + static_cast<float>(rhs);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE float16& operator-=(const T& rhs) {
*this = static_cast<float>(*this) - static_cast<float>(rhs);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE float16& operator*=(const T& rhs) {
*this = static_cast<float>(*this) * static_cast<float>(rhs);
return *this;
}
template <typename T, typename = typename std::enable_if<
isNumericType<T>::value && !std::is_same<T, bfloat16>::value
>::type>
SD_INLINE SD_HOST_DEVICE float16& operator/=(const T& rhs) {
*this = static_cast<float>(*this) / static_cast<float>(rhs);
return *this;
}
SD_INLINE SD_HOST_DEVICE float16& operator++() {
*this = static_cast<float>(*this) + 1.0f;
return *this;
}
SD_INLINE SD_HOST_DEVICE float16& operator--() {
*this = static_cast<float>(*this) - 1.0f;
return *this;
}
SD_INLINE SD_HOST_DEVICE float16 operator++(int) {
float16 tmp = *this;
*this = static_cast<float>(*this) + 1.0f;
return tmp;
}
SD_INLINE SD_HOST_DEVICE float16 operator--(int) {
float16 tmp = *this;
*this = static_cast<float>(*this) - 1.0f;
return tmp;
}
SD_INLINE SD_HOST_DEVICE float16 operator-() const {
float16 result;
*result.data.getXP() = data.getX() ^ 0x8000U;
return result;
}
// Static utility methods
SD_INLINE SD_HOST_DEVICE static float16 min() {
float16 result;
*result.data.getXP() = 0x0400;
return result;
}
SD_INLINE SD_HOST_DEVICE static float16 max() {
float16 result;
*result.data.getXP() = 0x7BFF;
return result;
}
SD_INLINE SD_HOST_DEVICE static float16 infinity() {
float16 result;
*result.data.getXP() = 0x7C00;
return result;
}
SD_INLINE SD_HOST_DEVICE static float16 quiet_NaN() {
float16 result;
*result.data.getXP() = 0x7E00;
return result;
}
// Helper methods
SD_INLINE SD_HOST_DEVICE static float as_float(const float16& f16) {
return static_cast<float>(f16);
}
SD_INLINE SD_HOST_DEVICE static float16 from_float(float f) {
return float16(f);
}
};
static_assert(sizeof(float16) == 2, "float16 must be 2 bytes");
static_assert(alignof(float16) >= 2, "float16 must be at least 2-byte aligned");
namespace std {
template<>
struct is_arithmetic<float16> : std::true_type {};
template<>
struct is_floating_point<float16> : std::true_type {};
template<>
struct numeric_limits<float16> {
static constexpr bool is_specialized = true;
static constexpr bool is_signed = true;
static constexpr bool is_integer = false;
static constexpr bool is_exact = false;
static constexpr bool has_infinity = true;
static constexpr bool has_quiet_NaN = true;
static constexpr bool has_signaling_NaN = false;
static constexpr float_denorm_style has_denorm = denorm_present;
static constexpr bool has_denorm_loss = false;
static constexpr float_round_style round_style = round_to_nearest;
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
static constexpr int digits = 11;
static constexpr int digits10 = 3;
static constexpr int max_digits10 = 5;
static constexpr int radix = 2;
static constexpr int min_exponent = -13;
static constexpr int min_exponent10 = -4;
static constexpr int max_exponent = 16;
static constexpr int max_exponent10 = 4;
static float16 min() noexcept {
float16 result;
*result.data.getXP() = 0x0400;
return result;
}
static float16 lowest() noexcept {
float16 result;
*result.data.getXP() = 0xFBFF;
return result;
}
static float16 max() noexcept {
float16 result;
*result.data.getXP() = 0x7BFF;
return result;
}
static float16 epsilon() noexcept {
float16 result;
*result.data.getXP() = 0x1400;
return result;
}
static float16 round_error() noexcept {
float16 result;
*result.data.getXP() = 0x3800;
return result;
}
static float16 infinity() noexcept {
float16 result;
*result.data.getXP() = 0x7C00;
return result;
}
static float16 quiet_NaN() noexcept {
float16 result;
*result.data.getXP() = 0x7E00;
return result;
}
static float16 signaling_NaN() noexcept {
float16 result;
*result.data.getXP() = 0x7D00;
return result;
}
static float16 denorm_min() noexcept {
float16 result;
*result.data.getXP() = 0x0001;
return result;
}
};
}
#ifdef CUDACC
SD_INLINE SD_HOST_DEVICE int isnan(const float16& h) { return ishnan_(((ihalf)h.data).getX()); }
SD_INLINE SD_HOST_DEVICE int isinf(const float16& h) { return ishinf_(((ihalf)h.data).getX()); }
#endif
#endif
+163
View File
@@ -0,0 +1,163 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver119 on 10.08.16.
//
#ifndef LIBND4J_FLOAT8_H
#define LIBND4J_FLOAT8_H
#include <system/op_boilerplate.h>
namespace sd {
typedef struct {
unsigned char x;
} __quarter;
typedef __quarter quarter;
quarter SD_INLINE SD_HOST_DEVICE cpu_float2quarter_rn(float f);
float SD_INLINE SD_HOST_DEVICE cpu_quarter2float(quarter b);
struct float8 {
constexpr float8(const float8&) = default;
quarter data;
SD_INLINE SD_HOST_DEVICE float8();
template <class T>
SD_INLINE SD_HOST_DEVICE float8(const T& rhs);
template <class T>
SD_INLINE SD_HOST_DEVICE float8& operator=(const T& rhs);
SD_INLINE SD_HOST_DEVICE operator float() const;
SD_INLINE SD_HOST_DEVICE void assign(double rhs);
SD_INLINE SD_HOST_DEVICE void assign(float rhs);
};
float cpu_quarter2float(quarter b) {
unsigned sign = ((b.x >> 7) & 1);
unsigned exponent = ((b.x >> 4) & 0x7);
unsigned mantissa = ((b.x & 0xf) << 19);
if (exponent == 0x7) { /* NaN or Inf */
mantissa = (mantissa ? (sign = 0, 0x7fffff) : 0);
exponent = 0xff;
} else if (!exponent) { /* Denorm or Zero */
if (mantissa) {
unsigned int msb;
exponent = 0x7d;
do {
msb = (mantissa & 0x400000);
mantissa <<= 1; /* normalize */
--exponent;
} while (!msb);
mantissa &= 0x7fffff; /* 1.mantissa is implicit */
}
} else {
exponent += 0x7C;
}
int temp = ((sign << 31) | (exponent << 23) | mantissa);
return *((float*)((void*)&temp));
}
quarter cpu_float2quarter_rn(float f) {
quarter ret;
unsigned x = *((int*)(void*)(&f));
unsigned u = (x & 0x7fffffff), remainder, shift, lsb, lsb_s1, lsb_m1;
unsigned sign, exponent, mantissa;
// Get rid of +NaN/-NaN case first.
if (u > 0x7f800000) {
ret.x = 0x7fU;
return ret;
}
sign = ((x >> 24) & 0x80);
// Get rid of +Inf/-Inf, +0/-0.
if (u > 0x477fefff) {
ret.x = sign | 0x70U;
return ret;
}
if (u < 0x33000001) {
ret.x = (sign | 0x00);
return ret;
}
exponent = ((u >> 23) & 0xff);
mantissa = (u & 0x7fffff);
if (exponent > 0x7C) {
shift = 19;
exponent -= 0x7C;
} else {
shift = 0x90 - exponent;
exponent = 0;
mantissa |= 0x800000;
}
lsb = (1 << shift);
lsb_s1 = (lsb >> 1);
lsb_m1 = (lsb - 1);
// Round to nearest even.
remainder = (mantissa & lsb_m1);
mantissa >>= shift;
if (remainder > lsb_s1 || (remainder == lsb_s1 && (mantissa & 0x1))) {
++mantissa;
if (!(mantissa & 0xf)) {
++exponent;
mantissa = 0;
}
}
ret.x = (sign | (exponent << 4) | mantissa);
return ret;
}
float8::float8() { data = cpu_float2quarter_rn(0.0f); }
template <class T>
float8::float8(const T& rhs) {
assign(rhs);
}
template <class T>
float8& float8::operator=(const T& rhs) {
assign(rhs);
return *this;
}
float8::operator float() const { return cpu_quarter2float(data); }
void float8::assign(double rhs) { assign((float)rhs); }
void float8::assign(float rhs) { data = cpu_float2quarter_rn(rhs); }
} // namespace sd
#endif // LIBND4J_FLOAT8_H
+27
View File
@@ -0,0 +1,27 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver119 on 07/11/17.
//
#include <types/float8.h>
namespace sd {
}
+27
View File
@@ -0,0 +1,27 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver119 on 07/11/17.
//
#include <types/int16.h>
namespace sd {
}
+26
View File
@@ -0,0 +1,26 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver119 on 07/11/17.
//
#include <types/int8.h>
namespace sd {
}
+33
View File
@@ -0,0 +1,33 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver119 on 24.01.18.
//
#include <types/pair.h>
namespace sd {
Pair::Pair(int first, int second) {
_first = first;
_second = second;
}
int Pair::first() const { return _first; }
int Pair::second() const { return _second; };
} // namespace sd
+36
View File
@@ -0,0 +1,36 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver on 4/5/2018.
//
#include <types/triple.h>
namespace sd {
int Triple::first() const { return _first; }
int Triple::second() const { return _second; }
int Triple::third() const { return _third; }
Triple::Triple(int first, int second, int third) {
_first = first;
_second = second;
_third = third;
}
} // namespace sd
+27
View File
@@ -0,0 +1,27 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@gmail.com
//
#include <system/op_boilerplate.h>
#include <types/uint16.h>
namespace sd {
}
+26
View File
@@ -0,0 +1,26 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver119 on 07/11/17.
//
#include <types/uint8.h>
namespace sd {
}
+76
View File
@@ -0,0 +1,76 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@gmail.com
//
#include <types/utf8string.h>
#include <cstring>
namespace sd {
utf8string::~utf8string() {
if (_allocated) delete[] _buffer;
}
utf8string::utf8string() {
_allocated = false;
_length = 0;
_buffer = nullptr;
}
utf8string::utf8string(const char *string, int length) {
_length = length;
_buffer = new char[_length];
_allocated = true;
std::memset(_buffer, 0, _length + 1);
std::memcpy(_buffer, string, _length);
}
utf8string::utf8string(const std::string &str) {
_length = str.length();
_buffer = new char[_length + 1];
_allocated = true;
std::memset(_buffer, 0, _length + 1);
std::memcpy(_buffer, str.data(), _length);
_buffer[_length] = 0;
}
utf8string::utf8string(const utf8string &other) {
_length = other._length;
_buffer = new char[_length + 1];
_allocated = true;
std::memset(_buffer, 0, _length + 1);
std::memcpy(_buffer, other._buffer, _length);
_buffer[_length] = 0;
}
void utf8string::Swap(utf8string &other) {
std::swap(_length, other._length);
std::swap(_buffer, other._buffer);
std::swap(_allocated, other._allocated);
}
utf8string &utf8string::operator=(const utf8string &other) {
if (this != &other) {
utf8string temp(other);
Swap(temp);
}
return *this;
}
} // namespace sd
+85
View File
@@ -0,0 +1,85 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef LIBND4J_INT16_H
#define LIBND4J_INT16_H
#include <stdint.h>
#include <system/op_boilerplate.h>
namespace sd {
float SD_INLINE SD_HOST_DEVICE cpu_int162float(int16_t data);
int16_t SD_INLINE SD_HOST_DEVICE cpu_float2int16(float data);
struct int16 {
int16_t data;
SD_INLINE SD_HOST_DEVICE int16();
SD_INLINE SD_HOST_DEVICE ~int16() = default;
template <class T>
SD_INLINE SD_HOST_DEVICE int16(const T& rhs);
template <class T>
SD_INLINE SD_HOST_DEVICE int16& operator=(const T& rhs);
SD_INLINE SD_HOST_DEVICE operator float() const;
SD_INLINE SD_HOST_DEVICE void assign(double rhs);
SD_INLINE SD_HOST_DEVICE void assign(float rhs);
};
//////////////////////////////
float cpu_int162float(int16_t data) { return (float)((int)data); }
int16_t cpu_float2int16(float data) {
auto t = static_cast<int>(data);
if (t > 32767) t = 32767;
if (t < -32768) t = -32768;
return static_cast<int16_t>(t);
}
int16::int16() { data = cpu_float2int16(0.0f); }
template <class T>
int16::int16(const T& rhs) {
assign(rhs);
}
template <class T>
int16& int16::operator=(const T& rhs) {
assign(rhs);
return *this;
}
int16::operator float() const { return cpu_int162float(data); }
void int16::assign(double rhs) { assign(static_cast<float>(rhs)); }
void int16::assign(float rhs) { data = cpu_float2int16(rhs); }
} // namespace sd
#endif // LIBND4J_INT16_H
+82
View File
@@ -0,0 +1,82 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef LIBND4J_INT8_H
#define LIBND4J_INT8_H
#include <stdint.h>
#include <system/op_boilerplate.h>
namespace sd {
float SD_INLINE SD_HOST_DEVICE cpu_int82float(int8_t data);
int8_t SD_INLINE SD_HOST_DEVICE cpu_float2int8(float data);
struct int8 {
int8_t data;
SD_INLINE SD_HOST_DEVICE int8();
SD_INLINE SD_HOST_DEVICE ~int8() = default;
template <class T>
SD_INLINE SD_HOST_DEVICE int8(const T& rhs);
template <class T>
SD_INLINE SD_HOST_DEVICE int8& operator=(const T& rhs);
SD_INLINE SD_HOST_DEVICE operator float() const;
SD_INLINE SD_HOST_DEVICE void assign(double rhs);
SD_INLINE SD_HOST_DEVICE void assign(float rhs);
};
float cpu_int82float(int8_t data) { return (float)((int)data); }
int8_t cpu_float2int8(float data) {
int t = (int)data;
if (t > 127) t = 127;
if (t < -128) t = -128;
return (int8_t)t;
}
int8::int8() { data = cpu_float2int8(0.0f); }
template <class T>
int8::int8(const T& rhs) {
assign(rhs);
}
template <class T>
int8& int8::operator=(const T& rhs) {
assign(rhs);
return *this;
}
int8::operator float() const { return cpu_int82float(data); }
void int8::assign(double rhs) { assign((float)rhs); }
void int8::assign(float rhs) { data = cpu_float2int8(rhs); }
} // namespace sd
#endif // LIBND4J_INT8_H
+42
View File
@@ -0,0 +1,42 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver119 on 24.01.18.
//
#ifndef LIBND4J_PAIR_H
#define LIBND4J_PAIR_H
#include <system/common.h>
namespace sd {
class SD_LIB_EXPORT Pair {
protected:
int _first = 0;
int _second = 0;
public:
Pair(int first = 0, int second = 0);
~Pair() = default;
int first() const;
int second() const;
};
} // namespace sd
#endif // LIBND4J_PAIR_H
+117
View File
@@ -0,0 +1,117 @@
/*
* ******************************************************************************
* *
* *
* * 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_SAFE_TYPE_ACCESS_H
#define LIBND4J_SAFE_TYPE_ACCESS_H
#include "types.h"
// Safe type access macros that prevent out-of-bounds access when using custom type sets
// These macros gracefully handle cases where type indices don't exist
// Safe GET macro that falls back to the first type if index is out of bounds
#define SAFE_GET(INDEX, TYPE_LIST) \
SAFE_GET_IMPL(INDEX, TYPE_LIST, COUNT_NARG(TYPE_LIST))
// Implementation helper - uses the first type as fallback
#define SAFE_GET_IMPL(INDEX, TYPE_LIST, TYPE_COUNT) \
SAFE_GET_EXPAND(INDEX, TYPE_LIST, TYPE_COUNT)
#define SAFE_GET_EXPAND(INDEX, TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_SAFE_##INDEX(TYPE_LIST, TYPE_COUNT)
// Safe GET_ELEMENT implementations
#define GET_ELEMENT_SAFE_0(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT(0, TYPE_LIST)
#define GET_ELEMENT_SAFE_1(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_1(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_2(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_2(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_3(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_3(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_4(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_4(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_5(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_5(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_6(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_6(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_7(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_7(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_8(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_8(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_9(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_9(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_10(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_10(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_11(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_11(TYPE_LIST, TYPE_COUNT)
#define GET_ELEMENT_SAFE_12(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT_CONDITIONAL_12(TYPE_LIST, TYPE_COUNT)
// Conditional implementations that fall back to index 0
#define GET_ELEMENT_CONDITIONAL_1(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 1) ? 1 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_2(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 2) ? 2 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_3(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 3) ? 3 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_4(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 4) ? 4 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_5(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 5) ? 5 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_6(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 6) ? 6 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_7(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 7) ? 7 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_8(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 8) ? 8 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_9(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 9) ? 9 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_10(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 10) ? 10 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_11(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 11) ? 11 : 0, TYPE_LIST)
#define GET_ELEMENT_CONDITIONAL_12(TYPE_LIST, TYPE_COUNT) \
GET_ELEMENT((TYPE_COUNT > 12) ? 12 : 0, TYPE_LIST)
#endif // LIBND4J_SAFE_TYPE_ACCESS_H
+44
View File
@@ -0,0 +1,44 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// Created by raver on 4/5/2018.
//
#ifndef LIBND4J_TRIPLE_H
#define LIBND4J_TRIPLE_H
#include <system/common.h>
namespace sd {
class SD_LIB_EXPORT Triple {
protected:
int _first = 0;
int _second = 0;
int _third = 0;
public:
Triple(int first = 0, int second = 0, int third = 0);
~Triple() = default;
int first() const;
int second() const;
int third() const;
};
} // namespace sd
#endif // LIBND4J_TRIPLE_H
+460
View File
@@ -0,0 +1,460 @@
//
// Created by agibsonccc on 11/22/24.
//
/* ******************************************************************************
*
*
* 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_TYPE_PROMOTE_H
#define LIBND4J_TYPE_PROMOTE_H
#include <types/types.h>
#include <string>
/*
* Enhanced Type Ranking System with ML Awareness:
type_rank template and its specializations assign an integer rank to each supported type.
This ranking helps in determining the "promoted" type when combining different types.
Type Promotion Traits:
promote_type and promote_type3 templates determine the promoted type between two or three types based on their ranks.
Type Name System:
type_name template and its specializations provide a string representation for each supported type.
Helper Functions and Macros:
promote function template converts a value to the promoted type.
Macros like INSTANTIATE_PROMOTE and CALLBACK_INSTANTIATE_PROMOTE help in instantiating the promote function for different type combinations.
PROMOTE_ARGS macro handles function arguments correctly.
ML-Aware Extensions:
- String type rankings (-10 for UTF types)
- Quantization pattern detection
- Semantic validation functions
*/
// Type ranking system with fallback and ML-aware rankings
template<typename T>
struct type_rank {
// Default fallback - gives a very low rank to unknown types
static constexpr int value = -1;
};
#if defined(HAS_BOOL)
template<> struct type_rank<bool> : std::integral_constant<int, 1> {};
#endif
#if defined(HAS_INT8)
template<> struct type_rank<int8_t> : std::integral_constant<int, 2> {};
#endif
#if defined(HAS_UINT8)
template<> struct type_rank<uint8_t> : std::integral_constant<int, 2> {};
#endif
#if defined(HAS_INT16)
template<> struct type_rank<int16_t> : std::integral_constant<int, 3> {};
#endif
#if defined(HAS_UINT16)
template<> struct type_rank<uint16_t> : std::integral_constant<int, 3> {};
#endif
#if defined(HAS_INT32)
template<> struct type_rank<int32_t> : std::integral_constant<int, 4> {};
#endif
#if defined(HAS_UINT32)
template<> struct type_rank<uint32_t> : std::integral_constant<int, 4> {};
#endif
template<> struct type_rank<int64_t> : std::integral_constant<int, 5> {};
#if !defined(__APPLE__) && !defined(_WIN32)
template<> struct type_rank<long long int> : std::integral_constant<int, 5> {};
#endif
template<> struct type_rank<uint64_t> : std::integral_constant<int, 5> {};
// Add unsigned long for macOS which is causing the compile error
#if defined(__APPLE__)
template<> struct type_rank<unsigned long> : std::integral_constant<int, 5> {};
#endif
// FIXED: Only specialize for float16/bfloat16 if they are actually enabled
#if defined(HAS_FLOAT16)
template<> struct type_rank<float16> : std::integral_constant<int, 6> {};
#endif
#if defined(HAS_BFLOAT16)
template<> struct type_rank<bfloat16> : std::integral_constant<int, 6> {};
#endif
#if defined(HAS_FLOAT32)
template<> struct type_rank<float> : std::integral_constant<int, 7> {};
#endif
#if defined(HAS_DOUBLE)
template<> struct type_rank<double> : std::integral_constant<int, 8> {};
#endif
// String type rankings (negative values for special handling)
#if defined(SD_ENABLE_STRING_OPERATIONS) || defined(HAS_UTF8)
template<> struct type_rank<std::string> : std::integral_constant<int, -10> {};
#endif
#if defined(SD_ENABLE_STRING_OPERATIONS) || defined(HAS_UTF16)
template<> struct type_rank<std::u16string> : std::integral_constant<int, -10> {};
#endif
#if defined(SD_ENABLE_STRING_OPERATIONS) || defined(HAS_UTF32)
template<> struct type_rank<std::u32string> : std::integral_constant<int, -10> {};
#endif
// SFINAE helper to check if a type has a valid type_rank
template<typename T, typename = void>
struct has_type_rank : std::false_type {};
template<typename T>
struct has_type_rank<T, typename std::enable_if<(type_rank<T>::value >= -10)>::type> : std::true_type {};
// Helper to check if a type is a string type
template<typename T>
struct is_string_type : std::false_type {};
#if defined(SD_ENABLE_STRING_OPERATIONS)
template<> struct is_string_type<std::string> : std::true_type {};
template<> struct is_string_type<std::u16string> : std::true_type {};
template<> struct is_string_type<std::u32string> : std::true_type {};
#endif
// Helper to check if a type is a quantization type (int8/uint8)
template<typename T>
struct is_quantization_type : std::false_type {};
#if defined(HAS_INT8)
template<> struct is_quantization_type<int8_t> : std::true_type {};
#endif
#if defined(HAS_UINT8)
template<> struct is_quantization_type<uint8_t> : std::true_type {};
#endif
// Helper to check if a type is a floating point type
template<typename T>
struct is_floating_point_type : std::false_type {};
#if defined(HAS_FLOAT16)
template<> struct is_floating_point_type<float16> : std::true_type {};
#endif
#if defined(HAS_BFLOAT16)
template<> struct is_floating_point_type<bfloat16> : std::true_type {};
#endif
#if defined(HAS_FLOAT32)
template<> struct is_floating_point_type<float> : std::true_type {};
#endif
#if defined(HAS_DOUBLE)
template<> struct is_floating_point_type<double> : std::true_type {};
#endif
// Quantization pattern detection templates
template<typename T1, typename T2, typename T3>
struct is_quantization_pattern {
// Forward quantization: (float, float, int8/uint8)
static constexpr bool value =
is_floating_point_type<T1>::value &&
is_floating_point_type<T2>::value &&
is_quantization_type<T3>::value;
};
template<typename T1, typename T2, typename T3>
struct is_dequantization_pattern {
// Dequantization: (int8/uint8, float, float)
static constexpr bool value =
is_quantization_type<T1>::value &&
is_floating_point_type<T2>::value &&
is_floating_point_type<T3>::value;
};
template<typename T1, typename T2, typename T3>
struct is_mixed_quantization_pattern {
// Mixed patterns: (int8/uint8, float, int8/uint8) or similar
static constexpr bool value =
(is_quantization_type<T1>::value && is_floating_point_type<T2>::value) ||
(is_floating_point_type<T1>::value && is_quantization_type<T2>::value);
};
// String + numeric pattern detection for NLP operations
template<typename T1, typename T2>
struct is_string_numeric_pattern {
static constexpr bool value =
(is_string_type<T1>::value && !is_string_type<T2>::value) ||
(!is_string_type<T1>::value && is_string_type<T2>::value);
};
// Triple string pattern detection (should be avoided)
template<typename T1, typename T2, typename T3>
struct is_triple_string_pattern {
static constexpr bool value =
is_string_type<T1>::value &&
is_string_type<T2>::value &&
is_string_type<T3>::value;
};
// ML operation semantic validation
template<typename T1, typename T2, typename T3>
struct is_semantically_valid_ml_combination {
static constexpr bool value =
// Allow quantization patterns
is_quantization_pattern<T1, T2, T3>::value ||
is_dequantization_pattern<T1, T2, T3>::value ||
is_mixed_quantization_pattern<T1, T2, T3>::value ||
// Reject triple string operations
!is_triple_string_pattern<T1, T2, T3>::value;
};
// Safe promote_type trait that only works with enabled types
template<typename T1, typename T2, typename Enable = void>
struct promote_type {
// Fallback - if either type doesn't have a rank, default to T1
using type = T1;
};
template<typename T1, typename T2>
struct promote_type<T1, T2, typename std::enable_if<
has_type_rank<T1>::value && has_type_rank<T2>::value
>::type> {
using type = typename std::conditional<(type_rank<T1>::value >= type_rank<T2>::value), T1, T2>::type;
};
// Special case for string types - don't promote across string boundaries
template<typename T1, typename T2>
struct promote_type<T1, T2, typename std::enable_if<
is_string_type<T1>::value && !is_string_type<T2>::value
>::type> {
using type = T1; // Keep string type when mixed with numeric
};
template<typename T1, typename T2>
struct promote_type<T1, T2, typename std::enable_if<
!is_string_type<T1>::value && is_string_type<T2>::value
>::type> {
using type = T2; // Keep string type when mixed with numeric
};
// promote function template with SFINAE guard
template <typename Type1, typename Type2, typename ValueType>
typename std::enable_if<
has_type_rank<Type1>::value && has_type_rank<Type2>::value,
typename promote_type<Type1, Type2>::type
>::type promote(ValueType value) {
return static_cast<typename promote_type<Type1, Type2>::type>(value);
}
// Fallback promote function for disabled types
template <typename Type1, typename Type2, typename ValueType>
typename std::enable_if<
!has_type_rank<Type1>::value || !has_type_rank<Type2>::value,
Type1
>::type promote(ValueType value) {
return static_cast<Type1>(value);
}
// promote_type3 trait for three types with safety checks and ML awareness
template<typename T1, typename T2, typename T3, typename Enable = void>
struct promote_type3 {
using type = T1; // Fallback
};
template<typename T1, typename T2, typename T3>
struct promote_type3<T1, T2, T3, typename std::enable_if<
has_type_rank<T1>::value &&
has_type_rank<T2>::value &&
has_type_rank<T3>::value &&
is_semantically_valid_ml_combination<T1, T2, T3>::value
>::type> {
using type = typename promote_type<typename promote_type<T1, T2>::type, T3>::type;
};
// Extension for 3-type operations with quantization awareness
template<typename T1, typename T2, typename T3>
struct promote_type3_quantization_aware {
using type = typename std::conditional<
is_quantization_pattern<T1, T2, T3>::value,
T3, // For quantization, use the output type (typically int8/uint8)
typename std::conditional<
is_dequantization_pattern<T1, T2, T3>::value,
T3, // For dequantization, use the output type (typically float)
typename promote_type3<T1, T2, T3>::type
>::type
>::type;
};
// Primary template for type_name - undefined to trigger a compile-time error for unsupported types
template<typename T>
struct type_name;
#if defined(HAS_BOOL)
template<> struct type_name<bool> { static const char* get() { return "bool"; } };
#endif
#if defined(HAS_INT8)
template<> struct type_name<int8_t> { static const char* get() { return "int8_t"; } };
#endif
#if defined(HAS_UINT8)
template<> struct type_name<uint8_t> { static const char* get() { return "uint8_t"; } };
#endif
#if defined(HAS_INT16)
template<> struct type_name<int16_t> { static const char* get() { return "int16_t"; } };
#endif
#if defined(HAS_UINT16)
template<> struct type_name<uint16_t> { static const char* get() { return "uint16_t"; } };
#endif
#if defined(HAS_INT32)
template<> struct type_name<int32_t> { static const char* get() { return "int32_t"; } };
#endif
#if defined(HAS_UINT32)
template<> struct type_name<uint32_t> { static const char* get() { return "uint32_t"; } };
#endif
#if defined(HAS_INT64)
template<> struct type_name<int64_t> { static const char* get() { return "int64_t"; } };
#if !defined(__APPLE__) && !defined(_WIN32)
template<> struct type_name<long long int> { static const char* get() { return "long long int"; } };
#endif
#endif
#if defined(HAS_UINT64)
template<> struct type_name<uint64_t> { static const char* get() { return "uint64_t"; } };
#endif
// Add unsigned long for macOS which is causing the compile error
#if defined(__APPLE__)
template<> struct type_name<unsigned long> { static const char* get() { return "unsigned long"; } };
#endif
// FIXED: Only specialize type_name for enabled types
#if defined(HAS_FLOAT16)
template<> struct type_name<float16> { static const char* get() { return "float16"; } };
#endif
#if defined(HAS_BFLOAT16)
template<> struct type_name<bfloat16> { static const char* get() { return "bfloat16"; } };
#endif
#if defined(HAS_FLOAT32)
template<> struct type_name<float> { static const char* get() { return "float"; } };
#endif
#if defined(HAS_DOUBLE)
template<> struct type_name<double> { static const char* get() { return "double"; } };
#endif
// String type names
#if defined(SD_ENABLE_STRING_OPERATIONS) || defined(HAS_UTF8)
template<> struct type_name<std::string> { static const char* get() { return "std::string"; } };
#endif
#if defined(SD_ENABLE_STRING_OPERATIONS) || defined(HAS_UTF16)
template<> struct type_name<std::u16string> { static const char* get() { return "std::u16string"; } };
#endif
#if defined(SD_ENABLE_STRING_OPERATIONS) || defined(HAS_UTF32)
template<> struct type_name<std::u32string> { static const char* get() { return "std::u32string"; } };
#endif
// Helper function to get type name with fallback
template<typename T>
const char* get_type_name() {
return type_name<T>::get();
}
// ML-aware helper functions for runtime type checking
template<typename T1, typename T2, typename T3>
constexpr bool is_valid_quantization_combination() {
return is_quantization_pattern<T1, T2, T3>::value ||
is_dequantization_pattern<T1, T2, T3>::value ||
is_mixed_quantization_pattern<T1, T2, T3>::value;
}
template<typename T1, typename T2, typename T3>
constexpr bool is_valid_ml_combination() {
return is_semantically_valid_ml_combination<T1, T2, T3>::value;
}
template<typename T1, typename T2>
constexpr bool is_valid_string_numeric_combination() {
return is_string_numeric_pattern<T1, T2>::value;
}
// Quantization-aware promotion helpers
template<typename T1, typename T2, typename T3>
using quantization_aware_promote_t = typename promote_type3_quantization_aware<T1, T2, T3>::type;
// Runtime validation functions (for debugging and validation)
template<typename T1, typename T2, typename T3>
bool validate_type_combination_semantics() {
// Check for problematic patterns
if (is_triple_string_pattern<T1, T2, T3>::value) {
return false; // Triple string operations are semantically invalid
}
// Check type availability
if (!has_type_rank<T1>::value || !has_type_rank<T2>::value || !has_type_rank<T3>::value) {
return false; // Unknown types
}
// All other combinations are valid
return true;
}
// Macro to instantiate the promote function
#define INSTANTIATE_PROMOTE(a1, b1, FUNC_NAME, ARGS) \
template sd::math::promote_type<GET_SECOND(a1), GET_SECOND(b1)>::type \
sd::math::promote<GET_SECOND(a1), GET_SECOND(b1), GET_SECOND(a1)>(GET_SECOND(a1));
// Callback macro
#define CALLBACK_INSTANTIATE_PROMOTE(a1, b1, FUNC_NAME, ARGS) \
INSTANTIATE_PROMOTE(a1, b1, FUNC_NAME, ARGS)
// ML-aware instantiation macros
#define INSTANTIATE_PROMOTE_ML_AWARE(a1, b1, c1, FUNC_NAME, ARGS) \
template<> \
typename std::enable_if< \
sd::is_semantically_valid_ml_combination<GET_SECOND(a1), GET_SECOND(b1), GET_SECOND(c1)>::value, \
sd::quantization_aware_promote_t<GET_SECOND(a1), GET_SECOND(b1), GET_SECOND(c1)> \
>::type \
sd::math::promote_ml_aware<GET_SECOND(a1), GET_SECOND(b1), GET_SECOND(c1)>(GET_SECOND(a1));
// Quantization-specific instantiation macro
#define INSTANTIATE_QUANTIZATION_PROMOTE(a1, b1, c1, FUNC_NAME, ARGS) \
template<> \
typename std::enable_if< \
sd::is_valid_quantization_combination<GET_SECOND(a1), GET_SECOND(b1), GET_SECOND(c1)>(), \
sd::quantization_aware_promote_t<GET_SECOND(a1), GET_SECOND(b1), GET_SECOND(c1)> \
>::type \
sd::math::promote_quantization<GET_SECOND(a1), GET_SECOND(b1), GET_SECOND(c1)>(GET_SECOND(a1));
#endif // LIBND4J_TYPE_PROMOTE_H
File diff suppressed because it is too large Load Diff
+38
View File
@@ -0,0 +1,38 @@
/* ******************************************************************************
*
*
* 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_TYPES_IMPL_H
#define LIBND4J_TYPES_IMPL_H
// This header contains the cross-type constructor implementations
// that require both float16 and bfloat16 to be fully defined
#include "float16.h"
#include "bfloat16.h"
// Implementation of float16 constructor from bfloat16
SD_INLINE SD_HOST_DEVICE float16::float16(const bfloat16& value) : data{} {
*this = static_cast<float>(value);
}
// Implementation of bfloat16 constructor from float16
SD_INLINE SD_HOST_DEVICE bfloat16::bfloat16(const float16& value) : _data(0) {
*this = static_cast<float>(value);
}
#endif // LIBND4J_TYPES_IMPL_H
+39
View File
@@ -0,0 +1,39 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@protonmail.com
//
#ifndef SD_U32_H
#define SD_U32_H
#include <cstdint>
namespace sd {
union u32 {
bool _bool;
int8_t _s8;
uint8_t _u8;
int16_t _s16;
uint16_t _u16;
int32_t _s32;
uint32_t _u32;
float _f32;
};
} // namespace sd
#endif
+62
View File
@@ -0,0 +1,62 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@protonmail.com
//
#ifndef LIBND4J_U64_H
#define LIBND4J_U64_H
#include <types/float16.h>
#include <cstdint>
namespace sd {
typedef struct {
int16_t _v0;
int16_t _v1;
int16_t _v2;
int16_t _v3;
} di16;
typedef struct {
int _v0;
int _v1;
} di32;
typedef struct {
uint32_t _v0;
uint32_t _v1;
} du32;
union u64 {
bool _bool;
int8_t _char;
int16_t _short;
int32_t _int;
// float16 _half = 0.0f;
float _float;
double _double;
sd::LongType _long;
uint64_t _ulong;
di32 _di32;
du32 _du32;
u64() { _long = 0; }
};
} // namespace sd
#endif
+88
View File
@@ -0,0 +1,88 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef LIBND4J_UINT16_H
#define LIBND4J_UINT16_H
#include <stdint.h>
#include <system/op_boilerplate.h>
namespace sd {
uint16_t SD_INLINE SD_HOST_DEVICE cpu_float2uint16(float data);
float SD_INLINE SD_HOST_DEVICE cpu_uint162float(uint16_t data);
struct uint16 {
uint16_t data;
SD_INLINE SD_HOST_DEVICE uint16();
SD_INLINE SD_HOST_DEVICE ~uint16();
template <class T>
SD_INLINE SD_HOST_DEVICE uint16(const T& rhs);
template <class T>
SD_INLINE SD_HOST_DEVICE uint16& operator=(const T& rhs);
SD_INLINE SD_HOST_DEVICE operator float() const;
SD_INLINE SD_HOST_DEVICE void assign(double rhs);
SD_INLINE SD_HOST_DEVICE void assign(float rhs);
};
//////////////////// IMPLEMENTATIONS
float SD_HOST_DEVICE cpu_uint162float(uint16_t data) { return static_cast<float>(data); }
uint16_t SD_HOST_DEVICE cpu_float2uint16(float data) {
auto t = static_cast<int>(data);
if (t > 65536) t = 65536;
if (t < 0) t = 0;
return static_cast<uint16_t>(t);
}
SD_HOST_DEVICE uint16::uint16() { data = cpu_float2uint16(0.0f); }
SD_HOST_DEVICE uint16::~uint16() {
//
}
template <class T>
SD_HOST_DEVICE uint16::uint16(const T& rhs) {
assign(rhs);
}
template <class T>
SD_HOST_DEVICE uint16& uint16::operator=(const T& rhs) {
assign(rhs);
return *this;
}
SD_HOST_DEVICE uint16::operator float() const { return cpu_uint162float(data); }
SD_HOST_DEVICE void uint16::assign(float rhs) { data = cpu_float2uint16(rhs); }
SD_HOST_DEVICE void uint16::assign(double rhs) { assign((float)rhs); }
} // namespace sd
#endif // LIBND4J_UINT16_H
+84
View File
@@ -0,0 +1,84 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef LIBND4J_UINT8_H
#define LIBND4J_UINT8_H
#include <stdint.h>
#include <system/op_boilerplate.h>
namespace sd {
float SD_INLINE SD_HOST_DEVICE cpu_uint82float(uint8_t data);
uint8_t SD_INLINE SD_HOST_DEVICE cpu_float2uint8(float data);
struct uint8 {
uint8_t data;
SD_INLINE SD_HOST_DEVICE uint8();
SD_INLINE SD_HOST_DEVICE ~uint8() = default;
template <class T>
SD_INLINE SD_HOST_DEVICE uint8(const T& rhs);
template <class T>
SD_INLINE SD_HOST_DEVICE uint8& operator=(const T& rhs);
SD_INLINE SD_HOST_DEVICE operator float() const;
SD_INLINE SD_HOST_DEVICE void assign(double rhs);
SD_INLINE SD_HOST_DEVICE void assign(float rhs);
};
///////////////////////////
float cpu_uint82float(uint8_t data) { return static_cast<float>(static_cast<int>(data)); }
uint8_t cpu_float2uint8(float data) {
auto t = static_cast<int>(data);
if (t > 255) t = 255;
if (t < 0) t = 0;
return static_cast<uint8_t>(t);
}
uint8::uint8() { data = cpu_float2uint8(0.0f); }
template <class T>
uint8::uint8(const T& rhs) {
assign(rhs);
}
template <class T>
uint8& uint8::operator=(const T& rhs) {
assign(rhs);
return *this;
}
uint8::operator float() const { return cpu_uint82float(data); }
void uint8::assign(double rhs) { assign(static_cast<float>(rhs)); }
void uint8::assign(float rhs) { data = cpu_float2uint8(rhs); }
} // namespace sd
#endif // LIBND4J_UINT8_H
+50
View File
@@ -0,0 +1,50 @@
/* ******************************************************************************
*
*
* 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
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef DEV_TESTS_UTF8STRING_H
#define DEV_TESTS_UTF8STRING_H
#include <string>
#include <system/common.h>
namespace sd {
class SD_LIB_EXPORT utf8string {
private:
bool _allocated = false;
public:
char *_buffer = nullptr;
unsigned int _length = 0;
utf8string();
~utf8string();
utf8string(const char *string, int length);
utf8string(const std::string &string);
utf8string(const utf8string &other);
utf8string &operator=(const utf8string &other);
protected:
void Swap(utf8string &other);
};
} // namespace sd
#endif // DEV_TESTS_UTF8STRING_H