Atan?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
misol101
Posts: 475
Joined: 02 May 2016 18:20

Atan?

#1 Post by misol101 » 09 Jun 2020 12:23

Anybody happen to be sitting on an atan or atan2 batch macro?

This is the best I got at the moment:

Code: Select all

atan2.js:
WScript.Echo(Math.floor(Math.atan2(WScript.Arguments.Item(0),WScript.Arguments.Item(1))/Math.PI*180))

batch script:
cscript //nologo //e:javascript "atan2.js" !TXE! !TZE! >res.txt
set /p ERY=<res.txt
Not good for realtime graphics.

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Atan?

#2 Post by ShadowThief » 09 Jun 2020 12:54

Just about everything I could find online for how to calculate arctangent boiled down to "press the atan button on your calculator." Further digging ended up suggesting lookup tables and something called https://en.wikipedia.org/wiki/CORDIC, which I'm going to have to look into some more.

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Atan?

#3 Post by misol101 » 09 Jun 2020 17:03

Here is a crude estimation of atan, based on the second answer at https://math.stackexchange.com/question ... roximation. I also had to handle the case where y is 0.

This could be improved upon in many ways, but it is acceptable for what I needed it for.

Code: Select all

@echo off
rem Calculates atan(x/y) in whole degrees 
setlocal EnableDelayedExpansion
set /a x=%1, y=%2, mul=1,base=0, negmul=1
if !y! neq 0 (
	set /a "a=(x*100)/y"
	if !a! lss 0 set /a negmul=-1, a=-a
	if !a! gtr 100 set /a "a=10000/a, mul=-1, base=90"

	set /a "r=(a*(4500-1566*(a-100)/100))/10000"
	set /a "r=(base+mul*r)*negmul"
) else (
	set /a r=90
	if !x! lss 0 set /a r=-90
	if !x! equ 0 set /a r=0
)	
echo %r%

T3RRY
Posts: 250
Joined: 06 May 2020 10:14

Re: Atan?

#4 Post by T3RRY » 09 Jun 2020 21:54

Here's a (golfed) marco conversion

Code: Select all

@Echo off 
Setlocal DisableDelayedExpansion

    (Set LF=^


    %= Above Empty lines Required =%)

    Set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

::: usage: %atan%{X val}{Y val}{Return var}
Set atan=For %%n in (1 2)Do if %%n==2 (%\n%
	For /F "tokens=1,2,3 Delims={}" %%x in ("!xyz!")Do (%\n%
		set/a "m=1,_=0,n=1"%\n%
		if not %%y==0 (%\n%
			set/a "a=(%%x*100)/%%y"%\n%
			if !a! lss 0 set/a "n=-1,a=-!a!"%\n%
			if !a! gtr 100 set/a "a=10000/a,m=-1,_=90"%\n%
			set/a "r=(!a!*(4500-1566*(!a!-100)/100))/10000"%\n%
			set/a "r=(!_!+!m!*!r!)*!n!"%\n%
		) else (%\n%
			set/a r=90%\n%
			if %%x lss 0 set/a r=-90%\n%
			if %%x equ 0 set/a r=0%\n%
		)%\n%
	For %%o in (!r!)Do (Endlocal ^& Set "%%z=%%o")%\n%
	)%\n%
) Else Setlocal EnabledelayedExpansion ^& set xyz=

%atan%{20}{1}{r.}
%atan%{79}{20}{r.2}
%atan%{79}{0}{r.3}
set r.
pause
If decimal places are required, the old trick of suffixing the number of digits in each value of the operations with 0 and 'fixing' the result with substring modification to reinsert the decimal point should do the trick

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Atan?

#5 Post by Aacini » 11 Jun 2020 19:59

I think this is the fastest method to evaluate ATAN with good precision:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

rem CORDIC reference:  https://bsvi.ru/uploads/CORDIC--_10EBA/cordic.pdf

rem Angles: 45.0000 22.5000 11.2500 5.6250 2.8125 1.4062 0.7031
rem Values below are: tan(angle) * 10000
set "TanTable=10000 4142 1989 985 491 246 123 " & rem NOTE the last space!

rem Values for test
rem Angles:     85    80    75    70    60     45    30    20    15    10     5
for %%t in (114300 56713 37320 27475 17321  10000  5774  3640  2679  1763   875) do (
   set /P "=atan(angle)*10000=%%t, " < nul

   rem The long SET command below calculate ATAN(%%t^) based on TanTable above
   set /A "Y=%%t, x=10000, curAngle=450000, sumAngle=0,  sign=(Y>>31)|1, Xnew=X+sign*Y*(Tan=%TanTable: =)/10000, Y-=sign*X*Tan/10000, X=Xnew, sumAngle+=sign*curAngle, curAngle>>=1,  sign=(Y>>31)|1, Xnew=X+sign*Y*(Tan=%0),  sumAngle=(sumAngle+5000)/10000"

   echo Angle = !sumAngle!
)


This code uses CORDIC method with 7 elements. If you want more precision you may increase the number of elements and/or the factor used to multiply tangent values (10000 in this case). As complement, if less precision is enough for you, you may diminish the number of elements and/or the 10000 factor, so the method run faster.

You may also use shorter variable names, so the expression be shorter and run faster. The variable names are the same used in the CORDIC description.

Antonio

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Atan?

#6 Post by misol101 » 12 Jun 2020 01:40

Thanks to both of you!

Post Reply