Преглед на файлове

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`.
Hendiadyoin1 преди 3 години
родител
ревизия
cd21e03225
променени са 6 файла, в които са добавени 30 реда и са изтрити 10 реда
  1. 3 1
      AK/Complex.h
  2. 15 0
      AK/Math.h
  3. 1 1
      Userland/DevTools/UserspaceEmulator/SoftFPU.cpp
  4. 6 4
      Userland/Libraries/LibAudio/Sample.h
  5. 3 2
      Userland/Libraries/LibDSP/FFT.h
  6. 2 2
      Userland/Libraries/LibGfx/Matrix4x4.h

+ 3 - 1
AK/Complex.h

@@ -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>

+ 15 - 0
AK/Math.h

@@ -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 {

+ 1 - 1
Userland/DevTools/UserspaceEmulator/SoftFPU.cpp

@@ -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
 {

+ 6 - 4
Userland/Libraries/LibAudio/Sample.h

@@ -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 };
     }

+ 3 - 2
Userland/Libraries/LibDSP/FFT.h

@@ -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;

+ 2 - 2
Userland/Libraries/LibGfx/Matrix4x4.h

@@ -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();