Another update from ingydotnet^djgoku

This commit is contained in:
Ingy döt Net 2015-11-18 06:14:39 +00:00
parent 91df62d461
commit 948b86eafa
7604 changed files with 108452 additions and 22726 deletions

View file

@ -0,0 +1,62 @@
begin
% Algol W only supplies sin, cos and arctan as standard. We can define %
% arcsin, arccos and tan functions using these. The standard functions %
% use radians so we also provide versions that use degrees %
% convert degrees to radians %
real procedure toRadians( real value x ) ; pi * ( x / 180 );
% convert radians to degrees %
real procedure toDegrees( real value x ) ; 180 * ( x / pi );
% tan of an angle in radians %
real procedure tan( real value x ) ; sin( x ) / cos( x );
% arcsin in radians %
real procedure arcsin( real value x ) ; arctan( x / sqrt( 1 - ( x * x ) ) );
% arccos in radians %
real procedure arccos( real value x ) ; arctan( sqrt( 1 - ( x * x ) ) / x );
% sin of an angle in degrees %
real procedure sinD( real value x ) ; sin( toRadians( x ) );
% cos of an angle in degrees %
real procedure cosD( real value x ) ; cos( toRadians( x ) );
% tan of an angle in degrees %
real procedure tanD( real value x ) ; tan( toRadians( x ) );
% arctan in degrees %
real procedure arctanD( real value x ) ; toDegrees( arctan( x ) );
% arcsin in degrees %
real procedure arcsinD( real value x ) ; toDegrees( arcsin( x ) );
% arccos in degrees %
real procedure arccosD( real value x ) ; toDegrees( arccos( x ) );
% test the procedures %
begin
real piOver4, piOver3, oneOverRoot2, root3Over2;
piOver3 := pi / 3; piOver4 := pi / 4;
oneOverRoot2 := 1.0 / sqrt( 2 ); root3Over2 := sqrt( 3 ) / 2;
r_w := 12; r_d := 5; r_format := "A"; s_w := 0; % set output format %
write( "PI/4: ", piOver4, " 1/root(2): ", oneOverRoot2 );
write();
write( "sin 45 degrees: ", sinD( 45 ), " sin pi/4 radians: ", sin( piOver4 ) );
write( "cos 45 degrees: ", cosD( 45 ), " cos pi/4 radians: ", cos( piOver4 ) );
write( "tan 45 degrees: ", tanD( 45 ), " tan pi/4 radians: ", tan( piOver4 ) );
write();
write( "arcsin( sin( pi/4 radians ) ): ", arcsin( sin( piOver4 ) ) );
write( "arccos( cos( pi/4 radians ) ): ", arccos( cos( piOver4 ) ) );
write( "arctan( tan( pi/4 radians ) ): ", arctan( tan( piOver4 ) ) );
write();
write( "PI/3: ", piOver4, " root(3)/2: ", root3Over2 );
write();
write( "sin 60 degrees: ", sinD( 60 ), " sin pi/3 radians: ", sin( piOver3 ) );
write( "cos 60 degrees: ", cosD( 60 ), " cos pi/3 radians: ", cos( piOver3 ) );
write( "tan 60 degrees: ", tanD( 60 ), " tan pi/3 radians: ", tan( piOver3 ) );
write();
write( "arcsin( sin( 60 degrees ) ): ", arcsinD( sinD( 60 ) ) );
write( "arccos( cos( 60 degrees ) ): ", arccosD( cosD( 60 ) ) );
write( "arctan( tan( 60 degrees ) ): ", arctanD( tanD( 60 ) ) );
end
end.

View file

@ -0,0 +1,18 @@
iex(61)> deg = 45
45
iex(62)> rad = :math.pi / 4
0.7853981633974483
iex(63)> :math.sin(deg * :math.pi / 180) == :math.sin(rad)
true
iex(64)> :math.cos(deg * :math.pi / 180) == :math.cos(rad)
true
iex(65)> :math.tan(deg * :math.pi / 180) == :math.tan(rad)
true
iex(66)> temp = :math.acos(:math.cos(rad))
0.7853981633974483
iex(67)> temp * 180 / :math.pi == deg
true
iex(68)> temp = :math.atan(:math.tan(rad))
0.7853981633974483
iex(69)> temp * 180 / :math.pi == deg
true

View file

@ -0,0 +1,63 @@
Calculate various trigonometric functions from the Fortran library.
INTEGER BIT(32),B,IP !Stuff for bit fiddling.
INTEGER ENUFF,I !Step through the test angles.
PARAMETER (ENUFF = 17) !A selection of special values.
INTEGER ANGLE(ENUFF) !All in whole degrees.
DATA ANGLE/0,30,45,60,90,120,135,150,180, !Here they are.
1 210,225,240,270,300,315,330,360/ !Thus check angle folding.
REAL PI,DEG2RAD !Special numbers.
REAL D,R,FD,FR,AD,AR !Degree, Radian, F(D), F(R), inverses.
PI = 4*ATAN(1.0) !SINGLE PRECISION 1·0.
DEG2RAD = PI/180 !Limited precision here too for a transcendental number.
Case the first: sines.
WRITE (6,10) ("Sin", I = 1,4) !Supply some names.
10 FORMAT (" Deg.",A7,"(Deg)",A7,"(Rad) Rad - Deg", !Ah, layout.
1 6X,"Arc",A3,"D",6X,"Arc",A3,"R",9X,"Diff")
DO I = 1,ENUFF !Step through the test values.
D = ANGLE(I) !The angle in degrees, in floating point.
R = D*DEG2RAD !Approximation, in radians.
FD = SIND(D); AD = ASIND(FD) !Functions working in degrees.
FR = SIN(R); AR = ASIN(FR)/DEG2RAD !Functions working in radians.
WRITE (6,11) INT(D),FD,FR,FR - FD,AD,AR,AR - AD !Results.
11 FORMAT (I4,":",3F12.8,3F13.7) !Ah, alignment with FORMAT 10...
END DO !On to the next test value.
Case the second: cosines.
WRITE (6,10) ("Cos", I = 1,4)
DO I = 1,ENUFF
D = ANGLE(I)
R = D*DEG2RAD
FD = COSD(D); AD = ACOSD(FD)
FR = COS(R); AR = ACOS(FR)/DEG2RAD
WRITE (6,11) INT(D),FD,FR,FR - FD,AD,AR,AR - AD
END DO
Case the third: tangents.
WRITE (6,10) ("Tan", I = 1,4)
DO I = 1,ENUFF
D = ANGLE(I)
R = D*DEG2RAD
FD = TAND(D); AD = ATAND(FD)
FR = TAN(R); AR = ATAN(FR)/DEG2RAD
WRITE (6,11) INT(D),FD,FR,FR - FD,AD,AR,AR - AD
END DO
WRITE (6,*) "...Special deal for 90 degrees..."
D = 90
R = D*DEG2RAD
FD = TAND(D); AD = ATAND(FD)
FR = TAN(R); AR = ATAN(FR)/DEG2RAD
WRITE (6,*) "TanD =",FD,"Atan =",AD
WRITE (6,*) "TanR =",FR,"Atan =",AR
Convert PI to binary...
PI = PI - 3 !I know it starts with three, and I need the fractional part.
BIT(1:2) = 1 !So, the binary is 11. something.
B = 2 !Two bits known.
DO I = 1,26 !For single precision, more than enough additional bits.
PI = PI*2 !Hoist a bit to the hot spot.
IP = PI !The integral part.
PI = PI - IP !Remove it from the work in progress.
B = B + 1 !Another bit bitten.
BIT(B) = IP !Place it.
END DO !On to the next.
WRITE (6,20) BIT(1:B) !Reveal the bits.
20 FORMAT (" Pi ~ ",2I1,".",66I1) !A known format.
WRITE (6,*) " = 11.00100100001111110110101010001000100001..." !But actually...
END !So much for that.

View file

@ -1 +1,4 @@
>,:(1&o. ; 2&o. ; 3&o.) (4%~o. 1), 180%~o. 45
(1&o. , 2&o. ,: 3&o.) (4 %~ o. 1) , 180 %~ o. 45
0.707107 0.707107
0.707107 0.707107
1 1

View file

@ -1 +1,4 @@
>,:([ , 180p_1&*)&.> (_1&o. ; _2&o. ; _3&o.) 0.5
([ ,. 180p_1&*) (_1&o. , _2&o. ,: _3&o.) 0.5
0.523599 30
1.0472 60
0.463648 26.5651

View file

@ -0,0 +1,10 @@
require 'trig'
(sin , cos ,: tan) (1p1 % 4), rfd 45
0.707107 0.707107
0.707107 0.707107
1 1
([ ,. dfr) (arcsin , arccos ,: arctan) 0.5
0.523599 30
1.0472 60
0.463648 26.5651

View file

@ -2,7 +2,7 @@
One common method that ensures enough accuracy in REXX is specifying
more precision (via NUMERIC DIGITS nnn) than is needed, and then
displaying the number of digits that are desired, or the number(s)
could be re-normalized using the FORMAT bif.
could be re-normalized using the FORMAT BIF.
The technique used (below) is to set the numeric digits ten higher
than the desired digits, as specified by the SHOWDIGS variable.

View file

@ -2,6 +2,7 @@
showdigs=30 /*show only 30 digits of number. */
numeric digits showdigs+10 /*DIGITS default is 9, but use */
/*extra digs to prevent rounding.*/
say 'Using' showdigs 'decimal digits precision.'; say
do j=-180 to +180 by 15 /*let's just do a half-Monty. */
@ -22,7 +23,7 @@ say; do k=-1 to +1 by 1/2 /*keep the Arc-functions happy. */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────subroutines─────────────────────────*/
Asin: procedure; parse arg x 1 z 1 o 1 p; a=abs(x); aa=a*a
if a>1 then call $81r -1,1,x,"ASIN" /*X arg is out of range.*/
if a>1 then call AsinErr x /*X arg is out of range.*/
if a>=sqrt(2)*.5 then return sign(x)*acos(sqrt(1-aa), '-ASIN')
do j=2 by 2 until p=z; p=z; o=o*aa*(j-1)/j; z=z+o/(j+1); end
return z /* [↑] compute until no noise.*/
@ -30,56 +31,54 @@ Asin: procedure; parse arg x 1 z 1 o 1 p; a=abs(x); aa=a*a
Atan: procedure; parse arg x; if abs(x)=1 then return pi() * .25 * sign(x)
return Asin(x/sqrt(1+x*x) )
cos: procedure; parse arg x; x=r2r(x); a=abs(x); numeric fuzz min(9,digits()-9)
if a=pi then return -1; if a=pi*.5 | a=pi*2 then return 0
pi3=pi/3; if a=pi3 then return .5; if a=2*pi3 then return -.5
return .sinCos(1,1,-1)
cos: procedure; parse arg x; x=r2r(x); a=abs(x); hpi=pi*.5
numeric fuzz min(6,digits()-3); if a=pi() then return -1
if a=hpi | a=hpi*3 then return 0; if a=pi()/3 then return .5
if a=pi()*2/3 then return -.5; return .sinCos(1,-1)
sin: procedure; parse arg x; x=r2r(x); numeric fuzz $fuzz(5, 3)
if x=pi*.5 then return 1; if x==pi*1.5 then return -1
if abs(x)=pi | x=0 then return 0; return .sinCos(x, x, +1)
sin: procedure; parse arg x; x=r2r(x); numeric fuzz $fuzz(5, 3)
if x=pi*.5 then return 1; if x==pi*1.5 then return -1
if abs(x)=pi | x=0 then return 0; return .sinCos(x,1)
.sinCos: parse arg z,_,i; x=x*x
do k=2 by 2 until p=z; p=z; _=-_*x/(k*(k+i)); z=z+_; end /*k*/
.sinCos: parse arg z 1 _,i; q=x*x
do k=2 by 2 until p=z; p=z; _=-_*q/(k*(k+i)); z=z+_; end /*k*/
return z
sqrt: procedure; parse arg x,i; if x=0 then return 0; d=digits(); m.=11
if x<0 then i='i'; numeric digits 11; numeric form; p=d+d%4+2
parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g*.5'E'_%2
do j=0 while p>9; m.j=p; p=p%2+1; end /*j*/
do k=j+5 to 0 by -1; if m.k>11 then numeric digits m.k
g=.5*(g+x/g); end /*k*/; numeric digits d; return g/1
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); i=; m.=9
numeric digits 9; numeric form; h=d+6; if x<0 then do; x=-x; i='i'; end
parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g*.5'e'_%2
do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/
numeric digits d; return (g/1)i /*make complex if X < 0.*/
e: e=2.7182818284590452353602874713526624977572470936999595749669676277240766303535
return e /*Note: the actual E subroutine returns E's accuracy that */
/*matches the current NUMERIC DIGITS, up to 1 million digits.*/
/*If more than 1 million digits are required, be patient. */
return e /*Note: the actual E subroutine returns E's accuracy that */
/*matches the current NUMERIC DIGITS, up to 1 million digits.*/
exp: procedure; parse arg x; ix=x%1; if abs(x-ix)>.5 then ix=ix+sign(x); x=x-ix
z=1; _=1; w=z; do j=1; _=_*x/j; z=(z+_)/1; if z==w then leave; w=z; end
if z\==0 then z=e()**ix*z; return z
pi: pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862
return pi /*Note: the actual PI subroutine returns PI's accuracy that */
/*matches the current NUMERIC DIGITS, up to 1 million digits.*/
/*John Machin's formula is used for calculating more digits. */
/*If more than 1 million digits are required, be patient. */
return pi /*Note: the actual PI subroutine returns PI's accuracy that */
/*matches the current NUMERIC DIGITS, up to 1 million digits.*/
/*John Machin's formula is used for calculating more digits. */
$fuzz: return min(arg(1), max(1, digits() - arg(2) ) )
Acos: procedure; parse arg x; if x<-1|x>1 then call AcosErr; return .5*pi()-Asin(x)
Acos: procedure; parse arg x; if x<-1|x>1 then call AcosErr; return pi()*.5-Asin(x)
AcosD: return r2d(Acos(arg(1)))
AsinD: return r2d(Asin(arg(1)))
cosD: return cos(d2r(arg(1)))
sinD: return sin(d2r(d2d(arg(1))))
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)/_
tanD: return tan(d2r(arg(1)))
d2d: return arg(1) // 360 /*normalize degrees►1 unit circle. */
d2r: return r2r(d2d(arg(1))*pi() /180) /*convert degrees ──► radians. */
r2d: return d2d((arg(1)*180 /pi())) /*convert radians ──► degrees. */
r2r: return arg(1) // (pi()*2) /*normalize radians ──►a unit circle*/
d2d: return arg(1) // 360 /*normalize degrees ──► a unit circle*/
d2r: return r2r(d2d(arg(1))*pi() / 180) /*convert degrees ──► radians. */
r2d: return d2d((arg(1)*180 / pi())) /*convert radians ──► degrees. */
r2r: return arg(1) // (pi()*2) /*normalize radians ──► a unit circle*/
show: return left(left('',arg(1)>=0)format(arg(1),,showdigs)/1,showdigs)
tellErr: say; say '*** error! ***'; say; say arg(1); say; exit 13
tanErr: call tellErr 'tan('||x") causes division by zero, X=" || x
tellErr: say; say '*** error! ***'; say; say arg(1); say; exit 13
tanErr: call tellErr 'tan(' || x") causes division by zero, X=" || x
AsinErr: call tellErr 'Asin(x), X must be in the range of -1 +1, X=' || x
AcosErr: call tellErr 'Acos(x), X must be in the range of -1 +1, X=' || x
sqrtErr: call tellErr "sqrt(x), X can't be negative, X=" || x

View file

@ -0,0 +1,30 @@
Functions that are not included here are (among others):
some of the usual higher-math functions normally associated with trig
functions: POW, GAMMA, LGGAMMA, ERF, ERFC, ROOT, ATAN2,
LOG (LN), LOG2, LOG10, and all of the
hyperbolic trigonometric functions and their inverses (too many to list
here),
angle conversions/normalizations: degrees/radians/grads/mils:
a circle 2 pi radians 360 degrees 400 grads 6400 mils.
Some of the other trigonometric functions are (hyphens added intentionally):
CHORD
COT (co-tangent)
CSC (co-secant)
CVC (co-versed cosine)
CVS (co-versed sine)
CXS (co-exsecant)
HAC (haver-cosine)
HAV (haver-sine
SEC (secant)
VCS (versed cosine or ver-cosine)
VSN (versed sine or ver-sine)
XCS (ex-secant)
COS/SIN/TAN cardinal (damped COS/SIN/TAN functions)
COS/SIN integral
and all pertinent inverses of the above functions (AVSN, ACVS, ···).

View file

@ -1,13 +1,19 @@
deg = 45.0
' Run BASIC works in radians. Convert deg and rad as shown.
d2r = ACS(-1)/180
rad = deg*d2r
r2d = 180/ACS(-1)
' Find these three ratios: Sine, Cosine, Tangent. (These ratios have NO units.)
print "Sine: ";SIN(rad);" ";SIN(deg*d2r)
print "Cosine: ";COS(rad);" ";COS(deg*d2r)
print "Tangent: ";TAN(rad);" ";TAN(deg*d2r)
print
print "Arcsine: ";ASN(SIN(rad));" radians, (or ";ASN(SIN(deg*d2r))*r2d;" degrees)"
print "Arccosine: ";ACS(COS(rad));" radians, (or ";ACS(COS(deg*d2r))*r2d;" degrees)"
print "Arctangent: ";ATN(TAN(rad));" radians, (or ";ATN(TAN(deg*d2r))*r2d;" degrees)"
deg = 45.0
' Run BASIC works in radians; so, first convert deg to rad as shown in next line.
rad = deg * (atn(1)/45)
print "Ratios for a "; deg; " degree angle, (or "; rad; " radian angle.)"
print "Sine: "; SIN(rad)
print "Cosine: "; COS(rad)
print "Tangent: "; TAN(rad)
print "Inverse Functions - - (Using above ratios)"
' Now, use those ratios to work backwards to show their original angle in radians.
' Also, use this: rad / (atn(1)/45) = deg (To change radians to degrees.)
print "Arcsine: "; ASN(SIN(rad)); " radians, (or "; ASN(SIN(rad))/(atn(1)/45); " degrees)"
print "Arccosine: "; ACS(COS(rad)); " radians, (or "; ACS(COS(rad))/(atn(1)/45); " degrees)"
print "Arctangent: "; ATN(TAN(rad)); " radians, (or "; ATN(TAN(rad))/(atn(1)/45); " degrees)"
' This code also works in Liberty BASIC.
' The above (atn(1)/45) = approx .01745329252