xref: /aosp_15_r20/external/skia/tests/SkRasterPipelineOptsTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2022 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/core/SkOpts.h"
9 #include "tests/Test.h"
10 
11 #include <algorithm>
12 #include <array>
13 #include <cstddef>
14 
15 #define SK_OPTS_NS RPOptsTest
16 
17 #if defined(__clang__)
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wunused-function"
20 #elif defined(__GNUC__)
21 #pragma GCC diagnostic push
22 #pragma GCC diagnostic ignored "-Wunused-function"
23 #pragma GCC diagnostic ignored "-Wunused-variable"
24 #endif
25 
26 #include "src/opts/SkRasterPipeline_opts.h"
27 
28 #if defined(__clang__)
29 #pragma clang diagnostic pop
30 #elif defined(__GNUC__)
31 #pragma GCC diagnostic pop
32 #endif
33 
34 constexpr auto F_ = SK_OPTS_NS::F_;
35 using F = SK_OPTS_NS::F;
36 using I32 = SK_OPTS_NS::I32;
37 
38 template <size_t N>
make_masks(int bits)39 static std::array<int32_t, N> make_masks(int bits) {
40     // Make an array of masks that correspond to the bit pattern of `bits`.
41     std::array<int32_t, N> masks;
42     for (size_t idx = 0; idx < N; ++idx) {
43         masks[idx] = (bits & 1) ? ~0 : 0;
44         bits >>= 1;
45     }
46     SkASSERT(!bits);
47     return masks;
48 }
49 
DEF_TEST(SkRasterPipelineOpts_Any,r)50 DEF_TEST(SkRasterPipelineOpts_Any, r) {
51     static constexpr size_t N = sizeof(I32) / sizeof(int32_t);
52 
53     for (int value = 0; value < (1 << N); ++value) {
54         // Load masks corresponding to the bit-pattern of `value` into lanes of `i`.
55         std::array<int32_t, N> masks = make_masks<N>(value);
56         I32 i = sk_unaligned_load<I32>(masks.data());
57 
58         // Verify that the raster pipeline any() matches expectations.
59         REPORTER_ASSERT(r, SK_OPTS_NS::any(i) == std::any_of(masks.begin(), masks.end(),
60                                                              [](int32_t m) { return m != 0; }));
61     }
62 }
63 
DEF_TEST(SkRasterPipelineOpts_All,r)64 DEF_TEST(SkRasterPipelineOpts_All, r) {
65     static constexpr size_t N = sizeof(I32) / sizeof(int32_t);
66 
67     for (int value = 0; value < (1 << N); ++value) {
68         // Load masks corresponding to the bit-pattern of `value` into lanes of `i`.
69         std::array<int32_t, N> masks = make_masks<N>(value);
70         I32 i = sk_unaligned_load<I32>(masks.data());
71 
72         // Verify that the raster pipeline all() matches expectations.
73         REPORTER_ASSERT(r, SK_OPTS_NS::all(i) == std::all_of(masks.begin(), masks.end(),
74                                                              [](int32_t m) { return m != 0; }));
75     }
76 }
77 
DEF_TEST(SkRasterPipelineOpts_Sin,r)78 DEF_TEST(SkRasterPipelineOpts_Sin, r) {
79     constexpr float Pi = SK_ScalarPI;
80     constexpr float kTolerance = 0.000875f;
81     for (float rad = -5*Pi; rad <= 5*Pi; rad += 0.1f) {
82         F result = SK_OPTS_NS::sin_(F_(rad));
83         F expected = F_(std::sin(rad));
84         F delta = SK_OPTS_NS::abs_(expected - result);
85 
86         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
87     }
88 }
89 
DEF_TEST(SkRasterPipelineOpts_Cos,r)90 DEF_TEST(SkRasterPipelineOpts_Cos, r) {
91     constexpr float Pi = SK_ScalarPI;
92     constexpr float kTolerance = 0.000875f;
93     for (float rad = -5*Pi; rad <= 5*Pi; rad += 0.1f) {
94         F result = SK_OPTS_NS::cos_(F_(rad));
95         F expected = F_(std::cos(rad));
96         F delta = SK_OPTS_NS::abs_(expected - result);
97 
98         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
99     }
100 }
101 
DEF_TEST(SkRasterPipelineOpts_Tan,r)102 DEF_TEST(SkRasterPipelineOpts_Tan, r) {
103     // Our tangent diverges more as we get near infinities (x near +- Pi/2),
104     // so we bring in the domain a little.
105     constexpr float Pi = SK_ScalarPI;
106     constexpr float kEpsilon = 0.16f;
107     constexpr float kTolerance = 0.00175f;
108 
109     // Test against various multiples of Pi, to check our periodicity
110     for (float period : {0.0f, -3*Pi, 3*Pi}) {
111         for (float rad = -Pi/2 + kEpsilon; rad <= Pi/2 - kEpsilon; rad += 0.01f) {
112             F result = SK_OPTS_NS::tan_(F_(rad + period));
113             F expected = F_(std::tan(rad));
114             F delta = SK_OPTS_NS::abs_(expected - result);
115 
116             REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
117         }
118     }
119 }
120 
DEF_TEST(SkRasterPipelineOpts_Asin,r)121 DEF_TEST(SkRasterPipelineOpts_Asin, r) {
122     constexpr float kTolerance = 0.00175f;
123     for (float x = -1; x <= 1; x += 1.0f/64) {
124         F result = SK_OPTS_NS::asin_(F_(x));
125         F expected = F_(asinf(x));
126         F delta = SK_OPTS_NS::abs_(expected - result);
127 
128         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
129     }
130 }
131 
DEF_TEST(SkRasterPipelineOpts_Acos,r)132 DEF_TEST(SkRasterPipelineOpts_Acos, r) {
133     constexpr float kTolerance = 0.00175f;
134     for (float x = -1; x <= 1; x += 1.0f/64) {
135         F result = SK_OPTS_NS::acos_(F_(x));
136         F expected = F_(acosf(x));
137         F delta = SK_OPTS_NS::abs_(expected - result);
138 
139         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
140     }
141 }
142 
DEF_TEST(SkRasterPipelineOpts_Atan,r)143 DEF_TEST(SkRasterPipelineOpts_Atan, r) {
144     constexpr float kTolerance = 0.00175f;
145     for (float x = -10.0f; x <= 10.0f; x += 0.1f) {
146         F result = SK_OPTS_NS::atan_(F_(x));
147         F expected = F_(atanf(x));
148         F delta = SK_OPTS_NS::abs_(expected - result);
149 
150         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
151     }
152 }
153 
DEF_TEST(SkRasterPipelineOpts_Atan2,r)154 DEF_TEST(SkRasterPipelineOpts_Atan2, r) {
155     constexpr float kTolerance = 0.00175f;
156     for (float y = -3.0f; y <= 3.0f; y += 0.1f) {
157         for (float x = -3.0f; x <= 3.0f; x += 0.1f) {
158             F result = SK_OPTS_NS::atan2_(F_(y), F_(x));
159             F expected = F_(std::atan2(y, x));
160             F delta = SK_OPTS_NS::abs_(expected - result);
161 
162             REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
163         }
164     }
165 }
166 
DEF_TEST(SkRasterPipelineOpts_Log2,r)167 DEF_TEST(SkRasterPipelineOpts_Log2, r) {
168     constexpr float kTolerance = 0.001f;
169     for (float value : {0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 8.0f}) {
170         F result = SK_OPTS_NS::approx_log2(F_(value));
171         F expected = F_(std::log2(value));
172         F delta = SK_OPTS_NS::abs_(expected - result);
173 
174         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
175     }
176 }
177 
DEF_TEST(SkRasterPipelineOpts_Pow2,r)178 DEF_TEST(SkRasterPipelineOpts_Pow2, r) {
179     constexpr float kTolerance = 0.001f;
180     for (float value : {-80, -5, -2, -1, 0, 1, 2, 3, 5}) {
181         F result = SK_OPTS_NS::approx_pow2(F_(value));
182         F expected = F_(std::pow(2.0, value));
183         F delta = SK_OPTS_NS::abs_(expected - result);
184 
185         REPORTER_ASSERT(r, SK_OPTS_NS::all(delta < kTolerance));
186     }
187 
188     F result = SK_OPTS_NS::approx_pow2(F_(160));
189     REPORTER_ASSERT(r, SK_OPTS_NS::all(result == INFINITY));
190 }
191