# New Ticket Created by Cory Spencer # Please include the string: [perl #64860] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=64860 >
The attached patch moves the trigonometry functions into setting/Num.pm from builtins/math.pir. Trig functions are now exported from the Num package when requested via the :Trig tag: use Num :Trig; Degrees, gradians and revolutions are now also supported (though tests for these still need to be added to the spectest suite).
>From 70ea2ec0c81b19ecbb768bff4976ff70b8e6e199 Mon Sep 17 00:00:00 2001 From: Cory Spencer <cspen...@sprocket.org> Date: Sun, 19 Apr 2009 12:31:28 -0700 Subject: [PATCH] Squashed commit of the following: commit 268fc3340aba0486bb401b98faf44ae155df6518 Author: Cory Spencer <cspen...@sprocket.org> Date: Sun Apr 19 10:26:56 2009 -0700 Moved the trigonometry functions into setting/Num.pm from builtins/math.pir Trig functions are now exported from the Num package when requested via the :Trig tag: use Num :Trig; Degrees, gradians and revolutions are now also supported (though tests for these need to be added to the spectest suite). --- src/builtins/math.pir | 343 ------------------------------------------------ src/setting/Any-num.pm | 11 ++ src/setting/Num.pm | 310 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 318 insertions(+), 346 deletions(-) diff --git a/src/builtins/math.pir b/src/builtins/math.pir index 476f456..2416c31 100644 --- a/src/builtins/math.pir +++ b/src/builtins/math.pir @@ -242,349 +242,6 @@ you I<must> call C<srand()> yourself if you wish to specify a deterministic seed =cut - -=head1 Math::Trig - -=head2 Functions - -=over 4 - -=cut - - -## TODO: figure out what to get working, in order to uncomment the following -## .namespace [ 'Math'; 'Trig' ] - - -=item I<Standard Trig Functions> - - our Num multi Num::func ( Num $x : :$base = 'radians' ) - our Num multi Math::Trig::func ( Num $x, :$base = 'radians' ) - -where I<func> is one of: -sin, cos, tan, asin, acos, atan, sec, cosec, cotan, asec, acosec, -acotan, sinh, cosh, tanh, asinh, acosh, atanh, sech, cosech, cotanh, -asech, acosech, acotanh. - -Performs the various trigonometric functions. - -Option C<:$base> is used to declare how you measure your angles. -Given the value of an arc representing a single full revolution. - - $base Result - ---- ------- - /:i ^r/ Radians (2*pi) - /:i ^d/ Degrees (360) - /:i ^g/ Gradians (400) - Num Units of 1 revolution. - -Note that module currying can be used within a lexical scope to specify -a consistent base so you don't have to supply it with every call: - - my module Trig ::= Math::Trig.assuming(:base<degrees>); - -This overrides the default of "radians". - -B<NOTE:> These only work with radians so far. - -=item atan - - our Num multi Math::Trig::atan2 ( Num $y, Num $x = 1 : Num :$base ) - -This second form of C<atan> computes the arctangent of $y/$x, and takes -the quadrant into account. Otherwise behaves as other trigonometric functions. - -[Note: changed atan back to atan2, or the default $x = 1 will confuse MMD. -The other alternative would be to remove the default. --law] - -=cut - - -## XXX: conjectural as Rakudo subs do not support adverbs yet -.sub 'sin' - .param num a - .param string base :optional :named('base') - .param int has_base :opt_flag - .local num converter - converter = 1 - unless has_base goto doit - unless base goto doit - $S0 = base - downcase $S0 - $S1 = substr $S0, 0, 1 - $I0 = index 'rdg123456789', $S1 - if $I0 == -1 goto err_unrecognized_base - if $I0 == 0 goto doit - converter = atan 1 - if $I0 == 1 goto deg - if $I0 == 2 goto grad - user_defined: - $N0 = $S0 - $N0 /= 8 - converter /= $N0 - goto doit - deg: - converter /= 45 - goto doit - grad: - converter /= 50 - doit: - a *= converter - - body: - $N0 = sin a - .return ($N0) - - err_unrecognized_base: - $S1 = "sin: unrecognized base '" - $S1 .= $S0 - $S1 .= "'" - .tailcall 'die'($S1) -.end - - -.sub 'cos' - .param num a - $N0 = cos a - .return ($N0) -.end - - -.sub 'tan' - .param num a - $N0 = tan a - .return ($N0) -.end - - -.sub 'asin' - .param num a - $N0 = asin a - .return ($N0) -.end - - -.sub 'acos' - .param num a - $N0 = acos a - .return ($N0) -.end - - -.sub 'atan' - .param num a - $N0 = atan a - .return ($N0) -.end - - -.sub 'atan2' - .param num a - .param num b :optional - .param int has_b :opt_flag - if has_b goto have_b - b = 1 - have_b: - $N0 = atan a, b - .return ($N0) -.end - - -.sub 'cosec' - .param num a - $N0 = sin a - $N0 = 1 / $N0 - .return ($N0) -.end - - -.sub 'sec' - .param num a - $N0 = sec a - .return ($N0) -.end - - -.sub 'cotan' - .param num a - $N0 = tan a - $N0 = 1 / $N0 - .return ($N0) -.end - - -## acosec(A) = atan(A / sqrt(A * A - 1)) + (sign(A) - 1) * (2 * atan(1)) -.sub 'acosec' - .param num a - $N0 = a ** 2 - $N0 -= 1 - $N0 = a / $N0 - $N0 = atan $N0 - $N1 = 'sign'(a) - $N1 -= 1 - $N1 *= 2 - $N2 = atan 1 - $N1 *= $N2 - $N0 += $N1 - .return ($N0) -.end - - -## asec(A) = atan(A / sqrt(A * A - 1)) + sign(A - 1) * (2 * atan(1)) -.sub 'asec' - .param num a - $N0 = a ** 2 - $N0 -= 1 - $N0 = a / $N0 - $N0 = atan $N0 - $N1 = a - 1 - $N1 = 'sign'($N1) - $N1 *= 2 - $N2 = atan 1 - $N1 *= $N2 - $N0 += $N1 - .return ($N0) -.end - - -## acotan(A) = atan(A) + 2 * atan(1) -.sub 'acotan' - .param num a - $N0 = atan 1 - $N0 *= 2 - $N1 = atan a - $N0 += $N1 - .return ($N0) -.end - - -.sub 'sinh' - .param num a - $N0 = sinh a - .return ($N0) -.end - - -.sub 'cosh' - .param num a - $N0 = cosh a - .return ($N0) -.end - - -.sub 'tanh' - .param num a - $N0 = tanh a - .return ($N0) -.end - - -## asinh(A) = ln(A + sqrt(A * A + 1)) -.sub 'asinh' - .param num a - $N0 = a * a - $N0 += 1 - $N0 = sqrt $N0 - a += $N0 - a = ln a - .return (a) -.end - - -## acosh(A) = ln(A + sqrt(A * A - 1)) -.sub 'acosh' - .param num a - $N0 = a * a - $N0 -= 1 - $N0 = sqrt $N0 - a += $N0 - a = ln a - .return (a) -.end - - -## atanh(A) = ln((1 + A) / (1 - A)) / 2 -.sub 'atanh' - .param num a - $N0 = 1 - a - a += 1 - a /= $N0 - a = ln a - a /= 2 - .return (a) -.end - - -## cosech(A) = 1 / sinh(A) -.sub 'cosech' - .param num a - a = sinh a - a = 1 / a - .return (a) -.end - - -.sub 'sech' - .param num a - $N0 = sech a - .return ($N0) -.end - - -## cotanh(A) = 1 / tanh(A) -.sub 'cotanh' - .param num a - a = tanh a - a = 1 / a - .return (a) -.end - - -## acosech(A) = ln((sign(A) * sqrt(A * A + 1) + 1) / A) -.sub 'acosech' - .param num a - $N0 = a * a - $N0 += 1 - $N0 = sqrt $N0 - $N1 = 'sign'(a) - $N0 *= $N1 - $N0 += 1 - $N0 = ln $N0 - $N0 /= a - .return ($N0) -.end - - -## asech(A) = ln((sqrt(-A * A + 1) + 1) / A) -.sub 'asech' - .param num a - $N0 = neg a - $N0 *= a - $N0 += 1 - $N0 = sqrt $N0 - $N0 += 1 - $N0 /= a - $N0 = ln $N0 - .return ($N0) -.end - - -## acotanh(A) = ln((A + 1) / (A - 1)) / 2 -.sub 'acotanh' - .param num a - $N0 = a - 1 - a += 1 - a /= $N0 - a = ln a - a /= 2 - .return (a) -.end - - -=back - -=cut - # Local Variables: # mode: pir # fill-column: 100 diff --git a/src/setting/Any-num.pm b/src/setting/Any-num.pm index 396e6e1..e5a378e 100644 --- a/src/setting/Any-num.pm +++ b/src/setting/Any-num.pm @@ -45,6 +45,17 @@ class Any is also { %r = box $I0 } } + + # Used by the :Trig subs and methods in the Int and Num classes. + multi method !convert-to-radians($base) { + given $base { + when /:i ^d/ { self * pi/180 } # Convert from degrees. + when /:i ^g/ { self * pi/200 } # Convert from gradians. + when /:i ^r/ { self } # Convert from radians. + when Num { self * 2 * pi } # Convert from revolutions. + default { die "Unable to convert to base: $base" } + } + } } our Int sub rand (*...@args) { diff --git a/src/setting/Num.pm b/src/setting/Num.pm index 21ea8de..b8a4e5c 100644 --- a/src/setting/Num.pm +++ b/src/setting/Num.pm @@ -1,7 +1,311 @@ class Num is also { - multi method perl() { + our Num multi method acos($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = acos $N0 + %r = box $N1 + } + } + + our Num multi method acosh($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = $N0 * $N0 + $N1 -= 1 + $N1 = sqrt $N1 + $N0 += $N1 + $N0 = ln $N0 + %r = box $N0 + } + } + + our Num multi method acosec($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = $N0 ** 2 + $N1 -= 1 + $N1 = $N0 / $N1 + $N1 = atan $N1 + $N2 = 'sign'($N0) + $N2 -= 1 + $N2 *= 2 + $N3 = atan 1 + $N2 *= $N3 + $N1 += $N2 + %r = box $N1 + } + } + + our Num multi method acosech($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = $N0 * $N0 + $N1 += 1 + $N1 = sqrt $N1 + $N2 = 'sign'($N0) + $N1 *= $N2 + $N1 += 1 + $N1 = ln $N1 + $N1 /= $N0 + %r = box $N1 + } + } + + our Num multi method acotan($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = atan 1 + $N1 *= 2 + $N2 = atan $N0 + $N1 += $N2 + %r = box $N1 + } + } + + our Num multi method acotanh($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = $N0 - 1 + $N0 += 1 + $N0 /= $N0 + $N0 = ln $N0 + $N0 /= 2 + %r = box $N0 + } + } + + our Num multi method asec($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = $N0 ** 2 + $N1 -= 1 + $N1 = $N0 / $N1 + $N1 = atan $N1 + $N2 = $N0 - 1 + $N2 = 'sign'($N2) + $N2 *= 2 + $N3 = atan 1 + $N2 *= $N3 + $N1 += $N2 + %r = box $N1 + } + } + + our Num multi method asech($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = neg $N0 + $N1 *= $N0 + $N1 += 1 + $N1 = sqrt $N1 + $N1 += 1 + $N1 /= $N0 + $N1 = ln $N1 + %r = box $N1 + } + } + + our Num multi method asin($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = asin $N0 + %r = box $N1 + } + } + + our Num multi method asinh($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = $N0 * $N0 + $N1 += 1 + $N1 = sqrt $N1 + $N0 += $N1 + $N0 = ln $N0 + %r = box $N0 + } + } + + our Num multi method atan($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = atan $N0 + %r = box $N1 + } + } + + our Num multi method atan2(Num $x = 1, $base = 'radians') is export(:Trig) { + my $y = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$y" + $N0 = $P0 + $P1 = find_lex "$x" + $N1 = $P1 + $N2 = atan $N0, $N1 + %r = box $N2 + } + } + + our Num multi method atanh($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = 1 - $N0 + $N0 += 1 + $N0 /= $N1 + $N0 = ln $N0 + $N0 /= 2 + %r = box $N0 + } + } + + our Num multi method cos($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = cos $N0 + %r = box $N1 + }; + } + + our Num multi method cosh($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = cosh $N0 + %r = box $N1 + } + } + + our Num multi method cosec($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = sin $N0 + $N1 = 1 / $N1 + %r = box $N1 + } + } + + our Num multi method cosech($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = sinh $N0 + $N1 = 1 / $N1 + %r = box $N1 + } + } + + our Num multi method cotan($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = tan $N0 + $N1 = 1 / $N1 + %r = box $N1 + } + } + + our Num multi method cotanh($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = tanh $N0 + $N1 = 1 / $N1 + %r = box $N1 + } + } + + our Str multi method perl() { ~self } -} -# vim: ft=perl6 + our Num multi method sec($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = sec $N0 + %r = box $N1 + } + } + + our Num multi method sech($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = sech $N0 + %r = box $N1 + } + } + + our Num multi method sin($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = sin $N0 + %r = box $N1 + } + } + + our Num multi method sinh($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = sinh $N0 + %r = box $N1 + } + } + + our Num multi method tan($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = tan $N0 + %r = box $N1 + } + } + + our Num multi method tanh($base = 'radians') is export(:Trig) { + my $x = self!convert-to-radians($base); + Q:PIR { + $P0 = find_lex "$x" + $N0 = $P0 + $N1 = tanh $N0 + %r = box $N1 + } + } +} -- 1.6.0.6