(   Title:  FATAN2 tests
     File:  fatan2-test.fs
   Author:  David N. Williams
  Version:  0.1.0
  License:  Public Domain
  Revised:  March 27, 2009

Version 0.1.0
14Mar09 * Started.
19Mar09 * Added angles to complete the circle.
23Mar09 * Added definitions of fractions of pi in terms of pi,
	  which avoids most of the decimal to binary
	  conversions.  Suggested by Bernd Paysan.
27Mar09 * Added link to Krishna Myneni's kforth version.

This file tests the ISO C / Single UNIX 3 specification for
the ANS Forth Floating-Ext word:
)
\ FATAN2 ( f: y x -- radians ) or ( y x -- radians )
(
It expects the return value to be the principal angle, and
includes a number of tests with +/-0, +/-NaN, and +/-Inf that
are not required by the ANS Forth 94 standard.

A version that works with kForth can be found here:

  ftp://ccreweb.org/software/kforth/examples/fatan2-test.4th
)

\ for pfe:
\ s" FLOATING-EXT" environment? [IF] drop [THEN]

\ for kforth
s" ans-words" included

[UNDEFINED]  NaN [IF]  0e 0e f/ fconstant  NaN [THEN]
[UNDEFINED] +Inf [IF]  1e 0e f/ fconstant +Inf [THEN]
[UNDEFINED] -Inf [IF] -1e 0e f/ fconstant -Inf [THEN]

s" ttester" included
true verbose !
decimal

\ The ttester default for EXACT? is TRUE.  Uncomment the
\ following line if your system needs it to be FALSE:
\ SET-NEAR

variable #errors    0 #errors !

:noname  ( c-addr u -- )
(
Display an error message followed by the line that had the
error.
)
  1 #errors +! error1 ;  error-xt !

[UNDEFINED] \\ [IF]
  : \\  ( -- )  -1 parse 2drop BEGIN refill 0= UNTIL ; [THEN]

[UNDEFINED] pi [IF]
 0.3141592653589793238463E1 fconstant  pi
[THEN]
[UNDEFINED] -pi [IF]
 pi fnegate fconstant -pi
[THEN]

false [IF]
 0.7853981633974483096157E0 fconstant   pi/4
-0.7853981633974483096157E0 fconstant  -pi/4
 0.1570796326794896619231E1 fconstant   pi/2
-0.1570796326794896619231E1 fconstant  -pi/2
 0.4712388980384689857694E1 fconstant  3pi/2
 0.2356194490192344928847E1 fconstant  3pi/4
-0.2356194490192344928847E1 fconstant -3pi/4
[ELSE]
 pi 4e f/   fconstant   pi/4
-pi 4e f/   fconstant  -pi/4
 pi 2e f/   fconstant   pi/2
-pi 2e f/   fconstant  -pi/2
 pi/2 3e f* fconstant  3pi/2
 pi/4 3e f* fconstant  3pi/4
-pi/4 3e f* fconstant -3pi/4
[THEN]

verbose @ [IF]
:noname  ( -- fp.separate? )
  depth >r 1e depth >r fdrop 2r> = ;  execute
cr .( floating-point and data stacks )
[IF] .( *separate*) [ELSE] .( *not separate*) [THEN]
cr
[THEN]

testing normal values

\ Input x-y values taken from Ed, comp.lang.forth,
\ "Re: Ambiguity in FATAN2", 14Mar09, 17Mar09:
\   y   x              rad          deg
t{  0e  1e fatan2 ->   0e   }t    \   0
t{  1e  1e fatan2 ->   pi/4 }t    \  45
t{  1e  0e fatan2 ->   pi/2 }t    \  90
t{ -1e -1e fatan2 -> -3pi/4 }t    \ 135
t{  0e -1e fatan2 ->   pi   }t    \ 180
t{ -1e  1e fatan2 ->  -pi/4 }t    \ 225
t{ -1e  0e fatan2 ->  -pi/2 }t    \ 270
t{ -1e  1e fatan2 ->  -pi/4 }t    \ 315

testing Single UNIX 3 special values spec

\ ISO C / Single UNIX Specification Version 3:
\   http://www.unix.org/single_unix_specification/
\ Select "Topic", then "Math Interfaces", then "atan2()":
\   http://www.opengroup.org/onlinepubs/009695399/functions/atan2f.html

\ If y is +/-0 and x is < 0, +/-pi shall be returned.
t{  0e -1e fatan2 ->  pi }t
t{ -0e -1e fatan2 -> -pi }t

\ If y is +/-0 and x is > 0, +/-0 shall be returned.
t{  0e  1e fatan2 ->  0e }t
t{ -0e  1e fatan2 -> -0e }t

\ If y is < 0 and x is +/-0, -pi/2 shall be returned.
t{ -1e  0e fatan2 -> -pi/2 }t
t{ -1e -0e fatan2 -> -pi/2 }t

\ If y is > 0 and x is +/-0, pi/2 shall be returned.
t{  1e  0e fatan2 -> pi/2 }t
t{  1e -0e fatan2 -> pi/2 }t

testing Single UNIX 3 special values optional spec

\ Optional ISO C / single UNIX specs:

\ If either x or y is NaN, a NaN shall be returned.
t{ NaN  1e fatan2 -> NaN }t
t{  1e NaN fatan2 -> NaN }t
t{ NaN NaN fatan2 -> NaN }t

\ If y is +/-0 and x is -0, +/-pi shall be returned.
t{  0e -0e fatan2 ->  pi }t
t{ -0e -0e fatan2 -> -pi }t

\ If y is +/-0 and x is +0, +/-0 shall be returned.
t{  0e  0e fatan2 -> +0e }t
t{ -0e  0e fatan2 -> -0e }t

\ For finite values of +/-y > 0, if x is -Inf, +/-pi shall be returned.
t{  1e -Inf fatan2 ->  pi }t
t{ -1e -Inf fatan2 -> -pi }t

\ For finite values of +/-y > 0, if x is +Inf, +/-0 shall be returned.
t{  1e +Inf fatan2 -> +0e }t
t{ -1e +Inf fatan2 -> -0e }t

\ For finite values of x, if y is +/-Inf, +/-pi/2 shall be returned.
t{ +Inf  1e fatan2 ->  pi/2 }t
t{ +Inf -1e fatan2 ->  pi/2 }t
t{ +Inf  0e fatan2 ->  pi/2 }t
t{ +Inf -0e fatan2 ->  pi/2 }t
t{ -Inf  1e fatan2 -> -pi/2 }t
t{ -Inf -1e fatan2 -> -pi/2 }t
t{ -Inf  0e fatan2 -> -pi/2 }t
t{ -Inf -0e fatan2 -> -pi/2 }t

\ If y is +/-Inf and x is -Inf, +/-3pi/4 shall be returned.
t{ +Inf -Inf fatan2 ->  3pi/4 }t
t{ -Inf -Inf fatan2 -> -3pi/4 }t

\ If y is +/-Inf and x is +Inf, +/-pi/4 shall be returned.
t{ +Inf +Inf fatan2 ->  pi/4 }t
t{ -Inf +Inf fatan2 -> -pi/4 }t

verbose @ [IF]
cr .( #ERRORS: ) #errors @ . cr
[THEN]
