' ******************************************************************
' Hyperbolic functions
' ******************************************************************

' ------------------------------------------------------------------
' Error codes
' ------------------------------------------------------------------

#DEFINE FOk 0  
' No error

#DEFINE FDomain -1  
' Argument domain error

#DEFINE FSing -2  
' Singularity

#DEFINE FOverflow -3  
' Overflow range error

' ------------------------------------------------------------------
' Machine-dependent constants
' ------------------------------------------------------------------

#DEFINE MaxNum 1.797693134862315D+308
' Max. floating point number: 2^1024

#DEFINE MaxLog 709.782712893384#        
' Max. argument for Exp

#DEFINE MinLog -708.3964185322641#       
' Min. argument for Exp

' ------------------------------------------------------------------
' Global variable
' ------------------------------------------------------------------

COMMON SHARED ErrCode AS INTEGER
' Error code from the latest function evaluation

' ******************************************************************

FUNCTION ACosh (X AS DOUBLE) AS DOUBLE
  IF X < 1 THEN
    ErrCode = FDomain
    ACosh = 0
  ELSE
    ErrCode = FOk
    ACosh = LOG(X + SQR(X * X - 1))
  END IF
END FUNCTION

FUNCTION ASinh (X AS DOUBLE) AS DOUBLE
  ErrCode = FOk
  ASinh = LOG(X + SQR(X * X + 1))
END FUNCTION

FUNCTION ATanh (X AS DOUBLE) AS DOUBLE
  IF X < -1 OR X > 1 THEN
    ErrCode = FDomain
    ATanh = SGN(X) * MaxNum
  ELSEIF (X = -1) OR (X = 1) THEN
    ErrCode = FSing
    ATanh = SGN(X) * MaxNum
  ELSE
    ErrCode = FOk
    ATanh = 0.5 * LOG((1 + X) / (1 - X))
  END IF
END FUNCTION

FUNCTION Cosh (X AS DOUBLE) AS DOUBLE
  DIM ExpX AS DOUBLE
   
  IF X < MinLog OR X > MaxLog THEN
    ErrCode = FOverflow
    Cosh = MaxNum
  ELSE
    ErrCode = FOk
    ExpX = EXP(X)
    Cosh = 0.5 * (ExpX + 1 / ExpX)
  END IF
END FUNCTION

FUNCTION Sinh (X AS DOUBLE) AS DOUBLE
  DIM ExpX AS DOUBLE

  IF X < MinLog OR X > MaxLog THEN
    ErrCode = FOverflow
    Sinh = SGN(X) * MaxNum
  ELSE
    ErrCode = FOk
    ExpX = EXP(X)
    Sinh = 0.5 * (ExpX - 1 / ExpX)
  END IF
END FUNCTION

SUB SinhCosh (X AS DOUBLE, BYREF SinhX AS DOUBLE, BYREF CoshX AS DOUBLE)
  DIM AS DOUBLE ExpX, ExpMinusX
   
  IF X < MinLog OR X > MaxLog THEN
    ErrCode = FOverflow
    CoshX = MaxNum
    SinhX = SGN(X) * CoshX
  ELSE
    ErrCode = FOk
    ExpX = EXP(X)
    ExpMinusX = 1 / ExpX
    SinhX = .5 * (ExpX - ExpMinusX)
    CoshX = .5 * (ExpX + ExpMinusX)
  END IF
END SUB

FUNCTION Tanh (X AS DOUBLE) AS DOUBLE
  DIM AS DOUBLE SinhX, CoshX
 
  SinhCosh X, SinhX, CoshX
  Tanh = SinhX / CoshX
END FUNCTION

