chore: import upstream snapshot with attribution
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user