summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mathoms.c20
-rw-r--r--opcode.h8
-rwxr-xr-xopcode.pl1
-rw-r--r--pp.c83
4 files changed, 58 insertions, 54 deletions
diff --git a/mathoms.c b/mathoms.c
index 0f0f15737b..a96c75268d 100644
--- 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)
{
diff --git a/opcode.h b/opcode.h
index adacc4c73c..95510146df 100644
--- 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),
diff --git a/opcode.pl b/opcode.pl
index ff171ac915..fdf07c17be 100755
--- 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 08578cc088..8d6421c7cd 100644
--- 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);