-- Test that the complex elementary functions have the same range as the real -- elementary functions when called with a real arguments in the domain -- of the real elementary functions. -- The two instantiations at the bottom attempt to produce -- TEST_FLOAT_FUNCTIONS_RANGE TEST_LONG_FLOAT_FUNCTIONS_RANGE -- Link and execute the subset that compile. with GENERIC_COMPLEX_TYPES; with GENERIC_ELEMENTARY_FUNCTIONS; with GENERIC_COMPLEX_ELEMENTARY_FUNCTIONS; with TEXT_IO; use TEXT_IO; generic type REAL is digits <>; Procedure TEST_REAL_COMPLEX_FUNCTIONS_RANGE; Procedure TEST_REAL_COMPLEX_FUNCTIONS_RANGE is package REAL_IO is new FLOAT_IO(REAL); use REAL_IO; package REAL_FUNCTIONS is new GENERIC_ELEMENTARY_FUNCTIONS(REAL); use REAL_FUNCTIONS; package COMPLEX_TYPES is new GENERIC_COMPLEX_TYPES(REAL); use COMPLEX_TYPES; package COMPLEX_FUNCTIONS is new GENERIC_COMPLEX_ELEMENTARY_FUNCTIONS (REAL, COMPLEX, IMAGINARY); use COMPLEX_FUNCTIONS; X : REAL; Y_REAL : REAL; Y_COMPLEX : COMPLEX; EPSILON : REAL := REAL'EPSILON; IM_NON_ZERO : BOOLEAN := FALSE; IM_TOO_BIG : BOOLEAN := FALSE; Y_COMPLEX_AT_ERROR : COMPLEX := COMPOSE_FROM_CARTESIAN(0.0,0.0); Y_REAL_AT_ERROR : REAL := 0.0; X_AT_ERROR : REAL := 0.0; MAX_ERROR : REAL := 0.0; EXCEPTION_COUNT_GEF : INTEGER := 0; EXCEPTION_COUNT_GCEF : INTEGER := 0; GEF_EXCEPTION : BOOLEAN := FALSE; GCEF_EXCEPTION : BOOLEAN := FALSE; type VECTOR is array (INTEGER range <>) of REAL; DATA1 : VECTOR(1..25) := (-REAL'SAFE_LARGE, -1.0E6, -1.0E3, -10.0, -1.5, -1.0, -0.99, -0.5, -0.1, -1.0E-3, -1.0E-6, -REAL'SAFE_SMALL, 0.0, REAL'SAFE_SMALL, 1.0E-6, 1.0E-3, 0.1, 0.5, 0.99, 1.0, 1.5, 10.0, 1.0E3, 1.0E6, REAL'SAFE_LARGE); -- mathematically unbounded DATA2 : VECTOR(1..19) := ( 0.0, REAL'SAFE_SMALL, 1.0E-6, 1.0E-5, 1.0E-4, 1.0E-3, 1.0E-2, 0.1, 0.5, 0.99, 1.0, 1.5, 10.0, 1.0E2, 1.0E3, 1.0E4, 1.0E5, 1.0E6, REAL'SAFE_LARGE); -- X >= 0.0 DATA3 : VECTOR(1..19) := (-0.0, -10.0, -1.5, -1.0, -0.99, -0.5, -0.1, -0.001, -REAL'SAFE_SMALL, 0.0, REAL'SAFE_SMALL, 0.001, 0.1, 0.5, 0.99, 1.0, 1.5, 10.0, 0.0); -- mathematically unbounded, limited by ln('LARGE/2) DATA4 : VECTOR(1..13) := (-1.0, -0.99, -0.5, -0.1, -0.001, -REAL'SAFE_SMALL, 0.0, REAL'SAFE_SMALL, 0.001, 0.1, 0.5, 0.99, 1.0); -- -1.0..1.0 DATA5 : VECTOR(1..10) := (-REAL'SAFE_LARGE, -1000.0, -10.0, -1.5, -1.0, 1.0, 1.5, 10.0, 1000.0, REAL'SAFE_LARGE); -- |X|>=1.0 DATA6 : VECTOR(1..5) := ( 1.0, 1.5, 10.0, 1000.0, REAL'SAFE_LARGE); -- X >= 1.0 procedure CHECK(DOMAIN: REAL; GEF_VALUE: REAL; GCEF_VALUE: COMPLEX; PRINT_ALL: BOOLEAN := FALSE) is ERROR : REAL; begin if GEF_EXCEPTION or GCEF_EXCEPTION then if GEF_EXCEPTION then EXCEPTION_COUNT_GEF := EXCEPTION_COUNT_GEF +1; end if; if GCEF_EXCEPTION then EXCEPTION_COUNT_GCEF := EXCEPTION_COUNT_GCEF +1; end if; if GEF_EXCEPTION /= GCEF_EXCEPTION then PUT("Exceptions differ at X = "); PUT(DOMAIN); PUT_LINE(" GEF_EXCEPTION=" & BOOLEAN'IMAGE(GEF_EXCEPTION) & " GCEF_EXCEPTION=" & BOOLEAN'IMAGE(GCEF_EXCEPTION)); end if; GEF_EXCEPTION := FALSE; GCEF_EXCEPTION := FALSE; else if GEF_VALUE /= 0.0 then ERROR := abs((RE(GCEF_VALUE)- GEF_VALUE)/GEF_VALUE); else ERROR := abs(RE(GCEF_VALUE) - GEF_VALUE); end if; if ERROR > MAX_ERROR then if PRINT_ALL then PUT("CHECK at X= "); PUT(DOMAIN); PUT(", real error= "); PUT(ERROR); NEW_LINE; PUT(" Y_REAL= "); PUT(GEF_VALUE); PUT(", Y_COMPLEX= ("); PUT(RE(GCEF_VALUE)); PUT(","); PUT(IM(GCEF_VALUE)); PUT_LINE(")"); end if; MAX_ERROR := ERROR; X_AT_ERROR := DOMAIN; Y_REAL_AT_ERROR := GEF_VALUE; Y_COMPLEX_AT_ERROR := GCEF_VALUE; end if; if IM(GCEF_VALUE) /= 0.0 then IM_NON_ZERO := TRUE; if GEF_VALUE /= 0.0 then if abs(IM(GCEF_VALUE)/GEF_VALUE) > 16.0*EPSILON then IM_TOO_BIG := TRUE; end if; end if; end if; end if; end CHECK; procedure PRINT_CHECK is begin if EXCEPTION_COUNT_GEF + EXCEPTION_COUNT_GCEF /= 0 then PUT_LINE("GEF exception count = " & INTEGER'IMAGE(EXCEPTION_COUNT_GEF)); PUT_LINE("GCEF exception count = " & INTEGER'IMAGE(EXCEPTION_COUNT_GCEF)); end if; PUT(" MAX_ERROR "); PUT(MAX_ERROR); NEW_LINE; PUT(" X at MAX_ERROR "); PUT(X_AT_ERROR); NEW_LINE; PUT("Y_REAL_AT_ERROR ="); PUT(Y_REAL_AT_ERROR); NEW_LINE; PUT("Y_COMPLEX_AT_ERROR ("); PUT(RE(Y_COMPLEX_AT_ERROR)); PUT(","); PUT(IM(Y_COMPLEX_AT_ERROR)); PUT_LINE(")"); NEW_LINE; MAX_ERROR := 0.0; X_AT_ERROR := 0.0; Y_REAL_AT_ERROR := 0.0; Y_COMPLEX_AT_ERROR := COMPOSE_FROM_CARTESIAN(0.0,0.0); EXCEPTION_COUNT_GEF := 0; EXCEPTION_COUNT_GCEF := 0; IM_NON_ZERO := FALSE; IM_TOO_BIG := FALSE; end PRINT_CHECK; begin PUT_LINE("Beginning TEST_REAL_COMPLEX_FUNCTIONS_RANGE"); DATA3(DATA3'LAST) := LOG(REAL'SAFE_LARGE/2.0) * (1.0-4.0*REAL'EPSILON); DATA3(DATA3'FIRST) := - DATA3(DATA3'LAST); -- SQRT PUT_LINE("SQRT X >= 0.0"); for I in DATA2'RANGE loop X := DATA2(I); begin Y_REAL := SQRT(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := SQRT(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- LOG PUT_LINE("LOG X > 0.0"); for I in DATA2'RANGE loop X := DATA2(I); begin Y_REAL := LOG(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := LOG(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- EXP PUT_LINE("EXP unbounded, size limit"); for I in DATA3'RANGE loop X := DATA3(I); begin Y_REAL := EXP(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := EXP(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- SIN PUT_LINE("SIN unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := SIN(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := SIN(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- COS PUT_LINE("COS unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := COS(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := COS(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- TAN PUT_LINE("TAN unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := TAN(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := TAN(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- COT PUT_LINE("COT unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := COT(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := COT(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- ARCSIN PUT_LINE("ARCSIN -1.0..1.0"); for I in DATA4'RANGE loop X := DATA4(I); begin Y_REAL := ARCSIN(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := ARCSIN(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- ARCCOS PUT_LINE("ARCCOS -1.0..1.0"); for I in DATA4'RANGE loop X := DATA4(I); begin Y_REAL := ARCCOS(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := ARCCOS(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- ARCTAN PUT_LINE("ARCTAN unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := ARCTAN(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := ARCTAN(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- ARCCOT PUT_LINE("ARCCOT unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := ARCCOT(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := ARCCOT(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- SINH PUT_LINE("SINH unbounded, size limit"); for I in DATA3'RANGE loop X := DATA3(I); begin Y_REAL := SINH(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := SINH(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- COSH PUT_LINE("COSH unbounded, size limit"); for I in DATA3'RANGE loop X := DATA3(I); begin Y_REAL := COSH(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := COSH(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- TANH PUT_LINE("TANH unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := TANH(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := TANH(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- COTH PUT_LINE("COTH unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := COTH(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := COTH(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- ARCSINH PUT_LINE("ARCSINH unbounded"); for I in DATA1'RANGE loop X := DATA1(I); begin Y_REAL := ARCSINH(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := ARCSINH(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- ARCCOSH PUT_LINE("ARCCOSH X>1.0"); for I in DATA6'RANGE loop X := DATA6(I); begin Y_REAL := ARCCOSH(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := ARCCOSH(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- ARCTANH PUT_LINE("ARCTANH -1.0..1.0"); for I in DATA4'RANGE loop X := DATA4(I); begin Y_REAL := ARCTANH(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := ARCTANH(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; -- ARCCOTH PUT_LINE("ARCCOTH |X|>=1.0"); for I in DATA5'RANGE loop X := DATA5(I); begin Y_REAL := ARCCOTH(X); exception when others => GEF_EXCEPTION := TRUE; end; begin Y_COMPLEX := ARCCOTH(COMPOSE_FROM_CARTESIAN(X,0.0)); exception when others => GCEF_EXCEPTION := TRUE; end; CHECK(X, Y_REAL, Y_COMPLEX); end loop; PRINT_CHECK; PUT_LINE("End TEST_REAL_COMPLEX_FUNCTIONS_RANGE"); end TEST_REAL_COMPLEX_FUNCTIONS_RANGE; -- Instantiate for existing predefined type of FLOAT with TEST_REAL_COMPLEX_FUNCTIONS_RANGE; Procedure TEST_FLOAT_FUNCTIONS_RANGE is new TEST_REAL_COMPLEX_FUNCTIONS_RANGE(FLOAT); -- Instantiate for possible predefined type of LONG_FLOAT with TEST_REAL_COMPLEX_FUNCTIONS_RANGE; Procedure TEST_LONG_FLOAT_FUNCTIONS_RANGE is new TEST_REAL_COMPLEX_FUNCTIONS_RANGE(LONG_FLOAT);