Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added nan to the DaCe math namespace #1437

Merged
merged 9 commits into from
Dec 12, 2023
8 changes: 5 additions & 3 deletions dace/runtime/include/dace/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
#ifndef __DACE_MATH_H
#define __DACE_MATH_H

#include "pi.h"
#include "types.h"

#include <complex>
#include <numeric>
#include <cmath>
#include <cfloat>
#include <type_traits>

#include "pi.h"
#include "nan.h"
#include "types.h"

#ifdef __CUDACC__
#include <thrust/complex.h>
#endif
Expand Down Expand Up @@ -457,6 +458,7 @@ namespace dace
namespace math
{
static DACE_CONSTEXPR typeless_pi pi{};
static DACE_CONSTEXPR typeless_nan nan{};
//////////////////////////////////////////////////////
template<typename T>
DACE_CONSTEXPR DACE_HDFI T exp(const T& a)
Expand Down
112 changes: 112 additions & 0 deletions dace/runtime/include/dace/nan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright 2019-2021 ETH Zurich and the DaCe authors. All rights reserved.
#ifndef __DACE_NAN_H
#define __DACE_NAN_H

// Class to define a stateless NAN and related operators.

namespace dace
{
namespace math
{
//////////////////////////////////////////////////////
// Defines a typeless Pi
struct typeless_nan
{
operator int() const = delete;
operator float() const
{
return std::nanf("");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::nan* use strto*, which will be slow. Please use numeric_limits' NaN: https://en.cppreference.com/w/cpp/types/numeric_limits/quiet_NaN

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reminding me about that thing.

}
operator double() const
{
return std::nan("");
}
operator long double() const
{
return std::nanl("");
}
typeless_nan operator+() const
{
return typeless_nan{};
}
typeless_nan operator-() const
{
return typeless_nan{};
}
};

template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator*(const T&, const typeless_nan&) { return typeless_nan{}; }

template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator*(const typeless_nan&, const T&) { return typeless_nan{}; }

inline typeless_nan
operator*(const typeless_nan&, const typeless_nan&) { return typeless_nan{}; }


template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator+(const T&, const typeless_nan&) { return typeless_nan{}; }

template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator+(const typeless_nan&, const T&) { return typeless_nan{}; }

inline typeless_nan
operator+(const typeless_nan&, const typeless_nan&) { return typeless_nan{}; }


template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator-(const T&, const typeless_nan&) { return typeless_nan{}; }

template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator-(const typeless_nan&, const T&) { return typeless_nan{}; }

inline typeless_nan
operator-(const typeless_nan&, const typeless_nan&) { return typeless_nan{}; }


template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator/(const T&, const typeless_nan&) { return typeless_nan{}; }

template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator/(const typeless_nan&, const T&) { return typeless_nan{}; }

inline typeless_nan
operator/(const typeless_nan&, const typeless_nan&) { return typeless_nan{}; }


template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator%(const T&, const typeless_nan&) { return typeless_nan{}; }

template<typename T>
DACE_CONSTEXPR typename std::enable_if<std::is_floating_point<T>::value, typeless_nan>::type
operator%(const typeless_nan&, const T&) { return typeless_nan{}; }

inline typeless_nan
operator%(const typeless_nan&, const typeless_nan&) { return typeless_nan{}; }

}
}

//These functions allows to perfrom operations with `typeless_nan` instances.
# define FADAPT(F) DACE_CONSTEXPR ::dace::math::typeless_nan F (::dace::math::typeless_nan) { return ::dace::math::typeless_nan{}; }
# define FADAPT2(F) template<typename T1> DACE_CONSTEXPR dace::math::typeless_nan F (T1&&, dace::math::typeless_nan) { return ::dace::math::typeless_nan{}; }; \
template<typename T2> DACE_CONSTEXPR dace::math::typeless_nan F (dace::math::typeless_nan, T2&&) { return ::dace::math::typeless_nan{}; }; \
DACE_CONSTEXPR ::dace::math::typeless_nan F (dace::math::typeless_nan, dace::math::typeless_nan) { return ::dace::math::typeless_nan{}; }
FADAPT(tanh); FADAPT(cos); FADAPT(sin); FADAPT(sqrt); FADAPT(tan);
FADAPT(acos); FADAPT(asin); FADAPT(atan); FADAPT(log); FADAPT(exp);
FADAPT(floor); FADAPT(ceil); FADAPT(round); FADAPT(abs);
FADAPT2(max); FADAPT2(min);
# undef FADAPT2
# undef FADAPT

#endif // __DACE_NAN_H
Loading