Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AK: fmod(), sin(), cos(), atan2() for non-x86 #25578

Merged
merged 5 commits into from
Dec 24, 2024
Merged

Conversation

nico
Copy link
Contributor

@nico nico commented Dec 24, 2024

atan2() is implemented in terms of atan(), so the implementation isn't super useful yet.

@github-actions github-actions bot added the 👀 pr-needs-review PR needs review from a maintainer or community member label Dec 24, 2024
@nico
Copy link
Contributor Author

nico commented Dec 24, 2024

With this local diff:

local patch to Gradient
diff --git a/Userland/Demos/Gradient/Gradient.cpp b/Userland/Demos/Gradient/Gradient.cpp
index 56168c6057b..b29ec23e38d 100644
--- a/Userland/Demos/Gradient/Gradient.cpp
+++ b/Userland/Demos/Gradient/Gradient.cpp
@@ -12,6 +12,7 @@
 #include <LibGUI/Painter.h>
 #include <LibGUI/Window.h>
 #include <LibGfx/Bitmap.h>
+#include <LibGfx/Path.h>
 #include <LibMain/Main.h>
 #include <stdio.h>
 #include <time.h>
@@ -83,6 +84,35 @@ void Gradient::draw()
         m_bitmap->rect(),
         colors[start_color_index],
         colors[end_color_index]);
+
+    //Gfx::Path p1, p2;
+    int last_x, last_y1, last_y2;
+    for (int x = 0; x < m_bitmap->width(); ++x) {
+        float fx = x / (float)m_bitmap->width();
+        fx = (fx - 0.5f) * 4 * 2 * AK::Pi<float>;
+        float fy1 = sin(fx);
+        float fy2 = cos(fx);
+
+        int y1 = m_bitmap->height() / 2 * (1 - 0.5f * 0.4f * fy1);
+        int y2 = m_bitmap->height() / 2 * (1 - 0.5f * 0.7f * fy2);
+
+        if (x == 0) {
+            //p1.move_to({ x, y1 });
+            //p2.move_to({ x, y2 });
+        } else {
+            //p1.line_to({ x, y1 });
+            //p2.line_to({ x, y2 });
+
+           painter.draw_line({ last_x, last_y1 }, { x, y1 }, Gfx::Color::Red);
+           painter.draw_line({ last_x, last_y2 }, { x, y2 }, Gfx::Color::Green);
+        }
+        last_x = x;
+        last_y1 = y1;
+        last_y2 = y2;
+    }
+
+    //painter.stroke_path(p1, Gfx::Color::Red, 3);
+    //painter.stroke_path(p2, Gfx::Color::Green, 3);
 }
 
 ErrorOr<int> serenity_main(Main::Arguments arguments)
@@ -97,7 +127,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
 
     auto window = TRY(Desktop::Screensaver::create_window("Gradient"sv, "app-gradient"sv));
 
-    auto gradient_widget = window->set_main_widget<Gradient>(64, 48, 10000);
+    auto gradient_widget = window->set_main_widget<Gradient>(640, 480, 10000);
     gradient_widget->set_fill_with_background_color(false);
     gradient_widget->set_override_cursor(Gfx::StandardCursor::Hidden);
     gradient_widget->update();

Before:

Screenshot 2024-12-23 at 3 14 14 PM

After the "Make periodic" commit:

Screenshot 2024-12-23 at 1 35 13 PM

After the "a bit better" commit:

Screenshot 2024-12-23 at 2 30 58 PM

AK/Math.h Show resolved Hide resolved
@nico
Copy link
Contributor Author

nico commented Dec 24, 2024

More screenshots!

Before:

Screenshot 2024-12-23 at 9 00 10 AM

After "Make periodic":

Screenshot 2024-12-23 at 1 43 12 PM

After "a bit better":

Screenshot 2024-12-23 at 2 31 17 PM

After atan2:

Screenshot 2024-12-23 at 3 08 04 PM

Build/lagom/bin/pdf in lagom still renders it fine (it now uses the new atan2 which calls local libc atan):

out

@nico
Copy link
Contributor Author

nico commented Dec 24, 2024

Huh, looks like you're right! Are the macOS lagom bots running on arm machines? Must be, I suppose?

@ADKaster
Copy link
Member

Yeah GitHub has a load of racks of re-housed mac minis they use for the macOS free tier

@nico
Copy link
Contributor Author

nico commented Dec 24, 2024

Locally, it seems removing the sin/cos libcall is at fault. I put those back, let's see what CI says.

nico added 5 commits December 24, 2024 10:54
This is a pretty naive implementation, but it mostly works.
Now that we have fmod(), we can implement some symmetries for
sin() and cos(). The core approximation is still very simplistic,
but now it only has to approximate in [0, Pi/2]. So while its error
is still high, it's no longer unbounded.
With this, sin() and cos() are fairly close to the correct values
for all x. It's neither fast nor very accurate, but much better than
what we had before.
atan() isn't implemented yet on non-x86, so this isn't super useful yet.
But it does handle a couple corner cases correctly already, and those
are even enough to make all the atan2 tests in Tests/LibC/TestMath.cpp
pass 🙃
@nico
Copy link
Contributor Author

nico commented Dec 24, 2024

css-gradients.png was different with the atan2 change. (From manually eyeing the diff, in harmless ways, but I didn't expect the atan2 change to change behavior at all, so I want to investigate that a bit.) I put back the libcalls for both atan2 and fmod for now since replacing the non-serenity codepath isn't the main thrust of this PR. I still want to do this in a future PR, but it doesn't have to be in here.

@nico nico merged commit 69b2b86 into SerenityOS:master Dec 24, 2024
13 checks passed
@nico nico deleted the fmod branch December 24, 2024 18:11
@github-actions github-actions bot removed the 👀 pr-needs-review PR needs review from a maintainer or community member label Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants