Unverified Commit 2f441653 authored by Liu, Yuxuan's avatar Liu, Yuxuan Committed by GitHub
Browse files

Mixed precision utilities (#318)

* Add comparison of mixed precisions into IntrType.

* Make the mixed precision as an option through compiler preprocessing

* Add scaling factors for unit testing with mixed precisions.

* Add assertions for mixed precison operators.

* Address Ben and Aaron's comments.

* Fix failing test due to restructuring the operators.

* Remove unused variables.
parent 49acf57c
......@@ -7,4 +7,3 @@
#cmakedefine HAVE_MKL
#cmakedefine DBL
#cmakedefine DBLINT
......@@ -178,6 +178,10 @@ INTERFACE OPERATOR(.APPROXEQ.)
MODULE PROCEDURE approxeq_abs_single
!> @copybrief IntrType::approxeq_abs_double
MODULE PROCEDURE approxeq_abs_double
!> @copybrief IntrType::approxeq_abs_mixsd
MODULE PROCEDURE approxeq_abs_mixsd
!> @copybrief IntrType::approxeq_abs_mixds
MODULE PROCEDURE approxeq_abs_mixds
ENDINTERFACE
!> @brief Interface for the operator for "approximately equals" for intrinsic
......@@ -187,6 +191,10 @@ INTERFACE OPERATOR(.APPROXEQA.)
MODULE PROCEDURE approxeq_abs_single
!> @copybrief IntrType::approxeq_abs_double
MODULE PROCEDURE approxeq_abs_double
!> @copybrief IntrType::approxeq_abs_mixsd
MODULE PROCEDURE approxeq_abs_mixsd
!> @copybrief IntrType::approxeq_abs_mixds
MODULE PROCEDURE approxeq_abs_mixds
ENDINTERFACE
!> @brief Interface for the operator for "approximately equals" for intrinsic
......@@ -196,6 +204,10 @@ INTERFACE OPERATOR(.APPROXEQR.)
MODULE PROCEDURE approxeq_rel_single
!> @copybrief IntrType::approxeq_rel_double
MODULE PROCEDURE approxeq_rel_double
!> @copybrief IntrType::approxeq_rel_mixsd
MODULE PROCEDURE approxeq_rel_mixsd
!> @copybrief IntrType::approxeq_rel_mixds
MODULE PROCEDURE approxeq_rel_mixds
ENDINTERFACE
!> @brief Interface for the operator for "approximately equals" for intrinsic
......@@ -398,6 +410,44 @@ ELEMENTAL FUNCTION approxeq_abs_double(a,b) RESULT(bool)
ENDFUNCTION approxeq_abs_double
!
!-------------------------------------------------------------------------------
!> @brief Defines the operation for performing an absolute comparison of one
!> single-precision and one double-precision reals with .APPROXEQA.
!> @param a
!> @param b
!> @returns bool logical indicating if a and b are approximately equal
!>
!> This routine just does a simple absolute comparison using an epsilon that is
!> a compile time constant. It should be used whenever possible because it has
!> the least overhead. However, it is not appropriate to use when @c a and @c b
!> are either very large or very small.
!>
ELEMENTAL FUNCTION approxeq_abs_mixsd(a,b) RESULT(bool)
REAL(SSK),INTENT(IN) :: a
REAL(SDK),INTENT(IN) :: b
LOGICAL(SBK) :: bool
bool=approxeq_abs_single(a, REAL(b,SSK))
ENDFUNCTION approxeq_abs_mixsd
!
!-------------------------------------------------------------------------------
!> @brief Defines the operation for performing an absolute comparison of one
!> double-precision and one single-precision reals with .APPROXEQA.
!> @param a
!> @param b
!> @returns bool logical indicating if a and b are approximately equal
!>
!> This routine just does a simple absolute comparison using an epsilon that is
!> a compile time constant. It should be used whenever possible because it has
!> the least overhead. However, it is not appropriate to use when @c a and @c b
!> are either very large or very small.
!>
ELEMENTAL FUNCTION approxeq_abs_mixds(a,b) RESULT(bool)
REAL(SDK),INTENT(IN) :: a
REAL(SSK),INTENT(IN) :: b
LOGICAL(SBK) :: bool
bool=approxeq_abs_single(REAL(a,SSK),b)
ENDFUNCTION approxeq_abs_mixds
!
!-------------------------------------------------------------------------------
!> @brief Defines the operation for performing a relative comparison of two
!> single precision reals with .APPROXEQA.
!> @param a
......@@ -440,6 +490,44 @@ ELEMENTAL FUNCTION approxeq_rel_double(a,b) RESULT(bool)
ENDFUNCTION approxeq_rel_double
!
!-------------------------------------------------------------------------------
!> @brief Defines the operation for performing a relative comparison of one
!> single-precision and one double-precision reals with .APPROXEQR.
!> @param a
!> @param b
!> @returns bool logical indicating if a and b are approximately equal
!>
!> This performs a relative comparison by scaling the default epsilon value to
!> the size of the larger of the two. It should be used when @c and @b are of
!> the same magnitude and very large or very small. If either @c a or @c b is
!> zero (exactly) then this routine is equivalent to an absolute comparison.
!>
ELEMENTAL FUNCTION approxeq_rel_mixsd(a,b) RESULT(bool)
REAL(SSK),INTENT(IN) :: a
REAL(SDK),INTENT(IN) :: b
LOGICAL(SBK) :: bool
bool=approxeq_rel_single(a, REAL(b,SSK))
ENDFUNCTION approxeq_rel_mixsd
!
!-------------------------------------------------------------------------------
!> @brief Defines the operation for performing a relative comparison of one
!> double-precision and one single-precision reals with .APPROXEQR.
!> @param a
!> @param b
!> @returns bool logical indicating if a and b are approximately equal
!>
!> This performs a relative comparison by scaling the default epsilon value to
!> the size of the larger of the two. It should be used when @c and @b are of
!> the same magnitude and very large or very small. If either @c a or @c b is
!> zero (exactly) then this routine is equivalent to an absolute comparison.
!>
ELEMENTAL FUNCTION approxeq_rel_mixds(a,b) RESULT(bool)
REAL(SDK),INTENT(IN) :: a
REAL(SSK),INTENT(IN) :: b
LOGICAL(SBK) :: bool
bool=approxeq_rel_single(REAL(a,SSK),b)
ENDFUNCTION approxeq_rel_mixds
!
!-------------------------------------------------------------------------------
!> @brief Defines the operation for performing a comparison of two single
!> precision reals on the floating point number line with .APPROXEQF.
!> @param a
......
......@@ -212,6 +212,20 @@ SUBROUTINE testAPPROXEQ()
ASSERT(bool, '1.0_SDK .APPROXEQ. -1.0_SDK')
bool=.NOT.(1.0e10_SDK .APPROXEQ. 1.0e-10_SDK)
ASSERT(bool, '1.0e10_SDK .APPROXEQ. 1.0e-10_SDK')
COMPONENT_TEST('.APPROXEQ. (MIXED PRECISION)')
bool=1.234567890123450_SDK .APPROXEQ. 1.234567890123465_SSK
ASSERT(bool, '1.234567890123450_SDK .APPROXEQ. 1.234567890123465_SSK')
bool=1.234567890123450_SSK .APPROXEQ. 1.234567890123465_SDK
ASSERT(bool, '1.234567890123450_SSK .APPROXEQ. 1.234567890123465_SDK')
bool=.NOT.(1.234550_SSK .APPROXEQ. 1.234567890123465_SDK)
ASSERT(bool, '1.234550_SSK .APPROXEQ. 1.234567890123465_SDK')
bool=.NOT.(1.234567890123465_SDK .APPROXEQ. 1.234550_SSK)
ASSERT(bool, '1.234567890123465_SDK .APPROXEQ. 1.234550_SSK')
bool=.NOT.(1.0e7_SSK .APPROXEQ. 0.9999999e7_SDK)
ASSERT(bool, '1.0e7_SSK .APPROXEQ. 0.9999999e7_SDK')
bool=0.0_SSK .APPROXEQ. 0.9999999e-5_SDK
ASSERT(bool, '0.0_SSK .APPROXEQ. 0.9999999e-5_SDK')
ENDSUBROUTINE testAPPROXEQ
!
!-------------------------------------------------------------------------------
......@@ -265,6 +279,20 @@ SUBROUTINE testAPPROXEQA()
ASSERT(bool, '1.0_SDK .APPROXEQA. -1.0_SDK')
bool=.NOT.(1.0e10_SDK .APPROXEQA. 1.0e-10_SDK)
ASSERT(bool, '1.0e10_SDK .APPROXEQA. 1.0e-10_SDK')
COMPONENT_TEST('.APPROXEQA. (MIXED PRECISION)')
bool=1.234567890123450_SDK .APPROXEQA. 1.234567890123465_SSK
ASSERT(bool, '1.234567890123450_SDK .APPROXEQA. 1.234567890123465_SSK')
bool=1.234567890123450_SSK .APPROXEQA. 1.234567890123465_SDK
ASSERT(bool, '1.234567890123450_SSK .APPROXEQA. 1.234567890123465_SDK')
bool=.NOT.(1.234550_SSK .APPROXEQA. 1.234567890123465_SDK)
ASSERT(bool, '1.234550_SSK .APPROXEQA. 1.234567890123465_SDK')
bool=.NOT.(1.234567890123465_SDK .APPROXEQA. 1.234550_SSK)
ASSERT(bool, '1.234567890123465_SDK .APPROXEQA. 1.234550_SSK')
bool=.NOT.(1.0e7_SSK .APPROXEQA. 0.9999999e7_SDK)
ASSERT(bool, '1.0e7_SSK .APPROXEQA. 0.9999999e7_SDK')
bool=0.0_SSK .APPROXEQA. 0.9999999e-5_SDK
ASSERT(bool, '0.0_SSK .APPROXEQA. 0.9999999e-5_SDK')
ENDSUBROUTINE testAPPROXEQA
!
!-------------------------------------------------------------------------------
......@@ -318,6 +346,22 @@ SUBROUTINE testAPPROXEQR()
ASSERT(bool, '1.0_SDK .APPROXEQR. -1.0_SDK')
bool=.NOT.(1.0e10_SDK .APPROXEQR. 1.0e-10_SDK)
ASSERT(bool, '1.0e10_SDK .APPROXEQR. 1.0e-10_SDK')
COMPONENT_TEST('.APPROXEQR. (MIXED PRECISION)')
bool=1.234567890123450_SDK .APPROXEQR. 1.234567890123465_SSK
ASSERT(bool, '1.234567890123450_SDK .APPROXEQR. 1.234567890123465_SSK')
bool=1.234567890123450e-10_SSK .APPROXEQR. 1.234567890123465e-10_SDK
ASSERT(bool, '1.234567890123450e-10_SSK .APPROXEQR. 1.234567890123465e-10_SDK')
bool=2.234550_SSK .APPROXEQR. 2.234567890123465_SDK
ASSERT(bool, '2.234550_SSK .APPROXEQR. 2.234567890123465_SDK')
bool=.NOT.(1.234567890123465_SDK .APPROXEQR. 1.234550_SSK)
ASSERT(bool, '1.234567890123465_SDK .APPROXEQR. 1.234550_SSK')
bool=1.0e7_SSK .APPROXEQR. 0.9999999e7_SDK
ASSERT(bool, '1.0e7_SSK .APPROXEQR. 0.9999999e7_SDK')
bool=1.0e7_SSK .APPROXEQR. 0.9999910e7_SDK
ASSERT(bool, '1.0e7_SSK .APPROXEQR. 1.9999910e7_SDK')
bool=.NOT.(1.0e20_SSK .APPROXEQR. 0.9999899999999999e20_SDK)
ASSERT(bool, '1.0e20_SSK .APPROXEQR. 0.9999899999999999e20_SDK')
ENDSUBROUTINE testAPPROXEQR
!
!-------------------------------------------------------------------------------
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment