AK+Everywhere: Add sincos and use it in some places

Calculating sin and cos at once is quite a bit cheaper than calculating
them individually.
x87 has even a dedicated instruction for it: `fsincos`.
This commit is contained in:
Hendiadyoin1 2022-02-03 12:48:17 +01:00 committed by Andreas Kling
parent 47fe911196
commit cd21e03225
6 changed files with 30 additions and 10 deletions

View file

@ -55,7 +55,9 @@ public:
template<AK::Concepts::Arithmetic U, AK::Concepts::Arithmetic V>
static constexpr Complex<T> from_polar(U magnitude, V phase)
{
return Complex<T>(magnitude * cos(phase), magnitude * sin(phase));
V s, c;
sincos(phase, s, c);
return Complex<T>(magnitude * c, magnitude * s);
}
template<AK::Concepts::Arithmetic U>

View file

@ -203,6 +203,20 @@ constexpr T cos(T angle)
#endif
}
template<FloatingPoint T>
constexpr void sincos(T angle, T& sin_val, T& cos_val)
{
if (is_constant_evaluated()) {
sin_val = sin(angle);
cos_val = cos(angle);
return;
}
asm(
"fsincos"
: "=t"(cos_val), "=u"(sin_val)
: "0"(angle));
}
template<FloatingPoint T>
constexpr T tan(T angle)
{
@ -303,6 +317,7 @@ using Trigonometry::atan2;
using Trigonometry::cos;
using Trigonometry::hypot;
using Trigonometry::sin;
using Trigonometry::sincos;
using Trigonometry::tan;
namespace Exponentials {

View file

@ -36,7 +36,7 @@ ALWAYS_INLINE void warn_if_uninitialized(T value_with_shadow, const char* messag
}
}
namespace UserspaceEmulator {
namespace UserspaceEmulator { // NOLINT(readability-implicit-bool-conversion) 0/1 to follow spec closer
ALWAYS_INLINE void SoftFPU::warn_if_mmx_absolute(u8 index) const
{

View file

@ -97,8 +97,10 @@ struct Sample {
double const pi_over_2 = AK::Pi<double> * 0.5;
double const root_over_2 = AK::sqrt(2.0) * 0.5;
double const angle = position * pi_over_2 * 0.5;
left *= root_over_2 * (AK::cos(angle) - AK::sin(angle));
right *= root_over_2 * (AK::cos(angle) + AK::sin(angle));
double s, c;
AK::sincos(angle, s, c);
left *= root_over_2 * (c - s);
right *= root_over_2 * (c + s);
return *this;
}
@ -116,7 +118,7 @@ struct Sample {
return *this;
}
constexpr Sample operator*(double const mult)
constexpr Sample operator*(double const mult) const
{
return { left * mult, right * mult };
}
@ -134,7 +136,7 @@ struct Sample {
return *this;
}
constexpr Sample operator+(Sample const& other)
constexpr Sample operator+(Sample const& other) const
{
return { left + other.left, right + other.right };
}

View file

@ -28,11 +28,12 @@ constexpr void fft(Span<Complex<double>> sample_data, bool invert = false)
for (int len = 2; len <= n; len <<= 1) {
double ang = 2 * AK::Pi<double> / len * (invert ? -1 : 1);
Complex<double> wlen(AK::cos(ang), AK::sin(ang));
Complex<double> wlen = Complex<double>::from_polar(1., ang);
for (int i = 0; i < n; i += len) {
Complex<double> w = { 1., 0. };
for (int j = 0; j < len / 2; j++) {
Complex<double> u = sample_data[i + j], v = sample_data[i + j + len / 2] * w;
Complex<double> u = sample_data[i + j];
Complex<double> v = sample_data[i + j + len / 2] * w;
sample_data[i + j] = u + v;
sample_data[i + j + len / 2] = u - v;
w *= wlen;

View file

@ -70,8 +70,8 @@ constexpr static Matrix4x4<T> scale_matrix(const Vector3<T>& s)
template<typename T>
constexpr static Matrix4x4<T> rotation_matrix(const Vector3<T>& axis, T angle)
{
T c = AK::cos(angle);
T s = AK::sin(angle);
T c, s;
AK::sincos(angle, s, c);
T t = 1 - c;
T x = axis.x();
T y = axis.y();