1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

Merge pull request #29369 from abhishek-gola:fp8_support

FP8 support in core module #29369

Core part of https://github.com/opencv/opencv/issues/29313

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Abhishek Gola
2026-07-15 18:15:01 +05:30
committed by GitHub
parent 18f9bffb0d
commit 34074075b2
19 changed files with 766 additions and 22 deletions
+61
View File
@@ -332,6 +332,12 @@ convertTo(const _Tp* src, void* dst, int dtype,
case CV_16BF:
convert_(src, (cv::bfloat*)dst, total, alpha, beta);
break;
case CV_8F_E4M3FN:
convert_(src, (cv::fp8_t*)dst, total, alpha, beta);
break;
case CV_8F_E4M3FNUZ:
convert_(src, (cv::fp8a_t*)dst, total, alpha, beta);
break;
case CV_Bool:
convert_to_bool(src, (bool*)dst, total, alpha, beta);
break;
@@ -415,6 +421,12 @@ void convert(const Mat& src, cv::OutputArray _dst,
case CV_16BF:
convertTo((const cv::bfloat*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_8F_E4M3FN:
convertTo((const cv::fp8_t*)sptr, dptr, dtype, total, alpha, beta);
break;
case CV_8F_E4M3FNUZ:
convertTo((const cv::fp8a_t*)sptr, dptr, dtype, total, alpha, beta);
break;
default:
CV_Error(cv::Error::StsNotImplemented, "unknown/unsupported depth");
}
@@ -2251,6 +2263,15 @@ int check( const Mat& a, double fmin, double fmax, vector<int>* _idx )
// success_err_level is maximum allowed difference, idx is the index of the first
// element for which difference is >success_err_level
// (or index of element with the maximum difference)
static inline double decodeFP8(const uchar* p, int depth)
{
switch (depth)
{
case CV_8F_E4M3FN: return (double)(float)*reinterpret_cast<const cv::fp8_t*>(p);
default: return (double)(float)*reinterpret_cast<const cv::fp8a_t*>(p);
}
}
int cmpEps( const Mat& arr_, const Mat& refarr_, double* _realmaxdiff,
double success_err_level, vector<int>* _idx,
bool element_wise_relative_error )
@@ -2375,6 +2396,38 @@ int cmpEps( const Mat& arr_, const Mat& refarr_, double* _realmaxdiff,
}
}
break;
case CV_8F_E4M3FN:
case CV_8F_E4M3FNUZ:
for( j = 0; j < total; j++ )
{
if( ((uchar*)sptr1)[j] == ((uchar*)sptr2)[j] )
continue;
double a_val = decodeFP8((const uchar*)sptr1 + j, depth);
double b_val = decodeFP8((const uchar*)sptr2 + j, depth);
double threshold;
if( cvIsNaN(a_val) || cvIsInf(a_val) )
{
result = CMP_EPS_INVALID_TEST_DATA;
idx = startidx + j;
break;
}
if( cvIsNaN(b_val) || cvIsInf(b_val) )
{
result = CMP_EPS_INVALID_REF_DATA;
idx = startidx + j;
break;
}
a_val = fabs(a_val - b_val);
threshold = element_wise_relative_error ? fabs(b_val) + 1 : maxval;
if( a_val > threshold*success_err_level )
{
realmaxdiff = a_val/threshold;
if( idx == 0 )
idx = startidx + j;
break;
}
}
break;
case CV_32F:
for( j = 0; j < total; j++ )
{
@@ -3404,6 +3457,14 @@ static void writeElems(std::ostream& out, const void* data, int nelems, int dept
writeElems<cv::bfloat, float>(out, data, nelems, starpos);
out.precision(pp);
}
else if(depth == CV_8F_E4M3FN || depth == CV_8F_E4M3FNUZ)
{
std::streamsize pp = out.precision();
out.precision(4);
if(depth == CV_8F_E4M3FN) writeElems<cv::fp8_t, float>(out, data, nelems, starpos);
else writeElems<cv::fp8a_t, float>(out, data, nelems, starpos);
out.precision(pp);
}
else if(depth == CV_32F)
{
std::streamsize pp = out.precision();