# 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 <[email protected]>
Date: Sun, 19 Apr 2009 12:31:28 -0700
Subject: [PATCH] Squashed commit of the following:
commit 268fc3340aba0486bb401b98faf44ae155df6518
Author: Cory Spencer <[email protected]>
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