<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Approximatrix Forums — No Intrinsic Procedure for real equals real?]]></title>
	<link rel="self" href="https://forums.approximatrix.com/extern.php?action=feed&amp;tid=790&amp;type=atom" />
	<updated>2020-11-09T16:29:47Z</updated>
	<generator>PunBB</generator>
	<id>https://forums.approximatrix.com/viewtopic.php?id=790</id>
		<entry>
			<title type="html"><![CDATA[Re: No Intrinsic Procedure for real equals real?]]></title>
			<link rel="alternate" href="https://forums.approximatrix.com/viewtopic.php?pid=3649#p3649" />
			<content type="html"><![CDATA[<p>Hi Jeff,</p><p>Thank you for your good suggestions on improving the equality function for real numbers.</p><p>Your suggestions were,<br />&quot;The answer from this calculation should just be SPACING(y1), which should effectively be the same as SPACING(x).&quot;<br />and<br />&quot;you might want to create a module that implements this same routine in single-, double-, and quad-precision and uses an interface to call the appropriate routine based on precision.&quot;</p><p>Per your suggestions, please find a new and improved routine for testing the equality of two real numbers, based on SPACING and an interface module for the appropriate precision routine, listed below.</p><p>KIND regards,<br />Frank</p><p>!--- The EQUALITY MODULE is listed here:</p><p>&nbsp; &nbsp; &nbsp; &nbsp; MODULE EQUAL_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; !***************************************************************<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; EQ_FP version 1.1<br />&nbsp; &nbsp; &nbsp; &nbsp; !---<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; Developed by F.W. Perrella, Ph.D.&nbsp; November 9, 2020<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; EQ_FP™ Copyright © 2020 F.W. PERRELLA, Ph.D.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Silver Spring, Maryland U.S.A.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; All Rights Reserved.<br />&nbsp; &nbsp; &nbsp; &nbsp; !***************************************************************<br />&nbsp; &nbsp; &nbsp; &nbsp; ! NAME:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;EQ_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; ! PURPOSE:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Program to determine whether two real numbers are equal.<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; ! MODULE:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Type_Kinds: Definition for kind variable types.<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; ! ROUTINE:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;EQ_FP: Routine to perform equality comparison of<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; single, double, quadruple precision real numbers.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; CALLING SEQUENCE:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Result = EQ_FP( x,y )<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; INPUT ARGUMENTS:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;x, y:&nbsp; &nbsp; &nbsp; &nbsp;Two real numbers to compare.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;TYPE:&nbsp; &nbsp; &nbsp; &nbsp;REAL( KIND = Single, Double, Quadruple )<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; FUNCTION RESULT:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;TYPE:&nbsp; &nbsp; Logical<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;RESULT: A returned logical value indicating whether the<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;x and y inputs are equal within the set precision.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Set to .TRUE. if the real numbers are equal<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;within the specified tolerance.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Set to .FALSE. if the real numbers are not equal.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; USE Type_Kinds</p><p>&nbsp; &nbsp; &nbsp; &nbsp; IMPLICIT NONE</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- Visible function<br />&nbsp; &nbsp; &nbsp; &nbsp; !--------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; PUBLIC :: EQ_FP</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !----------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- Floating Point Precision<br />&nbsp; &nbsp; &nbsp; &nbsp; !----------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; REAL( KIND )<br />&nbsp; &nbsp; &nbsp; &nbsp; !============================<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Single (SP, 4&nbsp; bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Double (DP, 8&nbsp; bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Quad&nbsp; &nbsp;(QP, 16 bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !----------------------------</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !---------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- Procedures<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; INTERFACE EQ_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MODULE PROCEDURE EQ_FP4&nbsp; &nbsp; &nbsp;!--- Kind(SP)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MODULE PROCEDURE EQ_FP8&nbsp; &nbsp; &nbsp;!--- Kind(DP)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MODULE PROCEDURE EQ_FP16&nbsp; &nbsp; !--- Kind(QP)<br />&nbsp; &nbsp; &nbsp; &nbsp; END INTERFACE EQ_FP</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; CONTAINS<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; ELEMENTAL FUNCTION EQ_FP4( x,y ) Result( IsEQ )<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- USE Type_Kinds<br />&nbsp; &nbsp; &nbsp; &nbsp; IMPLICIT NONE</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Define Kind as single precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:: KIND_FP = SP</p><p>&nbsp; &nbsp; &nbsp; &nbsp; LOGICAL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: IsEQ<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), INTENT( IN )&nbsp; :: x<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), INTENT( IN )&nbsp; :: y</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Local Variables<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: DiffR<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: Dif<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), PARAMETER&nbsp; &nbsp; &nbsp;:: Rel = 2.0_KIND_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; INTRINSIC&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: NEAREST, SPACING, ABS</p><p>&nbsp; &nbsp; &nbsp; &nbsp; Dif&nbsp; &nbsp;= NEAREST( ABS(y-x),x )<br />&nbsp; &nbsp; &nbsp; &nbsp; DiffR = SPACING( ABS(x) )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Test for equality<br />&nbsp; &nbsp; &nbsp; &nbsp; IF ( x == y ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ELSEIF ( Dif &lt; Rel*DiffR ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ELSE<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .FALSE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ENDIF</p><p>&nbsp; &nbsp; &nbsp; &nbsp; END FUNCTION EQ_FP4</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; ELEMENTAL FUNCTION EQ_FP8( x,y ) Result( IsEQ )<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- USE Type_Kinds<br />&nbsp; &nbsp; &nbsp; &nbsp; IMPLICIT NONE</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Define Kind as double precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:: KIND_FP = DP</p><p>&nbsp; &nbsp; &nbsp; &nbsp; LOGICAL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: IsEQ<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), INTENT( IN )&nbsp; :: x<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), INTENT( IN )&nbsp; :: y</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Local Variables<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: DiffR<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: Dif<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), PARAMETER&nbsp; &nbsp; &nbsp;:: Rel = 2.0_KIND_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; INTRINSIC&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: NEAREST, SPACING, ABS</p><p>&nbsp; &nbsp; &nbsp; &nbsp; Dif&nbsp; &nbsp;= NEAREST( ABS(y-x),x )<br />&nbsp; &nbsp; &nbsp; &nbsp; DiffR = SPACING( ABS(x) )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Test for equality<br />&nbsp; &nbsp; &nbsp; &nbsp; IF ( x == y ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ELSEIF ( ABS(Dif) &lt; Rel*DiffR ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ELSE<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .FALSE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ENDIF</p><p>&nbsp; &nbsp; &nbsp; &nbsp; END FUNCTION EQ_FP8</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; ELEMENTAL FUNCTION EQ_FP16( x,y ) Result( IsEQ )<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- USE Type_Kinds<br />&nbsp; &nbsp; &nbsp; &nbsp; IMPLICIT NONE</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Define Kind as quadruple precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:: KIND_FP = QP</p><p>&nbsp; &nbsp; &nbsp; &nbsp; LOGICAL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: IsEQ<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), INTENT( IN )&nbsp; :: x<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), INTENT( IN )&nbsp; :: y</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Local Variables<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: DiffR<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: Dif<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( KIND_FP ), PARAMETER&nbsp; &nbsp; &nbsp;:: Rel = 2.0_KIND_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; INTRINSIC&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: NEAREST, SPACING, ABS</p><p>&nbsp; &nbsp; &nbsp; &nbsp; Dif&nbsp; &nbsp;= NEAREST( ABS(y-x),x )<br />&nbsp; &nbsp; &nbsp; &nbsp; DiffR = SPACING( ABS(x) )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Test for equality<br />&nbsp; &nbsp; &nbsp; &nbsp; IF ( x == y ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ELSEIF ( ABS(Dif) &lt; Rel*DiffR ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ELSE<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IsEQ = .FALSE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ENDIF</p><p>&nbsp; &nbsp; &nbsp; &nbsp; END FUNCTION EQ_FP16<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; END MODULE EQUAL_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />!--- The MAIN PROGRAM is listed here:</p><p>&nbsp; &nbsp; &nbsp; &nbsp; PROGRAM Test_EQUAL_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! NAME:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Test_EQ_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; ! PURPOSE:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Program to test the routine EQ_FP(x,y).<br />&nbsp; &nbsp; &nbsp; &nbsp; ! MODULES:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Type_Kinds: Definitions for kinds of variable types.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;EQ_FP:&nbsp; &nbsp;Performs equality comparison of real numbers.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; USE Type_Kinds<br />&nbsp; &nbsp; &nbsp; &nbsp; USE EQUAL_FP</p><p>&nbsp; &nbsp; &nbsp; &nbsp; IMPLICIT NONE<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Floating Point Precision<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; REAL( KIND )<br />&nbsp; &nbsp; &nbsp; &nbsp; !===============================<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Single (SP, 4&nbsp; bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Double (DP, 8&nbsp; bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Quad&nbsp; &nbsp;(QP, 16 bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------------</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !-----------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! Parameters<br />&nbsp; &nbsp; &nbsp; &nbsp; !-----------<br />&nbsp; &nbsp; &nbsp; &nbsp; CHARACTER( * ), PARAMETER :: Title = &#039;Test EQ_FP(x,y):&#039;<br />&nbsp; &nbsp; &nbsp; &nbsp; CHARACTER( * ), PARAMETER :: cLine = REPEAT(&quot;-&quot;,50)<br />&nbsp; &nbsp; &nbsp; &nbsp; CHARACTER( * ), PARAMETER :: cDot = REPEAT(&quot;.&quot;,50)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! Numbers to test for precision<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: NUMBERS = 5<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( SP ), PARAMETER, DIMENSION( NUMBERS ) :: SINGLE_NUMBER = &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; (/ 1.000000000000000e-32_SP,&nbsp; &nbsp; &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e-16_SP,&nbsp; &nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.000000000000000e+00_SP,&nbsp; &nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+16_SP,&nbsp; &nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+32_SP /)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; REAL( DP ), PARAMETER, DIMENSION( NUMBERS ) :: DOUBLE_NUMBER = &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; (/ 1.000000000000000e-32_DP,&nbsp; &nbsp; &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e-16_DP,&nbsp; &nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.000000000000000e+00_DP,&nbsp; &nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+16_DP,&nbsp; &nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+32_DP /)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; REAL( QP ), PARAMETER, DIMENSION( NUMBERS ) :: QUAD_NUMBER = &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; (/ 1.000000000000000e-32_QP,&nbsp; &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e-16_QP,&nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.000000000000000e+00_QP,&nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+16_QP,&nbsp; &nbsp; &nbsp;&amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+32_QP /)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !----------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! Variables<br />&nbsp; &nbsp; &nbsp; &nbsp; !----------<br />&nbsp; &nbsp; &nbsp; &nbsp; CHARACTER(len=256) :: cend<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER :: i<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( SP ) ::&nbsp; x,&nbsp; y1,&nbsp; y2,&nbsp; y3,&nbsp; y4,&nbsp; x0,&nbsp; y0, es<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( DP ) :: xd, yd1, yd2, yd3, yd4, xd0, yd0, ed<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( QP ) :: xq, yq1, yq2, yq3, yq4, xq0, yq0, eq</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! Test equality of x and y reals<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a)&#039;) Title<br />&nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a)&#039;)&nbsp; cLine<br />&nbsp; &nbsp; &nbsp; &nbsp; DO i = 1, NUMBERS<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x, &quot;NUMBER &quot;, i2, &quot; of &quot;, i2 )&#039; ) i, NUMBERS<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Single precision test<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = SINGLE_NUMBER(i)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y1 = NEAREST( x, 1.0_SP )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y2 = y1 - SPACING( x )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y3 = NEAREST( x, -1.0_SP )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y4 = y3 + SPACING( x )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Error variables<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; es = x * 5.e-08_SP<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = x + es</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Test single precision function<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( /5x, &quot;SINGLE PRECISION: x&nbsp; = &quot;, es20.13, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y1 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x, 1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y2 = &quot;, es20.13, 2x, &quot;:&nbsp; y1 - SPACING( x )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y3 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x,-1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y4 = &quot;, es20.13, 2x, &quot;:&nbsp; y3 + SPACING( x )&quot; )&#039; ) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x, y1, y2, y3, y4</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;EQ_FP4(x,y1): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP4(x,y2): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP4(x,y3): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP4(x,y4): X=Y?&#039;, EQ_FP(x0,y0)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Double precision test<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd = DOUBLE_NUMBER(i)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yd1 = NEAREST( xd, 1.0_DP )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yd2 = yd1 - SPACING( xd )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yd3 = NEAREST( xd, -1.0_DP )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yd4 = yd3 + SPACING( xd )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Error variables<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ed = xd * 5.e-16_DP<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd = xd + ed</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Test stand alone double precision function routines<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a)&#039;)&nbsp; cDot<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( /5x, &quot;DOUBLE PRECISION: x&nbsp; = &quot;, es20.13, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y1 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x, 1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y2 = &quot;, es20.13, 2x, &quot;:&nbsp; y1 - SPACING( x )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y3 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x,-1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y4 = &quot;, es20.13, 2x, &quot;:&nbsp; y3 + SPACING( x )&quot; )&#039; ) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd, yd1, yd2, yd3, yd4</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd0 = xd; yd0 = yd1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd0 = xd; yd0 = yd2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd0 = xd; yd0 = yd3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd0 = xd; yd0 = yd4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd0 = xd; yd0 = yd1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y1): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd0 = xd; yd0 = yd2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y2): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd0 = xd; yd0 = yd3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y3): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd0 = xd; yd0 = yd4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y4): X=Y?&#039;, EQ_FP(x0,y0)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !-------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Quadruple precision test<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !-------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq = QUAD_NUMBER(i)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yq1 = NEAREST( xq, 1.0_QP )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yq2 = yq1 - SPACING( xq )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yq3 = NEAREST( xq, -1.0_QP )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yq4 = yq3 + SPACING( xq )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Error variables<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eq = xq * 5.e-32_QP<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq = xq + eq</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Test quadruple precision function<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a)&#039;)&nbsp; cDot<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( /5x, &quot;QUADRULE PRECISION: x&nbsp; = &quot;, es20.13, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y1 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x, 1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y2 = &quot;, es20.13, 2x, &quot;:&nbsp; y1 - SPACING( x )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y3 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x,-1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y4 = &quot;, es20.13, 2x, &quot;:&nbsp; y3 + SPACING( x )&quot; )&#039; ) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq, yq1, yq2, yq3, yq4</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq0 = xq; yq0 = yq1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq0 = xq; yq0 = yq2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq0 = xq; yq0 = yq3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq0 = xq; yq0 = yq4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;(x==y1): X=Y?&#039;, (x0==y0)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq0 = xq; yq0 = yq1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;EQ_FP16(x,y1): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq0 = xq; yq0 = yq2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;EQ_FP16(x,y2): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq0 = xq; yq0 = yq3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;EQ_FP16(x,y3): X=Y?&#039;, EQ_FP(x0,y0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq0 = xq; yq0 = yq4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(5x,a,2x,L6)&#039;) &#039;EQ_FP16(x,y4): X=Y?&#039;, EQ_FP(x0,y0)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a)&#039;)&nbsp; cLine<br />&nbsp; &nbsp; &nbsp; &nbsp; END DO</p><p>&nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( /10x, &quot;Press &lt;ENTER&gt; to continue...&quot; )&#039; )<br />&nbsp; &nbsp; &nbsp; &nbsp; READ( *, &#039;(a)&#039; ) cend</p><p>&nbsp; &nbsp; &nbsp; &nbsp; END PROGRAM Test_EQUAL_FP<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------</p><p>!--- The KIND TYPE MODULE is listed here:</p><p>&nbsp; &nbsp; MODULE Type_Kinds<br />&nbsp; &nbsp; &nbsp; &nbsp; IMPLICIT NONE<br />&nbsp; &nbsp; &nbsp; &nbsp; PRIVATE<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! Floating Point Precision<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; REAL( KIND )<br />&nbsp; &nbsp; &nbsp; &nbsp; !=========================<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Single (SP, 4&nbsp; bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Double (DP, 8&nbsp; bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Quad&nbsp; &nbsp;(QP, 16 bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- Single precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Single = SELECTED_REAL_KIND(6)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Double precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Double = SELECTED_REAL_KIND(2*precision(1.0_Single))</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Quadruple precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Quadr = SELECTED_REAL_KIND(2*precision(1.0_Double))<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Quad = (((1 + SIGN(1,Quadr)) / 2) * Quadr) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; + (((1 - SIGN(1,Quadr)) / 2) * Double)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER, PUBLIC:: SP = Single, DP = Double, QP = Quad</p><p>&nbsp; &nbsp; END MODULE Type_Kinds<br />&nbsp; &nbsp; <br />!--- The END of the program EQ_FP(x,y)<br />! -----------------------------------------------------------------------------------------------------</p>]]></content>
			<author>
				<name><![CDATA[drfrank]]></name>
				<uri>https://forums.approximatrix.com/profile.php?id=223</uri>
			</author>
			<updated>2020-11-09T16:29:47Z</updated>
			<id>https://forums.approximatrix.com/viewtopic.php?pid=3649#p3649</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: No Intrinsic Procedure for real equals real?]]></title>
			<link rel="alternate" href="https://forums.approximatrix.com/viewtopic.php?pid=3648#p3648" />
			<content type="html"><![CDATA[<p>Frank,</p><p>This post is absolutely appropriate for this forum.&nbsp; Please feel free to post things like this.&nbsp; I&#039;ll try to answer your questions as best I can.</p><div class="quotebox"><blockquote><p>(1) Is this the best way to test for equality?</p></blockquote></div><p>It really depends on the situation.&nbsp; If you have a simple calculation that you think the floating point result should be exactly a number, then this routine will work fine.&nbsp; The problem arises when you&#039;re testing a drastically more complex calculation that you think should end up &quot;equal&quot; to a given value.&nbsp; The errors inherent in floating-point mathematics on a computer can build as calculations use the results of previous calculations.&nbsp; While this build-up of errors might result in a value that is different from the expected answer by more than machine precision (i.e. the result of Fortran&#039;s <em>NEAREST</em> intrinsic), it is still effectively correct.</p><p>In my work, I would usually make a subjective judgment based on the problem being solved.&nbsp; For example, for some temperatures resulting from slow combustion, it was more than sufficient to test for equality within 0.01K.&nbsp; There was no need to get closer considering the flame was burning near 500-600K.</p><p>I normally will just use something like</p><div class="codebox"><pre><code>IF(ABS(x-y) &lt; 0.01) THEN ! Equal</code></pre></div><div class="quotebox"><blockquote><p>(2) Is there a better approach that works well?</p></blockquote></div><p>Again, it would depend on what you&#039;re trying to do.&nbsp; You can also think about how complicated you want the check to be.&nbsp; For example, your equality function is great, but if you&#039;re calling it in a loop that iterates over 400,000 points in two arrays every time step, maybe you&#039;ll start spending too much time in that calculation.&nbsp; It might be better to use something more like what I suggested above that only involves subtraction, a single bit modification, and a comparison.</p><div class="quotebox"><blockquote><p>(3) Why does double precision x+factor == y1 (.true.) in my example?</p></blockquote></div><p>Your value of y1 is the next largest representable value from x.&nbsp; In your test routine, though, you subtract the two numbers and then find the next largest value (<em>Difxy</em>) from that difference that is representable.&nbsp; </p><p>This <em>Difxy</em> value is then tested against:</p><div class="codebox"><pre><code>2.D0*DABS(Difx + Dify - DABS(x))</code></pre></div><p>This is adding the smaller (x) to the spacing of numbers calculated from the larger (SPACING(y1)) and subtracting the absolute value of x explicitly.&nbsp; The answer from this calculation should just be SPACING(y1), which should effectively be the same as SPACING(x).&nbsp; That value is multiplied by two, which I assume is almost like a buffer for further floating-point inaccuracy.&nbsp; But because <em>Difxy</em> is effectively going to be SPACING(x) anyway, it is indeed smaller than double the same value.</p><p>The same test fails for single precision, of course, because <em>Difxy</em> is computed in double precision, whereas the difference is actually going to be much larger because x and y were created in single precision.</p><p>I would say that you might want to create a module that implements this same routine in single-, double-, and quad-precision and uses an interface to call the appropriate routine based on precision.&nbsp; Something like:</p><div class="codebox"><pre><code>INTERFACE EQ_FP
    MODULE PROCEDURE EQ_FP4, EQ_FP8, EQ_FP16
END INTERFACE EQ_FP</code></pre></div><p>Then code could just call EQ_FP, and the interface block would route it to the proper precision test.</p>]]></content>
			<author>
				<name><![CDATA[jeff]]></name>
				<uri>https://forums.approximatrix.com/profile.php?id=2</uri>
			</author>
			<updated>2020-11-09T13:07:10Z</updated>
			<id>https://forums.approximatrix.com/viewtopic.php?pid=3648#p3648</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[Re: No Intrinsic Procedure for real equals real?]]></title>
			<link rel="alternate" href="https://forums.approximatrix.com/viewtopic.php?pid=3647#p3647" />
			<content type="html"><![CDATA[<p>Hi Jeff,</p><p>The equality routine FUNCTION EQ_FP8( x,y ) previously listed should be corrected to -</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Evaluate if x is equal to y?<br />&nbsp; &nbsp; &nbsp; &nbsp; IF (DABS(Difxy) &lt; TINY(u)) Difxy = TINY(u)<br />&nbsp; &nbsp; &nbsp; &nbsp; IF ( x == y ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DrFP = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ELSEIF ( DABS(Difxy) &lt; 2.D0*DABS(Difx + Dify - DABS(x)) ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DrFP = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ELSE<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DrFP = .FALSE.<br />&nbsp; &nbsp; &nbsp; &nbsp; ENDIF</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; SOURCE listing of EQ_FP8.f90:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;u = DMIN1(DABS(x), DABS(y))<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;v = DMAX1(DABS(x), DABS(y))<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Difx&nbsp; = NEAREST( u, v )<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Dify&nbsp; = SPACING( v )<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Difxy = NEAREST( v-u, v )<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;IF (DABS(Difxy) &lt; TINY(u)) Difxy = TINY(u)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;IF ( x == y ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DrFP = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;ELSEIF ( DABS(Difxy) &lt; 2.D0*DABS(Difx + Dify - DABS(x)) ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DrFP = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;ELSE<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DrFP = .FALSE.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;ENDIF<br />Frank</p>]]></content>
			<author>
				<name><![CDATA[drfrank]]></name>
				<uri>https://forums.approximatrix.com/profile.php?id=223</uri>
			</author>
			<updated>2020-11-08T23:09:14Z</updated>
			<id>https://forums.approximatrix.com/viewtopic.php?pid=3647#p3647</id>
		</entry>
		<entry>
			<title type="html"><![CDATA[No Intrinsic Procedure for real equals real?]]></title>
			<link rel="alternate" href="https://forums.approximatrix.com/viewtopic.php?pid=3646#p3646" />
			<content type="html"><![CDATA[<p>Hi Jeff,</p><p>I have a general programming question regarding the precision of real variables. Particularly when testing two reals for equality (x == y).&nbsp; Due to the lack of precision, there are situations when x should equal y, but due to the error in precision they are not equal (1.0000000000000000 /= 0.9999999999999999).&nbsp; As far as I understand, there is not a FORTRAN intrinsic procedure for the equality of two real numbers other than x == y.&nbsp; Therefore, I&#039;ve written a procedure to test for the equality of two real numbers that allows for the lack of precision in variables x and y.&nbsp; The routine is copied below.&nbsp; My question is as follows, (1) Is this the best way to test for equality?, (2) Is there a better approach that works well?, (3) Why does double precision x+factor == y1 (.true.) in my example?&nbsp; I welcome any thoughts on or improvements in this approach.&nbsp; Finally, Jeff, if you think my question is not appropriate for this forum, please remove this message.</p><p>Frank</p><p>Equality Program:</p><p>&nbsp; &nbsp; &nbsp; &nbsp; PROGRAM Test_EQ_FP8<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! NAME:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Test_EQ_FP8<br />&nbsp; &nbsp; &nbsp; &nbsp; ! PURPOSE:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Program to test the routines in the EQ_FP8(x,y) routine.<br />&nbsp; &nbsp; &nbsp; &nbsp; ! MODULES:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Type_Kinds: Definitions for kinds of variable types.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;EQ_FP8:&nbsp; &nbsp; &nbsp;Performs equality comparison of real numbers.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------</p><p>&nbsp; &nbsp; &nbsp; &nbsp; IMPLICIT NONE<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- Floating Point Precision<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; REAL( KIND )<br />&nbsp; &nbsp; &nbsp; &nbsp; !===============================<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Single (4&nbsp; bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Double (8&nbsp; bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; Quad&nbsp; &nbsp;(16 bytes)<br />&nbsp; &nbsp; &nbsp; &nbsp; !-------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !--- Six decimal place precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Single = SELECTED_REAL_KIND(6)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Fourteen decimal place precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Double = SELECTED_REAL_KIND(2*precision(1.0_Single))</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Sixteen decimal place precision<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Quadr = SELECTED_REAL_KIND(2*precision(1.0_Double))<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Quad = (((1 + SIGN(1,Quadr)) / 2) * Quadr) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; + (((1 - SIGN(1,Quadr)) / 2) * Double)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; Q = Quad, D = Double, S = Single</p><p>&nbsp; &nbsp; &nbsp; &nbsp; ! ----------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! Parameters<br />&nbsp; &nbsp; &nbsp; &nbsp; CHARACTER( * ), PARAMETER :: ROUTINE = &#039;Test_EQ_FP8&#039;</p><p>&nbsp; &nbsp; &nbsp; &nbsp; ! -- The test numbers<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: N_NUMBERS = 7</p><p>&nbsp; &nbsp; &nbsp; &nbsp; REAL( Single ), PARAMETER, DIMENSION( N_NUMBERS ) :: SINGLE_NUMBER = &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; (/ 1.000000000000000e-32_Single, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e-16_Single, 1.234567890123456e-08_Single, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.000000000000000e+00_Single, 1.234567890123456e+08_Single, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+16_Single, 1.234567890123456e+32_Single /)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; REAL( Double ), PARAMETER, DIMENSION( N_NUMBERS ) :: DOUBLE_NUMBER = &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; (/ 1.000000000000000e-32_Double, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e-16_Double, 1.234567890123456e-08_Double, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.000000000000000e+00_Double, 1.234567890123456e+08_Double, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+16_Double, 1.234567890123456e+32_Double /)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; REAL( Quad ), PARAMETER, DIMENSION( N_NUMBERS ) :: QUAD_NUMBER = &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; (/ 1.000000000000000e-32_Quad, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e-16_Quad, 1.234567890123456e-08_Quad, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.000000000000000e+00_Quad, 1.234567890123456e+08_Quad, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; 1.234567890123456e+16_Quad, 1.234567890123456e+32_Quad /)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; ! ---------<br />&nbsp; &nbsp; &nbsp; &nbsp; ! Variables<br />&nbsp; &nbsp; &nbsp; &nbsp; ! ---------<br />&nbsp; &nbsp; &nbsp; &nbsp; CHARACTER(len=256) :: cend<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( Single ) :: x,&nbsp; y1, y2, y3, y4<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( Double ) :: xd, yd1, yd2, yd3, yd4<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( Quad&nbsp; &nbsp;) :: xq, yq1, yq2, yq3, yq4<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( Double ) :: x0, y0<br />&nbsp; &nbsp; &nbsp; &nbsp; INTEGER :: i</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- Added error<br />&nbsp; &nbsp; &nbsp; &nbsp; REAL( Double ), PARAMETER :: e = 1.0e-30_Double</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !--- TEST EQUALITY OF X AND Y REALS<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; DO i = 1, N_NUMBERS<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x, &quot;NUMBER &quot;, i2, &quot; of &quot;, i2 )&#039; ) i, N_NUMBERS</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Single precision test<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = SINGLE_NUMBER(i)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y1 = NEAREST( x, 1.0_Single )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y2 = y1 - SPACING( x )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y3 = NEAREST( x, -1.0_Single )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y4 = y3 + SPACING( x )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = x + e</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Test standalone single precision function routines<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( /5x, &quot;SINGLE PRECISION: x&nbsp; = &quot;, es20.13, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y1 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x, 1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y2 = &quot;, es20.13, 2x, &quot;:&nbsp; y1 - SPACING( x )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y3 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x,-1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y4 = &quot;, es20.13, 2x, &quot;:&nbsp; y3 + SPACING( x )&quot; )&#039; ) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x, y1, y2, y3, y4</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y1): X=Y?&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y2): X=Y?&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y3): X=Y?&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = x; y0 = y4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y4): X=Y?&#039;, EQ_FP8( x0, y0 )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Double precision test<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd = DOUBLE_NUMBER(i)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yd1 = NEAREST( xd, 1.0_Double )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yd2 = yd1 - SPACING( xd )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yd3 = NEAREST( xd, -1.0_Double )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yd4 = yd3 + SPACING( xd )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd = xd + e</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Test stand alone double precision function routines<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( /5x, &quot;DOUBLE PRECISION: x&nbsp; = &quot;, es20.13, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y1 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x, 1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y2 = &quot;, es20.13, 2x, &quot;:&nbsp; y1 - SPACING( x )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y3 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x,-1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y4 = &quot;, es20.13, 2x, &quot;:&nbsp; y3 + SPACING( x )&quot; )&#039; ) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xd, yd1, yd2, yd3, yd4</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = xd; y0 = yd1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y1) X=Y?:&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = xd; y0 = yd2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y2) X=Y?:&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = xd; y0 = yd3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y3) X=Y?:&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = xd; y0 = yd4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y4) X=Y?:&#039;, EQ_FP8( x0, y0 )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !-------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! Quadruple precision test<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !-------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq = QUAD_NUMBER(i)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yq1 = NEAREST( xq, 1.0_Quad )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yq2 = yq1 - SPACING( xq )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yq3 = NEAREST( xq, -1.0_Quad )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yq4 = yq3 + SPACING( xq )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq = xq + e</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Test stand alone quadruple precision function routines<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( /5x, &quot;QUADRULE PRECISION: x&nbsp; = &quot;, es20.13, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y1 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x, 1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y2 = &quot;, es20.13, 2x, &quot;:&nbsp; y1 - SPACING( x )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y3 = &quot;, es20.13, 2x, &quot;:&nbsp; NEAREST( x,-1.0 )&quot;, &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;/5x, &quot;y4 = &quot;, es20.13, 2x, &quot;:&nbsp; y3 + SPACING( x )&quot; )&#039; ) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xq, yq1, yq2, yq3, yq4</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = xq; y0 = yq1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y1) X=Y?:&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = xq; y0 = yq2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y2) X=Y?:&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = xq; y0 = yq3<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y3) X=Y?:&#039;, EQ_FP8( x0, y0 )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x0 = xq; y0 = yq4<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( 5x,a,2x,L6)&#039;) &#039;EQ_FP8(x,y4) X=Y?:&#039;, EQ_FP8( x0, y0 )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *,&#039;(5x,a)&#039;) REPEAT(&quot;-&quot;,50)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Question?<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !----------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;(/5x,a/)&#039;) &amp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;Why is double precision number x+e=y1 true?&quot;<br />&nbsp; &nbsp; &nbsp; &nbsp; END DO</p><p>&nbsp; &nbsp; &nbsp; &nbsp; WRITE( *, &#039;( /10x, &quot;Press &lt;ENTER&gt; to continue...&quot; )&#039; )<br />&nbsp; &nbsp; &nbsp; &nbsp; READ( *, &#039;(a)&#039; ) cend</p><p>&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; CONTAINS<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------</p><p>&nbsp; &nbsp; &nbsp; &nbsp; FUNCTION EQ_FP8( x,y ) Result( DrFP )<br />&nbsp; &nbsp; &nbsp; &nbsp; !***************************************************************<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; EQ_FP8 version 1.0<br />&nbsp; &nbsp; &nbsp; &nbsp; !---<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; Developed by F.W. Perrella, Ph.D.&nbsp; November 7, 2020<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; EQ_FP8™ Copyright © 2020 F.W. PERRELLA, Ph.D.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Silver Spring, Maryland U.S.A.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; All Rights Reserved.<br />&nbsp; &nbsp; &nbsp; &nbsp; !***************************************************************<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; ! NAME:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;EQ_FP8<br />&nbsp; &nbsp; &nbsp; &nbsp; ! PURPOSE:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Program to determine whether two real numbers are equal.<br />&nbsp; &nbsp; &nbsp; &nbsp; ! MODULES:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Type_Kinds:&nbsp; &nbsp; &nbsp; Definition for double kind variable types.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;EQ_FP8:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Routine to perform equality comparison<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;of real numbers.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; SOURCE listing of EQ_FP8.f90:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;u = DMIN1(DABS(x), DABS(y))<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;v = DMAX1(DABS(x), DABS(y))<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Difx&nbsp; = NEAREST( u, v )<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Dify&nbsp; = SPACING( v )<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Difxy = NEAREST( v-u, v )<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;IF (Difxy &lt; TINY(u)) Difxy = TINY(u)<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;IF ( Difxy &lt; DABS(Difx + Dify - x) ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DrFP = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;ELSE<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DrFP = .FALSE.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;ENDIF<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; FORTRAN 90 INTRINSIC FUNCTIONS:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; SPACING(x) determines the absolute distance between the<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; argument x and the nearest adjacent number of the same type.<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; SPACING(x) = 2.D0**( EXPONENT(x) - DIGITS(x) )<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; NEAREST( x,s ) determines the processor-representable number<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; nearest to x in the direction indicated by the sign of s.<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; NEAREST(x,y) = x + SIGN(1.D0,x)*2.D0**(EXPONENT(x)-DIGITS(x))<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; CALLING SEQUENCE:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;Result = EQ_FP8( x,y )<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; INPUT ARGUMENTS:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;x, y:&nbsp; &nbsp; &nbsp; &nbsp;Two real numbers to compare.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;TYPE:&nbsp; &nbsp; &nbsp; &nbsp;REAL( Double )<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; ATTRIBUTES:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;INTENT( IN )<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; FUNCTION RESULT:<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;TYPE:&nbsp; &nbsp; &nbsp;Logical<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp;RESULT:&nbsp; &nbsp;A returned logical value indicating whether the<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;x and y inputs are equal within the set precision.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Set to .TRUE. if the real numbers are equal<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;within the specified tolerance.<br />&nbsp; &nbsp; &nbsp; &nbsp; !&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Set to .FALSE. if the real numbers are not equal.<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IMPLICIT NONE</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Input variables<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; REAL(Kind=8), INTENT( IN )&nbsp; :: x<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; REAL(Kind=8), INTENT( IN )&nbsp; :: y<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LOGICAL&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:: DrFP</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Double precision<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; INTEGER, PARAMETER :: Doubles = SELECTED_REAL_KIND(15,300)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Local Variables<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; REAL(Doubles)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: u, v<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; REAL(Doubles)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: Difx<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; REAL(Doubles)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: Dify<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; REAL(Doubles)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: Difxy<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; INTRINSIC&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; :: NEAREST, SPACING, DMIN1, DMAX1, DABS</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Minimum and maximum of x and y<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; u = DMIN1(DABS(x), DABS(y))<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v = DMAX1(DABS(x), DABS(y))</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Determine Nearest, Spacing, and Nearest difference<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Difx&nbsp; = NEAREST( u, v )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Dify&nbsp; = SPACING( v )<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Difxy = NEAREST( v-u, v )</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Nearest difference cannot be less than Tiny<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IF (Difxy &lt; TINY(u)) Difxy = TINY(u)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !--- Evaluate if x is equal to y?<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IF ( Difxy &lt; DABS(Difx + Dify - x) ) THEN<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DrFP = .TRUE.<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ELSE<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DrFP = .FALSE.<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ENDIF</p><p>&nbsp; &nbsp; &nbsp; &nbsp; END FUNCTION EQ_FP8<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------</p><p>&nbsp; &nbsp; &nbsp; &nbsp; END PROGRAM Test_EQ_FP8<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------<br />&nbsp; &nbsp; &nbsp; &nbsp; !---------------------------------------------------------------</p>]]></content>
			<author>
				<name><![CDATA[drfrank]]></name>
				<uri>https://forums.approximatrix.com/profile.php?id=223</uri>
			</author>
			<updated>2020-11-07T22:15:28Z</updated>
			<id>https://forums.approximatrix.com/viewtopic.php?pid=3646#p3646</id>
		</entry>
</feed>
