# 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

Reply via email to