133 lines
5.3 KiB
C++
133 lines
5.3 KiB
C++
// Copyright (c) 2022 PaddlePaddle 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 <math.h>
|
|
#include "paddle/phi/common/complex.h"
|
|
namespace phi {
|
|
namespace funcs {
|
|
|
|
#define COMPARE_FUNCTOR(func_name, op) \
|
|
template <typename InT, typename OutT = bool> \
|
|
struct func_name { \
|
|
HOSTDEVICE OutT operator()(const InT a, const InT b) const { \
|
|
return static_cast<OutT>(a op b); \
|
|
} \
|
|
};
|
|
|
|
#define COMPARE_COMPLEX_FUNCTOR(func_name, op) \
|
|
template <typename T> \
|
|
struct func_name<phi::dtype::complex<T>> { \
|
|
HOSTDEVICE bool operator()(const phi::dtype::complex<T> a, \
|
|
const phi::dtype::complex<T> b) const { \
|
|
if (isnan(a.real) || isnan(a.imag) || isnan(b.real) || isnan(b.imag)) \
|
|
return false; \
|
|
return (a.real op b.real) || (a.real == b.real && a.imag op b.imag); \
|
|
} \
|
|
};
|
|
|
|
#define COMPARE_COMPLEX_EQUAL_FUNCTOR(func_name, op_equal, op) \
|
|
template <typename T> \
|
|
struct func_name<phi::dtype::complex<T>> { \
|
|
HOSTDEVICE bool operator()(const phi::dtype::complex<T> a, \
|
|
const phi::dtype::complex<T> b) const { \
|
|
if (isnan(a.real) || isnan(a.imag) || isnan(b.real) || isnan(b.imag)) \
|
|
return false; \
|
|
return (a.real op b.real) || \
|
|
(a.real == b.real && a.imag op_equal b.imag); \
|
|
} \
|
|
};
|
|
|
|
COMPARE_FUNCTOR(LessThanFunctor, <)
|
|
COMPARE_FUNCTOR(LessEqualFunctor, <=)
|
|
COMPARE_FUNCTOR(GreaterThanFunctor, >)
|
|
COMPARE_FUNCTOR(GreaterEqualFunctor, >=)
|
|
|
|
COMPARE_COMPLEX_FUNCTOR(LessThanFunctor, <)
|
|
COMPARE_COMPLEX_FUNCTOR(GreaterThanFunctor, >)
|
|
COMPARE_COMPLEX_EQUAL_FUNCTOR(LessEqualFunctor, <=, <)
|
|
COMPARE_COMPLEX_EQUAL_FUNCTOR(GreaterEqualFunctor, >=, >)
|
|
|
|
#undef COMPARE_FUNCTOR
|
|
#undef COMPARE_COMPLEX_FUNCTOR
|
|
#undef COMPARE_COMPLEX_EQUAL_FUNCTOR
|
|
|
|
template <typename InT, typename OutT = bool>
|
|
struct EqualFunctor {
|
|
HOSTDEVICE OutT operator()(const InT a, const InT b) const {
|
|
if (std::is_floating_point<InT>::value) {
|
|
if (isnan(static_cast<float>(a)) || isnan(static_cast<float>(b))) {
|
|
return static_cast<OutT>(false);
|
|
}
|
|
if (isinf(static_cast<float>(a)) || isinf(static_cast<float>(b))) {
|
|
return static_cast<OutT>(a == b);
|
|
}
|
|
return static_cast<OutT>(fabs(static_cast<double>(a - b)) < 1e-15);
|
|
} else {
|
|
return static_cast<OutT>(a == b);
|
|
}
|
|
}
|
|
};
|
|
template <typename InT, typename OutT = bool>
|
|
struct NanEqualFunctor {
|
|
HOSTDEVICE OutT operator()(const InT a, const InT b) const {
|
|
if (std::is_floating_point<InT>::value) {
|
|
if (isnan(static_cast<float>(a)) && isnan(static_cast<float>(b))) {
|
|
return static_cast<OutT>(true);
|
|
}
|
|
if (isnan(static_cast<float>(a)) || isnan(static_cast<float>(b))) {
|
|
return static_cast<OutT>(false);
|
|
}
|
|
if (isinf(static_cast<float>(a)) || isinf(static_cast<float>(b))) {
|
|
return static_cast<OutT>(a == b);
|
|
}
|
|
return static_cast<OutT>(fabs(static_cast<double>(a - b)) < 1e-15);
|
|
} else {
|
|
return static_cast<OutT>(a == b);
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct EqualFunctor<phi::dtype::complex<T>> {
|
|
HOSTDEVICE bool operator()(const phi::dtype::complex<T> a,
|
|
const phi::dtype::complex<T> b) const {
|
|
if (isnan(static_cast<float>(a.real)) ||
|
|
isnan(static_cast<float>(a.imag)) ||
|
|
isnan(static_cast<float>(b.real)) ||
|
|
isnan(static_cast<float>(b.imag))) {
|
|
return static_cast<bool>(false);
|
|
}
|
|
if (isinf(static_cast<float>(a.real)) ||
|
|
isinf(static_cast<float>(a.imag)) ||
|
|
isinf(static_cast<float>(b.real)) ||
|
|
isinf(static_cast<float>(b.imag))) {
|
|
return static_cast<bool>(a.real == b.real && a.imag == b.imag);
|
|
}
|
|
return static_cast<bool>(
|
|
fabs(static_cast<double>(a.real - b.real)) < 1e-15 &&
|
|
fabs(static_cast<double>(a.imag - b.imag)) < 1e-15);
|
|
}
|
|
};
|
|
|
|
template <typename InT, typename OutT = bool>
|
|
struct NotEqualFunctor {
|
|
HOSTDEVICE bool operator()(const InT a, const InT b) const {
|
|
return !EqualFunctor<InT, OutT>()(a, b);
|
|
}
|
|
};
|
|
|
|
} // namespace funcs
|
|
} // namespace phi
|