--
--	Inmos Libraries
--	Copyright (C) 1988, 1989, 1990, 1991, 1993  Inmos Limited
--
--	This library is free software; you can redistribute it and/or
--	modify it under the terms of the GNU Lesser General Public
--	License as published by the Free Software Foundation; either
--	version 2 of the License, or (at your option) any later version.
--
--	This library is distributed in the hope that it will be useful,
--	but WITHOUT ANY WARRANTY; without even the implied warranty of
--	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--	Lesser General Public License for more details.
--
--	You should have received a copy of the GNU Lesser General Public
--	License along with this library; if not, write to the Free Software
--	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
--

--** @module maths

#OPTION "V"  -- no vector space
#COMMENT "Floating point maths library, V1.2 10/04/91"
#COMMENT "(c) Copyright INMOS Limited 1988"
#INCLUDE "mathhdr.inc"

--{{{  history
-- V1.0 1-Jul-88
-- Added OPTION "V"; V1.1 27-Mar-90 SRH
-- Removed unnecessary calls to ABS in the last two branches of the IF
-- in DATAN2.
-- Before:
--      V.compared.with.zero = less.than
--        Result := DATAN (DABS (REAL64OP(V, Div, U))) - DPi
--      TRUE
--        Result := DPi - DATAN (DABS (REAL64OP(V, Div, U)))
-- After:
--      V.compared.with.zero = less.than
--        Result := DATAN( REAL64OP(V, Div, U) ) - DPi
--      TRUE
--        Result := DPi + DATAN( REAL64OP(V, Div, U) )
-- TS/1232, V1.2, 10-Apr-91 SRH
--}}}
--{{{  DATAN
--* Double-precision arctangent.
--
-- @param X Input value
-- @return Arctangent of X
REAL64 FUNCTION DATAN (VAL REAL64 X)
  REAL64 Result :
  VALOF
    --{{{  FUNCTION DReducedATan
    REAL64 FUNCTION DReducedATan (VAL REAL64 X)
      REAL64 RWork :
      VALOF
        --{{{  definitions and variables
        VAL REAL64 TwoSubR3 RETYPES #3FD126145E9ECD56(INT64) : -- 2 - sqrt(3)
        VAL REAL64 DPiBy6   RETYPES #3FE0C152382D7366(INT64) :
        VAL A  IS 0.73205080756887729353(REAL64) :
        VAL R3 IS 1.73205080756887729353(REAL64) :
        VAL P IS [-8.3758299368150059274E-1(REAL64),
                  -8.4946240351320683534E+0(REAL64),
                  -2.0505855195861651981E+1(REAL64),
                  -1.3688768894191926929E+1(REAL64)] :
        VAL Q IS [1.5024001160028576121E+1(REAL64),
                  5.9578436142597344465E+1(REAL64),
                  8.6157349597130242515E+1(REAL64),
                  4.1066306682575781263E+1(REAL64)] :
        REAL64 XWork :
        BOOL Reduced :
        --}}}
        SEQ
          --{{{  further reduce argument
          IF
            X > TwoSubR3
              SEQ
                Reduced := TRUE
                XWork := ((((A * X) - DHalf) - DHalf) + X) / (R3 + X)
            TRUE
              SEQ
                Reduced := FALSE
                XWork := X
          --}}}
          --{{{  compute rational
          VAL G IS XWork * XWork :
          RWork := XWork + (XWork * ((((((((P[0]*G)+P[1])*G)+P[2])*G)+P[3])*G)/
                        (((((((G+Q[0])*G)+Q[1])*G)+Q[2])*G)+Q[3])))
          --}}}
          IF
            Reduced
              RWork := RWork + DPiBy6
            TRUE
              SKIP
        RESULT RWork
    :
    --}}}
    IF
      DNOTFINITE (X)
        --{{{  NaNs and Infs
        INT order :
        SEQ
          order:= DIEEECOMPARE (X, DZero)
          CASE order
            less.than
              Result := - DPiBy2
            greater.than
              Result := DPiBy2
            is.nan
              Result := X  -- transmit NaN
        --}}}
      --{{{  definitions and variables
      -- For X > XMax, PiBy2 - (1/X) = PiBy2 to machine precision.
      VAL REAL64 XMax RETYPES #4340000000000000(INT64) :
      VAL XWork IS DABS (X) :
      --}}}
      IF
        XWork > XMax
          --{{{  + or - Pi/2
          IF
            X < DZero
              Result := - DPiBy2
            TRUE
              Result := DPiBy2
          --}}}
        XWork > DOne
          --{{{  reduce argument and compute
          IF
            X < DZero
              Result := (DReducedATan (DOne/XWork) - DPiBy2.err) - DPiBy2
            TRUE
              Result := DPiBy2 + (DPiBy2.err - DReducedATan (DOne/XWork))
          --}}}
        X < DZero
          Result := - DReducedATan (XWork)
        TRUE
          Result :=  DReducedATan (XWork)
    RESULT Result
:
--}}}
--{{{  DATAN2
--* Double-precision divide and arctangent.
--
-- See [@ref ATAN2] for more details.
--
-- @param U, V Input values
-- @return Arctangent of [@code U / V]
REAL64 FUNCTION DATAN2 (VAL REAL64 U, V)

  REAL64 Result :
  VALOF
    VAL U.compared.with.zero IS DIEEECOMPARE (U,DZero) :
    VAL V.compared.with.zero IS DIEEECOMPARE (V,DZero) :
    IF
      (U.compared.with.zero = is.nan) OR (V.compared.with.zero = is.nan)
        -- incorporates precedence rule for NaNs
        Result := REAL64OP (U, Add, V)
      DNOTFINITE (U) AND DNOTFINITE (V)
        Result := Dundefined.NaN
      U.compared.with.zero = equal.to
        --{{{  depends on V
        IF
          V.compared.with.zero = equal.to
            Result := Dundefined.NaN
          V.compared.with.zero = greater.than
            Result := DPiBy2
          TRUE
            Result := - DPiBy2
        --}}}
      U.compared.with.zero = greater.than
        -- NB V/U may overflow, and so must not be 'checked'
        Result := DATAN (REAL64OP (V, Div, U))
      V.compared.with.zero = less.than
        -- U < Zero; V < Zero; and one may be -infinity
        Result := DATAN( REAL64OP(V, Div, U) ) - DPi
      TRUE
        -- U < Zero; V < Zero; and one may be -infinity
        Result := DPi + DATAN( REAL64OP(V, Div, U) )
    RESULT Result
:
--}}}
