--
--	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 ATAN2.
-- Before:
--      V.compared.with.zero = less.than
--        Result := ATAN (ABS (REAL32OP(V, Div, U))) - Pi
--      TRUE
--        Result := Pi - ATAN (ABS (REAL32OP(V, Div, U)))
-- After:
--      V.compared.with.zero = less.than
--        Result := ATAN( REAL32OP(V, Div, U) ) - Pi
--      TRUE
--        Result := Pi + ATAN( REAL32OP(V, Div, U) )
--
-- TS/1232, V1.2, 10-Apr-91 SRH
--}}}
--{{{  ATAN
--* Single-precision arctangent.
--
-- @param X Input value
-- @return Arctangent of X
REAL32 FUNCTION ATAN (VAL REAL32 X)

  REAL32 Result :
  VALOF
    --{{{  Reduced ArcTan
    REAL32 FUNCTION ReducedATan (VAL REAL32 X)
      REAL32 RWork :
      VALOF
        --{{{  definitions and variables
        -- Threshold for atan(x) = x is 2 ** (-ManBits/2), see C&W p200.
        VAL REAL32 TwoSubR3 RETYPES #3E8930A3(INT32) : -- 2 - sqrt(3)
        VAL REAL32 PiBy6 RETYPES #3F060A92(INT32) :
        VAL A  IS  7.320508076E-1(REAL32) :
        VAL R3 IS  1.732050808(REAL32) :
        VAL P1 IS -5.090958253E-2(REAL32) :
        VAL P0 IS -4.708325141E-1(REAL32) :
        VAL Q0 IS  1.412500740(REAL32) :
        REAL32 XWork :
        BOOL Reduced :
        --}}}
        SEQ
          --{{{  further reduce argument
          IF
            X > TwoSubR3
              SEQ
                Reduced := TRUE
                XWork :=  ((((A * X) - Half) - Half) + X) / (R3 + X)
            TRUE
              SEQ
                Reduced := FALSE
                XWork := X
          --}}}
          SEQ
            --{{{  compute rational
            VAL G IS XWork * XWork :
            RWork := (((((P1 * G) + P0) * G) / (G + Q0)) * XWork) + XWork
            --}}}
            IF
              Reduced
                RWork := RWork + PiBy6
              TRUE
                SKIP
        RESULT RWork
    :
    --}}}
    IF
      NOTFINITE (X)
        --{{{  Infs and NaNs
        INT order :
        SEQ
          order := IEEECOMPARE (X, Zero)
          CASE order
            less.than
              Result := - PiBy2
            greater.than
              Result :=  PiBy2
            is.nan
              Result := X -- transmit NaN
        --}}}
      --{{{  definitions
      -- For X > XMax, PiBy2 - (1/X) = PiBy2 to machine precision.
      VAL REAL32 XMax RETYPES #4B800000(INT32) :
      VAL XWork IS ABS (X) :
      --}}}
      IF
        XWork > XMax
          --{{{  + or - Pi/2
          IF
            X < Zero
              Result := - PiBy2
            TRUE
              Result := PiBy2
          --}}}
        XWork > One
          --{{{  reduce argument and compute
          IF
            X < Zero
              Result := (ReducedATan (One/XWork) - PiBy2.err) - PiBy2
            TRUE
              Result := PiBy2 + (PiBy2.err - ReducedATan (One/XWork))
          --}}}
        X < Zero
          Result := - ReducedATan (XWork)
        TRUE
          Result := ReducedATan (XWork)
    RESULT Result
:
--}}}
--{{{  ATAN2
--* Single-precision divide and arctangent.
--
-- This can be used to convert a 2D coordinate to a polar angle. It is more
-- accurate than doing the equivalent division and call to [@ref ATAN].
--
-- @param U, V Input values
-- @return Arctangent of [@code U / V]
REAL32 FUNCTION ATAN2 (VAL REAL32 U, V)

  REAL32 Result :
  VALOF
    --{{{  definitions
    VAL U.compared.with.zero IS IEEECOMPARE (U, Zero) :
    VAL V.compared.with.zero IS IEEECOMPARE (V, Zero) :
    --}}}
    IF
      (U.compared.with.zero = is.nan) OR (V.compared.with.zero = is.nan)
        -- incorporates precedence rule for NaNs
        Result := REAL32OP (U, Add, V)
      NOTFINITE (U) AND NOTFINITE (V)
        Result := undefined.NaN
      U.compared.with.zero = equal.to
        --{{{  depends on V
        IF
          V.compared.with.zero = equal.to
            Result := undefined.NaN
          V.compared.with.zero = greater.than
            Result := PiBy2
          TRUE
            Result := - PiBy2
        --}}}
      U.compared.with.zero = greater.than
        -- NB V/U may overflow, and so must not be 'checked'
        Result := ATAN (REAL32OP (V, Div, U))
      V.compared.with.zero = less.than
        -- U < Zero; V < Zero; and one may be -infinity
        Result := ATAN( REAL32OP(V, Div, U) ) - Pi
      TRUE
        -- U < Zero; V >= Zero; and possibly U = -infinity or V = +infinity
        Result := Pi + ATAN( REAL32OP(V, Div, U) )
    RESULT Result
:
--}}}
