' ******************************************************************
' This program tests the accuracy of the elementary functions.
' For each function, 20 random arguments are picked, then the
' function is computed, the reciprocal function is applied to
' the result, and the relative error between this last result
' and the original argument is computed.
' ******************************************************************

#INCLUDE "fbmath.bi"

CONST NARG = 20  ' Number of arguments

DIM SHARED AS DOUBLE X(1 TO NARG), Y(1 TO NARG)  ' Random arguments

' ------------------------------------------------------------------
' Subprograms
' ------------------------------------------------------------------

SUB Pause ()
    PRINT
    PRINT "Press any key to continue";
    SLEEP
    PRINT
END SUB

SUB PrintResult (X AS DOUBLE, Y AS DOUBLE, Z AS DOUBLE)
    PRINT USING "  #####.####"; X; Y; Z;
    IF X <> 0 THEN PRINT USING "    ##.##^^^^"; (X - Z) / X
END SUB

SUB PrintTitle (FuncName1 AS STRING, FuncName2 AS STRING)
    PRINT
    PRINT "        X     Y = "; FuncName1; "(X)   X = "; FuncName2; "(Y)     Error"
    PRINT STRING$(77, "-")
END SUB

SUB RanArgs (X() AS DOUBLE, Xmin AS DOUBLE, Xmax AS DOUBLE)
' Fills a table of random arguments between Xmin and Xmax,
' rounded to 4 decimal places and sorted in increasing order.

    DIM AS INTEGER I, J, K
    DIM AS DOUBLE  A

    RANDOMIZE TIMER
    FOR I = 1 TO NARG
        A = (Xmax - Xmin) * RND + Xmin
        IF ABS(A) < 0.0001# THEN A = SGN(A) * 0.0001#
        X(I) = INT(10000 * A) / 10000
    NEXT I

    ' Insertion sort
    FOR I = 1 TO NARG - 1
        K = I
        A = X(I)
        FOR J = I + 1 TO NARG
          IF X(J) < A THEN
              K = J
              A = X(J)
          END IF
        NEXT J
        SWAP X(I), X(K)
    NEXT I
END SUB

SUB TestCos ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), 0, Pi

    PrintTitle "Cos", "ACos"

    FOR I = 1 TO NARG
        Z = COS(X(I))
        T = ACOS(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

SUB TestCosh ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), 0, 5

    PrintTitle "Cosh", "ACosh"

    FOR I = 1 TO NARG
        Z = Cosh(X(I))
        T = ACosh(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

SUB TestExp10 ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), -5, 5

    PrintTitle "Exp10", "Log10"

    FOR I = 1 TO NARG
        Z = Exp10(X(I))
        T = Log10(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

SUB TestExp2 ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), -15, 15

    PrintTitle "Exp2", "Log2"

    FOR I = 1 TO NARG
        Z = Exp2(X(I))
        T = Log2(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

SUB TestExpo ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), -10, 10

    PrintTitle "Expo", "Ln"

    FOR I = 1 TO NARG
        Z = Expo(X(I))
        T = Ln(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

SUB TestSin ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), -PiDiv2, PiDiv2

    PrintTitle "Sin", "ASin"

    FOR I = 1 TO NARG
        Z = SIN(X(I))
        T = ASIN(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

SUB TestSinh ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), 0, 5

    PrintTitle "Sinh", "ASinh"

    FOR I = 1 TO NARG
        Z = Sinh(X(I))
        T = ASinh(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

SUB TestTan ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), -PiDiv2, PiDiv2

    PrintTitle "Tan", "Atn"

    FOR I = 1 TO NARG
        Z = TAN(X(I))
        T = ATN(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

SUB TestTanh ()

    DIM AS INTEGER I
    DIM AS DOUBLE  Z, T

    RanArgs X(), -5, 5

    PrintTitle "Tanh", "ATanh"

    FOR I = 1 TO NARG
        Z = Tanh(X(I))
        T = ATanh(Z)
        PrintResult X(I), Z, T
    NEXT I

    Pause
END SUB

' ------------------------------------------------------------------
' Main program
' ------------------------------------------------------------------

' Test exponential functions

TestExpo
TestExp10
TestExp2

' Test trigonometric functions

TestSin
TestCos
TestTan

' Test hyperbolic functions

TestSinh
TestCosh
TestTanh
