summaryrefslogtreecommitdiff
path: root/complex.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2020-05-03 14:38:19 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2020-05-03 15:29:51 +0900
commite49ecaed57181c10bf01e1f84b9eead65a759386 (patch)
tree21b48793d6c844854384734d244e4efe570a86b7 /complex.c
parent8af098b40ee3788f3d13f02298eeecfb52fa0c16 (diff)
downloadruby-e49ecaed57181c10bf01e1f84b9eead65a759386.tar.gz
Optimize sin/cos
GCC/Clang can optimize to calculate `sin(x)` and `cos(x)` at once, when the both are closely called on the same argument. Similar optimization is possible for `__sinpi(x)` and `__cospi(x)` if available, which calculate arguments in radian, i.e. `sin(x*M_PI)` and `cos(x*M_PI)` respectively.
Diffstat (limited to 'complex.c')
-rw-r--r--complex.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/complex.c b/complex.c
index 2a37c42126..95b1abbd45 100644
--- a/complex.c
+++ b/complex.c
@@ -661,8 +661,9 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y)
y = DBL2NUM(imag);
}
else {
- y = f_mul(x, DBL2NUM(sin(arg)));
- x = f_mul(x, DBL2NUM(cos(arg)));
+ const double ax = sin(arg), ay = cos(arg);
+ y = f_mul(x, DBL2NUM(ax));
+ x = f_mul(x, DBL2NUM(ay));
if (canonicalization && f_zero_p(y)) return x;
}
return nucomp_s_new_internal(klass, x, y);
@@ -672,6 +673,16 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y)
f_mul(x, m_sin(y)));
}
+#ifdef HAVE___COSPI
+# define cospi(x) __cospi(x)
+#else
+# define cospi(x) cos((x) * M_PI)
+#endif
+#ifdef HAVE___SINPI
+# define sinpi(x) __sinpi(x)
+#else
+# define sinpi(x) sin((x) * M_PI)
+#endif
/* returns a Complex or Float of ang*PI-rotated abs */
VALUE
rb_dbl_complex_new_polar_pi(double abs, double ang)
@@ -689,8 +700,8 @@ rb_dbl_complex_new_polar_pi(double abs, double ang)
return DBL2NUM(abs);
}
else {
- ang *= M_PI;
- return rb_complex_new(DBL2NUM(abs * cos(ang)), DBL2NUM(abs * sin(ang)));
+ const double real = abs * cospi(ang), imag = abs * sinpi(ang);
+ return rb_complex_new(DBL2NUM(real), DBL2NUM(imag));
}
}