All the trancendental unary operators can be merged into PP_sin
Nicholas Clark [Tue, 7 Feb 2006 17:12:08 +0000 (17:12 +0000)]
(cos, exp, log, sqrt)

p4raw-id: //depot/perl@27124

mathoms.c
opcode.h
opcode.pl
pp.c

index 0f0f157..a96c752 100644 (file)
--- a/mathoms.c
+++ b/mathoms.c
@@ -1054,6 +1054,26 @@ PP(pp_pop)
     return pp_shift();
 }
 
+PP(pp_cos)
+{
+    return pp_sin();
+}
+
+PP(pp_exp)
+{
+    return pp_sin();
+}
+
+PP(pp_log)
+{
+    return pp_sin();
+}
+
+PP(pp_sqrt)
+{
+    return pp_sin();
+}
+
 U8 *
 Perl_uvuni_to_utf8(pTHX_ U8 *d, UV uv)
 {
index adacc4c..9551014 100644 (file)
--- a/opcode.h
+++ b/opcode.h
@@ -885,12 +885,12 @@ EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */
        MEMBER_TO_FPTR(Perl_pp_complement),
        MEMBER_TO_FPTR(Perl_pp_atan2),
        MEMBER_TO_FPTR(Perl_pp_sin),
-       MEMBER_TO_FPTR(Perl_pp_cos),
+       MEMBER_TO_FPTR(Perl_pp_sin),    /* Perl_pp_cos */
        MEMBER_TO_FPTR(Perl_pp_rand),
        MEMBER_TO_FPTR(Perl_pp_srand),
-       MEMBER_TO_FPTR(Perl_pp_exp),
-       MEMBER_TO_FPTR(Perl_pp_log),
-       MEMBER_TO_FPTR(Perl_pp_sqrt),
+       MEMBER_TO_FPTR(Perl_pp_sin),    /* Perl_pp_exp */
+       MEMBER_TO_FPTR(Perl_pp_sin),    /* Perl_pp_log */
+       MEMBER_TO_FPTR(Perl_pp_sin),    /* Perl_pp_sqrt */
        MEMBER_TO_FPTR(Perl_pp_int),
        MEMBER_TO_FPTR(Perl_pp_oct),    /* Perl_pp_hex */
        MEMBER_TO_FPTR(Perl_pp_oct),
index ff171ac..fdf07c1 100755 (executable)
--- a/opcode.pl
+++ b/opcode.pl
@@ -82,6 +82,7 @@ my @raw_alias = (
                 Perl_pp_index => ['rindex'],
                 Perl_pp_oct => ['hex'],
                 Perl_pp_shift => ['pop'],
+                Perl_pp_sin => [qw(cos exp log sqrt)],
                );
 
 while (my ($func, $names) = splice @raw_alias, 0, 2) {
diff --git a/pp.c b/pp.c
index 08578cc..8d6421c 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -2643,20 +2643,43 @@ PP(pp_atan2)
 
 PP(pp_sin)
 {
-    dVAR; dSP; dTARGET; tryAMAGICun_var(sin_amg);
-    {
-      const NV value = POPn;
-      XPUSHn(Perl_sin(value));
-      RETURN;
+    dVAR; dSP; dTARGET;
+    int amg_type = sin_amg;
+    const char *neg_report = NULL;
+    NV (*func)(NV) = &Perl_sin;
+    const int op_type = PL_op->op_type;
+
+    switch (op_type) {
+    case OP_COS:
+       amg_type = cos_amg;
+       func = &Perl_cos;
+       break;
+    case OP_EXP:
+       amg_type = exp_amg;
+       func = &Perl_exp;
+       break;
+    case OP_LOG:
+       amg_type = log_amg;
+       func = &Perl_log;
+       neg_report = "log";
+       break;
+    case OP_SQRT:
+       amg_type = sqrt_amg;
+       func = &Perl_sqrt;
+       neg_report = "sqrt";
+       break;
     }
-}
 
-PP(pp_cos)
-{
-    dVAR; dSP; dTARGET; tryAMAGICun_var(cos_amg);
+    tryAMAGICun_var(amg_type);
     {
       const NV value = POPn;
-      XPUSHn(Perl_cos(value));
+      if (neg_report) {
+         if (op_type == OP_LOG ? (value <= 0.0) : (value < 0.0)) {
+             SET_NUMERIC_STANDARD();
+             DIE(aTHX_ "Can't take %s of %"NVgf, neg_report, value);
+         }
+      }
+      XPUSHn(func(value));
       RETURN;
     }
 }
@@ -2705,46 +2728,6 @@ PP(pp_srand)
     RETPUSHYES;
 }
 
-PP(pp_exp)
-{
-    dVAR; dSP; dTARGET; tryAMAGICun_var(exp_amg);
-    {
-      NV value;
-      value = POPn;
-      value = Perl_exp(value);
-      XPUSHn(value);
-      RETURN;
-    }
-}
-
-PP(pp_log)
-{
-    dVAR; dSP; dTARGET; tryAMAGICun_var(log_amg);
-    {
-      const NV value = POPn;
-      if (value <= 0.0) {
-       SET_NUMERIC_STANDARD();
-       DIE(aTHX_ "Can't take log of %"NVgf, value);
-      }
-      XPUSHn(Perl_log(value));
-      RETURN;
-    }
-}
-
-PP(pp_sqrt)
-{
-    dVAR; dSP; dTARGET; tryAMAGICun_var(sqrt_amg);
-    {
-      const NV value = POPn;
-      if (value < 0.0) {
-       SET_NUMERIC_STANDARD();
-       DIE(aTHX_ "Can't take sqrt of %"NVgf, value);
-      }
-      XPUSHn(Perl_sqrt(value));
-      RETURN;
-    }
-}
-
 PP(pp_int)
 {
     dVAR; dSP; dTARGET; tryAMAGICun(int);