Files
paddlepaddle--paddle/paddle/cinn/common/float8e4m3_utils.h
T
2026-07-13 12:40:42 +08:00

154 lines
5.0 KiB
C++

// Copyright (c) 2025 CINN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
#pragma once
#include <iostream>
#include <limits>
#include "paddle/cinn/common/float8e4m3.h"
namespace std {
// Override the std::is_pod::value for float8e4m3
template <>
struct is_pod<cinn::common::float8e4m3> {
static const bool value = is_trivial<cinn::common::float8e4m3>::value &&
is_standard_layout<cinn::common::float8e4m3>::value;
};
template <>
struct is_floating_point<cinn::common::float8e4m3>
: std::integral_constant<
bool,
std::is_same<
cinn::common::float8e4m3,
typename std::remove_cv<cinn::common::float8e4m3>::type>::value> {
};
template <>
struct is_signed<cinn::common::float8e4m3> {
static const bool value = true;
};
template <>
struct is_unsigned<cinn::common::float8e4m3> {
static const bool value = false;
};
__host__ __device__ inline cinn::common::float8e4m3 abs(
const cinn::common::float8e4m3& a) {
#if defined(CINN_CUDA_FP8)
__half fp16_val = __nv_cvt_fp8_to_halfraw(a.x, __NV_E4M3);
__half fp16_abs = __habs(fp16_val);
return cinn::common::float8e4m3(__nv_cvt_halfraw_to_fp8(fp16_abs, __NV_E4M3));
#else
return cinn::common::float8e4m3(a.x & 0x7F);
#endif
}
__host__ __device__ inline bool isnan(const cinn::common::float8e4m3& a) {
#if defined(CINN_CUDA_FP8)
__half fp16_val = __nv_cvt_fp8_to_halfraw(a.x, __NV_E4M3);
return __hisnan(fp16_val);
#else
return (a.x & 0x7F) == 0x7F &&
(a.x & 0x07) != 0; // E4M3 NaN: exp=15, mantissa≠0
#endif
}
__host__ __device__ inline bool isinf(const cinn::common::float8e4m3& a) {
#if defined(CINN_CUDA_FP8)
__half fp16_val = __nv_cvt_fp8_to_halfraw(a.x, __NV_E4M3);
return __hisinf(fp16_val);
#else
return (a.x & 0x7F) == 0x7F &&
(a.x & 0x07) == 0; // E4M3 Inf: exp=15, mantissa=0
#endif
}
__host__ __device__ inline bool isfinite(const cinn::common::float8e4m3& a) {
#if defined(CINN_CUDA_FP8)
__half fp16_val = __nv_cvt_fp8_to_halfraw(a.x, __NV_E4M3);
return !__hisnan(fp16_val) && !__hisinf(fp16_val);
#else
return !isnan(a) && !isinf(a);
#endif
}
template <>
struct numeric_limits<cinn::common::float8e4m3> {
static const bool is_specialized = true;
static const bool is_signed = true;
static const bool is_integer = false;
static const bool is_exact = false;
static const bool has_infinity = true;
static const bool has_quiet_NaN = true;
static const bool has_signaling_NaN = true;
static const float_denorm_style has_denorm = denorm_present;
static const bool has_denorm_loss = false;
static const std::float_round_style round_style = std::round_to_nearest;
static const bool is_iec559 = false;
static const bool is_bounded = false;
static const bool is_modulo = false;
static const int digits = 4; // 3 mantissa + implicit 1
static const int digits10 = 0; // floor(3 * log10(2));
static const int max_digits10 = 3; // ceil(4 * log10(2) + 1)
static const int radix = 2;
static const int min_exponent = -5;
static const int min_exponent10 = -1;
static const int max_exponent = 9;
static const int max_exponent10 = 2;
static const bool traps = true;
static const bool tinyness_before = false;
__host__ __device__ static cinn::common::float8e4m3(min)() {
return cinn::common::raw_uint8_to_float8e4m3(0x04);
}
__host__ __device__ static cinn::common::float8e4m3 lowest() {
return cinn::common::raw_uint8_to_float8e4m3(0xFB);
}
__host__ __device__ static cinn::common::float8e4m3(max)() {
return cinn::common::raw_uint8_to_float8e4m3(0x7B);
}
__host__ __device__ static cinn::common::float8e4m3 epsilon() {
return cinn::common::raw_uint8_to_float8e4m3(0x08);
}
__host__ __device__ static cinn::common::float8e4m3 round_error() {
return cinn::common::float8e4m3(0.5);
}
__host__ __device__ static cinn::common::float8e4m3 infinity() {
return cinn::common::raw_uint8_to_float8e4m3(0x7C);
}
__host__ __device__ static cinn::common::float8e4m3 quiet_NaN() {
return cinn::common::raw_uint8_to_float8e4m3(0x7E);
}
__host__ __device__ static cinn::common::float8e4m3 signaling_NaN() {
return cinn::common::raw_uint8_to_float8e4m3(0x7E);
}
__host__ __device__ static cinn::common::float8e4m3 denorm_min() {
return cinn::common::raw_uint8_to_float8e4m3(0x01);
}
};
} // namespace std
namespace cinn {
namespace common {
inline std::ostream& operator<<(std::ostream& os, const float8e4m3& a) {
os << std::showpoint << static_cast<float>(a);
return os;
}
} // namespace common
} // namespace cinn