Horizontal sundial calculations: Difference between revisions

Content added Content deleted
(→‎{{header|Kotlin}}: Updated example see https://github.com/dkandalov/rosettacode-kotlin for details)
m (→‎{{header|REXX}}: added/changed wording in the REXX section header, added/changed comments and whitespace, optimized the ATAN function.)
Line 2,030: Line 2,030:


=={{header|REXX}}==
=={{header|REXX}}==
REXX doesn't have the usual trig functions, nor for that matter, a SQRT (square root) function, so these as well as PI were added to this program.
The REXX language doesn't have the usual trigonometric functions, nor for that matter, a   '''sqrt'''   (square root) function,
<br>so these as well as &nbsp; '''pi''' &nbsp; were added to this program.


No attempt was made to explain the inner workings of the trigonometric functions.
No attempt was made to explain the inner workings of the trigonometric functions.
<lang rexx>/*REXX program displays: hour, sun hour angle, dial hour line angle, 6am ───► 6pm. */
<lang rexx>/*REXX program displays: hour, sun hour angle, dial hour line angle, 6am ───► 6pm. */
numeric digits 60 /*better digit overkill then underkill.*/
numeric digits 60 /*in case sundial is in polar regions. */
parse arg lat lng mer . /*obtain optional arguments from the CL*/
parse arg lat lng mer . /*obtain optional arguments from the CL*/
/* ┌───────────◄ None specified? Then use the default*/
/* ┌───────────◄ None specified? Then use the default*/
Line 2,042: Line 2,043:
if lng=='' | lng=="," then lng= -150.5 /* " " " " " " */
if lng=='' | lng=="," then lng= -150.5 /* " " " " " " */
if mer=='' | mer=="," then mer= -150 /* " " " " " " */
if mer=='' | mer=="," then mer= -150 /* " " " " " " */
L=max(length(lat), length(lng), length(mer) ) /*find maximum length of three numbers.*/
say ' latitude:' right(lat, L) /*display the latitude to the terminal*/
say ' longitude:' right(lng, L) /* " " longitude " " " */
say ' legal meridian:' right(mer, L) /* " legal meridian " " " */
sineLat=sin( d2r(lat) ) /*calculate sine of (radian) latitude. */
sineLat=sin( d2r(lat) ) /*calculate sine of (radian) latitude. */
w1=max(length('hour') , length("midnight")) + 2 /*compute the max hour width. */
w1=max( length('hour' ), length("midnight" )) + 2 /*compute the max hour width.*/
w2=max(length('sun hour') , length("angle")) + 2 /* " " " angle " */
w2=max( length('sun hour' ), length("angle" )) + 2 /* " " " angle " */
w3=max(length('dial hour'), length("line angle")) + 2 /* " " " lineº " */
w3=max( length('dial hour'), length("line angle")) + 2 /* " " " lineº " */
L=max(length(lat), length(lng), length(mer) ) /*find maximum length of three numbers.*/
indent=left('', 30) /*make the presentation a bit prettier.*/
say ' latitude:' right(lat, L) /*display the latitude to the terminal*/
say indent center(' ',w1) center("sun hour",w2) center('dial hour' ,w3)
say ' longitude:' right(lng, L) /* " " longitude " " " */
say indent center('hour',w1) center("angle" ,w2) center('line angle',w3)
call sep /*add a separator line for the eyeballs*/
say ' legal meridian:' right(mer, L) /* " legal meridian " " " */
do h=-6 to 6 /*Okey dokey then, now let's get busy.*/
indent=left('', 30) /*make prettier: indented presentation.*/
say indent center(' ', w1) center("sun hour", w2) center('dial hour' , w3)
say indent center('hour', w1) center("angle" , w2) center('line angle', w3)
call sep /*to help a one-eyed pirate's eyeball. */
do h=-6 to 6 /*Okey dokey then, now let's show stuff*/
select
select
when abs(h)==12 then hc='midnight' /*Holy smokes! Above the arctic circle.*/
when abs(h)==12 then hc='midnight' /*Holy smokes! Above the arctic circle.*/
when h <0 then hc=-h 'am' /*convert da hour for human beans (sic)*/
when h <0 then hc= -h 'am' /*convert da hour for human beans (sic)*/
when h==0 then hc='noon' /* ··· easier to understand now. */
when h==0 then hc='noon' /* ··· easier to understand now. */
when h >0 then hc=h 'pm' /* ··· even more meaningful. */
when h >0 then hc= h 'pm' /* ··· even more meaningful. */
end /*select*/
end /*select*/
hra=15 * h - lng + mer /*calculate sun hour angle (in degrees)*/
hra=15 * h - lng + mer /*calculate sun hour angle (in degrees)*/
hla=r2d(Atan(sineLat * tan( d2r(hra)))) /*this is the heavy lifting calculation*/
hla=r2d( Atan(sineLat * tan( d2r(hra)))) /*this is the heavy lifting calculation*/
say indent center(hc, w1) right(format(hra, ,1), w2) right(format(hla, ,1), w3)
say indent center(hc, w1) right(format(hra, ,1), w2) right(format(hla, ,1), w3)
end /*h*/
end /*h*/
call sep /*to help a one-eyed pirate's eyeball. */
call sep
exit /*stick a fork in it, we're all done. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
Line 2,073: Line 2,074:
r2d: return d2d( (arg(1) * 180 / pi() ) ) /*convert radians ──► degrees. */
r2d: return d2d( (arg(1) * 180 / pi() ) ) /*convert radians ──► degrees. */
r2r: return arg(1) //(pi() * 2) /*normalize radians ──► a unit circle. */
r2r: return arg(1) //(pi() * 2) /*normalize radians ──► a unit circle. */
sep: say indent copies('═', w1) copies("═",w2) copies('═',w3); return
sep: say indent copies('═', w1) copies("═", w2) copies('═', w3); return
tan: procedure; parse arg x; _=cos(x); if _=0 then call tanErr; return sin(x)/_
tan: procedure; parse arg x; _=cos(x); if _=0 then call tanErr; return sin(x)/_
tellErr: say; say '*** error ***'; say; say arg(1); say; exit 13
tellErr: say; say '*** error ***'; say; say arg(1); say; exit 13
Line 2,080: Line 2,081:
tanErr: call tellErr 'tan(' || x") causes division by zero, X=" x
tanErr: call tellErr 'tan(' || x") causes division by zero, X=" x
Acos: procedure; arg x; if x<-1 | x>1 then call AcosErr; return .5 * pi() - Asin(x)
Acos: procedure; arg x; if x<-1 | x>1 then call AcosErr; return .5 * pi() - Asin(x)
Atan: procedure; parse arg x; if abs(x)=1 then return pi()/4*x; return Asin(x/sqrt(1+x*x))
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
Asin: procedure; parse arg x; if x<-1 | x>1 then call AsinErr; s=x*x
Asin: procedure; parse arg x; if x<-1 | x>1 then call AsinErr; s=x*x
if abs(x)>=sqrt(2)*.4 then return sign(x) * Acos(sqrt(1-s)); z=x; o=x; p=z
if abs(x)>=sqrt(2)*.4 then return sign(x) * Acos(sqrt(1-s)); z=x; o=x; p=z
do j=2 by 2; o=o*s*(j-1)/j; z=z+o/(j+1); if z=p then leave; p=z; end; return z
do j=2 by 2; o=o*s*(j-1)/j; z=z+o/(j+1); if z=p then leave; p=z; end; return z
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
Atan: procedure; arg x; if abs(x)=1 then return pi() / 4 * sign(x)
sin: procedure; parse arg x; x=r2r(x); numeric fuzz min(5, digits() - 3)
return Asin(x / sqrt(1 + x*x) )
if abs(x)=pi() then return ; return .sinCos(x,x,1)
/*──────────────────────────────────────────────────────────────────────────────────────*/
sin: procedure; arg x; x=r2r(x); numeric fuzz min(5, digits() - 3)
if abs(x)=pi() then return 0; return .sinCos(x,x,1)
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
cos: procedure; parse arg x; x=r2r(x); a=abs(x); hpi=pi*.5
cos: procedure; parse arg x; x=r2r(x); a=abs(x); hpi=pi*.5
Line 2,096: Line 2,095:
if a=pi() * 2 / 3 then return -.5; return .sinCos(1,1,-1)
if a=pi() * 2 / 3 then return -.5; return .sinCos(1,1,-1)
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
.sinCos: parse arg z,_,i; x=x*x; p=z
.sinCos: parse arg z,_,i; x=x*x; p=z
do k=2 by 2; _= -_ * x / (k*(k+i)); z=z+_; if z=p then leave; p=z; end; return z
do k=2 by 2; _= -_*x/(k*(k+i)); z=z+_; if z=p then leave; p=z; end; return z
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); numeric digits; h=d+6
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); numeric digits; h=d+6